Jump to content


  • Content Count

  • Joined

  • Last visited

Everything posted by Logger

  1. You should use a register model with multiple uvm_reg_maps. One per interface. Assuming you're generating your register model using some sort of tool (rather than by hand), you need to find out how your tool supports that.
  2. You need to provide more detail. Like, why do you currently have to select one at compilation time? What exactly do you mean by parallel access? Do you have 3 separate physical interfaces which can simultaneously access the same register? Or as often the case, do you have 3 masters which can all access the same registers via a fabric and a single physical interface to the registers? What are you using for your register model? RAL ( uvm_reg ) ?
  3. Looking for suggestions on the best approach to modeling something akin the following. value1 and value0 are implemented as value_reg[31:0] in RTL. The value actually stored in this register is always whatever you wrote to it. However, what you read back, and what HW sees when it looks at this register depends on the value of value_mode. When value_mode == DIRECT, you'll read back the whatever value is physically stored in value_reg[15:0] as value0 and value_reg[31:16] as value1. When value_mode == MULT, you'll read back a computed value instead. Let quotient == value_reg[15:0
  4. The short answer is yes. However, from the way you worded your question, I'm immediately inclined to use the PLI/VPI instead of the DPI. There are a lot of ways to skin this cat. If you want more guidance, you'll need to give more details about what you're trying to accomplish.
  5. Seen quite a few posts on various forums like this. Moving your register model to UVM-1.2 yields a bunch of warnings like this. [uVM/RSRC/NOREGEX] a resource with meta characters in the field name has been created As far as I can tell this is a bug in uvm_reg_block::configure(). If special regex characters are not allowed in the call to uvm_resource_db#(uvm_reg_block)::set(), then this function needs to sanitize the return value from get_full_name before passing it to set. get_full_name() is return hierarchical paths with dots in them, as it is supposed to, but those are regex ch
  6. This section of the LRM is vague. 18.11 In-line random variable control What is the expected behavior for the following code? class child; rand int a; rand int b; constraint cb { a inside {[0:100]}; b inside {[0:(2*a)]}; } endclass class parent; //Uncomment to force desired behavior: rand int a; rand child c; constraint cb { //Uncomment to force desired behavior: a == c.a; c.b >= c.a; } //Uncomment to force desired behavior: function void pre_randomize(); //Uncomment to force desired behavior: a = c.a; //Unco
  7. Bonus points for testing what happens when you change the constraint to the following: constraint c_1 { soft var1<100; }
  8. What am I missing here? Say you model an APB transaction that includes a cycles_before_delay member. The driver will have to implement that like this: seq_item_port.get_next_item( item ); // stall for item.cycles_before_delay; // do transaction seq_item_port.item_done( ); During that stall, no other transaction will be able to execute on that driver. Now there was the suggestion of forking this, but you can't call get_next_item() again, until you first call item_done(). Calling item_done() before the transaction is actually completed, is a non-blocking completion model, as the sequen
  9. So in the scenario where the spec says write register A, then wait 40 cycles before writing register B. You propose modeling that 40 cycle delay at the end of A, or the beginning of B. I know that is how a lot of models do it, but that doesn't make it right. In the case of APB, I'd like to allow other sequences to write to other registers during that delay. Which implies I now need to implement what otherwise would have been a simple in order atomic driver, as a non-blocking driver, so it can fork threads and return immediately. In addition to that, the sequence using the APB transa
  10. Good points. I've been real lazy about directly referring to m_sequencer rather than using get_sequencer(). You point out a good reason to stop that. I concur. I don't like this approach for two reasons: First and foremost, the delay before or after a transaction is not part of that transaction (mixing abstractions agains), but it is part of the sequence containing that transaction. Hence, the sequence needs some mechanism to perform delays. And time based delays doesn't cut it, so it needs to be cycle delays. Second, it requires you use a non-blocking
  11. I kind of have a gripe against directly referring to the interface from a sequence for these common use case scenarios. Different sequences on different interfaces can be doing the same thing, but implement it differently and it looks different. m_sequencer is the window/proxy by which a sequence knows which interface it is operating on. I was just meaning to say a virtual wait_cycles() method in the uvm_sequencer_base, would make it possible for all sequences to call m_sequencer.wait_cycles(x) without having to refer directly to the interface. That of course adds the burden of having to ex
  12. I have made it a standard practice to add a wait_cycles() task to all my sequencers to abstract this. Then in my sequences I can simply write: p_sequencer.wait_cycles(x); This requires you use the `uvm_declare_p_sequencer() macro in your sequence. Too bad that's not built into uvm_sequencer. -Ryan
  13. But that's the problem, this "standard operating procedure" is not a documented procedure, nor is it a single procedure. No two people do it the same way, and good luck finding an example when you google or search the UVM forums. You'll mostly likely come across someone raising the question, but it's never answered. So is there no canned solution, because we haven't yet agreed on how this should be implemented in the general case? Or is it just one of those things that UVM hasn't gotten around to yet?
  14. It would be really nice to be able to receive TLM messages in some sequences for the purposes of coordinating stimulus with monitored events. I have a solution which gets the job done, but it's not as clean as it should be, and this missing feature feels like a gaping hole in the methodology. I think a very nice solution would be to have uvm_analysis_imp#() class either implement the get() method, or maybe more clearly have a new method called wait_for_write( T t ). You could then extend your sequencer to have a uvm_analysis_imp#(), and use `uvm_declare_p_sequencer() in your sequen
  15. Why does uvm_reg_map::get_n_bytes() return 0 if you call it on a system level map? That is completely useless and tells me nothing about the system. If on the other hand, I call uvm_reg_map::get_n_bytes() from a lower level map in my register model, then I get the narrowest bus width in the map hierarchy. That makes sense. It seems I should get that same value when calling get_n_bytes() on the system level map. Returning 0 is not useful under any circumstance.
  16. To be a little more precise here, the field macros do call uvm_config_db::get() for component fields in the component's build_phase. uvm_config_db::get() is not called for non-phased objects like uvm_sequence_items or plain uvm_objects.
  17. I figured out an example for master and slave ports. Not exactly what I was looking for, but since I didn't find such an example in the UVM docs I thought I'd post it here for you reading pleasure. program test; import uvm_pkg::*; class Master extends uvm_component; uvm_master_port#(uvm_sequence_item) port; `uvm_component_utils(Master) function new(string name="Master", uvm_component parent=null); super.new(name,parent); port = new("port",this); endfunction // new virtual task run_phase(uvm_phase phase); uvm_sequence_item item = new("master_item");
  18. I want to create a master model that performs a non-blocking put to a slave. Later, I expect the slave to do a blocking put back to the master. So my master should have a uvm_nonblocking_put_port and a uvm_blocking_put_imp. I'm trying to figure out if one of those bidir port types includes that combination. It's kind of hard to decipher the TLM code. Anyone know of example code using the bidir ports?
  19. You could add an event to the sequence's events pool. Once you've randomized the sequence_item in the sequence, trigger the event passing the sequence_item as the parameter. The test can then wait on that event, and get the sequence_item to get at the address. edit: If this is a pre-existing sequence, that you don't want to modify, extend it instead. You can put the event trigger in the mid_do() or post_do() methods, which ever is appropriate.
  20. First, why do a type override of the from your module? You can do that in your test's build_phase instead. Since you are trying to access a member that is not present in the base_env class, you can't use a base_env class handle to access that member. You'll have to use a x_env handle. In this case, you'd have to cast the object like so: class x_test extends base_test ; function start_of_simulation(); x_env x; $cast(x,env); x.x_agent.set_report_verboisty(UVM_FULL); endfunction endclass
  21. Could you post the very obvious error message as well your verbosity override code or runtime switch?
  22. Oh sweet relief. Thanks Janick. I did not manage to find that one in Mantis. I look forward to this enhancement.
  23. I think the performance issue have largely been addressed since that article was written. Probably still room for improvement though. My biggest problem with the macros is tracking down the source of compile errors. Practice has made me a lot better at divining the source of the macro based compile errors. And I do mean divining in the divining rod sense. I still end up commenting out large blocks of code and doing a binary search occasionally, because the error message says something like "UVM is from Venus and Engineers are from Mars". That said, I think I'm still saving significant
  24. What is the proper use of begin_tr() and end_tr() and their associated events? There are these very nice descriptions for begin_event and end_event. // Variable: begin_event // // A <uvm_event> that is triggered when this transaction's actual execution on the // bus begins, typically as a result of a driver calling <uvm_component::begin_tr>. // Processes that wait on this event will block until the transaction has // begun. // // For more information, see the general discussion for <uvm_transaction>. // See <uvm_event> for details on the event API
  • Create New...