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

📄 vpassert

📁 Verilog Parser in Perl
💻
📖 第 1 页 / 共 4 页
字号:
#!/usr/bin/perl -w# See copyright, etc in below POD section.######################################################################require 5.005;use Getopt::Long;use IO::File;use IO::Dir;use Pod::Usage;use FindBin qw($RealBin);use File::Copy;use strict "vars";use lib 'blib/arch';use lib 'blib/lib';use lib '.';use Verilog::Parser;use Verilog::Getopt;use vars qw ($VERSION $Debug $Opt %Vpassert_Conversions	     $Vpassert_Conversions_Regexp	     %Vpassert_Chiponly_Rename	     $Opt_Vericov $Opt_Chiponly	     @Endmodule_Inserts	     $Last_Parser	     $Last_Module	     $Last_Task	     $ReqAck_Num	     $Vericov_Enabled	     $Got_Change	     @Sendout	     %Insure_Symbols	     %File_Mtime %File_Mtime_Read %File_Mtime_Read_Used	     %File_Dest	     );$VERSION = '3.120';####################################################################### configuration# Hash with key of macro to convert and value of the function to call when it occurs# Avoid having a token that is a substring of a standard function, for example#     $wr would be bad (beginning of $write).  That would slow down the parsing.%Vpassert_Conversions    = (## U versions, to avoid conflicts with SystemVerilog       '$uassert' =>		\&ins_uassert,       '$uassert_amone' =>	sub {shift; uassert_hot(0,@_); },   # atmost one hot       '$uassert_onehot' =>	sub {shift; uassert_hot(1,@_); },       '$uassert_req_ack' =>	\&ins_uassert_req_ack,       '$uassert_info' =>	\&ins_uassert_info,       '$ucheck_ilevel' =>	\&ins_ucheck_ilevel,       '$uerror' =>		\&ins_uerror,       #'$ui' =>		# Used inside ucover_foreach_clk       '$uinfo' =>		\&ins_uinfo,       '$uwarn' =>		\&ins_uwarn,       #'$uassert_clk' =>	sub {shift; my $clk=shift; my $cond=shift; umessage_clk("%%E", $cond,$clk,@_); }, # May be confusing, try without       '$uerror_clk' =>		sub {shift; umessage_clk("%%E", 0, @_); },       '$uwarn_clk' =>		sub {shift; umessage_clk("%%W", 0, @_); },       '$ucover_clk' =>		sub {shift; ucover_clk(@_); },       '$ucover_foreach_clk' =>	sub {shift; ucover_foreach_clk(@_); },       );# Any tokens appearing here will be removed with the --chiponly option# This allows v files to be given to people that don't have our PLI library, and# cah have these "true-PLI" functions to do something simpler.%Vpassert_Chiponly_Rename = ();%Vpassert_Chiponly_Rename    = (#Token	  Convert to (0=remove)       '$cmd_stop' => '$stop',       );####################################################################### main$Debug = 0;my $output_dirname = ".vpassert/";my $Opt_Quiet = 0;	# Don't blab about what files are being worked onmy $Opt_AllFiles = 0;	# Preprocess all filesmy $Opt_Date = 0;	# Check datesmy $Opt_NoPli = 0;	# Delete all pli calls$Opt_Vericov = 0;	# Add vericov on/off comments (messes up line # counts)$Opt_Chiponly = 0;	# Only chip model; apply Vpassert_Chiponly_Rename'smy $Opt_RealIntent;	# RealIntentmy $Opt_Stop = 1;	# Put $stop in error messagesmy $Opt_Verilator;	# Verilatormy $Last_ArgsDiffer;	# Last run's Opt_* mismatchmy $Opt_Minimum;	# Include `__message_minimummy @Opt_Exclude;my $Opt_Timeformat_Units = undef;my $Opt_Timeformat_Precision = 0;my $Opt_Line;my $Total_Files = 0;my @files = ();my @instance_tests_list = ();my $Prog_Mtime = 0;	# Time program last changed, so we bag cache on change(-r "$RealBin/vpassert") or die "%Error: Where'd the vpassert source code go?";$Prog_Mtime = (stat("$RealBin/vpassert"))[9];autoflush STDOUT 1;$Opt = new Verilog::Getopt();@ARGV = $Opt->parameter(@ARGV);	# Strip -y, +incdir+, etcif (! GetOptions (		  "-o=s"	=> \$output_dirname,		  "allfiles!"	=> \$Opt_AllFiles,		  "chiponly!"	=> \$Opt_Chiponly,	# For makeesim only		  "date!"	=> \$Opt_Date,		  "debug"	=> \&debug,		  "exclude=s"	=> sub {shift; push @Opt_Exclude, shift;},		  "help"	=> \&usage,		  "language=s"	=> sub { shift; Verilog::Language::language_standard(shift); },	  	  "line!"	=> \$Opt_Line,		  "minimum!"	=> \$Opt_Minimum,		  "nopli!"	=> \$Opt_NoPli,		  "realintent!"	=> \$Opt_RealIntent,		  "quiet!"	=> \$Opt_Quiet,		  "stop!"	=> \$Opt_Stop,		  "timeformat-precision=s" => \$Opt_Timeformat_Precision,		  "timeformat-units=s"	=> \$Opt_Timeformat_Units,		  "vericov!"	=> \$Opt_Vericov,		  "verilator!"	=> \$Opt_Verilator,		  "version"	=> sub { print "Version $VERSION\n"; exit(0); },		  "<>"		=> \&parameter,		  )) {    die "%Error: Bad usage, try 'vpassert --help'\n";}sub _switch_line {    # If any of these flags change, we must regenerate output    my $sw = "";    $sw .= " --chiponly" if $Opt_Chiponly;    $sw .= " --line" if $Opt_Line;    $sw .= " --minimum=$Opt_Minimum" if defined $Opt_Minimum;    $sw .= " --nopli" if $Opt_NoPli;    $sw .= " --realintent" if $Opt_RealIntent;    $sw .= " --stop" if $Opt_Stop;    $sw .= " --vericov" if $Opt_Vericov;    $sw .= " --verilator" if $Opt_Verilator;    return $sw;}if (!defined $Opt_Line) {    $Opt_Line = $Opt_Verilator || Verilog::Language::is_compdirect("`line"); # uses language_standard()}push @files, ($Opt->incdir(), $Opt->library(), $Opt->module_dir());@files = $Opt->remove_duplicates(@files);(@files) or die "%Error: No directories or files specified for processing, try --help\n";if ($#files >= 0) {    (!-f $output_dirname) or die "%Error: $output_dirname already exists as a file, should be a directory.\n";    vpassert_recursive_prelude($output_dirname);  file:    foreach my $file (@files) {	next if $file eq $output_dirname;	foreach my $exclude (@Opt_Exclude) {	    next file if $file =~ /^$exclude/;	}	vpassert_recursive ($file, $output_dirname);    }    vpassert_recursive_postlude($output_dirname);}print "\tVPASSERT generated $Total_Files new file(s)\n";exit (0);######################################################################sub usage {    print "Version $VERSION\n";    print "\nThe following tokens are converted:\n";    foreach my $tok (keys %Vpassert_Conversions ) {	print "\tToken $tok\n";    }    print "\n";    pod2usage(-verbose=>2, -exitval => 2);    exit (1);}sub debug {    $Debug = 1;    $Verilog::Parser::Debug = 1;    $Opt_Quiet = 0;}sub parameter {    my $param = shift;    (-r $param) or die "%Error: Can't open $param";    push @files, $param;}##################################################################################################################################################################################################################################################################################################################################################################################################################################### Functions that transform the tokens# Note -I is specially detected belowsub ins_uinfo   { shift; sendout( message (get_lineinfo(), 1, "-I",  1, "", @_)); }sub ins_uwarn   { shift; sendout( message (get_lineinfo(), 1, "%%W", 1, "", @_)); }sub ins_uerror  { shift; sendout( message (get_lineinfo(), 1, "%%E", 1, "", @_)); }sub ins_uassert {    shift;    my $cond = shift;    my @params = @_;    sendout( message (get_lineinfo(), 1, "%%E", $cond, "", 0, @params));}sub ins_uassert_info {    shift;    my $cond = shift;    my @params = @_;    # Lower case -i indicates it's a assert vs. a info    sendout( message (get_lineinfo(), 1, "-i", $cond, "", 0, @params));}sub check_signame {    my $sig = shift;    return undef if !$sig;    return $1 if ($sig =~ /^\s*([a-zA-Z_\$][a-z0-9A-Z_\$]*)\s*$/);    return undef;}sub ins_uassert_req_ack {    shift;    my @params = @_;    # Check parameters    my $req = check_signame(shift @params);    my $ack = check_signame(shift @params);    ($req && $ack) or die "%Error: ".$Last_Parser->fileline.": Format of \$uassert_req_ack boggled.\n";    @params = map {	my $ipar = $_;	$ipar = check_signame($ipar);	($ipar) or die "%Error: ".$Last_Parser->fileline.": Parameter $ipar isn't a signal\n";	$ipar;    } @params;    # Form new variables    $ReqAck_Num or die "%Error: ".$Last_Parser->fileline.": \$uassert_req_ack can't find module statement\n";    my $busy = "_assertreqack${ReqAck_Num}_busy_r";    $Insure_Symbols{$Last_Module}{$busy} = ['reg', 0];	# Make this symbol exist if doesn't    # We make a parity across all data signals, as we don't have the width    # of the original signal, and I'm too lazy to add code to find it out.    my @dholds = ();    for (my $n=0; $n<=$#params; $n++) {	my $dhold = "_assertreqack${ReqAck_Num}_data${n}_r";	push @dholds, $dhold;	$Insure_Symbols{$Last_Module}{$dhold} = ['reg', 0];    }    # Output it    sendout(message_header());    sendout("if (`__message_on) begin ");  # Need to wait till after reset, so FSM doesn't start    sendout("casez({($busy),($req),($ack)}) ");    sendout(" 3'b000: ;");    sendout(" 3'b010: $busy<=1'b1;");    sendout(" 3'b011: "); ins_uerror(0,"\"Unexpected $req coincident with $ack\\n\"");    sendout(" 3'b001: "); ins_uerror(0,"\"Unexpected $ack with no request pending\\n\"");    sendout(" 3'b100: ;");    sendout(" 3'b11?: "); ins_uerror(0,"\"Unexpected $req with request already pending\\n\"");    sendout(" 3'b101: $busy<=1'b0;");    sendout("endcase ");    if ($#params>=0) {	sendout(" if (($req)||($busy)) begin");	sendout(" if (($busy)) begin");	for (my $n=0; $n<=$#params; $n++) {	    sendout(" if ($dholds[$n] != ^($params[$n])) ");	    ins_uerror(0,"\"Unexpected transition of $params[$n] during transaction\\n\"");	}	sendout(" end");	# Save state of signals	for (my $n=0; $n<=$#params; $n++) {	    sendout(" $dholds[$n] <= ^($params[$n]);");	}	sendout(" end ");    }    sendout(" end ");    sendout(message_trailer());    $ReqAck_Num++;}sub ins_ucheck_ilevel {    shift; # $ucheck_ilevel    my $level = shift;    my $chk = "/*vpassert*/if ((`__message_on) && ";    $chk .= ' && (`__message_minimum >= (' . $level . '))' if $Opt_Minimum;    $chk = $chk . '(__message >= (' . $level . ')))';    sendout ($chk);}sub uassert_hot {    my $check_nohot = shift;    my @params = @_;    my $text = "";    my ($elem,$i,$ptemp,$plist,$pnone);    my $len = 0;    my @cl = ();    while ($elem = shift @params){	$elem =~ s/^\s*//;	if ($elem =~ /^\"/){   # beginning quote	    $elem =~ s/\"//g;	    $text .= $elem;	    last;	}else{	    foreach my $subel (split ',', $elem) {		$len = $len + bitwidth($subel);	    }	    push @cl, $elem;	};    }    # We use === so that x's will properly cause error messages    my $vec = "({".join(",",@cl)."})";    sendout("if (($vec & ($vec - ${len}'b1)) !== ${len}'b0 && `__message_on) ");    ins_uerror(0,"\"MULTIPLE ACTIVE %b --> $text\\n\"",$vec);    if ($check_nohot==1){	sendout("if ($vec === ${len}'b0 && `__message_on) ");	ins_uerror(0,"\"NONE ACTIVE %b --> $text\\n\"",$vec);    }}sub umessage_clk {    my $char = shift;    my $cond = shift;    my $clk = shift;    my @params = @_;    $params[0] = convert_concat_string($params[0]);    ($params[0] =~ /^\s*\"/)	or die "%Error: ".$Last_Parser->fileline.": Non-string \$message second argument: $params[0]\n";    $ReqAck_Num or die "%Error: ".$Last_Parser->fileline.": \$uassert_req_ack can't find module statement\n";    my $sig = "_umessageclk${ReqAck_Num}";    $Insure_Symbols{$Last_Module}{$sig} = ['reg', 0];	# Make this symbol exist if doesn't    $ReqAck_Num++;    if ($cond eq '0') {	sendout("/*vpassert*/$sig=1'b1;/*vpassert*/");    } else {	sendout("/*vpassert*/$sig=!($cond);/*vpassert*/");    }    _insert_always_begin('assert', "/*vpassert*/ $sig=1'b0; /*vpassert*/");    my $bot = (" always @ (posedge $clk) if ($sig) "	       .message (get_lineinfo(), 1, $char, 1, "", @_)	       ." ");    push @Endmodule_Inserts, $bot;}sub ucover_foreach_clk {    my $clk = shift;    my $label = shift;    my $range = shift;    my $expr = shift;    $#_==-1	or die "%Error: ".$Last_Parser->fileline.": Extra arguments to \$ucover_foreach_clk: $_[0]\n";    # We require quotes around the label so synthesis tools won't gripe if not wrapping in vpassert    # (Otherwise it would look like a system call with a variable of the name of the label.)    ($label =~ s/^\s*\"([a-zA-Z][a-zA-Z0-9_]+)\"\s*$/$1/)	or die "%Error: ".$Last_Parser->fileline.": Non-string label \$ucover_clk second argument: $label\n";    ($range =~ s/^\s*\"\s*(\d[0-9,:]+)\s*\"\s*$/$1/)	or die "%Error: ".$Last_Parser->fileline.": Can't parse msb:lsb in \$ucover_foreach_clk: $range\n";    my @values = _convert_foreach_comma($range);

⌨️ 快捷键说明

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