Adjust to newer simutil_verilator
simutil_verilator was improved in various ways. The main improvements
are:
- Memories can be loaded with ELF files directly, instead of VMEM files.
- A generic way to specify memories was added.
- Reworked interface to be easier to use (less duplicated code).
These changes require adjustemnts to our code.
- The memory primitives need to support a new
`simutil_verilator_memload()` DPI function, which is used to write the
converted ELF file.
- libelf is required for ELF parsing. Add this dependency to the
core files, documentation and to the CI setup.
- VerilatorSimCtrl is now much easier to use by calling the `Exec()`
function. Everything else is now handled by VerilatorSimCtrl itself.
By using stack-allocated objects we can simplify error/free handling.
- VerilatorSimCtrl doesn't expose a static variable `simctrl` any more,
but instead implements a singleton accessible through
`VerilatorSimCtrl::GetInstance()`. Update spidpi to use this.
Signed-off-by: Philipp Wagner <phw@lowrisc.org>
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index eb56edc..2fcd1dd 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -174,7 +174,7 @@
pool: Default
steps:
- bash: |
- sudo apt-get install -y python3 python3-pip build-essential srecord python3-setuptools zlib1g-dev libusb-1.0 \
+ sudo apt-get install -y python3 python3-pip build-essential srecord python3-setuptools zlib1g-dev libusb-1.0 libelf-dev \
&& sudo pip3 install -U -r python-requirements.txt \
&& sudo apt-get install git make autoconf g++ flex bison curl
displayName: 'Install dependencies'
@@ -265,7 +265,7 @@
- sw_build
steps:
- bash: |
- sudo apt-get install -y python3 python3-pip build-essential python3-setuptools tree
+ sudo apt-get install -y python3 python3-pip build-essential python3-setuptools libelf1 tree
sudo pip3 install -r python-requirements.txt
displayName: 'Install dependencies'
- template: 'ci/download-artifacts-template.yml'
diff --git a/doc/ug/install_instructions/index.md b/doc/ug/install_instructions/index.md
index b64face..5355acd 100644
--- a/doc/ug/install_instructions/index.md
+++ b/doc/ug/install_instructions/index.md
@@ -59,7 +59,7 @@
$ sudo apt-get install git python3 python3-pip python3-setuptools \
build-essential autoconf flex bison ninja-build pkgconf \
srecord zlib1g-dev libftdi1-dev libftdi1-2 libssl-dev \
- libusb-1.0-0-dev libtool
+ libusb-1.0-0-dev libtool libelf-dev
```
Some tools in this repository are written in Python 3 and require Python dependencies to be installed through `pip`.
diff --git a/doc/ug/quickstart.md b/doc/ug/quickstart.md
index 69d8c81..c3a1ab7 100644
--- a/doc/ug/quickstart.md
+++ b/doc/ug/quickstart.md
@@ -12,10 +12,11 @@
* libusb 1.x
* libftdi1 1.x
* usbutils
+* libelf1
Under Ubuntu these can be installed with:
```console
-$ sudo apt-get install xz-utils screen fdisk libftdi1-2 libusb-1.0-0 usbutils
+$ sudo apt-get install xz-utils screen fdisk libftdi1-2 libusb-1.0-0 usbutils libelf1
```
## Extract the release
diff --git a/hw/dv/dpi/spidpi/spidpi.c b/hw/dv/dpi/spidpi/spidpi.c
index c1dc7d0..08a80d7 100644
--- a/hw/dv/dpi/spidpi/spidpi.c
+++ b/hw/dv/dpi/spidpi/spidpi.c
@@ -26,28 +26,6 @@
// and resume at the first SPI packet
// #define CONTROL_TRACE
-extern VerilatorSimCtrl *simctrl;
-
-static void finish(void) {
- if (!simctrl) {
- return;
- }
- simctrl->RequestStop(true);
-}
-
-#ifdef CONTROL_TRACE
-static void trace(int enable) {
- if (!simctrl) {
- return;
- }
- if (enable) {
- simctrl->TraceOn();
- } else {
- simctrl->TraceOff();
- }
-}
-#endif
-
void *spidpi_create(const char *name, int mode, int loglevel) {
int i;
struct spidpi_ctx *ctx =
@@ -126,7 +104,7 @@
#ifdef CONTROL_TRACE
if (ctx->tick == 4) {
- trace(0);
+ VerilatorSimCtrl::GetInstance().TraceOff();
}
#endif
@@ -149,7 +127,7 @@
ctx->din = 0;
ctx->state = SP_CSFALL;
#ifdef CONTROL_TRACE
- trace(1);
+ VerilatorSimCtrl::GetInstance().TraceOn();
#endif
}
}
@@ -218,7 +196,7 @@
ctx->state = SP_IDLE;
break;
case SP_FINISH:
- finish();
+ VerilatorSimCtrl::GetInstance().RequestStop(true);
break;
default:
ctx->driving = set_sck | (ctx->driving & ~P2D_SCK);
diff --git a/hw/dv/dpi/usbdpi/usbdpi.c b/hw/dv/dpi/usbdpi/usbdpi.c
index 5ba8909..5ce8265 100644
--- a/hw/dv/dpi/usbdpi/usbdpi.c
+++ b/hw/dv/dpi/usbdpi/usbdpi.c
@@ -32,15 +32,6 @@
"HS_SENDACK 8", "HS_WAIT_PKT 9", "HS_ACKIFDATA 10", "HS_SENDHI 11",
"HS_EMPTYDATA 12", "HS_WAITACK2 13", "HS_NEXTFRAME 14"};
-extern VerilatorSimCtrl *simctrl;
-
-static void usbdpi_finish(int simulation_success) {
- if (!simctrl) {
- return;
- }
- simctrl->RequestStop(simulation_success);
-}
-
void *usbdpi_create(const char *name, int loglevel) {
int i;
struct usbdpi_ctx *ctx =
@@ -553,7 +544,8 @@
}
switch (ctx->state) {
case ST_IDLE:
- if ((simctrl && simctrl->TracingEnabled() && (ctx->frame == 20)) ||
+ if ((VerilatorSimCtrl::GetInstance().TracingEnabled() &&
+ (ctx->frame == 20)) ||
(ctx->frame > 50)) {
printf("USB: usbdpi done, frame: %d, success: %d, state: %d\n",
ctx->frame, ctx->baudrate_set_successfully, ctx->state);
@@ -561,7 +553,8 @@
// If we were able to set the BAUD rate sucessfully, the DUT
// provided reasonable responses to our requests. Ideally, we
// would have a more advanced test here.
- usbdpi_finish(ctx->baudrate_set_successfully);
+ VerilatorSimCtrl::GetInstance().RequestStop(
+ ctx->baudrate_set_successfully);
}
switch (ctx->frame) {
diff --git a/hw/ip/prim_generic/rtl/prim_generic_ram_1p.sv b/hw/ip/prim_generic/rtl/prim_generic_ram_1p.sv
index b860da5..ad03e43 100644
--- a/hw/ip/prim_generic/rtl/prim_generic_ram_1p.sv
+++ b/hw/ip/prim_generic/rtl/prim_generic_ram_1p.sv
@@ -64,18 +64,32 @@
end
`ifdef VERILATOR
+ // Task for loading 'mem' with SystemVerilog system task $readmemh()
export "DPI-C" task simutil_verilator_memload;
+ // Function for setting a specific 32 bit element in |mem|
+ // Returns 1 (true) for success, 0 (false) for errors.
+ export "DPI-C" function simutil_verilator_set_mem;
task simutil_verilator_memload;
input string file;
$readmemh(file, mem);
endtask
+
+ // TODO: Allow 'val' to have other widths than 32 bit
+ function int simutil_verilator_set_mem(input int index,
+ input logic[31:0] val);
+ if (index >= Depth) begin
+ return 0;
+ end
+
+ mem[index] = val;
+ return 1;
+ endfunction
`endif
`ifdef SRAM_INIT_FILE
- localparam MEM_FILE = `"`SRAM_INIT_FILE`";
- initial
- begin
+ localparam MEM_FILE = `"`SRAM_INIT_FILE`";
+ initial begin
$display("Initializing SRAM from %s", MEM_FILE);
$readmemh(MEM_FILE, mem);
end
diff --git a/hw/ip/prim_generic/rtl/prim_generic_rom.sv b/hw/ip/prim_generic/rtl/prim_generic_rom.sv
index 6228622..30bed51 100644
--- a/hw/ip/prim_generic/rtl/prim_generic_rom.sv
+++ b/hw/ip/prim_generic/rtl/prim_generic_rom.sv
@@ -39,16 +39,30 @@
`ASSERT(noXOnCsI, !$isunknown(cs_i), clk_i, '0)
`ifdef VERILATOR
+ // Task for loading 'mem' with SystemVerilog system task $readmemh()
export "DPI-C" task simutil_verilator_memload;
+ // Function for setting a specific 32 bit element in |mem|
+ // Returns 1 (true) for success, 0 (false) for errors.
+ export "DPI-C" function simutil_verilator_set_mem;
task simutil_verilator_memload;
input string file;
$readmemh(file, mem);
endtask
+
+ // TODO: Allow 'val' to have other widths than 32 bit
+ function int simutil_verilator_set_mem(input int index,
+ input logic[31:0] val);
+ if (index >= Depth) begin
+ return 0;
+ end
+
+ mem[index] = val;
+ return 1;
+ endfunction
`endif
`ifdef ROM_INIT_FILE
-
localparam MEM_FILE = `"`ROM_INIT_FILE`";
initial begin
$display("Initializing ROM from %s", MEM_FILE);
diff --git a/hw/top_earlgrey/top_earlgrey_usb_verilator.cc b/hw/top_earlgrey/top_earlgrey_usb_verilator.cc
index a27653b..8ff36a4 100644
--- a/hw/top_earlgrey/top_earlgrey_usb_verilator.cc
+++ b/hw/top_earlgrey/top_earlgrey_usb_verilator.cc
@@ -2,101 +2,35 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
-#include <signal.h>
-
#include <iostream>
-#include "Vtop_earlgrey_usb_verilator.h"
#include "verilated_toplevel.h"
#include "verilator_sim_ctrl.h"
-top_earlgrey_usb_verilator *top;
-VerilatorSimCtrl *simctrl;
-
-static void SignalHandler(int sig) {
- if (!simctrl) {
- return;
- }
-
- switch (sig) {
- case SIGINT:
- simctrl->RequestStop(true);
- break;
- case SIGUSR1:
- if (simctrl->TracingEnabled()) {
- simctrl->TraceOff();
- } else {
- simctrl->TraceOn();
- }
- break;
- }
-}
-
-static void SetupSignalHandler() {
- struct sigaction sigIntHandler;
-
- sigIntHandler.sa_handler = SignalHandler;
- sigemptyset(&sigIntHandler.sa_mask);
- sigIntHandler.sa_flags = 0;
-
- sigaction(SIGINT, &sigIntHandler, NULL);
- sigaction(SIGUSR1, &sigIntHandler, NULL);
-}
-
int main(int argc, char **argv) {
- int retcode;
- top = new top_earlgrey_usb_verilator;
- simctrl = new VerilatorSimCtrl(top, top->clk_i, top->rst_ni,
- VerilatorSimCtrlFlags::ResetPolarityNegative);
+ top_earlgrey_usb_verilator top;
+ VerilatorSimCtrl &simctrl = VerilatorSimCtrl::GetInstance();
+ simctrl.SetTop(&top, &top.clk_i, &top.rst_ni,
+ VerilatorSimCtrlFlags::ResetPolarityNegative);
- SetupSignalHandler();
-
- if (!simctrl->ParseCommandArgs(argc, argv, retcode)) {
- goto free_return;
- }
-
- std::cout << "Simulation of OpenTitan Earl Grey" << std::endl
- << "=================================" << std::endl
- << std::endl;
-
- if (simctrl->TracingPossible()) {
- std::cout << "Tracing can be toggled by sending SIGUSR1 to this process:"
- << std::endl
- << "$ kill -USR1 " << getpid() << std::endl;
- }
-
- // Initialize ROM
- simctrl->InitRom(
- "TOP.top_earlgrey_usb_verilator.top_earlgrey_usb.u_rom_rom"
- ".gen_mem_generic.u_impl_generic");
-
- // Initialize Ram
- simctrl->InitRam(
+ simctrl.RegisterMemoryArea("rom",
+ "TOP.top_earlgrey_usb_verilator.top_earlgrey_usb."
+ "u_rom_rom.gen_mem_generic."
+ "u_impl_generic");
+ simctrl.RegisterMemoryArea(
+ "ram",
"TOP.top_earlgrey_usb_verilator.top_earlgrey_usb.u_ram1p_ram_main"
".gen_mem_generic.u_impl_generic");
-
- // Initialize Flash
- // simctrl->InitFlash(
- // "TOP.top_earlgrey_usb_verilator.top_earlgrey_usb.u_flash_eflash.gen_flash."
- // "u_impl_generic.gen_flash_banks[0].u_impl_generic.gen_mem_generic.u_impl_"
- // "generic");
- simctrl->InitFlash(
+ simctrl.RegisterMemoryArea(
+ "flash",
"TOP.top_earlgrey_usb_verilator.top_earlgrey_usb.u_flash_eflash."
"gen_flash_banks[0].u_flash.gen_flash.u_impl_generic.u_mem.gen_mem_"
"generic.u_impl_"
"generic");
- simctrl->Run();
- simctrl->PrintStatistics();
+ std::cout << "Simulation of OpenTitan Earl Grey" << std::endl
+ << "=================================" << std::endl
+ << std::endl;
- if (simctrl->TracingEverEnabled()) {
- std::cout << std::endl
- << "You can view the simulation traces by calling" << std::endl
- << "$ gtkwave " << simctrl->GetSimulationFileName() << std::endl;
- }
-
-free_return:
- delete top;
- delete simctrl;
- return retcode;
+ return simctrl.Exec(argc, argv);
}
diff --git a/hw/top_earlgrey/top_earlgrey_usb_verilator.core b/hw/top_earlgrey/top_earlgrey_usb_verilator.core
index 28555ab..d951058 100644
--- a/hw/top_earlgrey/top_earlgrey_usb_verilator.core
+++ b/hw/top_earlgrey/top_earlgrey_usb_verilator.core
@@ -46,7 +46,7 @@
- '--trace-params'
- '--trace-max-array 1024'
- '-CFLAGS "-std=c++11 -Wall -DVM_TRACE_FMT_FST -DTOPLEVEL_NAME=top_earlgrey_usb_verilator -g"'
- - '-LDFLAGS "-pthread -lutil"'
+ - '-LDFLAGS "-pthread -lutil -lelf"'
- "-Wall"
- "-Wno-PINCONNECTEMPTY"
# XXX: Cleanup all warnings and remove this option
diff --git a/hw/top_earlgrey/top_earlgrey_verilator.cc b/hw/top_earlgrey/top_earlgrey_verilator.cc
index d18a53f..03efc1c 100644
--- a/hw/top_earlgrey/top_earlgrey_verilator.cc
+++ b/hw/top_earlgrey/top_earlgrey_verilator.cc
@@ -2,103 +2,35 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
-#include <signal.h>
-
#include <iostream>
-
-#include "Vtop_earlgrey_verilator.h"
#include "verilated_toplevel.h"
#include "verilator_sim_ctrl.h"
-
-top_earlgrey_verilator *top;
-VerilatorSimCtrl *simctrl;
-
-static void SignalHandler(int sig) {
- if (!simctrl) {
- return;
- }
-
- switch (sig) {
- case SIGINT:
- simctrl->RequestStop(true);
- break;
- case SIGUSR1:
- if (simctrl->TracingEnabled()) {
- simctrl->TraceOff();
- } else {
- simctrl->TraceOn();
- }
- break;
- }
-}
-
-static void SetupSignalHandler() {
- struct sigaction sigIntHandler;
-
- sigIntHandler.sa_handler = SignalHandler;
- sigemptyset(&sigIntHandler.sa_mask);
- sigIntHandler.sa_flags = 0;
-
- sigaction(SIGINT, &sigIntHandler, NULL);
- sigaction(SIGUSR1, &sigIntHandler, NULL);
-}
-
int main(int argc, char **argv) {
- int retcode;
- top = new top_earlgrey_verilator;
- simctrl = new VerilatorSimCtrl(top, top->clk_i, top->rst_ni,
- VerilatorSimCtrlFlags::ResetPolarityNegative);
+ top_earlgrey_verilator top;
+ VerilatorSimCtrl &simctrl = VerilatorSimCtrl::GetInstance();
+ simctrl.SetTop(&top, &top.clk_i, &top.rst_ni,
+ VerilatorSimCtrlFlags::ResetPolarityNegative);
- SetupSignalHandler();
-
- if (!simctrl->ParseCommandArgs(argc, argv, retcode)) {
- goto free_return;
- }
-
- std::cout << "Simulation of OpenTitan Earl Grey" << std::endl
- << "=================================" << std::endl
- << std::endl;
-
- if (simctrl->TracingPossible()) {
- std::cout << "Tracing can be toggled by sending SIGUSR1 to this process:"
- << std::endl
- << "$ kill -USR1 " << getpid() << std::endl;
- }
-
- // Initialize ROM
- simctrl->InitRom(
- "TOP.top_earlgrey_verilator.top_earlgrey.u_rom_rom"
- ".gen_mem_generic.u_impl_generic");
-
- // Initialize Ram
- simctrl->InitRam(
+ simctrl.RegisterMemoryArea(
+ "rom",
+ "TOP.top_earlgrey_verilator.top_earlgrey.u_rom_rom.gen_mem_generic."
+ "u_impl_generic");
+ simctrl.RegisterMemoryArea(
+ "ram",
"TOP.top_earlgrey_verilator.top_earlgrey.u_ram1p_ram_main"
".gen_mem_generic.u_impl_generic");
-
- // Initialize Flash
- // simctrl->InitFlash(
- // "TOP.top_earlgrey_verilator.top_earlgrey.u_flash_eflash.gen_flash."
- // "u_impl_generic.gen_flash_banks[0].u_impl_generic.gen_mem_generic.u_impl_"
- // "generic");
- simctrl->InitFlash(
+ simctrl.RegisterMemoryArea(
+ "flash",
"TOP.top_earlgrey_verilator.top_earlgrey.u_flash_eflash."
"gen_flash_banks[0].u_flash.gen_flash.u_impl_generic.u_mem.gen_mem_"
"generic.u_impl_"
"generic");
- simctrl->Run();
- simctrl->PrintStatistics();
+ std::cout << "Simulation of OpenTitan Earl Grey" << std::endl
+ << "=================================" << std::endl
+ << std::endl;
- if (simctrl->TracingEverEnabled()) {
- std::cout << std::endl
- << "You can view the simulation traces by calling" << std::endl
- << "$ gtkwave " << simctrl->GetSimulationFileName() << std::endl;
- }
-
-free_return:
- delete top;
- delete simctrl;
- return retcode;
+ return simctrl.Exec(argc, argv);
}
diff --git a/hw/top_earlgrey/top_earlgrey_verilator.core b/hw/top_earlgrey/top_earlgrey_verilator.core
index 371bb13..a83cfae 100644
--- a/hw/top_earlgrey/top_earlgrey_verilator.core
+++ b/hw/top_earlgrey/top_earlgrey_verilator.core
@@ -73,7 +73,7 @@
- '--trace-params'
- '--trace-max-array 1024'
- '-CFLAGS "-std=c++11 -Wall -DVM_TRACE_FMT_FST -DTOPLEVEL_NAME=top_earlgrey_verilator -g"'
- - '-LDFLAGS "-pthread -lutil"'
+ - '-LDFLAGS "-pthread -lutil -lelf"'
- "-Wall"
- "-Wno-PINCONNECTEMPTY"
# XXX: Cleanup all warnings and remove this option