From a67cca5aa8713e5b6e63ced561e9df23520a16d1 Mon Sep 17 00:00:00 2001 From: Nikolay Puzanov Date: Thu, 17 Nov 2022 13:02:15 +0300 Subject: [PATCH] Initial commit --- .gitignore | 4 ++ _template_iverilog/Makefile | 28 ++++++++ _template_iverilog/shell-latest.nix | 9 +++ _template_iverilog/shell.nix | 5 ++ _template_iverilog/testbench.sv | 13 ++++ _template_verilator/.clang-format | 38 ++++++++++ _template_verilator/.gitignore | 1 + _template_verilator/Makefile | 23 ++++++ _template_verilator/clock_generator.cpp | 95 +++++++++++++++++++++++++ _template_verilator/clock_generator.hpp | 31 ++++++++ _template_verilator/shell.nix | 20 ++++++ _template_verilator/top.cpp | 72 +++++++++++++++++++ _template_verilator/top.sv | 22 ++++++ 13 files changed, 361 insertions(+) create mode 100644 .gitignore create mode 100644 _template_iverilog/Makefile create mode 100644 _template_iverilog/shell-latest.nix create mode 100644 _template_iverilog/shell.nix create mode 100644 _template_iverilog/testbench.sv create mode 100644 _template_verilator/.clang-format create mode 100644 _template_verilator/.gitignore create mode 100644 _template_verilator/Makefile create mode 100644 _template_verilator/clock_generator.cpp create mode 100644 _template_verilator/clock_generator.hpp create mode 100644 _template_verilator/shell.nix create mode 100644 _template_verilator/top.cpp create mode 100644 _template_verilator/top.sv diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fac15ee --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/* +!.gitignore +!_template_iverilog +!_template_verilator diff --git a/_template_iverilog/Makefile b/_template_iverilog/Makefile new file mode 100644 index 0000000..ebef602 --- /dev/null +++ b/_template_iverilog/Makefile @@ -0,0 +1,28 @@ +TESTBENCH ?= testbench +SOURCES ?= testbench.sv +INCLUDE ?= + +COMPILE_FLAGS += -DTESTBENCH -g2012 +PLUSARGS = -fst + +.SILENT: + +all: clean run + +dump: COMPILE_FLAGS += -DDUMP +dump: all + +$(TESTBENCH).vvp: $(SOURCES) + iverilog $(COMPILE_FLAGS) $(INCLUDE) -s $(TESTBENCH) -o $(TESTBENCH).vvp $(SOURCES) + +run: $(TESTBENCH).vvp + vvp $(TESTBENCH).vvp $(PLUSARGS) + +preprocess: $(SORCES) + iverilog -E $(COMPILE_FLAGS) $(INCLUDE) -s $(TESTBENCH) -o $(TESTBENCH)_preprocessed.sv $(SOURCES) + +clean: + rm -rf *.vvp + rm -rf *.fst + rm -rf *.vcd + rm -rf *.csv diff --git a/_template_iverilog/shell-latest.nix b/_template_iverilog/shell-latest.nix new file mode 100644 index 0000000..dcdc51a --- /dev/null +++ b/_template_iverilog/shell-latest.nix @@ -0,0 +1,9 @@ +{ pkgs ? import {} }: + +with pkgs; +let + iverilog-latest = callPackage /etc/nixos/programs/iverilog-latest.nix {}; +in +mkShell { + packages = [ iverilog-latest gnumake ]; +} diff --git a/_template_iverilog/shell.nix b/_template_iverilog/shell.nix new file mode 100644 index 0000000..2c8ea2d --- /dev/null +++ b/_template_iverilog/shell.nix @@ -0,0 +1,5 @@ +{ pkgs ? import {} }: + +with pkgs; mkShell { + packages = [ verilog gnumake ]; +} diff --git a/_template_iverilog/testbench.sv b/_template_iverilog/testbench.sv new file mode 100644 index 0000000..b91d2af --- /dev/null +++ b/_template_iverilog/testbench.sv @@ -0,0 +1,13 @@ +`timescale 1ps/1ps + +/* verilator lint_off DECLFILENAME */ +/* verilator lint_off MULTITOP */ +/* verilator lint_off STMTDLY */ +/* verilator lint_off INFINITELOOP */ +/* verilator lint_off INITIALDLY */ + +module testbench; + initial begin + $finish; + end +endmodule diff --git a/_template_verilator/.clang-format b/_template_verilator/.clang-format new file mode 100644 index 0000000..f034a58 --- /dev/null +++ b/_template_verilator/.clang-format @@ -0,0 +1,38 @@ +BasedOnStyle: LLVM +IndentWidth: 4 +UseTab: false + +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: true +AlignConsecutiveMacros: true +AlignEscapedNewlines: Left +AlignOperands: Align + +AlignTrailingComments: true +AllowShortBlocksOnASingleLine: Empty +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: WithoutElse + +BinPackArguments: true + +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterControlStatement: MultiLine + AfterFunction: true + AfterStruct: true + BeforeElse: true + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + +IncludeBlocks: Regroup +SpaceBeforeParens: ControlStatements +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpacesBeforeTrailingComments: 4 +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: false +SpacesInParentheses: false +SpacesInSquareBrackets: false diff --git a/_template_verilator/.gitignore b/_template_verilator/.gitignore new file mode 100644 index 0000000..895dab3 --- /dev/null +++ b/_template_verilator/.gitignore @@ -0,0 +1 @@ +compile_flags.txt diff --git a/_template_verilator/Makefile b/_template_verilator/Makefile new file mode 100644 index 0000000..265c94c --- /dev/null +++ b/_template_verilator/Makefile @@ -0,0 +1,23 @@ +TOP_MODULE = top + +SOURCES = top.sv top.cpp clock_generator.cpp +INCLUDES = + +## Parameters example: +# PARAM_INPUT_WIDTH ?= 15 +# PARAM_FFT_LENGTH ?= 256 +# PARAM_REJECTOR_K_WIDTH ?= 8 + +FLAGS = -Wno-WIDTH -cc --top-module $(TOP_MODULE) +1800-2017ext+sv --timing --trace --Mdir $(TOP_MODULE) +FLAGS += $(foreach V,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(V))=$($(V))) + +all: $(SOURCES) + verilator $(FLAGS) --exe --build $(INCLUDES) $(SOURCES) + +pre: + verilator $(FLAGS) $(INCLUDES) $(SOURCES) + +clean: + rm -rf obj_dir + rm -rf datapath + rm -rf *.vcd diff --git a/_template_verilator/clock_generator.cpp b/_template_verilator/clock_generator.cpp new file mode 100644 index 0000000..99f3732 --- /dev/null +++ b/_template_verilator/clock_generator.cpp @@ -0,0 +1,95 @@ +#include "clock_generator.hpp" + +ClockGenerator::~ClockGenerator() +{ + while (clocks) { + clock *next = clocks->next; + delete clocks; + clocks = next; + } +}; + +void ClockGenerator::add_clock(uint8_t &net, uint64_t period, uint64_t skew) +{ + if (skew >= period) throw "The skew value cannot exceed the period"; + + clock *clk = new clock(net, period, skew); + net = (clk->position < clk->period / 2) ? 0 : 1; + + if (clocks == NULL) + clocks = clk; + else { + clock *last = clocks; + while (last->next) + last = last->next; + last->next = clk; + } +}; + +uint64_t ClockGenerator::next_event(void) +{ + uint64_t time_to_next = UINT64_MAX; + clock *clk = clocks; + + while (clk) { + uint64_t ttn; + + if (clk->position < clk->period / 2) + ttn = clk->period / 2 - clk->position; + else + ttn = clk->period - clk->position; + + if (time_to_next > ttn) time_to_next = ttn; + + clk = clk->next; + } + + clk = clocks; + while (clk) { + uint8_t next_val; + + clk->position += time_to_next; + if (clk->position >= clk->period) clk->position -= clk->period; + + next_val = (clk->position < clk->period / 2) ? 0 : 1; + clk->posedge = (next_val == 1 && clk->net == 0) ? true : false; + clk->negedge = (next_val == 0 && clk->net == 1) ? true : false; + clk->net = next_val; + + clk = clk->next; + } + + return time_to_next; +}; + +bool ClockGenerator::is_posegde(uint8_t &net) +{ + clock *clk = clocks; + bool posedge = false; + + while (clk) { + if (std::addressof(net) == std::addressof(clk->net)) { + posedge = clk->posedge; + break; + } + clk = clk->next; + } + + return posedge; +}; + +bool ClockGenerator::is_negedge(uint8_t &net) +{ + clock *clk = clocks; + bool negedge = false; + + while (clk) { + if (std::addressof(net) == std::addressof(clk->net)) { + negedge = clk->negedge; + break; + } + clk = clk->next; + } + + return negedge; +}; diff --git a/_template_verilator/clock_generator.hpp b/_template_verilator/clock_generator.hpp new file mode 100644 index 0000000..3d7aad4 --- /dev/null +++ b/_template_verilator/clock_generator.hpp @@ -0,0 +1,31 @@ +#ifndef _CLOCK_GENERATOR_HPP +#define _CLOCK_GENERATOR_HPP + +#include +#include + +class ClockGenerator +{ +protected: + struct clock { + clock(uint8_t &net, uint64_t period, uint64_t position) : + net(net), period(period), position(position), next(NULL), + posedge(false), negedge(false) {}; + + uint8_t &net; + uint64_t period; + uint64_t position; + bool posedge; + bool negedge; + clock *next; + } *clocks = NULL; + +public: + ~ClockGenerator(); + void add_clock(uint8_t &net, uint64_t period, uint64_t skew); + uint64_t next_event(void); + bool is_posegde(uint8_t &net); + bool is_negedge(uint8_t &net); +}; + +#endif // _CLOCK_GENERATOR_HPP diff --git a/_template_verilator/shell.nix b/_template_verilator/shell.nix new file mode 100644 index 0000000..d40ec27 --- /dev/null +++ b/_template_verilator/shell.nix @@ -0,0 +1,20 @@ +{ pkgs ? import {} }: + +with pkgs; +let + unstable = import {}; + flags-file = "compile_flags.txt"; +in +mkShell { + packages = [ gnumake unstable.verilator ]; + + shellHook = '' + echo -n > ${flags-file} + echo -DVM_TRACE=1 >> ${flags-file} + echo -xc++ >> ${flags-file} + echo -I./obj_dir >> ${flags-file} + echo -I${unstable.verilator}/share/verilator/include >> ${flags-file} + echo -I${clang}/resource-root/include >> ${flags-file} + echo -I${glibc.dev}/include >> ${flags-file} + ''; +} diff --git a/_template_verilator/top.cpp b/_template_verilator/top.cpp new file mode 100644 index 0000000..c50c9a5 --- /dev/null +++ b/_template_verilator/top.cpp @@ -0,0 +1,72 @@ +#include "Vtop.h" +#include "clock_generator.hpp" + +#include +#include +#include + +#define DUMPFILE "test.vcd" + +int main(int argc, char **argv) +{ + VerilatedContext *ctx = new VerilatedContext; + ctx->commandArgs(argc, argv); + + /* Create model instance */ + Vtop *top = new Vtop(ctx); + +#if (VM_TRACE == 1) + VerilatedVcdC *vcd = new VerilatedVcdC; + ctx->traceEverOn(true); + top->trace(vcd, 99); + vcd->open(DUMPFILE); +#endif + + /* Create clock source */ + ClockGenerator *clk = new ClockGenerator; + + /* Add clocks and go to first event */ + clk->add_clock(top->clock, 10000, 0); + clk->next_event(); + + /* Initial */ + top->reset = 0; + + /* ---- Evaluation loop ---- */ + while (!ctx->gotFinish()) { + /* Clock event */ + ctx->timeInc(clk->next_event()); + + /* Get output values (before clock edge) */ + if (clk->is_posegde(top->clock)) { + printf("-- posedge clock @ %lu\n", ctx->time()); + } + + /* Eval */ + top->eval(); + + /* Put input values (after clock edge)*/ + if (clk->is_posegde(top->clock)) { + top->reset = !top->reset; + } + + /* Trace steady-state values */ +#if (VM_TRACE == 1) + if (vcd) vcd->dump(ctx->time()); +#endif + } + + top->final(); + printf("[%lu] Stop simulation\n", ctx->time()); + +#if (VM_TRACE == 1) + if (vcd) { + vcd->close(); + delete vcd; + } +#endif + + delete top; + delete ctx; + return 0; +} diff --git a/_template_verilator/top.sv b/_template_verilator/top.sv new file mode 100644 index 0000000..2744f99 --- /dev/null +++ b/_template_verilator/top.sv @@ -0,0 +1,22 @@ +`timescale 1ps/1ps + +/* -verilator lint_off DECLFILENAME */ +/* -verilator lint_off MULTITOP */ +/* -verilator lint_off STMTDLY */ +/* -verilator lint_off INFINITELOOP */ +/* -verilator lint_off INITIALDLY */ + +module top + (input wire clock, + input wire reset); + + initial begin + for (int n = 0; n < 10; n += 1) begin + $display("R@%0t: %0b\n", $time, reset); + @(posedge clock); + end + + $finish; + end + +endmodule // top