Hi,
I am in a process of developing an SV based verification env for a generic fifo where in primary functionalities of the VIP shall be to INSERT , UPDATE& DELETE.
i wanted to apply these commands to the DUT by randomly distributing the weights for qhich i have come up with the below implementation in the input generator class of the SV test bench.
class generator;
//declaring transaction class
rand transaction trans,tr;
//repeat count, to specify number of items to generate
// This section has declaration for declaring the other block
int repeat_count;
int insert_wt;
int delete_wt;
int update_wt;
int initial_insert;
bit [31:0] price [];
bit [31:0] OrderId[];
int totalInsert=-1;
bit[1:0] Opcodes ;
rand int randno=0;
//mailbox, to generate and send the packet to driver
mailbox gen2driv;
//event
event ended;
//constructor
function new(mailbox gen2driv,event ended);
//getting the mailbox handle from env, in order to share the transaction packet between the generator and driver, the same mailbox is shared between both.
this.gen2driv = gen2driv;
this.ended = ended;
trans = new();
endfunction
//main task, generates(create and randomizes) the repeat_count number of transaction packets and puts into mailbox
task main();
// set the distribution here
price= new [repeat_count];
OrderId= new [repeat_count];
//Opcodes= new [repeat_count];
// Opcodes = trans.GenerateOpcode(repeat_count,initial_insert,insert_wt,update_wt,delete_wt);
trans.setdistribution( insert_wt,update_wt,delete_wt);
trans.displaydistribution();
for (int i=0;i<repeat_count;i++)
begin
if( !trans.randomize() )
$fatal("Gen:: trans randomization failed");
if (i<initial_insert)
begin
trans.cmdcode =0; //insert
totalInsert=totalInsert+1;
price[totalInsert] = trans.ORDER_BOOK.Price;
OrderId[totalInsert]=trans.ORDER_BOOK.OrderID;
$display("Insert initial iteration =%d, order ID =%d, price =%d ",i,trans.ORDER_BOOK.OrderID,trans.ORDER_BOOK.Price);
end
else if (i>=initial_insert)
begin
Opcodes=trans.cmdcode;
if(Opcodes==0)
begin
trans.cmdcode =0; //insert
totalInsert=totalInsert+1;
price[totalInsert] = trans.ORDER_BOOK.Price;
OrderId[totalInsert]=trans.ORDER_BOOK.OrderID;
$display("This is insert command itertion =%d, OrderId=%d, price=%d, ",i,trans.ORDER_BOOK.OrderID,trans.ORDER_BOOK.Price);
end
if(Opcodes==1)
begin
$display("This is delete command orderID=%d, iteration =%d ", OrderId[totalInsert],i);
// Delete the last element added //LIFO
trans.cmdcode =1; //delete
trans.ORDER_BOOK.OrderID=OrderId[totalInsert];
totalInsert=totalInsert-1;
end
if(Opcodes==2)
begin
randno = $urandom_range(0,totalInsert);
trans.cmdcode =2; //update
trans.ORDER_BOOK.OrderID=OrderId[randno];
trans.newprice = trans.CalNewPrice(price[randno]);
$display("This is update command orderID =%d, updated price =%d, itr =%d", OrderId[randno],trans.newprice,i);
end
end
tr = trans.do_copy();
gen2driv.put(tr);
end
-> ended;
endtask
endclass
After which i am applying weights to these commands from my test case as shown below
`include "environment.sv"
//
program test(mem_intf intf);
environment env;
transaction my_tr;
initial begin
//creating environment
env = new(intf);
my_tr = new();
//setting the repeat count of generator as 4, means to generate 4 packets
env.gen.repeat_count = 40;
env.gen.initial_insert =10;
// control the distribution of the insert , delete and update
env.gen.insert_wt=70;
env.gen.delete_wt=10;
env.gen.update_wt=50;
// env.gen.trans.
env.gen.trans = my_tr;
//calling run of env, it interns calls generator and driver main tasks.
env.run();
end
endprogram
I wanted to understand if there is a much simpler way to implement this… something like i wanted to apply total 10 commands out of which 5 insert , 3 update and 2 delete. I.e. 50% of inserts 30% of updates and 20% deletes