Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


alangloria last won the day on November 11 2015

alangloria had the most liked content!

About alangloria

  • Rank

Recent Profile Visitors

298 profile views
  1. UVM 1.2 Visitors: class visitor_capable_wrapper#(type NODE=uvm_void, TYPE=uvm_component) extends uvm_visitor#(NODE); local TYPE actual; function new(TYPE actual); this.actual = actual; endfunction virtual function void begin_v(); this.actual.begin_v(); endfunction virtual function void visit(NODE node); this.actual.visit(node); endfunction virtual function void end_v(); this.actual.begin_v(); endfunction endclass virtual class visitor_capable#(type NODE=uvm_void, BASE=uvm_component) extends BASE; `uvm_component_param_utils(visitor_capable#(NODE,BASE)) function new(string name, uvm_component parent); super.new(name, parent); endfunction virtual function void begin_v(); endfunction pure virtual function void visit(NODE node); virtual function void end_v(); endfunction function uvm_visitor as_uvm_visitor; visitor_capable_wrapper#(NODE,visitor_capable#(NODE, BASE)) rv; rv = new(this); return rv; endfunction endclass : visitor_capable This way, you can make any component (sequencer, driver, monitor, agent, scoreboard...) be a visitor. You probably need another visitor_capable_object so that UVM objects can also be converted to UVM Visitors, but well. Sincerely, AmkG
  2. Yeah, and the answer was, "when our overseas mother company upgrades". ^^
  3. Thank you for checking on other simulators. Our shop has only one simulator, so I couldn't check. I fear that even if the pattern is technically valid under IEEE 1800-2005, it might not be a common use model and simulators might not handle it correctly. Even our IUS10.2 occasionally crashes if you make an otherwise-unrelated syntax error if I use this pattern; if I remove this pattern and leave in the syntax error the compiler will report the syntax error correctly. Using mixin classes and a few helper classes, it's possible to emulate multiple inheritance to the point that you can treat a class as being derived from multiple classes, with a lot of coding overhead. For example, see below: // This is the "unrelated" class that can be converted to. // Notice it is not derived from a UVM base class. virtual class frobnicatable_base; pure virtual task frobnicate; endclass // This is a helper class to translate from your class // to frobnicatable_base class frobnicatable_base_param#(type this_type = frobnicatable_base) extends frobnicatable_base; // this is where the magic happens! this_type actual; function new(this_type actual); this.actual = actual; endfunction virtual task frobnicate; actual.frobnicate; endtask endclass // You can derive from this class via frobnicatable#(uvm_component) // to get multiple inheritance of frobnicatable and uvm_component: class frobnicatable#(type BASE=uvm_component) extends BASE; typedef frobnicatable#(BASE) this_type; `uvm_component_param_utils(this_type) function new(string name, uvm_component parent); super.new(name, parent); endfunction // perform frobnication virtual task frobnicate; `uvm_info("FROBNICATE", "The component was frobnicated!", UVM_NONE); endtask : frobnicate // conversion to frobnicatable base function frobnicatable_base as_frobnicatable_base; frobnicatable_base_param#(this_type) rv; rv = new(this); return this; endfunction endclass : frobnicatable With this, you can create a queue of frobnicatable objects, which can be monitors, drivers, sequencers, agents, scoreboards, etc., but all of which are frobnicatable. frobnicatable_base frobnicatables[$]; virtual function build_phase(uvm_phase phase); super.build_phase(phase); monitor = my_frobnicatable_monitor::type_id::create("monitor", this); driver = my_frobnicatable_driver::type_id::create("monitor", this); sequencer = my_frobnicatable_sequencer::type_id::create("sequencer", this); .... frobnicatables.push_back(monitor.as_frobnicatable_base); frobnicatables.push_back(driver.as_frobnicatable_base); frobnicatables.push_back(sequencer.as_frobnicatable_base); endfunction : build_phase This technique is called "proxy object", and is another technique I picked up from Boost C++ library.
  4. Hi UVM and SystemVerilog users, I've stumbled upon a particular pattern of writing a "utility" class, which I have called "mixin". class derived_class#(type BASE=base_class) extends BASE; .... endclass : derived_class This pattern was inspired by some C++ Boost code I saw, where the base class is templated. The reasoning was that under some compilers, multiple inheritance had higher overhead than chains of inheritance (specifically, an "empty" base class might be allocated the minimum size, so multiple inheritance would increase the size of the object, but if you used a chain of inheritance and a derived class in the chain was "empty" (i.e. did not add any data members), it would not increase the object size). So instead of inheriting from multiple C++ classes, you'd typedef a class like foo<bar<nitz> > and derive from that. Since SystemVerilog has no multiple inheritance, I thought this pattern would be appropriate for use in SV, to at least ease some of the "oh no SV has no multiple inheritance oh no" pain. I've defined a simple utility class, utility::slave_sequence_item (utility is a package) defined like so: class slave_sequence_item#(type BASE=uvm_sequence_item) extends BASE; local uvm_barrier wait_barrier_; local uvm_barrier fin_barrier_; `uvm_object_param_utils_begin(utility::slave_sequence_item#(BASE)) `uvm_field_object(wait_barrier_, UVM_ALL_ON) `uvm_field_object(fin_barrier_, UVM_ALL_ON) `uvm_ojbect_utils_end function new(string name=""); super.new(name); wait_barrier_ = new("wait_barrier_", 2); fin_barrier_ = new("fin_barrier_", 2); endfunction // to be called by sequence task wait_for_transaction; wait_barrier_.wait_for; endtask task finish_transaction; finish_barrier_.wait_for; endtask // to be called by driver task indicate_transaction; wait_barrier_.wait_for; finish_barrier_.wait_for; endtask endclass : slave_sequence_item Basically, this slave sequence item class adds three new methods. By default, you just derive from utility::slave_sequence_item. But if you already have an existing sequence item type derived from uvm_sequence_item, you just do typedef utility::slave_sequence_item#(my_sequence_item) my_slave_sequence_item; and the added methods and variables will get "mixed in" the my_slave_sequence_item type. What do you think? I've tested it on Cadence IUS10.20-s103, and it seems to work properly. From my understanding of the IEEE standard, the above is not specifically disallowed (but then it might not be well supported on actual simulators).
  • Create New...