Heart:

Heart is one of the central system keeping the human body alive. The instant it stops working, you go dead. Heart failure is the number one cause of death.

Here's a good link to Heart's working: https://www.youtube.com/watch?v=_qmNCJxpsr0

One more good one with hand drawn diagram by Dr John Campbell: https://www.youtube.com/watch?v=VWamhZ8vTL4

Heart explained with a physical 3D model: https://www.youtube.com/watch?v=WyKBFWYKRBY

There's artificial hearts being made, which are someday going to replace failed hearts all together. The longest such an artificial heart has worked continuously in a human body is about 4 years. So, there's hope that over the next few decades, we may have artificial hearts lasting 20-30 years. Here's a video on such artificial hearts: https://www.youtube.com/watch?v=3uV8XZcIBbk

 

Heart anatomy: Heart sits in the center of our body near chest region. However, we hear that Heart is to our left. This is because some bigger chamber of heart is little bit to the left, so looks like heat is to the left. Right half of Heart is the one that collects dirty deoxygenated blood and passes it to the lungs for oxygenation. Once it gets oxygenated by lung, it's pushed to the left side of heart which transfers it to the rest of the body.

Link => https://medicoapps.org/wp-content/uploads/2018/10/1522314495.jpg

4 chambers of heart:

  1. Right Atrium (RA): Deoxygenated blood from all over the body is passed via blood pipes called Vena Cava (Superior Vena Cava (SVC) for top part and Anterior Vena Cava (AVC) for bottom part). These pipes or Veins enters the RA chamber here. Blood is passed to Right Ventricle which is sitting below the right atrium. There is a valve called "Tricuspid valve (TV)" that opens or closes to allow blood to pass from right atrium to right ventricle.
  2. Right Ventricle (RV): Deoxygenated blood flows from Right atrium to right ventricle and is pumped out to Lungs for oxygenation. There is a valve called "Pulmonic valve (PV)" that opens or closes to allow blood to pass from right ventricle to the lungs. The pipes going out of the heart to the lungs are called Pulmonary Artery (PA).
  3. Left Atrium (LA): Oxygenated blood from lungs is passed via blood vessels called Pulmonary Veins (PV). These pipes or veins enter the LA chamber here. The blood is then pushed to Left Ventricle which is sitting below the left atrium. There is a valve called "Bicuspid valve (BV)" or "mitral valve (MV)" that opens or closes to allow blood to pass from left atrium to left ventricle. MV is the equiv of TV that's seen on right side of heart b/w RA and RV.
  4. Left Ventricle (LV): Oxygenated blood flows from left atrium to left ventricle and is pumped out to the whole body (from brain to legs). Blood gets to cells which take oxygen from the blood, which gets the blood deoxygenated. Then this deoxygenated blood is passed on to the right atrium, and the 4 step cycle repeats again. There is a valve called "Aorotic valve (AV)" that opens or closes to allow blood to pass from left ventricle to the Aorta (a thick blood pipe which are arteries) which eventually branches out to the whole body. AV is the equiv of PV that's seen on right side of heart b/w RV and PA.

Atrium are much smaller than Ventricle, so when you see a pic of heart, you mostly see 2 front ventricles. The atriums are on the back and on the top of the heart (Ventricles are on the bottom). Though the cycle repeats from step 1 to step 4, processes in right side of heart are going in parallel to left side of heart, implying right and left atrium beat at the same time, while right and left ventricle also beat exactly at same time. So, we can consider only right side of heart for understanding purposes.

 


 

Veins and Arteries:

It's important to understand the difference b/w the two. Both are referred to as the blood vessels in the body. Veins are blood vessels going to the heart, while arteries are blood vessels going out of the heart. Veins get into the heart from 2 places => one from SVC/AVC into RA, and other from the lungs to LA in heart. Arteries get out of the heart from 2 places => one from RV going to the lungs, and other from the LV in heart. Usually blood vessels going into the heart carry deoxygenated blood, so veins are shown blue in color (blue means deprived blood, i.e in Hindi, people say a person's body has turned blue or "neela"meaning blood supply is dying), while blood vessels going out of the heart carry oxygenated blood, so arteries are shown red in color (red means rich blood). The only exception to this is the blood vessels going to the lungs and coming out of the lungs. The PA goes out of the heart to lungs carrying deoxygenated blood, and is shown blue even though it's an artery. Similarly, the PV goes from lungs to the heart carrying oxygenated blood, and is shown red even though it's a vein.

Blood Flow:

  • Right Heart: SVC/AVC (Veins) --> Heart (RA) -> Valve (TV) --> Heart (RV) -> Valve (PV) --> PA (Artery)
  • Lungs:                                                               --> Lungs -->
  • Left Heart:                PV (Vein) ->  Heart (LA) -> Valve (MV)  --> Heart (LV) -> Valve (AV) --> Aorta (Artery)

Arteries: Arteries carry blood away from the heart to the rest of the body. It needs pressure to push blood to everywhere in body. So, they have thick walls with muscle tissue. That thick pipe carrying blood from the heart to body is called "Aorta" as it's a Artery. It's the widest tube you find anywhere in body. It goes until the neck (which is a very short distance), before it branches off into smaller arteries to go to the head. The Aorta then curves back down to your chest. It continues through your abdomen and ends at your groin. Along the way, it splits off into other arteries that deliver oxygen-rich blood to your arms, legs, and the rest of your body..

Veins: Veins push deoxygenated blood back to your heart. Veins have thinner walls and are not as wide as arteries. Unlike arteries, veins generally need to work against gravity to push blood back to your heart. Veins have valves to help with this. These are one-way pairs of flaps inside a vein. They open for blood that’s heading upwards toward the heart, and close to keep blood from flowing back downwards.‌ Your veins usually hold about 75% of all the blood flowing through your body.‌ Your largest veins are the superior and inferior vena cava. Your superior vena cava carries blood from your upper body to the heart. Your inferior vena cava carries blood from everywhere below your heart. Like arteries, these two veins branch off into many other veins throughout your body. The veins coming out of right hear to go to Lungs are called Left Pulmonary Vein and Right Pulmonary vein. Muscle surrounds most veins in your body. When you walk, run, or otherwise use your muscles, they make a squeezing motion. These squeezes push against the vein and force the blood upwards toward your heart.

Capillaries: Arteries and veins connect through structures called capillaries. Capillaries are small webs of thin tubes that connect to an artery on one side and a vein on the other.‌ Some parts of your body have more capillaries depending on how much energy they need. For example, your muscles use a lot more energy than your skin, which is why your muscles have more capillaries than your outer skin.

 


 

Heart Disease:

CVD (Cardiovascular disease) refers to all diseases of cardiovascular system – which consists of the heart and all the blood vessels in the body. CVD is leading cause of death globally, with 18M deaths every year.

  1. Atherosclerosis: It is the main underlying cause of CVD. It is a disease in which plaques consisting of fat, cholesterol, calcium and other substances build up in the walls of arteries. Over time, the plaques harden, narrowing the opening of the arteries and restricting blood flow. If atherosclerosis occurs in one of the arteries that supply blood to the heart, it can cause a Heart Attack. If blood clot (known as thrombosis) occurs in one of the arteries to the brain, it causes a Stroke. Heart Attack and Cardian Arrest are used interchangeably, though they are different. A cardiac arrest usually occurs when there is a malfunction in the heart’s electrical system that causes the heart to stop beating properly. It suddenly stops beating. This results in the stoppage of blood flow to the brain and other vital organs, and the sufferer loses consciousness and stops breathing normally, resulting in death.
    1. Stroke (Aka Brain Stroke or Brain attack): 16M ppl suffer from stroke every year. Just a few hours of poor blood flow to some parts of brain causes the body to become paralyzed forever. Few symptoms of stroke include face changes, unbalanced walking, difficulty speaking or slurred speech, etc. 2 kinds of stroke:
      1. Ischemic Stroke:  This is caused due to lack of blood flow (because of a clot in the blood artery to brain). It can be temporary called as Transient Ischemic Attack (TIA) or permanent called as Ischemic Stroke. There is no medication for this, although some medicines given within few hours of stroke have been said to help dissolve the clot. However, there are medicines that are actively being researched to give to survivors of a Brain stroke so that they they form any more blood clots in future. One such medicine => https://www.hri.org.au/news/groundbreaking-world-first-trial-offers-new-hope-to-stroke-sufferers
      2. Hemorrhagic stroke: This is caused when a blood vessel in your brain ruptures or breaks, spilling blood into the surrounding tissues. This is very deadly and untreatable. However this is less common.
  2. Arrythmia (Irregular heartbeat): t is a type of heart condition where the heart rhythm is not steady. Instead, the heart may feel as though it were skipping a beat, have extra heartbeats every now and then, flutter or race, or beat faster or slower than normal. There are many types of arrhythmias, varying in severity and danger. Atrial Fibrillation (AF) is the most common type. Problems with the heart’s rhythm can occur when there is any interruption to the electrical signals that stimulate the heart’s pumping activity.
  3. Congestive heart failure (CHF):  CHF is #1 heart disease. It is a broad term used to describe a clinical condition resulting from the inability of the heart to adequately pump blood and causing symptoms such as orthopnea, dyspnea on exertion and edema.Heart has blood filling in and blood pumped out every beat. Insufficient filling or insufficient pumping are both problems that lead to CHF.
    1. Diastolic dysfunction, which is a condition of impaired ventricular filling. Less common.
    2. Systolic dysfunction, which is a condition of impaired ventricular emptying.
      1. Ejection Fraction (EF) : of heart is defined as volume of blood pumped per beat out of heart's chamber to the volume of blood filled per beat into the heart's chamber. This is defined for both left ventricle (LVEF) and right ventricle (RVEF). The full capacity of heart is about 120ml-150ml for an adult, and after each beat, volume of blood remaining is ~50ml, meaning 70ml-100ml was pumped out per beat giving an EF=60%-65%. EF of 50%-70% is considered normal. Low LVEF of < 40% is the most common kind of CHF (known as HFrEF) as it results in insufficient supply of blood to body parts. Low RVEF means heart is not pumping enough blood in lungs resulting in various issues. Usually, HF refers to tlow LVEF.

 


 

Treatment plan for HFrEF (Heart Failure with reduced Ejection Fraction):

These are 4 pillars of this treatment, which cosnsists of 4 different medications introduced in parallel.

Link => https://blog.bswhealth.med/four-pillars-of-heart-failure-therapy-should-be-rapidly-and-simultaneously-introduced/

4 Pillars:

  • Beta Blocker: This is the first pillar. These medications have been around for 30+ years.These are first line of defense. 
    • There are several types of beta-blockers, but only three are approved by the FDA to treat heart failure:
      • Bisoprolol (Zebeta) => Bisoprolol (Zebeta) is a selective beta1 antagonist without significant intrinsic sympathetic activity or vasodilating properties 
      • Carvedilol (Coreg) => Carvedilol is a non-selective beta-blocker with additional alpha1-blocking and antioxidant activities. Nebivolol is a novel beta-blocker with both a greater degree of selectivity for beta-1 adrenergic receptors than other agents in this class and an ability to stimulate endothelial nitric oxide production, leading to vasodilation and other potential clinical effects. Carvedilol (Coreg) is a novel agent with antagonist activity against alpha1, beta1 and beta2 receptors, as well as some antioxidant activity. It is the only beta blocker labeled by the U.S. Food and Drug Administration (FDA) for the treatment of heart failure.
      • Metoprolol (Toprol) => Like bisoprolol, metoprolol tartrate (Lopressor) and metoprolol succinate (Toprol XL) are beta1-selective blockers without significant intrinsic sympathetic activity or vasodilating properties.
    • A study published in 2000, showed little benefits for all 3 drugs when measured in terms of mortality rates (only 40% fewer deaths, but => https://www.aafp.org/pubs/afp/issues/2000/1201/p2453.html
       
  • ARNI inhibitor: ARNI is a combination of sacubitril, a neprilysin inhibitor, and valsartan, an angiotensin II receptor blocker (ARB) and is now considered first choice for initiation. ex: Vyamada (sold in India).
  • SGLT2 inhibitor: This has an additive when added on top of ARNI inhibitor. Two drugs, dapagliflozin or empagliflozin are recommended to reduce the risk of heart failure hospitalization and cardiovascular death in HFrEF patients.
  • MRA: Aldosterone Receptor Antagonist are also known as MRA. Discovered in the 1990s, these drugs are aldosterone antagonists that reduce excess fluid in the body while preventing the loss of potassium. Yet the primary efficacy is from neurohormonal blockage. They are weak diuretics. The normal dose is usually 25 mg daily.

 


 

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.