Jump to content


  • Content count

  • Joined

  • Last visited

  • Days Won


bhunter1972 last won the day on August 11 2016

bhunter1972 had the most liked content!

About bhunter1972

  • Rank

Profile Information

  • Gender
  • Location
    Palo Alto, CA

Recent Profile Visitors

419 profile views
  1. I've found a use for set_int_local and noticed that it does not work with dynamic arrays or queues. Issue can be demonstrated with this code: https://www.edaplayground.com/x/6B8e The problem appears to be on the first line of this code block: else if(uvm_is_match(str__, {__m_uvm_status_container.scope.get_arg(),$sformatf("[%0d]", index__)})) begin \ if(index__+1 > ARG.size()) begin \ int sz = index__; \ int tmp__; \ `M_UVM_``TYPE``_RESIZE(ARG,tmp__) \ end \ if (__m_uvm_status_container.print_matches) \ uvm_report_info("STRMTC", {"set_int()", ": Matched string ", str__, " to field ", __m_uvm_status_container.get_full_scope_arg()}, UVM_LOW); \ ARG[index__] = uvm_object::__m_uvm_status_container.bitstream; \ __m_uvm_status_container.status = 1; \ end \ At this line, str__ is set to "cfg.arr_var[0]", this: {__m_uvm_status_container.scope.get_arg(),$sformatf("[%0d]", index__)} evaluates only to "arr_var[0]", hence the match does not succeed. I believe that the code would be correct if it used get() instead of get_arg().
  2. UVM requires that the sequencer first stop its sequences and then the driver must be certain to not call item_done on any outstanding sequences. To get this working correctly, there's a simple recipe in this paper from a few years ago, and also in the book: http://sunburst-design.com/papers/HunterSNUGSV_UVM_Resets_paper.pdf
  3. Improving transaction recording

    Only if recording is enabled for that transaction. To do that, you need to call the enable_recording() function and give it a stream.
  4. I can do even better. You can go here and press Click Inside to look at it yourself: http://tinyurl.com/h7nfgbz
  5. how to use uvm_in_order_comparator

    I find it to be a perfectly reasonable alternative to writing your own comparator. I'm not sure why back in 2012 was considered old. But it does only do one thing. If you need any more advanced comparisons, then it's not that useful. Implementing do_compare in your class is a pretty simple thing to do. Once done, the do_compare provides the ability to create your own custom comparators that can provide more flexibility.
  6. Your sequence has a handle to the sequencer it runs on, called p_sequencer. You can create a TLM imp there, and a TLM port in your block_cfg_mngr component, and then write the data from the port to the imp. Your sequence can then see the value using its handle to the sequencer.
  7. Under the right circumstances, UVM 1.2 can report an error such as this one: 'uvm_test_top.some_sequence' attempted to raise on 'run', however 'run' is not a task-based phase node! (This is a UVM_PHASE_IMP, you have to query the schedule to find the UVM_PHASE_NODE) This is perplexing because obviously, run is a task-based phase, and one might think that UVM is off its rocker. But the real issue is what is found in the parentheses. This came up while migrating a codebase to 1.2 (not the funnest of tasks, thank you very much). The user had this code working in 1.1d: some_sequence.set_starting_phase(uvm_run_phase::get()); Now, however, that get() call returns a UVM_PHASE_IMP and not the NODE itself. Most users probably don't care about the difference between these, as it has nothing to do with finding RTL bugs. In any case, the above code must be replaced with something like this so that the NODE is used instead: some_sequence.set_starting_phase(uvm_domain::get_common_domain().find(uvm_run_phase::get())); This is not exactly the prettiest solution, but it seemed to work for me. Can anyone suggest a better solution?
  8. predictor / TLM model paradigm

    Agree, although I cannot speak for everyone's design or algorithm that they are trying to verify. There are generally two types of predictors: "white models" and "scoreboards." There are plenty of other names for the same things, but generally they boil down to those two. The difference between them is that the former tries to emulate exactly what the RTL does and perform a cycle-by-cycle comparison, whereas the latter sees stimulus input and predicts what the design will do at some point in the future. Of course, there are varying degrees to which these descriptions hold true. For example, a white model might not handle error cases very cleanly, but generally gets everything else correct. The advantage of the white model is that an error is generated very quickly once the device gets out of sync. The disadvantage, as you said, is that as the implementation matures the white model must be re-coded every time. This, in my experience, is a fatal flaw. But again, it depends on what you're trying to verify. The scoreboard approach, meanwhile, provides flexibility for the design to change over time. It also usually has less "granularity" to its predictions. For example, if a series of memory writes to contiguous addresses are expected, followed by a "DONE" cycle, a less granular scoreboard would not predict each and every memory write transaction and the done transaction. Instead, it would model the memory and only look at the final results once the DONE is seen. This approach gives the design the flexibility to chop up these writes as it sees fit and makes things easier for us. Especially in a constrained random environment, because the variety of stimulus can be arbitrary and outrageous, the white model is generally unacceptable.
  9. So, it was fixed? Was a new version of UVM 1.2 released? Or is it part of UVM 1.3?
  10. At Cavium, we hand edited our version of UVM (egads!) to explicitly allow periods. Although, we felt that asterisks and a few others were probably a bad idea. I know I'll probably get hate mail for abusing the standard like that, but we've got chips to make. Here is a patch that you can apply: Index: 1_2/src/base/uvm_resource.svh =================================================================== --- 1_2/src/base/uvm_resource.svh (revision 329382) +++ 1_2/src/base/uvm_resource.svh (working copy) @@ -1412,7 +1412,8 @@ `ifndef UVM_NO_DEPRECATED begin for(int i=0;i<name.len();i++) begin - if(name.getc(i) inside {".","/","[","*","{"}) begin + // CAVM: Permit periods inside instance names + if(name.getc(i) inside {"/","[","*","{"}) begin `uvm_warning("UVM/RSRC/NOREGEX", $sformatf("a resource with meta characters in the field name has been created \"%s\"",name)) break; end
  11. Come say hi at DVCon 2016 in San Jose on March 2nd at the Real Intent panel! http://dvcon.org/content/event-details?id=199-126
  12. When should we use uvm export

    I've been told that the explanation I have in my book is clear, so I'll just put this here. The diagram in the text helps a lot, but hopefully this will work: When initiating transactions up through a hierarchy, ports can talk to other ports just fine. Imps, though, are always the end of the line. To push transactions down through a hierarchy, TLM provides exports. Exports promote an imp to a higher level in the hierarchy. From another component’s point of view, they look exactly like an imp, but the real imp is buried someplace within the hierarchy. With exports, the external component need not know anything about the lower-level hierarchy. Knowing that I shouldn't pass up a chance to advertise, you can get the book at: http://tinyurl.com/AdvancedUVM????
  13. Randomization of dynamic arrays

    The data array will be created implicitly based on the .size(), if it isn't already created, whenever you randomize the class. However, if you allow the simulator to do this implicitly, then you lose the ability to constrain any of the array's variables, which may or may not be something you care about. If you do, then here's how I do this. First, in my class's new function, I new the array to whatever the largest possible size will be. This is important, and perhaps a little wasteful. Second, I constrain the data.size() as you have above. Third, I can then constrain the data bytes, usually using a foreach constraint. When the class is randomized, the data will automatically re-size itself and constrain the data appropriately. So, like this: class pushk_c extends uvm_object; rand int unsigned data_len; constraint data_len_cnstr { data_len < MAX_DATA_LEN; // some parameter or constant } rand byte data[]; constraint data_cnstr { data.size() == data_len; foreach(data[idx]) { data[idx] == idx; } } function new(string name="pushk"); super.new(name); data = new[MAX_DATALEN]; endfunction : new endclass : pushk_c I would prefer not to self-promote, but I will anyway. I demonstrate this a few times in my book: http://tinyurl.com/AdvancedUVM, or for the e-book: http://tinyurl.com/AdvancedUVM-ebook
  14. For your specific case, you might consider an alternative frontdoor path. With this method, you create a sequence that runs on--well, any sequencer really--and is assigned to the A & B registers using set_frontdoor. This sequence extends uvm_reg_frontdoor and contains an 'rw_info' variable. This rw_info variable holds the information of the transaction. Based on the value of C, the registers can then be manipulated like any other. Consider: uvm_reg chosen_reg; uvm_reg_status status; chosen_reg = (p_sequencer.reg_block.C.SELECTOR.get() == <A_SELECTED>)? p_sequencer.reg_block.A : p_sequencer.reg_block.B; if(rw_info.kind == WRITE) chosen_reg.write(status, rw_info.value[0]); else begin uvm_reg_data_t value; rw_info.value = new[1]; chosen_reg.mirror(status, value); rw_info.value[0] = value; end It's something like that. Not to be too self-aggrandizing, but my book demonstrates this method more clearly: http://tinyurl.com/AdvancedUVM. or the e-book: http://tinyurl.com/AdvancedUVM-ebook.