Jump to content

uwes

Members
  • Posts

    625
  • Joined

  • Last visited

  • Days Won

    11

Everything posted by uwes

  1. hi, normally i have the vlog name and the logical name being the same. exceptions for me are when arrays,QDA etc are involved or when generic code is used some examples when the logical name and the vlog instance path can diverge (for me). /uwe string names[$] ='{"AHB","FOO","BLA"}; uvm_component c[$]; foreach(names[i]) c.push_back(uvm_component::type_id::create(names[i],this)); // stored in assoc array comp["AHB"]=uvm_component::type_id::create("AHB",this); btw althrough its convenient to use the string or logical names they are typically unchecked strings and may certain errors during compile. using the facility has a likelihood to hide static errors and only reveal them at runtime. for most code situations the vlog names are a better choice while for debug situations the string names are the better choice. /uwe
  2. hi, i think this isnt really a question for the SV LRM. it defines that one can interact with the simulator/signals via vpi_put_value() BUT it also defines as to when you can interact with the simulator. I dont think that the simulator is prepared that the vpi functions are invoked at any time, re-are entrant, thread-safe etc (almost everything can happen when you try to operate from a threaded system a potentially not thread aware system (at point the system isnt aware of). another point in the whole discussion is "repeatability". when you rerun a simulation is then thread order, thread timing the same? im not sure if the standard thread implementations care for this ... /uwe
  3. hi, >It looks like it was "accidentally" fixed by the rewrite of the function as a part of that fix, I guess? when i rewrote the function due to the issue raised in the mantis i saw a couple of "suspect" code sections. i havent made a mantis for each suspect area. there is no intent to make a uvm11e. uvm is open source and all bugfixes are avail in the sourceforge repository. if you do require a fix for a particular bug feel free to merge in the one fix you you require....
  4. hi, i think this has been fixed as part of another mantis (http://eda.org/svdb/view.php?id=4885) /uwe
  5. hi tudor, usually the LRM text is "normative". LRM examples are "informative". so unless this is a bigger bug in the LRM i'd say your first quote states the correct behaviour. the example comment is "buggy". /uwe
  6. i filed http://eda.org/svdb/view.php?id=5069 to track the issue /uwe
  7. dave, >so that implies a unique inst_id across all constructed objects derived from uvm_object that cannot be reused. maybe the term "instance counter" is misleading - all the inst-id is about is an unique id for an object. unfortunately UVM does specify another "instance id" on top of the handles the simulator is already using. it is guaranteed that the internal heap id is unique among all existing objects. An internal heap id can only be reused once all references to that object are gone and the object is garbage collected.
  8. hi, >In this case, the simulator doesn't do what the code tells it do you could see it this way - on the other hand from an UVM API perspective there is no guarantee that you are getting an incremental number starting from 0. the get_inst_id() is supposed to return the "object's unique id" as per specification. >but it causes confusion. well its the first time time it causes confusion. when the get_inst_id() and the internal heap id ius is using in all other places would differ then there would be much more confusion. /uwe btw: this functionality obviously is only enabled for uvm_object::m_inst_id
  9. hi, uvm_object::new says that m_inst_id == m_inst_count++. essentially take the current global id then increment the counter. so when you print the object right after its construction you both should be almost the same. as you can see from your log that isnt the case for IUS. the reason for this is that for IUS the m_inst_id is being set to the (internal) heap id of the object in the simulator. the reason for this is that that way simulator internal heap id's does not differ from those printed/used via UVM. regarding dave's points: >First of all, the object is in use until the next object gets created. As long as a class variable holds a handle to a class object, that object must exist. agreed, but in the example code that isnt the case. in the original code the "my_object" gets new() and the old handle isnt used anymore therefore the core can garbage collect the object (and therefore free the IUS internal heap id (the uvm m_inst doesnt reuse id's) >Second, when you construct an object, all class members get initialized with default values. That is independent of any simulator >implementation; the user should not be aware of any reused objects. yes >Third, there is only one static variable m_inst_count for all classes derived from uvm_object. So how could the id not be unique until >you construct the 232th object? m_inst_count is unique as the log indicates. all what happens is that IUS overrides m_inst_id for the newly created object with the heap-id (which is also unique). the difference here is that UVM m_inst_id is unique over the full simulation while the IUS heap id gets reused if an object is disposed. here is an example illustrating that the print of the uvm object showing object with the inst_id 2570 can be as well referenced with TCL cmds as @2570 ncsim> run -next UVM_INFO test387.sv(33) @ 0: reporter [] ----------------------------------- Name Type Size Value ----------------------------------- my_object my_object_t - @2570 ----------------------------------- ncsim> describe @2570 test.my_object_t@2570_1...handle class test.my_object_t extends uvm_pkg::uvm_object { static int next_id = 1 int my_id = 0 const static string type_name = my_object_t static bit use_uvm_seeding = 1'h1 (from class uvm_object) local string m_leaf_name = my_object (from class uvm_object) local int m_inst_id = 2570 (from class uvm_object) static protected int m_inst_count = 448 (from class uvm_object) static handle class uvm_pkg::uvm_status_container __m_uvm_status_container = @425_1 (from class uvm_object) } so this is a feature not a bug. /uwe
  10. hi, to get multiple ports into one component you can A) make one port only and have a wrapper transaction which encodes the source port plus the original transaction use the uvm_subscriber (essentially a component with a single port forwarding the call to the place you want) C) the *_decl macros the decl macros create a new class in the scope where you use the macros. that means you cant use them twice in the same scope with the same argument. /uwe
  11. hi, my initial take is that this is simply due to the fact that you allocate the object but since its unused the object gets garbage collected AND the id gets reused in a subsequent object allocation. the point is that there is that the id's are the actual internal heap id's from the simulator and they are reused (there is no guarantee that an id is uniquie over the whole simulation its only unique in the current set of objects) to prove the assumption simply keep the ref by pushing it into an dyn array. /uwe
  12. hi, i think your problem isnt the example you show. as written test_ben.cpu.block[0].instan[1].set[2] must be a string and if this is the case the code should compile For example : uvm_hdl_force( test_ben.cpu.block[0].instan[1].set[2] ,1 ); BUT the hard question is actually if the path argument A) refers to an instance path in the right language domain (SV,VHDL,SC,..) which the HDL backbone supports (might be vendor dependent) from the vendor support and LRM for your path expression (does the string path involve slices, indices, addon levels via generics) /uwe
  13. hi, this isnt register aliasing (aliasing would be to access the same reg via the same IF on a different address). I think the point here is that uvmreg supports that of course BUT since you cant have multiple sequencer for a map (and you cant have a attach the same map into different parent maps (each with a sequencer)) the path is to create a new map with the same contents as the primary map and just supply a different sequencer for that map. there is another problem here which is the fact that accesses to a register are serialized by the register and not by the lower level infrastructure/bus/arbitration. the result is that if you model a single register in a component (with two slave ports of different busses and both ports can access the same register of the component) then with the setup mentioned below you will NOT get any concurrent accesses to the same register from both busses. essentially the current implementation forces that there can be only ONE ongoing access to a single register instance at a time. /uwe
  14. hi, both prior posts highlight two important points: 1. uvm_report_server's prior to uvm12 could not be chained properly resulting in formatting problems and/or message/error count/display problems. with uvm12 you can chain a vendor server with hyperlinking etc with your formatting. 2. if you have performance issues use the profiler to figure out where time is spend. there are various potential places and without the profiler its just guessing. /uwe
  15. hi, to stay with the common pattern in UVM you should be invoking a function "XYZ()" to get a functionality "XYZ" and implement own functionality which should be considered/run during the execution of "XYZ()" in "do_XYZ()". however you should never invoke do_XYZ directly. this pattern at least applies to pack,unpack,print,compare,record,copy,accept_tr,begin_tr and a few other places and i believe we should stick to the same pattern throughout UVM from my point of view uvm_component::flush and uvm_component::do:_flush are exactly the other way around (and not documented). so essentially 1. uvm_component::flush -> uvm_component::do_flush 2. uvm_component::do_flush -> uvm_component::flush 3. implementation of uvm_component::flush needs to perform traversal and propagate flush() down to children and invoke do_flush() 4. uvm_in_order_comparator::flush -> uvm_in_order_comparator::do_flush 5. do_flush should be virtual
  16. hi, UVM doesnt have a ready to use infrastructure for this. however i do believe with a few building blocks you can accomplish this. 1. i would write a new backdoor deriving from uvm_reg_backdoor 2. each reg with your setup i would set my new backdoor as the backdoor to use instead of the hdl backdoor (.set_backdoor) 3. i would implement the backdoor so that the backdoor has access to to register being accessed currently and via the reg i would have access to the setup of the hdl_backdoor (the path setup) 4. the the standard hdl-path setup i could then choose the right hdl path for a read or a write operation for instance "RTL2-R" for read and "RTL2-W" for write... i havent coded that and there might be problems along the road but i could see this working. /uwe
  17. hi, needs_update() is called as part of update() in order to determine the smallest subset of regs to be written in the update operation. with a volatile reg one has to assume that the reg needs to be written because the value of the reg cannot be determined for sure (it could change right after it has been read). therefore volatile regs do not attempt to determine if they have to be written by comparing desired+value you simply have to write them (if they are accessible). >Before 1.2, the predictor simply stored the register value on read without checking, and write's didn't happen because the register was never written to >explicitly, and randomizing the model didn't change the value, and thus update() didn't touch the register. basically you never wrote the reg because you did assume you know the reg value (which is wrong). the truth is that the regs value can change at any time and update has to unconditionally write the value. or the other way around: update() is a shortcut compared to write() which writes all registers unconditionally so in order to update the right regs/fields volatile have to be included unconditionally. /uwe
  18. hi, this is because of the fact that volatile fields always needed to be updated. there is no way to filter out accesses based upon the knowledge that the write value is already in the register. uvm_reg::update() would otherwise not operate properly on volatile fields. >volatile fields are to be updated, which doesn't work when the underlaying protocol doesn't allow writing to such fields. it sounds as if you are not using the right access policy. the volatile property is orthogonal to the fact that you can access a field . i didnt check in the UVM implementation if the update() operation would omit inaccessible regs. (a (volatile) reg/field with an effective policy NOACCESS should not be attempted to be written) /uwe
  19. hi, "cold" killing a sequence by terminating the thread via fork/join/disable or process::kill very likely hangs the sequence-sequencer-driver interaction and a couple of handshakes. In the good case all you get is a message like the one you show. in the bad case it will render the sequencer in-operational. If you really need to terminate a sequence from the outside then .stop_sequences() and seq.kill(). But also keep in mind that one eventually has to perform add actions like resetting registers semaphores, resetting the driver etc otherwise you did just a reset of one part of your env and the rest is still in flight (for instance if you terminate a sequence which currently executes an item on the driver you need todo something with the driver otherwise the sequencer-driver handshake is out of sync. /uwe
  20. @tudor, the access should go through the map for which you have extracted the addresses. Instead of sorted_regs_ntb.next[idx].write(status, wdata, parent(this); it should be foreach(sorted_regs_ntb[idx]) sorted_regs_ntb[idx].write(status, wdata, parent(this),map(map));
  21. hi, you should be 1. getting all registers of a map via uvm_reg_map::get_registers() 2. get the set of addresses of each reg within that map 3, iterate over the ordered set of addresses /uwe
  22. well, if im not mistaken the tool should have rejected this assignment since its not type compatible in the first place. extern virtual function void set_sequencer (uvm_sequencer_base sequencer, uvm_reg_adapter adapter=null); both should have the same effect. when you distribute the same regmodel to different sequencers then the wildcard is usually better (simpler+faster). i usually prefer the ::get(get_sequencer(),"","reg_model", model) because it avoid the string handling, is to some extend type safe and it doesnt use the m_* variable (which is an uvm internal). Also it might be better to further expand the check. if(!(uvm_config_db#(dutblk)::get(get_sequencer(),"","reg_model", model))) begin if(model==null) `uvm_fatal("NO_REG_CONFIG","reg model set to NULL") end else `uvm_fatal("NO_REG_CONFIG", "Seq reg model was not set"
  23. @Uwe: I think this is how QuestaSim displays null pointer accesses in SV in its console, with SIGSEGV. yes, at the first glance there should no nullptr error in that line given that this is an unmodified uvm11d (you never know). SIGSEGV is a very specific error typically only used by the OS itself. in any case i would think this is a tool issue /uwe
  24. hi, a SIGSEGV is an OS error which you cannot "directly" accomplish with SV. this is a tool error /uwe
  25. hi, some pseudo code (lacking checks,ctor and other things) class vseq1 extends uvm_sequence...; seqr1 s1; seqr2 s2; task body(); ... endtask endclass // with this simply instantiate the sequence assign the sequencers and start it vseq1 = new(); vseq1.s1 = path.to.my.sqr1; vseq1.s2 = path.to.other.sqr1; vseq.start(null); you may also do it via the config-db class vseq1 extends uvm_sequence...; task body(); seqr1 s1; seqr2 s2; uvm_config_db#(seq1type)::get(ctxt,"sqr1",s1); uvm_config_db#(seq1type)::get(ctxt,"sqr2",s2); `uvm_do_on(....) endtask endclass the challenge here is to invent a 'context'. 'null' or get_sequencer() isnt a good context alone here since it would map to uvm_root::get() and doesnt scale. but you could use ctxt=null and {get_full_name(),".sqr1"} as the full path for your virtual sequence plus the "sqr1" postfix /uwe.
×
×
  • Create New...