Jump to content


  • Content Count

  • Joined

  • Last visited

About PlayDough

  • Rank

Profile Information

  • Gender
    Not Telling
  1. I bought a couple of books on UVM and am intrigued by it. After reading through the first book, I wanted to give things a try. We do not have any SystemVerilog licenses here at work, so I decided to try to compile the UVM using Vivado's included simulator. I know that Xilinx hasn't announced official support for the UVM, but Vivado does support SystemVerilog, though it appears to be limited to design constructs. Regardless, I decided to proceed. When compiling I get several errors. I know that some are likely limitations on the Xilinx simulator. But some appear to be more generic in nature and I'm not sure if it is a Xilinx issue. I downloaded the UVM 1.2 release and tried to compile using Xilinx's 'xvlog' command with: xvlog --sv --include uvm-1.2/src uvm-1.2/src/uvm.sv And the first few errors: ERROR: [VRFC 10-91] process is not declared [uvm-1.2/src/base/uvm_coreservice.svh:155] ERROR: [VRFC 10-1432] task or function check with ref arguments must be automatic [uvm-1.2/src/base/uvm_spell_chkr.svh:70] ERROR: [VRFC 10-91] process is not declared [uvm-1.2/src/base/uvm_resource.svh:879] ERROR: [VRFC 10-1432] task or function sort_by_precedence with ref arguments must be automatic [uvm-1.2/src/base/uvm_resource.svh:954] ERROR: [VRFC 10-1432] task or function get_highest_precedence with ref arguments must be automatic [uvm-1.2/src/base/uvm_resource.svh:1650] The first error appears to be due to Xilinx not supporting the building 'process' class. I get this one. But the next one seems strange to me. From uvm_spell_chkr.svh, line 70: static function bit check ( /* const */ ref tab_t strtab, input string s); The error text implies this is a language requirement. That is, because 'check' is a static function, the ref argument must be automatic. From a post I found at Verification Academy (see https://verificationacademy.com/forums/systemverilog/what-meant-reference-argument-must-be-automatic), the LRM says in 13.5.2: It shall be illegal to use argument passing by reference for subroutines with a lifetime of static. So it seems that this line violates the LRM. Yet clearly the UVM 1.2 release works with numerous other simulators which are implemented from the same LRM. Is this issue Xilinx specific? Or are there changes to the UVM for these types of errors?
  2. First off, thank you for your responses! You have been very helpful. I'm a bit confused here. Say I had the following class definitions: class base { public: virtual void write(int) = 0; virtual int read() = 0; }; I can define a template class like this: template<typename T> class derived : public base { public: virtual void write(int) { // Do whatever is specific to convert int to T } // Override specific to T virtual void write(T) { } virtual int read() { // Do whatever is specific to convert T to int } // Override specific to T (perhaps the return value is by value) virtual const T& read() { } }; I can then do: base *p = new derived<sc_logic>; I can then access read/write with: p->read(); p->write(0); // Int only. T specific would require a downcast to derived. Getting back to my OP, I'm saying that sc_interface lacks a read/write with conversions from standard types, relying instead upon derived classes to provide them (sc_in_if provides read() and sc_out_if() provides write(), and sc_inout_if derives from sc_in_if and sc_out_if).Granted, I'm no C++ expert (I'm perhaps "upper middle class" in terms of knowledge/experience). However, it seemed that it was a design decision to push the read/write methods to the derived classes (which are templates). I did some reading on type erasure. I get the concept, and I think I know of it implicitly (though your mention of its explicit name is new to me). Your explanation has cleared some things up for me. It appears that in order to be fully generic, I have to explicitly support the various sc_lv<N> options and sc_logic in a factory. I'm not familiar with UVM (only having heard of it). Though I did register on Mentors "Verification Academy" to do some reading on it. Perhaps UVM can already solve what I'm trying to do. Well, to be clear what I'm trying to do is support a dynamic SystemC object for mixed language simulations. The idea is to declare an interface to a testbench object (call it "tb_control") in another language (either Verilog or VHDL), and connect that object to the DUT(s) under test. This "tb_control" object would dynamically determine it's interface (perhaps based on a configuration file) and drive stimulus and verify output. The testbench object would be scripted (language yet to be determined, perhaps embedded Lua).So it's more than just linking in a new library with the additional methods. Of course, this restriction is tool dependent. Unfortunately, the DUT may be in a language other than SystemC. So a wrapper in SystemC for each DUT requires compilation, which is what this exercise is trying to avoid.The ultimate goal is to have a single shared object (call it "tb_control.so") that is pulled into the simulator (we are using Modelsim right now, but the goal is to be cross platform by using SystemC rather than the FLI--though the FLI is significantly easier to use). And being that the DUT language can be Verilog or VHDL, I don't want to rely upon the VPI or VHPI (since not everyone has dual-language licenses). Any, thanks for your responses. They are helpful. I'm going to dig a bit more.
  3. Sure. It appears that the design decision when implementing SystemC (or perhaps even part of the standard) was the use of templates. Or at least, templates deep enough into the class hierarchy to preclude the use of polymorphism to pass around base pointers with relevant methods (though Phillip does point out sc_port_base below, but more on this point in a bit). I get the need for a factory. That isn't the issue. Rather, it was how to read/write a port from a base class, when I don't see a base class that will let me do that. I misread the hierarchy. I followed the template parameters to sc_port<>, rather than sc_port itself. This point, by itself, already sparked an idea. But working through the idea, I'm still hit a roadblock at sc_interface. I can use something like: std::unordered_map<const std::string, sc_core::sc_port_base *> dut_ports; Then, after doing a lookup, I can do something like: sc_core::sc_port_base *port = dut_ports["port_name"]; port->get_interface()->??? The returned pointer from get_interface() is an sc_interface, which has no read/write method. I'd have to downcast it to a templated class (sc_in_if, sc_out_if, or sc_inout_if), which requires a factory. I do get the need for a factory. When I generate the ports on my testbench module, I'll need a factory to create them of the appropriate size. But because of the templated nature of ports, this can become a pain. Given the need to support sc_in/out/inout<sc_logic> and sc_in/out/inout<sc_lv<N> > for N in 1..X, I have to choose X sufficiently large to be useful (128? 256? 1024?) and make that a limitation on the testbench. I can generate the factory with a script for a given value of X, but if X is too small for a particular use, I have to regenerate the factory and recompile. I was hoping there might be a more abstract way to get a pointer an object that I can read/write. Digging in the code, it looks like only sc_in_if has read() and sc_out_if() has write, but both of these are templated classes.
  4. I'm working on a small simulation library based on SystemC for a research project. What I'd like to do is have the I/O from a testbench module be dynamically determined at runtime (perhaps through some sort of configuration file). The point is to avoid recompilation and have the testbench dynamically configure itself to accommodate the UUT. The problem is not that I cannot traverse the hierarchy (I've figured that out) and get the ports. The problem is that I cannot seem to dynamically generate a "database". Since all the ports are templated, I can't generate a generic data structure for all ports. For example, I'd like to be able to do something like: std::unordered_map<const std::string, ????> dut_ports; I don't know what to use for ????. I've thought of using some sort of generic wrapper, e.g.: struct port_wrapper { template<T> port_wrapper(T port_) port(port_) { } T port; }; But this is still a problem since T isn't known until runtime. Is there a way to store a "generic" pointer to a sc_in, sc_out, or sc_inout? Looking through the source code, it looks like everything is parameterized all the way back until sc_interface. But sc_interface doesn't provide any methods to access the port (i.e. read/write). Any hints or suggestions?
  • Create New...