Showing posts with label systemverilog. Show all posts
Showing posts with label systemverilog. Show all posts

Saturday, October 29, 2016

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

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

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



Friday, October 7, 2016

OVM 101 - part 2.

Test Environment Nitty Gritty Code
  • Configuration - Connecting virtual interface from top level to DUT.
  • Use configuration table to store the wrapper(s) of virtual interface properties.
  • This way, the test bench can be used with different configurations, changing wrappers.
  • Configuration using "set_config_object" and "get_config_object" overrides top-down.
    ( from ovm_test -> ovm_env -> ovm_component)
// Top level "module" contains class based test environment
//        and structural interface that drives DUT (module)
module top;

import ovm_pkg::*;
import my_pkg::*;

...
dut_if dut_if_inst1 ();
dut dut_inst0 (._if (dut_if_inst1) );

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_set");
end

endmodule : top

class dut_if_wrapper extends ovm_object;

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

endclass : dut_if_wrapper

// ovm classes
// usually classes of test environment that includes fixed test bench
// and variable test sets

`include "ovm_macros.svh"

package my_package;
import ovm_pkg::*;

// Fixed test environment
class my_test_env extends ovm_env;
    `ovm_component_utils (my_test_env)

    virtual dut_if dut_virtual_if_inst;

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

    function void build;
        super.build ();
        begin
            ovm_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 ovm_top.stop_request();
    endtask : run

endclass : my_test_env

class my_test_set extends ovm_test;
    `ovm_component_utils (my_test_set)

    my_test_env my_test_env_handle;

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

    function void build;
        super.build();
        my_test_env_handle = my_test_env::type_id::create
            ("my_test_env_handle", this);
    endfunction : build

endclass : my_test_set

// interface dut_if(); -> between test components and DUT
interface dut_if ();

    logic clock, reset;
    logic data_input;

endinterface : dut_if

// Design under test
module DUT (dut_if _if);

    always @ (posedge _if.clock)
    begin
    end

endmodule : dut

// Higher level overriding lower level configuration
// Overriding Example:
// in ovm_test
set_config_object ("*", "data", x);
// in ovm_env
get_config_object ("opt", y);
set_config_object ("*", "data", y);
// in ovm_component
get_config_object ("data", obj); // obj = x


OVM 101.

Test Environment Structure
diagram
// Top level "module" contains class based test environment
//        and structural interface that drives DUT (module)
module top;

import ovm_pkg::*;
import my_pkg::*;

...
dut_if dut_if_inst0 ();
dut dut_inst0 (._if (dut_if_inst0) );

initial
begin
    run_test ("my_test_set");
end

endmodule : top

// ovm classes
// usually classes of test environment that includes fixed test bench
// and variable test sets

`include "ovm_macros.svh"

package my_package;
import ovm_pkg::*;

// Fixed test environment
class my_test_env extends ovm_env;
    `ovm_component_utils (my_test_env)

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

    function void build;
        super.build ();
    endfunction : build

    task run;
        #10 ovm_top.stop_request();
    endtask : run

endclass : my_test_env

class my_test_set extends ovm_test;
    `ovm_component_utils (my_test_set)

    my_test_env my_test_env_handle;

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

    function void build;
        super.build();
        my_test_env_handle = my_test_env::type_id::create 
            ("my_test_env_handle", this);
    endfunction : build

endclass : my_test_set

// interface dut_if(); -> between test components and DUT
interface dut_if ();
...
endinterface : dut_if

// Design under test
module DUT (dut_if _if); 
endmodule : dut


Tuesday, September 27, 2016

Array Initialization.

Java:
// anArray = new int[10];
int[] anArray = { 
    100, 200, 300,
    400, 500, 600, 
    700, 800, 900, 1000
};

anArray[0] = 100; // initialize first element
anArray[1] = 200; // initialize second element
anArray[2] = 300; // and so forth

System.out.println("Element 1 at index 0: " + anArray[0]);
System.out.println("Element 2 at index 1: " + anArray[1]);
System.out.println("Element 3 at index 2: " + anArray[2]);


Python:
myList=[]
for i in range(10):
    myList[i]=1

for i in range(10):
    myList.append(1)

myList=[i*i for i in range(10)]
myArray=[[1,2],[3,4]]

list_of4 = [3, "test", True, 7.4]

s = ["Lee", "Walsh", "Roberson"]
s2 = ["Williams", "Redick", "Ewing", "Dockery"]
s3 = [s, s2] # 2x2 list
s4 = s + s2; # concatenation two lists

list1, list2, list3 = [1,2,3], ['a','b','c'], [7,8,9]
all_lists = sum([list1, list2, list3], [])
# all_lists == [1, 2, 3, 'a', 'b', 'c', 7, 8, 9]

listanimal.append("cat")
listanimal.extend(["dog", "mouse"])

# This is tuple
b = ("Bob", 19, "CS")       # tuple packing
(name, age, studies) = b    # tuple unpacking

# data structure with lists and tuples
students = [
    ("John", ["CompSci", "Physics"]),
    ("Vusi", ["Maths", "CompSci", "Stats"]),
    ("Jess", ["CompSci", "Accounting", "Economics", "Management"]),
    ("Sarah", ["InfSys", "Accounting", "Economics", "CommLaw"]),
    ("Zuki", ["Sociology", "Economics", "Law", "Stats", "Music"])]

julia_more_info = ( ("Julia", "Roberts"), (8, "October", 1967),
                     "Actress", ("Atlanta", "Georgia"),
                     [ ("Duplicity", 2009),
                       ("Notting Hill", 1999),
                       ("Pretty Woman", 1990),
                       ("Erin Brockovich", 2000),
                       ("Eat Pray Love", 2010),
                       ("Mona Lisa Smile", 2003),
                       ("Oceans Twelve", 2004) ])



Perl:
my @other_array = (0,0,0,1,2,2,3,3,3,4);
my @zeroes = (0) x 5; 
my @zeroes = (0) x @other_array; # A zero for each item in @other_array.
                                 # This works because in scalar context
                                 # an array evaluates to its size.
# To get the "length" or "size" of an array, simply use it in a scalar context. 
$count = @array;
# Get the highest index
$highest_index = $#array;


Ruby:
names = Array.new(20)
puts names.size  # This returns 20
puts names.length 

names = Array.new(4, "mac")
puts "#{names}"  # This returns "["mac", "mac", "mac", "mac"]"

nums = Array.new(10) { |e| e = e * 2 }
puts "#{nums}"   # This returns "[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]"

nums = Array.[](1, 2, 3, 4,5)
nums = Array[1, 2, 3, 4,5]

digits = Array(0..9)
num = digits.at(6)


JavaScript:
var cars = ["Saab", "Volvo", "BMW"];
var cars = new Array("Saab", "Volvo", "BMW");
var name = cars[0];
document.getElementById("demo").innerHTML = cars[0];

// This is array
var person = ["John", "Doe", 46];
// This is object
var person = {firstName:"John", lastName:"Doe", age:46};


C++:
#include <iostream>
using namespace std;

int foo [] = {16, 2, 77, 40, 12071};
int another_foo [5] = { 16, 2, 77, 40, 12071 };

int jimmy [3][5];   // is equivalent to
int jimmy [15];     // (3 * 5 = 15) 
 
#define WIDTH 5
#define HEIGHT 3

int jimmy [HEIGHT][WIDTH];
int n,m;
int main ()
{
    for (n=0; n<HEIGHT; n++)
        for (m=0; m<WIDTH; m++) {
            jimmy[n][m]=(n+1)*(m+1);
        }
}


SystemVerilog:

  • Fixed-size (multi-dimension)
  • dynamic (single dimension)
  • queue (single dimension)
  • associative (single dimension)

typedef enum {IDLE, TEST, START} state;
enum bit[2:0] {S0 = 'b001, S1 = 'b010, S2 = 'b100} st;
state cst, nst = IDLE;
$display ("st = %3b, nst = %s", st, nst.name;
// showing on screen: st = 0, nst = IDLE

typedef reg [7:0] octet;
octet b;
// same as reg [7:0] b;
typedef octet [3:0]
quadOctet;
quadOctet qBytes [1:10];
// same as 
// reg [3:0][7:0] qBytes [1:10];
typedef enum { circle, ellipse, freeform } ClosedCurve;
ClosedCurve c;
// same as
// enum { circle, ellipse, freeform } c;
struct {
  int x, y;
} p;
p.x = 1;
p = {1,2};
typedef struct packed {
  int x, y;
} Point;
Point p;

integer numbers[5]; // array of 5 integers, indexed 0-4
int b[2] = '{3,7};
int c[2][3] = '{{3,7,1},{5,1,9}};
byte d[7][2] = '{default:-1};
bit[31:0] a[3][2] = c;
for (int i=0; i<$dimensions(a);i++) begin
   $display ($size(a, i+1));
end

// queues
int j = 1;
int q[$] = {0,1,3,6}; // note, no' as in arrays
int b[$] = {4,5};   // no '
q.insert (2, j);    // {0,1,2,3,6}
q.insert (4, b);    // {0,1,2,3,4,5,6}
q.delete (1);       // {0,2,3,4,5,6}
q.push_front (7);   // {7,0,2,3,4,5,6}
j = q.pop_back();   // {7,0,2,3,4,5}   j = 6
q.push_back(8);     // {7,0,2,3,4,5,8}
$display($size(q)); // 7
q.delete();         // delete all elements
$display($size(q)); // 0

// Associative Arrays
integer aa[*];
integer aa_too[int];
// use aa.delete(), aa.first(), aa.next(), aa.prev(), aa.last()
// to traverse
byte ba[string], t[*], a[*];
int index;
ba["byte0"] = -8;
for (int i=0; i < 10; i++) 
   t[1<<i] = i;
a=t;
$display ("size of t array is: %0d", t.num()); // array size

// Array Methods
// num(), delete(), exists(), first(), last(), next(), prev()

byte ba[string], t[*], a[*];
int index;
ba["byte0"] = -8;
for (int i=0; i mmm 10; i++) begin
   t[1<<i] = i;
end
// t[1]=0, t[2]=1; t[4]=2, t[8]=3,...
a=t;
$display ("size of t array is: %0d", t.num()); // array size

// Array Loop : foreach (array[i]) 
// Array Methods:
// function array[$] array.find() with (item < 3) // returns {value}
// function int[$] array.find_index() with (item < 3) // returns {index}
// function array[$] array.find_first() [with (exp)]
// function int[$] array.find_first_index() [with (exp)]