Sunday, October 30, 2016

UVM Virtual Sequence Example.

// Base Virtual Sequence Class
class base_vseq extends uvm_sequence #(uvm_sequence_item);
   `uvm_object_utils(base_vseq)
 
   // Target Agent Sequencers
   uvm_sequencer #(ahb_txn) SQR_AHB;
   uvm_sequencer #(axi_txn) SQR_AXI;
 
   // Constructor
   function new (string name = "base_vseq");
      super.new(name);
   endfunction: new
 
endclass: vseq_base

// Virtual Sequence Class
class my_vseq extends base_vseq;
   `uvm_object_utils(my_vseq)
 
   // Constructor
   function new (string name = "my_vseq");
      super.new(name);
   endfunction: new
 
   // Sequence Body Task
   task body();
 
      ahb_seqeunce ahb_seq;
      axi_sequence axi_seq;
 
      ahb_seq = ahb_sequence::type_id::create("ahb_seq");
      axi_seq = axi_sequence::type_id::create("axi_seq");
 
      fork
         abh_seq.start(SQR_AHB);
         axi_seq.start(SQR_AXI);
     join
   endtask
 
endclass: my_vseq

// Base Test Class
class base_test extends uvm_test;
   `uvm_component_utils(base_test);
 
   // Environment Class Instantiation
   top_env Env;
 
   // Constructor
   function new (string name = "base_test", uvm_component parent = null);
      super.new(name, parent);
   endfunction: new
 
   // Build Phase
   function void build_phase (uvm_phase phase);
      Env = top_env::type_id::create("Env");
   endfunction: build_phase
 
   // Method to Connect Sequencer Handles in VSEQ
   function void init_vseq (base_vseq vseq);
      vseq.SQR_AHB = test.env.ahb_agent.SQR_AHB;
      vseq.SQR_AXI = test.env.axi_agent.SQR_AXI;
   endfunction: init_vseq
 
endclass: base_test

// Main Test
class test extends base_test;
   `uvm_component_utils(test)
 
   // Constructor
   function new (string name = "test", uvm_component parent = null);
      super.new(name, parent);
   endfunction: new
 
   // Run Phase
   task run_phase (uvm_phase phase);
      // Create the Virtual Sequence
      my_vseq vseq = my_vseq::type_id::create("vseq");
      phase.raise_objection(this);
      // Virtual Sequence Initialization
      init_vseq(vseq);
      // Start the Virtual Sequence
      vseq.start(null);
      phase.drop_objection(this);
   endtask: run_phase
 
endclass: test

UVM AHB Driver Example.

////////// Sequence Item //////////
class ahb_seq_item extends uvm_sequence_item;
   `uvm_object_utils(ahb_seq_item)
 
   // Master to Slave Data Flow
   rand logic [31:0] HADDR;
   rand logic [31:0] HWDATA;
   rand logic HWRITE;
   ahb_burst_e HBURST;
 
   // Slave to Master Data Flow
   logic [31:0] HRDATA;
   ahb_resp_e HRESP;
 
   // Constructor
   function new (string name);
      super.new(name);
   endfunction: new
 
   // Constraints
   constraint addr_for_32bit {HADDR[1:0] == 0;}
 
endclass: ahb_seq_item


////////// AHB Interface //////////
interface ahb_interface;
 
   // TO both Master & Slave
   logic HCLK;
   logic RESETn;
 
   // Master to Slave
   logic [31:0] HADDR;
   logic [31:0] HWDATA;
   logic HWRITE;
   ahb_burst_e HBURST;
 
   // Slave to Master
   logic [31:0] HRDATA;
   ahb_resp_e HRESP;
   logic HREADY;
 
endinterface: ahb_interface


////////// Pipelined UVM Driver //////////
class ahb_pipelined_driver extends uvm_driver #(ahb_seq_item);
   `uvm_component_utils(ahb_pipelined_driver)
 
   // Virtual Interface
   virtual ahb_interface ahb_if;
 
   // Constructor
   function new (string name, uvm_component parent);
      super.new(name, parent);
   endfunction: new
 
   // Semaphore Declaration
   semaphore pipeline_lock = new(1);
 
   // Run Phase Task
   task run_phase (uvm_phase phase);
 
      @(posedge ahb_if.HRESETn);
      @(posedge ahb_if.HCLK);
 
      fork
         do_pipelined_transfer;
         do_pipelined_transfer;
      join
 
   endtask: run_phase
 
   // do_pipelined_transfer task
   task automatic do_pipelined_transfer;
 
    ahb_seq_item req;
 
    forever begin
      pipeline_lock.get();
      seq_item_port.get(req);
      accept_tr(req, $time);
      void'(begin_tr(req, "pipelined_driver");
      ahb_if.HADDR <= req.HADDR;
      ahb_if.HWRITE <= req.HWRITE;
      ahb_if.HBURST <= req.HBURST;
      @(posedge ahb_if.HCLK);
      while(!ahb_if.HREADY == 1) begin
         @(posedge ahb_if.HCLK);
      end
      // Command phase ends here
      // Unlock semaphore
      pipeline_lock.put();
      // Data phase starts here
      if (req.HWRITE == 0) begin
         @(posedge ahb_if.HCLK);
         while(ahb_if.HREADY != 1) begin
            @(posedge ahb_if.HCLK);
         end
        req.HRDATA = ahb_if.HRDATA;
        req.HRESP = ahb_if.HRESP;
      end
      else begin
         ahb_if.HWDATA <= req.HWDATA;
         @(posedge ahb_if.HCLK);
         while(ahb_if.HREADY != 1) begin
            @(posedge ahb_if.HCLK);
         end
         req.HRESP = ahb_if.HRESP;
      end
      // Return the Request as Response
      seq_item_port.put(req);
      end_tr(req);
    end
   endtask: do_pipelined_transfer
 
 endclass: ahb_pipelined_driver


////////// Pipelined Sequence ////////// 
 class ahb_pipelined_seq extends uvm_sequence  #(ahb_seq_item);
   `uvm_object_utils(ahb_pipelined_seq)
 
   logic [31:0] addr[10]; // To save addresses
   int count; // To ensure that the seq does'nt complete too early
 
   // Constructor
   function new (string name);
      super.new(name);
   endfunction: new
 
   // Task body()
   task body;
 
      ahb_seq_item req;
      req = ahb_seq_item::type_id::create("req", this);
      use_response_handler(1); // Enable Response Handler
      count = 0;
 
      for(int i=0; i<10; i++) begin
        start_item(req);
        assert(req.randomize() 
            with {MWRITE == 1; HBURST == SINGLE; HADDR 
            inside {[32'h0010_1000:32'h0010_1FFC]};});
        addr[i] = req.HADDR;
        finish_item(req);
      end
 
      foreach (addr[i]) begin
        start_item(req);
        req.HADDR = addr[i];
        req.HWRITE = 0;
        finish_item(req);
      end
 
      // Wait till last seq item is over
      wait(count == 20);
   endtask: body
 
   // This response_handler function is enabled 
   // to keep the sequence response FIFO empty
   function void response_handler(uvm_sequence_item response);
      count++;
   endfunction: response_handler
 
 endclass: ahb_pipelined_seq

UVM APB Driver Example.

// APB Bus Interface
interface apb_interface;
 
   logic clk;
   logic rstn;
   logic [31:0] Addr;
   logic [31:0] Write_Data;
   logic RNW;
   logic Valid;
   logic Ready;
   logic [31:0] Read_Data;
   logic Error;
 
endinterface: apb_interface

// APB Bus Sequence Item Class
class apb_seq_item extends uvm_sequence_item;
   `uvm_object_utils(apb_seq_item)
 
   // Request fields
   rand logic [31:0] addr;
   rand logic [31:0] write_data;
   rand bit read_not_write;
   rand int delay;
 
   // Response fields
   bit error;
   logic [31:0] read_data;
 
endclass: apb_seq_item

// APB Bus Driver Class
class apb_bus_driver extends uvm_driver #(apb_seq_item);
   `uvm_component_utils(apb_bus_driver)
 
   apb_seq_item req;
 
   virtual apb_interface apb_if;
 
   function new (string name, uvm_component parent);
      super.new(name, parent);
      endfunction: new
 
   task run_phase (uvm_phase phase);
 
      apb_if.Valid <= 0;
      apb_if.RNW <= 0;
 
      // Out of Reset
      @(posedge apb_if.rstn);
      // Pin Level Transfer
      forever begin
         seq_item_port.get_next_item(req);
         repeat(req.delay) begin
            @(posedge apb_if.clk);
         end
         apb_if.Valid <= 1;
         apb_if.Addr <= req.addr;
         apb_if.RNW <= req.read_not_write;
         if (req.read_not_write == 0) begin
            apb_if.Write_Data <= req.write_data;
         end
         while(apb_if.Ready != 1) begin
            @(posedge apb_if.clk);
         end
         // At the end of pin level bus transaction
         // Copy response data into the req related fields
         if (req.read_not_write == 1) begin
            req.read_data <= apb_if.Read_Data;
         end
         req.error <= apb_if.Error;
         apb_if.Valid <= 0;
         seq_item_port.item_done();
      end
   endtask: run_phase
endclass: apb_bus_driver

// APB Bus Sequence
class apb_bus_seq extends uvm_sequence #(apb_seq_item)
   `uvm_object_utils(apb_bus_seq)
 
   function new(string name);
      super.new(name);
   endfunction: new
 
   // No. of iterations
   rand int iti = 30
 
   apb_seq_item req;
 
   task body();
      req = apb_seq_item::type_id::create("req", this);
      repeat(iti) begin
         start_item(req);
         assert (!req.randomize() 
            with {addr inside {[32`h1000_0000:32`h1000_001C]};}) 
         begin
            `uvm_error("Body", "Randomization Error");
         end 
         finish_item(req);
         `uvm_info ("Response Fields", 
            $sformatf("Read Data = %h", req.read_data), UVM_LOW)
      end
   endtask: body
 
endclass: apb_bus_seq

UVM PCM Driver Example.

// Interface Declaration
interface adpcm_int;
 
   logic clk;
   logic frame;
   logic [3:0] data;
 
endinterface: adpcm_int


// Transaction item class adpcm_txn
class adpcm_txn extends uvm_sequence_item;
   `uvm_object_util(adpcm_txn)
 
   rand logic[3:0] data;
   rand int delay;
 
   function new (string name);
      super.new(name);
   endfunction: new
 
   constraint del_bet_pac {delay inside {[1:20]};}
 
endclass: adpcm_txn


// Driver class adpcm_drv
class adpcm_drv extends uvm_driver #(adpcm_txn);
   `uvm_component_utils (adpcm_drv)
 
   adpcm_txn req;
 
   virtual adpcm_int adpcm_if;
 
   function new(string name, uvm_components parent)
      super.new(name, parent);
   endfunction: new
 
   task run_phase (uvm_phase phase);
 
      // Default conditions
      adpcm_if.frame <= 0;
      adpcm_if.data <= 0;
      forever begin
         seq_item_port.get_next_item(req);
         repeat(req.delay) begin
            @(posedge adpcm_if.clk);
         end
 
         adpcm_if.frame <= 1;
         for (int i = 0; i < 8; i++) begin
            @(posedge adpcm_if.clk);
            adpcm_if.data <= req.data[3:0];
            req.data = req.data >> 4;
         end
         adpcm_if.frame <= 0;
         seq_item_port.item_done();
      end
   endtask: run_phase
 
endclass: adpcm_drv

                                                                                                                                                                   
// Sequence Class adpcm_seq
class adpcm_seq extends uvm_sequence #(adpcm_txn);
   `uvm_component_utils (adpcm_seq)
 
   adpcm_txn req;
 
   rand int no_of_reps = 10;
 
   function new (string name);
      super.new(name);
   endfunction: new
 
   task body;
      req = adpcm_txn::type_id::create("req", this);
      for (int i = 0; i < no_of_reps; i++) begin
         start_item(req);
         if (!req.randomize()) begin
            `uvm_error("BODY", "req randomization failed")
         end
         finish_item(req);
         `uvm_info("ADPCM_SEQ BODY", 
            $sformatf("Transmitted frame %0d", i), UVM_LOW)
      end
   endtask: body
 
endclass: adpcm_seq

Saturday, October 29, 2016

AMBA 101.

Advanced Microcontroller Bus Architecture by ARM
  • ASB - advanced system bus
  • APB - advanced peripheral bus (used for low power peripheral modules)
  • AHB - advanced high performance bus
    • Arbitration
      • round robin priority scheme (default priority: master0)
      • fair chance
      • random access
      • high priority
    • burst transfer 
      • undefined length or 4, 8, 16 in length
      • fixed address, incremental address, or wrap address for cache line
    • split transactions
    • multiple masters
      • through a central arbiter
      • through  multiple slave level arbiters in multi-layer AHB-Lite system.
      • masters could be DMA controller, a peripheral core master interface, etc.
    • wider address bus, separate read or write data bus
    • larger data paths (multiplexed, not tri-state)
    • pipelined operation
    • wait-state insertion
    • data-valid signal HREADY
  • AHB and APB is linked through a bridge that acts as the master to the peripheral bus slave devices.

AHB Signals
  • General
    • HCLK
    • HRESET
  • Arbiter / Master
    • HBUSREQ (one from each master) 
    • HGRANT (one for each master)
  • Master / Slave
    • HRESP ([1:0] or [0] in AHB-Lite)
      • 00 - OKAY
      • 01 - ERROR
      • 10 - RETRY
      • 11 - SPLIT
    • HREADY (used by slave to insert wait state)
      • when it's low (from slave) all control signals shall hold their values.
    • HTRANS[1:0] (set according to RD or WR)
      • 00 - IDLE
      • 01 - BUSY (master can use BUSY to insert wait state during bursting)
      • 10 - NONSEQ
        • First transfer of an AHB sequence is always NONSEQ
      • 11 - SEQ
        • All transfer following the first shall be SEQ in nature.
    • HWRITE
    • HADDR [31:0] (muxed from individual masters to slaves and address decoder)
    • HRDATA / HWDATA
  • Slave / Arbiter
    • HMASTER [3:0] / HMASTLOCK - from arbiter
    • HSPLIT# [15:0] - one from each slave
  • Address Decoder / Slave
    • HSEL# (one for each slave unit)
  • More from Masters to Slave
    • HSIZE[2:0]
    • HBURST[2:0]
      • 4, 8, 16 in size
      • incremental
      • wrapping
      • 000 - single
      • 001 - INCR
      • 010 - WRAP4
      • 011 - INCR4
      • 100 - WRAP8
      • 101 - INCR8
      • 110 - WRAP16
      • 111 - INCR16
    • HPROT[3:0] - protection control
    • HLOCK# - locked transfer, one from each master
      • lowered during the last transfer of an AHB sequence
  • Example Auxilary Signals for AHB Masters
    • REQ_VLD - input to bus master, asserted when HBUSREQ is asserted
    • WR - input to bus master, high when HWRITE is high
    • RD -  input to bus master, high when HWRITE is low
    • IN_ADDR[31:0] - input to bus master, used to decide HADDR[31:0]
    • IN_DATA[31:0]
    • LEN#
    • LAST
    • OUT_DATA[31:0] - output from bus master
    • REQ_WR_DATA - output from bus master
      • It shall be high when (REQ_ADDR & WR) to ensure data shall be put on data bus one cycle after address is on.
      • When REQ_WR_DATA ==1, IN_DATA will be put to data bus in next cycle.
    • REQ_RD_DATA - output from bus master
      • It shall be high when it's a read transfer and HREADY == 1.
    • REQ_ADDR - output from bus master
      • It shall be high when (HREADY & HGRANT) to ensure master can put address in next cycle.
      • When REQ_ADDR == 1, IN_ADDR will be put to address bus in next cycle.

AHB Phases
  • address/control 
  • phase data phase

AHB Protocols
  1. bus master sends HBUSREQ to arbiter and an address, decoded by central decoder to provide a dedicated HSEL to selected slave unit.
  2. Slaves should only sample address when both HSEL and HREADY are high.
  3. If the slave is under re-configuration or needs to terminate a transaction, it saves the Hmaster number, and sends RETRY or SPLIT to arbiter and arbiter remove the requesting master from list until the targeted slave de-assert Hsplit. If RETRY is sent, the transaction is dropped.
  4. When the slave is ready, it signals the arbiter with the saved master number and the arbiter grants the bus access to the master to restart the transaction.
  5. No master can have more than one pending split transaction.
  6. Otherwise, master gets Hgrant and lock the bus. 
  7. During burst mode (size indicated by HBURST[2:0]), master can insert wait state by sending HTRANS == BUSY. The slave has to send immediate OKAY in next cycle as for the case of IDLE and ignore the transfer.
  8.  First burst cycle is always NONSEQUENTIAL.
  9. HADDR must be aligned to the HBURST size, that is, A[1:0] == 2'b00 in word transfer and A[0] == 1'b0 in halfword transfer.
  10. If a master is granted the bus without requesting it, it has to drive the transfer type IDLE.

APB Signals
  • PCLK
  • PRESETn - active LOW
  • PSEL# - APB select
  • PEN or PENABLE - APB strobe
  • PADDR[31:0] - Address bus
  • PWRITE - Transfer direction
  • PWDATA[31:0] - Write data bus (can be 8, 16, 32 bit)
  • PRDATA[31:0]  - Read data bus
  • PREADY

APB States
  • IDLE       : (~PSEL & ~PEN)
  • SETUP    : (  PSEL & ~PEN)
  • ACCESS : (  PSEL &   PEN)

AHB/APB Bridge Approach
  • Cross clock domain data transfer
    • handshake signaling method (double stage synchronizer)
    • asynchronous FIFO

ASB Signals
  • AGNT# - Bus grant
  • AREQ# - Bus request
  • BA[31:0] - Address bus
  • BCLK - Bus clock
  • BD[31:0] - Data bus
  • BERROR - Error response
  • BLAST - Last response
  • BLOK - Locked transfer
  • BnRES - Reset
  • BPROT[1:0] - Protection control
  • BSIZE[1:0] - Transfer size
  • BTRAN[1:0] - Transfer bype (driven when AGNT# is asserted)
    • ADDRESS-ONLY
    • NON-SEQUENTIAL
    • SEQUENTIAL
  • BWAIT - Wait response
  • BWRITE - Transfer direction
  • DSEL# - Slave select


UVM Coverage.

Basics
  • Put all covergroups in a class or module
  • Use local variables in the class or module
  • Make covergroups sensitive to a variable or explicitly sample a variable
  • Have a coverage test plan
  • Use automatic bins for simple covergroup
  • Code coverage is not functional coverage
    • line coverage
    • block / statement coverage
    • branch coverage
    • path coverage
    • toggle coverage
    • expression coverage
    • FSM coverage
    • transition coverage

<coverpoint_name>  :  coverpoint  <expression>  { bins <bin_name> = { <list of values > } }
class coverage extends uvm_agent;
   `uvm_component_utils (coverage)

   tlm_analysis_fifo #(mem_req) req_fifo;
   mem_req req;
   mem_op op;
   logic [15:0] addr;

   covergroup mem_ops;
      coverpoint memop {
         bins action[] = {read, write};
      }

   coverpoint addr {
         bins zeros  = {0};
         bins others = {[1 : 16'hFFFE]};
         bins ones   = {16'hFFFF};
      }
      edges : cross op, addr;
   endgroup

   covergroup alu_cv;

      all_ops : coverpoint op;
      a_op: coverpoint A {bins Ais0 = {'h00};}
      b_op: coverpoint B {bins Bis0 = {'h00};}

   endgroup

   function new (string name, uvm_component parent);
      super.new(name, parent);
      mem_ops = new();
      alu_cv = new();
   endfunction : new

   task run();
      mem_data cln;
      mem_req req_tx;
      forever begin : run_loop
         req_fifo.get (req_tx);
         op = req_tx.op;
         addr = req_tx.addr;
         mem_ops.sample();
      end
   endtask : run

endclass


Example: automatic bins
   typedef enum {add, and, xor, mul, rst, nop} op_t;

   covergroup opcov;
      coverpoint op;
   endgroup : opcov

   task sample_req;
      A = req.A;
      B = req.B;
      op = req.op;
      opcov.sample();
   endtask

   covergroup alu_cv2;

      coverpoint op;
      coverpoint A;
      coverpoint B;

      option.auto_bin_max = 4; // default to 64 bins

   endgroup


Example: Basic Bins
   covergroup opcov;
      coverpoint op;
      A00FF : coverpoint A {
         bins zeros = { 0 };
         bins ones  = { 8'hFF };
      }
      B00FF : coverpoint B {
         bins zeros_ones  = { 0, 8'hFF };
      }
   endgroup


Bins with Ranges, Bins with sequences
   typedef enum {add, and, xor, mul, rst, nop} op_t;

   covergroup opcov;
      coverpoint op {
         bins single_cyc = {[add : xor] , rst, nop};
         bins multi_cyc  = {mul};
      }
   endgroup : opcov

   // Automatic bins with ranges
   bins onepervalue [] = {< list of="" values="" >};
   bins n_bins [n] = { < list of="" values="" >};
   bins threebins [3] = {[1:2],[2:6]};
   // same as 
   // bins threebins [3] = {1,2,2,3,4,5,6};

   // Bins with sequences
   // run multi-cycle after reset
   // bins bin_name = ( < value1 > => < value2 >);

   covergroup opcov;
      coverpoint op {
         bins single_cycle = {[add : xor], rst, nop};
         bins multi_cycle  = {mul};
         bins mult_rst = (mul => rst);
         bins rst_mult = (rst => mul);
      }
   endgroup


Bins with multiple value transitions in sequences
 
   // Bins with multiple value transitions
   // bins bin_name = (< value list >  =>  < value list >);
   // 1, 2 => [3:5], 7
   // 1=>3, 2=>3, 1=>4, 2=>4, 1=>5, 2=>5, 1=>7, 2=>7
   bins op_rst[]   = ( [add : nop ] => rst );
   bins rst_mult[] = ( rst => [add : nop]);

   // multi-cycle after single-cycle
   bins singl_mul[]   = ( [add : xor ], nop => mul );

   // single-cycle after multi-cycle
   bins mul_sngl[]   = ( mul => [add : xor ], nop );

   // Run all operations twice in a row 
   // bins <name> = (<value list> [* n]); bins <name> = (<value list> [* n:m]);
   // Ex: Run 3-5 Multiplies in a row
   bins twoops[] = ([add:nop] [*2]);
   bins manymult = (mul [* 3:5]);

   // Nonconsecutive Repetition
   // <value list> [= n:m];     // nonconsecutive operator 
   // <value list> [-> n:m]; // goto operator
   // • Nonconsecutive Operator (=) matches if n:m values occur 
   //        in a list of value regardless of the terminating value.
   // • Goto Operator (->) matches if n:m values occur in a list 
   //        of values and then a terminating value appears.

   bins rstmulrst   = (rst => mul [=  2] => rst);
   // rstmulrst (match): rst => mul => xor => mul => and => rst
   bins rstmulrstim = (rst => mul [-> 2] => rst);
   // rstmulrst and rstmulrstim (match): rst => mul => xor => and => mul => rst


Cross Coverage : Use Cross and Binsof to capture combinations of values
 
   covergroup zeros_ones_ops;

      all_ops : coverpoint op {
         ignore_bins null_ops = {rst, nop};
      }
      a_op: coverpoint A {
         bins zeros  = {'h00};
         bins others = {['h01:'hFE]};
         bins ones   = {'hFF};
      }
      b_op: coverpoint B {
         bins zeros  = {'h00};
         bins others = {['h01:'hFE]};
         bins ones   = {'hFF};
      }

      basic : cross a_op, b_op, all_ops;

      with_a0bin : cross a_op, b_op, all_ops {
         bins a0bin  = binsof (a_op.zeros);
      }

      // bins <bin> = binsof(<somebins>) && binsof(<otherbins>); 
      // bins <bin> = binsof(<somebins>) || binsof(<otherbins>);
      zeros_ones : cross a_op, b_op, all_ops {
         bins AorBzero  = binsof (a_op.zeros) || binsof (b_op.zeros);
         bins AorBones  = binsof (a_op.ones)  || binsof (b_op.ones);
         ignore_bins the_others =
                binsof (a_op.others) && binsof (b_op.others);
      }

      // intersect qualifier
      // bins <bin> = binsof(<somebins> intersect (<value_list>))
      zeros_ones_2 : cross a_op, b_op, all_ops {
         bins add_bin  = binsof (all_ops) intersect {add};
         ignore_bins x = ! binsof (all_ops) intersect {add};
      }

   endgroup



Friday, October 28, 2016

SystemVerilog Question.


  • Automatic vs Static
    For a static task, multiple invocations of the same task will reference the same local variables. For an automatic task, the local variables will be unique to each invocation of the task. The function should be automatic so that there will be multiple memory allocations for the index variable to show increasing values instead of a single value.
  • packed vs unpacked
    Unpacked array is an array with gap between variables.
  • Join / Join_any / Join_none
    Join (and all done) / Join_any (or any done) / Join_none (none is done, non-blocking)
    (use "wait fork;" or implement watch_dog timer for "join_none" for synchronization)
  • Wire vs Logic
    Logic and wire are almost the same except wire can be driven by multiple sources. Logic can only driven by single source.
  • Virtual
    Means "abstract"

Randomization.


  • $random : return an 32-bit signed random number.
  • $urandom : return an 32-bit unsigned random number.
  • $srandom(seed) : set random seed for $urandm.
  • use run-time switch : +ntb_random_seed=seed_value
  • $urandom_range(min, max)
  • randcase

randcase
   10 : f1();
   20 : f2();
   30 : x = 100;
   50 : randcase ... endcase; // nested
endcase

Thursday, October 27, 2016

UVM Report.


  • Formatting
    • $sformat (str, "%m : a = $2h", a);
    • $timeformat (-9, 2, " ps", 4);
    • timeunit 100ps;
    • timeprecision 10ps;
  • System Calls
    • $display
    • $fdisplay - to write to files.
    • $time, $stime, $realtime,
  • Opening Files
    • integer fha = $fopen("fileaname");
    • integer fhb = $fopen("filebname");
    • integer fhboth = filea | fileb;
    • $fdisplay (fha, "string");
    • $fclose (fhboth);
  • UVM_macros for Reporting
    • $display (`__FILE__);
    • `uvm_info ("message_ID", "This is info message", verbose_level, UVM_INFO);
    • `uvm_warning ("message_ID", "message", Severity);
    • `uvm_error ("message_ID", "message", Severity);
    • `uvm_fatal ("message_ID", "message", Severity);
    • Each reporting method call gets a verbosity number
    • The object has a reporting verbosity number
    • The method acts only if its verbosity number is below the object's verbosity number
    • inst.set_report_verbosity_level_hier (800);
  • UVM Report Control
    • Verbosity level set
    • Reporting methods for actions
      • in end_of_elaboration_phase
      • UVM_DISPLAY
      • UVM_LOG - write to a file
        • Open the file(s) and get the MCDs
        • Set the logging action on the ID's
        • Attach the MCDs to the severities or ID's
          • set_report_default_file() 
          • set_report_id_file ("printer", printer_file);
          • set_report_severity_action
            (UVM_WARNING, UVM_DISPLAY | UVM_LOG);
          • set_report_severity_file (UVM_WARNING, warning_file);
          • dump_report_state();
          • set_report_max_quit_count (10);
      • UVM_COUNT
      • UVM_EXIT
      • UVM_CALL_HOOK - call user defined method
      • UVM_STOP
    • Reporting action controls
      • set_severity_action (severity sv, action a)
      • set_id_action (string id, action a)
      • set_severity_id_action (severity sv, string id, action a)
      • set_severity_action_hier (severity sv, action a)
      • set_id_action_hier (string id, action a)
      • set_severity_id_action_hier (severity sv, string id, action a)
      • Default:
        • UVM_INFO            : UVM_DISPLAY
        • UVM_WARNING  : UVM_DISPLAY
        • UVM_ERROR        : UVM_DISPLAY  |  UVM_COUNT
        • UVM_FATAL         : UVM_DISPLAY  |  UVM_EXIT
    • File ID

UVM Test Analysis.

Analysis Layer

  • Scoreboard / Subscriber / Monitor / Predictor
    • Watch / Observe
    • Recognize transactions
    • Place the transactions to the analysis ports
  • Coverage
  • Reporting
  • Simulation
    • Tests/Transactions -> Drivr -> DUT -> Responder -> TLM models
  • Can connect to multiple objects (unlike uvm_put_port)
  • Analysis Ports, Exports, Imps
  • Port, Export and Imp

Example of Monitor Class
class monitor extends interface_base;
   `uvm_component_utils(monitor)
   uvm_analysis_port #(mem_data) rspa;
   uvm_analysis_port #(mem_req)  reqa;

   function new (string name = "driver",
                uvm_component parent = null);
      super.new (name, parent);
   endfunction : new

   virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      reqa = new ("reqa", this);
      rspa = new ("rspa", this);
   endfunction: build_phase

   task run_phase(uvm_phase phase);
      mem_req  req = new(), c_req;
      mem_data rsp = new(), c_rsp;

      forever begin : monitor_loop

         @(posedge mif.clk);
         #UNIT_DELAY;
         req.load_data (mif.addr, mif.data, nop);
         rsp.load_data (mif.addr, mif.data);
         if (mif.wr) req.op = write;
         if (mif.rd) req.op = read;
         if (req.op != nop) begin
            $cast(c_req, req.clone());
            reqa.write (c_req);
         end
         if (mif.rd) begin
            $cast (c_rap, rsp.clone());
            rspa.write (c_rsp);
         end

      end : monitor_loop
   endtask
endclass : monitor


Create a Subscriber
  • Instantiate a "uvm_tlm_analysis_fifo"
  • Connect to the analysis_port at the top level
  • Use get() to block and take data out of the analysis fifo



Create a Predictor
  • It gets a request from the analysis_port connected to the monitor.
  • It predicts what response transaction will appear.

class predictor extends uvm_agent;
   `uvm_component_utils (predictor)
   logic [15:0] mem [2**16-1 : 0];

   uvm_tlm_analysis_fifo #(mem_req) reqfifo;
   uvm_put_port #(mem_data) rsp_p; // to connect to comparator
   mem_data rsp = new();

   function new (string name, uvm_component parent);
      super.new (name, parent);
   endfunction: new

   virtual function void build_phase (uvm_phase phase);
      super.build_phase(phase);
      req_fifo = new("req_fifl", this);
      rsp_p = new ("rsp_po", this);
   endfunction : build_phase

   task run_phase (uvm_phase phase);
      mem_data cln;
      mem_req req_txn;
      forever begin : run_loop
         req_fifo.get (req_tx);
         case (req_tx.op)
            write : mem[req_tx.addr] = req_tx.data;
            read  : begin : read_op
               rsp.load_data (req_tx.addr, mem[req_tx.addr]);
               $case (cln, rsp.clong());
               rsp_p.put(cln);
            end : read_op
         endcase
      end : run_loop
   endtask : run_phase

endclass : predictor


Create a Comparator and a Printer to Report
  • It gets a response transaction from the monitor.
  • It compares the actual response transaction to the predicted response transaction.

class comparator extends uvm_agent;

   `uvm_component_utils (comparator)

   uvm_tlm_analysis_fifo #(mem_data) actual_f;
   uvm_get_port #(mem_data) predicted_p;
   mem_data actual_rsp, predicted_rsp;

   function new ...

   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      actual_f = new ("actual_f", this);
      predicted_p = new ("predicted_p", this);
   endfunction : build_phase

   task run_phase (uvm_phase phase);
      forever begin : run_loop
         actual_f.get (actual_rsp);
         predicted_p.get (predicted_rsp);
         if (actual_rsp.comp(predicted_rsp))
            uvm_report_info ("run",
               $psprintf ("passed: %s", 
                          actual_rsp.convert2string()) );
         else
            uvm_report_info ("run",
               $psprintf ("ERROR: expected: %s does not match actual: %s", 
                          predicted_rsp.convert2string(),
                          actual_rsp.convert2string()) );
      end : run_loop
   endtask : run_phase
endclass : comparator

class printer #(type T = mem_data) extends uvm_agent;
   `uvm_component_utils (printer#(T))

   uvm_tlm_analysis_fifo #(T) a_fifo;

   function new ...

   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      a_fifo = new ("a_fifo", this);
   endfunction : build_phase

   task run_phase (uvm_phase phase);
      forever begin
         T data;
         a_fifo.get(data);
         uvm_report_info ("run", data.convert2string());
      end
   endtask : run_phase
endclass : printer


class mem_data extends uvm_transaction;
   `uvm_object_utils (mem_data)
   rand logic [15:0] data;
   rand lobic [15:0] addr;

   virtual function bit comp (uvm_object rhs);
      mem_data RHS;
      $cast (RHS, rhs);
      return ((RHS.addr == addr) && (RHS.data == data));
   endfunction : comp
endclass : mem_data

class mem_req extends mem_data;
...
endclass : mem_req


Top Leven Test Environment
class test_env extends uvm_env;
   `uvm_component_utils (test_env)

   tester tst;
   driver drv;
   uvm_tlm_fifo #(mem_req) tester2driv;

   printer #(mem_req)  req_prt;
   printer #(mem_data) rsp_prt;
   monitor mon;
   predictor pred;
   comparator cmp;
   uvm_tlm_fifo #(mem_data) pred2cmp;

   function new (string name = "tester_env",
                 uvm_component parent = null );
      super.new (name, parent);
   endfunction : new

   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      tst = tester::type_id::create ("tst", this);
      drv = driver::type_id::create ("drv", this);
      tester2drv = new ("tester2drv");

      req_prt = printer#(mem_req)::type_id::create("req_prt", this);
      rsp_prt = printer#(mem_data)::type_id::create("rsp_prt", this);

      mon = monitor::type_id::create ("mon", this);
      pred = predictor::type_id::create ("pred", this);
      cmp = comparator;:type_id::create ("cmp", this);
      pred2cmp = new("pred2cmp"< this);
   endfunction : build_phase

   virtual function void connect_phase (uvm_phase phase);
      super.connect_phase(phase);
      tst.tb_port.connect (tester2drv.put_export);
      drv.req_f.connect (tester2drv.get_export);
      cmp.predicted_p.connect (pred2cmp.get_export);
      pred.rsp_p.connect(pred2cmp.put_export);
      mon.req_a.connect (pred.req_fifo.analysis_export);
      mon.rsp_a.connect (cmp.req_fifo.analysis_export);
      mon.req_a.connect (req_prt.a_fifo.analysis_export);
      mon.rsp_a.connect (rsp_prt.a_fifo.analysis_export);

   endfunction : connect_phase

endclass : test_env

class bucket #(type T = mem_data) extends printer #(T);

   typedef bit_bucket#(T) thistype;
   `uvm_component_param_utils (thistype)

   function new ...

   task run_phase (uvm_phase phase);
      forever begin
         T data;
         a_fifo.get(data);
      end
   endtask : run_phase

endclass : bucket

class qtest extends uvm_test;
   `uvm_component_utils (qtest)

   test_env t_env;

   function new ...

   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      printer#(mem_data)::type_id::set_type_override
         (bucket#(mem_data)::get_type());
      printer#(mem_req)::type_id::set_type_override
         (bucket#(mem_data)::get_type());
      t_env = test_env::type_id::create ("t_env", this);
   endfunction : build_phase

endclass : qtest



SystemVerilog Demystified.

Virtual (Abstract) vs Concrete
The clone method is used to provide a deep (nested) copy of an object. clone first allocates new memory for the object, then copies over each field to the new object. If a field is an object handle, then instead of copying the handle (which would do a "shallow" copy) you would call fieldname.clone() to recursively allocate memory for that field (a "deep" copy).

Clone (Virtual) vs Copy (Concrete)

class base;
int p1;
  function void copy(base orig);
    this.p1 = orig.p1;
  endfunction
endclass
class ex_base;
  int p2;
  function void copy(base orig);
    super.copy(b);
    this.p2 = orig.p2;
  endfunction
endclass
 
base b1,b2;
ex_base eb1, eb2;
initial begin
   eb1 = new; eb2 = new();
   eb2.p2 = 5;
   b1 = eb1; b2 = eb2;
   b1.copy(b2); // p2 is not copied
   eb1.copy(eb2); // p2 is copied
end

// Since copy() is not virtual, calling b1.copy() calls base::copy(), 
// and the additional property p2 is not copied even though it exists 
// in object referenced by b1.

Wednesday, October 26, 2016

UVM Configuration DB Gotchas.


  • Missing super.build_phase()
  • Missing field macro
  • UVM_READONLY on field
  • Missing get() after set() changes the entry
  • uvm_config_object::set() writes a null object
  • Wrong or mismatched types
  • Missing $cast in explicit get()
  • Wrong string in field names, wrong context
  • Not a good practice to use wildcard in ::set() - creating too much visibility

 References:

UVM Configuration DB.

Concepts
  • Share information between
    • Test
      • Top environment
        • sub environment
          • agents
            • sequencers
            • monitors
            • drivers
  • Need a consistent way of storing shared data 
  • Need simple, flexible access from anywhere
  • Need automatic access (done by uvm_component::build_phase())
  • Compare to traditional
    • enclosing pushes
    • ex. env.m_this_config = m_cfg
How to Use
  • Share the information of Physical IFs (between DUT and uvm_test)
    • Put into configuration db at top test module and get it in
      uvm_env.uvm_agent
      uvm_env.uvm_agent.uvm_driver
      uvm_env.uvm_agent.uvm_sequencer
      uvm_env.uvm_agent.uvm_monitor
  • Share DUT specific information

Syntax
//
// UVM 1.1
set_config_int(...) => uvm_config_db#(uvm_bitstream_t)::set(cntxt,...)
set_config_string(...) => uvm_config_db#(string)::set(cntxt,...)
set_config_object(...) => uvm_config_db#(uvm_object)::set(cntxt,...)
//
// UVM 1.2
// type T=int
// class uvm_config_db#(type T=int) extends uvm_resource_db#(T)
//
//                   context, inst,  key,   value   
uvm_config_db#(T)::set(cntxt,"inst","field",value); // modify central entries
uvm_config_db#(T)::get(cntxt,"inst","field",value); // update local variabbles
// There is a uvm11-to-uvm12.pl conversion script
uvm_config_db#(T)::exists(cntxt,"inst","field");
uvm_config_db#(T)::wait_modified(cntxt,"inst","field");

// For objects use this
set_config_object::set(this,"env.agent1","config", m_config);
// For enums use this
set_config_int::set(this,"env.agent1","bus_sz", SZ_128 );

// cntxt must be of type uvm_component, null or uvm_root::get()
// m_config: recommend to use uvm_object and $cast 
// Examples:
uvm_config_db#(T)::set(uvm_root::get(),”test1.env.agent1”, ”config”, m_config);
uvm_config_db#(T)::set(this,”env.agent*”,”config”, m_config);
uvm_config_db#(T)::set(null,”*”,”global_cfg”, m_global_cfg);

// to fetch the entry
if (!uvm_config_db#(uvm_object)::get(this, "","config",m_config)) begin
   `uvm_fatal(...) 
end
// check if it exists
if(!uvm_config_db#(int)::exists(this,"","low_power_mode")) begin 
   // do something interesting
end

// To automate field configuration
// Use uvm_config_object typedef
// Use uvm_object and $cast to concrete type for get()
function void uvm_component::build_phase(...); 
   // find fields, do get(), $cast
   apply_config_settings(...); 
endfunction

// Gotchas: 1. Don't miss field-macro
//         2. Make sure it's not UVM_READONL
/          3. remember to use super.build

class my_comp extends uvm_component;
   `uvm_component_utils_begin(my_comp)
      `uvm_field_int(my_field,UVM_DEFAULT) 
      `uvm_field_object(my_special,(UVM_DEFAULT|UVM_READONLY))
      `uvm_field_object(my_config,UVM_DEFAULT)  

      function void build_phase(...);
         super.build_phase(...);
         ...
      endfunction

// Using uvm_object and $cast in set() and get()
my_config m_config;
   ...
uvm_config_object::set(..., m_config);

uvm_object tmp;
uvm_config_object::get(..., tmp); 
$cast(m_config, tmp); // back to original type

// Using enums (can be int, uvm_bitstream_t or uvm_integral_t
my_enum_t m_bus_sz;
uvm_config_int::set(... , "m_bus_sz", SZ16);

int tmp;
uvm_config_int::get(... ,"m_bus_sz", tmp)
m_bus_sz = my_enum_t'(tmp); // back to original type

// Recommend use the factory 
m_srio_config = uvc_srio_config::type_id::create("m_srio_config");


Hierarchy of Configuration Objects
class top_env_config extends uvm_object; 
   env1_config m_env1_config; 
   env2_config m_env2_config;
   ...
endclass

class env1_config extends uvm_object;
   int some_var;
   int some_other_var;
   agent1_config m_agent1_config;
   agent2_config m_agent2_config;
   ... 
endclass

class top_env extends uvm_env;
   env1 m_env1;
   env2 m_env2;
   top_env_config m_config;
   ...
   'uvm_component_utils_begin(top_env)
      'uvm_field_object(m_config, UVM_DEFAULT)
   'uvm_component_utils_end

   function build_phase();
      super.build_phase();
      set_config_object(this, "env1","m_config",
                       m_config.m_env1_config);
      set_config_object(this, "env2","m_config",
                       m_config.m_env2_config);
      m_env1 = env1::type_id::create("m_env1");
      m_env2 = env2::type_id::create("m_env2");
   endfunction
endclass

// Next Level Down
class env1 extends uvm_env; 
   env1_config m_config;
   ...
   'uvm_component_utils_begin(top_env)
      'uvm_field_object(m_config, UVM_DEFAULT)
   'uvm_component_utils_end

   function void build_phase();
      super.build_phase();
      set_config_object(this, "m_agent1","m_config",
                m_config.m_agent1_config); 
      set_config_object(this, "m_agent2","m_config",
                m_config.m_agent2_config); 
      m_agent1 = env1::type_id::create("m_agent1"); 
      m_agent2 = env2::type_id::create("m_agent2");
   endfunction
endclass


Turn on the debugging in simulation

% sim_cmd +UVM_TESTNAME=my_test +UVM_CONFIG_DB_TRACE


SystemVerilog 101.

Design
  • RTL
  • blocks
  • modules
  • vectors
  • assignments
  • arrays

Verification
  • signals, states
  • interfaces
  • clocking block
  • scheduling
  • functions
  • tasks
  • class
  • random
  • constraints
  • coverage
  • queues and arrays

Methodology
  • objects
  • components
  • messaging
  • virtual interfaces
  • TLM ports
  • field macros
  • event pool
  • transaction recording
  • phases
  • transactions
  • sequence item
  • sequences
  • parameterization
  • callbacks
  • configuration-db
  • factory
  • register model

Concepts
  • Test Layer and Functional Coverage
  • Scenario Layer
    • Generator / Virtual Sequence
    • Environment
  • Functional Layer
    • Agent
    • Scoreboard
    • Checker
  • Command Layer
    • Driver
    • Assertions
    • Monitor
  • Signal Layer
    • Dut
    • Interface
  • Phases
    • Build phase
      • Generate configuration: 
        • Randomize the configuration of the DUT
        • Randomize the surrounding environment
      • Build environment
        • Allocate and connect the test bench components based on the configuration
        • A testbench component exists in the testbench as opposed to physical components in the design.
      • Reset DUT
      • Configure DUT
        • load DUT command registers
        • Initialization
    • Run phase
      • Start Environment
        • Run the test bench components, BFMs and stimulus generators.
      • Run the test
        • Start the test and wait for doneness.
          • For random test, use the testbench layers as a guide. Wait for a layer to drain all the inputs from the previous layer and become idle. Then wait for the next lower layer.
          • Use time-out checkers to make sure it doesn't lock-up.
    • Wrap-up phase
      • Sweep
        • After the lower layer completes, wait for the final transactions to drain out of the DUT
      • Report
        • Once the DUT is idle, sweep the testbench for lost data
        • Check scoreboard for leftover transactions held that never came out.
        • Create the final report on whether the test passed.
        • If it failed, delete incorrect functional coverage results.
  • Constrained-random test with a test plan
    • First, build layered test bench, including self-checking portion.
    • Second, creating stimulus specific to a goal in test plan.
      • Error injection
    • Third,  add instrumentation to the environment and gathers functional coverage data.
    • Fourth, analyze the results to see if the goals are met.

Data Types
  • 4-state: logic, reg, integer, time
    • use $isunknown(some_logic_port) == 1 to check
  • 2-state: bit, byte, int, shortint, longint, real
  • String Methods

Arrays
  • Fixed-size Arrays
  • Dynamic Arrays
  • Queues
  • Associative Arrays

`default_nettype none
int cs[16];
int sc[15:0];
int array0 [7:0][3:0]; // packed, int=32bit
int array1[4] = '{0,1,2,3};
int descent[5] = '{9,8,default:0};
int addr[] = new[4];
array0[7][3] = 1;
bit [7:0] b_unpack[3]; // unpacked
bit [3:0][7:0] test[1:10]; // 10 entries of 4 bytes packed into 32bits
// packed array
bit [1:0] [2:0] [3:0] barray;
barray = '{'{4’h6, 4’h5, 4’h4}, '{4’h3, 4’h2, 4’h1}};

bit [3:0] nibble[];
integer mem[]; // dynamic array of integers

// Array Operations
for (int i=0; i<$size(array1); i++) array1[i] = i;
foreach (descent[j]) descent[j] = array1[j] * 4;
foreach (array0[i,j]) 
   $display ("@%0t: array[%0d][%0d] = %0d", $time, i, j, array0[i][j]);
array0 = '{'{9,8,7}, '{3{'5}}}; // tick - packed
int md[2][3] = ‘{‘{0,1,2}, ‘{3,4,5}};
foreach (md[i,j]) $display(“%d “, md[i][j]);
foreach (md[,j]) $display(“%d “, md[1][j]);
bit [31:0] src[5] = '{5{5}};
$displayb(src[0],, src[0][0],, src[2][2:1]);

// Dynamic Arrays
int dyn[], d2[];
dyn = new[5];
d2=new[20](dyn);
dyn=new[100];
dyn = ‘{dyn,5};
// shrinking
dyn = dyn[1:3];

integer addr[];
addr = new[100];
addr = new[200](addr); // double the size and preserving previous values.
addr = new [addr.size()*4](addr); // quadruple addr array
addr.delete; // delete all contents
addr.delete();
// var = $size(addr);

//
// Associative Arrays 
// Unused elements don't use memory, unlike standard array
//
int item[*]; // not recommended
int item[string];
int item[integer];
int item[classname];

item [ 2'b3 ] = 1;
item[ 16’hffff ] = 2;
item[ 4b’1000 ] = 3;
$display( "%0d entries\n", item.num ); // prints "3 entries"
// item.num = 3; // returns only number of assigned elements
item.delete; // remove all entries
item.delete (2'b3); // remove index 3
byte unsigned assoc[int], idx = 1;

int map [string];
map["is"] = 2;
map.delete["easy"];
if (map.exists("is")) map["is"] +=1;
// map.first(s) // assign map[s] to be the first value
// map.last(s)
// map.next(s)
// map.prev(s)

// Queues
int q[$] = {1,2,3,5,8}; //unbounded queue, initialized with 5 locations;
typedef struct {int a, b; bit flag} packet_t;
packet_t q3 [$:16]; //a bounded queue, with a maximum size of 16

// Queue Methods
// insert(value)
// delete(value)
// push_front(value)
// push_back(value)
// var = pop_front()
// var = pop_back()
// var = q[index]
// var = size()




UVM Scoreboard Methodology.

Principles and Concepts
  • Verify transaction functional correctness with the following approaches
    • constrained-randomization
    • coverage driven
    • transaction-level compartment
    • Use sequences
    • Use scoreboard
    • Use configuration-db
  • Use SystemVerilog to provide aggregate types for transaction storage and search
    • Dynamic Arrays, Associative Arrays, Queues, Classes
  • UVM analysis ports is easier to use than callbacks
  • UVM_transaction provides compare() / do_compare() methods
  • UVM factor for extension, replacement and reuse.

Plan of Attack
  • Analysis_port
    • port, export and imp classes used for transaction analysis
    • uvm_analysis_port - broadcasts a value to all subscribers implementing a uvm_analysis_imp
    • uvm_analysis_imp - receives all transactions broadcasted by a uvm_analysis_port.
  • Transaction Predictor
    • Required when the compared transaction is not the same format as input (ex. protocol bridges)
    • Design transforms data (ex. encryption, filter, encoder)
    • To Re-Use
      • encapsulation : a separate class
      • uvm_analysis_port / imp to connect
      • UVM factory to extend, replace existing objects
      • Replace complex predictors with several simpler scoreboards
  • Storage (for read scoreboard and for write scoreboard)
    • FIFO : queues
    • OOO : dynamic arrays, queues
    • MEM : associative array (indexed by address)
    • Associative array of queues
  • TLM Model
    • Used when you have multiple different transaction paths/routes
    • Used when behavior depends on the address or opcodes or other attributes of transactions
  • Using Factory
  • Interconnect
  • Automate by Randomization
  • Checks and Coverage
  • Assertions
  • Pool



Transactions
  • Transaction content
    • Data, address, Attributes, Opcode, Response, 
    • Data types:
      • memory -> scalar, bytes, integers, 
    • Data path:
      • Scalar
      • Transaction Item Class
  • Transaction ordering
    • FIFO
    • OOO
    • Precedence relationship
  • Test Data/Transactions -> Item of Sequences -> Sequences -> Sequencer -> Driver -> VIF -> DUT
  • DUT -> monitor -> Analysys_ports -> Scoreboard




Monday, October 24, 2016

UVM / System Verilog - Threads and Synchronization.


  • In SystemVerilog, when you instantiate static modules, you create multiple threads running the procedures within each instances.
  • Synchronization
    • Mailbox
    • Streams
    • Semaphore
    • Use Ports, Exports and TLM_FIFOs
      • uvm_put_port # (int) p1;
        p1 = new("put_port", this);
      • uvm_get_port #(int) p2;
      • uvm_tlm_fifl #(int) p3;
      • m1.p1.connect (p3.put_export);
        m2.p2.connect (p3.get_export);
      • // in f1.svh, for class c1
           uvm_put_port # (int) p1;
           p1 = new("put_port", this);
        // in f2.svh, for class c2
           uvm_get_port #(int) p2;
           p2 = new("p2", this);
        // in f3.svh, which contains the 
        //     test env for c1 and c2
           uvm_tlm_fifo #(int) p3;
           p3 = new("p3", this);
           c1.p1.connect (p3.put_export);
           c2.p2.connect (p3.get_export0;
        
        // c1.p1 -> (put_export of env)
        //               ->(p3)->
        //          (get_export of env) -> c2.p2
        
           
        endtask : run
        
    • Put shared variable in a package, together with all the classes that share that variable (using `include);
    • virtual task run();
         integer i;
         for (i = 1; i < cnt; i++) begin : loop
            uvm_report_info ("run", $psprintf(...));
            my_pkg::shared = i; // used by other classes 
                                // for synchronization
            // i = my_pkg::shared; // to read from the shared
         end : loop
      endtask : run
      
      
    • Blocking Methods vs Non-Blocking Methods
      • blocking method
        • myport.put(<data>);
        • myport.get(<data>);
      • non-blocking method (returns 0 if failed)
        • myport.try_put();
        • myport.try_get();

Example
class c1 extends uvm_agent;
   uvm_put_port #(int)p1;
   `uvm_component_utils(c1)

   function new...

   virtual function void build_phase (uvm_phase phase);
      super.build_phase(phase);
      p1 = new("p1", this);
   endfunction : build_phase

   virtual task run_phase (uvm_phase phase);
      phase.raise_objection(this);
      for (int i = 0; i < cnt; i++) begin
         p1.put(i);
         uvm_report_info("run_phase",...);
      end : loop
      phase.drop_objection(this);
   endtask : run_phase
endclass : c1

class c2 extends uvm_agent;
   uvm_put_port #(int)p2;
   `uvm_component_utils(c2)

   function new...

   virtual function void build_phase (uvm_phase phase);
      super.build_phase(phase);
      p2 = new("p2", this);
   endfunction : build_phase

   virtual task run_phase (uvm_phase phase);
      int i;
      forever begin : loop
         p2.get(i);
         uvm_report_info("run_phase",...);
      end : loop
   endtask : run_phase
endclass : c2

class c3 extends uvm_agent;

   `uvm_component_utils(c3)

   c1 p1;
   c2 p2;
   uvm_tlm_fifo #(int) p3;

   function new...

   virtual function void build_phase (uvm_phase phase);
      super.build_phase(phase);
      p1 = c1::type_id::create("p1", this);
      p2 = c2::type_id::create("p2", this);
      p3 = new("p3", this);
   endfunction : build_phase

   virtual function void connect_phase (uvm_phase phase);
      super.connect_phase(phase);
      c1.p1.connect(p3.put_export);
      c2.p2.connect(p3.get_export);
   endfunction : connect_phase

   virtual task run_phase (uvm_phase phase);
   endtask : run_phase

endclass : c3


Example : Blocking Communication vs Non-blocking Communication
// blocking
// @(posedge clk); // this could be missed 
//                   and block the following
// my_port.get(data);
// bus <= data; 

// non-blocking
// @(posedge clk)
// my_port.try_get(data); // won't suspend
// bus <= data;
//

class c1 extends uvm_agent;

   `uvm_component_utils(c1)
   uvm_put_port #(int)p1;

   function new...

   virtual function void build_phase (uvm_phase phase);
      super.build_phase(phase);
      p1 = new("p1", this);
   endfunction : build_phase

   virtual task run_phase (uvm_phase phase);
      phase.raise_objection(this);
      for (int i = 0; i < cnt; i++) begin
         // p1.put(i);
         // uvm_report_info("run_phase",...);
         #UNIT_DELAY; // to delay this thread so the following
                      // is always slower than p2 and 
                      // should never fail
         assert (p1.try_put(i)) else
            uvm_report_info("run_phase: p1 not connected");
         uvm_report_info("run_phase", $psprintf("put: %0d",i));
      end : loop
      phase.drop_objection(this);
   endtask : run_phase
endclass : c1

class c2 extends uvm_agent;

   `uvm_component_utils(c2)
   uvm_put_port #(int)p2;

   function new...

   virtual function void build_phase (uvm_phase phase);
      super.build_phase(phase);
      p2 = new("p2", this);
   endfunction : build_phase

   virtual task run_phase (uvm_phase phase);
      int i;
      forever begin : loop
         // p2.get(i);
         // uvm_report_info("run_phase",...);
         if (p2.try_get(i))
            uvm_report_info ("run",
               $psprintf ("got: %0d",i));
         else
            uvm_report_info ("run","got nothing");
      end : loop
   endtask : run_phase
endclass : c2



UVM - Scoreboard, Checking and Reporting.


  • Scoreboard
  • Reporting printer
  • Using create

Scoreboard

  • Scoreboard could hold the entire self-checking structure including the transfer function or reference model, the expected data storage mechanism and the output comparison function . It could also be limited to the data structure used to hold the expected data for ease of comparison against the monitored output values.
  • Stimulus Generator or Sequencer
    • DUT -> Response Monitor
    • TLM or transfer function
  • Output from the DUT responses are compared with expected result from transfer model

class scoreboard extends uvm_agent;
   `uvm_component_utils(scoreboard)

   virtual interface mem_if vif;
   logic [15:0] exp [2**16-1:0];

   function new (string name = "scoreboard", uvm_component parent = null);
      super.new (name, parent);
   endfunction : new

   task run_phase (uvm_phase phase);
      forever begin
         @ (vif.cb)
         if (vif.rd) begin
            #`UNIT_DELAY
            assert (vif.data === exp[vif.addr]) else
               uvm_report_error ("run",
                  $psprintf("expected %0h  actual: %0h",
                      exp[vif.addr], vif.data));
         end
         if (vif.wr) begin
            exp[vif.addr] = vif.data;
         end
      end
   endtask : run_phase 


Reporting
class reporter extends uvm_agent;

   `uvm_component_utils (reporter)
   virtual interface mem_if vif;

   function new (string name = "reporter", uvm_component parent = null);
      super.new (name parent);
   endfunction : new

   task run_phase (uvm_phase phase);
      forever begin
         @(vif.cb);
         uvm_report_info ("run",
            $psprintf ("addr: %1h  data:%4h  rd:%1b  wr: %1b",
               vif.addr, vif.data, vif.rd, vif.wr));
      end
   endtask : run_phase
endclass : reporter

class bucket extends reporter;

   `uvm_component_util(bucket)

   function new ...

   task run_phase (uvm_phase phase); // override to do nothing
   endtask : run_phase

endclass : bucket



Create Tests
// In the test class file
class test1 extends uvm_test;

   `uvm component_utils(test1)

   test_env tenv;

   function new (string name, uvm_component parent);
      super.new(name, parent);
   endfunction : new

   virtual function void build_phase (uvm_phase phase);
      tenv = test_env::type_id::create("tenv", this);
   endfunction : build_phase

endclass

class test2 extends uvm_test;

   `uvm component_utils(test2)

   test_env tenv;

   function new (string name, uvm_component parent);
      super.new(name, parent);
   endfunction : new

   virtual function void build_phase (uvm_phase phase);
      // When you call the overriding run_phase in bucket,
      // the test will run without printing line by line data in
      // in default reporter.run_phase
      reporter::type_id::set_type_override(bucket::get_type());
      tenv = test_env::type_id::create("tenv", this);
   endfunction : build_phase

endclass : test2

class test_env extends uvm_env;

   `uvm_component_utils (test_env)

   driver drv;
   scoreboard sb;
   reporter rpt;

   function new ...

   virtual function void build_phase (uvm_phase phase);
      drv = driver::type_id::create("drv", this);
      sb  = scoreboard::type_id::create("sb", this);
      rpt = reporter::type_id::create("rpt", this);
   endfunction : build_phase

endclass



UVM Connections.

Using Interface
  • Virtual interface
  • Static interface

Example 1
`include "uvm_macros.svh"

package my_pkg;
   import uvm_pkg::*;
   int shared_int;
   int shared_count;

   virtual interface mem_if global_vmi;
   `include "uvm_macros.svh"
   `include "test_1.svh"
   `include "test_2.svh"

endpackage: my_pkg

import uvm_pkg::*;
import my_pkg::*;

module top;
   mem_if mi();
   sram dut (mi.mem_modport);

   initial begin
      string test_name;
      my_pkg::global_vmi = mi;
     run_test();
   end

endmodule: top

// typedef struct packed
typedef struct {
   bit     sign;
   bit[24:0] mantissa;
   bit[ 5:0] exponent;
} ieee_sp_float;

union packed {
   bit [7:0] data[1500];
   struct packed {
      bit [7:0] dsap;
      bit [7:0] ssap;
      bit [7:0] control;
      bit [7:0] data[1497];
   } label;
} payload;

class test_1 extends uvm_test;
   `uvm_component_utils(test_1)

   ieee_sp_float v1, v2;
   v1 = {1, 24'h800, 6'h0};
   v1 = abs(v1);
   virtual interface mem_if mi;

   function new (string name, uvm_component base);
      super.new(name, base);
   endfunction : new

   virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      mi = my_pkg::global_vmi;
   endfunction : build_phase

   virtual task run_phase(uvm_phase phase);

      int cnt=5;
      logic [3:0] sub_addr;
      rand logic [11:0] upper_addr;
      sub_addr = $urandom($random);
      phase.raise_objection(this);
      mi.wr = 1'b1;
      mi.rd = ~mi.wr;
      mi.wr_data = $urandom($random);
      `uvm_info("TESTER", 
         $psprintf("addr: %2h  data: %2h  rd: %1b  wr: %1b", 
         mi.addr, mi.data, mi.rd, mi.wr), UVM_INFO);

      super.run();
      mi.addr = {upper_addr, sub_addr};

      repeat (cnt) begin
         @(posedge mi.clk);
         ...
      end
         @(posedge mi.clk);

         phase.drop_objection(this);

   endtask // run_phase


Example 2
import my_pkg::*;

// Virtual interface in driver
class my_driver extends uvm_driver #(my_transaction); 

   `uvm_component_utils(my_driver)

   virtual dut_if dut_vi;

   function new(string name, uvm_component parent); 
      super.new(name, parent);
   endfunction: new

   // function void build;
   virtual function void build_phase (uvm_phase phase);
      super.build();
      dut_vi = global_dutvi;
   endfunction : build_phase

   // task run;
   task run_phase (uvm_phase phase);
      repeat(4)
      begin
         phase.raise_objection(this);
         my_transaction tx;
         @(posedge dut_vi.clock);

         // Driver consumes the transactions generated by
         // my_transaction and wiggles the pins on the DUT
         seq_item_port.get(tx);

         // Pin Wiggling
         dut_vi.cmd  = tx.cmd;
         dut_vi.addr = tx.addr;
         dut_vi.data = tx.data;

      end
      @(posedge dut_vi.clock) top.stop_request();
      phase.drop_objection(this);

   endtask: run

endclass : my_driver


Example 3, connecting sequencer to driver
class my_sequencer extends uvm_sequencer;
   ...
   uvm_put_port #(int) port1;
   port1 = new ("port1", this);

endclass

class my_driver extends uvm_driver;
   ...
   uvm_get_port #(int) port2;
   port2 = new ("port2", this);

endclass

class my_agent extends uvm_agent; 
   `uvm_component_utils(my_agent) // register for type_id

   my_sequencer my_sequencer_h;
   my_driver my_driver_h;

   function new(string name, uvm_component parent); 
      super.new(name, parent);
   endfunction: new

   function void build;
      super.build(); 
      my_sequencer_h = 
         my_sequencer::type_id::create("my_sequencer_h", this);
                                     // instance name,   parent
      my_driver_h =
         my_driver::type_id::create  ("my_driver_h" , this);

   endfunction: build

   // Lower level connection in another function is good practice
   // seq_item_port is the handler of the ports

   function void connect; 
      my_driver_h.seq_item_port.connect(
         my_sequencer_h.seq_item_export ); 
   endfunction: connect

endclass : my_agent


Example 4, connecting through top module
`timescale 1ns/1ns

module top;

   mem_if mi();
   sram dut (mi.mem_modport);
   tester tst (mi.test_modport);

endmodule // top

interface mem_if;
   bit clk, rd, wr;
   logic [15:0] wr_data;
   wire  [15:0] data;
   logic [15:0] addr;

   modport mem_modport (
      inout data,
      input addr,
      input clk,
      input rd,
      input wr
   );

   modport test_modport (
      input clk,
      output wr_data,
      output addr,
      output rd,
      output wr
   );

   clocking cb @ (negedge clk);
      output data <= ...;
      output addr <= ...;
   endclocking: cb

   initial begin
      @(cb) ; wr_data <= ...;
      @(cb) ; wr <= $urandom;
   end

   assign rd = ~wr;
   assign data = (wr) ? wr_data : 16'hzzzz;

   initial begin
      clk = 0;
      $monitor ();
   end

   always #10 clk = ~clk;

endinterface // mem_if


Example 5, connecting in tester
module top;

   mem_if mi();
   sram dut (mi.mem_modport);
   tester tst;

   initial begin
      tst = new(mi);
      fork
         tst.run;
      join_none
   end

endmodule // top

class tester; // driver

   logic [3:0] sub_addr;
   virtual interface mem_if tmi;

   function new (virtual interface mem_if vmi);
      tmi = vmi;
   endfunction // new

   task run;
      // generate transaction data
      tmi.wr = 1'b1;

      @ (posedge tmi.clk); 
      repeat (100) begin
         @ (posedge tmi.clk); 
         tmi.wr = $random;
         tmi.rd = ~tmi.wr;
         tmi.addr = $random;
         tmi.wr_data = $urandom($random);
      end
      $stop;
   endtask // run

endclass // tester


Example 6, use wrapper_if
module top;

import uvm_pkg::*;
import my_pkg::*;

   mem_if mi();
   sram dut (mi.mem_modport);
   // tester tst; // replaced by if_wrapper

   initial begin: blk
      dut_if_wrapper if_wrapper = new ("if_wrapper", dut_if_inst1);
                   // path  field_name        value      0: don't clone
      set_config_object("*", "dut_if_wrapper", if_wrapper, 0);

      run_test ("my_test");
   end

endmodule : top

class dut_if_wrapper extends uvm_object;

   virtual dut_if dut_vi;
   function new (string s, virtual dut_if if_arg); 
      super.new(s);
      dut_vi = if_arg;
   endfunction : new

   // you can have task run; here

endclass : dut_if_wrapper

`include "uvm_macros.svh"

package my_pkg;
import uvm_pkg::*;

// Fixed test environment
class my_env extends uvm_env;
    `uvm_component_utils (my_env)

    virtual dut_if dut_virtual_if_inst;

    // constructor
    function new (string s, uvm_component inst_parent);
        super.new (s, inst_parent);
    endfunction : new

    function void build;
        super.build ();
        begin
            uvm_object obj;
            dut_if_wrapper if_wrapper; 
            get_config_object("dut_if_wrapper", obj, 0);
            assert( $cast(if_wrapper, obj) );
            dut_virtual_if_inst = if_wrapper.dut_vi;
        end
    endfunction : build

    task run;
        #10 dut_virtual_if_inst.data = 0;
        #10 dut_virtual_if_inst.data = 1;
        #10 stop_request();
    endtask : run

endclass : my_env


Example 7, use uvm_get_port and uvm_put_port in tlm_fifo / tlm_analysis_fifo
class producer extends uvm_agent;
   uvm_put_port #(int) phone1;
   ...

   virtual function void build_phase (uvm_phase phase);
      super.build_phase(phase);
      phone1 = new("phone1", this);
   endfunction

   virtual task run_phase (uvm_phase phase);
      phase.raise_objection(this);
      for (int i = 0; i < count; i++) begin : loop
         phone1.put(i);
         uvm_report_into ("run_phase", $psprintf("...");
      end : loop
      phase.drop_objection(this);
   endtask : run_phase

endclass : producer

class consumer extends uvm_agent;
   uvm_get_port #(int) phone2;
   ...

   virtual function void build_phase (uvm_phase phase);
      super.build_phase(phase);
      phone2 = new("phone2", this);
   endfunction

   virtual task run_phase (uvm_phase phase);
      phase.raise_objection(this);
      for (int i = 0; i < count; i++) begin : loop
         phone1.put(i);
         uvm_report_into ("run_phase", $psprintf("...");
      end : loop
      phase.drop_objection(this);
   endtask : run_phase

endclass : producer

class test_env extends uvm_env;

   producer p;
   consumer c;
   uvm_tlm_fifo #(int) tlmff;

   function new () ...

   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      p = producer::type_id::create ("p", this);
      p = producer::type_id::create ("p", this);
      tlmff = new ("tlmff", this);
   endfunction : build_phase

   virtual function void connect_phase (uvm_phase phase);
      super.connect_phase (phase);
      p.phone1.connect (tlmff.put_export);
      c.phone2.connect (tlmff.get_export);
   endfunction : connect_phase


Example 8, using uvm_config_db
module top;
   ...
   dut_if dut_if1 ();
   initial
   begin: blk
      //             type of value        prefix   path
      uvm_config_db #(virtual dut_if)::set(null, “uvm_test_top”, 
                  "dut_vi", dut_if1);
      //          field name, value
      run_test("my_test");
   end
endmodule: top

class my_test extends uvm_test;
   ...
   my_dut_config dut_config_0; 
   ...

   function void build_phase(uvm_phase phase);
      dut_config_0 = new();
      //             type of value    prefix   path
      if(!uvm_config_db #(dut_if)::get( this, “”, 
                        “dut_vi”, dut_config_0.dut_vi))
             `uvm_fatal(“MY_TEST”, “No DUT_IF”);

      // other DUT configuration settings
      uvm_config_db#(my_dut_config)::set(this, “*”, “dut_config”,
                                       dut_config_0);     
    endfunction
endclass

class my_driver extends uvm_driver;
   `uvm_component_utils(my_driver)
   virtual dut_if dut_vi;

   function new(string name, uvm_component parent); ...

   function void build_phase(uvm_phase phase); ...

   task run_phase(uvm_phase phase);
      phase.raise_objection(this);
      #10 dut_vi.data = 0;
      #10 dut_vi.data = 1;
      #10 phase.drop_objection(this); 
   endtask: run_phase

endclass


Sunday, October 23, 2016

Java Data Structure - Collections.

Collections

  • Autoboxing
  • Array List vs Linked List vs Queue
  • Hash map vs Tree map
  • untyped collections and wrapper class with untyped collections
  • Wrapper classes for primitive types
    • Byte (byte)
    • Short (short)
    • Integer (int)
    • Long (long)
    • Float (float)
    • Double (double)
    • Character (char)
    • Boolean (boolean)
  • Java Collection Framework (Collections is the basic methods):
    • Lists (ordered) - ArrayList and LinkedList
    • Sets  (no dupicate) - HashSet
    • Mapes (key value pair) - HashMap and TreeMap
  • How it's different from Arrays
    • Collections are classes in Java API, array is a Java Language feature.
    • Collection classes have methods.
    • Collections are varied in size.
    • Collections are containers for objects, not for primitive types.
    • Collections can process without indices while indices are usually required to process arrays.
  • Generic collections
    • ex. ArrayList<String> al = new ArrayList<String>();

Example
// This is an untyped array list
ArrayList al = new ArrayList();
al.add("item1");
al.add("item2");
for (Object o : al)
    { ... }

ArrayList p = new ArrayList();
p.add (new className (...));

for (int i = 0; i < p.size(); i++) {
    className c = (className)p.get(i);
    ...
}

// untyped array list will result in compiler warning
// Note: file.java uses unchecked or unsafe operations.
// Note: Recompile with -Xlint:unchecked for details.


ArrayList Numbers = new ArrayList();
numbers.add(new Interger(1));
numbers.add("Mary");

//
// and gives run time errors:
// Exception in thread "main" java.lang.ClassCastException: java.lang.String 
// cannot be cast to java.lang.Integer at Demo.main(file.java:37)

        ArrayList numbers = new ArrayList();
           numbers.add(new Integer(1));
           numbers.add(new Integer(2));
           numbers.add("Mary");
           numbers.add("Helen");

        for (int i = 0; i < numbers.size(); i++)
           {
               int number = (Integer)numbers.get(i);
               System.out.println(number);
           }



// Use collection in a generic array

ArrayList<String> codes = new ArrayList<String>();
codes.add("Mary");
codes.add("Helen");
codes.add("Raymond");
codes.add(100); //compiler error, wrong type, has to be String
System.out.println(codes);


// Using wrappers for primitives
ArrayList Numbers = new ArrayList();
numbers.add(new Integer(1));


Classes and Packages

  • java.util.Arrays
  • java.util.ArrayList
    • Constructors
      • ArrayList<E>()
      • ArrayList<E>(intCapacity)
      • ArrayList<E>(Collection)
    • Methods:
      • add(object)
      • add(index, object)
      • clear()
      • contains(object)
      • get(index)
      • indexOf(object)
      • isEmpty()
      • remove(index)
      • remove(object)
      • set(index, object)
      • size()
      • toArray()


Java Data Structure - Arrays.

Arrays
  • Array is aggregate data types that contains elements of the items in an array.
  • Built-in in Java for primitives or references.
  • Jagged array vs Retangular array
  • Enhanced for loop
  • Array Class: java.util.Arrays
    • fill (arrayName, value) // Fill out all elements to "value"
    • fill (arrayName, fromIndex, toIndes_plus_1, value)
    • equals (array1, array2)
    • copyOf (arrayFrom,  length) // JDK 1.6+ shallow copy for ref type
    • copyOfRange (arrayFrom,  fromIndes, toIndex_plus_one) // JDK 1.6+
    • sort (arrayName) // MUST implememts Comparable Interface
    • sort (arrayName, fromIndex, toIndex)
    • binarySearch (arrayName, value) // Must have compareTo, sort or binarySearch method defined and must do Arrays.sort first for binarySearch

Example
String [] sArray;
String sArray[];
sArray = new String[];
sArray = new String[10];
sArray = new String[10][];

String [] SArray = new String[];
String sArray [] = {"Mary", "Susan", "Raymond"};
double [] dArray = new double[10];
double [] prices = {12.95, 11.95, 10.95};

final int TOTAL_STUDENTS = 50;
Scanner sc = new Scanner(System.in);
int totalStudents = sc.nextInt();
String [] StudentsA = new String[TOTAL_STUDENTS];
String [] StudentsB = new String[totalStudents];

StudentsA[0] = "Mary";

String[] name1 = {"Forrest Gump", "A Beautiful Mind"};
String[] name2 = {"Forrest Gump", "A Beautiful Mind"};
// if (name1 == name2) ==> gives "false"
// if (Arrays.equals(name1, name2) ==> gives "true"

Public interface Comparable {
    int compareTo (Object obj);
}

class Item implements Comparable {
    private int number;
    private String name;
    public Item (int n, String s) {
        this.number = n;
        this.name = s;
    }

    public int getNumber () {
        return number;
    }

    // This overriding compareTo compares the first field
    //     which is the item.number in this case
    //     can be altered by supplementing with another
    //     class implementing "Comparator" interface
    //     to compare by name
    //
    @Ovrride
    public int compareTo(Object o) {
        if (o instanceof Item) {
            Item i = (Item) o;
            if (this.getNumber() < i.getNumber()) {
                return -1;
            } else if (this.getNumber() > i.getNumber()) {
                return 1;
            }
            return 0; 
        }
    }
}

public class ItemOtherCompare implements Comparator {
    public int compare (Object o1, Objece o2) {
        int i1 = ((Item) o1).getOtherField();
        int i2 = ((Item) o2).getOtherField();
        if (i1 > i2) return 1;
        if (i2 > i2) return -1;
        return 0;
    }

    public boolean equals (Object o1, Object o2) {
        int i1 = ((Item) o1).getOtherField();
        int i2 = ((Item) o2).getOtherField();
        return (i1 == i2);
        return false;
    }
}

// Arrays.sort(items); // this will sort by first field data
// Arrays.sort(items, new ItemOtherCompare()); // this will sort by other field


Saturday, October 22, 2016

Java - Test Yourself.

 • Which of the following is an invalid list of elements in an array?
 "Joe", "Doug", "Anne"
 "Joe", 3, 25.5
 3, 17, 12
 12.3, 32.6, 21.7

 • What happens when the code that follows is executed?
 
   int[] nums = new int[4];
   for (int i = 0; i <= nums.length; i++)
   {
       nums[i] = i;
   }
   System.out.println(nums[2]);

 It prints “1” to the console.
 It prints “2” to the console.
 It prints “3” to the console.
It throws an ArrayIndexOutOfBoundsException.


 • What is printed to the console when the code that follows is executed?
 
   int[] years = new int[5];
   years[1] = 1992;
   for (int i = 0; i < years.length; i++)
   {
       years[i]++;
   }
   System.out.println(years[3]);

 “3”
 “4”
 “1”
 “1994”

 • Before you can sort an array of objects created from a class that you 
   defined, the class must implement the ____________ interface.

   (Comparable)

 • Which of the following, if any, is an invalid array declaration?

 String[] names = new String[5];
 String names[] = new String[5];
 String[] names = new String[0];
 String[] names = {"one", "two"};
 all are valid


 • How many rows are in the array that follows?
 
   Rental[][] transactions = new Rental[7][3];

 7
 6
 3
 2

 • What is the value of temps[2][1] after the code that follows is executed?
 
   double[][] temps = new double[10][5];
   for (int i = 0; i < temps.length; i++)
   {
       for (int j = 0; j < temps[i].length; j++)
       {
           temps[i][j] = j + i;
       }
   }
 1.0
 2.0
 3.0
 4.0


 • A two-dimensional array whose rows can have different numbers of 
   columns is called a ____________ array. 

   (jagged)


 • What is the value of the variable named len after the code that follows is executed?
 
   int[][] nums = { {1, 2, 3}, {3, 4, 5, 6, 8}, {1}, {8, 8} };
   int len = nums.length;

 1
 2
 3
 4
 5


 • What is the value of the third element in the array that follows?
 
   double[] percents = new double[4];
   percents[1] = 85.66;
   percents[2] = 56.98;
   percents[3] = 25.66;

 25.66
 56.98
 85.66
 a third element doesn’t exist


 • What is printed to the console when the code that follows is executed?
 
   int[][] points = { {8,3}, {4,3}, {7,2} };
   String s = "";
   for (int i = 0; i < points.length; i++)
   {
       Arrays.sort(points[i]);
       for (int j = 0; j < points[i].length; j++)
       {
           s += points[i][j];
       }
   }
   System.out.println(s);

 383427
 437283
 342738
 233478


 • What is the value of the string named lowest when the code that follows is executed?
 
   String[] types = {"lux", "eco", "comp", "mid"};
   Arrays.sort(types);
   String lowest = types[0];

 lux
 eco
 comp
 mid


 • What is the highest index value associated with the array that follows?
 
   byte[] values = new byte[x];

 0
 x
 x + 1
 x – 1
 can’t tell from information given


 • Consider the following code:
 
   double[] times = {3.56, 3.9, 2.6, 4.5, 2.4, 5.2};
   double[] bestTimes = new double[4];
   Arrays.sort(times);
   bestTimes = Arrays.copyOfRange(times, 1, 4);
 
 • What values are in the bestTimes array?

 2.4, 2.6, 3.56
 2.6, 3.56, 3.9
 2.4, 2.6, 3.56, 3.9
 2.6, 3.56, 3.9, 4.5


 • What does the x represent in the following declaration?
 
   BigDecimal[][] sales = new BigDecimal[x][y];

 the number of elements in each array
 the number of arrays in the sales array
 the number of tables in the sales array


 • What is the value of the variable named lists after the statements that follow are executed?
 
   String[][] names = new String[200][10];
   int lists = names.length;

 9
 10
 199
 200
 code doesn’t compile

 • A two-dimensional array whose rows all have the same number of 
   columns is called a ____________ array.  

   (rectangular)


 • What is printed to the console when the code that follows is executed?
 
   int[] values = {2, 1, 6, 5, 3};
   Arrays.sort(values);
   int index = Arrays.binarySearch(values, 5);
   System.out.println(values[index] - 1);

 “2”
 “3”
 “4”
 “5”
 “6”


 • Which of the following statements performs the same task as the 
   for loop in the code that follows?
 
   double[] times = new double[3];
   for (int i = 0; i < times.length; i++)
   {
       times[i] = 2.0;
   }

 Arrays.fill(times, 0, 3, 2.0);
 Arrays.fill(times, 1, 3, 2.0);
 Arrays.fill(times, 1, 4, 2.0);
 Arrays.fill(times, 0, 2, 2.0);


 • What is printed to the console after the code that follows is executed?
 
   int[][] types = new int[4][];
   for (int i = 0; i < types.length; i++)
   {
       types[i] = new int[i+1];
   }
   System.out.println(types[1].length);

 “2”
 “4”
 “1”
 “3”
 code doesn’t compile


 • Which of the following is an invalid two-dimensional array definition?

 double[][] values = new double[2][8];
 double values[][] = new double[8][2];
 double[][] values = new double[8][];
 double[][] values = new double[][8];What is printed to the console when the code that follows is executed?
 
   int[] nums = new int[2];
   int[] vals = new int[2];
   if (Arrays.equals(nums, vals))
       System.out.println("One");
   vals[1] = 2;
   nums = vals;
   if (Arrays.equals(nums, vals))
       System.out.println("Two");

 “One”
 “Two”
 “One” and “Two”
 nothing is printed to the console


 • What is the value of names[4] in the following array?
 
   String[] names = {"Jeff", "Dan", "Sally", "Jill", "Allie"};

 Sally
 Jill
 Allie
 name[4] doesn’t exist


 • An enhanced for loop can only be used

 to work with arrays that contain integers
 to work with one-dimensional arrays
 to work with all the elements of an array
 to work with jagged arrays


 • To use the binarySearch method of the Arrays class on an array of ints, 
   you must first

 create an Arrays object
 sort the array
 implement the Comparable interface
 override the equals method


 • What is the value of grades[1] after the following statements are executed?
 
   int[] grades = new int[2];
   grades[0] = 98;
   grades[1] = 84;
   grades = new int[2];

 98
 84
 0

 • What is the value of times[2][1] in the array that follows?
 
   double[][] times = { {23.0, 3.5}, {22.4, 3.6}, {21.3, 3.7} };

 3.7
 22.4
 3.5
 21.3
 3.6


 • Why won’t the following code execute?
 
   double values[] = new double[5];
   values[5] = 6;

 The brackets in the first statement are misplaced.
 An int value can’t be assigned to a double.
 The index is out of bounds.


 • Since the sort method of the Arrays class can sort String objects, what must be true of the String class?

 It contains a sort method.
 It implements the comparable method.
 It inherits a sort method.
 It implements the Comparable interface.


 • Which of the following statements gets the number of Customer objects 
   in the array that follows?
 
   Customer[] customers = new Customer[55];

 int size = customers.length();
 int size = customers.length;
 int size = customers.size();
 int size = Arrays.size(customers);


 • When you use an enhanced for loop with an array, you don’t 
   need to use a ________________ to iterate through the elements of the array.

   (counter variable or counter) 


 • Before you can use the binarySearch method of the Arrays class to 
   search for an element with a specified value in an array, you must ________________.  
   (sort the array)

 • Each row of a two-dimensional array is stored as a/an ____________. 
   (array)

 • Consider the following code:
 
   double[] times = {3.56, 3.9, 2.6, 4.5, 2.4, 5.2}; 
   double[] bestTimes = new double[4]; 
   Arrays.sort(times); 
   bestTimes = Arrays.copyOfRange(times, 1, 4); 
 
   What is the length of the bestTimes array?

 6
 5
 4
 3


 • What is the value of the variable named len after the code that follows is executed?
 
   int[][] nums = { {1, 2, 3}, {3, 4, 5, 6, 8}, {1}, {8, 8} };
   int len = nums[2].length;

 1
 2
 3
 4
 5


 • Consider the following code:
 
   double[] times = {3.56, 3.9, 2.6, 4.5, 2.4, 5.2};
   double[] bestTimes = new double[4];
   Arrays.sort(times);
   bestTimes = Arrays.copyOfRange(times, 1, 4);
 
   What values are in the times array after the code is executed?

 2.4, 2.6, 3.56, 3.9, 4.5, 5.2
 3.56, 3.9, 2.6, 4.5, 2.4, 5.2
 2.4, 2.6, 3.56
 2.4, 2.6, 3.56, 3.9


 • What is the value of nums[2] after the following statements are executed?
 
   int[] values = {2, 3, 5, 7, 9};
   int[] nums = values;
   values[2] = 1;

 3
 1
 5
 0






Friday, October 21, 2016

UVM 101.

Packages
  • Provide a common name space •
  • Can be imported • 
  • Can contain common objects •
// You can have the followings in a package
// • Common typedefs 
// • Common class definitions
// • Shared instances or variables

import uvm_pkg::*;

`include "defines.svh"
`include "macro_defines.svh"
`include "test_plugin.svh"

module top;
        initial begin
                #10ns;
                uvm_top.uvm_report_info ($psprintf("%m"),
                        "This is an info message");
        end
endmodule


Macros
`define info(msg)    uvm_top.uvm_report_info($psprintf("%m"), msg);
`define warning(msg) uvm_top.uvm_report_warning($psprintf("%m"), msg);
`define error(msg)   uvm_top.uvm_report_error($psprintf("%m"), msg);
`define fatal(msg)   uvm_top.uvm_report_fatal($psprintf("%m"), msg);

import uvm_pkg::*;

module top;
    initial begin
        `info ("My info message goes here");
        `warning ("My warning message goes here");
        `error ("My error message goes here");
        `fatal ("My fatal message goes here");
    end
endmodule

`ifdef FPGA

module sythesizable_block;
endmodule // monitor

`else

module beh_model;
endmodule // beh_model;

`endif // !`ifdef FPGA

// Define macro when you compile in dofile
% if (file exists work) {delete -all}
% vlib work
% vlog top.sv +define+FPGA
% vsim -novopt top
% run -all

Classes
class read_op extends memory_op;
    constraint read_only_c {mem_op == read;};
endclass // read_op

// • Put each class in individual .svh file
// • Put all .svh files in a package "tb_pkg" using `include
// • Put all files in a file list "vfiles.f" to compile 
// • In the top test bench file, import "uvm_pkg" and this "tb_pkg"


UVM package
  • uvm_report_object
    • uvm_cmdline_processor
    • uvm_component
      • uvm_agent
      • uvm_driver #()
      • uvm_env
      • uvm_monitor
      • uvm_port_component_base
      • uvm_root
      • uvm_scoreboard
      • uvm_sequencer_base
      • uvm_test
      • uvm_tlm_fifo_base #()
  • UVM phases used in uvm_test
    • function void build_phase()
    • function void connect_phase()
    • function void end_of_elaboration_phase()
    • function void start_of_simulation_phase()
    • function void run_phase()
    • function void extract_phase()
    • function void check_phase()
    • function void report_phase()
  • Use "+UVM_TESTNAME=test1" to run different tests
    • The sub classes extended rom uvm_test with UVM_TESTNAME plusarg will start the run_test() that is defined in uvm_pkg and the run_test() uses UVM factory pattern to create a test object.

class test1 extends uvm_test;
   `uvm_component_util(test1)

    function new (string name, uvm_component base);
        super.new(name, base);
    endfunction : new

    task run_phase(uvm_phase phase);
        phase.raise_objection(this); // tell UVM this thread started
        super.run();
        `uvm_info("test1: ", "Starting...", UVM_INFO);
        phase.drop_objection(this);  // tell UVM this thread finished
    endtask
endclass : test1

// in top module
module top;

    initial run_test(); // this will create a test object 
                        // and executes its run_phase() 
endmodule : top


UVM Structure
  • Top
    • uvm_test or program in SystemVerilog
      • task run();
      • uvm_env
        • uvm_agent
          • driver
            • run
          • monitor
            • $monitoron / $monitoroff
            • sync_reset
            • semaphore
              • semaphore sem = new(1);
              • sem.get(1) ... sem.put(1)
              • `uvm_raise_objection(this)
                / `uvm_drop_objection(this)
            • disable <block_name>;
          • sequencer
            • sequence
              • body
              • start
            • transaction
              • build
              • run
        • uvm_scoreboard or ovm_subscriber
        • uvm_agent for coverage
    • interface
    • DUT

UVM Randomization and Constraints
typedef logic [15:0] addr_type;
typedef logic [7:0] data_type;
typedef enum {read, write, nop} op_type;

class my_op;
   rand addr_type addr;
   rand data_type data;
   rand op_type cmd;
   ...
endclass : my_op

class read_op extends my_op;
   constraint read_only_cmd {my_op == read;};
endclass // read_op

module top;
   my_op op;
   read_op rdop;
   addr_type addr2;

   initial begin
      op = new();
      addr2 = $random;
      repeat (2) begin

         assert(op.randomize());
         // with constraint
         assert(op.randomize() with {my_op == read;});

         assert(rdop.randomize()); // this will be limited to read only

      end
   end
endmodule // top



Thursday, October 20, 2016

NCG 101.

How to Sell Yourself
  • Competent
  • Confident
  • Caring
  • Consistent

How to Prepare
Always
  • Build your profile and projects out of school/work.
  • Network, connect with people in your field.
  • Build portfolio/website, join GitHub, C9.io, cloud collaboration.
  • Get exposed to large, meaty projects, find internship, take classes.

By 3-6 month
  • Create resume and get review.
  • Search for job openings.
  • Hone technical skills, test yourself in Java/C++ or what you use.
  • Ask friends to give you mock interviews.

By 1-3 month
  • Solidify key concepts for the job you target.
  • Practice interview questions and use mock interviews.
  • Review mistakes you made often.

By 1-4 weeks
  • Review your resume.
  • More mock interviews and rehearse interview questions.
  • Review key concepts, architectures, algorithms, approaches, data structures.
  • Review mistakes you made.

By 1-7 days
  • Print resumes to bring with you.
  • Repeat steps in "By 1-4 weeks" above.

Game day
  • Make sure to have plenty of sleep. (All time cliche, I know.)
  • Get up early and eat well.
  • Bring resumes and a notepad with you.
  • Bring something to read while you wait.
  • Don't forget thank-you note when you get home.

Information to Provide
  • Background - Prior Experience/Education
  • Behavior - Reliability, Stability, Ethics, Culture Fit
  • Technical Skill - Coding, programming
  • Intelligence - Analytical ability

Questions to Be Prepared to Answer
  • Technical - to know your skill set and level
  • Behavioral - to know your personality
    • Tell me a project that you find most challenging
    • What did you learn
    • How did you solve the problem
      • Explain the situation, your action that lead to result.
    • What was most interesting project you did in the past
    • What was the hardest bug you have experienced
    • What project did you enjoy the most
    • How did you deal with problems such as
      • Conflicts with teammates
      • Different opinions to persuade
      • Project delays or failures
  • What are your strengths and weaknesses

Questions You Should Ask
  • The quality of your questions will be a factor in the decisions.
  • You can ask about
    • Working environment questions, day-to-day office norm.
    • Team size, teammates background, products to be worked on, organization.
    • Tools to be used, management style, meeting style and frequency
    • Work flow
    • Technology used in projects
    • Opportunities to learn and grow
  • Find a Mentor