Learning BSV‎ > ‎

Compiler Options

Overview
Compiler flags are available to both guide the compiler in some of its decisions or to provide information to understand the compilation.  Some of the flags can be expressed as [[attributes]] within the code, or compiler flags during compilation. 

You can obtain an up-to-date listing of the available flags along with brief explanations by entering:

 bsc  -help

Most flags may be preceded by a -no to reverse their effect. Flags that appear later on the command line override earlier ones.

You can set default flag values to be used each time the compiler is called, by setting the environment variable BSC_OPTIONS.

Common Compile and Linking Flags
-g module              generate code for module
-u                            check and recompile packages that are not up to date
-sim                        compile BSV generating Bluesim object
-verilog                  compile BSV generating Verilog file
-vsim simulator      specify which Verilog simulator to use              
-e module                top-level module for simulation
-o name                   name of generated executable

A module can be selected for code-generation either in the BSV code or at compile-time.  The recommended method is to mark the module for code-generation in the BSV code, using the [[Synthesize Attribute| synthesize attribute]]. The alternative is at compile-time, to use the -g flag, which instructs the compiler to generate code for a particular module.  The -g flag can be used multiple times within a compile command line to specify multiple modules for code generation.

Whether this code will be Bluesim or Verilog depends on which back end has been selected.  The -verilog and -sim  command line flags are used to specify which back end to generate.

The linking stage is  separate from the compilation stage and requires a separate call to the compiler. The result of the linking stage is a binary which, when executed, simulates a module. The user must specify what top-level object is being specified with the -e flag.   The name following the flag must be the name of a BSV module and, unlike with the -g flag, only one module can be specified.

You must also specify the back end with a flag, either -sim for Bluesim or -verilog for Verilog.
For Bluesim linking, the implementation files (.ba files) for all modules in the design must be specified on the command line. Remember, depending on the compile options chosen, the implementation for a module hierarchy may be in one or more files.

For Verilog linking, the Verilog files (.v files) for all modules in the design should be specified.  Since most Verilog simulators will search in the path for any missing modules, you can often just specify one Verilog file.  However, if the name or the location of a Verilog file is not obvious, you should give it explicitly on the command-line.

Here is a sample to link for Bluesim:
 bsc -sim -e mkFoo -o mkFoo mkFoo.ba mkBaz.ba

or, for Verilog,
 bsc -verilog -e mkFoo -o mkFoo mkFoo.v mkBaz.v

The -o flag gives a name for the binary that is being created (here, mkFoo). If this flag is not used, the binary will have the default name a.out.

Verilog back-end Flags
-remove-unused-modules      remove unconnected modules from the Verilog
-v95                                            generate strict Verilog 95 code
-unspecified-to val                  remaining unspecified values are set to: 'X', '0', '1', 'Z', or 'A'
-remove-dollar                         remove dollar signs from Verilog identifiers

The -remove-unused-modules will remove from the generated Verilog any modules which are not connected to an output.  This has has the effect of removing redundant or unused modules, which would also be done by synthesis tools.   This option should be used on modules undergoing synthesis, and not be used for testbench modules.

The -v95 flag restricts the Verilog output to pure Verilog-95. By default, the Verilog output uses features which are not in the Verilog-95 standard.  These features include passing module parameters by name and use of the $signed system task for formatting $display output.  When the -v95 flag is turned on, uses of these features are removed, but comments are left in the Verilog indicating the parameter names or system tasks which were removed.

The -unspecified-to val flag defines the value which any remaining unspecified values should be tied to.  The valid set of values are: X, 0, 1, Z, or A, where the first four correspond to the Verilog value, and A corresponds to a vector of alternating ones and zeros. The default value is A.  The choice of value is used by both the Verilog and Bluesim back ends.  However, since Bluesim is a two-value simulator, it does not support the values X and Z. For final synthesis runs, the use of X (or 0) is strongly suggested to give the best synthesis results.

The -remove-dollar flag causes identifiers in Verilog output to substitute underscores instead of dollar signs to separate instance names from port names.  If this substitution causes a name collision, the underscore is suffixed with a number until a non-colliding name is found.

Resource scheduling flags (all back ends)
-resource-off               fail on insufficient resources
-resource-simple        reschedule on insufficient resources

Resource scheduling for a particular interface method involves finding all rules that call that method. A single method name can refer to multiple ports in the hardware --- for example, a double-ported RAM can have two read ports, but a design in BSV can use the name read and it will rely on the compiler to determine which port is being used. If the number of rules that use read is two or less, then there is no problem; each rule is connected to its own port and there is never any contention. If the number of rules vying for a method is more than the number of copies of that method, then a problem exists.

If -resource-off is specified, the compiler will give up and tell the user that resource scheduling is not possible. This is the default behavior. The straightforward way to proceed is by adding logic that explicitly arbitrates between the competing rules (choosing the more important one to fire depending on the situation).

The alternative way to resolve a resource conflict is to block competing rules until the number of rules vying for a method is less than the number of available ports for that method.  This behavior can be turned ''on'' with the -resource-simple flag. The compiler selects rules to block from the competing rules arbitrarily (and may change its selection when different compilation flags or compiler versions are used), so this flag is not recommended for a completed design, but automatic resource arbitration can be useful when experimenting.

Setting the path

-i dir                     directory for Bluespec files
-p path                 directory path (`:' sep.) for Bluespec interface files
-bdir path            output directory for .bi, .bo, and .ba files
-simdir path        output directory for Bluesim intermediate files
-vdir path            output directory for .v files
-I path                  include path for compiling foreign C/C++ source
-L path                 library path for linking foreign C/C++ objects
-l library               library to use when linking foreign C/C++ objects

The flags -i and -p control where the compiler looks for other files if they are not in their default location or if you wish to use another set of files instead of the defaults. The -p flag takes a path argument, which is a colon-delimited list of directories. This path is used to find interface files imported by the package being compiled (including the standard prelude). The path can contain the character -%, representing the current BSV directory, as well as +, representing the current path. The default path is:
 .:%/Prelude:%/Libraries

The -bdir,-simdir and -vdir flags specify where output files should be placed. The default is the directory in which the input file(s) reside.

The flags -I, -L, and-l are used during the linking stage when foreign C functions are imported.  The -I and -L flags add to the path of where to find C header files and libraries, respectively.  The libraries to be used during linking are specified by the -l flag.

License-related flags

The following flags are related to the license:
-licenseWarning days    sets the number of days before a license expires to issue a warning
-print-expiration             print the expiration date and exit
-show-license-detail      show more details regarding license acquisition
-wait-for-license             wait for license to free rather than exit

To find out when your Bluespec compiler license expires, use -print-expiration.  By default, bsc warns when the license expires in 30 days or less, use -licenseWarning to set the warning period.  The option -show-license-detail shows details of the license acquisition including search path and the server where the license was acquired.

The option -wait-for-license is useful for batch operations when the user does not want the job to fail due to a busy license. Under this option, the Bluespec compiler will queue a request for a license and then block execution until a license is freed.  License queuing is under the control of the FLEXnet software.   If you kill a process which is waiting for a license, ensure that all threads are killed; FLEXnet starts a separate thread to communicate with the license server.

Miscellaneous flags
Here are some other flags recognized by the compiler:
-D macro                               define a macro for the pre-processor
-E                                           run just the preprocessor, dumping result to stdout
-print-flags                           print flag values after command-line parsing
-steps n                                 set the number of function unfolding steps
-steps-max-intervals n        terminate elaboration after this many function unfolding messages
-steps-warn-interval n         issue a warning every time this many function unfolding steps are executed

Pre-processor macros may be defined on the command line using the -D option.  Two versions are supported, a simple macro definition and an assignment of a string to a macro:
 -D foo            
 -D size=148

Note that a space is required after the -D and that no spaces are allowed in the macro names, values or around the equals.

Function definitions in BSV are purely compile-time entities.  The compiler replaces all function calls by their bodies and continually simplifies expressions. Function definitions may be recursive as long as this substitution and simplification process terminates, but of course the compiler cannot predict whether it will terminate. The -steps, -steps-warn-interval, and -steps-max-intervals flags provide feedback and safety mechanisms for potentially infinite function unfoldings. The -steps-warn-interval tells the compiler to issue a compilation warning every time that many function unfolding steps are executed. This provides feedback to a designer that a particular design requires an unusual amount of effort to elaborate. A designer may choose to terminate elaboration and investigate whether there is a bug, infinite loop or an inefficient construct in a design or they may choose to let elaboration proceed to see if additional time will result in elaboration completing. The -steps-max-intervals flag is the safety mechanism. It prevents an unattended compilation from consuming resources indefinitely by terminating elaboration after a certain number of function unfolding warnings. This means, for example, with the default values of 100000 for -steps-warn-interval and 10 for -steps-max-intervals an infinite compilation will execute for 1000000 steps, issuing 9 unfolding warnings before terminating with an unfolding error message. The -steps flag is a simpler version of this mechanism. It is equivalent to setting -steps-warn-interval to the argument of -steps and -steps-max-intervals to 1.

The settings that are being used by the compiler can be dumped with -print-flags.

Run-time system

These flags are passed along to the Haskell compiler run-time system that is used to execute the Bluespec compiler.  Among the RTS flags available are:
-Hsize                  set the maximum heap size
-Ksize                  set the maximum stack size

As the compiler executes, it allocates its internal intermediate data structures in a heap memory managed by its run-time system (RTS). When compiling a large BSV design, the compiler may run out of heap space. If you encounter this, please rerun the compiler with a larger heap space, using the flags:

 bsc ... +RTS -H''size'' -RTS ...

For example, to use an 80-megabyte heap, you would enter:

 bsc ... +RTS -H80M -RTS ...

Similarly, if you run out of stack space, you can increase the stack with the -K RTS flag.  If a design runs out of stack space, it is probably caught in an infinite loop.  For large designs that involve many recursive functions, it may be necessary to increase the stack size.  If you run out of stack space, first try increasing the stack to a reasonable size, such as 10 or 15 megabytes.  If you still exhaust the stack memory, try examining your design for infinite loops.

Any flags encapsulated between +RTS and -RTS are passed to the run-time system and are not given to the BSV compiler itself. In addition to -H and -K, various flags are available to control garbage collection, memory usage, function unfolding, etc.  However, the user should never need to use these other flags.

Automatic recompilation
-u                                 check and recompile packages that are not up to date
-show-compiles         show recompilations

The -u flag implements a make-like functionality. If a needed .bi or .bo file is found to be older or non-existent compared to the .bsv file, the latter is recompiled. Similarly, if a .bsv file has a modification time that is more recent than that of any of its generated Verilog or Bluesim modules, the .bsv file is recompiled.

The -show-compiles flag turns ''on'' the compiler output during recompilation of auxiliary files. It can also be used as -no-show-compiles to suppress the compiler output.

For the purposes of comparing modification times, the intermediate files (.bi, .bo, and .ba) are assumed to be in the same directory as the .bsv source file.  If no file is found there, the compiler then searches in the directory specified by the -bdir flag (if used).  The generated Verilog files and Bluesim files are assumed to be in the same directory as the source unless the-simdir or-vdir flag is used, respectively.

Compiler transformations
-aggressive-conditions      construct implicit conditions aggressively
-split-if                                   split "if" in actions
-lift                                          lift method calls in "if" actions

When a rule contains an if-statement, the compiler has the option either of splitting the rule into two mutually exclusive rules, or leaving it as one rule for scheduling but using MUXes in the production of the action. Rule splitting can sometimes be desirable because the two split rules are scheduled independently, so non-conflicting branches of otherwise conflicting rules can be scheduled concurrently. The -split-if flag tells the compiler to split rules. Splitting is turned ''off'' by default for two reasons:
  • When a rule contains many if-statements, it can lead to an exponential explosion in the number of rules. A rule with 15 if-statements might split into 2^15 rules, depending on how independent the statements (and their branch conditions) are. An explosion in the number of rules can dramatically slow down (and cause other problems) for later compiler phases, particularly scheduling.
  • Splitting propagates the branch condition of each if to the predicates of the split rules. Resources required to compute rule predicates are reserved on every cycle. If a branch condition requires a scarce resource, this can starve other parts of the design that want to use that resource.

If you need the effect of splitting for certain rules, but do not want to split all the rules in an entire design using -split-if, use  the (*split*) and (*nosplit*) attributes.

When rules are not split along if-statements, it is important to lift actions through the if-statement.  If both branches of an if-statement call the same method but with different arguments, it's better to make one call to the method and MUX the argument. The -lift flag turns ''on'' this optimization. Lifting is recommended when rule splitting is turned ''off''. When rule splitting is ''on'', lifting is not required and can make rules more resource hungry. Currently, lifting with splitting ''off'' can result in poor resource allocation, so we recommend using -no-liftwith -split-if.

When the action in a branch of an if-statement has an implicit condition, that condition needs to be propagated to the rule predicate. This can be done conservatively, by simply placing implicit conditions for all branches in the predicate. Or it can be done more aggressively (i.e. attempting to fire the concerned rule more often), by linking each implicit condition with its associated branch condition. The flag -aggressive-conditions turns ''on'' this feature. This flag is off by default because, as discussed above, propagating branch conditions to rule predicates can have undesirable effects. However, if -split-if is on, branch conditions will be propagated to rule predicates regardless, so we recommend using -aggressive-conditions with -split-if, since it may improve the generated schedule.

Compiler optimizations

-O                                           turn on various optimizations
-opt-undetermined-vals     aggressive optimization of undetermined values

The -O flag turns ''on'' several compiler optimizations. Using these optimization, there may be an increase in bsc runtime, memory use or both.

In late stages of the compiler, don't-care values are converted into specific constants.  In order that the Verilog and Bluesim simulation paths produce exactly the same value dumps, the compiler assigns a value to the don't-care signals at the point where the Verilog and Bluesim back ends diverge.  However, the Verilog back end can generate more efficient hardware if it is allowed to assign the don't-care signals better values based on context.  The -opt-undetermined-vals flag permits the Verilog back end of the compiler to make better decisions about don't-care values.  This flag is ''off'' by default.  Turning this flag on may produce better hardware in Verilog, but can result in the Bluesim and Verilog simulations producing different intermediate values.

Some non-deterministic optimizations are used during scheduling, which may result in excessive run time or conversely, a too conservative (less optimal) schedule.  The effort is controlled with the following switches.
-scheduler-effort limit:          set effort for disjoint testing during scheduling
-warn-scheduler-effort :          displays warnings when the scheduler limit is reached

The default limit is 20, and typical values range from 10 to 500. This value should not be changed unless a less-than-optimal schedule is observed, and -warn-scheduler-effort shows that the limit is indeed exceeded.  Larger limits may cause excessive runtime, and still not produce optimal schedules. Note that the scheduled Verilog is logically correct even if this limit is exceeded.

BSV debugging flags
The following flags might be useful in debugging a BSV design:
-check-assert                       test assertions with the Assert library
-cross-info    generate  cross reference file for emacs and position information for late phase error messages
-keep-fires                            preserve CAN_FIRE and WILL_FIRE signals
-keep-inlined-boundaries   preserve inlined register and wire boundaries
-remove-false-rules            remove rules whose condition is probably false
-remove-starved-rules       remove rules that are never fired by the generated schedule
-show-method-conf            show method conflict information in the generated code
-show-module-use              output instantiated Verilog modules names
-show-rule-rel r1 r2             display scheduling information about rules r1 and r2
-show-schedule                   show generated schedule
-show-stats                          show package statistics
-Werror
                                  make warnings to errors
-continue-after-errors        continue processing after an error is encountered

The -check-assert flag instructs the compiler to abort compilation if an boolean assertion ever fails. These are assertions which are explicitly embedded in a BSV design using the Assert package. If this flag is ''off'', assertions of this type in a BSV design are ignored.

The -cross-info flag is used when compiling BSV files to Verilog targets.  With this switch, the compiler will generate cross reference information tying source files to output files.  The flag is also helpful in providing position information for late phase error messages, such as those for rules or methods with multiple clocks or resets.

To view rule firings in the Verilog output, use the -keep-fires flag. This flag will direct the compiler to leave the CAN_FIRE and WILL_FIRE signals in the output Verilog (some of which might otherwise be optimized away).  These signals are generated for each rule and indicate whether a rule's predicate would allow the rule to fire in the current cycle and whether the scheduler chose the rule to fire in the current cycle, respectively.  Leaving these signals in the Verilog allows the designer to dump the signals to VCD and view the firings in a waveform viewer.

When elaborating a design, if the compiler determines that a rule's explicit condition is always false, it issues a warning about the situation and removes the rule from the design (so the presumably irrelevant rule does not interfere with scheduling). Sometimes, for debugging purposes it can be helpful to preserve this (never enabled) rule in the output code. That can be done by disabling the -remove-false-rules flag (i.e. passing -no-remove-false-rules).  As you might expect, the compiler will find more false rules when aggressive optimization (i.e. -O) is turned on, but it can be helpful to turn ''off'' -O when you want to examine the condition that the compiler can prove false.

Similarly, the compiler might determine, after scheduling, that a rule will never fire because conflicting rule(s) block it whenever it is enabled. The compiler warns about such rules, but does ''not'' remove them by default because they probably indicate an important problem in scheduling the design. If you wish to removed these rules,
you can use the -remove-starved-rules flag.

If the rules in a design are not firing the way you thought they would, the -show-schedule and the -show-rule-rel flags may help you inspect the situation.

Conflict relationships between methods of the generated module's interface can be dumped (in the generated code) with the -show-method-conf flag. This is enabled by default and is useful for documenting the interface protocol a generated module expects (particularly when the generated module is going to be called by non-Bluespec modules). The -show-stats flag dumps various statistics at the end of each compiler stage (such as the number of rules and number of definitions).  To find out what Verilog modules are instantiated by the generated module, use the -show-module-use flag.  This flag causes the compiler to create a file mkFoo.use which contains a list of each Verilog module instantiated by module mkFoo, separated by newlines.

By default, the compiler stops once it finds errors in a module.  The -continue-after-errors flag allows the compiler to continue on to other modules and other phases after an error is encountered.  This may be helpful in finding multiple errors in a single compile, though some of later errors may be misleading and vanish once the cause of initial error is fixed.  Note that  the compiler may not be able to successfully complete because of the cummulative effects of errors encountered.

Subpages (1): BSC Options
Comments