UVM like tb framework using SV: (from sample project)

Here, we build a testbench framework using all these SV constructs that we learned earlier, i.e class, program, env, interface, etc. This is how UVM framework is developed that we'll learn in other section.


usbpd_tb.sv:

`include testbench.sv //this has the program for all classes
module usbpd_tb();
 wire, reg, ...;
 function/task func1() .. endfunction //functions/tasks
 initial/always @(...) begin .... end //build osc, release porz, checkers for clk
 digtop I_digtop (.in1(tb_in1), out1(tb_out1)); //DUT inst
 i2c_bfm I_i2c_bfm ( ...);
 sram_monitor i_mon (.addr(s_addr), ...);
 cm0_tarmac u_tarmac(.en(1'b1),...); //tarmac inst for M0
 specify $width(...); ....; endspecify //we can define our own clk pulse width check, etc (similar to what's in gate models)
//property checkers included here
 property hready_checker;
  @(posedge clk) disable iff (hresetn) !hready |=> hready_i; //checker disabled if hresetn=0, else hready_i should match !hready on next clk posedge
 endproperty
 ass_prop_chk : assert property (hready_checker) //property asserted here
                      begin $display("OK"); end
               else begin $display("ERR"); end
 cov_prop_chk : cover property (hready_checker) //property covered here

 tb_intf I_tb_if(); //interface defined  below in testbench.sv
endmodule

testbench.sv:

typedef class register_base;
typedef class register_field_base;
typedef class register_block_base;
typedef class ahb_collector;

interface tb_intf(); //i/f defn
 logic data, addr, ...;
 task wrt_addr(...);
endinterface

//start of register_base class => has all reg attributes as name, value, etc.
class register_base;
   string         parent_module;
   string         name;
   enum {READ, WRITE} rw;
   bit [31:0] address;
   bit [31:0] value;             // same as mirrored_value in UVM registers
   bit [31:0] rand_value;        // same as value or desired value in UVM registers
   bit [31:0] rd_mask; //similarly wr_mask, rd_to_clr, wr0_to_clr, wr1_to_clr, wr1_to_set.

  register_block_base parent_reg_blk;
  //covergroups
   covergroup cg_bit_31 @(bit_31_wr_done_ev or bit_31_rd_done_ev); //sampled whenever these events happen
      cp_bit_31 : coverpoint {rw,value[31] } { //coverpoint cp_bit_31 defined for rw and value[31] bits
     wildcard bins tran_r0_w0_r = ({READ,1'b0} => {WRITE,1'b0} => {READ,1'bx}); // bin for transition from rd to wrt to rd
     wildcard bins trans_r1_r   = ({READ,1'b1} => {READ,1'bx});
      }
   endgroup //similar covergroup for other bits  

   register_field_base reg_fld_q[$]; // queue of register fields
   
   function new ( string module_name, string reg_name, bit [31:0] reg_address,
          bit [31:0] rd_mask, bit [31:0] wr_value, bit [31:0] rd_value, register_block_base register_block_base_inst);
      this.parent_module = module_name;
      this.nmame = reg_name;
      this.address = reg_address;
      this.value = rst_value;
      this.rd_mask = rd_mask;
      this.parent_reg_blk = register_block_base_inst;
      this.d_value   = this.value;
 
     register_block_base_inst.add_reg(module_name, this); //func defined in reg block base
   endfunction

   virtual function string get_name(); //string implies return value
      return (name); //returns name and so on for other func
   endfunction

   virtual function void reset(); //to reset fields, return value is nothing, so "void" used
      value      = rst_value;
      foreach (reg_fld_q[i]) void'(reg_fld_q[i].reset());
   endfunction
endclass //end of register_base class

//create a class for each reg
class SPARE_REG_type extends register_base;
   rand register_field #(6) RESERVED;
   rand register_field #(6) STICKY_STS_SET;
   rand register_field #(20) RESERVED1;

   function new ( string module_name, string reg_name, bit [31:0] reg_address, bit [31:0] rst_value,
                  bit [31:0] rd_mask, bit [31:0] wr_value, bit [31:0] rd_value, register_block_base reg_blk_inst);
     super.new(module_name, reg_name, reg_address, rst_value, rd_mask,  wr_value, rd_value, reg_blk_inst);
   endfunction
endclass

class AUX_REG ... endclass // and so on for all regs
//end of class for all regs in design

//start of register_field_base
class register_field_base;
   string          name;
   bit      [7:0]      start_bit;
   bit      [7:0]      length;
   register_base parent_reg;

   function new ();
   endfunction // note: nothing defined in new func, similarly other func defined with nothing in them, as they will be defined in register_field class
endclass

class register_field #(int FIELD_LENGTH = 32) extends register_field_base;
   rand bit [FIELD_LENGTH-1:0]      rand_value; // desired_value   // parameterized
   bit      [FIELD_LENGTH-1:0]      value;      // mirrrored_value // parameterized

   covergroup    reg_field_cg  @(parent_reg.wr_done_ev or parent_reg.rd_done_ev);
      option.name = name;
      cp_reg_field_value: coverpoint (value) { // coverpoint for all values of that reg field
     bins field_val[] = {[0: max_value]}; //array of bins created from field_val_0 to field_val[max_value]. So, if 0 sampled, then bin fiel_val_0 is covered and so on. advantage of array of bins is that we can see which values are missing from coverage
      }
   endgroup // reg_field_cg
 
   function new ( string fld_name, int start_bit, int fld_len, register_base parent_register);
      this.name       = fld_name; //name, start_bit, length properties come from reg field base
      this.start_bit  = start_bit;
      this.length     = fld_len;
      this.parent_reg = parent_register;
      parent_register.add_reg_field(this);
   endfunction // new

   virtual       function void reset();
      // get the reset value from the parent register and copy to the rest of values
      value      = ((parent_reg.rst_value >> start_bit) & max_value);
      prev_value = value;
   endfunction // reset
endclass

//class reg block base => largest class in terms of code => all checkers implemented here as tasks
class register_block_base;
 register_base reg_q[string][$]; //contains queue of reg base
 mailbox reg_tr_mbx;
 SPARE_REG_type SPARE_REG; //and so on for all other regs
 
   covergroup custom_SPI_cg; //specify covergroups for regs and bits which we want sampled when C pgm accesses those
    cp_mon: coverpoint SPARE_REG.MODE.value;
    ...
   endgroup

   task ... forever ... endtask
   task automatic cfg_assert(); //all IO pin checks are in this task, similarly frs_assert, gpio_assert etc
     config_assert: assert(SPARE_REG.SPARE_OUT.value === `TB.pin[12]) else $display("ASSERTION ERROR"); //similarly for all other IO pins
   endtask
 
   function void add_reg (string module_name, register_base reg_inst);    
      foreach (reg_q[module_name][i]) // check existing registers to make sure there is no duplicate address
    if (reg_q[module_name][i].get_address() == reg_inst.get_address()) //do not add reg
    begin
         $display("ERROR: module_name.substr %s", module_name.substr(0,2));
             $finish;
        end  
      reg_q[module_name].push_back(reg_inst); // push reg at end of queue,
   endfunction // add_reg
 
   function cg_sample ( ...) //called from detect_rand_request (whenever C pgm writes to loc indicating it wants sampling)
     if (testname.substr(0, 2) == "spi") custom_SPI_cg.sample();
     else if (...)                     custom_UART0_cg.sample();

   function void build();      
      create_reg_space(); // instantiate register model and covergroups etc (defined in function below)
      CONFIG_SPARE_WAKEUP_REG.rd_mask = 32'hFFF81FFF;      
   endfunction // build

   task start (); //impl as task since they have always, forever etc
      apply_hw_lock_mask(); //func defined in this class
      apply_trim_lock_mask(); //func defined in this class
      fork
     register_adapter(); forever task in reg_block_base. At every FCLK edge, it samples AHB tran, and calls gpio_sample, config_sample, etc, depending on addr.
     detect_rand_request(); //forever task (@ posedge FCLK, HWRITE=1 and HADDR=RAND_REQ_ADDR and then look at HWDATA[15:0]) to detect random req wrt to different regs (wrt rand val to reg model and copy that to sram)
     detect_incoming_rand_xfer(); //to detect tb_if.req to wrt incoming addr/data to sram + detect tb_if.done to wrt end signature once done
     test_end_detect(); //this is a forever task to detect "EXIT" inst being written
         output_checker(); //it's a fork forever task that calls bunch of other assert tasks as "cfg_assert", on event @config_debug_sampled, etc. these events are triggered in func "config_sample" (called in register_adapter task) when addr match for wrt happens on AHB bus.
      join_none //above forked process keep running for ever
  endtask // start
 
   function void create_reg_space();
      SPARE_REG = new("CONFIG", "SPARE_REG", 32'h01F0, 32'h00000000, 32'hffffffff, 32'hffffffff, 32'h00000000, 32'h00000000, 32'h00000000, 32'h00000000, 32'h00000000, 32'h00000000, 32'h00000000, this); // 0x01F0 - SPARE_WAKEUP_SET_REG
        SPARE_REG.RESERVED = new("RESERVED", 26, 6, SPARE_REG);
        SPARE_REG.STICKY_STS_SET = new("STICKY_STS_SET", 20, 6, SPARE_REG);
        SPARE_REG.RESERVED1 = new("RESERVED1", 0, 20, SPARE_REG);

     AUX_REG = new("...); //similarly for all other regs and corresponding bits
   endfunction

   task register_adapter(); //samples transaction on AHB, and depending on reg addr, puts deglitch values, etc on tb_pin_intf signals
    forever begin
      @(posedge `CPUTOP.FCLK);
        if (reg_tr_mbx.try_get(curr_tran) == 1'b0) $display ("NO AHB transaction"); //get AHB msg that was put in collector below
        else begin (if curr_tran.addr == 16'h0F30) reg_h = config_sample(curr_tran.addr[15:2], curr_tran.wr_data, curr_tran.rd_data, 0);
    else       (if curr_tran.addr == 16'h0A50) reg_h = gpio_sample(...) and so on
   endtask

endclass //end of reg block base

//AHB collector
class ahb_collector; //this collects 1 AHB transaction with addr, rddata, wrdata, etc
  string name;
  mailbox tr_mbx;
  ahb_transaction ahb_tran; //a class defined with addr, wrdata, etc
 
  function new (string name, mailbox tr_mbx);
    this.name = name;
    this.tr_mbx = tr_mbx;
  endfunction // new
      
  task body();    
     forever begin        
        @(negedge `CPUTOP.FCLK);
          ahb_tran = new(`CPUTOP.HWDATA, `CPUTOP.HRDATA, ... );
        if (tr_mbx.try_put(ahb_tran) == 1'b0) $display(ERROR"); //ahb_tran class object pushed into mailbox
         end
  endtask
endclass
               
       
//class env
class env;
   register_block_base reg_blk_inst;
   mailbox tr_mbx; //mailbox to store 1 AHB transaction from M0
   ahb_collector  ahb_collector_0;
 
   function new();
      tr_mbx       = new(1); // each module mailbox is one deep
      ahb_collector_0     = new("AHB Collector for M0p", tr_mbx);  
      reg_blk_inst = new(tr_mbx);
   endfunction // new
    
   virtual task build();
      reg_blk_inst.build(); //creates reg class for all regs and their fields by calling "create_reg_space" func
   endtask // build
   
   virtual task start();
      fork
     reg_blk_inst.start(); //task start, which itself is bunch of forked proc, called from reg block_base. all checkers, etc here
     ahb_collector_0.body(); //collects all AHB transactions
     misc_collector_0.body();
     dbg_fifo_sb_0.body();    
      join_none; //above forked proc run forever
   endtask // start
endclass // env

//testbench starts from here. this is another top level module besides usbpd_tb. It's not called from anywhere.
program testbench();
 env env_inst;

 initial begin
  env_inst = new();
  env_inst.build();
  env_inst.start();
  wait(`TB.tb_finish_test == 1); // wait for test bench to finish test (happens on receiving "EXIT" from main pgm
 end

 property .... endproperty
endprogram


 

SDC Synthesis Constraints:

SDC was developed mainly for Synthesis design constarints, but we saw above that a lot of other cmds got added over time. Below we see the design constraints that are standard in all synthesis tools now.
write_sdc is an sdc cmd that writes all constraints that the synthsis tool sees in the design (provided by the user in any format) in the sdc format. This file in sdc format can then be used as i/p to any other tool, that relies on sdc cmds. This is very useful when porting constraints. These are few SDC cmds that are provided to any design for synthesis:

  1. Environment Constraints: external to design: op cond (PVT), WLM, load (both i/p and o/p), drive (only on i/p) and fanout(only on o/p).
  2. Clocks (primary and generated clocks): clk pins, freq, uncertainty and drive.
  3. Constraints: design and opt constraints. Mainly input and output delays.
  4. False paths and multicycle paths: timing constraints
  5. Case analysis (for functional and scan): global constraints. sets appr pins and nets to 0/1 to enable func or scan. needed only when scan present.
  6. Misc: set_don_touch, set_dont_use: global constraints. not needed for PT.

1. Environment Constraints: op cond (PVT), WLM, load (both i/p and o/p), drive (only on i/p) and fanout(only on o/p).

  1. op cond: set operating condition of design
    1. set_operating_conditions =>
  2. wire load models (WLM): WLM are set based on how we want to model net delays.
    1. set_wire_load_model: used only when design is not in physical (DC-topo or RC Physical) mode. WLM estimates effect of wire length and Fanout on res, cap and area of net. No. of fanout determines net length based on fanout to length table. Which Fanout to length table to use is determined based on area of cell which drives the net. DC uses the cap/res to calc wire delay.
    2. NOTE: In .lib file, we specify wire load model and wire load selection for different area of cell. See in liberty.txt for details.
      1. set auto_wire_load_selection true
      2. set_wire_load_model "6K_3LM" => sets wire load model to something other than the default one set in .lib file
      3. set_wire_load_mode enlosed:  Setting enclosed wire load mode. We may set different wire load models for different hier cells. By setting this parameter, we help tool decide which wire load mode to pick for a net in a specific hier. allowed values are: top(default), enclosed, segmented. By setting to enclosed, Wire load model of the module that entirely encompasses the wire is used for each wire. This more realistic than the more conservation "top" mode (in top mode, WLM for top design is used for all nets). segmented mode is most accurate as it uses WLM for each segment of wire, depending on which design it lies in.
    3. set_wire_load_min_block_size
    4. set_wire_load_selection_group
  3. load (on both i/p and o/p): set_load cmd sets load on i/p or o/p ports and nets in design. -min/max can be used for hold/setup. we need to set load on i/p ports when the driving_cell on i/p port is far away or has extra fanout, so wire/pin cap added on i/p port using this cmd. Usually we only specify load for o/p ports, as i/p ports don't branch out anywhere else, so no extra load.
    1. NOTE: set_load also applies on internal nets, and so will override internally calculated net load value. When using DC-TOPO, for each net, cap and resistance are estimated based on estimated physical layout. so, in DC-TOPO, when we write sdc using write_sdc, we get set_load and set_resistance for each internal net in the sdc file. Be careful, not to use this sdc file in PnR tools as EDI or timing tools as PT. In EDI, use report_ports to view cap on ports. For EDI, Cap is in units from tech lib. For DC, cap is in units of set_units, if specified, else from tech lib.
    2. ex: set_load -pin_load 4.1912 [get_ports n_puc_sync] => -pin_load implies that load value for the port should be treated as extrnal pin cap and -wire_load implies external wire cap, or tot cap (pin+wire) when nothing specified.
    3. ex: set_load 4.1912 [all_outputs] => sets load of 4.2 units (total cap=pin+wire) on all o/p ports.
      1. Cadence Synthesis RC cmd: set_attribute external_pin_cap 0.05 [all_outputs] => RC cmd for setting cap on all o/p ports. set_load is preferred cmd as it's sdc cmd.
  4. drive on i/p: 2 cmds used here: set_driving_cell and set_drive/set_input_transition
    1. ex: set_driving_cell -lib_cell <cell_name> [ports] => Sets  attributes  on input or inout ports of the current design, specifying that a library cell or output pin of a  library  cell drives specified ports. last entry is the name of i/p or inout ports on which driving cells are to be placed. These driving cells are not actually put in the design, they are used to model what is driving the pins from external world.
    2. set_driving_cell -lib_cell IV110 [get_ports n_puc] => puts IV110 to drive port n_puc
      1. Cadence Synthesis RC equiv => set_attr external_driver [find /lib*/ -libcell IV110] [all_inputs]
    3. set_drive => to set drive resitance (res unit in .libfile, usually Kohm) directly on port. For clocks, set drive res to 0 (infinite drive), so that DC/RC doesn't put buffers on it.
      1. syntax: set_drive <port_list> <resistance> => sets resistance of external driver in units of .lib for that port
      2. ex: set_drive 0 clk1 => sets clk1 driver res to be 0 Kohms, i.e ideal driver (infinite drive)
        1. RC equiv => set_attr external_resistance 0 [clk1]
    4. set_input_transition => Alt to set_drive. Sets  the  max_transition_rise, max_transition_fall, min_transition_rise, or min_transition_fall attributes  to  the  specified input and inout ports. -min/max state whether it's to be applied for hold/setup. "0" implies infinite transition
  5. fanout on o/p: set_fanout_load cmd is used to model expected FO load on o/p port. When synthesizing, DC tries to keep FO on o/p port (by adding FO specified on o/p  port plus FO presented internally by cells connected to o/p port) less than max_FO specified for the design.
    1. ex: set_fanout_load 4 {out1} => puts FO of 4 (unitless number) on out1.
    2. set_port_fanout_number
  6. MISC: Many misc cmds which are not needed in regular synthsis flow.
    1. set_resistance => sets the back annotated resistance value, which enables the back-annotation of resistance value for nets in net_list. The  specified  value overrides the internally-estimated net resistance value, so use it carefully. To use diff value for min delay analysis (hold), and max delay analysis (setup), use -min/-max option
      1. ex: set_resistance -min 300 U1/U2/NET3 => sets a resistance of 300 units to be used for hold analysis on net U1/U2/NET3


2. design constraints:

  1. Design rule constraints: set_min_capacitance, set_max_transition, set_max_fanout, set_max_capacitance, set_cell_degradation (usually in .lib). precedence of design rule const in DC: min_cap (highest priority), max_tran, max_FO, max_cap, cell_degrad (lowest priority). precednece can be changed by using set_cost_priority in DC.
    1. set_min_capacitance => sets min cap attr on i/p ports. This ensures that load driven by i/p port is not below a certain value. not set in std cell .lib file. min cap is usually the lowest cap value with which a cell has been characterized to operate.
    2. set_max_transition 4.0 [find design *] => sets  the  maximum  transition  time, on specified clocks, ports, or designs. set by default for all i/p pin of all the cells in .lib (using max_transition : 4.10;). We can override the one in lib by specifying it explicitly for i/p, o/p ports or designs.
      1. Ex: set_max_transition 5 [get_clocks Clk] => sets value of 5 on all pins belonging to "Clk" clock group. Needed in cases where there are multiple clocks running at diff freq, so transition requirement for each group might be diff.
    3. set_max_fanout 20 => default_max_fanout defines as 20 in top of .lib file. Then for o/p pin of some cells (as tie-hi/tie-lo cell TO020), we specify max_fanout to 50 (max_fanout : 50;) in .lib file. Can be specified on i/p ports or designs.
    4. set_max_capacitance => Sets  the  max_capacitance attribute to a specified value on the specified clocks, ports and designs.
      1. ex: set_max_capacitance 2.0 [current_design] => sets max cap of 2 units on all design. Not needed as it's set by default for o/p pin of all the cells in .lib (using max_capacitance : 0.21;). allows to control cap directly, while set_max_transition & set_max_fanout control cap indirectly.
    5. set_cell_degradation => some .lib contain cell degradation table that list the maximum capacitance that can be driven by a cell as a function of the transition times at the inputs of the cell.
  2. Optimization constraints: defines goals for area, power and timing (clocks, clock skews, i/p delay, o/p delay). DC attempts to meet these goals, w/o violating design rule constraints.
    1. area const:
      1. ex: set_max_area 0 => tries to reduce area to min. Not supported by Cadence
    2. power const: max_dynamic_power and max_leakage_power (requires power compiler license). Not needed if no pwr const for design.
    3. timing const:
      1. set_input_delay: sets external i/p delay on i/p ports. The delay specified is the delay from the rising edge of specified clk. Default is rising edge of clk (may be changed via -clock_fall option). Assumption is that the specified clk is firing the i/p port and is taking the specified amount of time outside the block, before it gets to the i/p port.
        • set_input_delay 0.2 -clock clk1 [remove_from_collection [all_inputs] [get_ports {all_clocks}]] => sets 0.2 unit delay on all i/p pins (except clk ports) relative to clk1 (clk1 is imaginary clk that fires the imaginary flop that is firing the i/p pin. It's NOT the i/p clk port of DUT. Almost all the time, clk1 is chosen to be same as i/p clk port). By default, i/p delay is 0 if not specified. -max specifies that delay refers to longest path (i.e for setup calc), while -min is for shortest path (i.e for hold calc). If not specified, same delay is used for both setup/hold and rise/fall. Usually for spi/i2c etc signals, we specify diff min/max value as setup/hold numbers are different (we try to provide large setup delay and almost 0 hold delay). We can also specify rising/falling edge of clk.
          • ex: setup: set_input_delay -max 40 -clock spi_clk spi_cs_n => specifies a setup time of 10ns (assuming clk=50ns period, then 50-40=10ns of time available for internal ckt) for port "spi_cs_n". The port data is fired on rising edge of "spi_clk". Depending on how it's captured inside the chip, it may be full cycle orhaf cycle path.
          • ex: hold:  set_input_delay -min 0 -clock spi_clk spi_cs_n => specifies 0ns holdtime. "-min" is not needed in DC, as we don't run any hold timing optimization (as there are no clk tree buffers, clk is treated ideal). But it's needed to be used in PnR for the tool to work on this path to fix hold.
      2. set_output_delay: sets external o/p delay on o/p ports. The delay specified is the delay from the output port to the rising edge of specified clk. Default is rising edge of clk (may be changed via -clock_fall option). Assumption is that the specified clk is capturing the o/p port and is taking the specified amount of time outside the block, before it gets captured.
        • ex: set_output_delay -clock osc_clk -clock_fall 10  [get_ports {dout[65]}] => specifies o/p delay of 10ns wrt falling edge of osc_clk for port "dout[65]". By default, delay is wrt rising edge of clk.
        • ex: set the input and output delays for the bidirectional port INOUT1. The input signal arrives at INOUT1 2.5 units after the falling edge of CLK1. The output signal is required at INOUT1 at 1.4 units before the rising edge of CLK2.
          • set_input_delay 2.5 -clock CLK1 -clock_fall { INOUT1 }
          • set_output_delay 1.4 -clock CLK2 { INOUT1 }
      3. Optional ideal attr => not needed for clocks in synthesis tools (such as DC). clk nets are ideal nets by default.
        1. set_ideal_network {clk1 clk2} (added in sdc 1.7) => marks ports/pins (clk1, clk2) as src of ideal network. Ideal networks are an extension of ideal nets that incorporate automatic propagation  of  the  ideal  attribute. All nets, cells, and pins on the transitive fanout of these objects are treated as ideal. Propagation  traverses through combinational cells but stops at sequential cells. "-no_propagate" option prevents ideal propagation thru logic gates. In  addition  to disabling timing updates and timing optimizations, all cells and nets in the ideal network have the dont_touch attribute  set. The latency and transition times of an ideal network are 0 by  default, but   you   can  override  them  by  using  the  set_ideal_latency  and set_ideal_transition commands.
        2. set_ideal_latency 2 clk1 (added in sdc 1.7) => Specifies latency of 2 units for ideal network (clk1). By default, "0" ideal latency ias assumed for ideal networks.
        3. set_ideal_transition (added in sdc 1.7) =>
        4. set_dont_touch_network [get_clocks *] => dont_touch attributes is placed on all cells/nets in the transitive  fanout  of  dont_touch_network objects (clk, pins or ports). It's intended primarily  for clock circuitry. Placing a dont_touch_network on a clock object prevents the compile command from  modifying  the  clock  buffer network.

 
clock related:
-------------
create_clock

create_generated_clock

set_clock_gating_check

set_clock_latency

set_clock_transition

set_clock_uncertainty

set_propagated_clock

clock_group, path group cmds

timing exceptions:
-----------
set_false_path:

set_multicycle_path:

set_max_delay/set_min_delay

set_disable_timing
set_max_time_borrow

set_data_check

set_timing_derate
                           
3. global constraints:

These are extra constraints that we want the tool to adhere to.

  1. set_dont_use => It says not to use certain lib cells in design.
    1. syntax: set_dont_use <libcell> <true/false> => sets dont_use attr on that libcell to true/false. default=true. true/false can also come before libcell, i.e: set_dont_use  <true/false> <libcell>. NOTE: set_dont_use isn't supported in PT.
      1. set_dont_use [get_lib_cells CGP*] FALSE  => sets clk gating attr dont_use to false => use CGP cells. We can use "list" to get all cells in a particular library "set_dont_use [list PML30_W_150_1.65_CTS.db/CGP*] FALSE", but this won't work in RC, as list is not sdc cmd.
        1. RC equiv => set_attr avoid 0 [find /lib* -libcell CGP*]  => 0/false means use it.  1/true means dont use. NOTE: PML30*.db lib exist in /libraries/MSL* virtual dir structure in RC, so, we have to use find in /libraries/. We could use dc::get_lib_cells also in RC. ex:
          1. set_attr avoid 0 [dc::get_lib_cells PML30*/CGP*] => finds all CGP* cells in any subdir with PML30* name in top virtual dir.
          2. set_attr avoid 0 [dc::get_lib_cells CGP*] => finds all CGP* cells in all dir/subdir in virtual dir /libraries/MSL270_W_125_2.5_CTS.db/libcells/CGP40, etc.
  2. set_dont_touch => This specifies not to touch this object. This may be needed when we have an instance in RTL that is already speciifed as a std cell from lib, and we don't want synthesis tool to mess with it.
    1. syntax: set_dont_touch {<design> | <subdesign> | <instance> | <net> | <libcell>} => keeps that object.
      1. ex: set_dont_touch Imtr_a/hs_buf => keeps hs_buf in design as it is. However, nets connected to this buf can be optimized away. To keep the nets untouched too, use this:
      2. ex: set_dont_touch [get_nets -of_objects [get_cells {Imtr_a/hs_buf}]] => all nets connected to hs_buf set to dont_touch. this needed to prevent nets of that cell from getting removed. Otherwise the cell may be there, but it's i/p, o/p nets may be optimized away.
        1. RC equiv => set_attr preserve 1 Imtr_a/hs_buf => .  1/true means dont touch. 0/false means the tool is free to modify it (which is the default case)
  3. set_case_analysis:
  4. set_logic_dc,set_logic_one, set_logic_zero

 

 

Motors:

Motors is a very important topic in any science material, as most of the moving things you see around work on motors. Motors are very simple to understand. It amazing to think, someone initially even thought of a device that could move for ever by using electricity.

Here's a very nice video on DC motors: https://www.youtube.com/watch?v=CWulQ1ZSE3c

Motors use the basic principle of magnets and their attraction/repulsion to keep them moving for over. As shown in the video above, if magnet's polarity could be reversed every cycle, then the magnet would keep rotating for ever.

Motors are of many different kinds. We will divie them in 2 broad categories:

  1. DC motors: These motors work on DC voltage.
  2. AC motors: These motors need an AC current to run.

Simplest Electric Train:

This is based on Electromagnetic theory on which motors work. It's pretty cool to watch this.

Link => https://www.youtube.com/watch?v=J9b0J29OzAU

Just amazing to even think of something like this. Let's go into the theory of why it works. FIXME

 

 

Cadence Commands: Legacy Vs Stylus CUI mode

In the past, Cadence had different cmds for their synthesis tools, timing tools and PnR tools. This caused lots of confusion and inefficiency. So, they moved to Stylus CUI (common user interface) around 2015, which tries to use common cmds across all tools. Now, all tools for Synthesis (Genus), PnR (Innovus) and Timing (Tempus) use same cmds which make it easier to port scripts across tools, as well get consistent behaviour across tools for same cmds. NOTE that cmds in Cadence tools are different than cmds in Synopsys tools, even though the name of the cmd might be the same. The arguments of these cmds may be different as well as their behaviour.

FlowKit:

We'll look at the common cmds here, and then look at speciifc cmds in the respective tool section. Before that, let's look at the "FlowKit" that Cadence provides that auto generates scripts for all their flows, which make it easier to get started. We don't have to write our own scripts from scratch, and they have configs, and other hooks to modify scripts as needed.

From within any of the Cadence tool. run this "FlowKit" cmd to auto generate all scripts.

genus_shell:/> write_flow_template => writes the scripts for tools as genus, innovus, Tempus, etc. If you specify dir as scripts, then following are the files generated (llok on Cadence site for all options):

  • Master File: scripts/run_flow.tcl is the master file generated,
  • Step Files: step files are in in scripts/flow/common_steps.tcl, genus_steps.tcl, innovus_steps.tcl, tempus_steps.tcl
  • Template/Config files are in scripts/flow_config.template, design_config.template, genus_config.template, innovus_config.template, tempus_config.template, etc.

Invoking tools:

New tools can be invoked in either legacy mode or in newer CUI mode (as of 2015). Newer CUI mode is the default. However in the new mode, legacy scripts written for older designs won't work. So, a "legacy_ui" switch was added when starting the tool, that would bring up the tool in "legacy mode'. On the shell, it will show "legacy_*>" to indicate that it is invoked in legacy mode. i.e when bringing up Genus, for CUI mode, it will show "genus :/>", while in legacy mode, it will show "legacy_genus :/>". Similarly fort other tools. To test UI mode type, type cmd "is_common_ui_mode" which should shows 0 if in legacy mode and 1 if in CUI mode. Even if we bring the tool in one mode, we can change it to other mode permanently by changing the attribute "common_ui" to true (to change from legacy to CUI) and to false (to change from CUI to legacy). See below steps on how to do it:

 

Started In Legacy mode: Type" genus -legacy_ui" on cmdline. It brings up the tool with "legacy_genus :/>"

legacy_genus :/> is_common_ui_mode => shows "0" implying it's in legacy mode now.

legacy_genus :/> set_attribute common_ui true / => sets mode to CUI

genus@root:> is_common_ui_mode => shows "1" implying it's in CUI mode now. Also, the shell changes from legacy_genus to genus indicating it's in CUI mode.

 

Started In CUI mode: Type" genus" on cmdline. It brings up the tool with "genus@root:>"

genus@root:> is_common_ui_mode => shows "1" implying it's in CUI mode now.

genus@root:> set_db common_ui false / => sets mode to Legacy. NOTE: cmd "set_attribute" is no longer valid as it's not supported in CUI, so use "set_db" instead

legacy_genus :/> is_common_ui_mode => shows "0" implying it's in Legacy mode now. Also, the shell changes from genus to legacy_genus indicating it's in Legacy mode.

 

Gui mode:

Type gui_show on shell to bring up GUI window from within the tool to see the design in graphics form.

Help / Man:

type "help cmd_name" or "man cmd_name" and it will show the details of the cmd. Also, partial cmd name as "help *lib*" will show all cmds with lib in the name. Typing first few letters of cmd followed by a tab shows all possible cmds starting with those letters.

ex: help report_timing => shows man page for report_timing.

Legacy mode:

We saw above how to bring up any tool in legacy mode by using switch "-legacy_ui". Few highlights of CUI mode:

Virtual dir structure: Most confusing feature in Legacy mode is the existence of a virtual dir. This Virtual dir is used by the tool to store various design data. This dir structure is same as in Linux, where top level dir is "/". Inside this, we have subdir as "designs", "object_types", "libraries", etc. These are called containers, and they can be present at any level. All these containers which are part of virtual dir/subdir contain objects and their attributes. The objects belong to object types such as designs, instances, clocks, ports, etc. Attributes are properties of these objects that affect synthesis and opt of these objects.
Path format: To see path of flops under hier-inst, this is what is reported => /designs/m1/instances_hier/m2/instances_seq/my_flop (It shows the full dir path with containers, not easy to know where what is stored)
Most linux cmds work in this virtual dir. Instead of working on Linux dir, they work on Cadence virtual design dir. Let's look at some of these cmds:
  • ls: Just like unix cmd, it lists dir contents. ex: ls / => shows subdir for root dir as shown below. This is the virtual dir that Legacy mode has. It keeps all design, lib, tech, etc info inside it.
    • designs => contains design contents. Here you'll see subdir for top level design (as I_top), and within that dir for as nets, ports_in, ports_out, power, timing, instances_hier, subdesigns etc. As an example, if you  do "ls /designs/I_top/ports_in/", it will show all i/p ports of the top level design. Similarly "ls /designs/I_top/subdesigns/" will show all lower level modules in I_top which is the top level design.
    • libraries =>
    • hdl_libraries      
    • object_types => This has all object types (i.e pin, net, etc) and their attributes under /object_types/<obj_type>/attributes/<attr>, i.e /object_types/pin/attributes/max_capacitance
    • tech        
    • commands          
    • flows         
    • messages    
  • find: Just like unix cmd, it finds the required object of given type and pattern. This is THE most IMPORTANT CMD to find anything in the database relating to design, lib, etc. Since all related stuff is in their respective subdir, just doing a vanilla find in any of these dir works.
    • syntax: find <virtual dir to start searching from> -<object_type> <pattern> => For pattern type, default is glob. regexp is also available
      • ex: find /libraries -libcell DFF2* => Here it finds all libcell object type which match the pattern "DFF2*", starting from dir /libraries in the virtual dir.
  • filter: filter is used to narrow the results.
    • syntax: filter <attribute on the object> <value of the attribute> <list of objects>
      • ex: filter avoid false [vfind /libraries -libcell DFF2*] => attribute name is "avoid" with a value "false" (i.e this returns a list of cells DFF2* that are not avoided)
  • rm: remove or delete design objects.
    • ex: rm /designs/* => removes everything in designs
  • history: history works as native "linux" history cmd, and shows all cmds run before this in the current shell. The reason history cmd doesn't have lhistory is because history cmd is not needed in virtual dir, and so it's usage is retained as native linux cmd.

 All linux cmds have been remapped to "l" prefix followed by the linux cmd.

  • lls: This is the real "linux ls" cmd that lists all files in linux dir. ex: lls dir1/ => list all files/subdir inside <dir1>
  • lpwd: shows current linux dir
  • lfind: Real linux "find" cmd. Finds given file in said dir

We always are in "/" virtual dir when we start the tool, so the shell shows ": />" in legacy mode to indicate it's in virtual dir "/". If we cd into some other virtual dir, it will show that dir at prompt. i.e legacy_genus:/designs/m1/instances_hier/m2>

 

Stylus CUI Mode:

We saw above that by default any tool comes up in CUI mode. Few highlights of CUI mode:

Virtual dir structure:  Virtual dir structure from legacy is changed, and a different dir structure corresponding to design hier itself is maintained. All intermediate containers have been dropped. (instances_hier etc.). A 'object type' string prefixes all object pathnames with a ':' (colon) separating the type-prefix from the object pathname. Path name= <obj type>:<name>. This is known as Dual Port Object (DPO) notation

Path format: To see path of flops under hier-inst, this is what is reported => inst:m1/m2/my_flop (It shows the design hier path with no containers, intuitive as that is how RTL hier is)

So, many of previous legacy "linux alike" cmds are no longer valid. Native linux cmds are supported for Linux filesystem. So, "ls" works as "Linux ls" cmd. If you want to list contents of virtual dir, you have to use "vls" which is "virtual ls". All virtual linux cmds here work in Legacy mode too (i.e ls and vls both work same way in legacy mode).

  • vcd => cd into virtual dir, similar to cd of legacy ui. Similarly "vls" list contents of virtual dir, similar to ls of legacy ui, vpwd, etc.
  • cd => linux "cd" cmd. works on linux file system. Similarly for ls, pwd, etc.
  • find => this is linux "find" cmd. Equiv "find" for objects in CUI mode is "get_db".
  • mv/rm => These are linux cmds. Equiv cmds for objects in CUI mode are "rename_obj", "delete_obj", etc.
    • delete_obj [get_db designs] => deletes everything in designs.

CUI mode shows prompt differently than in Legacy mode. It shows @root instead of "/". If we cd into some other virtual dir, it shows design instance hier., i.e We always are in "/" virtual dir when we start the tool, so the shell shows ": />" in legacy mode to indicate it's in virtual dir "/". If we cd into some other virtual dir, it will show that dir at prompt. i.e genus@hinst:m1/m2>

Differences between Legacy and CUI mode commands:

Objects and Attributes:

Many of the cmds that we see in Synopsys PT for accessing objects and their attr are same in Legacy mode, but slightly different in CUI mode.

Objects are same as what we discussed under PT section. Valid objects are design, port , cell, pin, net , lib, lib_cell, lib_pin, and clock. Each of these objects may have multiple attribute. However attributes defined on objects differ in Cadence tools.

As an ex, each gate may have 100's of attributes as gate_name, size, pins, delay_arcs, lib_name, etc. These objects are further put into several class as ports, cells, nets, pins, clocks, etc. Most commands operate on these objects.

1. Use db cmds to access tool objects: get_db, set_db

2.

 

Genus is the synthesis tool that supports CUI. It's supposed to replace Cadence RC (RTL Compiler), which is the older synthesis tool. Most of the cmds and flow are same as RC. However there are some differences in cmds, etc. So, genus provides 2 modes: a legacy mode, which allows older scripts written for RC to still work in Genus. Then there is newer native mode where new cmds for CUI work in Genus, and legacy cmds from RC may not work anymore. We should move to newer Genus cmds.

Maths Olympiad and Competitions:

I've a separate section for Maths Competitions, as it deserves it's own section. There are many Maths competition organized all over the world. We'll look at few popular Maths competitions in the USA.

Mathworks Maths Contest (MMC):

This is an annual exam organized by Math Works, which is part of "Texas State College of Engineering and Science". This has nothing to do with "MathWorks" Company which developed MatLab. it is only for kids from 6th to 8th grade, so questions are relatively easy.  There are 15 questions (no multiple choice) to be completed in 2 hrs. Test is administered in November. Top selected students participate in "Primary Math World Competition (PMWC)' in HongKong, with all expenses paid. Many students get prestigious "recognition certificates".

MMC: https://www.txst.edu/mathworks/MMC.html

Question papers from previous years => https://www.txst.edu/mathworks/mmc-information/mmc-sample-tests.html

Link not working anymore => https://www.txst.edu/mathworks/mmc/previous-mmc-tests.html

 


 

Mathcounts Competition Series:

This is an annual exam series organized by Mathcounts, which is a non profit org. This exam is also only for middle schoolers. It's based on speed, and so questions are even easier than Mathworks exam. It's held in style similar to spelling bee. It has 4 levels, from school level to National level. Emphasis is more on speed, rather than complexity of problems. Many students get prestigious "recognition certificates".

Mathcounts.org: https://www.mathcounts.org/

Question papers from previous years => https://www.mathcounts.org/resources/past-competitions

 


 

Maths Olympiad

Maths Olympiad is one of the world's most prestigious Maths competition. The best thing about  Maths Olympiad is that it requires no prior knowledge except for basic Maths abilities (i.e basic algebra, geometry, etc). This makes it suitable for anyone to take this test irrespective of age (ideally >14 years) or grade (ideally > 8th grade).

IMO (International Maths Olympaid) is organized by an International organization every year. Each country gets to send 6 top maths students to participate in this. Anyone who is still in High School (i.e 12th grade or under0, but not in College yet, is qualified to participate. If you are selected to represent your country at the International Maths olympaid, you are among the top 0.001% of the population when it comes to Maths. That by itself is good enough to land you at worlds' top university, irrespective of your other achievements. When I say top universities, I mean MIT, Stanford and Berkeley !!!

Each country has it's own National Maths Olympiad competition, which they use to select top 500 or so candidates from all of the country. Then a second level exam is held to filter out top 30 candidates out of this, who go through a rigorous Maths Training for a couple of months. Finally 6 students are selected out of these top 30 to represent their country.

 

Indian National Maths Olympiad (INMO):

This is the Maths olympiad held every year in India conducted under the aegis of National Board of Higher Mathematics (NBHM). First a Regional Maths olympiad (RMO) is held at state level in which 30 top students from each state are invited to appear for the INMO. Top 30 students from INMO go thru a camp training and finally 6 are selected for IMO.

More details on wiki => https://en.wikipedia.org/wiki/Indian_National_Mathematical_Olympiad

Questions from prior years (1986 - 2012) in INMO => http://madanpur.in/inmo/inmo.htm

 

USA Maths Olympiad (USAMO):

This is the Maths olympiad held every year in USA conducted under the aegis of MAA (Mathematical Association of America). Any American or Candian citizen or resident is eligible to participate in these exams. It has been separated out in 2 parts for students in different levels. Students who are in college (i.e already graduated from high school) are not eligible to participate.

  • USAJMO (USA Junior MO) => This is for kids who are in 10th grade or lower or under 17.5 years of age.
  • USAMO (USA MO) => This is for kids in who are in 12th grade or lower or under 19.5 years of age.

More details on wiki => https://en.wikipedia.org/wiki/United_States_of_America_Mathematical_Olympiad

More details on USA MO is on MAA site: https://www.maa.org/math-competitions

Unfortunately none of the previous year olympiad papers are provided on MAA website for free. Instead they charge you $20 for a USB. Fortunately, there are other resources available which provide these papers for free.

There are 3 tier of Maths exams that students have to take depending on their grade level. Students who qualify in 1st tier (AMC 10/12), move to the 2nd tier exam (AIME), and finally to the 3rd tier (USAMO/USAJMO). There's also a 0th tier called AMC 8, which is to prepare young elementary school students for the tier 1 exam. About 300K students from USA/Canada sit in the below exams annually. Roughly 100K students appear for each of AMC 8, AMC 10 and AMC 12

  • AMC 8 (American Maths Competition): AMC 8 is for kids who are in 8th grade or lower. It's a 25-question, 75-minute, multiple-choice exam. Each question has only one correct answer and carries 1 mark, for a total of 25 marks. There's no -ve marking. It's a good stepping platform for kids to get their brains working in Maths and to prepare for higher level Maths Olympiad. About 100K students take AMC 8 exam. Scoring a perfect score here means you are in top 100 kids in Maths in all of USA (Top 0.1%), and most likely going to make it to AIME in high school. Even getting a score of 20+ gets you in top 5%.
  • AMC 10/12 (American Maths Competition): The AMC 10 and AMC 12 are both 25-question, 75-minute, multiple-choice examinations in high school mathematics. Question pattern is the same as AMC 8, but questions are harder. The AMC 10/12 being multiple choice questions are scored in a way that penalizes guesses. Correct answers are worth 6 points, incorrect questions are worth 0 points, and unanswered answers are worth 1.5 points (before 2006, unanswered questions were worth 2.5 points), to give a total score out of 150 points. Usually getting over 100 gets you close to qualifying for the next level exam (i.e AIME). The AMC 10 is for students in 10th grade and below (for USAJMO) and covers the high school curriculum up to 10th grade. The AMC 12 is for students in 12th grade or below (for USAMO) and covers the entire high school curriculum, including trigonometry, advanced algebra, and advanced geometry, but excluding calculus. Students may take the next level AIME after qualification by being in the (approximately) top 10% of scorers on AMC 10/12. Before 2020, it was lot tougher to qualify for AIME as only top 2.5% of scorers on the AMC 10 and the top 5% of scorers on the AMC 12.
  • AIME (American Invitational Maths Exam): AIME is a challenging competition offered for those who excelled on the AMC 10 and/or AMC 12. AMC 8 students are not considered for AIME. The AIME is a 15-question, 3-hour examination, in which each answer is an integer number between 0 to 999. Each question carries 10 marks for a total of 150 marks (In reality each question is only 1 mark for a total of 15 marks, but the total score later gets multiplied by 10 when considering for qualification). The questions on the AIME are much more difficult than those on the AMC 10 and AMC 12. Scores from both AMC 10 or AMC 12 and AIME are considered to qualify for next level. Total score from AMC 10/12 is 150 and from AIME is 150 for a total of 300. Scoring above 200 will usually qualify you for next level. To scroe 200+, it's better to score high in AMC10/12 as questions there are easier, and then try to solve may be 7-8 problems in AIME. Solving 10 or more problems in AIME is really tough, at least for me. Top-scoring participants on the AIME are invited to take the USAMO or USAJMO. About 250 students from AMC10 + AIME scores are invited for USJMO. Similarly 250 students from AMC12 + AIME scores are invited for USAMO. Here's the link for qualifying scores from all past years: https://www.momentumlearning.org/amc-cutoff-scores/
  • USAMO/USJMO: Once you have made it through the AMC 10/12 and AIME, you are invited to take the USAMO or USJMO exam. This is the toughest exam of all 3. Since 2002, the USAMO has been a six-question, nine-hour maths proof competition spread out over two days. (The IMO uses the same format.) On each day, four and a half hours are given for three questions. Each question is graded on a scale from 0 to 7, with a score of 7 representing a proof that is mathematically sound. Thus, a perfect score is 42 points, and is relatively rare (only 10 or so participants were able to get it for 2023)!! Top scorers in USAMO/USJMO (Total 60 from pool of 100K+ AMC10/12 participants) are invited to join the maths olympiad pgm (MOP), go thru an extensive training from which 6 students (6 selected from USAMO only. USJMO partcipants are eligible next year) are finally selected to represent USA in IMO.

Here's the chart showing how this :

 

Here is the cutoff for all prior years: https://artofproblemsolving.com/wiki/index.php/AMC_historical_results

More on MAA for latest year: https://maa.edvistas.com/eduview/report.aspx?mode=6

  • AMC 8: You need to get at least 20 out of 25 questions correct in order to get in top 5% so that you get a certificate.
  • AMC 10: You need to get at least 15 out of 25 questions correct in order to get in top 10% so that you qualify for AIME. To get in top 1% for a "distinguished Honor Certificate", you need to get 21-22 questions correct.
  • AMC 12: You need to get at least 15 out of 25 questions correct in order to get in top 10% so that you qualify for AIME. To get in top 1% for a "distinguished Honor Certificate", you need to get 21-22 questions correct. So, it's same requirement as AMC12, but last 10 questions in AMC12 are usually harder than in AMC10, so getting same score in AMC12 is harder than in AMC10.
  • AIME: You need to get at least 10 out of 15 questions correct in order to comfortably get a total score of AMC10/AMC12 + AIME to be > 200. A combined score of 200+ is usually needed to qualify for USJMO, while 220+ is needed to qualify for USAMO. AMC questions are easier, so get 20 questions correct in AMC, and then shoot for 10 questions in AIME. There are no multiple choice in AIME, so getting 10 questions correct is very difficult.
  • USJMO/USAMO: From MAA website, looking at results for 2023, looks like USJMO participants need 4 out of 6 to qualify for selection, while USAMO need 5 out of 6. Since the questions are extremely tough here, less than 1/2 the participants are able to get 3 or more correct.

There's also a AMC trainer that generates new questions for you as you progress => https://www.amctrainer.com/

Sample Practice Paper for AMC 8:

There is a sample practice paper for starters from AMC10 2017 on MAA website (this is one of the easiest paper that you can possibly find in Maths olympiad, and I realized it's from AMC 8, even though it says it's AMC 10/12). If you are able to solve all 8 questions over here, then Maths Olympiad is definitely for you to try and have fun.

Link => https://www.maa.org/sites/default/files/2017_AMC1012_Practice_Questions.pdf

If you find that too easy, you may head to AIME papers which are significantly harder than AMC papers. One such paper from 2020 is here (local copy) => 2020 AIME Paper

Being able to solve more than 7 out of 15 questions here is already getting you as a strong participant for USAMO/USJMO.

Few more sample papers:

 

International Maths Olympiad (IMO):

This is the ultimate Maths Olympiad, where very few in the world get to participate and represent their country. After being selected in top 6 in your country, you get to participate in IMO. Participating in the IMO and winning a medal gets you to stand in the same league as the Noble Prize winners in Maths. That's something !!

Official website: https://www.imo-official.org

All question papers from 1959 to until now can be found on this link: https://www.imo-official.org/problems.aspx

 


 

Maths Olympiad topics:

There a lot of topics Maths Olympiad covers, but all of them are basic Maths (12th grade or lower with no AP/Pre-AP courses), and don't require formula. However, I've seen complex number problems, which seems unfair to kids who are not familiar with such topics. Below are topics that I gathered:

  • Probability: These are the most popular questions on AMC8/10/12 and AIME. Questions get harder with higher grade level exams, and most of the times you have to think of all possible permutation/combination. Some of the problems sre very hard, and it's easy to miss some possible combinations, getting ll your hard work in vain.
  • Geometry: Basic Geometry including traingles, circles, Pythagoras Theorem, Incircle, CircumCircle, Orthocenter, etc. Also basic area, volume for 2D/3D structures.
  • Algebra: Basic algebra using variables, reducing polynomials, solving equations, etc.
  • Logical: Basic logical questions which require minimal maths
  • Trignometry, Advanced Algebra and Advanced Geometry are for AMC12 and beyond.