Verilog-Perl-3.478/0000755000177100017500000000000014057150520014020 5ustar wsnyderwsnyderVerilog-Perl-3.478/README0000644000177100017500000002702014056561160014706 0ustar wsnyderwsnyderNAME Verilog-Perl - Overview of Verilog language packages for Perl DESCRIPTION The Verilog-Perl distribution provides Perl parsing and utilities for the Verilog Language. This file provides an overview of the distribution. Verilog-Perl is currently a mature tool. Bugs are fixed and IEEE language capabilities updated as needed, but the basic features and API are not expected to change. For general information see . For specific details on each component, see that component's manpage. You may also want to try the AUTO features present in Verilog-Mode. SCRIPTS The following scripts are installed by Verilog-Perl: vhier Vhier reads the Verilog files passed on the command line and outputs a tree of all of the filenames, modules, and cells referenced by that file. vpassert Vpassert will read the specified Verilog files and preprocess special PLI assertions. vppreproc Vppreproc (Verilog-Perl Pre Processor) reads the Verilog files passed on the command line and outputs preprocessed output. vrename Vrename will allow a signal to be changed across all levels of the design hierarchy, or to create a cross reference of signal names. PACKAGES Verilog::Getopt Verilog::Getopt provides standardized handling of options similar to Verilog/VCS and cc/GCC. Verilog::Language Verilog::Language provides general utilities for using the Verilog Language, such as parsing numbers or determining what keywords exist. Verilog::Netlist Verilog::Netlist reads and holds interconnect information about a whole design database. Verilog::Netlist::Cell A Verilog::Netlist::Cell object is created by Verilog::Netlist for every instantiation in the current module. Verilog::Netlist::ContAssign A Verilog::Netlist::ContAssign object is created by Verilog::Netlist for every continuous assignment in the current module. Verilog::Netlist::File Verilog::Netlist::File allows Verilog::Netlist objects to be read and written in Verilog format. Verilog::Netlist::Module A Verilog::Netlist::Module object is created by Verilog::Netlist for every module in the design. Verilog::Netlist::Net A Verilog::Netlist::Net object is created by Verilog::Netlist::Module for every signal and input/output declaration in the current module. Verilog::Netlist::Pin A Verilog::Netlist::Pin object is created by Verilog::Netlist::Cell for for each pin connection on a cell. Verilog::Netlist::Port A Verilog::Netlist::Port object is created by Verilog::Netlist::Module for every port connection in the module. Verilog::Netlist::Subclass The Verilog::Netlist::Subclass is used as a base class for all Verilog::Netlist::* structures. Verilog::Parser Verilog::Parser will tokenize a Verilog file and invoke various callback methods. Verilog::Preproc Verilog::Preproc reads Verilog files, and preprocesses them according to the Verilog specification. Programs can be easily converted from reading a IO::File into reading preprocessed output from Verilog::Preproc. Verilog::SigParse Verilog::SigParser builds upon the Verilog::Parser package to provide callbacks for when a signal is declared, a module instantiated, or a module defined. WHICH PARSER PACKAGE? If you are starting a new application which needs to parse the Verilog language you have several tools available to you. Which you pick depends on how low level and complete the information you need is. VParseBison.y The low level VParse* source files may be of use when you need a starting point for your own a full C++ SystemVerilog grammar parser, using Bison and Flex. It understands most of the SystemVerilog 2017 grammar (1800-2017 Appendix A). Verilog::Preproc Verilog::Preproc is useful when you need only post-preprocessed text output, or a list of defines, includes, etc. It can preprocess a file, or be used to provide the Verilog macro language on top of synthesis scripts. It understands and implements all preprocessor features of SystemVerilog 2017. Verilog::Parser Verilog::Parser is useful when you need to tokenize or write source filters (where you need everything including whitespace). It can take raw files, or preprocessed input, and generates callbacks. It understands all SystemVerilog 2017 keywords. Abstract Syntax Tree Verilog::Parser knows enough to make a complete Abstract Syntax Tree (AST) of Verilog syntax. This represents all major constructs such as a "module" as a data structure, but does not interconnect the AST nodes as would be needed to follow signals. Not all keywords have been implemented; many are parsed but otherwise ignored. A complete Ast tree would allow any arbitrary transformation of Verilog syntax (everything is known excluding whitespace). For these applications consider Verilator's XML output (below). Verilog::SigParser Verilog::SigParser is useful when you need a list of modules, signals, ports, functions, etc. It requires a preprocessed file (from Verilog::Preproc), and can parse all SystemVerilog 2017 files, but only provides callbacks on certain interesting things. The SigParser operates only on a file at a time; it does not interconnect signals nor perform any elaboration (resolution of parameters). Verilog::Netlist Verilog::Netlist is useful for when you need the hierarchy, and a list of signals per module, pins per cell, etc. It builds upon the output of Verilog::SigParser, so requires preprocessed files (from Verilog::Preproc). It parses all SystemVerilog 2017 files, but not all SystemVerilog constructs are loaded into objects. Verilog::Netlist interconnects modules with instantiations but does not perform any elaboration (resolution of parameters). VPI Using the VPI is the best way to access the behavior of the design. It is not part of this package as it requires a compliant simulator and C++ code to call the VPI, and understands as much of the language as the simulator supports. This allows writing lint checks and full knowledge of all parts of the code. The VPI can operate ONLY on an elaborated design (where all parameters are resolved). Walking a VPI tree general requires a good deal of work compared to simple scripting (though little work compared to writing a parser from scratch). Verilator The Verilator program also contains a very similar front end as Verilog-Perl and can create XML output showing the abstract syntax tree. Verilator also understands how to elaborate and connect complex pins and types, but supports mostly only the synthesis subset of SystemVerilog. If you're looking to parse only synthesizable code this is the recommended route. Verilog-Mode for Emacs Although not a parser, a common requested use of Verilog-Perl is to automatically make shell modules and interconnect modules. Verilog-Mode is a better solution to this problem, as it results in completely portable code; the program (Verilog-Mode) isn't needed for others to update the design. It's also in very common usage, including by many IP providers. INSTALLATION Skip this section if Verilog-Perl has already been installed. Verilog-Perl should run on any system with Perl, G++, Flex, and Bison. It is known to work on most Linux distributions, plus Cygwin. You may install using either CPAN, or the sources. If you plan to do any development on Verilog-Perl, use the sources. CPAN Installation Option 1: Easiest installation is using the "CPAN" command line that comes with Perl. After configuring CPAN the first time, simply cpan install Verilog-Perl # And see the documentation man Verilog-Perl # Or, sometimes the capitalization is changed man verilog-perl Read the rest of this file for details on the programs provided. Manual Installation from Repository Option 2: Build any version using the source development repository with: git clone http://git.veripool.org/git/Verilog-Perl # Only first time cd Verilog-Perl git pull # Make sure we're up-to-date git tag # See what versions exist (recent GITs only) #git checkout master # Use development branch (e.g. recent bug fix) #git checkout stable # Use most recent release #git checkout v{version} # Switch to specified release version perl Makefile.PL # Ignore warning about README, this file will be generated make make test make install Read the rest of this file for details on the programs provided. FAQ Why do I get "unexpected `do'" or "unexpected `bit'" errors? Do, bit, ref, return, and other words are now SystemVerilog keywords. You should change your code to not use them to insure it works with newer tools. Alternatively, surround them by the Verilog 2005/SystemVerilog begin_keywords pragma to indicate Verilog 2001 code. `begin_keywords "1364-2001" integer bit; initial bit = 1; `end_keywords Alternatively use the --language (for vhier) or Verilog::Language::language_standard call to specify "1364-2001", or for really old code, "1364-1995". But, again, you really should fix the Verilog code. With Verilog::Netlist how do I resolve signal widths that include parameters down to constants? Unfortunately parameter resolution is part of elaboration. Verilog-Perl doesn't do elaboration as it requires a good fraction of a complete simulator implementation. Many applications can work around this limitation, if yours still requires elaboration you're stuck with using Verilator or the VPI, see the sections above. DISTRIBUTION Verilog-Perl is part of the free Verilog EDA software tool suite. The latest version is available from CPAN and from . Copyright 2000-2021 by Wilson Snyder. This package is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. This code is provided with no warranty of any kind, and is used entirely at your own risk. AUTHORS Wilson Snyder SEE ALSO vhier, vpassert, vppreproc, vrename Verilog::EditFiles, Verilog::Getopt, Verilog::Language Verilog::Netlist, Verilog::Parser, Verilog::Preproc, Verilog::SigParser Verilog::Netlist::Cell, Verilog::Netlist::ContAssign, Verilog::Netlist::File, Verilog::Netlist::Interface, Verilog::Netlist::ModPort, Verilog::Netlist::Module, Verilog::Netlist::Net, Verilog::Netlist::Pin, Verilog::Netlist::Port, Verilog::Netlist::Subclass, And the Verilog-Mode package for Emacs. Verilog-Perl-3.478/META.yml0000644000177100017500000000141714057150455015303 0ustar wsnyderwsnyder--- #YAML:1.0 name: Verilog-Perl version: 3.478 version_from: Language.pm abstract: Verilog language utilities and parsing license: perl installdirs: site author: - Wilson Snyder resources: homepage: https://www.veripool.org/verilog-perl bugtracker: https://www.veripool.org/verilog-perl/issues requires: Pod::Usage: 1.34 Data::Dumper: 1 warnings: 1 build_requires: Digest::SHA: 0 Test: 1 Test::More: 0 Time::HiRes: 1 meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 distribution_type: module generated_by: hand Verilog-Perl-3.478/Netlist/0000755000177100017500000000000014057150520015442 5ustar wsnyderwsnyderVerilog-Perl-3.478/Netlist/Net.pm0000644000177100017500000002762214057150455016546 0ustar wsnyderwsnyder# Verilog - Verilog Perl Interface # See copyright, etc in below POD section. ###################################################################### package Verilog::Netlist::Net; use Verilog::Netlist; use Verilog::Netlist::Subclass; use vars qw($VERSION @ISA); use strict; @ISA = qw(Verilog::Netlist::Net::Struct Verilog::Netlist::Subclass); $VERSION = '3.478'; my %_Type_Widths = ( 'bit' => 1, 'byte' => 8, 'genvar' => 32, 'integer' => 32, 'localparam'=> 32, 'logic' => 1, 'longint' => 64, 'parameter' => 32, 'reg' => 1, 'shortint' => 16, 'supply0' => 1, 'supply1' => 1, 'tri' => 1, 'tri0' => 1, 'tri1' => 1, 'triand' => 1, 'trior' => 1, 'trireg' => 1, 'wand' => 1, 'wire' => 1, 'wor' => 1, ); my %_Type_Accessors = ( 'genvar' => 'decl_type', 'localparam'=> 'decl_type', 'parameter' => 'decl_type', 'var' => 'decl_type', # Not in old version, but for completeness #'port' => 'decl_type', # Internals - Look at Port (input/output/inout/ref) #'net' => 'decl_type', # Internals - Look at net_type (wire/tri/...) # 'supply0' => 'net_type', 'supply1' => 'net_type', 'tri' => 'net_type', 'tri0' => 'net_type', 'tri1' => 'net_type', 'triand' => 'net_type', 'trior' => 'net_type', 'trireg' => 'net_type', 'wand' => 'net_type', 'wire' => 'net_type', 'wor' => 'net_type', # 'bit' => 'data_type', 'byte' => 'data_type', 'chandle' => 'data_type', 'event' => 'data_type', 'int' => 'data_type', 'integer' => 'data_type', 'logic' => 'data_type', 'longint' => 'data_type', 'real' => 'data_type', 'realtime' => 'data_type', 'reg' => 'data_type', 'shortint' => 'data_type', 'shortreal' => 'data_type', 'string' => 'data_type', 'time' => 'data_type', ); ###################################################################### structs('_new_base', 'Verilog::Netlist::Net::Struct' =>[name => '$', #' # Name of the net filename => '$', #' # Filename this came from lineno => '$', #' # Linenumber this came from userdata => '%', # User information attributes => '%', #' # Misc attributes for systemperl or other processors # data_type => '$', #' # SystemVerilog Type (logic/integer/reg [3:0] etc) decl_type => '$', #' # Declaration type (parameter/genvar/port/net etc) net_type => '$', #' # Net type (wire/tri/supply0 etc) comment => '$', #' # Comment provided by user array => '$', #' # Vector module => '$', #' # Module, Program or Interface entity belongs to signed => '$', #' # True if signed value => '$', #' # For parameters, the value of the parameter # below only after links() port => '$', #' # Reference to port connected to msb => '$', #' # MSB of signal (if known) lsb => '$', #' # LSB of signal (if known) stored_lsb => '$', #' # Bit number of signal stored in bit 0 (generally lsb) _used_in => '$', #' # Driver count onto signal _used_out => '$', #' # Receiver count on signal _used_inout => '$', #' # Bidirect count on signal # SystemPerl only: below only after autos() simple_type => '$', #' # True if is uint (as opposed to sc_signal) sp_traced => '$', #' # Created by SP_TRACED sp_autocreated => '$', #' # Created by /*AUTOSIGNAL*/ ]); sub new { my $class = shift; my %params = @_; my $self = $class->_new_base(%params); $self->type($params{type}) if $params{type}; # Backward compatibility return $self; } sub delete { my $self = shift; my $h = $self->module->_nets; delete $h->{$self->name}; return undef; } ###################################################################### sub logger { return $_[0]->netlist->logger; } sub netlist { return $_[0]->module->netlist; } sub _used_in_inc { $_[0]->_used_in(1+($_[0]->_used_in()||0)); } sub _used_out_inc { $_[0]->_used_out(1+($_[0]->_used_out()||0)); } sub _used_inout_inc { $_[0]->_used_inout(1+($_[0]->_used_inout()||0)); } sub _used_in_dec { return if !$_[0]->_used_in(); $_[0]->_used_in(-1+$_[0]->_used_in()); } sub _used_out_dec { return if !$_[0]->_used_out(); $_[0]->_used_out(-1+$_[0]->_used_out()); } sub _used_inout_dec { return if !$_[0]->_used_inout(); $_[0]->_used_inout(-1+$_[0]->_used_inout()); } sub stored_lsb { defined $_[0]->SUPER::stored_lsb ? $_[0]->SUPER::stored_lsb : $_[0]->lsb; } sub width { my $self = shift; # Return bit width (if known) my $dt = $self->data_type; $dt="" if $dt eq "signed"; if (defined $self->msb && defined $self->lsb) { return (abs($self->msb - $self->lsb) + 1); } elsif (my $width = $_Type_Widths{$dt || $self->net_type || $self->decl_type}) { return $width; } return undef; } sub type { my $self = shift; my $flag = shift; if (defined $flag) { if (my $acc = $_Type_Accessors{$flag}) { if ($acc eq 'decl_type') { $self->decl_type($flag); } elsif ($acc eq 'net_type') { $self->net_type($flag); } else { $self->data_type($flag); } } else { $self->data_type($flag); } } my $dt = $self->data_type; $dt="" if $dt && $dt eq "signed"; return $dt || $self->net_type || $self->decl_type; } ###################################################################### sub _link {} sub lint { my $self = shift; # Sequential logic may gen/use a signal, so we have to be a little sloppy if (0&&$self->_used_inout() && $self->_used_out() && !$self->array()) { # if an array, different outputs might hit different bits $self->warn("Signal is used as both a inout and output: ",$self->name(), "\n"); $self->dump_drivers(8); } elsif ($self->_used_out()) { if ($self->_used_out()>1 # if an array, different outputs might hit different bits && !$self->array() # if vector, warn only if # of usages is higher than # of bits in vector && (abs($self->msb() - $self->lsb()) + 1) < $self->_used_out()) { $self->warn("Signal has multiple drivers (", $self->_used_out(),"): ",$self->name(), "\n"); $self->dump_drivers(8); } } if (0&&$self->_used_in() && !$self->_used_out()) { $self->warn("Signal has no drivers: ",$self->name(), "\n"); } if (0&&$self->_used_out() && !$self->_used_in() && $self->name() !~ /unused/) { $self->dump(5); $self->port->dump(10) if $self->port; $self->warn("Signal is not used (or needs signal declaration): ",$self->name(), "\n"); flush STDOUT; flush STDERR; } } ###################################################################### ## Outputters sub _decls { my $self = shift; my $out = $self->net_type || $self->decl_type; if ($self->port) { $out = "input" if $self->port->direction eq "in"; $out = "output" if $self->port->direction eq "out"; $out = "inout" if $self->port->direction eq "inout"; } return $out; } sub verilog_text { my $self = shift; my @out; foreach my $decl ($self->_decls) { push @out, $decl; push @out, " ".$self->data_type if $self->data_type; push @out, " ".$self->name; push @out, " ".$self->array if $self->array; push @out, " = ".$self->value if defined $self->value && $self->value ne ''; push @out, ";"; push @out, " ".$self->comment if defined $self->comment && $self->comment ne ''; } return (wantarray ? @out : join('',@out)); } sub dump { my $self = shift; my $indent = shift||0; print " "x$indent,"Net:",$self->name() ," ",($self->_used_in() ? "I":""),($self->_used_out() ? "O":""), ," DeclT:",$self->decl_type||'' ," NetT:",$self->net_type||'' ," DataT:",$self->data_type||'' ," Array:",$self->array()||''; print " ",($self->msb).":".($self->lsb) if defined $self->msb; print " Value:",$self->value if defined $self->value && $self->value ne ''; print "\n"; } sub dump_drivers { my $self = shift; my $indent = shift||0; print " "x$indent,"Net:",$self->name,"\n"; if (my $port = $self->port) { print " "x$indent," Port: ",$port->name," ",$port->direction,"\n"; } foreach my $cell ($self->module->cells_sorted) { foreach my $pin ($cell->pins_sorted) { foreach my $net ($pin->nets) { next unless defined $net->{net}; if ($pin->port && $net->{net} == $self) { print " "x$indent," Pin: ",$cell->name,".",$pin->name ," ",$pin->port->direction,"\n"; } elsif ($self->name eq $net->{net}->name) { warn "%Warning: Internal net name duplicate: ".$cell->name." ".$self->name."\n" .$self->comment." ".$net->{net}->comment."\n" ."$self ".$net->{net}->name."\n"; } } } } flush STDERR; flush STDOUT; } ###################################################################### #### Package return 1; __END__ =pod =head1 NAME Verilog::Netlist::Net - Net for a Verilog Module =head1 SYNOPSIS use Verilog::Netlist; ... my $net = $module->find_net('signalname'); print $net->name; =head1 DESCRIPTION A Verilog::Netlist::Net object is created by Verilog::Netlist::Module for every signal and input/output declaration, and parameter in the current module. =head1 ACCESSORS See also Verilog::Netlist::Subclass for additional accessors and methods. =over 4 =item $self->array Any array (vector) declaration for the net. This is for Verilog 2001 multidimensional signals; for the width of a signal, use msb/lsb/width. For newer applications use data_type() as it supports SystemVerilog types. =item $self->comment Returns any comments following the definition. keep_comments=>1 must be passed to Verilog::Netlist::new for comments to be retained. =item $self->data_type The data type of the net. This may be a data type keyword ("integer", "logic", etc), user defined type from a type def, a range ("[11:0]", "signed [1:0]" or "" for an implicit wire. =item $self->decl_type How the net was declared. A declaration keyword ("genvar", "localparam", "parameter", "var") or "port" if only as a port - and see the port method, or "net" - and see the net_type method. =item $self->module Reference to the Verilog::Netlist::Module or Verilog::Netlist::Interface the net is under. =item $self->lsb The least significant bit number of the net. =item $self->msb The most significant bit number of the net. =item $self->name The name of the net. =item $self->net_type The net type, if one applies. Always a net type keyword ('supply0', 'supply1', 'tri', 'tri0', 'tri1', 'triand', 'trior', 'trireg', 'wand', 'wire', 'wor'). =item $self->type The type function is provided for backward compatibility to Verilog-Perl versions before 3.200. Applications should change to use data_type() and/or decl_type() instead. The type function returns an agglomeration of data_type, net_type and decl_type that worked ok in Verilog, but does not work with SystemVerilog. Calls to type() will be converted to calls to data_type, decl_type or net_type in a way that attempts to maintain backward compatibility, however compatibility is not always possible. =item $self->value If the net's type is 'parameter', the value from the parameter's declaration. =item $self->width The width of the net in bits. =back =head1 MEMBER FUNCTIONS See also Verilog::Netlist::Subclass for additional accessors and methods. =over 4 =item $self->lint Checks the net for errors. Normally called by Verilog::Netlist::lint. =item $self->dump Prints debugging information for this net. =item $self->dump_drivers Prints debugging information for this net, and all pins driving the net. =back =head1 DISTRIBUTION Verilog-Perl is part of the L free Verilog EDA software tool suite. The latest version is available from CPAN and from L. Copyright 2000-2021 by Wilson Snyder. This package is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. =head1 AUTHORS Wilson Snyder =head1 SEE ALSO L, L L =cut Verilog-Perl-3.478/Netlist/Subclass.pm0000644000177100017500000002117414057150455017573 0ustar wsnyderwsnyder# Verilog - Verilog Perl Interface # See copyright, etc in below POD section. ###################################################################### package Verilog::Netlist::Subclass; use Scalar::Util qw(weaken); use Carp; use Verilog::Netlist::Logger; require Exporter; use base qw(Exporter); use vars qw($VERSION @EXPORT); use strict; $VERSION = '3.478'; @EXPORT = qw(structs); # Maybe in the future. For now all users of this must do it themselves #struct ('Verilog::Netlist::Subclass' # =>[name => '$', #' # Name of the element # filename => '$', #' # Filename this came from # lineno => '$', #' # Linenumber this came from # logger => '%', # Logger object, or undef # userdata => '%', # User information # ]); ###################################################################### #### Member functions sub fileline { my $self = shift; return ($self->filename||"").":".($self->lineno||""); } ###################################################################### #### Error Handling our $_Subclass_Logger_Warned; sub logger { my $self = shift; # This provides forward compatibility to derived classes written before # Verilog-Perl 3.041. At some point this function will be removed; all # new derived classes should provide an override for this function. if (!$_Subclass_Logger_Warned) { warn "-Info: Object class missing logger method, update the package?: ".ref($self)."\n"; $_Subclass_Logger_Warned = Verilog::Netlist::Logger->new(); } return $_Subclass_Logger_Warned; } sub errors { my $self = shift; return $self->logger->errors; } sub warnings { my $self = shift; return $self->logger->warnings; } # Methods sub info { my $self = shift; my $objref = $self; $objref = shift if ref $_[0]; # Optional reference to object $self->logger->info($objref,@_); } sub warn { my $self = shift; my $objref = $self; $objref = shift if ref $_[0]; # Optional reference to object $self->logger->warn($objref,@_); } sub error { my $self = shift; my $objref = $self; $objref = shift if ref $_[0]; # Optional reference to object $self->logger->error($objref,@_); } sub exit_if_error { my $self = shift; return $self->logger->exit_if_error(@_); } sub unlink_if_error { my $self = shift; # Not documented; Depreciated in Verilog-Perl 3.041. # Applications should call the logger object's unlink_if_error directly. return $self->logger->unlink_if_error(@_); } ###################################################################### ###################################################################### ###################################################################### # # Prior to perl 5.6, Class::Struct's new didn't bless the arguments, # or allow parameter initialization! Later versions didn't support weak # references. # This code is thus from Class::Struct, copyright under the Artistic license sub structs { my $func = shift; my $baseclass = $_[0]; # Determine parameter list structure, one of: # struct (class => [ element-list ]) my ($class, @decls); my $base_type = ref $_[1]; if ($base_type eq 'ARRAY') { $class = shift; @decls = @{shift()}; confess "structs usage error" if @_; } else { confess "structs usage error"; } confess "structs usage error" if @decls % 2 == 1; # Create constructor. croak "function 'new' already defined in package $class" if do { no strict 'refs'; defined &{$class . "::new"} }; my @methods = (); my %refs = (); my %arrays = (); my %hashes = (); my %types; my $got_class = 0; my $out = ''; $out .= "{\n package $class;\n use Carp;\n"; $out .= " use Scalar::Util qw(weaken);\n\n"; $out .= " sub new {\n"; $out .= " my (\$class, \%init) = \@_;\n"; $out .= " \$class = __PACKAGE__ unless \@_;\n"; my $cnt = 0; my ($cmt, $elem); if ($base_type eq 'ARRAY') { $out .= " my(\$r) = [];\n"; } for (my $idx=0; $idx < @decls; $idx+=2) { my $name = $decls[$idx]; my $type = $decls[$idx+1]; $types{$name} = $type; push (@methods, $name); if ($base_type eq 'ARRAY') { $elem = "[$cnt]"; ++$cnt; $cmt = " # $name"; } if ($type =~ /^\*(.)/) { $refs{$name}++; $type = $1; } my $init = "defined(\$init{'$name'}) ? \$init{'$name'} :"; if ($type eq '@') { $out .= " croak 'Initializer for $name must be array reference'\n"; $out .= " if defined(\$init{'$name'}) && ref(\$init{'$name'}) ne 'ARRAY';\n"; $out .= " \$r->$elem = $init [];$cmt\n"; $arrays{$name}++; } elsif ($type eq '%') { $out .= " croak 'Initializer for $name must be hash reference'\n"; $out .= " if defined(\$init{'$name'}) && ref(\$init{'$name'}) ne 'HASH';\n"; $out .= " \$r->$elem = $init {};$cmt\n"; $hashes{$name}++; } elsif ($type eq '$') { $out .= " \$r->$elem = $init undef;$cmt\n"; } else{ croak "'$type' is not a valid struct element type"; } } $out .= " bless \$r, \$class;\n }\n"; # Create accessor methods. my ($pre, $pst, $sel); $cnt = 0; foreach my $name (@methods) { my $type = $types{$name}; if (do { no strict 'refs'; defined &{$class . "::$name"} }) { warnings::warnif("function '$name' already defined, overrides struct accessor method"); } else { $pre = $pst = $cmt = $sel = ''; if (defined $refs{$name}) { $pre = "\\("; $pst = ")"; $cmt = " # returns ref"; } $out .= " sub $name {$cmt\n my \$r = shift;\n"; if ($base_type eq 'ARRAY') { $elem = "[$cnt]"; ++$cnt; } if (defined $arrays{$name}) { $out .= " my \$i;\n"; $out .= " \@_ ? (\$i = shift) : return \$r->$elem;\n"; $out .= " if (ref(\$i) eq 'ARRAY' && !\@_) { \$r->$elem = \$i; return \$r }\n"; $sel = "->[\$i]"; } elsif (defined $hashes{$name}) { $out .= " my \$i;\n"; $out .= " \@_ ? (\$i = shift) : return \$r->$elem;\n"; $out .= " if (ref(\$i) eq 'HASH' && !\@_) { \$r->$elem = \$i; return \$r }\n"; $sel = "->{\$i}"; } $out .= " croak 'Too many args to $name' if \@_ > 1;\n"; $out .= " \@_ ? ($pre\$r->$elem$sel = shift$pst) : $pre\$r->$elem$sel$pst;\n"; $out .= " }\n"; } } #print $out; $out .= "}\n1;\n"; my $result = eval $out; carp $@ if $@; # Create top class (my $overclass = $baseclass) =~ s/::Struct$//; { #print \"NEW \",join(' ',\@_),\"\\n\"; eval " package $overclass; sub ${func} { my \$class = shift; my \$self = new $baseclass(\@_); bless \$self, \$class; }"; } } ###################################################################### #### Package return 1; __END__ =pod =head1 NAME Verilog::Netlist::Subclass - Common routines for all classes =head1 SYNOPSIS package Verilog::Netlist::Something; use Verilog::Netlist::Subclass; use base qw(Verilog::Netlist::Subclass); ... $self->info("We're here\n"); $self->warn("Things look bad\n"); $self->error("Things are even worse\n"); $self->exit_if_error(); =head1 DESCRIPTION The Verilog::Netlist::Subclass is used as a base class for all Verilog::Netlist::* structures. It is mainly used so that $self->warn() and $self->error() will produce consistent results. =head1 MEMBER FUNCTIONS =over 4 =item $self->error(I) Print an error in a standard format. =item $self->errors() Return number of errors detected. =item $self->exit_if_error() Exits the program if any errors were detected. =item $self->filename() The filename number the entity was created in. =item $self->info(I) Print a informational in a standard format. =item $self->lineno() The line number the entity was created on. =item $self->logger() The class to report errors using, generally a Verilog::Netlist::Logger object. =item $self->userdata(I) =item $self->userdata(I, I) Sets (with two arguments) or retrieves the specified key from an opaque hash. This may be used to store application data on the specified node. =item $self->warn(I) Print a warning in a standard format. =item $self->warnings() Return number of warnings detected. =back =head1 DISTRIBUTION Verilog-Perl is part of the L free Verilog EDA software tool suite. The latest version is available from CPAN and from L. Copyright 2000-2021 by Wilson Snyder. This package is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. =head1 AUTHORS Wilson Snyder =head1 SEE ALSO L, L =cut Verilog-Perl-3.478/Netlist/ModPort.pm0000644000177100017500000001564114057150455017402 0ustar wsnyderwsnyder# Verilog - Verilog Perl Modport # See copyright, etc in below POD section. ###################################################################### package Verilog::Netlist::ModPort; use Verilog::Netlist; use Verilog::Netlist::Net; use Verilog::Netlist::Subclass; use vars qw($VERSION @ISA); use strict; @ISA = qw(Verilog::Netlist::ModPort::Struct Verilog::Netlist::Subclass); $VERSION = '3.478'; structs('new', 'Verilog::Netlist::ModPort::Struct' =>[name => '$', #' # Name of the module filename => '$', #' # Filename this came from lineno => '$', #' # Linenumber this came from module => '$', #' # Interface is a member of userdata => '%', # User information attributes => '%', #' # Misc attributes for systemperl or other processors # comment => '$', #' # Comment provided by user _ports => '%', # hash of Verilog::Netlist::Ports _portsordered=> '@', # list of Verilog::Netlist::Ports as ordered in list of ports _nets => '%', # hash of Verilog::Netlist::Nets ]); sub delete { my $self = shift; foreach my $oref ($self->nets) { $oref->delete; } foreach my $oref ($self->ports) { $oref->delete; } my $h = $self->module->{_modports}; delete $h->{$self->name}; return undef; } ###################################################################### sub netlist { return $_[0]->module->netlist; } sub is_top {} # Ignored, for module compatibility sub keyword { return 'modport'; } sub logger { return $_[0]->netlist->logger; } sub find_net { my $self = shift; my $search = shift; my $rtn = $self->_nets->{$search}||""; #print "FINDNET ",$self->name, " SS $search $rtn\n"; return $self->_nets->{$search} || $self->_nets->{"\\".$search." "}; } sub find_port { my $self = shift; my $search = shift; return $self->_ports->{$search} || $self->_ports->{"\\".$search." "}; } sub find_port_by_index { my $self = shift; my $myindex = shift; # @{$self->_portsordered}[$myindex-1] returns the name of # the port in the module at this index. Then, this is # used to find the port reference via the port hash return $self->_ports->{@{$self->_portsordered}[$myindex-1]}; } sub attrs_sorted { return (sort {$a cmp $b} @{$_[0]->attrs}); } sub nets { return (values %{$_[0]->_nets}); } sub nets_sorted { return (sort {$a->name() cmp $b->name()} (values %{$_[0]->_nets})); } sub ports { return (values %{$_[0]->_ports}); } sub ports_sorted { return (sort {$a->name() cmp $b->name()} (values %{$_[0]->_ports})); } sub ports_ordered { my $self = shift; return map {$self->_ports->{$_}} @{$self->_portsordered}; } sub nets_and_ports_sorted { return Verilog::Netlist::Module::nets_and_ports_sorted(@_); } sub new_attr { my $self = shift; my $clean_text = shift; push @{$self->attrs}, $clean_text; } sub new_net { my $self = shift; # @_ params # Create a new net under this my $netref = new Verilog::Netlist::Net(direction=>'net', data_type=>'wire', @_, module=>$self, ); $self->_nets($netref->name(), $netref); return $netref; } sub new_port { my $self = shift; # @_ params # Create a new port under this module my $portref = new Verilog::Netlist::Port(@_, module=>$self,); $self->_ports($portref->name(), $portref); return $portref; } sub _link { my $self = shift; # Ports create nets, so link ports before nets foreach my $oref ($self->ports) { $oref->_link(); } } sub lint { my $self = shift; if ($self->netlist->{use_vars}) { foreach my $oref ($self->ports) { $oref->lint(); } } } sub verilog_text { my $self = shift; my @out = "modport ".$self->name." (\n"; my $indent = " "; # Port list my $comma=""; push @out, $indent; foreach my $oref ($self->ports_sorted) { push @out, $comma, $oref->verilog_text; $comma = ", "; } push @out, ");\n"; push @out, "endmodport\n"; return (wantarray ? @out : join('',@out)); } sub dump { my $self = shift; my $indent = shift||0; my $norecurse = shift; print " "x$indent,"ModPort:",$self->name()," File:",$self->filename(),"\n"; if (!$norecurse) { foreach my $oref ($self->ports_sorted) { $oref->dump($indent+2); } } } ###################################################################### #### Package return 1; __END__ =pod =head1 NAME Verilog::Netlist::ModPort - ModPort within a Verilog Interface =head1 SYNOPSIS use Verilog::Netlist; ... my $interface = $netlist->find_interface('name'); my $modport = $interface->find_modport('name') =head1 DESCRIPTION A Verilog::Netlist::ModPort object is created by Verilog::Netlist::Interface for every modport under the interface. =head1 METHODS See also Verilog::Netlist::Subclass for additional accessors and methods. =over 4 =item $self->comment Returns any comments following the definition. keep_comments=>1 must be passed to Verilog::Netlist::new for comments to be retained. =item $self->dump Prints debugging information for this modport. =item $self->find_port(I) Returns Verilog::Netlist::Net matching given name. =item $self->find_port_by_index Returns the port name associated with the given index. =item $self->module Returns Verilog::Netlist::Interface the ModPort belongs to. =item $self->lint Checks the modport for errors. =item $self->name The name of the modport. =item $self->netlist Reference to the Verilog::Netlist the modport is under. =item $self->nets Returns list of references to Verilog::Netlist::Net in the interface. =item $self->nets_sorted Returns list of name sorted references to Verilog::Netlist::Net in the interface. =item $self->nets_and_ports_sorted Returns list of name sorted references to Verilog::Netlist::Net and Verilog::Netlist::Port in the modport. =item $self->ports Returns list of references to Verilog::Netlist::Port in the modport. =item $self->ports_ordered Returns list of references to Verilog::Netlist::Port in the modport sorted by pin number. =item $self->ports_sorted Returns list of references to Verilog::Netlist::Port in the modport sorted by name. =item $self->verilog_text Returns verilog code which represents this modport. Returned as an array that must be joined together to form the final text string. The netlist must be already ->link'ed for this to work correctly. =back =head1 DISTRIBUTION Verilog-Perl is part of the L free Verilog EDA software tool suite. The latest version is available from CPAN and from L. Copyright 2000-2021 by Wilson Snyder. This package is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. =head1 AUTHORS Wilson Snyder =head1 SEE ALSO L, L L L =cut Verilog-Perl-3.478/Netlist/Cell.pm0000644000177100017500000001730714057150455016676 0ustar wsnyderwsnyder# Verilog - Verilog Perl Interface # See copyright, etc in below POD section. ###################################################################### package Verilog::Netlist::Cell; use Verilog::Netlist; use Verilog::Netlist::Subclass; use vars qw($VERSION @ISA); use strict; @ISA = qw(Verilog::Netlist::Cell::Struct Verilog::Netlist::Subclass); $VERSION = '3.478'; structs('new', 'Verilog::Netlist::Cell::Struct' =>[name => '$', #' # Instantiation name filename => '$', #' # Filename this came from lineno => '$', #' # Linenumber this came from userdata => '%', # User information attributes => '%', #' # Misc attributes for systemperl or other processors # comment => '$', #' # Comment provided by user submodname => '$', #' # Which module it instantiates module => '$', #' # Module reference params => '$', #' # Textual description of parameters range => '$', #' # Range of ranged instance _pins => '%', # List of Verilog::Netlist::Pins byorder => '$', # True if Cell call uses order based pins # after link(): submod => '$', #' # Sub Module reference gateprim => '$', #' # Primitive (and/buf/cmos etc), but not UDPs # system perl _autoinst => '$', #' # Marked with AUTOINST tag ]); sub delete { my $self = shift; foreach my $pinref ($self->pins_sorted) { $pinref->delete; } my $h = $self->module->_cells; delete $h->{$self->name}; return undef; } ###################################################################### #### Methods sub logger { my $self = shift; return $self->netlist->logger; } sub netlist { my $self = shift; return $self->module->netlist; } sub _link_guts { my $self = shift; # This function is HOT, keep simple if (!$self->submod) { if (my $name = $self->submodname) { my $netlist = $self->netlist; my $sm = $netlist->find_module_or_interface_for_cell($name); if (!$sm) { my $name2 = $netlist->remove_defines($name); $sm = $netlist->find_module_or_interface_for_cell($name2) if $name ne $name2; } if ($sm) { $self->submod($sm); $sm->is_top(0); } } } } sub _link { my $self = shift; # This function is HOT, keep simple $self->_link_guts(); if (!$self->submod && Verilog::Language::is_gateprim($self->submodname)) { $self->gateprim(1); } if (!$self->submod() && !$self->gateprim && !$self->module->is_libcell() && $self->netlist->{link_read} && !$self->netlist->{_missing_submod}{$self->submodname} ) { print " Link_Read ",$self->submodname,"\n" if $Verilog::Netlist::Debug; # Try 1: Direct filename $self->netlist->read_file(filename=>$self->submodname, error_self=>0); $self->_link_guts(); # # Try 2: Libraries if (!$self->submod()) { $self->netlist->read_libraries(); $self->_link_guts(); } # Try 3: Bitch about missing file if (!$self->submod()) { $self->netlist->read_file(filename=>$self->submodname, error_self=>($self->netlist->{link_read_nonfatal} ? 0:$self)); } # Still missing if (!$self->submod()) { # Don't link this file again - speeds up if many common gate-ish missing primitives $self->netlist->{_missing_submod}{$self->submodname} = 1; } # Note if got it the new_module will add it to the _need_link list } # Link pins after module resolved, so don't do it multiple times if not found foreach my $pinref ($self->pins) { $pinref->_link(); } } sub lint { my $self = shift; if (!$self->submod() && !$self->gateprim && !$self->netlist->{link_read_nonfatal}) { $self->error($self,"Module/Program/Interface reference not found: ",$self->submodname(),,"\n"); } if ($self->netlist->{use_vars}) { foreach my $pinref ($self->pins) { $pinref->lint(); } } } sub verilog_text { my $self = shift; my @out = $self->submodname; if ($self->params) { push @out, " #(".$self->params.")"; } push @out, " ".$self->name; if ($self->range) { push @out, " ".$self->range; } push @out, " ("; my $comma=""; foreach my $pinref ($self->pins_sorted) { push @out, $comma if $comma; $comma=", "; push @out, $pinref->verilog_text; } push @out, ");"; return (wantarray ? @out : join('',@out)); } sub dump { my $self = shift; my $indent = shift||0; my $norecurse = shift; print " "x$indent,"Cell:",$self->name()," is-a:",$self->submodname(); print " ".$self->params if (($self->params||"") ne ""); print "\n"; if ($self->submod()) { $self->submod->dump($indent+10, 'norecurse'); } if (!$norecurse) { foreach my $pinref ($self->pins_sorted) { $pinref->dump($indent+2); } } } ###################################################################### #### Pins sub new_pin { my $self = shift; # @_ params # Create a new pin under this cell push @_, (cell=>$self); my $pinref = new Verilog::Netlist::Pin(@_); $self->_pins($pinref->name(), $pinref); return $pinref; } sub find_pin { my $self = shift; my $name = shift; return $self->_pins($name) || $self->_pins("\\".$name." "); } sub pins { return (values %{$_[0]->_pins}); } sub pins_sorted { return (sort {$a->name() cmp $b->name()} (values %{$_[0]->_pins})); } ###################################################################### #### Package return 1; __END__ =pod =head1 NAME Verilog::Netlist::Cell - Instantiated cell within a Verilog Netlist =head1 SYNOPSIS use Verilog::Netlist; ... my $cell = $module->find_cell('cellname'); print $cell->name; =head1 DESCRIPTION A Verilog::Netlist::Cell object is created by Verilog::Netlist for every instantiation in the current module. =head1 ACCESSORS See also Verilog::Netlist::Subclass for additional accessors and methods. =over 4 =item $self->comment Returns any comments following the definition. keep_comments=>1 must be passed to Verilog::Netlist::new for comments to be retained. =item $self->delete Delete the cell from the module it's under. =item $self->gateprim True if the cell is a gate primitive instantiation (buf/cmos/etc), but not a UDP. =item $self->module Pointer to the module the cell is in. =item $self->name The instantiation name of the cell. =item $self->netlist Reference to the Verilog::Netlist the cell is under. =item $self->pins List of Verilog::Netlist::Pin connections for the cell. =item $self->pins_sorted List of name sorted Verilog::Netlist::Pin connections for the cell. =item $self->range The range for the cell (e.g. "[1:0]") or false (i.e. undef or "") if not ranged. =item $self->submod Reference to the Verilog::Netlist::Module the cell instantiates. Only valid after the design is linked. =item $self->submodname The module name the cell instantiates (under the cell). =back =head1 MEMBER FUNCTIONS See also Verilog::Netlist::Subclass for additional accessors and methods. =over 4 =item $self->lint Checks the cell for errors. Normally called by Verilog::Netlist::lint. =item $self->new_pin Creates a new Verilog::Netlist::Pin connection for this cell. =item $self->pins_sorted Returns all Verilog::Netlist::Pin connections for this cell. =item $self->dump Prints debugging information for this cell. =back =head1 DISTRIBUTION Verilog-Perl is part of the L free Verilog EDA software tool suite. The latest version is available from CPAN and from L. Copyright 2000-2021 by Wilson Snyder. This package is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. =head1 AUTHORS Wilson Snyder =head1 SEE ALSO L, L L =cut Verilog-Perl-3.478/Netlist/Interface.pm0000644000177100017500000002355414057150455017720 0ustar wsnyderwsnyder# Verilog - Verilog Perl Interface # See copyright, etc in below POD section. ###################################################################### package Verilog::Netlist::Interface; use Verilog::Netlist; use Verilog::Netlist::ModPort; use Verilog::Netlist::Net; use Verilog::Netlist::Pin; use Verilog::Netlist::Subclass; use vars qw($VERSION @ISA); use strict; @ISA = qw(Verilog::Netlist::Interface::Struct Verilog::Netlist::Subclass); $VERSION = '3.478'; structs('new', 'Verilog::Netlist::Interface::Struct' =>[name => '$', #' # Name of the module filename => '$', #' # Filename this came from lineno => '$', #' # Linenumber this came from netlist => '$', #' # Netlist is a member of userdata => '%', # User information attributes => '%', #' # Misc attributes for systemperl or other processors # comment => '$', #' # Comment provided by user _cells => '%', # hash of Verilog::Netlist::Cells _modports => '%', # hash of Verilog::Netlist::ModPorts _ports => '%', # hash of Verilog::Netlist::Ports _portsordered=> '@', # list of Verilog::Netlist::Ports as ordered in list of ports _nets => '%', # hash of Verilog::Netlist::Nets _level => '$', # Depth in hierarchy (if calculated) ]); sub delete { my $self = shift; foreach my $oref ($self->nets) { $oref->delete; } foreach my $oref ($self->ports) { $oref->delete; } foreach my $oref ($self->modports) { $oref->delete; } foreach my $oref ($self->cells) { $oref->delete; } my $h = $self->netlist->{_interfaces}; delete $h->{$self->name}; return undef; } ###################################################################### sub is_top {} # Ignored, for module compatibility sub keyword { return 'interface'; } sub logger { return $_[0]->netlist->logger; } sub find_modport { my $self = shift; my $search = shift; return $self->_modports->{$search} || $self->_modports->{"\\".$search." "}; } sub find_port { my $self = shift; my $search = shift; return $self->_ports->{$search} || $self->_ports->{"\\".$search." "}; } sub find_port_by_index { my $self = shift; my $myindex = shift; # @{$self->_portsordered}[$myindex-1] returns the name of # the port in the module at this index. Then, this is # used to find the port reference via the port hash return $self->_ports->{@{$self->_portsordered}[$myindex-1]}; } sub find_cell { my $self = shift; my $search = shift; return $self->_cells->{$search} || $self->_cells->{"\\".$search." "}; } sub find_net { my $self = shift; my $search = shift; my $rtn = $self->_nets->{$search}||""; #print "FINDNET ",$self->name, " SS $search $rtn\n"; return $self->_nets->{$search} || $self->_nets->{"\\".$search." "}; } sub attrs_sorted { return (sort {$a cmp $b} @{$_[0]->attrs}); } sub cells { return (values %{$_[0]->_cells}); } sub cells_sorted { return (sort {$a->name() cmp $b->name()} (values %{$_[0]->_cells})); } sub modports { return (values %{$_[0]->_modports}); } sub modports_sorted { return (sort {$a->name() cmp $b->name()} (values %{$_[0]->_modports})); } sub nets { return (values %{$_[0]->_nets}); } sub nets_sorted { return (sort {$a->name() cmp $b->name()} (values %{$_[0]->_nets})); } sub ports { return (values %{$_[0]->_ports}); } sub ports_sorted { return (sort {$a->name() cmp $b->name()} (values %{$_[0]->_ports})); } sub ports_ordered { my $self = shift; return map {$self->_ports->{$_}} @{$self->_portsordered}; } sub nets_and_ports_sorted { return Verilog::Netlist::Module::nets_and_ports_sorted(@_); } sub new_net { my $self = shift; # @_ params # Create a new net under this my $netref = new Verilog::Netlist::Net(direction=>'net', data_type=>'wire', @_, module=>$self, ); $self->_nets($netref->name(), $netref); return $netref; } sub new_attr { my $self = shift; my $clean_text = shift; push @{$self->attrs}, $clean_text; } sub new_modport { my $self = shift; # @_ params my $oref = new Verilog::Netlist::ModPort(@_, module=>$self,); $self->_modports($oref->name(), $oref); return $oref; } sub new_port { my $self = shift; # @_ params # Create a new port under this module my $portref = new Verilog::Netlist::Port(@_, module=>$self,); $self->_ports($portref->name(), $portref); return $portref; } sub new_cell { return Verilog::Netlist::Module::new_cell(@_); } sub level { my $self = shift; my $level = $self->_level; return $level if defined $level; $self->_level(2); # Interfaces are never up "top" foreach my $cell ($self->cells) { if ($cell->submod) { my $celllevel = $cell->submod->level; $self->_level($celllevel+1) if $celllevel >= $self->_level; } } return $self->_level; } sub link { my $self = shift; # Ports create nets, so link ports before nets foreach my $portref ($self->ports) { $portref->_link(); } foreach my $netref ($self->nets) { $netref->_link(); } foreach my $oref ($self->modports) { $oref->_link(); } foreach my $cellref ($self->cells) { $cellref->_link(); } } sub lint { my $self = shift; if ($self->netlist->{use_vars}) { foreach my $portref ($self->ports) { $portref->lint(); } foreach my $netref ($self->nets) { $netref->lint(); } } foreach my $cellref ($self->cells) { $cellref->lint(); } } sub verilog_text { my $self = shift; my @out = "interface ".$self->name." (\n"; my $indent = " "; # Port list my $comma=""; push @out, $indent; foreach my $portref ($self->ports_sorted) { push @out, $comma, $portref->verilog_text; $comma = ", "; } push @out, ");\n"; foreach my $netref ($self->nets_sorted) { push @out, $indent, $netref->verilog_text, "\n"; } foreach my $oref ($self->modports_sorted) { push @out, $indent, $oref->verilog_text, "\n"; } foreach my $cellref ($self->cells_sorted) { push @out, $indent, $cellref->verilog_text, "\n"; } push @out, "endinterface\n"; return (wantarray ? @out : join('',@out)); } sub dump { my $self = shift; my $indent = shift||0; my $norecurse = shift; print " "x$indent,"Interface:",$self->name()," File:",$self->filename(),"\n"; if (!$norecurse) { foreach my $portref ($self->ports_sorted) { $portref->dump($indent+2); } foreach my $netref ($self->nets_sorted) { $netref->dump($indent+2); } foreach my $oref ($self->modports_sorted) { $oref->dump($indent+2); } foreach my $cellref ($self->cells_sorted) { $cellref->dump($indent+2); } } } ###################################################################### #### Package return 1; __END__ =pod =head1 NAME Verilog::Netlist::Interface - Interface within a Verilog Netlist =head1 SYNOPSIS use Verilog::Netlist; ... my $interface = $netlist->find_interface('name'); my $cell = $self->find_cell('name') my $port = $self->find_port('name') my $net = $self->find_net('name') =head1 DESCRIPTION A Verilog::Netlist::Interface object is created by Verilog::Netlist for every interface in the design. =head1 ACCESSORS See also Verilog::Netlist::Subclass for additional accessors and methods. =over 4 =item $self->comment Returns any comments following the definition. keep_comments=>1 must be passed to Verilog::Netlist::new for comments to be retained. =item $self->find_port_by_index Returns the port name associated with the given index. =item $self->modports Returns list of references to Verilog::Netlist::ModPort in the interface. =item $self->modports_sorted Returns list of references to Verilog::Netlist::ModPort in the interface sorted by name. =item $self->name The name of the interface. =item $self->netlist Reference to the Verilog::Netlist the interface is under. =item $self->nets Returns list of references to Verilog::Netlist::Net in the interface. =item $self->nets_sorted Returns list of name sorted references to Verilog::Netlist::Net in the interface. =item $self->nets_and_ports_sorted Returns list of name sorted references to Verilog::Netlist::Net and Verilog::Netlist::Port in the interface. =item $self->ports Returns list of references to Verilog::Netlist::Port in the interface. =item $self->ports_ordered Returns list of references to Verilog::Netlist::Port in the interface sorted by pin number. =item $self->ports_sorted Returns list of references to Verilog::Netlist::Port in the interface sorted by name. =back =head1 MEMBER FUNCTIONS See also Verilog::Netlist::Subclass for additional accessors and methods. =over 4 =item $self->find_net(I) Returns Verilog::Netlist::Net matching given name. =item $self->level Returns the reverse depth of this interface with respect to other modules and interfaces. See also Netlist's modules_sorted_level. =item $self->lint Checks the interface for errors. =item $self->link Creates interconnections between this interface and other interfaces. =item $self->new_net Creates a new Verilog::Netlist::Net. =item $self->dump Prints debugging information for this interface. =item $self->verilog_text Returns verilog code which represents this interface. Returned as an array that must be joined together to form the final text string. The netlist must be already ->link'ed for this to work correctly. =back =head1 DISTRIBUTION Verilog-Perl is part of the L free Verilog EDA software tool suite. The latest version is available from CPAN and from L. Copyright 2000-2021 by Wilson Snyder. This package is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. =head1 AUTHORS Wilson Snyder =head1 SEE ALSO L, L L =cut Verilog-Perl-3.478/Netlist/Logger.pm0000644000177100017500000001024614057150455017231 0ustar wsnyderwsnyder# Verilog - Verilog Perl Interface # See copyright, etc in below POD section. ###################################################################### package Verilog::Netlist::Logger; require Exporter; use vars qw($VERSION); use strict; $VERSION = '3.478'; # We don't use Verilog::Netlist::Subclass, as this is called from it! ###################################################################### #### Constructors sub new { my $class = shift; my $self = { _warnings => 0, _errors => 0, _error_unlink_files => {}, @_ }; bless $self, $class; return $self; } ###################################################################### #### Accessors sub errors { my $self = shift; $self->{_errors} = shift if $#_>=0; return $self->{_errors}; } sub warnings { my $self = shift; $self->{_warnings} = shift if $#_>=0; return $self->{_warnings}; } ###################################################################### #### Error Handling sub info { my $self = shift; my $objref = shift; CORE::warn "-Info: ".$objref->fileline.": ".join('',@_); } sub warn { my $self = shift; my $objref = shift; CORE::warn "%Warning: ".$objref->fileline.": ".join('',@_); $self->warnings($self->warnings+1); } sub error { my $self = shift; my $objref = shift; CORE::warn "%Error: ".$objref->fileline.": ".join('',@_); $self->errors($self->errors+1); } sub exit_if_error { my $self = shift; my %params = @_; my $allow = $params{allow} || ""; if ($self->errors || ($self->warnings && $allow !~ /warning/)) { CORE::warn "Exiting due to errors\n"; exit(10); } return ($self->errors + $self->warnings); } sub unlink_if_error { my $self = shift; $self->{_error_unlink_files}{$_[0]} = 1; } sub error_unlink { my $self = shift; foreach my $file (keys %{$self->{_error_unlink_files}}) { unlink $file; delete $self->{_error_unlink_files}{$file}; } } sub DESTROY { my $self = shift; my $has_err = $? || $self->errors || $self->warnings; if ($has_err) { $self->error_unlink; } } ###################################################################### #### Package return 1; __END__ =pod =head1 NAME Verilog::Netlist::Logger - Error collection and reporting =head1 SYNOPSIS use Verilog::Netlist::Logger; ... my $self = Verilog::Netlist::Logger->new(); $self->info("We're here\n"); $self->warn("Things look bad\n"); $self->error("Things are even worse\n"); $self->exit_if_error(); =head1 DESCRIPTION The Verilog::Netlist::Logger is used to report all errors detected by Verilog::Netlist::* structures. By default, Verilog::Netlist creates a new Logger object, and passes it down to all contained objects. Users may create their own logger objects to catch or otherwise handle error messages. =head1 MEMBER FUNCTIONS =over 4 =item $self->error(object, I) Print an error about the object in a standard format. The object must have a fileline method. =item $self->exit_if_error([allow=>'warning']) Exits the program if any errors were detected. Optionally specify allow=>'warning' to ignore warnings. =item $self->info(I) Print an informational about the object in a standard format. The object must have a fileline method. =item $self->lineno() The line number the entity was created on. =item $self->unlink_if_error(I) Requests the given file be deleted if any errors are detected when the Logger object is destroyed. Used for temporary files. =item $self->warn(I) Print a warning about the object in a standard format. The object must have a fileline method. =back =head1 DISTRIBUTION Verilog-Perl is part of the L free Verilog EDA software tool suite. The latest version is available from CPAN and from L. Copyright 2000-2021 by Wilson Snyder. This package is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. =head1 AUTHORS Wilson Snyder =head1 SEE ALSO L, L, L =cut Verilog-Perl-3.478/Netlist/Pin.pm0000644000177100017500000002446514057150455016550 0ustar wsnyderwsnyder# Verilog - Verilog Perl Interface # See copyright, etc in below POD section. ###################################################################### package Verilog::Netlist::Pin; use Verilog::Netlist; use Verilog::Netlist::Port; use Verilog::Netlist::Net; use Verilog::Netlist::Cell; use Verilog::Netlist::Module; use Verilog::Netlist::Pin; use Verilog::Netlist::PinSelection; use Verilog::Netlist::Subclass; use vars qw($VERSION @ISA); use strict; @ISA = qw(Verilog::Netlist::Pin::Struct Verilog::Netlist::Subclass); $VERSION = '3.478'; structs('_new_base', 'Verilog::Netlist::Pin::Struct' =>[name => '$', #' # Pin connection filename => '$', #' # Filename this came from lineno => '$', #' # Linenumber this came from userdata => '%', # User information attributes => '%', #' # Misc attributes for systemperl or other processors # comment => '$', #' # Comment provided by user _pinselects => '$', #' # Arrayref to Verilog::Netlist::PinSelections portname => '$', #' # Port connection name portnumber => '$', #' # Position of name in call pinnamed => '$', #' # True if name assigned cell => '$', #' # Cell reference # below only after link() _nets => '$', #' # Arrayref to references to connected nets port => '$', #' # Port connection reference # SystemPerl: below only after autos() sp_autocreated => '$', #' # Created by auto() # below by accessor computation #module #submod ]); sub new { my $class = shift; my %params = (@_); if (defined $params{netname}) { # handle legacy constructor parameter "netname" $params{_pinselects} = [new Verilog::Netlist::PinSelection($params{netname})]; delete $params{netname}; } elsif (defined $params{pinselects}) { # remap pinselects to _pinselects foreach my $pinselect (@{$params{pinselects}}) { push @{$params{_pinselects}}, new Verilog::Netlist::PinSelection($pinselect->{netname}, $pinselect->{msb}, $pinselect->{lsb}); } delete $params{pinselects}; } return $class->_new_base(%params); } sub delete { my $self = shift; if ($self->nets && $self->port) { foreach my $net ($self->nets) { next unless $net->{net}; my $dir = $self->port->direction; if ($dir eq 'in') { $net->{net}->_used_in_dec(); } elsif ($dir eq 'out') { $net->{net}->_used_out_dec(); } elsif ($dir eq 'inout') { $net->{net}->_used_inout_dec(); } } } my $h = $self->cell->_pins; delete $h->{$self->name}; return undef; } ###################################################################### #### Methods # Legacy accessors sub netname { return undef if !defined($_[0]->_pinselects); return @{$_[0]->_pinselects}[0]->{_netname}; } sub net { my $nets = $_[0]->_nets; return undef if !defined($nets); return undef if !@{$nets}[0]; return @{$nets}[0]->{net}; } # Standard accessors sub nets { return [] if !defined($_[0]->_nets); return (@{$_[0]->_nets}); } sub nets_sorted { return [] if !defined($_[0]->_nets); return (sort {$a->name cmp $b->name} (@{$_[0]->_nets})); } sub pinselects { return [] if !defined($_[0]->_pinselects); return @{$_[0]->_pinselects}; } sub logger { return $_[0]->netlist->logger; } sub module { return $_[0]->cell->module; } sub submod { return $_[0]->cell->submod; } sub netlist { return $_[0]->cell->module->netlist; } sub _link { my $self = shift; # Note this routine is HOT my $change; if (!$self->_nets) { if ($self->_pinselects) { my @nets = (); foreach my $pinselect (@{$self->_pinselects}) { my $net = $self->module->find_net($pinselect->netname); next if (!defined($net)); my ($msb, $lsb); # if the parsed description includes a range, use that, # else use the complete range of the underlying net. if (defined($pinselect->msb)) { $msb = $pinselect->msb; $lsb = $pinselect->lsb; } else { $msb = $net->msb; $lsb = $net->lsb; } push(@nets, {net => $net, msb => $msb, lsb => $lsb}); } $self->_nets(\@nets); $change = 1; } } if (!$self->port) { if (my $submod = $self->submod) { my $portname = $self->portname; if ($portname && !$self->cell->byorder ) { $self->port($submod->find_port($portname)); $change = 1; } else { $self->port($submod->find_port_by_index($self->portnumber)); # changing name from pin# to actual port name $self->name($self->port->name) if $self->port; $change = 1; } } } if ($change && $self->_nets && $self->port) { my $dir = $self->port->direction; foreach my $net ($self->nets) { next unless $net->{net}; if ($dir eq 'in') { $net->{net}->_used_in_inc(); } elsif ($dir eq 'out') { $net->{net}->_used_out_inc(); } elsif ($dir eq 'inout') { $net->{net}->_used_inout_inc(); } } } } sub type_match { my $self = shift; # We could check for specific types being OK, but nearly everything, # reg/trireg/wire/wand etc/tri/ supply0|1 etc # is allowed to connect with everything else, and we're not a lint tool... # So, not: return $self->net->data_type eq $self->port->data_type; return 1; } sub lint { my $self = shift; if (!$self->port && $self->submod) { $self->error($self,"Port not found in ",$self->submod->keyword," ",$self->submod->name,": ",$self->portname,"\n"); } if ($self->port && $self->nets) { if (!$self->type_match) { my $nettype = $self->net->data_type; my $porttype = $self->port->data_type; $self->error("Port pin data type '$porttype' != Net data type '$nettype': " ,$self->name,"\n"); } foreach my $net ($self->nets) { next unless $net->{net} && $net->{net}->port; my $portdir = $self->port->direction; my $netdir = $net->{net}->port->direction; if (($netdir eq "in" && $portdir eq "out") #Legal: ($netdir eq "in" && $portdir eq "inout") #Legal: ($netdir eq "out" && $portdir eq "inout") ) { $self->error("Port is ${portdir}put from submodule, but ${netdir}put from this module: " ,$self->name,"\n"); #$self->cell->module->netlist->dump; } } } } sub verilog_text { my $self = shift; my $inst; if ($self->port) { # Even if it was by position, after linking we can write it as if it's by name. $inst = ".".$self->port->name."("; } elsif ($self->pinnamed) { $inst = ".".$self->name."("; } else { # not by name, and unlinked $inst = ".".$self->portname."("; } my $net_cnt = $self->pinselects; if ($net_cnt >= 2) { $inst .= "{"; my $comma = ""; foreach my $pinselect (reverse($self->pinselects)) { $inst .= $comma; $inst .= $pinselect->bracketed_msb_lsb; $comma = ","; } $inst .= "}"; } elsif ($net_cnt == 1) { my @tmp = $self->pinselects; $inst .= $tmp[0]->bracketed_msb_lsb; } $inst .= ")"; return $inst; } sub dump { my $self = shift; my $indent = shift||0; my $net_cnt = $self->pinselects; my $out = " "x$indent."Pin:".$self->name; $out .= ($net_cnt > 1) ? " Nets:" : " Net:"; my $comma = ""; foreach my $pinselect (reverse($self->pinselects)) { $out .= $comma; $out .= $pinselect->bracketed_msb_lsb; $comma = ","; } print "$out\n"; if ($self->port) { $self->port->dump($indent+10, 'norecurse'); } foreach my $net ($self->nets) { next unless $net->{net}; $net->{net}->dump($indent+10, 'norecurse'); } } ###################################################################### #### Package return 1; __END__ =pod =head1 NAME Verilog::Netlist::Pin - Pin on a Verilog Cell =head1 SYNOPSIS use Verilog::Netlist; ... my $pin = $cell->find_pin('pinname'); print $pin->name; =head1 DESCRIPTION A Verilog::Netlist::Pin object is created by Verilog::Netlist::Cell for for each pin connection on a cell. A Pin connects a net in the current design to a port on the instantiated cell's module. =head1 ACCESSORS See also Verilog::Netlist::Subclass for additional accessors and methods. =over 4 =item $self->cell Reference to the Verilog::Netlist::Cell the pin is under. =item $self->comment Returns any comments following the definition. keep_comments=>1 must be passed to Verilog::Netlist::new for comments to be retained. =item $self->delete Delete the pin from the cell it's under. =item $self->module Reference to the Verilog::Netlist::Module the pin is in. =item $self->name The name of the pin. May have extra characters to make vectors connect, generally portname is a more readable version. There may be multiple pins with the same portname, only one pin has a given name. =item $self->net Reference to the Verilog::Netlist::Net the pin connects to. Only valid after a link. This function is deprecated; use nets or nets_sorted instead. =item $self->nets Array of hashes the pin connects to. Each hash contains a msb, lsb, and net (a Verilog::Netlist::Net). Only valid after a link. =item $self->nets_sorted Array of sorted hashes the pin connects to. Each hash contains a msb, lsb, and net (a Verilog::Netlist::Net). Only valid after a link. =item $self->netlist Reference to the Verilog::Netlist the pin is in. =item $self->netname The net name the pin connects to. This function is deprecated; use pinselects instead. =item $self->pinselects The net names the pins connect to, as an array of Verilog::Netlist::PinSelection elements. =item $self->portname The name of the port connected to. =item $self->port Reference to the Verilog::Netlist::Port the pin connects to. Only valid after a link. =back =head1 MEMBER FUNCTIONS See also Verilog::Netlist::Subclass for additional accessors and methods. =over 4 =item $self->lint Checks the pin for errors. Normally called by Verilog::Netlist::lint. =item $self->dump Prints debugging information for this pin. =back =head1 DISTRIBUTION Verilog-Perl is part of the L free Verilog EDA software tool suite. The latest version is available from CPAN and from L. Copyright 2000-2021 by Wilson Snyder. This package is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. =head1 AUTHORS Wilson Snyder =head1 SEE ALSO L, L, L, L =cut Verilog-Perl-3.478/Netlist/Port.pm0000644000177100017500000001301314057150455016731 0ustar wsnyderwsnyder# Verilog - Verilog Perl Interface # See copyright, etc in below POD section. ###################################################################### package Verilog::Netlist::Port; use Verilog::Netlist; use Verilog::Netlist::Subclass; use vars qw($VERSION @ISA); use strict; @ISA = qw(Verilog::Netlist::Port::Struct Verilog::Netlist::Subclass); $VERSION = '3.478'; structs('_new_base', 'Verilog::Netlist::Port::Struct' =>[name => '$', #' # Name of the port filename => '$', #' # Filename this came from lineno => '$', #' # Linenumber this came from userdata => '%', # User information attributes => '%', #' # Misc attributes for systemperl or other processors # direction => '$', #' # Direction (in/out/inout) data_type => '$', #' # SystemVerilog Type (logic/integer etc) comment => '$', #' # Comment provided by user array => '$', #' # Vectorization module => '$', #' # Module entity belongs to # below only after links() net => '$', #' # Net port connects # below only after autos() sp_autocreated => '$', #' # Created by /*AUTOINOUT*/ ]); sub new { my $class = shift; my %params = (@_); $params{data_type} = $params{type} if defined $params{type}; # Backward compatibility if ($params{direction}) { # Correct common mistakes; plus the parser itself needs this conversion $params{direction} = 'in' if $params{direction} eq 'input'; $params{direction} = 'out' if $params{direction} eq 'output'; } return $class->_new_base(%params); } sub delete { my $self = shift; my $h = $self->module->_ports; delete $h->{$self->name}; return undef; } ###################################################################### sub netlist { return $_[0]->module->netlist; } sub logger { return $_[0]->netlist->logger; } sub type { # Backward compatibility only my $self=shift; if ($#_ >= 0) { $self->data_type(@_); } return ($self->data_type || ($self->net && $self->net->type))||''; } sub _link { my $self = shift; if (!$self->net) { my $net = $self->module->find_net($self->name); if (!$net) { my $msb; my $lsb; if (defined $self->data_type) { $self->data_type =~ /\[([^:]+)(:(.*))?\]$/; $msb = $1; $lsb = defined($3) ? $3 : $1; } $net = $self->module->new_net (name=>$self->name, filename=>$self->filename, lineno=>$self->lineno, decl_type=>"port", net_type=>"wire", data_type=>$self->data_type, array=>$self->array, comment=>undef, msb=>$msb, lsb=>$lsb, ); $net->attributes($self->attributes); # Copy attributes across } if ($net && $net->port && $net->port != $self) { $self->error("Port redeclares existing port: ",$self->name,"\n"); } $self->net($net); $self->net->port($self); # A input to the module is actually a "source" or thus "out" of the net. $self->net->_used_in_inc() if ($self->direction() eq 'out'); $self->net->_used_out_inc() if ($self->direction() eq 'in'); $self->net->_used_inout_inc() if ($self->direction() eq 'inout'); } } sub lint {} sub verilog_text { my $self = shift; return $self->name; } sub dump { my $self = shift; my $indent = shift||0; print " "x$indent,"Port:",$self->name()," Dir:",$self->direction() ," DataT:",$self->data_type()," Array:",$self->array()||"","\n"; } ###################################################################### #### Package return 1; __END__ =pod =head1 NAME Verilog::Netlist::Port - Port for a Verilog Module =head1 SYNOPSIS use Verilog::Netlist; ... my $port = $module->find_port('pinname'); print $port->name; =head1 DESCRIPTION A Verilog::Netlist::Port object is created by Verilog::Netlist::Module for every port connection in the module. =head1 ACCESSORS See also Verilog::Netlist::Subclass for additional accessors and methods. =over 4 =item $self->array Any array declaration for the port. This only applies to Verilog 1995 style ports which can declare port bits independently from the signal declarations. When using Verilog 2001 style ports, see the matching net declaration's data_type, msb and lsb methods instead, for example C<$module->find_net($port->name)->data_type>. =item $self->comment Returns any comments following the definition. keep_comments=>1 must be passed to Verilog::Netlist::new for comments to be retained. =item $self->data_type The SystemVerilog data type of the port. =item $self->direction The direction of the port: "in", "out", or "inout". =item $self->module Reference to the Verilog::Netlist::Module the port is in. =item $self->name The name of the port. =item $self->net Reference to the Verilog::Netlist::Net the port connects to. Only valid after the netlist is linked. =item $self->type Approximately an alias of data_type for backward compatibility. Do not use for new applications. =back =head1 MEMBER FUNCTIONS See also Verilog::Netlist::Subclass for additional accessors and methods. =over 4 =item $self->dump Prints debugging information for this port. =back =head1 DISTRIBUTION Verilog-Perl is part of the L free Verilog EDA software tool suite. The latest version is available from CPAN and from L. Copyright 2000-2021 by Wilson Snyder. This package is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. =head1 AUTHORS Wilson Snyder =head1 SEE ALSO L, L L =cut Verilog-Perl-3.478/Netlist/File.pm0000644000177100017500000003744514057150455016703 0ustar wsnyderwsnyder# Verilog - Verilog Perl Interface # See copyright, etc in below POD section. ###################################################################### package Verilog::Netlist::File; use Carp; use Verilog::Netlist; use Verilog::Netlist::Subclass; use vars qw($VERSION @ISA); use strict; @ISA = qw(Verilog::Netlist::File::Struct Verilog::Netlist::Subclass); $VERSION = '3.478'; structs('new', 'Verilog::Netlist::File::Struct' =>[name => '$', #' # Filename this came from basename => '$', #' # Basename of the file netlist => '$', #' # Netlist is a member of userdata => '%', # User information attributes => '%', #' # Misc attributes for systemperl or other processors comment => '$', #' # Comment provided by user is_libcell => '$', #' # True if is a library cell preproc => '$', #' # Preprocessor object # For special procedures _interfaces => '%', # For autosubcell_include _modules => '%', # For autosubcell_include ]); ###################################################################### ###################################################################### #### Read class package Verilog::Netlist::File::Parser; use Verilog::SigParser; use Verilog::Preproc; use base qw(Verilog::SigParser); use strict; sub new { my $class = shift; my %params = (preproc => "Verilog::Preproc", @_); # filename=> my $preproc_class = $params{preproc}; delete $params{preproc}; # Remove as preproc doesn't need passing down to Preprocessor # A new file; make new information $params{fileref} or die "%Error: No fileref parameter?"; $params{netlist} = $params{fileref}->netlist; my $parser = $class->SUPER::new (%params, modref=>undef, # Module being parsed now cellref=>undef, # Cell being parsed now _cmtref=>undef, # Object to attach comments to # Must parse all files in same compilation unit with # same symbol_table, or a package won't exist for link() symbol_table => $params{netlist}->{symbol_table}, ); my @opt; push @opt, (options=>$params{netlist}{options}) if $params{netlist}{options}; my $meta = $params{metacomment}; if ($meta) { die "%Error: 'metacomment' arg of Netlist or read_file() must be a hash," unless (ref($meta) eq 'HASH'); push @opt, metacomments=>[ grep({ $meta->{$_} } keys %$meta) ]; push @opt, keep_comments=>($params{netlist}{keep_comments} || 1); } elsif ($params{netlist}{keep_comments}) { push @opt, keep_comments=>$params{netlist}{keep_comments}; } else { push @opt, keep_comments=>0; } push @opt, keep_whitespace=>1; # So we don't loose newlines push @opt, include_open_nonfatal=>1 if $params{netlist}{include_open_nonfatal}; push @opt, synthesis=>1 if $params{netlist}{synthesis}; my $preproc = $preproc_class->new(@opt, parent => $params{fileref}); $params{fileref}->preproc($preproc); $preproc->open($params{filename}); $parser->parse_preproc_file($preproc); return $parser; } sub contassign { my $self = shift; my $keyword = shift; my $lhs = shift; my $rhs = shift; print " ContAssign $keyword $lhs\n" if $Verilog::Netlist::Debug; my $modref = $self->{modref}; if (!$modref) { return $self->error("CONTASSIGN outside of module definition", $lhs); } $modref->new_contassign (filename=>$self->filename, lineno=>$self->lineno, keyword=>$keyword, lhs=>$lhs, rhs=>$rhs); } sub defparam { my $self = shift; my $keyword = shift; my $lhs = shift; my $rhs = shift; print " Defparam $keyword $lhs\n" if $Verilog::Netlist::Debug; my $modref = $self->{modref}; if (!$modref) { return $self->error("DEFPARAM outside of module definition", $lhs); } $modref->new_defparam (filename=>$self->filename, lineno=>$self->lineno, keyword=>$keyword, lhs=>$lhs, rhs=>$rhs); } sub interface { my $self = shift; my $keyword = shift; my $name = shift; my $fileref = $self->{fileref}; my $netlist = $self->{netlist}; print "Interface $name\n" if $Verilog::Netlist::Debug; $self->{modref} = $netlist->new_interface (name=>$name, filename=>$self->filename, lineno=>$self->lineno); $fileref->_interfaces($name, $self->{modref}); $self->{_cmtpre} = undef; $self->{_cmtref} = $self->{modref}; } sub modport { my $self = shift; my $keyword = shift; my $name = shift; print " Modport $name\n" if $Verilog::Netlist::Debug; my $modref = $self->{modref}; if (!$modref) { return $self->error("MODPORT outside of interface definition", $name); } $self->{_modportref} = $modref->new_modport (name=>$name, filename=>$self->filename, lineno=>$self->lineno); $self->{_cmtpre} = undef; $self->{_cmtref} = $self->{modref}; } sub module { my $self = shift; my $keyword = shift; my $name = shift; my $orderref = shift; my $in_celldefine = shift; my $fileref = $self->{fileref}; my $netlist = $self->{netlist}; print "Module $name\n" if $Verilog::Netlist::Debug; $self->{modref} = $netlist->new_module (name=>$name, keyword=>$keyword, is_libcell=>($fileref->is_libcell() || $in_celldefine), filename=>$self->filename, lineno=>$self->lineno); $fileref->_modules($name, $self->{modref}); $self->{_cmtpre} = undef; $self->{_cmtref} = $self->{modref}; } sub program { my $self = shift; $self->module(@_); } sub endinterface { my $self = shift; $self->endmodule(@_); } sub endmodport { my $self = shift; $self->{_cmtpre} = undef; $self->{_cmtref} = $self->{modref}; $self->{_modportref} = undef; } sub endmodule { my $self = shift; $self->{_cmtpre} = undef; $self->{_cmtref} = undef; # Assume all module comments are inside the module, not after $self->{modref} = undef; } sub endprogram { my $self = shift; $self->endmodule(@_); } sub attribute { my $self = shift; my $text = shift||''; my $modref = $self->{modref}; my ($category, $name, $eql, $rest); if ($text =~ m!^([\$A-Za-z]\w*)\s+ (\w+) (\s*=\s*)? (.*) !x) { ($category, $name, $eql, $rest) = ($1, $2, ($3 || ""), $4); if ($eql ne "") { $eql = "="; } my $cleaned = ($category ." ". $name . $eql . $rest); if ($Verilog::Netlist::Debug) { printf +("%d: Attribute '%s'\n", $self->lineno, $cleaned); } # Treat as module-level if attribute appears before any declarations. if ($modref) { my $attr = $modref->new_attr($cleaned); } } } sub port { my $self = shift; my $name = shift; my $objof = shift; my $direction = shift; my $type = shift; my $array = shift; my $pinnum = shift; return if !($objof eq 'module' || $objof eq 'interface' || $objof eq 'modport'); my $underref = $self->{_modportref} || $self->{modref}; if ($pinnum) { # Else a "input" etc outside the "(...)"s $underref->_portsordered($pinnum-1, $name); # -1 because [0] has first pin } if ($direction) { # Else just a pin number without declaration my $port = $underref->new_port (name=>$name, filename=>$self->filename, lineno=>$self->lineno, direction=>$direction, data_type=>$type, array=>$array, comment=>undef,); } } sub var { my $self = shift; #use Data::Dumper; print " DEBUG: var callback: ",Dumper(\@_); my $decl_type = shift; my $name = shift; my $objof = shift; my $net_type = shift; my $data_type = shift; my $array = shift; my $value = shift; print " Sig $name dt=$decl_type nt=$net_type d=$data_type\n" if $Verilog::Netlist::Debug; return if !($objof eq 'module' || $objof eq 'interface' || $objof eq 'modport' || $objof eq 'netlist'); my $msb; my $lsb; if ($data_type && $data_type =~ /\[(.*):(.*)\]/) { $msb = $1; $lsb = $2; } elsif ($data_type && $data_type =~ /\[(.*)\]/) { $msb = $lsb = $1; } my $underref = $self->{_modportref} || $self->{modref}; if ($objof eq 'netlist') { $underref = $self->{netlist}->new_root_module (filename=>$self->filename, lineno=>$self->lineno); } if (!$underref) { return $self->error("Signal declaration outside of module definition", $name); } my $signed = ($data_type =~ /signed/); my $net = $underref->find_net($name); $net or $net = $underref->new_net (name=>$name, filename=>$self->filename, lineno=>$self->lineno, simple_type=>1, data_type=>$data_type, array=>$array, comment=>$self->{_cmtpre}, msb=>$msb, lsb=>$lsb, net_type=>$net_type, decl_type=>$decl_type, signed=>$signed, value=>$value, ); $net->data_type($data_type); # If it was declared earlier as in/out etc $net->net_type($net_type) if $net_type; # (from a single non-typed input/output stmt), remark the type now $self->{_cmtpre} = undef; $self->{_cmtref} = $net; } sub instant { my $self = shift; my $submodname = shift; my $instname = shift; my $range = shift; print " Cell $instname\n" if $Verilog::Netlist::Debug; my $modref = $self->{modref}; if (!$modref) { return $self->error("CELL outside of module definition", $instname); } $self->{cellref} = $modref->new_cell (name=>$instname, filename=>$self->filename, lineno=>$self->lineno, submodname=>$submodname, range=>$range,); $self->{_cmtpre} = undef; $self->{_cmtref} = $self->{cellref}; } sub endcell { my $self = shift; $self->{_cmtpre} = undef; $self->{_cmtref} = $self->{cellref}; # Comments after cell decl go to the cell } sub parampin { my $self = shift; my $pin = shift; my $conn = shift; my $number = shift; my $prev = $self->{cellref}->params(); $prev .= ", " if $prev; $prev .= ($pin ? ".$pin($conn)" : $conn); $self->{cellref}->params($prev); } sub pin { my $self = shift; if (!$self->{use_pinselects}) { $self->pinselects(@_); } } sub pinselects { my $self = shift; my $pin = shift; my $nets = shift; my $number = shift; my $hasnamedports = (($pin||'') ne ''); $pin = "pin".$number if !$hasnamedports; my $net_cnt = scalar($nets); print " Pin $pin $number (connected to $net_cnt nets) \n" if $Verilog::Netlist::Debug; my $cellref = $self->{cellref}; if (!$cellref) { return $self->error("PIN outside of cell definition", $pin); } my %params = ( name => $pin, portname => $pin, portnumber => $number, pinnamed => $hasnamedports, filename => $self->filename, lineno => $self->lineno, ); if ($self->{use_pinselects}) { $params{pinselects} = $nets; } else { $params{netname} = $nets; } my $pinref = $cellref->new_pin(%params); # If any pin uses call-by-name, then all are assumed to use call-by-name $cellref->byorder(1) if !$hasnamedports; $self->{_cmtpre} = undef; $self->{_cmtref} = $pinref; } sub keyword { # OVERRIDE Verilog::Parse calls when keyword occurs # Note we use_cb_keyword only if comments are parsed! my $self = shift; # Parser invoked $self->{_cmtpre} = undef; $self->{_cmtref} = undef; } sub comment { my $self = shift; # OVERRIDE Verilog::Parse calls when comment occurs my $text = shift; # Includes comment delimiters if ($self->{_cmtref}) { my $old = $self->{_cmtref}->comment(); $old = (defined $old) ? $old."\n".$text : $text; $self->{_cmtref}->comment($old); } elsif ($self->{modref}) { my $old = $self->{_cmtpre}; $old = (defined $old) ? $old."\n".$text : $text; $self->{_cmtpre} = $old; } } # sub operator { ... Disabled by new(use_cmt_operator => 0) # sub number { ... Disabled by new(use_cmt_number => 0) # sub string { ... Disabled by new(use_cmt_string => 0) # sub symbol { ... Disabled by new(use_cmt_symbol => 0) sub error { my $self = shift; my $text = shift; my $fileref = $self->{fileref}; # Call Verilog::Netlist::Subclass's error reporting, it will track # errors $fileref->error($self, "$text\n"); } sub warn { my $self = shift; my $text = shift; my $fileref = $self->{fileref}; $fileref->warn($self, "$text\n"); } package Verilog::Netlist::File; ###################################################################### ###################################################################### #### Functions sub delete { my $self = shift; $self->netlist(undef); # Break circular $self->preproc(undef); # Break circular } sub logger { my $self = shift; return $self->netlist->logger; } sub read { my %params = (lookup_type=>'module', @_); # netlist=>, filename=>, per-file options my $filename = $params{filename} or croak "%Error: ".__PACKAGE__."::read_file (filename=>) parameter required, stopped"; my $netlist = $params{netlist} or croak("Call Verilog::Netlist::read_file instead,"); my $filepath = $netlist->resolve_filename($filename, $params{lookup_type}); if (!$filepath) { if ($params{error_self}) { $params{error_self}->error("Cannot find $filename\n"); } elsif (!defined $params{error_self}) { die "%Error: Cannot find $filename\n"; } # 0=suppress error return undef; } print __PACKAGE__."::read_file $filepath\n" if $Verilog::Netlist::Debug; my $fileref = $netlist->new_file(name=>$filepath, is_libcell=>$params{is_libcell}||0, ); my $keep_cmt = ($params{keep_comments} || $netlist->{keep_comments}); my $parser_class = ($params{parser} || $netlist->{parser}); my $parser = $parser_class->new ( fileref => $fileref, filename => $filepath, # for ->read metacomment => ($params{metacomment} || $netlist->{metacomment}), keep_comments => $keep_cmt, use_vars => ($params{use_vars} || $netlist->{use_vars}), use_pinselects => ($params{use_pinselects} || $netlist->{use_pinselects}), use_protected => 0, preproc => ($params{preproc} || $netlist->{preproc}), # Callbacks we need; disable unused for speed use_cb_attribute => 1, use_cb_comment => $keep_cmt, use_cb_keyword => $keep_cmt, use_cb_number => 0, use_cb_operator => 0, use_cb_string => 0, use_cb_symbol => 0, ); return $fileref; } sub link { # For backward compatibility for SystemC child class, call _link $_[0]->_link(@_); } sub _link { } sub dump { my $self = shift; my $indent = shift||0; print " "x$indent,"File:",$self->name(),"\n"; } ###################################################################### #### Package return 1; __END__ =pod =head1 NAME Verilog::Netlist::File - File containing Verilog code =head1 SYNOPSIS use Verilog::Netlist; my $nl = new Verilog::Netlist; my $fileref = $nl->read_file(filename=>'filename'); =head1 DESCRIPTION Verilog::Netlist::File allows Verilog::Netlist objects to be read and written in Verilog format. =head1 ACCESSORS See also Verilog::Netlist::Subclass for additional accessors and methods. =over 4 =item $self->basename The filename of the file with any path and . suffix stripped off. =item $self->name The filename of the file. =item $self->preproc The Verilog::Preproc object this file is using. =back =head1 MEMBER FUNCTIONS See also Verilog::Netlist::Subclass for additional accessors and methods. =over 4 =item $self->read Generally called as $netlist->read_file. Pass a hash of parameters. Reads the filename=> parameter, parsing all instantiations, ports, and signals, and creating Verilog::Netlist::Module structures. =item $self->dump Prints debugging information for this file. =back =head1 DISTRIBUTION Verilog-Perl is part of the L free Verilog EDA software tool suite. The latest version is available from CPAN and from L. Copyright 2000-2021 by Wilson Snyder. This package is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. =head1 AUTHORS Wilson Snyder =head1 SEE ALSO L, L L =cut Verilog-Perl-3.478/Netlist/Module.pm0000644000177100017500000003614414057150455017244 0ustar wsnyderwsnyder# Verilog - Verilog Perl Interface # See copyright, etc in below POD section. ###################################################################### package Verilog::Netlist::Module; use Verilog::Netlist; use Verilog::Netlist::ContAssign; use Verilog::Netlist::Defparam; use Verilog::Netlist::Port; use Verilog::Netlist::Net; use Verilog::Netlist::Cell; use Verilog::Netlist::Pin; use Verilog::Netlist::Subclass; use vars qw($VERSION @ISA); use strict; @ISA = qw(Verilog::Netlist::Module::Struct Verilog::Netlist::Subclass); $VERSION = '3.478'; structs('new', 'Verilog::Netlist::Module::Struct' =>[name => '$', #' # Name of the module filename => '$', #' # Filename this came from lineno => '$', #' # Linenumber this came from netlist => '$', #' # Netlist is a member of keyword => '$', #' # Type of module userdata => '%', # User information attributes => '%', #' # Misc attributes for systemperl or other processors # attrs => '@', # list of "category name[ =](.*)" strings comment => '$', #' # Comment provided by user _ports => '%', # hash of Verilog::Netlist::Ports _portsordered=> '@', # list of Verilog::Netlist::Ports as ordered in list of ports _nets => '%', # hash of Verilog::Netlist::Nets _cells => '%', # hash of Verilog::Netlist::Cells _celldecls => '%', # hash of declared cells (for autocell only) _cellarray => '%', # hash of declared cell widths (for autocell only) _cellnum => '$', # Number of next unnamed cell _level => '$', # Depth in hierarchy (if calculated) _statements => '%', # hash of Verilog::Netlist::ContAssigns _stmtnum => '$', # Number of next unnamed statement is_top => '$', #' # Module is at top of hier (not a child) is_libcell => '$', #' # Module is a library cell # SystemPerl: _autocovers => '%', #' # Hash of covers found in code _autosignal => '$', #' # Module has /*AUTOSIGNAL*/ in it _autosubcells=> '$', #' # Module has /*AUTOSUBCELL_DECL*/ in it _autotrace => '%', #' # Module has /*AUTOTRACE*/ in it _autoinoutmod=> '$', #' # Module has /*AUTOINOUT_MODULE*/ in it _pintemplates=> '@', #' # Module SP_TEMPLATEs _ctor => '$', #' # Module has SC_CTOR in it _code_symbols=> '$', #' # Hash ref of symbols found in raw code _covergroups => '%', #' # Hash of covergroups found in code lesswarn => '$', #' # True if some warnings should be disabled ]); sub delete { my $self = shift; foreach my $oref ($self->nets) { $oref->delete; } foreach my $oref ($self->ports) { $oref->delete; } foreach my $oref ($self->cells) { $oref->delete; } foreach my $oref ($self->statements) { $oref->delete; } my $h = $self->netlist->{_modules}; delete $h->{$self->name}; return undef; } ###################################################################### sub logger { return $_[0]->netlist->logger; } sub modulename_from_filename { my $filename = shift; (my $module = $filename) =~ s/.*\///; $module =~ s/\.[a-z]+$//; return $module; } sub find_port { my $self = shift; my $search = shift; return $self->_ports->{$search} || $self->_ports->{"\\".$search." "}; } sub find_port_by_index { my $self = shift; my $myindex = shift; # @{$self->_portsordered}[$myindex-1] returns the name of # the port in the module at this index. Then, this is # used to find the port reference via the port hash my $name = @{$self->_portsordered}[$myindex-1]; return undef if !$name; return $self->_ports->{$name}; } sub find_cell { my $self = shift; my $search = shift; return $self->_cells->{$search} || $self->_cells->{"\\".$search." "}; } sub find_net { my $self = shift; my $search = shift; my $rtn = $self->_nets->{$search}||""; #print "FINDNET ",$self->name, " SS $search $rtn\n"; return $self->_nets->{$search} || $self->_nets->{"\\".$search." "}; } sub attrs_sorted { return (sort {$a cmp $b} @{$_[0]->attrs}); } sub nets { return (values %{$_[0]->_nets}); } sub nets_sorted { return (sort {$a->name() cmp $b->name()} (values %{$_[0]->_nets})); } sub ports { return (values %{$_[0]->_ports}); } sub ports_sorted { return (sort {$a->name() cmp $b->name()} (values %{$_[0]->_ports})); } sub ports_ordered { my $self = shift; return map {$self->_ports->{$_}} @{$self->_portsordered}; } sub cells { return (values %{$_[0]->_cells}); } sub cells_sorted { return (sort {$a->name() cmp $b->name()} (values %{$_[0]->_cells})); } sub statements { return (values %{$_[0]->_statements}); } sub statements_sorted { return (sort {$a->name() cmp $b->name()} (values %{$_[0]->_statements})); } sub nets_and_ports_sorted { my $self = shift; my @list = ($self->nets, $self->ports,); my @outlist; my $last = ""; # Eliminate duplicates foreach my $e (sort {$a->name() cmp $b->name()} (@list)) { next if $e eq $last; push @outlist, $e; $last = $e; } return (@outlist); } sub new_net { my $self = shift; my %params = @_; # Create a new net under this my $netref; if (defined($params{msb})) { my $data_type; $data_type = "[".($params{msb}); $data_type .= ":".($params{lsb}) if defined $params{lsb}; $data_type .= "]"; $netref = new Verilog::Netlist::Net(decl_type=>'net', net_type => 'wire', data_type => $data_type, %params, module => $self); } else { $netref = new Verilog::Netlist::Net(decl_type => 'net', net_type => 'wire', %params, module => $self); } $self->_nets($netref->name(), $netref); return $netref; } sub new_attr { my $self = shift; my $clean_text = shift; push @{$self->attrs}, $clean_text; } sub new_port { my $self = shift; # @_ params # Create a new port under this module my $portref = new Verilog::Netlist::Port(@_, module=>$self,); $self->_ports($portref->name(), $portref); return $portref; } sub new_cell { my $self = shift; my %params = @_; # name=>, filename=>, lineno=>, submodname=>, params=> # Create a new cell under this module if (!defined $params{name} || $params{name} eq '') { # Blank instance name; invent a new one; use the next instance number in this module t$ $self->_cellnum(($self->_cellnum||0) + 1); $params{name} = '__unnamed_instance_' . $self->_cellnum; } if (my $preexist = $self->find_cell($params{name})) { $self->_cellnum(($self->_cellnum||0) + 1); $params{name} .= '__duplicate_' . $self->_cellnum; } # Create a new cell; pass the potentially modified options my $cellref = new Verilog::Netlist::Cell(%params, module=>$self,); # Add the new cell to the hash of cells in this module $self->_cells($params{name}, $cellref); return $cellref; } sub new_contassign { my $self = shift; my %params = @_; # name=>, filename=>, lineno=>, keyword=> etc # Create a new statement under this module if (!defined $params{name} || $params{name} eq '') { # Blank instance name; invent a new one; use the next instance number in this module t$ $self->_stmtnum(($self->_stmtnum||0) + 1); $params{name} = '__unnamed_statement_' . $self->_stmtnum; } # Create a new object; pass the potentially modified options my $newref = new Verilog::Netlist::ContAssign(%params, module=>$self,); # Add the new object to the hash of statements in this module $self->_statements($params{name}, $newref); return $newref; } sub new_defparam { my $self = shift; my %params = @_; # name=>, filename=>, lineno=>, keyword=> etc # Create a new statement under this module if (!defined $params{name} || $params{name} eq '') { # Blank instance name; invent a new one; use the next instance number in this module t$ $self->_stmtnum(($self->_stmtnum||0) + 1); $params{name} = '__unnamed_statement_' . $self->_stmtnum; } # Create a new object; pass the potentially modified options my $newref = new Verilog::Netlist::Defparam(%params, module=>$self,); # Add the new object to the hash of statements in this module $self->_statements($params{name}, $newref); return $newref; } sub level { my $self = shift; my $level = $self->_level; return $level if defined $level; $self->_level(1); # Set before recurse in case there's circular module refs foreach my $cell ($self->cells) { if ($cell->submod) { my $celllevel = $cell->submod->level; $self->_level($celllevel+1) if $celllevel >= $self->_level; } } return $self->_level; } sub link { my $self = shift; # Ports create nets, so link ports before nets foreach my $portref ($self->ports) { $portref->_link(); } foreach my $netref ($self->nets) { $netref->_link(); } foreach my $cellref ($self->cells) { $cellref->_link(); } } sub lint { my $self = shift; if ($self->netlist->{use_vars}) { foreach my $portref ($self->ports) { $portref->lint(); } foreach my $netref ($self->nets) { $netref->lint(); } } foreach my $cellref ($self->cells) { $cellref->lint(); } foreach my $oref ($self->statements) { $oref->lint(); } } sub verilog_text { my $self = shift; my @out = ($self->keyword||'module')." ".$self->name." (\n"; my $indent = " "; # Port list my $comma=""; push @out, $indent; foreach my $portref ($self->ports_sorted) { push @out, $comma, $portref->verilog_text; $comma = ", "; } push @out, ");\n"; # Signal list foreach my $netref ($self->nets_sorted) { push @out, $indent, $netref->verilog_text, "\n"; } # Cell list foreach my $cellref ($self->cells_sorted) { push @out, $indent, $cellref->verilog_text, "\n"; } foreach my $oref ($self->statements_sorted) { push @out, $indent, $oref->verilog_text, "\n"; } push @out, "end".($self->keyword||'module')."\n"; return (wantarray ? @out : join('',@out)); } sub dump { my $self = shift; my $indent = shift||0; my $norecurse = shift; print " "x$indent,"Module:",$self->name()," Kwd:",($self->keyword||'')," File:",$self->filename(),"\n"; if (!$norecurse) { foreach my $portref ($self->ports_sorted) { $portref->dump($indent+2); } foreach my $netref ($self->nets_sorted) { $netref->dump($indent+2); } foreach my $cellref ($self->cells_sorted) { $cellref->dump($indent+2); } foreach my $cellref ($self->statements_sorted) { $cellref->dump($indent+2); } } } ###################################################################### #### Package return 1; __END__ =pod =head1 NAME Verilog::Netlist::Module - Module within a Verilog Netlist =head1 SYNOPSIS use Verilog::Netlist; ... my $module = $netlist->find_module('modname'); my $cell = $self->find_cell('name') my $port = $self->find_port('name') my $net = $self->find_net('name') =head1 DESCRIPTION A Verilog::Netlist::Module object is created by Verilog::Netlist for every module, macromodule, primitive or program in the design. =head1 ACCESSORS See also Verilog::Netlist::Subclass for additional accessors and methods. =over 4 =item $self->cells Returns list of references to Verilog::Netlist::Cell in the module. =item $self->cells_sorted Returns list of name sorted references to Verilog::Netlist::Cell in the module. =item $self->comment Returns any comments following the definition. keep_comments=>1 must be passed to Verilog::Netlist::new for comments to be retained. =item $self->find_port_by_index Returns the port name associated with the given index. Indexes start at 1 (pin numbers are traditionally counted from pin 1..pin N, not starting at zero. This was probably an unfortunate choice, sorry.) =item $self->is_top Returns true if the module has no cells referencing it (is at the top of the hierarchy.) =item $self->keyword Returns the keyword used to declare the module ("module", "macromodule", "primitive" or "program".) It might at first not seem obvious that programs are considered modules, but in most cases they contain the same type of objects so can be handled identically. =item $self->name The name of the module. =item $self->netlist Reference to the Verilog::Netlist the module is under. =item $self->nets Returns list of references to Verilog::Netlist::Net in the module. =item $self->nets_sorted Returns list of name sorted references to Verilog::Netlist::Net in the module. =item $self->nets_and_ports_sorted Returns list of name sorted references to Verilog::Netlist::Net and Verilog::Netlist::Port in the module. =item $self->ports Returns list of references to Verilog::Netlist::Port in the module. =item $self->ports_ordered Returns list of references to Verilog::Netlist::Port in the module sorted by pin number. =item $self->ports_sorted Returns list of references to Verilog::Netlist::Port in the module sorted by name. =item $self->statements Returns list of references to Verilog::Netlist::ContAssign in the module. Other statement types (Always, etc) may also be added to this list in the future. =item $self->statements_sorted Returns list of name sorted references to Verilog::Netlist::ContAssign in the module. Other statement types (Always, etc) may also be added to this list in the future. =back =head1 MEMBER FUNCTIONS See also Verilog::Netlist::Subclass for additional accessors and methods. =over 4 =item $self->find_cell(I) Returns Verilog::Netlist::Cell matching given name. =item $self->find_port(I) Returns Verilog::Netlist::Port matching given name. =item $self->find_net(I) Returns Verilog::Netlist::Net matching given name. =item $self->is_libcell Returns if module declared inside a `celldefine. =item $self->level Returns the reverse depth of this module with respect to other modules. Leaf modules (modules with no cells) will be level 1. Modules which instantiate cells of level 1 will be level 2 modules and so forth. See also Netlist's modules_sorted_level. =item $self->lint Checks the module for errors. =item $self->link Creates interconnections between this module and other modules. =item $self->modulename_from_filename Uses a rough algorithm (drop the extension) to convert a filename to the module that is expected to be inside it. =item $self->new_cell Creates a new Verilog::Netlist::Cell. =item $self->new_port Creates a new Verilog::Netlist::Port. =item $self->new_net Creates a new Verilog::Netlist::Net. =item $self->dump Prints debugging information for this module. =item $self->verilog_text Returns verilog code which represents this module. Returned as an array that must be joined together to form the final text string. The netlist must be already ->link'ed for this to work correctly. =back =head1 DISTRIBUTION Verilog-Perl is part of the L free Verilog EDA software tool suite. The latest version is available from CPAN and from L. Copyright 2000-2021 by Wilson Snyder. This package is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. =head1 AUTHORS Wilson Snyder =head1 SEE ALSO L, L L =cut Verilog-Perl-3.478/Netlist/Defparam.pm0000644000177100017500000000625214057150455017533 0ustar wsnyderwsnyder# Verilog - Verilog Perl Interface # See copyright, etc in below POD section. ###################################################################### package Verilog::Netlist::Defparam; use Verilog::Netlist; use Verilog::Netlist::Subclass; use vars qw($VERSION @ISA); use strict; @ISA = qw(Verilog::Netlist::Defparam::Struct Verilog::Netlist::Subclass); $VERSION = '3.478'; structs('new', 'Verilog::Netlist::Defparam::Struct' =>[name => '$', #' # Unique ID keyword => '$', #' # Keyword name filename => '$', #' # Filename this came from lineno => '$', #' # Linenumber this came from userdata => '%', # User information attributes => '%', #' # Misc attributes for systemperl or other processors # lhs => '$', #' # Left hand side of assignment rhs => '$', #' # Right hand side of assignment module => '$', #' # Module reference ]); sub delete { my $self = shift; my $h = $self->module->_statements; delete $h->{$self->name}; return undef; } ###################################################################### #### Methods sub logger { my $self = shift; return $self->netlist->logger; } sub netlist { my $self = shift; return $self->module->netlist; } sub lint {} sub link {} sub verilog_text { my $self = shift; my @out = ($self->keyword," ",$self->lhs," = ",$self->rhs,";"); return (wantarray ? @out : join('',@out)); } sub dump { my $self = shift; my $indent = shift||0; print " "x$indent,"Defparam:",$self->keyword," lhs:",$self->lhs," rhs:",$self->rhs; print "\n"; } ###################################################################### #### Package return 1; __END__ =pod =head1 NAME Verilog::Netlist::Defparam - Defparam assignment =head1 SYNOPSIS use Verilog::Netlist; ... foreach my $cont ($module->statements) print $cont->name; =head1 DESCRIPTION A Verilog::Netlist::Defparam object is created by Verilog::Netlist for every defparam in the current module. =head1 ACCESSORS See also Verilog::Netlist::Subclass for additional accessors and methods. =over 4 =item $self->keyword Keyword used to declare the assignment. Currently "defparam" is the only supported value. =item $self->lhs Left hand side of the assignment. =item $self->module Pointer to the module the cell is in. =item $self->netlist Reference to the Verilog::Netlist the cell is under. =item $self->rhs Right hand side of the assignment. =back =head1 MEMBER FUNCTIONS See also Verilog::Netlist::Subclass for additional accessors and methods. =over 4 =item $self->dump Prints debugging information for this cell. =back =head1 DISTRIBUTION Verilog-Perl is part of the L free Verilog EDA software tool suite. The latest version is available from CPAN and from L. Copyright 2000-2021 by Wilson Snyder. This package is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. =head1 AUTHORS Wilson Snyder =head1 SEE ALSO L, L L =cut Verilog-Perl-3.478/Netlist/ContAssign.pm0000644000177100017500000000631514057150455020064 0ustar wsnyderwsnyder# Verilog - Verilog Perl Interface # See copyright, etc in below POD section. ###################################################################### package Verilog::Netlist::ContAssign; use Verilog::Netlist; use Verilog::Netlist::Subclass; use vars qw($VERSION @ISA); use strict; @ISA = qw(Verilog::Netlist::ContAssign::Struct Verilog::Netlist::Subclass); $VERSION = '3.478'; structs('new', 'Verilog::Netlist::ContAssign::Struct' =>[name => '$', #' # Unique ID keyword => '$', #' # Keyword name filename => '$', #' # Filename this came from lineno => '$', #' # Linenumber this came from userdata => '%', # User information attributes => '%', #' # Misc attributes for systemperl or other processors # lhs => '$', #' # Left hand side of assignment rhs => '$', #' # Right hand side of assignment module => '$', #' # Module reference ]); sub delete { my $self = shift; my $h = $self->module->_statements; delete $h->{$self->name}; return undef; } ###################################################################### #### Methods sub logger { my $self = shift; return $self->netlist->logger; } sub netlist { my $self = shift; return $self->module->netlist; } sub lint {} sub link {} sub verilog_text { my $self = shift; my @out = ($self->keyword," ",$self->lhs," = ",$self->rhs,";"); return (wantarray ? @out : join('',@out)); } sub dump { my $self = shift; my $indent = shift||0; print " "x$indent,"ContAssign:",$self->keyword," lhs:",$self->lhs," rhs:",$self->rhs; print "\n"; } ###################################################################### #### Package return 1; __END__ =pod =head1 NAME Verilog::Netlist::ContAssign - ContAssign assignment =head1 SYNOPSIS use Verilog::Netlist; ... foreach my $cont ($module->statements) print $cont->name; =head1 DESCRIPTION A Verilog::Netlist::ContAssign object is created by Verilog::Netlist for every continuous assignment statement in the current module. =head1 ACCESSORS See also Verilog::Netlist::Subclass for additional accessors and methods. =over 4 =item $self->keyword Keyword used to declare the assignment. Currently "assign" is the only supported value. =item $self->lhs Left hand side of the assignment. =item $self->module Pointer to the module the cell is in. =item $self->netlist Reference to the Verilog::Netlist the cell is under. =item $self->rhs Right hand side of the assignment. =back =head1 MEMBER FUNCTIONS See also Verilog::Netlist::Subclass for additional accessors and methods. =over 4 =item $self->dump Prints debugging information for this cell. =back =head1 DISTRIBUTION Verilog-Perl is part of the L free Verilog EDA software tool suite. The latest version is available from CPAN and from L. Copyright 2000-2021 by Wilson Snyder. This package is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. =head1 AUTHORS Wilson Snyder =head1 SEE ALSO L, L L =cut Verilog-Perl-3.478/Netlist/PinSelection.pm0000644000177100017500000000575014035374034020407 0ustar wsnyderwsnyder# Verilog - Verilog Perl Interface # See copyright, etc in below POD section. ###################################################################### package Verilog::Netlist::PinSelection; use vars qw($VERSION); use strict; use warnings; $VERSION = '3.427'; ###################################################################### #### Methods ## Constructor sub new { my ($class, $netname, $msb, $lsb) = @_; my $self = bless({}, $class); $self->{_netname} = $netname; $self->{_msb} = $msb; $self->{_lsb} = $lsb; return $self; } ## Standard accessors sub netname { # ($self, $new) = @_; $_[0]->{_netname} = $_[1] if (@_ == 2); return $_[0]->{_netname}; } sub lsb { # ($self, $new) = @_; $_[0]->{_lsb} = $_[1] if (@_ == 2); return $_[0]->{_lsb}; } sub msb { # ($self, $new) = @_; $_[0]->{_msb} = $_[1] if (@_ == 2); return $_[0]->{_msb}; } ## Member functions sub bracketed_msb_lsb { my $self = shift; my $out = ""; # Handle sized constant numbers (e.g., 7'b0) distinctively # but leave unsized constants (msb/lsb undefined) alone. if ($self->netname =~ /^'/) { $out .= $self->msb + 1 if defined($self->msb); $out .= $self->netname; } else { $out .= $self->netname; if (defined($self->msb)) { if ($self->msb == $self->lsb) { $out .= "[".$self->msb."]"; } else { $out .= "[".$self->msb.":".$self->lsb."]"; } } } return $out; } ###################################################################### #### Package return 1; __END__ =pod =head1 NAME Verilog::Netlist::PinSelection - Nets attached to a Verilog Cell's Pins =head1 DESCRIPTION Verilog::Netlist::PinSelection objects are used by Verilog::Netlist::Pin to define ranges of nets attached to the respective pin of a cell. =head1 ACCESSORS =over 4 =item $self->netname Name of the respective net, or, if use_pinselects is disabled, the string representation of the whole pin value. In the case of a sized constant only the part following the ' is stored while the width is encoded in the msb and lsb fields. =item $self->lsb Least significant bit of the underlying net within the selection. =item $self->msb Most significant bit of the underlying net within the selection. =back =head1 MEMBER FUNCTIONS =over 4 =item $self->bracketed_msb_lsb Returns the common string representation of a vectored net, e.g. netA[15:8]. =back =head1 DISTRIBUTION Verilog-Perl is part of the L free Verilog EDA software tool suite. The latest version is available from CPAN and from L. Copyright 2000-2021 by Wilson Snyder. This package is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. =head1 AUTHORS Stefan Tauner Wilson Snyder # =head1 SEE ALSO # L, # L # L =cut Verilog-Perl-3.478/README.pod0000644000177100017500000002605014035374034015470 0ustar wsnyderwsnyder=pod =head1 NAME Verilog-Perl - Overview of Verilog language packages for Perl =head1 DESCRIPTION The Verilog-Perl distribution provides Perl parsing and utilities for the Verilog Language. This file provides an overview of the distribution. Verilog-Perl is currently a mature tool. Bugs are fixed and IEEE language capabilities updated as needed, but the basic features and API are not expected to change. For general information see L. For specific details on each component, see that component's manpage. You may also want to try the AUTO features present in L Verilog-Mode. =head1 SCRIPTS The following scripts are installed by Verilog-Perl: =over 4 =item L Vhier reads the Verilog files passed on the command line and outputs a tree of all of the filenames, modules, and cells referenced by that file. =item L Vpassert will read the specified Verilog files and preprocess special PLI assertions. =item L Vppreproc (Verilog-Perl Pre Processor) reads the Verilog files passed on the command line and outputs preprocessed output. =item L Vrename will allow a signal to be changed across all levels of the design hierarchy, or to create a cross reference of signal names. =back =head1 PACKAGES =over 4 =item L Verilog::Getopt provides standardized handling of options similar to Verilog/VCS and cc/GCC. =item L Verilog::Language provides general utilities for using the Verilog Language, such as parsing numbers or determining what keywords exist. =item L Verilog::Netlist reads and holds interconnect information about a whole design database. =item L A Verilog::Netlist::Cell object is created by Verilog::Netlist for every instantiation in the current module. =item L A Verilog::Netlist::ContAssign object is created by Verilog::Netlist for every continuous assignment in the current module. =item L Verilog::Netlist::File allows Verilog::Netlist objects to be read and written in Verilog format. =item L A Verilog::Netlist::Module object is created by Verilog::Netlist for every module in the design. =item L A Verilog::Netlist::Net object is created by Verilog::Netlist::Module for every signal and input/output declaration in the current module. =item L A Verilog::Netlist::Pin object is created by Verilog::Netlist::Cell for for each pin connection on a cell. =item L A Verilog::Netlist::Port object is created by Verilog::Netlist::Module for every port connection in the module. =item L The Verilog::Netlist::Subclass is used as a base class for all Verilog::Netlist::* structures. =item L Verilog::Parser will tokenize a Verilog file and invoke various callback methods. =item L Verilog::Preproc reads Verilog files, and preprocesses them according to the Verilog specification. Programs can be easily converted from reading a IO::File into reading preprocessed output from Verilog::Preproc. =item L Verilog::SigParser builds upon the Verilog::Parser package to provide callbacks for when a signal is declared, a module instantiated, or a module defined. =back =head1 WHICH PARSER PACKAGE? If you are starting a new application which needs to parse the Verilog language you have several tools available to you. Which you pick depends on how low level and complete the information you need is. =over 4 =item VParseBison.y The low level VParse* source files may be of use when you need a starting point for your own a full C++ SystemVerilog grammar parser, using Bison and Flex. It understands most of the SystemVerilog 2017 grammar (1800-2017 Appendix A). =item Verilog::Preproc Verilog::Preproc is useful when you need only post-preprocessed text output, or a list of defines, includes, etc. It can preprocess a file, or be used to provide the Verilog macro language on top of synthesis scripts. It understands and implements all preprocessor features of SystemVerilog 2017. =item Verilog::Parser Verilog::Parser is useful when you need to tokenize or write source filters (where you need everything including whitespace). It can take raw files, or preprocessed input, and generates callbacks. It understands all SystemVerilog 2017 keywords. =item Abstract Syntax Tree Verilog::Parser knows enough to make a complete Abstract Syntax Tree (AST) of Verilog syntax. This represents all major constructs such as a "module" as a data structure, but does not interconnect the AST nodes as would be needed to follow signals. Not all keywords have been implemented; many are parsed but otherwise ignored. A complete Ast tree would allow any arbitrary transformation of Verilog syntax (everything is known excluding whitespace). For these applications consider Verilator's XML output (below). =item Verilog::SigParser Verilog::SigParser is useful when you need a list of modules, signals, ports, functions, etc. It requires a preprocessed file (from Verilog::Preproc), and can parse all SystemVerilog 2017 files, but only provides callbacks on certain interesting things. The SigParser operates only on a file at a time; it does not interconnect signals nor perform any elaboration (resolution of parameters). =item Verilog::Netlist Verilog::Netlist is useful for when you need the hierarchy, and a list of signals per module, pins per cell, etc. It builds upon the output of Verilog::SigParser, so requires preprocessed files (from Verilog::Preproc). It parses all SystemVerilog 2017 files, but not all SystemVerilog constructs are loaded into objects. Verilog::Netlist interconnects modules with instantiations but does not perform any elaboration (resolution of parameters). =item VPI Using the VPI is the best way to access the behavior of the design. It is not part of this package as it requires a compliant simulator and C++ code to call the VPI, and understands as much of the language as the simulator supports. This allows writing lint checks and full knowledge of all parts of the code. The VPI can operate ONLY on an elaborated design (where all parameters are resolved). Walking a VPI tree general requires a good deal of work compared to simple scripting (though little work compared to writing a parser from scratch). =item Verilator The Verilator program also contains a very similar front end as Verilog-Perl and can create XML output showing the abstract syntax tree. Verilator also understands how to elaborate and connect complex pins and types, but supports mostly only the synthesis subset of SystemVerilog. If you're looking to parse only synthesizable code this is the recommended route. =item Verilog-Mode for Emacs Although not a parser, a common requested use of Verilog-Perl is to automatically make shell modules and interconnect modules. Verilog-Mode is a better solution to this problem, as it results in completely portable code; the program (Verilog-Mode) isn't needed for others to update the design. It's also in very common usage, including by many IP providers. =back =head1 INSTALLATION Skip this section if Verilog-Perl has already been installed. Verilog-Perl should run on any system with Perl, G++, Flex, and Bison. It is known to work on most Linux distributions, plus Cygwin. You may install using either CPAN, or the sources. If you plan to do any development on Verilog-Perl, use the sources. =head2 CPAN Installation Option 1: Easiest installation is using the "CPAN" command line that comes with Perl. After configuring CPAN the first time, simply cpan install Verilog-Perl # And see the documentation man Verilog-Perl # Or, sometimes the capitalization is changed man verilog-perl Read the rest of this file for details on the programs provided. =head2 Manual Installation from Repository Option 2: Build any version using the source development repository with: git clone http://git.veripool.org/git/Verilog-Perl # Only first time cd Verilog-Perl git pull # Make sure we're up-to-date git tag # See what versions exist (recent GITs only) #git checkout master # Use development branch (e.g. recent bug fix) #git checkout stable # Use most recent release #git checkout v{version} # Switch to specified release version perl Makefile.PL # Ignore warning about README, this file will be generated make make test make install Read the rest of this file for details on the programs provided. =head1 FAQ =over 4 =item Why do I get "unexpected `do'" or "unexpected `bit'" errors? Do, bit, ref, return, and other words are now SystemVerilog keywords. You should change your code to not use them to insure it works with newer tools. Alternatively, surround them by the Verilog 2005/SystemVerilog begin_keywords pragma to indicate Verilog 2001 code. `begin_keywords "1364-2001" integer bit; initial bit = 1; `end_keywords Alternatively use the --language (for vhier) or Verilog::Language::language_standard call to specify "1364-2001", or for really old code, "1364-1995". But, again, you really should fix the Verilog code. =item With Verilog::Netlist how do I resolve signal widths that include parameters down to constants? Unfortunately parameter resolution is part of elaboration. Verilog-Perl doesn't do elaboration as it requires a good fraction of a complete simulator implementation. Many applications can work around this limitation, if yours still requires elaboration you're stuck with using Verilator or the VPI, see the sections above. =back =head1 DISTRIBUTION Verilog-Perl is part of the L free Verilog EDA software tool suite. The latest version is available from CPAN and from L. Copyright 2000-2021 by Wilson Snyder. This package is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. This code is provided with no warranty of any kind, and is used entirely at your own risk. =head1 AUTHORS Wilson Snyder =head1 SEE ALSO L, L, L, L L, L, L L, L, L, L L, L, L, L, L, L, L, L, L, L, And the LVerilog-Mode package for Emacs. =cut Verilog-Perl-3.478/Makefile.PL0000755000177100017500000001251214035374034016002 0ustar wsnyderwsnyder# DESCRIPTION: Perl ExtUtils: Type 'perl Makefile.PL' to create a Makefile for this package # # Copyright 2000-2021 by Wilson Snyder. This program is free software; # you can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. require 5.005; use ExtUtils::MakeMaker; use Carp; use Config; sub MY::postamble { my $out=""; # Note OPTIMIZE is passed from upper makefile, so this code needed there too. # -O2 optimization seems unreasonably slow on nearly every platform. I give up. my $optimize = $Config{optimize}; $optimize =~ s/(^| )-O2( |$)/\1-O\2/g; # pass hardening flags $optimize .= " $ENV{CFLAGS} $ENV{CPPFLAGS}"; $out .= "OPTIMIZE = $optimize\n"; if ($Config{osname} =~ /cygwin/i || $Config{archname} =~ /cygwin/i) { # Cygwin ExtUtils::MakeMaker ignores our LIBS declaration and says # "No library found for -lstdc++". Force it. $out .= "LDLOADLIBS += -lstdc++\n"; # Cygwin: High optimization causes g++ "out of memory" $out .= "OPTIMIZE += -O\n"; } if ($Config{osname} =~ /darwin/i || $Config{archname} =~ /darwin/i) { # MakeMaker wants to create bundles on MacOSX rather than dylibs. We override DLEXT and LDDLFLAGS generated by MakeMaker in this case $out .= "DLEXT = dylib\n"; if ($^V eq '5.16.2') { $out .= sprintf("LDDLFLAGS = -dynamiclib -lstdc++ -L/System/Library/Perl/5.16.2/%s/CORE -lperl -L/usr/local/lib\n",$Config{archname}); } elsif ($^V eq '5.12.4') { $out .= sprintf("LDDLFLAGS = -dynamiclib -lstdc++ -L/System/Library/Perl/5.12/%s/CORE -lperl -L/usr/local/lib\n",$Config{archname}); } elsif ($^V eq '5.18.2') { $out .= sprintf("LDDLFLAGS = -dynamiclib -lstdc++ -L/System/Library/Perl/5.18/%s/CORE -lperl -L/usr/local/lib\n",$Config{archname}); } elsif ($^V < 'v5.26.3') { $out .= sprintf("LDDLFLAGS = -dynamiclib -lstdc++ -L/System/Library/Perl/%vd/%s/CORE -lperl -lgcc_eh -L/usr/local/lib\n",$^V,$Config{archname}); } } $out .= "CCFLAGS += -Wall -Wno-unused -Wno-sign-compare -Werror\n" if $ENV{VERILATOR_AUTHOR_SITE}; $out .= "CCFLAGS += $ENV{VERILOGPERL_CCFLAGS}\n" if defined $ENV{VERILOGPERL_CCFLAGS}; $out .= "OPTIMIZE += -Wno-unused\n" if $ENV{VERILATOR_AUTHOR_SITE}; # Makefile has another -Wall #$out .= "OPTIMIZE += -O0 -ggdb\n" if $ENV{VERILATOR_AUTHOR_SITE}; print "%Warning: -O0 --gdb on, also FLEX -d on\n"; $out .= "OPTIMIZE += $ENV{VERILOGPERL_CCFLAGS}\n" if defined $ENV{VERILOGPERL_CCFLAGS}; $out .= ' all:: README README: README.pod -$(RM_RF) $@ pod2text --loose $< > $@ clean:: -$(RM_RF) simv .vpassert test_dir *.tmp dist: maintainer-copy distcheck README ## Maintainer use: preexist: svnorcvs nexists $(DISTNAME)_$(VERSION_SYM) test -s README tag: svnorcvs tag $(DISTNAME)_$(VERSION_SYM) maintainer-diff: svnorcvs diff $(DISTNAME)_$(VERSION_SYM) maintainer-dist: preexist dist tag svnorcvs release $(DISTVNAME).tar.gz maintainer-copy: maintainer-clean:: distclean -$(RM_RF) README Makefile MANIFEST.bak $(MAKEFILE_OLD) */gen ## cppcheck CPPCHECK = cppcheck CPPCHECK_FLAGS = --enable=all --inline-suppr CPPCHECK_CPP = $(wildcard */*.cpp) CPPCHECK_DEP = $(subst .cpp,.cppcheck,$(CPPCHECK_CPP)) cppcheck: $(CPPCHECK_DEP) %.cppcheck: %.cpp $(CPPCHECK) $(CPPCHECK_FLAGS) $< '; return $out; } my $fail; local $! = undef; my $have_gen = -d "Preproc/gen"; `flex --version`; if ($?) { if ($have_gen) { warn "\n-Note: 'flex' must be installed to build from sources\n"; } else { $fail=1; warn "\n%Error: 'flex' must be installed to build\n\n"; } } `bison --version`; if ($?) { if ($have_gen) { warn "\n-Note: 'bison' must be installed to build from sources\n"; } else { $fail=1; warn "\n%Error: 'bison' must be installed to build\n\n"; } } `g++ --version`; if ($?) { $fail=1; warn "\n%Error: 'gcc/g++' must be installed to build\n"; } if ($fail) { if ($ENV{AUTOMATED_TESTING}) { exit(0); } else { die "%Error: Exiting due to above missing dependencies.\n"; } } if (!-r "README" && !-r "Makefile") { warn "-Note: If building from 'git' sources (not from a CPAN tar file),\n" ."-Note: ignore any 'files are missing' below for */gen/ and README:\n"; } WriteMakefile( DISTNAME => 'Verilog-Perl', NAME => 'Verilog::Language', AUTHOR => 'Wilson Snyder ', ABSTRACT => 'Verilog language utilities and parsing', VERSION_FROM => 'Language.pm', NO_META => 1, #OPTIMIZE => '-ggdb', PREREQ_PM => { 'Pod::Usage' => 1.34, 'Data::Dumper' => 1, 'warnings' => 1, #---- Below are really BUILD_REQUIRES, but only newer perls understand that 'Digest::SHA' => 0, 'Test' => 1, 'Test::More' => 0, 'Time::HiRes' => 1, #'Test::Pod' => 1, # Required only for author tests #'Test::Perl::Critic' => 1, # Required only for author tests }, PMLIBDIRS => ['lib', 'Parser', 'Preproc', 'Netlist',], EXE_FILES => [qw( vrename vpassert vppreproc vhier vsplitmodule )], 'clean' => {FILES => qw (test_dir signals.vrename .vpassert simv ),}, 'dist' => {COMPRESS => 'gzip -9f', SUFFIX => '.gz', DIST_DEFAULT => 'README all tardist', }, ); my $mkv = `make --version`; if ($? || $mkv !~ /GNU Make/i) { warn "-Important: Now type 'gmake MAKE=gmake' as this package requires GNU Make\n"; } 1; Verilog-Perl-3.478/vsplitmodule0000755000177100017500000000641113422450702016477 0ustar wsnyderwsnyder#!/usr/bin/perl -w # See copyright, etc in below POD section. ###################################################################### use lib 'blib/lib'; use Verilog::EditFiles; use FindBin qw($RealBin $RealScript $Script); use strict; #====================================================================== # When editing, delete this section up to the next #==== die <new (# Verilog::EditFiles will use the below program name in its comments program => $Script, # Name of the directory to write the output modules to. # I like to put all generated files under a dir named "gen" # so it is obvious the files are generated. # (But for the Verilog-Perl internal tests, this needs to be test_dir) outdir => "test_dir", #"gen", # If true, add "`celldefine" before every module statement. #celldefine => 1, # For the write_lint method, the name of the linter to use. #lint_command => 'vlint --brief', # If defined, add the provided text before every module statement. # Generally used to insert lint off pragmas. #lint_header => "// lint_checking MY_RULES OFF\n", # If defined, add the provided text before every module statement. # Generally used to insert lint off pragmas. #include_header => "`include \"my_defines.v\"\n", # If defined, add the provided text before every module statement. # Generally used to insert lint off pragmas. #timescale_header => "`include \"my_timescale.v\"\n", # If set, remove any `timescales. #timescale_removal => 1, # If 1, replace any synopsys translate on/offs with "`ifdef SYNTHESIS" and # "`endif"s. If set to a string, use that string instead of "SYNTHESIS". translate_synthesis => 'SYNTHESIS', # The suffix to add to convert a module name into a filename. Defaults to #v_suffix => '.v', # If set, show what files are being read and written verbose => 1, ); # Remove all existing files under the output. You might not want to do # this if there are files you want to keep from there unlink(glob("$split->{outdir}/*.v")); # Read specified libraries and split them $split->read_and_split(glob("t/*.v")); # And write them out $split->write_files(); # And create a lint file $split->write_lint(); # If a file needs 'manual' search and replaces, we can do that too. $split->edit_file (# The filename to be edited filename=>"$split->{outdir}/a.v", # Callback subroutine that takes file contents as a string # and returns the new file contents cb=>sub { my $wholefile = shift; # Globally search and comment out any lines with "pulldown PULLDOWN" # See "man perlre" for examples. # The %mg here means to match multiple lines (you can put # \n in the regexp), and to do it globally $wholefile =~ s%(pulldown PULLDOWN;)%//vsplitmodule: $1%mg; return $wholefile; }); Verilog-Perl-3.478/MANIFEST.SKIP0000644000177100017500000000114014030463163015713 0ustar wsnyderwsnyder^CVS/ /CVS/ ^.git/ ,v$ \.(bak|old|new)/ \.(bak|old|new)$ \bMakefile$ ^INSTALL$ \.wpsin$ \.texi$ \.tar\. \.bs$ \.vpassert/.* \.o$ \.def$ \.dll$ \.exp$ \.gitattributes$ \.tmp$ \.vcs.*$ \.pre\..*$ _pretmp\..*$ VPreLex\.cpp$ simv .*\.tar\.gz \bblib\b nodist/.* pm_to_blib$ Parser/Parser.c Parser/VParseBison.*\.cpp Parser/VParseBison.*\.h Parser/VParseBison.*\.tab.c Parser/VParseBison.*\.output Parser/VParseLex.cpp Parser/VParseLex_pretmp.cpp Parser/.*_callbackgen\..* Parser/.*_cleaned\..* Preproc/Preproc.c Preproc/VPreLex_pretmp.cpp Preproc/.*_cleaned\..* signals.vrename test_dir \.svn/ ^(.*/)?MYMETA\..*$ Verilog-Perl-3.478/Preproc/0000755000177100017500000000000014057150520015432 5ustar wsnyderwsnyderVerilog-Perl-3.478/Preproc/toolhash0000755000177100017500000001621014035374034017205 0ustar wsnyderwsnyder#!/usr/bin/perl -w use Digest::SHA; use File::Copy qw(copy); # Core module use IO::File; use strict; our $Debug; # We don't use getopt, as want multiple in/outs and stop at first command my @opt_name; my @opt_in; # We allow empty opt_in and opt_out so we can cache --version checks. my @opt_out; my @opt_cmd; my @opt_vercmd; my $Opt_Gen = "gen"; my $Opt_Verbose; my $opt_skip_cmd = 0; my $in_cmd; my $list = \@opt_in; while (defined(my $param=shift @ARGV)) { if ($in_cmd) { push @opt_cmd, $param; } elsif ($param =~ /^-?-debug/) { $Debug=1; } elsif ($param =~ /^-?-cmd/) { $in_cmd = 1; } elsif ($param =~ /^-?-in/) { $list = \@opt_in; } elsif ($param =~ /^-?-name/) { $list = \@opt_name; } elsif ($param =~ /^-?-skip-cmd/) { $opt_skip_cmd = shift @ARGV; } elsif ($param =~ /^-?-out/) { $list = \@opt_out; } elsif ($param =~ /^-?-verbose/) { $Opt_Verbose=1; } elsif ($param =~ /^-?-gen/) { $Opt_Gen = shift @ARGV; } elsif ($param =~ /^-?-vercmd/) { $list = \@opt_vercmd; } elsif ($param =~ /^-/) { die "%Error: Unexpected argument: $param,"; } else { push @$list, $param; } } $opt_name[0] ||= $opt_cmd[0]; $opt_vercmd[0] ||= $opt_cmd[0]; $Opt_Verbose = 1 if $Debug; mkdir $Opt_Gen, 0777; # Hash of command, including this program args my $digest = Digest::SHA->new(1); { my $str = 'toolhash_1.0'; $str .= '----'.join(' ',@opt_in); $str .= '----'.join(' ',@opt_out); $str .= '----'; my $i = $opt_skip_cmd; foreach (@opt_cmd) { next if ($i-- > 0); $str.=' '.$_; } $str .= '----'; print "toolhash: Hashing $str\n" if $Debug; $digest->add($str); } foreach my $fn (@opt_in) { print "toolhash: Hashing $fn\n" if $Debug; my $fh = IO::File->new("<$fn") or die "toolhash: %Error: $! reading $fn\n"; $digest->addfile($fh); $fh->close; } my $arcfn = $Opt_Gen."/".$opt_name[0]; my $hash = $digest->b64digest; # Cache hit? If so, fill as we go remove_out(); my $hit = restore($hash, 1); if ($hit) { print "toolhash: Cache hit running $opt_name[0]\n" if $Opt_Verbose; exit(0); } else { print "toolhash: Cache miss running $opt_name[0]\n" if $Opt_Verbose; } remove_named(); my $out = run_cmd(); encache($hash, $out); remove_out(); $hit = restore($hash, 0); exit(0) if $hit; die "toolhash: %Error: encaching failed, didn't hit second time\n"; ####################################################################### sub restore { my $hash = shift; my $pass1 = shift; if ($pass1 && $ENV{TOOLHASH_RECACHE}) { print "toolhash: TOOLHASH_RECACHE set, missing\n" if $Debug; return 0; } # Returns hit my $hit = 1; my $fh = IO::File->new("<${arcfn}-0"); if (!$fh) { print "toolhash: Cache hash empty $arcfn\n" if $Debug; return 0; } my $line = $fh->getline; chomp $line; print "toolhash: Cache hash test $arcfn $line ".$hash."\n" if $Debug; if ($line ne $hash) { print "toolhash: Cache hash miss\n" if $Debug; return 0; } my $n = 1; foreach my $fn (@opt_out) { my $digout = "${arcfn}-${n}"; if (-r $digout) { print "toolhash: Cache hit $digout for $fn\n" if $Debug; # Restore, assuming all hits. copy($digout, $fn) or die "toolhash: %Error: $! on 'cp $digout $fn'\n"; } else { print "toolhash: Cache miss $digout for $fn\n" if $Debug; $hit = 0; last; } $n++; } if ($hit) { print "toolhash: Cache hit\n" if $Debug; if (my $fh = IO::File->new("<${arcfn}-s")) { # Dump stdout print join('',$fh->getlines); $fh->close; } } return $hit; } sub run_cmd { remove_out(); my $cmd = join(' ',@opt_cmd); # We can't use system() as we need the output and fork() isn't portable # without pulling in yet another package, so punt on spaces foreach (@opt_cmd) { if (/ /) { die "%Error: unsupported: spaces in command: '$cmd',"; } } print "\t$cmd\n" if $Debug||1; my $out = `$cmd`; my $status = $?; print $out; if ($status) { remove_out(); # See if bison/gcc/flex --version works my $vcmd = "$opt_vercmd[0] --version"; print "\t$vcmd\n" if $Debug; `$vcmd`; if ($?) { die "\n%Error: '$opt_cmd[0]' must be installed to build\n"; } exit $status >> 8; } return $out; } sub encache { my $hash = shift; my $out = shift; print "toolhash: Encache ".$hash."\n" if $Debug; my $fh = IO::File->new(">${arcfn}-0") or die "toolhash: %Error: $! ${arcfn}-0\n"; $fh->print($hash); $fh->close; if ($out ne "") { $fh = IO::File->new(">${arcfn}-s") or die "toolhash: %Error: $! ${arcfn}-s\n"; $fh->print($out); $fh->close; } my $n = 1; foreach my $fn (@opt_out) { my $digout = "${arcfn}-${n}"; copy($fn, $digout) or die "toolhash: %Error: $! on 'cp $fn $digout'\n"; $n++; } } sub remove_out { unlink for (@opt_out); # Ok if error } sub remove_named { unlink for (glob $Opt_Gen."/$opt_name[0]-*"); # Ok if error } ####################################################################### __END__ =pod =head1 NAME toolhash - Generate and hash files to avoid installation of build tools =head1 SYNOPSIS toolhash --in foo.c --out foo.o --cmd gcc -c -o foo.o foo.c =head1 DESCRIPTION Toolhash is used to install Verilog-Perl and other tools. It stores a hash of generated files (aka the cons make utility) for distribution to avoid building those files from scratch. The hash isn't stored as part of the filename, so that the MANIFEST can remain constant. =head1 ARGUMENTS =over 4 =item --cmd command args... Command and arguments to run. All further arguments are passed to the command. =item --gen ARG Specify location of generated file cache, defaults to "gen". =item --in filenames... Input filenames. =item --name Prefix for output files, or defaults to first --cmd argument. =item --verbose Print hit/miss messages. =item --skip-cmd Disable hashing first num-arg components of the command. This is used to avoid commands like "/usr/bin/perl ...." from hash missing when the Perl version and thus the path changes. =item --out filenames... Output filenames. =item --vercmd command Command to run to get --version. =back =head1 ENVIRONMENT =over 4 =item TOOLHASH_RECACHE Write the cache, but do not read from it. =back =head1 DISTRIBUTION This is part of the L free Verilog EDA software tool suite. The latest version is available from CPAN and from L. Copyright 2010-2021 by Wilson Snyder. This package is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. =head1 AUTHORS Wilson Snyder =head1 SEE ALSO C =cut ###################################################################### ### Local Variables: ### compile-command: "echo 'void i() {}' > foo.c; ./toolhash toolhash --debug --in foo.c --out foo.o --cmd gcc -c -o foo.o foo.c ; ls -la foo.* gen/* ; rm foo.*" ### End: Verilog-Perl-3.478/Preproc/Makefile.PL0000644000177100017500000000745414035374034017422 0ustar wsnyderwsnyder# DESCRIPTION: Perl ExtUtils: Type 'perl Makefile.PL' to create a Makefile for this package # # Copyright 2000-2021 by Wilson Snyder. This program is free software; # you can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. use ExtUtils::MakeMaker; use Config; sub MY::postamble { my $out; #print Config::myconfig(); if ($Config{osname} !~ /cygwin/i && $Config{archname} !~ /cygwin/i && $Config{osname} !~ /darwin/i && $Config{archname} !~ /darwin/i) { # Cygwin: Don't change LD, it breaks # Sun: Requires g++ LD # Linux: Either way $out .= "LD = g++\n"; } # Note OPTIMIZE is passed from upper makefile, so this code needed there too. my $optimize = $Config{optimize}; $optimize =~ s/(^| )-O2( |$)/\1-O\2/g; # pass hardening flags $optimize .= " $ENV{CFLAGS} $ENV{CPPFLAGS}"; $out .= "OPTIMIZE = $optimize\n"; if ($Config{osname} =~ /cygwin/i || $Config{archname} =~ /cygwin/i) { # Cygwin ExtUtils::MakeMaker ignores our LIBS declaration and says # "No library found for -lstdc++". Force it. $out .= "LDLOADLIBS += -lstdc++\n"; # Cygwin: High optimization causes g++ "out of memory" $out .= "OPTIMIZE += -O\n"; } if ($Config{osname} =~ /darwin/i || $Config{archname} =~ /darwin/i) { # MakeMaker wants to create bundles on MacOSX rather than dylibs. We override DLEXT and LDDLFLAGS generated by MakeMaker in this case $out .= "DLEXT = dylib\n"; if ($^V eq '5.12.4') { $out .= sprintf("LDDLFLAGS = -dynamiclib -lstdc++ -L/System/Library/Perl/5.12/%s/CORE -lperl -L/usr/local/lib\n",$Config{archname}); } elsif ($^V eq '5.18.2') { $out .= sprintf("LDDLFLAGS = -dynamiclib -lstdc++ -L/System/Library/Perl/5.18/%s/CORE -lperl -L/usr/local/lib\n",$Config{archname}); } elsif ($^V < 'v5.26.3') { $out .= sprintf("LDDLFLAGS = -dynamiclib -lstdc++ -L/System/Library/Perl/%vd/%s/CORE -lperl -lgcc_eh -L/usr/local/lib\n",$^V,$Config{archname}); } } $out .= "CCFLAGS += -Wall -Wno-unused -Wno-sign-compare -Werror\n" if $ENV{VERILATOR_AUTHOR_SITE}; #$out .= "CCFLAGS += -O0 -ggdb\n" if $ENV{VERILATOR_AUTHOR_SITE}; print "%Warning: -O0 --gdb on, also FLEX -d on"; $out .= "CCFLAGS += $ENV{VERILOGPERL_CCFLAGS}\n" if defined $ENV{VERILOGPERL_CCFLAGS}; $out .= "OPTIMIZE += -Wno-unused\n" if $ENV{VERILATOR_AUTHOR_SITE}; # Makefile has another -Wall $out .= "OPTIMIZE += $ENV{VERILOGPERL_CCFLAGS}\n" if defined $ENV{VERILOGPERL_CCFLAGS}; $out .= "CCFLAGS += -I\$(PPSRC)\n"; my $cmt = $ENV{VERILOGPERL_FLEX_DEBUG} ? "" : "#"; $out .= "${cmt}CFLAGS += -DFLEX_DEBUG\n"; $out .= "${cmt}LEXFLAGS += -d\n"; $out .= ' CC = $(OBJCACHE) g++ LEX = flex YACC = bison PPSRC = ../Preproc FLEXFIX = $(PPSRC)/flexfix TOOLHASH = $(PPSRC)/toolhash XSUBPPFIX = $(PPSRC)/xsubppfix VPATH += . $(PPSRC) VPreLex.o: VPreLex.h VPreProc.h VFileLine.h VPreProc.o: VPreLex.h VPreProc.h VFileLine.h VFileLine.o: VFileLine.h VPreLex_pretmp.cpp: VPreLex.l -$(LEX) --version $(PERL) $(TOOLHASH) --verbose --in $< --out $@ --cmd $(LEX) $(LEXFLAGS) -o$@ $< VPreLex.cpp: $(FLEXFIX) VPreLex_pretmp.cpp $(PERL) $(FLEXFIX) VPreLex < VPreLex_pretmp.cpp > $@ Preproc_cleaned.cpp: Preproc.c $(PERL) $(XSUBPPFIX) < Preproc.c > Preproc_cleaned.cpp clean:: -$(RM_RF) test *.d *.o *.output -$(RM_RF) VPreLex*.cpp Preproc_cleaned.* -$(RM_RF) VPreprocLex* '; return $out; } # Grr; some flags cause warnings in g++ (my $ccflags = $Config{ccflags}) =~ s/ *-Wdeclaration-after-statement//; WriteMakefile( NAME => "Verilog::Preproc", LIBS => '-lstdc++', VERSION_FROM => 'Preproc.pm', XSOPT => '-C++', CCFLAGS => $ccflags, OBJECT => 'VFileLine.o VPreProc.o VPreLex.o', MYEXTLIB => 'Preproc_cleaned.o', ); Verilog-Perl-3.478/Preproc/Preproc.xs0000644000177100017500000002472414035374034017435 0ustar wsnyderwsnyder#/* Verilog.xs -- Verilog Booter -*- C++ -*- #********************************************************************* #* #* DESCRIPTION: Verilog::Preproc Perl XS interface #* #* Author: Wilson Snyder #* #* Code available from: https://www.veripool.org/ #* #********************************************************************* #* #* Copyright 2000-2021 by Wilson Snyder. This program is free software; #* you can redistribute it and/or modify it under the terms of either the GNU #* Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. #* #* This program is distributed in the hope that it will be useful, #* but WITHOUT ANY WARRANTY; without even the implied warranty of #* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #* GNU General Public License for more details. #* #* You should have received a copy of the Perl Artistic License #* along with this module; see the file COPYING. If not, see #* www.cpan.org #* #*********************************************************************** #* Note with C++ XS libraries, the CLASS parameter is implied... #***********************************************************************/ /* Mine: */ #include "VPreProc.h" #include /* Perl */ extern "C" { # include "EXTERN.h" # include "perl.h" # include "XSUB.h" } #ifdef open # undef open /* Perl 64 bit on solaris has a nasty hack that redefines open */ #endif class VFileLineXs; #//********************************************************************** #// Preprocessor derived classes, so we can override the callbacks to call perl. class VPreProcXs : public VPreProc { public: SV* m_self; // Class called from (the hash, not SV pointing to the hash) deque m_filelineps; VPreProcXs() : VPreProc() {} virtual ~VPreProcXs(); // Callback methods virtual void comment(string filename); // Comment for keepComments=>sub virtual void include(string filename); // Request a include file be processed virtual void define(string name, string value, string params); // `define with parameters virtual void undef(string name); // Remove a definition virtual void undefineall(); // Remove all non-command-line definitions virtual bool defExists(string name); // Return true if define exists virtual string defParams(string name); // Return parameter list if define exists virtual string defValue(string name); // Return value of given define (should exist) virtual string defSubstitute(string substitute); // Return value to substitute for given post-parameter value void call(string* rtnStrp, int params, const char* method, ...); void unreadback(char* text); }; class VFileLineXs : public VFileLine { VPreProcXs* m_vPreprocp; // Parser handling the errors public: VFileLineXs(VPreProcXs* pp) : VFileLine(true), m_vPreprocp(pp) { if (pp) pushFl(); } virtual ~VFileLineXs() { } virtual VFileLine* create(const string& filename, int lineno) { VFileLineXs* filelp = new VFileLineXs(m_vPreprocp); filelp->init(filename, lineno); return filelp; } virtual void error(const string& msg); // Report a error at given location void setPreproc(VPreProcXs* pp) { m_vPreprocp=pp; pushFl(); // The very first construction used pp=NULL, as pp wasn't created yet so make it now } // Record the structure so we can delete it later void pushFl() { m_vPreprocp->m_filelineps.push_back(this); } }; #//********************************************************************** #// Overrides error handling virtual functions to invoke callbacks void VFileLineXs::error(const string& msg) { static string holdmsg; holdmsg = msg; m_vPreprocp->call(NULL, 1,"error",holdmsg.c_str()); } #//********************************************************************** #// VPreProcXs functions VPreProcXs::~VPreProcXs() { for (deque::iterator it=m_filelineps.begin(); it!=m_filelineps.end(); ++it) { delete *it; } } #//********************************************************************** #// Overrides of virtual functions to invoke callbacks void VPreProcXs::comment(string cmt) { static string holdcmt; holdcmt = cmt; call(NULL, 1,"comment",holdcmt.c_str()); } void VPreProcXs::include(string filename) { static string holdfilename; holdfilename = filename; call(NULL, 1,"include",holdfilename.c_str()); } void VPreProcXs::undef(string define) { static string holddefine; holddefine = define; call(NULL, 1,"undef", holddefine.c_str()); } void VPreProcXs::undefineall() { call(NULL, 0,"undefineall"); } void VPreProcXs::define(string define, string value, string params) { static string holddefine; holddefine = define; static string holdvalue; holdvalue = value; static string holdparams; holdparams = params; // 4th argument is cmdline; always undef from here call(NULL, 3,"define", holddefine.c_str(), holdvalue.c_str(), holdparams.c_str()); } bool VPreProcXs::defExists(string define) { return defParams(define)!=""; } string VPreProcXs::defParams(string define) { static string holddefine; holddefine = define; string paramStr; call(¶mStr, 1,"def_params", holddefine.c_str()); return paramStr; } string VPreProcXs::defValue(string define) { static string holddefine; holddefine = define; string valueStr; call(&valueStr, 1,"def_value", holddefine.c_str()); return valueStr; } string VPreProcXs::defSubstitute(string subs) { static string holdsubs; holdsubs = subs; string outStr; call(&outStr, 1, "def_substitute", holdsubs.c_str()); return outStr; } void VPreProcXs::call( string* rtnStrp, /* If non-null, load return value here */ int params, /* Number of parameters. Negative frees the parameters */ const char* method, /* Name of method to call */ ...) /* Arguments to pass to method's @_ */ { // Call $perlself->method (passedparam1, parsedparam2) va_list ap; va_start(ap, method); { dSP; /* Initialize stack pointer */ ENTER; /* everything created after here */ SAVETMPS; /* ...is a temporary variable. */ PUSHMARK(SP); /* remember the stack pointer */ SV* selfsv = newRV_inc(m_self); /* $self-> */ XPUSHs(sv_2mortal(selfsv)); while (params--) { char* text = va_arg(ap, char *); SV* sv; if (text) { sv = sv_2mortal(newSVpv(text, 0)); } else { sv = &PL_sv_undef; } XPUSHs(sv); /* token */ } PUTBACK; /* make local stack pointer global */ if (rtnStrp) { int rtnCount = perl_call_method((char*)method, G_SCALAR); SPAGAIN; /* refresh stack pointer */ if (rtnCount > 0) { SV* sv = POPs; //printf("RTN %ld %d %s\n", SvTYPE(sv),SvTRUE(sv),SvPV_nolen(sv)); #ifdef SvPV_nolen // Perl 5.6 and later *rtnStrp = SvPV_nolen(sv); #else *rtnStrp = SvPV(sv,PL_na); #endif } PUTBACK; } else { perl_call_method((char*)method, G_DISCARD | G_VOID); } FREETMPS; /* free that return value */ LEAVE; /* ...and the XPUSHed "mortal" args.*/ } va_end(ap); } #//********************************************************************** MODULE = Verilog::Preproc PACKAGE = Verilog::Preproc #//********************************************************************** #// self->_new(class, keepcmt, keepwhite, linedir, pedantic, synthesis) static VPreProcXs * VPreProcXs::_new(SELF, keepcmt, keepwhite, linedir, pedantic, synthesis) SV *SELF int keepcmt int keepwhite int linedir int pedantic int synthesis PROTOTYPE: $$$$$$ CODE: { if (CLASS) {} /* Prevent unused warning */ if (!SvROK(SELF)) { warn("${Package}::$func_name() -- SELF is not a hash reference"); } VFileLineXs* filelinep = new VFileLineXs(NULL/*ok,for initial*/); VPreProcXs* preprocp = new VPreProcXs(); filelinep->setPreproc(preprocp); preprocp->m_self = SvRV(SELF); preprocp->keepComments(keepcmt); preprocp->keepWhitespace(keepwhite); preprocp->lineDirectives(linedir); preprocp->pedantic(pedantic); preprocp->synthesis(synthesis); preprocp->configure(filelinep); RETVAL = preprocp; } OUTPUT: RETVAL #//********************************************************************** #// self->_DESTROY() void VPreProcXs::_DESTROY() PROTOTYPE: $ CODE: { delete THIS; } #//********************************************************************** #// self->debug() void VPreProcXs::_debug(level) int level PROTOTYPE: $$ CODE: { THIS->debug(level); } #//********************************************************************** #// self->lineno() int VPreProcXs::lineno() PROTOTYPE: $ CODE: { if (!THIS) XSRETURN_UNDEF; RETVAL = (THIS->fileline()->lineno()); } OUTPUT: RETVAL #//********************************************************************** #// self->filename() SV* VPreProcXs::filename() PROTOTYPE: $ CODE: { if (!THIS) XSRETURN_UNDEF; string ret = THIS->fileline()->filename(); RETVAL = newSVpv(ret.c_str(), ret.length()); } OUTPUT: RETVAL #//********************************************************************** #// self->unreadback() void VPreProcXs::unreadback(text) char* text PROTOTYPE: $$ CODE: { if (!THIS) XSRETURN_UNDEF; THIS->insertUnreadback((string)text); } #//********************************************************************** #// self->getall() SV* VPreProcXs::getall(approx_chunk=0) size_t approx_chunk PROTOTYPE: $;$ CODE: { static string holdline; if (!THIS || THIS->isEof()) XSRETURN_UNDEF; string lastline = THIS->getall(approx_chunk); holdline = lastline; /* Stash it so c_str() doesn't disappear immediately */ if (holdline=="" && THIS->isEof()) XSRETURN_UNDEF; RETVAL = newSVpv(lastline.c_str(), lastline.length()); } OUTPUT: RETVAL #//********************************************************************** #// self->getline() SV* VPreProcXs::getline() PROTOTYPE: $ CODE: { static string holdline; if (!THIS || THIS->isEof()) XSRETURN_UNDEF; string lastline = THIS->getline(); holdline = lastline; /* Stash it so c_str() doesn't disappear immediately */ if (holdline=="" && THIS->isEof()) XSRETURN_UNDEF; RETVAL = newSVpv(lastline.c_str(), lastline.length()); } OUTPUT: RETVAL #//********************************************************************** #// self->eof() int VPreProcXs::eof() PROTOTYPE: $ CODE: { RETVAL = THIS->isEof(); } OUTPUT: RETVAL #//********************************************************************** #// self->_open(filename) int VPreProcXs::_open(filename) const char *filename PROTOTYPE: $$ CODE: { if (!THIS) XSRETURN_UNDEF; THIS->openFile(filename); RETVAL = 1; } OUTPUT: RETVAL Verilog-Perl-3.478/Preproc/VFileLine.cpp0000644000177100017500000000653014035374034017763 0ustar wsnyderwsnyder// -*- C++ -*- //************************************************************************* // // Copyright 2000-2021 by Wilson Snyder. This program is free software; // you can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // //************************************************************************* /// \file /// \brief Verilog::Preproc: Error handling implementation /// /// Authors: Wilson Snyder /// /// Code available from: https://www.veripool.org/verilog-perl /// //************************************************************************* #include #include #include "VFileLine.h" int VFileLine::s_numErrors = 0; ///< Number of errors detected //============================================================================ void VFileLine::init(const string& filename, int lineno) { m_filename = filename; m_lineno = lineno; } const string VFileLine::filebasename() const { string name = filename(); string::size_type slash; if ((slash = name.rfind("/")) != string::npos) { name.erase(0,slash+1); } return name; } void VFileLine::fatal(const string& msg) { error(msg); error("Fatal Error detected"); abort(); } void VFileLine::error(const string& msg) { VFileLine::s_numErrors++; if (msg[msg.length()-1] != '\n') { fprintf(stderr, "%%Error: %s", msg.c_str()); } else { fprintf(stderr, "%%Error: %s\n", msg.c_str()); // Append newline, as user omitted it. } } const char* VFileLine::itoa(int i) { static char buf[100]; sprintf(buf,"%d",i); return buf; } string VFileLine::lineDirectiveStrg(int enterExit) const { char numbuf[20]; sprintf(numbuf, "%d", lineno()); char levelbuf[20]; sprintf(levelbuf, "%d", enterExit); return ((string)"`line "+numbuf+" \""+filename()+"\" "+levelbuf+"\n"); } VFileLine* VFileLine::lineDirective(const char* textp, int& enterExitRef) { // Handle `line directive // Skip `line while (*textp && isspace(*textp)) textp++; while (*textp && !isspace(*textp)) textp++; while (*textp && (isspace(*textp) || *textp=='"')) textp++; // Grab linenumber int lineno = this->lineno(); const char *ln = textp; while (*textp && !isspace(*textp)) textp++; if (isdigit(*ln)) { lineno = atoi(ln); } while (*textp && (isspace(*textp) || *textp=='"')) textp++; // Grab filename string filename = this->filename(); const char* fn = textp; while (*textp && !(isspace(*textp) || *textp=='"')) textp++; if (textp != fn) { string strfn = fn; strfn = strfn.substr(0, textp-fn); filename = strfn; } // Grab level while (*textp && (isspace(*textp) || *textp=='"')) textp++; if (isdigit(*textp)) enterExitRef = atoi(textp); else enterExitRef = 0; return create(filename,lineno); } //====================================================================== // Global scope ostream& operator<<(ostream& os, VFileLine* flp) { if (flp->filename()!="") { os <filename()<<":"<lineno()<<": "<{_cthis} O_CTHIS // SELF->{_cthis} = THIS if( sv_isobject(SELF) && (SvTYPE(SvRV(SELF)) == SVt_PVHV) ) { SV **svp = hv_fetch((HV*)SvRV(SELF), \"_cthis\", 6, 1); sv_setiv(*svp, PTR2IV( $var )); XSRETURN_UNDEF; } else { warn( \"${Package}::$func_name() -- $var is not a Verilog::Preproc object\" ); XSRETURN_UNDEF; } INPUT O_CTHIS $var = NULL; if( sv_isobject($arg) && (SvTYPE(SvRV( $arg )) == SVt_PVHV) ) { SV **svp = hv_fetch((HV*)SvRV(( $arg )), \"_cthis\", 6, 0); $var = NULL; if (svp) { $var = INT2PTR($type,SvIV( *svp )); } } if (!$var || !dynamic_cast($var)) { warn( \"${Package}::$func_name() -- $var is not a Verilog::Preproc object\" ); XSRETURN_UNDEF; } Verilog-Perl-3.478/Preproc/VPreProc.cpp0000644000177100017500000013336214035374034017652 0ustar wsnyderwsnyder// -*- C++ -*- //************************************************************************* // // Copyright 2000-2021 by Wilson Snyder. This program is free software; // you can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // //************************************************************************* /// \file /// \brief Verilog::Preproc: Internal implementation of default preprocessor /// /// Authors: Wilson Snyder /// /// Code available from: https://www.veripool.org/verilog-perl /// //************************************************************************* #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__) # include #else # include #endif #include "VPreProc.h" #include "VPreLex.h" //#undef yyFlexLexer //#define yyFlexLexer xxFlexLexer //#include //************************************************************************* class VPreDefRef { // One for each pending define substitution string m_name; // Define last name being defined string m_params; // Define parameter list for next expansion string m_nextarg; // String being built for next argument int m_parenLevel; // Parenthesis counting inside def args (for PARENT not child) vector m_args; // List of define arguments public: string name() const { return m_name; } string params() const { return m_params; } string nextarg() const { return m_nextarg; } void nextarg(const string& value) { m_nextarg = value; } int parenLevel() const { return m_parenLevel; } void parenLevel(int value) { m_parenLevel = value; } vector& args() { return m_args; } VPreDefRef(const string& name, const string& params) : m_name(name), m_params(params), m_parenLevel(0) {} ~VPreDefRef() {} }; //************************************************************************* /// Data for parsing on/off class VPreIfEntry { // One for each pending ifdef/ifndef bool m_on; // Current parse for this ifdef level is "on" bool m_everOn; // Some if term in elsif tree has been on public: bool on() const { return m_on; } bool everOn() const { return m_everOn; } VPreIfEntry(bool on, bool everOn) : m_on(on), m_everOn(everOn || on) {} // Note everOn includes new state ~VPreIfEntry() {} }; //************************************************************************* /// Data for a preprocessor instantiation. class VPreProcImp : public VPreProcOpaque { public: typedef list StrList; VPreProc* m_preprocp; ///< Object we're holding data for int m_debug; ///< Debugging level VPreLex* m_lexp; ///< Current lexer state (NULL = closed) enum ProcState { ps_TOP, ps_DEFNAME_UNDEF, ps_DEFNAME_DEFINE, ps_DEFNAME_IFDEF, ps_DEFNAME_IFNDEF, ps_DEFNAME_ELSIF, ps_DEFFORM, ps_DEFVALUE, ps_DEFPAREN, ps_DEFARG, ps_INCNAME, ps_ERRORNAME, ps_JOIN, ps_STRIFY }; static const char* procStateName(ProcState s) { static const char* states[] = {"ps_TOP", "ps_DEFNAME_UNDEF", "ps_DEFNAME_DEFINE", "ps_DEFNAME_IFDEF", "ps_DEFNAME_IFNDEF", "ps_DEFNAME_ELSIF", "ps_DEFFORM", "ps_DEFVALUE", "ps_DEFPAREN", "ps_DEFARG", "ps_INCNAME", "ps_ERRORNAME", "ps_JOIN", "ps_STRIFY" }; return states[s]; }; stack m_states; ///< Current state of parser int m_off; ///< If non-zero, ifdef level is turned off, don't dump text string m_lastSym; ///< Last symbol name found. string m_formals; ///< Last formals found // For getRawToken/ `line insertion string m_lineCmt; ///< Line comment(s) to be returned bool m_lineCmtNl; ///< Newline needed before inserting lineCmt int m_lineAdd; ///< Empty lines to return to maintain line count bool m_rawAtBol; ///< Last rawToken left us at beginning of line // For getFinalToken bool m_finAhead; ///< Have read a token ahead int m_finToken; ///< Last token read string m_finBuf; ///< Last yytext read bool m_finAtBol; ///< Last getFinalToken left us at beginning of line VFileLine* m_finFilelinep; ///< Location of last returned token (internal only) // For stringification string m_strify; ///< Text to be stringified // For defines stack m_defRefs; // Pending definine substitution stack m_ifdefStack; ///< Stack of true/false emitting evaluations unsigned m_defDepth; ///< How many `defines deep bool m_defPutJoin; ///< Insert `` after substitution // For `` join stack m_joinStack; ///< Text on lhs of join // For getline() string m_lineChars; ///< Characters left for next line VPreProcImp() { m_debug = 0; m_states.push(ps_TOP); m_off = 0; m_lineChars = ""; m_lastSym = ""; m_lineAdd = 0; m_lineCmtNl = false; m_rawAtBol = true; m_finAhead = false; m_finAtBol = true; m_defDepth = 0; m_defPutJoin = false; m_finToken = 0; m_finFilelinep = NULL; m_lexp = NULL; m_preprocp = NULL; } void configure(VFileLine* filelinep, VPreProc* preprocp) { // configure() separate from constructor to avoid calling abstract functions m_preprocp = preprocp; m_finFilelinep = filelinep->create(1); // Create lexer m_lexp = new VPreLex(this, filelinep); m_lexp->m_keepComments = m_preprocp->keepComments(); m_lexp->m_keepWhitespace = m_preprocp->keepWhitespace(); m_lexp->m_pedantic = m_preprocp->pedantic(); m_lexp->m_synthesis = m_preprocp->synthesis(); m_lexp->debug(debug()>=10 ? debug() : 0); // See also VPreProc::debug() method } ~VPreProcImp() { if (m_lexp) { delete m_lexp; m_lexp = NULL; } } const char* tokenName(int tok); void debugToken(int tok, const char* cmtp); void parseTop(); void parseUndef(); string getparseline(bool stop_at_eol, size_t approx_chunk); bool isEof() const { return m_lexp->curStreamp()->m_eof; } bool readWholefile(const string& filename, StrList& outl); void openFile(string filename, VFileLine* filelinep); void insertUnreadback(const string& text) { m_lineCmt += text; } void insertUnreadbackAtBol(const string& text); void addLineComment(int enter_exit_level); private: void error(string msg) { m_lexp->m_tokFilelinep->error(msg); } void fatal(string msg) { m_lexp->m_tokFilelinep->fatal(msg); } int debug() const { return m_debug; } void endOfOneFile(); string defineSubst(VPreDefRef* refp); string trimWhitespace(const string& strg, bool trailing); void unputString(const string& strg); void unputDefrefString(const string& strg); void parsingOn() { m_off--; if (m_off<0) fatalSrc("Underflow of parsing cmds"); // addLineComment no longer needed; getFinalToken will correct. } void parsingOff() { m_off++; } int getRawToken(); int getStateToken(string& buf); int getFinalToken(string& buf); ProcState state() const { return m_states.top(); } bool stateIsDefname() const { return state()==ps_DEFNAME_UNDEF || state()==ps_DEFNAME_DEFINE || state()==ps_DEFNAME_IFDEF || state()==ps_DEFNAME_IFNDEF || state()==ps_DEFNAME_ELSIF; } void statePush(ProcState state) { m_states.push(state); } void statePop() { m_states.pop(); if (m_states.empty()) { error("InternalError: Pop of parser state with nothing on stack"); m_states.push(ps_TOP); } } void stateChange(ProcState state) { statePop(); statePush(state); } }; //************************************************************************* // Creation VPreProc::VPreProc() { VPreProcImp* idatap = new VPreProcImp(); m_opaquep = idatap; // Below overridden by configure() m_keepComments = true; m_keepWhitespace = true; m_lineDirectives = true; m_pedantic = false; m_synthesis = false; } void VPreProc::configure(VFileLine* filelinep) { VPreProcImp* idatap = static_cast(m_opaquep); idatap->configure(filelinep, this); } VPreProc::~VPreProc() { if (m_opaquep) { delete m_opaquep; m_opaquep = NULL; } } //************************************************************************* // VPreProc Methods. Just call the implementation functions. void VPreProc::comment(string cmt) { } void VPreProc::openFile(string filename, VFileLine* filelinep) { VPreProcImp* idatap = static_cast(m_opaquep); idatap->openFile(filename,filelinep); } string VPreProc::getline() { VPreProcImp* idatap = static_cast(m_opaquep); return idatap->getparseline(true,0); } string VPreProc::getall(size_t approx_chunk) { VPreProcImp* idatap = static_cast(m_opaquep); return idatap->getparseline(false,approx_chunk); } void VPreProc::debug(int level) { VPreProcImp* idatap = static_cast(m_opaquep); idatap->m_debug = level; // To see "accepting rule" debug, Makefile.PL must be changed to enable flex debug // export VERILOGPERL_FLEX_DEBUG=1 idatap->m_lexp->debug(level>=10 ? level : 0); } bool VPreProc::isEof() { VPreProcImp* idatap = static_cast(m_opaquep); return idatap->isEof(); } VFileLine* VPreProc::fileline() { VPreProcImp* idatap = static_cast(m_opaquep); return idatap->m_lexp->m_tokFilelinep; } void VPreProc::insertUnreadback(string text) { VPreProcImp* idatap = static_cast(m_opaquep); return idatap->insertUnreadback(text); } //********************************************************************** // Parser Utilities const char* VPreProcImp::tokenName(int tok) { switch (tok) { case VP_BACKQUOTE : return("BACKQUOTE"); case VP_COMMENT : return("COMMENT"); case VP_DEFARG : return("DEFARG"); case VP_DEFFORM : return("DEFFORM"); case VP_DEFINE : return("DEFINE"); case VP_DEFREF : return("DEFREF"); case VP_DEFREF_JOIN : return("DEFREF_JOIN"); case VP_DEFVALUE : return("DEFVALUE"); case VP_ELSE : return("ELSE"); case VP_ELSIF : return("ELSIF"); case VP_ENDIF : return("ENDIF"); case VP_EOF : return("EOF"); case VP_ERROR : return("ERROR"); case VP_IFDEF : return("IFDEF"); case VP_IFNDEF : return("IFNDEF"); case VP_JOIN : return("JOIN"); case VP_INCLUDE : return("INCLUDE"); case VP_LINE : return("LINE"); case VP_PSL : return("PSL"); case VP_STRIFY : return("STRIFY"); case VP_STRING : return("STRING"); case VP_SYMBOL : return("SYMBOL"); case VP_SYMBOL_JOIN : return("SYMBOL_JOIN"); case VP_TEXT : return("TEXT"); case VP_UNDEF : return("UNDEF"); case VP_UNDEFINEALL : return("UNDEFINEALL"); case VP_WHITE : return("WHITE"); default: return("?"); } } void VPreProcImp::unputString(const string& strg) { // Note: The preliminary call in ::openFile bypasses this function // We used to just m_lexp->unputString(strg.c_str()); // However this can lead to "flex scanner push-back overflow" // so instead we scan from a temporary buffer, then on EOF return. // This is also faster than the old scheme, amazingly. if (m_lexp->m_bufferState!=m_lexp->currentBuffer()) { fatalSrc("bufferStack missing current buffer; will return incorrectly"); // Hard to debug lost text as won't know till much later } m_lexp->scanBytes(strg); } void VPreProcImp::unputDefrefString(const string& strg) { int multiline = 0; for (size_t i=0; icurStreamp()->m_ignNewlines += multiline; // Must be after unput - applies to new stream } string VPreProcImp::trimWhitespace(const string& strg, bool trailing) { // Remove leading whitespace string out = strg; string::size_type leadspace = 0; while (out.length() > leadspace && isspace(out[leadspace])) leadspace++; if (leadspace) out.erase(0,leadspace); // Remove trailing whitespace if (trailing) { string::size_type trailspace = 0; while (out.length() > trailspace && isspace(out[out.length()-1-trailspace])) trailspace++; // Don't remove \{space_or_newline} if (trailspace && out.length() > trailspace && out[out.length()-1-trailspace]=='\\') trailspace--; if (trailspace) out.erase(out.length()-trailspace,trailspace); } return out; } string VPreProcImp::defineSubst(VPreDefRef* refp) { // Substitute out defines in a define reference. // (We also need to call here on non-param defines to handle `") // We could push the define text back into the lexer, but that's slow // and would make recursive definitions and parameter handling nasty. // // Note we parse the definition parameters and value here. If a // parametrized define is used many, many times, we could cache the // parsed result. if (debug()>=5) { cout<<"defineSubstIn `"<name()<<" "<params()<args().size(); i++) { cout<<"defineArg["<args()[i]<<"'"<defValue(refp->name()); if (debug()>=5) cout<<"defineValue '"< argValueByName; { // Parse argument list into map unsigned numArgs=0; string argName; int paren = 1; // (), {} and [] can use same counter, as must be matched pair per spec string token; bool quote = false; bool haveDefault = false; // Note there's a leading ( and trailing ), so parens==1 is the base parsing level string params = refp->params(); // Must keep str in scope to get pointer const char* cp=params.c_str(); if (*cp == '(') cp++; for (; *cp; cp++) { //if (debug()>=5) cout <<" Parse Paren="<args().size() > numArgs) { // A call `def( a ) must be equivelent to `def(a ), so trimWhitespace // At one point we didn't trim trailing whitespace, but this confuses `" string arg = trimWhitespace(refp->args()[numArgs], true); if (arg != "") valueDef = arg; } else if (!haveDefault) { error("Define missing argument '"+argName+"' for: "+refp->name()+"\n"); return " `"+refp->name()+" "; } numArgs++; } argValueByName[argName] = valueDef; // Prepare for next argName = ""; token = ""; haveDefault = false; continue; } else if (*cp=='=') { haveDefault = true; argName = token; token = ""; continue; } } if (cp[0]=='\\' && cp[1]) { token += cp[0]; // \{any} Put out literal next character token += cp[1]; cp++; continue; } if (!quote) { if (*cp=='(' || *cp=='{' || *cp=='[') paren++; else if (*cp==')' || *cp=='}' || *cp==']') paren--; } if (*cp=='"') quote=!quote; if (*cp) token += *cp; } if (refp->args().size() > numArgs // `define X() is ok to call with nothing && !(refp->args().size()==1 && numArgs==0 && trimWhitespace(refp->args()[0],false)=="")) { error("Define passed too many arguments: "+refp->name()+"\n"); return " `"+refp->name()+" "; } } string out = ""; { // Parse substitution define using arguments string argName; bool quote = false; bool backslashesc = false; // In \.....{space} block // Note we go through the loop once more at the NULL end-of-string for (const char* cp=value.c_str(); (*cp) || argName!=""; cp=(*cp?cp+1:cp)) { //cout << "CH "<<*cp<<" an "<::iterator iter = argValueByName.find(argName); if (iter != argValueByName.end()) { // Substitute string subst = iter->second; if (subst == "") { // Normally `` is removed later, but with no token after, we're otherwise // stuck, so remove proceeding `` if (out.size()>=2 && out.substr(out.size()-2) == "``") { out = out.substr(0, out.size()-2); } } else { out += subst; } } else { out += argName; } argName = ""; } if (!quote) { // Check for `` only after we've detected end-of-argname if (cp[0]=='`' && cp[1]=='`') { if (backslashesc) { // Don't put out the ``, we're forming an escape which will not expand further later } else { out += "``"; // `` must get removed later, as `FOO```BAR must pre-expand FOO and BAR // See also removal in empty substitutes above } cp++; continue; } else if (cp[0]=='`' && cp[1]=='"') { out += "`\""; // `" means to put out a " without enabling quote mode (sort of) // however we must expand any macro calls inside it first. // So keep it `", so we don't enter quote mode. cp++; continue; } else if (cp[0]=='`' && cp[1]=='\\' && cp[2]=='`' && cp[3]=='"') { out += "`\\`\""; // `\`" means to put out a backslash quote // Leave it literal until we parse the VP_STRIFY string cp+=3; continue; } else if (cp[0]=='`' && cp[1]=='\\') { out += '\\'; // `\ means to put out a backslash cp++; continue; } else if (cp[0]=='\\' && cp[1]=='\n') { // We kept the \\n when we lexed because we don't want whitespace // trimming to mis-drop the final \\n // At replacement time we need the standard newline. out += "\n"; // \\n newline cp++; continue; } } if (cp[0]=='\\' && cp[1]=='\"') { out += cp[0]; // \{any} Put out literal next character out += cp[1]; cp++; continue; } else if (cp[0]=='\\') { // Normally \{any} would put out literal next character // Instead we allow "`define A(nm) \nm" to expand, per proposed mantis1537 out += cp[0]; continue; } if (*cp=='"') quote=!quote; if (*cp) out += *cp; } } if (debug()>=5) cout<<"defineSubstOut '"<3 && 0==filename.compare(filename.length()-3, 3, ".gz")) { string cmd = "gunzip -c "+filename; if ((fp = popen(cmd.c_str(), "r")) == NULL) { return false; } fd = fileno(fp); } else { fd = open(filename.c_str(), O_RDONLY); if (fd<0) return false; } while (!eof) { ssize_t todo = INFILTER_IPC_BUFSIZ; errno = 0; ssize_t got = read(fd, buf, todo); if (got>0) { outl.push_back(string(buf, got)); } else if (errno == EINTR || errno == EAGAIN #ifdef EWOULDBLOCK || errno == EWOULDBLOCK #endif ) { } else { eof = true; break; } } if (fp) { pclose(fp); fp=NULL; } else close(fd); return true; } void VPreProcImp::openFile(string filename, VFileLine* filelinep) { // Open a new file, possibly overriding the current one which is active. // Read a list with the whole file. StrList wholefile; bool ok = readWholefile(filename, wholefile/*ref*/); if (!ok) { error("File not found: "+filename+"\n"); return; } if (!m_preprocp->isEof()) { // IE not the first file. // We allow the same include file twice, because occasionally it pops // up, with guards preventing a real recursion. if (m_lexp->m_streampStack.size()>VPreProc::INCLUDE_DEPTH_MAX) { error("Recursive inclusion of file: "+filename); return; } // There's already a file active. Push it to work on the new one. addLineComment(0); } // Create new stream structure m_lexp->scanNewFile(m_preprocp->fileline()->create(filename, 1)); addLineComment(1); // Enter // Filter all DOS CR's en-mass. This avoids bugs with lexing CRs in the wrong places. // This will also strip them from strings, but strings aren't supposed to be multi-line without a "\" for (StrList::iterator it=wholefile.begin(); it!=wholefile.end(); ++it) { // We don't end-loop at \0 as we allow and strip mid-string '\0's (for now). bool strip = false; const char* sp = it->data(); const char* ep = sp + it->length(); // Only process if needed, as saves extra string allocations for (const char* cp=sp; cplength()); for (const char* cp=sp; cpscanBytesBack(*it); // Reclaim memory; the push saved the string contents for us *it = ""; } } void VPreProcImp::insertUnreadbackAtBol(const string& text) { // Insert insuring we're at the beginning of line, for `line // We don't always add a leading newline, as it may result in extra unreadback(newlines). if (m_lineCmt == "") { m_lineCmtNl = true; } else if (m_lineCmt[m_lineCmt.length()-1]!='\n') { insertUnreadback("\n"); } insertUnreadback(text); } void VPreProcImp::addLineComment(int enter_exit_level) { if (m_preprocp->lineDirectives()) { insertUnreadbackAtBol(m_lexp->curFilelinep()->lineDirectiveStrg(enter_exit_level)); } } int VPreProcImp::getRawToken() { // Get a token from the file, whatever it may be. while (1) { next_tok: if (m_lineAdd) { m_lineAdd--; m_rawAtBol = true; yyourtext("\n",1); if (debug()>=5) debugToken(VP_WHITE, "LNA"); return (VP_WHITE); } if (m_lineCmt!="") { // We have some `line directive or other processed data to return to the user. static string rtncmt; // Keep the c string till next call rtncmt = m_lineCmt; if (m_lineCmtNl) { if (!m_rawAtBol) rtncmt = "\n"+rtncmt; m_lineCmtNl = false; } yyourtext(rtncmt.c_str(), rtncmt.length()); m_lineCmt = ""; if (yyourleng()) m_rawAtBol = (yyourtext()[yyourleng()-1]=='\n'); if (state()==ps_DEFVALUE) { VPreLex::s_currentLexp->appendDefValue(yyourtext(),yyourleng()); goto next_tok; } else { if (debug()>=5) debugToken(VP_TEXT, "LCM"); return (VP_TEXT); } } if (isEof()) return (VP_EOF); // Snarf next token from the file int tok = m_lexp->lex(); if (debug()>=5) debugToken(tok, "RAW"); // A EOF on an include, so we can print `line and detect mis-matched "s if (tok==VP_EOF) { goto next_tok; // find the EOF, after adding needed lines } if (yyourleng()) m_rawAtBol = (yyourtext()[yyourleng()-1]=='\n'); return tok; } } void VPreProcImp::debugToken(int tok, const char* cmtp) { if (debug()>=5) { string buf = string(yyourtext(), yyourleng()); string::size_type pos; while ((pos=buf.find("\n")) != string::npos) { buf.replace(pos, 1, "\\n"); } while ((pos=buf.find("\r")) != string::npos) { buf.replace(pos, 1, "\\r"); } fprintf(stderr, "%d: %s %s %s(%d) dr%d: <%d>%-10s: %s\n", m_lexp->m_tokFilelinep->lineno(), cmtp, m_off?"of":"on", procStateName(state()), (int)m_states.size(), (int)m_defRefs.size(), m_lexp->currentStartState(), tokenName(tok), buf.c_str()); } } // Sorry, we're not using bison/yacc. It doesn't handle returning white space // in the middle of parsing other tokens. int VPreProcImp::getStateToken(string& buf) { // Return the next state-determined token while (1) { next_tok: if (isEof()) { buf = string(yyourtext(), yyourleng()); return VP_EOF; } int tok = getRawToken(); // Most states emit white space and comments between tokens. (Unless collecting a string) if (tok==VP_WHITE && state() !=ps_STRIFY) { buf = string(yyourtext(), yyourleng()); return (tok); } if (tok==VP_BACKQUOTE && state() !=ps_STRIFY) { tok = VP_TEXT; } if (tok==VP_COMMENT) { if (!m_off) { if (m_lexp->m_keepComments == KEEPCMT_SUB || m_lexp->m_keepComments == KEEPCMT_EXP) { string rtn; rtn.assign(yyourtext(),yyourleng()); m_preprocp->comment(rtn); // Need to insure "foo/**/bar" becomes two tokens insertUnreadback(" "); } else if (m_lexp->m_keepComments) { buf = string(yyourtext(), yyourleng()); return (tok); } else { // Need to insure "foo/**/bar" becomes two tokens insertUnreadback(" "); } } // We're off or processed the comment specially. If there are newlines // in it, we also return the newlines as TEXT so that the linenumber // count is maintained for downstream tools for (size_t len=0; len<(size_t)yyourleng(); len++) { if (yyourtext()[len]=='\n') m_lineAdd++; } goto next_tok; } if (tok==VP_LINE) { addLineComment(m_lexp->m_enterExit); goto next_tok; } if (tok==VP_DEFREF_JOIN) { // Here's something fun and unspecified as yet: // The existance of non-existance of a base define changes `` expansion // `define QA_b zzz // `define Q1 `QA``_b // 1Q1 -> zzz // `define QA a // `Q1 -> a_b // Note parenthesis make this unambiguous // `define Q1 `QA()``_b // -> a_b // This may be a side effect of how `UNDEFINED remains as `UNDEFINED, // but it screws up our method here. So hardcode it. string name(yyourtext()+1,yyourleng()-1); if (m_preprocp->defExists(name)) { // JOIN(DEFREF) // Put back the `` and process the defref if (debug()>=5) cout<<"```: define "<=5) cout<<"TOKEN now DEFREF\n"; tok = VP_DEFREF; } else { // DEFREF(JOIN) if (debug()>=5) cout<<"```: define "< string doesn't include the ``, so can just grab next and continue string out(yyourtext(),yyourleng()); if (debug()>=5) cout<<"`` LHS:"<defExists(m_lastSym); if (debug()>=5) cout<<"Ifdef "<defExists(m_lastSym); if (debug()>=5) cout<<"Elsif "<=5) cout<<"Undef "<undef(m_lastSym); } statePop(); goto next_tok; } else if (state()==ps_DEFNAME_DEFINE) { // m_lastSym already set. stateChange(ps_DEFFORM); m_lexp->pushStateDefForm(); goto next_tok; } else fatalSrc("Bad case\n"); goto next_tok; } else if (tok==VP_TEXT) { // IE, something like comment between define and symbol if (!m_off) { buf = string(yyourtext(), yyourleng()); return tok; } else goto next_tok; } else if (tok==VP_DEFREF) { // IE, `ifdef `MACRO(x): Substitue and come back here when state pops. break; } else { error((string)"Expecting define name. Found: "+tokenName(tok)+"\n"); goto next_tok; } } case ps_DEFFORM: { if (tok==VP_DEFFORM) { m_formals = m_lexp->m_defValue; if (debug()>=5) cout<<"DefFormals='"<pushStateDefValue(); goto next_tok; } else if (tok==VP_TEXT) { // IE, something like comment in formals if (!m_off) { buf = string(yyourtext(), yyourleng()); return tok; } else goto next_tok; } else { error((string)"Expecting define formal arguments. Found: "+tokenName(tok)+"\n"); goto next_tok; } } case ps_DEFVALUE: { static string newlines; newlines = "\n"; // Always start with trailing return if (tok == VP_DEFVALUE) { if (debug()>=5) cout<<"DefValue='"<m_defValue) <<"' formals='"<m_defValue; // Remove returns // Not removing returns in values has two problems, // 1. we need to correct line numbers with `line after each substitution // 2. Substituting in " .... " with embedded returns requires \ escape. // This is very difficult in the presence of `", so we keep the \ before the newline. for (size_t i=0; i=5) cout<<"Define "<define(m_lastSym, value, formals); } } else { string msg = string("Bad define text, unexpected ")+tokenName(tok)+"\n"; fatalSrc(msg); } statePop(); // DEFVALUE is terminated by a return, but lex can't return both tokens. // Thus, we emit a return here. buf = newlines; return(VP_WHITE); } case ps_DEFPAREN: { if (tok==VP_TEXT && yyourleng()==1 && yyourtext()[0]=='(') { stateChange(ps_DEFARG); goto next_tok; } else { if (m_defRefs.empty()) fatalSrc("Shouldn't be in DEFPAREN w/o active defref"); VPreDefRef* refp = &(m_defRefs.top()); error((string)"Expecting ( to begin argument list for define reference `"+refp->name()+"\n"); statePop(); goto next_tok; } } case ps_DEFARG: { if (m_defRefs.empty()) fatalSrc("Shouldn't be in DEFARG w/o active defref"); VPreDefRef* refp = &(m_defRefs.top()); refp->nextarg(refp->nextarg()+m_lexp->m_defValue); m_lexp->m_defValue=""; if (debug()>=5) cout<<"defarg++ "<nextarg()<args().push_back(refp->nextarg()); stateChange(ps_DEFARG); m_lexp->pushStateDefArg(1); refp->nextarg(""); goto next_tok; } else if (tok==VP_DEFARG && yyourleng()==1 && yyourtext()[0]==')') { // Substitute in and prepare for next action // Similar code in non-parenthesized define (Search for END_OF_DEFARG) refp->args().push_back(refp->nextarg()); string out; if (!m_off) { out = defineSubst(refp); out = m_preprocp->defSubstitute(out); } m_defRefs.pop(); refp=NULL; if (m_defRefs.empty()) { statePop(); if (state() == ps_JOIN) { // Handle {left}```FOO(ARG) where `FOO(ARG) might be empty if (m_joinStack.empty()) fatalSrc("`` join stack empty, but in a ``"); string lhs = m_joinStack.top(); m_joinStack.pop(); out = lhs+out; if (debug()>=5) cout<<"``-end-defarg Out:"<m_parenLevel = 0; } else { // Finished a defref inside a upper defref // Can't subst now, or // `define a(ign) x,y // foo(`a(ign),`b) would break because a contains comma refp = &(m_defRefs.top()); // We popped, so new top refp->nextarg(refp->nextarg()+m_lexp->m_defValue+out); m_lexp->m_defValue=""; m_lexp->m_parenLevel = refp->parenLevel(); statePop(); // Will go to ps_DEFARG, as we're under another define } goto next_tok; } else if (tok==VP_DEFREF) { // Expand it, then state will come back here // Value of building argument is data before the lower defref // we'll append it when we push the argument. break; } else if (tok==VP_SYMBOL || tok==VP_STRING || tok==VP_TEXT || tok==VP_WHITE || tok==VP_PSL) { string rtn; rtn.assign(yyourtext(),yyourleng()); refp->nextarg(refp->nextarg()+rtn); goto next_tok; } else if (tok==VP_STRIFY) { // We must expand stringinfication, when done will return to this state statePush(ps_STRIFY); goto next_tok; } else { error((string)"Expecting ) or , to end argument list for define reference. Found: "+tokenName(tok)); statePop(); goto next_tok; } } case ps_INCNAME: { if (tok==VP_STRING) { statePop(); m_lastSym.assign(yyourtext(),yyourleng()); if (debug()>=5) cout<<"Include "<include(m_lastSym); goto next_tok; } else if (tok==VP_TEXT && yyourleng()==1 && yyourtext()[0]=='<') { // include stateChange(ps_INCNAME); // Still m_lexp->pushStateIncFilename(); goto next_tok; } else if (tok==VP_DEFREF || tok==VP_STRIFY) { // Expand it, then state will come back here break; } else { statePop(); error((string)"Expecting include filename. Found: "+tokenName(tok)+"\n"); goto next_tok; } } case ps_ERRORNAME: { if (tok==VP_STRING) { if (!m_off) { m_lastSym.assign(yyourtext(),yyourleng()); error(m_lastSym); } statePop(); goto next_tok; } else { error((string)"Expecting `error string. Found: "+tokenName(tok)+"\n"); statePop(); goto next_tok; } } case ps_JOIN: { if (tok==VP_SYMBOL || tok==VP_TEXT) { if (m_joinStack.empty()) fatalSrc("`` join stack empty, but in a ``"); string lhs = m_joinStack.top(); m_joinStack.pop(); if (debug()>=5) cout<<"`` LHS:"<=5) cout<<"`` RHS:"<=5) cout<<"`` Out:"<=5) cout<<"Else "<<(enable?" ON":" OFF")<=5) cout<<"Endif "<=5) cout<<"DefRef "< VPreProc::DEFINE_RECURSION_LEVEL_MAX) { error("Recursive `define substitution: `"+name); goto next_tok; } // Substitute string params = m_preprocp->defParams(name); if (params=="") { // Not found, return original string as-is m_defDepth = 0; if (debug()>=5) cout<<"Defref `"< not_defined"<defSubstitute(out); if (m_defRefs.empty()) { // Just output the substitution if (state() == ps_JOIN) { // Handle {left}```FOO where `FOO might be empty if (m_joinStack.empty()) fatalSrc("`` join stack empty, but in a ``"); string lhs = m_joinStack.top(); m_joinStack.pop(); out = lhs+out; if (debug()>=5) cout<<"``-end-defref Out:"<nextarg(refp->nextarg()+m_lexp->m_defValue+out); m_lexp->m_defValue=""; } goto next_tok; } else { // Found, with parameters if (debug()>=5) cout<<"Defref `"< parametrized"<m_parenLevel); m_defRefs.push(VPreDefRef(name, params)); statePush(ps_DEFPAREN); m_lexp->pushStateDefArg(0); goto next_tok; } fatalSrc("Bad case\n"); } case VP_ERROR: { statePush(ps_ERRORNAME); goto next_tok; } case VP_EOF: if (!m_ifdefStack.empty()) { error("`ifdef not terminated at EOF\n"); } buf = string(yyourtext(), yyourleng()); return tok; case VP_UNDEFINEALL: if (!m_off) { if (debug()>=5) cout<<"Undefineall "<undefineall(); } goto next_tok; case VP_STRIFY: // We must expand macros in the body of the stringification // Then, when done, form a final string to return // (it could be used as a include filename, for example, so need the string token) statePush(ps_STRIFY); goto next_tok; case VP_SYMBOL: case VP_STRING: case VP_PSL: case VP_TEXT: { m_defDepth = 0; if (!m_off) { buf = string(yyourtext(), yyourleng()); return tok; } else goto next_tok; } case VP_WHITE: // Handled at top of loop case VP_COMMENT: // Handled at top of loop case VP_DEFFORM: // Handled by state=ps_DEFFORM; case VP_DEFVALUE: // Handled by state=ps_DEFVALUE; default: fatalSrc((string)"Internal error: Unexpected token "+tokenName(tok)+"\n"); break; } buf = string(yyourtext(), yyourleng()); return tok; } } int VPreProcImp::getFinalToken(string& buf) { // Return the next user-visible token in the input stream. // Includes and such are handled here, and are never seen by the caller. if (!m_finAhead) { m_finAhead = true; m_finToken = getStateToken(m_finBuf); } int tok = m_finToken; buf = m_finBuf; if (0 && debug()>=5) { string bufcln = VPreLex::cleanDbgStrg(buf); fprintf(stderr,"%d: FIN: %-10s: %s\n", m_lexp->m_tokFilelinep->lineno(), tokenName(tok), bufcln.c_str()); } // Track `line const char* bufp = buf.c_str(); while (*bufp == '\n') bufp++; if ((tok == VP_TEXT || tok == VP_LINE) && 0==strncmp(bufp,"`line ",6)) { int enter; m_finFilelinep = m_finFilelinep->lineDirective(bufp, enter/*ref*/); } else { if (m_finAtBol && !(tok==VP_TEXT && buf=="\n") && m_preprocp->lineDirectives()) { if (int outBehind = m_lexp->m_tokFilelinep->lineno() - m_finFilelinep->lineno()) { if (debug()>=5) fprintf(stderr,"%d: FIN: readjust, fin at %d request at %d\n", m_lexp->m_tokFilelinep->lineno(), m_finFilelinep->lineno(), m_lexp->m_tokFilelinep->lineno()); m_finFilelinep = m_finFilelinep->create(m_lexp->m_tokFilelinep->filename(),m_lexp->m_tokFilelinep->lineno()); if (outBehind > 0 && outBehind <= (int)VPreProc::NEWLINES_VS_TICKLINE) { // Output stream is behind, send newlines to get back in sync // (Most likely because we're completing a disabled `endif) if (m_preprocp->keepWhitespace()) { buf = string(outBehind,'\n'); return VP_TEXT; } } else { // Need to backup, use `line buf = m_finFilelinep->lineDirectiveStrg(0); return VP_LINE; } } } // Track newlines in prep for next token for (string::iterator cp=buf.begin(); cp!=buf.end(); ++cp) { if (*cp == '\n') { m_finAtBol = true; m_finFilelinep->linenoIncInPlace(); // Increment in place to avoid new/delete calls. It's private data. } else { m_finAtBol = false; } } } m_finAhead = false; // Consumed the token return tok; } string VPreProcImp::getparseline(bool stop_at_eol, size_t approx_chunk) { // Get a single line from the parse stream. Buffer unreturned text until the newline. if (isEof()) return ""; while (1) { const char* rtnp = NULL; bool gotEof = false; while ((stop_at_eol ? (NULL==(rtnp=strchr(m_lineChars.c_str(),'\n'))) : (approx_chunk==0 || (m_lineChars.length() < approx_chunk))) && !gotEof) { string buf; int tok = getFinalToken(buf/*ref*/); if (debug()>=5) { string bufcln = VPreLex::cleanDbgStrg(buf); fprintf(stderr,"%d: GETFETC: %-10s: %s\n", m_lexp->m_tokFilelinep->lineno(), tokenName(tok), bufcln.c_str()); } if (tok==VP_EOF) { // Add a final newline, if the user forgot the final \n. if (m_lineChars != "" && m_lineChars[m_lineChars.length()-1] != '\n') { m_lineChars.append("\n"); } gotEof = true; } else if (tok==VP_PSL) { m_lineChars.append(" psl "); } else { m_lineChars.append(buf); } } // Make new string with data up to the newline. size_t len = stop_at_eol ? (rtnp-m_lineChars.c_str()+1) : m_lineChars.length(); string theLine(m_lineChars, 0, len); m_lineChars = m_lineChars.erase(0,len); // Remove returned characters if (!m_preprocp->keepWhitespace() && !gotEof) { const char* cp=theLine.c_str(); for (; *cp && (isspace(*cp) || *cp=='\n'); cp++) {} if (!*cp) continue; } if (debug()>=4) { string lncln = VPreLex::cleanDbgStrg(theLine); fprintf(stderr,"%d: GETLINE: %s\n", m_lexp->m_tokFilelinep->lineno(), lncln.c_str()); } return theLine; } } Verilog-Perl-3.478/Preproc/VPreLex.h0000644000177100017500000001740714035374034017145 0ustar wsnyderwsnyder// -*- C++ -*- //************************************************************************* // // Copyright 2000-2021 by Wilson Snyder. This program is free software; // you can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // //************************************************************************* /// \file /// \brief Verilog::Preproc: Internal header for lex interfacing /// /// Authors: Wilson Snyder /// /// Code available from: https://www.veripool.org/verilog-perl /// /// This header provides the interface between the lex proper VPreLex.l/.cpp /// and the class implementation file VPreProc.cpp /// It is not intended for user applications. /// //************************************************************************* #ifndef _VPREPROCLEX_H_ // Guard #define _VPREPROCLEX_H_ 1 #include #include #include "VFileLine.h" class VPreLex; class VPreProcImp; //====================================================================== // Token codes // If changing, see VPreProc.cpp's VPreProcImp::tokenName() #define VP_EOF 0 #define VP_INCLUDE 256 #define VP_IFDEF 257 #define VP_IFNDEF 258 #define VP_ENDIF 259 #define VP_UNDEF 260 #define VP_DEFINE 261 #define VP_ELSE 262 #define VP_ELSIF 263 #define VP_LINE 264 #define VP_UNDEFINEALL 265 #define VP_SYMBOL 300 #define VP_STRING 301 #define VP_DEFVALUE 302 #define VP_COMMENT 303 #define VP_TEXT 304 #define VP_WHITE 305 #define VP_DEFREF 306 #define VP_DEFARG 307 #define VP_ERROR 308 #define VP_DEFFORM 309 #define VP_STRIFY 310 #define VP_BACKQUOTE 311 #define VP_SYMBOL_JOIN 312 #define VP_DEFREF_JOIN 313 #define VP_JOIN 314 #define VP_PSL 350 //====================================================================== // Externs created by flex // We add a prefix so that other lexers/flexers in the same program won't collide. #ifndef yy_create_buffer # define yy_create_buffer VPreLex_create_buffer # define yy_delete_buffer VPreLex_delete_buffer # define yy_scan_buffer VPreLex_scan_buffer # define yy_scan_string VPreLex_scan_string # define yy_scan_bytes VPreLex_scan_bytes # define yy_flex_debug VPreLex_flex_debug # define yy_init_buffer VPreLex_init_buffer # define yy_flush_buffer VPreLex_flush_buffer # define yy_load_buffer_state VPreLex_load_buffer_state # define yy_switch_to_buffer VPreLex_switch_to_buffer # define yyin VPreLexin # define yyleng VPreLexleng # define yylex VPreLexlex # define yyout VPreLexout # define yyrestart VPreLexrestart # define yytext VPreLextext #endif #ifndef yyourleng # define yyourleng VPreLexourleng # define yyourtext VPreLexourtext #endif #ifndef YY_BUFFER_STATE struct yy_buffer_state; typedef struct yy_buffer_state *YY_BUFFER_STATE; # define YY_BUF_SIZE 16384 #endif extern int yylex(); extern void yyrestart(FILE*); // Accessors, because flex keeps changing the type of yyleng extern char* yyourtext(); extern size_t yyourleng(); extern void yyourtext(const char* textp, size_t size); // Must call with static YY_BUFFER_STATE yy_create_buffer(FILE *file, int size); void yy_switch_to_buffer(YY_BUFFER_STATE new_buffer); void yy_delete_buffer(YY_BUFFER_STATE b); //====================================================================== #define KEEPCMT_SUB 2 #define KEEPCMT_EXP 3 //====================================================================== // Entry for each file processed; a stack of entries included class VPreStream { public: VFileLine* m_curFilelinep; // Current processing point (see also m_tokFilelinep) VPreLex* m_lexp; // Lexer, for resource tracking deque m_buffers; // Buffer of characters to process int m_ignNewlines; // Ignore multiline newlines bool m_eof; // "EOF" buffer bool m_file; // Buffer is start of new file int m_termState; // Termination fsm VPreStream(VFileLine* fl, VPreLex* lexp) : m_curFilelinep(fl), m_lexp(lexp), m_ignNewlines(0), m_eof(false), m_file(false), m_termState(0) { lexStreamDepthAdd(1); } ~VPreStream() { lexStreamDepthAdd(-1); } private: void lexStreamDepthAdd(int delta); }; //====================================================================== // Class entry for each per-lexer state class VPreLex { public: // Used only by VPreLex.cpp and VPreProc.cpp VPreProcImp* m_preimpp; // Preprocessor lexor belongs to stack m_streampStack; // Stack of processing files int m_streamDepth; // Depth of stream processing YY_BUFFER_STATE m_bufferState; // Flex state VFileLine* m_tokFilelinep; // Starting position of current token // State to lexer static VPreLex* s_currentLexp; ///< Current lexing point int m_keepComments; ///< Emit comments in output text int m_keepWhitespace; ///< Emit all whitespace in output text bool m_pedantic; ///< Obey standard; don't Substitute `error bool m_synthesis; ///< Remove translate_offs // State from lexer int m_formalLevel; ///< Parenthesis counting inside def formals int m_parenLevel; ///< Parenthesis counting inside def args bool m_defCmtSlash; ///< /*...*/ comment in define had \ ending bool m_defQuote; ///< Definition value inside quote string m_defValue; ///< Definition value being built. int m_enterExit; ///< For VL_LINE, the enter/exit level // CONSTRUCTORS VPreLex(VPreProcImp* preimpp, VFileLine* filelinep) { m_preimpp = preimpp; m_streamDepth = 0; m_keepComments = 0; m_keepWhitespace = 1; m_pedantic = false; m_synthesis = false; m_formalLevel = 0; m_parenLevel = 0; m_defQuote = false; m_defCmtSlash = false; m_tokFilelinep = filelinep; m_enterExit = 0; initFirstBuffer(filelinep); } ~VPreLex() { while (!m_streampStack.empty()) { delete m_streampStack.top(); m_streampStack.pop(); } yy_delete_buffer(m_bufferState); m_bufferState=NULL; } /// Called by VPreLex.l from lexer VPreStream* curStreamp() { return m_streampStack.top(); } // Can't be empty, "EOF" is on top VFileLine* curFilelinep() { return curStreamp()->m_curFilelinep; } void curFilelinep(VFileLine* fl) { curStreamp()->m_curFilelinep = fl; } void appendDefValue(const char* textp, size_t len) { m_defValue.append(textp,len); } void lineDirective(const char* textp) { curFilelinep(curFilelinep()->lineDirective(textp, m_enterExit/*ref*/)); } void linenoInc() { if (curStreamp()->m_ignNewlines) curStreamp()->m_ignNewlines--; else curFilelinep(curFilelinep()->create(curFilelinep()->lineno()+1)); } /// Called by VPreProc.cpp to inform lexer void pushStateDefArg(int level); void pushStateDefForm(); void pushStateDefValue(); void pushStateIncFilename(); void scanNewFile(VFileLine* filelinep); void scanBytes(const string& str); void scanBytesBack(const string& str); size_t inputToLex(char* buf, size_t max_size); /// Called by VPreProc.cpp to get data from lexer YY_BUFFER_STATE currentBuffer(); int lex(); int currentStartState(); void dumpSummary(); void dumpStack(); void unused(); // Called by VPreStream void streamDepthAdd(int delta) { m_streamDepth += delta; } int streamDepth() const { return m_streamDepth; } /// Utility static int debug(); static void debug(int level); static string cleanDbgStrg(const string& in); private: string currentUnreadChars(); string endOfStream(bool& againr); void initFirstBuffer(VFileLine* filelinep); void scanSwitchStream(VPreStream* streamp); }; inline void VPreStream::lexStreamDepthAdd(int delta) { m_lexp->streamDepthAdd(delta); } #endif // Guard Verilog-Perl-3.478/Preproc/flexfix0000755000177100017500000000342714035374034017037 0ustar wsnyderwsnyder#!/usr/bin/perl -w ###################################################################### # # Copyright 2002-2021 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # ###################################################################### # DESCRIPTION: Edits flex output to get around various broken flex issues. my $Opt_Prefix = $ARGV[0] or die "%Error: No prefix specified,"; foreach my $line () { # Fix flex 2.6.0 warning $line =~ s/ number_to_move == YY_MORE_ADJ / (int)number_to_move == (int)YY_MORE_ADJ /; # Fix flex 2.5.4 namespace omission $line =~ s/^class istream;/\#include \nusing namespace std;\n/; # Fix flex 2.5.31 redefinition $line =~ s!(\#define\s+yyFlexLexer\s+yyFlexLexer)!//flexfix: $1!g; # Fix flex 2.5.1 yytext_ptr undef $line =~ s!(\#undef\s+yytext_ptr)!//flexfix: $1!g; # Fix flex 2.5.4 and GCC 4.1.0 warn_unused_result $line =~ s!\(void\) *fwrite\((.*)\)!if (fwrite($1)) {}!g; # Fix flex 2.5.33 and GCC 4.1.2 "warning: comparison between signed and unsigned integer expressions" in YY_INPUT $line =~ s!for \( n = 0; n < max_size && !for ( n = 0; ((size_t)n < (size_t)max_size) && !g; # Fix flex 2.5.4 and GCC 4.0.2 under FLEX_DEBUG $line =~ s!--accepting rule at line %d !--accepting rule at line %ld !g; # Fix compiler warning filenames $line =~ s!(#line \d+ ".*)_pretmp!$1!; print "$line"; } Verilog-Perl-3.478/Preproc/VPreProc.h0000644000177100017500000001145714035374034017317 0ustar wsnyderwsnyder// -*- C++ -*- //************************************************************************* // // Copyright 2000-2021 by Wilson Snyder. This program is free software; // you can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // //************************************************************************* /// \file /// \brief Verilog::Preproc: Preprocess verilog code /// /// Authors: Wilson Snyder /// /// Code available from: https://www.veripool.org/verilog-perl /// //************************************************************************* #ifndef _VPREPROC_H_ #define _VPREPROC_H_ 1 #include #include #include using namespace std; #include "VFileLine.h" /// Generic opaque pointer to VPreProcImp implementation class. struct VPreProcOpaque { virtual ~VPreProcOpaque() {} }; class VDefine; //********************************************************************** // VPreProc /// Verilog Preprocessor. //// /// This defines a preprocessor. Functions are virtual so users can override them. /// After creating, call openFile(), then getline() in a loop. The class will to the rest... class VPreProc { public: VPreProc(); void configure(VFileLine* filelinep); virtual ~VPreProc(); // STATE private: int m_keepComments; int m_keepWhitespace; bool m_lineDirectives; bool m_pedantic; bool m_synthesis; public: // CONSTANTS enum MiscConsts { DEFINE_RECURSION_LEVEL_MAX = 1000, // How many `def substitutions before an error INCLUDE_DEPTH_MAX = 500, // How many `includes deep before an error STREAM_DEPTH_LEVEL_MAX = 2000, // How many streams deep (sometimes `def deep) before an error // // Set more than DEFINE_RECURSION_LEVEL_MAX or INCLUDE_DEPTH_MAX NEWLINES_VS_TICKLINE = 20 // Use `line in place of this many newlines }; // ACCESSORS /// Insert given file into this point in input stream void openFile(string filename, VFileLine* filelinep=NULL); void debug(int level); ///< Set debugging level string getall(size_t approx_chunk); ///< Return all lines, or at least approx_chunk bytes. (Null if done.) string getline(); ///< Return next line/lines. (Null if done.) bool isEof(); ///< Return true on EOF. void insertUnreadback(string text); VFileLine* fileline(); ///< File/Line number for last getline call // The default behavior is to pass all unknown `defines right through. // This lets the user determine how to report the errors. It also nicely // allows `celldefine and such to remain in the output stream. // CONTROL METHODS // These options control how the parsing proceeds int keepComments() { return m_keepComments; } void keepComments(int flag) { m_keepComments=flag; } // Return comments, 0=no, 1=yes, 2=callback int keepWhitespace() { return m_keepWhitespace; } void keepWhitespace(int flag) { m_keepWhitespace=flag; } // Return extra whitespace bool lineDirectives() { return m_lineDirectives; } void lineDirectives(bool flag) { m_lineDirectives=flag; } // Insert `line directives bool pedantic() { return m_pedantic; } void pedantic(bool flag) { m_pedantic=flag; } // Obey standard; Don't substitute `error bool synthesis() { return m_synthesis; } void synthesis(bool flag) { m_synthesis=flag; } // Ignore translate off // CALLBACK METHODS // This probably will want to be overridden for given child users of this class. virtual void comment(string cmt) = 0; ///< Comment detected (if keepComments==2) virtual void include(string filename) = 0; ///< Request a include file be processed virtual void define(string name, string value, string params) = 0; ///< `define without any parameters virtual void undef(string name) = 0; ///< Remove a definition virtual void undefineall() = 0; ///< Remove all non-command-line definitions virtual bool defExists(string name) = 0; ///< Return true if define exists virtual string defParams(string name) = 0; ///< Return parameter list if define exists virtual string defValue(string name) = 0; ///< Return value of given define (should exist) virtual string defSubstitute(string substitute) = 0; ///< Return value to substitute for given post-parameter value // UTILITIES void error(string msg) { fileline()->error(msg); } ///< Report a error void fatal(string msg) { fileline()->fatal(msg); } ///< Report a fatal error private: VPreProcOpaque* m_opaquep; ///< Pointer to parser's implementation data. }; #endif // Guard Verilog-Perl-3.478/Preproc/.gitignore0000644000177100017500000000015213234726611017426 0ustar wsnyderwsnyderblib gen Makefile pm_to_blib VPreLex*.cpp *.def *.dll *.exp *.o *.c *.bs *.xsc *.output *.old *_cleaned.* Verilog-Perl-3.478/Preproc/VFileLine.h0000644000177100017500000000634514035374034017434 0ustar wsnyderwsnyder// -*- C++ -*- //************************************************************************* // // Copyright 2000-2021 by Wilson Snyder. This program is free software; // you can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // //************************************************************************* /// \file /// \brief Verilog::Preproc: Error handling /// /// Authors: Wilson Snyder /// /// Code available from: https://www.veripool.org/verilog-perl /// //************************************************************************* #ifndef _VFILELINE_H_ #define _VFILELINE_H_ 1 #include #include #include using namespace std; //============================================================================ // VFileLine /// User information and error reporting functions //// /// Users can override this class to implement their own error handling class VFileLine { private: int m_lineno; ///< Line number in file string m_filename; ///< File name static int s_numErrors; ///< Number of errors detected protected: VFileLine(int called_only_for_default) {init("",0);} public: // CONSTRUCTORS /// Create a new fileline, for a new file and/or line number. /// Member functions, so that if a user provides another class, a change in the /// filename/linenumber will create a new element using the derived class. virtual VFileLine* create(const string& filename, int lineno) = 0; /// Create with same filename, new line number; just calls create(fn,ln) virtual VFileLine* create(int lineno) { return create(filename(), lineno); } virtual void init(const string& filename, int lineno); virtual ~VFileLine() {} // ACCESSORS int lineno() const { return m_lineno; } ///< Return line number void linenoIncInPlace() { m_lineno++; } ///< Increment line IN PLACE; normally use create() instead const string filename() const { return m_filename; } ///< Return filename const string filebasename() const; ///< Filename with any directory stripped string lineDirectiveStrg(int enter_exit_level) const; // METHODS virtual void fatal(const string& msg); ///< Report a fatal error at given location virtual void error(const string& msg); ///< Report a error at given location VFileLine* lineDirective(const char* textp, int& enterExitRef); // STATIC METHODS static int numErrors() { return s_numErrors; } ///< Return total errors detected // Internal methods -- special use static const char* itoa(int i); ///< Internal: Not reentrant! - for fatalSrc() only }; ostream& operator<<(ostream& os, VFileLine* fileline); /// Use this instead of fatal() to mention the source code line. #define fatalSrc(msg) fatal((string)"Internal Error: "+__FILE__+":"+VFileLine::itoa(__LINE__)+": "+(msg)) template< class T> std::string cvtToStr(const T& t) { ostringstream os; os<1, keep_whitespace=>1, line_directives=>1, ieee_predefined=>1, pedantic=>0, synthesis=>0, options=>Verilog::Getopt->new(), # If the user didn't give one, still work! parent => undef, #include_open_nonfatal=>0, @_}; bless $self, $class; # Sets $self->{_cthis} $self->{keep_comments} = 2 if ($self->{keep_comments} eq 'sub'); $self->{keep_comments} = 3 if ($self->{keep_comments} eq 'expand'); #TBD $self->_new($self, $self->{keep_comments}, $self->{keep_whitespace}, $self->{line_directives}, $self->{pedantic}, $self->{synthesis}, ); if ($self->{synthesis}) { # Fourth argument 1 for cmdline - no `undefineall effect $self->define('SYNTHESIS',1,undef,1); } if ($self->{ieee_predefined}) { $self->define('SV_COV_START', 0,undef,1); $self->define('SV_COV_STOP', 1,undef,1); $self->define('SV_COV_RESET', 2,undef,1); $self->define('SV_COV_CHECK', 3,undef,1); $self->define('SV_COV_MODULE', 10,undef,1); $self->define('SV_COV_HIER', 11,undef,1); $self->define('SV_COV_ASSERTION', 20,undef,1); $self->define('SV_COV_FSM_STATE', 21,undef,1); $self->define('SV_COV_STATEMENT', 22,undef,1); $self->define('SV_COV_TOGGLE', 23,undef,1); $self->define('SV_COV_OVERFLOW', -2,undef,1); $self->define('SV_COV_ERROR', -1,undef,1); $self->define('SV_COV_NOCOV', 0,undef,1); $self->define('SV_COV_OK', 1,undef,1); $self->define('SV_COV_PARTIAL', 2,undef,1); } #use Data::Dumper; print Dumper($self); return $self; } sub DESTROY { my $self = shift; $self->_DESTROY; } sub STORABLE_freeze { my ($self, $cloning) = @_; # Prevent crash on Storable::store then retrieve delete $self->{_cthis}; return; } sub open { my $self = shift; my %params = ( # filename => # open_nonfatal => 0, ); if ($#_ > 0) { %params=(@_); } else { $params{filename}=shift; } # We allow either open(name) or open(filename=>name); # Allow user to put `defined names on the command line instead of filenames, # then convert them properly. my $filename = $params{filename}; $filename = $self->remove_defines($filename); printf ("Perl open $filename\n") if $self->{debug}; $filename = $self->{options}->file_path($filename); printf ("Perl openfp $filename\n") if $self->{debug}; if (!-r $filename) { if (!$params{open_nonfatal}) { $self->error("Cannot open $filename"); } return undef; } else { $self->_open($filename); } return $self; } sub debug { my $self = shift; my $level = shift; $self->{debug} = $level; $self->_debug($level); } sub parent { my $self = shift; return $self->{parent}; } ###################################################################### #### Utilities sub remove_defines { my $self = shift; my $sym = shift; my $val = "x"; while (defined $val) { last if $sym eq $val; (my $xsym = $sym) =~ s/^\`//; $val = $self->{options}->defvalue_nowarn($xsym); #Undef if not found $sym = $val if defined $val; } return $sym; } sub fileline { my $self = shift; return ($self->filename||"").":".($self->lineno||""); } ###################################################################### #### Called by the parser sub error { my ($self,$text,$token)=@_; my $fileline = $self->filename.":".$self->lineno; croak ("%Error: $fileline: $text\n" ."Stopped"); } sub comment {} sub def_substitute { my ($self, $out) = @_; return $out; } sub include { my ($self,$filename)=@_; print "INCLUDE $filename\n" if $self->{debug}; $self->{options}->includes($self->filename, $filename); $self->open(filename => $filename, open_nonfatal => $self->{include_open_nonfatal}, ); } # Note rather than overriding these, a derived Verilog::Getopt class can # accomplish the same thing. sub undef { my $self = shift; $self->{options}->undef(@_); } sub undefineall { my $self = shift; $self->{options}->undefineall(@_); } sub define { my $self = shift; #print "DEFINE @_\n"; $self->{options}->fileline($self->filename.":".$self->lineno); $self->{options}->define(@_); } sub def_params { # Return define parameters my $self = shift; my $val = $self->{options}->defparams(@_); #printf "DEFPARAMS @_ -> %s\n", $val if $self->{debug}; $val = "" if !defined $val; return $val; } sub def_value { # Return value my $self = shift; #printf "DEFVALUE @_ -> %s\n", $self->{options}->defvalue_nowarn(@_); return $self->{options}->defvalue(@_); } ###################################################################### #### Package return 1; __END__ =pod =head1 NAME Verilog::Preproc - Preprocess Verilog files =head1 SYNOPSIS use Verilog::Getopt; my $vp = Verilog::Preproc->new(I); $vp->open(filename=>"verilog_file.v"); my $line = $vp->getline(); =head1 EXAMPLE # This is a complete verilog pre-parser! # For a command line version, see vppreproc use Verilog::Getopt; use Verilog::Preproc; my $opt = new Verilog::Getopt; @ARGV = $opt->parameter(@ARGV); my $vp = Verilog::Preproc->new(options=>$opt,); $vp->open(filename=>"verilog_file.v"); while (defined (my $line = $vp->getline())) { print $line; } =head1 DESCRIPTION Verilog::Preproc reads Verilog files, and preprocesses them according to the SystemVerilog 2009 (1800-2009) specification. Programs can be easily converted from reading a IO::File into reading preprocessed output from Verilog::Preproc. See the "Which Package" section of L if you are unsure which parsing package to use for a new application. =head1 MEMBER FUNCTIONS =over 4 =item $self->eof() Returns true at the end of the file. =item $self->filename() Returns the filename of the most recently returned getline(). May not match the filename passed on the command line, as `line directives are honored. =item $self->getall() Return the entire translated text up to the final EOF, similar to calling join('',$self->getline) but significantly faster. With optional argument, returns approximately that number of characters. Returns undef at EOF. =item $self->getline() Return the next line of text. Returns undef at EOF. (Just like IO::File->getline().) =item $self->lineno() Returns the line number of the last getline(). Note that the line number may change several times between getline(), for example when traversing multiple include files. =item $self->parent() Returns a reference to the Verilog::Netlist::File which created this object, if any. =item $self->new(I) Creates a new preprocessor. See the PARAMETERS section for the options that may be passed to new. =item $self->open(filename=>I) Opens the specified file. If filename ends in .gz, decompress while reading. If called before a file is completely parsed, the new file will be parsed completely before returning to the previously open file. (As if it was an include file.) Open may also be called without named parameters, in which case the only argument is the filename. =item $self->unreadback(I) Insert text into the input stream at the given point. The text will not be parsed, just returned to the application. This lets comment() callbacks insert special code into the output stream. =back =head1 PARAMETERS The following named parameters may be passed to the new constructor. =over 4 =item ieee_predefines=>0 With ieee_predefines false, disable defining SV_COV_START and other IEEE mandated definitions. =item include_open_nonfatal=>1 With include_open_nonfatal set to one, ignore any include files that do not exist. =item keep_comments=>0 With keep_comments set to zero, strip all comments. When set to one (the default), insert comments in output streams. When set to 'sub', call the comment() function so that meta-comments can be processed outside of the output stream. Note that some programs use meta-comments to embed useful information (synthesis and lint), so strip with caution if feeding to tools other than your own. Defaults to 1. =item keep_whitespace=>0 With keep_whitespace set to zero, compress all whitespace to a single space or newline. When set to one (the default), retain whitespace. Defaults to 1. =item line_directives=>0 With line_directives set to zero, suppress "`line" comments which indicate filename and line number changes. Use the lineno() and filename() methods instead to retrieve this information. Defaults true. =item options=>Verilog::Getopt object Specifies the object to be used for resolving filenames and defines. Other classes may be used, as long as their interface matches that of Getopt. =item pedantic=>1 With pedantic set, rigorously obey the Verilog pedantic. This used to disable the `__FILE__ and `__LINE__ features but no longer does as they were added to the 1800-2009 standard. It remains to disable `error and may disable other future features that are not specified in the language standard. Defaults false. =item synthesis=>1 With synthesis set, define SYNTHESIS, and ignore text between "ambit", "pragma", "synopsys" or "synthesis" translate_off and translate_on meta comments. Note using metacomments is discouraged as they have led to silicon bugs (versus ifdef SYNTHESIS); see L. =back =head1 CALLBACKS Default callbacks are implemented that are suitable for most applications. Derived classes may override these callbacks as needed. =over 4 =item $self->comment(I) Called with each comment, when keep_comments=>'sub' is used. Defaults to do nothing. =item $self->undef(I) Called with each `undef. Defaults to use options object. =item $self->undefineall() Called with each `undefineall. Defaults to use options object. =item $self->define(I, I, I) Called with each `define. Defaults to use options object. =item $self->def_params(I) Called to determine if the define exists and the parameters it expects. Return undef if the define doesn't exist, 0 if the define exists with no arguments, or argument list with leading parenthesis if the define has arguments. Defaults to use options object's defparams method. =item $self->def_substitute(I) Called to determine what string to insert for a define substitution. Called with the value of the define after parameters have been expanded computed per the SystemVerilog spec. Generally this function would just return the same string as it is passed, but this can be overridden to allow customized preprocessing. =item $self->def_value(I) Called to return value to substitute for specified define. Defaults to use options object. =item $self->error(I) Called on errors, with the error message as an argument. Defaults to die. =item $self->include(I) Specifies a include file has been found. Defaults to call $self->open after resolving the filename with the options parameter. =back =head1 COMPLIANCE The preprocessor supports the constructs defined in the SystemVerilog 2017 standard (IEEE 1800-2017), which is a superset of Verilog 1995 (IEEE 1364-1995), Verilog 2001 (IEEE 1364-2001), Verilog 2005 (IEEE 1364-2005) SystemVerilog 2005 (IEEE 1800-2005), SystemVerilog 2009 (IEEE 1800-2009), and SystemVerilog 2012 (IEEE 1800-2012). Verilog::Preproc adds the `error macro (unless the pedantic parameter is set.): =over 4 =item `__FILE__ The __FILE__ define expands to the current filename as a string, like C++'s __FILE__. This was incorporated into to the 1800-2009 standard (but supported by Verilog-Perl since 2004!) =item `__LINE__ The __LINE__ define expands to the current filename as a string, like C++'s __LINE__. This was incorporated into to the 1800-2009 standard (but supported by Verilog-Perl since 2004!) =item `error I<"string"> `error will be reported whenever it is encountered. (Like C++ #error.) These are useful for error macros, similar to assert() in C++. =back =head1 DISTRIBUTION Verilog-Perl is part of the L free Verilog EDA software tool suite. The latest version is available from CPAN and from L. Copyright 2000-2021 by Wilson Snyder. This package is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. =head1 AUTHORS Wilson Snyder =head1 SEE ALSO L, L, L L This package is layered on a C++ interface which may be found in the kit. =cut Verilog-Perl-3.478/Preproc/gen/0000755000177100017500000000000014057150520016203 5ustar wsnyderwsnyderVerilog-Perl-3.478/Preproc/gen/flex-10000644000177100017500000034552514035373774017256 0ustar wsnyderwsnyder#line 2 "VPreLex_pretmp.cpp" #line 4 "VPreLex_pretmp.cpp" #define YY_INT_ALIGNED long int /* A lexical scanner generated by flex */ #define yy_create_buffer VPreLex_create_buffer #define yy_delete_buffer VPreLex_delete_buffer #define yy_scan_buffer VPreLex_scan_buffer #define yy_scan_string VPreLex_scan_string #define yy_scan_bytes VPreLex_scan_bytes #define yy_init_buffer VPreLex_init_buffer #define yy_flush_buffer VPreLex_flush_buffer #define yy_load_buffer_state VPreLex_load_buffer_state #define yy_switch_to_buffer VPreLex_switch_to_buffer #define yypush_buffer_state VPreLexpush_buffer_state #define yypop_buffer_state VPreLexpop_buffer_state #define yyensure_buffer_stack VPreLexensure_buffer_stack #define yy_flex_debug VPreLex_flex_debug #define yyin VPreLexin #define yyleng VPreLexleng #define yylex VPreLexlex #define yylineno VPreLexlineno #define yyout VPreLexout #define yyrestart VPreLexrestart #define yytext VPreLextext #define yywrap VPreLexwrap #define yyalloc VPreLexalloc #define yyrealloc VPreLexrealloc #define yyfree VPreLexfree #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 6 #define YY_FLEX_SUBMINOR_VERSION 4 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif #ifdef yy_create_buffer #define VPreLex_create_buffer_ALREADY_DEFINED #else #define yy_create_buffer VPreLex_create_buffer #endif #ifdef yy_delete_buffer #define VPreLex_delete_buffer_ALREADY_DEFINED #else #define yy_delete_buffer VPreLex_delete_buffer #endif #ifdef yy_scan_buffer #define VPreLex_scan_buffer_ALREADY_DEFINED #else #define yy_scan_buffer VPreLex_scan_buffer #endif #ifdef yy_scan_string #define VPreLex_scan_string_ALREADY_DEFINED #else #define yy_scan_string VPreLex_scan_string #endif #ifdef yy_scan_bytes #define VPreLex_scan_bytes_ALREADY_DEFINED #else #define yy_scan_bytes VPreLex_scan_bytes #endif #ifdef yy_init_buffer #define VPreLex_init_buffer_ALREADY_DEFINED #else #define yy_init_buffer VPreLex_init_buffer #endif #ifdef yy_flush_buffer #define VPreLex_flush_buffer_ALREADY_DEFINED #else #define yy_flush_buffer VPreLex_flush_buffer #endif #ifdef yy_load_buffer_state #define VPreLex_load_buffer_state_ALREADY_DEFINED #else #define yy_load_buffer_state VPreLex_load_buffer_state #endif #ifdef yy_switch_to_buffer #define VPreLex_switch_to_buffer_ALREADY_DEFINED #else #define yy_switch_to_buffer VPreLex_switch_to_buffer #endif #ifdef yypush_buffer_state #define VPreLexpush_buffer_state_ALREADY_DEFINED #else #define yypush_buffer_state VPreLexpush_buffer_state #endif #ifdef yypop_buffer_state #define VPreLexpop_buffer_state_ALREADY_DEFINED #else #define yypop_buffer_state VPreLexpop_buffer_state #endif #ifdef yyensure_buffer_stack #define VPreLexensure_buffer_stack_ALREADY_DEFINED #else #define yyensure_buffer_stack VPreLexensure_buffer_stack #endif #ifdef yylex #define VPreLexlex_ALREADY_DEFINED #else #define yylex VPreLexlex #endif #ifdef yyrestart #define VPreLexrestart_ALREADY_DEFINED #else #define yyrestart VPreLexrestart #endif #ifdef yylex_init #define VPreLexlex_init_ALREADY_DEFINED #else #define yylex_init VPreLexlex_init #endif #ifdef yylex_init_extra #define VPreLexlex_init_extra_ALREADY_DEFINED #else #define yylex_init_extra VPreLexlex_init_extra #endif #ifdef yylex_destroy #define VPreLexlex_destroy_ALREADY_DEFINED #else #define yylex_destroy VPreLexlex_destroy #endif #ifdef yyget_debug #define VPreLexget_debug_ALREADY_DEFINED #else #define yyget_debug VPreLexget_debug #endif #ifdef yyset_debug #define VPreLexset_debug_ALREADY_DEFINED #else #define yyset_debug VPreLexset_debug #endif #ifdef yyget_extra #define VPreLexget_extra_ALREADY_DEFINED #else #define yyget_extra VPreLexget_extra #endif #ifdef yyset_extra #define VPreLexset_extra_ALREADY_DEFINED #else #define yyset_extra VPreLexset_extra #endif #ifdef yyget_in #define VPreLexget_in_ALREADY_DEFINED #else #define yyget_in VPreLexget_in #endif #ifdef yyset_in #define VPreLexset_in_ALREADY_DEFINED #else #define yyset_in VPreLexset_in #endif #ifdef yyget_out #define VPreLexget_out_ALREADY_DEFINED #else #define yyget_out VPreLexget_out #endif #ifdef yyset_out #define VPreLexset_out_ALREADY_DEFINED #else #define yyset_out VPreLexset_out #endif #ifdef yyget_leng #define VPreLexget_leng_ALREADY_DEFINED #else #define yyget_leng VPreLexget_leng #endif #ifdef yyget_text #define VPreLexget_text_ALREADY_DEFINED #else #define yyget_text VPreLexget_text #endif #ifdef yyget_lineno #define VPreLexget_lineno_ALREADY_DEFINED #else #define yyget_lineno VPreLexget_lineno #endif #ifdef yyset_lineno #define VPreLexset_lineno_ALREADY_DEFINED #else #define yyset_lineno VPreLexset_lineno #endif #ifdef yywrap #define VPreLexwrap_ALREADY_DEFINED #else #define yywrap VPreLexwrap #endif #ifdef yyalloc #define VPreLexalloc_ALREADY_DEFINED #else #define yyalloc VPreLexalloc #endif #ifdef yyrealloc #define VPreLexrealloc_ALREADY_DEFINED #else #define yyrealloc VPreLexrealloc #endif #ifdef yyfree #define VPreLexfree_ALREADY_DEFINED #else #define yyfree VPreLexfree #endif #ifdef yytext #define VPreLextext_ALREADY_DEFINED #else #define yytext VPreLextext #endif #ifdef yyleng #define VPreLexleng_ALREADY_DEFINED #else #define yyleng VPreLexleng #endif #ifdef yyin #define VPreLexin_ALREADY_DEFINED #else #define yyin VPreLexin #endif #ifdef yyout #define VPreLexout_ALREADY_DEFINED #else #define yyout VPreLexout #endif #ifdef yy_flex_debug #define VPreLex_flex_debug_ALREADY_DEFINED #else #define yy_flex_debug VPreLex_flex_debug #endif #ifdef yylineno #define VPreLexlineno_ALREADY_DEFINED #else #define yylineno VPreLexlineno #endif /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ #include #include #include #include /* end standard C headers. */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #ifndef SIZE_MAX #define SIZE_MAX (~(size_t)0) #endif #endif /* ! C99 */ #endif /* ! FLEXINT_H */ /* begin standard C++ headers. */ /* TODO: this is always defined, so inline it */ #define yyconst const #if defined(__GNUC__) && __GNUC__ >= 3 #define yynoreturn __attribute__((__noreturn__)) #else #define yynoreturn #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an * integer in range [0..255] for use as an array index. */ #define YY_SC_TO_UI(c) ((YY_CHAR) (c)) /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN (yy_start) = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START (((yy_start) - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE yyrestart( yyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k. * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. * Ditto for the __ia64__ case accordingly. */ #define YY_BUF_SIZE 32768 #else #define YY_BUF_SIZE 16384 #endif /* __ia64__ */ #endif /* The state buf must be large enough to hold one state per character in the main buffer. */ #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef size_t yy_size_t; #endif extern int yyleng; extern FILE *yyin, *yyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 #define YY_LESS_LINENO(n) #define YY_LINENO_REWIND_TO(ptr) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = (yy_hold_char); \ YY_RESTORE_YY_MORE_OFFSET \ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, (yytext_ptr) ) #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ int yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ /* Stack of input buffers. */ static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ static YY_BUFFER_STATE * yy_buffer_stack = NULL; /**< Stack as an array. */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ : NULL) /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] /* yy_hold_char holds the character lost when yytext is formed. */ static char yy_hold_char; static int yy_n_chars; /* number of characters read into yy_ch_buf */ int yyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = NULL; static int yy_init = 0; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow yywrap()'s to do buffer switches * instead of setting up a fresh yyin. A bit of a hack ... */ static int yy_did_buffer_switch_on_eof; void yyrestart ( FILE *input_file ); void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer ); YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size ); void yy_delete_buffer ( YY_BUFFER_STATE b ); void yy_flush_buffer ( YY_BUFFER_STATE b ); void yypush_buffer_state ( YY_BUFFER_STATE new_buffer ); void yypop_buffer_state ( void ); static void yyensure_buffer_stack ( void ); static void yy_load_buffer_state ( void ); static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file ); #define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER ) YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size ); YY_BUFFER_STATE yy_scan_string ( const char *yy_str ); YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len ); void *yyalloc ( yy_size_t ); void *yyrealloc ( void *, yy_size_t ); void yyfree ( void * ); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer( yyin, YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer( yyin, YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* Begin user sect3 */ #define VPreLexwrap() (/*CONSTCOND*/1) #define YY_SKIP_YYWRAP typedef flex_uint8_t YY_CHAR; FILE *yyin = NULL, *yyout = NULL; typedef int yy_state_type; extern int yylineno; int yylineno = 1; extern char *yytext; #ifdef yytext_ptr #undef yytext_ptr #endif #define yytext_ptr yytext static yy_state_type yy_get_previous_state ( void ); static yy_state_type yy_try_NUL_trans ( yy_state_type current_state ); static int yy_get_next_buffer ( void ); static void yynoreturn yy_fatal_error ( const char* msg ); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ (yytext_ptr) -= (yy_more_len); \ yyleng = (int) (yy_cp - (yytext_ptr)); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; #define YY_NUM_RULES 121 #define YY_END_OF_BUFFER 122 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info { flex_int32_t yy_verify; flex_int32_t yy_nxt; }; static const flex_int32_t yy_accept[692] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 119, 117, 112, 116, 118, 15, 119, 113, 119, 119, 1, 117, 116, 119, 108, 106, 108, 108, 107, 18, 16, 18, 21, 17, 120, 50, 49, 50, 48, 63, 56, 65, 55, 58, 51, 52, 65, 65, 61, 65, 62, 63, 73, 70, 75, 69, 72, 75, 75, 75, 80, 78, 80, 80, 79, 80, 35, 32, 31, 34, 33, 24, 26, 35, 35, 32, 34, 35, 96, 84, 97, 83, 85, 90, 91, 97, 92, 97, 88, 89, 97, 45, 44, 45, 47, 120, 40, 39, 40, 40, 40, 102, 100, 102, 102, 101, 117, 112, 0, 104, 103, 113, 0, 113, 22, 109, 0, 109, 111, 109, 109, 109, 109, 109, 117, 0, 0, 0, 109, 106, 0, 105, 107, 16, 0, 17, 20, 19, 20, 49, 0, 63, 56, 0, 53, 54, 64, 57, 0, 60, 0, 73, 70, 0, 66, 68, 74, 71, 0, 78, 0, 76, 79, 77, 0, 32, 31, 0, 26, 0, 26, 25, 28, 0, 28, 30, 32, 0, 28, 96, 84, 0, 81, 82, 87, 93, 0, 95, 44, 0, 46, 39, 0, 0, 0, 0, 100, 0, 0, 0, 101, 0, 0, 0, 0, 103, 103, 0, 103, 103, 103, 103, 114, 113, 109, 0, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 0, 109, 0, 54, 0, 68, 68, 27, 28, 0, 28, 0, 28, 28, 82, 93, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 103, 103, 103, 113, 110, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 0, 109, 59, 67, 0, 29, 23, 28, 28, 28, 94, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 103, 103, 103, 109, 109, 109, 4, 109, 109, 109, 109, 109, 109, 109, 109, 109, 0, 109, 28, 28, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 103, 103, 103, 103, 109, 109, 109, 5, 6, 12, 7, 109, 109, 109, 109, 10, 0, 0, 28, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 103, 103, 103, 103, 109, 109, 3, 8, 109, 109, 109, 109, 0, 0, 2, 0, 28, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 0, 103, 103, 103, 109, 109, 9, 0, 109, 109, 0, 28, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 0, 103, 103, 103, 0, 13, 14, 0, 109, 109, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 0, 103, 103, 0, 0, 36, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 0, 103, 0, 0, 109, 0, 0, 0, 0, 0, 0, 103, 0, 103, 0, 0, 11, 0, 0, 0, 0, 0, 0, 103, 0, 103, 0, 0, 0, 41, 0, 0, 0, 0, 103, 0, 103, 0, 0, 0, 0, 0, 0, 0, 103, 0, 103, 0, 0, 0, 0, 0, 0, 0, 103, 0, 103, 0, 0, 0, 0, 0, 0, 0, 103, 0, 103, 0, 0, 0, 0, 0, 0, 0, 103, 0, 103, 0, 0, 0, 0, 0, 0, 0, 103, 0, 103, 0, 0, 0, 0, 0, 0, 0, 103, 0, 103, 0, 0, 0, 0, 0, 99, 0, 98, 98, 103, 0, 0, 0, 0, 0, 0, 99, 99, 99, 0, 0, 98, 98, 98, 98, 98, 103, 0, 0, 0, 0, 99, 98, 103, 0, 0, 0, 0, 103, 0, 0, 0, 0, 103, 0, 0, 0, 0, 103, 0, 0, 0, 0, 103, 0, 0, 0, 0, 103, 0, 0, 0, 0, 103, 0, 0, 0, 42, 103, 0, 0, 43, 103, 0, 37, 38, 38, 0 } ; static const YY_CHAR yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 2, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 1, 1, 1, 1, 2, 1, 6, 1, 7, 1, 1, 1, 8, 9, 10, 1, 11, 1, 1, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 1, 1, 1, 1, 14, 1, 1, 15, 16, 17, 17, 18, 19, 20, 21, 22, 17, 17, 23, 24, 25, 26, 27, 17, 28, 29, 30, 17, 17, 17, 17, 31, 17, 32, 33, 34, 1, 35, 36, 37, 38, 39, 40, 41, 42, 43, 21, 44, 17, 17, 45, 46, 47, 48, 49, 17, 50, 51, 52, 53, 17, 17, 17, 31, 17, 32, 1, 34, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 54, 1, 1, 1, 54, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 54, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static const YY_CHAR yy_meta[55] = { 0, 1, 2, 3, 4, 1, 5, 6, 7, 7, 8, 9, 8, 10, 1, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 7, 5, 7, 11, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 1 } ; static const flex_int32_t yy_base[736] = { 0, 0, 54, 108, 162, 216, 270, 12, 14, 322, 356, 36, 67, 392, 446, 500, 554, 606, 640, 71, 88, 40, 91, 676, 730, 1773, 1774, 1770, 1774, 20, 1774, 1774, 9, 1735, 0, 779, 1774, 45, 94, 827, 1774, 1774, 22, 1758, 0, 1774, 1774, 24, 1774, 0, 26, 1774, 1774, 34, 1774, 0, 1774, 47, 0, 1774, 1774, 1774, 1774, 68, 1774, 79, 1774, 93, 0, 1774, 102, 0, 1774, 1774, 113, 125, 1774, 1774, 128, 1757, 0, 130, 1774, 1766, 1774, 132, 1774, 1774, 1731, 0, 118, 141, 144, 146, 0, 1774, 134, 0, 1774, 1774, 1774, 1774, 1774, 145, 1774, 1774, 150, 1774, 1774, 146, 1774, 0, 1774, 1774, 155, 1754, 4, 1774, 1774, 157, 175, 0, 1763, 1774, 185, 284, 570, 1728, 1727, 1726, 1774, 1725, 0, 157, 1774, 48, 154, 161, 57, 164, 203, 208, 1715, 211, 193, 1774, 228, 1774, 0, 1774, 230, 0, 1774, 1774, 232, 1774, 237, 0, 1774, 239, 1774, 0, 1774, 1774, 242, 1774, 1723, 0, 1774, 250, 1774, 1725, 1774, 1774, 252, 1774, 254, 1774, 0, 1774, 256, 1755, 1774, 258, 1720, 1719, 1718, 1774, 1717, 1716, 228, 1774, 264, 287, 249, 0, 1774, 291, 1774, 0, 1774, 1715, 1714, 1774, 1774, 293, 1774, 1774, 304, 263, 1702, 1698, 1774, 306, 576, 741, 0, 744, 160, 255, 1716, 1742, 745, 750, 294, 288, 171, 313, 1774, 1709, 1708, 1707, 1706, 334, 278, 286, 279, 251, 303, 306, 335, 308, 1697, 300, 348, 0, 1734, 1706, 372, 1774, 1702, 1701, 1700, 1729, 350, 331, 0, 1698, 1697, 1696, 1725, 378, 1680, 1689, 1691, 798, 361, 359, 1696, 802, 367, 380, 1695, 394, 396, 387, 390, 387, 1694, 388, 425, 427, 414, 455, 1688, 1774, 399, 440, 429, 430, 431, 433, 338, 341, 432, 447, 436, 381, 1676, 404, 1774, 1774, 416, 1774, 1774, 462, 463, 450, 1774, 1774, 1685, 1672, 1677, 477, 479, 470, 480, 482, 495, 499, 502, 498, 509, 511, 502, 514, 531, 580, 572, 627, 215, 505, 534, 1683, 495, 502, 533, 535, 553, 293, 546, 560, 537, 1677, 624, 516, 568, 628, 1674, 1666, 1669, 611, 586, 611, 612, 615, 641, 623, 645, 665, 1693, 672, 675, 671, 678, 698, 751, 702, 519, 765, 618, 681, 621, 1677, 1676, 1666, 1654, 669, 625, 407, 664, 660, 485, 722, 740, 762, 1632, 1607, 1617, 731, 762, 761, 1632, 786, 794, 794, 1627, 664, 807, 795, 785, 800, 810, 809, 1626, 813, 711, 846, 837, 851, 850, 838, 842, 1610, 1600, 686, 755, 812, 834, 881, 887, 1774, 891, 861, 863, 1598, 1572, 1621, 803, 842, 853, 868, 898, 886, 874, 887, 904, 1591, 878, 908, 896, 884, 896, 901, 913, 916, 591, 915, 920, 891, 895, 1581, 718, 900, 904, 944, 914, 916, 951, 1575, 930, 955, 1584, 910, 956, 1574, 913, 926, 933, 945, 1573, 940, 968, 959, 943, 969, 970, 973, 986, 1557, 1556, 1532, 942, 944, 1545, 1544, 992, 1536, 1524, 955, 966, 975, 971, 972, 980, 989, 977, 981, 989, 1014, 997, 1011, 703, 1523, 1514, 1512, 991, 1493, 1490, 1493, 1015, 1002, 1022, 1010, 1017, 1014, 1041, 1021, 996, 1492, 1487, 1011, 1487, 1493, 1481, 1023, 1024, 1021, 1050, 1026, 1053, 1479, 1489, 1493, 1472, 1483, 1481, 1029, 1031, 1040, 1063, 1046, 1069, 1480, 1481, 1470, 1774, 1471, 1051, 1052, 1061, 1074, 1066, 345, 1470, 1452, 1464, 1450, 1069, 1072, 1060, 1088, 1063, 1079, 1430, 1477, 1426, 1475, 1064, 1065, 1081, 1096, 1084, 1117, 1122, 807, 1125, 137, 1089, 1095, 1423, 1100, 1422, 1130, 1137, 1414, 1140, 1407, 1418, 1397, 1097, 1124, 1107, 1116, 1390, 1387, 1382, 1388, 1112, 1117, 1127, 1143, 1129, 1145, 1375, 1373, 1376, 1376, 1126, 1127, 1134, 1159, 1135, 1152, 1366, 1362, 1227, 1212, 1157, 1162, 1180, 1185, 1189, 1166, 1213, 1224, 1209, 1207, 1190, 1244, 1251, 1193, 1200, 1201, 1240, 1247, 1204, 1205, 1246, 1208, 1179, 1214, 1199, 1197, 1198, 1774, 1774, 1175, 1196, 1194, 1195, 1190, 871, 1191, 1192, 1187, 1197, 1182, 1189, 1184, 1192, 1193, 1176, 1179, 1188, 1188, 1174, 1194, 1184, 1184, 1170, 1180, 1195, 1181, 1167, 1176, 1118, 1211, 961, 801, 383, 1774, 1212, 228, 169, 1774, 1214, 61, 1774, 27, 1774, 1774, 1263, 1275, 1287, 1299, 1311, 1323, 1335, 1347, 1359, 1371, 1383, 1395, 1402, 1414, 1422, 1425, 1427, 1438, 1450, 1462, 1474, 1486, 1489, 1495, 1507, 1514, 1526, 1533, 1545, 1548, 1559, 1566, 1578, 1589, 1601, 1608, 1620, 1632, 1639, 1651, 1663, 1675, 1687, 1699 } ; static const flex_int32_t yy_def[736] = { 0, 692, 692, 693, 693, 694, 694, 695, 695, 696, 696, 697, 697, 698, 698, 699, 699, 700, 700, 701, 701, 702, 702, 703, 703, 691, 691, 691, 691, 691, 691, 691, 691, 704, 705, 706, 691, 691, 691, 706, 691, 691, 691, 691, 707, 691, 691, 691, 691, 708, 709, 691, 691, 691, 691, 710, 691, 691, 710, 691, 691, 691, 691, 691, 691, 711, 691, 710, 712, 691, 691, 712, 691, 691, 691, 713, 691, 691, 691, 691, 714, 691, 691, 691, 691, 691, 691, 691, 715, 716, 717, 691, 691, 717, 718, 691, 691, 718, 691, 691, 691, 691, 691, 691, 691, 691, 719, 691, 691, 691, 691, 720, 691, 691, 691, 691, 691, 691, 691, 691, 691, 721, 691, 691, 691, 691, 722, 704, 691, 705, 691, 723, 724, 723, 691, 723, 723, 723, 723, 723, 691, 691, 691, 691, 723, 691, 691, 691, 707, 691, 691, 708, 691, 691, 691, 691, 691, 710, 691, 691, 691, 725, 691, 691, 691, 691, 691, 712, 691, 691, 691, 726, 691, 691, 691, 691, 691, 691, 714, 691, 691, 691, 691, 691, 715, 691, 716, 691, 727, 728, 727, 691, 691, 691, 727, 718, 691, 691, 691, 729, 691, 730, 731, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 721, 691, 691, 691, 691, 722, 722, 691, 722, 722, 722, 722, 691, 705, 723, 691, 724, 723, 723, 723, 723, 723, 723, 723, 723, 723, 691, 723, 691, 725, 691, 726, 726, 691, 727, 691, 728, 691, 727, 727, 729, 730, 691, 731, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 722, 722, 722, 722, 705, 691, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 691, 723, 691, 691, 691, 691, 691, 727, 727, 727, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 722, 722, 722, 722, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 691, 723, 727, 727, 727, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 722, 722, 722, 722, 722, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 691, 732, 727, 727, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 722, 722, 722, 722, 722, 723, 723, 723, 723, 723, 723, 723, 723, 732, 732, 691, 732, 727, 727, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 722, 691, 722, 722, 722, 723, 723, 723, 691, 723, 723, 732, 727, 727, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 722, 691, 722, 722, 722, 691, 723, 723, 691, 723, 723, 727, 727, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 722, 691, 722, 722, 691, 691, 723, 723, 691, 691, 691, 691, 691, 691, 691, 691, 691, 722, 691, 722, 691, 691, 723, 691, 691, 691, 691, 691, 691, 722, 691, 722, 691, 691, 723, 691, 691, 691, 691, 691, 691, 722, 691, 722, 691, 691, 691, 691, 691, 691, 691, 691, 722, 691, 722, 691, 691, 691, 691, 691, 691, 691, 722, 691, 722, 691, 691, 691, 691, 691, 691, 691, 722, 691, 722, 691, 691, 691, 691, 691, 691, 691, 722, 691, 722, 691, 691, 691, 691, 691, 691, 691, 722, 691, 722, 691, 691, 691, 691, 691, 691, 691, 722, 691, 722, 691, 691, 691, 691, 691, 691, 691, 722, 691, 722, 691, 691, 691, 691, 691, 733, 691, 734, 735, 722, 691, 691, 691, 691, 691, 691, 733, 733, 733, 691, 691, 734, 734, 735, 735, 735, 722, 691, 691, 691, 691, 691, 691, 722, 691, 691, 691, 691, 722, 691, 691, 691, 691, 722, 691, 691, 691, 691, 722, 691, 691, 691, 691, 722, 691, 691, 691, 691, 722, 691, 691, 691, 691, 722, 691, 691, 691, 691, 722, 691, 691, 691, 722, 691, 691, 722, 691, 0, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691 } ; static const flex_int32_t yy_nxt[1829] = { 0, 26, 27, 28, 29, 30, 31, 26, 26, 26, 26, 26, 32, 26, 26, 52, 53, 52, 53, 125, 54, 126, 54, 123, 124, 145, 146, 149, 150, 153, 154, 691, 26, 34, 26, 691, 35, 155, 156, 69, 70, 71, 72, 113, 114, 210, 73, 140, 74, 141, 158, 159, 115, 211, 36, 26, 37, 28, 38, 30, 31, 26, 26, 26, 26, 26, 32, 26, 26, 75, 69, 70, 71, 72, 108, 109, 116, 73, 160, 74, 161, 142, 163, 164, 231, 110, 26, 34, 26, 234, 39, 108, 109, 231, 113, 114, 141, 123, 143, 165, 75, 690, 110, 115, 111, 168, 169, 240, 36, 40, 40, 41, 42, 40, 40, 40, 40, 40, 43, 40, 40, 111, 40, 170, 187, 171, 166, 116, 173, 174, 142, 175, 176, 179, 180, 182, 183, 196, 197, 577, 40, 40, 40, 192, 40, 141, 141, 182, 193, 204, 205, 189, 187, 190, 191, 198, 200, 199, 207, 208, 212, 213, 40, 40, 40, 41, 42, 40, 40, 40, 40, 40, 43, 40, 40, 691, 40, 142, 587, 189, 142, 190, 191, 202, 273, 214, 203, 215, 123, 124, 231, 194, 233, 231, 40, 40, 40, 231, 40, 235, 231, 236, 282, 238, 237, 140, 273, 141, 239, 688, 141, 241, 141, 141, 123, 143, 40, 45, 45, 46, 47, 45, 48, 45, 45, 45, 45, 45, 45, 231, 45, 145, 146, 149, 150, 153, 244, 243, 370, 142, 155, 156, 158, 159, 142, 163, 164, 142, 45, 50, 45, 231, 45, 168, 169, 173, 174, 175, 176, 179, 180, 182, 183, 254, 251, 261, 192, 261, 141, 687, 45, 45, 45, 46, 47, 45, 48, 45, 45, 45, 45, 45, 45, 274, 45, 251, 217, 231, 217, 141, 182, 193, 691, 255, 196, 197, 204, 205, 691, 218, 142, 291, 45, 50, 45, 274, 45, 207, 208, 212, 213, 219, 262, 220, 231, 231, 281, 691, 280, 290, 288, 218, 231, 142, 45, 56, 57, 58, 59, 231, 60, 61, 62, 219, 63, 220, 231, 289, 281, 231, 280, 281, 231, 292, 231, 294, 378, 299, 297, 691, 293, 153, 244, 286, 64, 65, 66, 287, 67, 56, 57, 58, 59, 283, 60, 61, 62, 251, 63, 305, 231, 231, 295, 306, 231, 301, 302, 231, 307, 337, 261, 338, 261, 296, 563, 313, 251, 314, 64, 65, 66, 316, 67, 76, 76, 77, 78, 76, 76, 76, 76, 76, 79, 76, 76, 248, 76, 313, 317, 314, 319, 320, 321, 316, 322, 323, 323, 231, 691, 301, 302, 330, 342, 685, 76, 81, 76, 262, 76, 691, 317, 691, 319, 320, 321, 231, 322, 323, 325, 328, 231, 326, 327, 231, 416, 344, 76, 76, 76, 77, 78, 76, 76, 76, 76, 76, 79, 76, 76, 691, 76, 328, 331, 326, 327, 231, 231, 231, 231, 231, 327, 333, 231, 332, 334, 335, 231, 339, 76, 81, 76, 336, 76, 231, 345, 346, 251, 383, 341, 383, 340, 347, 329, 351, 352, 353, 354, 355, 251, 251, 76, 82, 83, 84, 85, 86, 87, 82, 82, 82, 82, 82, 82, 82, 82, 351, 352, 353, 354, 355, 356, 357, 358, 691, 359, 361, 362, 363, 360, 362, 371, 231, 82, 89, 82, 691, 90, 373, 231, 384, 409, 231, 356, 357, 374, 358, 359, 361, 362, 363, 360, 364, 251, 365, 82, 82, 91, 84, 92, 86, 87, 82, 82, 82, 82, 82, 82, 82, 82, 231, 231, 231, 222, 231, 223, 365, 691, 376, 265, 381, 265, 372, 231, 375, 691, 224, 82, 89, 82, 231, 93, 266, 379, 385, 377, 691, 231, 225, 367, 226, 366, 380, 368, 267, 251, 268, 390, 224, 82, 95, 96, 97, 98, 266, 99, 100, 101, 102, 103, 227, 367, 226, 475, 366, 368, 267, 383, 268, 383, 390, 383, 691, 383, 389, 393, 394, 411, 391, 104, 101, 105, 392, 106, 95, 96, 97, 98, 366, 99, 100, 101, 102, 103, 397, 231, 389, 393, 231, 394, 391, 231, 231, 413, 392, 251, 415, 436, 395, 436, 398, 369, 396, 104, 101, 105, 397, 106, 117, 117, 118, 119, 117, 117, 117, 117, 117, 117, 117, 120, 395, 117, 398, 399, 396, 401, 402, 231, 403, 402, 412, 231, 404, 691, 417, 418, 231, 691, 691, 117, 117, 117, 414, 117, 444, 399, 445, 401, 231, 402, 403, 452, 405, 231, 404, 420, 421, 422, 451, 406, 408, 117, 117, 117, 118, 119, 117, 117, 117, 117, 117, 117, 117, 120, 269, 117, 269, 217, 222, 217, 223, 406, 408, 223, 518, 223, 691, 270, 452, 423, 218, 224, 428, 117, 117, 117, 276, 117, 481, 271, 691, 272, 219, 225, 220, 226, 407, 251, 277, 270, 278, 424, 218, 224, 428, 117, 130, 429, 276, 430, 407, 271, 231, 272, 219, 227, 220, 226, 407, 251, 279, 265, 278, 265, 438, 269, 461, 269, 461, 429, 575, 430, 410, 132, 266, 133, 134, 432, 270, 433, 135, 136, 434, 397, 137, 437, 267, 438, 268, 138, 271, 439, 272, 139, 130, 440, 266, 441, 440, 432, 270, 433, 691, 684, 434, 397, 585, 437, 267, 231, 268, 691, 271, 439, 272, 691, 691, 440, 428, 441, 443, 132, 406, 133, 134, 453, 406, 446, 135, 136, 447, 231, 137, 144, 449, 231, 691, 138, 450, 231, 428, 139, 454, 462, 406, 421, 455, 463, 448, 446, 420, 421, 422, 447, 420, 421, 422, 456, 251, 457, 251, 464, 432, 464, 465, 462, 466, 436, 469, 436, 463, 445, 439, 445, 470, 471, 444, 439, 445, 445, 691, 445, 657, 477, 432, 478, 465, 479, 231, 466, 469, 480, 231, 460, 439, 467, 470, 231, 471, 472, 491, 231, 482, 494, 473, 476, 483, 474, 421, 455, 484, 251, 485, 251, 486, 495, 486, 467, 461, 464, 461, 464, 491, 397, 691, 494, 473, 476, 496, 474, 498, 478, 500, 478, 691, 691, 477, 495, 478, 231, 488, 231, 506, 505, 510, 397, 489, 492, 499, 478, 496, 478, 498, 501, 500, 486, 428, 486, 511, 406, 512, 691, 432, 513, 473, 514, 510, 397, 489, 492, 499, 439, 515, 517, 683, 501, 691, 474, 428, 691, 511, 406, 512, 502, 432, 513, 473, 514, 231, 397, 516, 525, 428, 439, 515, 517, 503, 521, 526, 474, 432, 406, 507, 527, 439, 530, 691, 529, 231, 537, 538, 539, 516, 525, 428, 691, 541, 533, 691, 548, 526, 549, 432, 406, 550, 527, 439, 528, 691, 529, 552, 537, 538, 539, 691, 558, 559, 560, 541, 691, 540, 548, 562, 549, 691, 568, 550, 551, 569, 528, 561, 570, 552, 691, 572, 578, 579, 558, 559, 560, 580, 691, 540, 582, 562, 691, 542, 568, 588, 551, 569, 553, 561, 570, 589, 581, 572, 578, 579, 571, 583, 691, 584, 580, 600, 584, 582, 584, 586, 691, 586, 588, 573, 583, 602, 584, 591, 589, 581, 608, 584, 571, 584, 586, 609, 586, 600, 610, 691, 612, 691, 601, 618, 619, 620, 622, 602, 691, 603, 681, 628, 608, 628, 611, 691, 631, 609, 632, 629, 593, 610, 691, 612, 601, 618, 619, 594, 620, 622, 621, 691, 691, 596, 633, 691, 633, 611, 691, 636, 613, 637, 634, 639, 628, 637, 628, 631, 623, 632, 691, 691, 629, 621, 631, 633, 632, 633, 636, 639, 637, 637, 639, 634, 637, 640, 647, 691, 691, 680, 691, 679, 678, 676, 675, 674, 652, 673, 671, 670, 667, 669, 662, 668, 666, 665, 677, 672, 664, 663, 661, 660, 659, 658, 656, 655, 654, 653, 651, 650, 649, 648, 691, 691, 646, 686, 689, 691, 645, 644, 643, 642, 641, 627, 626, 682, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 127, 625, 624, 617, 127, 127, 127, 129, 616, 615, 614, 129, 129, 129, 129, 129, 129, 129, 129, 131, 607, 606, 605, 604, 599, 131, 131, 148, 148, 151, 151, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 157, 157, 598, 597, 595, 157, 592, 590, 157, 157, 157, 157, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 167, 167, 577, 576, 575, 167, 167, 574, 167, 167, 167, 167, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 178, 178, 184, 567, 566, 565, 184, 184, 184, 186, 564, 557, 556, 186, 186, 186, 186, 186, 186, 186, 188, 555, 554, 547, 546, 545, 188, 188, 195, 195, 231, 544, 543, 195, 536, 535, 534, 195, 195, 201, 532, 531, 524, 523, 522, 201, 201, 206, 206, 231, 206, 206, 206, 206, 206, 206, 206, 206, 206, 216, 216, 221, 221, 520, 221, 221, 221, 221, 221, 221, 221, 221, 221, 230, 519, 509, 508, 230, 230, 230, 232, 251, 251, 504, 232, 232, 232, 232, 232, 232, 232, 245, 245, 231, 231, 245, 245, 245, 245, 245, 245, 245, 245, 247, 247, 497, 493, 247, 247, 247, 247, 247, 247, 247, 247, 250, 490, 487, 231, 250, 250, 250, 252, 468, 460, 459, 252, 252, 252, 252, 252, 252, 252, 252, 256, 256, 458, 231, 256, 256, 256, 256, 256, 256, 256, 256, 257, 231, 442, 435, 257, 257, 257, 259, 431, 427, 426, 259, 259, 259, 259, 259, 259, 259, 259, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, 630, 630, 425, 630, 630, 630, 630, 630, 630, 630, 630, 630, 635, 635, 231, 635, 635, 635, 635, 635, 635, 635, 635, 635, 638, 638, 231, 638, 638, 638, 638, 638, 638, 638, 638, 638, 231, 231, 400, 388, 387, 386, 382, 231, 350, 349, 348, 343, 284, 324, 318, 315, 312, 311, 310, 309, 258, 308, 258, 304, 251, 303, 251, 248, 300, 298, 231, 285, 231, 284, 691, 275, 264, 263, 260, 258, 253, 251, 185, 249, 185, 181, 248, 246, 242, 231, 229, 228, 128, 122, 209, 185, 181, 177, 147, 128, 122, 691, 25, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691 } ; static const flex_int32_t yy_chk[1829] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 7, 7, 8, 8, 32, 7, 32, 8, 29, 29, 42, 42, 47, 47, 50, 50, 689, 1, 1, 1, 0, 1, 53, 53, 11, 11, 11, 11, 21, 21, 116, 11, 37, 11, 37, 57, 57, 21, 116, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 11, 12, 12, 12, 12, 19, 19, 21, 12, 63, 12, 63, 37, 65, 65, 135, 19, 2, 2, 2, 135, 2, 20, 20, 138, 22, 22, 38, 38, 38, 67, 12, 687, 20, 22, 19, 70, 70, 138, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 20, 3, 74, 90, 74, 67, 22, 75, 75, 38, 78, 78, 81, 81, 85, 85, 96, 96, 577, 3, 3, 3, 91, 3, 91, 92, 92, 92, 109, 109, 90, 93, 90, 90, 103, 106, 103, 114, 114, 119, 119, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 226, 4, 91, 577, 93, 92, 93, 93, 106, 218, 120, 106, 120, 124, 124, 136, 93, 133, 133, 4, 4, 4, 137, 4, 136, 139, 136, 226, 137, 136, 140, 218, 140, 137, 684, 141, 139, 141, 143, 143, 143, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 144, 5, 146, 146, 150, 150, 154, 154, 144, 330, 140, 156, 156, 159, 159, 141, 164, 164, 143, 5, 5, 5, 330, 5, 169, 169, 174, 174, 176, 176, 180, 180, 183, 183, 190, 190, 209, 192, 209, 192, 683, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 219, 6, 194, 125, 237, 125, 193, 193, 193, 225, 194, 197, 197, 205, 205, 224, 125, 192, 237, 6, 6, 6, 219, 6, 208, 208, 213, 213, 125, 209, 125, 234, 236, 225, 227, 224, 236, 234, 125, 235, 193, 6, 9, 9, 9, 9, 339, 9, 9, 9, 125, 9, 125, 243, 235, 225, 238, 224, 227, 239, 238, 241, 239, 339, 243, 241, 553, 238, 244, 244, 233, 9, 9, 9, 233, 9, 10, 10, 10, 10, 227, 10, 10, 10, 255, 10, 254, 233, 240, 240, 254, 292, 248, 248, 293, 255, 292, 261, 293, 261, 240, 553, 266, 254, 267, 10, 10, 10, 270, 10, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 248, 13, 266, 271, 267, 273, 274, 275, 270, 276, 277, 279, 297, 282, 302, 302, 286, 297, 680, 13, 13, 13, 261, 13, 280, 271, 281, 273, 274, 275, 286, 276, 277, 279, 282, 299, 280, 281, 379, 379, 299, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 283, 14, 282, 287, 280, 281, 288, 289, 290, 294, 291, 283, 289, 296, 288, 289, 290, 287, 294, 14, 14, 14, 291, 14, 295, 305, 306, 307, 382, 296, 382, 295, 307, 283, 313, 314, 315, 316, 317, 305, 306, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 313, 314, 315, 316, 317, 318, 319, 320, 368, 321, 322, 323, 324, 321, 325, 331, 334, 15, 15, 15, 326, 15, 334, 335, 345, 368, 331, 318, 319, 335, 320, 321, 322, 323, 324, 321, 325, 345, 326, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 336, 332, 337, 126, 342, 126, 326, 328, 337, 214, 342, 214, 332, 340, 336, 327, 126, 16, 16, 16, 338, 16, 214, 340, 346, 338, 446, 341, 126, 328, 126, 327, 341, 328, 214, 346, 214, 352, 126, 16, 17, 17, 17, 17, 214, 17, 17, 17, 17, 17, 126, 328, 126, 446, 327, 328, 214, 344, 214, 344, 352, 347, 329, 347, 351, 354, 355, 370, 353, 17, 17, 17, 353, 17, 18, 18, 18, 18, 329, 18, 18, 18, 18, 18, 357, 370, 351, 354, 372, 355, 353, 344, 378, 372, 353, 347, 378, 397, 356, 397, 358, 329, 356, 18, 18, 18, 357, 18, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 356, 23, 358, 359, 356, 361, 362, 381, 363, 364, 371, 380, 363, 365, 380, 381, 377, 367, 502, 23, 23, 23, 377, 23, 406, 359, 406, 361, 371, 362, 363, 452, 364, 415, 363, 383, 383, 383, 415, 365, 367, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 215, 24, 215, 217, 222, 217, 222, 365, 367, 223, 502, 223, 366, 215, 416, 384, 217, 222, 389, 24, 24, 24, 223, 24, 452, 215, 369, 215, 217, 222, 217, 222, 366, 384, 223, 215, 223, 385, 217, 222, 389, 24, 35, 390, 223, 391, 369, 215, 416, 215, 217, 222, 217, 222, 366, 385, 223, 265, 223, 265, 400, 269, 428, 269, 428, 390, 575, 391, 369, 35, 265, 35, 35, 393, 269, 394, 35, 35, 395, 398, 35, 399, 265, 400, 265, 35, 269, 401, 269, 35, 39, 402, 265, 403, 405, 393, 269, 394, 408, 679, 395, 398, 575, 399, 265, 417, 265, 407, 269, 401, 269, 410, 409, 402, 429, 403, 405, 39, 407, 39, 39, 417, 410, 408, 39, 39, 409, 418, 39, 39, 411, 411, 652, 39, 412, 412, 429, 39, 418, 430, 407, 419, 419, 431, 410, 408, 420, 420, 420, 409, 422, 422, 422, 423, 423, 424, 424, 432, 433, 432, 434, 430, 435, 436, 438, 436, 431, 439, 440, 439, 441, 442, 444, 443, 444, 445, 447, 445, 652, 448, 433, 448, 434, 449, 449, 435, 438, 450, 450, 460, 440, 436, 441, 453, 442, 443, 463, 454, 453, 466, 444, 447, 454, 445, 455, 455, 456, 456, 457, 457, 458, 467, 458, 436, 461, 464, 461, 464, 463, 468, 473, 466, 444, 447, 469, 445, 471, 472, 474, 472, 475, 476, 477, 467, 477, 482, 460, 483, 483, 482, 489, 468, 461, 464, 473, 478, 469, 478, 471, 476, 474, 486, 490, 486, 491, 475, 492, 518, 493, 494, 477, 495, 489, 496, 461, 464, 473, 497, 498, 500, 678, 476, 501, 478, 490, 499, 491, 475, 492, 477, 493, 494, 477, 495, 506, 496, 499, 510, 511, 497, 498, 500, 478, 506, 512, 478, 513, 501, 486, 514, 515, 518, 516, 517, 521, 525, 526, 527, 499, 510, 511, 528, 529, 521, 530, 537, 512, 538, 513, 501, 539, 514, 515, 516, 540, 517, 541, 525, 526, 527, 542, 548, 549, 550, 529, 551, 528, 537, 552, 538, 563, 558, 539, 540, 559, 516, 551, 560, 541, 561, 562, 568, 569, 548, 549, 550, 570, 571, 528, 572, 552, 581, 530, 558, 578, 540, 559, 542, 551, 560, 579, 571, 562, 568, 569, 561, 573, 593, 573, 570, 590, 574, 572, 574, 576, 591, 576, 578, 563, 583, 592, 583, 581, 579, 571, 598, 584, 561, 584, 586, 599, 586, 590, 600, 601, 602, 603, 591, 608, 609, 610, 612, 592, 613, 593, 676, 618, 598, 618, 601, 611, 619, 599, 619, 618, 583, 600, 623, 602, 591, 608, 609, 584, 610, 612, 611, 647, 662, 586, 620, 640, 620, 601, 657, 621, 603, 621, 620, 622, 628, 622, 628, 631, 613, 631, 667, 672, 628, 611, 632, 633, 632, 633, 636, 637, 636, 637, 639, 633, 639, 623, 640, 677, 682, 675, 686, 674, 673, 671, 670, 669, 647, 668, 666, 665, 662, 664, 657, 663, 661, 660, 672, 667, 659, 658, 656, 655, 654, 653, 651, 650, 649, 648, 644, 643, 642, 641, 638, 635, 634, 682, 686, 630, 629, 627, 626, 625, 624, 617, 616, 677, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 704, 615, 614, 607, 704, 704, 704, 705, 606, 605, 604, 705, 705, 705, 705, 705, 705, 705, 705, 706, 597, 596, 595, 594, 589, 706, 706, 707, 707, 708, 708, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 710, 710, 588, 587, 585, 710, 582, 580, 710, 710, 710, 710, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 712, 712, 567, 566, 565, 712, 712, 564, 712, 712, 712, 712, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 714, 714, 715, 557, 556, 555, 715, 715, 715, 716, 554, 547, 545, 716, 716, 716, 716, 716, 716, 716, 717, 544, 543, 536, 535, 534, 717, 717, 718, 718, 533, 532, 531, 718, 524, 523, 522, 718, 718, 719, 520, 519, 509, 508, 507, 719, 719, 720, 720, 505, 720, 720, 720, 720, 720, 720, 720, 720, 720, 721, 721, 722, 722, 504, 722, 722, 722, 722, 722, 722, 722, 722, 722, 723, 503, 488, 487, 723, 723, 723, 724, 485, 484, 481, 724, 724, 724, 724, 724, 724, 724, 725, 725, 480, 479, 725, 725, 725, 725, 725, 725, 725, 725, 726, 726, 470, 465, 726, 726, 726, 726, 726, 726, 726, 726, 727, 462, 459, 451, 727, 727, 727, 728, 437, 427, 426, 728, 728, 728, 728, 728, 728, 728, 728, 729, 729, 425, 414, 729, 729, 729, 729, 729, 729, 729, 729, 730, 413, 404, 396, 730, 730, 730, 731, 392, 388, 387, 731, 731, 731, 731, 731, 731, 731, 731, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 732, 733, 733, 386, 733, 733, 733, 733, 733, 733, 733, 733, 733, 734, 734, 376, 734, 734, 734, 734, 734, 734, 734, 734, 734, 735, 735, 375, 735, 735, 735, 735, 735, 735, 735, 735, 735, 374, 373, 360, 350, 349, 348, 343, 333, 312, 311, 310, 298, 284, 278, 272, 268, 264, 263, 262, 260, 259, 258, 257, 253, 252, 251, 250, 247, 246, 242, 232, 231, 230, 229, 221, 220, 211, 210, 202, 201, 189, 188, 186, 185, 184, 181, 171, 166, 142, 131, 129, 128, 127, 122, 115, 88, 83, 79, 43, 33, 27, 25, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691 } ; static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; extern int yy_flex_debug; int yy_flex_debug = 0; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected static int yy_more_flag = 0; static int yy_more_len = 0; #define yymore() ((yy_more_flag) = 1) #define YY_MORE_ADJ (yy_more_len) #define YY_RESTORE_YY_MORE_OFFSET char *yytext; #line 1 "VPreLex.l" #line 6 "VPreLex.l" /****************************************************************************** * DESCRIPTION: Verilog Preprocessor Lexer * * This file is part of Verilog-Perl. * * Author: Wilson Snyder * * Code available from: https://www.veripool.org/verilog-perl * ****************************************************************************** * * Copyright 2000-2021 by Wilson Snyder. This program is free software; * you can redistribute it and/or modify it under the terms of either the GNU * Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * ***************************************************************************** * Do not use Flex in C++ mode. It has bugs with yyunput() which result in * lost characters. *****************************************************************************/ #include "VPreProc.h" #include "VPreLex.h" #include #include #include #include // Flex 2.5.35 has compile warning in ECHO, so we'll default our own rule #define ECHO yyerrorf("Missing VPreLex.l rule: ECHO rule invoked in state %d: %s", YY_START, yytext); VPreLex* VPreLex::s_currentLexp = NULL; // Current lexing point #define LEXP VPreLex::s_currentLexp #define linenoInc() { LEXP->linenoInc(); } static bool pedantic() { return LEXP->m_pedantic; } static bool keepWhitespace() { return LEXP->m_keepWhitespace; } static void appendDefValue(const char* t, size_t l) { LEXP->appendDefValue(t,l); } void yyerror(char* msg) { LEXP->curFilelinep()->error(msg); } #define YY_INPUT(buf,result,max_size) \ result = LEXP->inputToLex(buf,max_size); // Accessors, because flex keeps changing the type of yyleng char* yyourtext() { return yytext; } size_t yyourleng() { return (size_t)yyleng; } void yyourtext(const char* textp, size_t size) { yytext=(char*)textp; yyleng=size; } void yyerrorf(const char* format, ...) { char msg[1024]; va_list ap; va_start(ap,format); vsprintf(msg,format,ap); va_end(ap); yyerror(msg); } static bool isWhitespace(const std::string& str) { for (std::string::const_iterator pos = str.begin(); pos != str.end(); ++pos) { if (!isspace(*pos)) return false; } return true; } /**********************************************************************/ #line 1421 "VPreLex_pretmp.cpp" /* drop: Drop Ctrl-Z - can't pass thru or may EOF the output too soon */ /* Where we use symb/symbdef, we must also look for a `` join */ /* Note in the preprocessor \ESCaped is *not* always special; mantis1537/bug441 */ /* Case insensitive; unfortunately ?i: isn't in flex 2.5.4 which is popular */ #line 119 "VPreLex.l" /**************************************************************/ #line 1429 "VPreLex_pretmp.cpp" #define INITIAL 0 #define CMTMODE 1 #define STRMODE 2 #define DEFFPAR 3 #define DEFFORM 4 #define DEFVAL 5 #define DEFCMT 6 #define STRIFY 7 #define ARGMODE 8 #define INCMODE 9 #define PRTMODE 10 #define OFFMODE 11 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ #include #endif #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * #endif static int yy_init_globals ( void ); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ int yylex_destroy ( void ); int yyget_debug ( void ); void yyset_debug ( int debug_flag ); YY_EXTRA_TYPE yyget_extra ( void ); void yyset_extra ( YY_EXTRA_TYPE user_defined ); FILE *yyget_in ( void ); void yyset_in ( FILE * _in_str ); FILE *yyget_out ( void ); void yyset_out ( FILE * _out_str ); int yyget_leng ( void ); char *yyget_text ( void ); int yyget_lineno ( void ); void yyset_lineno ( int _line_number ); /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int yywrap ( void ); #else extern int yywrap ( void ); #endif #endif #ifndef YY_NO_UNPUT static void yyunput ( int c, char *buf_ptr ); #endif #ifndef yytext_ptr static void yy_flex_strncpy ( char *, const char *, int ); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen ( const char * ); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput ( void ); #else static int input ( void ); #endif #endif static int yy_start_stack_ptr = 0; static int yy_start_stack_depth = 0; static int *yy_start_stack = NULL; static void yy_push_state ( int _new_state ); static void yy_pop_state ( void ); static int yy_top_state ( void ); /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k */ #define YY_READ_BUF_SIZE 16384 #else #define YY_READ_BUF_SIZE 8192 #endif /* __ia64__ */ #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ int n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else \ { \ errno=0; \ while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \ { \ if( errno != EINTR) \ { \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ break; \ } \ errno=0; \ clearerr(yyin); \ } \ }\ \ #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif /* end tables serialization structures and prototypes */ /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 extern int yylex (void); #define YY_DECL int yylex (void) #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK /*LINTED*/break; #endif #define YY_RULE_SETUP \ if ( yyleng > 0 ) \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \ (yytext[yyleng - 1] == '\n'); \ YY_USER_ACTION /** The main scanner function which does all the work. */ YY_DECL { yy_state_type yy_current_state; char *yy_cp, *yy_bp; int yy_act; if ( !(yy_init) ) { (yy_init) = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! (yy_start) ) (yy_start) = 1; /* first start state */ if ( ! yyin ) yyin = stdin; if ( ! yyout ) yyout = stdout; if ( ! YY_CURRENT_BUFFER ) { yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer( yyin, YY_BUF_SIZE ); } yy_load_buffer_state( ); } { #line 120 "VPreLex.l" #line 1673 "VPreLex_pretmp.cpp" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { (yy_more_len) = 0; if ( (yy_more_flag) ) { (yy_more_len) = (int) ((yy_c_buf_p) - (yytext_ptr)); (yy_more_flag) = 0; } yy_cp = (yy_c_buf_p); /* Support of yytext. */ *yy_cp = (yy_hold_char); /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = (yy_start); yy_current_state += YY_AT_BOL(); yy_match: do { YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 692 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; ++yy_cp; } while ( yy_base[yy_current_state] != 1774 ); yy_find_action: yy_act = yy_accept[yy_current_state]; if ( yy_act == 0 ) { /* have to back up */ yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); yy_act = yy_accept[yy_current_state]; } YY_DO_BEFORE_ACTION; do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = (yy_hold_char); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); goto yy_find_action; case 1: YY_RULE_SETUP #line 122 "VPreLex.l" { } YY_BREAK case 2: /* rule 2 can match eol */ YY_RULE_SETUP #line 123 "VPreLex.l" { LEXP->lineDirective(yytext); return(VP_LINE); } YY_BREAK /* Special directives we recognize */ case 3: YY_RULE_SETUP #line 127 "VPreLex.l" { return(VP_DEFINE); } YY_BREAK case 4: YY_RULE_SETUP #line 128 "VPreLex.l" { return(VP_ELSE); } YY_BREAK case 5: YY_RULE_SETUP #line 129 "VPreLex.l" { return(VP_ELSIF); } YY_BREAK case 6: YY_RULE_SETUP #line 130 "VPreLex.l" { return(VP_ENDIF); } YY_BREAK case 7: YY_RULE_SETUP #line 131 "VPreLex.l" { return(VP_IFDEF); } YY_BREAK case 8: YY_RULE_SETUP #line 132 "VPreLex.l" { return(VP_IFNDEF); } YY_BREAK case 9: YY_RULE_SETUP #line 133 "VPreLex.l" { return(VP_INCLUDE); } YY_BREAK case 10: YY_RULE_SETUP #line 134 "VPreLex.l" { return(VP_UNDEF); } YY_BREAK case 11: YY_RULE_SETUP #line 135 "VPreLex.l" { return(VP_UNDEFINEALL); } YY_BREAK case 12: YY_RULE_SETUP #line 136 "VPreLex.l" { if (!pedantic()) return (VP_ERROR); else return(VP_DEFREF); } YY_BREAK case 13: YY_RULE_SETUP #line 137 "VPreLex.l" { static string rtnfile; rtnfile = '"'; rtnfile += LEXP->curFilelinep()->filename(); rtnfile += '"'; yytext=(char*)rtnfile.c_str(); yyleng = rtnfile.length(); return (VP_STRING); } YY_BREAK case 14: YY_RULE_SETUP #line 141 "VPreLex.l" { static char buf[10]; sprintf(buf, "%d",LEXP->curFilelinep()->lineno()); yytext = buf; yyleng = strlen(yytext); return (VP_TEXT); } YY_BREAK /* Pass-through strings */ case 15: YY_RULE_SETUP #line 147 "VPreLex.l" { yy_push_state(STRMODE); yymore(); } YY_BREAK case YY_STATE_EOF(STRMODE): #line 148 "VPreLex.l" { linenoInc(); yyerrorf("EOF in unterminated string"); yyleng=0; yyterminate(); } YY_BREAK case 16: /* rule 16 can match eol */ YY_RULE_SETUP #line 149 "VPreLex.l" { linenoInc(); yyerrorf("Unterminated string"); BEGIN(INITIAL); } YY_BREAK case 17: YY_RULE_SETUP #line 150 "VPreLex.l" { yymore(); } YY_BREAK case 18: /* rule 18 can match eol */ YY_RULE_SETUP #line 151 "VPreLex.l" { yymore(); } YY_BREAK case 19: /* rule 19 can match eol */ YY_RULE_SETUP #line 152 "VPreLex.l" { linenoInc(); yymore(); } YY_BREAK case 20: YY_RULE_SETUP #line 153 "VPreLex.l" { yymore(); } YY_BREAK case 21: YY_RULE_SETUP #line 154 "VPreLex.l" { yy_pop_state(); if (LEXP->m_parenLevel || LEXP->m_defQuote) { LEXP->m_defQuote=false; appendDefValue(yytext,yyleng); yyleng=0; } else return (VP_STRING); } YY_BREAK /* Stringification */ case 22: YY_RULE_SETUP #line 159 "VPreLex.l" { yy_push_state(STRIFY); return VP_STRIFY; } YY_BREAK case YY_STATE_EOF(STRIFY): #line 160 "VPreLex.l" { linenoInc(); yyerrorf("EOF in unterminated '\""); yyleng=0; yyterminate(); } YY_BREAK case 23: YY_RULE_SETUP #line 161 "VPreLex.l" { return VP_BACKQUOTE; } YY_BREAK case 24: YY_RULE_SETUP #line 162 "VPreLex.l" { yy_push_state(STRMODE); yymore(); } YY_BREAK case 25: YY_RULE_SETUP #line 163 "VPreLex.l" { yy_pop_state(); return VP_STRIFY; } YY_BREAK case 26: YY_RULE_SETUP #line 164 "VPreLex.l" { return (VP_SYMBOL); } YY_BREAK case 27: YY_RULE_SETUP #line 165 "VPreLex.l" { yyleng-=2; return (VP_SYMBOL_JOIN); } YY_BREAK case 28: YY_RULE_SETUP #line 166 "VPreLex.l" { return (VP_DEFREF); } YY_BREAK case 29: YY_RULE_SETUP #line 167 "VPreLex.l" { yyleng-=2; return (VP_DEFREF_JOIN); } YY_BREAK case 30: YY_RULE_SETUP #line 168 "VPreLex.l" { yyleng-=2; return (VP_JOIN); } YY_BREAK case 31: /* rule 31 can match eol */ YY_RULE_SETUP #line 169 "VPreLex.l" { linenoInc(); yytext=(char*)"\n"; yyleng=1; return(VP_WHITE); } YY_BREAK case 32: YY_RULE_SETUP #line 170 "VPreLex.l" { return (VP_WHITE); } YY_BREAK case 33: YY_RULE_SETUP #line 171 "VPreLex.l" { } YY_BREAK case 34: YY_RULE_SETUP #line 172 "VPreLex.l" { } YY_BREAK case 35: YY_RULE_SETUP #line 173 "VPreLex.l" { return (VP_TEXT); } YY_BREAK /* Protected blocks */ case 36: YY_RULE_SETUP #line 176 "VPreLex.l" { yy_push_state(PRTMODE); yymore(); } YY_BREAK case 37: YY_RULE_SETUP #line 177 "VPreLex.l" { yy_push_state(PRTMODE); yymore(); } YY_BREAK case 38: YY_RULE_SETUP #line 178 "VPreLex.l" { yy_push_state(PRTMODE); yymore(); } YY_BREAK case YY_STATE_EOF(PRTMODE): #line 179 "VPreLex.l" { linenoInc(); yyerrorf("EOF in `protected"); yyleng=0; yyterminate(); } YY_BREAK case 39: /* rule 39 can match eol */ YY_RULE_SETUP #line 180 "VPreLex.l" { linenoInc(); return VP_TEXT; } YY_BREAK case 40: YY_RULE_SETUP #line 181 "VPreLex.l" { yymore(); } YY_BREAK case 41: YY_RULE_SETUP #line 182 "VPreLex.l" { yy_pop_state(); return VP_TEXT; } YY_BREAK case 42: YY_RULE_SETUP #line 183 "VPreLex.l" { yy_pop_state(); return VP_TEXT; } YY_BREAK case 43: YY_RULE_SETUP #line 184 "VPreLex.l" { yy_pop_state(); return VP_TEXT; } YY_BREAK /* Pass-through include <> filenames */ case YY_STATE_EOF(INCMODE): #line 187 "VPreLex.l" { linenoInc(); yyerrorf("EOF in unterminated include filename"); yyleng=0; yyterminate(); } YY_BREAK case 44: /* rule 44 can match eol */ YY_RULE_SETUP #line 188 "VPreLex.l" { linenoInc(); yyerrorf("Unterminated include filename"); BEGIN(INITIAL); } YY_BREAK case 45: /* rule 45 can match eol */ YY_RULE_SETUP #line 189 "VPreLex.l" { yymore(); } YY_BREAK case 46: YY_RULE_SETUP #line 190 "VPreLex.l" { yymore(); } YY_BREAK case 47: YY_RULE_SETUP #line 191 "VPreLex.l" { yy_pop_state(); return VP_STRING; } YY_BREAK /* Reading definition formal parenthesis (or not) to begin formal arguments */ /* Note '(' must IMMEDIATELY follow definition name */ case 48: YY_RULE_SETUP #line 195 "VPreLex.l" { appendDefValue("(",1); LEXP->m_formalLevel=1; BEGIN(DEFFORM); } YY_BREAK case 49: /* rule 49 can match eol */ YY_RULE_SETUP #line 196 "VPreLex.l" { yy_pop_state(); unput('\n'); yyleng=0; return VP_DEFFORM; } /* DEFVAL will later grab the return */ YY_BREAK case YY_STATE_EOF(DEFFPAR): #line 197 "VPreLex.l" { yy_pop_state(); return VP_DEFFORM; } /* empty formals */ YY_BREAK case 50: YY_RULE_SETUP #line 198 "VPreLex.l" { yy_pop_state(); unput(yytext[yyleng-1]); yyleng=0; return VP_DEFFORM; } /* empty formals */ YY_BREAK /* Reading definition formals (declaration of a define) */ case 51: YY_RULE_SETUP #line 201 "VPreLex.l" { appendDefValue(yytext,yyleng); yyleng=0; ++LEXP->m_formalLevel; } YY_BREAK case 52: YY_RULE_SETUP #line 202 "VPreLex.l" { appendDefValue(yytext,yyleng); yyleng=0; if ((--LEXP->m_formalLevel)==0) { yy_pop_state(); return VP_DEFFORM; } } YY_BREAK case 53: YY_RULE_SETUP #line 203 "VPreLex.l" { yy_push_state(CMTMODE); yymore(); } YY_BREAK case 54: YY_RULE_SETUP #line 204 "VPreLex.l" { return (VP_COMMENT);} YY_BREAK case 55: YY_RULE_SETUP #line 205 "VPreLex.l" { } YY_BREAK case YY_STATE_EOF(DEFFORM): #line 206 "VPreLex.l" { linenoInc(); yy_pop_state(); yyerrorf("Unterminated ( in define formal arguments."); yyleng=0; return VP_DEFFORM; } YY_BREAK case 56: /* rule 56 can match eol */ YY_RULE_SETUP #line 207 "VPreLex.l" { linenoInc(); appendDefValue((char*)"\n",1); } /* Include return so can maintain output line count */ YY_BREAK case 57: /* rule 57 can match eol */ YY_RULE_SETUP #line 208 "VPreLex.l" { linenoInc(); appendDefValue((char*)"\\\n",2); } /* Include return so can maintain output line count */ YY_BREAK case 58: YY_RULE_SETUP #line 209 "VPreLex.l" { LEXP->m_defQuote=true; yy_push_state(STRMODE); yymore(); } /* Legal only in default values */ YY_BREAK case 59: YY_RULE_SETUP #line 210 "VPreLex.l" { appendDefValue(yytext,yyleng); } /* Maybe illegal, otherwise in default value */ YY_BREAK case 60: YY_RULE_SETUP #line 211 "VPreLex.l" { appendDefValue(yytext,yyleng); } /* Maybe illegal, otherwise in default value */ YY_BREAK case 61: YY_RULE_SETUP #line 212 "VPreLex.l" { LEXP->m_formalLevel++; appendDefValue(yytext,yyleng); } YY_BREAK case 62: YY_RULE_SETUP #line 213 "VPreLex.l" { LEXP->m_formalLevel--; appendDefValue(yytext,yyleng); } YY_BREAK case 63: #line 215 "VPreLex.l" case 64: #line 216 "VPreLex.l" case 65: YY_RULE_SETUP #line 216 "VPreLex.l" { appendDefValue(yytext,yyleng); } YY_BREAK /* Reading definition value (declaration of a define's text) */ case 66: YY_RULE_SETUP #line 219 "VPreLex.l" { LEXP->m_defCmtSlash=false; yy_push_state(DEFCMT); yymore(); } /* Special comment parser */ YY_BREAK case 67: /* rule 67 can match eol */ YY_RULE_SETUP #line 220 "VPreLex.l" { linenoInc(); appendDefValue((char*)"\n",1); } /* Spec says // not part of define value */ YY_BREAK case 68: YY_RULE_SETUP #line 221 "VPreLex.l" { return (VP_COMMENT);} YY_BREAK case 69: YY_RULE_SETUP #line 222 "VPreLex.l" { } YY_BREAK case YY_STATE_EOF(DEFVAL): #line 223 "VPreLex.l" { linenoInc(); yy_pop_state(); yytext=(char*)"\n"; yyleng=1; return (VP_DEFVALUE); } /* Technically illegal, but people complained */ YY_BREAK case 70: /* rule 70 can match eol */ YY_RULE_SETUP #line 224 "VPreLex.l" { linenoInc(); yy_pop_state(); yytext=(char*)"\n"; yyleng=1; return (VP_DEFVALUE); } YY_BREAK case 71: /* rule 71 can match eol */ YY_RULE_SETUP #line 225 "VPreLex.l" { linenoInc(); appendDefValue((char*)"\\\n",2); } /* Return, AND \ is part of define value */ YY_BREAK case 72: YY_RULE_SETUP #line 226 "VPreLex.l" { LEXP->m_defQuote=true; yy_push_state(STRMODE); yymore(); } YY_BREAK case 73: #line 228 "VPreLex.l" case 74: #line 229 "VPreLex.l" case 75: YY_RULE_SETUP #line 229 "VPreLex.l" { appendDefValue(yytext,yyleng); } YY_BREAK /* Comments inside define values - if embedded get added to define value per spec */ /* - if no \{crnl} ending then the comment belongs to the next line, as a non-embedded comment */ /* - if all but (say) 3rd line is missing \ then it's indeterminate */ case 76: YY_RULE_SETUP #line 234 "VPreLex.l" { yy_pop_state(); appendDefValue(yytext,yyleng); } YY_BREAK case 77: /* rule 77 can match eol */ YY_RULE_SETUP #line 235 "VPreLex.l" { linenoInc(); LEXP->m_defCmtSlash=true; appendDefValue(yytext,yyleng-2); appendDefValue((char*)"\n",1); } /* Return but not \ */ YY_BREAK case 78: /* rule 78 can match eol */ YY_RULE_SETUP #line 237 "VPreLex.l" { linenoInc(); yymore(); if (LEXP->m_defCmtSlash) yyerrorf("One line of /* ... */ is missing \\ before newline"); BEGIN(CMTMODE); } YY_BREAK case 79: YY_RULE_SETUP #line 239 "VPreLex.l" { yymore(); } YY_BREAK case 80: YY_RULE_SETUP #line 240 "VPreLex.l" { yymore(); } YY_BREAK case YY_STATE_EOF(DEFCMT): #line 241 "VPreLex.l" { yyerrorf("EOF in '/* ... */' block comment\n"); yyleng=0; yyterminate(); } YY_BREAK /* Define arguments (use of a define) */ case 81: YY_RULE_SETUP #line 244 "VPreLex.l" { yy_push_state(CMTMODE); yymore(); } YY_BREAK case 82: YY_RULE_SETUP #line 245 "VPreLex.l" { return (VP_COMMENT);} YY_BREAK case 83: YY_RULE_SETUP #line 246 "VPreLex.l" { } YY_BREAK case YY_STATE_EOF(ARGMODE): #line 247 "VPreLex.l" { yyerrorf("EOF in define argument list\n"); yyleng = 0; yyterminate(); } YY_BREAK case 84: /* rule 84 can match eol */ YY_RULE_SETUP #line 248 "VPreLex.l" { linenoInc(); yytext=(char*)"\n"; yyleng=1; return(VP_WHITE); } YY_BREAK case 85: YY_RULE_SETUP #line 249 "VPreLex.l" { yy_push_state(STRMODE); yymore(); } YY_BREAK case 86: YY_RULE_SETUP #line 250 "VPreLex.l" { appendDefValue(yytext,yyleng); } /* Literal text */ YY_BREAK case 87: YY_RULE_SETUP #line 251 "VPreLex.l" { yy_push_state(STRIFY); return(VP_STRIFY); } YY_BREAK case 88: YY_RULE_SETUP #line 252 "VPreLex.l" { LEXP->m_parenLevel++; appendDefValue(yytext,yyleng); } YY_BREAK case 89: YY_RULE_SETUP #line 253 "VPreLex.l" { LEXP->m_parenLevel--; appendDefValue(yytext,yyleng); } YY_BREAK case 90: YY_RULE_SETUP #line 254 "VPreLex.l" { LEXP->m_parenLevel++; // Note paren level 0 means before "(" of starting args // Level 1 means "," between arguments // Level 2+ means one argument's internal () if (LEXP->m_parenLevel == 1) { // Starting ( if (!isWhitespace(LEXP->m_defValue)) { yyerrorf("Illegal text before '(' that starts define arguments: '%s'", LEXP->m_defValue.c_str()); } } if (LEXP->m_parenLevel>1) { appendDefValue(yytext,yyleng); } else { return (VP_TEXT); }} YY_BREAK case 91: YY_RULE_SETUP #line 269 "VPreLex.l" { LEXP->m_parenLevel--; if (LEXP->m_parenLevel>0) { appendDefValue(yytext,yyleng); } else { yy_pop_state(); return (VP_DEFARG); }} YY_BREAK case 92: YY_RULE_SETUP #line 275 "VPreLex.l" { if (LEXP->m_parenLevel>1) { appendDefValue(yytext,yyleng); } else { yy_pop_state(); return (VP_DEFARG); }} YY_BREAK case 93: YY_RULE_SETUP #line 280 "VPreLex.l" { appendDefValue(yytext,yyleng); } /* defref in defref - outer macro expands first */ YY_BREAK case 94: YY_RULE_SETUP #line 281 "VPreLex.l" { appendDefValue(yytext,yyleng); } /* defref in defref - outer macro expands first */ YY_BREAK case 95: YY_RULE_SETUP #line 282 "VPreLex.l" { appendDefValue(yytext,yyleng); } /* defref in defref - outer macro expands first */ YY_BREAK case 96: #line 284 "VPreLex.l" case 97: YY_RULE_SETUP #line 284 "VPreLex.l" { appendDefValue(yytext,yyleng); } YY_BREAK /* Translate offs. Note final newline not included */ case 98: YY_RULE_SETUP #line 287 "VPreLex.l" { if (LEXP->m_synthesis) { yy_push_state(OFFMODE); } return(VP_COMMENT); } YY_BREAK case 99: YY_RULE_SETUP #line 290 "VPreLex.l" { if (LEXP->m_synthesis) { yy_pop_state(); } return(VP_COMMENT); } YY_BREAK case 100: /* rule 100 can match eol */ YY_RULE_SETUP #line 293 "VPreLex.l" { linenoInc(); yymore(); } /* Need to end the / / */ YY_BREAK case 101: YY_RULE_SETUP #line 294 "VPreLex.l" { } YY_BREAK case 102: YY_RULE_SETUP #line 295 "VPreLex.l" { } YY_BREAK case YY_STATE_EOF(OFFMODE): #line 296 "VPreLex.l" { yyerrorf("EOF in '/*synthesis translate_off*/' region\n"); yyleng=0; yyterminate(); } YY_BREAK /* One line comments. Note final newline not included */ case 103: YY_RULE_SETUP #line 299 "VPreLex.l" { return (VP_COMMENT); } YY_BREAK /* C-style comments. */ /**** See also DEFCMT */ case 104: YY_RULE_SETUP #line 303 "VPreLex.l" { yy_push_state(CMTMODE); yymore(); } YY_BREAK case 105: YY_RULE_SETUP #line 304 "VPreLex.l" { yy_pop_state(); return(VP_COMMENT); } YY_BREAK case 106: /* rule 106 can match eol */ YY_RULE_SETUP #line 305 "VPreLex.l" { linenoInc(); yymore(); } YY_BREAK case 107: YY_RULE_SETUP #line 306 "VPreLex.l" { yymore(); } YY_BREAK case 108: YY_RULE_SETUP #line 307 "VPreLex.l" { yymore(); } YY_BREAK case YY_STATE_EOF(CMTMODE): #line 308 "VPreLex.l" { yyerrorf("EOF in '/* ... */' block comment\n"); yyleng=0; yyterminate(); } YY_BREAK /* Define calls */ /* symbdef prevents normal lex rules from making `\`"foo a symbol {`"foo} instead of a BACKQUOTE */ case 109: YY_RULE_SETUP #line 312 "VPreLex.l" { return (VP_DEFREF); } YY_BREAK case 110: YY_RULE_SETUP #line 313 "VPreLex.l" { yyleng-=2; return (VP_DEFREF_JOIN); } YY_BREAK case 111: YY_RULE_SETUP #line 314 "VPreLex.l" { yyleng-=2; return (VP_JOIN); } YY_BREAK /* Generics */ case YY_STATE_EOF(INITIAL): #line 317 "VPreLex.l" { yyterminate(); } /* A "normal" EOF */ YY_BREAK case 112: /* rule 112 can match eol */ YY_RULE_SETUP #line 318 "VPreLex.l" { linenoInc(); yytext=(char*)"\n"; yyleng=1; return(VP_WHITE); } YY_BREAK case 113: YY_RULE_SETUP #line 319 "VPreLex.l" { return (VP_SYMBOL); } YY_BREAK case 114: YY_RULE_SETUP #line 320 "VPreLex.l" { yyleng-=2; return (VP_SYMBOL_JOIN); } YY_BREAK case 115: YY_RULE_SETUP #line 321 "VPreLex.l" { yyleng-=2; return (VP_JOIN); } YY_BREAK case 116: YY_RULE_SETUP #line 322 "VPreLex.l" { } YY_BREAK case 117: YY_RULE_SETUP #line 323 "VPreLex.l" { if (!keepWhitespace()) { yytext=(char*)" "; yyleng=1; } return VP_WHITE; } YY_BREAK case 118: YY_RULE_SETUP #line 324 "VPreLex.l" { } YY_BREAK case 119: YY_RULE_SETUP #line 325 "VPreLex.l" { return (VP_TEXT); } YY_BREAK case 120: /* rule 120 can match eol */ YY_RULE_SETUP #line 327 "VPreLex.l" { yymore(); } /* Prevent hitting ECHO; */ YY_BREAK case 121: YY_RULE_SETUP #line 328 "VPreLex.l" ECHO; YY_BREAK #line 2454 "VPreLex_pretmp.cpp" case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = (yy_hold_char); YY_RESTORE_YY_MORE_OFFSET if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) { /* This was really a NUL. */ yy_state_type yy_next_state; (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = (yytext_ptr) + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++(yy_c_buf_p); yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = (yy_c_buf_p); goto yy_find_action; } } else switch ( yy_get_next_buffer( ) ) { case EOB_ACT_END_OF_FILE: { (yy_did_buffer_switch_on_eof) = 0; if ( yywrap( ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * yytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: (yy_c_buf_p) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of user's declarations */ } /* end of yylex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer (void) { char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; char *source = (yytext_ptr); int number_to_move, i; int ret_val; if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr) - 1); for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; else { int num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; int yy_c_buf_p_offset = (int) ((yy_c_buf_p) - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ yyrealloc( (void *) b->yy_ch_buf, (yy_size_t) (b->yy_buf_size + 2) ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = NULL; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), (yy_n_chars), num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } if ( (yy_n_chars) == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; yyrestart( yyin ); } else { ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc( (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); /* "- 2" to take care of EOB's */ YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2); } (yy_n_chars) += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state (void) { yy_state_type yy_current_state; char *yy_cp; yy_current_state = (yy_start); yy_current_state += YY_AT_BOL(); for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) { YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 692 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) { int yy_is_jam; char *yy_cp = (yy_c_buf_p); YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 692 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; yy_is_jam = (yy_current_state == 691); return yy_is_jam ? 0 : yy_current_state; } #ifndef YY_NO_UNPUT static void yyunput (int c, char * yy_bp ) { char *yy_cp; yy_cp = (yy_c_buf_p); /* undo effects of setting up yytext */ *yy_cp = (yy_hold_char); if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ int number_to_move = (yy_n_chars) + 2; char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; char *source = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = (int) YY_CURRENT_BUFFER_LVALUE->yy_buf_size; if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; (yytext_ptr) = yy_bp; (yy_hold_char) = *yy_cp; (yy_c_buf_p) = yy_cp; } #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void) #else static int input (void) #endif { int c; *(yy_c_buf_p) = (yy_hold_char); if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) /* This was really a NUL. */ *(yy_c_buf_p) = '\0'; else { /* need more input */ int offset = (int) ((yy_c_buf_p) - (yytext_ptr)); ++(yy_c_buf_p); switch ( yy_get_next_buffer( ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ yyrestart( yyin ); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( yywrap( ) ) return 0; if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + offset; break; } } } c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ *(yy_c_buf_p) = '\0'; /* preserve yytext */ (yy_hold_char) = *++(yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n'); return c; } #endif /* ifndef YY_NO_INPUT */ /** Immediately switch to a different input stream. * @param input_file A readable stream. * * @note This function does not reset the start condition to @c INITIAL . */ void yyrestart (FILE * input_file ) { if ( ! YY_CURRENT_BUFFER ){ yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer( yyin, YY_BUF_SIZE ); } yy_init_buffer( YY_CURRENT_BUFFER, input_file ); yy_load_buffer_state( ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * */ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) { /* TODO. We should be able to replace this entire function body * with * yypop_buffer_state(); * yypush_buffer_state(new_buffer); */ yyensure_buffer_stack (); if ( YY_CURRENT_BUFFER == new_buffer ) return; if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } YY_CURRENT_BUFFER_LVALUE = new_buffer; yy_load_buffer_state( ); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ (yy_did_buffer_switch_on_eof) = 1; } static void yy_load_buffer_state (void) { (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; (yy_hold_char) = *(yy_c_buf_p); } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. * * @return the allocated buffer state. */ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; yy_init_buffer( b, file ); return b; } /** Destroy the buffer. * @param b a buffer created with yy_create_buffer() * */ void yy_delete_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) yyfree( (void *) b->yy_ch_buf ); yyfree( (void *) b ); } /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a yyrestart() or at EOF. */ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) { int oerrno = errno; yy_flush_buffer( b ); b->yy_input_file = file; b->yy_fill_buffer = 1; /* If b is the current buffer, then yy_init_buffer was _probably_ * called from yyrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ b->yy_bs_lineno = 1; b->yy_bs_column = 0; } b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * */ void yy_flush_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) yy_load_buffer_state( ); } /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * */ void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) { if (new_buffer == NULL) return; yyensure_buffer_stack(); /* This block is copied from yy_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) (yy_buffer_stack_top)++; YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from yy_switch_to_buffer. */ yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * */ void yypop_buffer_state (void) { if (!YY_CURRENT_BUFFER) return; yy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; if ((yy_buffer_stack_top) > 0) --(yy_buffer_stack_top); if (YY_CURRENT_BUFFER) { yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } } /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ static void yyensure_buffer_stack (void) { yy_size_t num_to_alloc; if (!(yy_buffer_stack)) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc (num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; (yy_buffer_stack_top) = 0; return; } if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ /* Increase the buffer to prepare for a possible push. */ yy_size_t grow_size = 8 /* arbitrary grow size */; num_to_alloc = (yy_buffer_stack_max) + grow_size; (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc ((yy_buffer_stack), num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); /* zero only the new slots.*/ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; } } /** Setup the input buffer state to scan directly from a user-specified character buffer. * @param base the character buffer * @param size the size in bytes of the character buffer * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return NULL; b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = NULL; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; yy_switch_to_buffer( b ); return b; } /** Setup the input buffer state to scan a string. The next call to yylex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * yy_scan_bytes() instead. */ YY_BUFFER_STATE yy_scan_string (const char * yystr ) { return yy_scan_bytes( yystr, (int) strlen(yystr) ); } /** Setup the input buffer state to scan the given bytes. The next call to yylex() will * scan from a @e copy of @a bytes. * @param yybytes the byte buffer to scan * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len ) { YY_BUFFER_STATE b; char *buf; yy_size_t n; int i; /* Get memory for full buffer, including space for trailing EOB's. */ n = (yy_size_t) (_yybytes_len + 2); buf = (char *) yyalloc( n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; b = yy_scan_buffer( buf, n ); if ( ! b ) YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } static void yy_push_state (int _new_state ) { if ( (yy_start_stack_ptr) >= (yy_start_stack_depth) ) { yy_size_t new_size; (yy_start_stack_depth) += YY_START_STACK_INCR; new_size = (yy_size_t) (yy_start_stack_depth) * sizeof( int ); if ( ! (yy_start_stack) ) (yy_start_stack) = (int *) yyalloc( new_size ); else (yy_start_stack) = (int *) yyrealloc( (void *) (yy_start_stack), new_size ); if ( ! (yy_start_stack) ) YY_FATAL_ERROR( "out of memory expanding start-condition stack" ); } (yy_start_stack)[(yy_start_stack_ptr)++] = YY_START; BEGIN(_new_state); } static void yy_pop_state (void) { if ( --(yy_start_stack_ptr) < 0 ) YY_FATAL_ERROR( "start-condition stack underflow" ); BEGIN((yy_start_stack)[(yy_start_stack_ptr)]); } static int yy_top_state (void) { return (yy_start_stack)[(yy_start_stack_ptr) - 1]; } #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif static void yynoreturn yy_fatal_error (const char* msg ) { fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ yytext[yyleng] = (yy_hold_char); \ (yy_c_buf_p) = yytext + yyless_macro_arg; \ (yy_hold_char) = *(yy_c_buf_p); \ *(yy_c_buf_p) = '\0'; \ yyleng = yyless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ /** Get the current line number. * */ int yyget_lineno (void) { return yylineno; } /** Get the input stream. * */ FILE *yyget_in (void) { return yyin; } /** Get the output stream. * */ FILE *yyget_out (void) { return yyout; } /** Get the length of the current token. * */ int yyget_leng (void) { return yyleng; } /** Get the current token. * */ char *yyget_text (void) { return yytext; } /** Set the current line number. * @param _line_number line number * */ void yyset_lineno (int _line_number ) { yylineno = _line_number; } /** Set the input stream. This does not discard the current * input buffer. * @param _in_str A readable stream. * * @see yy_switch_to_buffer */ void yyset_in (FILE * _in_str ) { yyin = _in_str ; } void yyset_out (FILE * _out_str ) { yyout = _out_str ; } int yyget_debug (void) { return yy_flex_debug; } void yyset_debug (int _bdebug ) { yy_flex_debug = _bdebug ; } static int yy_init_globals (void) { /* Initialization is the same as for the non-reentrant scanner. * This function is called from yylex_destroy(), so don't allocate here. */ (yy_buffer_stack) = NULL; (yy_buffer_stack_top) = 0; (yy_buffer_stack_max) = 0; (yy_c_buf_p) = NULL; (yy_init) = 0; (yy_start) = 0; (yy_start_stack_ptr) = 0; (yy_start_stack_depth) = 0; (yy_start_stack) = NULL; /* Defined in main.c */ #ifdef YY_STDINIT yyin = stdin; yyout = stdout; #else yyin = NULL; yyout = NULL; #endif /* For future reference: Set errno on error, since we are called by * yylex_init() */ return 0; } /* yylex_destroy is for both reentrant and non-reentrant scanners. */ int yylex_destroy (void) { /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ yy_delete_buffer( YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; yypop_buffer_state(); } /* Destroy the stack itself. */ yyfree((yy_buffer_stack) ); (yy_buffer_stack) = NULL; /* Destroy the start condition stack. */ yyfree( (yy_start_stack) ); (yy_start_stack) = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time * yylex() is called, initialization will occur. */ yy_init_globals( ); return 0; } /* * Internal utility routines. */ #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, const char * s2, int n ) { int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (const char * s ) { int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif void *yyalloc (yy_size_t size ) { return malloc(size); } void *yyrealloc (void * ptr, yy_size_t size ) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return realloc(ptr, size); } void yyfree (void * ptr ) { free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ } #define YYTABLES_NAME "yytables" #line 328 "VPreLex.l" void VPreLex::pushStateDefArg(int level) { // Enter define substitution argument state yy_push_state(ARGMODE); m_parenLevel = level; m_defValue = ""; } void VPreLex::pushStateDefForm() { // Enter define formal arguments state yy_push_state(DEFFPAR); // First is an optional ( to begin args m_parenLevel = 0; m_defValue = ""; } void VPreLex::pushStateDefValue() { // Enter define value state yy_push_state(DEFVAL); m_parenLevel = 0; m_defValue = ""; } void VPreLex::pushStateIncFilename() { // Enter include <> filename state yy_push_state(INCMODE); yymore(); } void VPreLex::debug(int level) { #ifdef FLEX_DEBUG yy_flex_debug=level; #endif } int VPreLex::debug() { #ifdef FLEX_DEBUG return yy_flex_debug; #else return 0; #endif } int VPreLex::lex() { VPreLex::s_currentLexp = this; // Tell parser where to get/put data m_tokFilelinep = curFilelinep(); // Remember token start location, may be updated by the lexer later return yylex(); } size_t VPreLex::inputToLex(char* buf, size_t max_size) { // We need a custom YY_INPUT because we can't use flex buffers. // Flex buffers are limited to 2GB, and we can't chop into 2G pieces // because buffers can't end in the middle of tokens. // Note if we switched streams here (which we don't) "buf" would be // become a stale invalid pointer. // VPreStream* streamp = curStreamp(); if (debug()>=10) { cout<<"- pp:inputToLex ITL s="< max_size) { yyerrorf("Output buffer too small for a `line"); } else { got = forceOut.length(); strncpy(buf, forceOut.c_str(), got); } } else { if (streamp->m_eof) { if (debug()) cout<<"- EOF\n"; } got = 0; // 0=EOF/EOS - although got was already 0. if (again) goto again; } } if (debug()>=10) { cout<<"- pp::inputToLex got="<m_eof) return ""; // Don't delete the final "EOF" stream bool exited_file = curStreamp()->m_file; if (!exited_file) { // Midpoint of stream, just change buffers delete curStreamp(); m_streampStack.pop(); // Must work as size>1; EOF is entry 0 againr = true; return ""; } // Multiple steps because we need FLEX to see ending \n and EOS to end // any illegal states, like an unterminated `protected region else if (!curStreamp()->m_termState) { // First shutdown phase for a file // Terminate all files with a newline. This prevents problems if // the user had a define without a terminating newline, // otherwise the resumed file's next line would get tacked on. // Also makes it likely the `line that changes files comes out // immediately. curStreamp()->m_termState = 1; return "\n"; // Exit old file } else if (curStreamp()->m_termState == 1) { // Now the EOF - can't be sent with other characters curStreamp()->m_termState = 2; return ""; // End of file } else if (curStreamp()->m_termState == 2) { // Now ending `line curStreamp()->m_termState = 3; return curFilelinep()->lineDirectiveStrg(2); // Exit old file } else { // Final shutdown phase for a stream, we can finally change the // current fileline to the new stream curStreamp()->m_termState = 0; VFileLine* filelinep = curFilelinep(); delete curStreamp(); m_streampStack.pop(); // Must work as size>1; EOF is entry 0 if (curStreamp()->m_eof) { // EOF doesn't have a "real" fileline, but a linenumber of 0 from init time // Inherit whatever we last parsed so it's more obvious. curFilelinep(filelinep); } // The caller parser remembered the start location for the text we are parsing, // but we've discovered there was a file switch along the way, so update it. m_tokFilelinep = curFilelinep(); // if (curStreamp()->m_eof) { return ""; } else { return curFilelinep()->lineDirectiveStrg(0); // Reenter resumed file } } } void VPreLex::initFirstBuffer(VFileLine* filelinep) { // Called from constructor to make first buffer // yy_create_buffer also sets yy_fill_buffer=1 so reads from YY_INPUT VPreStream* streamp = new VPreStream(filelinep, this); streamp->m_eof = true; m_streampStack.push(streamp); // m_bufferState = yy_create_buffer(NULL, YY_BUF_SIZE); yy_switch_to_buffer(m_bufferState); yyrestart(NULL); } void VPreLex::scanNewFile(VFileLine* filelinep) { // Called on new open file. scanBytesBack will be called next. if (streamDepth() > VPreProc::DEFINE_RECURSION_LEVEL_MAX) { // The recursive `include in VPreProcImp should trigger first yyerrorf("Recursive `define or other nested inclusion"); curStreamp()->m_eof = true; // Fake it to stop recursion } else { VPreStream* streamp = new VPreStream(filelinep, this); m_tokFilelinep = curFilelinep(); streamp->m_file = true; scanSwitchStream(streamp); } } void VPreLex::scanBytes(const string& str) { // Note buffers also appended in ::scanBytesBack // Not "m_buffers.push_front(string(strp,len))" as we need a `define // to take effect immediately, in the middle of the current buffer // Also we don't use scan_bytes that would set yy_fill_buffer // which would force Flex to bypass our YY_INPUT routine. if (streamDepth() > VPreProc::DEFINE_RECURSION_LEVEL_MAX) { // More streams if recursive `define with complex insertion // More buffers mostly if something internal goes funky yyerrorf("Recursive `define or other nested inclusion"); curStreamp()->m_eof = true; // Fake it to stop recursion } else { VPreStream* streamp = new VPreStream(curFilelinep(), this); streamp->m_buffers.push_front(str); scanSwitchStream(streamp); } } void VPreLex::scanSwitchStream(VPreStream* streamp) { curStreamp()->m_buffers.push_front(currentUnreadChars()); m_streampStack.push(streamp); yyrestart(NULL); } void VPreLex::scanBytesBack(const string& str) { // Initial creation, that will pull from YY_INPUT==inputToLex // Note buffers also appended in ::scanBytes if (curStreamp()->m_eof) yyerrorf("scanBytesBack without being under scanNewFile"); curStreamp()->m_buffers.push_back(str); } string VPreLex::currentUnreadChars() { // WARNING - Peeking at internals if (!currentBuffer()) return ""; ssize_t left = (yy_n_chars - (yy_c_buf_p - currentBuffer()->yy_ch_buf)); if (left > 0) { // left may be -1 at EOS *(yy_c_buf_p) = (yy_hold_char); return string(yy_c_buf_p, left); } else { return ""; } } YY_BUFFER_STATE VPreLex::currentBuffer() { return YY_CURRENT_BUFFER; } int VPreLex::currentStartState() { return YY_START; } void VPreLex::dumpSummary() { cout<<"- pp::dumpSummary curBuf="<<(void*)(currentBuffer()); #ifdef FLEX_DEBUG // Else peeking at internals may cause portability issues ssize_t left = (yy_n_chars - (yy_c_buf_p -currentBuffer()->yy_ch_buf)); cout<<" left="< tmpstack = LEXP->m_streampStack; while (!tmpstack.empty()) { VPreStream* streamp = tmpstack.top(); cout<<"- bufferStack["<<(void*)(streamp)<<"]: " <<" at="<m_curFilelinep <<" nBuf="<m_buffers.size() <<" size0="<<(streamp->m_buffers.empty() ? 0 : streamp->m_buffers.front().length()) <<(streamp->m_eof?" [EOF]":"") <<(streamp->m_file?" [FILE]":""); cout< * * Code available from: https://www.veripool.org/verilog-perl * ****************************************************************************** * * Copyright 2000-2021 by Wilson Snyder. This program is free software; * you can redistribute it and/or modify it under the terms of either the GNU * Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * ***************************************************************************** * Do not use Flex in C++ mode. It has bugs with yyunput() which result in * lost characters. *****************************************************************************/ #include "VPreProc.h" #include "VPreLex.h" #include #include #include #include // Flex 2.5.35 has compile warning in ECHO, so we'll default our own rule #define ECHO yyerrorf("Missing VPreLex.l rule: ECHO rule invoked in state %d: %s", YY_START, yytext); VPreLex* VPreLex::s_currentLexp = NULL; // Current lexing point #define LEXP VPreLex::s_currentLexp #define linenoInc() { LEXP->linenoInc(); } static bool pedantic() { return LEXP->m_pedantic; } static bool keepWhitespace() { return LEXP->m_keepWhitespace; } static void appendDefValue(const char* t, size_t l) { LEXP->appendDefValue(t,l); } void yyerror(char* msg) { LEXP->curFilelinep()->error(msg); } #define YY_INPUT(buf,result,max_size) \ result = LEXP->inputToLex(buf,max_size); // Accessors, because flex keeps changing the type of yyleng char* yyourtext() { return yytext; } size_t yyourleng() { return (size_t)yyleng; } void yyourtext(const char* textp, size_t size) { yytext=(char*)textp; yyleng=size; } void yyerrorf(const char* format, ...) { char msg[1024]; va_list ap; va_start(ap,format); vsprintf(msg,format,ap); va_end(ap); yyerror(msg); } static bool isWhitespace(const std::string& str) { for (std::string::const_iterator pos = str.begin(); pos != str.end(); ++pos) { if (!isspace(*pos)) return false; } return true; } /**********************************************************************/ %} %x CMTMODE %x STRMODE %x DEFFPAR %x DEFFORM %x DEFVAL %x DEFCMT %x STRIFY %x ARGMODE %x INCMODE %x PRTMODE %x OFFMODE /* drop: Drop Ctrl-Z - can't pass thru or may EOF the output too soon */ ws [ \t\f\r] wsn [ \t\f] crnl [\r]*[\n] quote [\"] tickquote [`][\"] /* Where we use symb/symbdef, we must also look for a `` join */ /* Note in the preprocessor \ESCaped is *not* always special; mantis1537/bug441 */ backslash [\\] symb ([a-zA-Z_][a-zA-Z0-9_$]*|\\[^ \t\f\r\n]+) symbdef ([a-zA-Z_][a-zA-Z0-9_$]*|\\[^ \t\f\r\n`]+) word [a-zA-Z0-9_]+ drop [\032] bom [\357\273\277] /* Case insensitive; unfortunately ?i: isn't in flex 2.5.4 which is popular */ ambit [Aa][Mm][Bb][Ii][Tt] pragma [Pp][Rr][Aa][Gg][Mm][Aa] synopsys [Ss][Yy][Nn][Oo][Pp][Ss][Yy][Ss] synthesis [Ss][Yy][Nn][Tt][Hh][Ee][Ss][Ii][Ss] pragma_tools ({ambit}|{pragma}|{synopsys}|{synthesis}) translate_off [Tt][Rr][Aa][Nn][Ss][Ll][Aa][Tt][Ee]_[Oo][Ff][Ff] translate_on [Tt][Rr][Aa][Nn][Ss][Ll][Aa][Tt][Ee]_[Oo][Nn] prag_trans_off ({ws}*{pragma_tools}{ws}+{translate_off}{ws}*) prag_trans_on ({ws}*{pragma_tools}{ws}+{translate_on}{ws}*) /**************************************************************/ %% {bom} { } ^{ws}*"`line"{ws}+.*{crnl} { LEXP->lineDirective(yytext); return(VP_LINE); } /* Special directives we recognize */ "`define" { return(VP_DEFINE); } "`else" { return(VP_ELSE); } "`elsif" { return(VP_ELSIF); } "`endif" { return(VP_ENDIF); } "`ifdef" { return(VP_IFDEF); } "`ifndef" { return(VP_IFNDEF); } "`include" { return(VP_INCLUDE); } "`undef" { return(VP_UNDEF); } "`undefineall" { return(VP_UNDEFINEALL); } "`error" { if (!pedantic()) return (VP_ERROR); else return(VP_DEFREF); } "`__FILE__" { static string rtnfile; rtnfile = '"'; rtnfile += LEXP->curFilelinep()->filename(); rtnfile += '"'; yytext=(char*)rtnfile.c_str(); yyleng = rtnfile.length(); return (VP_STRING); } "`__LINE__" { static char buf[10]; sprintf(buf, "%d",LEXP->curFilelinep()->lineno()); yytext = buf; yyleng = strlen(yytext); return (VP_TEXT); } /* Pass-through strings */ {quote} { yy_push_state(STRMODE); yymore(); } <> { linenoInc(); yyerrorf("EOF in unterminated string"); yyleng=0; yyterminate(); } {crnl} { linenoInc(); yyerrorf("Unterminated string"); BEGIN(INITIAL); } {word} { yymore(); } [^\"\\] { yymore(); } {backslash}{crnl} { linenoInc(); yymore(); } {backslash}. { yymore(); } {quote} { yy_pop_state(); if (LEXP->m_parenLevel || LEXP->m_defQuote) { LEXP->m_defQuote=false; appendDefValue(yytext,yyleng); yyleng=0; } else return (VP_STRING); } /* Stringification */ {tickquote} { yy_push_state(STRIFY); return VP_STRIFY; } <> { linenoInc(); yyerrorf("EOF in unterminated '\""); yyleng=0; yyterminate(); } "`\\`\"" { return VP_BACKQUOTE; } {quote} { yy_push_state(STRMODE); yymore(); } {tickquote} { yy_pop_state(); return VP_STRIFY; } {symbdef} { return (VP_SYMBOL); } {symbdef}`` { yyleng-=2; return (VP_SYMBOL_JOIN); } "`"{symbdef} { return (VP_DEFREF); } "`"{symbdef}`` { yyleng-=2; return (VP_DEFREF_JOIN); } `` { yyleng-=2; return (VP_JOIN); } {crnl} { linenoInc(); yytext=(char*)"\n"; yyleng=1; return(VP_WHITE); } {wsn}+ { return (VP_WHITE); } {drop} { } [\r] { } . { return (VP_TEXT); } /* Protected blocks */ "`protected" { yy_push_state(PRTMODE); yymore(); } "`pragma"{wsn}+"protect"{wsn}+"begin_protected" { yy_push_state(PRTMODE); yymore(); } "//"{ws}*"pragma"{ws}+"protect"{ws}+"begin_protected" { yy_push_state(PRTMODE); yymore(); } <> { linenoInc(); yyerrorf("EOF in `protected"); yyleng=0; yyterminate(); } {crnl} { linenoInc(); return VP_TEXT; } . { yymore(); } "`endprotected" { yy_pop_state(); return VP_TEXT; } "`pragma"{wsn}+"protect"{wsn}+"end_protected" { yy_pop_state(); return VP_TEXT; } "//"{ws}*"pragma"{ws}+"protect"{ws}+"end_protected" { yy_pop_state(); return VP_TEXT; } /* Pass-through include <> filenames */ <> { linenoInc(); yyerrorf("EOF in unterminated include filename"); yyleng=0; yyterminate(); } {crnl} { linenoInc(); yyerrorf("Unterminated include filename"); BEGIN(INITIAL); } [^\>\\] { yymore(); } {backslash}. { yymore(); } [\>] { yy_pop_state(); return VP_STRING; } /* Reading definition formal parenthesis (or not) to begin formal arguments */ /* Note '(' must IMMEDIATELY follow definition name */ [(] { appendDefValue("(",1); LEXP->m_formalLevel=1; BEGIN(DEFFORM); } {crnl} { yy_pop_state(); unput('\n'); yyleng=0; return VP_DEFFORM; } /* DEFVAL will later grab the return */ <> { yy_pop_state(); return VP_DEFFORM; } /* empty formals */ . { yy_pop_state(); unput(yytext[yyleng-1]); yyleng=0; return VP_DEFFORM; } /* empty formals */ /* Reading definition formals (declaration of a define) */ [(] { appendDefValue(yytext,yyleng); yyleng=0; ++LEXP->m_formalLevel; } [)] { appendDefValue(yytext,yyleng); yyleng=0; if ((--LEXP->m_formalLevel)==0) { yy_pop_state(); return VP_DEFFORM; } } "/*" { yy_push_state(CMTMODE); yymore(); } "//"[^\n\r]* { return (VP_COMMENT);} {drop} { } <> { linenoInc(); yy_pop_state(); yyerrorf("Unterminated ( in define formal arguments."); yyleng=0; return VP_DEFFORM; } {crnl} { linenoInc(); appendDefValue((char*)"\n",1); } /* Include return so can maintain output line count */ [\\]{crnl} { linenoInc(); appendDefValue((char*)"\\\n",2); } /* Include return so can maintain output line count */ {quote} { LEXP->m_defQuote=true; yy_push_state(STRMODE); yymore(); } /* Legal only in default values */ "`\\`\"" { appendDefValue(yytext,yyleng); } /* Maybe illegal, otherwise in default value */ {tickquote} { appendDefValue(yytext,yyleng); } /* Maybe illegal, otherwise in default value */ [{\[] { LEXP->m_formalLevel++; appendDefValue(yytext,yyleng); } [}\]] { LEXP->m_formalLevel--; appendDefValue(yytext,yyleng); } [^\/\*\n\r\\(){}\[\]\"]+ | [\\][^\n\r] | . { appendDefValue(yytext,yyleng); } /* Reading definition value (declaration of a define's text) */ "/*" { LEXP->m_defCmtSlash=false; yy_push_state(DEFCMT); yymore(); } /* Special comment parser */ "//"[^\n\r]*[\\]{crnl} { linenoInc(); appendDefValue((char*)"\n",1); } /* Spec says // not part of define value */ "//"[^\n\r]* { return (VP_COMMENT);} {drop} { } <> { linenoInc(); yy_pop_state(); yytext=(char*)"\n"; yyleng=1; return (VP_DEFVALUE); } /* Technically illegal, but people complained */ {crnl} { linenoInc(); yy_pop_state(); yytext=(char*)"\n"; yyleng=1; return (VP_DEFVALUE); } [\\]{crnl} { linenoInc(); appendDefValue((char*)"\\\n",2); } /* Return, AND \ is part of define value */ {quote} { LEXP->m_defQuote=true; yy_push_state(STRMODE); yymore(); } [^\/\*\n\r\\\"]+ | [\\][^\n\r] | . { appendDefValue(yytext,yyleng); } /* Comments inside define values - if embedded get added to define value per spec */ /* - if no \{crnl} ending then the comment belongs to the next line, as a non-embedded comment */ /* - if all but (say) 3rd line is missing \ then it's indeterminate */ "*/" { yy_pop_state(); appendDefValue(yytext,yyleng); } [\\]{crnl} { linenoInc(); LEXP->m_defCmtSlash=true; appendDefValue(yytext,yyleng-2); appendDefValue((char*)"\n",1); } /* Return but not \ */ {crnl} { linenoInc(); yymore(); if (LEXP->m_defCmtSlash) yyerrorf("One line of /* ... */ is missing \\ before newline"); BEGIN(CMTMODE); } {word} { yymore(); } . { yymore(); } <> { yyerrorf("EOF in '/* ... */' block comment\n"); yyleng=0; yyterminate(); } /* Define arguments (use of a define) */ "/*" { yy_push_state(CMTMODE); yymore(); } "//"[^\n\r]* { return (VP_COMMENT);} {drop} { } <> { yyerrorf("EOF in define argument list\n"); yyleng = 0; yyterminate(); } {crnl} { linenoInc(); yytext=(char*)"\n"; yyleng=1; return(VP_WHITE); } {quote} { yy_push_state(STRMODE); yymore(); } "`\\`\"" { appendDefValue(yytext,yyleng); } /* Literal text */ {tickquote} { yy_push_state(STRIFY); return(VP_STRIFY); } [{\[] { LEXP->m_parenLevel++; appendDefValue(yytext,yyleng); } [}\]] { LEXP->m_parenLevel--; appendDefValue(yytext,yyleng); } [(] { LEXP->m_parenLevel++; // Note paren level 0 means before "(" of starting args // Level 1 means "," between arguments // Level 2+ means one argument's internal () if (LEXP->m_parenLevel == 1) { // Starting ( if (!isWhitespace(LEXP->m_defValue)) { yyerrorf("Illegal text before '(' that starts define arguments: '%s'", LEXP->m_defValue.c_str()); } } if (LEXP->m_parenLevel>1) { appendDefValue(yytext,yyleng); } else { return (VP_TEXT); }} [)] { LEXP->m_parenLevel--; if (LEXP->m_parenLevel>0) { appendDefValue(yytext,yyleng); } else { yy_pop_state(); return (VP_DEFARG); }} [,] { if (LEXP->m_parenLevel>1) { appendDefValue(yytext,yyleng); } else { yy_pop_state(); return (VP_DEFARG); }} "`"{symbdef} { appendDefValue(yytext,yyleng); } /* defref in defref - outer macro expands first */ "`"{symbdef}`` { appendDefValue(yytext,yyleng); } /* defref in defref - outer macro expands first */ `` { appendDefValue(yytext,yyleng); } /* defref in defref - outer macro expands first */ [^\/\*\n\r\\(,){}\[\]\"`]+ | . { appendDefValue(yytext,yyleng); } /* Translate offs. Note final newline not included */ (("//"{prag_trans_off}[^\n\r]*)|("/*"{prag_trans_off}"*/")) { if (LEXP->m_synthesis) { yy_push_state(OFFMODE); } return(VP_COMMENT); } (("//"{prag_trans_on}[^\n\r]*)|("/*"{prag_trans_on}"*/")) { if (LEXP->m_synthesis) { yy_pop_state(); } return(VP_COMMENT); } {crnl} { linenoInc(); yymore(); } /* Need to end the / / */ {word} { } . { } <> { yyerrorf("EOF in '/*synthesis translate_off*/' region\n"); yyleng=0; yyterminate(); } /* One line comments. Note final newline not included */ "//"[^\n\r]* { return (VP_COMMENT); } /* C-style comments. */ /**** See also DEFCMT */ "/*" { yy_push_state(CMTMODE); yymore(); } "*/" { yy_pop_state(); return(VP_COMMENT); } {crnl} { linenoInc(); yymore(); } {word} { yymore(); } . { yymore(); } <> { yyerrorf("EOF in '/* ... */' block comment\n"); yyleng=0; yyterminate(); } /* Define calls */ /* symbdef prevents normal lex rules from making `\`"foo a symbol {`"foo} instead of a BACKQUOTE */ "`"{symbdef} { return (VP_DEFREF); } "`"{symbdef}`` { yyleng-=2; return (VP_DEFREF_JOIN); } `` { yyleng-=2; return (VP_JOIN); } /* Generics */ <> { yyterminate(); } /* A "normal" EOF */ {crnl} { linenoInc(); yytext=(char*)"\n"; yyleng=1; return(VP_WHITE); } {symb} { return (VP_SYMBOL); } {symb}`` { yyleng-=2; return (VP_SYMBOL_JOIN); } `` { yyleng-=2; return (VP_JOIN); } [\r] { } {wsn}+ { if (!keepWhitespace()) { yytext=(char*)" "; yyleng=1; } return VP_WHITE; } {drop} { } . { return (VP_TEXT); } <*>.|\n { yymore(); } /* Prevent hitting ECHO; */ %% void VPreLex::pushStateDefArg(int level) { // Enter define substitution argument state yy_push_state(ARGMODE); m_parenLevel = level; m_defValue = ""; } void VPreLex::pushStateDefForm() { // Enter define formal arguments state yy_push_state(DEFFPAR); // First is an optional ( to begin args m_parenLevel = 0; m_defValue = ""; } void VPreLex::pushStateDefValue() { // Enter define value state yy_push_state(DEFVAL); m_parenLevel = 0; m_defValue = ""; } void VPreLex::pushStateIncFilename() { // Enter include <> filename state yy_push_state(INCMODE); yymore(); } void VPreLex::debug(int level) { #ifdef FLEX_DEBUG yy_flex_debug=level; #endif } int VPreLex::debug() { #ifdef FLEX_DEBUG return yy_flex_debug; #else return 0; #endif } int VPreLex::lex() { VPreLex::s_currentLexp = this; // Tell parser where to get/put data m_tokFilelinep = curFilelinep(); // Remember token start location, may be updated by the lexer later return yylex(); } size_t VPreLex::inputToLex(char* buf, size_t max_size) { // We need a custom YY_INPUT because we can't use flex buffers. // Flex buffers are limited to 2GB, and we can't chop into 2G pieces // because buffers can't end in the middle of tokens. // Note if we switched streams here (which we don't) "buf" would be // become a stale invalid pointer. // VPreStream* streamp = curStreamp(); if (debug()>=10) { cout<<"- pp:inputToLex ITL s="< max_size) { yyerrorf("Output buffer too small for a `line"); } else { got = forceOut.length(); strncpy(buf, forceOut.c_str(), got); } } else { if (streamp->m_eof) { if (debug()) cout<<"- EOF\n"; } got = 0; // 0=EOF/EOS - although got was already 0. if (again) goto again; } } if (debug()>=10) { cout<<"- pp::inputToLex got="<m_eof) return ""; // Don't delete the final "EOF" stream bool exited_file = curStreamp()->m_file; if (!exited_file) { // Midpoint of stream, just change buffers delete curStreamp(); m_streampStack.pop(); // Must work as size>1; EOF is entry 0 againr = true; return ""; } // Multiple steps because we need FLEX to see ending \n and EOS to end // any illegal states, like an unterminated `protected region else if (!curStreamp()->m_termState) { // First shutdown phase for a file // Terminate all files with a newline. This prevents problems if // the user had a define without a terminating newline, // otherwise the resumed file's next line would get tacked on. // Also makes it likely the `line that changes files comes out // immediately. curStreamp()->m_termState = 1; return "\n"; // Exit old file } else if (curStreamp()->m_termState == 1) { // Now the EOF - can't be sent with other characters curStreamp()->m_termState = 2; return ""; // End of file } else if (curStreamp()->m_termState == 2) { // Now ending `line curStreamp()->m_termState = 3; return curFilelinep()->lineDirectiveStrg(2); // Exit old file } else { // Final shutdown phase for a stream, we can finally change the // current fileline to the new stream curStreamp()->m_termState = 0; VFileLine* filelinep = curFilelinep(); delete curStreamp(); m_streampStack.pop(); // Must work as size>1; EOF is entry 0 if (curStreamp()->m_eof) { // EOF doesn't have a "real" fileline, but a linenumber of 0 from init time // Inherit whatever we last parsed so it's more obvious. curFilelinep(filelinep); } // The caller parser remembered the start location for the text we are parsing, // but we've discovered there was a file switch along the way, so update it. m_tokFilelinep = curFilelinep(); // if (curStreamp()->m_eof) { return ""; } else { return curFilelinep()->lineDirectiveStrg(0); // Reenter resumed file } } } void VPreLex::initFirstBuffer(VFileLine* filelinep) { // Called from constructor to make first buffer // yy_create_buffer also sets yy_fill_buffer=1 so reads from YY_INPUT VPreStream* streamp = new VPreStream(filelinep, this); streamp->m_eof = true; m_streampStack.push(streamp); // m_bufferState = yy_create_buffer(NULL, YY_BUF_SIZE); yy_switch_to_buffer(m_bufferState); yyrestart(NULL); } void VPreLex::scanNewFile(VFileLine* filelinep) { // Called on new open file. scanBytesBack will be called next. if (streamDepth() > VPreProc::DEFINE_RECURSION_LEVEL_MAX) { // The recursive `include in VPreProcImp should trigger first yyerrorf("Recursive `define or other nested inclusion"); curStreamp()->m_eof = true; // Fake it to stop recursion } else { VPreStream* streamp = new VPreStream(filelinep, this); m_tokFilelinep = curFilelinep(); streamp->m_file = true; scanSwitchStream(streamp); } } void VPreLex::scanBytes(const string& str) { // Note buffers also appended in ::scanBytesBack // Not "m_buffers.push_front(string(strp,len))" as we need a `define // to take effect immediately, in the middle of the current buffer // Also we don't use scan_bytes that would set yy_fill_buffer // which would force Flex to bypass our YY_INPUT routine. if (streamDepth() > VPreProc::DEFINE_RECURSION_LEVEL_MAX) { // More streams if recursive `define with complex insertion // More buffers mostly if something internal goes funky yyerrorf("Recursive `define or other nested inclusion"); curStreamp()->m_eof = true; // Fake it to stop recursion } else { VPreStream* streamp = new VPreStream(curFilelinep(), this); streamp->m_buffers.push_front(str); scanSwitchStream(streamp); } } void VPreLex::scanSwitchStream(VPreStream* streamp) { curStreamp()->m_buffers.push_front(currentUnreadChars()); m_streampStack.push(streamp); yyrestart(NULL); } void VPreLex::scanBytesBack(const string& str) { // Initial creation, that will pull from YY_INPUT==inputToLex // Note buffers also appended in ::scanBytes if (curStreamp()->m_eof) yyerrorf("scanBytesBack without being under scanNewFile"); curStreamp()->m_buffers.push_back(str); } string VPreLex::currentUnreadChars() { // WARNING - Peeking at internals if (!currentBuffer()) return ""; ssize_t left = (yy_n_chars - (yy_c_buf_p - currentBuffer()->yy_ch_buf)); if (left > 0) { // left may be -1 at EOS *(yy_c_buf_p) = (yy_hold_char); return string(yy_c_buf_p, left); } else { return ""; } } YY_BUFFER_STATE VPreLex::currentBuffer() { return YY_CURRENT_BUFFER; } int VPreLex::currentStartState() { return YY_START; } void VPreLex::dumpSummary() { cout<<"- pp::dumpSummary curBuf="<<(void*)(currentBuffer()); #ifdef FLEX_DEBUG // Else peeking at internals may cause portability issues ssize_t left = (yy_n_chars - (yy_c_buf_p -currentBuffer()->yy_ch_buf)); cout<<" left="< tmpstack = LEXP->m_streampStack; while (!tmpstack.empty()) { VPreStream* streamp = tmpstack.top(); cout<<"- bufferStack["<<(void*)(streamp)<<"]: " <<" at="<m_curFilelinep <<" nBuf="<m_buffers.size() <<" size0="<<(streamp->m_buffers.empty() ? 0 : streamp->m_buffers.front().length()) <<(streamp->m_eof?" [EOF]":"") <<(streamp->m_file?" [FILE]":""); cout<) { # Fix xsubpp 1.9508 and GCC 4.2.1 warning # "warning: deprecated conversion from string constant to ‘char*’" $line =~ s/^(\s*)(?:const\s*|)char\*\s*file\s*=\s*__FILE__;/${1}char* file = (char*)__FILE__;/; if ($line =~ /newXSproto/) { $line =~ s/([(,]\s*)"/$1(char*)"/g; } # print "$line"; } Verilog-Perl-3.478/vrename0000755000177100017500000004655414057150455015430 0ustar wsnyderwsnyder#!/usr/bin/perl -w # See copyright, etc in below POD section. ###################################################################### package main; use FindBin qw($RealBin); use lib "$RealBin/blib/arch"; use lib "$RealBin/blib/lib"; use lib "$RealBin"; use Getopt::Long; use IO::Dir; use IO::File; use Pod::Usage; use Verilog::Language; use Verilog::Getopt; use Verilog::Parser; use strict; use vars qw($VERSION %Vrename_Dont_Crypt %Vrename_Left_Edge_Define %Signal_Locs %Signal_Newname %Encrypt $Debug $Opt_Xref $Opt_Crypt $Opt_Crypt_All $Opt_Write $Opt_Keywords @Files); $VERSION = '3.478'; ###################################################################### # List of signals to never crypt # (Just put temporaries into signals.vrename) foreach ( 'unused_ok', '__FILE__', # Verilator, proposed for Verilog 2005 '__LINE__', # Verilator, proposed for Verilog 2005 'verilator', 'ms','us','ns','ps','fs', # Time precision arguments used in `timescale 'a'..'z', 'A'..'Z', # Single character names (cryptic enough!) ) { $Vrename_Dont_Crypt{$_} = ""; } # These defines contain a preprocessor directive # Thus when crypting we have to keep them at left edge %Vrename_Left_Edge_Define = ('`time_scale' => "", '`timescale' => "", ); ###################################################################### # main # capitalized are globals $Debug = 0; my $opt_change = 0; my $opt_list = 0; $Opt_Xref = 0; $Opt_Crypt = 0; # Global scope, used in sub-package $Opt_Crypt_All = 0; # Global scope, used in sub-package $Opt_Write = 1; $Opt_Keywords = 0; my $opt_read = 0; my $opt_change_filename = "signals.vrename"; my $opt_change_lang; my $output_dir = ""; @Files = (); if (! GetOptions ( "help" => \&usage, "debug" => \&debug, "version" => sub { print "Version $VERSION\n"; exit(0); }, "change!" => \$opt_change, "changefile=s"=> \$opt_change_filename, "changelang!" => \$opt_change_lang, "crypt!" => \$Opt_Crypt, "cryptall!" => \$Opt_Crypt_All, "keywords!" => \$Opt_Keywords, "language=s" => sub { shift; Verilog::Language::language_standard(shift); }, "list!" => \$opt_list, "o=s" => \$output_dir, "read!" => \$opt_read, "write!" => \$Opt_Write, "xref!" => \$Opt_Xref, "<>" => \¶meter, )) { die "%Error: Bad usage, try 'vrename --help'\n"; } $Opt_Crypt = 1 if $Opt_Crypt_All; if ($output_dir ne "" && $output_dir !~ /[\/\\]$/) { $output_dir .= "/"; } if (!@Files) { &usage(); } if ($output_dir eq "" && $Opt_Crypt && $opt_change) { print STDERR "You must use -o with -crypt or your uncrypted files will be overwritten.\n"; exit(10); } if ($opt_read || $opt_change) { changes_read($opt_change_filename); } if ($opt_change) { foreach my $file_or_dir (@Files) { verilog_change_sig($file_or_dir); } } if ($opt_list) { foreach my $file_or_dir (@Files) { parse_file($file_or_dir); } if ($Opt_Crypt) { changes_crypt(); } changes_from_loc(); if ($opt_change_lang) { changes_lang(); } changes_write($opt_change_filename); } exit(0); ###################################################################### sub nop{} sub usage { print "Version: $VERSION\n"; pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT, -noperldoc=>1); exit(1); } sub debug { $Debug = 1; $Verilog::Parser::Debug = $Debug; $Verilog::Vrename::Reader::Debug = $Debug; } sub parameter { my $param = shift; push @Files, "$param"; # Must quote to convert Getopt to string, bug298 (-r $param) or die "%Error: Can't open $param"; } ###################################################################### sub changes_from_loc { # If a signal was found, but doesn't have change information, make it # default to have a change record with replacement same as basename. foreach my $sig (sort (keys %Signal_Locs)) { if (! defined $Signal_Newname{$sig}) { $Signal_Newname{$sig} = $sig; } } } ###################################################################### sub changes_crypt { # Make random names for signals my %used_rand = (); foreach my $sig (sort keys %Signal_Locs) { if (! defined $Signal_Newname{$sig} && $sig !~ /\$/ && (! defined $Vrename_Dont_Crypt{$sig}) && !Verilog::Language::is_compdirect("`".$sig) ) { my $has_encry = 0; my $has_uncry = 0; $has_uncry ||= $main::Dont_Decrypt{$sig}; if ($Opt_Crypt_All) { $has_encry = 1; } else { foreach my $loc (@{$Signal_Locs{$sig}}) { $has_encry ||= defined $Encrypt{$loc}; $has_uncry ||= ! (defined $Encrypt{$loc}); } } if ($has_encry && !$has_uncry) { my $rand = random_string(); while (defined $used_rand{$rand}) { $rand = random_string(); } $used_rand{$rand} = 1; $Signal_Newname{$sig} = $rand; } } } } sub random_string { while (1) { my $sig = sprintf("%c%c%c%c%c%c", (rand(26)) + ord('a'), (rand(26)) + ord('a'), (rand(26)) + ord('a'), (rand(26)) + ord('a'), (rand(26)) + ord('a'), (rand(26)) + ord('a')); return $sig if !Verilog::Language::is_keyword($sig); } } ###################################################################### sub changes_write { # Read in the list of signal names to change my $filename = shift; my $fh = IO::File->new(">$filename") or die "%Error: $! $filename.\n"; my $sigcnt=0; print $fh "# Generated by vrename on ", scalar(localtime), "\n"; print $fh "#\n"; print $fh "# Files read for this analysis:\n"; foreach my $file (@Files) { print $fh "vfile\t\"$file\""; if ($Encrypt{$file}) { print $fh "\t-crypt"; } print $fh "\n"; } print $fh "#\n"; print $fh "#\tOriginal Signal Name\t\tName to change to\n"; print $fh "#\t--------------------\t\t-----------------\n"; print $fh "#\n"; foreach my $sig (sort (keys %Signal_Newname)) { $sigcnt++; print $fh "sigren\t\"$sig\""; my $len = 8 + 2 + length $sig; while ($len < 32) { print $fh "\t"; $len += 8; } print $fh "\t\"$Signal_Newname{$sig}\""; if ($Opt_Xref) { my $len = 40 + 2 + length $sig; while ($len < 64) { print $fh "\t"; $len += 8; } print $fh "\t#"; foreach my $loc (@{$Signal_Locs{$sig}}) { print $fh "$loc "; } } print $fh "\n"; } print $fh "#\n"; print $fh "# Use M-x compile in emacs to automatically perform the changes:\n"; print $fh "## Local Variables: ***\n"; print $fh "## compile-command: \"$0 -change "; foreach my $file (@Files) { print $fh $file, " "; } print $fh "\" ***\n"; print $fh "## End: ***\n"; $fh->close(); print "Wrote $filename (Changes list, $sigcnt signals)\n"; } sub changes_read { # Write out the list of signals in a format for easy editing my $filename = shift; print "Read $filename\n"; my $fh = IO::File->new("<$filename") or die "%Error: $! $filename.\n"; while (my $line = $fh->getline()) { chomp $line; $line =~ s/#.*$//; $line =~ s/^[ \t]+//; if ($line =~ /^$/ ) { # comment } elsif ($line =~ /^sigren\s+\"([^\"]+)\"\s+\"([^\"]+)\"/ ) { print "Rename got $1 $2\n" if ($Debug); $Signal_Newname {$1} = $2; } elsif ($line =~ /^vfile/ ) { # ignore } else { die "%Error: $filename $.: Can't parse \"$line\"\n"; } } $fh->close(); } sub changes_lang { # Grab keywords from most recent spec, not current --language my %kwds = Verilog::Language::language_keywords(Verilog::Language::language_maximum()); foreach my $kwd (sort keys %kwds) { next if Verilog::Language::is_keyword($kwd); # Already a keyword in sources next if !$Signal_Newname{$kwd}; # Not needed for the current file $Signal_Newname{$kwd} = '\\'.$kwd.' '; } } ###################################################################### sub crypt_string { my $filestrg = shift; my $magicb = "@@@@@!~SAVEVLB~!@@@@@"; my $magice = "@@@@@!~SAVEVLE~!@@@@@"; $filestrg =~ s/(\/[*\/]\s*)[Vv]erilint\s*([0-9]+)\s*off/$magicb Verilint $2 off $magice$1/g; $filestrg =~ s/(\/[*\/]\s*)([Ss]ynopsys\s*\S+)/$magicb $2 $magice$1/g; $filestrg =~ s/\/\*[\000-\377]*?\*\///g; # block comments $filestrg =~ s/^\s*\/\/.*\n//g; # lines beginning with '//' $filestrg =~ s/\/\/[^\"\n]*\n//g; # inline comments with no '"' chars, saves '"////stuf"' $filestrg =~ s/\/\/[^\"\n]*\"[^\"\n]*\".*\n//g; # inline comments with 2 '"' chars, kills '// "stuff"' $filestrg =~ s/[ \t]+/ /g; $filestrg =~ s/^[ \t]+//g; $filestrg =~ s/[ \t]+$//g; my $oldstrg = $filestrg; $filestrg = "/*ENCRYPTED:VRENAME*/"; my $pos = 0; my $oldpos; my $literal = 0; my $define = 0; for ($oldpos = 0; $oldpos < length $oldstrg; $oldpos++) { my $char = substr $oldstrg, $oldpos, 1; if ($char eq "\n") { if ($define || $literal) { $filestrg .= $char; $pos = 0; $define = 0; } else { $filestrg .= " "; $pos++; } } elsif ($char eq "`" && !$literal) { my $defkwd = (substr $oldstrg, $oldpos); $defkwd =~ /^(\`[a-z0-9_]*)/; $defkwd = $1; if (Verilog::Language::is_keyword ($defkwd) || (defined $Vrename_Left_Edge_Define {$defkwd})) { $filestrg .= "\n"; $pos = 0; $filestrg .= $char; $pos++; $define = 1; } else { $filestrg .= $char; $pos++; } } elsif ($char eq '"') { $filestrg .= $char; $pos++; $literal = ! $literal; } elsif ($char eq " " && !$literal && !$define) { if ($pos > 80) { $filestrg .= "\n"; $pos = 0; } elsif ($pos != 0) { $filestrg .= $char; $pos++; } } else { $filestrg .= $char; $pos++; } } $filestrg =~ s/[ \t]+/ /g; while ($filestrg =~ /$magicb([\000-\377]*?)$magice/) { my $rep = $1; $rep =~ s/[\n]/ /g; $filestrg =~ s/$magicb([\000-\377]*?)$magice/\n\/\*$rep\*\/\n/; } $filestrg .= "\n"; return $filestrg; } ###################################################################### sub _recurse_dir { my $dir = shift; my $callback = shift; my $dh = new IO::Dir($dir) or warn "%Warning: $! $dir\n"; while (defined (my $basefile = $dh->read)) { next if Verilog::Getopt->file_skip_special($basefile); &$callback("$dir/$basefile"); } $dh->close(); return; } sub parse_file { my $filename = shift; print "parse file $filename\n"; if (-d $filename) { _recurse_dir($filename, \&parse_file); return; } my $parser = Verilog::Vrename::Reader->new(); $parser->parse_file($filename); } sub verilog_change_sig { # Rename signals in this filename my $filename = shift; if (-d $filename) { _recurse_dir($filename, \&verilog_change_sig); return; } # Read in the whole file in a swath my $fh = IO::File->new ("<$filename") or die "%Error: $! $filename"; my $filestrg = join('',$fh->getlines()); $fh->close(); if ($Opt_Crypt) { if ($filestrg =~ /ENCRYPT_ME/) { $Encrypt{$filename} = 1; } } # If crypting, strip comments if ($Encrypt{$filename}) { $filestrg = crypt_string($filestrg); } # Replace any changed signals my $hadrepl = 0; my %signal_magic = (); # pass1: replace with magic replacement string # (two steps so renaming a->b and b->a at the same time doesn't screw up) foreach my $sig (sort keys %Signal_Newname) { my $new = $Signal_Newname{$sig}; if ($new ne $sig) { my $magic = "@@@@@!~${hadrepl}~!@@@@@"; my $hit; my $signs = $sig; if ($signs =~ /\\.* $/) { # Escaped $signs =~ s/ $//; my $sig_quoted = quotemeta $signs; $hit = 1 if $filestrg =~ s/$sig_quoted(?=[ \t\n\r])/$magic/g; } else { # Unescaped my $sig_quoted = quotemeta $signs; $hit = 1 if $filestrg =~ s/([^a-zA-Z0-9_\$\%\'\\])$sig_quoted(?=[^a-zA-Z0-9_])/$1$magic/g; # Consume leading \; either getting removed or part of replacement $hit = 1 if $filestrg =~ s/(\\)$sig_quoted(?=[ \t\n\r])/$magic/g; } if ($hit) { print "match s$sig n$new m$magic\n" if $Debug; $hadrepl ++; $signal_magic{$sig} = $magic; } } } # pass2: magic->new foreach my $sig (sort keys %Signal_Newname) { if (defined $signal_magic{$sig}) { my $magic = $signal_magic{$sig}; my $new = $Signal_Newname{$sig}; if ($new =~ / $/) { # new has trailing whitespace (due to escape) then # try to remove a space from original file also if we can, # so spacing remains the same $magic .= ' ?'; } if ($filestrg =~ s/$magic/$new/g) { print "match s$sig n$new m$magic\n" if $Debug; } } } # Save it if ($hadrepl || $Opt_Crypt) { if (!$Opt_Write) { print "$filename ($hadrepl signals matched) (-n: Not written)\n"; } else { my $fh = IO::File->new(">$output_dir$filename") or die "%Error: $! $output_dir$filename.\n"; $fh->print($filestrg); $fh->close; if ($Encrypt{$filename}) {print "Encrypted ";} else {print "Wrote ";} print "$filename ($hadrepl signals matched)\n"; } } } ###################################################################### package Verilog::Vrename::Reader; use Carp; use Verilog::Parser; use base qw(Verilog::Parser); use vars qw($Debug); use strict; sub new { my $class = shift; my $self = $class->SUPER::new (_last_keyword=>'', _file_sigs=>{}, @_); bless $self, $class; return $self; } sub _track_signal { my $self = shift; my $sig = shift; $sig =~ s/\`//g; # Remove `s from define usages else won't match define declaration if (!$self->{_file_sigs}{$sig}) { push @{$main::Signal_Locs{$sig}}, $self->filename; } $self->{_file_sigs}{$sig} = 1; if ($main::Opt_Crypt && ($self->{_last_keyword} eq "module" || $self->{_last_keyword} eq "function" || $self->{_last_keyword} eq "task")) { $main::Dont_Decrypt{$sig} = 1; $self->{_last_keyword} = ""; } } sub keyword { # Callback from parser when a keyword occurs my $self = shift; # Parser invoked my $token = shift; # What token was parsed $self->{_last_keyword} = $token; if ($main::Opt_Keywords) { $self->_track_signal($token); } } sub symbol { # Callback from parser when a symbol occurs my $self = shift; # Parser invoked my $sig = shift; # What token was parsed #print "Signal callback $self $token\n" if ($Debug); $self->_track_signal($sig); } sub parse_file { # Read all signals in this filename @_ == 2 or croak 'usage: $parser->parse_file($filename)'; my $self = shift; my $filename = shift; $self->{_file_sigs} = {}; # Signals already found in module $self->{_last_keyword} = ""; $self->SUPER::parse_file($filename); if ($main::Opt_Crypt) { my $fh = IO::File->new("<$filename") or die "%Error: $! $filename\n"; local $/ = undef; my $filestrg = <$fh>; # Same test below if ($filestrg =~ /ENCRYPT_ME/) { $main::Encrypt{$filename} = 1; } $fh->close; } } ###################################################################### ###################################################################### __END__ =pod =head1 NAME vrename - change signal names across many Verilog files =head1 SYNOPSIS vrename ... =head1 DESCRIPTION Vrename will allow a signal to be changed across all levels of the design hierarchy, or to create a cross reference of signal names. (It actually includes module names, macros, and other definitions, so those can be changed too.) Vpm uses a three step process. First, use vrename --list [...] [....] This reads the specified files, or all files below the specified directory, and creates a signals.vrename file. Now, edit the signals.vrename file manually to specify the new signal names. Then, use vrename --change [...] [....] Note that in the signals.vrename file any signal names including special characters must follow Verilog naming rules in that they must be escaped with a leading backslash and trailing space. Vrename will attempt to preserve spacing when changing escaped to non-escaped names and vice-versa, however in some cases extra whitespace may be inserted to ensure proper downstream parsing. =head1 ARGUMENTS vrename takes the following arguments: =over 4 =item --help Displays this message and program version and exits. =item --version Displays program version and exits. =item --change Take the signals file signals.vrename in the current directory and change the signals in the design as specified by the signals file. Either --list or --change must be specified. =item --changefile {file} Use the given filename instead of "signals.vrename". =item --changelang Include in the signals.vrename file the template needed to change the language standard for the file. For the first run, use "--list --changelang" and --language to specify the file's original language, then rerun with the "--change" option. The files will get escaped identifiers for the most recent Verilog standard. For example with --language 1364-2005, "do" will become "\do ". =item --crypt With --list, randomize the signal renames. With --change, compress spaces and comments and apply those renames listed in the file (presumably created with vrename --list --crypt). The comment /*ENCRYPT_ME*/ must be included in all files that need to be encrypted, or use the --cryptall flag. If a signal should not be encrypted, it can simply be set in the signals.vrename list to be changed to itself. After encrypting, you may want to save the signals.vrename file so you have a key for decoding, and also so that it may be used for the next encryption run. When used in this way for the next encryption run, only new signals will get new encryptions, all other encryptions will be encrypted the same. =item --cryptall As with --crypt, but put cryptic names into signals.vrename even if the file does not include ENCRYPT_ME. Generally you will then need to edit the signals.vrename file manually to exclude any top level signals that should be preserved. =item --keywords Include keywords in the renaming list. Default is to ignore keywords, as changing a keyword will probably result in unrunnable code, however, occasionally it may be necessary to rename signals which happen to match the name of keywords recently added to the language (such as 'bit'). =item --language <1364-1995|1364-2001|1364-2005|1800-2005|1800-2009|1800-2012|1800-2017> Set the language standard for the files. This determines which tokens are signals versus keywords, such as the ever-common "do" (data-out signal, versus a do-while loop keyword). =item --list Create a list of signals in the design and write to signals.vrename. Either --list or --change must be specified. =item --nowrite Don't write the actual changes, just report the files that would be changed. =item --o {dir} Use the given directory for output instead of the current directory. =item --read Read the changes list, allows --list to append to the changes already read. =item --xref Include a cross reference of where the signals are used. --list must also be specified. =back =head1 DISTRIBUTION Verilog-Perl is part of the L free Verilog EDA software tool suite. The latest version is available from CPAN and from L. Copyright 2000-2021 by Wilson Snyder. This package is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. =head1 AUTHORS Wilson Snyder =head1 SEE ALSO L, L =cut Verilog-Perl-3.478/MANIFEST0000644000177100017500000000700214035374034015154 0ustar wsnyderwsnyder.clang-format .gitignore Changes COPYING EditFiles.pm Getopt.pm Language.pm Makefile.PL MANIFEST This list of files MANIFEST.SKIP META.yml Netlist.pm Netlist/Cell.pm Netlist/ContAssign.pm Netlist/Defparam.pm Netlist/File.pm Netlist/Interface.pm Netlist/Logger.pm Netlist/ModPort.pm Netlist/Module.pm Netlist/Net.pm Netlist/Pin.pm Netlist/PinSelection.pm Netlist/Port.pm Netlist/Subclass.pm Parser/.gitignore Parser/bisonpre Parser/callbackgen Parser/gen/bisonpre-0 Parser/gen/bisonpre-1 Parser/gen/bisonpre-2 Parser/gen/bisonpre-s Parser/gen/flex-0 Parser/gen/flex-1 Parser/Makefile.PL Parser/Parser.pm Parser/Parser.xs Parser/SigParser.pm Parser/typemap Parser/VAst.cpp Parser/VAst.h Parser/VParse.cpp Parser/VParse.h Parser/VParseBison.y Parser/VParseGrammar.h Parser/VParseLex.h Parser/VParseLex.l Parser/VSymTable.cpp Parser/VSymTable.h Preproc/.gitignore Preproc/flexfix Preproc/gen/flex-0 Preproc/gen/flex-1 Preproc/Makefile.PL Preproc/Preproc.pm Preproc/Preproc.xs Preproc/toolhash Preproc/typemap Preproc/VFileLine.cpp Preproc/VFileLine.h Preproc/VPreLex.h Preproc/VPreLex.l Preproc/VPreProc.cpp Preproc/VPreProc.h Preproc/xsubppfix README README.pod Std.pm t/00_pod.t t/01_manifest.t t/02_help.t t/03_spaces.t t/04_critic.t t/05_yaml.t t/10_keywords.t t/12_splitbus.t t/14_numbers.t t/16_std.t t/20_getopt.opt t/20_getopt.t t/30_preproc.out t/30_preproc.t t/30_preproc_nows.out t/30_preproc_on.out t/30_preproc_sub.out t/30_preproc_syn.out t/32_noinc.t t/32_noinc.v t/33_gzip.t t/34_parser.out t/34_parser.t t/35_sigparser.out t/35_sigparser.t t/35_sigparser_ps.out t/36_sigmany.t t/40_netlist.t t/41_example.out t/41_example.t t/42_dumpcheck.t t/42_dumpcheck_1.out t/42_dumpcheck_1_ps.out t/42_dumpcheck_1v.out t/42_dumpcheck_1v_ps.out t/42_dumpcheck_2.out t/42_dumpcheck_2e.out t/42_dumpcheck_2v.out t/42_dumpcheck_sv.out t/42_dumpcheck_v2k.out t/42_dumpcheck_v2kv.out t/43_storable.t t/44_create.out t/44_create.t t/46_link.t t/48_leak.t t/49_largeish.t t/50_vrename.out t/50_vrename.t t/51_vrename_kwd.t t/51_vrename_kwd.v t/51_vrename_kwd_chg.out t/51_vrename_kwd_chg2.out t/51_vrename_kwd_chg2.vrename t/51_vrename_kwd_list.out t/56_editfiles.t t/56_editfiles.v t/56_editfiles_a.out t/56_editfiles_b.out t/56_editfiles_edit.out t/58_vsplitmodule.t t/60_vpassert.out t/60_vpassert.t t/80_vppreproc.t t/80_vppreproc_cmped.out t/80_vppreproc_defines.out t/80_vppreproc_none.out t/80_vppreproc_rel_file.out t/80_vppreproc_simple.out t/85_vhier.t t/85_vhier_cells.out t/85_vhier_forest.out t/85_vhier_includes.out t/85_vhier_inpfiles.out t/85_vhier_modfiles.out t/85_vhier_resolvefiles.out t/85_vhier_skiplist.dat t/85_vhier_skiplist.out t/85_vhier_topmodule.out t/85_vhier_xml.out t/86_vhier_tick.t t/87_vhier_unicode.t t/test_utils.pl verilog/example.v verilog/inc1.v verilog/inc2.v verilog/inc_def09.v verilog/inc_ifdef.v verilog/inc_nonl.v verilog/parser_bugs.v verilog/parser_sv.v verilog/parser_sv09.v verilog/parser_sv17.v verilog/parser_vectors.v verilog/pinorder.v verilog/pli.v verilog/t_80_bar/bar.f verilog/t_80_bar/bar.v verilog/t_80_foo.f verilog/t_80_foo.v verilog/t_86_vhier_tick.v verilog/t_86_vhier_tick_sub.v verilog/t_preproc_inc3.vh verilog/t_preproc_inc4.vh verilog/test.v verilog/test.vrename verilog/v_comments.v verilog/v_gate.v verilog/v_hier_inc.vh verilog/v_hier_noport.v verilog/v_hier_sub.v verilog/v_hier_subprim.v verilog/v_hier_subsub.v verilog/v_hier_top.v verilog/v_hier_top2.v verilog/v_recursive.v verilog/v_sv_intf.v verilog/v_sv_mod.v verilog/v_sv_pgm.v verilog/v_sv_pkg.v verilog/v_v2k.v vhier vpassert vppreproc vrename vsplitmodule Verilog-Perl-3.478/verilog/0000755000177100017500000000000014057150520015467 5ustar wsnyderwsnyderVerilog-Perl-3.478/verilog/test.vrename0000644000177100017500000000066014035374034020033 0ustar wsnyderwsnyder# DESCRIPTION: vrename: For test.pl testing of vrename # # Copyright 2000-2021 by Wilson Snyder. This program is free software; # you can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. ###################################################################### sigren "a" "or_term_1" sigren "b" "or_term_2" sigren "z" "ored_output" Verilog-Perl-3.478/verilog/v_sv_mod.v0000644000177100017500000000072713234726611017506 0ustar wsnyderwsnyder// DESCRIPTION: Verilog-Perl: Example Verilog for testing package // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2009-2012 by Wilson Snyder. `include "v_sv_pkg" interface sv_if_ported (input clk); endinterface module v_sv_mod (v_sv_intf intf, input clk); // Import types import v_sv_pkg::*; // Internal interface (unconnected) sv_if_ported if_ported(.clk(clk)); // Grab a program v_sv_pgm pgm(); endmodule Verilog-Perl-3.478/verilog/parser_sv.v0000644000177100017500000002273314035374034017675 0ustar wsnyderwsnyderpackage mypackage; bit [7:0] pkg_addr; bit [7:0] pkg_data; endpackage module times (); time x; initial x = 33ns; // Note no space endmodule : times interface itf #(parameter num_of_cli = 0); logic blabla; logic [7:0] addr, data[9]; modport Master(input data, date_delayed, output addr); endinterface : itf module test ( itf whole_int, itf.test modported_int, input logic clk, rst, input logic d_in, output logic d_out ); import mypackage::*; logic d_int; logic [7:0] data_, bork[2]; assign d_int = d_in + pkg_data; assign modported_int.data = data_; always_ff @(posedge clk or negedge rst) begin if (~rst) d_out <= '0; else d_out <= d_int; end property p1; @(posedge clk) disable iff(!rst) $rose(d_int) |-> ##1 d_int; endproperty //a1: assert property(p1) else $warning("\nProperty violated\n"); c1: cover property(p1) $display("\np1_cover\n"); endmodule : test // Different ways of declaring pins/vars module line49_diff_pins1 ( input in_nw, // Input, no type input [1:0] in_vec[2:0], // Input, implicit input in_nvec, // Isn't vectorized output logic out_logic, // Output and var output out_also_logic // "logic" sticks ); endmodule module line49_diff_pins2 (in2_nw, in2_vec, out2reg); input in2_nw; input [1:0] in2_vec [2:0]; output reg out2_reg; input signed in2_signed; var var1_imp; var [1:0] var1_imp_vec [2:0]; var reg var1_imp_reg; var logic var1_imp_logic; endmodule program automatic first_prog; int i; endprogram // Importing package imp_test_pkg; typedef logic [7:0] byte_t; typedef logic [15:0] word_t; function afunc(integer w); afunc=0; endfunction endpackage module imp_test_mod; import imp_test_pkg::byte_t; byte_t some_byte; endmodule module imp_test_mod2; import imp_test_pkg::*; word_t some_word; endmodule module imp_test_mod3 ( input imp_test_pkg::word_t wordin ); localparam FROM_FUNC = imp_test_pkg::afunc(1); endmodule module var_unnamed_block; initial begin integer var_in_unnamed; end endmodule module cell_with_typeparam; addr #(.PARAMTYPE(integer)) acell (); endmodule module arrayed_wire; wire [3:0][7:0] n2; endmodule task empty_task; // sv design book endtask task empty_task2; // sv design book integer i; endtask task check_casts; typedef integer integer_t; sum = a + integer '(3); sum = a + integer_t '(3); sum = a + 10'(3); endtask module comma_assign; int n[1:2][1:3] = '{'{0,1,2}, '{3{4}}}; endmodule task typed_pattern; typedef int triple [1:3]; $mydisplay(triple'{0,1,2}); endtask virtual class VclassWCopy; extern function new(); virtual function VclassWCopy copy(input VclassWCopy src=null); endfunction endclass : VclassWCopy function VclassWCopy::new(); endfunction : new typedef class FwdClass; function bit [3:0] FwdClass::ffunc (bit [3:0] in); ffunc = in; endfunction : ffunc function VclassWCopy VclassWCopy::copy (input VclassWCopy to); dst = new(); endfunction : copy task foreach_memref; bit [0:52] [7:0] mem; // It's *not* legal according to the grammar to have dotted/package ids here foreach (mem[i]) $write("i=%x ", mem[i]); $display; endtask typedef class PreTypedefedClass; class PreTypedefedClass; extern function new(); endclass typedef class PreTypedefedClass; class NewInNew; function new; s_self = new; endfunction : new endclass // std package class TryStd; semaphore s1; std::semaphore s2; mailbox #(integer) m1; std::mailbox m2; process p1; std::process p2; endclass module cg_test1; covergroup counter1 @ (posedge cyc); cyc_bined : coverpoint cyc { bins zero = {0}; bins low = {1,5}; bins mid = {[5:$]}; } value_and_toggle: cross cyc_value, toggle; endgroup endmodule task randomize_dotted(); int vbl; assert(vbl.randomize()); endtask module prop_parens; LABEL: cover property (@(posedge clk) ((foo[3:0] == 4'h0) & bar)); endmodule class this_dot_tests; task ass; this.super.foo = this.bar; endtask endclass module sized_out #( parameter SZ = 4 ) ( output logic [SZ-1:0] o_sized ); endmodule class solve_size; rand byte arrayed[]; rand bit b; // The dot below doesn't seem legal according to grammar, but // the intent makes sense, and it appears in the VMM constraint solve_a_b { solve arrayed.size before b; } endclass class vmm_stuff; task examples; void'(this.a.funccall(x)); this.a.taskcall(); super.new(name2); endtask extern static local function bit foo1(); extern virtual protected function void foo2(); protected static string foo3; extern function bit foo4(); static local bit foo5[string]; endclass class vmm_cl_func_colon; typedef enum int unsigned {FIRM} restart_e; function void do_all(vmm_cl_func_colon::restart_e kind = vmm_cl_func_colon::FIRM); endfunction extern function int uses_class_type(); endclass class vmm_cl_subenv; extern protected virtual task do_reset(vmm_cl_func_colon::restart_e kind = vmm_cl_func_colon::FIRM); endclass task empty_comma; extracomma1(,); extracomma2("a",); extracomma3("a",,"c"); extracomma4(,"b"); endtask task vmm_more; file_is_a_string(`__FILE__,`__LINE__); foreach(this.text[i]) begin $display("%s\n", this.text[i]); end // Not part of 1800-2005 grammar, but likely in 1800-2009 queue = '{}; -> this.item_taken; endtask // Extern Functions/tasks when defined must scope to the class they're in to get appropriate types function int vmm_cl_func_colon::uses_class_type(restart_e note_uses_class_type); var restart_e also_uses_class_type; endfunction module hidden_checks; typedef int T; sub (.T(123)); // Different T task hidden; typedef bit T; // Different T endtask endmodule typedef struct packed signed { rand int m_a; bit [7:0] m_b; } t_bug91; t_bug91 v_bug91; module bug98(interfacex x_if); h inst_h(.push(x_if.pop)); endmodule module bugas; initial begin ASSERT_CHK: assert (0) else $error("%m -- not allowed %d", 0); end endmodule typedef enum [2:0] { ENUM_RANGED_VALUE } enum_ranged_t; typedef struct packed { logic val; } t_bug202_struct; typedef union packed { logic val; } t_bug202_union; class ln288; extern virtual function string extvirtstr; extern virtual task extvirttask; endclass class cl_to_init; extern function new(); extern static function cl_to_init init(); endclass function cl_to_init cl_to_init::init(); endfunction function cl_to_init::new(); endfunction cl_to_init cl_inited = cl_to_init::init(); // pure virtual functions have no endfunction. virtual class pure_virt_func_class; pure virtual function string pure_virt_func(); pure virtual task pure_virt_task(); endclass class extend_base; typedef enum { EN_A, EN_B } base_enum; virtual function extend_base create(); return null; endfunction endclass class extended extends extend_base; typedef base_enum be_t; // type must come from base class virtual function int create (); // Must override base's create be_t mye; endfunction endclass task rand_with_ln320(); if (!randomize(v) with { v > 0 && v < maxval; }) begin end if (randomize(null)) begin end endtask task apply_request(data_req, input bit randomize = 1); if (randomize == 1) begin data_req.randomize(); // Generic method, not std::randomize end endtask task foreach_class_scope_ln330; foreach (extended::some_array[i,j]) begin end endtask module clkif_334; always @(posedge top.clk iff !top.clken_l) begin end endmodule module gen_ln338; generate case (P) 32'b0: initial begin end default: initial begin end endcase endgenerate endmodule module par_packed; parameter logic [31:0] P1 [3:0] = '{ 1, 2, 3, 4 } ; // unpacked array wire struct packed { logic ecc; logic [7:0] data; } memsig; endmodule module not_a_bug315; typedef int supply_net_t; input int i; input imp_test_pkg::byte_t i; input supply_net_t bug316; endmodule module bins_bracket; parameter N = 2; covergroup cg_debitor @(posedge eclk); count: coverpoint count iff (erst_n) { // 'std' overrides std:: package, which confuses VP //bins std[] = { [0:N] }; } endgroup endmodule virtual class ovm_void; endclass virtual class ovm_port_base #(type IF=ovm_void) extends ovm_void; endclass virtual class uvm_build_phase #(type BASE=ovm_void) extends BASE; static const string type_name = "uvm_build_phase"; endclass class bug627sub; endclass class bug627 #(type TYPE=bug627sub); typedef TYPE types_t[$]; static function types_t f(); $display("%s", { TYPE::type_name }); return types; endfunction endclass interface if_bug777; wire a; modport master (input a); modport slave (output a); endinterface module bug777 (clk, ifport); input clk; if_bug777 ifport (); if_bug777.mp ifportmp; //if_bug777.mp ifportmp (); // Not legal // Currently unsupported, parens required so VP knows is instance //if_bug777 ifport; endmodule module bug778 (); virtual if_bug777.master bar; endmodule class cls778; virtual if_bug777.master bar; endclass : cls778; module bug810 #( /*parameter*/ int unsigned DW = 32); endmodule interface test_if (input clk); endinterface module bug815 ( test_if bad[2]); endmodule module bug868 (ifmp); if_bug777.master ifmp; endmodule module bug_param_struct #(int ROWS = 2, type data_t = struct packed { logic [ROWS-1:0] row_id; }) (input data_t d); endmodule Verilog-Perl-3.478/verilog/inc_def09.v0000644000177100017500000000341413234726611017426 0ustar wsnyderwsnyder// DESCRIPTION: Verilog-Perl: Verilog Test module // // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2009 by Wilson Snyder. `undefineall // Definitions as speced // Note there are trailing spaces, which spec doesn't show properly `define D(x,y) initial $display("start", x , y, "end"); '`D( "msg1" , "msg2" )' 'initial $display("start", "msg1" , "msg2" , "end");' '`D( " msg1", )' 'initial $display("start", " msg1" , , "end");' '`D(, "msg2 ")' 'initial $display("start", , "msg2 ", "end");' '`D(,)' 'initial $display("start", , , "end");' '`D( , )' 'initial $display("start", , , "end");' //`D("msg1") // ILLEGAL: only one argument //`D() // ILLEGAL: only one empty argument //`D(,,) // ILLEGAL: more actual than formal arguments // Defaults: `define MACRO1(a=5,b="B",c) $display(a,,b,,c); '`MACRO1 ( , 2, 3 )' '$display(5,,2,,3);' '`MACRO1 ( 1 , , 3 )' '$display(1 ,,"B",,3 );' '`MACRO1 ( , 2, )' '$display(5,,2,,);' //`MACRO1 ( 1 ) // ILLEGAL: b and c omitted, no default for c `define MACRO2(a=5, b, c="C") $display(a,,b,,c); '`MACRO2 (1, , 3)' '$display(5,,,,"C");' '`MACRO2 (, 2, )' '$display(5,,2,,"C");' '`MACRO2 (, 2)' '$display(5,,2,,"C");' `define MACRO3(a=5, b=0, c="C") $display(a,,b,,c); '`MACRO3 ( 1 )' '$display(1 ,,0,,"C");' '`MACRO3 ( )' '$display(5,,0,,"C");' //`MACRO3 // ILLEGAL: parentheses required `define DTOP(a,b) a + b '`DTOP( `DTOP(b,1), `DTOP(42,a) )' 'b + 1 + 42 + a' // Local tests `define MACROQUOTE(a="==)",b="((((",c=() ) 'a b c' `MACROQUOTE(); '"==)" "((((" () '; // Also check our line counting doesn't go bad `define MACROPAREN(a=(6), b=(eq=al), c) 'a b c' `MACROPAREN( ,, ZOT) HERE-`__LINE__ - Line71 //====================================================================== Verilog-Perl-3.478/verilog/t_86_vhier_tick.v0000644000177100017500000000043413234726611020654 0ustar wsnyderwsnyder// DESCRIPTION: Verilog::Preproc: Example source code // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2000-2012 by Wilson Snyder. module t_86_vhier_tick; `define t_86_vhier_tick_sub FOOBAR_NOT_FOUND t_86_vhier_tick_sub sub (); endmodule Verilog-Perl-3.478/verilog/v_sv_intf.v0000644000177100017500000000062713234726611017666 0ustar wsnyderwsnyder// DESCRIPTION: Verilog-Perl: Example Verilog for testing package // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2009-2012 by Wilson Snyder. `include "v_sv_pkg.v" interface v_sv_intf; v_sv_pkg::byte_t byte_port; v_sv_intf2 subintf(.*); endinterface interface v_sv_intf2; v_sv_pkg::byte_t byte_port; modport Master(input data, output addr); endinterface Verilog-Perl-3.478/verilog/v_recursive.v0000644000177100017500000000025313234726611020220 0ustar wsnyderwsnydermodule v_recursive (); parameter DEPTH = 1; generate if (DEPTH > 1) begin : rec v_recursive #(.DEPTH(DEPTH-1)) recurse (); end endgenerate endmodule Verilog-Perl-3.478/verilog/v_hier_noport.v0000644000177100017500000000036613422450702020540 0ustar wsnyderwsnyder// DESCRIPTION: Verilog-Perl: Example Verilog for testing package // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2000-2012 by Wilson Snyder. module v_hier_noport; parameter P; reg internal; endmodule Verilog-Perl-3.478/verilog/v_v2k.v0000644000177100017500000000113013234726611016706 0ustar wsnyderwsnyder// DESCRIPTION: Verilog-Perl: Example Verilog for testing package // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2006-2012 by Wilson Snyder. module v_v2k #(parameter WIDTH = 16) ( input clk, input rst, input [WIDTH:0] sig1, output reg [WIDTH:0] sig2 ); always @(clk) begin if (rst) begin sig2 <= #1 0; end else begin sig2 <= #1 sig1; end end // Multidim, bug1206 wire [1:2] [3:4] netmd; v_v2k_sub sub (.net1 (netmd[1])); endmodule module v_v2k_sub ( input [3:4] net1 ); endmodule Verilog-Perl-3.478/verilog/t_80_foo.f0000644000177100017500000000005513234726611017261 0ustar wsnyderwsnyderverilog/t_80_foo.v -F verilog/t_80_bar/bar.f Verilog-Perl-3.478/verilog/inc1.v0000644000177100017500000004662714030463163016530 0ustar wsnyderwsnyder// DESCRIPTION: Verilog::Preproc: Example source code // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2000-2012 by Wilson Snyder. text. //=========================================================================== // Includes //=========================================================================== // Defines `define DEF_A3 `define DEF_A1 // DEF_A0 set by command line wire [3:0] q = { `ifdef DEF_A3 1'b1 `else 1'b0 `endif , `ifdef DEF_A2 1'b1 `else 1'b0 `endif , `ifdef DEF_A1 1'b1 `else 1'b0 `endif , `ifdef DEF_A0 1'b1 `else 1'b0 `endif }; text. `define FOOBAR foo /*this */ bar /* this too */ `define FOOBAR2 foobar2 // but not `FOOBAR `FOOBAR2 `define MULTILINE first part \ second part \ third part `define MOREMULTILINE {\ a,\ b,\ c} /*******COMMENT*****/ `MULTILINE `MOREMULTILINE Line_Preproc_Check `__LINE__ //=========================================================================== `define syn_negedge_reset_l or negedge reset_l `define DEEP deep `define DEEPER `DEEP `DEEP `DEEPER `define nosubst NOT_SUBSTITUTED `define WITHTICK "`nosubst" "Inside: `nosubst" `WITHTICK `define withparam(a, b) a b LLZZ a b `withparam(x,y) `withparam(`withparam(p,q),`withparam ( r , s )) `withparam(firstline , comma","line) `define withquote(a, bar) a bar LLZZ "a" bar `withquote( x , y) // Simulators disagree here; some substitute "a" others do not `define noparam (a,b) `noparam(a,b) `define msg(x,y) `"x: `\`"y`\`"`" $display(`msg(left side, right side)) `define foo(f) f``_suffix `foo(bar) more `define zap(which) \ $c("Zap(\"",which,"\");"); `zap(bug1); `zap("bug2"); /* Define inside comment: `DEEPER and `WITHTICK */ // More commentary: `zap(bug1); `zap("bug2"); //====================================================================== // display passthru `define ls left_side `define rs right_side `define noarg na `define thru(x) x `define thruthru `ls `rs // Doesn't expand `define msg(x,y) `"x: `\`"y`\`"`" initial begin //$display(`msg( \`, \`)); // Illegal $display(`msg(pre `thru(thrupre `thru(thrumid) thrupost) post,right side)); $display(`msg(left side,right side)); $display(`msg( left side , right side )); $display(`msg( `ls , `rs )); $display(`msg( `noarg , `rs )); $display(`msg( prep ( midp1 `ls midp2 ( outp ) ) , `rs )); $display(`msg(`noarg,`noarg`noarg)); $display(`msg( `thruthru , `thruthru )); // Results vary between simulators $display(`msg(`thru(),)); // Empty $display(`msg(`thru(left side),`thru(right side))); $display(`msg( `thru( left side ) , `thru( right side ) )); $display(`"standalone`"); // Unspecified when the stringification has multiple lines `define twoline first \ second $display(`msg(twoline, `twoline)); //$display(`msg(left side, \ right side \ )); // Not sure \{space} is legal. $write("*-* All Finished *-*\n"); $finish; end endmodule //====================================================================== // rt.cpan.org bug34429 `define ADD_UP(a,c) \ wire tmp_``a = a; \ wire tmp_``c = tmp_``a + 1; \ assign c = tmp_``c ; module add1 ( input wire d1, output wire o1); `ADD_UP(d1,o1) // expansion is OK endmodule module add2 ( input wire d2, output wire o2); `ADD_UP( d2 , o2 ) // expansion is bad endmodule `define check(mod, width, flopname, gate, path) \ generate for (i=0; i<(width); i=i+1) begin \ psl cover { path.d[i] & ~path.q[i] & !path.cond & (gate)} report `"fondNoRise: mod.flopname`"; \ psl cover { ~path.d[i] & path.q[i] & !path.cond & (gate)} report `"fondNoFall: mod.flopname`"; \ end endgenerate // parameterized macro with arguments that are macros `define MK m5k.f `define MF `MK .ctl `define CK_fr (`MF.alive & `MF.alive_m1) `check(m5kc_fcl, 3, _ctl_mvldx_m1, `CK_fr, `MF._ctl_mvldx_m1) // ignorecmt //====================================================================== // Quotes are legal in protected blocks. Grr. module prot(); `protected I!#r#e6<_Q{{E2+]I3<[3s)1@D|'E''i!O?]jD>Jo_![Cl) #nj1]p,3^1~,="E@QZB\T)eU\pC#C|7=\$J$##A[@-@{Qk] `endprotected endmodule module prot2(); `pragma protect begin_protected `pragma protect encrypt_agent = "Whatever agent" `pragma protect encrypt_agent_info = "1.2.3" `pragma protect data_method = "aes128-cbc" `pragma protect key_keyowner = "Someone" `pragma protect key_keyname = "somekey", key_method = "rsa" `pragma protect key_block encoding = (enctype = "base64") wefjosdfjklajklasjkl `pragma protect data_block encoding = (enctype = "base64", bytes = 1059) I!#r#e6<_Q{{E2+]I3<[3s)1@D|'E''i!O?]jD>Jo_![Cl) #nj1]p,3^1~,="E@QZB\T)eU\pC#C|7=\$J$##A[@-@{Qk] `pragma protect end_protected `pragma reset protect endmodule module prot3(); //pragma protect begin_protected //pragma protect key_keyowner=Cadence Design Systems. //pragma protect key_keyname=CDS_KEY //pragma protect key_method=RC5 //pragma protect key_block zzZzZ/4ZzzZZZzzz4zZzZzZZZZzZzZ/Zz+33zZ2zz/zzzzzzzzZZZzZ4z+ZZZZz1 Z1ZzzzZZzZZzz9ZZZZ37zzZzZzZzzz9ZZzzZzZz9Zz64+z8Z7ZzZZZzzzzZZZzZz zzZzZZZzZ0463zzzzzZzZ6z00z4zZzzZZzzZzzzZZ8zzz09ZzZZZZZ== //pragma protect end_key_block //pragma protect digest_block ZzZZzzZ9ZZZZz2ZzzzZz/Zzzz8Z= //pragma protect end_digest_block //pragma protect data_block ZZZ8zZzz6ZZ/zZZ5zZZzzz3ZzzzZzZZZ6ZzZzZZZZZz1zzZZZZ7ZZZZz3Zzz+9zz 4zzz+8zZzzzzZzZZzzzZzz1Z7ZzZz+zZz8ZZZZzZ6ZzzZzZZzzZZzzZzzZzZzZzZ ZzzzzZ0zZz1ZzzZzzZzZzz== //pragma protect end_data_block //pragma protect digest_block Z4Z6zZzZ3Z7ZZ6zzZZZZzzzzZZZ= //pragma protect end_digest_block //pragma protect end_protected endmodule //====================================================================== // macro call with define that has comma `define REG_H 6 `define REG_L 7 `define _H regs[`REG_H] `define _L regs[`REG_L] `define _HL {`_H, `_L} `define EX_WRITE(ad, da) begin addr <= (ad); wdata <= (da); wr <= 1; end `define EX_READ(ad) begin addr <= (ad); rd <= 1; end `EX_READ((`_HL + 1)) and `EX_WRITE((`_HL), rdata) `EX_READ(`_HL + 1) `EX_WRITE(`_HL, rdata) more //====================================================================== // include of parameterized file `define INCNAME "t_preproc_inc4.vh" `include `INCNAME `ifndef T_PREPROC_INC4 `error "No Inc4" `endif `undef T_PREPROC_INC4 `ifdef NOT_DEFINED_INC `include NOT_DEFINED_INC `endif //====================================================================== // macro call with , in {} `define xxerror(logfile, msg) $blah(logfile,msg) `xxerror("ab,cd","e,f"); `xxerror(this.logfile, vec); `xxerror(this.logfile, vec[1,2,3]); `xxerror(this.logfile, {blah.name(), " is not foo"}); //====================================================================== // pragma/default net type `pragma foo = 1 `default_nettype none `default_nettype uwire //====================================================================== // Ifdef `define EMPTY_TRUE `ifndef EMPTY_TRUE `error "Empty is still true" `endif Line_Preproc_Check `__LINE__ //====================================================================== // bug84 `define ARGPAR(a, // Hello, comments MIGHT not be legal /*more,,)cmts*/ b // But newlines ARE legal... who speced THAT? ) (a,b) `ARGPAR(p,q) `ARGPAR( //Here x, y //Too ) Line_Preproc_Check `__LINE__ //====================================================================== // defines split arguments `define BEGIN begin `define END end `define BEGINEND `BEGIN`END `define quoteit(x) `"x`" `BEGIN`END // 2001 spec doesn't require two tokens, so "beginend" ok `BEGINEND // 2001 spec doesn't require two tokens, so "beginend" ok `quoteit(`BEGIN`END) // No space "beginend" //====================================================================== // bug106 `define \esc`def got_escaped `ifdef \esc`def `\esc`def `endif Not a \`define //====================================================================== // misparsed comma in submacro `define sb bee `define appease_emacs_paren_matcher ( `define sa(l) x,y) `define sfoo(q,r) q--r `sfoo(`sa(el),`sb) submacro has comma paren //====================================================================== // bug191 `define bug191(bits) $display("bits %d %d", $bits(foo), bits); `bug191(10) //====================================================================== // 1800-2009 `define UDALL `ifndef PREDEF_COMMAND_LINE `error "Test setup error, PREDEF_COMMAND_LINE pre-missing" `endif `undefineall `ifdef UDALL `error "undefineall failed" `endif `ifndef PREDEF_COMMAND_LINE `error "Deleted too much, no PREDEF_COMMAND_LINE" `endif //====================================================================== // bug202 `define FC_INV3(out, in) \ `ifdef DC \ cell \inv_``out <$typeof(out)> (.a(), .o()); \ /* multi-line comment \ multi-line comment */ \ `else \ `ifdef MACRO_ATTRIBUTE \ (* macro_attribute = `"INV (out``,in``)`" *) \ `endif \ assign out = ~in ; \ `endif `FC_INV3(a3,b3) `define /* multi \ line1*/ \ bug202( i /*multi \ line2*/ \ ) \ /* multi \ line 3*/ \ def i \ `bug202(foo) //====================================================================== `define CMT1 // verilator NOT IN DEFINE `define CMT2 /* verilator PART OF DEFINE */ `define CMT3 /* verilator NOT PART OF DEFINE */ `define CMT4 /* verilator PART \ OF DEFINE */ `define CMT5 // CMT NOT \ also in // BUT TEXT IS \ also3 // CMT NOT 1 `CMT1 (nodef) 2 `CMT2 (hasdef) 3 `CMT3 (nodef) 4 `CMT4 (nodef) 5 `CMT5 (nodef) `define NL HAS a NEW \ LINE `NL //====================================================================== `define msg_fatal(log, msg) \ do \ /* synopsys translate_off */ \ `ifdef NEVER \ `error "WTF" \ `else \ if (start(`__FILE__, `__LINE__)) begin \ `endif \ message(msg); \ end \ /* synopsys translate_on */ \ while(0) `define msg_scen_(cl) cl``_scen `define MSG_MACRO_TO_STRING(x) `"x`" EXP: clxx_scen `msg_scen_(clxx) EXP: clxx_scen `MSG_MACRO_TO_STRING(`msg_scen_(clxx)) `define mf(clx) `msg_fatal(this.log, {"Blah-", `MSG_MACRO_TO_STRING(`msg_scen_(clx)), " end"}); EXP: do if (start("verilog/inc1.v", 25)) begin message({"Blah-", "clx_scen", " end"}); end while(0); `mf(clx) //====================================================================== `define makedefine(name) \ `define def_``name This is name \ `define def_``name``_2 This is name``_2 \ `makedefine(fooed) `ifndef def_fooed `error "No def_fooed" `endif //`ifndef def_fooed_2 `error "No def_fooed_2" `endif EXP: This is fooed `def_fooed EXP: This is fooed_2 `def_fooed_2 //====================================================================== `define NOPARAM() np `NOPARAM() `NOPARAM( ) //====================================================================== // It's unclear if the spec allows this; is text_macro_idenitfier before or after substitution? `define NODS_DEFINED `define NODS_INDIRECT(x) x `ifndef `NODS_INDIRECT(NODS_DEFINED) `error "Indirect failed" `endif `ifdef `NODS_INDIRECT(NODS_UNDEFINED) `error "Indirect2 failed" `endif //====================================================================== // Metaprogramming `define REPEAT_0(d) `define REPEAT_1(d) d `define REPEAT_2(d) `REPEAT_1(d)d `define REPEAT_3(d) `REPEAT_2(d)d `define REPEAT_4(d) `REPEAT_3(d)d `define CONCAT(a, b) a``b `define REPEATC(n, d) `CONCAT(`REPEAT_, n)(d) `define REPEATT(n, d) `REPEAT_``n(d) `REPEATC(3, hello3 ) `REPEATT(4, hello4 ) //====================================================================== // Include from stringification `undef T_PREPROC_INC4 `define NODS_CONC_VH(m) `"m.vh`" `include `NODS_CONC_VH(t_preproc_inc4) `ifndef T_PREPROC_INC4 `error_here `endif //====================================================================== // Defines doing defines // Note the newline on the end - required to form the end of a define `define DEFINEIT(d) d \ `define _DEFIF_Z_0 1 `define DEFIF_NZ(d,n) `undef d `ifndef _DEFIF_Z_``n `DEFINEIT(`define d 1) `endif `DEFIF_NZ(TEMP,1) `ifndef TEMP `error "bad1" `endif `DEFIF_NZ(TEMP,0) `ifdef TEMP `error "bad0" `endif Line_Preproc_Check `__LINE__ //====================================================================== // Quoted multiline - track line numbers, and insure \\n gets propagated `define MULQUOTE "FOO \ BAR " `define MULQUOTE2(mq) `MULQUOTE mq `MULQUOTE Line_Preproc_Check `__LINE__ `MULQUOTE2("arg_line1 \ arg_line2") Line_Preproc_Check `__LINE__ //====================================================================== // bug283 `define A a `define B b `define C c // EXP: abc `define C5 `A``b```C `C5 `undef A `undef B `undef C `define XTYPE sonet `define XJOIN(__arg1, __arg2) __arg1``__arg2 `define XACTION `XJOIN(`XTYPE, _frame) EXP: sonet_frame `XACTION // `define XFRAME frame `define XACTION2 `XJOIN(sonet_, `XFRAME) EXP: sonet_frame `XACTION2 // This result varies between simulators `define sonet_frame other_frame `define XACTION3 `XTYPE``_frame EXP: sonet_frame `XACTION3 // The existance of non-existance of a base define can make a difference `define QA_b zzz `define Q1 `QA``_b EXP: module zzz ; endmodule module `Q1 ; endmodule module `Q1 ; endmodule `define QA a EXP: module a_b ; endmodule module `Q1 ; endmodule module `Q1 ; endmodule //====================================================================== // bug311 integer/*NEED_SPACE*/foo; //====================================================================== synth_test: // synopsys translate_off synthesis_turned_off // synthesis translate_on EXP: on //====================================================================== // bug441 module t; //----- // case provided // note this does NOT escape as suggested in the mail `define LEX_CAT(lexem1, lexem2) lexem1``lexem2 `define LEX_ESC(name) \name \ initial begin : `LEX_ESC( `LEX_CAT(a[0],_assignment) ) $write("GOT%%m='%m' EXP='%s'\n", "t.\\`LEX_CAT(a[0],_assignment) "); end //----- // SHOULD(simulator-dependant): Backslash doesn't prevent arguments from // substituting and the \ staying in the expansion // Note space after name is important so when substitute it has ending whitespace `define ESC_CAT(name,name2) \name``_assignment_``name2 \ initial begin : `ESC_CAT( a[0],a[1] ) $write("GOT%%m='%m' EXP='%s'\n", "t.\\a[0]_assignment_a[1] "); end `undef ESC_CAT //----- `define CAT(a,b) a``b `define ESC(name) \`CAT(name,suffix) // RULE: Ignoring backslash does NOT allow an additional expansion level // (Because ESC gets expanded then the \ has it's normal escape meaning) initial begin : `ESC(pp) $write("GOT%%m='%m' EXP='%s'\n", "t.\\`CAT(pp,suffix) "); end `undef CAT `undef ESC //----- `define CAT(a,b) a``b `define ESC(name) \name \ // Similar to above; \ does not allow expansion after substitution initial begin : `ESC( `CAT(ff,bb) ) $write("GOT%%m='%m' EXP='%s'\n", "t.\\`CAT(ff,bb) "); end `undef CAT `undef ESC //----- `define ESC(name) \name \ // MUST: Unknown macro with backslash escape stays as escaped symbol name initial begin : `ESC( `zzz ) $write("GOT%%m='%m' EXP='%s'\n", "t.\\`zzz "); end `undef ESC //----- `define FOO bar `define ESC(name) \name \ // SHOULD(simulator-dependant): Known macro with backslash escape expands initial begin : `ESC( `FOO ) $write("GOT%%m='%m' OTHER_EXP='%s'\n OUR_EXP='%s'", "t.bar ","t.\\`FOO "); end // SHOULD(simulator-dependant): Prefix breaks the above initial begin : `ESC( xx`FOO ) $write("GOT%%m='%m' EXP='%s'\n", "t.\\xx`FOO "); end `undef FOO `undef ESC //----- // MUST: Unknown macro not under call with backslash escape doesn't expand `undef UNKNOWN initial begin : \`UNKNOWN $write("GOT%%m='%m' EXP='%s'\n", "t.\\`UNKNOWN "); end //----- // MUST: Unknown macro not under call doesn't expand `define DEF_NO_EXPAND error_dont_expand initial begin : \`DEF_NO_EXPAND $write("GOT%%m='%m' EXP='%s'\n", "t.\\`DEF_NO_EXPAND "); end `undef DEF_NO_EXPAND //----- // bug441 derivative // SHOULD(simulator-dependant): Quotes doesn't prevent arguments from expanding (like backslashes above) `define STR(name) "foo name baz" initial $write("GOT='%s' EXP='%s'\n", `STR(bar), "foo bar baz"); `undef STR //----- // RULE: Because there are quotes after substituting STR, the `A does NOT expand `define STR(name) "foo name baz" `define A(name) boo name hiss initial $write("GOT='%s' EXP='%s'\n", `STR(`A(bar)), "foo `A(bar) baz"); `undef A `undef STR //---- // bug845 `define SLASHED "1//2.3" initial $write("Slashed=`%s'\n", `SLASHED); //---- // bug915 `define BUG915(a,b,c) \ $display("%s%s",a,`"b``c``\n`") initial `BUG915("a1",b2,c3); endmodule //====================================================================== //bug1225 `define X_ITEM(SUB,UNIT) `X_STRING(SUB``UNIT) `define X_STRING(A) `"A`" $display(`X_ITEM(RAM,0)); $display(`X_ITEM(CPU,)); `define EMPTY `define EMPTYP(foo) `define SOME some `define SOMEP(foo) foo `define XXE_FAMILY XXE_```EMPTY XXE_FAMILY = `XXE_FAMILY `define XXE_```EMPTY `ifdef XXE_ $display("XXE_ is defined"); `endif `define XYE_FAMILY XYE_```EMPTYP(foo) XYE_FAMILY = `XYE_FAMILY `define XYE_```EMPTYP(foo) `ifdef XYE_ $display("XYE_ is defined"); `endif `define XXS_FAMILY XXS_```SOME XXS_FAMILY = `XXS_FAMILY `define XXS_```SOME `ifdef XXS_some $display("XXS_some is defined"); `endif `define XYS_FAMILY XYS_```SOMEP(foo) XYS_FAMILY = `XYS_FAMILY `define XYS_```SOMEP(foo) `ifdef XYS_foo $display("XYS_foo is defined"); `endif //==== `ifdef NEVER `define NXE_FAMILY NXE_```EMPTY NXE_FAMILY = `NXE_FAMILY `define NXE_```EMPTY `ifdef NXE_ $display("NXE_ is defined"); `endif `define NYE_FAMILY NYE_```EMPTYP(foo) NYE_FAMILY = `NYE_FAMILY `define NYE_```EMPTYP(foo) `ifdef NYE_ $display("NYE_ is defined"); `endif `define NXS_FAMILY NXS_```SOME NXS_FAMILY = `NXS_FAMILY `define NXS_```SOME `ifdef NXS_some $display("NXS_some is defined"); `endif `define NYS_FAMILY NYS_```SOMEP(foo) NYS_FAMILY = `NYS_FAMILY `define NYS_```SOMEP(foo) `ifdef NYS_foo $display("NYS_foo is defined"); `endif `include `EMPTY `endif // NEVER //bug1227 `define INSTANCE(NAME) (.mySig (myInterface.``NAME), `INSTANCE(pa5) //====================================================================== // Stringify bug `define hack(GRP) `dbg_hdl(UVM_LOW, (`"Functional coverage enabled: GRP`")); `hack(paramgrp) `define dbg_hdl(LVL, MSG) $display ("DEBUG : %s [%m]", $sformatf MSG) `define svfcov_new(GRP) \ initial do begin `dbg_hdl(UVM_LOW, (`"Functional coverage enabled: GRP`")); end while(0) `define simple_svfcov_clk(LBL, CLK, RST, ARG) \ covergroup LBL @(posedge CLK); \ c: coverpoint ARG iff ((RST) === 1'b1); endgroup \ LBL u_``LBL; `svfcov_new(u_``LBL) module pcc2_cfg; generate `simple_svfcov_clk(a, b, c, d); endgenerate endmodule //====================================================================== // Verilog-Perl bug1668 `define stringify(text) `"text`" `stringify(`NOT_DEFINED_STR) //====================================================================== // IEEE mandated predefines `undefineall // undefineall should have no effect on these predef `SV_COV_START 0 predef `SV_COV_STOP 1 predef `SV_COV_RESET 2 predef `SV_COV_CHECK 3 predef `SV_COV_MODULE 10 predef `SV_COV_HIER 11 predef `SV_COV_ASSERTION 20 predef `SV_COV_FSM_STATE 21 predef `SV_COV_STATEMENT 22 predef `SV_COV_TOGGLE 23 predef `SV_COV_OVERFLOW -2 predef `SV_COV_ERROR -1 predef `SV_COV_NOCOV 0 predef `SV_COV_OK 1 predef `SV_COV_PARTIAL 2 Verilog-Perl-3.478/verilog/parser_sv09.v0000644000177100017500000000247213264012701020035 0ustar wsnyderwsnyder// 1800-2009 mantis1769 module mantis1769 #(N=1); if (N < 1) $error("Bad N value %d", N); endmodule // 1800-2009 mantis1134 module mantis1134_decoder #(BITS = 3, localparam OUT_BITS = 1 << BITS) (input [BITS-1:0] A, output reg [OUT_BITS-1:0] Y); assign Y = 1 << A; endmodule // 1800-2009 mantis907 module mantis907_default_parameter #(REQUIRED); endmodule module mantis1619_default_input (input integer deflt = 10); endmodule module global_anal; // Don't be anal about "global" in old code integer global = 1; global clocking z @(posedge clk); // But still get it right endclocking endmodule module bug400; assert property ( @(posedge clk) disable iff (rst || $past (rst,1,,@(posedge clk)) || $isunknown(rst)) "assert 0"); endmodule // dobbie package pkga; endpackage package pkgb; endpackage module impbegin import pkga::*; import pkgb::*; (input foobar); endmodule // msg2546 module def_cov_point; logic [7:0] data; logic [7:0] addr; covergroup c; ADDRESS : coverpoint addr { bins low[] = {[0:10]}; bins med[] = {[11:20]}; } endgroup // Can't handle this due to package parsing yaID__ETC //covergroup d; // d : coverpoint data { // bins low[] = {[0:10]}; // bins med[] = {[11:20]}; // } //endgroup endmodule Verilog-Perl-3.478/verilog/v_gate.v0000644000177100017500000000023013234726611017124 0ustar wsnyderwsnydermodule buffer ( output Z, input A); buf u_buf(Z, A); endmodule module gate ( output Z, input A); buffer u_buf(Z, A); endmodule Verilog-Perl-3.478/verilog/t_80_bar/0000755000177100017500000000000014057150520017065 5ustar wsnyderwsnyderVerilog-Perl-3.478/verilog/t_80_bar/bar.f0000644000177100017500000000000613234726611020002 0ustar wsnyderwsnyderbar.v Verilog-Perl-3.478/verilog/t_80_bar/bar.v0000644000177100017500000000042713234726611020031 0ustar wsnyderwsnyder// DESCRIPTION: Verilog::Preproc: Example source code // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2012-2012 by Wilson Snyder. // // Test -F option in vppreproc. module bar(output wire y, input wire x); assign y = x; endmodule // bar Verilog-Perl-3.478/verilog/parser_bugs.v0000644000177100017500000003137213536545407020215 0ustar wsnyderwsnyder// Not legal: // end : ADDRESS_TEST_BLOCK // See 9.8.1 // `define at EOF with no newline module bug26141 (); wire [0:3] b; wire a = b[2]; endmodule module bug26940 (); (* attribute *) assign q = {1'b0,a} +{1'b0,b}; adder u_add (.q(q),.a(d),.b(d)); initial begin # 1; q=0; if (q!=0) $stop; end endmodule module bug26968 (); reg [4:0] vect = 5'b10100; wire [4:0] tmp = { vect[0], vect[1], vect[2], vect[3], vect[4] }; initial begin #1 $display("vect=%b, tmp=%b", vect, tmp); end endmodule module bug26969 (input [31:0] ad, output [15:0] regff, input [31:0] read); bufif0 ad_drv [31:0] (ad, {16'b0, regff}, read); endmodule module bug26970; parameter A = 2'b1, B = 3'b0; parameter x = {B,B,B,A,A,B}; endmodule module bug26997; MUX_REG_8x8 PAGE_REG_B3 ( .CLK (CLK), /* .IN (DATA_RES[31:24]), .OUT (PAGE[31:24]), .EN_IN (EN_B3), .EN_OUT (PAGE_SEL), */ .TC (), .TD (), .TQ ()); endmodule module bug27013; submod u1(0); submod u2(1); endmodule module bug27036; reg [2:0] a_fifo_cam_indices[3:0], lt_fifo_cam_indices[5:0]; wire [2:0] db0_a_fifo_cam_indices = a_fifo_cam_indices[0]; endmodule module bug27037; reg mem[12:2]; reg [7:0] i; endmodule module bug27039; integer i; endmodule module bug27045( input clk, input reset, input [7:0] d, output reg [7:0] q ); parameter REG_DELAY = 0; always @(posedge clk or posedge reset) q <= #(REG_DELAY*2) d; endmodule module bug27062 (input D, output Q); p(Q, D); endmodule `timescale 1ns/1ns module bug27066; integer i; time t; realtime rt; function integer toint; input integer y; input [15:0] x; toint = x|y; endfunction endmodule module bug27067; initial $monitor( "%T %b %b %b", $time, clk1, clko1, clko2 ); initial forever @( negedge clk1 ) dclk1ff <= #50 ~ dclk1ff; endmodule module bug27072( output reg sum, input wire ci); endmodule `resetall module spec; specify specparam Tac = 0.1, Tcs = 0.2; if ( !B & !M ) ( posedge CLK => ( Q[0] : 1'bx )) = ( Tac, Tcs ); $width (negedge CLK &&& EN, Tac, 0, notif_clk); ( in1 => q ) = (3, 4); ( in1 +=> q ) = Tac; ( a, b, c *> q1, q2) = 10; ( s +*> q ) = Tcs; endspecify endmodule module bugevent; event e; initial ->e; always @ (e && e) $write("Legal\n"); endmodule module bugio (input [31:0] a, a2, output [15:0] o, o2, input ibit); endmodule module buglocal; always #(cyclehalf) begin clk <= ~clk; end always @(*) begin end initial force flag = 0; initial #(delta+0.5) CLRN <= 1; assign (weak0,weak1) VDD=1'b0; assign (weak0,weak1) VSS=1'b1; wire [71:0] #1 xxout = xxin; initial #1000_000 $finish; initial $display($time,,"Double commas are stupid"); initial for (counter[3:0] = 4'h0; counter[3:0] < limit[3:0]; counter[3:0] = counter[3:0] + 4'h1) $write(); always @(posedge(clk && !xclk) or negedge(clk && xclk) or reset) $write(); nmos # (PullTime, PullTime, 0) (PT,PU,1'b1); pulldown (strong0) pullinst (r); defparam x.y.z.PAR = 1; cdrv #5.0 clk(clk); initial PI = 3.1415926535_8979323846; always val = @ eventid 1'h1; always dly = # (2:3:4) 5'h6 ; wire \33escapeneeded = 1'b1; wire \33escapenewlineend = 1'b1; wire \noescapenewlineend = 1'b1; wire \noescapespaceend = 1'b1; endmodule module v2kparam #(parameter WIDTH = 1, parameter LENGTH = 1, LENGTH2 = 1) (output [WIDTH-1:0] myout, input [LENGTH-1:0] myin, myinb ); assign myout = myin ^ myinb ^ $callemptyparens(); endmodule module foreqn (in); input [1:0] in; reg a,b; reg [1:0] c; always for ({a,c[0]} = in; a < 1'b1; {b,c[1]} = in) begin end always for ({a,c[in]} = 0; a < 1'b1; {b,c[in]} = 2'b10) begin end endmodule module colonslash; always @* case (cond&4'b1110) 'h0://Error t = 7; 'h2:/*Another comment*/ t = 6; 'h4: t = 5; endcase endmodule module enums; enum {red, yellow, green} light; enum integer {IDLE, XX='x, S1='b01, S2='b10} state, next; enum {bronze=3, silver, gold} medal; enum { add=10, sub[5], jmp[6:8] } E1; typedef enum {NOPE, YUP} boolean; enum logic [1:0] {IDLE, DIR} STATE, NSTATE; endmodule module invec ( output logic novec, output logic [7:0] range, output logic [1:0] [7:0] arrayAndRange, output logic [2:0] [1:0] [7:0] arrayAndArrayAndRange, output reg signed novec2 ); endmodule module bug34575; wire a,b,c,d; assign #(0,0) a = 1; assign #(0:1:2) b = 1; assign #(0:1:2,0:1:2) c = 1; assign #(0:1:2,0) d = 1; endmodule module bug34649 (name); output reg name = 0; endmodule module bug34649b ( output reg name = 0 ); endmodule module bug10; initial begin x += 1; x -= 1; x /= 1; x *= 1; x |= 1; x ^= 1; x <<= 1; x >>= 1; x <<<= 1; x >>>= 1; y = x++; // Part of expression y = ++x; y = x--; y = --x; x++; // Statement ++x; x--; --x; end endmodule module bug33; integer i; initial begin unique case (i) endcase priority case (i) endcase if (i) begin end else begin end end endmodule module bug16; timeunit 0.1ns; timeprecision 1ns; endmodule parameter bug39 = 0; `default_nettype none `pragma foo = bar `default_nettype wire module bug64; parameter integer a=1,b=2; parameter real c=3.0; parameter realtime d=4.0; parameter time e=5.0; endmodule module bug166; assign {{o1,o2},o3,o4,{o5,o6}} = {{i1,i2},i3,i4,{i5,i6}}; endmodule module coverage20090318; task atask; begin end endtask endmodule module svsig; function int count (input logic [3:0] d); automatic int count = d[0]+d[1]+d[2]+d[3]; for (int i=0; i<4; i++) begin if (d[i]) count++; end return (count); endfunction task automatic autoconst; const int CONS = 8; $display("CONS=%x\n", CONS); $display("Another stmt\n"); endtask endmodule module bug_empty_func_param; //function int intfunc(int a=0, b=1); // return a+b; //endfunction always_comb begin foo = funccall(); foo = intfunc(a, b); foo = intfunc(a, .b(b)); foo = intfunc(.b(b), .a(a)); end endmodule module dotted_funcs; initial ram.dotTask(addr[31:0],ramdata); // Call task initial zz = ram.a.dotFunc(foo); // Call function endmodule module var_only_in_block; initial begin : named integer only_a_var_in_blk; end endmodule module v2k_vec_no_vec ( input [2:0] VEC, VEC2, // No direction, no port, no data type; inherits input NOVEC, // No direction, no data type; use `default_nettype input ARY [1:0], NOARY2, // Array doesn't inherit logic STILL_IN, // No direction, data type; inherits direction input logic TYPED // Logic type ); task t (input [2:0] FVEC, FVEC2, input NOVEC); begin end endtask endmodule module bugfor; initial for (a=0;a;) begin end endmodule module bug85 #(parameter type T_DATA = byte) (data); input T_DATA data; sub #(.T_DATA( T_DATA )) sub (.data(data)); endmodule module bugmodportcomma (,a,); input a; endmodule module bug168; initial $display("\nWarning! This is a\ string with a line\ continuation\ at time %0d PS", $time); endmodule module bug183 #(parameter NUM = 9 , WIDTH = 8 ) ( input logic [NUM-1:0][WIDTH-1:0] a , output logic [WIDTH-1:0] sum ); localparam NLOG = (NUM <= 2) ? 1 : (NUM <= 1024) ? 10 : 0; typedef logic [WIDTH-1:0] val_t; val_t [NLOG:0][NUM-1:0] tree; endmodule module bug192; covergroup cg192 @(posedge cclk); count_tag_busy: coverpoint countones_tag_busy { bins count[] = {[0:DEPTH]}; } endgroup: cg192 cg192 cover_ts = new(); // also bug361 endmodule function bit func_implied_in (bit i); g_bit = ~i; endfunction module sparam; specparam delay = 10; endmodule // bug221 sequence stable_before_s(sig, clks_before, clk, rst=1'b0); @(clk) !rst throughout(##1 $stable(sig)[*clks_before-1]); endsequence : stable_before_s property stable_window(sample, sig, clks_before, clks_after, clk=$default_clk ,rst=1'b0); @(clk) disable iff(rst) ## clks_before sample |-> stable_before_s(sig, clks_before, clk, rst).ended ##1 ($stable(sig)[*clks_after]); endproperty : stable_window property never(prop, clk=$default_clk , rst=1'b0); @(clk) disable iff(rst) not(prop); endproperty : never property recur_triggers(trig, n, cond, clk=$default_clk , rst=1'b0); @(clk) disable iff (rst) not ( !cond throughout (trig ##1 trig[->(n-1)]) ); endproperty : recur_triggers property data_transfer( start_ev, start_data, end_ev, end_data, clk=$default_clk ,rst=1'b0); logic [$bits(start_data)-1:0] local_data; @(clk) disable iff (rst) (start_ev, local_data = start_data) ##0 (end_ev or (!end_ev ##1 (!start_ev throughout end_ev[->1]))) |-> (local_data == end_data); endproperty : data_transfer module bug228; wire net1, net2, net3; nmos #(0:1:10, 0:1:10, 0:1:10) u (net1, net2, net3); endmodule module bug262 ( Y, {A1, A2} , B ); output Y; input A1, A2, B; endmodule wire \wire = bug282_must_keep_escape; module bug403_bug404; // Simulators vary as to if "(* /* */ )" is legal or not (* attr *) wire foo; always @ (*) begin end always @ (* ) begin end endmodule /* multi line bug459*/ module bug422; generate endgenerate endmodule module bug461; generate genvar g; // bug461 begin : topgen genvar g2; genvar g1; for (g=0; g<100; g++) begin end for (g=0; g<100; g++) begin end end for (g=0; g<100; g++) begin end endgenerate endmodule module bug507; integer x = 32'd 6; endmodule // bug_msg_887; bind path.to.example_mod example_mod_fcov uexample_mod_fcov (.*); package bug586_pkg; parameter B = 10; endpackage module non_bug586; // Verilator only input logic [bug586_pkg::B : 0] bvar; endmodule // bug_641 import "DPI-C" function bit mydpi_bug641(input a_dpi_input); // .f() in function call module fbug; initial a = f(, 1); initial a = f(.s(1), .j(2)); initial a = f(.s(), .j()); initial a = f(2); initial a = f(); endmodule parameter bug671 = 5 : 10 : 20 ; module bug256; always @(posedge clk) begin myreg1 <= # 100 7'd0; myreg1 <= # 100 'b0; myreg1 <= # 100'b0; // [#] [100] ['b0] myreg1 <= 100'b0; end endmodule module msg1491(A,B); output A; trireg (small) A; output trireg B; endmodule module msg2540 (output signed foo); endmodule module prot(); `protected I!#r#e6<_Q{{E2+]I3<[3s)1@D|'E''i!O?]jD>Jo_![Cl) #nj1]p,3^1~,="E@QZB\T)eU\pC#C|7=\$J$##A[@-@{Qk] `endprotected endmodule module prot2(); `pragma protect begin_protected `pragma protect encrypt_agent = "Whatever agent" `pragma protect encrypt_agent_info = "1.2.3" `pragma protect data_method = "aes128-cbc" `pragma protect key_keyowner = "Someone" `pragma protect key_keyname = "somekey", key_method = "rsa" `pragma protect key_block encoding = (enctype = "base64") wefjosdfjklajklasjkl `pragma protect data_block encoding = (enctype = "base64", bytes = 1059) I!#r#e6<_Q{{E2+]I3<[3s)1@D|'E''i!O?]jD>Jo_![Cl) #nj1]p,3^1~,="E@QZB\T)eU\pC#C|7=\$J$##A[@-@{Qk] `pragma protect end_protected `pragma reset protect endmodule module prot3(); //pragma protect begin_protected //pragma protect key_keyowner=Cadence Design Systems. //pragma protect key_keyname=CDS_KEY //pragma protect key_method=RC5 //pragma protect key_block zzZzZ/4ZzzZZZzzz4zZzZzZZZZzZzZ/Zz+33zZ2zz/zzzzzzzzZZZzZ4z+ZZZZz1 Z1ZzzzZZzZZzz9ZZZZ37zzZzZzZzzz9ZZzzZzZz9Zz64+z8Z7ZzZZZzzzzZZZzZz zzZzZZZzZ0463zzzzzZzZ6z00z4zZzzZZzzZzzzZZ8zzz09ZzZZZZZ== //pragma protect end_key_block //pragma protect digest_block ZzZZzzZ9ZZZZz2ZzzzZz/Zzzz8Z= //pragma protect end_digest_block //pragma protect data_block ZZZ8zZzz6ZZ/zZZ5zZZzzz3ZzzzZzZZZ6ZzZzZZZZZz1zzZZZZ7ZZZZz3Zzz+9zz 4zzz+8zZzzzzZzZZzzzZzz1Z7ZzZz+zZz8ZZZZzZ6ZzzZzZZzzZZzzZzzZzZzZzZ ZzzzzZ0zZz1ZzzZzzZzZzz== //pragma protect end_data_block //pragma protect digest_block Z4Z6zZzZ3Z7ZZ6zzZZZZzzzzZZZ= //pragma protect end_digest_block //pragma protect end_protected endmodule module bug1340; parameter B= 8 'b 1 ; endmodule module msg2931; nettype int net1_t; net1_t mynet1; nettype int net2_t with resolvefunc; net2_t mynet2; nettype net_t net3_t; net3_t mynet3; endmodule module bug1505; sub i_suba (); sub i_subb[1:2] (); sub i_subc[1:2][3:4][5:6] (); endmodule Verilog-Perl-3.478/verilog/v_hier_top.v0000644000177100017500000000173514030463163020023 0ustar wsnyderwsnyder// DESCRIPTION: Verilog-Perl: Example Verilog for testing package // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2000-2012 by Wilson Snyder. `include "v_hier_inc.vh" module v_hier_top (/*AUTOARG*/ // Inputs clk ); input clk; /* pragma jsc_clk */ defparam sub.FROM_DEFPARAM = 2; `hsub sub (/*AUTOINST*/ // Outputs .qvec (qvec[3:0]), // Inputs .avec ({avec[3],avec[2:0]}), .clk (1'b0)); missing missing (); v_recursive #(.DEPTH(3)) recursive (); // Width checks, bug65 wire WC_w1; wire [0:0] WC_w1b; wire [2:0] WC_w3; wire [-1:2] WC_w4; localparam WC_p32=0; localparam [0:0] WC_p1=0; localparam [2:0] WC_p3=0; localparam [-1:2] WC_p4=0; localparam integer WC_pint=0; // Assignments wire asn_clk; assign asn_clk = clk; endmodule localparam GLOBAL_PARAM = 1; // Local Variables: // eval:(verilog-read-defines) // End: Verilog-Perl-3.478/verilog/v_hier_inc.vh0000644000177100017500000000042614030463163020136 0ustar wsnyderwsnyder// DESCRIPTION: Verilog-Perl: Example Verilog for testing package // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2000-2012 by Wilson Snyder. `ifndef V_HIER_INC_VH `define V_HIER_INC_VH // Guard `define hsub v_hier_sub `endif // Guard Verilog-Perl-3.478/verilog/parser_sv17.v0000644000177100017500000000023114020733063020025 0ustar wsnyderwsnyder// 1800-2017 module sv17; integer i; initial begin for (i=0;;) break; for (;i!=0;) begin end for (;;++i) break; end endmodule Verilog-Perl-3.478/verilog/v_hier_top2.v0000644000177100017500000000104513422450702020076 0ustar wsnyderwsnyder// DESCRIPTION: Verilog-Perl: Example Verilog for testing package // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2000-2012 by Wilson Snyder. module v_hier_top2 (/*AUTOARG*/ // Inputs clk ); input clk; v_hier_noport noport (); v_hier_noport #(.P(1)) noportp (); //bug1393 v_hier_noport #(.P(1)) noporta[1:0] (); inout [2:0] iosig/* synthesis useioff = 1 //*synthesis fpga_attr = "BLAH=ON"//* synthesis fpga_pin = "A22"*/;/* synthesis aftersemi*/ // NetListName=F12_IO endmodule Verilog-Perl-3.478/verilog/v_comments.v0000644000177100017500000000145513234726611020043 0ustar wsnyderwsnyder`define ThirtyTwo 32 module v_comments ( a, // Pragma for a b, // pragma for b c, d, d1, d2, d3 ); input a; // comment for a inout [10:0] b; output [0:10] c; // comment for c output [ ((2*`ThirtyTwo) - 1) : 0 ] d; output [ `ThirtyTwo : 0 ] d1; output [ ( MATH - 1 ): 0 ] d2; output [ `ThirtyTwo - 1: 0 ] d3; reg d; reg [11:0] e; // Comment for e endmodule // 'Third' below must attach to 'b' becase there's no ) or , after b. module v_bug917 // modcmt (input wire a, // a-First output wire m // m-Second , output wire b // b-Third ); // Third endmodule module v_bug917p (input wire a, // a-First output wire b); // b-Secondparen // Third endmodule Verilog-Perl-3.478/verilog/t_preproc_inc4.vh0000644000177100017500000000030013234726611020737 0ustar wsnyderwsnyder// DESCRIPTION: Verilog::Preproc: Example source code // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2000-2012 by Wilson Snyder. `define T_PREPROC_INC4 Verilog-Perl-3.478/verilog/example.v0000644000177100017500000000710013234726611017315 0ustar wsnyderwsnyder// DESCRIPTION: Example top verilog file for vpassert program // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2000-2012 by Wilson Snyder. `timescale 1ns/1ns module example; pli pli (); // Put on highest level of your design integer i; `define ten 10 reg \escaped[10] ; initial begin $uinfo (0, "Welcome to a VPASSERTed file\n"); // $uinfo (1, "Printed only at debug level %0d\n",1); $uinfo (9, "Printed only at debug level %0d\n",9); // \escaped[10] = 1'b1; $uassert (\escaped[10] , "Escaped not 1\n"); $uassert_info (\escaped[10] , "Escaped not 1\n"); // i=0; $uassert (1==1, "Why doesn't 1==1??\n"); $uassert (10==`ten, "Why doesn't 10==10??\n"); $uassert (/*comm ent*/1==1, //comment /*com ent*/"Why doesn't 1==1??\n"/*com ent*/ ); // i=3'b100; $uassert_amone(\i [2:0], "amone ok\n"); i=3'b010; $uassert_amone(i[2:0], "amone ok\n"); i=3'b001; $uassert_amone(i[2:0], "amone ok\n"); i=3'b000; $uassert_amone(i[2:0], "amone ok\n"); //i=3'b011; $uassert_amone(i[2:0], "amone error expected\n"); //i=3'b110; $uassert_amone(i[2:0], "amone error expected\n"); // i=2'b10; $uassert_onehot(i[1:0], "onehot ok\n"); i=2'b01; $uassert_onehot(i[1:0], "onehot ok\n"); i=2'b10; $uassert_onehot(i[1],i[0], "onehot ok\n"); i=2'b10; $uassert_onehot({i[1],i[0]}, "onehot ok\n"); //i=2'b11; $uassert_onehot(i[2:0], "onehot error expected\n"); //i=2'b00; $uassert_onehot(i[2:0], "onehot error expected\n"); end // Test assertions within case statements initial begin i=3'b100; casez (i) 3'b100: ; 3'b000: $stop; 3'b010: $uerror("Why?\n"); default: $stop; endcase if ($time > 1000) $stop; end // Example of request/grant handshake reg clk; reg bus_req; // Request a transaction, single cycle pulse reg bus_ack; // Acknowledged transaction, single cycle pulse reg [31:0] bus_data; initial begin // Reset signals bus_req = 1'b0; bus_ack = 1'b0; bus_data = 1'b0; // Assert a request @ (posedge clk) ; bus_req = 1'b1; bus_data = 32'hfeed; // Wait for ack @ (posedge clk) ; bus_req = 1'b0; // Send ack @ (posedge clk) ; bus_ack = 1'b1; // Next request could be here @ (posedge clk) ; bus_ack = 1'b0; end always @ (posedge clk) begin $uassert_req_ack (bus_req, bus_ack /*COMMENT*/, bus_data); end // Overall control loop initial clk = 1'b0; initial forever begin #1; i = i + 1; clk = !clk; if (i==20) $uwarn (0, "Don't know what to do next!\n"); if (i==22) $uerror (0, "Guess I'll error out!\n"); end // Moved clock asserts always @* begin if (i==19) $uwarn_clk (clk,"Called at next edge (1 of 2)\n"); if (i==18) $ucover_clk (clk,"example_cover_label"); $ucover_foreach_clk(clk, "foreach_label", "27:3,1,0", (i[$ui])); end // Meta coverage disables initial begin // vp_coverage_off if (0) begin end // cover off'ed // vp_coverage_on end // Ifdef based disables initial begin `ifndef NEVER `ifdef SYNTHESIS if (1) begin end // cover on `elsif SYNTHESIS if (1) begin end // cover on `else if (1) begin end // cover off'ed `endif `ifndef SYNTHESIS if (1) begin end // cover off'ed `else if (1) begin end // cover on `endif `endif end endmodule Verilog-Perl-3.478/verilog/t_preproc_inc3.vh0000644000177100017500000000070213234726611020744 0ustar wsnyderwsnyder`line 2 "inc3_a_filename_from_line_directive" 0 // DESCRIPTION: Verilog::Preproc: Example source code // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2000-2012 by Wilson Snyder. `ifndef _EXAMPLE_INC2_V_ `define _EXAMPLE_INC2_V_ 1 `define _EMPTY // FOO At file `__FILE__ line `__LINE__ `else `error "INC2 File already included once" `endif // guard `ifdef not_defined `include "NotToBeInced.v" `endif Verilog-Perl-3.478/verilog/inc_ifdef.v0000644000177100017500000000134313234726611017573 0ustar wsnyderwsnyder// DESCRIPTION: Verilog::Preproc: Example source code // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2000-2012 by Wilson Snyder. `define EMPTY_TRUE `ifndef EMPTY_TRUE `error "Empty is still true" `endif `define A `ifdef A $display("1A"); `ifdef C $display("%Error: 2C"); `elsif A $display("2A"); `ifdef C $display("%Error: 3C"); `elsif B $display("%Error: 3B"); `else $display("3AELSE"); `endif `else $display("%Error: 2ELSE"); `endif `elsif B $display("%Error: 1B"); `ifdef A $display("%Error: noC"); `elsif A $display("%Error: noB"); `else $display("%Error: noELSE"); `endif `elsif C $display("%Error: 1C"); `else $display("%Error: 1ELSE"); `endif Verilog-Perl-3.478/verilog/v_hier_subprim.v0000644000177100017500000000106513234726611020703 0ustar wsnyderwsnyder// DESCRIPTION: Verilog-Perl: Example Verilog for testing package // // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2000-2012 by Wilson Snyder. // surefire lint_off UDPUNS primitive v_hier_prim (/*AUTOARG*/ // Outputs q, // Inputs a ); output q; input a; table 0 : 1; 1 : 0; endtable endprimitive `celldefine module bug27070(); `define W 4 parameter TAP = `W'b1001; endmodule `endcelldefine `celldefine module bug893(); reg r; initial r <=#1 '0; endmodule `endcelldefine Verilog-Perl-3.478/verilog/v_sv_pkg.v0000644000177100017500000000045313234726611017504 0ustar wsnyderwsnyder// DESCRIPTION: Verilog-Perl: Example Verilog for testing package // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2009-2012 by Wilson Snyder. `ifndef _V_SV_PKG_ `define _V_SV_PKG_ package v_sv_pkg; typedef logic [7:0] byte_t; endpackage `endif // guard Verilog-Perl-3.478/verilog/pli.v0000644000177100017500000000207313234726611016452 0ustar wsnyderwsnyder// DESCRIPTION: Example pli file for vpassert program // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2000-2012 by Wilson Snyder. `timescale 1ns/1ns module pli; // A module called PLI is required, to contain the error counts // This is required with the vpassert --nostop option, which this example uses // By default (--stop), this file isn't needed at all integer errors; initial errors = 0; integer warnings; initial warnings = 0; // Normally this would be 0 at startup, then become 1 after reset deasserts // This prevents false assertion checks during reset integer message_on; initial message_on = 1; always @ (errors or warnings) begin `ifdef OPTIONAL_EXIT_ON_WARNING if (errors!=0 || warnings!=0) begin $uinfo (0, "Errors/warnings found, exiting!\n"); $finish; end `else if (errors!=0) begin $uinfo (0, "Errors found, exiting!\n"); $finish; end else if (warnings!=0) begin $uinfo (0, {"Warnings found, ","consider stopping!\n"}); end `endif end endmodule Verilog-Perl-3.478/verilog/v_hier_subsub.v0000644000177100017500000000167113234726611020530 0ustar wsnyderwsnyder// DESCRIPTION: Verilog-Perl: Example Verilog for testing package // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2000-2012 by Wilson Snyder. module v_hier_subsub (/*AUTOARG*/ // Outputs q, // Inputs a ); parameter IGNORED = 0; input signed a; output q; wire q = a; // Test protected `pragma protect begin_protected `pragma protect encrypt_agent = "Whatever agent" `pragma protect encrypt_agent_info = "1.2.3" `pragma protect data_method = "aes128-cbc" `pragma protect key_keyowner = "Someone" `pragma protect key_keyname = "somekey", key_method = "rsa" `pragma protect key_block encoding = (enctype = "base64") wefjosdfjklajklasjkl `pragma protect data_block encoding = (enctype = "base64", bytes = 1059) I!#r#e6<_Q{{E2+]I3<[3s)1@D|'E''i!O?]jD>Jo_![Cl) #nj1]p,3^1~,="E@QZB\T)eU\pC#C|7=\$J$##A[@-@{Qk] `pragma protect end_protected `pragma reset protect //" endmodule Verilog-Perl-3.478/verilog/inc_nonl.v0000644000177100017500000000011613234726611017461 0ustar wsnyderwsnyder// The lack of a newline on the next line is intentional blah-no-newline-here>Verilog-Perl-3.478/verilog/t_86_vhier_tick_sub.v0000644000177100017500000000031713234726611021525 0ustar wsnyderwsnyder// DESCRIPTION: Verilog::Preproc: Example source code // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2000-2012 by Wilson Snyder. module t_86_vhier_tick_sub; endmodule Verilog-Perl-3.478/verilog/test.v0000644000177100017500000000074214030463163016641 0ustar wsnyderwsnyder// DESCRIPTION: Verilog-Perl: Example Verilog for testing package // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2000-2012 by Wilson Snyder. // ENCRYPT_ME module example (/*AUTOARG*/ // Outputs z, // Inputs a, b ); // See https://www.veripool.org // for what AUTOARG and friends can do for you! /*Comment // test*/ // input a; input b; output z; wire result = a|b; wire z = result; endmodule Verilog-Perl-3.478/verilog/v_sv_pgm.v0000644000177100017500000000034113234726611017502 0ustar wsnyderwsnyder// DESCRIPTION: Verilog-Perl: Example Verilog for testing package // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2009-2012 by Wilson Snyder. program v_sv_pgm; int in_pgm; endprogram Verilog-Perl-3.478/verilog/pinorder.v0000644000177100017500000000165513234726611017515 0ustar wsnyderwsnyder// DESCRIPTION: Verilog-Perl: Example Verilog for testing package // // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2003 by Wilson Snyder. module pinorder4(); wire b_i; wire d_o; wire [7:0] a_i; wire [31:0] IPCD_const = 32'h1; assign a_i = 0; assign b_i = 0; foo foo1( .y(b_i), .x(a_i), .abcconst(3'h0), .noconnect(), .def(IPCD_const)); foo foo3( b_i, a_i, 3'h0, , IPCD_const); foo2 foo2( b_i, a_i[0], d_o); endmodule module foo2(/*AUTOARG*/ // Outputs x, // Inputs z, y ); input z; input y; output x; reg x; always @(z or y) x = z & y; endmodule module foo (/*AUTOARG*/ // Inputs y, x, abcconst, noconnect, def ); input y; input x; input [2:0] abcconst; input signed [3:0] noconnect; input [31:0] def; endmodule module bug278 ( output wire ow, inout wire iow, input wire iw); endmodule Verilog-Perl-3.478/verilog/inc2.v0000644000177100017500000000035113234726611016516 0ustar wsnyderwsnyder// DESCRIPTION: Verilog::Preproc: Example source code // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2000-2012 by Wilson Snyder. At file `__FILE__ line `__LINE__ `include Verilog-Perl-3.478/verilog/v_hier_sub.v0000644000177100017500000000163013234726611020011 0ustar wsnyderwsnyder// DESCRIPTION: Verilog-Perl: Example Verilog for testing package // // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2000-2012 by Wilson Snyder. module v_hier_sub (/*AUTOARG*/ input clk, input [3:0] avec, // Comment for v_hier_sub, avec output [3:0] qvec /* Comment for v_hier_sub, qvec */ ); parameter FROM_DEFPARAM = 1; supply1 a1; v_hier_subsub #( .IGNORED('sh20) ) \subsub0 ( // Outputs .q (qvec[0]), // Inputs .a (a1)); // Comment for subsub cell generate genvar K, K_UNUSED; for (K=0; K<1; K=K+1) begin : genloop // By pin position, inside generate v_hier_subsub subsub2 (qvec[2], 1'b0); end endgenerate function foo; (* attribute *) /* synopsys metacommenttest */ input not_part_of_pinlist; foo = not_part_of_pinlist; endfunction endmodule Verilog-Perl-3.478/verilog/parser_vectors.v0000644000177100017500000000214013234726611020722 0ustar wsnyderwsnyder/* This file contains some instantiations of an unknown module that use bit vectors. */ module top(i,o); input [31:0] i; output [31:0] o; wire [3:0] somebus, someotherbus; wire somenet_1,somenet_2,somenet_3; wire [29:0] somewidebus; parameter SOMEPARAM = 10; assign somewidebus=i[31:2]; assign o[1]=somenet_1; assign o[2]=somenet_2; assign o[0]=1'b0; assign o[3]=someotherbus[2]; assign o[28:4]=25'b0; assign o[31]=~somenet_1; mod instmod_1 ( .a(somebus), .y(somenet_1) ); mod instmod_2 ( .a(somebus), .y(someotherbus[2]) ); mod instmod_3 ( .a(somewidebus[24:21]), .y(somenet_2) ); mod instmod_4 ( .a(i[31:27]), .y(o[29]) ); mod instmod_5 ( .a({somenet_1,3'b101,someotherbus[2],somewidebus[2:1]}), .y(o[30]) ); mod instmod_6 ( .a({somenet_1,3'b101,{someotherbus[2],someotherbus[2]},somewidebus[2:1]}), .y(o[30]) ); mod instmod_7 ( .a(somebus[{SOMEPARAM_3[1],SOMEPARAM_3[0]}]), .y(someotherbus[2]) ); endmodule Verilog-Perl-3.478/verilog/t_80_foo.v0000644000177100017500000000047313234726611017305 0ustar wsnyderwsnyder// DESCRIPTION: Verilog::Preproc: Example source code // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2012-2012 by Wilson Snyder. // // Test -F option in vppreproc. // This is the top level module. module foo(output wire y, input wire x); bar i_bar(y, x); endmodule // foo Verilog-Perl-3.478/vppreproc0000755000177100017500000001656514057150455016012 0ustar wsnyderwsnyder#!/usr/bin/perl -w # See copyright, etc in below POD section. ###################################################################### use FindBin qw($RealBin); use lib "$RealBin/blib/arch"; use lib "$RealBin/blib/lib"; use lib "$RealBin"; use Getopt::Long; use IO::File; use Pod::Usage; use Verilog::Preproc; use Verilog::Getopt; use strict; use vars qw($Debug $VERSION); $VERSION = '3.478'; ###################################################################### # main $Debug = 0; my $opt_output_filename = undef; my $opt_blank=1; my $opt_dump_defines; my @opt_files; my @opt_pp_flags; autoflush STDOUT 1; autoflush STDERR 1; # Option parsing Getopt::Long::config("no_auto_abbrev","pass_through"); GetOptions("debug" => \&debug); # Snarf --debug ASAP, before parse -f files my $Opt = new Verilog::Getopt(filename_expansion=>1); @ARGV = $Opt->parameter(@ARGV); Getopt::Long::config("no_auto_abbrev","no_pass_through"); if (! GetOptions ( "help" => \&usage, "debug" => \&debug, "o=s" => \$opt_output_filename, "blank!" => \$opt_blank, "comment!" => sub { push @opt_pp_flags, (keep_comments=>$_[1]); }, "dump-defines!" => \$opt_dump_defines, "line!" => sub { push @opt_pp_flags, (line_directives=>$_[1]); }, "P!" => sub { $opt_blank=0; push @opt_pp_flags, (line_directives=>$_[1]); }, "pedantic!" => sub { push @opt_pp_flags, (pedantic=>$_[1]); }, "simple!" => sub { if ($_[1]) { push @opt_pp_flags, (keep_comments=>0, line_directives=>0, ); $opt_blank=0; } }, "synthesis!" => sub { push @opt_pp_flags, (synthesis=>$_[1]); }, "version" => sub { print "Version $VERSION\n"; exit(0); }, "<>" => \¶meter, )) { die "%Error: Bad usage, try 'vppreproc --help'\n"; } if (!@opt_files) { die "%Error: vppreproc: No input filenames specified.\n"; } my $fh = IO::File->new; if ($opt_output_filename) { $fh->open(">$opt_output_filename") or die "%Error: $! $opt_output_filename\n"; } else { $fh->open(">-") or die; } my $vp = Verilog::Preproc->new(@opt_pp_flags, options=>$Opt,); $vp->debug($Debug) if $Debug; foreach my $file (@opt_files) { $vp->open($file); # Alternatively, use $vp->getall for better performance while (defined (my $line = $vp->getline())) { next if !$opt_blank && $line =~ /^\s*[\n]?$/; print $fh $line unless $opt_dump_defines; } } if ($opt_dump_defines) { foreach my $name ($Opt->define_names_sorted) { my $par = $Opt->defparams($name); $par="" if !$par; my $value = $Opt->defvalue($name); printf "`define %s%s %s\n", $name,$par,$value; } } exit(0); ###################################################################### sub usage { print "Version $VERSION\n"; pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT, -noperldoc=>1); exit(1); } sub debug { $Debug = 1; #$Verilog::Getopt::Debug = 1; } sub parameter { my $param = shift; if ($param =~ /^--?/) { die "%Error: vppreproc: Unknown parameter: $param\n"; } else { push @opt_files, "$param"; # Must quote to convert Getopt to string, bug298 } } ###################################################################### ###################################################################### ###################################################################### __END__ =pod =head1 NAME vppreproc - Preprocess Verilog code using verilog-perl =head1 SYNOPSIS vppreproc --help vppreproc [verilog_options] [-o filename] [verilog_files.v...] =head1 DESCRIPTION Vppreproc reads the Verilog files passed on the command line and outputs preprocessed output to standard out or the filename passed with B<-o>. Note vppreproc was named vppp until release 3.100, so if you're looking for vppp, this is the right replacement. The vppp name conflicted with another non-Verilog related tool. =head1 VERILOG ARGUMENTS The following arguments are compatible with GCC, VCS and most Verilog programs. =over 4 =item +define+I+I =item -DI=I Defines the given preprocessor symbol. =item -f I Read the specified file, and act as if all text inside it was specified as command line parameters. =item -f I Read the specified file, and act as if all text inside it was specified as command line parameters. Any relative paths are relative to the current directory. =item +incdir+I =item -II Add the directory to the list of directories that should be searched for include directories or libraries. =item +libext+I+I... Specify the extensions that should be used for finding modules. If for example module I is referenced, look in I.I. =item -y I Add the directory to the list of directories that should be searched for include directories or libraries. =back =head1 VPPREPROC ARGUMENTS =over 4 =item --help Displays this message and program version and exits. =item --o I Use the given filename for output instead of stdout. =item --dump-defines Suppress normal output, and instead print a list of all defines existing at the end of processing the input file. =item --noblank Removes empty lines from the output. Should be used with --noline, as if correct line numbers are needed, blank lines must be preserved for proper accounting by the program reading the output of vppreproc. =item --nocomment Remove comments. =item --noline Remove `line directives. =item -P Same as --noline --noblank, similar to "GCC -P" behavior. =item --pedantic Rigorously obey the Verilog spec. This disables the `error feature, and may disable other features that are not specified in the approved language reference manual. Defaults false. =item --simple Requests simple output, an alias for --noline, --nocomment and --noblank. =item --synthesis Define SYNTHESIS, and ignore text between "ambit", "pragma", "synopsys" or "synthesis" translate_off and translate_on meta comments. Note using metacomments is discouraged as they have led to silicon bugs (versus ifdef SYNTHESIS); see L. =item --version Displays program version and exits. =back =head1 LANGUAGE EXTENSIONS Vppreproc supports the preprocessing constructs defined in the Verilog 2001 and SystemVerilog 2005 standards. The following additional constructs may be added to your Verilog code. =over 4 =item `__FILE__ The __FILE__ define expands to the current filename as a string, like C++'s __FILE__. This was incorporated into to the 1800-2009 standard (but supported by Verilog-Perl since 2004!) =item `__LINE__ The __LINE__ define expands to the current filename as a string, like C++'s __LINE__. This was incorporated into to the 1800-2009 standard (but supported by Verilog-Perl since 2004!) =item `error I This will report an error when encountered, like C++'s #error. =back =head1 DISTRIBUTION Verilog-Perl is part of the L free Verilog EDA software tool suite. The latest version is available from CPAN and from L. Copyright 2000-2021 by Wilson Snyder. This package is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. =head1 AUTHORS Wilson Snyder =head1 SEE ALSO L, L, L =cut ###################################################################### Verilog-Perl-3.478/vpassert0000755000177100017500000014412514057150455015633 0ustar wsnyderwsnyder#!/usr/bin/perl -w # See copyright, etc in below POD section. ###################################################################### require 5.005; use FindBin qw($RealBin); use lib "$RealBin/blib/arch"; use lib "$RealBin/blib/lib"; use lib "$RealBin"; use File::Copy; use FindBin qw($RealBin); use Getopt::Long; use IO::Dir; use IO::File; use POSIX qw(); use Pod::Usage; use strict "vars"; use Verilog::Parser; use Verilog::Getopt; use vars qw ($VERSION $Debug $Opt %Vpassert_Conversions $Vpassert_Conversions_Regexp $Opt_Synthcov $Opt_Vericov @Endmodule_Inserts $Last_Parser $Last_Module $Last_Task $ReqAck_Num $Vericov_Enabled $Got_Change @Sendout %Insure_Symbols %Files %Files_Read %File_Dest ); $VERSION = '3.478'; ###################################################################### # 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(@_); }, ); ###################################################################### # main $Debug = 0; my $output_dirname = ".vpassert/"; my $Opt_Quiet = 0; # Don't blab about what files are being worked on my $Opt_Axiom; # Athdl my $Opt_AllFiles = 0; # Preprocess all files my $Opt_Call_Error; my $Opt_Call_Info; my $Opt_Call_Warn; my $Opt_Date = 0; # Check dates my $Opt_NoPli = 0; # Delete all pli calls $Opt_Vericov = 0; # Add vericov on/off comments (messes up line # counts) my $Opt_RealIntent; # RealIntent my $Opt_Stop = 1; # Put $stop in error messages my $Opt_Verilator; # Verilator my $Opt_Vcs; # Vcs my $Last_ArgsDiffer; # Last run's Opt_* mismatch my $Opt_Minimum; # Include `__message_minimum my @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; Getopt::Long::config("no_auto_abbrev","pass_through"); GetOptions("debug" => \&debug); # Snarf --debug ASAP, before parse -f files $Opt = new Verilog::Getopt(); @ARGV = $Opt->parameter(@ARGV); # Strip -y, +incdir+, etc Getopt::Long::config("no_auto_abbrev","no_pass_through"); if (! GetOptions ( # When add flags, update _switch_line also as appropriate "-o=s" => \$output_dirname, "allfiles!" => \$Opt_AllFiles, "axiom!" => \$Opt_Axiom, "call-error=s" => \$Opt_Call_Error, "call-info=s" => \$Opt_Call_Info, "call-warn=s" => \$Opt_Call_Warn, "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, "synthcov!" => \$Opt_Synthcov, "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); }, "vcs!" => \$Opt_Vcs, "<>" => \¶meter, )) { die "%Error: Bad usage, try 'vpassert --help'\n"; } sub _switch_line { # If any of these flags change, we must regenerate output my $sw = ""; $sw .= " --axiom" if $Opt_Axiom; $sw .= " --call-error=$Opt_Call_Error" if $Opt_Call_Error; $sw .= " --call-info=$Opt_Call_Info" if $Opt_Call_Info; $sw .= " --call-warn=$Opt_Call_Warn" if $Opt_Call_Warn; $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 .= " --synthcov" if $Opt_Synthcov; $sw .= " --timeformat-precision=$Opt_Timeformat_Precision" if $Opt_Timeformat_Precision; $sw .= " --timeformat-units=$Opt_Timeformat_Units" if $Opt_Timeformat_Units; $sw .= " --vericov" if $Opt_Vericov; $sw .= " --verilator" if $Opt_Verilator; $sw .= " --vcs" if $Opt_Vcs; 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 (sort keys %Vpassert_Conversions ) { print "\tToken $tok\n"; } print "\n"; pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT, -noperldoc=>1); 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"; # Must quote to convert Getopt to string, bug298 } ###################################################################### ###################################################################### ###################################################################### ###################################################################### ###################################################################### ###################################################################### # Functions that transform the tokens # Note -I is specially detected below sub 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()); push @Sendout, [$Last_Parser->lineno, ""]; # Make sure message_header newlines leave us in right place 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, [0, $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); foreach my $i (@values) { my $nexpr = $expr; $nexpr =~ s/\$ui\b/($i)/g or die "%Error: ".$Last_Parser->fileline.": No \$ui in \$ucover_foreach_clk expression: $expr\n"; _ucover_clk_guts($clk, $label."__".$i, "(${nexpr})"); } } sub ucover_clk { my $clk = shift; my $label = shift; $#_==-1 or die "%Error: ".$Last_Parser->fileline.": Extra arguments to \$ucover_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"; _ucover_clk_guts($clk,$label, "1'b1"); } sub _ucover_clk_guts { my $clk = shift; my $label = shift; my $expr = shift; $ReqAck_Num or die "%Error: ".$Last_Parser->fileline.": \$ucover_clk can't find module statement\n"; my $sig = "_ucoverclk${ReqAck_Num}"; $Insure_Symbols{$Last_Module}{$sig} = ['reg', 0]; # Make this symbol exist if doesn't $ReqAck_Num++; sendout("/*vpassert*/$sig=${expr};/*vpassert*/"); _insert_always_begin('cover', "/*vpassert*/ $sig=1'b0; /*vpassert*/"); # Note correct `line is required to see correct cover point push @Endmodule_Inserts, [$Last_Parser->lineno," $label: cover property (@(posedge $clk) ($sig));\n"]; } sub _insert_always_begin { my $for_assert = shift; my $text = shift; my $beginl; for (my $l = $#Sendout; $l>=0; $l--) { my $tok = $Sendout[$l][1]; #print "HUNT $l: ".($beginl||"").": $tok\n"; # Fortunately all comments must be a single array entry $tok =~ s!//.*?\n!!go; $tok =~ s!/\*.*?\*/$!!go; if ($tok =~ /\bbegin\b/) { $beginl = $l; } if ($tok =~ /\b(if|initial|final)\b/) { $beginl = undef; } if ($tok =~ /\bposedge\b/) { if ($for_assert ne 'cover') { die "%Error: ".$Last_Parser->fileline.": \$uerror_clk is under a posedge clk, use \$uerror instead\n"; } } if ($tok =~ /\balways\b/) { last if !defined $beginl; # And die below my $insert = $text; $Sendout[$beginl][1] =~ s/(\bbegin\b)/$1$insert/; return; } } die "%Error: ".$Last_Parser->fileline.": \$uerror_clk is not somewhere under an 'always begin' block\n"; } sub get_lineinfo { # Align the lineinfo so that right hand sides are aligned my $message_filename = $Last_Parser->filename; $message_filename =~ s/^.*\///g; my $lineinfo = substr($message_filename, 0, 17); # Don't make too long $lineinfo = $lineinfo . sprintf(":%04d:", $Last_Parser->lineno ); $lineinfo = sprintf("%-21s", $lineinfo); } use vars qw($Msg_Header_Level); sub coverage_off { my $subcall = shift; my $out = ""; if (!$Msg_Header_Level) { $out .= "/*summit modcovoff -bpen*/\n" if $Vericov_Enabled; $out .= "/*ri userpass BE on*/\n" if $Opt_RealIntent; $out .= "/*VCS coverage off*/\n" if $Opt_Vcs; $out .= "/*ax_line_coverage_off*/\n" if $Opt_Axiom; $out .= "/*verilator coverage_off*/\n" if $Opt_Verilator && !$subcall; $out = "\n".$out if $out; $out .= "/*vpassert*/"; $Got_Change = 1; } $Msg_Header_Level++; return $out; } sub coverage_on { my $subcall = shift; my $out = ""; if ((--$Msg_Header_Level)==0) { $out .= "/*verilator coverage_on*/\n" if $Opt_Verilator && !$subcall; $out .= "/*VCS coverage on*/\n" if $Opt_Vcs; $out .= "/*ax_line_coverage_on*/\n" if $Opt_Axiom; $out .= "/*ri userpass BE off*/\n" if $Opt_RealIntent; $out .= "/*summit modcovon -bpen*/\n" if $Vericov_Enabled; $out = "\n".$out if $out; $out = '/*vpassert*/'.$out; } return $out; } sub message_header { my $off = coverage_off(1); my $out = $off; $out .= "begin "; $out .= "/*verilator coverage_block_off*/" if ($Opt_Verilator && $off); return $out; } sub message_trailer { my $out = 'end '; $out .= coverage_on(1); return $out; } sub message { my $lineinfo = shift; my $show_id = shift; my $char = shift; my $cond = shift; my $otherargs = shift; my @params = @_; # Level, printf string, args if ($params[0] =~ /^\s*\"/) { # No digit in first parameter # Push new parameter [0] as a 0. unshift @params, '0'; } $params[1] = convert_concat_string($params[1]); unless ($char =~ /^-I/i) { if ($params[1] =~ s/\s*\"\s*$//) { # For a well-formed message, $params[1] now ends in "\\n". $params[1] .= "\\n" if $params[1] !~ /\\n$/; $params[1] = $params[1]."${char}: In %m\\n\""; } } ($params[0] =~ /^\s*[0-9]/) or die "%Error: ".$Last_Parser->fileline.": Non-numeric \$message first argument: $params[0]\n"; ($params[1] =~ /^\s*\"/) or die "%Error: ".$Last_Parser->fileline.": Non-string \$message second argument: $params[1]\n"; my $out = message_header(); # These long lines without breaks are intentional; I want to preserve line numbers my $is_warn = (($char eq '%%E') || ($char eq '%%W') || ($char eq "-i")); if ($cond ne "1") { # Conditional code, for $uassert # Note this will only work in RTL code! $out .= "if (!($cond) && (`__message_on)) "; } elsif ($params[0] =~ /^\s*0\s*$/) { # Always enabled if ($is_warn) { $out .= "if (`__message_on) "; } } else { # Complex test $Insure_Symbols{$Last_Module}{__message} = ['integer',5]; # Make this symbol exist if doesn't my $chk = 'if ((__message >= (' . $params[0] . '))'; $chk .= ' && (`__message_minimum >= (' . $params[0] . '))' if $Opt_Minimum; $chk .= " && (`__message_on) " if $is_warn; $chk .= ') '; $out .= $chk; } my $task; my $call; if (($char eq '-I') || ($char eq '-i')) { if ($Opt_Call_Info) { $call = $Opt_Call_Info; } } elsif ($char eq '%%E') { if ($Opt_Call_Error) { $call = $Opt_Call_Error; } else { $task = ($Opt_Stop ? '$stop;' : "`pli.errors = `pli.errors+1;"); } } elsif ($char eq '%%W') { if ($Opt_Call_Error) { $call = $Opt_Call_Warn; } else { $task = ($Opt_Stop ? '$stop;' : "`pli.warnings = `pli.warnings+1;"); } } else { die "%Error: Unknown message character class '$char'\n"; } { # if's body $out .= "begin"; $out .= " \$timeformat($Opt_Timeformat_Units, $Opt_Timeformat_Precision,\"\",20);" if defined $Opt_Timeformat_Units; $out .= " \$write (\"[%0t] ${char}:${lineinfo} " if !$call; $out .= " ${call} (\"" if $call; my $par = $params[1]; $par =~ s/^\s*\"//; $out .= "$par"; $out .= ",\$time" if !$call; $out .= $otherargs; for my $parn (2 .. $#params) { my $p = $params[$parn]; $out .= ", $p"; print "MESSAGE $char, Parameter $p\n" if ($Debug); } $out .= ');'; $out .= $task if $task; $out .= ' end '; } $out .= message_trailer(); return $out; } ###################################################################### sub _convert_foreach_comma { my $in = shift; # Similar to Verilog::Language::split_bus my @out; $in =~ s/\s+//g; while ($in =~ s!,?(((\d+):(\d+))|(\d+))!!) { if (defined $3 && defined $4) { if ($3<$4) { foreach (my $i=$3; $i<=$4; $i++) { push @out, $i; } } else { foreach (my $i=$3; $i>=$4; $i--) { push @out, $i; } } } elsif (defined $5) { push @out, $5; } } $in eq "" or die "%Error: ".$Last_Parser->fileline.": Strange range expression: $in\n"; return @out; } sub convert_concat_string { my $string = shift; # Convert {"string"} or {"str","in","g"} to just "string" # Beware embedded quotes "\"" return $string if ($string !~ /^\s*\{\s*(\".*)\s*\}\s*$/); my $in = $1; my $out = ""; my $quote; my $slash; for (my $i=0; $ilineno, $string]; $Got_Change = 1; } ###################################################################### ###################################################################### ###################################################################### ###################################################################### sub form_conversions_regexp { # Create $Vpassert_Conversions_Regexp, a regexp that matches any of the conversions # This regexp will allow us to quickly look at the file and ignore it if no matches my $re = ''; my $last_tok = "\$ignore"; foreach my $tok (sort (keys %Vpassert_Conversions)) { ($tok =~ s/^\$//) or die "%Error: Vpassert_Conversion $tok doesn't have leading \$\n"; if (substr ($tok, 0, length($last_tok)) eq $last_tok) { #print "Suppress $tok $last_tok\n" if $Debug; } else { $re .= "|" if $re; $re .= '\$'.$tok; $last_tok = $tok; } } if ($Opt_NoPli) { $re .= "|" if $re; $re .= '\$'; } if ($Opt_Synthcov) { $re .= "|" if $re; $re .= 'SYNTHESIS'; } $re = "(".$re.")"; $re = "\$NEVER_MATCH_ANYTHING" if $re eq '\$()'; #print "CV REGEXP $re\n" if $Debug; $Vpassert_Conversions_Regexp = qr/$re/; } sub vpassert_process { # Read all signals in this filename # Return TRUE if the file changed my $filename = shift; my $outname = shift; $Got_Change = shift; # True if should always write output, not only if have change if ($outname =~ /[\/\\]$/) { # Directory, not file, so append filename my $basename = $filename; $basename =~ s/.*[\/\\]//g; $outname .= $basename; } print "vpassert_process ($filename, $outname, $Got_Change)\n" if ($Debug); ($filename ne $outname) or die "%Error: $filename: Would overwrite self."; @Sendout = (); $Msg_Header_Level = 0; @instance_tests_list = (); # Set up parsing my $parser = new Verilog::Vpassert::Parser; $parser->filename($filename); $parser->lineno(1); $Last_Parser = $parser; # Open file for reading and parse it my $fh = IO::File->new("<$filename") or die "%Error: $! $filename."; if (!$Got_Change) { while (<$fh>) { goto diff if (/$Vpassert_Conversions_Regexp/); } print "$filename: No dollars, not processing\n" if ($Debug); return; diff: $fh->seek(0,0); $. = 1; } while (my $line = $fh->getline() ) { $parser->parse($line); } $parser->eof; push @Sendout, [$Last_Parser->lineno, $parser->unreadback()]; $parser->unreadback(''); $fh->close; # Hack the output text to add in the messages variable foreach my $mod (sort keys %Insure_Symbols) { my $insert=""; my $n=0; # Some compilers choke if lines get too long; foreach my $sym (sort keys %{$Insure_Symbols{$mod}}) { #if ! $module_symbols{$sym} # For now always put it in my $type = $Insure_Symbols{$mod}{$sym}[0]; my $value = $Insure_Symbols{$mod}{$sym}[1]; $insert .= "$type $sym; initial $sym = $value;"; if (++$n > 10) { $insert .= "\n"; $n=0; } } if ($insert) { my $hit; for (my $l = $#Sendout; $l>=0; $l--) { my $tok = $Sendout[$l][1]; if ($tok =~ m%/\*vpassert beginmodule $mod\*/%) { my $lineno = $Sendout[$l][0]; if ($Opt_Line) { $insert .= "\n`line ".$lineno." \"".$Last_Parser->filename."\" 0\n"; } $tok =~ s%/\*vpassert beginmodule $mod\*/%/*vpassert*/$insert%g or die; # Must exist, found above! $Sendout[$l][1] = $tok; $hit = 1; # Don't exit the loop, keep looking for more. # It's possible there's a `ifdef with multiple "module x" headers } } $hit or die "vpassert %Error: $filename: Couldn't find symbol insertion point in $mod\n"; } } $#Endmodule_Inserts < 0 or die "vpassert %Error: $filename: Couldn't find endmodule\n"; # Put out the processed file print "Got_Change? $Got_Change $outname\n" if ($Debug); if ($Got_Change) { my $date = localtime; $fh->open(">$outname") or die "%Error: Can't write $outname."; my $curline = -1; my $needline = 1; # No newline so line counts not affected print $fh "/* Generated by vpassert; File:\"$filename\" */"; my @out; foreach my $outref (@Sendout) { #print "CL $curline WL $outref->[0] TT $outref->[1]\n"; if ($outref->[0]) { $needline = $outref->[0]; } if ($curline != $needline) { push @out, "\n`line $needline \"$filename\" 0\n" if $Opt_Line; $curline = $needline; } push @out, $outref->[1]; $curline++ while ($outref->[1] =~ /\n/g); } my $out = join('',@out); # Simplify redundant `lines to save space $out =~ s%(\`line[^\n]*)\n[ \t\n]*(\`line[^\n]*\n)%$2%mg; $out =~ s%\n+(\n\`line[^\n]*)%$1%mg; print $fh $out; $fh->close; if (defined $Files{$filename}{mtime}) { utime $Files{$filename}{mtime}, $Files{$filename}{mtime}, $outname; } } return $Got_Change; } #---------------------------------------------------------------------- sub bitwidth { # Take a string like "{foo[5:0],bar} and return bit width (7 in this case) my $statement = shift; my $bits = 0; foreach my $sig (split /,\{\]/, $statement) { if ($sig =~ /[a-z].* \[ (-?[0-9]+) : (-?[0-9]+) \]/x) { $bits += ($1 - $2) + 1; } elsif ($sig =~ /[a-z]/) { $bits ++; } } return $bits; } #---------------------------------------------------------------------- #---------------------------------------------------------------------- #---------------------------------------------------------------------- sub vpassert_db_read_file { # Read when the unprocessed files were last known to not need processing my $filename = shift; my $fh = IO::File->new("<$filename") or return; # no error if fails while (my $line = $fh->getline) { chomp $line; if ($line =~ /^switch\s*(.*$)/) { my $old = $1; my $now = _switch_line(); $old =~ s/\s+//g; $now =~ s/\s+//g; $Last_ArgsDiffer = ($old ne $now); } else { my ($tt_cmd, $tt_file, $tt_mtime, $tt_size) = split(/\t/,$line); $tt_cmd .= ""; # Warning removal $Files_Read{$tt_file}{mtime} = $tt_mtime; $Files_Read{$tt_file}{size} = $tt_size; } } $fh->close; } sub vpassert_db_write_file { # Save which unprocessed files did not need processing my $filename = shift; my $fh = IO::File->new(">$filename") or die "%Error: $! $filename.\n"; $fh->print("switch\t"._switch_line()."\n"); foreach my $file (sort (keys %Files)) { next if !$Files{$file}{mtime}; $fh->print("unproc\t$file\t$Files{$file}{mtime}\t$Files{$file}{size}\n"); } $fh->close; } #---------------------------------------------------------------------- sub vpassert_recursive_prelude { # What to do before processing any files my $destdir = shift; $destdir .= "/" if ($destdir !~ /[\\\/]$/); %Files = (); %Files_Read = (); vpassert_db_read_file("${destdir}/.vpassert_skipped_times"); form_conversions_regexp(); if (! -d $destdir) { mkdir($destdir,0777) or die "%Error: Can't mkdir $destdir\n"; } # Don't include directory in time saving, as path may change dep how run my $dest_mtime = $Files_Read{"vpassert"}{mtime} || 0; if (!$Opt_Date || ($Prog_Mtime > $dest_mtime) || $Last_ArgsDiffer) { # Flush the whole read cache %Files_Read = (); print "\t VPASSERT (or overall flags) changed... Two minutes...\n"; print "\t Mtime = $Prog_Mtime\n" if $Debug; } #print "FF $Opt_Date, $Prog_Mtime, $dest_mtime, $Opt_Vericov, $Last_Vericov\n"; $Files{"vpassert"}{mtime} = $Prog_Mtime; $Files{"vpassert"}{size} = 1; } sub vpassert_recursive_postlude { my $destdir = shift; $destdir .= "/" if ($destdir !~ /[\\\/]$/); # What to do after processing all files # Check for deletions foreach my $srcfile (sort keys %Files_Read) { if ($Files_Read{$srcfile}{mtime} && !$Files{$srcfile}{mtime}) { (my $basefile = $srcfile) =~ s/.*\///; my $destfile = "$destdir$basefile"; # A file with the same basename may now be in a different dir, # and already processed, so don't delete it. if (!$File_Dest{$destfile}) { print "\t vpassert: Deleted? $srcfile\n" if !$Opt_Quiet; unlink $destfile; } } } vpassert_db_write_file("${destdir}/.vpassert_skipped_times"); } sub vpassert_recursive { # Recursively process this directory or file argument my $srcdir = shift; my $destdir = shift; print "Recursing $srcdir $destdir\n" if ($Debug); if (-d $srcdir) { $srcdir .= "/" if ($srcdir !~ /[\\\/]$/); $destdir .= "/" if ($destdir !~ /[\\\/]$/); my $dh = new IO::Dir $srcdir or die "%Error: Could not directory $srcdir.\n"; while (defined (my $basefile = $dh->read)) { my $srcfile = $srcdir . $basefile; if ($Opt->libext_matches($srcfile)) { next if -d $srcfile; vpassert_process_one($srcfile, $destdir); } } $dh->close(); } else { # Plain file vpassert_process_one($srcdir, $destdir, 1); } } use vars (qw(%file_directory)); sub vpassert_process_one { # Process one file, keeping cache consistent my $srcfile = shift; my $destdir = shift; (my $basefile = $srcfile) =~ s!.*[/\\]!!; my $destfile = "$destdir$basefile"; $File_Dest{$destfile} = 1; my @stat = (stat($srcfile)); my $src_mtime = $stat[9] || 0; my $src_size = $stat[7] || 0; my $dest_mtime = $Files_Read{$srcfile}{mtime} || 0; # Mark times #print "BCK $basefile $src_mtime, $dest_mtime\n"; $Files{$srcfile}{mtime} = $src_mtime; $Files{$srcfile}{size} = $src_size; if ($src_mtime != $dest_mtime || $src_size != $Files_Read{$srcfile}{size}) { my $no_output = 0; unlink $destfile; $Total_Files++; if (! vpassert_process ($srcfile, $destfile, $Opt_AllFiles)) { # Didn't need to do processing $no_output = 1; print "nooutput: vpassert_process ($srcfile, $destfile,0 )\n" if ($Debug); nochange_copy($srcfile,$destfile); } else { # Make sure didn't clobber another directory's file print "madenew: vpassert_process ($srcfile, $destfile,0 )\n" if ($Debug); if ($file_directory{$destfile}) { my $old = $file_directory{$destfile}; die "%Error: Two files with same basename: $srcfile, $old\n"; # This warning is to prevent search order dependence in the # verilog search path. It also makes sure we don't clobber # one file with another by the same name in the .vpassert directory } } if (!$Opt_Quiet) { print " VPASSERT'ing file ($Total_Files) $srcfile ", ($dest_mtime ? "(Changed)":"(New)"), ($no_output ? " (no-output)" : ""),"\n"; } } $file_directory{$destfile} = $srcfile; } sub nochange_copy { my $srcfile = shift; my $dstfile = shift; my $fhw = IO::File->new(">$dstfile"); my $fhr = IO::File->new("<$srcfile"); if (!$fhr) { warn "%Warning: $! $srcfile\n"; return; } $fhw->print("`line 1 \"$srcfile\" 0\n") if $Opt_Line; # Unfortunately File::Copy::copy overwrites our line statement. my $eof; my $chunk = POSIX::BUFSIZ; # On 5.8.8 this isn't a number but text $chunk = 8*1024 if $chunk !~ /^\d+$/; while (!$eof) { my $data = ''; $!=undef; my $rv = $fhr->sysread($data, $chunk, 0); #print "RRV=$rv b=$!\n" if $Debug; $eof = 1 if !$rv || (!$fhr || ($! && $! != POSIX::EWOULDBLOCK)); $fhw->print($data); } } ###################################################################### ###################################################################### ###################################################################### ###################################################################### # Parser functions called by Verilog::Parser package Verilog::Vpassert::Parser; ## no critic require Exporter; use Verilog::Parser; use base qw(Verilog::Parser); BEGIN { # Symbols to alias to global scope use vars qw(@GLOBALS); @GLOBALS = qw ( $Debug @Sendout $Last_Task $Last_Module $Opt_Vericov $Opt_Synthcov $ReqAck_Num $Vericov_Enabled %Vpassert_Conversions %Insure_Symbols @Endmodule_Inserts ); foreach (@GLOBALS) { my ($type,$sym) = /^(.)(.*)$/; *{"$sym"} = \${"::$sym"} if ($type eq "\$"); *{"$sym"} = \%{"::$sym"} if ($type eq "%"); *{"$sym"} = \@{"::$sym"} if ($type eq "@"); } } use strict; use vars (@GLOBALS, qw ( $Last_Keyword $Last_Lineno $Last_Prekwd @Last_Symbols @Last_Number_Ops $Need_Vpassert_Symbols @Params $Param_Num $Parens $PreLevel @PreCovOff $In_Message )); use Verilog::Parser; sub new { my $class = shift; my $self = $class->SUPER::new(); bless $self, $class; # State of the parser # These could be put under the class, but this is faster and we only parse # one file at a time @Endmodule_Inserts = (); $Last_Keyword = ""; $Last_Lineno = 0; $Last_Prekwd = 0; @Last_Symbols = (); @Last_Number_Ops = (); $Last_Task = ""; $Last_Module = ""; $Vericov_Enabled = $Opt_Vericov; $Need_Vpassert_Symbols = 0; $Param_Num = 0; $Parens = 0; $PreLevel = 0; @PreCovOff = (); $In_Message = 0; #%module_symbols = (); %Insure_Symbols = (); @Params = (); return $self; } sub keyword { # Callback from parser when a keyword occurs my ($parser, $token) = @_; my $since = $parser->unreadback(); $parser->unreadback(''); $Last_Keyword = $token; @Last_Symbols = (); @Last_Number_Ops = (); if ($Opt_Vericov && (($token eq "case") || ($token eq "casex") || ($token eq "casez"))) { push @Sendout, [$Last_Lineno, $since]; push @Sendout, [$Last_Lineno, "\n/*summit implicit off*/\n"] if $Vericov_Enabled; push @Sendout, [$Last_Lineno, $token]; } elsif ($Opt_Vericov && ($token eq "endcase")) { push @Sendout, [$Last_Lineno, $since . $token]; push @Sendout, [$Last_Lineno, "\n/*summit implicit on*/\n"] if $Vericov_Enabled; } elsif ($token eq "endmodule") { if ($#Endmodule_Inserts >= 0) { push @Sendout, @Endmodule_Inserts; @Endmodule_Inserts = (); } push @Sendout, [$Last_Lineno, $since . $token]; } else { push @Sendout, [$Last_Lineno, $since . $token]; } $Last_Lineno = $parser->lineno; } sub symbol { # Callback from parser when a symbol occurs my ($parser, $token) = @_; my $since = $parser->unreadback(); $parser->unreadback(''); if ($In_Message) { $Params[$Param_Num] .= $since . $token; } else { if ($Vpassert_Conversions {$token} || ($Opt_NoPli && $token =~ /^\$/ && $Parens==0)) { push @Sendout, [$Last_Lineno, $since]; print "Callback SYMBOL $token\n" if ($Debug); $In_Message = 1; $Param_Num = 1; @Params = (); $Params[0] = $token; } else { # Actually a keyword; we check for that too push @Sendout, [$Last_Lineno, $since . $token]; } } if ($Last_Keyword eq "task") { $Last_Task = $token; $Last_Keyword = ""; $Parens = 0; } if ($Last_Keyword eq "module") { $Last_Module = $token; $Last_Keyword = ""; $Need_Vpassert_Symbols = 1; $ReqAck_Num = 1; $Parens = 0; } if ($Last_Prekwd) { if ($Last_Prekwd eq "`ifdef" || $Last_Prekwd eq "`elsif" || $Last_Prekwd eq "`ifndef") { if ($token eq "SYNTHESIS") { my $ndef = ($Last_Prekwd eq "`ifndef"); $PreCovOff[$PreLevel] = $ndef; if ($PreCovOff[$PreLevel] && $Opt_Synthcov) { push @Sendout, [0, ::coverage_off(0)]; } } else { $PreCovOff[$PreLevel] = 0; } } $Last_Prekwd = 0; } push @Last_Symbols, $token; $Last_Lineno = $parser->lineno; } sub number { # Callback from parser when a number occurs my ($parser, $token) = @_; my $since = $parser->unreadback(); $parser->unreadback(''); if ($In_Message) { print "Callback NUMBER $token\n" if ($Debug); $Params[$Param_Num] .= $since . $token; } else { push @Sendout, [$Last_Lineno, $since . $token]; } push @Last_Number_Ops, $token; $Last_Lineno = $parser->lineno; } sub operator { # Callback from parser when a operator occurs my ($parser, $token) = @_; my $since = $parser->unreadback(); $parser->unreadback(''); if ($In_Message) { print "Callback OPERATOR $token ($Parens, $Param_Num)\n" if ($Debug); if (($token eq ',') && ($Parens==1)) { # Top level comma $Params[$Param_Num] .= $since; $Param_Num ++; } elsif (($token eq ';' && ($Parens==0))) { # Final statement close if ($In_Message) { if ($Opt_NoPli) { # "" doesn't work, as need semi for "if (1) $x()" # ";" doesn't work, as need empty for "begin $x() end" ::sendout("begin end "); for (my $p=0; $p<=$#Params; $p++) { while ($Params[$p]=~/\n/g) { ::sendout("\n"); } } } elsif (defined $Vpassert_Conversions {$Params[0]}) { #print " CALLPRE ",join(':',@Params),"\n" if $Debug; my $nl = ""; for (my $p=0; $p<=$#Params; $p++) { while ($Params[$p]=~/\n/g) { $nl .= "\n"; } $Params[$p] = Verilog::Language::strip_comments($Params[$p]); $Params[$p]=~ s/\n//g; } my $func = $Vpassert_Conversions {$Params[0]}; print " CALL ",join(':',@Params),"\n" if $Debug; &$func(@Params); ::sendout($nl) if $nl; # Adjust for \n's in params } else { ::sendout(""); } } $In_Message=0; } elsif (($token eq ')' || $token eq '}') && ($Parens==1)) { # Final paren $Params[$Param_Num] .= $since; } elsif ($token eq ')' || $token eq '}') { # Other paren $Params[$Param_Num] .= $since . $token; } elsif ($token eq '(' || $token eq '{') { if ($Parens!=0) { $Params[$Param_Num] .= $since . $token; } } else { $Params[$Param_Num] .= $since . $token; } } elsif ($Need_Vpassert_Symbols && ($token eq ';')) { $Need_Vpassert_Symbols = 0; # Squeeze it after module (..); push @Sendout, [$Last_Lineno, $since . $token . '/*vpassert beginmodule '.$Last_Module.'*/']; } else { push @Sendout, [$Last_Lineno, $since . $token]; } # Track parens if ($token eq '(' || $token eq '{') { $Parens++; } elsif ($token eq ')' || $token eq '}') { $Parens--; } push @Last_Number_Ops, $token; $Last_Lineno = $parser->lineno; } sub string { # Callback from parser when a string occurs my ($parser, $token) = @_; my $since = $parser->unreadback(); $parser->unreadback(''); if ($In_Message) { print "Callback STRING $token\n" if ($Debug); $Params[$Param_Num] .= $since . $token; } else { push @Sendout, [$Last_Lineno, $since . $token]; if (($Last_Keyword eq "`include") && ($token =~ /\//)) { print STDERR "%Warning: ".$parser->fileline.": `include has directory," . " remove and add +incdir+ to input.vc\n"; } } $Last_Lineno = $parser->lineno; } sub comment { # Callback from parser when a comment # *** To speed things up, this is only invoked when doing vericov my ($parser, $token) = @_; if (!$Opt_Vericov && $token !~ /_coverage_/) { $parser->unreadback($parser->unreadback() . $token); return; } my $since = $parser->unreadback(); $parser->unreadback(''); if ($Opt_Vericov) { if ($token =~ /summit\s+modcovon/ || $token =~ /simtech\s+modcovon/) { $Vericov_Enabled = 1; } elsif ($token =~ /summit\s+modcovoff/ || $token =~ /simtech\s+modcovoff/) { $Vericov_Enabled = 0; } } push @Sendout, [$Last_Lineno, $since . $token]; if ($token =~ /\b(cn|vp)_coverage_(off|on)/) { if ($2 eq 'off') { push @Sendout, [0, ::coverage_off(0)]; } else { push @Sendout, [0, ::coverage_on(0)]; } } $Last_Lineno = $parser->lineno; } sub preproc { my ($self, $token) = @_; if (Verilog::Language::is_compdirect($token)) { my $since = $self->unreadback(); $self->unreadback(''); # Close previous endif if ($Opt_Synthcov) { # Else accelerate if ($token eq "`elsif" || $token eq "`else" || $token eq "`endif") { if ($PreCovOff[$PreLevel] && $Opt_Synthcov) { push @Sendout, [0, ::coverage_on(0)]; } $PreLevel--; } } # Current token push @Sendout, [$Last_Lineno, $since . $token]; # Begin new endif if ($Opt_Synthcov) { # Else accelerate if ($token eq "`ifdef" || $token eq "`ifndef" || $token eq "`elsif") { $PreLevel++; $Last_Prekwd = $token; } elsif ($token eq "`else") { $PreLevel++; $PreCovOff[$PreLevel] = !$PreCovOff[$PreLevel]; if ($PreCovOff[$PreLevel] && $Opt_Synthcov) { push @Sendout, [0, ::coverage_off(0)]; } } } $Last_Lineno = $self->lineno; } else { $self->symbol($token); } } package main; ###################################################################### ###################################################################### ###################################################################### __END__ =pod =head1 NAME vpassert - Preprocess Verilog code assertions =head1 SYNOPSIS B [ B<--help> ] [ B<--date> ] [ B<--quiet> ] [ -y B ] [ B ] =head1 DESCRIPTION Vpassert will read the specified Verilog files and preprocess special PLI assertions. The files are written to the directory named .vpassert unless another name is given with B<-o>. If a directory is passed, all files in that directory will be preprocessed. =head1 ARGUMENTS Standard VCS and GCC-like parameters are used to specify the files to be preprocessed: +libext+I+I... Specify extensions to be processed -f I Parse parameters in file -v I Parse the library file (I) -y I Parse all files in the directory (I) -II Parse all files in the directory (I) +incdir+I Parse all files in the directory (I) To prevent recursion and allow reuse of the input.vc being passed to the simulator, if the output directory is requested to be preprocessed, that directory is simply ignored. =over 4 =item --allfiles Preprocess and write out files that do not have any macros that need expanding. By default, files that do not need processing are not written out. This option may speed up simulator compile times; the file will always be found in the preprocessed directory, saving the compiler from having to search a large number of -v directories to find it. =item --axiom Special Axiom ATHDL enables/disables added around unreachable code. =item --call-error When $uerror (or $uassert etc.) wants to display a message, call the specified function instead of $display and $stop. =item --call-info When $uinfo wants to display a message, call the specified function instead of $display. =item --call-warn When $uwarn (or $uwarn_clk etc.) wants to display a message, call the specified function instead of $display and $stop. =item --date Check file dates and sizes versus the last run of vpassert and don't process if the given source file has not changed. =item --exclude Exclude processing any files which begin with the specified prefix. =item --help Displays this message and program version and exits. =item --language <1364-1995|1364-2001|1364-2005|1800-2005|1800-2009|1800-2012|1800-2017> Set the language standard for the files. This determines which tokens are signals versus keywords, such as the ever-common "do" (data-out signal, versus a do-while loop keyword). =item --minimum Include `__message_minimum in the $uinfo test, so that by defining __message_minimum=1 some uinfos may be optimized away at compile time. =item --noline Do not emit `line directives. If not specified they will be used under --language 1364-2001 and later. =item --nopli Delete all 'simple' PLI calls. PLI function calls inside parenthesis will not be changed, and thus may still need to be manually ifdef'ed out. Useful for reducing the amount of `ifdef's required to feed non-PLI competent synthesis programs. =item --nostop By default, $error and $warn insert a $stop statement. With --nostop, this is replaced by incrementing a variable, which may then be used to conditionally halt simulation. =item --o I Use the given filename for output instead of the input name .vpassert. If the name ends in a / it is used as a output directory with the default name. =item --quiet Suppress messages about what files are being preprocessed. =item --realintent Special RealIntent enable/disables added around unreachable code. =item --synthcov When "ifdef SYNTHESIS" is seen, disable coverage. Resume on the `else or `endif. This does NOT follow child defines, for example: `ifdef SYNTHSIS `define MYSYNTH `endif `ifdef MYSYNTH // This will not be coveraged-off =item --timeformat-units I If specified, include Verilog $timeformat calls before all messages. Use the provided argument as the units. Units is in powers of 10, so -9 indicates to use nanoseconds. =item --timeformat-precision I When using --timeformat-units, use this as the precision value, the number of digits after the decimal point. Defaults to zero. =item --vericov Special Vericov enable/disables added around unreachable code. =item --verilator Special Verilator translations enabled. =item --version Displays program version and exits. =item --vcs Special Synopsys VCS enables/disables added around unreachable code. =back =head1 FUNCTIONS These Verilog pseudo-pli calls are expanded: =over 4 =item /*vp_coverage_off*/ Disable coverage for all tools starting at this point. Does not need to be on a unique line. =item /*vp_coverage_on*/ Re-enable coverage after a vp_coverage_off. Does not need to be on a unique line. =item $uassert(I, "message", [I...] ) Report a $uerror if the given case is FALSE. (Like assert() in C.) =item $uassert_amone(I, [I...], "message", [I...] ) Report a $uerror if more than one signal is asserted, or any are X. (None asserted is ok.) The error message will include a binary display of the signal values. =item $uassert_info(I, "message", [I...] ) Report a $uinfo if the given case is FALSE. (Like assert() in C.) =item $uassert_onehot(I, [I...], "message", [I...] ) Report a $uerror if other than one signal is asserted, or any are X. The error message will include a binary display of the signal values. =item $uassert_req_ack(I, I, [I,...] ) Check for a single cycle request pulse, followed by a single cycle acknowledgment pulse. Do not allow any of the data signals to change between the request and acknowledgment. =item $ucheck_ilevel(I ) Return true if the __message level is greater or equal to the given level, and that global messages are turned on. =item $ucover_clk(I, I