diff --git a/.github/workflows/makefile.yml b/.github/workflows/makefile.yml index 7b4b5bb..21f48b9 100644 --- a/.github/workflows/makefile.yml +++ b/.github/workflows/makefile.yml @@ -15,4 +15,4 @@ jobs: - uses: actions/checkout@v3 - name: Docker test - run: docker run -v ${PWD}:/work --user $(id -u):$(id -g) -e CCACHE_DIR=/work/.ccache --entrypoint make verilator/verilator:stable + run: make diff --git a/.gitignore b/.gitignore index a2a6896..18dbb45 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ examples/**/obj_dir examples/**/*.txt examples/**/*.vcd +.ccache diff --git a/README.md b/README.md index a8c720c..6c94472 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ The main contribution of this project is the `verilator.mk` makefile. Include it The examples show how Verilator can be used to simualate a Verilog circuit. Feel free to add more examples and tests for them. -All examples can be run using the `makefile` at the top level of this repository. +All examples can be run using the `makefile` at the top level of this repository. Simply type `make` to run the makefile. ## And diff --git a/examples/add/Add.sv b/examples/Add/Add.sv similarity index 100% rename from examples/add/Add.sv rename to examples/Add/Add.sv diff --git a/examples/add/makefile b/examples/Add/makefile similarity index 100% rename from examples/add/makefile rename to examples/Add/makefile diff --git a/examples/add/sim.cpp b/examples/Add/sim.cpp similarity index 71% rename from examples/add/sim.cpp rename to examples/Add/sim.cpp index 3d1c0be..ff06709 100644 --- a/examples/add/sim.cpp +++ b/examples/Add/sim.cpp @@ -6,15 +6,14 @@ #include int main(int argc, char** argv) { - VerilatedContext* contextp = new VerilatedContext; - contextp->commandArgs(argc, argv); - VAdd* top = new VAdd{contextp}; + VAdd* top = new VAdd; + Verilated::commandArgs(argc, argv); int stimuli_a[] = { 2, -1, 1, -6 }; int stimuli_b[] = { 4, 5, 2, 7 }; for (int i = 0; i < sizeof(stimuli_a) / sizeof(stimuli_a[0]); i++) { - if (contextp->gotFinish()) break; + if (Verilated::gotFinish()) break; top->a = stimuli_a[i]; top->b = stimuli_b[i]; @@ -25,6 +24,5 @@ int main(int argc, char** argv) { } delete top; - delete contextp; return 0; } diff --git a/examples/and/And.sv b/examples/And/And.sv similarity index 100% rename from examples/and/And.sv rename to examples/And/And.sv diff --git a/examples/and/makefile b/examples/And/makefile similarity index 100% rename from examples/and/makefile rename to examples/And/makefile diff --git a/examples/and/sim.cpp b/examples/And/sim.cpp similarity index 84% rename from examples/and/sim.cpp rename to examples/And/sim.cpp index 825d148..992d461 100644 --- a/examples/and/sim.cpp +++ b/examples/And/sim.cpp @@ -9,9 +9,8 @@ #include int main(int argc, char** argv) { - VerilatedContext* contextp = new VerilatedContext; - contextp->commandArgs(argc, argv); - VAnd* top = new VAnd{contextp}; + VAnd* top = new VAnd; + Verilated::commandArgs(argc, argv); // For waveform generation unsigned long tickcount = 0; @@ -27,7 +26,7 @@ int main(int argc, char** argv) { bool stimuli_b[] = { false, true, false, true }; for (int i = 0; i < sizeof(stimuli_a) / sizeof(stimuli_a[0]); i++) { - if (contextp->gotFinish()) break; + if (Verilated::gotFinish()) break; top->a = stimuli_a[i]; top->b = stimuli_b[i]; @@ -47,6 +46,5 @@ int main(int argc, char** argv) { delete trace; delete top; - delete contextp; return 0; } diff --git a/examples/doublesub/DoubleSub.sv b/examples/Doublesub/DoubleSub.sv similarity index 100% rename from examples/doublesub/DoubleSub.sv rename to examples/Doublesub/DoubleSub.sv diff --git a/examples/doublesub/Sub.sv b/examples/Doublesub/Sub.sv similarity index 100% rename from examples/doublesub/Sub.sv rename to examples/Doublesub/Sub.sv diff --git a/examples/doublesub/from_file.cpp b/examples/Doublesub/from_file.cpp similarity index 100% rename from examples/doublesub/from_file.cpp rename to examples/Doublesub/from_file.cpp diff --git a/examples/doublesub/makefile b/examples/Doublesub/makefile similarity index 100% rename from examples/doublesub/makefile rename to examples/Doublesub/makefile diff --git a/examples/doublesub/operands.data b/examples/Doublesub/operands.data similarity index 100% rename from examples/doublesub/operands.data rename to examples/Doublesub/operands.data diff --git a/examples/doublesub/sim.cpp b/examples/Doublesub/sim.cpp similarity index 80% rename from examples/doublesub/sim.cpp rename to examples/Doublesub/sim.cpp index 2357fb7..bddcdf2 100644 --- a/examples/doublesub/sim.cpp +++ b/examples/Doublesub/sim.cpp @@ -7,9 +7,8 @@ int get_stimuli(std::string filename, int *data); int main(int argc, char** argv) { - VerilatedContext* contextp = new VerilatedContext; - contextp->commandArgs(argc, argv); - VDoubleSub* top = new VDoubleSub{contextp}; + VDoubleSub* top = new VDoubleSub; + Verilated::commandArgs(argc, argv); int *operands = new int[200]; int noperands = get_stimuli(std::string{"operands.data"}, operands); @@ -29,6 +28,5 @@ int main(int argc, char** argv) { delete top; - delete contextp; return 0; } diff --git a/examples/hierarchy/delay/Delay.sv b/examples/Hierarchy/Delay/Delay.sv similarity index 100% rename from examples/hierarchy/delay/Delay.sv rename to examples/Hierarchy/Delay/Delay.sv diff --git a/examples/hierarchy/delay/main.cpp b/examples/Hierarchy/Delay/main.cpp similarity index 83% rename from examples/hierarchy/delay/main.cpp rename to examples/Hierarchy/Delay/main.cpp index e103c73..41de97a 100644 --- a/examples/hierarchy/delay/main.cpp +++ b/examples/Hierarchy/Delay/main.cpp @@ -5,9 +5,8 @@ #include int main(int argc, char** argv) { - VerilatedContext* contextp = new VerilatedContext; - contextp->commandArgs(argc, argv); - VDelay* top = new VDelay{contextp}; + VDelay* top = new VDelay; + Verilated::commandArgs(argc, argv); int data_in = 0x66234223; @@ -40,6 +39,5 @@ int main(int argc, char** argv) { assert(top->delayed_data == data_in); delete top; - delete contextp; return 0; } diff --git a/examples/hierarchy/delay/makefile b/examples/Hierarchy/Delay/makefile similarity index 100% rename from examples/hierarchy/delay/makefile rename to examples/Hierarchy/Delay/makefile diff --git a/examples/hierarchy/Hierarchy.sv b/examples/Hierarchy/Hierarchy.sv similarity index 92% rename from examples/hierarchy/Hierarchy.sv rename to examples/Hierarchy/Hierarchy.sv index f188c92..53d909f 100644 --- a/examples/hierarchy/Hierarchy.sv +++ b/examples/Hierarchy/Hierarchy.sv @@ -1,5 +1,5 @@ -`include "../doublesub/Sub.sv" -`include "delay/Delay.sv" +`include "../Doublesub/Sub.sv" +`include "Delay/Delay.sv" module Hierarchy ( input clk, diff --git a/examples/hierarchy/main.cpp b/examples/Hierarchy/main.cpp similarity index 84% rename from examples/hierarchy/main.cpp rename to examples/Hierarchy/main.cpp index e427fe8..ec9fc49 100644 --- a/examples/hierarchy/main.cpp +++ b/examples/Hierarchy/main.cpp @@ -5,9 +5,8 @@ #include int main(int argc, char** argv) { - VerilatedContext* contextp = new VerilatedContext; - contextp->commandArgs(argc, argv); - VHierarchy* top = new VHierarchy{contextp}; + VHierarchy* top = new VHierarchy; + Verilated::commandArgs(argc, argv); int data_in = 0x66234223; int subtract = 22; @@ -44,6 +43,5 @@ int main(int argc, char** argv) { assert(top->data_out == (data_in - subtract)); delete top; - delete contextp; return 0; } diff --git a/examples/hierarchy/makefile b/examples/Hierarchy/makefile similarity index 100% rename from examples/hierarchy/makefile rename to examples/Hierarchy/makefile diff --git a/verilator-docker.sh b/verilator-docker.sh new file mode 100755 index 0000000..15a5d15 --- /dev/null +++ b/verilator-docker.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# DESCRIPTION: Wrap a verilator call to run a docker container +# +# Copyright 2020 by Stefan Wallentowitz. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +# Pull newest image +docker pull verilator/verilator:4.038 > /dev/null + +# Get the project root +project_root=$(realpath $3) + +# Run the docker image with the user we "made" above +docker run -e CCACHE_DIR=/work/.ccache -v ${project_root}:/work -w /work/$2 --user $(id -u):$(id -g) verilator/verilator:$1 "${@:4}" diff --git a/verilator-wrap.sh b/verilator-wrap.sh new file mode 100755 index 0000000..80d839b --- /dev/null +++ b/verilator-wrap.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# DESCRIPTION: Wrap a Verilator call and copy vlt includes +# (inside docker container) +# +# Copyright 2020 by Stefan Wallentowitz. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +perl /usr/local/bin/verilator "$@" +status=$? +if [ $status -ne 0 ]; then + exit $status +fi + +# Check if user set an obj_dir +obj_dir=$(echo " $@" | grep -oP '\s--Mdir\s*\K\S+') +if [ "$obj_dir" == "" ]; then + obj_dir="obj_dir" +fi + +# If the run was successful: Copy required files to allow build without this container +if [ -e ${obj_dir} ]; then + # Copy files required for the build + mkdir -p ${obj_dir}/vlt + cp -r /usr/local/share/verilator/bin ${obj_dir}/vlt + cp -r /usr/local/share/verilator/include ${obj_dir}/vlt + # Point Makefile to that folder + sed -i 's/VERILATOR_ROOT = \/usr\/local\/share\/verilator/VERILATOR_ROOT = vlt/g' ${obj_dir}/*.mk +fi diff --git a/verilator.mk b/verilator.mk index b63992b..5f424f1 100644 --- a/verilator.mk +++ b/verilator.mk @@ -1,23 +1,38 @@ +MODULE_FOLDER ?= examples +PROJECT_ROOT ?= ${VERILATOR_ROOT} -VERILATOR_EXE := obj_dir/V$(PROJECT_NAME) +SHELL := /bin/bash -PARSER ?= $(VERILATOR_ROOT)/default_parser.sh +# Hashtag is a comment in make, but we want to use it in shell commands +HASHTAG := \# + +# Find the path between the top level folder and the source code folder +# Just doing ${MODULE_FOLDER}/${PROJECT_NAME} is not sufficient, because there +# might be folders between the module folder and project folder. Like in the +# Hierachy example. +PATH_FROM_ROOT_TO_SRC = $(shell p=$(shell pwd); g=$${p${HASHTAG}${HASHTAG}*/${MODULE_FOLDER}}; echo $$g) -VERILATOR_ARGS += --cc --build --exe --trace +VERILATOR := $(VERILATOR_ROOT)/verilator-docker.sh +VERILATOR_ARGS := 4.038 ${MODULE_FOLDER}${PATH_FROM_ROOT_TO_SRC} ${PROJECT_ROOT} +VERILATOR_ARGS_LINT := --lint-only -Wall +VERILATOR_ARGS_EMULATOR := --cc --build --exe --trace + +VERILATOR_EMULATOR := obj_dir/V$(PROJECT_NAME) +PARSER ?= $(VERILATOR_ROOT)/default_parser.sh all: run -lint: $(SOURCES) - verilator --lint-only -Wall $^ --top-module $(PROJECT_NAME) +lint: $(SOURCES) $(GENERATED) + ./$(VERILATOR) $(VERILATOR_ARGS) $(VERILATOR_ARGS_LINT) $(SOURCES) --top-module $(PROJECT_NAME) -$(VERILATOR_EXE): lint | $(SOURCES) - verilator $(VERILATOR_ARGS) $(SIMFILES) $(SOURCES) > /dev/null +$(VERILATOR_EMULATOR): lint | $(SOURCES) $(GENERATED) + ./$(VERILATOR) $(VERILATOR_ARGS) $(VERILATOR_ARGS_EMULATOR) $(SIMFILES) $(SOURCES) > /dev/null -run: $(VERILATOR_EXE) - # https://stackoverflow.com/questions/17757039/equivalent-of-pipefail-in-dash-shell +# https://stackoverflow.com/questions/17757039/equivalent-of-pipefail-in-dash-shell +run: $(VERILATOR_EMULATOR) @mkfifo named_pipe @tee output.txt < named_pipe & - @./$(VERILATOR_EXE) > named_pipe; ./$(PARSER) $(PROJECT_NAME) $$? output.txt + @./$(VERILATOR_EMULATOR) > named_pipe; ./$(PARSER) $(PROJECT_NAME) $$? output.txt @rm named_pipe clean: