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