From 5f561bdcb1d562d6f975b4a27beca1b8b7af908f Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 12 Aug 2019 20:19:54 +0200 Subject: [PATCH] Proper arith for Anlogic and use standard pass --- techlibs/anlogic/Makefile.inc | 2 +- techlibs/anlogic/anlogic_determine_init.cc | 72 ------------ techlibs/anlogic/anlogic_fixcarry.cc | 130 +++++++++++++++++++++ techlibs/anlogic/arith_map.v | 42 ++++--- techlibs/anlogic/synth_anlogic.cc | 7 +- 5 files changed, 162 insertions(+), 91 deletions(-) delete mode 100644 techlibs/anlogic/anlogic_determine_init.cc create mode 100644 techlibs/anlogic/anlogic_fixcarry.cc diff --git a/techlibs/anlogic/Makefile.inc b/techlibs/anlogic/Makefile.inc index 67cf9cf10..9426b5ca5 100644 --- a/techlibs/anlogic/Makefile.inc +++ b/techlibs/anlogic/Makefile.inc @@ -1,7 +1,7 @@ OBJS += techlibs/anlogic/synth_anlogic.o OBJS += techlibs/anlogic/anlogic_eqn.o -OBJS += techlibs/anlogic/anlogic_determine_init.o +OBJS += techlibs/anlogic/anlogic_fixcarry.o $(eval $(call add_share_file,share/anlogic,techlibs/anlogic/cells_map.v)) $(eval $(call add_share_file,share/anlogic,techlibs/anlogic/arith_map.v)) diff --git a/techlibs/anlogic/anlogic_determine_init.cc b/techlibs/anlogic/anlogic_determine_init.cc deleted file mode 100644 index c4089dac2..000000000 --- a/techlibs/anlogic/anlogic_determine_init.cc +++ /dev/null @@ -1,72 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2018 Icenowy Zheng - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include "kernel/yosys.h" -#include "kernel/sigtools.h" - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -struct AnlogicDetermineInitPass : public Pass { - AnlogicDetermineInitPass() : Pass("anlogic_determine_init", "Anlogic: Determine the init value of cells") { } - void help() YS_OVERRIDE - { - log("\n"); - log(" anlogic_determine_init [selection]\n"); - log("\n"); - log("Determine the init value of cells that doesn't allow unknown init value.\n"); - log("\n"); - } - - Const determine_init(Const init) - { - for (int i = 0; i < GetSize(init); i++) { - if (init[i] != State::S0 && init[i] != State::S1) - init[i] = State::S0; - } - - return init; - } - - void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE - { - log_header(design, "Executing ANLOGIC_DETERMINE_INIT pass (determine init value for cells).\n"); - - extra_args(args, args.size(), design); - - int cnt = 0; - for (auto module : design->selected_modules()) - { - for (auto cell : module->selected_cells()) - { - if (cell->type == "\\EG_LOGIC_DRAM16X4") - { - cell->setParam("\\INIT_D0", determine_init(cell->getParam("\\INIT_D0"))); - cell->setParam("\\INIT_D1", determine_init(cell->getParam("\\INIT_D1"))); - cell->setParam("\\INIT_D2", determine_init(cell->getParam("\\INIT_D2"))); - cell->setParam("\\INIT_D3", determine_init(cell->getParam("\\INIT_D3"))); - cnt++; - } - } - } - log_header(design, "Updated %d cells with determined init value.\n", cnt); - } -} AnlogicDetermineInitPass; - -PRIVATE_NAMESPACE_END diff --git a/techlibs/anlogic/anlogic_fixcarry.cc b/techlibs/anlogic/anlogic_fixcarry.cc new file mode 100644 index 000000000..87164d375 --- /dev/null +++ b/techlibs/anlogic/anlogic_fixcarry.cc @@ -0,0 +1,130 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2019 Miodrag Milanovic + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/yosys.h" +#include "kernel/sigtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +static SigBit get_bit_or_zero(const SigSpec &sig) +{ + if (GetSize(sig) == 0) + return State::S0; + return sig[0]; +} + +static void fix_carry_chain(Module *module) +{ + SigMap sigmap(module); + + pool ci_bits; + dict mapping_bits; + + for (auto cell : module->cells()) + { + if (cell->type == "\\AL_MAP_ADDER") { + if (cell->getParam("\\ALUTYPE") != Const("ADD")) continue; + SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\a")); + SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\b")); + if (bit_i0 == State::S0 && bit_i1== State::S0) { + SigBit bit_ci = get_bit_or_zero(cell->getPort("\\c")); + SigSpec o = cell->getPort("\\o"); + if (GetSize(o) == 2) { + SigBit bit_o = o[0]; + ci_bits.insert(bit_ci); + mapping_bits[bit_ci] = bit_o; + } + } + } + } + vector adders_to_fix_cells; + for (auto cell : module->cells()) + { + if (cell->type == "\\AL_MAP_ADDER") { + if (cell->getParam("\\ALUTYPE") != Const("ADD")) continue; + SigBit bit_ci = get_bit_or_zero(cell->getPort("\\c")); + SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\a")); + SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\b")); + SigBit canonical_bit = sigmap(bit_ci); + if (!ci_bits.count(canonical_bit)) + continue; + if (bit_i0 == State::S0 && bit_i1== State::S0) + continue; + + adders_to_fix_cells.push_back(cell); + log("Found %s cell named %s with invalid 'c' signal.\n", log_id(cell->type), log_id(cell)); + } + } + + for (auto cell : adders_to_fix_cells) + { + SigBit bit_ci = get_bit_or_zero(cell->getPort("\\c")); + SigBit canonical_bit = sigmap(bit_ci); + auto bit = mapping_bits.at(canonical_bit); + log("Fixing %s cell named %s breaking carry chain.\n", log_id(cell->type), log_id(cell)); + Cell *c = module->addCell(NEW_ID, "\\AL_MAP_ADDER"); + SigBit new_bit = module->addWire(NEW_ID); + SigBit dummy_bit = module->addWire(NEW_ID); + SigSpec bits; + bits.append(dummy_bit); + bits.append(new_bit); + c->setParam("\\ALUTYPE", Const("ADD_CARRY")); + c->setPort("\\a", bit); + c->setPort("\\b", State::S0); + c->setPort("\\c", State::S0); + c->setPort("\\o", bits); + + cell->setPort("\\c", new_bit); + } + +} + +struct AnlogicCarryFixPass : public Pass { + AnlogicCarryFixPass() : Pass("anlogic_fixcarry", "Anlogic: fix carry chain") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" anlogic_fixcarry [options] [selection]\n"); + log("\n"); + log("Add Anlogic adders to fix carry chain if needed.\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing anlogic_fixcarry pass (fix invalid carry chain).\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + break; + } + extra_args(args, argidx, design); + + Module *module = design->top_module(); + + if (module == nullptr) + log_cmd_error("No top module found.\n"); + + fix_carry_chain(module); + } +} AnlogicCarryFixPass; + +PRIVATE_NAMESPACE_END diff --git a/techlibs/anlogic/arith_map.v b/techlibs/anlogic/arith_map.v index 6d6a7ca37..d783b0212 100644 --- a/techlibs/anlogic/arith_map.v +++ b/techlibs/anlogic/arith_map.v @@ -31,7 +31,10 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO); output [Y_WIDTH-1:0] X, Y; input CI, BI; - output CO; + output [Y_WIDTH-1:0] CO; + + wire CIx; + wire [Y_WIDTH-1:0] COx; wire _TECHMAP_FAIL_ = Y_WIDTH <= 2; @@ -41,15 +44,16 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO); wire [Y_WIDTH-1:0] AA = A_buf; wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; - wire [Y_WIDTH+1:0] COx; - wire [Y_WIDTH+2:0] C = {COx, CI}; + wire [Y_WIDTH-1:0] C = { COx, CIx }; wire dummy; AL_MAP_ADDER #( .ALUTYPE("ADD_CARRY")) adder_cin ( - .a(C[0]), - .o({COx[0], dummy}) + .a(CI), + .b(1'b0), + .c(1'b0), + .o({CIx, dummy}) ); genvar i; @@ -59,18 +63,22 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO); ) adder_i ( .a(AA[i]), .b(BB[i]), - .c(C[i+1]), - .o({COx[i+1],Y[i]}) + .c(C[i]), + .o({COx[i],Y[i]}) ); - end: slice + + wire cout; + AL_MAP_ADDER #( + .ALUTYPE("ADD")) + adder_cout ( + .a(1'b0), + .b(1'b0), + .c(COx[i]), + .o({cout, CO[i]}) + ); + end: slice endgenerate - /* End implementation */ - AL_MAP_ADDER #( - .ALUTYPE("ADD")) - adder_cout ( - .c(C[Y_WIDTH+1]), - .o(COx[Y_WIDTH+1]) - ); - assign CO = COx[Y_WIDTH+1]; - assign X = AA ^ BB; + + /* End implementation */ + assign X = AA ^ BB; endmodule \ No newline at end of file diff --git a/techlibs/anlogic/synth_anlogic.cc b/techlibs/anlogic/synth_anlogic.cc index 620bf3965..b87fc8566 100644 --- a/techlibs/anlogic/synth_anlogic.cc +++ b/techlibs/anlogic/synth_anlogic.cc @@ -154,7 +154,7 @@ struct SynthAnlogicPass : public ScriptPass { run("memory_bram -rules +/anlogic/drams.txt"); run("techmap -map +/anlogic/drams_map.v"); - run("anlogic_determine_init"); + run("setundef -zero -params t:EG_LOGIC_DRAM16X4"); } if (check_label("fine")) @@ -186,6 +186,11 @@ struct SynthAnlogicPass : public ScriptPass { run("techmap -map +/anlogic/cells_map.v"); run("clean"); + } + + if (check_label("map_anlogic")) + { + run("anlogic_fixcarry"); run("anlogic_eqn"); }