Jump to content

ljepson74

Members
  • Content Count

    107
  • Joined

  • Last visited

  • Days Won

    3

Everything posted by ljepson74

  1. Is there any free systemverilog simulator (w/ UVM support) for small amounts of code? i.e. perhaps a vendor offers the license for free, to hook newbies and students, restricting them to less than 1000 lines of code or something?
  2. ljepson74

    simple override example - with error

    Allowable creation times: transaction objects versus testbench components Can someone comment on why I/we cannot create a component after the build_phase, or even during the run_phase. (See UVM_FATAL note above.) I think I understand the philosophy behind or difference between 'statically instantiated hierarchy' 'dynamically instantiated hierarchy' 'transaction objects' as Doulos breaks it down in their literature. But, I haven't dug enough into the UVM base-class to understand what prevents component creation during this time.
  3. ljepson74

    simple override example - with error

    Thanks a lot for the feedback, uwes and adiel. Below is my code that works and the relevant output. Commenting out the override line reverts back to apple, as expected. package my_pkg; import uvm_pkg::*; `include "uvm_macros.svh" class apple extends uvm_component; `uvm_component_utils(apple) function new(string name, uvm_component parent); super.new(name,parent); endfunction : new task run_phase (uvm_phase phase); `uvm_info("UVC","run_phase: Executing. Apple run_phase<<<",UVM_LOW) endtask : run_phase endclass : apple class orange extends apple; `uvm_component_utils(orange) function new(string name, uvm_component parent); super.new(name,parent); endfunction : new task run_phase (uvm_phase phase); `uvm_info("UVC","run_phase: Executing. Orange run_phase<<<<",UVM_LOW) endtask : run_phase endclass : orange class my_testbench extends uvm_component; apple my_uvc; `uvm_component_utils(my_testbench) function new(string name, uvm_component parent); super.new(name, parent); endfunction : new function void build_phase(uvm_phase phase); super.build_phase(phase); apple::type_id::set_type_override(orange::get_type()); //Replace apple with orange my_uvc=apple::type_id::create("my_uvc",this); endfunction : build_phase task run_phase (uvm_phase phase); //my_uvc=apple::type_id::create("my_uvc",this); //**1 cannot create a component in run phase `uvm_info("TESTBENCH","run_phase: Executing. Testbench run_phase<<<<",UVM_LOW) endtask : run_phase endclass : my_testbench endpackage : my_pkg module top; import uvm_pkg::*; `include "uvm_macros.svh" import my_pkg::*; my_testbench testbench; initial begin $display("******Start of Sim w/ the kids*******************"); testbench = my_testbench::type_id::create("testbench",null); run_test(); end endmodule : top ******Start of Sim w/ the kids******************* UVM_INFO @ 0: reporter [RNTST] Running test ... UVM_INFO top.sv(39) @ 0: testbench [TESTBENCH] run_phase: Executing. Testbench run_phase<<<< UVM_INFO top.sv(20) @ 0: testbench.my_uvc [UVC] run_phase: Executing. Orange run_phase<<<< Sharing with other newbies something I 'learned': See commented out line "**1", which gave the below error and taught me that I cannot create components after build. It makes sense, but I had never thought about it before. UVM_FATAL @ 0: my_uvc [iLLCRT] It is illegal to create a component ('my_uvc' under 'testbench') after the build phase has ended.
  4. Apologies for not replying yet to those that replied. I am still getting back to it. Thank you for your replies.
  5. May a module or interface have default 'no-connect' port connections, for ports that we don't need to connect? I need to use an interface which is shared between testbenches. I instantiate it a lot and don't use many of the ports (i.e. they can be 'no connects') Using Cadence irun, I get this warning when I don't connect inputs to the interface: ncelab: *W,CUVWSI With tasks/functions, I can have a default value for an input argument. Is there anything similar for interfaces (or modules for that matter)? Rather than creating a bunch of dummy inputs for these ports that are not relevant to me, I'd like to change the interface somehow to clear up the warnings for cases where I don't want to use them. trying to clean up some warnings, thanks Note: the interface inputs mentioned are being used for a small piece of internal control logic in the interface. I suppose someone might suggest using parameterized interfaces. I don't recall offhand, but believe there is a reason that we are not using a parameterized interface for this. I'll have to check with the original developer.
  6. Thanks a lot, Uwes. That helps. As a simple/quick solution, I think I am going with #1 (and a clear note that the transaction type is mostly irrelevant, so as not to confuse whomever inherits my code). I tried #2 and ran into some trouble. If I explore it (#2) more and am still stuck, I'll post here.
  7. We are using TLM to pass transactions from SystemVerilog to SystemC. I have two cases where I am stuck. Actually, it is the same case, but I have two angles to my question. 1) Is it possible to still use a TLM setup, but without a transaction type. (I realize that this is contradictory to the acronym.) A c-model has a debug function which takes no input arguments. So, when the SV testbench runs into a problem, it can call this function in the SystemC/c-model. As all of our connections now are sc_port/sc_export, with TLM, I'd like to stick with that flow if possible, rather than adding DPIs/VPIs/(PLIs) or any other mechanism to communicate between languages. However, since the function has no input arguments, I don't need a transaction type. So, is there a way to do a TLM call without a transaction type? (I suppose I could just use another transaction type and ignore the data.) 2) Imagine the above c-model input function that takes no input arguments. Let's say now that the c-model function takes a single integer as its input. So, now I do have a transaction type, but a very simple one. It seems like overkill, but do I still need to define matching .h and .svh (that extends uvm_sequence_item) transcation types and the related do_pack, do_unpack, etc. routines? It seems like overkill. I suspect that I must, if I want to use TLM. (Given that the answer to this question must be, yes, does anyone out there just use a generic grab-bag transaction type for cases like this?) //my thought of passing a transaction which is just an int in sv tb: uvm_blocking_put_port #(int) sb_debug_call1_to_cmodel; in sc c-model public tlm::tlm_blocking_put_if<sc_int <32>> //or smthg like that Any thoughts? I know I just need to refresh myself on DPIs, but answers to the above question are welcome.
  8. ljepson74

    UVM_FATAL invokes $finish(1)

    I suppose that Adiel means here: http://www.eda.org/svdb, but you probably don't have permissions to create a mantis item there. It appears that he might be able to file it on your behalf.
  9. Q1) Is there truth to the hearsay that the Technical Committee (UVM Working Group) will/might remove run_phase's twelve sub phases (pre_reset, reset, etc.)? If so, when might we expect it? Q2) When is UVM 1.2 expected? Q3) I am just looking into precompiling the uvm base class for our testbenches. (I suppose that I would need two versions, one with -linedebug and one w/o.) Does anyone have any comments about pre-compiling the UVM base class as I now work thru an example?
  10. Additional info: [263]irun -version TOOL: irun 13.10-s006 [264]nchelp ncvlog EXPENC nchelp: 13.10-s006: © Copyright 1995-2013 Cadence Design Systems, Inc. ncvlog/EXPENC = The keyword 'endclass' was expected to terminate the declaration of a class. It was not found.
  11. In my earlier UVM days I ran into this confusing error message a number of times. I just hit it again, so am posting my solution here, to share and to help myself rediscover when it is time. Error (running IUS 13.1): uvm_analysis_imp_my_snoop #( xyz_trans, my_scoreboard) my_snoop_port; | ncvlog: *E,EXPENC (/user/goblin_dev/tb/my_scoreboard.svh,60|50): Expecting the keyword 'endclass'. Below is the pseudo code w/o the error. In converting the real code to pseudo code (to make it more succinct and sterilized), I do not believe I created any inconsistencies, but this is not what was compiled, of course. `uvm_analysis_imp_decl(_my_snoop) class my_scoreboard extends uvm_scoreboard; `uvm_component_utils(my_scoreboard) uvm_analysis_imp_my_snoop #( xyz_trans, my_scoreboard) my_snoop_port; function void build_phase(uvm_phase phase) my_snoop_port = new("my_snoop_port",this); endfunction : build_phase function void write_my_snoop( xyz_trans t ); //guts here endfunction : write_my_snoop endclass : my_scoreboard The error occurred when the following line was missing from above. `uvm_analysis_imp_decl(_my_snoop) So, without this macro called, the uvm_analysis_imp_my_snoop class is not declared. So, I would think that the error message would instead say that the class was not found. (I should try removing some random class that my tb needs and see what error message appears - b/c that is the error message I would expect here as well.) Appendix: The following code is taken from uvm-1.1/uvm_lib/uvm_sv/src/macros/uvm_tlm_defines.svh : // MACRO: `uvm_analysis_imp_decl // //| `uvm_analysis_imp_decl(SFX) // // Define the class uvm_analysis_impSFX for providing an analysis // implementation. ~SFX~ is the suffix for the new class type. The analysis // implemenation is the write function. The `uvm_analysis_imp_decl allows // for a scoreboard (or other analysis component) to support input from many // places. For example: // //| `uvm_analysis_imp_decl(_ingress) //| `uvm_analysis_imp_decl(_egress) //| //| class myscoreboard extends uvm_component; //| uvm_analysis_imp_ingress#(mydata, myscoreboard) ingress; //| uvm_analysis_imp_egress#(mydata, myscoreboard) egress; //| mydata ingress_list[$]; //| ... //| //| function new(string name, uvm_component parent); //| super.new(name,parent); //| ingress = new("ingress", this); //| egress = new("egress", this); //| endfunction //| //| function void write_ingress(mydata t); //| ingress_list.push_back(t); //| endfunction //| //| function void write_egress(mydata t); //| find_match_in_ingress_list(t); //| endfunction //| //| function void find_match_in_ingress_list(mydata t); //| //implement scoreboarding for this particular dut //| ... //| endfunction //| endclass `define uvm_analysis_imp_decl(SFX) \ class uvm_analysis_imp``SFX #(type T=int, type IMP=int) \ extends uvm_port_base #(uvm_tlm_if_base #(T,T)); \ `UVM_IMP_COMMON(`UVM_TLM_ANALYSIS_MASK,`"uvm_analysis_imp``SFX`",IMP) \ function void write( input T t); \ m_imp.write``SFX( t); \ endfunction \ \ endclass
  12. Per my co-worker Jose's suggestion: So, I didn't try to tamper with the builtin reg sequences or any generation scripts at all. I simply added a reset_phase to my register test, to delay the start of (main_phase) the builtin reg sequences, like this: task dmx_rg3_reg_test::reset_phase(uvm_phase phase); `uvm_info("dmx_rg3_reg_test", "Running register test reset_phase. Raising objection", UVM_LOW); phase.raise_objection(this); wait (env.m_dmx_rg3_fiver_agent.m_vif.resetn); repeat (12) begin @ (posedge env.m_dmx_rg3_fiver_agent.m_vif.clk); end `uvm_info("dmx_rg3_reg_test", "Running register test reset_phase. Dropping objection", UVM_LOW); phase.drop_objection(this); endtask : reset_phase I realize a more robust solution would be to do a wait on the proper reset, instead of the combo of doing the wait on the top-level one (which I did via the m_vif above), and then overshooting the delay of the reset that is used, by waiting an addition 12 clk cycles. I may change that. anyhow, Case Closed.
  13. I've run into the following issue using the built-in UVM register tests. The built-in UVM register tests (seem to) start R/W-ing immediately after top-level reset is released. This was fine, initially. See attached image "Capture". We now have some delay between the release of top-level reset and the actual reset going to the register block. This is resulting in a read occurring before reset to the rtl regblock is released, and causes the test to hang. See attached image "Capture2". Without modifying the built-in register tests/sequences, how would anyone suggest that we cleanly delay the stimulus? Perhaps I just need to make the stimulus aware of the different reset when the model/stimulus is generated, or simple add some delay to a phase before the R/W-ing starts. (The former sounds right. If that's the solution, I'll need to figure out how we're generating the model/stimulus.) I've just started hunting around for the built-in UVM register test sequences and will return to it tomorrow, but will anyone tip me off as to what names I should be searching for? thanks This has been useful, https://verificationacademy.com/cookbook/registers/builtinsequences, but it seems I need to do some more reading and hunting before I grasp how the built-in register stimulus is created and used.
  14. Thank you very much Alan and Ajeetha. Ajeetha, I have not tried $stable yet, but it is on my list to do. I've played around with my version of Alan's example quite a bit and discovered that I needed to qualify the third stage** of the assertion with a check that valid==1. Thank you both for your help. **I'm not sure if 'stage' is the proper term. Below is my working code and crude testbench (using irun 12.2-s004). You'll notice that I created two assertions. One to check that "new_data==1" works and one to check that "new_data==0" works. If anyone knows a readable way to combine these into a single assertion, please share. module top; bit clk; logic valid, new_data; logic [1:0] data; property new_data_1_works; logic [1:0] prev_data; (valid, prev_data = data) ##1 ~valid[*0:$] ##1 (new_data && valid) |-> (data !== prev_data); endproperty property new_data_0_works; logic [1:0] prev_data; (valid, prev_data = data) ##1 ~valid[*0:$] ##1 (!new_data && valid) |-> (data === prev_data); endproperty always begin #5 clk = ~clk; end new_data_yes : assert property (@(posedge clk) new_data_1_works) else begin $warning("OUR ASSERTION new_data_1_works FAILED."); end new_data_no : assert property (@(posedge clk) new_data_0_works) else begin $warning("OUR ASSERTION new_data_0_works FAILED."); end initial begin clk = 1; valid=0; new_data=0; #14; repeat (10) begin clock(1); end repeat (10) begin clock(2); end repeat (10) begin clock(3); end repeat (10) begin clock(4); end $finish; end task clock(input int my_type); @(posedge clk); #2; case (my_type) 1 : begin valid=1'b1; new_data=1'b1; data=$urandom; end 2 : begin valid=1'b1; new_data=1'b0; data=$urandom; end 3 : begin valid=1'b1; new_data=$urandom; data=$urandom; end 4 : begin valid=$urandom; new_data=$urandom; data=$urandom; end default : begin valid=1'bX; end endcase endtask always@(posedge clk) begin $display($time, " valid=%1b, new_data=%1b, data=%1x",valid,new_data,data); end endmodule : top //Notes to self /*Put this into the initial block and use this in place of the top assertion. Note the missing valid in 3rd stage. (valid, prev_data = data) ##1 ~valid[*0:$] ##1 (new_data) |-> (data !== prev_data); //Here I showed to myself that I must must qualify the 3rd stage of the above assertions // with valid being true. (ex: new_data && valid) //This is done by trying to make new_data_yes fail on a non-valid cycle here. // // Below, two cycles of 'good' data is generated. // Then valid is dropped to 0 (entering the 2nd stage of the assertion - I don't know correct terminology for this). // Then without raising valid to 1, we can move to the 3rd stage by setting new_data=1. (which was my problem) // I suppose I had focused on the "~valid[*0:$]" being what controlled when we moved to the 3rd stage of the assertion, but // realize now that is not correct. // The 2nd stage can stay true (i.e. valid=0) for as long as it will, but each clock we are just looking for what is after // the "##1" to move on to the next stage. In this case, new_data==1. @(posedge clk); #2; valid=1'b1; new_data=1'b1; data=2'b10; @(posedge clk); #2; valid=1'b1; new_data=1'b1; data=2'b01; @(posedge clk); #2; valid=1'b0; new_data=1'b0; @(posedge clk); #2; valid=1'b0; new_data=1'b0; @(posedge clk); #2; valid=1'b0; new_data=1'b1; //error will fire now b/c new_data==1. @(posedge clk); #2; valid=1'b0; new_data=1'b1; $finish; */ Thanks again. Thinking more about my question of combining the assertions, I am wondering why the implication operator would be used at all, and why I couldn't just do a check like ( valid && ( (new_data && (data!==prev_data)) || (!new_data && (data===prev_data)) ) ) I'll experiment with this later. Comments very welcome.
  15. Assertion experts, I know how to do a check of new_data_io (see below) in terms of 'regular' SV code, but will someone comment on how/if I can put this into a nice assertion to put into my interface? All based on posedge clk: valid_io - indicates valid data data_io - the data new_data_io - signifies that data_io has changed since the previous valid_io cycle So, when (valid_io && (!new_data_io)), the receiver can just use the most recently valid data. (The fact that there can be cycles of !valid_io, while this assertion is active, is what's throwing me off. Well, and also the concept of retaining previous state of data_io. Perhaps this might not be suitable for an assertion and I should just stick with a small process to do the check.) thx for any feedback, Assertion Novice (Why ever did I loan out my book Art of Verification with SystemVerilog Assertions by Faisal Haque?)
  16. I had expected all 3 of these calls to randomize to return values using the constraint. However, the first does not. Can anyone tell me why? (note: In the following code, there is no local randomize method defined. So, I think that all randomize functions are the same...and perhaps only scope varies.) Code, followed by sim results: class thursday_seq extends junk_seq_seq; //which extends uvm_sequence rand int count; constraint c1 { count >= 2; count <= 9; } function new(string name="thursday_seq"); super.new(name); if (std::randomize(count)) begin `uvm_info("",$psprintf(" cnt=%0d .....",count),UVM_LOW) end else $finish; if (randomize(count)) begin `uvm_info("",$psprintf(" cnt=%0d .....",count),UVM_LOW) end else $finish; if (this.randomize()) begin `uvm_info("",$psprintf(" cnt=%0d .....",count),UVM_LOW) end else $finish; $finish; endfunction:new `uvm_object_utils(thursday_seq) UVM_INFO @ 0: reporter@ [] cnt=415747889 ..... UVM_INFO @ 0: reporter@ [] cnt=9 ..... UVM_INFO @ 0: reporter@ [] cnt=2 ..... It seems what is happening is that while std::randomize and randomize are calling the same method in the standard package, the standard version is oblivious to local constraints. I see in 1800-2012.pdf (SV spec), sec. 18.5.2 "The randomize() method is virtual and therefore honors constraints of the object on which it was called, ..." (highlighting mine) Later in the spec, there is reference to the 'scope of the randomize(' which confuses me a bit, if the constraints are always to be honored. (Although, I suppose in the first two cases above "of the object on which it was called" is not true, b/c I don't call it on the object, but on a property of the object.) Is that correct? After doing a bunch more reading, I am going to continue with this post for feedback. Here is something more I learned. This quote in section "18.12 Randomization of scope variables—std::randomize()" I think explains it all for me. "The scope randomize function, std::randomize(), enables users to randomize data in the current scope without the need to define a class or instantiate a class object." I'm a bit unsure, but I think the answer to my question is this. "without the need to define a class" and "in the current scope", from above, imply that std::randomize performs only on the scope that is passed to it. i.e. if I pass it a class object, then it knows of that object's constraints. If I pass it a data-member of a class, then the scope that data-member exists in is not seen (i.e. any constraints which are in the scope above that data-member are not seen). Though they could be replicated as inline constraints.). The local randomize knows of all the constraints in the object from which it is called. Do I understand this correctly? I think I just walked myself through understanding this. Comments welcome. thx, note: using Cadence's IUS12.1-s004
  17. Dave, thanks a lot for this great answer. I've just found myself Google-ing and returning to this answer 2+ times since I originally read it. (I guess some things don't stick so well with me.)
  18. Alan, that was a fantastic explanation. That makes sense to me. Thank you very much.
  19. Below I define a uvm_scoreboard. Why will this not compile when I remove the (3) lines THIS AND THAT? Should it? `uvm_analysis_imp_decl(_rcvd_pkt) //THIS class dpx_rr_scoreboard extends uvm_scoreboard; `uvm_component_utils(dpx_rr_scoreboard) virtual function void write_rcvd_pkt(input some_trans t); //AND THAT endfunction : write_rcvd_pkt //AND THAT endclass : dpx_rr_scoreboard I am using irun 12.X and get the following error when I remove the aforementioned lines: class dpx_rr_scoreboard extends uvm_scoreboard; | ncvlog: *E,FAABP1 (/user/posedgeclk/tb/dpx_rr_scoreboard.svh,25|46): task, function, or assertion instance does not specify all required formal arguments [10.2.2][10\ .3(IEEE)]. I poked around in the uvm class library just a bit, but did not figure this out. Any ideas? Is this a uvm thing or Cadence thing (trying to enforce that I write sensible code) or just fooling thing on my part? I am asking Cadence directly as well, but wanted to throw this out to the crowd. **I am just trying to get a shell of a scoreboard compiling, and don't care that it doesn't do anything yet. Let's ignore the fact that I don't have uvm_analysis_imp_rcvd_pkt created.
  20. Ok. I am still obviously climbing up the UVM/SV learning curve. Adding an implementation of new allows my shell of a scoreboard to compile. I did not need to do anything with analysis import. (This makes me ponder deleting this entire post right now.) class dpx_rr_scoreboard extends uvm_scoreboard; `uvm_component_utils(dpx_rr_scoreboard) function new(string name="scoreboard_", uvm_component parent = null); super.new(name,parent); endfunction : new endclass : dpx_rr_scoreboard I see now that uvm_scoreboard is an abstract class, as specified by the "virtual" in front of the first line of its definition: "virtual class uvm_scoreboard extends uvm_component;" I have read that classes extended from an abstract class must provide implementations for all of the abstract class' pure virtual methods. However, "new" is not a pure virtual method. So, I am a bit confused about this. Can anyone enlighten me?
  21. Please ignore this question. Further research being conducted now.
  22. //This is not a question, but me storing some debug notes online, lest I run into this problem again. //good for debugging this issue, print_topology in particular. Put them in your test. `uvm_info("TEST",$psprintf(" TOPOLOGY..............................."),UVM_HIGH); uvm_top.print_topology(); `uvm_info("TEST",$psprintf(" CONFIG_DB_DUMP..............................."),UVM_HIGH); uvm_config_db::dump(); //When a sequence doesn't run, double-check the following. //in the test (or wherever) where we assign the sequence to run on a sequencer uvm_config_db#(uvm_object_wrapper)::set(this, "*.dpx_xyz_agent_m.dpx_xyz_seq.main_phase", "default_sequence", dpx_xyz_simple1_seq::type_id::get()); //compare the name of the sequencer with the name that is given to the factory for the sequencer, when it is created //where we create the sequencer (in the agent), what name did we supply to it with the factory? m_seq = dpx_xyz_sequencer::type_id::create("dpx_xyz_seq", this); //make sure they match. This problem has bitten me a few times.
  23. Uwe, Thank you very much for that feedback. Those seem to be the techniques I should have been using. I'll give them try and add them to my debug arsenal.
  24. Thanks, Alan. I tried a simple example and discovered that checkers aren't supported in irun 12.2. I don't know about the other simulators, and suppose that time will tell whether the gurus that prescribe style/best-practices will find a place for checkers in the UVM.
×