flounder has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks, I am writing a perl program to parse a verilog file for case statements. Once this is done, I am checking that all cases have been covered(we don't allow falling into default in our hardware design). But, the way I think is very C like(forgive me), and the code below can take a very long time to execute for large values of current_size, since the for loops are nested. Please help me reduce the execution time of this code.
for $j (0..((2**$current_size) - 1)) { $found = 0; @final_values = split(/[\s|\t]+/, $current_case); foreach $statement (@final_values) { if (bintodec($statement) == $j) {$found = 1;} } if (!$found){$missed_one = 1;} }
current_size is the number of bits, and current_case is a space separated string containing all of the case values in binary format. Thanks in advance for your help!

Replies are listed 'Best First'.
Re: Comparison effeciency
by Masem (Monsignor) on Apr 05, 2001 at 04:47 UTC
    A hash will work much better here:
    # Why was this line in the loop? It appears to be 'constant' # WRT to $j... # convert the binaries to decimals out here before we get into the loo +p... my @final_values = map { bintodec($_) } split(/[\s|\t]+/, $current_cas +e); my %hash; # just initialize these, but need no values... @hash{ @final_values } = (); my $not_found = 0; for $j (0..((2**$current_size) - 1)) { $not_found ||= !defined(%hash{ $j }); last if $not_found; } # $not_found will be 1 if at least one was missed...
    (Update should be !defined....)
    Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
      Thanks, you're right, the split should not be in the loop. Now, as a follow up, how would you check for multiple existences in the hash, and count them as you go along? Also, if you wouldn't mind, could you explain what exactly the ||= operator does. Thanks again!
        ||= either sets the variable on the left hand side to the value on the left hand side (unmodified, IOW) if it's not false, or sets it to the right hand side value. Now that I think about it, it's not necessary in this case ( you can just do $not_found = (!defined(...), and last to escape the loop...), but it's useful for optional parameters from command line or CGI scripts.

        Now, are you talking about multiple existences in your original array? To do that, simply apply a similar approach, as an example...

        my %hash; foreach $item (@array) { $hash{ $item } = ( !defined( $hash{ $item } ) ) ? $hash{ $item }++ : 1; }
        Which will count and enumerate all duplicates in your list.
        Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
Re: Comparison effeciency
by chromatic (Archbishop) on Apr 05, 2001 at 04:48 UTC
    If I were you, I'd split $current_case once, and put the values in a hash. Then, I'd loop through your $j loop, checking for the existence of keys in the hash.

    That way, you don't repeat the split and comparison for each case for each bit.

    I can do demo code if you need it, drop me a message.

    Very Fast Update: My example could would strongly resemble that of Masem. So don't message me, use his instead.

Re: Comparison effeciency
by domo (Initiate) on Apr 05, 2001 at 15:05 UTC
    You may or may not consider this answer responsive, but... Have you tried throwing the word 'verilog' at CPAN ? You'll find 12 modules, including a choice of parsers, which seem to me to address your problem space and could reduce the amount of code you have to write. (Not that I have any experience of Verilog, much less the modules in question.) I've found it a good idea always to check CPAN first before embarking on a Perl project.

    Apart from that, yes, use hashes as more advanced acolytes have advised.