`ifdef FORK_1
program test;
initial
begin
for(int i=0;i<16;i++) size="+0">send(i);
end
task send(int i);
fork
begin
$write("Driving port %d\n",i);
#1;
end
join_none
endtask:send
endprogram:test
`endif
/*
observation : In the above example,for loop creates 15 processes which in turn each have their own child threads(send(i)) which are queued but not executed since it is join none,once the parent thread completes it's execution(i.e initial begin for loop end,i.e the main parent thread completes its execution or once for_loop completes) All the queued threads are shifted to execution state which now share the same memory stack i.e i=15. Hence it generates the output 15.
*/
`ifdef FORK_2
program test;
initial
begin
for(int i=0;i<16;i++) size="+0">send(i);
end
task send(int i);
automatic int j;
j=i;
fork
begin
$write("Driving port %d\n",j);
#1;
end
join_none
endtask:send
endprogram:test
`endif
/* observation :
STATIC : storage allocated on instantiation,never deallocated.
AUTOMATIC : storage allocated once it entered to the stack,such as task,function or block and deallocated on exist. It gives the expected outputs : 0,1,2....15
*/
`ifdef FORK_3
program automatic test;
initial
begin
for(int i=0;i<16;i++) size="+0">send(i);
end
task send(int i);
fork
begin
$write("Driving port %d\n",i);
#1;
end
join_none
//wait fork; //to understand the simulation time.
endtask:send
endprogram:test
`endif
/*
observation :
In this example all send(i) threads will try to access the same resource i that is passed to the task send(), but since the program is itself made automatic the tasks also are executed automatic , in the sense a task once called with a value ,performs it's operation for the called value and hence the threads execute for their respective value.Here program automatic helps in avoiding the race condition where in a same task can be called with n number of values but it should perform it's operation w.r.t the value for which it is called.But here the simulation time completes at 0 irrespective of the delay element #1.
wait fork helps in preventing improper early termination of the jobs
In the above example,if we use wait fork system task the simulation time will be 16,since it waits
for the threads to execute completely (here each thread will completes it's execution only after #1 unit,hence 16)
else simulation time will be 0.
output : Generates the expected output : 0,1,2.....15
*/
`ifdef FORK_4
program automatic test;
initial
begin
for(int i=0;i<16;i++) size="+0">fork
send(i);
join_none
end
task send(int i);
begin
$write("Driving port %d\n",i);
#1;
end
//wait fork; //to understand the simulation time.
endtask:send
endprogram:test
`endif
/* observation :In this example the send(i) is spawned with a same shared resource variable i , hence the final updated values is printed by all the threads.
generates the output as 16. last value of i.
*/
`ifdef FORK_5
program automatic test;
initial
begin
for(int i=0;i<16;i++) size="+0">automatic int index = i;
fork
send(index);
join_none end
end
task send(int i);
begin
$write("Driving port %d\n",i);
#1;
end
//wait fork; //to understand the simulation time.
endtask:send
endprogram:test
`endif
/* observation : In this example the shared resource variable is dragged specific for each thread by automatic key word , hence each thread has it's own local copy of it's own value
generates the desired output i.e 0,1,2,...15
*/
`ifdef FORK_6
program test; // automatic test
initial
begin
for(int i=0;i<16;i++) size="+0">fork
send(i);
join
end
task send(int i);
begin
$write("Driving port %d\n",i);
#1;
end
//wait fork; //to understand the simulation time.
endtask:send
endprogram:test
`endif
/* observation :In this example though all the threads share the same resource value,i is not incremented until the present thread completes it's execution irrespective of the automatic keyword. It generates the expected output i.e 0,1,2,...15
*/
`ifdef FORK_7
program automatic fork_join_8;
initial
begin
for(int i =0 ; i<16;i++)begin size="+0">fork
send(i);
join_none
end
end
task send(int i);
$display("Driving port %0d",i);
endtask
endprogram
`endif
/* observation : In this example though the program block is made automatic , we find no effect as the thread is being spawned and now send(i) is treated as a thread and not a special task , so as in any other case all the threads share the same resource and hence get only the final updated value.while when the send(i) was treated as a task, the send(i) task was itself getting automatic with separate value for each of it's call.
REF : FORK_3 example
*/
`ifdef JOIN_NONE
program test;
initial
begin
int thread1 = 1 ;
string thread2 = "2" ;
reg [7:0] thread3 = 3 ;
fork
begin
$write (" First thread = %d\n",thread1); //
#(100);
end
join_none
$write (" Thread execution completed\n"); //
end
endprogram : test
`endif
/* observation : In this example it indicates that threads in join_none are queued but not executed until the parent thread encounters a wait statement or completes. (whereas it's not the same in VERA).
*/
Tuesday, June 3, 2008
Few examples on Fork and Join
Sunday, May 18, 2008
Scenario Generator
A scenario generator generates a stream of scenario objects, each of which is composed of an array of transaction objects.
Purpose : To validate the protocol that includes sequence of scenarios to be applied to the DUT.The vmm_scenario_gen macro can be used to automatically generate a scenario generator transactor for the user defined class.The resulting generator class is an extension of vmm_xactor. This macro would inturn generates a class_name_scenario class that extends vmm_data , a class_name_scenario_election class and an class_name_atomic_scenario class that extends the class_name_scenario class.
i.e.`vmm_scenario_gen ( class_name, class_description_string ) ==> Creates :
class_name_scenario_gen ==> Generator Class that interfaces with the remaining classes and generates the stream of transactions and puts it on to the channel.It provides a set of callbacks that can be used to access the scenario related information.class_name_scenario ==> Scenario Class to define a set of constraints that are written to control the randomization of the scenarios and the randomized scenarios are placed in the items[] present in scenario class.It provides a set of members that can be accessed for scenario-related-meta-data.
class_name_scenario_election ==>Scenario Election Class to help the generator in selecting one among the various scenarios defined.It provides a set of constraints for the selection process which can be overridden.class_name_atomic_scenario ==> Atomic Scenario Class defines a set of constraints for an atomic transaction,which forms the default transaction generated by the scenario generator.
Flowchart which describes the flow of the scenario generator,
Steps to be followed by the user,
2. Extending the base data_class_scenario class to add application specific scenario's.
3. Deploy them into the verification environment by adding the instance of derived_data_class_scenario class to the generator object's scenario_set[] array.
i.e
derived_data_class scen_object = new();
env.scen_gen.push_back(scen_object);
4. Specify the no_of_scenari_count or no_of_instance.
There are many ways to construct the scenario's depending on the application,.
1. Customized scenarios or constraints can be defined by having one or more derived classes of class_name_scenario class.Here entire scenario is constructed and it's items are delivered one by one to the output channel. It is a conventional method,straightforward.flexible and easy to extend.
2. Procedural type of scenarios is another method to create directed transactions. Here, transactions are not randomized until they are needed.This can achieved by extending the scenario's apply method.A procedural scenario may require runtime feedback information from the environment.i.e visibility over the environment or design signals
In the normal flow, Generator will call a scenario’s apply method automatically once the scenario has been selected and randomized. This functionality can be customized in hierarchical scenario generation by customizing the scenario’s _apply_ method based on the scenario’s requirements. (mean to say that scenario’s apply method in turn used to create further scenarios)
Atomic Generator
An atomic generator is a process of generating a single instance of random data object or transaction at a time.
Purpose :
To validate the protocol/to reach the functional coverage space, that does not depend on any specific sequence.
The vmm_atomic_gen macro can be used to automatically generate an atomic generator transactor for the user defined clas.The resulting generator class is an extension of vmm_xactor.
i.e
`vmm_atomic_gen ( class_name, class_description_string ) ==> Creates class class_name_atomic_gen (see below)
class class_name_atomic_gen extends vmm_xactor;
The properties and methods of atomic generator are,
function new ( string instance, int stream_id = -1,
class_name_channel out_chan = null );
class_name_channel out_chan;
int unsigned stop_after_n_insts;
class_name randomized_obj;
enum { GENERATED };
enum { DONE };
virtual task inject ( class_name data, ref bit dropped );
Flow Chart which describes the internal operation of the atomic generator, This flow chart is drawn based on our understandings by working on various examples, SNUG papers and rvm/vmm manual.

Sunday, May 11, 2008
Objectives
Blog Archive
About Me
- raghu/aravinda
- It's better we can say it's about us,since I and aravinda together joined CDAC -HYDERABAD to do our PG Diploma in VLSI Design and We are working in VLSI industry since more than 5 years
