I am trying to implement a queue to replace the mailbox implementation (which is only FIFO) in a SV testbench structure. Currently I have :
- Environment - where I am initializing generator/driver/monitors/checkers. and the queue for holding the transactions:
class environment;
transaction gen2driv[$]; //This is to hold the transactions generated and also helps the driver pops the transaction
transaction mon2check[$];
...
.....
generator = new(gen2driv);
monitor = new(mon2check);
.....
endclass
class generator;
transaction trans;
transaction gen2driv[$];
function new(ref transaction gen2driv[$]);
this.gen2driv = gen2driv;
endfunction
...
...
trans = new();
gen2driv.push_back(trans);
...
..
endclass
class driver;
transaction trans;
transaction gen2driv[$];
function new(ref transaction gen2driv[$]);
this.gen2driv = gen2driv;
endfunction
...
...
transaction tr = gen2driv.pop_front(trans);
...
..
endclass
While executing the above code , the transaction is only pushing in. But when I display in the driver side - it complains that the size is 0.
Can someone please help in here ?
In reply to kb646bits:
You have three unconnected gen2driv queues. The generator::new just copies the queue as it exists when the constructor get called, and is probably empty. Same problem with driver::new().
What you need to do is encapsulate the queue in a class mymailbox, construct it in your environment, and pass a handle to that class into your generator and driver. And while you are at it, add put/get methods to your mymailbox.
This is exactly how you would connect up the built-in mailbox class.
In reply to dave_59:
Thanks Dave,
I have following questions to above :
-
When you say unconnected gen2driv queues : you mean that - if in the generator, queue.push_back(transaction) is being implemented – the queue in the environment class will not be filled ?
-
Is the queue definition correct? i.e. Here i am defining a queue of transaction class objects. So as per your suggestion :
class mymailbox;
transaction gen2driv[$]; //Is this definition correct ?
task push(transaction tr); . //Is this correct way of passing my transaction class objects
gen2driv.push_back(tr);
endtask
task transaction get();
transaction tr1 = gen2driv.pop_front();
return tr1;
endtask
endclass
Looking forward to your reply.
In reply to kb646bits:
- Yes.
- That will work mostly. However I suggest you parameterize the class just like the built-in mailbox class.
A couple more suggestions. Use functions for methods that cannot block. Tasks can block, you the output has to be from an argument
Your code should look like
class mymailbox #(type T);
protected T Q[$]; //must use a method to access Q
function void push(T tr);
Q.push_back(tr);
endfunction
task get(ref T tr);
wait(Q.size()>0)
tr = gen2driv.pop_front();
endtask
endclass // mymailbox
class environment;
mymailbox#(transaction) gen2driv;
transaction_driver driver;
transaction_generator generator;
...
...
gen2driv = new();
driver = new(gen2driv);
generator = new(gen2driv);
.....
endclass
class transaction_generator;
transaction trans;
mymailbox#(transaction) mailbox_h;
function new(mymailbox#(transaction) mbx);
mailbox_h = mbx;
endfunction
...
...
trans = new();
maillbox_h.push(trans);
...
..
endclass
class transaction_driver;
transaction trans;
mymailbox#(transaction) mailbox_h;
function new(mymailbox#(transaction) mbx);
mailbox_h = mbx;
endfunction
...
...
mailbox_h.get(trans);
...
..
endclass