Services - tools - models - for embedded software development
Embecosm divider strip
Prev  Next

6.2.3.  Access to Verilator Model Signals via Tasks and Functions

The recommended way to access signals is via a Verilog task or function. These are converted by Verilator into C++ class functions. Inputs to tasks and functions become arguments passed by value to the C++ function, while outputs become arguments passed by reference (and so can be used for results).

Verilog tasks become C++ void functions, while Verilog functions become C++ functions with a return type of a size appropriate to the result of the Verilog function (uint8_t, uint16_t, uint32_t or uint64_t).

[Caution]Caution

One limitation of Verilator is that it cannot handle functions which return values of more than 64 bits. If this is required, an output argument of either a task or function should be used.

For an example consider the 32-bit wb_insn register in the ORPSoC control unit. It's full hierarchical reference is:

orpsoc_fpga_top.or1200_top.or1200_cpu.or1200_ctrl.wb_insn
	

It is declared as:

reg [31:0]  wb_insn;
	

A Verilog function is declared to give access to this register:

`ifdef verilator
   function [31:0] get_wb_insn;
      // verilator public
      get_wb_insn = wb_insn;
   endfunction // get_wb_insn
`endif
	

There are two items of note. First the function must include a verilog public comment immediately after its declaration. Secondly functions without inputs are not permitted in IEEE 1364-2001, so this code must only be exposed to Verilator processing.

Verilator defines verilator, so this can be achieved by surrounding the code with `ifdef verilator and endif.

The signal can then be accessed from C++, having included the headers for all the intermediate classes:

#include "Vorpsoc_fpga_top_orpsoc_fpga_top.h"
#include "Vorpsoc_fpga_top_or1200_top.h"
#include "Vorpsoc_fpga_top_or1200_cpu.h"
#include "Vorpsoc_fpga_top_or1200_ctrl.h"

...

  Vorpsoc_fpga_top *orpsoc = new Vorpsoc_fpga_top ("orpsoc");

...

  uint32_t  wb_insn =
    orpsoc->v->or1200_top->or1200_cpu->or1200_ctrl->get_wb_insn ();
	

Pitfalls with Accessing Signals using Tasks and Functions

Accessor functions typically require no inputs. This is acceptable to Verilator, but is not valid Verilog according to IEEE 1364-2001. Thus (as in the example above), these functions must be surrounded by `ifdef verilator and endif so they are only seen by Verilator

Verilator cannot make public functions with return values of greater than 64-bits. Such results should be returned via an output argument, where they will be an array of uint32_t.

Embecosm divider strip