#!/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 MEASURES \n---------------------------------- \n"; open(FH, '<', $filename) or die "Format of bench file name: circuit_name.v \n example : s1423.v\n"; while() { #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 => "$element", 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 end 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->{input_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}}{CC0}) + 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"; } } #### 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