Example C++ Execution

We’ll compile this example into C++. For an extended and commented version of what this C++ code is doing, see examples/make_tracing_c/sim_main.cpp in the distribution.

First you need Verilator installed, see Installation. In brief, if you installed Verilator using the package manager of your operating system, or did a make install to place Verilator into your default path, you do not need anything special in your environment, and should not have VERILATOR_ROOT set. However, if you installed Verilator from sources and want to run Verilator out of where you compiled Verilator, you need to point to the kit:

# See above; don't do this if using an OS-distributed Verilator
export VERILATOR_ROOT=/path/to/where/verilator/was/installed
export PATH=$VERILATOR_ROOT/bin:$PATH

Now, let’s create an example Verilog and C++ wrapper file:

mkdir test_our
cd test_our

cat >our.v <<'EOF'
  module our;
     initial begin $display("Hello World"); $finish; end
  endmodule
EOF

cat >sim_main.cpp <<'EOF'
  #include "Vour.h"
  #include "verilated.h"
  int main(int argc, char** argv) {
      VerilatedContext* contextp = new VerilatedContext;
      contextp->commandArgs(argc, argv);
      Vour* top = new Vour{contextp};
      while (!contextp->gotFinish()) { top->eval(); }
      delete top;
      delete contextp;
      return 0;
  }
EOF

Now we run Verilator on our little example;

verilator --cc --exe --build -j 0 -Wall sim_main.cpp our.v

Breaking this command down:

  1. --cc to get C++ output (versus e.g., SystemC, or only linting).

  2. --exe, along with our sim_main.cpp wrapper file, so the build will create an executable instead of only a library.

  3. --build so Verilator will call make itself. This is we don’t need to manually call make as a separate step. You can also write your own compile rules, and run make yourself as we show in Example SystemC Execution.)

  4. -j 0 to Verilate using use as many CPU threads as the machine has.

  5. -Wall so Verilator has stronger lint warnings enabled.

  6. And finally, our.v which is our SystemVerilog design file.

Once Verilator completes we can see the generated C++ code under the obj_dir directory.

ls -l obj_dir

(See Files Read/Written for descriptions of some of the files that were created.)

And now we run it:

obj_dir/Vour

And we get as output:

Hello World
- our.v:2: Verilog $finish

You’re better off using a Makefile to run the steps for you, so when your source changes, it will automatically run all of the appropriate steps. To aid this, Verilator can create a makefile dependency file. For examples that do this, see the examples directory in the distribution.