4

I want to convert a particular Verilog Bus into individual split form using sed or awk command.

Input

module test ( temp_bus[3:0], temp_B[1:0] )
    input [3:0] temp_bus;
    output [1:0] temp_B;
endmodule

Output

module test ( temp_bus[3], temp_bus[2], temp_bus[1], temp_bus[0], temp_B[1], temp_B[0])
   input temp_bus[3], temp_bus[2], temp_bus[1], temp_bus[0];
   output temp_B[1], temp_B[0];
endmodule

Edit1: Case with multiple declaration

module test ( temp_bus[3:0], temp_B[1:0] , temp_C[1:0] )
    input [3:0] temp_bus;
    output [1:0] temp_B , temp_c;
endmodule

Resultant must have output temp_B[1], temp_B[0], temp_C[1], temp_C[0] ;

cas has almost done given the best solution.

6
  • this would be very difficult to do with sed. try awk or perl or python instead.
    – cas
    Jul 4, 2016 at 8:50
  • Answerers are so focussed on the tools that they've probably not noticed that this won't work in standard Verilog 2005. (-:
    – JdeBP
    Jul 4, 2016 at 15:08
  • @JdeBP - i've never even used verilog. i was focused on the input and the output.
    – cas
    Jul 8, 2016 at 9:46
  • 1
    @JigarGhandi Your Edit1 belongs in a new question, it's not just a minor variation of the original question. It requires a different approach, actually parsing the lines and remembering what has been seen before rather than making relatively simple, stateless transformations of whatever the current line is.
    – cas
    Jul 8, 2016 at 9:47
  • @cas I agree , Well I just edited the question. I am working on your answer to go for further modification. Meanwhile I feel the Edit1 should be stated for reader's use. Jul 8, 2016 at 9:51

2 Answers 2

4

Here's one way to do it in perl:

(revised version will handle both of your sample inputs. It also looks like a semi-colon inside [] doesn't confuse the markdown syntax highlighting)

#! /usr/bin/perl

use strict;

sub expand {
  my ($name,$start,$stop) = @_;
  my $step = ( $start < $stop ? 1 : -1);
  my @names=();

  my $i = $start;
  while ($i ne $stop + $step) {
    push @names, "$name\[$i\]";
    $i += $step;
  }
  return @names;
};

while(<>) {
  chomp;
  s/([(),;])/ $1/g;   # add a space before any commas, semi-colons, and
                      #  parentheses, so they get split into separate fields.

  my @l=();           # array to hold the output line as it's being built

  my @line = split ;  # split input line into fields, with 1-or-more
                      # whitespace characters (spaces or tabs) between each
                      # field.

  my $f=0;            # field counter

  while ($f < @line) {
    if ( $line[$f] =~ m/module/io ) {
        push @l,$line[$f++];
        while ($f < @line) {
            if ( $line[$f] =~ m/^(.*)\[(\d+):(\d+)\]$/o ) {
                # expand [n:n] on module line
                push @l, join(", ",expand($1,$2,$3));
            } else { 
                push @l, $line[$f]
            };
            $f++;
        };
    } elsif ($line[$f] =~ m/^(?:input|output)$/io) {
        # use sprintf() to indent first field to 10 chars wide.
        $line[$f] = sprintf("%10s",$line[$f]);
        push @l, $line[$f++];;

        my @exp = ();
        while ($f < @line) {
            if ( $line[$f] =~ m/^\[(\d+):(\d+)\]$/o ) {
                # extract and store [n:n] on input or output lines
                @exp=($1,$2);
            } elsif ( $line[$f] =~ m/^\w+$/io) {
                # expand "word" with [n:n] on input or output lines
                push @l,join(", ",expand($line[$f],@exp));
            } else {
                push @l, $line[$f];
            };
            $f++;
        };

    } else {
      # just append everything else to the output @l array
      push @l, $line[$f];
    };
    $f++;
  }
  print join(" ",@l),"\n";
}

Output:

$ ./jigar.pl ./jigar.txt 
module test ( temp_bus[3], temp_bus[2], temp_bus[1], temp_bus[0] , temp_B[1], temp_B[0] ) 
     input temp_bus[3], temp_bus[2], temp_bus[1], temp_bus[0] ; 
    output temp_B[1], temp_B[0] ; 
endmodule 

Output from your second sample:

$ ./jigar2.pl jigar2.txt 
module test ( temp_bus[3], temp_bus[2], temp_bus[1], temp_bus[0] , temp_B[1], temp_B[0] , temp_C[1], temp_C[0] )
     input temp_bus[3], temp_bus[2], temp_bus[1], temp_bus[0] ;
    output temp_B[1], temp_B[0] , temp_c[1], temp_c[0] ;
endmodule
1
  • This code works fine, But I need to modify it for certain cases . I am updating the question containing such cases. Jul 8, 2016 at 9:12
0

Provided that you are only interested in the intervals in your example, it would be awkward, but not too difficult, to do in sed:

/(in|out)put/s/(\[.*\]+) *(.*);/\2\1;/
s/([A-Za-z_]+)\[3:0\]/\1[3], \1[2:0]/g
s/([A-Za-z_]+)\[2:0\]/\1[2], \1[1:0]/g
s/([A-Za-z_]+)\[1:0\]/\1[1], \1[0]/g

A slightly more general solution is also somewhat more involved:

/(in|out)put/s/(\[.*\]+) *(.*);/\2\1;/
/\[[0-9:]+\]/s/$/#9876543210/
:a {
   s/([A-Za-z_]+)\[([0-9]):0\](.*)(#[0-9]+)\2([0-9]+)$/\1[\2], \1[\5]\3\4\2\5/
   ta
}
s/#9876543210$//
:b {
   s/([A-Za-z_]+)\[([0-9])([0-9]+)\]/\1[\2], \1[\3]/
   tb
}

Not that I recommend doing it that way.

6
  • IMO, awkward is difficult.
    – cas
    Jul 4, 2016 at 9:32
  • should I go for Tcl or Perl ? Jul 4, 2016 at 9:33
  • I'd use perl but use whichever language you're most comfortable with.
    – cas
    Jul 4, 2016 at 10:14
  • BTW, in case performance is important here (which it shouldn't be unless you're processing millions of lines). The sed version here ran in 0.005 seconds with your 4-line input. My perl version ran in 0.009 seconds (perl has greater startup overhead than sed). Copying your 4 lines 500 times into a second file (total 2000 lines, 51KB), the sed script took between 0.044 seconds and 0.053 seconds to run. My perl script rain in 0.028 to 0.033 seconds. With 1M lines (25MB), sed took 20.1-20.9 seconds, while perl took 9.4-9.6 seconds. Tcl would be a lot slower than either sed or perl
    – cas
    Jul 4, 2016 at 11:12
  • @cas I'm not surprised. The sed version is inherently inefficient, as the iteration has to be implemented via regular expression matching. Jul 4, 2016 at 12:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.