Preprocessor
Limited preprocessor for Verilog.
First, a warning. In general, the Verilog specification does not
cover how preprocessing is to be done in a very complete way. We are left with
many subtle questions about how the preprocessor should behave, and to resolve
these questions we have sometimes just given test cases to simulators such as
Verilog-XL, NCVerilog, and VCS. This is not a very satisfying state of
affairs.
Supported Directives
Our preprocessor has pretty good support for the define- and
ifdef-related directives:
- define
- ifdef
- ifndef
- elsif
- else
- undef
See preprocessor-ifdef-minutia for some details and additional
discussion.
We also have pretty good support for `include directives. This is
quite underspecified, and we have basically tried to mimic the behavior of
Verilog-XL and NCVerilog. See also preprocessor-include-minutia.
We also support `__FILE__ and `__LINE__ directives.
Ignored Directives
We also "support" certain directives by ignoring them.
- `celldefine
- `endcelldefine
- `resetall
- `timescale
- `protect
- `endprotect
When we say we ignore these directives, we mean that the preprocessor
literally removes them from the source code that the lexer sees. No record of
these directives is ever kept. A consequence of this is, upon having loaded
some VL modules, there is not really any way to know whether these directives
were included anywhere in the source code.
In the case of celldefine and endcelldefine, this seems pretty
reasonable. It seems that these directives only mark modules as "cells" for
certain PLI directives or other tools. None of the tools we are developing
care about this, so for now we just ignore this directive.
The resetall directive is tool dependent and it seems valid to ignore
it entirely. We do not try to enforce the restriction that resetall must
not occur within a module definition.
We also ignore timescale directives. This is not ideal, but is pretty
reasonable for things like ESIM where timing is irrelevant. It is also fairly
reasonable even for something like a transistor analyzer that cares about unit
delays, as long as differnet timescales are not being mixed together. (Mixing
timescales within a single design seems insane, and after all what is the
"default" timescale supposed to be? BOZO maybe add a warning if more than
one kind of timescale is seen.
We also ignore `protect and `endprotect, which seem to be old
Verilog-XL directives for marking code that you want a tool to encrypt. VL
doesn't implement any support for decrypting protected code, but it can at
least ignore these indications that you want to encrypt something. Note that
these directives are not documented in the SystemVerilog-2012 standard and are
probably subsumed by the pragma syntax described in Section 34, protected
envelopes.
As future work, there might be some benefit to somehow preserving these
directives so that they can be printed out again in the simplified Verilog we
produce. That is, maybe it would make the simplified Verilog easier to use as
a "drop-in replacement" for the unsimplified Verilog.
Unsupported Directives
We currently make no attempt to support:
- `begin_keywords
- `default_nettype
- `end_keywords
- `line
- `pragma
- `nounconnected_drive
- `unconnected_drive
It might be good to ignore `begin_keywords "1364-2005" and just cause
an error if a different set of keywords is requested. We could also ignore
`end_keywords. But trying to add anything more sophisticated than this
seems very tricky and messy.
It would be good to add proper support for `line. Failing that, it
would be quite easy to just ignore it, like the other ignored directives. We
should probably also ignore `pragma directives, and this should be easy to
do.
It would be somewhat difficult to support `default_nettype and
`unconnected_drive. Probably the thing to do would be build a table of
when the declarations are made, and then use some trick like comment injection
to mark modules appropriately. We would then have to change the make-implicit-wires transform to consider the `default_nettype for the
module, and probably use a separate transform to handle `unconnected_drive
stuff.
Subtopics
- Vl-iframe
- `ifdef stack frame objects.
- Preprocessor-ifdef-minutia
- Subtle notes about or `define and `ifdef handling.
- Vl-preprocess
- Top-level interface to the preprocessor.
- Vl-preprocess-loop
- Main loop for the preprocessor.
- Vl-includeskips
- A record of which files we have already included that have ``proper''
include guards and may not need to be included again.
- Vl-read-until-end-of-define
- Read from `define until the end of the line.
- Vl-define-formallist->defaults
- (vl-define-formallist->defaults x) maps vl-define-formal->default across a list.
- Vl-define
- Internal representation of a `define directive.
- Vl-expand-define
- Expand uses of defines like `foo and `max(a,b).
- Vl-read-include
- Read an `include directive.
- Vl-substitute-into-macro-text
- Vl-process-ifdef
- Handler for ifdef, ifndef, and elsif directives.
- Ppst
- Preprocessor state object.
- Vl-read-define-default-text
- Vl-process-define
- Handler for define directives.
- Preprocessor-include-minutia
- Subtle notes about `include handling.
- Vl-trim-for-preproc
- Trim whitespace from a string, but preserving space that might be syntactically significant.
- Vl-line-up-define-formals-and-actuals
- Vl-process-undef
- Handler for undef directives.
- Vl-split-define-text
- Split up the rest of a define line into macro arguments and macro text.
- Vl-def-context
- Information about a single use of a define like `FOO.
- Vl-process-endif
- Handler for endif directives.
- Scan-backward-for-non-whitespace
- Vl-ifdef-context
- Information about a single use of ifdef FOO or elsif BAR.
- Scan-backward-for-whitespace
- Vl-atvl-atts-text
- Scan-for-non-whitespace
- Vl-check-remaining-formals-all-have-defaults
- Vl-process-else
- Handler for else directives.
- Vl-is-compiler-directive-p
- List of Verilog-2005 compiler directives.
- Vl-includeskips-controller-lookup
- Look up the controlling define for this file, if one is known.
- Vl-ifdef-use-map
- A log of where `defines are used in the `ifdef tree.
- Vl-defines
- An alist mapping stringp to vl-maybe-define-p.
- Vl-def-use-map
- A log of where `defines are used, outside of ifdefs.
- Vl-nice-bytes
- Human-friendly summary of some number of bytes.
- Vl-safe-previous-n
- Used to get a context for error messages.
- Vl-safe-next-n
- Used to get a context for error messages.
- Vl-ppst-pad
- Prefix for lines produced by the preprocessor.
- Vl-filename-to-string-literal
- Vl-maybe-update-filemap
- *vl-preprocess-clock*
- Artificial bound on preprocessor loops, for termination.
- Vl-ppst->warnings
- Vl-ppst->iskips
- Vl-ppst->ifdefmap
- Vl-ppst->idcache
- Vl-istack
- A list of vl-iframe-p objects.
- Vl-ppst->istack
- Vl-ppst->includes
- Vl-ppst->filemap
- Vl-ppst->defmap
- Vl-ppst->defines
- Vl-ppst->config
- Vl-ppst->bytes
- Vl-ppst->activep
- Vl-ppst->acc
- Vl-ppst-record-ifdef-use
- Vl-ppst-record-def-use
- Vl-ifdef-context-list
- A list of vl-ifdef-context-p objects.
- Vl-def-context-list
- A list of vl-def-context-p objects.
- Vl-ppst-update-warnings
- Vl-ppst-update-istack
- Vl-ppst-update-iskips
- Vl-ppst-update-includes
- Vl-ppst-update-ifdefmap
- Vl-ppst-update-idcache
- Vl-ppst-update-filemap
- Vl-ppst-update-defmap
- Vl-ppst-update-defines
- Vl-ppst-update-config
- Vl-ppst-update-activep
- Vl-ppst-update-bytes
- Vl-ppst-update-acc
- Vl-ppst-unsound-nreverse-acc