From 635aa2a3fcfb4e9c6a9beba3fd5d818631c75c3f Mon Sep 17 00:00:00 2001 From: Lloyd Parkes Date: Sun, 16 Oct 2022 12:36:00 +1300 Subject: [PATCH 01/34] Forcibly set the current seek location of gz files that we are accessing via dup(fileno());gzdopen() because stdio might have buffered data from the underlying file meaning that the underlying seek position isn't what we think it is. --- libs/fst/fstapi.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/fst/fstapi.cc b/libs/fst/fstapi.cc index b79470db3..f1b726518 100644 --- a/libs/fst/fstapi.cc +++ b/libs/fst/fstapi.cc @@ -4272,6 +4272,7 @@ int fstReaderInit(struct fstReaderContext *xc) #endif zfd = dup(fileno(xc->f)); + lseek(zfd, ftell(xc->f), SEEK_SET); zhandle = gzdopen(zfd, "rb"); if (zhandle) { for (offpnt = 0; offpnt < uclen; offpnt += FST_GZIO_LEN) { From 7dcc9c664e5d4f5116f9872ea3fab4a84b61fa40 Mon Sep 17 00:00:00 2001 From: Lloyd Parkes Date: Sun, 16 Oct 2022 12:50:49 +1300 Subject: [PATCH 02/34] And another place we need to lseek() after dup(). --- libs/fst/fstapi.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/fst/fstapi.cc b/libs/fst/fstapi.cc index f1b726518..da0d959a0 100644 --- a/libs/fst/fstapi.cc +++ b/libs/fst/fstapi.cc @@ -3607,6 +3607,7 @@ static int fstReaderRecreateHierFile(struct fstReaderContext *xc) fflush(xc->f); #endif zfd = dup(fileno(xc->f)); + lseek(zfd, ftell(xc->f), SEEK_SET); zhandle = gzdopen(zfd, "rb"); if (!zhandle) { close(zfd); From 96029400cbf661fb5303572923df3f0dc17164ee Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Thu, 20 Oct 2022 13:44:45 +0200 Subject: [PATCH 03/34] smtbmc: Do not assume skipped assertions when loading a witness trace This is not valid when the prefix of a trace already violates assertions. This can happen when the trace generating solver doesn't look for a minimal length counterexample. --- backends/smt2/smtbmc.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/backends/smt2/smtbmc.py b/backends/smt2/smtbmc.py index 4c1f07229..cb21eb3aa 100644 --- a/backends/smt2/smtbmc.py +++ b/backends/smt2/smtbmc.py @@ -453,7 +453,6 @@ assert topmod in smt.modinfo if cexfile is not None: if not got_topt: - assume_skipped = 0 skip_steps = 0 num_steps = 0 @@ -499,7 +498,6 @@ if aimfile is not None: latch_map = dict() if not got_topt: - assume_skipped = 0 skip_steps = 0 num_steps = 0 @@ -633,7 +631,6 @@ if aimfile is not None: if inywfile is not None: if not got_topt: - assume_skipped = 0 skip_steps = 0 num_steps = 0 From 0f96ae599037a945967070211676e32d6e50714d Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Thu, 20 Oct 2022 15:41:17 +0200 Subject: [PATCH 04/34] Add smtmap.v describing the smt2 backend's behavior for undef bits Some builtin cells have an undefined (x) output even when all inputs are defined. This is not natively supported by the formal backends which will produce a fully defined value instead. This can lead to issues when combining different backends in a formal flow. To work around these, this adds a file containing verilog implementation of cells matching the fully defined behavior implemented by the smt2 backend. --- techlibs/common/Makefile.inc | 1 + techlibs/common/smtmap.v | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 techlibs/common/smtmap.v diff --git a/techlibs/common/Makefile.inc b/techlibs/common/Makefile.inc index 607e772a2..47f1ed604 100644 --- a/techlibs/common/Makefile.inc +++ b/techlibs/common/Makefile.inc @@ -22,6 +22,7 @@ kernel/register.o: techlibs/common/simlib_help.inc techlibs/common/simcells_help $(eval $(call add_share_file,share,techlibs/common/simlib.v)) $(eval $(call add_share_file,share,techlibs/common/simcells.v)) $(eval $(call add_share_file,share,techlibs/common/techmap.v)) +$(eval $(call add_share_file,share,techlibs/common/smtmap.v)) $(eval $(call add_share_file,share,techlibs/common/pmux2mux.v)) $(eval $(call add_share_file,share,techlibs/common/adff2dff.v)) $(eval $(call add_share_file,share,techlibs/common/dff2ff.v)) diff --git a/techlibs/common/smtmap.v b/techlibs/common/smtmap.v new file mode 100644 index 000000000..8c7503dc8 --- /dev/null +++ b/techlibs/common/smtmap.v @@ -0,0 +1,28 @@ +(* techmap_celltype = "$pmux" *) +module smt_pmux (A, B, S, Y); + parameter WIDTH = 1; + parameter S_WIDTH = 1; + + (* force_downto *) + input [WIDTH-1:0] A; + (* force_downto *) + input [WIDTH*S_WIDTH-1:0] B; + (* force_downto *) + input [S_WIDTH-1:0] S; + (* force_downto *) + output [WIDTH-1:0] Y; + + (* force_downto *) + wire [WIDTH-1:0] Y_B; + + genvar i, j; + generate + (* force_downto *) + wire [WIDTH*(S_WIDTH+1)-1:0] C; + + assign C[WIDTH-1:0] = A; + for (i = 0; i < S_WIDTH; i = i + 1) + assign C[WIDTH*(i+2)-1:WIDTH*(i+1)] = S[i] ? B[WIDTH*(i+1)-1:WIDTH*i] : C[WIDTH*(i+1)-1:WIDTH*i]; + assign Y = C[WIDTH*(S_WIDTH+1)-1:WIDTH*S_WIDTH]; + endgenerate +endmodule From 4f4cff00800dec70796d4d5ec70c73eef837f948 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 21 Oct 2022 00:23:12 +0000 Subject: [PATCH 05/34] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0acf55a72..52338120e 100644 --- a/Makefile +++ b/Makefile @@ -131,7 +131,7 @@ LDLIBS += -lrt endif endif -YOSYS_VER := 0.22+37 +YOSYS_VER := 0.22+39 # Note: We arrange for .gitcommit to contain the (short) commit hash in # tarballs generated with git-archive(1) using .gitattributes. The git repo From 61dfc26d74fba85c99187568651be8f72aee6652 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 21 Oct 2022 17:00:46 +0200 Subject: [PATCH 06/34] Update versions of CI actions used --- .github/workflows/emcc.yml | 6 +++--- .github/workflows/test-linux.yml | 4 ++-- .github/workflows/test-macos.yml | 4 ++-- .github/workflows/version.yml | 6 +++--- .github/workflows/vs.yml | 8 ++++---- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/emcc.yml b/.github/workflows/emcc.yml index f1cc4b3e7..7a9a6064f 100644 --- a/.github/workflows/emcc.yml +++ b/.github/workflows/emcc.yml @@ -7,10 +7,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: mymindstorm/setup-emsdk@v11 - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Cache sources id: cache-sources - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: . key: cache-yosys @@ -18,7 +18,7 @@ jobs: run: | make config-emcc make YOSYS_VER=latest - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: yosysjs path: yosysjs-latest.zip diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml index e27ea37d2..b974757c4 100644 --- a/.github/workflows/test-linux.yml +++ b/.github/workflows/test-linux.yml @@ -84,7 +84,7 @@ jobs: $CXX --version - name: Checkout Yosys - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Get iverilog shell: bash @@ -93,7 +93,7 @@ jobs: - name: Cache iverilog id: cache-iverilog - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: .local/ key: ${{ matrix.os.id }}-${{ hashFiles('iverilog/.git/refs/heads/master') }} diff --git a/.github/workflows/test-macos.yml b/.github/workflows/test-macos.yml index 22cf5e658..048457234 100644 --- a/.github/workflows/test-macos.yml +++ b/.github/workflows/test-macos.yml @@ -35,7 +35,7 @@ jobs: cc --version - name: Checkout Yosys - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Get iverilog shell: bash @@ -44,7 +44,7 @@ jobs: - name: Cache iverilog id: cache-iverilog - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: .local/ key: ${{ matrix.os.id }}-${{ hashFiles('iverilog/.git/refs/heads/master') }} diff --git a/.github/workflows/version.yml b/.github/workflows/version.yml index c6f4da30d..c2a1756e9 100644 --- a/.github/workflows/version.yml +++ b/.github/workflows/version.yml @@ -10,15 +10,15 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 - name: Take last commit id: log - run: echo "::set-output name=message::$(git log --no-merges -1 --oneline)" + run: echo "message=$(git log --no-merges -1 --oneline)" >> $GITHUB_OUTPUT - name: Take repository id: repo - run: echo "::set-output name=message::$GITHUB_REPOSITORY" + run: echo "message=$GITHUB_REPOSITORY" >> $GITHUB_OUTPUT - name: Bump version if: "!contains(steps.log.outputs.message, 'Bump version') && contains(steps.repo.outputs.message, 'YosysHQ/yosys')" run: | diff --git a/.github/workflows/vs.yml b/.github/workflows/vs.yml index 79a8401d6..744ad5677 100644 --- a/.github/workflows/vs.yml +++ b/.github/workflows/vs.yml @@ -6,16 +6,16 @@ jobs: yosys-vcxsrc: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Cache sources id: cache-sources - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: . key: cache-yosys - name: Build run: make vcxsrc YOSYS_VER=latest - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: vcxsrc path: yosys-win32-vcxsrc-latest.zip @@ -24,7 +24,7 @@ jobs: runs-on: windows-2019 needs: yosys-vcxsrc steps: - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 with: name: vcxsrc path: . From 713d42d25db4fe2bf44aaabc633401455507fbe6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 22 Oct 2022 00:26:01 +0000 Subject: [PATCH 07/34] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 52338120e..7802a3cc3 100644 --- a/Makefile +++ b/Makefile @@ -131,7 +131,7 @@ LDLIBS += -lrt endif endif -YOSYS_VER := 0.22+39 +YOSYS_VER := 0.22+42 # Note: We arrange for .gitcommit to contain the (short) commit hash in # tarballs generated with git-archive(1) using .gitattributes. The git repo From 49945ab1c29482344a36c17eefde44243de90972 Mon Sep 17 00:00:00 2001 From: Lloyd Parkes Date: Sun, 23 Oct 2022 11:02:18 +1300 Subject: [PATCH 08/34] Replace GNU specific invocation of basename(1) with the equivalent POSIX one. The tests now complete on BSD as well as GNU/Linux. --- tests/sim/run-test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/sim/run-test.sh b/tests/sim/run-test.sh index d34d1f3c9..a5120e77e 100755 --- a/tests/sim/run-test.sh +++ b/tests/sim/run-test.sh @@ -3,7 +3,7 @@ set -eu source ../gen-tests-makefile.sh echo "Generate FST for sim models" find tb/* -name tb*.v | while read name; do - test_name=$(basename -s .v $name) + test_name=$(basename $name .v) echo "Test $test_name" verilog_name=${test_name:3}.v iverilog -o tb/$test_name.out $name $verilog_name From 7fcc39abe3d0cf5a7b8572c9999f83d81d2e9452 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 24 Oct 2022 07:39:34 +0200 Subject: [PATCH 09/34] Update CodeQL action --- .github/workflows/codeql.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 57cbe5010..2a046703b 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -14,7 +14,7 @@ jobs: run: sudo apt-get install bison flex libreadline-dev tcl-dev libffi-dev - name: Checkout repository - uses: actions/checkout@v3.0.0 + uses: actions/checkout@v3 - name: Initialize CodeQL uses: github/codeql-action/init@v2 From c77b7343d0412a009436a57764d907e2ae332da2 Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Fri, 21 Oct 2022 15:41:20 +0200 Subject: [PATCH 10/34] Consistent $mux undef handling * Change simlib's $mux cell to use the ternary operator as $_MUX_ already does * Stop opt_expr -keepdc from changing S=x to S=0 * Change const eval of $mux and $pmux to match the updated simlib (fixes sim) * The sat behavior of $mux already matches the updated simlib The verilog frontend uses $mux for the ternary operators and this changes all interpreations of the $mux cell (that I found) to match the verilog simulation behavior for the ternary operator. For 'if' and 'case' expressions the frontend may also use $mux but uses $eqx if the verilog simulation behavior is requested with the '-ifx' option. For $pmux there is a remaining mismatch between the sat behavior and the simlib behavior. Resolving this requires more discussion, as the $pmux cell does not directly correspond to a specific verilog construct. --- kernel/calc.cc | 30 ++++++++++++++++++++++++++++++ kernel/celltypes.h | 14 ++++---------- kernel/rtlil.h | 2 ++ passes/opt/opt_expr.cc | 2 +- techlibs/common/simlib.v | 5 +---- 5 files changed, 38 insertions(+), 15 deletions(-) diff --git a/kernel/calc.cc b/kernel/calc.cc index 0865db526..32e8a49fe 100644 --- a/kernel/calc.cc +++ b/kernel/calc.cc @@ -609,6 +609,36 @@ RTLIL::Const RTLIL::const_neg(const RTLIL::Const &arg1, const RTLIL::Const&, boo return RTLIL::const_sub(zero, arg1_ext, true, signed1, result_len); } +RTLIL::Const RTLIL::const_mux(const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3) +{ + log_assert(arg2.size() == arg1.size()); + if (arg3[0] == State::S0) + return arg1; + else if (arg3[0] == State::S1) + return arg2; + + RTLIL::Const ret = arg1; + for (int i = 0; i < ret.size(); i++) + if (ret[i] != arg2[i]) + ret[i] = State::Sx; + return ret; +} + +RTLIL::Const RTLIL::const_pmux(const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3) +{ + if (arg3.is_fully_zero()) + return arg1; + + if (!arg3.is_onehot()) + return RTLIL::Const(State::Sx, arg1.size()); + + for (int i = 0; i < arg3.size(); i++) + if (arg3[i] == State::S1) + return RTLIL::Const(std::vector(arg2.bits.begin() + i*arg1.bits.size(), arg2.bits.begin() + (i+1)*arg1.bits.size())); + + log_abort(); // unreachable +} + RTLIL::Const RTLIL::const_bmux(const RTLIL::Const &arg1, const RTLIL::Const &arg2) { std::vector t = arg1.bits; diff --git a/kernel/celltypes.h b/kernel/celltypes.h index d62ba1506..e617b4603 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -488,16 +488,10 @@ struct CellTypes static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, bool *errp = nullptr) { - if (cell->type.in(ID($mux), ID($pmux), ID($_MUX_))) { - RTLIL::Const ret = arg1; - for (size_t i = 0; i < arg3.bits.size(); i++) - if (arg3.bits[i] == RTLIL::State::S1) { - std::vector bits(arg2.bits.begin() + i*arg1.bits.size(), arg2.bits.begin() + (i+1)*arg1.bits.size()); - ret = RTLIL::Const(bits); - } - return ret; - } - + if (cell->type.in(ID($mux), ID($_MUX_))) + return const_mux(arg1, arg2, arg3); + if (cell->type == ID($pmux)) + return const_pmux(arg1, arg2, arg3); if (cell->type == ID($_AOI3_)) return eval_not(const_or(const_and(arg1, arg2, false, false, 1), arg3, false, false, 1)); if (cell->type == ID($_OAI3_)) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 27ffdff1f..755abf534 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -500,6 +500,8 @@ namespace RTLIL RTLIL::Const const_pos (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); RTLIL::Const const_neg (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); + RTLIL::Const const_mux (const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3); + RTLIL::Const const_pmux (const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3); RTLIL::Const const_bmux (const RTLIL::Const &arg1, const RTLIL::Const &arg2); RTLIL::Const const_demux (const RTLIL::Const &arg1, const RTLIL::Const &arg2); diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index be0cd470b..9cc0170dc 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -1494,7 +1494,7 @@ skip_identity: RTLIL::SigSpec input = assign_map(cell->getPort(ID::S)); RTLIL::SigSpec inA = assign_map(cell->getPort(ID::A)); RTLIL::SigSpec inB = assign_map(cell->getPort(ID::B)); - if (input.is_fully_const()) + if (input.is_fully_const() && (!keepdc || input.is_fully_def())) ACTION_DO(ID::Y, input.as_bool() ? cell->getPort(ID::B) : cell->getPort(ID::A)); else if (inA == inB) ACTION_DO(ID::Y, cell->getPort(ID::A)); diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index ab9bd7e1d..2fd75372d 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -1282,10 +1282,7 @@ input S; output reg [WIDTH-1:0] Y; always @* begin - if (S) - Y = B; - else - Y = A; + assign Y = S ? B : A; end endmodule From d04c17fd58492c904ef4177984acc4dc79c5629e Mon Sep 17 00:00:00 2001 From: Claire Xenia Wolf Date: Mon, 24 Oct 2022 23:23:33 +0200 Subject: [PATCH 11/34] Add miter -cross option --- passes/sat/miter.cc | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/passes/sat/miter.cc b/passes/sat/miter.cc index 37efadfbd..bf33c9ce3 100644 --- a/passes/sat/miter.cc +++ b/passes/sat/miter.cc @@ -31,6 +31,7 @@ void create_miter_equiv(struct Pass *that, std::vector args, RTLIL: bool flag_make_outcmp = false; bool flag_make_assert = false; bool flag_flatten = false; + bool flag_cross = false; log_header(design, "Executing MITER pass (creating miter circuit).\n"); @@ -57,6 +58,10 @@ void create_miter_equiv(struct Pass *that, std::vector args, RTLIL: flag_flatten = true; continue; } + if (args[argidx] == "-cross") { + flag_cross = true; + continue; + } break; } if (argidx+3 != args.size() || args[argidx].compare(0, 1, "-") == 0) @@ -75,6 +80,7 @@ void create_miter_equiv(struct Pass *that, std::vector args, RTLIL: RTLIL::Module *gold_module = design->module(gold_name); RTLIL::Module *gate_module = design->module(gate_name); + pool gold_cross_ports; for (auto gold_wire : gold_module->wires()) { if (gold_wire->port_id == 0) @@ -82,12 +88,17 @@ void create_miter_equiv(struct Pass *that, std::vector args, RTLIL: RTLIL::Wire *gate_wire = gate_module->wire(gold_wire->name); if (gate_wire == nullptr) goto match_gold_port_error; + if (gold_wire->width != gate_wire->width) + goto match_gold_port_error; + if (flag_cross && !gold_wire->port_input && gold_wire->port_output && + gate_wire->port_input && !gate_wire->port_output) { + gold_cross_ports.insert(gold_wire); + continue; + } if (gold_wire->port_input != gate_wire->port_input) goto match_gold_port_error; if (gold_wire->port_output != gate_wire->port_output) goto match_gold_port_error; - if (gold_wire->width != gate_wire->width) - goto match_gold_port_error; continue; match_gold_port_error: log_cmd_error("No matching port in gate module was found for %s!\n", gold_wire->name.c_str()); @@ -99,12 +110,15 @@ void create_miter_equiv(struct Pass *that, std::vector args, RTLIL: RTLIL::Wire *gold_wire = gold_module->wire(gate_wire->name); if (gold_wire == nullptr) goto match_gate_port_error; + if (gate_wire->width != gold_wire->width) + goto match_gate_port_error; + if (flag_cross && !gold_wire->port_input && gold_wire->port_output && + gate_wire->port_input && !gate_wire->port_output) + continue; if (gate_wire->port_input != gold_wire->port_input) goto match_gate_port_error; if (gate_wire->port_output != gold_wire->port_output) goto match_gate_port_error; - if (gate_wire->width != gold_wire->width) - goto match_gate_port_error; continue; match_gate_port_error: log_cmd_error("No matching port in gold module was found for %s!\n", gate_wire->name.c_str()); @@ -123,6 +137,14 @@ void create_miter_equiv(struct Pass *that, std::vector args, RTLIL: for (auto gold_wire : gold_module->wires()) { + if (gold_cross_ports.count(gold_wire)) + { + RTLIL::Wire *w = miter_module->addWire("\\cross_" + RTLIL::unescape_id(gold_wire->name), gold_wire->width); + gold_cell->setPort(gold_wire->name, w); + gate_cell->setPort(gold_wire->name, w); + continue; + } + if (gold_wire->port_input) { RTLIL::Wire *w = miter_module->addWire("\\in_" + RTLIL::unescape_id(gold_wire->name), gold_wire->width); @@ -384,6 +406,12 @@ struct MiterPass : public Pass { log(" call 'flatten -wb; opt_expr -keepdc -undriven;;' on the miter circuit.\n"); log("\n"); log("\n"); + log(" -cross\n"); + log(" allow output ports on the gold module to match input ports on the\n"); + log(" gate module. This is useful when the gold module contains additional\n"); + log(" logic to drive some of the gate module inputs.\n"); + log("\n"); + log("\n"); log(" miter -assert [options] module [miter_name]\n"); log("\n"); log("Creates a miter circuit for property checking. All input ports are kept,\n"); From 518194fac1d9915b82d0898177ef0546a2a69abe Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 25 Oct 2022 00:30:03 +0000 Subject: [PATCH 12/34] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7802a3cc3..9c5b2529d 100644 --- a/Makefile +++ b/Makefile @@ -131,7 +131,7 @@ LDLIBS += -lrt endif endif -YOSYS_VER := 0.22+42 +YOSYS_VER := 0.22+57 # Note: We arrange for .gitcommit to contain the (short) commit hash in # tarballs generated with git-archive(1) using .gitattributes. The git repo From 05218ec900fb5237043ade928fe1e1e96a53e7c7 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 28 Oct 2022 16:15:30 +0200 Subject: [PATCH 13/34] Add dlfcn library for win32 --- libs/dlfcn-win32/dlfcn.cc | 820 ++++++++++++++++++++++++++++++++++++++ libs/dlfcn-win32/dlfcn.h | 94 +++++ 2 files changed, 914 insertions(+) create mode 100644 libs/dlfcn-win32/dlfcn.cc create mode 100644 libs/dlfcn-win32/dlfcn.h diff --git a/libs/dlfcn-win32/dlfcn.cc b/libs/dlfcn-win32/dlfcn.cc new file mode 100644 index 000000000..03ed34dba --- /dev/null +++ b/libs/dlfcn-win32/dlfcn.cc @@ -0,0 +1,820 @@ +/* + * dlfcn-win32 + * Copyright (c) 2007 Ramiro Polla + * Copyright (c) 2015 Tiancheng "Timothy" Gu + * Copyright (c) 2019 Pali Rohár + * Copyright (c) 2020 Ralf Habacker + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifdef _DEBUG +#define _CRTDBG_MAP_ALLOC +#include +#include +#endif +#include +#include +#include + +/* Older versions do not have this type */ +#if _WIN32_WINNT < 0x0500 +typedef ULONG ULONG_PTR; +#endif + +/* Older SDK versions do not have these macros */ +#ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS +#define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 0x4 +#endif +#ifndef GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT +#define GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT 0x2 +#endif + +#ifdef _MSC_VER +/* https://docs.microsoft.com/en-us/cpp/intrinsics/returnaddress */ +#pragma intrinsic( _ReturnAddress ) +#else +/* https://gcc.gnu.org/onlinedocs/gcc/Return-Address.html */ +#ifndef _ReturnAddress +#define _ReturnAddress( ) ( __builtin_extract_return_addr( __builtin_return_address( 0 ) ) ) +#endif +#endif + +#ifdef DLFCN_WIN32_SHARED +#define DLFCN_WIN32_EXPORTS +#endif +#include "dlfcn.h" + +#if defined( _MSC_VER ) && _MSC_VER >= 1300 +/* https://docs.microsoft.com/en-us/cpp/cpp/noinline */ +#define DLFCN_NOINLINE __declspec( noinline ) +#elif defined( __GNUC__ ) && ( ( __GNUC__ > 3 ) || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 1 ) ) +/* https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html */ +#define DLFCN_NOINLINE __attribute__(( noinline )) +#else +#define DLFCN_NOINLINE +#endif + +/* Note: + * MSDN says these functions are not thread-safe. We make no efforts to have + * any kind of thread safety. + */ + +typedef struct local_object { + HMODULE hModule; + struct local_object *previous; + struct local_object *next; +} local_object; + +static local_object first_object; + +/* These functions implement a double linked list for the local objects. */ +static local_object *local_search( HMODULE hModule ) +{ + local_object *pobject; + + if( hModule == NULL ) + return NULL; + + for( pobject = &first_object; pobject; pobject = pobject->next ) + if( pobject->hModule == hModule ) + return pobject; + + return NULL; +} + +static BOOL local_add( HMODULE hModule ) +{ + local_object *pobject; + local_object *nobject; + + if( hModule == NULL ) + return TRUE; + + pobject = local_search( hModule ); + + /* Do not add object again if it's already on the list */ + if( pobject != NULL ) + return TRUE; + + for( pobject = &first_object; pobject->next; pobject = pobject->next ); + + nobject = (local_object *) malloc( sizeof( local_object ) ); + + if( !nobject ) + return FALSE; + + pobject->next = nobject; + nobject->next = NULL; + nobject->previous = pobject; + nobject->hModule = hModule; + + return TRUE; +} + +static void local_rem( HMODULE hModule ) +{ + local_object *pobject; + + if( hModule == NULL ) + return; + + pobject = local_search( hModule ); + + if( pobject == NULL ) + return; + + if( pobject->next ) + pobject->next->previous = pobject->previous; + if( pobject->previous ) + pobject->previous->next = pobject->next; + + free( pobject ); +} + +/* POSIX says dlerror( ) doesn't have to be thread-safe, so we use one + * static buffer. + * MSDN says the buffer cannot be larger than 64K bytes, so we set it to + * the limit. + */ +static char error_buffer[65535]; +static BOOL error_occurred; + +static void save_err_str( const char *str, DWORD dwMessageId ) +{ + DWORD ret; + size_t pos, len; + + len = strlen( str ); + if( len > sizeof( error_buffer ) - 5 ) + len = sizeof( error_buffer ) - 5; + + /* Format error message to: + * "": + */ + pos = 0; + error_buffer[pos++] = '"'; + memcpy( error_buffer + pos, str, len ); + pos += len; + error_buffer[pos++] = '"'; + error_buffer[pos++] = ':'; + error_buffer[pos++] = ' '; + + ret = FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwMessageId, + MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), + error_buffer + pos, (DWORD) ( sizeof( error_buffer ) - pos ), NULL ); + pos += ret; + + /* When FormatMessageA() fails it returns zero and does not touch buffer + * so add trailing null byte */ + if( ret == 0 ) + error_buffer[pos] = '\0'; + + if( pos > 1 ) + { + /* POSIX says the string must not have trailing */ + if( error_buffer[pos-2] == '\r' && error_buffer[pos-1] == '\n' ) + error_buffer[pos-2] = '\0'; + } + + error_occurred = TRUE; +} + +static void save_err_ptr_str( const void *ptr, DWORD dwMessageId ) +{ + char ptr_buf[2 + 2 * sizeof( ptr ) + 1]; + char num; + size_t i; + + ptr_buf[0] = '0'; + ptr_buf[1] = 'x'; + + for( i = 0; i < 2 * sizeof( ptr ); i++ ) + { + num = (char) ( ( ( (ULONG_PTR) ptr ) >> ( 8 * sizeof( ptr ) - 4 * ( i + 1 ) ) ) & 0xF ); + ptr_buf[2 + i] = num + ( ( num < 0xA ) ? '0' : ( 'A' - 0xA ) ); + } + + ptr_buf[2 + 2 * sizeof( ptr )] = 0; + + save_err_str( ptr_buf, dwMessageId ); +} + +static UINT MySetErrorMode( UINT uMode ) +{ + static BOOL (WINAPI *SetThreadErrorModePtr)(DWORD, DWORD *) = NULL; + static BOOL failed = FALSE; + HMODULE kernel32; + DWORD oldMode; + + if( !failed && SetThreadErrorModePtr == NULL ) + { + kernel32 = GetModuleHandleA( "Kernel32.dll" ); + if( kernel32 != NULL ) + SetThreadErrorModePtr = (BOOL (WINAPI *)(DWORD, DWORD *)) (LPVOID) GetProcAddress( kernel32, "SetThreadErrorMode" ); + if( SetThreadErrorModePtr == NULL ) + failed = TRUE; + } + + if( !failed ) + { + if( !SetThreadErrorModePtr( uMode, &oldMode ) ) + return 0; + else + return oldMode; + } + else + { + return SetErrorMode( uMode ); + } +} + +static HMODULE MyGetModuleHandleFromAddress( const void *addr ) +{ + static BOOL (WINAPI *GetModuleHandleExAPtr)(DWORD, LPCSTR, HMODULE *) = NULL; + static BOOL failed = FALSE; + HMODULE kernel32; + HMODULE hModule; + MEMORY_BASIC_INFORMATION info; + SIZE_T sLen; + + if( !failed && GetModuleHandleExAPtr == NULL ) + { + kernel32 = GetModuleHandleA( "Kernel32.dll" ); + if( kernel32 != NULL ) + GetModuleHandleExAPtr = (BOOL (WINAPI *)(DWORD, LPCSTR, HMODULE *)) (LPVOID) GetProcAddress( kernel32, "GetModuleHandleExA" ); + if( GetModuleHandleExAPtr == NULL ) + failed = TRUE; + } + + if( !failed ) + { + /* If GetModuleHandleExA is available use it with GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS */ + if( !GetModuleHandleExAPtr( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (const char *)addr, &hModule ) ) + return NULL; + } + else + { + /* To get HMODULE from address use undocumented hack from https://stackoverflow.com/a/2396380 + * The HMODULE of a DLL is the same value as the module's base address. + */ + sLen = VirtualQuery( addr, &info, sizeof( info ) ); + if( sLen != sizeof( info ) ) + return NULL; + hModule = (HMODULE) info.AllocationBase; + } + + return hModule; +} + +/* Load Psapi.dll at runtime, this avoids linking caveat */ +static BOOL MyEnumProcessModules( HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded ) +{ + static BOOL (WINAPI *EnumProcessModulesPtr)(HANDLE, HMODULE *, DWORD, LPDWORD) = NULL; + static BOOL failed = FALSE; + UINT uMode; + HMODULE psapi; + + if( failed ) + return FALSE; + + if( EnumProcessModulesPtr == NULL ) + { + /* Windows 7 and newer versions have K32EnumProcessModules in Kernel32.dll which is always pre-loaded */ + psapi = GetModuleHandleA( "Kernel32.dll" ); + if( psapi != NULL ) + EnumProcessModulesPtr = (BOOL (WINAPI *)(HANDLE, HMODULE *, DWORD, LPDWORD)) (LPVOID) GetProcAddress( psapi, "K32EnumProcessModules" ); + + /* Windows Vista and older version have EnumProcessModules in Psapi.dll which needs to be loaded */ + if( EnumProcessModulesPtr == NULL ) + { + /* Do not let Windows display the critical-error-handler message box */ + uMode = MySetErrorMode( SEM_FAILCRITICALERRORS ); + psapi = LoadLibraryA( "Psapi.dll" ); + if( psapi != NULL ) + { + EnumProcessModulesPtr = (BOOL (WINAPI *)(HANDLE, HMODULE *, DWORD, LPDWORD)) (LPVOID) GetProcAddress( psapi, "EnumProcessModules" ); + if( EnumProcessModulesPtr == NULL ) + FreeLibrary( psapi ); + } + MySetErrorMode( uMode ); + } + + if( EnumProcessModulesPtr == NULL ) + { + failed = TRUE; + return FALSE; + } + } + + return EnumProcessModulesPtr( hProcess, lphModule, cb, lpcbNeeded ); +} + +DLFCN_EXPORT +void *dlopen( const char *file, int mode ) +{ + HMODULE hModule; + UINT uMode; + + error_occurred = FALSE; + + /* Do not let Windows display the critical-error-handler message box */ + uMode = MySetErrorMode( SEM_FAILCRITICALERRORS ); + + if( file == NULL ) + { + /* POSIX says that if the value of file is NULL, a handle on a global + * symbol object must be provided. That object must be able to access + * all symbols from the original program file, and any objects loaded + * with the RTLD_GLOBAL flag. + * The return value from GetModuleHandle( ) allows us to retrieve + * symbols only from the original program file. EnumProcessModules() is + * used to access symbols from other libraries. For objects loaded + * with the RTLD_LOCAL flag, we create our own list later on. They are + * excluded from EnumProcessModules() iteration. + */ + hModule = GetModuleHandle( NULL ); + + if( !hModule ) + save_err_str( "(null)", GetLastError( ) ); + } + else + { + HANDLE hCurrentProc; + DWORD dwProcModsBefore, dwProcModsAfter; + char lpFileName[MAX_PATH]; + size_t i, len; + + len = strlen( file ); + + if( len >= sizeof( lpFileName ) ) + { + save_err_str( file, ERROR_FILENAME_EXCED_RANGE ); + hModule = NULL; + } + else + { + /* MSDN says backslashes *must* be used instead of forward slashes. */ + for( i = 0; i < len; i++ ) + { + if( file[i] == '/' ) + lpFileName[i] = '\\'; + else + lpFileName[i] = file[i]; + } + lpFileName[len] = '\0'; + + hCurrentProc = GetCurrentProcess( ); + + if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwProcModsBefore ) == 0 ) + dwProcModsBefore = 0; + + /* POSIX says the search path is implementation-defined. + * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely + * to UNIX's search paths (start with system folders instead of current + * folder). + */ + hModule = LoadLibraryExA( lpFileName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH ); + + if( !hModule ) + { + save_err_str( lpFileName, GetLastError( ) ); + } + else + { + if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwProcModsAfter ) == 0 ) + dwProcModsAfter = 0; + + /* If the object was loaded with RTLD_LOCAL, add it to list of local + * objects, so that its symbols cannot be retrieved even if the handle for + * the original program file is passed. POSIX says that if the same + * file is specified in multiple invocations, and any of them are + * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the + * symbols will remain global. If number of loaded modules was not + * changed after calling LoadLibraryEx(), it means that library was + * already loaded. + */ + if( (mode & RTLD_LOCAL) && dwProcModsBefore != dwProcModsAfter ) + { + if( !local_add( hModule ) ) + { + save_err_str( lpFileName, ERROR_NOT_ENOUGH_MEMORY ); + FreeLibrary( hModule ); + hModule = NULL; + } + } + else if( !(mode & RTLD_LOCAL) && dwProcModsBefore == dwProcModsAfter ) + { + local_rem( hModule ); + } + } + } + } + + /* Return to previous state of the error-mode bit flags. */ + MySetErrorMode( uMode ); + + return (void *) hModule; +} + +DLFCN_EXPORT +int dlclose( void *handle ) +{ + HMODULE hModule = (HMODULE) handle; + BOOL ret; + + error_occurred = FALSE; + + ret = FreeLibrary( hModule ); + + /* If the object was loaded with RTLD_LOCAL, remove it from list of local + * objects. + */ + if( ret ) + local_rem( hModule ); + else + save_err_ptr_str( handle, GetLastError( ) ); + + /* dlclose's return value in inverted in relation to FreeLibrary's. */ + ret = !ret; + + return (int) ret; +} + +DLFCN_NOINLINE /* Needed for _ReturnAddress() */ +DLFCN_EXPORT +void *dlsym( void *handle, const char *name ) +{ + FARPROC symbol; + HMODULE hCaller; + HMODULE hModule; + DWORD dwMessageId; + + error_occurred = FALSE; + + symbol = NULL; + hCaller = NULL; + hModule = GetModuleHandle( NULL ); + dwMessageId = 0; + + if( handle == RTLD_DEFAULT ) + { + /* The symbol lookup happens in the normal global scope; that is, + * a search for a symbol using this handle would find the same + * definition as a direct use of this symbol in the program code. + * So use same lookup procedure as when filename is NULL. + */ + handle = hModule; + } + else if( handle == RTLD_NEXT ) + { + /* Specifies the next object after this one that defines name. + * This one refers to the object containing the invocation of dlsym(). + * The next object is the one found upon the application of a load + * order symbol resolution algorithm. To get caller function of dlsym() + * use _ReturnAddress() intrinsic. To get HMODULE of caller function + * use MyGetModuleHandleFromAddress() which calls either standard + * GetModuleHandleExA() function or hack via VirtualQuery(). + */ + hCaller = MyGetModuleHandleFromAddress( _ReturnAddress( ) ); + + if( hCaller == NULL ) + { + dwMessageId = ERROR_INVALID_PARAMETER; + goto end; + } + } + + if( handle != RTLD_NEXT ) + { + symbol = GetProcAddress( (HMODULE) handle, name ); + + if( symbol != NULL ) + goto end; + } + + /* If the handle for the original program file is passed, also search + * in all globally loaded objects. + */ + + if( hModule == handle || handle == RTLD_NEXT ) + { + HANDLE hCurrentProc; + HMODULE *modules; + DWORD cbNeeded; + DWORD dwSize; + size_t i; + + hCurrentProc = GetCurrentProcess( ); + + /* GetModuleHandle( NULL ) only returns the current program file. So + * if we want to get ALL loaded module including those in linked DLLs, + * we have to use EnumProcessModules( ). + */ + if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwSize ) != 0 ) + { + modules = (HMODULE *)malloc( dwSize ); + if( modules ) + { + if( MyEnumProcessModules( hCurrentProc, modules, dwSize, &cbNeeded ) != 0 && dwSize == cbNeeded ) + { + for( i = 0; i < dwSize / sizeof( HMODULE ); i++ ) + { + if( handle == RTLD_NEXT && hCaller ) + { + /* Next modules can be used for RTLD_NEXT */ + if( hCaller == modules[i] ) + hCaller = NULL; + continue; + } + if( local_search( modules[i] ) ) + continue; + symbol = GetProcAddress( modules[i], name ); + if( symbol != NULL ) + { + free( modules ); + goto end; + } + } + + } + free( modules ); + } + else + { + dwMessageId = ERROR_NOT_ENOUGH_MEMORY; + goto end; + } + } + } + +end: + if( symbol == NULL ) + { + if( !dwMessageId ) + dwMessageId = ERROR_PROC_NOT_FOUND; + save_err_str( name, dwMessageId ); + } + + return *(void **) (&symbol); +} + +DLFCN_EXPORT +char *dlerror( void ) +{ + /* If this is the second consecutive call to dlerror, return NULL */ + if( !error_occurred ) + return NULL; + + /* POSIX says that invoking dlerror( ) a second time, immediately following + * a prior invocation, shall result in NULL being returned. + */ + error_occurred = FALSE; + + return error_buffer; +} + +/* See https://docs.microsoft.com/en-us/archive/msdn-magazine/2002/march/inside-windows-an-in-depth-look-into-the-win32-portable-executable-file-format-part-2 + * for details */ + +/* Get specific image section */ +static BOOL get_image_section( HMODULE module, int index, void **ptr, DWORD *size ) +{ + IMAGE_DOS_HEADER *dosHeader; + IMAGE_NT_HEADERS *ntHeaders; + IMAGE_OPTIONAL_HEADER *optionalHeader; + + dosHeader = (IMAGE_DOS_HEADER *) module; + + if( dosHeader->e_magic != IMAGE_DOS_SIGNATURE ) + return FALSE; + + ntHeaders = (IMAGE_NT_HEADERS *) ( (BYTE *) dosHeader + dosHeader->e_lfanew ); + + if( ntHeaders->Signature != IMAGE_NT_SIGNATURE ) + return FALSE; + + optionalHeader = &ntHeaders->OptionalHeader; + + if( optionalHeader->Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC ) + return FALSE; + + if( index < 0 || index > IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR ) + return FALSE; + + if( optionalHeader->DataDirectory[index].Size == 0 || optionalHeader->DataDirectory[index].VirtualAddress == 0 ) + return FALSE; + + if( size != NULL ) + *size = optionalHeader->DataDirectory[index].Size; + + *ptr = (void *)( (BYTE *) module + optionalHeader->DataDirectory[index].VirtualAddress ); + + return TRUE; +} + +/* Return symbol name for a given address from export table */ +static const char *get_export_symbol_name( HMODULE module, IMAGE_EXPORT_DIRECTORY *ied, const void *addr, void **func_address ) +{ + DWORD i; + void *candidateAddr = NULL; + int candidateIndex = -1; + BYTE *base = (BYTE *) module; + DWORD *functionAddressesOffsets = (DWORD *) (base + ied->AddressOfFunctions); + DWORD *functionNamesOffsets = (DWORD *) (base + ied->AddressOfNames); + USHORT *functionNameOrdinalsIndexes = (USHORT *) (base + ied->AddressOfNameOrdinals); + + for( i = 0; i < ied->NumberOfFunctions; i++ ) + { + if( (void *) ( base + functionAddressesOffsets[i] ) > addr || candidateAddr >= (void *) ( base + functionAddressesOffsets[i] ) ) + continue; + + candidateAddr = (void *) ( base + functionAddressesOffsets[i] ); + candidateIndex = i; + } + + if( candidateIndex == -1 ) + return NULL; + + *func_address = candidateAddr; + + for( i = 0; i < ied->NumberOfNames; i++ ) + { + if( functionNameOrdinalsIndexes[i] == candidateIndex ) + return (const char *) ( base + functionNamesOffsets[i] ); + } + + return NULL; +} + +static BOOL is_valid_address( const void *addr ) +{ + MEMORY_BASIC_INFORMATION info; + SIZE_T result; + + if( addr == NULL ) + return FALSE; + + /* check valid pointer */ + result = VirtualQuery( addr, &info, sizeof( info ) ); + + if( result == 0 || info.AllocationBase == NULL || info.AllocationProtect == 0 || info.AllocationProtect == PAGE_NOACCESS ) + return FALSE; + + return TRUE; +} + +/* Return state if address points to an import thunk + * + * An import thunk is setup with a 'jmp' instruction followed by an + * absolute address (32bit) or relative offset (64bit) pointing into + * the import address table (iat), which is partially maintained by + * the runtime linker. + */ +static BOOL is_import_thunk( const void *addr ) +{ + return *(short *) addr == 0x25ff ? TRUE : FALSE; +} + +/* Return adress from the import address table (iat), + * if the original address points to a thunk table entry. + */ +static void *get_address_from_import_address_table( void *iat, DWORD iat_size, const void *addr ) +{ + BYTE *thkp = (BYTE *) addr; + /* Get offset from thunk table (after instruction 0xff 0x25) + * 4018c8 <_VirtualQuery>: ff 25 4a 8a 00 00 + */ + ULONG offset = *(ULONG *)( thkp + 2 ); +#ifdef _WIN64 + /* On 64 bit the offset is relative + * 4018c8: ff 25 4a 8a 00 00 jmpq *0x8a4a(%rip) # 40a318 <__imp_VirtualQuery> + * And can be also negative (MSVC in WDK) + * 100002f20: ff 25 3a e1 ff ff jmpq *-0x1ec6(%rip) # 0x100001060 + * So cast to signed LONG type + */ + BYTE *ptr = (BYTE *)( thkp + 6 + (LONG) offset ); +#else + /* On 32 bit the offset is absolute + * 4019b4: ff 25 90 71 40 00 jmp *0x40719 + */ + BYTE *ptr = (BYTE *) offset; +#endif + + if( !is_valid_address( ptr ) || ptr < (BYTE *) iat || ptr > (BYTE *) iat + iat_size ) + return NULL; + + return *(void **) ptr; +} + +/* Holds module filename */ +static char module_filename[2*MAX_PATH]; + +static BOOL fill_info( const void *addr, Dl_info *info ) +{ + HMODULE hModule; + DWORD dwSize; + IMAGE_EXPORT_DIRECTORY *ied; + void *funcAddress = NULL; + + /* Get module of the specified address */ + hModule = MyGetModuleHandleFromAddress( addr ); + + if( hModule == NULL ) + return FALSE; + + dwSize = GetModuleFileNameA( hModule, module_filename, sizeof( module_filename ) ); + + if( dwSize == 0 || dwSize == sizeof( module_filename ) ) + return FALSE; + + info->dli_fname = module_filename; + info->dli_fbase = (void *) hModule; + + /* Find function name and function address in module's export table */ + if( get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_EXPORT, (void **) &ied, NULL ) ) + info->dli_sname = get_export_symbol_name( hModule, ied, addr, &funcAddress ); + else + info->dli_sname = NULL; + + info->dli_saddr = info->dli_sname == NULL ? NULL : funcAddress != NULL ? funcAddress : (void *) addr; + + return TRUE; +} + +DLFCN_EXPORT +int dladdr( const void *addr, Dl_info *info ) +{ + if( info == NULL ) + return 0; + + if( !is_valid_address( addr ) ) + return 0; + + if( is_import_thunk( addr ) ) + { + void *iat; + DWORD iatSize; + HMODULE hModule; + + /* Get module of the import thunk address */ + hModule = MyGetModuleHandleFromAddress( addr ); + + if( hModule == NULL ) + return 0; + + if( !get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_IAT, &iat, &iatSize ) ) + { + /* Fallback for cases where the iat is not defined, + * for example i586-mingw32msvc-gcc */ + IMAGE_IMPORT_DESCRIPTOR *iid; + DWORD iidSize; + + if( !get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_IMPORT, (void **) &iid, &iidSize ) ) + return 0; + + if( iid == NULL || iid->Characteristics == 0 || iid->FirstThunk == 0 ) + return 0; + + iat = (void *)( (BYTE *) hModule + iid->FirstThunk ); + /* We assume that in this case iid and iat's are in linear order */ + iatSize = iidSize - (DWORD) ( (BYTE *) iat - (BYTE *) iid ); + } + + addr = get_address_from_import_address_table( iat, iatSize, addr ); + + if( !is_valid_address( addr ) ) + return 0; + } + + if( !fill_info( addr, info ) ) + return 0; + + return 1; +} + +#ifdef DLFCN_WIN32_SHARED +BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) +{ + (void) hinstDLL; + (void) fdwReason; + (void) lpvReserved; + return TRUE; +} +#endif diff --git a/libs/dlfcn-win32/dlfcn.h b/libs/dlfcn-win32/dlfcn.h new file mode 100644 index 000000000..bf5c7d4d1 --- /dev/null +++ b/libs/dlfcn-win32/dlfcn.h @@ -0,0 +1,94 @@ +/* + * dlfcn-win32 + * Copyright (c) 2007 Ramiro Polla + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef DLFCN_H +#define DLFCN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(DLFCN_WIN32_SHARED) +#if defined(DLFCN_WIN32_EXPORTS) +# define DLFCN_EXPORT __declspec(dllexport) +#else +# define DLFCN_EXPORT __declspec(dllimport) +#endif +#else +# define DLFCN_EXPORT +#endif + +/* Relocations are performed when the object is loaded. */ +#define RTLD_NOW 0 + +/* Relocations are performed at an implementation-defined time. + * Windows API does not support lazy symbol resolving (when first reference + * to a given symbol occurs). So RTLD_LAZY implementation is same as RTLD_NOW. + */ +#define RTLD_LAZY RTLD_NOW + +/* All symbols are available for relocation processing of other modules. */ +#define RTLD_GLOBAL (1 << 1) + +/* All symbols are not made available for relocation processing by other modules. */ +#define RTLD_LOCAL (1 << 2) + +/* These two were added in The Open Group Base Specifications Issue 6. + * Note: All other RTLD_* flags in any dlfcn.h are not standard compliant. + */ + +/* The symbol lookup happens in the normal global scope. */ +#define RTLD_DEFAULT ((void *)0) + +/* Specifies the next object after this one that defines name. */ +#define RTLD_NEXT ((void *)-1) + +/* Structure filled in by dladdr() */ +typedef struct dl_info +{ + const char *dli_fname; /* Filename of defining object (thread unsafe and reused on every call to dladdr) */ + void *dli_fbase; /* Load address of that object */ + const char *dli_sname; /* Name of nearest lower symbol */ + void *dli_saddr; /* Exact value of nearest symbol */ +} Dl_info; + +/* Open a symbol table handle. */ +DLFCN_EXPORT void *dlopen(const char *file, int mode); + +/* Close a symbol table handle. */ +DLFCN_EXPORT int dlclose(void *handle); + +/* Get the address of a symbol from a symbol table handle. */ +DLFCN_EXPORT void *dlsym(void *handle, const char *name); + +/* Get diagnostic information. */ +DLFCN_EXPORT char *dlerror(void); + +/* Translate address to symbolic information (no POSIX standard) */ +DLFCN_EXPORT int dladdr(const void *addr, Dl_info *info); + +#ifdef __cplusplus +} +#endif + +#endif /* DLFCN_H */ From aa7e7df19f21baff7e6ccfbf106c3b23ec9d4f6d Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Fri, 28 Oct 2022 19:48:00 +0200 Subject: [PATCH 14/34] simlib: Simplify recently changed $mux model The use of a procedural continuous assignment introduced in #3526 was unintended and is completely unnecessary for the actual change of that PR. --- techlibs/common/simlib.v | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 2fd75372d..e64697efb 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -1279,11 +1279,9 @@ parameter WIDTH = 0; input [WIDTH-1:0] A, B; input S; -output reg [WIDTH-1:0] Y; +output [WIDTH-1:0] Y; -always @* begin - assign Y = S ? B : A; -end +assign Y = S ? B : A; endmodule From c0ad6b3bc64e4210531c4629f266aa0b3beecbb0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 30 Oct 2022 00:23:01 +0000 Subject: [PATCH 15/34] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9c5b2529d..e806a6067 100644 --- a/Makefile +++ b/Makefile @@ -131,7 +131,7 @@ LDLIBS += -lrt endif endif -YOSYS_VER := 0.22+57 +YOSYS_VER := 0.22+60 # Note: We arrange for .gitcommit to contain the (short) commit hash in # tarballs generated with git-archive(1) using .gitattributes. The git repo From fe438ca1ab2f5c6e1bf14dce184c588808e557d2 Mon Sep 17 00:00:00 2001 From: Claire Xenia Wolf Date: Sun, 30 Oct 2022 18:57:50 +0100 Subject: [PATCH 16/34] Add missing log_dump_val_worker forward declarations Signed-off-by: Claire Xenia Wolf --- kernel/log.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kernel/log.h b/kernel/log.h index 8ef6e6d0e..822816cb4 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -393,6 +393,11 @@ void log_dump_val_worker(RTLIL::IdString v); void log_dump_val_worker(RTLIL::SigSpec v); void log_dump_val_worker(RTLIL::State v); +template static inline void log_dump_val_worker(dict &v); +template static inline void log_dump_val_worker(pool &v); +template static inline void log_dump_val_worker(std::vector &v); +template static inline void log_dump_val_worker(T *ptr); + template static inline void log_dump_val_worker(dict &v) { log("{"); From 5f209f8be56d119478ffc75a1848a7c12b04cc19 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 31 Oct 2022 00:22:50 +0000 Subject: [PATCH 17/34] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e806a6067..b7071f53c 100644 --- a/Makefile +++ b/Makefile @@ -131,7 +131,7 @@ LDLIBS += -lrt endif endif -YOSYS_VER := 0.22+60 +YOSYS_VER := 0.22+62 # Note: We arrange for .gitcommit to contain the (short) commit hash in # tarballs generated with git-archive(1) using .gitattributes. The git repo From d1b3a250db111364a3356dbc9e0f715aff159b48 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 31 Oct 2022 09:10:46 +0100 Subject: [PATCH 18/34] Windows plugin build support --- Makefile | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 9c5b2529d..e03a873b4 100644 --- a/Makefile +++ b/Makefile @@ -56,6 +56,9 @@ PROGRAM_PREFIX := OS := $(shell uname -s) PREFIX ?= /usr/local INSTALL_SUDO := +ifneq ($(filter MINGW%,$(OS)),) +OS := MINGW +endif ifneq ($(wildcard Makefile.conf),) include Makefile.conf @@ -91,6 +94,13 @@ CXXSTD ?= c++11 CXXFLAGS := $(CXXFLAGS) -Wall -Wextra -ggdb -I. -I"$(YOSYS_SRC)" -MD -MP -D_YOSYS_ -fPIC -I$(PREFIX)/include LDLIBS := $(LDLIBS) -lstdc++ -lm PLUGIN_LDFLAGS := +PLUGIN_LDLIBS := +EXE_LDFLAGS := +ifeq ($(OS), MINGW) +EXE_LDFLAGS := -Wl,--export-all-symbols -Wl,--out-implib,libyosys_exe.a +PLUGIN_LDFLAGS += -L"$(LIBDIR)" +PLUGIN_LDLIBS := -lyosys_exe +endif PKG_CONFIG ?= pkg-config SED ?= sed @@ -436,8 +446,11 @@ endif ifeq ($(ENABLE_PLUGINS),1) CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags libffi) -DYOSYS_ENABLE_PLUGINS +ifeq ($(OS), MINGW) +CXXFLAGS += -Ilibs/dlfcn-win32 +endif LDLIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --libs libffi || echo -lffi) -ifneq ($(OS), $(filter $(OS),FreeBSD OpenBSD NetBSD)) +ifneq ($(OS), $(filter $(OS),FreeBSD OpenBSD NetBSD MINGW)) LDLIBS += -ldl endif endif @@ -646,6 +659,11 @@ OBJS += kernel/cellaigs.o kernel/celledges.o kernel/satgen.o kernel/qcsat.o kern ifeq ($(ENABLE_ZLIB),1) OBJS += kernel/fstdata.o endif +ifeq ($(ENABLE_PLUGINS),1) +ifeq ($(OS), MINGW) +OBJS += libs/dlfcn-win32/dlfcn.o +endif +endif kernel/log.o: CXXFLAGS += -DYOSYS_SRC='"$(YOSYS_SRC)"' kernel/yosys.o: CXXFLAGS += -DYOSYS_DATDIR='"$(DATDIR)"' -DYOSYS_PROGRAM_PREFIX='"$(PROGRAM_PREFIX)"' @@ -724,7 +742,7 @@ yosys.js: $(filter-out yosysjs-$(YOSYS_VER).zip,$(EXTRA_TARGETS)) endif $(PROGRAM_PREFIX)yosys$(EXE): $(OBJS) - $(P) $(LD) -o $(PROGRAM_PREFIX)yosys$(EXE) $(LDFLAGS) $(OBJS) $(LDLIBS) + $(P) $(LD) -o $(PROGRAM_PREFIX)yosys$(EXE) $(EXE_LDFLAGS) $(LDFLAGS) $(OBJS) $(LDLIBS) libyosys.so: $(filter-out kernel/driver.o,$(OBJS)) ifeq ($(OS), Darwin) @@ -767,8 +785,8 @@ LDLIBS_NOVERIFIC = $(LDLIBS) endif $(PROGRAM_PREFIX)yosys-config: misc/yosys-config.in - $(P) $(SED) -e 's#@CXXFLAGS@#$(subst -I. -I"$(YOSYS_SRC)",-I"$(DATDIR)/include",$(strip $(CXXFLAGS_NOVERIFIC)))#;' \ - -e 's#@CXX@#$(strip $(CXX))#;' -e 's#@LDFLAGS@#$(strip $(LDFLAGS) $(PLUGIN_LDFLAGS))#;' -e 's#@LDLIBS@#$(strip $(LDLIBS_NOVERIFIC))#;' \ + $(P) $(SED) -e 's#@CXXFLAGS@#$(subst -Ilibs/dlfcn-win32,,$(subst -I. -I"$(YOSYS_SRC)",-I"$(DATDIR)/include",$(strip $(CXXFLAGS_NOVERIFIC))))#;' \ + -e 's#@CXX@#$(strip $(CXX))#;' -e 's#@LDFLAGS@#$(strip $(LDFLAGS) $(PLUGIN_LDFLAGS))#;' -e 's#@LDLIBS@#$(strip $(LDLIBS_NOVERIFIC) $(PLUGIN_LDLIBS))#;' \ -e 's#@BINDIR@#$(strip $(BINDIR))#;' -e 's#@DATDIR@#$(strip $(DATDIR))#;' < $< > $(PROGRAM_PREFIX)yosys-config $(Q) chmod +x $(PROGRAM_PREFIX)yosys-config @@ -916,6 +934,12 @@ ifeq ($(ENABLE_PYOSYS),1) $(INSTALL_SUDO) cp misc/__init__.py $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/ endif endif +ifeq ($(ENABLE_PLUGINS),1) +ifeq ($(OS), MINGW) + $(INSTALL_SUDO) mkdir -p $(DESTDIR)$(LIBDIR) + $(INSTALL_SUDO) cp libyosys_exe.a $(DESTDIR)$(LIBDIR)/ +endif +endif uninstall: $(INSTALL_SUDO) rm -vf $(addprefix $(DESTDIR)$(BINDIR)/,$(notdir $(TARGETS))) @@ -1040,12 +1064,10 @@ config-mxe: clean config-msys2-32: clean echo 'CONFIG := msys2-32' > Makefile.conf - echo 'ENABLE_PLUGINS := 0' >> Makefile.conf echo "PREFIX := $(MINGW_PREFIX)" >> Makefile.conf config-msys2-64: clean echo 'CONFIG := msys2-64' > Makefile.conf - echo 'ENABLE_PLUGINS := 0' >> Makefile.conf echo "PREFIX := $(MINGW_PREFIX)" >> Makefile.conf config-cygwin: clean From e702f2894a1089ee50ede6edee1b6999369a2486 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 31 Oct 2022 10:15:05 +0100 Subject: [PATCH 19/34] Support for reading liberty files using verific --- Makefile | 5 ++++ frontends/verific/verific.cc | 46 +++++++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b7071f53c..25e412413 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,7 @@ ENABLE_EDITLINE := 0 ENABLE_GHDL := 0 ENABLE_VERIFIC := 0 ENABLE_VERIFIC_EDIF := 0 +ENABLE_VERIFIC_LIBERTY := 0 DISABLE_VERIFIC_EXTENSIONS := 0 DISABLE_VERIFIC_VHDL := 0 ENABLE_COVER := 1 @@ -531,6 +532,10 @@ ifeq ($(ENABLE_VERIFIC_EDIF),1) VERIFIC_COMPONENTS += edif CXXFLAGS += -DVERIFIC_EDIF_SUPPORT endif +ifeq ($(ENABLE_VERIFIC_LIBERTY),1) +VERIFIC_COMPONENTS += synlib +CXXFLAGS += -DVERIFIC_LIBERTY_SUPPORT +endif ifneq ($(DISABLE_VERIFIC_EXTENSIONS),1) VERIFIC_COMPONENTS += extensions CXXFLAGS += -DYOSYSHQ_VERIFIC_EXTENSIONS diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 71b87755d..0f4eceba4 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -57,6 +57,10 @@ USING_YOSYS_NAMESPACE #include "edif_file.h" #endif +#ifdef VERIFIC_LIBERTY_SUPPORT +#include "synlib_file.h" +#endif + #include "VerificStream.h" #include "FileSystem.h" @@ -2358,6 +2362,9 @@ void verific_import(Design *design, const std::map &par #endif #ifdef VERIFIC_EDIF_SUPPORT edif_file::Reset(); +#endif +#ifdef VERIFIC_LIBERTY_SUPPORT + synlib_file::Reset(); #endif Libset::Reset(); Message::Reset(); @@ -2426,6 +2433,13 @@ struct VerificPass : public Pass { log("Load the specified EDIF files into Verific.\n"); log("\n"); log("\n"); +#endif +#ifdef VERIFIC_LIBERTY_SUPPORT + log(" verific {-liberty} ..\n"); + log("\n"); + log("Load the specified Liberty files into Verific.\n"); + log("\n"); + log("\n"); #endif log(" verific {-f|-F} [-vlog95|-vlog2k|-sv2005|-sv2009|\n"); log(" -sv2012|-sv|-formal] \n"); @@ -2535,7 +2549,7 @@ struct VerificPass : public Pass { log("\n"); log(" -cells\n"); log(" Import all cell definitions from Verific loaded libraries even if they are\n"); - log(" unused in design. Useful with \"-edif\" option.\n"); + log(" unused in design. Useful with \"-edif\" and \"-liberty\" option.\n"); log("\n"); log(" -chparam name value \n"); log(" Elaborate the specified top modules (all modules when -all given) using\n"); @@ -2729,6 +2743,7 @@ struct VerificPass : public Pass { int argidx = 1; std::string work = "work"; + bool is_work_set = false; veri_file::RegisterCallBackVerificStream(&verific_read_cb); if (GetSize(args) > argidx && (args[argidx] == "-set-error" || args[argidx] == "-set-warning" || @@ -2813,6 +2828,7 @@ struct VerificPass : public Pass { { if (args[argidx] == "-work" && argidx+1 < GetSize(args)) { work = args[++argidx]; + is_work_set = true; continue; } if (args[argidx] == "-L" && argidx+1 < GetSize(args)) { @@ -3001,6 +3017,17 @@ struct VerificPass : public Pass { } goto check_error; } +#endif +#ifdef VERIFIC_LIBERTY_SUPPORT + if (GetSize(args) > argidx && args[argidx] == "-liberty") { + argidx++; + while (argidx < GetSize(args)) { + std::string filename = frontent_rewrite(args, argidx, tmp_files); + if (!synlib_file::Read(filename.c_str(), is_work_set ? work.c_str() : nullptr)) + log_cmd_error("Reading `%s' in LIBERTY mode failed.\n", filename.c_str()); + } + goto check_error; + } #endif if (argidx < GetSize(args) && args[argidx] == "-pp") { @@ -3293,6 +3320,9 @@ struct VerificPass : public Pass { #endif #ifdef VERIFIC_EDIF_SUPPORT edif_file::Reset(); +#endif +#ifdef VERIFIC_LIBERTY_SUPPORT + synlib_file::Reset(); #endif Libset::Reset(); Message::Reset(); @@ -3427,6 +3457,11 @@ struct ReadPass : public Pass { log("\n"); log("\n"); #endif + log(" read {-liberty} ..\n"); + log("\n"); + log("Load the specified Liberty files.\n"); + log("\n"); + log("\n"); log(" read {-f|-F} \n"); log("\n"); log("Load and execute the specified command file. (Requires Verific.)\n"); @@ -3531,6 +3566,15 @@ struct ReadPass : public Pass { return; } #endif + if (args[1] == "-liberty") { + if (use_verific) { + args[0] = "verific"; + } else { + args[0] = "read_liberty"; + } + Pass::call(design, args); + return; + } if (args[1] == "-f" || args[1] == "-F") { if (use_verific) { args[0] = "verific"; From 6fb80bce1577e298fb25e387beb1ff5fb6c7c53e Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 31 Oct 2022 10:51:28 +0100 Subject: [PATCH 20/34] Enable importing blackbox modules only --- frontends/verific/verific.cc | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 0f4eceba4..fb5fc0c6c 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -59,6 +59,7 @@ USING_YOSYS_NAMESPACE #ifdef VERIFIC_LIBERTY_SUPPORT #include "synlib_file.h" +#include "SynlibGroup.h" #endif #include "VerificStream.h" @@ -2439,6 +2440,9 @@ struct VerificPass : public Pass { log("\n"); log("Load the specified Liberty files into Verific.\n"); log("\n"); + log(" -lib\n"); + log(" only create empty blackbox modules\n"); + log("\n"); log("\n"); #endif log(" verific {-f|-F} [-vlog95|-vlog2k|-sv2005|-sv2009|\n"); @@ -3020,11 +3024,36 @@ struct VerificPass : public Pass { #endif #ifdef VERIFIC_LIBERTY_SUPPORT if (GetSize(args) > argidx && args[argidx] == "-liberty") { - argidx++; + bool flag_lib = false; + for (argidx++; argidx < GetSize(args); argidx++) { + if (args[argidx] == "-lib") { + flag_lib = true; + continue; + } + if (args[argidx].compare(0, 1, "-") == 0) { + cmd_error(args, argidx, "unknown option"); + goto check_error; + } + break; + } + while (argidx < GetSize(args)) { std::string filename = frontent_rewrite(args, argidx, tmp_files); if (!synlib_file::Read(filename.c_str(), is_work_set ? work.c_str() : nullptr)) log_cmd_error("Reading `%s' in LIBERTY mode failed.\n", filename.c_str()); + SynlibLibrary *lib = synlib_file::GetLastLibraryAnalyzed(); + if (lib && flag_lib) { + MapIter mi ; + Verific::Cell *c ; + FOREACH_CELL_OF_LIBRARY(lib->GetLibrary(),mi,c) { + MapIter ni ; + Netlist *nl; + FOREACH_NETLIST_OF_CELL(c, ni, nl) { + if (nl) + nl->MakeBlackBox(); + } + } + } } goto check_error; } @@ -3461,6 +3490,9 @@ struct ReadPass : public Pass { log("\n"); log("Load the specified Liberty files.\n"); log("\n"); + log(" -lib\n"); + log(" only create empty blackbox modules\n"); + log("\n"); log("\n"); log(" read {-f|-F} \n"); log("\n"); From 59b6ac47c9121278c9259b82c68b38477ccb73ad Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 31 Oct 2022 18:04:34 +0100 Subject: [PATCH 21/34] Add additional help info --- frontends/verific/verific.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index fb5fc0c6c..6ef563929 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -2439,6 +2439,8 @@ struct VerificPass : public Pass { log(" verific {-liberty} ..\n"); log("\n"); log("Load the specified Liberty files into Verific.\n"); + log("Default library when -work is not present is one specified in liberty file.\n"); + log("To use from SystemVerilog or VHDL use -L to specify liberty library."); log("\n"); log(" -lib\n"); log(" only create empty blackbox modules\n"); From d8ea5ef6e2e6f6da132d8755eddcdaf71b5caf9e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 1 Nov 2022 00:23:48 +0000 Subject: [PATCH 22/34] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 02afebe2e..d0600de6c 100644 --- a/Makefile +++ b/Makefile @@ -142,7 +142,7 @@ LDLIBS += -lrt endif endif -YOSYS_VER := 0.22+62 +YOSYS_VER := 0.22+70 # Note: We arrange for .gitcommit to contain the (short) commit hash in # tarballs generated with git-archive(1) using .gitattributes. The git repo From a4eb7e41c08d6efa02e00dee16674dfb68c9cacc Mon Sep 17 00:00:00 2001 From: Claire Xenia Wolf Date: Tue, 1 Nov 2022 17:51:46 +0100 Subject: [PATCH 23/34] Add extra time at the end of a sat VCD trace Otherwise the final values will not show up in gtkwave waveforms when looking at the generated traces. Signed-off-by: Claire Xenia Wolf --- passes/sat/sat.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/passes/sat/sat.cc b/passes/sat/sat.cc index df2725b3c..e10517d72 100644 --- a/passes/sat/sat.cc +++ b/passes/sat/sat.cc @@ -758,6 +758,7 @@ struct SatHelper if (last_timestep == -2) log(" no model variables selected for display.\n"); + fprintf(f, "#%d\n", last_timestep+1); fclose(f); } From 310281a96c025ea2335b9b5e1c786cd00fede13a Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 4 Nov 2022 14:49:12 +0100 Subject: [PATCH 24/34] Separate deprecated compilers on CI --- .github/workflows/deprecated.yml | 21 +++++++++++++++++++++ .github/workflows/test-linux.yml | 14 -------------- 2 files changed, 21 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/deprecated.yml diff --git a/.github/workflows/deprecated.yml b/.github/workflows/deprecated.yml new file mode 100644 index 000000000..073b9ded3 --- /dev/null +++ b/.github/workflows/deprecated.yml @@ -0,0 +1,21 @@ +name: Deprecated compilers + +on: [push, pull_request] + +jobs: + gcc48: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Build GCC 4.8 + run: | + docker run --rm -v $(pwd):/work yosyshq/deprecated-compilers:1.0 make config-gcc-4.8 + docker run --rm -v $(pwd):/work yosyshq/deprecated-compilers:1.0 make -j8 + + clang39: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Build Clang 3.9 + run: | + docker run --rm -v $(pwd):/work yosyshq/deprecated-compilers:1.0 make CC=clang-3.9 CXX=clang-3.9 LD=clang-3.9 -j8 diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml index b974757c4..eee556794 100644 --- a/.github/workflows/test-linux.yml +++ b/.github/workflows/test-linux.yml @@ -25,12 +25,6 @@ jobs: - os: { id: ubuntu-20.04, name: focal } compiler: 'gcc-10' cpp_std: 'c++11' - - os: { id: ubuntu-18.04, name: bionic } - compiler: 'clang-3.9' - cpp_std: 'c++11' - - os: { id: ubuntu-18.04, name: bionic } - compiler: 'gcc-4.8' - cpp_std: 'c++11' fail-fast: false steps: - name: Install Dependencies @@ -109,15 +103,7 @@ jobs: make -j${{ env.procs }} make install - - name: Build yosys (gcc-4.8) - if: matrix.compiler == 'gcc-4.8' - shell: bash - run: | - make config-${{ matrix.compiler }} - make -j${{ env.procs }} CCXXSTD=${{ matrix.cpp_std }} CC=$CC CXX=$CC LD=$CC - - name: Build yosys - if: matrix.compiler != 'gcc-4.8' shell: bash run: | make config-${CC%%-*} From 14aa485176e11e4095717613c5a958ac1c1f4a45 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 5 Nov 2022 00:20:11 +0000 Subject: [PATCH 25/34] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d0600de6c..5a5288d54 100644 --- a/Makefile +++ b/Makefile @@ -142,7 +142,7 @@ LDLIBS += -lrt endif endif -YOSYS_VER := 0.22+70 +YOSYS_VER := 0.22+72 # Note: We arrange for .gitcommit to contain the (short) commit hash in # tarballs generated with git-archive(1) using .gitattributes. The git repo From 9470ef9efebc1041c5cbbcb2c5fdf0e9125b6014 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 7 Nov 2022 12:13:19 +0100 Subject: [PATCH 26/34] Update CHANGELOG --- CHANGELOG | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index bb55c0c59..47bc7c2b9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,7 +4,18 @@ List of major changes and improvements between releases Yosys 0.22 .. Yosys 0.22-dev -------------------------- + * New commands and options + - Added option "-cross" to "miter" pass. + - Added option "-nocheck" to "equiv_opt" pass. + + * Verific support + - Added support for reading Liberty files using Verific library. + (Optinally enabled with ENABLE_VERIFIC_LIBERTY) + - Added option "-cells" to "verific -import" enabling import of + all cells from verific design. + * Various + - MinGW build (Windows) plugin support - Added YOSYS_ABORT_ON_LOG_ERROR environment variable for debugging. Setting it to 1 causes abort() to be called when Yosys terminates with an error message. From 3477f2d00bd6f4df66248f80917a0c5371cfeaae Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Mon, 7 Nov 2022 11:55:22 +0100 Subject: [PATCH 27/34] fstdata: Handle square/angle bracket replacemnt, change memory handling When writing VCDs smtbmc replaces square brackets with angle brackets to avoid the issues with VCD readers misinterpreting such signal names. For memory addresses it also uses angle brackets and hexadecimal addresses, while other tools will use square brackets and decimal addresses. Previously the code handled both forms of memory addresses, assuming that any signal that looks like a memory address is a memory address. This is not the case when the user uses regular signals whose names include square brackets _or_ when the verific frontend generates such names to represent various constructs. With this change all angular brackets are turned into square brackets when reading the trace _and_ when performing a signal lookup. This means no matter which kind of brackets are used in the design or in the VCD signals will be matched. This will not handle multiple signals that are the same apart from replacing square/angle brackets, but this will cause issues during the VCD writing of smtbmc already. It still uses the distinction between square and angle brackets for memories to decide whether the address is hex or decimal, but even if something looks like a memory and is added to the `memory_to_handle` data, the plain signal added to `name_to_handle` is used as-is, without rewriting the address. This last change is needed to successfully match verific generated signal names that look like memory addresses while keeping memories working at the same time. It may cause regressions when VCD generation was done with a design that had memories but simulation is done with a design where the memories were mapped to registers. This seems like an unusual setup, but could be worked around with some further changes should this be required. --- kernel/fstdata.cc | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc index b2e574b02..ed186d29e 100644 --- a/kernel/fstdata.cc +++ b/kernel/fstdata.cc @@ -78,7 +78,18 @@ uint64_t FstData::getStartTime() { return fstReaderGetStartTime(ctx); } uint64_t FstData::getEndTime() { return fstReaderGetEndTime(ctx); } +static void normalize_brackets(std::string &str) +{ + for (auto &c : str) { + if (c == '<') + c = '['; + else if (c == '>') + c = ']'; + } +} + fstHandle FstData::getHandle(std::string name) { + normalize_brackets(name); if (name_to_handle.find(name) != name_to_handle.end()) return name_to_handle[name]; else @@ -120,6 +131,7 @@ void FstData::extractVarNames() var.is_reg = (fstVarType)h->u.var.typ == FST_VT_VCD_REG; var.name = remove_spaces(h->u.var.name); var.scope = fst_scope_name; + normalize_brackets(var.scope); var.width = h->u.var.length; vars.push_back(var); if (!var.is_alias) @@ -134,35 +146,34 @@ void FstData::extractVarNames() if (clean_name[0]=='\\') clean_name = clean_name.substr(1); size_t pos = clean_name.find_last_of("<"); - if (pos != std::string::npos) { + if (pos != std::string::npos && clean_name.back() == '>') { std::string mem_cell = clean_name.substr(0, pos); + normalize_brackets(mem_cell); std::string addr = clean_name.substr(pos+1); addr.pop_back(); // remove closing bracket char *endptr; int mem_addr = strtol(addr.c_str(), &endptr, 16); if (*endptr) { - log_warning("Error parsing memory address in : %s\n", clean_name.c_str()); + log_debug("Error parsing memory address in : %s\n", clean_name.c_str()); } else { memory_to_handle[var.scope+"."+mem_cell][mem_addr] = var.id; - name_to_handle[stringf("%s.%s[%d]",var.scope.c_str(),mem_cell.c_str(),mem_addr)] = h->u.var.handle; - continue; } } pos = clean_name.find_last_of("["); - if (pos != std::string::npos) { + if (pos != std::string::npos && clean_name.back() == ']') { std::string mem_cell = clean_name.substr(0, pos); + normalize_brackets(mem_cell); std::string addr = clean_name.substr(pos+1); addr.pop_back(); // remove closing bracket char *endptr; int mem_addr = strtol(addr.c_str(), &endptr, 10); if (*endptr) { - log_warning("Error parsing memory address in : %s\n", clean_name.c_str()); + log_debug("Error parsing memory address in : %s\n", clean_name.c_str()); } else { memory_to_handle[var.scope+"."+mem_cell][mem_addr] = var.id; - name_to_handle[stringf("%s.%s[%d]",var.scope.c_str(),mem_cell.c_str(),mem_addr)] = h->u.var.handle; - continue; } } + normalize_brackets(clean_name); name_to_handle[var.scope+"."+clean_name] = h->u.var.handle; break; } From 68d52cb1b1b5fca37742b21376af1f4ffb49c9b2 Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Mon, 7 Nov 2022 12:28:11 +0100 Subject: [PATCH 28/34] fstdata: Update past_data before end_time callback Required to make the '-at' parameter work. --- kernel/fstdata.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc index ed186d29e..1b8043f9a 100644 --- a/kernel/fstdata.cc +++ b/kernel/fstdata.cc @@ -252,6 +252,7 @@ void FstData::reconstructAllAtTimes(std::vector &signal, uint64_t sta past_data = last_data; callback(last_time); } + past_data = last_data; callback(end_time); } From cff42f0af5953b66760df293bfce5d0f37a8504c Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 7 Nov 2022 13:16:38 +0100 Subject: [PATCH 29/34] Update CHANGELOG --- CHANGELOG | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 47bc7c2b9..d925ccd2c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -8,6 +8,10 @@ Yosys 0.22 .. Yosys 0.22-dev - Added option "-cross" to "miter" pass. - Added option "-nocheck" to "equiv_opt" pass. + * Formal Verification + - yosys-smtbmc: Added "--detect-loops" option for checking if states are + unique in temporal induction counter examples. + * Verific support - Added support for reading Liberty files using Verific library. (Optinally enabled with ENABLE_VERIFIC_LIBERTY) @@ -15,7 +19,7 @@ Yosys 0.22 .. Yosys 0.22-dev all cells from verific design. * Various - - MinGW build (Windows) plugin support + - MinGW build (Windows) plugin support. - Added YOSYS_ABORT_ON_LOG_ERROR environment variable for debugging. Setting it to 1 causes abort() to be called when Yosys terminates with an error message. From 9b4fba3870d3d32942fe6ea7fe758a9c17304eab Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Mon, 7 Nov 2022 14:09:33 +0100 Subject: [PATCH 30/34] sim: Run a comb-only update step to set past values during FST cosim The previous approach only initialized past_d and past_ad while for FST cosim we also need to initialize the other past values like past_clk, etc. Also to properly initialize them, we need to run a combinational update step in case any of the wires feeding into the FF are private or otherwise not part of the FST. --- passes/sat/sim.cc | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index b68783f20..3ac431223 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -813,18 +813,6 @@ struct SimInstance std::string v = shared->fst->valueOf(item.second); did_something |= set_state(item.first, Const::from_string(v)); } - for (auto &it : ff_database) - { - ff_state_t &ff = it.second; - SigSpec dsig = it.second.data.sig_d; - Const value = get_state(dsig); - if (dsig.is_wire()) { - ff.past_d = value; - if (ff.data.has_aload) - ff.past_ad = value; - did_something |= true; - } - } for (auto cell : module->cells()) { if (cell->is_mem_cell()) { @@ -1019,6 +1007,16 @@ struct SimWorker : SimShared top->update_ph3(); } + void initialize_stable_past() + { + if (debug) + log("\n-- ph1 (initialize) --\n"); + top->update_ph1(); + if (debug) + log("\n-- ph3 (initialize) --\n"); + top->update_ph3(); + } + void set_inports(pool ports, State value) { for (auto portname : ports) @@ -1191,6 +1189,7 @@ struct SimWorker : SimShared if (initial) { did_something |= top->setInitState(); + initialize_stable_past(); initial = false; } if (did_something) From 2cdbb85da674711f7eaa1f60244ee658d6593f48 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 8 Nov 2022 00:20:00 +0000 Subject: [PATCH 31/34] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5a5288d54..bf34ff497 100644 --- a/Makefile +++ b/Makefile @@ -142,7 +142,7 @@ LDLIBS += -lrt endif endif -YOSYS_VER := 0.22+72 +YOSYS_VER := 0.22+82 # Note: We arrange for .gitcommit to contain the (short) commit hash in # tarballs generated with git-archive(1) using .gitattributes. The git repo From 6758b7babc4caa1ab72d6fa3ae0380efc11f66dc Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 8 Nov 2022 07:54:14 +0100 Subject: [PATCH 32/34] Update manual --- manual/command-reference-manual.tex | 47 +++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/manual/command-reference-manual.tex b/manual/command-reference-manual.tex index 671fabb81..17689c141 100644 --- a/manual/command-reference-manual.tex +++ b/manual/command-reference-manual.tex @@ -902,6 +902,11 @@ widening it to 1-bit, or removing the cell altogether. This command replaces clocked flip-flops with generic $ff cells that use the implicit global clock. This is useful for formal verification of designs with multiple clocks. + +This pass assumes negative hold time for the async FF inputs. For example when +a reset deasserts with the clock edge, then the FF output will still drive the +reset value in the next cycle regardless of the data-in value at the time of +the clock edge. \end{lstlisting} \section{clkbufmap -- insert clock buffers on clock networks} @@ -1554,12 +1559,17 @@ after an optimization pass. -undef enable modelling of undef states during equiv_induct. + -nocheck + disable running check before and after the command under test. + The following commands are executed by this verification command: run_pass: hierarchy -auto-top design -save preopt + check -assert (unless -nocheck) [command] + check -assert (unless -nocheck) design -stash postopt prepare: @@ -3122,6 +3132,12 @@ detected. call 'flatten -wb; opt_expr -keepdc -undriven;;' on the miter circuit. + -cross + allow output ports on the gold module to match input ports on the + gate module. This is useful when the gold module contains additional + logic to drive some of the gate module inputs. + + miter -assert [options] module [miter_name] Creates a miter circuit for property checking. All input ports are kept, @@ -3989,6 +4005,19 @@ the language version (and before file names) to set additional verilog defines. Load the specified VHDL files. (Requires Verific.) + read {-edif} .. + +Load the specified EDIF files. (Requires Verific.) + + + read {-liberty} .. + +Load the specified Liberty files. + + -lib + only create empty blackbox modules + + read {-f|-F} Load and execute the specified command file. (Requires Verific.) @@ -7926,6 +7955,20 @@ Like -sv, but define FORMAL instead of SYNTHESIS. Load the specified VHDL files into Verific. + verific {-edif} .. + +Load the specified EDIF files into Verific. + + + verific {-liberty} .. + +Load the specified Liberty files into Verific. +Default library when -work is not present is one specified in liberty file. +To use from SystemVerilog or VHDL use -L to specify liberty library. + -lib + only create empty blackbox modules + + verific {-f|-F} [-vlog95|-vlog2k|-sv2005|-sv2009| -sv2012|-sv|-formal] @@ -8032,6 +8075,10 @@ Import options: -fullinit Keep all register initializations, even those for non-FF registers. + -cells + Import all cell definitions from Verific loaded libraries even if they are + unused in design. Useful with "-edif" and "-liberty" option. + -chparam name value Elaborate the specified top modules (all modules when -all given) using this parameter value. Modules on which this parameter does not exist will From 7ce5011c24bc4c605578bb16576cadf79373e23f Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 8 Nov 2022 07:55:31 +0100 Subject: [PATCH 33/34] Release version 0.23 --- CHANGELOG | 2 +- Makefile | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index d925ccd2c..2b4dbd03b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,7 +2,7 @@ List of major changes and improvements between releases ======================================================= -Yosys 0.22 .. Yosys 0.22-dev +Yosys 0.22 .. Yosys 0.23 -------------------------- * New commands and options - Added option "-cross" to "miter" pass. diff --git a/Makefile b/Makefile index bf34ff497..96f0f2274 100644 --- a/Makefile +++ b/Makefile @@ -142,7 +142,7 @@ LDLIBS += -lrt endif endif -YOSYS_VER := 0.22+82 +YOSYS_VER := 0.23 # Note: We arrange for .gitcommit to contain the (short) commit hash in # tarballs generated with git-archive(1) using .gitattributes. The git repo @@ -158,7 +158,7 @@ endif OBJS = kernel/version_$(GIT_REV).o bumpversion: - sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline f109fa3.. | wc -l`/;" Makefile +# sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline f109fa3.. | wc -l`/;" Makefile # set 'ABCREV = default' to use abc/ as it is # From cb7299c3dce58bd59d7d8fc0d469c4bd57a8518c Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 8 Nov 2022 07:57:48 +0100 Subject: [PATCH 34/34] Next dev cycle --- CHANGELOG | 3 +++ Makefile | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 2b4dbd03b..5fb698c90 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,9 @@ List of major changes and improvements between releases ======================================================= +Yosys 0.23 .. Yosys 0.23-dev +-------------------------- + Yosys 0.22 .. Yosys 0.23 -------------------------- * New commands and options diff --git a/Makefile b/Makefile index 96f0f2274..f6259886f 100644 --- a/Makefile +++ b/Makefile @@ -142,7 +142,7 @@ LDLIBS += -lrt endif endif -YOSYS_VER := 0.23 +YOSYS_VER := 0.23+0 # Note: We arrange for .gitcommit to contain the (short) commit hash in # tarballs generated with git-archive(1) using .gitattributes. The git repo @@ -158,7 +158,7 @@ endif OBJS = kernel/version_$(GIT_REV).o bumpversion: -# sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline f109fa3.. | wc -l`/;" Makefile + sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 7ce5011.. | wc -l`/;" Makefile # set 'ABCREV = default' to use abc/ as it is #