It is quite long.
#!/usr/bin/perl
use warnings;
use Data::Dumper;
use strict;
use List::Util qw(min max);
my $bench_file = $ARGV[0];
my $filename = 'c:\Users\aqids\Desktop\SEM 7\FYP 1\test_3.v';
my @input_array;
my @output_array;
my @wire_array;
my @gates;
my @gate_type;
my @gate_name;
my @output_gate;
my @input_A;
my @input_B;
my @gate_data;
my %primaryCC0;
use constant {CC0 => 0, CC1 =>1};
my $gate_type=0;
my $gate_name=0;
my $output_gate=0;
my $input_A=0;
my $input_B=0;
print "----------------------------------\n TESTABILITY MEASURE
+S \n---------------------------------- \n";
open(FH, '<', $filename) or die "Format of bench file name: circuit_na
+me.v \n example : s1423.v\n";
while(<FH>)
{
#READ MODULE NAME
my $MODULE_NAME = $_;
if (defined($MODULE_NAME) && ($MODULE_NAME =~ /module (\w+) /))
{
my $module_name = $1;
print "Circuit name = $module_name\n";
}
#READ input N1,N2,N3,N6,N7;
my $INPUT_DATA = $_;
if (defined($INPUT_DATA) && ($INPUT_DATA =~ /input (.*);/))
{
@input_array = split /,/, $1;
my $size_input = @input_array;
print "Primary input = ";
print scalar "@input_array\n";
print "Number of primary input = $size_input\n";
}
#READ output N22, N23;
my $OUTPUT_DATA = $_;
if (defined($OUTPUT_DATA) && ($OUTPUT_DATA =~ /output (.*);/))
{
@output_array = split /,/, $1;
my $size_output = @output_array;
print "Primary output = ";
print scalar "@output_array\n";
print "Number of primary output = $size_output\n";
}
#READ wire N10, N11, N16, N19;
my $WIRE_DATA = $_;
if (defined($WIRE_DATA) && ($WIRE_DATA =~ /wire (.*);/))
{
@wire_array = split /,/, $1;
my $size_wire = @wire_array;
print "Wires = ";
print scalar "@wire_array\n";
print "Number of wires = $size_wire\n\n";
}
#AND, OR, NAND, NOR, XOR
my $gate_DATA = $_;
if (defined($gate_DATA) && ($gate_DATA =~ /(.*) (.*) \((.*),(.*),(
+.*)\);/) && ($gate_DATA !~ /module/) )
{
$gate_type = $1, $gate_name = $2, $output_gate = $3, $input_A
+= $4, $input_B = $5;
push @gate_type, $gate_type;
push @gate_name, $gate_name;
push @input_A, $input_A;
push @input_B, $input_B;
push @output_gate, $output_gate;
push @gate_data, $gate_name, $output_gate, $input_A, $input_B;
push @gates,
{
element => "gate",
num_inputs => 2,
gate_type => "$1",
gate_name => "$2",
output => { element => "wire", wire_name => "$3", level
+=> 0, wire_delay => 0 },
input_1 => { element => "wire", wire_name => "$4", level
+ => 0, wire_delay => 0, },
input_2 => { element => "wire", wire_name => "$5", level
+ => 0, wire_delay => 0, },
processed => 0,
gate_delay => 2,
gate_level => -1
};
}
}
#File Read complete
my $gate, my $element, my $num_gates, my $inp, my $inp_test;
my @wire_struct;
my @input_list_struct;
my @input_list_struct_2;
my @output_list_struct;
my @gate_queue;
my %hash1;
my %hash2;
my %hash3;
my %hash4;
#wire struct holds fault data for all wires
#input_list_struct is used for levelization
for $element (@input_array){
push @wire_struct, {element => "wire",wire_name => "$element", sa0
+=> 1, sa1 =>1, level => 0,wire_delay=>0};
push @input_list_struct, {element => "wire",wire_name => "$element"
+, sa0 => 1, sa1 => 1, level => 0,wire_delay=>0};
push @input_list_struct_2, {element => "wire",wire_name => "$elemen
+t", sa0 => 1, sa1 => 1, level => 0,wire_delay=>0};
}
for $element (@wire_array){
push @wire_struct, { element => "wire",wire_name => "$element", sa0
+ => 1, sa1 =>1, level => -1,wire_delay=>0};
}
for $element (@output_array){
push @wire_struct, { element => "wire",wire_name => "$element", sa0
+ => 1, sa1 =>1, level => -1,wire_delay=>0};
push @output_list_struct, {element => "wire",wire_name => "$element
+", sa0 => 1, sa1 => 1, level => 0,wire_delay=>0};
}
$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}++;
if($gate->{processed}==1){
unshift(@gate_queue,$gate);
}
if($gate->{processed}>1){
$gate->{processed}=$gate->{num_inputs};
}
}
if(($gate->{num_inputs}!=1)){
if(($gate->{input_2})->{wire_name} =~ m/$inp_test$/){
$gate->{processed}++;
if($gate->{processed}==1){
unshift(@gate_queue,$gate);
}
}
if($gate->{processed}>1){
$gate->{processed}=$gate->{num_inputs};
}
}
}
}
#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 en
+d
my $num_gate_queue = scalar @gate_queue;
while ($num_gate_queue != 0)
{
$gate = pop(@gate_queue);
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--;
}
elsif($gate->{num_inputs}==1){
$gate->{gate_level} = $gate->{input_1}->{level};
$gate->{gate_level}++;
$gate->{output}->{level}=$gate->{gate_level};
unshift(@input_list_struct,$gate->{output});
$num_gate_queue--;
$num_gates--;
}
}
else{
unshift(@gate_queue,$gate);
$num_gate_queue--;
}
}
#the updated levels of the wires are present in input_list_struct
#update the fanouts of the gate with the levels from this struct
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};
}
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";
}
print "\n\n";
my $level_2_inputCC0;
my $level_2_inputCC1;
my $level_3_inputCC0;
my $level_3_inputCC1;
my $gate_check;
my %gate_check;
my @gate_check;
my @level_1_output;
my %hashout1;
my %hashout2;
my %hashout3;
my @CC0_value_1;
my @CC0_value_1_1;
my @CC0_value_1_2;
my @CC1_value_1;
my $max_CC0_1=0;
my $inputKey=0;
my %hash;
#print "Controllability\n\n";
print "______________Level 1______________ \n\n";
print "wire name CCO CC1\n";
for $gate (@gates)
{
if (grep { $gate->{gate_level} eq '1' } @gates)
{
push @level_1_output, $gate->{output}->{wire_name};
%hash1 = ( $gate->{input_1}->{wire_name} => { CC0 => 1, CC1 => 1}
+ );
%hash2 = ( $gate->{input_2}->{wire_name} => { CC0 => 1, CC1 => 1}
+ );
%hash3 = ( $gate->{output}->{wire_name} => { CC0 => 0, CC1 => 0}
+);
if (grep { $gate->{gate_type} eq 'nand' } @gates)
{
$hash3{$gate->{output}->{wire_name}}{CC0} = $hash1{$gate->{inpu
+t_1}->{wire_name}}{CC1} + $hash2{$gate->{input_2}->{wire_name}}{CC1}
++ 1;
$hash3{$gate->{output}->{wire_name}}{CC1} = min($hash1{$gate->{
+input_1}->{wire_name}}{CC0} , $hash2{$gate->{input_2}->{wire_name}}{C
+C0}) + 1;
}
printf (" %-15s %-10s %-10s\n", $gate->{input_1}->{wire_name
+}, $hash1{$gate->{input_1}->{wire_name}}{CC0}, $hash1{$gate->{input_1
+}->{wire_name}}{CC1});
printf (" %-15s %-10s %-10s\n", $gate->{input_2}->{wire_name
+}, $hash2{$gate->{input_2}->{wire_name}}{CC0}, $hash2{$gate->{input_2
+}->{wire_name}}{CC1});
printf (" %-15s %-10s %-10s\n", $gate->{output}->{wire_name}
+, $hash3{$gate->{output}->{wire_name}}{CC0}, $hash3{$gate->{output}->
+{wire_name}}{CC1});
$level_2_inputCC0 = $hash3{$gate->{output}->{wire_name}}{CC0};
$level_2_inputCC1 = $hash3{$gate->{output}->{wire_name}}{CC1};
push @CC0_value_1, $hash1{$gate->{input_1}->{wire_name}}{CC0}, $h
+ash2{$gate->{input_2}->{wire_name}}{CC0}, $hash3{$gate->{output}->{wi
+re_name}}{CC0};
push @CC1_value_1, $hash3{$gate->{output}->{wire_name}}{CC1};
$max_CC0_1 = max @CC0_value_1;
print "$max_CC0_1\n";
}
}
The input file is as below
module circuit_17 (N1,N2,N3,N6,N7,N22,N23);
input N1,N2,N3,N6,N7;
output N22,N23;
wire N10,N11,N16,N19;
nand nand2_1 (N10,N1,N3);
nand nand2_2 (N11,N3,N6);
nand nand2_3 (N16,N11,N2);
nand nand2_4 (N19,N11,N7);
nand nand2_5 (N22,N10,N16);
nand nand2_6 (N23,N16,N19);
endmodule