Jump to content

ljepson74

Members
  • Content Count

    107
  • Joined

  • Last visited

  • Days Won

    3

Posts posted by ljepson74


  1. I am trying to recreate/understand a testbench problem I currently have by creating a small example.  In creating that small example, I am running into a problem.

     

    Below, in the "try1" and "try2" lines, I am attempting to override apple with orange.  Can anyone tell me what I am doing incorrectly?

    package my_pkg;
       import uvm_pkg::*;
    `include "uvm_macros.svh"
    
    class orange extends uvm_component;
       `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 <<<<<<<<<<<<<",UVM_LOW)
       endtask : run_phase
    endclass : orange
    
    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 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);
    
          //try1	apple::type_id::set_type_override(orange::get_type());
          my_uvc=apple::type_id::create("my_uvc",this);
       endfunction : build_phase
    
       task run_phase (uvm_phase 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
    //try2	apple::type_id::set_type_override(orange::get_type());
    	$display("******Start of Sim w/ the kids*******************");
    	testbench = my_testbench::type_id::create("testbench",null);
    	run_test();
         end
    endmodule : top
    

    Running with Cadence irun 13.1, I get the following error when I try "try1".

     

    UVM_FATAL @ 0: reporter [FCTTYP] Factory did not return a component of type 'apple'. A component of type 'orange' was returned instead. Name=my_uvc Parent=my_testbench contxt=testbench
     
     
    irun -sv top.sv -uvm
    

  2. 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.


  3. 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.

     


  4. 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?


  5. 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
    

     


  6. Per my co-worker Jose's suggestion:

     

     

     

    We set up the register sequence as the "default_sequence" for the main_phase.   
     
        // Set the reg_agent sequence to run the uvm_reg builtin sequences
        uvm_config_db#(uvm_object_wrapper)::set(this, "*.m_reg_agent.m_seq_reg.main_phase", "default_sequence", uvm_builtin_reg_test_seq::type_id::get());
     
    What can be done is implement a "reset_phase" in your test that raises an objection, waits for reset to de-assert, waits for some amount of time, then drop the objection.  Your reset_phase will consume simulation time until the dut is ready to run, so then the main_phase isn't started until after your reset phase has completed.  This pushes out the time that your register sequence is started, as it is only run in the "main_phase" of your test.
     
    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.

  7. 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.

     

    post-2891-0-19934800-1379988552_thumb.png

    post-2891-0-43235600-1379988564_thumb.png


  8. 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.


  9. 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?)
     

  10. 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? 

  11.  

    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.


  12. //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.

     

     


  13. Q1) How well do the major simulators support SystemVerilog checkers (1800-2012.pdf Section 17.)?

    Q2) In (the) UVM, do you think there is a place for checkers?

     

    Context)  We have VHDL rtl.   For the data-interface between modules ABC and XYZ, we want to consolidate our protocol checking.  

    case1) ABC testbench.  We now have the protocol checking in the sv interface which ABC and XYZ share

    case2) XYZ testbench.               the same

    case3) Top level testbench (testing DUT which instantiates ABC and XYZ).  Either we have to move the protocol checking to a module which is bind-ed to the VHDL.  Or, we can bind the sv interface to the ABC-XYZ connection, to reuse the protocol checking of that interface.

     

    Without using a macro or `include of the protocol checking code, I'd like to just have a package or some place where we store the protocol checking code and can reuse it, whether in an sv interface, or a module which we bind to the VHDL.  Looking into this, and researching putting assertions into packages, I discovered checkers.  Hence this line of questioning.

     

     

    Please share your thoughts and experience. 

     

     


  14. SPOILER ALERT:  I figured this one out, but since I'd already typed up most of the question, here it is anyhow posted to the public domain.   Comments welcome.

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------

     

    Who can tell me how to pass a hex value into Systemverilog using uvm_cmdline_processor?

     

    My current code is shown below as well as the command line option that is supplied.

     
    code snippet: 
     
       bit [31:0] stimulus_xyz_min = 32'h12121212;             // *** setting default here works fine
    
          `uvm_info(get_type_name(), $psprintf("1st TEST-SETTINGS.  xyz_min=%8h",stimulus_xyz_min), UVM_LOW)
          if (cmdline_proc.get_arg_values(.match("+xyz_min="), .values(arg_values))) begin  
    		stimulus_xyz_min = arg_values[$];  
    	end
          `uvm_info(get_type_name(), $psprintf("2nd TEST-SETTINGS.  xyz_min=%8h",stimulus_xyz_min), UVM_LOW)
    

     

    command line option:   //** this value passed in from cmdline is not properly recognized
    +xyz_min=09090909
     
     
    The edited (for clarity) output is here (where you can see that the above +xyz_min did not 'take'):
    1st TEST-SETTINGS. xyz_min=12121212
    2nd TEST-SETTINGS. xyz_min=30393039
    

     

     
    More +options/results data points listed here:
    +xyz_min=09090909
    2nd TEST-SETTINGS. xyz_min=30393039
    +xyz_min=00000000
    2nd TEST-SETTINGS. xyz_min=30303030
    +xyz_min=00000001
    2nd TEST-SETTINGS.  xyz_min=30303031
    +xyz_min=00000002 
    2nd TEST-SETTINGS.  xyz_min=30303032
    +xyz_min=00000020
    2nd TEST-SETTINGS.  xyz_min=30303230
    

     

    Woo-hoo.  I looked at some other code I was using, which used

     

    stimulus_lkj = arg_values[$].atoi();
    

    and then in the sv spec found atohex.

    Using the following worked (emphasis on .atohex()).

     

          `uvm_info(get_type_name(), $psprintf("1st TEST-SETTINGS.  xyz_min=%8h",stimulus_xyz_min), UVM_LOW)
          if (cmdline_proc.get_arg_values(.match("+xyz_min="), .values(arg_values))) begin
                 stimulus_xyz_min = arg_values[$].atohex();  
          end
          `uvm_info(get_type_name(), $psprintf("2nd TEST-SETTINGS.  xyz_min=%8h",stimulus_xyz_min), UVM_LOW)
    

     

    +xyz_min=1ACECAFE
    2nd TEST-SETTINGS.  xyz_min=1acecafe
    

     

     
    Even thoe I initially thought I was seeing the ASCII values, I mistakenly looked at an ASCII table of decimal-to-char, instead of hex-to-char, which further confused me.
     
    I'd even tried this (as a wild hope that cmdline_processor would recognize it):
       +xyz_min=0x12121212
       +xyz_min=32'h12121212
     

     

×
×
  • Create New...