• Top
    • Documentation
    • Books
    • Boolean-reasoning
    • Projects
    • Debugging
    • Std
    • Proof-automation
    • Macro-libraries
    • ACL2
    • Interfacing-tools
    • Hardware-verification
      • Gl
      • Esim
      • Vl2014
        • Warnings
        • Primitives
        • Use-set
        • Syntax
        • Getting-started
        • Utilities
        • Loader
          • Preprocessor
            • Vl-iframe-p
            • Preprocessor-ifdef-minutia
            • Vl-preprocess-loop
            • Vl-read-until-end-of-define
            • Vl-expand-define
            • Vl-read-include
            • Vl-process-ifdef
            • Vl-substitute-into-macro-text
            • Vl-preprocess
            • Vl-define
            • Vl-process-define
            • Vl-process-undef
            • Preprocessor-include-minutia
            • Vl-split-define-text
            • Vl-read-timescale
            • Vl-line-up-define-formals-and-actuals
            • Vl-process-else
            • Vl-process-endif
            • Vl-istack-p
            • Vl-is-compiler-directive-p
            • Vl-check-remaining-formals-all-have-defaults
            • Vl-safe-previous-n
            • Vl-safe-next-n
            • Vl-defines
            • *vl-preprocess-clock*
          • Vl-loadconfig
          • Lexer
          • Vl-loadstate
          • Parser
          • Vl-load-merge-descriptions
          • Scope-of-defines
          • Vl-load-file
          • Vl-flush-out-descriptions
          • Vl-description
          • Vl-loadresult
          • Vl-read-file
          • Vl-find-basename/extension
          • Vl-find-file
          • Vl-read-files
          • Extended-characters
          • Vl-load
          • Vl-load-main
          • Vl-load-description
          • Vl-descriptions-left-to-load
          • Inject-warnings
          • Vl-load-descriptions
          • Vl-load-files
          • Vl-load-summary
          • Vl-collect-modules-from-descriptions
          • Vl-descriptionlist
        • Transforms
        • Lint
        • Mlib
        • Server
        • Kit
        • Printer
        • Esim-vl
        • Well-formedness
      • Sv
      • Fgl
      • Vwsim
      • Vl
      • X86isa
      • Svl
      • Rtl
    • Software-verification
    • Math
    • Testing-utilities
  • Loader

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

We place some (reasonable) restrictions on the above macros. For instance, we do not allow definitions to include most compiler directives—we allow the body of `foo to include `bar, but not `endif. These restrictions are intended to ensure that we do not "mispreprocess" anything. 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.

Ignored Directives

We also "support" certain directives by ignoring them.

  • `celldefine
  • `endcelldefine
  • `resetall
  • `timescale

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.

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-p
`ifdef stack frame objects.
Preprocessor-ifdef-minutia
Subtle notes about or `define and `ifdef handling.
Vl-preprocess-loop
Main loop for the preprocessor.
Vl-read-until-end-of-define
Read from `define until the end of the line.
Vl-expand-define
Expand uses of defines like `foo and `max(a,b).
Vl-read-include
Read an `include directive.
Vl-process-ifdef
Handler for ifdef, ifndef, and elsif directives.
Vl-substitute-into-macro-text
Vl-preprocess
Top-level interface to the preprocessor.
Vl-define
Internal representation of a `define directive.
Vl-process-define
Handler for define directives.
Vl-process-undef
Handler for undef directives.
Preprocessor-include-minutia
Subtle notes about `include handling.
Vl-split-define-text
Split up the rest of a define line into macro arguments and macro text.
Vl-read-timescale
Vl-line-up-define-formals-and-actuals
Vl-process-else
Handler for else directives.
Vl-process-endif
Handler for endif directives.
Vl-istack-p
(vl-istack-p x) recognizes lists where every element satisfies vl-iframe-p.
Vl-is-compiler-directive-p
List of Verilog-2005 compiler directives.
Vl-check-remaining-formals-all-have-defaults
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-defines
A list of vl-define-p objects.
*vl-preprocess-clock*
Artificial bound on preprocessor loops, for termination.