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