Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Re: Understanding the scripting

by roboticus (Chancellor)
on Apr 02, 2019 at 19:06 UTC ( [id://1232045]=note: print w/replies, xml ) Need Help??


in reply to Understanding the scripting

ameezys:

It's a bit much to ask someone to go to the effort of commenting all the lines of a script like that. In fact, a question like this will often be ignored by people, as it's just an awful lot of work and there's no way to be sure that the work would be useful. I wasn't going to reply but I happened to be a bit bored and noticed that it was electronics-related, so I thought I'd offer a couple things.

Normally, if you can target your questions you'll get more and better responses. So if you get stuck like this and don't know where to start, what I'd suggest instead is to start simplifying the script, bit by bit, and ask for help when you get stuck. That way, it'll be much more educational for you. Getting started is often the hard part, so I'll offer a few suggestions in that direction:

  • First off, the indentation is inconsistent, making it difficult to actually see the structure of what's happening. I'd suggest choosing an indentation style and indenting the code. A good start would be to use perltidy to handle the indentation for you. Once you've properly indented it, you should be able to see a bit better the overall picture of what the code is actually doing. You can then add a few comments to label various chunks with what you *think* is going on.
  • Second, having all your variables declared at the beginning makes it difficult to see how "wide ranging" they are. Each set of curly braces gives you the opportunity to limit variables to a smaller scope, reducing the amount of stuff you have to remember and/or look for when trying to understand your code. So try to move your declarations to the innermost scope that lets your program continue to work.
    As an example, $circuit_name is used only inside an if statement, so you could just put the my immediately before the assignment, like this:
    if ( $INPUT_DATA =~ /module (\w+) /) { my $circuit_name = $1; print "circuit name = $circuit_name\n"; }
    Of course, when you see that it's used only like this, you'd probably just eliminate the variable name altogether:
    if ( $INPUT_DATA =~ /module (\w+) /) { print "circuit name = $1\n"; }

So go ahead and reindent your script and tighten up your variable scopes. This will give you the opportunity to see more opportunities to remove useless code and make the overall structure a bit easier to see. As I was looking over the code, I found:

  • Several variables that were declared but never used: index, num_outputs, num_wires, sorted_gates, wire1, wire2, wire3. So I deleted them.
  • I also noticed a variable that was written to but never read from (wire-struct), so I deleted all the code referencing that.
  • While removing the bits of code for wire-struct, it removed the only uses of two other variables (wire_array and output_array), allowing me to remove all that code.
  • There were also some variables that were declared at multiple levels in the code ($line, $role). This can be *very* confusing, since they are different variables. In the cases I noticed, I just kept the innermost declaration and the code checked out OK[1].

So with just these changes, I was able to quickly reduce the size of the script from 317 lines to 250 lines:

#!/usr/bin/perl #levelization.plx use warnings; use Data::Dumper; use strict; #Test netlist file my $bench_file = $ARGV[0]; if ( $bench_file !~ /(.*).v/ ) { print "Format of bench file name: circuit_name.v \n example : s142 +3.v\n"; } #Read Netlist File my @input_array; my @gates; while (<>) { my $INPUT_DATA = $_; chomp($INPUT_DATA); #MODULE NAME if ( $INPUT_DATA =~ /module (\w+) / ) { print "circuit name = $1\n"; } #INPUT OUTPUT WIRES if ( $INPUT_DATA =~ /input (.*);/ ) { @input_array = split /,/, $1; } #AND, OR, NAND, NOR, XOR if ( ( $INPUT_DATA =~ /(.*) (.*) \((.*),(.*),(.*)\);/ ) && ( $INPUT_DATA !~ /module/ ) ) { 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", CC0 => 1, CC1 => 1, level => 0, +}, input_2 => { wire_name => "$2_$5", CC0 => 1, CC1 => 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) (.*) \((.*),(.*),(.*)\);$/ ) { 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 #input_list_struct is used for levelization my @input_list_struct; for my $element (@input_array) { print "input: $element\n"; push @input_list_struct, { wire_name => "$element", sa0 => 1, sa1 => 1, level => 0 }; } print "Initial inputs\n"; for my $href (@input_list_struct) { print "{ "; for my $role ( keys %$href ) { print "$role=$href->{$role} "; } print "}\n"; } my $num_gates = scalar @gates; #gate_processed = 2 then all inputs are processed #shift gate into the queue if even one of the inputs processed my @gate_queue; 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 g +ate 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 le +vel of the gate # if only one of the inputs are processed, then add the gate to th +e end my $num_gate_queue = scalar @gate_queue; while ( $num_gate_queue != 0 ) { my $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 { 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 i +nput # being processed are shifted in here, they need not be sh +ifted 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 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->{input_1}->{level} = $inp->{level}; print "$gate->{gate_name}: $gate->{input_1}->{wire_nam +e} " . "- $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 my $gate (@gates) { print "$gate->{gate_name}: $gate->{gate_level}\n"; }

So I'd suggest documenting the parts you understand, and if you come across a bit you *don't* understand, then post and ask a question about what that bit of code means. Since you specifically asked about what the code was doing at the push @gates statement, I'll describe that now:

The push statement tells perl that you want to push a list of values onto an array:

my @array; # Push the value 1 onto @array push @array, 1; # Push the values 3, 4 and 5 onto @array push @array, 3, 4, 5; # Push an array reference (containing two strings) onto @array push @array, ['bill', 'bob']; # Push a hash reference onto @array push @array, {type=>'AND', inp_1=>'net_7', inp_2=>'net_8'}; # We can access the various values: print $array[0], "\n"; # 1 print $array[2], "\n"; # 4 print $array[4][1], "\n"; # bob print $array[5]{inp_1}, "\n"; # net_7

As you can see, you can push different types of values onto the array, and access them. So your code is building hashes containing information about parts of your circuit, and storing them into an array for later access. I noticed that the code also uses the unshift command to put information into the array. The primary difference is that push adds the information at the end of the array, while unshift adds information to the beginning of the array.

Note 1: I just asked perl to do a syntax check with "perl -c pm_1231976.pl" and it didn't report any errors. You didn't provide any input data, so I couldn't check whether the actual meaning of the program changed due to any of my changes.

...roboticus

When your only tool is a hammer, all problems look like your thumb.

Replies are listed 'Best First'.
Re^2: Understanding the scripting
by jwkrahn (Abbot) on Apr 03, 2019 at 01:00 UTC
    So with just these changes, I was able to quickly reduce the size of the script from 317 lines to 250 lines:

    I went a bit further and got it down to 216 lines.     :)

    I also noticed that on line 30 (original file) that the regular expression was testing if the file name ended with '.v' but the period wasn't escaped so I also assumed the same problem on lines 71 and 109.

Re^2: Understanding the scripting
by ameezys (Acolyte) on Apr 03, 2019 at 09:37 UTC
    Sorry for the inconvenience. And thank you for explaining regarding push function as I couldn't really understand regarding pushing a hash reference onto @array. The input data is actually named as test.v. Below here is the text file.
    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

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1232045]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (4)
As of 2024-04-24 21:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found