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

if a file name soc.v (contents as following), I want to using "module xxx/endmodule" to split it to 3 files (ck_soc.v ck_misc.v ck_analog.v) , how to do ? thanks!!
module soc (PAD_TEST , VDIG_ON , GNDD_ON , VPP_EF , PAD_BOND_OPT ); inout [31:0] PAD_TEST ; input VDIG_ON ; input GNDD_ON ; inout VPP_EF ; inout [5:0] PAD_BOND_OPT ; endmodule module analog_atop_wrapper (PAD_VDDTX , PAD_VREFADC , PAD_VSSRF , DPAD_GSUB_XTAL24M , DPAD_GSUB_RX ); inout PAD_VDDTX ; inout PAD_VREFADC ; inout PAD_VSSRF ; inout DPAD_GSUB_XTAL24M ; inout DPAD_GSUB_RX ; endmodule module misc_atop_wrapper (VDIG , VRTC , AVDD , EBUS , IOGND , VDIG_ON +); inout VDIG ; inout VRTC ; inout AVDD ; inout EBUS ; inout IOGND ; input VDIG_ON ; endmodule

Replies are listed 'Best First'.
Re: how to split file with some pattern
by Discipulus (Canon) on Jan 23, 2015 at 08:14 UTC
    Hello, you asked the wrong question: if you split your file using "module xxx/endmodule" you end up with two empty lines.
    What you really want is to grab everything between two markers to go in separates files. I underline this because the wrong question preclude you to obtain good answers.

    In the case you describe you'll find very useful the flip-flop operator, a not well known operator, very useful insetad, described in the docs

    #!/usr/bin/perl use strict; use warnings; use Data::Dumper; my @files; my $file_index=0; while (<DATA>) { if ($_ =~ /^module\s+/ .. /endmodule$/){ $files[$file_index].=$_; } else {++$file_index;} } print scalar @files," elements in \@files:\n",Dumper (\@files); __DATA__ module soc (PAD_TEST , VDIG_ON , GNDD_ON , VPP_EF , PAD_BOND_OPT ); inout [31:0] PAD_TEST ; input VDIG_ON ; input GNDD_ON ; inout VPP_EF ; inout [5:0] PAD_BOND_OPT ; endmodule module analog_atop_wrapper (PAD_VDDTX , PAD_VREFADC , PAD_VSSRF , DPAD_GSUB_XTAL24M , DPAD_GSUB_RX ); inout PAD_VDDTX ; inout PAD_VREFADC ; inout PAD_VSSRF ; inout DPAD_GSUB_XTAL24M ; inout DPAD_GSUB_RX ; endmodule module misc_atop_wrapper (VDIG , VRTC , AVDD , EBUS , IOGND , VDIG_ON +); inout VDIG ; inout VRTC ; inout AVDD ; inout EBUS ; inout IOGND ; input VDIG_ON ; endmodule


    HtH
    L*
    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: how to split file with some pattern
by blindluke (Hermit) on Jan 23, 2015 at 08:21 UTC

    It's a shame that you did not tell us what you already have tried, and what went wrong with your attempt. You are also missing some important information: how are the output files supposed to look? Should they contain the delimiter lines? Or should they contain everything, including module and endmodule?

    Since the text blocks seem not to contain any blank lines, here is a very lazy way to solve the problem you are having.

    #!/usr/bin/perl use warnings; use strict; use Data::Dumper; my $file = 'soc.v'; open(my $fh, "<", $file) or die "Cannot open the file!"; my @data; $/ = ""; while (my $paragraph = <$fh>) { $paragraph =~ m/^\s*module\s*([A-Za-z]+)/; push @data, { filename => $1, content => $paragraph }; } #use Data::Dumper; print Dumper \@data; for my $outfile (@data) { open(my $out, ">", $outfile->{filename}) or die "Cannot open the f +ile!"; print $out $outfile->{content}; }

    This solution uses the "paragraph mode" - this line: $/ = ""; makes sure that the iterating over the contents of the file is done not by line, as it usually is, but by whole paragraphs. If you uncomment the Data::Dumper line, you will see that the data from your input file is parsed into an array of hash references, in a way that gives you the information about the contents of the output file and its name.

    Good luck with your problem.

    - Luke

      1. sorry , I should say it more detail. if a blank line in module/endmodule the program you write will stop to run , that is not what I want. please ignore the blank line and let the program continue run until see "endmodule"

      2. yes , I hope text in module/endmodule to a new file include module/endmodule.

      Thanks !!

        Good. Now that you have your requirements figured out, try to combine elements of my solution with the suggestions provided by this reply by Discipulus. In particular, ignore the "paragraph mode", start with the while loop suggested by Discipulus, expand the pattern he provided by capturing the desired file name (look at this regexp in my reply: m/^\s*module\s*([A-Za-z]+)/), and finish with writing to files, using either the approach I have show or the one suggested by vinoth.ree.

        Try writing your script, and if you encounter any problems, post your code and we will do our best to help you improve it.

        - Luke

        you have the solution in my first reply: you just need to fire @files elemnts in separate files..
        L*
        There are no rules, there are no thumbs..
        Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: how to split file with some pattern
by vinoth.ree (Monsignor) on Jan 23, 2015 at 08:21 UTC

    Hi,

    If you have blank line as delimiter in the file you can use below code, Changing $/ to the empty string will cause the perl to read the input as 'paragraph mode', where the input record separator is one or more blank lines.

    #!/usr/bin/perl use strict; use warnings; open ($soc, '>', "ck_soc.v") or die "$!"; open ($misc, '>', "ck_misc.v") or die "$!"; open ($analog, '>', "ck_analog.v") or die "$!"; my @data; { local $/ = ''; @data = <DATA>; } my $line; foreach $line (@data) { if ($line =~/soc/) { print $soc $line; } elsif($line =~/misc/) { print $misc $line; } elsif($line=~/analog/) { print $analog $line; } } close $soc; close $misc close $analog; __DATA__ module soc (PAD_TEST , VDIG_ON , GNDD_ON , VPP_EF , PAD_BOND_OPT ); inout [31:0] PAD_TEST ; input VDIG_ON ; input GNDD_ON ; inout VPP_EF ; inout [5:0] PAD_BOND_OPT ; endmodule module analog_atop_wrapper (PAD_VDDTX , PAD_VREFADC , PAD_VSSRF , DPAD_GSUB_XTAL24M , DPAD_GSUB_RX ); inout PAD_VDDTX ; inout PAD_VREFADC ; inout PAD_VSSRF ; inout DPAD_GSUB_XTAL24M ; inout DPAD_GSUB_RX ; endmodule module misc_atop_wrapper (VDIG , VRTC , AVDD , EBUS , IOGND , VDIG_ON +); inout VDIG ; inout VRTC ; inout AVDD ; inout EBUS ; inout IOGND ; input VDIG_ON ; endmodule

    There can be more efficient way to do this

    As I currently do not have access to perl, not tested this code.


    All is well
Re: how to split file with some pattern (Verilog)
by toolic (Bishop) on Jan 23, 2015 at 14:32 UTC
    If you have anything more complex than that, you should use a proper Verilog parser: Verilog-Perl.

    However, given your simple input, this script I created 13 years ago should do the trick. It also supports SystemVerilog classes, and it warns about some compiler directives:

    =head1 NAME B<hdl_splitlib> - Split up a single Verilog library file into several +files =head1 SYNOPSIS hdl_splitlib file ... =head1 DESCRIPTION Split up a single Verilog library file into several files. Each outpu +t file will contain a single C<module> or C<class>. Input is a file (or files). Output is written to the current directory (several files). Some warning messages may be sent to STDOUT. Known limitations: - `endcelldefine or `undef compiler directives may follow endmodul +e - Those pesky `define macros!! - module/class definitions which are commented out Example: hdl_splitlib lib.v =cut use warnings FATAL => 'all'; use strict; my $directives_found = 0; my $out = 'temp.v'; my $fh; my $modname; open $fh, '>', $out; while (<>) { print $fh $_; if (/^\s*end(?:module|class)\b/) { close $fh; rename $out, "$modname.v"; open $fh, '>', $out; } elsif (/^\s*(?:module|class)\s+(\w+)/) { $modname = $1; } if (/`(define|celldefine|undef)/) { # ` $directives_found = 1; print; } } if ($directives_found) { print "\nWarning. The input file may contain problematic compiler +"; print " directives (define, undef, celldefine).\n\n"; } unless (-z $out) { print "\nWarning. All lines after the last 'endmodule' "; print "line in the input file have been deleted. These "; print "should have only been comments.\n\n"; } unlink $out;
      thanks toolic , using your codes can exactly split the verilog code into 3 files,many thanks!
      Hi toolic, could I ask a verilog:perl module usage question, how I can use the script to extract all pin in analog_atop instance (as following codes) to analog_atop_io array?
      analog_atop u_analog_atop (.PAD_VDDA ( PAD_VDDA ) , .DPAD_VSSA ( DPAD +_VSSA ) , .PAD_VREFADC ( PAD_VREFADC ) , .PAD_ADGPIO_4 ( PAD_ADGPIO_4 ) , .PAD_ADGPIO_7 ( PAD_ADGPIO_7 ) , .PAD_ADGPIO_5 ( PAD_ADGPIO_5 ) , .DPAD_VSS_ACMP ( DPAD_VSS_ACMP ) , .DPAD_VSS_PM ( DPAD_VSS_PM ) , .PAD_VDDADDAC ( PAD_VDDADDAC ) , .PAD_VDDCLK ( PAD_VDDCLK ) , .DPAD_VSS_XTAL24M ( DPAD_VSS_XTAL24M ) , .DVSS ( GNDD_ON ) , .DVDD12 ( VDIG_ON ) , .LNA_EN ( n_IP_protect_576 ) , .PAD_XO ( P +AD_XO ) , .LNA1_CURSET ( {n_IP_protect_573 , n_IP_protect_572 } ) , .FILT_MUX_IN_HZ ( n_IP_protect_446 ) , .FILT_MUX_IN_IQSWAP ( n_IP_protect_447 ) , .CTL_SYNTH_COARSE_CAL_EN ( n_IP_protect_312 ) , .PAD_ADGPIO_6 ( PAD_ADGPIO_6 ) , .SEL_RXMIX_LOBIAS ( {n_IP_protect_864 , n_IP_protect_863 } ) , .CTL_CXI_XO24M ( {n662 , n447 , n449 , n2478 } ) , .CTL_SYNTH_EN ( n_IP_protect_313 ) , .CTL_CXO_XO24M ( {n2705 , n439 , n441 , n443 } ) , .CTL_BBPLL_EN + ( n2303 ) , .CTL_BBPLL_DIV_RXADC ( {n540 , n1230 } ) , .CSR_BBPLL_CORE_GC ( {n516 , n403 , n1224 , n_IP_protect_104 , n +517 , n_IP_protect_102 , n_IP_protect_101 , n_IP_protect_100 } ) , .CSR_BBPLL_TEST_GC ( {n_IP_protect_124 , n416 , n_IP_protect_122 + , n509 , n417 , n511 , n_IP_protect_117 , n1213 , n512 , n_IP_protect_114, n_I +P_protect_113 , n513 , n406 , n514 , n_IP_protect_131 , n531 , n532 , n533 , n_IP_protect_127 , n398 , n409 , n410 , n515 , n_IP_protect_108 } ) );