顯示具有 UVM 標籤的文章。 顯示所有文章
顯示具有 UVM 標籤的文章。 顯示所有文章

2014年2月9日 星期日

xbus UVM example

purpose

a sample bus UVM/SV verification env that contains direct pattern, random pattern, trx replay pattern

pattern definition

  1. direct pattern : normal read/write test, like read after write test, the expected and answer had already known
  2. random pattern : random test based on it's constrain rule set
  3. trx replay pattern : replay trx via DPI interface supported

how to run it?

1.you can check our testsuites first, we provide three kinds of test at path ./sv/pat
1.1. for direct pattern +UVM_TESTNAME=test_xbus_normal_rw_seq_lib
1.2. for random pattern +UVM_TESTNAME=test_xbus_random_rw_seq_lib
1.3. for trx replay pattern +UVM_TESTNAME=test_xbus_adaptor_seq_lib
2.setup irun env please make sure your irun version is > 12.x
3.% irun -f run.f

2013年9月27日 星期五

fast debug key notes

these are my tips for fast debug.

  • set breakpoint when the assertion was happened
    • like GDB methodology 
      • forward, backward, force signal, release signal
    • tip
      • forcing the error signal value to your expect signal value when the simulation assertion was happened. if the signal was forced, then continuous go through it without rerun again. that can save the interrater running  times
  • dump the error time window waveform without whole simulation time dump
    • tip
      • using the interactive method to dump waveform. 
        • 1. find the error happened time
        • 2. set breakpoint 
        • 3. jumping the previous time window via backward breakpoint
        • 4. open interactive dump waveform command
        • 5. start dumping until the next breakpoint was happened
  • using assertion 
  • using verification IPs
    • sub IP test (selftest)
      • functional test, coverage test, Direct/Random pattern test
    • sub system test (sub system test)
      • protocol test, transaction path test, performance test
    • whole system test (H/S test)
      • OS boot, H/S correlation test

2013年9月21日 星期六

coverage group based on different bins

bus interface coverage catagology

classification

  • functional coverage bins
    • address rage bins
    • burst len bins
    • read/write bins
    • burst type bins
    • byten enable bins
    • cross coverage 
      • read trx
        • address, burst, read, ....
      • write trx
        • address, burst, write, ....
  • performance coverage bins
    • standard/normal bins
    • out standard bins
    • below standard bins
    • cross coverage
      • read trx
        • standard
      • write trx
        • standard
  • toggle coverage bins
    • 0 -> 1 
    • 1 -> 0
    • cross coverage
      • read trx
        • 0 -> 1 -> 0
      • write trx
        • 0 -> 1 -> 0
  • FSM coverage bins
    • default pass
  • protocol coverage bins
    • atomic bins
    • out of order bins
    • divide/conquer bins
    • address mapping table bins span tree
    • hit rate bins (cache coherence)



2013年9月14日 星期六

Cadence SimVision UVM/SystemVerilog debugger

transaction level debug via SimVision....

  • transaction waveform info/pin level waveform info 
  • transaction database info
  • UVM phase sequence info
  • assertion info
  • coverage rate
    • functional
    • fsm
    • code
    • assertion
    • performance 
  • debug step by step, like gdb forward, backward, stop point, value dump....
  • unknown signal trace back
  • vif (virtual interface), Driver 




2013年8月14日 星期三

UVM model notes 3


  • using callback func to handle the trx that's much more beautiful than using the trx handler in the same block  

    • this.trans_executed(tr); `uvm_do_callbacks(apb_master,apb_master_cbs,trans_executed(this,tr))   

  • using get_parent() to fetch the parent's pp and populate it to sub blocks

    • apb_agent agent;
      if ($cast(agent, get_parent()) && agent != null) begin
      sigs = agent.vif;
      end

  • using sequencer handler to sort/resort the sequence items by it's priority set, such as sorted([seq(0)->p(1), seq(1)->p(0)]) => [seq(1)->p(0), seq(0)->p(1)]  
    • register sub sequence to sequencer manager  

    • class dut_reset_seq extends uvm_sequence;

      function new(string name = "dut_reset_seq");
          super.new(name);
      endfunction

      `uvm_object_utils(dut_reset_seq)

      virtual task body();
          dut_top.rst = 1;
          repeat (5) @(negedge dut_top.clk);
          dut_top.rst = 0;
          endtask
      endclass

                ....
         dut_reset_seq rst_seq;                                                                                                  rst_seq = dut_reset_seq::type_id::create("rst_seq", this);
         rst_seq.start(null);

         ....
         my_tx tx;
         start_item(tx);
          ...// do something here
         finish_item(tx);

    • TLM interface (socket/package) it use like in "fifo" struct
      • pull_port (slave side)
        • querying the valuable trx from trx queue when the trx queue is not empty.

          uvm_seq_item_pull_port #(reg_rw) seqr_port;
          seqr_port.peek(rw); // aka 'get_next_rw
          ... // do trx handle
          seqr_port.get(rw); // aka 'item_done''
      • put_port(master side)
        • push the valuable trx to trx queue when the trx queue is not full
    • port/export TLM1
      • A component can send out a transaction out through a port, or receive an incoming transaction through an export.

      • function void connect;
            sqr2.seq_item_port.connect(sqr1.seq_item_export );
            ...
        endfunction

    • blocking/non-blocking trx in TLM2
      • non-blocking (return immediately) or blocking (suspend and wait for some event before returning)

      • non-blocking // no delay
        uvm_tlm_nb_target_socket#(device, usb_xfer, usb_tlm_phase) sock; // slave
        function uvm_tlm_sync_e nb_transport_fw(usb_xfer xfer, ref usb_tlm_phase ph...)

        uvm_tlm_nb_initiator_socket#(host, usb_xfer, usb_tlm_phase) sock; // master
        function uvm_tlm_sync_e nb_transport_bw(usb_xfer xfer,                        ref usb_tlm_phase ph, ...)
      • // connect sub sockets in uvm_env connect phase
        // master.sock.connect(slave.sock); 

      • blocking // support delay
      • uvm_tlm_b_target_socket #(target, apb_rw) sock; //slaveuvm_tlm_b_initiator_socket#(apb_rw) sock; // master
      • // connect sub sockets in uvm_env connect phase
        // master.sock.connect(slave.sock);
    • uvm_reg_field call back and sample
    class input_value_c extends uvm_reg;

      rand uvm_reg_field data;                                                                                                                                                        
      virtual function void build();
        data = uvm_reg_field::type_id::create("data");
        data.configure(this, 32, 0, "RO", 0, `UVM_REG_DATA_WIDTH'h0>>0, 1, 1, 1);
      endfunction

      covergroup value_cg;
        option.per_instance=1;
        coverpoint data.value[31:0];
      endgroup
     
      virtual function void sample_values();
        super.sample_values();
        value_cg.sample();
      endfunction

      `uvm_register_cb(input_value_c, uvm_reg_cbs)
      `uvm_set_super_type(input_value_c, uvm_reg)
      `uvm_object_utils(input_value_c)
      function new(input string name="unnamed-input_value_c");
        super.new(name, 32, build_coverage(UVM_CVR_FIELD_VALS));
        if(has_coverage(UVM_CVR_FIELD_VALS)) value_cg=new;
      endfunction : new
    endclass : input_value_c
    • uvm_reg_block
      • add sub classes "uvm_reg" to block set
    class gpio_regfile extends uvm_reg_block;                                                                       rand bypass_mode_c bypass_mode;
     
        virtual function void build();

         // Now create all registers

         bypass_mode = bypass_mode_c::type_id::create("bypass_mode", , get_full_name());
       
        // Now build the registers. Set parent and hdl_paths
         bypass_mode.configure(this, null, "bypass_mode_reg");
         bypass_mode.build();
         // Now define address mappings
        default_map = create_map("default_map", 0, 4, UVM_LITTLE_ENDIAN);
        default_map.add_reg(bypass_mode, `UVM_REG_ADDR_WIDTH'h0, "RW");

    endclass
    • uvm_report_server
      •    uvm_report_server svr;
           svr = _global_reporter.get_report_server();
           svr.set_max_quit_count(10);   

                                                          2013年6月27日 星期四

                                                          UVM AXI BFM 1.0 release

                                                          supported list

                                                          • AXI3/AXI4 bus protocol
                                                          • out of order/ inorder transactions
                                                          • each write/read phase is independent
                                                            • addr/write/resp is independent
                                                          • interlevel
                                                          • split
                                                          • performance watch dog 
                                                          • protocol watch dog
                                                          • performance report
                                                            • MAX, AVG, MIN bus bandwidth
                                                            • through put
                                                            • transaction list(disassemble bus info)
                                                          •  virtual master
                                                            • define each phase delay(req to grant or each valid/ready) or drive trx out time stamp
                                                          • virtual slave
                                                            • define each phase delay(req to grant or each valid/ready) or drive trx out time stamp
                                                          • scoreboard
                                                            • check connection
                                                            • check the memory read write is pass when the read/write trx in the same address, the read trx must be finished first than write trx to avoid the overwrite the address issue.
                                                          • STL 
                                                            • user define TRX language
                                                          • SystemC analysis port 
                                                            • user can use analysis port to link third part debug model by using DPI interface like Verilog to SystemC  or Verilog to C/C++

                                                          • https://github.com/funningboy/uvm_axi


                                                          2013年6月25日 星期二

                                                          UVM notes 2



                                                          • UVM reference flow
                                                          • UVM tutorial
                                                            • http://cluelogic.com/tag/vmm/UVM_AGENT
                                                          • virtual sequencer
                                                            • handle each sub sequencers when the platform contains multi sequences to drive the same DUT. 
                                                            • avoid race conditions,  transaction sequence, like multi threads system
                                                            •  ex:
                                                              •       jb_seq1 = same_flavored_jelly_beans_sequence::type_id::create( .name( "jb_seq1" ), .contxt( get_full_name() ) );
                                                              •       jb_seq2 = same_flavored_jelly_beans_sequence::type_id::create( .name( "jb_seq2" ), .contxt( get_full_name() ) );
                                                              •       case ( recipe )
                                                              •         LEMON_MERINGUE_PIE: begin
                                                              •            jb_seq1.flavor          = jelly_bean_transaction::LEMON;
                                                              •            jb_seq2.flavor          = jelly_bean_transaction::COCONUT;
                                                              •            jb_seq1.num_jelly_beans = 2;
                                                              •            jb_seq2.num_jelly_beans = 2;
                                                          • configure
                                                            • set  register , interface from top to down
                                                              • test_lib -> test_env -> test_cfg -> test_agent ... 
                                                            • ex:
                                                            •    initial begin
                                                            •       uvm_config_db#( virtual jelly_bean_if )::set
                                                            •          ( .cntxt( null ), .inst_name( "uvm_test_top" ), .field_name( "jb_if1" ), .value( jb_if1 ) );
                                                            •       uvm_config_db#( virtual jelly_bean_if )::set
                                                            •          ( .cntxt( null ), .inst_name( "uvm_test_top" ), .field_name( "jb_if2" ), .value( jb_if2 ) );
                                                            •       run_test();
                                                            •    end
                                                          • register abstract
                                                            • check register r/w limitation(only r/w), fields check, width check, coverage, assertion
                                                            • ex:
                                                            •       flavor = uvm_reg_field::type_id::create( "flavor" );
                                                            •       flavor.configure( .parent                 ( this ),
                                                            •                         .size                   ( 3    ),
                                                            •                         .lsb_pos                ( 0    ),
                                                            •                         .access                 ( "WO" ),
                                                            •                         .volatile               ( 0    ),
                                                            •                         .reset                  ( 0    ),
                                                            •                         .has_reset              ( 1    ),
                                                            •                         .is_rand                ( 1    ),
                                                            •                         .individually_accessible( 0    ) );

                                                          • assertion

                                                          • functional coverage

                                                          2013年6月20日 星期四

                                                          xilinx AXI interconnect

                                                          key notes


                                                          • cascade AXI bus if the input port > 4 (crossbar) multi to one
                                                          • traffic gen for DDR protocol (align burst length to 8), from AXI 2 DDR 
                                                          • example:
                                                            • 16 streams of 1920x1080 60/75p video information with up to 32 bits/pixel can be handled by a single 64-bit DDR3 interface
                                                            • VDMA
                                                            • Test Pattern Generators (TPGs) 
                                                            • Video Timing Control (VTC) 
                                                            •  On-Screen Display (OSD) 
                                                          • performance
                                                            • 622MB/s 
                                                            • 16 streams through memory, or nearly 9.95 GB/s (80 Gb/s)! This 18-port shared memory controller is used to support the 16 VDMA channels
                                                            • a memory clock speed of 800 MHz (1,600 MHz data rate).The primary internal AXI4 slave interface of the memory controller is operated at 200 MHz, using an AXI4 data width of 512 bits, supporting a theoretical maximum data bandwidth of 12.8 GB/s

                                                          refs: http://www.xilinx.com/support/documentation/white_papers/wp417-Xilinx-AXI4-Interconnects.pdfhttp://www.xilinx.com/support/documentation/application_notes/xapp521_XSVI_AXI4.pdf
                                                          http://www.xilinx.com/support/documentation/ip_documentation/ug761_axi_reference_guide.pdf

                                                          2013年5月25日 星期六

                                                          sytemverilog virtual interface setup time hold time check

                                                          we use systemveirlog virtual interface and simulator keys $setup, $hold to check the setup/hold time.




                                                          interface my_if #(c_clk_high_time = 5,
                                                                            c_clk_low_time  = 5) (input clk, en);
                                                            specify
                                                              specparam clk_high_time = c_clk_high_time;
                                                              specparam clk_low_time = c_clk_row_time;
                                                              $setup(en, negedge clk, clk_high_time * 4 / 5);
                                                              $hold(negedge clk, en, clk_low_time * 4 / 5);
                                                            endspecify
                                                          
                                                          endinterface;
                                                          
                                                          or
                                                          module timing_checks_in_sv (input clk, data, ...); 
                                                            ...
                                                            event ev_data_delayed_toggled;
                                                            
                                                            always @(data)
                                                            begin
                                                              fork
                                                              begin
                                                                # tSetup;
                                                                -> ev_data_delayed_toggled;
                                                              end
                                                              join_none
                                                            end
                                                          
                                                            property setup_hold_time_checker;
                                                              time curr_time;
                                                              @(posedge clk) (1, curr_time = $time) |->
                                                              @(ev_data_delayed_toggled) (($time - curr_time) > (tSetup + tHold)); // check data arrival time is meet $time - cur_time > (SetUp + Hold)
                                                            endproperty : setup_hold_time_checker
                                                          
                                                            ASSERT_SETUP_HOLD: assert property setup_hold_time_checker;
                                                          endmodule 
                                                          

                                                          ref :
                                                          http://learn-systemverilog.blogspot.tw/2010/07/writing-systemverilog-assertion-for.html
                                                          http://www.ee.ed.ac.uk/~gerard/Teach/Verilog/me5cds/me95rh.html

                                                          2013年5月24日 星期五

                                                          UVM TLM2.0 notes

                                                          if your are a ESL designer, you may heard about the SystemC TLM2.0 model that can help designer to design system level evaluation models very quick without any detail info such as Pin assignment, protocol selected, timing(real).... as you known, if you can use these abstract level api(blocking_trans, non_blocking_trans), you can replay or remodel design very quick without reconstruct your design again when the project is in evaluation phase. right now you can migrate your design from SystemC to UVM1.1d, because UVM1.1d is based on SystemVerilog that can be more suitable for EDA vendor supported and more friendly for verification designer... that's my guess ...


                                                          socket channel connection
                                                          initiator_socket : as same as master socket
                                                          target_socket    : as same as slave socket

                                                          ex:
                                                          1. create sockets in master/slave sides
                                                          initiator_socket ini_socket; // master socket
                                                          target_socket tgt_socket; // slave socket

                                                          connect(ini_socket, [tat_socket,...]) // connect one master to multi slaves

                                                          2. create trx payload to socket channel in master side
                                                          Trx trx = new();
                                                          trx.addr = 0x100;
                                                          trx.data = [0x1, 0x2, 0x3]; // generation payload
                                                          init_socket.write(trx);

                                                          3. collected trx in slave side
                                                          trx = tgt_socket.get_trx();     // fetch trx from socket channel fifo, and double check the trx is valid
                                                          if (trx != NULL) { // do something .... }


                                                          4. blocking trx
                                                          blocking interface conveys transactions in blocking fashion; its methods do not return until the transaction has been successfully sent or retrieved.  Because delivery may consume time to complete, the methods in such an interface are declared as tasks

                                                          5. non blocking trx
                                                          A non-blocking interface attempts to convey a transaction without consuming simulation time.  Its methods are declared as functions.  Because delivery may fail (e.g. the target component is busy and can not accept the request), the methods may return with failed status.

                                                          6. port, export, imps
                                                          port: instantiated in components that require, or use, the associate interface to initiate transaction requests. export : instantiated by components that forward an implementation of the methods defined in the associated interface. The implementation is typically provided by an imp port in a child component.

                                                          2013年5月21日 星期二

                                                          deep copy or shadow copy in your systemverilog object

                                                          as the same methodology as c/c++ or any languages. we usually used copy function to copy trx to avoid the overwrite trx when the trx had new ptr triggered. this is an sample example about what's the difference between deep copy and shadow copy, in short word. deep copy is top down copy, copy from this(current) level info to it's parents info. shadow copy is template current level copy, only for this level info.
                                                          class Based #(type T=int unsigned);
                                                            T val;
                                                          
                                                            function new (T v=0);
                                                              val = v; // assign new val
                                                            endfunction : new
                                                          
                                                            virtual function void deep_copy(Based b);
                                                              assert(b!=null);
                                                              b.val = val; // b.val = this.val
                                                            endfunction : deep_copy
                                                          
                                                            virtual function void shadow_copy(Based b);
                                                              assert(b!=null);
                                                              b.val = val; // b.val = this.val
                                                            endfunction : shadow_copy
                                                          
                                                            virtual function bool eq(Based b);
                                                              return b.val == val;
                                                            endfunction : eq
                                                          
                                                          endclass : Based
                                                          
                                                          class A #(type T=int unsigned) extens Based;
                                                            T val_a
                                                          
                                                            function new (T v=0);
                                                              super.new();
                                                              val_a = v; // assign val_a
                                                            endfunction : new 
                                                          
                                                            virtual function void deep_copy(A a); 
                                                              assert(a!=null);
                                                              Based b;
                                                              a.val_a = val_a;
                                                              $cast(b,a);
                                                              super.deep_copy(b);
                                                              // or
                                                              // a.val_a = val_a
                                                              // a.val  = super.val
                                                            endfunction : deep_copy
                                                          
                                                            // operator overwrite ... eq, lt, lt, ...
                                                            virtual function bool eq(A a0);
                                                              assert(a0!=null);
                                                              Based b0;
                                                              $cast(b0,a0);
                                                              return val_a == a0.val_a & super.eq(b0);
                                                            endfunction : eq
                                                          
                                                          
                                                          endclass : A
                                                          
                                                          
                                                          A a0 = new(1);
                                                          A a1 = new(2);
                                                          
                                                          a0.val_a = 3;
                                                          a0.val = 2;
                                                          
                                                          a0.deep_copy(a1);
                                                          
                                                          // check a0, a1 contains are eq  a0 = a1
                                                          assert(a0.eq(a1));  
                                                          

                                                          waveform modeling

                                                          as well as your are a ATE engineer, you may very familiar with the ATE test pattern formats that can transfer the waveform info into sample digital codes.
                                                          this is  a very example code for req/grant test case.
                                                          // timing modeling
                                                          task req_grant_00();                                                                                                                                                                 
                                                            m_vif.REQ   <= 0;
                                                            m_vif.GRANT <= 0;
                                                            @(posedge m_vif.CLK);
                                                          endtask : req_grant_00
                                                          
                                                          task req_grant_01();
                                                            m_vif.REQ   <= 0;
                                                            m_vif.GRANT <= 1;
                                                            @(posedge m_vif.CLK);
                                                          endtask : req_grant_01
                                                          
                                                          task req_grant_10();
                                                            m_vif.REQ   <= 1;
                                                            m_vif.GRANT <= 0;
                                                            @(posedge m_vif.CLK);
                                                          endtask : req_grant_10
                                                          
                                                          task req_grant_11();
                                                            m_vif.REQ   <= 1;
                                                            m_vif.GRANT <= 1;
                                                            @(posedge m_vif.CLK);
                                                          endtask : req_grant_1
                                                          
                                                          task
                                                          
                                                          task wave_gen();
                                                            list = {`ON_OFF, `ON_ON, `OFF_ON, `OFF_OFF};
                                                          
                                                            foreach(list[i]) begin
                                                              case(list[i])
                                                                `ON_OFF : req_grant_10();
                                                                `ON_ON  : req_grant_11();
                                                                `OFF_OFF: req_grant_00();
                                                                `OFF_ON : req_grant_01();
                                                              endcase
                                                            end 
                                                          endtask
                                                          
                                                          

                                                          2013年5月17日 星期五

                                                          UVM scoreboard to check with c/c++ golden model via uvm analysis port

                                                          1.systemverilog DPI interface to interconnect the c/c++ part and systemverilog part

                                                          2.uvm analysis port to valid event channel
                                                          // golden cehck via uvm analysis port
                                                          // ps : the port should be connected to it's callback module. that uvm can collected.
                                                          // ex: item_port.connect( analysis_export );
                                                          
                                                          uvm_analysis_port item_port
                                                          
                                                          // DPI import ... for our golen model
                                                          import "DPI" void *yuv2rgb(int unsigned y, int unsigned u, int unsigned v);  
                                                          // yub2rgb(void* trx); using ptr is a more friendly interface....
                                                          import "DPI" void *rgb2yuv(int unsigned r, int unsigned g, int unsigned b); 
                                                          
                                                          // callback func called from callable func/module
                                                          task callback(sample_trx trx);
                                                          
                                                            assert(trx!=null);
                                                            if (trx.type == YUV2RGB)
                                                              dpi_c_yuv2rgb(trx);
                                                            else
                                                              dpi_c_rgb2yuv(trx);
                                                          
                                                          endtask
                                                          
                                                          void dpi_c_yuv2rgb(sample_trx trx);
                                                                                                                                                                                                                                              
                                                            assert(trx!=null);
                                                            c_rst = yuv2rgb(trx.y, trx.u, trx.v)
                                                            assert( c_rst.r == trx.r &
                                                                    c_rst.g == trx.g &
                                                                    c_rst.b == trx.b);
                                                          endtask
                                                          
                                                          

                                                          2013年5月16日 星期四

                                                          adding performance monitor to your design

                                                          the UVM monitor can play not only a functional checker but also a performance checker which means, user can use it more quickly to find out where is their design bottleneck without waveform tracing. in this topic, we focused on how to use UVM monitor to point out the collected transactions had timing violation immediately when the simulation was running.

                                                          we write a UVM SystemVerilog "req happened until grant received" to our demo case.

                                                           
                                                          // spawn sub procs(threads)                                                                                                       
                                                          task run_phase(uvm_phase);
                                                            fork
                                                              sent_req();
                                                              sent_grant();
                                                          
                                                              collected_req();
                                                              collected_grant();
                                                          
                                                              check_performance();
                                                              check_protocol();
                                                            join
                                                          endtask : run_phase
                                                          
                                                          
                                                          // sent req 
                                                          task sent_req();
                                                          
                                                            forever begin
                                                              // random  wait ....
                                                              repeat($urandom_range(8,16)) @(posedge m_vif.CLK);
                                                          
                                                              // sent req 
                                                              `delay(conf.half_cycle);
                                                              m_vif.REQ <= `TRUE;
                                                              @(posedge m_vif.CLK);
                                                          
                                                              // wait until grant received
                                                              while(!m_vif.GRANT) @(posedge m_vif.CLK);
                                                          
                                                              // free req 
                                                              `delay(conf.half_cycle);
                                                              m_vif.REQ <= `FALSE;
                                                              @(posedge m_vif.CLK);
                                                          
                                                            end
                                                          
                                                          endtask : sent_req
                                                          
                                                          
                                                          // snet grant
                                                          task sent grant();
                                                          
                                                            forever begin
                                                          
                                                              // sent unvalid grant
                                                              `delay(conf.half_cycle);
                                                              m_vif.GRANT <= `FALSE;
                                                              @(posedge m_vif.CLK);
                                                          
                                                              // wait until req received
                                                              while(!m_vif.REQ) @(posedge m_vif.CLK);
                                                          
                                                              // random wait ...
                                                              repeat($urandom_range(8,16)) @(posedge m_vif.CLK);
                                                          
                                                              // sent valid grant to free req
                                                              `delay(conf.half_cycle);
                                                              m_vif.GRANT <= `TRUE;
                                                              @(posedge m_vif.CLK);
                                                          
                                                            end
                                                          
                                                          endtask : sent grant                                                                                                              
                                                          
                                                          
                                                          task collected_req();
                                                          
                                                            forever begin
                                                               // @ neg edge check
                                                                @(negedge m_vif.CLK iff m_vif.REQ);
                                                          
                                                                // assert only one fifo deep when req/grant case
                                                                assert(m_trx_q.size() < 1);
                                                          
                                                                // collect trx
                                                                TRX m_trx = new();
                                                                m_trx.REQ = m_vif.REQ;
                                                                m_trx.TIME = $time;
                                                                m_trx_q.push_back(m_trx);
                                                          
                                                            end
                                                          endtask : collected_req
                                                          
                                                          
                                                          task collected_grant();
                                                          
                                                            forever begin
                                                              // @ neg edge cehck
                                                              @(negedge m_vif.CLK iff m_vif.GRANT);
                                                          
                                                              //assert the queue size must be 1, means the req has been stored in the queue
                                                              assert(m_trx.q.size() == 1);
                                                          
                                                              // free queue
                                                              m_trx_q.pop_front();
                                                          
                                                            end
                                                                                                                                                                                            
                                                          endtask : collected_grant
                                                          
                                                          
                                                          task check_performance();
                                                            forever begin
                                                              // at each pos edge check
                                                              @(posedge m_vif.CLK);
                                                          
                                                              //assert queue
                                                              if (m_trx_q.size() == 1) begin
                                                                  if ($time - m_trx_q[0].TIME > conf.min_offset) begin
                                                                    `uvm_error(get_full_name(), {$psprintf("out of time %d"), conf.min_offset}, UVM_LOW)
                                                                  end else begin
                                                                    `uvm_error(get_full_name(), {$psprintf("req/grant seuence is not valid")}, UVM_LOW)
                                                                  end
                                                              end
                                                            end
                                                          
                                                          endtask             
                                                          

                                                          2013年5月15日 星期三

                                                          python unittest + UVM testsuites + Jenkins = DUT regression

                                                          in recently, i got a order from my boss. he asked me to build up a automatically unittest env that can very quick to know where is the problem such as protocol error, functional error, timing error ... when the design is changed. the below list is my auto regression flow and requirements


                                                          • i used python unittest to our based unittest framework
                                                            • python unittest
                                                              • check testsuite is pass/fail
                                                            • python nose 
                                                              • call python unittest folder and testsuites
                                                            • python subprocess/multiprocess
                                                              • call system call (irun, vcs....)
                                                            • python re(regular expression)
                                                              • check simulation result is pass/faill if the error tokens are not found

                                                          • UVM testsuites
                                                            • define UVM test sequence for your simulator
                                                              • irun -uvm +UVM_TESTNAME=""...
                                                            • prepare your test sequence
                                                              • like xxSequences.sv
                                                                • test_1read_after_1write
                                                                • test_mread_after_mwrite
                                                                • test_read_write_at_same_time
                                                          • jenkins
                                                            • job manager
                                                              • daily regression run 

                                                          2013年5月8日 星期三

                                                          Microsemi BFM script language


                                                          • a very useful script language for bus performance estimation and bus functional check
                                                            • example:
                                                              • # read B uart 0;
                                                                Reading offset 0 of uart – data = 0x1c
                                                                # write B uart 4 bb;
                                                                Writing 0xbb to offset 4 of uart
                                                                # read B uart 8;
                                                                Reading offset 8 of uart – data = 0x28
                                                                # write B mac 30 11;
                                                                Writing 0x11 to offset 30 of mac
                                                                # readcheck B mac 11;
                                                                Reading offset 0 of mac
                                                                Error: Expected data = 0x11, Actual data = 0x22
                                                                Test Failed, with 1 error
                                                                  
                                                                  

                                                              • 
                                                                
                                                              • advantage
                                                                • simple 
                                                                • error check 
                                                              • disadvantage
                                                                • no time stamp
                                                                  • maybe it use ASAP(as soon as possible) methodology to transfer transactions, it means masters or slaves are not in busy status, or fetch/push buffers not full
                                                                • no atomic transfer
                                                                  • if valid/ready is not continuous in the burst transaction, the interlevel transactions will happened, 
                                                                  • like A1(4), A2(4), A1 has burst 4 trxs, A2 has burst 4 trxs.
                                                                    • A1(2), A2(2), A1(2), A2(2) => atomic transactions when the A1 or A2 has busy or error in the internal transaction.

                                                            2013年5月6日 星期一

                                                            SystemVerilog Unit test = SVUnit = TDD(test drivent Development of Verification IP)

                                                            SystemVerilog UVM Unit test framework


                                                            • Methodology
                                                              • get UVM domain class and register it to unit test list
                                                              • fetch runnable  test suite from test list, the sorted priority is based on schedule manager definition
                                                              • collect test suite UVM report 
                                                              • report pass/fail coverages

                                                            ex:
                                                             
                                                              //************************************************************
                                                              // Test:
                                                              //   xformation_test
                                                              //  
                                                              // Desc:
                                                              //   ensure that objects going through the simple model have                                                                                                                       
                                                              //   their field property updated appropriately (multiply by
                                                              //   2)
                                                              //************************************************************
                                                              `SVTEST(xformation_test)
                                                                begin
                                                                  simple_xaction in_tr = new();
                                                                  simple_xaction out_tr;
                                                             
                                                                  void'(in_tr.randomize() with { field == 2; }); 
                                                             
                                                                  put_port.put(in_tr);
                                                                  get_port.get(out_tr);
                                                             
                                                                  `FAIL_IF(in_tr.field != 2); 
                                                                  `FAIL_IF(out_tr.field != 4); 
                                                                end 
                                                              `SVTEST_END(xformation_test)
                                                            

                                                            ref : http://www.agilesoc.com/svunit/

                                                            2013年5月4日 星期六

                                                            SystemVerilog parallel tasks by event trigger

                                                            SystemVeilog event trigger is implemented by event manager, that can define the dependences of parent and child tasks. and each tasks will be registered in event list when the building phase is done, after it, the task manager will sort event list by it's dependence or timing (such as E(timing(0)(0)), E(timing(1)(1)) E0 > E1, E0 will be run first than E1.

                                                            AXI write phase example. using delay constrain to define which one is first, which one is second


                                                            // @ write phase before write addr phase
                                                            // cfg.write_addr_delay = 10;
                                                            // cdg.write_data_phase = 0;
                                                            
                                                            
                                                            // @ write phase after write addr phase
                                                            // cfg.write_addr_phase = 0;
                                                            // cfg.write_data_phase = 10;
                                                            
                                                            task run_phase();
                                                              fork
                                                                write_addr_phase();
                                                                write_data_phase();
                                                                get_next_trx();
                                                              join
                                                            endtask
                                                            
                                                            
                                                            task get_next_trx();
                                                              forever begin
                                                                @(posedge vif.clk);
                                                                if (sequencer.item.has_next_trx()) begin
                                                                  trx = sequencer.item.get_next_trx();
                                                                  if (trx.rw == `WRITE)
                                                                    -> start_write;
                                                                  else
                                                                    -> start_read;
                                                                end 
                                                              end 
                                                            endtask
                                                            
                                                            task write_addr_phase();
                                                              forever begin
                                                                if (start_write.triggered) begin
                                                                  repeat(cfg.write_addr_delay) @(posedge vif.clk);
                                                                  // do write phase
                                                                end 
                                                              end 
                                                            endtask
                                                            
                                                            task write_data_phase();
                                                              forever begin
                                                                if (start_write.triggered) begin
                                                                  repeat(cfg.write_data_delay) @(posedge vif.clk);
                                                                  // do data phase
                                                              end 
                                                            endtask