On Mon, Jan 14, 2002 at 07:32:15PM -0500, Aaron D. Marasco wrote:
> OK, here is a problem I ran into (well, created) at work. I would like to 
> be able to paste an as-short-as-possible perl script at the end of a VHDL 
> file so that people can run it to change the interfaces (don't worry if you 
> don't get this).
>
> Anyway, here is the data going in (VHDL comments outlining what the 
> interface does):
> 
> -- SUN:
> --   S_RSTb      out
> --   S_INTb      in
> -- CMX INTERFACE:
> --   CMX_CSb     in
> --   CMX_D       inout     7
> --   CMX_A       inout     7
> 
> Here is the desired output VHDL:
> 
> --== SUN ==--
> S_RSTb  : out std_logic;
> S_INTb  : in std_logic;
> --== CMX INTERFACE ==--
> CMX_CSb : in std_logic;
> CMX_D   : inout std_logic_vector(7 downto 0);
> CMX_A   : inout std_logic_vector(7 downto 0);
> 
> The colons are aligned vertically with the length of the longest signal 
> name plus a space.
> 
> Please explain if you are doing anything "complicated" so we can all learn. 
> ;)
> 
> The double hyphen in front of the incoming text is optional and could have 
> spaces on either side of it. The spaces between "fields" is arbitrary (but 
> never tabs). The signal fields always have at least one space on the left, 
> and the comments always have the colon at the end (makes script a lot 
> simpler). The overall length of the script is the most important, speed is 
> no concern. Lines are limited to 78 characters too. :(
> 
> Here is my attempt, at 7 lines (need to count #! line)...
> 
> #!/cygdrive/r/perl/bin/perl -n
> if(/[\s-]*([^:]*)\s*:/){$a[$.]="--== $1 ==--\n";next}
> ($a[$.],$b[$.],$c[$.])=/\s+(\w+)\s*(\w*)\s*(\d*)/;
> $l=length$1;$m=$l if($l>$m);
> END{foreach$i(1..$.){$r=$a[$i];print$r;if($r!~/=/){
> print" "x($m-length$r)." : $b[$i] std_logic";
> print (($c[$i]!='')?"_vector($c[$i] downto 0);\n":"\n")}}}

-- SUN:
--   S_RSTb      out
--   S_INTb      in
-- CMX INTERFACE:
--   CMX_CSb     in
--   CMX_D       inout     7
--   CMX_A       inout     7
SUN:
  S_RSTb      out
  S_INTb      in
CMX INTERFACE:
  CMX_CSb     in
  CMX_D       inout     7
  CMX_A       inout     7

#!/usr/bin/perl  # run this file with perl -x

seek(DATA,0,0);
foreach (<DATA>) {
    last if /^#!/;
    /(\w+):/ && do { print "--== $1 ==--\n"; next; };
    /(\w+)[ ]+ (\w+)(?:[ ]+(\d+))?/ && 
        do { $sl = length $3 ? "_vector($3 downto 0);" : ';';
             printf "%-8s: %s std_logic%s\n", $1, $2, $sl;  next; };
}

__DATA__

This is literally the whole script, including the VHDL.  Run with perl
-x (the "ignore everything before the first #! line" switch) and it'll
parse out the VHDL above it.  The only real tricks are -x and the
seek(DATA,0,0) trick.  The DATA filehandle is for the current file
(you have to have the __DATA__ there), so you just seek to the top
(ie. the VHDL) and start reading.  The for loop ends itself when it
sees a #!.

I made sure to use [ ]+ in favor of \s+ since you mentioned tabs are
not allowed.

I cheated a little using printf instead of actually calculating the
length of the longest first field.


And here's a compressed version.

-- SUN:
--   S_RSTb      out
--   S_INTb      in
-- CMX INTERFACE:
--   CMX_CSb     in
--   CMX_D       inout     7
--   CMX_A       inout     7
SUN:
  S_RSTb      out
  S_INTb      in
CMX INTERFACE:
  CMX_CSb     in
  CMX_D       inout     7
  CMX_A       inout     7

#!/usr/bin/perl  # run this file with perl -x
seek(DATA,0,0);for(<DATA>){/^#!/&&last;/(\w+):/&&print("--== $1 ==--\n")
&&next;/(\w+)[ ]+ (\w+)(?:[ ]+(\d+))?/&&($sl = length $3 ? "_vector($3 ".
"downto 0);":';')&&printf("%-8s: %s std_logic%s\n",$1,$2,$sl)&&next}
__DATA__


-- 

Michael G. Schwern   <[EMAIL PROTECTED]>    http://www.pobox.com/~schwern/
Perl Quality Assurance      <[EMAIL PROTECTED]>         Kwalitee Is Job One
A tickle of paste
Teases down my sweaty thigh
Oh, plug it again!
        -- ignatz

Reply via email to