Jump to content

cliffc

Members
  • Content Count

    47
  • Joined

  • Last visited

  • Days Won

    2

cliffc last won the day on September 8 2014

cliffc had the most liked content!

About cliffc

  • Rank
    Junior Member

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Using VCS, I can compile and run multiple top-level modules. In the example I am running, I have a dut module and a bind-file module. The bind-file module is nothing more than: module bindfiles; bind dut pLib_dut p1 (.*); endmodule When I compile and run, I indeed see both top modules have been compiled: Top Level Modules: bindfiles dut And both run just fine as expected. Now the question: If I compile both top modules, can I run simv with just the dut module and ignore the bindfiles module? I would like to simulate both with the bindfiles and without the bindfiles module if possible without re-ocmpiling. Thanks - Cliff Cummings Sunburst Design, Inc.
  2. It is very common to include two identical agents in a UVM testbench. One uses a default-active sequencer-driver pair and the other sets an is_active bit to uvm_passive to disable the sequencer-driver pair. Both monitors are identical and sample the VIF signals to re-assemble a standard transaction that is then sent through the monitor-analysis port to the agent-analysis port and on to both sides of the scoreboard. Since the analysis port can write to multiple analysis export/imp-ports, when building simple UVM testbenches, why not just use one active agent that drives both sides of the scoreboard and discard the passive agent? Regards - Cliff Cummings
  3. The parameterized uvm_driver base class includes a built-in uvm_seq_item_pull_port called seq_item_port. The parameterized uvm_sequencer base class includes a built-in uvm_seq_item_pull_imp called seq_item_export. These are always connected in the agent. Every UVM agent that I create declares a uvm_analysis_port that I connect to the tb_monitor's uvm_analysis_port. Question for UVM Library Developers: Is there any reason the uvm_agent base class should not enhanced to be parameterized to the transaction type and include a built-in uvm_analysis_port? Regards - Cliff Cummings
  4. The parameterized uvm_driver base class includes a built-in uvm_seq_item_pull_port called seq_item_port. The parameterized uvm_sequencer base class includes a built-in uvm_seq_item_pull_imp called seq_item_export. These are always connected in the agent. Every UVM agent that I create has a tb_monitor extended from the uvm_monitor and everyone declares a uvm_analysis_port. Question for UVM Library Developers: Is there any reason the uvm_monitor base class should not be enhanced to be parameterized to the transaction type and include a built-in uvm_analysis_port? Regards - Cliff Cummings
  5. Thanks @cgales - This was indeed one of the biggest issues with this example. Regards - Cliff Cummings
  6. Hi, All - My thanks to those who responded and especially to my friends and colleagues, Tom Fitzpatrick of Mentor and Heath Chambers of HMC Design Verification for helping me to spot and correct the problems. The biggest issue was that I passed the sequencer and predictor handles to the reg-model using the set_sequencer command. I should have passed the sequencer and adapter handles to the set_sequencer command. This caused the null-handle references (SIGSEGV - this was not a tool issue - this was my mistake): ERROR: model.dutmap.set_sequencer(agnt.sqr, predict); CORRECT: model.dutmap.set_sequencer(agnt.sqr, reg2dut); Two other useful modifications were to store the model handle created in the env class using the uvm_config_db as shown: NEW: uvm_config_db#(dutblk)::set(this,"agnt.sqr","reg_model", model); Better than what I had: OLD: uvm_config_db#(dutblk)::set(this,"*","reg_model", model); This stores the reg model handle in the uvm_config_db, accessible from the env.agnt.sqr. I also modified how the tr_seq_base class extracts the reg model handle from the uvm_config_db using the command: if(!(uvm_config_db#(dutblk)::get(null,m_sequencer.get_full_name(),"reg_model", model))) `uvm_fatal("NO_REG_CONFIG", "Seq reg model was not set" The reference to m_sequencer.get_full_name() returns the full name of the sequencer where the uvm_config_db has the stored model handle. The example is now running. Thanks! Regards - Cliff Cummings
  7. Hi, All - I am hoping someone can spot my error in the following example. I am missing a handle while running a test and getting a handle fatal message. I am not 100% sure I am assigning the correct dutmap and the error happens when I try to do a reg-write from the tr_sequence. Pertinent code below. More code upon request. Regards - Cliff From test1.sv: task run_phase(uvm_phase phase); tr_sequence seq = tr_sequence::type_id::create("seq"); //---------------------------------------- phase.raise_objection(this); //`uvm_do(seq) //seq.start(null); seq.start(e.vsqr.tb_sqr); phase.drop_objection(this); endtask From tr_seq_base.sv dutblk model; rand logic[15:0] data; uvm_status_e status; ... task body; get_model(); endtask // Tried getting the reg_model handle two different ways - not sure either is working virtual function void get_model(); uvm_object tmpobj; `uvm_info("TR_SEQ_BASE",{"get_full_name: ", get_full_name()},UVM_FULL) if(uvm_config_object::get(get_sequencer(),"","reg_model", tmpobj)) if (!($cast(model, tmpobj))) `uvm_fatal("TR_SEQ_BASE", "BAD config cast operation") //`uvm_info("TR_SEQ_BASE",{"get_full_name: ", get_full_name(),".agnt.sqr"},UVM_FULL) //if(!(uvm_config_db#(dutblk)::get(null,{get_full_name(),".agnt.sqr"},"reg_model", model))) //`uvm_fatal("NO_REG_CONFIG", "Seq reg model was not set") endfunction From tr_sequence.sv task body; super.body(); `uvm_info("TRSEQ","going to randomize this.data",UVM_DEBUG) assert(this.randomize()); `uvm_info("TRSEQ","going to reg-write data",UVM_DEBUG) model.gp_reg0.write(status, data, .parent(this)); // *** FAILS HERE *** `uvm_info("TRSEQ","done reg-write-ing data",UVM_DEBUG) assert(this.randomize()); model.gp_reg1.reg1.write(status, data, .parent(this)); From env.sv tb_agent agnt; vsequencer vsqr; dutblk model; // Register model object reg2dut_adapter reg2dut; // Bus adapter object uvm_reg_predictor#(trans1) predict; // predictor component ... function void build_phase(uvm_phase phase); super.build_phase(phase); agnt = tb_agent::type_id::create("agnt", this); vsqr = vsequencer::type_id::create("vsqr", this); model = dutblk::type_id::create("model"); reg2dut = reg2dut_adapter::type_id::create("reg2dut"); predict = uvm_reg_predictor#(trans1)::type_id::create("predict", this); model.build(); model.lock_model(); // TRIED storing this handle two ways uvm_config_object::set(this,"*","reg_model", model); //uvm_config_db#(dutblk)::set(uvm_root::get(),"*","reg_model", model); endfunction function void connect_phase(uvm_phase phase); super.connect_phase(phase); `uvm_info("ENV",{"get_full_name.vsqr: ", get_full_name(), ".vsqr.tb_sqr"},UVM_DEBUG) `uvm_info("ENV",{"get_full_name.sqr : ", get_full_name(), ".agnt.sqr"},UVM_DEBUG) vsqr.tb_sqr = agnt.sqr; `uvm_info("ENV","copied agnt.sqr handle",UVM_DEBUG) model.dutmap.set_sequencer(agnt.sqr, predict); //predict.map = model.default_map; predict.map = model.dutmap; predict.adapter = reg2dut; // connect the predictor to the bus agent monitor analysis port agnt.aport.connect(predict.bus_in); endfunction From dutblk class: class dutblk extends uvm_reg_block; `uvm_object_utils(dutblk) rand gp_reg0_reg gp_reg0; // General Purpose Reg0 rand gp_reg1_reg gp_reg1; // General Purpose Reg1 uvm_reg_map dutmap; // dutregs bus map // Function: new // function new(string name = "dutblk"); super.new(name, UVM_NO_COVERAGE); endfunction // Function: build // virtual function void build(); gp_reg0 = gp_reg0_reg::type_id::create("gp_reg0"); gp_reg0.configure(this); gp_reg0.build(); gp_reg1 = gp_reg1_reg::type_id::create("gp_reg1"); gp_reg1.configure(this); gp_reg1.build(); dutmap = create_map("dutmap", 'h0, 2, UVM_LITTLE_ENDIAN); default_map = dutmap; dutmap.add_reg(gp_reg0, 'h0, "RW"); dutmap.add_reg(gp_reg1, 'h2, "RW"); lock_model(); endfunction endclass FATAL error message from : model.gp_reg0.write(status, data, .parent(this)); // *** FAILS HERE *** # UVM_INFO env.sv(42) @ 0: uvm_test_top.e [ENV] get_full_name.vsqr: uvm_test_top.e.vsqr.tb_sqr # UVM_INFO env.sv(43) @ 0: uvm_test_top.e [ENV] get_full_name.sqr : uvm_test_top.e.agnt.sqr # UVM_INFO env.sv(45) @ 0: uvm_test_top.e [ENV] copied agnt.sqr handle # UVM_INFO verilog_src/questa_uvm_pkg-1.2/src/questa_uvm_pkg.sv(272) @ 0: reporter [Questa UVM] End Of Elaboration # UVM_INFO verilog_src/uvm-1.1d/src/seq/uvm_sequencer_base.svh(1385) @ 0: uvm_test_top.e.vsqr [PHASESEQ] No default phase sequence for phase 'run' # UVM_INFO verilog_src/uvm-1.1d/src/seq/uvm_sequencer_base.svh(1385) @ 0: uvm_test_top.e.agnt.sqr [PHASESEQ] No default phase sequence for phase 'run' # UVM_INFO tb_driver.sv(40) @ 0: uvm_test_top.e.agnt.drv [iNIT] Initialize (time @0) # UVM_INFO tb_driver.sv(29) @ 0: uvm_test_top.e.agnt.drv [DEBUG: Driver Run] ... getting next item ... # UVM_INFO tr_seq_base.sv(30) @ 0: uvm_test_top.e.agnt.sqr@@seq [TR_SEQ_BASE] get_full_name: uvm_test_top.e.agnt.sqr.seq # UVM_INFO tr_sequence.sv(21) @ 0: uvm_test_top.e.agnt.sqr@@seq [TRSEQ] going to randomize this.data # UVM_INFO tr_sequence.sv(24) @ 0: uvm_test_top.e.agnt.sqr@@seq [TRSEQ] going to reg-write data # ** Fatal: (SIGSEGV) Bad handle or reference. # Time: 0 ns Iteration: 50 Process: /uvm_pkg::uvm_sequence_base::start/#FORK#294_b7048b8 File: /home/packages/questasim_10.3c/questasim/linux/../verilog_src/uvm-1.1d/src/reg/uvm_reg.svh # Fatal error in Task uvm_pkg/uvm_reg_map::do_write at /home/packages/questasim_10.3c/questasim/linux/../verilog_src/uvm-1.1d/src/reg/uvm_reg_map.svh line 1734
  8. Hi, @UWES - Thanks for the comments. I was not using a virtual sequencer and I believe I also was extending my tr_sequence from uvm_sequence instead of my tr_seq_base class. I am past this problem and am still having issues but will open a different thread. Regards - Cliff
  9. Hi, All - Hoping for a little help on this one. I have a very simple UVM register testbench but am having troubles getting it to work and having troubles figuring out the correct way to start the tests (there is lots of documentation on UVM REG setup except the final step of starting the test). Below is the error messages, the env.sv fle and the test1.sv file that I am using. I would be happy to tar-up the entire example if someone would like to look at more of my files. Thanks to anyone who can figure out this problem. Regards - Cliff # UVM_INFO verilog_src/uvm-1.1d/src/reg/uvm_reg_map.svh(1062) @ 0: reporter [REG_NO_ADAPT] Adapter not specified for map 'model.dutmap'. Accesses via this map will send abstract 'uvm_reg_item' items to sequencer 'uvm_test_top.e.agnt.sqr' # UVM_INFO verilog_src/questa_uvm_pkg-1.2/src/questa_uvm_pkg.sv(272) @ 0: reporter [Questa UVM] End Of Elaboration # UVM_INFO verilog_src/uvm-1.1d/src/seq/uvm_sequencer_base.svh(1385) @ 0: uvm_test_top.e.agnt.sqr [PHASESEQ] No default phase sequence for phase 'run' # UVM_INFO tb_driver.sv(40) @ 0: uvm_test_top.e.agnt.drv [iNIT] Initialize (time @0) # UVM_FATAL @ 0: reporter@@seq [sEQ] neither the item's sequencer nor dedicated sequencer has been supplied to start item in seq class env extends uvm_env; `uvm_component_utils(env) tb_agent agnt; dutblk model; // Register model object reg2dut_adapter reg2dut; // Bus adapter object uvm_reg_predictor#(trans1) predict; // predictor component function new (string name, uvm_component parent); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); super.build_phase(phase); agnt = tb_agent::type_id::create("agnt", this); model = dutblk::type_id::create("model"); reg2dut = reg2dut_adapter::type_id::create("reg2dut"); predict = uvm_reg_predictor#(trans1)::type_id::create("predict", this); model.build(); model.lock_model(); uvm_config_db#(dutblk)::set(uvm_root::get(),"*","reg_model", model); endfunction function void connect_phase(uvm_phase phase); super.connect_phase(phase); model.dutmap.set_sequencer(agnt.sqr); predict.map = model.dutmap; predict.adapter = reg2dut; // connect the predictor to the bus agent monitor analysis port agnt.aport.connect(predict.bus_in); endfunction endclass class test1 extends uvm_test; `uvm_component_utils(test1) env e; function new (string name, uvm_component parent); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); super.build_phase(phase); e = env::type_id::create("e", this); endfunction task run_phase(uvm_phase phase); tr_sequence seq; seq = tr_sequence::type_id::create("seq"); //---------------------------------------- phase.raise_objection(this); //`uvm_do(seq) seq.start(null); phase.drop_objection(this); endtask endclass
  10. @Alan - I have always used the almost-empty virtual sequencer with references to the sub-sequencers and used the env to copy the subsequencer handles to the handles declared in the virtual sequencer, then my vseq_base class would $cast the m_sequencer handle to the vseqr handle and use that handle to set the sub-sequencer handles declared in the vseq_base class. Then I could extend the vseq_base to create virtual sequences that started on the two sub-sequencer handles. Relevant code from the vseq_base and vseq classes below. Could you give an equivalent example of how you copy the handles into the virtual sequence and then execute the virtual sequence on null? Perhaps @uwes could explain how it tis done. Thanks - Cliff class vseq_base extends uvm_sequence; `uvm_object_utils(vseq_base) function new(string name="vseq_base"); super.new(name); endfunction vsequencer v_sqr; tb_ahb_sequencer ahb_sqr; tb_eth_sequencer eth_sqr; virtual task pre_body(); if(!$cast( v_sqr, get_sequencer() )) `uvm_fatal("vseq_base","BAD v_sqr type");; ahb_sqr = v_sqr.ahb_sqr; eth_sqr = v_sqr.eth_sqr; endtask endclass class v_seq1 extends vseq_base; `uvm_object_utils(v_seq1) function new(string name="v_seq1"); super.new(name); endfunction task body(); ahb_pkt ahb_pkt; eth_pkt eth_pkt; //--------------------------------------------------- `uvm_info("v_seq1", "Executing virtual sequence on DUT.", UVM_HIGH) `uvm_do_on(ahb_pkt, ahb_sqr) `uvm_do_on(eth_pkt, eth_sqr) `uvm_do_on(eth_pkt, eth_sqr) `uvm_do_on(ahb_pkt, ahb_sqr) `uvm_info("v_seq1", "Sequence complete.", UVM_MEDIUM) endtask endclass
  11. Hi, All - I have seen examples of sequences started on a null sequencer of the form: seq.start(null). How is a sequencer specified for these sequences? Thanks. Regards - Cliff
  12. cliffc

    Program blocks

    Death to Programs! It took me years to arrive at this conclusion, but I now believe that programs were a bad idea and should be avoided completely. After some convincing by other committee members, I voted for inclusion of programs into the SV Standard and I now regret that vote (please forgive me! ) The idea behind the program was that if an engineer applied stimulus on the active clock edge, the RTL design would completely respond to the clock, then the testbench would calculate new stimulus values on the same clock edge and send them into the RTL design, and any combinational inputs to the RTL design would then update before moving to the next clock edge. The idea was to avoid co-dependent, 0-time race conditions between the RTL and testbench execution. The point of the matter is, although it is a semi-common practice, you should never send stimulus on the active clock edge. In real hardware, this is known as a setup or hold-time violation and is never done. In 0-delay RTL simulations, if done properly, it works (but can be subject to a variety of race conditions). In gate-level simulations (GLS), this will violate setup and/or hold times, which means you have to modify the testbench to run with different timing values to perform GLS. I currently send stimulus using a time-budgeting scheme with my clocking blocks so that stimulus is sent 10%-20% of the clock cycle after the active clock edge (allowing for hold times and to meet long-combinational-input gate-delays). This allows me to use the same testbench for 0-delay RTL and GLS, and closely mimics the behavior of real hardware. If you don't send stimulus on the active clock edge (which you should never do), you don't need a program block. As has already been discussed in this thread, if you use programs, you have confusion, limitations and rules to follow, including the fact that a program cannot instantiate a module, and a module cannot call tasks/functions from a program. Removing programs greatly simplifies testbench development. Programs were a semi-good idea gone bad. As long as you do not have stimulus driven on the active clock edge (which is a bad idea - have I repeated that enough?), you can replace all program-endprogram keywords with module-endmodule. Chris Spear's very good SV Verification book uses programs. I have already informed my good friend and respected colleague that he should change all occurrences of program-endprogram to module-endmodule. I have never needed to use programs and standard UVM verification techniques do not use programs. Program usage is highly discouraged in my training classes. Regards - Cliff Cummings Verilog & SystemVerilog Guru
  13. Hi, all - When using uvm_config_db#(...)::set(...) from a top-module, is there any difference between using set-context=null and inst_name "*" and using set-context=uvm_root::get(), and inst_name "*"? top-module examples: uvm_config_db#(virtual dut_if)::set(null, "*", "vif", dif); uvm_config_db#(virtual dut_if)::set(uvm_root::get(),, "*", "vif", dif); Of course, per the UVM Class Reference, setting a context to null means that the inst_name provides the complete scope and "*" means any scope. Setting the context to uvm_top (returned by uvm_root::get()) and indicating "*" any scope in uvm_top seems to do the same thing. It seems that both are making the dut_if handle globally accessible. Comments? Regards - Cliff Cummings
  14. Hi, Dave - I agree. UVM Guideline #1 - quit using $display! I am still trying to find where I read the part about using $display for table headers (and again, I disagree. You should not use $display ... period!) Regards - Cliff
  15. Hi, All - Pardon the question, but I thought I had seen documentation that suggested using $display to only print headers and trailers when printing using UVM, but I cannot find a reference for this recomendation. BTW - I highly disagree with any usage of $display in UVM since it is not under UVM_VERBOSITY control. Am I completely mistaken or has anyone else seen recommended usage of $display for UVM table headers and trailers. If anyone knows of such a reference I would be greatful if you would post it. Thanks. This is not a critical issue, obviously! Regards - Cliff Cummings
×