Jump to content

tudor.timi

Members
  • Content Count

    289
  • Joined

  • Last visited

  • Days Won

    33

Reputation Activity

  1. Like
    tudor.timi got a reaction from qwerty in UVM_DEBUG verbosity level   
    You don't find it there because it's not meant to be used by UVM users. Messages flagged with UVM_DEBUG are intended for UVM base class library development and debugging.
  2. Like
    tudor.timi got a reaction from karandeep963 in DUT Model synchronization   
    As David already mentioned, you don't have to keep your model and the DUT in exact lockstep. Most of the times you don't need to care about such micro-architectural aspects that can be verified through other means (like SVAs). Your goal isn't to re-implement the design in all its glory in your testbench.
  3. Like
    tudor.timi reacted to David Black in uvm sequence   
    On the other hand, in order to use the macros correctly, you must learn what each of the macros does. Depending on whether you are using these for sequence_item's (transactions) or sub-sequences, there are only three or four basic steps in either one. Since the experts disagree, we suggest you learn both ways and only once you fully appreciate the differences make a selection. If you don't learn both ways, you may find yourself confused when you stumble over code written by somebody else.
  4. Like
    tudor.timi got a reaction from David Black in (Possible) Bug in uvm_mem   
    I'm trying to declare a memory like this:
    class some_mem extends uvm_mem; function new(string name = "some_mem"); super.new(name, 2 ** 24, 8, "RO"); endfunction endfunction Later on, I'm trying to add this memory to an address map that was created like this:
    default_map = create_map("some_map", 0, 4, UVM_NO_ENDIAN); By using the default value for the byte_addressing argument I want each address to represent a one byte location. The problem I'm seeing is that the uvm_reg_map_info associated with this memory shows an end address of 32'03ff_ffff and a stride of 4, instead of 32'00ff_ffff and a stride of 1. I've narrowed it down to the function uvm_reg_map::get_physical_address(...), at line 1378 of uvm_reg_map.svh:
    int multiplier = m_byte_addressing ? bus_width : 1; I guess this should be the other way around:
    int multiplier = m_byte_addressing ? 1: bus_width; Even better would be to use:
    int multiplier = get_addr_unit_bytes();
  5. Like
    tudor.timi got a reaction from c4brian in sequence DUT synchronization   
    Since you only have one interface you're driving (the DUTs RX if), you can make your life easier and just pass a handle of the RX monitor (looking at the DUTs TX interface) to your sequence using the config DB:
    class my_sequence extends uvm_sequence #(my_item); // handle to the monitor rx_monitor monitor; task body(); // get the monitor handle uvm_config_db #(rx_monitor)::get(p_sequencer, "", "monitor", monitor); // drive first TX wait (monitor.item_finished_e); // drive second TX endtask endclass Somewhere in your testbench you do the corresponding "set". You can use the sequencer's path for the config DB operations (seeing as how the sequences are running on the sequencer and have a handle to that):
    class my_test extends uvm_test; function void end_of_elaboration_phase(uvm_phase phase); uvm_config_db #(rx_monitor)::set(this, "path.to.tx.seqr", "monitor", path.to.rx.monitor); endfunction endclass
  6. Like
    tudor.timi got a reaction from fbochud in constraining sub-sequences in a virtual sequence - best practice?   
    The way you have it set up now is that the size_c constraint is part of the test_vseq scope. This means it only applies when an instance of test_vseq gets randomized. The `uvm_do_on(...) macro includes a call to randomize() on the item/sequence you pass to it. This means the cfg sequence will get randomized without the size_c block. You have two choices here.
     
    1. Use inline constraints:
    `uvm_do_on_with(cfg, p_sequencer.cfg_seqr, { cfg.size_x == this.size_x, .... }; 2. Randomize cfg in test_vseq's scope:
    `uvm_create_on(cfg, p_sequencer.cfg_seqr) if (!this.randomize(cfg)) `uvm_fatal("RANDERR", "Randomization error"); `uvm_send(cfg) The first method is less flexible in that you can't disable or extend the constraint in any way. It's hardcoded. For the second one, you can disable the size_c constraint when randomizing a test_vseq instance inline or you can overwrite it in a child class. For more info on the second method, have a look at my post on constraints from above.
  7. Like
    tudor.timi got a reaction from karandeep963 in ISSUE with 11.4.14 Streaming operators (pack/unpack) if the size of source not even   
    A suggestion for this type of questions: use StackOverflow. There is already a category for SystemVerilog and the you're more likely to get a quick answer.
  8. Like
    tudor.timi got a reaction from karandeep963 in ISSUE with 11.4.14 Streaming operators (pack/unpack) if the size of source not even   
    Also, I remember reading some blog posts on the topic:
     
    http://bryan-murdock.blogspot.de/2014/10/systemverilog-streaming-operator.html
    http://bryan-murdock.blogspot.de/2014/10/more-systemverilog-streaming-examples.html
     
    Have a look at these and see if you can figure out what's happening.
  9. Like
    tudor.timi reacted to mivan in UVM for ESL DUT verification   
    Hello all,
     
    How would one go about leveraging UVM for ES level DUT verification? Most of the stuff from RTL still applies but how do we
    correctly use the driver and monitor if the DUT does not have signals, but has TLM ports/sockets. The UVM states that one agent
    should be used per interface, but the problem on the ESL is that there are no signals so how do we monitor TLM ports/sockets with
    the monitor, while the driver stimulates the DUT? How do we connect ports/exports to the driver, monitor and the DUT simultaneously?
    A solution without using analysis ports would be great. I've included an image for easier reference.
     
    I guess that on ES level the monitor and driver are redundant, but then the sequencer would have to send packets to a checker and the
    DUT simultaneously, which would require either two ports or an analysis port. Another option would be to keep everything the same as
    in the image and have two ports, one from the driver to the DUT, and one from the driver to the monitor and send packets simultaneously.
    Please state your thoughts on this.
     

  10. Like
    tudor.timi got a reaction from David Black in Asynchronous driving/monitoring in a SV-UVM framework   
    I don't think you're going to achieve anything by simulating random delays w.r.t. clock edges in RTL simulations. If you want to see what effect signal delays have you need to run this on (timing annotated) gate level, but that defeats the purpose of doing architecture explorations, 'cause to get to the netlist you've done all steps of the design process.
     
    Also, clock jitters aren't going to bring you anything either. If you care about clock jitter for any clock crossings, then there are specialized tools for this.
     
    Personal opinion: Architecture exploration is something abstract. You want to see if you can get you're desire throughput on your internal bus, you want to see if your modules can work together in the intended way, etc. You don't care about such low level details as delays on input signals or clock jitter.
  11. Like
    tudor.timi got a reaction from David Black in Asynchronous driving/monitoring in a SV-UVM framework   
    Even afterwards, catching timing issues is best done with other tools, not with simulation. Simulation is there to show you that the RTL works, IMO. STA and CDC verification tell you that you don't have timing problems. You already have a huge stimulus space to cover when just considering that your signals come right after the clock edge. Adding randomness to the signal timings is only going to blow up your stimulus space even more. You'd be trying to model way too much.
  12. Like
    tudor.timi got a reaction from soloist_huaxin in multiple analysis_imp in a single class - other than _imp_decl macro?   
    Even so, using your idea you can still add a "`define CLASS_PKG_DEFINE" before including the class instead of importing the package and you haven't solved anything (I'd even go so far as to say you've done more harm than good). This is an issue that you can't fix by coding alone. You have to train people to use packages, pure and simple. If you use a linting tool, you could also catch such issues, by not allowing any user code (except packages) to include any file (maybe with the exception of uvm_macros.svh).
  13. Like
    tudor.timi got a reaction from soloist_huaxin in multiple analysis_imp in a single class - other than _imp_decl macro?   
    Seeing as how you have analysis ports of different types (different parametrizations), you can't use the analysis FIFO approach. Going by way of the macro is your best bet.
     
    You shouldn't have any problems with conflicts because you define these new analysis imports inside the same package where you define your scoreboard (you are using packages, aren't you?). This way, if the same analysis imp is declared in some different package, you're perfectly safe because it's defined in a different scope.
  14. Like
    tudor.timi got a reaction from karandeep963 in uvm reg limitation   
    I don't think there is any hard limitation in place. You just instantiate as many registers as you want. There are no fixed size arrays for the registers to go into. You are, probably, limited by the hardware you're simulating on (i.e. memory), but this has nothing to do with UVM RAL itself.
  15. Like
    tudor.timi got a reaction from karandeep963 in how do we sort the UVM_REG space based on address?   
    The register block doesn't have any knowledge of the register offsets. This is configured in the address map, so you need to call get_registers() from there. I'm not sure in what order the registers will be returned by this method. It doesn't say, so you should consider it an implementation detail and not rely on it. You can sort the output of the method yourself. Here's some code you could try (not tested):
    uvm_reg_map map = model.NTB_DB.default_map; uvm_reg sorted_regs_ntb[uvm_reg_addr_t]; // get all regs map.get_registers(total_regs_ntb); // loop through all of these regs and sort them by their offsets foreach(total_regs_ntb[i]) begin uvm_reg_addr_t offset = total_regs_ntb[i].get_offset(map); // add it to the assoc array sorted_regs_ntb[offset] = total_regs_ntb[i]; end // when you loop through the keys of the assoc array // it should be sorted while (1) begin int idx; if (!sorted_regs_ntb.next(idx)) break; sorted_regs_ntb.next[idx].write(status, wdata, parent(this); end This is code to get you started, so you have to figure out the details. Also, I'm not sure if it works if you have a map that has submaps.
  16. Like
    tudor.timi reacted to uwes in FATAL UVMREG register write operation   
    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"
  17. Like
    tudor.timi reacted to David Black in Configure DUT ports from outside agent   
    Replace start and end address range with another associative array. Populate it with the addresses of interest:
    class i2c_addr_map; ... typedef int unsigned addr_t; typedef addr_t list_t[$]; local list_t slave2addrs[string]; local string addr2slave[addr_t]; // Constructor -- uses default // function to add a slave function void add_slave(string name, int unsigned addr_list[$]); assert(name != ""); //< minimal criteria if (slave2addrs.exists(name)) `uvm_warning("i2c_addr_map","i2c device name already exists! - adding") foreach (addr_list[i]) begin if (addr2slave.exists(addr_list[i]) && addr2slave[addr_list[i] != name) begin `uvm_error("i2c_addr_map","Overlapping i2c address - ignoring") end else begin addr2slave[addr_list[i]] = name; slave2addrs[name].push_back(addr_list[i]); end end endfunction // a utility function to return the slave at a certain address function string get_slave_by_address(addr_t address); if (addr2slave.exists(address)) return addr2slave[address]; `uvm_error("i2c_addr_map","no such i2c device name registered") return ""; endfunction endclass Now you have to add all the addresses:
    addr_map.add_slave("slave1", {'h10,'h11,'h13}); Obviously, you could add methods for adding ranges and make it more complex as you like.
  18. Like
    tudor.timi got a reaction from mramdas in uvm_tlm_analysis_fifo issue   
    Do you create separate instances of packets for each one you put in the FIFO? If you don't, then all entries in the FIFO pointing to the same object, which you just update every time before you write it. This means all FIFO locations will see the updated object.
  19. Like
    tudor.timi got a reaction from David Black in how to start working with uvm   
    Or better yet, test your methods using SVUnit: http://www.agilesoc.com/open-source-projects/svunit/
  20. Like
    tudor.timi got a reaction from David Black in uvm reg limitation   
    I don't think there is any hard limitation in place. You just instantiate as many registers as you want. There are no fixed size arrays for the registers to go into. You are, probably, limited by the hardware you're simulating on (i.e. memory), but this has nothing to do with UVM RAL itself.
  21. Like
    tudor.timi got a reaction from karandeep963 in uvm_tlm_analysis_fifo issue   
    These are basically the same semantics as when calling functions: scalar arguments are passed by value and objects are passed by reference. Not 100% sure (and can't check right now), but arrays are most certainly also passed by reference. In our case, scalars values are stored, whereas object references are stored.
  22. Like
    tudor.timi got a reaction from karandeep963 in uvm_tlm_analysis_fifo issue   
    For int, the integers get stored in the FIFO (there is not pointer type in SystemVerilog, so you couldn't save anything else anyway). But for class objects, the only thing you can save is the pointer (handle/reference - same concept). Think of it conceptually, you want to store stuff somewhere, so you have to use memory to do it. You can't just plug in all of your objects into just one instance. If you are writing and getting from your analysis FIFO on a regular basis, then it's fine, you shouldn't worry about memory consumption.
  23. Like
    tudor.timi got a reaction from karandeep963 in uvm_tlm_analysis_fifo issue   
    Do you create separate instances of packets for each one you put in the FIFO? If you don't, then all entries in the FIFO pointing to the same object, which you just update every time before you write it. This means all FIFO locations will see the updated object.
  24. Like
    tudor.timi got a reaction from karandeep963 in Can we perform UVM_REG read/write access based on Address?   
    You can get the register that is defined at a specific offset using the get_reg_by_offset() method of the register map. Have a look in the class reference for more details.
     
    Note: a big point of using the register access layer is that you don't care at what address a register is defined. This future-proofs your stimulus/checking code, should the offsets change. Have a look at get_reg_by_name() in uvm_reg_block. This allows you to get a register inside a block (hierarchically) without knowing the exact hierarchical path. It takes a string argument, so changing the register name won't break the compile (you have to take care of this at run time), but it's a good compromise (better than hardcoding address values).
  25. Like
    tudor.timi got a reaction from karandeep963 in How to override set_timeout   
    What you could do is call set_timeout(...) again in start_of_simulation() (or end_of_elaboration(), basically any phase that isn't really used) to overwrite the value set by any base class.
×
×
  • Create New...