JanusHDL

Projects

Last updated: 

A project file holds what it takes to simulate a design: its source files with their libraries and VHDL versions, the top level and its generics, the stop time, and how to simulate it. It is a short text file with the extension .jhdlproj, made to be kept in version control next to the sources, so that everyone on a team, and the CI job, runs the design the same way.

You do not need a project to use JanusHDL: everything also works with file names or a file list on the command line. A project is worth it as soon as a design has several libraries, a library in another VHDL version, generics to set or options to remember.

Making a project

There are three ways:

  • In the window, from scratch. File → New project… asks where to save the project file, makes an empty project there and opens its settings, where you add the sources.
  • In the window, from a file list. File → Import a file list (.f) as a project… makes a project of a file list's files, in the same libraries and order, with their paths made relative to where you save the project. Its settings open so that you can set the top level and the rest.
  • By hand. A project file is plain text; write it in any editor, following the format below.

The project file

Here is a complete example:

jhdl-project 1
# The UART and its testbench.
std 2008

library uvvm_util
  source ../uvvm/uvvm_util/src/types_pkg.vhd
  source ../uvvm/uvvm_util/src/adaptations_pkg.vhd
library legacy std=1993
  source "old ip/regs.vhd"
library work
  source src/uart.vhd
  source tb/uart_tb.vhd

top work.uart_tb
generic baud=115200
stop-time 2 ms

# UVVM needs compatibility mode (chapter 6)
compat on
psl off
deny future-reserved-word
native-code on
ieee-warnings on
stop-level failure
exit-level error

wave-setup waves/uart.wavesetup

The rules of the format:

  • The first line that is not blank or a comment is the header, jhdl-project 1: the format and its version.
  • Then one statement per line, its words separated by spaces. Indentation is free.
  • Blank lines and lines that start with # are comments. A comment is always a whole line.
  • A word that contains a space, such as a path, is written in double quotes; a quote inside it is doubled: source "my designs/top level.vhd".
  • Paths are relative to the project file's folder, or absolute. Write them with forward slashes on every system, so the project reads the same on Windows and Linux.

Sources

Statement Meaning
std VERSION The project's VHDL version: 1993, 2002, 2008 or 2019 (93, 02, 08 and 19 are read too). It is the version of the standard packages and of every source that has no version of its own or of its library. Default 2008.
library NAME [std=VERSION] The sources after it go into library NAME, up to the next library line. std= gives the library a VHDL version of its own. A library may have several sections; it has one version.
source PATH [std=VERSION] A design file, analyzed into the library of its section (work before any library line). std= gives the file a version of its own.

Files are analyzed in the order of their source lines. Each file is read as its own VHDL version, else its library's, else the project's: with that version's reserved words, syntax and rules. So a VHDL-1993 library can use names that VHDL-2008 reserves, while the rest of the design is VHDL-2008. The standard packages, and the width of INTEGER, are those of the project's version.

The design

Statement Meaning
top NAME The top level: library.entity (or entity, or a configuration). Without it, the entity analyzed last.
generic NAME=VALUE A generic of the top level. With a path, such as uut.width=8, a generic of the instance below the top, replacing its actual. The value is the rest of the line, written as VHDL writes a literal of the generic's type, as -g takes it (Generics): 8, 16#FF#, "text", '1' or 1, x"A5", 10 ns. One line per generic.
define NAME=VALUE An identifier for VHDL-2019 conditional analysis, for `if NAME = "VALUE" (see Conditional analysis).
stop-time TIME When a run ends, such as 1 ms or 250 ns (the rest of the line). Without it, a run goes on until nothing is left to do.

How to simulate

Each of these is written in every project file JanusHDL saves, so a project runs the same whatever a later version's defaults are.

Statement Meaning Default
compat on\|off Compatibility mode: code the LRM forbids but whose meaning is clear is a warning, and simulated as written (Compatibility mode) off
psl on\|off Read PSL in -- psl comments too off
allow RULE, warn RULE, deny RULE Report a diagnostic rule not at all, as a warning or as an error (jhdl --rules lists the rules); one line per rule none
native-code on\|off Compile what qualifies to native code (Native code) on
ieee-warnings on\|off Whether assertions in the IEEE packages report on
stop-level LEVEL The least severity of a report that stops the simulation: note, warning, error or failure failure
exit-level LEVEL The least severity of a report that makes jhdl run exit with an error error
order-seed N Run the processes of each simulation cycle in a fixed order drawn from N (Determinism and races) the default order

Waves and recording

Statement Meaning
wave-setup PATH A wave setup to use (Wave setup files); one line each. The first is shown when a run's waveform opens in the window; the Project tab lists them all.
waveform PATH The waveform database jhdl run records every signal into.
vcd PATH A VCD file jhdl run writes at the end of the run.

The window shows a run as it goes and records it into a temporary file, whatever waveform says: these two lines are for runs from the command line.

Errors in a project file

A project file JanusHDL cannot read is refused, with the line, what is wrong and how to fix it:

error: counter.jhdlproj: line 10: a stop time is a time such as `1 ms` or `250 ns`: `stop-time soon`

A statement given twice where it may be given once is an error: std, top, stop-time, the on/off switches, stop-level, exit-level, order-seed, waveform and vcd. So is a generic, an identifier or a rule given twice, and a library given two VHDL versions. This is on purpose: when two people's edits of a project are merged, the result should not leave a choice between them to chance.

Newer and older versions

Later versions of JanusHDL may add statements and options. A version that meets a statement or option it does not know skips that line and says so, with its line number, so that a project written by a newer version still opens:

warning: uart.jhdlproj: line 11: this build does not know `frobnicate` (a newer JanusHDL may have written it); the line is skipped

A change that an older version would misread raises the number in the header; a version refuses a project file whose header is newer than it reads, and says which version it reads.

Running a project from the command line

jhdl run uart.jhdlproj

runs the project: its sources in their libraries, each file as its VHDL version, its top level and generics, its stop time and its options, recording into its waveform and vcd files if it names them. jhdl uart.jhdlproj, with the project first, does the same.

Options given after the project take precedence over the project's own:

jhdl run uart.jhdlproj --stop-time 10us -gbaud=9600 --wave quick.jhw

runs the project for 10 µs, with another baud rate, recording into quick.jhw. A generic given on the command line replaces the project's generic of the same name; the project's other generics still apply.

  • Relative paths in the project are relative to its folder, wherever you run jhdl from.
  • The exit code follows the project's exit-level (by default, a report of severity error or worse fails the run), unless --exit-level changes it.
  • A project file must come first: jhdl refuses one given among other files, and says how to run it.
  • --cache works for a project whose files have different VHDL versions too: the saved analysis records each file's version.

Project mode in the window

Opening a project

  • File → Open project…,
  • a project in the Recent list of the start page,
  • a .jhdlproj file dropped on the window, or
  • jhdlw PROJECT.jhdlproj on the command line.

jhdlw --run PROJECT.jhdlproj opens the project and runs it straight away. The window's title shows the project's name. One project is open at a time; opening another closes the first, keeping your state of it.

The Project tab

The Project tab, beside the Hierarchy, shows the open project (View → Show or hide the project brings it back if you closed it):

  • At the top, three buttons: Project settings, Add source files and Run the project. Under them, a line with the project's VHDL version, its top level and its stop time.
  • The sources, by library: each library with its own VHDL version if it has one, and each file with its own version beside it. A file that is not on disk is shown in red.
  • Double-click a file to open it in the code editor. Right-click it to Open it, Copy path, or Remove from the project (the project is saved at once).
  • Under the sources, the project's wave setups. Double-click one to show it in the wave view.

Project settings

File → Project settings… (Ctrl+Shift+,), or the cog button in the Project tab, opens the settings. They have four pages:

Page What it sets
Sources The files in analysis order, each with its library and VHDL version (its own, or its library's). Click a file to select it: Add files… adds the files you choose after it, into its library. The arrows move a file up or down; × removes it. Below the files, the VHDL version of each library.
Top level The top level (library.entity), the project's VHDL version, the top's generics (a path such as uut.width sets an instance's generic), and the conditional analysis identifiers.
Simulation The stop time, the severity that stops a run (Stop at reports of), the severity that fails a command-line run (A command-line run fails at), the process order seed, native code, compatibility mode, PSL in comments, IEEE warnings, and the diagnostic rules you want at another level than their default.
Waves The wave setups, in order (the first is shown when a run's waveform opens), and the waveform database and VCD file that jhdl run records into.

Save checks what you entered and writes the project file. If something is wrong, it says what and where, on the page concerned, and how to fix it: a top level with a space in it, a stop time that is not a time, a generic given twice, a rule listed twice. Cancel leaves the project as it was.

File → Save project writes the project file and your state of it; File → Close project closes it, keeping your state.

Running the project

With a project open, Run (F5), Run for (F10) and Restart (Ctrl+Shift+F5) run the project as it is saved. A run after the project or one of its sources changed analyzes it again. Simulate → Run simulation… runs it too, and a top level or stop time you type there takes precedence over the project's for that run.

The window records each run into a temporary file and shows it as it grows, whatever the project's waveform and vcd lines say; to keep a recording, run the project with jhdl run (see Recording waveforms).

The first time a project's run is shown, the wave view shows the project's first wave setup. After that it shows the view you left: the signals, radixes, cursor and visible time span of your last run of the project.

The editor and searches follow the project

With a project open, the code editor analyzes each of the project's files as the project does: after the files before it, into its library, as its VHDL version, with the project's compatibility mode, PSL comments, conditional analysis identifiers and rule levels, so its diagnostics are those jhdl run gives (Diagnostics). When the project file changes, the open files are analyzed again. Find in files with Files of the run searches the project's sources.

The language server uses a project too, for editors other than the window's (How the server finds your design).

Each user's state

The window keeps what belongs to you, rather than to the project, apart from the project file, in a folder named .jhdl beside it: .jhdl/NAME.state for the project NAME.jhdlproj. It holds:

  • the layout of the tabs, including tab windows and where they are on your screens;
  • the files open in the code editor, with their cursors;
  • the last wave view: the signals, cursor and visible time span of the last run you looked at.

It is written when you save or close the project, when the window exits, and every half minute while it runs; it is read when the project opens. A state file that cannot be read (one written by a newer version, say) is ignored, and the project opens with the window's current layout.

The state is not for version control. Add the folder to your .gitignore:

.jhdl/

Projects and file lists

A file list (.f) and a project file both name sources with their libraries, and both work on the command line and in the window. The differences:

File list (.f) Project file (.jhdlproj)
Sources and libraries Yes Yes
A VHDL version per library or file No Yes
Top level, generics, stop time No (command-line options, or the Run dialog) Yes
Simulation options and rule levels No (command-line options) Yes
Wave setups No Yes
Read by the language server Yes Yes
Read by jhdl jhdl -f FILES.f jhdl run PROJECT.jhdlproj

A file list stays useful as the shared part of several projects, or for tools that read one. File → Import a file list (.f) as a project… turns one into a project at any time.