Jump to content
Sign in to follow this  
mwhite_cp

Is there a way to pass argument to new()?

Recommended Posts

I would like to pass configuration object to seq_item when it is created so that dynamic array size defined in the configuration will be used when it is being created.

Right now, I am using the maximum size to define the dynamic array size when new function is called and let constraints resize the dynamic arrays in sequence. Sequence passes the configuration to seq_item. In the monitor, the default array size (maximum size) is being used.

This works OK but is not a clean way. And the simulation slows down significantly when the maximum size of array is big. I resized dynamic array size in monitor after creation, but simulation is still slow. (Using Cadence simulator.) If dynamic array size bigger than the maximum size is assigned, it does not work.

The ideal way is to pass the configuration as input argument when new() function is called but I am not sure if this is allowed in SystemVerilog/UVM.

What is the best way to handle this?

Thank you for your comments!

Share this post


Link to post
Share on other sites

Systemverilog does not allow you to have multiple constructors, so no additional arguments can be passed to new.

Use the uvm_resource_db or uvm_config_db to define a property for your monitor from your testcase. Get your size property during the build phase in the monitor and initialize your dynamic array with it.

Share this post


Link to post
Share on other sites

Hi there! I don't think there is a need to know the maximum transfer size in the transaction, certainly not to set the maximum size of the data payload. Consider a transaction with a dynamic array of logic[7:0] (or whatever you have) as payload. Any transaction would typically have a means of signalling the start and end of the transaction.

Firstly, in the monitor, when you see the start of the transaction, you new() the transaction and you new() the payload. Then you collect the payload, resizing the payload variable each time. When you see the end of the transaction, you write it to the analysis_port. That way you never need more storage space than each individual transaction ever needs.

Secondly, in the driver/sequencer, you would randomize the size of the payload anyway. You simply pin the size of your dynamic payload array to the same value. Job done. This has worked a treat in Questa for donkey's years. I know the Cadence guys tell you that you have to use a maximum-sized array, but it does work without.

So in your transaction:

rand logic [7:0] pl [];

rand int unsigned pl_size;

...

constraint c_payload {pl_size <= max_payload; pl.size == pl_size;}

When you use that transaction, you can then do a constrain with {pl_size == 10;} to get a transaction with 10 byte payload.

Sorry, you still may need a maximum size, but you can use the max size from the spec of the protocol you are using and it doesn't really matter how big it is. Most of the time you will use much less space for your transaction. You must constrain the size somewhere however, or you run the risk of getting a payload size of maxint. That'll kill your simulation speed...

Hope that helps.

Gunther

Edited by Gunther

Share this post


Link to post
Share on other sites

The only time you need to pre-allocate the array is if it's an object array (because randomize doesn't call constructors for new objects). If that's the case, you'll probably want to create your sequence, then call a sequence function to initialize the array size to what you need before calling randomize on it. (If you're using `uvm_do, you can use `uvm_create and `uvm_rand_send instead and call your initialize function in between.)

Share this post


Link to post
Share on other sites

The only time you need to pre-allocate the array is if it's an object array (because randomize doesn't call constructors for new objects).

Could you please explain what you mean by "object array"? Do you mean the dynamic array itself?

Share this post


Link to post
Share on other sites

Thank you all for response!

jadec, thank you so much for your explanation about pre-allocation. I thought I had to initialize any dynamic array in the constructor. I removed logic array size and object array initialization from the constructor and created function in sequence to initialize the object arrays. That seems to work and simulation runs a lot faster. I am doing the resizing in the monitor based on the configuration, that seems to work fine.

I also need to collect item without knowing dynamic object array size. I would not know the real size until I collect all data that will be stored to object arrays. In this case, do I have to allocate the maximum possible object array size?

Gunther, I use object arrays. It is an array of a class. In my case, I create a class of video line which has dynamic array of video data. I create another class of video frame which has dynamic arrays of line objects.

Thank you for the response and help!

Share this post


Link to post
Share on other sites

jadec, maybe I misunderstood about pre-allocation. I removed integer and object array initialization from the item constructor. Then I added function to initialize the size of object arrays in sequence. I have constraint to resize the size of integer dynamic array in the item. There is no problem with this, it creates object and integer array correctly. In the monitor, I added functions to resize object arrays and integer arrays based on configuration. This seems to work fine. I thought I could remove integer array resizing function because pre-allocation is not necessary. That is not the case. Could you clarify what you meant about pre-allocation? Thanks!

Share this post


Link to post
Share on other sites

For dynamic arrays that you wish to access normally, you'll need to first use "new[len]" to set the size of the array.

int arr[];

arr = new[10];

foreach( arr[ndx] ) arr[ndx] = ndx;

Inside of randomize call, the simulator will automatically do this for resized arrays.

int arr[];

constraint c { arr.size() == 10; }

...

void'(randomize());

For arrays of objects the default value is "null". If you want contents in your objects, you'll need to allocate an object for each entry.

obj arr[];

arr = len[10];

foreach( arr[ndx] ) begin arr[ndx] = new(); arr[ndx].val = ndx; end

Inside of randomize call, the simulator will NOT automatically do this. Thus it is necessary to pre-allocate the objects you might use in randomize.

rand obj arr[];

constraint c { arr.size() == 10; }

...

arr = len[MAX];

foreach( arr[ndx] ) arr[ndx] = new();

void'(randomize());

NOTE: randomize will size the object array automatically, but if new elements are added they will be null.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...