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

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

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

Now we run Verilator on our little example.

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

Breaking this command down:

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

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

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

  4. --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.)

  5. An 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:


And we get as output:

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

Really, 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.