diff --git a/BUILD.bazel b/BUILD.bazel new file mode 100644 index 0000000..931afa3 --- /dev/null +++ b/BUILD.bazel @@ -0,0 +1,7 @@ +sh_binary( + name = "verilogpp_bin", + srcs = ["verilogpp"], + visibility = ["//visibility:public"], +) + +exports_files(["verilogpp.rc"]) diff --git a/README.md b/README.md index 5e5ff71..ef077a8 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,14 @@ versions of this tool, and new code should avoid using them. If possible, consider configuring your editor to "fold" all code between the PPSTART and PPSTOP comments out of your visual field. -In VIM, you could add the following to your .vimrc file: +In VIM, the simplest way to fold generated code out of your way +is with the following commands, suitable for adding to your +`.vimrc` file: + + set foldmarker=PPSTART,PPSTOP + set foldmethod=marker + +Or, a more complicated way: autocmd BufWinEnter,Syntax *.v,*.sv syn region ppoutput \ start="\/\*PPSTART\*" end="\*PPSTOP\*" fold contains=TOP keepend diff --git a/WORKSPACE b/WORKSPACE new file mode 100644 index 0000000..e69de29 diff --git a/verilogpp b/verilogpp index fd7c615..07c24a9 100755 --- a/verilogpp +++ b/verilogpp @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/perl # A verilog preprocessor. # Copyright 2017 Google Inc. # Author: jonmayer@google.com (Jonathan Mayer) @@ -93,7 +93,9 @@ EOT use strict; use warnings; use 5.8.0; +use Data::Dumper qw(Dumper); use English qw( -no_match_vars ); +use File::Basename; use File::Spec; use FileHandle; use Getopt::Long; @@ -115,7 +117,8 @@ our $verbose = 0; our $quieter = 0; our $trim = 0; our $recursive = 0; -our @INCDIR = ( $ENV{'PWD'} ); +our $PWD = $ENV{'PWD'} || `pwd`; +our @INCDIR = ( $PWD ); our $configfile = ""; our $explicit_outputfile = ""; our $check = 0; # just check if changes are needed (dry run) @@ -135,6 +138,7 @@ $config{"disable_always_ff"} = 0; # disable always_ff in systemverilog code. $config{"register_delay"} = "#1ns"; $config{"autonet_allwires"} = 0; $config{"prettyprint"} = 0; # Set to enable "pretty" generated code +$config{"style"} = "default"; $config{"fsm_state_suffix"} = ""; # String appended to state signals $config{"enable_footer"} = 1; # writes a timestamp comment at end of each file $config{"depend_mode"} = 0; # generate a dependency comment instead of `include. @@ -142,6 +146,9 @@ $config{"generated_code_marker"} = ""; # extra indicator for generated text $config{"manifest"} = ""; # if set, update a manifest file when files are # reprocessed. $config{"enum_states"} = 1; # enumerate states by default +$config{"compact_ports"} = 0; # use ".clk" instead of .clk(clk)" +$config{"omit_empty"} = 0; # if enables, will omit empty macro expansions. +$config{"subpaths"} = ["."]; # search these subpaths beneath each INCDIR path for files. # global md5sum registry our $manifest = undef; @@ -152,6 +159,70 @@ our %PROCESSED = (); # global constants our $k_condition_list = "**| CONDITION LIST |**"; +sub dump_stack { + my $i = 0; + my ($package, $filename, $line, $subroutine, $hasargs, $wantarray, $evaltext, + $is_require, $hints, $bitmask, $hinthash); + + print STDERR "Stack trace:\n"; + while (($package, $filename, $line, $subroutine, $hasargs, $wantarray, $evaltext, + $is_require, $hints, $bitmask, $hinthash) = caller($i)) { + print STDERR "# ${i}: ${filename}:${line} ${subroutine}\n"; + $i++; + } +} + +sub log_debug { + if ($main::verbose > 0) { + print STDERR "DEBUG: @_\n"; + } +} + +# Search INCDIR for a file. +sub locate_file { + my $filename = shift; + if (!defined($filename)) { + die("locate_file() called with undefined filename argument"); + } + if (-e $filename) { + return $filename; + } + # check provided paths first, if any: + foreach my $dir (@_) { + if (!defined($dir)) { + # GetOptions is leaving an undefined value in this list for some reason? + next; + } + foreach my $subdir (@{$main::config{"subpaths"}}) { + my $path = File::Spec->catfile($dir, $subdir, $filename); + if (-e $path) { + return $path; + } + if (-e "${path}pp") { + return $path; + } + } + } + # check INCDIR paths: + foreach my $dir (@main::INCDIR) { + if (!defined($dir)) { + # GetOptions is leaving an undefined value in this list for some reason? + next; + } + foreach my $subdir (@{$main::config{"subpaths"}}) { + my $path = File::Spec->catfile($dir, $subdir, $filename); + if (-e $path) { + return $path; + } + if (-e "${path}pp") { + return $path; + } + } + } + warn("Could not find \"$filename\" in @main::INCDIR"); + return $filename; +} + # helper functions to return the proper verilog or systemverilog # constructs sub always_comb() { @@ -167,6 +238,14 @@ sub case() { return $config{"systemverilog"} ? "unique case" : "case"; } +sub expand_template ($\%) { + my $template = shift; + my %ctx = %{shift()}; + my $output = $template; + $output =~ s/\{\{\s*([a-zA-Z0-9_]+)\s*\}\}/$ctx{$1}/g; + return $output; +} + # returns a correctly constructed, inferred register. sub register { my (%options) = @_; @@ -177,6 +256,7 @@ sub register { my $clk = $options{"CLOCK"} || $config{"clock"}; my $reset_n =$options{"RESET_N"} || $config{"reset_n"}; my $delay = $options{"DELAY"} || $config{"register_delay"}; + my $template = $config{"reg_template"} || ""; my $ifclause = ""; if ($cond ne "1'b1") { @@ -186,6 +266,22 @@ sub register { if ($delay eq "none") { $delay = ""; } else { $delay =~ s/\s*$/ /; } + my %ctx = { + ALWAYS_FF => always_ff(), + CLK => $clk, + SRESET => $config{"synchronous_reset"}, + RESET_N => $reset_n, + REG => $reg, + NEXT => $next, + DELAY => $delay, + INITIAL => $initial, + IFCLAUSE => $ifclause, + LE => $cond}; + + if ($template ne "") { + return expand_template($template, %ctx); + } + return join("", always_ff(), " @(posedge ${clk}", @@ -460,6 +556,12 @@ sub AsNet($$$) { $unpacked->[$i] =~ s/\b${key}\b/$mapper->{PARAMS}->{$key}/g; } } + foreach my $key (keys %{$mapper->{LOCALPARAMS}}) { + $width =~ s/\b${key}\b/$mapper->{LOCALPARAMS}->{$key}/g; + for (my $i = 0; $i <= $#{$unpacked}; $i++) { + $unpacked->[$i] =~ s/\b${key}\b/$mapper->{LOCALPARAMS}->{$key}/g; + } + } my $n = new Net($mapped_signal, $width); if ($#{$unpacked} >= 0) { $n->set_unpacked($unpacked); @@ -536,7 +638,8 @@ sub init { $self->{ports} = {}; $self->{port_order} = []; $self->{filename} = ''; - $self->{assigns} = {}; # tracks assign statements + $self->{assigns} = {}; # tracks symbols assigned to in assign statements + $self->{assign_from} = {}; # tracks symbols used in assign expressions $self->{structs} = {}; } @@ -588,7 +691,7 @@ sub extract_module_interface($$) { my ($module, $parameters, $interface, $code); # try to match "module foo (a, b, c);" if ($verilog =~ m/^\s*module\s+ - (\S+?)\s* + ([a-zA-Z0-9_]+?)\s* \(\s*(.*?)\s*\)\s*;\s* (.*?) endmodule/xmso) { @@ -600,7 +703,7 @@ sub extract_module_interface($$) { # try to match "module foo #(a, b, c) (d, e, f);" elsif ($verilog =~ m/ ^\s*module\s+ - (\S+?)\s+ + ([a-zA-Z0-9_]+?)\s* \#\s*\(\s*(.*?)\s*\)\s* \(\s*(.*?)\s*\)\s*;\s* (.*?) @@ -613,7 +716,7 @@ sub extract_module_interface($$) { # try to match "module foo;" elsif ($verilog =~ m/ ^\s*module\s+ - (\S+?) + ([a-zA-Z0-9_]+?) \s*;\s* (.*?) endmodule/xmso) { @@ -694,6 +797,10 @@ sub parse_interface($$) { $width = ''; shift(@tokens); } + if ($tokens[0] =~ m/^([a-zA-Z0-9_]+)\.([a-zA-Z0-9_]+)$/) { + $tokens[0] = $1; + $io = "modport $1.$2"; # a special kind of inout + } my $unpacked = []; while ($tokens[$#tokens] =~ m/^\[.*\]$/) { unshift(@$unpacked, pop(@tokens)); @@ -714,21 +821,30 @@ sub parse_interface($$) { } # older verilog allows inputs and outputs to be declared in the body of -# the module. We scan for them here. +# the module. We scan for them here. This parser is a bit less featureful +# than the verilog-2001 parser. sub parse_body_for_extra_interfaces($$) { my $self = shift; my $code = shift; - # remove all clocking blocks - $code =~ s/^clocking .*?^endclocking//gmso; + # remove easy to remove blocks + $code =~ s/^clocking .*?^endclocking(?:\s*:\s*\S+)?//gmso; + $code =~ s/^function .*?^endfunction(?:\s*:\s*\S+)?//gmso; + $code =~ s/^task .*?^endtask(?:\s*:\s*\S+)?//gmso; # scan for some old-style declarations, too: my @blocks = split(m/\s*;\s*/s, $code); # scan for assign statements foreach my $block (@blocks) { - if ($block =~ m/^\s*assign\s+(\S+)\s*=/m) { - $self->{assigns}->{$1} = 1; + if ($block =~ m/^\s*assign\s+(\S+)\s*=(.*)/mso) { + my $to = $1; + my $from = $2; + $to =~ s/\[.*?\]//g; + $self->{assigns}->{$to} = 1; + foreach my $symbol ($from =~ m/([A-Za-z0-9_]+)/g) { + $self->{assign_from}->{$symbol} = 1; + } } } @@ -761,6 +877,7 @@ sub parse_body_for_extra_interfaces($$) { sub read_prototype { my $self = shift; my $filename = shift; + $filename = main::locate_file($filename, @_); $self->{'filename'} = $filename; my $fh = new FileHandle("<$filename") or return undef; @@ -1145,7 +1262,7 @@ sub init { $self->{width} = shift; $self->{unpacked} = undef; # Count the ports this net is connected to: - $self->{count} = { 'input' => 0, 'output' => 0, 'inout' => 0 }; + $self->{count} = { 'input' => 0, 'output' => 0, 'inout' => 0, 'modport' => 0 }; } sub set_unpacked($$) { @@ -1163,9 +1280,19 @@ sub width { return $self->{width}; } +sub MakeCompatibleWith($$) { + my $self = shift; + my $other_net = shift; + if (length($other_net->{width}) > length($self->{width})) { + $self->{width} = $other_net->{width}; + } + if ($#{$other_net->{unpacked}} > $#{$self->{unpacked}}) { $self->{unpacked} = $other_net->{unpacked}; } +} + sub CountConnection { my $self = shift; my $dir = shift; + if ($dir =~ m/^modport (\S+)/) { $dir = "modport"; $self->{intf_modport} = $1; } # Indicate that this signal is connected to a port of the indicated type. $self->{count}->{$dir} += 1; } @@ -1218,7 +1345,7 @@ sub Declaration() { if ($width =~ m/(^(?:\s*signed)?\s*\[)|(^\s*$)/) { # net is an array or single-element: $r = [$type, $width, $s]; - } else { + } else { # array is a struct, so don't declare a nettype: $r = [$width, $s]; } @@ -1229,19 +1356,18 @@ sub Declaration() { # Returns an array of tokens forming a port declaration sub Port { my $self = shift; - my $dir = 'output'; + my @return = ('output'); if ($self->NumberOfConnections('inout') > 0) { - $dir = 'inout'; + @return = ('inout'); } elsif ($self->NumberOfConnections('output') == 0) { - $dir = 'input'; - } - my @return = ($dir); - # A hack: if a port is named "_if", we assume it is an interface - # and doesn't need a direction. - if ($self->{width} =~ m/_if\b/) { - @return = (); + @return = ('input'); } push @return, @{$self->Declaration(1)}; + if ($self->NumberOfConnections('modport') == 1) { + # this is an interface. Replace the first two elements. + shift @return for 1..2; + unshift(@return, $self->{intf_modport}); + } return @return; } @@ -1351,7 +1477,11 @@ sub run_macro($$$) { } # return the expanded macro: - return "${text}\n/*PPSTART*/\n${result}\n/*PPSTOP*/\n"; + if ($result =~ m/^\s*$/ && $main::config{"omit_empty"}) { + return "${text}"; + } else { + return "${text}\n/*PPSTART*/\n${result}\n/*PPSTOP*/\n"; + } } # expand_macro(label, function_ref) @@ -1362,6 +1492,7 @@ sub run_macro($$$) { sub expand_macro($$) { my $self = shift; my ($label, $function) = @_; + main::log_debug("expanding $label"); $self->{text} =~ s{(/\*\*${label}\b.*?\*/)} {$self->run_macro($1, $function)}egxs; @@ -1380,6 +1511,7 @@ sub expand_all_macros { # operations if (!$main::trim) { + $self->expand_macro('CONFIG', \&expand_config); $self->expand_macro('FIXEDPOINT', \&expand_fixedpoint); $self->expand_macro('PERL', \&expand_perl); $self->expand_macro('EXEC', \&expand_exec); @@ -1394,6 +1526,7 @@ sub expand_all_macros { $self->expand_macro('FORINST', \&expand_forinst); $self->expand_macro('AUTOTOSTRING', \&expand_autotostring); $self->expand_macro('AUTOINC', \&expand_includes); + $self->expand_macro('AUTONC', \&expand_autonc); # note: AUTOINTERFACE must expand before AUTONET, as it will change # AUTONET's behavior. $self->expand_macro('AUTOINTERFACE', \&expand_autointerface); @@ -1466,45 +1599,49 @@ sub preprocess { print STDERR "${outputfile}: NEEDS UPDATE\n"; $self->{changes}++; } - } elsif ($self->is_changed() || ($outputfile ne $filename)) { - # make backup if we're running in-place, before overwriting the - # new file: - if ($outputfile eq $filename) { - $filename .= '.orig'; - my $fh = new FileHandle(">${filename}") or die ("${filename}: $!"); - print $fh $self->{src}; - $fh->close(); - $filename =~ s/.orig$//; - } - - unlink $outputfile if (-e $outputfile); - my $fh = new FileHandle(">$outputfile") or die ("$outputfile: $!"); + } else { + if ($self->is_changed() || ($outputfile ne $filename)) { + # make backup if we're running in-place, before overwriting the + # new file: + if ($outputfile eq $filename) { + $filename .= '.orig'; + my $fh = new FileHandle(">${filename}") or die ("${filename}: $!"); + print $fh $self->{src}; + $fh->close(); + $filename =~ s/.orig$//; + } - # make sure we've got a final newline: - $self->{text} =~ s/\n*$/\n/so; - print $fh $self->{text}; + unlink $outputfile if (-e $outputfile); + my $fh = new FileHandle(">$outputfile") or die ("$outputfile: $!"); + + # make sure we've got a final newline: + $self->{text} =~ s/\n*$/\n/so; + print $fh $self->{text}; + + # add the footer to the end of the file: + if ((!$main::trim) && ($main::config{"enable_footer"})) { + print $fh "\n"; + print $fh "/*PPSTART*/\n"; + print $fh main::wrap("// Source file: ${filename}", + "/", "/\n// ", 70) . "\n"; + print $fh "// preprocessed by user: " . $ENV{USER}. "\n"; + print $fh "// preprocessed on: " . (scalar localtime time()) . "\n"; + print $fh "/*PPSTOP*/\n"; + } + $fh->close(); - # add the footer to the end of the file: - if ((!$main::trim) && ($main::config{"enable_footer"})) { - print $fh "\n"; - print $fh "/*PPSTART*/\n"; - print $fh main::wrap("// Source file: ${filename}", - "/", "/\n// ", 70) . "\n"; - print $fh "// preprocessed by user: " . $ENV{USER}. "\n"; - print $fh "// preprocessed on: " . (scalar localtime time()) . "\n"; - print $fh "/*PPSTOP*/\n"; + if ($outputfile ne $filename) { + chmod 0444, $outputfile; # Set read-only to minimize accident edits. + } } - $fh->close(); - if ($outputfile ne $filename) { - chmod 0444, $outputfile; # Set read-only to minimize accident edits. + if ($self->is_changed()) { + print STDERR "${outputfile}: UPDATED\n"; + } else { + print STDERR "${outputfile}: no change.\n" + unless $main::quieter || $main::check; } - - print STDERR "${outputfile}: UPDATED\n"; - } else { - print STDERR "${outputfile}: no change.\n" - unless $main::quieter || $main::check; - } + } # else $main::check $self->UpdateManifest(); @@ -1528,7 +1665,6 @@ sub is_changed { return ($orig ne $self->{text}); } - sub report_error { print STDERR "ERROR: @_\n"; print "ERROR: @_\n"; @@ -1539,7 +1675,7 @@ sub recursively_process_all_dependencies { my $filename = shift; my $caller = shift; my $changes = 0; - my $path = normalize_path($filename); + my $path = main::locate_file($filename, @_); if ((! -e $path) && (! -e "${path}pp")) { warn "ERROR: File \"$caller->{srcfilename}\"\n" . " contains dependency on missing file \"$filename\"."; @@ -1572,6 +1708,11 @@ sub parse_instantiate_macro($$) { } $mapper->{PARAMS} = \%PARAMS; $mapper->{PARAM_KEYS} = \@PARAM_KEYS; + my %LOCALPARAMS = (); + while ($macro =~ s/^\s*localparam\s+(\S+)\s+(\S.*?)\s*$//mso) { + $LOCALPARAMS{$1} = $2; + } + $mapper->{LOCALPARAMS} = \%LOCALPARAMS; # # parse out overrides @@ -1611,6 +1752,15 @@ sub apply_mapper { return $signal; } +sub keep_track_of_assignment($$$) { + my $self = shift; + my $symbol = shift; + my $dir = shift; + if (defined($self->{NETS}->{$symbol})) { + $self->{NETS}->{$symbol}->CountConnection($dir); + } +} + sub keep_track_of_used_net { my $self = shift; my $prototype = shift; @@ -1618,21 +1768,20 @@ sub keep_track_of_used_net { my $mapped_signal = shift; my $mapper = shift; - return if ($signal eq 'clk'); - return if ($signal eq 'rst'); - return if ($signal eq $main::config{"clock"}); - return if ($signal eq $main::config{"reset_n"}); - my $port = $prototype->GetPortByName($signal); - if (!defined($self->{NETS}->{$mapped_signal})) { + my $normalized_net = $mapped_signal; + $normalized_net =~ s/\s*\[ [^\]]* \]\s*//gx; # strip away slice operators. + if (!defined($self->{NETS}->{$normalized_net})) { # This is the first time we've encountered this # wire. - $self->{NETS}->{$mapped_signal} = $port->AsNet($mapped_signal, $mapper); + $self->{NETS}->{$normalized_net} = $port->AsNet($normalized_net, $mapper); + } else { + $self->{NETS}->{$normalized_net}->MakeCompatibleWith($port->AsNet($normalized_net, $mapper)); } # update count of loads and drivers: { - my $ref = $self->{NETS}->{$mapped_signal}; + my $ref = $self->{NETS}->{$normalized_net}; my $dir = $prototype->{ports}->{$signal}->io(); $ref->CountConnection($dir); } @@ -1654,6 +1803,7 @@ sub extract_iterables($) { } else { ($items, $text) = split(m/\n/, $macro, 2); } + if (!defined($text)) { $text = ""; } sub Interval { my $first = shift; @@ -1758,34 +1908,59 @@ sub expand_forinst($$) { my ($path, $instance); $macro =~ s/^\s+//; + if (!defined($macro)) { + &main::dump_stack(); + die "macro undefined"; + } + # turn on pretty print if --pretty is supplied. my $prettyprint = $main::config{"prettyprint"}; if ($macro =~ s/^(.*)--pretty(?:print)?/$1/) { $prettyprint = 1; } + my $compact_ports = $main::config{"compact_ports"}; + if ($macro =~ s/^(.*)--compact(?:_ports)?/$1/) { + $compact_ports = 1; + } + my $style = $main::config{"style"}; + if ($macro =~ s/^(.*)--style=(\S+)/$1/) { + $style = $2; + if ($style eq "pretty") { $prettyprint = 1; } + } ($path, $instance, $macro) = split(m/\s+/, $macro, 3); + if (!defined($macro)) { + &main::dump_stack(); + die "macro undefined"; + } + my $itemsref; ($macro, $itemsref) = extract_iterables($macro); + if (!defined($macro)) { + &main::dump_stack(); + die "macro undefined"; + } my $prototype = $self->get_prototype_from_file($path); for (my $i = 0; $i <= $#{$itemsref}; $i++) { my $enumerator = $itemsref->[$i]; my $instancename = "${instance}_${enumerator}"; - $self->expand_instantiate_with_prototype($prototype, $instancename, - $macro, $enumerator, $prettyprint); + $self->expand_instantiate_with_prototype( + $prototype, $instancename, $macro, $enumerator, $prettyprint, + $compact_ports, $style); } } $MacroHelp{'INST'} = < + /**INST [] **/ Where: * "path" is the path to the module to be instantiated. * "instance" is the instance name to use for the instantiation. +* "options" is an optional list of flags. * "specifications" is a list of zero or more lines used to map port names onto signal names. This can take a couple of different forms. @@ -1801,6 +1976,17 @@ Transformation of port names onto signal names occurs by applying a set of transformation rules onto the port name to produce the signal name that port should connect to. +Some modules internally define local parameters which then leak +out of the module into the module interface. These local localparams +can be handled by manually computing the correct value for each +parameter, and then overriding the symbolic name of the parameter +in the port width. This can be specified like this: + + localparam + +Think of "localparam" as being the same as "parameter", except that a +parameter isn't added to the "#(...)" clause of a module instantiation. + The simplest transformation simply maps a port to a signal, like this: .portname(signalname) @@ -1816,6 +2002,13 @@ ports of INST-instantiated submodules. Additionally, the AUTOINTERFACE macro can be used to propagate unbound ports from INST-instantiated submodules to the module interface. +Options: + +* --pretty Turns on "pretty print" style (equivalent to --style=pretty). +* --style Sets the output style ("default", "v2", "pretty", "v3") +* --compact Use compact naming for ports whose names match the connecting + signal (ie. ".clk" instead of ".clk(clk)"). + See also: the AUTONET, AUTOINTERFACE, and FORINST macros. Example: @@ -1830,14 +2023,15 @@ EOT sub get_prototype_from_file{ my $self = shift; my $filename = shift; + my $curpath = File::Basename::dirname($self->{srcfilename}); if ($main::recursive) { my $changes = recursively_process_all_dependencies( - $filename, $self); + $filename, $self, $curpath); $self->{changes} += $changes; } - my $prototype = new ModuleSpec()->read_prototype($filename); + my $prototype = new ModuleSpec()->read_prototype($filename, $curpath); if (!$prototype) { report_error("Could not read ${filename}: $!"); return; @@ -1857,6 +2051,15 @@ sub expand_instantiate($$) { if ($macro =~ s/^(.*)--pretty(?:print)?/$1/) { $prettyprint = 1; } + my $compact_ports = $main::config{"compact_ports"}; + if ($macro =~ s/^(.*)--compact(?:_ports)?/$1/) { + $compact_ports = 1; + } + my $style = $main::config{"style"}; + if ($macro =~ s/^(.*)--style=(\S+)/$1/) { + $style = $2; + if ($style eq "pretty") { $prettyprint = 1; } + } if (!($macro =~ s/^\s*(\S+)\s+(\S+)\s*//so)) { report_error("Badly formatted INST macro"); @@ -1867,7 +2070,7 @@ sub expand_instantiate($$) { my $prototype = $self->get_prototype_from_file($filename); $self->expand_instantiate_with_prototype($prototype, $instancename, $macro, - undef, $prettyprint); + undef, $prettyprint, $compact_ports, $style); } sub expand_instantiate_with_prototype { @@ -1877,6 +2080,13 @@ sub expand_instantiate_with_prototype { my $macro = shift; my $enumerator = shift; my $prettyprint = shift; + my $compact_ports = shift; + my $style = shift; + + if (!defined($macro)) { + &main::dump_stack(); + die "Undefined macro."; + } if (!defined($enumerator)) { my @digits = ($instancename =~ m/(\d+)/g); @@ -1904,50 +2114,122 @@ sub expand_instantiate_with_prototype { # map ports onto signals: # my @d = (); + my @list_of_hookup_arrs = (); foreach my $signal (@signals) { my $mapped_signal = $self->apply_mapper($mapper, $signal, $enumerator); my $hookup; + my $hookup_arr = ['', '', '']; # port, signal, comment my $width = $prototype->{ports}->{$signal}->width(); # expand any Parameters within the $width expression: foreach my $key (keys %{$mapper->{PARAMS}}) { $width =~ s/\b${key}\b/$mapper->{PARAMS}->{$key}/g; } + # expand any localparams within the $width expression: + foreach my $key (keys %{$mapper->{LOCALPARAMS}}) { + $width =~ s/\b${key}\b/$mapper->{LOCALPARAMS}->{$key}/g; + } + my $dir = $prototype->{ports}->{$signal}->io(); if ($prettyprint) { - my $dir = $prototype->{ports}->{$signal}->io(); $hookup = sprintf ".%-25s (%-25s) // %6s", $signal, $mapped_signal, $dir; if ($width ne "") { $hookup .= " $width"; } } else { - $hookup = ".${signal} (${mapped_signal})"; + if (($compact_ports) && ($signal eq $mapped_signal)) { + $hookup = ".${signal}"; + } else { + $hookup = ".${signal} (${mapped_signal})"; + } + } + if ($signal eq $mapped_signal) { + $hookup_arr->[0] = ".${signal},"; + $hookup_arr->[1] = ""; + } else { + $hookup_arr->[0] = ".${signal}"; + $hookup_arr->[1] = "(${mapped_signal}),"; } + $hookup_arr->[2] = "// ${dir}"; push(@d, $hookup); + push(@list_of_hookup_arrs, $hookup_arr); $self->keep_track_of_used_net($prototype, $signal, $mapped_signal, $mapper); } + # trim final comma from last port: + $list_of_hookup_arrs[-1]->[0] =~ s/,$//; + $list_of_hookup_arrs[-1]->[1] =~ s/,$//; # # print module instantiation # - print "${mod} "; - # When in pretty-print mode, line up commas on the left - my $first_indent = ($prettyprint) ? " " : " "; - my $conjunction = ($prettyprint) ? "\n, " : ",\n "; - if (%{$mapper->{PARAMS}}) { - print "#(\n"; - print $first_indent, - join($conjunction, @params), - ") "; - } - if ($#d >= 0) { - print "${instancename} (\n"; - print $first_indent, join($conjunction, @d), "\n);\n"; + if ($style =~ m/\bv2\b/) { + print "${mod} "; + my $first_indent = " "; + my $conjunction = ",\n${first_indent}"; + if (%{$mapper->{PARAMS}}) { + print "#(\n"; + print $first_indent, + join($conjunction, @params), + "\n) "; + } + if ($#list_of_hookup_arrs >= 0) { + print "${instancename} (\n"; + print $first_indent, &main::TabularAlign(\@list_of_hookup_arrs, "\n${first_indent}"),"\n);\n"; + } else { + # module has no ports. + print "${instancename} ();\n"; + } + return; + } elsif ($style eq "v3") { + print "${mod} "; + if (%{$mapper->{PARAMS}}) { + print "#(\n"; + for my $i (0..$#params) { + my $param = $params[$i]; + my $conjunction = ",\n"; + if ($i == $#params) { $conjunction = "\n"; } + $param =~ m/.(\S+)\s*\((.+)\)/; + printf(" .%-29s (%s)%s", $1, $2, $conjunction); + } + print ") "; + } + if ($#list_of_hookup_arrs >= 0) { + print "${instancename} (\n"; + for my $i (0..$#list_of_hookup_arrs) { + my @hookup_arr = @{$list_of_hookup_arrs[$i]}; + if ($hookup_arr[1] eq "") { + printf " %-61s %s\n", $hookup_arr[0], $hookup_arr[2]; + } else { + printf " %-30s %-30s %s\n", $hookup_arr[0], $hookup_arr[1], $hookup_arr[2]; + } + } + print(");\n") + } else { + # module has no ports. + print "${instancename} ();\n"; + } + return; } else { - # module has no ports. - print "${instancename} ();\n"; - } + # default style: + print "${mod} "; + # When in pretty-print mode, line up commas on the left + my $first_indent = ($prettyprint) ? " " : " "; + my $conjunction = ($prettyprint) ? "\n, " : ",\n "; + if (%{$mapper->{PARAMS}}) { + print "#(\n"; + print $first_indent, + join($conjunction, @params), + ") "; + } + if ($#d >= 0) { + print "${instancename} (\n"; + print $first_indent, join($conjunction, @d), "\n);\n"; + } else { + # module has no ports. + print "${instancename} ();\n"; + } + } # end of style select } $MacroHelp{'AUTOINC'} = <parse_prototype($self->{text}); + + # mark assignments + for my $symbol_to (keys %{$my_interface->{assigns}}) { + $self->keep_track_of_assignment($symbol_to, "output"); + } + for my $symbol_from (keys %{$my_interface->{assign_from}}) { + $self->keep_track_of_assignment($symbol_from, "input"); + } + + my @sigs = sort keys %{$self->{NETS}}; + foreach my $s (@sigs) { + my $ref = $self->{NETS}->{$s}; + + next if ($my_interface->HasPort($s)); + next unless ($s =~ m/^[[:alpha:]]/); + next if ($s =~ m/\W/); + + my $found = 0; + if (grep(/^$s$/, @names)) { + $found = 1; + } else { + foreach my $re (@regexes) { + if ($s =~ $re) { + $found = 1; + last; + } + } + } + + if (!$found) {next;} + + # for apocryphal reasons / backwards compatibility: + next if ($s eq 'clk'); + next if ($s eq 'rst'); + next if ($s eq $main::config{"clock"}); + next if ($s eq $main::config{"reset_n"}); + + if ($ref->NumberOfConnections('inout') > 0) { + # ignore inout signals + } elsif ($ref->NumberOfConnections('modport') > 0) { + # ignore interfaces + } elsif ($ref->NumberOfConnections('output') == 0) { + # no drivers, so assign to zero. + push @tieoffs, $s; + $ref->{count}->{output} = 1; + } elsif ($ref->NumberOfConnections('input') == 0) { + # no loads, so add to lint_unused signal list. + push @unused, $s; + $ref->{count}->{input} = 1; + } + } + + if (@tieoffs) { + foreach my $s (@tieoffs) { + print "assign $s = '0;\n"; + } + } + if (@unused) { + if (@tieoffs) { print "\n"; } + print "logic lint_unused_signals;\n"; + print "assign lint_unused_signals =\n"; + print " ",join((" ||\n ", map { "($_ == '0)" } @unused)),";\n"; + } +} + $MacroHelp{'AUTOINTERFACE'} = <parse_prototype($self->{text}); @@ -2118,7 +2494,22 @@ sub expand_autointerface($$) { } &main::Pad2DArray(\@ports, 2, 5); - print &main::TabularAlign(\@ports, ",\n"), "\n"; + if ($style eq "v3") { + for my $i (0..$#ports) { + my @p = @{$ports[$i]}; + @p = grep {!/^$/} @p; + if ($p[1] eq "input") { $p[1] = "input "; } + if ($p[1] eq "inout") { $p[1] = "inout "; } + print (join(" ", @p)); + if ($i == $#ports) { + print "\n"; + } else { + print ",\n"; + } + } + } else { + print &main::TabularAlign(\@ports, ",\n"), "\n"; + } } sub CountAssignments { @@ -2131,6 +2522,12 @@ sub CountAssignments { $ref->CountConnection('output'); } } + foreach my $s (keys %{$my_interface->{assign_from}}) { + if (defined($self->{NETS}->{$s})) { + my $ref = $self->{NETS}->{$s}; + $ref->CountConnection('input'); + } + } } @@ -2166,6 +2563,9 @@ drivers, multiple drivers, or zero load. Note that verilogpp does not fully parse verilog, so AUTONET's warnings are only accurate in designs that only contain expansions of INST macros. +If the "--skipif" option is supplied, all signals marked as interfaces +will be omitted from the net declarations. + If the "--cb" option is supplied, verilogpp will create appropriate clocking blocks. verilogpp's ideas of appropriate clocking blocks are: @@ -2227,6 +2627,16 @@ sub expand_autonet($$) { $cb = 1; } + my $skipif = 0; + if ($macro =~ s/\s*--?skipifs?\s*//) { + $skipif = 1; + } + + my $style = $main::config{"style"}; + if ($macro =~ s/^(.*)--style=(\S+)/$1/) { + $style = $2; + } + # parse the input and output ports of this module my $my_interface = new ModuleSpec()->parse_prototype($self->{text}); $self->CountAssignments($my_interface); @@ -2244,6 +2654,12 @@ sub expand_autonet($$) { next; } + # for apocryphal reasons / backwards compatibility: + next if ($s eq 'clk'); + next if ($s eq 'rst'); + next if ($s eq $main::config{"clock"}); + next if ($s eq $main::config{"reset_n"}); + # Skip constants and expressions next unless ($s =~ m/[[:alpha:]]/); # Must have a letter next if ($s =~ m/\W/); # Must only contain "word" characters. @@ -2252,6 +2668,10 @@ sub expand_autonet($$) { # add it to autonets list of nets: my $ref = $self->{NETS}->{$s}; + if ($skipif && $ref->NumberOfConnections('modport') > 0) { + next; + } + my $warning = ""; if ($warn) { if (($ref->NumberOfConnections('input') == 0) && @@ -2289,7 +2709,9 @@ sub expand_autonet($$) { # determine what to initialize the register too, if needed. my $assignment = ""; # empty string by default if ($init) { - if ($ref->NumberOfConnections('inout') > 0) { + if ($ref->NumberOfConnections('modport') > 0) { + $assignment = ""; + } elsif ($ref->NumberOfConnections('inout') > 0) { $assignment = " = 'Z"; } elsif ($ref->NumberOfConnections('output') == 0) { $assignment = " = '0"; @@ -2460,6 +2882,42 @@ sub expand_reg($$) { } +$MacroHelp{'CONFIG'} = <" + +This attribute can be supplied multiple times, to specific multiple subpaths. +This subpath specifies an additional path component to be searched for files +referred to by INST and FORINST macros. The search is performed by iterating +through each INCDIR path, and then looking for the file in each SUBPATH +beneath each INCDIR path. + +Example: + + /**CONFIG + SUBPATH=generated/ip/directory + SUBPATH=another/very/long/path/we/dont/want/to/type/over/and/over/again + **/ + +EOT +sub expand_config($$) { + my $self = shift; + my $macro = shift; + my @lines = split(m/\s*\n\s*/, $macro); + foreach my $line (@lines) { + my ($key, $value) = ($line =~ m/^\s*(\S+?)\s*=\s*(\S+)\s*$/); + if ($key eq "SUBPATH") { + push(@{$main::config{"subpaths"}}, $value); + } else { + report_error("ERROR: unknown config attribute $key"); + } + } +} $MacroHelp{'FIXEDPOINT'} = < \$main::config{"autonet_allwires"}, "prettyprint|p!" => \$main::config{"prettyprint"}, + "style=s" => \$main::config{"style"}, "fsm_state_suffix|f=s" => \$main::config{"fsm_state_suffix"}, ); @@ -3151,8 +3610,10 @@ sub main { } my $file_count = keys %main::PROCESSED; - print STDERR "Processed ${file_count} files and made ", - (($changes == 1) ? "1 change.\n" : "$changes changes.\n"); + if (!$quieter) { + print STDERR "Processed ${file_count} files and made ", + (($changes == 1) ? "1 change.\n" : "$changes changes.\n"); + } if ($main::check) { # return error if any file needed changes diff --git a/verilogpp_tests/README b/verilogpp_tests/README index eb55f38..de42787 100644 --- a/verilogpp_tests/README +++ b/verilogpp_tests/README @@ -1,3 +1,13 @@ +# verilogpp regression suite + +## Quick Start + +``` +./verilogpp_files.t +``` + +## Overview + The files in this directory are used by the verilogpp_tests.t test. All files with .vpp extensions are processed by the preprocessor to diff --git a/verilogpp_tests/autoif.vpp b/verilogpp_tests/autoif.vpp index ae6d553..0aebd79 100644 --- a/verilogpp_tests/autoif.vpp +++ b/verilogpp_tests/autoif.vpp @@ -7,9 +7,9 @@ module inst_of_unpacked ( /**AUTOINTERFACE**/ /*PPSTART*/ output wire [7:0] bar, - input wire fee_en [0:10-1], - input wire [7:0] foo [0:5], - input wire foo_en [0:5] + input wire fee_en[0:10-1], + input wire [7:0] foo[0:5], + input wire foo_en[0:5] /*PPSTOP*/ ); diff --git a/verilogpp_tests/autoif_v3.vpp b/verilogpp_tests/autoif_v3.vpp new file mode 100644 index 0000000..0547998 --- /dev/null +++ b/verilogpp_tests/autoif_v3.vpp @@ -0,0 +1,50 @@ +// inst_of_unpacked instantiates an unpacked from unpacked.v + +module inst_of_unpacked ( + input wire clk, + input wire reset_n, + output [7:0] fee [0:10-1], + /**AUTOINTERFACE --style=v3 **/ +/*PPSTART*/ + output wire [7:0] bar, + input wire fee_en[0:10-1], + input wire [7:0] foo[0:5], + input wire foo_en[0:5] +/*PPSTOP*/ +); + +/**AUTONET --init **/ +/*PPSTART*/ + +/*PPSTOP*/ + + +/**INST unpacked.v u_unpacked --style=v3 **/ +/*PPSTART*/ +unpacked u_unpacked ( + .clk, // input + .reset_n, // input + .foo, // input + .foo_en, // input + .bar // output +); +/*PPSTOP*/ + +/**INST unpackedN.v u_unpackedN --style=v3 +parameter N 10 +s/^foo/fee/; +**/ +/*PPSTART*/ +unpackedN #( + .N (10) +) u_unpackedN ( + .clk, // input + .reset_n, // input + .foo (fee), // input + .foo_en (fee_en), // input + .bar // output +); +/*PPSTOP*/ + + +endmodule diff --git a/verilogpp_tests/autointerface_with_interface.vpp b/verilogpp_tests/autointerface_with_interface.vpp new file mode 100644 index 0000000..e1a94e7 --- /dev/null +++ b/verilogpp_tests/autointerface_with_interface.vpp @@ -0,0 +1,34 @@ +// inst_of_unpacked instantiates an unpacked from unpacked.v + +module inst_of_mod_with_interface ( + input wire clk, + input wire reset_n, + /**AUTOINTERFACE**/ +/*PPSTART*/ + axi4_if.completer axi, + output wire [15:0] fwd_data, + input wire fwd_ready, + output wire fwd_valid +/*PPSTOP*/ +); + +/**AUTONET**/ +/*PPSTART*/ + +/*PPSTOP*/ + +/**INST mod_with_interface.v mod_with_interface --style=v2 + .rst_n (reset_n) +**/ +/*PPSTART*/ +mod_with_interfaced mod_with_interface ( + .clk, // input + .rst_n (reset_n), // input + .axi, // modport axi4_if.completer + .fwd_data, // output + .fwd_valid, // output + .fwd_ready // input +); +/*PPSTOP*/ + +endmodule diff --git a/verilogpp_tests/autonc.vpp b/verilogpp_tests/autonc.vpp new file mode 100644 index 0000000..b3a81ca --- /dev/null +++ b/verilogpp_tests/autonc.vpp @@ -0,0 +1,82 @@ +// inst_of_unpacked instantiates an unpacked from unpacked.v + +module inst_of_unpacked ( + input wire clk, + input wire reset_n, + output [7:0] fee [0:10-1], + /**AUTOINTERFACE**/ +/*PPSTART*/ + input wire fee_en[0:5], + input wire [7:0] fie[0:5], + input wire fie_en[0:5] +/*PPSTOP*/ +); + +/**AUTONET --init **/ +/*PPSTART*/ +wire [7:0] another_output; +wire [7:0] bar; +wire [7:0] foo[0:5]; +wire foo_en[0:5]; +/*PPSTOP*/ + +/**AUTONC + weep + woe + /output$/ + bar + /^foo/ +**/ +/*PPSTART*/ +assign foo = '0; +assign foo_en = '0; + +logic lint_unused_signals; +assign lint_unused_signals = + (another_output == '0) || + (bar == '0); +/*PPSTOP*/ + + +/**INST unpacked.v u_unpacked **/ +/*PPSTART*/ +unpacked u_unpacked ( + .clk (clk), + .reset_n (reset_n), + .foo (foo), + .foo_en (foo_en), + .bar (bar) +); +/*PPSTOP*/ + +/**INST unpacked.v u_unpacked2 +parameter N 10 +s/^foo/fee/; +**/ +/*PPSTART*/ +unpacked #( + .N(10)) u_unpacked2 ( + .clk (clk), + .reset_n (reset_n), + .foo (fee), + .foo_en (fee_en), + .bar (bar) +); +/*PPSTOP*/ + +/**INST unpacked.v u_unpacked3 + .bar(another_output) + s/foo/fie/; +**/ +/*PPSTART*/ +unpacked u_unpacked3 ( + .clk (clk), + .reset_n (reset_n), + .foo (fie), + .foo_en (fie_en), + .bar (another_output) +); +/*PPSTOP*/ + + +endmodule diff --git a/verilogpp_tests/autonc2.vpp b/verilogpp_tests/autonc2.vpp new file mode 100644 index 0000000..b3a70b4 --- /dev/null +++ b/verilogpp_tests/autonc2.vpp @@ -0,0 +1,74 @@ +// inst_of_unpacked instantiates an unpacked from unpacked.v + +module inst_of_unpacked ( + input wire clk, + input wire reset_n, + output [7:0] fee [0:10-1], + input wire fee_en[0:5], + input wire [7:0] fie[0:5], + input wire fie_en[0:5] +); + +/**AUTONET --init **/ +/*PPSTART*/ +wire [7:0] another_output; +wire [7:0] bar; +wire [7:0] foo[0:5]; +wire foo_en[0:5]; +/*PPSTOP*/ + +/**AUTONC + /.+/ +**/ +/*PPSTART*/ +assign foo = '0; +assign foo_en = '0; + +logic lint_unused_signals; +assign lint_unused_signals = + (another_output == '0) || + (bar == '0); +/*PPSTOP*/ + +/**INST unpacked.v u_unpacked **/ +/*PPSTART*/ +unpacked u_unpacked ( + .clk (clk), + .reset_n (reset_n), + .foo (foo), + .foo_en (foo_en), + .bar (bar) +); +/*PPSTOP*/ + +/**INST unpacked.v u_unpacked2 +parameter N 10 +s/^foo/fee/; +**/ +/*PPSTART*/ +unpacked #( + .N(10)) u_unpacked2 ( + .clk (clk), + .reset_n (reset_n), + .foo (fee), + .foo_en (fee_en), + .bar (bar) +); +/*PPSTOP*/ + +/**INST unpacked.v u_unpacked3 + .bar(another_output) + s/foo/fie/; +**/ +/*PPSTART*/ +unpacked u_unpacked3 ( + .clk (clk), + .reset_n (reset_n), + .foo (fie), + .foo_en (fie_en), + .bar (another_output) +); +/*PPSTOP*/ + + +endmodule diff --git a/verilogpp_tests/autonc3.vpp b/verilogpp_tests/autonc3.vpp new file mode 100644 index 0000000..38f25c1 --- /dev/null +++ b/verilogpp_tests/autonc3.vpp @@ -0,0 +1,71 @@ +// inst_of_unpacked instantiates an unpacked from unpacked.v + +module inst_of_unpacked ( + input wire clk, + input wire reset_n, + output [7:0] fee [0:10-1], + input wire fee_en[0:5], + input wire [7:0] fie[0:5], + input wire fie_en[0:5] +); + +/**AUTONET --init **/ +/*PPSTART*/ +wire [7:0] another_output; +wire [7:0] bar; +wire [7:0] foo[0:5]; +wire foo_en[0:5]; +/*PPSTOP*/ + +assign foo_en[0] = bar; +assign foo_en[1] = bar && another_output; + +/**AUTONC + /.+/ +**/ +/*PPSTART*/ +assign foo = '0; +/*PPSTOP*/ + +/**INST unpacked.v u_unpacked **/ +/*PPSTART*/ +unpacked u_unpacked ( + .clk (clk), + .reset_n (reset_n), + .foo (foo), + .foo_en (foo_en), + .bar (bar) +); +/*PPSTOP*/ + +/**INST unpacked.v u_unpacked2 +parameter N 10 +s/^foo/fee/; +**/ +/*PPSTART*/ +unpacked #( + .N(10)) u_unpacked2 ( + .clk (clk), + .reset_n (reset_n), + .foo (fee), + .foo_en (fee_en), + .bar (bar) +); +/*PPSTOP*/ + +/**INST unpacked.v u_unpacked3 + .bar(another_output) + s/foo/fie/; +**/ +/*PPSTART*/ +unpacked u_unpacked3 ( + .clk (clk), + .reset_n (reset_n), + .foo (fie), + .foo_en (fie_en), + .bar (another_output) +); +/*PPSTOP*/ + + +endmodule diff --git a/verilogpp_tests/autonc4.vpp b/verilogpp_tests/autonc4.vpp new file mode 100644 index 0000000..56e8360 --- /dev/null +++ b/verilogpp_tests/autonc4.vpp @@ -0,0 +1,84 @@ +// inst_of_unpacked instantiates an unpacked from unpacked.v + +module inst_of_unpacked ( + input wire clk, + input wire reset_n, + output [7:0] fee [0:10-1], + input wire fee_en[0:5], + input wire [7:0] fie[0:5], + input wire fie_en[0:5] +); + +/**AUTONET --init **/ +/*PPSTART*/ +wire [7:0] another_output; +wire [7:0] bar; +wire derived; +wire [7:0] foo[0:5]; +wire foo_en[0:5]; +/*PPSTOP*/ + +assign foo_en[0] = bar; +assign foo_en[1] = bar && another_output; + +/**AUTONC + /.+/ +**/ +/*PPSTART*/ +assign foo = '0; +/*PPSTOP*/ + +/**INST drive_one.v drive_one_derived + .foo(derived) +**/ +/*PPSTART*/ +drive_one drive_one_derived ( + .foo (derived) +); +/*PPSTOP*/ + + +/**INST unpacked.v u_unpacked --style=v2 --compact **/ +/*PPSTART*/ +unpacked u_unpacked ( + .clk, // input + .reset_n, // input + .foo, // input + .foo_en, // input + .bar // output +); +/*PPSTOP*/ + +/**INST unpacked.v u_unpacked2 --style=v2 --compact +parameter N 10 +s/^foo/fee/; +.reset_n(derived) +**/ +/*PPSTART*/ +unpacked #( + .N(10) +) u_unpacked2 ( + .clk, // input + .reset_n (derived), // input + .foo (fee), // input + .foo_en (fee_en), // input + .bar // output +); +/*PPSTOP*/ + +/**INST unpacked.v u_unpacked3 --style=v2 --compact + .bar(another_output) + s/foo/fie/; +**/ +/*PPSTART*/ +unpacked u_unpacked3 ( + .clk, // input + .reset_n, // input + .foo (fie), // input + .foo_en (fie_en), // input + .bar (another_output) // output +); +/*PPSTOP*/ + + +endmodule diff --git a/verilogpp_tests/autonet_skipif.vpp b/verilogpp_tests/autonet_skipif.vpp new file mode 100644 index 0000000..1e0d200 --- /dev/null +++ b/verilogpp_tests/autonet_skipif.vpp @@ -0,0 +1,30 @@ +// inst_of_unpacked instantiates an unpacked from unpacked.v + +module inst_of_mod_with_interface ( + input wire clk, + input wire reset_n ); + +axi4_if axi(.clk, .reset_n); + +/**AUTONET --init --skipif **/ +/*PPSTART*/ +wire [15:0] fwd_data; +reg fwd_ready = '0; +wire fwd_valid; +reg rst_n = '0; +/*PPSTOP*/ + +/**INST mod_with_interface.v mod_with_interface --style=v2 +**/ +/*PPSTART*/ +mod_with_interfaced mod_with_interface ( + .clk, // input + .rst_n, // input + .axi, // modport axi4_if.completer + .fwd_data, // output + .fwd_valid, // output + .fwd_ready // input +); +/*PPSTOP*/ + +endmodule diff --git a/verilogpp_tests/connect_from_array.vpp b/verilogpp_tests/connect_from_array.vpp new file mode 100644 index 0000000..5c61fb3 --- /dev/null +++ b/verilogpp_tests/connect_from_array.vpp @@ -0,0 +1,35 @@ +module connect_to_array(); + +/**AUTONET --init **/ +/*PPSTART*/ +wire [1:0] bar; +/*PPSTOP*/ + +/**INST drive_two.v drive_two + .foo(bar) +**/ +/*PPSTART*/ +drive_two drive_two ( + .foo (bar) +); +/*PPSTOP*/ + +/**FORINST sink_one.v sink_one 0 1 + .foo(bar[${enumerator}]) +**/ +/*PPSTART*/ +sink_one sink_one_0 ( + .foo (bar[0]) +); +sink_one sink_one_1 ( + .foo (bar[1]) +); +/*PPSTOP*/ + +/**AUTONC**/ +/*PPSTART*/ + +/*PPSTOP*/ + + +endmodule : connect_to_array diff --git a/verilogpp_tests/connect_n_to_n.vpp b/verilogpp_tests/connect_n_to_n.vpp new file mode 100644 index 0000000..14cde33 --- /dev/null +++ b/verilogpp_tests/connect_n_to_n.vpp @@ -0,0 +1,36 @@ +module connect_to_array(); + +/**AUTONET --init **/ +/*PPSTART*/ +wire bar; +/*PPSTOP*/ + +/**FORINST drive_one.v drive_one 0 1 + .foo(bar[${enumerator}]) +**/ +/*PPSTART*/ +drive_one drive_one_0 ( + .foo (bar[0]) +); +drive_one drive_one_1 ( + .foo (bar[1]) +); +/*PPSTOP*/ + +for (genvar ii = 0; ii < 2; ii += 1) begin : g_sink +/**INST sink_one.v sink_one + .foo(bar[ii]) +**/ +/*PPSTART*/ +sink_one sink_one ( + .foo (bar[ii]) +); +/*PPSTOP*/ + +/**AUTONC**/ +/*PPSTART*/ + +/*PPSTOP*/ + + +endmodule : connect_to_array diff --git a/verilogpp_tests/connect_to_array.vpp b/verilogpp_tests/connect_to_array.vpp new file mode 100644 index 0000000..20993bb --- /dev/null +++ b/verilogpp_tests/connect_to_array.vpp @@ -0,0 +1,35 @@ +module connect_to_array(); + +/**AUTONET --init **/ +/*PPSTART*/ +wire [1:0] bar; +/*PPSTOP*/ + +/**FORINST drive_one.v drive_one 0 1 + .foo(bar[${enumerator}]) +**/ +/*PPSTART*/ +drive_one drive_one_0 ( + .foo (bar[0]) +); +drive_one drive_one_1 ( + .foo (bar[1]) +); +/*PPSTOP*/ + +/**INST sink_two.v sink_two + .foo(bar) +**/ +/*PPSTART*/ +drive_one sink_two ( + .foo (bar) +); +/*PPSTOP*/ + +/**AUTONC**/ +/*PPSTART*/ + +/*PPSTOP*/ + + +endmodule : connect_to_array diff --git a/verilogpp_tests/drive_one.v b/verilogpp_tests/drive_one.v new file mode 100644 index 0000000..6269d8c --- /dev/null +++ b/verilogpp_tests/drive_one.v @@ -0,0 +1,7 @@ +module drive_one( + output logic foo +); + +assign foo = 1'b1; + +endmodule : drive_one diff --git a/verilogpp_tests/drive_two.v b/verilogpp_tests/drive_two.v new file mode 100644 index 0000000..4470139 --- /dev/null +++ b/verilogpp_tests/drive_two.v @@ -0,0 +1,7 @@ +module drive_two ( + output logic [1:0] foo +); + +assign foo = 1'b1; + +endmodule : drive_one diff --git a/verilogpp_tests/incdir_test.vpp b/verilogpp_tests/incdir_test.vpp new file mode 100644 index 0000000..4040303 --- /dev/null +++ b/verilogpp_tests/incdir_test.vpp @@ -0,0 +1,36 @@ +/**INST submodule.v sub0 --pretty**/ +/*PPSTART*/ +submodule sub0 ( + .clk (clk ) // input +, .reset_n (reset_n ) // input +, .dive (dive ) // input +, .ascend (ascend ) // input +, .fathoms_deep (fathoms_deep ) // output [31:0] +); +/*PPSTOP*/ + + +/**FORINST submodule.v sub 1 2 3 **/ +/*PPSTART*/ +submodule sub_1 ( + .clk (clk), + .reset_n (reset_n), + .dive (dive), + .ascend (ascend), + .fathoms_deep (fathoms_deep) +); +submodule sub_2 ( + .clk (clk), + .reset_n (reset_n), + .dive (dive), + .ascend (ascend), + .fathoms_deep (fathoms_deep) +); +submodule sub_3 ( + .clk (clk), + .reset_n (reset_n), + .dive (dive), + .ascend (ascend), + .fathoms_deep (fathoms_deep) +); +/*PPSTOP*/ diff --git a/verilogpp_tests/inst_locparam.vpp b/verilogpp_tests/inst_locparam.vpp new file mode 100644 index 0000000..e49dbeb --- /dev/null +++ b/verilogpp_tests/inst_locparam.vpp @@ -0,0 +1,33 @@ +// inst_of_locparam instantiates an locparam from locparam.v + +module inst_locparam ( + input wire clk, + /**AUTOINTERFACE**/ +/*PPSTART*/ + input wire [8-1:0] a, + input wire [2*8-1:0] b, + output wire [8-1:0] c +/*PPSTOP*/ + + input wire reset_n ); + +/**AUTONET --init **/ +/*PPSTART*/ +wire [8-1:0] c; +/*PPSTOP*/ + + +/**INST locparam.v u_locparam +localparam FOO 8 +**/ +/*PPSTART*/ +locparam u_locparam ( + .clk (clk), + .a (a), + .b (b), + .c (c) +); +/*PPSTOP*/ + + +endmodule diff --git a/verilogpp_tests/inst_non_ansi.vpp b/verilogpp_tests/inst_non_ansi.vpp new file mode 100644 index 0000000..4bb0a7c --- /dev/null +++ b/verilogpp_tests/inst_non_ansi.vpp @@ -0,0 +1,37 @@ +// inst_of_non_ansi instantiates an non_ansi from non_ansi.v + +module inst_non_ansi ( + input wire clk, + /**AUTOINTERFACE**/ +/*PPSTART*/ + input wire [BYTES-1:0] a, + input wire b, + input wire [WIDTH-1:0] c, + output wire y +/*PPSTOP*/ + + input wire reset_n ); + +/**AUTONET --init **/ +/*PPSTART*/ +wire y; +/*PPSTOP*/ + + +/**INST non_ansi.v u_non_ansi +parameter ID 10 +**/ +/*PPSTART*/ +non_ansi #( + .ID(10)) u_non_ansi ( + .clk (clk), + .a (a), + .b (b), + .c (c), + .y (y), + .logic clk (logic clk) +); +/*PPSTOP*/ + + +endmodule diff --git a/verilogpp_tests/inst_of_mod_with_interface.vpp b/verilogpp_tests/inst_of_mod_with_interface.vpp new file mode 100644 index 0000000..96e32e2 --- /dev/null +++ b/verilogpp_tests/inst_of_mod_with_interface.vpp @@ -0,0 +1,29 @@ +// inst_of_unpacked instantiates an unpacked from unpacked.v + +module inst_of_mod_with_interface ( + input wire clk, + input wire reset_n ); + +/**AUTONET --init **/ +/*PPSTART*/ +axi4_if axi; +wire [15:0] fwd_data; +reg fwd_ready = '0; +wire fwd_valid; +reg rst_n = '0; +/*PPSTOP*/ + +/**INST mod_with_interface.v mod_with_interface --style=v2 +**/ +/*PPSTART*/ +mod_with_interfaced mod_with_interface ( + .clk, // input + .rst_n, // input + .axi, // modport axi4_if.completer + .fwd_data, // output + .fwd_valid, // output + .fwd_ready // input +); +/*PPSTOP*/ + +endmodule diff --git a/verilogpp_tests/inst_of_typed_module.vpp b/verilogpp_tests/inst_of_typed_module.vpp new file mode 100644 index 0000000..a658f87 --- /dev/null +++ b/verilogpp_tests/inst_of_typed_module.vpp @@ -0,0 +1,40 @@ +// inst_of_typed_module instantiates a typed_module from typed_module.v + +module inst_of_typed_module ( + input wire clk, + input wire reset_n ); + +typedef logic [15:0] my_type_t; + +/**AUTONET --init **/ +/*PPSTART*/ +my_type_t fwd_data = '0; +wire fwd_ready; +reg fwd_valid = '0; +my_type_t rev_data; +reg rev_ready = '0; +wire rev_valid; +reg rst_n = '0; +/*PPSTOP*/ + +/**INST typed_module.v typed_module --style=v2 +* parameter TYPE_T my_type_t +* parameter Mode 2 +**/ +/*PPSTART*/ +typed_moduled #( + .TYPE_T(my_type_t), + .Mode(2) +) typed_module ( + .clk, // input + .rst_n, // input + .fwd_data, // input + .fwd_valid, // input + .fwd_ready, // output + .rev_data, // output + .rev_valid, // output + .rev_ready // input +); +/*PPSTOP*/ + +endmodule diff --git a/verilogpp_tests/inst_of_unpacked.vpp b/verilogpp_tests/inst_of_unpacked.vpp index 94290c8..9032058 100644 --- a/verilogpp_tests/inst_of_unpacked.vpp +++ b/verilogpp_tests/inst_of_unpacked.vpp @@ -7,10 +7,10 @@ module inst_of_unpacked ( /**AUTONET --init **/ /*PPSTART*/ wire [7:0] bar; -reg [7:0] fee [0:10-1] = '{default: '0}; -reg fee_en [0:10-1] = '{default: '0}; -reg [7:0] foo [0:5] = '{default: '0}; -reg foo_en [0:5] = '{default: '0}; +reg [7:0] fee[0:10-1] = '{default: '0}; +reg fee_en[0:10-1] = '{default: '0}; +reg [7:0] foo[0:5] = '{default: '0}; +reg foo_en[0:5] = '{default: '0}; /*PPSTOP*/ diff --git a/verilogpp_tests/instv2.vpp b/verilogpp_tests/instv2.vpp new file mode 100644 index 0000000..284e684 --- /dev/null +++ b/verilogpp_tests/instv2.vpp @@ -0,0 +1,38 @@ +/**INST bus_keeper.v keeper7 --style=v2**/ +/*PPSTART*/ +bus_keeper keeper7 ( + .clk, // input + .reset_n, // input + .busNNN_valid, // input + .busNNN_in, // input + .busNNN_out // output +); +/*PPSTOP*/ + + +/**FORINST bus_keeper.v keeper 1 2 3 --style=v2 + s/NNN/${enumerator}/g; +**/ +/*PPSTART*/ +bus_keeper keeper_1 ( + .clk, // input + .reset_n, // input + .busNNN_valid (bus1_valid), // input + .busNNN_in (bus1_in), // input + .busNNN_out (bus1_out) // output +); +bus_keeper keeper_2 ( + .clk, // input + .reset_n, // input + .busNNN_valid (bus2_valid), // input + .busNNN_in (bus2_in), // input + .busNNN_out (bus2_out) // output +); +bus_keeper keeper_3 ( + .clk, // input + .reset_n, // input + .busNNN_valid (bus3_valid), // input + .busNNN_in (bus3_in), // input + .busNNN_out (bus3_out) // output +); +/*PPSTOP*/ diff --git a/verilogpp_tests/instv3.vpp b/verilogpp_tests/instv3.vpp new file mode 100644 index 0000000..fd47110 --- /dev/null +++ b/verilogpp_tests/instv3.vpp @@ -0,0 +1,38 @@ +/**INST bus_keeper.v keeper7 --style=v3**/ +/*PPSTART*/ +bus_keeper keeper7 ( + .clk, // input + .reset_n, // input + .busNNN_valid, // input + .busNNN_in, // input + .busNNN_out // output +); +/*PPSTOP*/ + + +/**FORINST bus_keeper.v keeper 1 2 3 --style=v3 + s/NNN/${enumerator}/g; +**/ +/*PPSTART*/ +bus_keeper keeper_1 ( + .clk, // input + .reset_n, // input + .busNNN_valid (bus1_valid), // input + .busNNN_in (bus1_in), // input + .busNNN_out (bus1_out) // output +); +bus_keeper keeper_2 ( + .clk, // input + .reset_n, // input + .busNNN_valid (bus2_valid), // input + .busNNN_in (bus2_in), // input + .busNNN_out (bus2_out) // output +); +bus_keeper keeper_3 ( + .clk, // input + .reset_n, // input + .busNNN_valid (bus3_valid), // input + .busNNN_in (bus3_in), // input + .busNNN_out (bus3_out) // output +); +/*PPSTOP*/ diff --git a/verilogpp_tests/locparam.v b/verilogpp_tests/locparam.v new file mode 100644 index 0000000..6087884 --- /dev/null +++ b/verilogpp_tests/locparam.v @@ -0,0 +1,9 @@ +module locparam(clk, a, b, c); + +localparam FOO = 8; + +input wire [FOO-1:0] a; +input wire [2*FOO-1:0] b; +output wire [FOO-1:0] c; + +endmodule : locparam diff --git a/verilogpp_tests/mod_with_interface.v b/verilogpp_tests/mod_with_interface.v new file mode 100644 index 0000000..ad3d90a --- /dev/null +++ b/verilogpp_tests/mod_with_interface.v @@ -0,0 +1,15 @@ +// An example of a module with an interface modport + +module mod_with_interfaced ( + input logic clk, + input logic rst_n, + axi4_if.completer axi, + output logic [15:0] fwd_data, + output logic fwd_valid, + input logic fwd_ready); + +assign fwd_valid = axi.wvalid; +assign fwd_data = axi.wdata; +assign axi.wready = axi.wready; + +endmodule : mod_with_interface diff --git a/verilogpp_tests/non_ansi.v b/verilogpp_tests/non_ansi.v new file mode 100644 index 0000000..29da449 --- /dev/null +++ b/verilogpp_tests/non_ansi.v @@ -0,0 +1,31 @@ +// bar is just an empty module with some interesting ports. + +module non_ansi #( + parameter int ID = 0 +) ( + clk, + a, + b, + c, + y +); + +localparam WIDTH = 32; + +localparam BYTES = WIDTH/8; + +function int foo(int x, int y); + return x + y; +endfunction : foo + +input logic clk; + + +input wire [BYTES-1:0] a; +input wire b; +input wire [WIDTH-1:0] c; +output wire y; + +assign y = b; + +endmodule diff --git a/verilogpp_tests/preproc.manifest b/verilogpp_tests/preproc.manifest index 50d47e1..855e3f7 100644 --- a/verilogpp_tests/preproc.manifest +++ b/verilogpp_tests/preproc.manifest @@ -1,27 +1,55 @@ -02fed040f81efecf23e076a461026c60 ../verilogpp +e338047b09235c54a83d5626830dba9e ../verilogpp ffa007a4806acae2aa22fae129423ebb autocb.vpp -5be2abe0b78d2c7cf1159026d82aa5ef autoif.vpp +e650ff66cc1639b0412f5194bcbeb6f0 autoif.vpp +bcafe31cdbc3425c992abed300acfbcb autoif_v3.vpp +2081fa73bc3e07c4f327902e67365f1f autointerface_with_interface.vpp +9590c1ebb34580fbc1e73b575bb94d74 autonc.vpp +f87b0017fad53e4c8f74ce7950d325c9 autonc2.vpp +20ece7df3404d1bc3b8fc7b2f24670f6 autonc3.vpp +4313a969dcfa8480476ae6f251501a59 autonc4.vpp +adf4397b7b5c4594f27499fc4dd750b7 autonet_skipif.vpp d8bf9099c93900253867a09b87c975c1 bar.vpp f53ad3ace68d13b0cfa962509f7aac7e bus_keeper.v 875e79d3a02ca25709b43c4ec4d996e7 busthing.v +06ac85dcf869566b67f34896f8351c15 connect_from_array.vpp +cece23c49bbd061d58a1f2c7b2b93a9d connect_n_to_n.vpp +5051d9f9ec99ea0dab3ab26e55546565 connect_to_array.vpp +d458295df0234bb3d7dcbbc5c2d46ab6 drive_one.v +9d4a3e8dabb67d3793081a2ad47ff869 drive_two.v d965329fce21a475bbd102e30793200c foo.vpp 9953d47357b8895179b277cbbeec420e foreach.vpp 58099f68bbae4cead0f4515559337e47 forinst.vpp 4277c8e11642969680dd5534da726828 forinst_params.vpp 7e7937f60d93529d3d343c2594b994c4 fsm.vpp 446a4f65830a19a56d67daa984991188 hard2parse.v +d538a5583cdba57c4ebaeffa3bc1889b incdir_test.vpp +51ba5116e93d3252c007296324ffce94 inst_locparam.vpp +40601cad657d19cf7de45cdb08a1f827 inst_non_ansi.vpp +1ba43f8894525f9d5cac017303322b80 inst_of_mod_with_interface.vpp 802bb1901a42b4b1cb6baaa9eb9234b3 inst_of_signed_thing.vpp -550f431b378fd5d1c0fa6b255add0c59 inst_of_unpacked.vpp +fe40f665771b6330bafa41add7135570 inst_of_typed_module.vpp +bba772325acb574bf5f74edd944818d5 inst_of_unpacked.vpp 6341c22c6d129c027a73582aa5407208 instpretty.vpp +9e61861cb151968a07324288211f0603 instv2.vpp +47d6aa5b76eb296a91fbb90f0f2c2d73 instv3.vpp +4d568db3f89a79de93fb77cc20d69154 locparam.v 7c439f5cdf30af3f4ddac68d373127dd mark.vpp 3e14e1391b4efd60fabaf617a4e8709e missing_file.vpp +bc8627ca8d97ff3344ee3396b924d568 mod_with_interface.v ac8a33665c3df3cc3c4bf0dc59175d82 multiclock.v +cadd7d4192f7ff9e94faa7f2dde190fe non_ansi.v cbf93af9a193c10198bdee6728bb5418 parameter_substitution.vpp a1b6387c90958d801423d77dc8c9ba8e signed_thing.v +3faf1ce6740e70274b260824fd6325be sink_one.v +bfdf1016afd58f35cf9192800ddb48ef sink_two.v c549a383ecce9a0fef280d445212504d splitlines.vpp +1a8d1a7c8dc9c34f04cba346f62ae596 subdir/submodule.v +398635838df34237c456fc86d09a22f9 subdir/subpath/module_a.v +735aaebb6bd9f3200a086c6e444e40b8 subpaths_test.vpp a4efe1d1ce09ad84c12a1c35e179585b tostring.vpp a604c3d55b35d04a4e7a6219257c9b3f tostring2.vpp +6858761f16ba200bb5ce571df3cb171d typed_module.v 808aad7f7d9ae0e7a3758b1b41067ea9 unpacked.v 89638f917b75fef631024b26b72791c7 unpackedN.v -21a559ac37865107b52ad725fbaa4e51 verilogpp.fortest.rc -e4daacead06c815c55083597344a76eb warnings.vpp +ec1b851d9d6e13d81182d33b07875e92 verilogpp.fortest.rc +be60aa4fc7942effca1526f484dd8dcb warnings.vpp diff --git a/verilogpp_tests/preproc.manifest.expected b/verilogpp_tests/preproc.manifest.expected index 50d47e1..f70b6a0 100644 --- a/verilogpp_tests/preproc.manifest.expected +++ b/verilogpp_tests/preproc.manifest.expected @@ -1,27 +1,55 @@ -02fed040f81efecf23e076a461026c60 ../verilogpp +9ef4167253bde2fedc218c53e7a546fd ../verilogpp ffa007a4806acae2aa22fae129423ebb autocb.vpp -5be2abe0b78d2c7cf1159026d82aa5ef autoif.vpp +e650ff66cc1639b0412f5194bcbeb6f0 autoif.vpp +bcafe31cdbc3425c992abed300acfbcb autoif_v3.vpp +2081fa73bc3e07c4f327902e67365f1f autointerface_with_interface.vpp +9590c1ebb34580fbc1e73b575bb94d74 autonc.vpp +f87b0017fad53e4c8f74ce7950d325c9 autonc2.vpp +20ece7df3404d1bc3b8fc7b2f24670f6 autonc3.vpp +4313a969dcfa8480476ae6f251501a59 autonc4.vpp +adf4397b7b5c4594f27499fc4dd750b7 autonet_skipif.vpp d8bf9099c93900253867a09b87c975c1 bar.vpp f53ad3ace68d13b0cfa962509f7aac7e bus_keeper.v 875e79d3a02ca25709b43c4ec4d996e7 busthing.v +06ac85dcf869566b67f34896f8351c15 connect_from_array.vpp +cece23c49bbd061d58a1f2c7b2b93a9d connect_n_to_n.vpp +5051d9f9ec99ea0dab3ab26e55546565 connect_to_array.vpp +d458295df0234bb3d7dcbbc5c2d46ab6 drive_one.v +9d4a3e8dabb67d3793081a2ad47ff869 drive_two.v d965329fce21a475bbd102e30793200c foo.vpp 9953d47357b8895179b277cbbeec420e foreach.vpp 58099f68bbae4cead0f4515559337e47 forinst.vpp 4277c8e11642969680dd5534da726828 forinst_params.vpp 7e7937f60d93529d3d343c2594b994c4 fsm.vpp 446a4f65830a19a56d67daa984991188 hard2parse.v +d538a5583cdba57c4ebaeffa3bc1889b incdir_test.vpp +51ba5116e93d3252c007296324ffce94 inst_locparam.vpp +40601cad657d19cf7de45cdb08a1f827 inst_non_ansi.vpp +1ba43f8894525f9d5cac017303322b80 inst_of_mod_with_interface.vpp 802bb1901a42b4b1cb6baaa9eb9234b3 inst_of_signed_thing.vpp -550f431b378fd5d1c0fa6b255add0c59 inst_of_unpacked.vpp +fe40f665771b6330bafa41add7135570 inst_of_typed_module.vpp +bba772325acb574bf5f74edd944818d5 inst_of_unpacked.vpp 6341c22c6d129c027a73582aa5407208 instpretty.vpp +9e61861cb151968a07324288211f0603 instv2.vpp +47d6aa5b76eb296a91fbb90f0f2c2d73 instv3.vpp +4d568db3f89a79de93fb77cc20d69154 locparam.v 7c439f5cdf30af3f4ddac68d373127dd mark.vpp 3e14e1391b4efd60fabaf617a4e8709e missing_file.vpp +bc8627ca8d97ff3344ee3396b924d568 mod_with_interface.v ac8a33665c3df3cc3c4bf0dc59175d82 multiclock.v +cadd7d4192f7ff9e94faa7f2dde190fe non_ansi.v cbf93af9a193c10198bdee6728bb5418 parameter_substitution.vpp a1b6387c90958d801423d77dc8c9ba8e signed_thing.v +3faf1ce6740e70274b260824fd6325be sink_one.v +bfdf1016afd58f35cf9192800ddb48ef sink_two.v c549a383ecce9a0fef280d445212504d splitlines.vpp +1a8d1a7c8dc9c34f04cba346f62ae596 subdir/submodule.v +398635838df34237c456fc86d09a22f9 subdir/subpath/module_a.v +735aaebb6bd9f3200a086c6e444e40b8 subpaths_test.vpp a4efe1d1ce09ad84c12a1c35e179585b tostring.vpp a604c3d55b35d04a4e7a6219257c9b3f tostring2.vpp +6858761f16ba200bb5ce571df3cb171d typed_module.v 808aad7f7d9ae0e7a3758b1b41067ea9 unpacked.v 89638f917b75fef631024b26b72791c7 unpackedN.v -21a559ac37865107b52ad725fbaa4e51 verilogpp.fortest.rc -e4daacead06c815c55083597344a76eb warnings.vpp +ec1b851d9d6e13d81182d33b07875e92 verilogpp.fortest.rc +be60aa4fc7942effca1526f484dd8dcb warnings.vpp diff --git a/verilogpp_tests/sink_one.v b/verilogpp_tests/sink_one.v new file mode 100644 index 0000000..41610d8 --- /dev/null +++ b/verilogpp_tests/sink_one.v @@ -0,0 +1,8 @@ +module sink_one( + input logic foo +); + +logic lint_unused_signal; +assign lint_unused_signal = |{foo}; + +endmodule : drive_one diff --git a/verilogpp_tests/sink_two.v b/verilogpp_tests/sink_two.v new file mode 100644 index 0000000..de43ef1 --- /dev/null +++ b/verilogpp_tests/sink_two.v @@ -0,0 +1,8 @@ +module drive_one( + input logic [1:0] foo +); + +logic lint_unused_signal; +assign lint_unused_signal = |{foo}; + +endmodule : drive_one diff --git a/verilogpp_tests/subdir/submodule.v b/verilogpp_tests/subdir/submodule.v new file mode 100644 index 0000000..a1d2e45 --- /dev/null +++ b/verilogpp_tests/subdir/submodule.v @@ -0,0 +1,19 @@ +// the submodule says bloop bloop bloop + +module submodule #( + parameter ID = 0 +) ( + input wire clk, + input wire reset_n, + + input wire dive, + input wire ascend, + output logic [31:0] fathoms_deep +); + +clocking cb; + output wire THIS_SHOULD_NOT_SHOW_UP_IN_INTERFACE; + input wire NOR_SHOULD_THIS; +endclocking + +endmodule diff --git a/verilogpp_tests/subdir/subpath/module_a.v b/verilogpp_tests/subdir/subpath/module_a.v new file mode 100644 index 0000000..dd75058 --- /dev/null +++ b/verilogpp_tests/subdir/subpath/module_a.v @@ -0,0 +1,19 @@ +// the submodule says bloop bloop bloop + +module module_a #( + parameter ID = 0 +) ( + input wire clk, + input wire reset_n, + + input wire launch, + input wire abort, + output logic [31:0] altitude +); + +clocking cb; + output wire THIS_SHOULD_NOT_SHOW_UP_IN_INTERFACE; + input wire NOR_SHOULD_THIS; +endclocking + +endmodule diff --git a/verilogpp_tests/subpaths_test.vpp b/verilogpp_tests/subpaths_test.vpp new file mode 100644 index 0000000..eca30ef --- /dev/null +++ b/verilogpp_tests/subpaths_test.vpp @@ -0,0 +1,55 @@ +/**CONFIG + SUBPATH=subpath + SUBPATH=xyzzy +**/ +/*PPSTART*/ + +/*PPSTOP*/ + + +/**INST submodule.v sub0 --pretty**/ +/*PPSTART*/ +submodule sub0 ( + .clk (clk ) // input +, .reset_n (reset_n ) // input +, .dive (dive ) // input +, .ascend (ascend ) // input +, .fathoms_deep (fathoms_deep ) // output [31:0] +); +/*PPSTOP*/ + +/**INST module_a.v sub0 --pretty**/ +/*PPSTART*/ +module_a sub0 ( + .clk (clk ) // input +, .reset_n (reset_n ) // input +, .launch (launch ) // input +, .abort (abort ) // input +, .altitude (altitude ) // output [31:0] +); +/*PPSTOP*/ + +/**FORINST module_a.v sub 1 2 3 **/ +/*PPSTART*/ +module_a sub_1 ( + .clk (clk), + .reset_n (reset_n), + .launch (launch), + .abort (abort), + .altitude (altitude) +); +module_a sub_2 ( + .clk (clk), + .reset_n (reset_n), + .launch (launch), + .abort (abort), + .altitude (altitude) +); +module_a sub_3 ( + .clk (clk), + .reset_n (reset_n), + .launch (launch), + .abort (abort), + .altitude (altitude) +); +/*PPSTOP*/ diff --git a/verilogpp_tests/typed_module.v b/verilogpp_tests/typed_module.v new file mode 100644 index 0000000..1428343 --- /dev/null +++ b/verilogpp_tests/typed_module.v @@ -0,0 +1,18 @@ +// An example of a module with a parameterized type. + +module typed_moduled#(type TYPE_T = logic [255:0], + integer Mode = 0) ( + input logic clk, + input logic rst_n, + input TYPE_T fwd_data, + input logic fwd_valid, + output logic fwd_ready, + output TYPE_T rev_data, + output logic rev_valid, + input logic rev_ready); + +assign rev_data = fwd_data; +assign rev_valid = fwd_valid; +assign fwd_ready = rev_ready; + +endmodule : typed_module diff --git a/verilogpp_tests/verilogpp.fortest.rc b/verilogpp_tests/verilogpp.fortest.rc index df3c868..9b58623 100644 --- a/verilogpp_tests/verilogpp.fortest.rc +++ b/verilogpp_tests/verilogpp.fortest.rc @@ -6,7 +6,6 @@ extension_selects_language = 1 # use file extension to select between v2k/sv clock = clk reset_n = reset_n synchronous_reset = 1 # xilinx recommends synchronous reset -use_perforce = 0 register_delay = "" enable_footer = 0 generated_code_marker = "" diff --git a/verilogpp_tests/verilogpp_files.t b/verilogpp_tests/verilogpp_files.t index 3870dc7..0e331be 100755 --- a/verilogpp_tests/verilogpp_files.t +++ b/verilogpp_tests/verilogpp_files.t @@ -26,6 +26,7 @@ use strict; use Cwd 'abs_path'; use Test::More; use File::Basename; +use lib File::Basename::dirname(abs_path($0)); use File::Temp qw/ tempfile /; use test_utils; @@ -39,10 +40,18 @@ $expected_tests++; # run the preprocessor over everything in the test files directory: my @testfiles = glob(q(./*.vpp)); +print("argv len = $#ARGV\n"); +if ($#ARGV > -1) { + @testfiles = @ARGV; +} +print "Running ",join(" ", @testfiles),"\n"; my $rc = system($VPP, "--quieter", "-r", "--config=./verilogpp.fortest.rc", + "--incdir", "./subdir", + "--incdir", "./notasubdir", + "--incdir", ".", @testfiles); # we don't check return codes as some test files are expected to fail. @@ -65,12 +74,13 @@ sub VerifyFile($) { sub VerifyManifest() { $expected_tests += 2; # this method adds 2 checks ok(-e "./preproc.manifest", "preproc.manifest exists"); - my $rc = system("diff -c -I verilogpp\$ ./preproc.manifest{.expected,}"); + my $rc = system("diff -c -I verilogpp\$ ./preproc.manifest.expected ./preproc.manifest"); is($rc, 0, "preproc.manifest contains expected checksums"); } # invoke the preprocessor on these files: foreach my $testfile (@testfiles) { + print "-------\n"; VerifyFile($testfile); } diff --git a/verilogpp_tests/warnings.vpp b/verilogpp_tests/warnings.vpp index 37024f4..d58a525 100644 --- a/verilogpp_tests/warnings.vpp +++ b/verilogpp_tests/warnings.vpp @@ -24,6 +24,8 @@ reg [`HARD2PARSE_COMMAND_WORD] control_input; // WARNING: zero drivers wire [`HARD2PARSE_STATUS_WORD] control_output; // WARNING: zero load wire [15:0] data_to_foobar; // WARNING: zero load wire data_to_foobar_valid; // WARNING: zero load +reg [31:0] foo_in32; // WARNING: zero drivers +word_t foo_in_word; // WARNING: zero drivers reg foobar_clear_to_send; // WARNING: zero drivers wire foobar_ready_to_send; // WARNING: zero load wire [31:0] in32; @@ -100,5 +102,17 @@ hard2parse u_hard2parse ( ); /*PPSTOP*/ +/**INST bar.v u_bar9 --compact + s/^in/foo_in/; +**/ +/*PPSTART*/ +bar u_bar9 ( + .in_word (foo_in_word), + .clk, + .reset_n, + .in32 (foo_in32), + .out32 +); +/*PPSTOP*/ endmodule