The verilog code is as follows:

module test;

reg clk0; initial clk0 = 1'b0;
reg clk1; initial clk1 = 1'b0;

initial forever #5 clk0 =~ clk0;
initial forever #7 clk1 =~ clk1;

initial #50000 $finish;

endmodule

Suraj N. Kurapati wrote:

Calvin Wong wrote:
Suraj Kurapati wrote:
Since the scheduler waits for *all* threads to either (1)
terminate or (2) invoke the "wait" or "advance_time" method, we
cannot have non-verification-related threads running in the
background.
Yes ... I am currently encountering this. I created two clocks
and am driving the clocks in verilog.

Please post your Verilog code also.

I created two threads and had each of them wait for a posedge
of their particular clock and print out the simulation time.

t1 = Thread.new do
5.times do |i|
  wait until Test.clk0.posedge?
  puts "@#{simuilation_time} clk0 seen"
end
end

t2 = Thread.new do
5.times do |i|
  wait until Test.clk1.posedge?
  puts "@#{simulation_time} clk1 seen"
end
end

t1.join
t2.join

Adding the t1.join and the t2.join causes the simulation to
lock up.

Correct.  There is no need to join the threads manually; the
scheduler will take care of it behind the scenes.

If I remove t1 and t2, then the simulation proceeds but in a
single thread fashion.  Meaning ... t1 runs first, with a lot of
delay in between, then t2 runs.

Correct, AFAIK Ruby uses green threads in a non-preemptive,
cooperative fashion.  You can set thread priorities using
Thread.priority= to make things more preemptive.

is there a better Verilog-related name for the creation of a verification-related thread than "process"? How would you like
to name this method?
In my previous projects, we have a C++ verification based
environment and we used the following terminology for running
many processes in parallel.
c_fork
// Process A
c_fork_begin
  for (i=0;i<10;i++) atPosedge("top.clk0");
c_fork_end

// Process B
c_fork_begin
  for (i=0;i<10;i++) atPosedge("top.clk1");
c_fork_end
c_join_all // could also be c_join_any or c_join_none

c_join_all indicates that all processes needs to be completed prior to exiting the fork block. c_join_any needs only one
process to complete prior to exiting, and c_join_none immediately
exits the block and allows them to run in the background.

Thanks for this insight.  This appears to be a complex interface for
solving (more) complex problems.  I'll stick with process() for now
and evolve my concurrency interface, as necessary, later on.

----

By the way, I have checked in a revised concurrency implementation
(which includes the process() method) into the code repository.
Please try that and see if it solves the problems you mentioned above.

Note that you have to replace:

 t1 = Thread.new do
   ...
 end

with:

 t1 = process do
   ...
 end

Reply via email to