Jump to content


  • Content Count

  • Joined

  • Last visited

  1. my_custom_t could be any user-defined type, such as typedef struct packed { logic parity; logic [7:0] data; } my_custom_t; I realized that I had a problem with the abstract class, which was originally defined as virtual class my_abstract#(type T=byte, string Tname=""); pure virtual task transact(input my_trans#(T, Tname) trans); endclass : my_abstract I fixed the concrete class to class my_concrete extends my_abstract#(T, Tname); But, the call to transact from the monitor, which has a handle to my_bfm via the configuration database, still causes the error where the formal
  2. I have a method inside a concrete class defined in a module to be instantiated in the testbench. The concrete class handle is passed to the UVM agent. I chose this approach over virtual interfaces to minimize the proliferation of parameters, because the interface by definition includes a decent set of parameters. I do need to support a type parameter for modeling the data in any way useful for the verification environment, and a corresponding string parameter that is the type's name for UVM factory reasons that I won't delve into. Anyway, here is example code to illustrate what I'm trying
  3. If you're talking about different encapsulations, then you can go about it in one of two possible ways: Define a single packet model that is flat, and includes knobs (random and non-random) to determine if a particular header is present or not. Define a class hierarchy/family of packet types. I think #1 is simpler and less unwieldy to deal with. Does that sort of address your question?
  4. Thanks, Dave. Actually, the with range needed to match the declared range of bit_vector: bit_array = {<<{bit_vector with [packer.count-1:0]}}; The fatal was resolved; I overlooked something, and it had nothing to do with the streaming assignment after all.
  5. No need. You can have your sequencer send down the packet streams in parallel threads, and define your sequence arbitration scheme however you wish (or leave it default if that's good enough). You could also set up a single stream that can mix up the packet types using random constraints or whatever. Technically, you could add more TLM connections between the sequencer and driver, but that's probably unnecessary. Besides, the driver can only push one packet at a time onto your interface, so the infrastructure that already exists between the sequencer and driver works quite well in a lot
  6. I'm stuck on a problem I encountered with a use of the streaming operator to unpack into a dynamic array. Rather than write procedural code, I thought I could use it actually with some amount of success. Here is what the code more or less looks like: uvm_pack_bitstream_t bit_vector; bit bit_array[]; ... bit_vector = packer.get_packed_bits(); {<<{bit_array with [0 +: packer.count]}} = bit_vector; myfunc(bit_array); Yes, I'm trying to use "unadvertised" features of the UVM packer here. This has worked in many cases, but there is one case that led to the following: # *
  7. I think one way you can do what you're trying to do is to set up a UVM heartbeat that watches for activity. There is a very good paper written on this. I think you can find it in the contributions area. Basically, you need logic that raises an objection to allow the simulation to run further, and drop it when you detect enough inactivity during a given window (a timeout mechanism). That's the basic idea that I think is what you might be looking for.
  8. Can't you detect SOF and EOF from the serial input that you're monitoring? Wouldn't that be a more reliable way to collect your packets instead of knowing the packet length ahead of time, and drive a fixed loop with that? How can you know the packet length before you even start collecting the packet in the monitor? I don't get it. I would also add the pkt_len variable to the transaction class, and let do_unpack determine the length and save it to the variable in the transaction. That way, the length is always coupled with the packet it belongs to. Anyone else interested in a packet's
  9. Have you checked the UVM class reference? The function prototype for unpack_bytes is function int unpack_bytes(ref byte unsigned bytestream[], input uvm_packer packer = null); You declared dataout (the actual) as an array of 10-bit values, which does not match in type with the bytestream argument (the formal), which is typed as an array of 8-bit values in the prototype. You need to pass in an array of bytes. You'll probably have to design your own 10b8b conversion in your decoder before unpacking into your packet.
  10. Assuming the driver and monitor share the same parent (agent), which is conventional, then you can access any public (i.e. not local, not protected) variables through the parent handle: Agent: my_driver m_drv; my_monitor m_mon; Driver: int unsigned m_pkt_len; Monitor: my_agent m_parent_handle; int unsigned m_pkt_len; // Not the same as m_pkt_len in the driver. ... task run_phase(uvm_phase phase); $cast(m_parent_handle, get_parent()); // Capture the handle of the parent, which should be the agent. m_pkt_len = m_parent_handle.m_drv.m_pkt_len; // Copy packet length
  11. In do_unpack, you can return the total packet size by querying the packer, then calculate the payload size by subtracting the known sizes of the other fields: virtual function void do_unpack(uvm_packer packer); int unsigned packet_size_in_bytes; super.do_unpack(packer); packet_size_in_bytes = packer.get_packed_size() / $bits(byte); payload_size_in_bytes = packet_size_in_bytes - ( ($bits(sync) + $bits(sof) + $bits(header) + $bits(crc) + $bits(eof)) / $bits(byte) ); // -- Allocate the payload array. // -- Unpack everything here. endfunction : do_unpa
  12. In general, the better way is to use analysis FIFOs, or instantiate multiple subscribers, rather than the imp_decl macros.
  13. Does VCS support UVM transaction recording? How can I do that? Latest I have available is 2011.12, and I'm supposedly using a UVM 1.1 implementation provided by Synopsys. I found some blurb about $vcdplusmsglog to record transaction streams. Don't tell me that I have to sprinkle that code into my UVM code base alongside the begin_tr/end_tr stuff. The UVM I have is intended to run on multiple simulators. BTW, Questa and Incisive have UVM transaction recording with next to no additional effort to enable.
  14. I agree. However, the issue described is related to type parameters, not value parameters. There are more limitations to overriding types, and none of the major simulators, as far as I know, supports overriding types from the command-line, such as a -g option (for generic) or from a params file. I suppose I could encapsulate the data item with a UVM object, develop a bunch of various classes for that, and use the factory override, which can be dictated by the test class. But, what if I want to keep it lightweight, and be able to override the data item within the transaction with a variety
  15. What's the best way to define the actual data type from a test, and set the module side accordingly? In the class side, the sequence item has a data member. Its type is parameterized, and it's intended to be overridden usually with some sort of bit vector of any size (e.g. bit[N-1:0], packed struct). The rest of the classes are parameterized on this data type. Similarly, the module side is parameterized (interface, top-module). If I define a particular type in a test class, then how can that pass over to the module side? Thanks for any ideas and opinions.
  • Create New...