⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 editfiles.pm

📁 Verilog Parser in Perl
💻 PM
字号:
# See copyright, etc in below POD section.######################################################################package Verilog::EditFiles;use Config;use IO::File;use File::Path;use Carp;use strict;use vars qw ($VERSION $Debug);########################################################################## Configuration Section$VERSION = '3.120';######################################################################## CONSTRUCTORSsub new {    my $class = shift;    my $self = {	# Options	program => "Verilog::EditFiles",	outdir => ".",	translate_synthesis => 0,	# Name of define or "1"	lint_header => undef,	celldefine => undef,	timescale_header => undef,	timescale_removal => undef,	lint_command => 'vlint --brief',	v_suffix => ".v",	verbose => 1,	# Internals	_files => {},   # Hash of module name, contains list of lines	@_,    };    $self->{verbose} = 1 if $Debug;    $self->{debug} = 1 if $Debug;    bless $self, $class;    return $self;}######################################################################sub read_and_split {    my $self = shift;    foreach my $filename (@_) {	$self->_read_split_file($filename);    }}sub _read_split_file {    my $self = shift;    my $filename = shift;    print "Reading $filename...\n" if $self->{verbose};    my $fh = IO::File->new("<$filename") or die "%Error: $! $filename\n";    (my $basename = $filename) =~ s!^.*/!!;    (my $basemod = $basename) =~ s!\.(v|inc)$!!;    my @header = "// Created by $self->{program} from $basename\n";    my @trailer = "\n";    my @lines = (@header);    my $modname;    my $ever_module;    my $commented;    while (defined(my $line = $fh->getline)) {	$line =~ s!\r!!mg;	$line =~ s![ \t]+\n$!\n!;	if ($self->{translate_synthesis}) {	    my $define = $self->{translate_synthesis};	    $define = "SYNTHESIS" if $define eq "1";	    $line =~ s!^\s*//\s*(ambit|synopsys|synthesis)\s*translate_off\s*$!`ifndef ${define}\n!;	    $line =~ s!^\s*//\s*(ambit|synopsys|synthesis)\s*translate_on\s*$!`endif //${define}\n!;	    if ($line =~ m!(ambit|synopsys|synthesis)\s*translate!) {		die "%Error: Unhandled translate comment: $line\n";	    }	}	(my $l2 = $line) =~ s!//.*$!!;	if ($l2 =~ s!.*?\*/!!) {	    $commented = 0;	}	while ($l2 =~ s!.*?/\*!!) {	    $commented = 1;	    if ($l2 =~ s!.*?\*/!!) {		$commented = 0;	    }	}	if (!$commented	    && $line =~ /^\s*(module|primitive)\s+([A-Za-z0-9_]+)/) {	    my $newmodname = $2;	    if ($modname) { # Already in a module		# Support code like this		# `ifdef x		#   module x (...)		# `else		#   module x (...)		($newmodname eq $modname)		    or die "%Error: $filename:$.: module without previous endmodule\n";		print "$basename:$.:  continue module $1\n" if $self->{debug};	    } else {		$modname = $newmodname;		$ever_module = 1;		print "$basename:$.:  module $1\n" if $self->{debug};		my @afterif;		my @oldlines = (@lines);		@lines = (@header);		# Insert our new header before any `ifdef's or `includes		my $gotifdef;		foreach my $oline (@oldlines) {		    $gotifdef = 1 if $oline =~ /`ifdef\b|`include\b/;		    if (!$gotifdef) {			push @lines, $oline;		    } else{			push @afterif, $oline;		    }		}		push @lines, $self->{include_header} if $self->{include_header};		push @lines, $self->{timescale_header} if $self->{timescale_header};		push @lines, "`celldefine\n" if $self->{celldefine};		push @lines, $self->{lint_header} if $self->{lint_header};		push @lines, @afterif;	    }	    push @lines, $line;	}	elsif (!$commented && $line =~ /^\s*end(module|primitive)\b/) {	    print "$basename:$.:  endmodule $modname\n" if $self->{debug};	    $modname or die "%Error: $filename:$.: endmodule without previous module\n";	    push @lines, $line;	    push @lines, "`endcelldefine\n" if $self->{celldefine};	    push @lines, @trailer;	    $self->{_files}{$modname}{created} = 1;	    $self->{_files}{$modname}{modname} = $modname;	    $self->{_files}{$modname}{lines} = [@lines];	    @lines = ();	    # Prep for next	    $modname = undef;	}	elsif (!$commented	    && $line =~ /^\s*\`timescale\s.*/	    && $self->{timescale_removal}) {	    # Strip existing timescale	}	elsif (!$commented	       && $line =~ /^\s*\`(end)?celldefine\b/	       && $self->{celldefine}) {	    # Strip existing celldefine, we'll add a new one	}	else {	    push @lines, $line;	}    }    $fh->close;    if (!$ever_module) {	print "$basename:1: No module, must be include file: $basemod\n" if $self->{debug};	push @lines, @trailer;	$self->{_files}{$basemod}{created} = 1;	$self->{_files}{$basemod}{modname} = $basemod;	$self->{_files}{$basemod}{lines} = [@lines];	$self->{_files}{$basemod}{is_include} = 1;    }}#######################################################################sub write_files {    my $self = shift;    mkpath($self->{outdir});    foreach my $file (sort (keys %{$self->{_files}})) {	my $fileref = $self->{_files}{$file};	next if !$fileref->{created};	$self->_write_file ($self->{outdir}."/".$fileref->{modname}.$self->{v_suffix}, $fileref);    }}sub _write_file {    my $self = shift;    my $filename = shift;    my $fileref = shift;    print "Writing $filename...\n" if $self->{verbose};    my $fh = IO::File->new(">$filename") or die "%Error: $! $filename\n";    foreach my $line (@{$fileref->{lines}}) {	print $fh $line;    }    $fh->close;}sub write_lint {    my $self = shift;    my %params = (filename => $self->{outdir}."/0LINT.sh",		  @_);    print "Writing $params{filename}...\n" if $self->{verbose};    my $fh = IO::File->new(">$params{filename}") or die "%Error: $! $params{filename}\n";    print $fh "#!/bin/bash\n";    print $fh "# Created by $self->{program}\n";    foreach my $fileref (sort {$a->{modname} cmp $b->{modname}} values %{$self->{_files}}) {	next if $fileref->{is_include};	next if $fileref->{skip_lint};	print $fh "echo \"".("*"x70),"\"\n";	print $fh "echo Lint ".$fileref->{modname},"\n";	print $fh $self->{lint_command}." \$* ".$fileref->{modname}.$self->{v_suffix},"\n";    }    $fh->close;    chmod 0777, $params{filename};}#######################################################################sub edit_file {    my $self = shift;    my %params = (filename => undef,		  write_filename => undef,		  cb => sub {},		  verbose => $self->{verbose},		  @_);    defined $params{filename} or croak "%Error: edit_file not passed filename=>,";    ref $params{cb} or croak "%Error: edit_file cb=> callback is not code,";    $params{write_filename} = $params{filename} if !defined $params{write_filename};    my $wholefile;    my $origwholefile;    {	# Read it	my $fh = IO::File->new ("<$params{filename}")	    or croak "%Error: $! $params{filename},";	local $/; undef $/;	$wholefile = <$fh>;	$origwholefile = $wholefile;	$fh->close();    }    # Edit    $wholefile = &{$params{cb}}($wholefile);    # Writeback    if ($wholefile ne $origwholefile) {	print "  $params{write_filename} (Changed)\n" if $params{verbose};	my ($dev,$ino,$mode) = stat($params{write_filename});	chmod 0777, $params{filename};	my $fh = IO::File->new (">$params{write_filename}")	    or croak "%Error: $! writing $params{write_filename},";	print $fh $wholefile;	$fh->close();	chmod $mode, $params{write_filename} if $mode;  # Preserve mode    }}#######################################################################1;__END__=pod=head1 NAMEVerilog::EditFiles - Split Verilog modules into separate files.=head1 SYNOPSISSee splitmodule command.   use Verilog::EditFiles;   my $split = EditFiles->new(outdir => "processed_rtl",				translate_synthesis => 0,				lint_header => undef,				celldefine => 1,				);   $split->read_and_split(glob("inbound_rtl/*.v"));   $split->write_files();   $split->edit_file(filename=>"foo", cb => sub { return $_[0]; });=head1 DESCRIPTIONVerilog::EditFiles provides a easy way to split library Verilog files thatcontain multiple modules into many files with one module per file.=head1 FUNCTIONS=over 4=item new (...)Create a new Verilog::EditFiles object.  Named parameters may be specified:=over 4=item celldefineIf true, add "`celldefine" before every module statement.=item lint_commandFor the write_lint method, the name of the linter to use.  Defaults to"vlint --brief".=item lint_headerIf defined, add the provided text before every module statement.  Generallyused to insert lint off pragmas.=item outdirName of the directory to write the output modules to.  Defaults to ".".=item programName of the program to add to comments.  Defaults to"Verilog::EditFiles".=item timescale_headerIf defined, add the provided text before every module statement.  Generallyset to the next needed to #include a timescale file.  Use withtimescale_removal.=item timescale_removalIf set, remove any `timescales.=item translate_synthesisIf 1, replace any synopsys translate on/offs with "`ifdef SYNTHESIS" and"`endif"s.  If set to a string, use that string instead of "SYNTHESIS".=item v_suffixThe suffix to add to convert a module name into a filename.  Defaults to".v".=item verboseIf true, print what files are being read and written.=back=item $self->read_and_split ([filenames])Read from the specified filenames.If there is no module statement in the file, assume it is a include file,and when write_files is called, place all of the file contents into theoutput.  If there is a module statement, when write_files is called placeall following output into a file named based on the module, with .v added.=item $self->write_files()Write all of the files created by read_and_split to the outdir.=item $self->write_lint([filename=>...])Create a shell script that will lint every file created by write_files.  Ifa "filename" parameter is not provided, "0LINT.sh" will be written in thedefault outdir.=item $self->edit_file(filename=>..., cb=>sub{...})Read a file, edit it with the provided callback, and save it if it haschanged.  The "filename" parameter is the filename to read.  The"write_filename" parameter is the filename to write, defaulting to the samename as the filename to read.  The "cb" parameter is a reference to acallback which takes the string of file contents and returns the string towrite back.  Often the callback will simply perform a search and replace.=back=head1 DISTRIBUTIONVerilog-Perl is part of the L<http://www.veripool.org/> free Verilog EDAsoftware tool suite.  The latest version is available from CPAN and fromL<http://www.veripool.org/verilog-perl>.Copyright 2006-2009 by Wilson Snyder.  This package is free software; youcan redistribute it and/or modify it under the terms of either the GNULesser General Public License or the Perl Artistic License.=head1 AUTHORSWilson Snyder <wsnyder@wsnyder.org>=head1 SEE ALSOL<Verilog-Perl>=cut######################################################################

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -