Monday, December 24, 2012

Levelization of circuits

Hello,

When working with benchmark circuits, it is convenient to levelize the gates and work with levels. This is useful when you want to calculate some metric for all gates or wires. It is efficient than recursively traversing through all wires, gates, and fanouts. 

Here I upload a program that levelizes the iscas bench marks.  It is written in perl. Use it the way you see fit and edit it if you find mistakes.



Levelization
1. Assign level number 0 to all primary inputs
2. For each PI fanout
  • Label that circuit line with level number of the PI 
  • Queue the logic gate driven by that fanout line (I need a queue)
3. While queue is not empty
  • dequeue the next logic gate in the queue 
  • If all of the gate fanins are labeled with level numbers, then label the logic gate and its fanouts with maximum of input levels + 1. Queue all fanouts of the logic gate. Otherwise requeue the logic gate. 

Algorithm - Levelization
loop
inputlist - list of primary inputs
for all gates
    if either of input of gates is present in the inputlist,
       add the gate to the queue

for the gates in the queue
    dequeue the gate
    if all the inputs of the gates have levels assigned (level is not -1) then
         level(gate)=max(level of inputs)+1, level(output wire) = max(level of inputs)+1
         push outputwire into input list
    if all inputs of gate do not have levels assigned
         push the gate to the end of the queue.
goto loop 

How to run: perl levelization.plx test_3.v 

Sample: test_3.v 
module test_3 (A1,B1,C1,D1,O1,O2,O3); 
input A1,B1,C1,D1; 
output O1,O2,O3; 
wire Z1,Z2,Z3,Z4; 
NAND2X1 NAND2_1 (.Y(Z1),.A(C1),.B(D1)); 
NAND2X1 NAND2_2 (.Y(Z2),.A(B1),.B(Z1)); 
NAND2X1 NAND2_3 (.Y(Z3),.A(A1),.B(Z2)); 
NAND2X1 NAND2_4 (.Y(Z4),.A(Z2),.B(Z1)); 
NAND2X1 NAND2_5 (.Y(O3),.A(C1),.B(D1)); 
NAND2X1 NAND2_6 (.Y(O1),.A(Z3),.B(Z4)); 
BUFX1 BUF1_1 (.Y(O2),.A(Z4)); 
endmodule 



Output 
gate: level 
NAND2_1: 1 
NAND2_2: 2 
NAND2_3: 3 
NAND2_4: 3 
NAND2_5: 1 
NAND2_6: 4 
BUF1_1: 4



 #!/usr/bin/perl  
 #levelization.plx  
 use warnings;  
 use Data::Dumper;  
 use strict;  
 my $bench_file = $ARGV[0];  
 my $file_name;  
 my $circuit_name;  
 my $element;  
 my @input_array;  
 my @output_array;  
 my @wire_array;  
 my @gates;  
 my @sorted_gates;  
 my @wire_struct;  
 my @input_list_struct;  
 my @gate_queue;  
 #my @fanout_test;  
 my $num_inputs=0;  
 my $num_outputs=0;  
 my $num_wires=0;  
 my $num_gates=0;  
 my $gate_name_temp;  
 my $gate;  
 my $line;  
 my $role;  
 my $inp;  
 my $inp_test;  
 #Test netlist file  
 if($bench_file =~ /(.*).v/)  
 {  
 $file_name = $1;  
 }   
 else  
 {  
 print "Format of bench file name: circuit_name.v \n example : s1423.v\n";  
 }  
 #Read Netlist File  
 while(<>)  
 {  
   my $INPUT_DATA = $_;  
   chomp($INPUT_DATA);  
 {  
 #MODULE NAME  
 if($INPUT_DATA =~ /module (.*) (.*);/)  
 {  
   $circuit_name = $1;  
   print "circuit name = $circuit_name\n";  
 }  
 #INPUT OUTPUT WIRES  
 if($INPUT_DATA =~ /input (.*);/)  
 {  
   @input_array = split /,/, $1;  
 }  
 if($INPUT_DATA =~ /output (.*);/)  
 {  
   @output_array = split /,/, $1;  
 }  
 if($INPUT_DATA =~ /wire (.*);/)  
 {  
   @wire_array = split /,/, $1;  
 }  
 my @wire1;  
 my @wire2;  
 my @wire3;  
 my $gate_name_temp;  
 my $gate;  
 my $line;  
 my $role;  
 #AND, OR, NAND, NOR, XOR  
 if($INPUT_DATA =~ /(.*) (.*) \(\.Y\((.*)\),\.A\((.*)\),\.B\((.*)\)\);/)  
 {  
   push @gates,   
   {   
      num_inputs => 2,  
      gate_type => "$1",   
      gate_name => "$2",   
      output =>   
      {  
        wire_name => "$3",  
        sa0 => 1,  
        sa1 => 1,  
        level => 0,  
      },  
      input_1 =>   
      {  
        wire_name => "$2_$4",   
        sa0 => 1,  
        sa1 => 1,  
        level => 0,  
      },  
      input_2 =>   
      {  
        wire_name => "$2_$5",   
        sa0 => 1,  
        sa1 => 1,  
        level => 0,  
      },  
      processed => 0,   
      processed_ip1 => 0,  
      processed_ip2 => 0,  
      gate_level => -1,  
      shifted => 0  
   };  
 }  
 #INV, BUF  
 #DE - Doesnt Exist  
 #renaming the gates at inputs of the gates for fanouts  
 if($INPUT_DATA =~ /(INVX1|BUFX1) (.*) \(\.Y\((.*)\),\.A\((.*)\)\);$/)  
 {  
   $gate_name_temp = $2;  
   push @gates,   
   {   
      num_inputs => 1,  
      gate_type => "$1",   
      gate_name => "$2",   
      output =>   
      {  
        wire_name => "$3",  
        sa0 => 1,  
        sa1 => 1,  
        level => 0,  
      },  
      input_1 =>   
      {  
        wire_name => "$2_$4",   
        sa0 => 1,  
        sa1 => 1,  
        level => 0,  
      },  
      processed => 0,   
      processed_ip1 => 0,  
      gate_level => -1,  
      shifted => 0  
   };  
 }  
 }  
 }  
 #File Read complete  
 #wire struct holds fault data for all wires  
 #input_list_struct is used for levelization  
 for $element (@input_array){  
   print "input: $element\n";  
   push @wire_struct, { wire_name => "$element", sa0 => 1, sa1 =>1, level => 0};  
   push @input_list_struct, {wire_name => "$element", sa0 => 1, sa1 => 1, level => 0};  
 }  
 for $element (@wire_array){  
   push @wire_struct, { wire_name => "$element", sa0 => 1, sa1 =>1, level => -1};  
 }  
 for $element (@output_array){  
   push @wire_struct, { wire_name => "$element", sa0 => 1, sa1 =>1, level => -1};  
 }  
 print "Initial inputs\n";  
 for my $href ( @input_list_struct ) {  
   print "{ ";  
   for my $role ( keys %$href ) {  
   print "$role=$href->{$role} ";  
 }  
 print "}\n";  
 }  
 $num_gates = scalar @gates;  
 my $index=0;  
 #gate_processed = 2 then all inputs are processed  
 #shift gate into the queue if even one of the inputs processed  
 while($num_gates != 0)  
 {  
   for my $gate(@gates){    
      for my $inp (@input_list_struct){  
        my $inp_test = $inp->{wire_name};  
        if(($gate->{input_1})->{wire_name} =~ m/$inp_test$/){  
           $gate->{processed_ip1} = 1;  
           if($gate->{num_inputs}==1){  
             print "NOTE: $gate->{gate_name}:$gate->{processed}\n";  
             getc();  
             if($gate->{processed}!=$gate->{num_inputs}){  
                unshift(@gate_queue,$gate);  
             }  
           }  
           elsif($gate->{processed_ip2}==1){  
             $gate->{processed}=$gate->{num_inputs};  
           }  
           elsif($gate->{processed}!=$gate->{num_inputs}){  
             if($gate->{shifted}==0){  
                print "1. shifting $gate->{gate_name} to gate queue\n";  
                getc();  
                unshift(@gate_queue,$gate);       
             }  
           }  
        }  
        if(($gate->{num_inputs}!=1)){  
           if(($gate->{input_2})->{wire_name} =~ m/$inp_test$/){  
             $gate->{processed_ip2} = 1;    
             if($gate->{processed_ip1}==1){  
                $gate->{processed}=$gate->{num_inputs};  
             }  
             if($gate->{processed}!=$gate->{num_inputs}){  
                if($gate->{shifted}==0){  
                  print "2. shifting $gate->{gate_name} to gate queue\n";  
                  getc();  
                  unshift(@gate_queue,$gate);  
                }  
             }  
           }  
        }  
      }  
   }    
   print "Gates in gate queue\n";  
   for my $line (@gate_queue)   
   {  
      for my $role (keys %$line)  
      {  
        if($role =~ m/^input_1$/)  
        {  
           print "$role: $line->{$role}->{wire_name},";  
           print "lvl: $line->{$role}->{level},";  
        }  
        elsif($role =~ m/^input_2$/)  
        {  
           print "$role: $line->{$role}->{wire_name},";  
           print "lvl: $line->{$role}->{level},";  
        }  
        elsif($role =~ m/^output$/)  
        {  
           print "$role: $line->{$role}->{wire_name},";  
           print "lvl: $line->{$role}->{level},";  
        }  
        else  
        {  
           print "$role:$line->{$role},";  
        }  
      }  
      print "\n";  
   }  
   getc();  
 #if both inputs of the gates are processed, then calculate the level of the gate  
 #if only one of the inputs are processed, then add the gate to the end  
   my $num_gate_queue = scalar @gate_queue;  
   while ($num_gate_queue != 0)  
   {  
      $gate = pop(@gate_queue);  
      if($gate->{num_inputs}==1){  
        print "Number of gates in queue: $num_gate_queue";  
        if($gate->{processed_ip1}==1){  
           $gate->{processed}=$gate->{num_inputs};  
        }  
      }  
      if($gate->{processed}==$gate->{num_inputs}){  
        if($gate->{num_inputs}==2){  
           if(($gate->{input_1}->{level})>($gate->{input_2}->{level})){  
             $gate->{gate_level} = ($gate->{input_1}->{level});  
           }  
           else{  
             $gate->{gate_level} = ($gate->{input_2}->{level});  
           }  
           $gate->{gate_level}++;  
           $gate->{output}->{level}=$gate->{gate_level};  
           unshift(@input_list_struct,$gate->{output});  
           $num_gate_queue--;  
           $num_gates--;  
           print "Number of gates left $num_gates";  
           getc();    
        }  
        elsif($gate->{num_inputs}==1){  
           print "input level: $gate->{input_1}->{level}\n";  
           getc();  
           $gate->{gate_level} = $gate->{input_1}->{level};  
           $gate->{gate_level}++;  
           $gate->{output}->{level}=$gate->{gate_level};  
           print "$gate->{gate_name}: $gate->{gate_level}";  
           unshift(@input_list_struct,$gate->{output});  
           $num_gate_queue--;  
           $num_gates--;  
           print "Number of gates left $num_gates";  
           getc();    
        }  
      }  
      else{  
 #       if($gate->{shifted}==0){  
        print "3. shifting $gate->{gate_name} to gate queue\n";  
        getc();  
        unshift(@gate_queue,$gate);  
        $num_gate_queue--;  
 #gates that are not processed because of lack of second input being processed are shifted in here, they need not be shifted again  
        $gate->{shifted}=1;  
 #       }         
      }  
   }  
   print "updated input list\n";  
   for my $href ( @input_list_struct ) {  
      print "{ ";  
      for my $role ( keys %$href ) {  
        print "$role=$href->{$role} ";  
      }  
      print "}\n";  
   }  
 #the updated levels of the wires are present in input_list_struct  
 #update the fanouts of the gate with the levels from this struct  
   print "modifying gate: level input of gate\n";  
   for $gate(@gates){    
      for $inp (@input_list_struct){  
        $inp_test = $inp->{wire_name};  
        if(($gate->{input_1})->{wire_name} =~ m/$inp_test$/){   
           $gate->{input_1}->{level} = $inp->{level};  
           print "$gate->{gate_name}: $gate->{input_1}->{wire_name} - $gate->{input_1}->{level}\n";  
        }  
        if($gate->{num_inputs}!=1){  
           if(($gate->{input_2})->{wire_name} =~ m/$inp_test$/){   
             $gate->{input_2}->{level} = $inp->{level};  
           }  
        }  
      }  
   }  
 }  
 print "gate: level\n";  
 for $gate (@gates){  
   print "$gate->{gate_name}: $gate->{gate_level}\n";  
 }  


Tuesday, October 30, 2012

The shot never fired



"I will go to paradise" he thought. Sitting there with the gun in his pocket in the jeep. He was waiting. "When do they come?" his friend asked. "4:30" he said keeping his mind focused on the task he had been given. "I will go to paradise and I will be under the feet of the almighty. I will be freed from my sins since I am doing this for him." he thought. "but....".

He had long stopped listening to the tiny squeeky voice inside his head. Whenever he was on a mission dictated to him by god, the voice was there. A voice at a pitch slightly higher than his voice. The voice always questioned him. It always started with a but. He had learnt to control it. He was taught to not listen to the voice. "It is the devil" they told him when he was all but 14. "If you listen to the voice, you will be condemned for all eternity to hell. you will be burning in brimstone. You will know only pain and suffering". His tiny mind was acting on its instincts. It trusted the bigger man and took him for granted. He learnt to not trust the voice. He learnt to not trust himself.

The task at hand confused him but he dared not question the intentions of god and those who entrusted him with the task. He was but chosen, he was but blessed. How can he be confused? He kept reminding it to himself. He also became aware that the voice was becoming louder. "But..".

His thought shifted, his focus waned as a flood of memories rushed. Aisha, his little sister, playing with a ragged doll. She seemed very happy and without a care in the world. The moment she was born, he knew it was his mission to care for her and protect her. Her smile evoked the deepest feelings of tenderness in him. He sat beside her for hours answering all her curious questions, watching her jump from one object of interest to another. He felt his heart light with love when thinking about how she used to wait for him everyday near the door of their beautiful home. He saw her bloom into a beautiful flower in front of his eyes. He showered her with gifts when he himself dressed like a pauper. "STOP" she used to scream. "Dont keep doing this. Please listen to me" she said. He never did. He missed her. Sadly the unrelenting train of thought, mercilessly lead him through the course of events. It did not spare him and be satisfied with just the happy days in his life. His eyes darkened. His heart grew heavy like a cloth filled with tears. A rage grew in his heart, burning fiery blue, consuming his blood for fuel. He remembered the drones.

"She will be avenged. They will pay." he thought. His friend suddenly called out to him, shaking him out of the haze. "Here they come, be ready quick". He felt he had the vision of an eagle. He felt nothing in the world would stop him. They ambushed the school van. "Come Out" he commanded. A train of little girls came out, crying in fear. He had his gun out and pointed at them. "They are small kids. Do not harm them" the school van driver pleaded. He knew whom he had to shoot, he knew who was conspiring with the enemy, he knew who is going to bring him closer to god. He aimed the gun for her neck. All of a sudden there was a high pitched scream from inside him. "STOP", He could recoginse it. "Dont keep doing this. Please listen to me" it pleaded. He heard a soulful cry, his ears shattered, breathing stopped and brains burned. Tears rained from his eyes uncontrollably. "I will listen to you my dear sister. I will always listen to you." He pointed the gun to his head. The cry seized to be heard to him anymore. He felt nothing of the pain or the agony. It did not feel like burning in brimstone. He felt peace as his body fell. His head never hit the ground. He felt joy. He felt Aisha's lap.

OpenSPARC Synthesis using Design Compiler

OpenSPARCT1 comes with a built in script called rsyn that is used to synthesize the required verilog files using synopsys design compiler. All the modules are individually compiled (except the mega cells) and you get the flattened and hierarchical verilog netlist file for individual modules.  You do not have the netlist file for the entire OpenSPARCT1 yet and that has to be done manually.

 
Important Scripts provided by SUN

The OpenSPARCT1/design/sys/synopsys/script folder contains the scripts to configure and run synopsys
 
There are two configuration files
    1. io configuration - project_io_cfg.scr
    2. sparc configuration - project_sparc_cfg.scr 
they contain the configuration information.

Rsyn flow
The rsyn command calls identifies the tool that is to be used and then calls the "rsyn,1.0" file in OpenSPARCT1/tools/perlmod

1. The rsyn file reads the block list that is present in OpenSPARCT1/design/sys/synopsys/.
2. It runs the synthesis for each block and stores the synthesized files in /design/sys/iop/$block/synopsys folder for each block
3. To do this it calls the run.scr file
This synthesizes all the files in the block list.


Here I describe different processes. If you feel the method is not right and changes are to be done. kindly let me know. 


Have fun,
Abishek

Synthesizing individual blocks separately


It would be required to synthesize individual blocks in SPARC separately. For example, the method to synthesize the Load Store Unit is described here.

You need to have successfully run rsyn -how?

example lsu unit present in design/sys/iop/sparc/lsu

Steps
1. Create a work folder anywhere you like
2. cd into design/sys/iop/sparc/lsu
3. Use the following script to collect the flat_files from the location
4. Use the following script to extract the flat nestlist from all modules inside lsu to a folder called flat_files

Script: file_collect.sh (location /design/sys/iop/sparc/lsu)
cd /home/ar2654/opt/OpenSPARCT1/design/sys/iop/sparc/lsu
for FILE in $(find . -type f | grep -e "flat")
do
echo "cp ${FILE} /home/ar2654/opt/OpenSPARCT1/design/sys/iop/sparc/lsu/flat_files"
cp ${FILE} /home/ar2654/opt/OpenSPARCT1/design/sys/iop/sparc/lsu/flat_files
done

5. copy the files that are present in the flat_files folder to the work folder.
6. Copy the top file for the lsu namely lsu.v present in design/sys/iop/sparc/lsu/rtl to the work folder
6. Invoke design vision, run the configuration script to set up the libraries and work folders etc
7. File -> analyze, add all the files that are present in the work directory
8. File -> Elaborate, you will get warnings saying that sram modules (bw_r*) are missing, they cannot be synthesized because they are memory modules
9. Design -> compile
10. Command "report_qor > result_file" to report the area gate information etc.
11. Save the synthesized file. File -> save

List of file to compile just the SPARC core


List of files to compile sparc core in design vision present in design/sys/iop/sparc/flat_files

bw_clk_cl_sparc_cmp_flat.v
lsu_stb_rwctl_flat.v
sparc_ffu_ctl_flat.v
sparc_ifu_invctl_flat.v
spu_lsurpt_flat.v
cpx_spc_buf_flat.v
lsu_stb_rwdp_flat.v
sparc_ffu_dp_flat.v
sparc_ifu_mbist_flat.v
spu_madp_flat.v
cpx_spc_rpt_flat.v
lsu_tagdp_flat.v
sparc_ffu.v
sparc_ifu_sscan_flat.v
spu.v
lsu_dcdp_flat.v
lsu_tlbdp_flat.v
sparc_ffu_vis_flat.v
sparc_ifu_swl_flat.v
tlu_hyperv_flat.v
lsu_dctldp_flat.v
lsu.v
sparc_ifu_dcl_flat.v
sparc_ifu.v
tlu_incr64_flat.v
lsu_dctl_flat.v
sparc_exu_alu_flat.v
sparc_ifu_dec_flat.v
sparc_ifu_wseldp_flat.v
tlu_misctl_flat.v
lsu_excpctl_flat.v
sparc_exu_byp_flat.v
sparc_ifu_errctl_flat.v
sparc_mul_top_flat.v
tlu_mmu_ctl_flat.v
lsu_qctl1_flat.v
sparc_exu_div_flat.v
sparc_ifu_errdp_flat.v
sparc_tlu_intctl_flat.v
tlu_mmu_dp_flat.v
lsu_qctl2_flat.v
sparc_exu_ecc_flat.v
sparc_ifu_fcl_flat.v
sparc_tlu_intdp_flat.v
tlu_pib_flat.v
lsu_qdp1_flat.v
sparc_exu_ecl_flat.v
sparc_ifu_fdp_flat.v
sparc.v
tlu_tcl_flat.v
lsu_qdp2_flat.v
sparc_exu_rml_flat.v
sparc_ifu_ifqctl_flat.v
spc_pcx_buf_flat.v
tlu_tdp_flat.v
lsu_stb_ctldp_flat.v
sparc_exu_shft_flat.v
sparc_ifu_ifqdp_flat.v
spu_ctl_flat.v
tlu.v
lsu_stb_ctl_flat.v
sparc_exu.v
sparc_ifu_imd_flat.v
spu_lsurpt1_flat.v

Synthesizing just the SPARC Core using design-vision

-->

You need to have successfully run rsyn - how?

Sparc has a number of blocks.
bw_clk_cl_sparc_cmp cpx_spc_buf cpx_spc_rpt exu ffu ifu lsu mul spu tlu spc_pcx_buf 
 
Steps are
1. collect all the flattened netlist files from each block in work folder

file_collect.sh - location design/sys/iop/sparc
cd /home/ar2654/opt/OpenSPARCT1/design/sys/iop/sparc/
for FILE in $(find . -type f | grep -e "flat")
do
echo "cp ${FILE} /home/ar2654/opt/OpenSPARCT1/design/sys/iop/sparc/flat_files"
cp ${FILE} /home/ar2654/opt/OpenSPARCT1/design/sys/iop/sparc/flat_files
done

cd design/sys/iop/sparc
mkdir flat_files
./file_collect.sh

All the flat files in the sparc folder are present in /design/sys/iop/sparc/flat_files

2. collect the top level files from each of the blocks
you will find the top level blocks for each module in the rtl folder inside that module

current fldr - design/sys/iop/sparc/

1. sparc_ffu.v - ffu/rtl
2. sparc_ifu.v - ifu/rtl
3. sparc_exu.v - exu/rtl
4. lsu.v - lsu/rtl
5. tlu.v - tlu/rtl
6. spu.v - spu/rtl
7. sparc.v - ./rt/

copy these files into flat_files mentioned above.
Now all the required files are in flat_files folder.

1. Invoke design vision, run the configuration script to set up the libraries and work folders etc
2. File -> analyze, add all the files that are present in the work directory
3. File -> Elaborate, you will get warnings saying that sram modules (bw_r*) are missing, they cannot be synthesized because they are memory modules
4. Design -> compile
5. Command "report_qor > result_file" to report the area gate information etc.
6. Save the synthesized file. File -> save

Synthesizing the entire OpenSPARCT1 processor using design-vision (design compiler)



If we are required to find area information or the routing information of the entire processor (with all 8 cores etc) we have to manually compile the flattened netlist file with the top level file of the processor. The procedure is described here.

The top level module for OpenSPARCT1 is “iop.v” located at design/sys/iop/rtl


Synthesize the whole processor using design vision
I need the area information of the processor with all 8 cores

1. Run rsyn to generate all the flattened netlist - how?
2. collect all the flattened netlist file in a folder

File: file_collect.sh
Location ~/opt/OpenSPARCT1/flat_files

cd /home/ar2654/opt/OpenSPARCT1/design/sys/iop
for FILE in $(find . -type f | grep -e "flat")
do
echo "cp ${FILE} /home/ar2654/opt/OpenSPARCT1/flat_files"
cp ${FILE} /home/ar2654/opt/OpenSPARCT1/flat_files
done

3. The top level file for the entire OpenSPARC chip is present in design/sys/iop/rtl and is called iop.v.
The processors and their connections are instantiated in this file.
This file does not instantiate the processors or other modules because of "ifdef" conditions (look inside iop.v)
We need to define our requirements (number of processors required, other hardware required) and I defined them in iop.h (design/sys/iop/include)

For example to instantiate all 8 SPARC cores, we need to add the following lines in iop.h
`define RTL_SPARC0 1
`define RTL_SPARC1 1
.
.
.
`define RTL_SPARC7 1

Other ifdef conditions are present in iop.v. In my case I defined everything to be 1.
alternatively you can remove the ifdef conditions in iop.v

4. This modified top level file (iop.v) file is added to the flat_files folder
5. design_vision is started inside a working directory,
6. The configuration synopsys_dc.setup script is run – sample dc_script file
7. Analyze all the files that are there in the flat_files folder (File -> Analyze)
8. Elaobrate the design with OpenSPARCT1 as the top module. (File -> Elaborate)
If there are unresolved references other than the memory modules (bw_r*), find those modules and add them to the flat_files folder.
Analyze the unresolved references and elaborate until references to memory modules only remain
9. Compile Design to generate the area information

Appendix


Configuration file for design_vision
# synopsys_dc.setup file for opensparc

# Define the lsi_10k library
set SYN_LIBS /opt/synopsys/syn/libraries/syn
set SPARC_INC /home/ar2654/opt/OpenSPARCT1/design/sys/iop/include

# Define the libraries and search path
set search_path [concat $search_path ${SYN_LIBS} ${SPARC_INC}]
set target_library ${SYN_LIBS}/lsi_10k.db
set link_library [concat "*" $target_library]
set symbol_library ${SYN_LIBS}/lsi_10k.sdb

define_design_lib WORK -path home/ar2654/opt/OpenSPARCT1/SYN_full/WORKar2654@nanovlsi %

File: file_collect.sh

cd /home/ar2654/opt/OpenSPARCT1/design/sys/iop
for FILE in $(find . -type f | grep -e "flat")
do
echo "cp ${FILE} /home/ar2654/opt/OpenSPARCT1/flat_files"
cp ${FILE} /home/ar2654/opt/OpenSPARCT1/flat_files
done

Synthesizing the individual modules of OpensparcT1 - RSYN

 
rsyn compiles all the files using design compiler. The default library used is lsi_10k.db
  1. Open Design and verification guide
  2. In the quick start section 1.3.1 follow unzip and untar commands
  3. cd to the folder untared
  4. Open the OpenSPARC.cshrc script
  5. Edit the document to set up the environment for openSPARC.cshrc
  6. synopsys libraries - /opt/synopsys/syn
  7. sparcos5 libraries -
  8. I was not able to find the libraries at the place mentioned in the document so I used to locate command to locate sparcos5 libraries
  9. locate sparcOS5
  10. source the .tcshrc_synopsys file (it contains the license file in my case)
  11. source OpenSPARCT1.cshrc file
  12. rsyn -all

If everything runs well you can find
  1. In the folder of every component (analog/*, ccx/* etc) you can find a folder called synopsys
  2. Inside that folder you will have log files for commands and design compiler
  3. A gate folder which contains the compiled, flattened and hierarchical netlist
  4. A log folder which contains the area report for that cell

ERRORS:
Runs well till the module ctu is being synthesized
Abort at 51
Fatal: Internal system error, cannot recover.

Googled this error and found

He says
I sorted this error it has to do with the fact that the read_file function in DC "Cannot pass parameters (must use directives in HDL)" as documented in table 6-2 of this pdf file http://www.vlsiip.com/dc_shell/dcug_6.pdf this means that the scripts for JBI and CTU must be edited. So with the CTU module the file ctu_revision.v has to be excluded from the "rtl_files" list at the top of the user_cfg.scr script (found in... /design/sys/iop/ctu/synopsys/script directory) and the following lines added at the bottom of the script:

read_file -format verilog -define RUNDC $dv_root/design/sys/iop/ctu/rtl/ctu_jtag_id.v
analyze -format verilog $dv_root/design/sys/iop/ctu/rtl/ctu_jtag_id.v
elaborate ctu_jtag_id

read_file -format verilog -define RUNDC $dv_root/design/sys/iop/ctu/rtl/ctu_mask_id.v
analyze -format verilog $dv_root/design/sys/iop/ctu/rtl/ctu_mask_id.v
elaborate ctu_mask_id

read_file -format verilog -define RUNDC $dv_root/design/sys/iop/ctu/rtl/ctu_revision.v
analyze -format verilog $dv_root/design/sys/iop/ctu/rtl/ctu_revision.v
elaborate ctu_revision ”

Works you need to do the same for more than one file . The files that fail need to be analyzed and elaborated. See appendix for sample user_cfg.scr file for ctu.
Everytime it fails, I go to the filename.log file in /design/sys/iop/ctu/synopsys and look at the last file that is executed. I then remove that line form the script file and added it at the end of the script in the format mentioned above.

Have fun,
Abishek

Sample OpenSPARCT1.cshrc


# User needs to define these new variables
setenv DV_ROOT /home/location_to/OpenSPARCT1
setenv MODEL_DIR /home/location_to/OpenSPARCT1_model

if (`uname -s` == "SunOS") then
setenv CC_BIN "/usr/dist/pkgs/sunstudio_`uname -p`/SUNWspro/bin"
else
setenv CC_BIN /usr/bin
endif

# Please define VERA_HOME only if you have VERA, otherwise comment it out.
if ((`uname -s` == "SunOS") && (`uname -p` == "sparc")) then
# setenv VERA_HOME /import/EDAtools/vera/vera,v6.2.10/5.x
else
# setenv VERA_HOME
endif

# Please define VCS_HOME only if you have VCS, otherwise comment it out.
#setenv VCS_HOME /import/EDAtools/vcs/vcs7.1.1R21

# Please define NCV_HOME only if you have NC-Verilog, otherwise comment it out.
#setenv NCV_HOME /import/EDAtools/ncverilog/ncverilog.v5.3.s2/5.x

# Please define NOVAS_HOME only if you have Debussy, otherwise comment it out.
if ((`uname -s` == "SunOS") && (`uname -p` == "sparc")) then
# setenv NOVAS_HOME /import/EDAtools/debussy/debussy,v5.3v19/5.x
endif

# Please define SYN_HOME only if you are running synopsys
setenv SYN_HOME "/opt/synopsys/syn"

# Please define SYNP_HOME only if you are running Synplicity
#setenv SYNP_HOME "/import/EDAtools/synplicity/synplify.v8.6.1/fpga_861"
#setenv LM_LICENSE_FILE
"/import/EDAtools/licenses/synopsys_key:/import/EDAtools/licenses/ncverilog_key"

# New variables (fixed or based on $DV_ROOT)
setenv TRE_ENTRY /
setenv TRE_LOG nobody
setenv TRE_SEARCH "$DV_ROOT/tools/env/tools.iver"
setenv ENVDIR $DV_ROOT/tools/env
setenv PERL_MODULE_BASE $DV_ROOT/tools/perlmod

# Synopsys variables from $SYN_HOME
setenv SYN_LIB /opt/synopsys/syn/libraries/syn
setenv SYN_BIN /opt/cadence/local/vtvtlib25/Synopsys_Libraries/vtvtlib25/sparcOS5

# Set Perl related variables
if ((`uname -s` == "SunOS") && (`uname -p` == "sparc")) then
setenv PERL_VER 5.8.7
setenv PERL_PATH $DV_ROOT/tools/perl-$PERL_VER
setenv PERL5_PATH $DV_ROOT/tools/perl-$PERL_VER/lib/perl5
setenv PERL_CMD "$PERL_PATH/bin/perl"
setenv PERL5LIB $PERL5_PATH
else
setenv PERL_CMD "/usr/bin/perl"
endif

# Set path
setenv PATH ".:$DV_ROOT/tools/bin:$SYN_BIN/:$CC_BIN/:$PATH"
set path = (. $DV_ROOT/tools/bin $SYN_BIN $CC_BIN $path)

Wednesday, October 17, 2012

Equivalent Fault Collapsing

Here is an equivalent fault collapsing program, The aim is to  read a combinational Verilog netlist file and perform equivalent fault collapsing for the circuit.

The program does equivalent fault collapsing for the following gate types
Two-input, one-output gates or One-input, one-output gates as follows:
AND2X1
OR2X1
NAND2X1
NOR2X1
XOR2X1
INVX1
BUFX1

Upgrade: Fanouts need to be considered separately. upgrade the program to include fanouts also
 #!/usr/bin/perl  
 #fault_collapsing.plx  
 use warnings;  
 use strict;  
 my $bench_file = $ARGV[0];  
 my $file_name;  
 my $circuit_name;  
 my $element;  
 my @input_array;  
 my @output_array;  
 my @wire_array;  
 my @gates;  
 my @sorted_gates;  
 my @wire_struct;  
 #my @fanout_test;  
 my $num_inputs=0;  
 my $num_outputs=0;  
 my $num_wires=0;  
 my $num_gates=0;  
 #Test netlist file  
 if($bench_file =~ /(.*).v/)  
 {  
 $file_name = $1;  
 }   
 else  
 {  
 print "Format of bench file name: circuit_name.v \n example : s1423.v\n";  
 }  
 #Read Netlist File  
 while(<>)  
 {  
   my $INPUT_DATA = $_;  
   chomp($INPUT_DATA);  
 {  
 #MODULE NAME  
 if($INPUT_DATA =~ /module (.*) (.*);/)  
 {  
   $circuit_name = $1;  
   print "circuit name = $circuit_name\n";  
 }  
 #INPUT OUTPUT WIRES  
 if($INPUT_DATA =~ /input (.*);/)  
 {  
   @input_array = split /,/, $1;  
 }  
 if($INPUT_DATA =~ /output (.*);/)  
 {  
   @output_array = split /,/, $1;  
 }  
 if($INPUT_DATA =~ /wire (.*);/)  
 {  
   @wire_array = split /,/, $1;  
 }  
 #AND, OR, NAND, NOR, XOR  
 if($INPUT_DATA =~ /(.*) (.*) \(\.Y\((.*)\),\.A\((.*)\),\.B\((.*)\)\);/)  
 {  
   push @gates, { gate_type => "$1", gate_name => "$2", output => "$3", input_1 => "$4", input_2 => "$5", processed => 0};  
 }  
 #INV, BUF  
 #DE - Doesnt Exist  
 if($INPUT_DATA =~ /(INVX1|BUFX1) (.*) \(\.Y\((.*)\),\.A\((.*)\)\);$/)  
 {  
   push @gates, { gate_type => "$1", gate_name => "$2", output => "$3", input_1 => "$4", input_2 => "DE", processed => 0};  
 }  
 }  
 }  
 #File Read complete  
 #wire struct holds fault data for all wires  
 for $element (@input_array){  
   print "input: $element\n";  
   push @wire_struct, { wire_name => "$element", sa0 => 1, sa1 =>1};  
 }  
 for $element (@wire_array){  
   push @wire_struct, { wire_name => "$element", sa0 => 1, sa1 =>1};  
 }  
 for $element (@output_array){  
   push @wire_struct, { wire_name => "$element", sa0 => 1, sa1 =>1};  
 }  
 =pod  
 print "\n";  
 for my $href ( @wire_struct ) {  
   print "{ ";  
   for my $role ( keys %$href ) {  
      print "$role=$href->{$role} ";  
   }  
   print "}\n";  
 }   
 =cut  
 $num_gates = scalar @gates;  
 my $index=0;  
 my @remd_gates_outputs;  
 my $gate_processed_flag=0;  
 while($num_gates>0)  
 {  
   $gate_processed_flag=0;  
   print "Number of Gates = $num_gates";  
   for my $gate (@gates)  
   {  
      print "\ngate fetched: $gate->{gate_name}";  
      if($gate->{processed}==0)  
      {  
        print "\ngate under process: $gate->{gate_name}";  
 #see if any of the inputs map to a single input gate  
        if($gate->{input_2}=~ m/^DE$/)  
        {  
           print "\nsingle input";  
           print "\ngate input : $gate->{input_1}";  
           for my $inp (@input_array)  
           {  
             if($gate->{input_1} =~ m/^$inp$/)  
             {  
                print "inp matches";  
 #for 1 input gate  
                print "\n";  
                for my $role ( keys %$gate )   
                {  
                  print "$role=$gate->{$role} ";  
                }  
 #NOT GATES  
                if($gate->{gate_type} =~ m/^INVX1$/)  
                {  
                  for my $wire (@wire_struct)  
                  {  
                     if($wire->{wire_name} =~ m/^$inp$/)  
                     {  
                       $wire->{sa0} = 0;  
                       $wire->{sa1} = 0;  
                       print "\n changing $inp sa0 to 0 and sa1 to 0";  
                     }  
                  }  
                  $gate->{processed}=1;  
                  $num_gates--;  
                  push @remd_gates_outputs, $gate->{output};  
                  $gate_processed_flag=1;  
                }  
 #BUFFER GATES  
                if($gate->{gate_type} =~ m/^BUFX1$/)  
                {  
                  for my $wire (@wire_struct)  
                  {  
                     if($wire->{wire_name} =~ m/^$inp$/)  
                     {  
                       $wire->{sa0} = 0;  
                       $wire->{sa1} = 0;  
                       print "\n changing $inp sa0 to 0 and sa1 to 0";  
                     }  
                  }  
                  $gate->{processed}=1;  
                  $num_gates--;  
                  push @remd_gates_outputs, $gate->{output};  
                  $gate_processed_flag=1;  
                }  
             }  
           }  
        }  
        for my $input1 (@input_array)  
        {  
           if($gate->{processed}==0)  
           {  
             print "\nInput wire 1: $input1";  
             if($gate->{input_1} =~ m/^$input1$/)  
             {  
                print "\t$gate->{gate_name}\t";  
                for my $input2 (@input_array)  
                {       
                  print "\nInput wire 2: $input2";  
 #for two input gates  
                  if($gate->{input_2} =~ m/^$input2$/)  
                  {  
                     print "Gate under consideration: $gate->{gate_name}";              
                     print "\n";  
                     for my $role ( keys %$gate )   
                     {  
                       print "$role=$gate->{$role} ";  
                     }  
 #NAND GATES  
                     if($gate->{gate_type} =~ m/^NAND2X1$/)  
                     {  
                       for my $wire (@wire_struct)  
                       {  
                          if($wire->{wire_name} =~ m/^$input1$/)  
                          {  
                            $wire->{sa0} = 0;  
                            print "\n changing $input1 sa0 to 0";  
                          }  
                          if($wire->{wire_name} =~ m/^$input2$/)  
                          {  
                            $wire->{sa0} = 0;  
                            print "\n changing $input2 sa0 to 0";  
                          }  
                       }  
                       $gate->{processed}=1;  
                       $num_gates--;  
                       push @remd_gates_outputs, $gate->{output};  
                       $gate_processed_flag=1;  
                     }  
 #AND GATES  
                     if($gate->{gate_type} =~ m/^AND2X1$/)  
                     {  
                       print "\nhi i am inside\n";  
                       for my $wire (@wire_struct)  
                       {  
                          if($wire->{wire_name} =~ m/^$input1$/)  
                          {  
                            $wire->{sa0} = 0;  
                            print "\n changing $input1 sa0 to 0";  
                          }  
                          if($wire->{wire_name} =~ m/^$input2$/)  
                          {  
                            $wire->{sa0} = 0;  
                            print "\n changing $input2 sa0 to 0";  
                          }  
                       }  
                       $gate->{processed}=1;  
                       $num_gates--;  
                       push @remd_gates_outputs, $gate->{output};  
                       $gate_processed_flag=1;  
                     }  
 #OR GATES  
                     if($gate->{gate_type} =~ m/^OR2X1$/)  
                     {  
                       for my $wire (@wire_struct)  
                       {  
                          if($wire->{wire_name} =~ m/^$input1$/)  
                          {  
                            $wire->{sa1} = 0;  
                            print "\n changing $input1 sa1to 0";  
                          }  
                          if($wire->{wire_name} =~ m/^$input2$/)  
                          {  
                            $wire->{sa1} = 0;  
                            print "\n changing $input2 sa1 to 0";  
                          }  
                       }  
                       $gate->{processed}=1;  
                       $num_gates--;  
                       push @remd_gates_outputs, $gate->{output};  
                       $gate_processed_flag=1;  
                     }  
 #NOR GATES  
                     if($gate->{gate_type} =~ m/^NOR2X1$/)  
                     {  
                       for my $wire (@wire_struct)  
                       {  
                          if($wire->{wire_name} =~ m/^$input1$/)  
                          {  
                            $wire->{sa1} = 0;  
                            print "\n changing $input1 sa0 to 0";  
                          }  
                          if($wire->{wire_name} =~ m/^$input2$/)  
                          {  
                            $wire->{sa1} = 0;  
                            print "\n changing $input2 sa0 to 0";  
                          }  
                       }  
                       $gate->{processed}=1;  
                       $num_gates--;  
                       push @remd_gates_outputs, $gate->{output};  
                       $gate_processed_flag=1;  
                       print "\nnum gates = $num_gates";  
                     }  
                  }  
                }  
             }  
           }  
        }  
      }  
   }  
   if($gate_processed_flag==1)  
   {  
      print "\ngate outputs to be made inputs\n";  
      for $element (@remd_gates_outputs)  
      {  
        print "$element\n";  
        push @input_array, $element;            
      }  
      print "\nThe list of gates after removed\n";  
      for $element (@gates)  
      {  
        if($element->{processed}==0){  
           print "$element->{gate_name}";}  
      }  
      print "Number of gates left: $num_gates";  
   }  
   my $x = ord(getc);  
 }  
 print "\n";  
 for my $href ( @wire_struct ) {  
   print "{ ";  
   for my $role ( keys %$href ) {  
      print "$role=$href->{$role} ";  
   }  
   print "}\n";  
 }  
 =pod  
 print "\n";  
 for my $href ( @gates ) {  
   print "{ ";  
   for my $role ( keys %$href ) {  
      print "$role=$href->{$role} ";  
   }  
   print "}\n";  
 }   
 =cut  
 =pod  
 my $href1;  
 for $href1 ( @gates ) {  
   for $element (@output_array){  
   if($href1->{output} =~ m/$element/){  
      print "output_arr=$element\n";  
      print "output=$href1->{output}\n ";  
      push @sorted_gates, $href1;  
     }  
   print "output_arr=$element\n";  
   print "output=$href1->{output}\n ";  
   }   
 }  
 =cut  
 =pod  
 print "\n";  
 for my $href ( @sorted_gates ) {  
   print "{ ";  
   for my $role ( keys %$href ) {  
      print "$role=$href->{$role} ";  
   }  
   print "}\n";  
 }  
 =cut  

Sunday, June 3, 2012

The answer that is known but still unknown.

 "No man can reveal to you aught but that which already lies half asleep in the dawning of your knowledge."

Whatever you have learnt is not new. It is already known to you. You are made aware of it by a teacher. It is human nature to know if told, to forget with time and then know again. Nevertheless we know it already. 

It is the duty of the teacher to enlighten the student of what he already knows. The teacher cannot give his knowledge to the student but rather takes the student to what he knows by virtue of reasoning and coherent discussion. What the teacher actually gives the student is his love. 

"And even as each one of you stands alone in God's knowledge, so must each one of you be alone in his knowledge of God and in his understanding of the earth."

These are my interpretation of the words of Khalil Gibran. The clarity of his thought resonate truth in me. It seems true that whatever we understand we already know. So it is in us the answers to all questions. We have to find our way to it, a coherent way so that everything makes sense and all questions are answered. 

I am trying to trace my thought process to the question of existence of god. There are a lot of things that are explained by science but extremely wonderful to be a mere coincidence. For example a calf that is born instinctively knows what to do. Similarly in the process of evolution, instinctively the female of a species chooses a male whose genes would be able to better protect her offsprings and help in the survival of species. How does it do it instinctively? Where do animals get their collective memory from. For example a pigeon need not have seen a falcon in its entire life but when it sees the silhouette of a falcon, it knows to fly away. Every species does something spectacular for their continuance. Where do all these memory come from? God maybe?

There are so many wonderful phenomena. The duality of light. The schrodinger's cat. Things that are to unbelievable to imagine. Case in point, the schrodinger's cat explanation led to this famous question of whether the moon exists if we don't look at it. Maybe it needs more imagination than what we understand because the senses we are provided with are not enough to imagine at such a level or maybe our own observations are changing the way it works. We don't know. Do we need to understand everything to get an answer to our question? How do we dig deeper into our understanding to know the answer which is just lying there waiting to be found out? How amazing is everything?

Thus we continue in our journey for knowledge. I hope that one day we will be able to understand this universe and hence be able to provide a coherent answer to the question. Until then we walk

Friday, May 4, 2012

What is important and what is not.


It is in stark contrast, how the rich differ from the poor. The extravagance is so appalling. I have seen poor schools back home. I have seen their resources and how people study there. It was only recently that I saw a "rich" school. It raised a number of questions in me. What is the need for an XBOX 360 and LCD Tvs in a school? Why do people put money in buying xbox 360s in schools when many schools do not have benches for people to sit on? Who needs to learn the art of bowling and para sailing when other people do not have a foot ball to play with? How is the rich privileged to do what ever they want and the poor need to have do with whatever little they have? Why is it that it is the rich who complain and poor are content with what they have despite the responsibilities they shoulder, burdened upon them by the rich? How can the rich take ownership of the "resources" that is bestowed upon all of us by mother nature? How can mother nature be partial?

Can mother nature be partial to her children? A mother loves all her children equally. So the greatest wealth she provides her children must be equal to all. This means that all these "resources" owned by the rich are not important to her. The gold and diamonds are just stones in her eyes. It doesn't matter to her when a few of her children get to play with shiny stones while others don't because they are just stones. She knows the air we breath is important and she gives it to everyone equally. She knows water is important and which she does provide for all her children. There is an Oasis even in a desert.

There lies the fundamental answer to all the questions. What is important and what is not. The greatest wealth provided by nature are free for everyone to take. They are available for everyone equally. This wealth is common for all and cannot be taken away from man. It can only be given in abundance. The greatest resource is knowledge. It is knowledge that we must be after. Not extravagant richness and hanging chandeliers. Not huge houses or expensive cars but simple elegant knowledge. Obtaining knowledge is the means and it is the end, moving us from ignorance into light.