diff options
Diffstat (limited to 'techlibs/anlogic')
-rw-r--r-- | techlibs/anlogic/Makefile.inc | 2 | ||||
-rw-r--r-- | techlibs/anlogic/anlogic_determine_init.cc | 72 | ||||
-rw-r--r-- | techlibs/anlogic/anlogic_fixcarry.cc | 130 | ||||
-rw-r--r-- | techlibs/anlogic/arith_map.v | 44 | ||||
-rw-r--r-- | techlibs/anlogic/cells_sim.v | 99 | ||||
-rw-r--r-- | techlibs/anlogic/synth_anlogic.cc | 7 |
6 files changed, 257 insertions, 97 deletions
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 <icenowy@aosc.io> - * - * 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<std::string> 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 <miodrag@symbioticeda.com> + * + * 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<SigBit> ci_bits; + dict<SigBit, SigBit> 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<Cell*> 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<std::string> 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..1186543da 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; -endmodule
\ No newline at end of file + + /* End implementation */ + assign X = AA ^ BB; +endmodule diff --git a/techlibs/anlogic/cells_sim.v b/techlibs/anlogic/cells_sim.v index 058e76605..0fba43572 100644 --- a/techlibs/anlogic/cells_sim.v +++ b/techlibs/anlogic/cells_sim.v @@ -1,5 +1,5 @@ module AL_MAP_SEQ ( - output q, + output reg q, input ce, input clk, input sr, @@ -9,6 +9,71 @@ module AL_MAP_SEQ ( parameter REGSET = "RESET"; //RESET/SET parameter SRMUX = "SR"; //SR/INV parameter SRMODE = "SYNC"; //SYNC/ASYNC + + wire clk_ce; + assign clk_ce = ce ? clk : 1'b0; + + wire srmux; + generate + case (SRMUX) + "SR": assign srmux = sr; + "INV": assign srmux = ~sr; + default: assign srmux = sr; + endcase + endgenerate + + wire regset; + generate + case (REGSET) + "RESET": assign regset = 1'b0; + "SET": assign regset = 1'b1; + default: assign regset = 1'b0; + endcase + endgenerate + + initial q = regset; + + generate + if (DFFMODE == "FF") + begin + if (SRMODE == "ASYNC") + begin + always @(posedge clk_ce, posedge srmux) + if (srmux) + q <= regset; + else + q <= d; + end + else + begin + always @(posedge clk_ce) + if (srmux) + q <= regset; + else + q <= d; + end + end + else + begin + // DFFMODE == "LATCH" + if (SRMODE == "ASYNC") + begin + always @(clk_ce, srmux) + if (srmux) + q <= regset; + else + q <= d; + end + else + begin + always @(clk_ce) + if (srmux) + q <= regset; + else + q <= d; + end + end + endgenerate endmodule module AL_MAP_LUT1 ( @@ -17,7 +82,8 @@ module AL_MAP_LUT1 ( ); parameter [1:0] INIT = 2'h0; parameter EQN = "(A)"; - assign o = INIT >> a; + + assign o = a ? INIT[1] : INIT[0]; endmodule module AL_MAP_LUT2 ( @@ -27,7 +93,9 @@ module AL_MAP_LUT2 ( ); parameter [3:0] INIT = 4'h0; parameter EQN = "(A)"; - assign o = INIT >> {b, a}; + + wire [1:0] s1 = b ? INIT[ 3:2] : INIT[1:0]; + assign o = a ? s1[1] : s1[0]; endmodule module AL_MAP_LUT3 ( @@ -38,7 +106,10 @@ module AL_MAP_LUT3 ( ); parameter [7:0] INIT = 8'h0; parameter EQN = "(A)"; - assign o = INIT >> {c, b, a}; + + wire [3:0] s2 = c ? INIT[ 7:4] : INIT[3:0]; + wire [1:0] s1 = b ? s2[ 3:2] : s2[1:0]; + assign o = a ? s1[1] : s1[0]; endmodule module AL_MAP_LUT4 ( @@ -50,7 +121,11 @@ module AL_MAP_LUT4 ( ); parameter [15:0] INIT = 16'h0; parameter EQN = "(A)"; - assign o = INIT >> {d, c, b, a}; + + wire [7:0] s3 = d ? INIT[15:8] : INIT[7:0]; + wire [3:0] s2 = c ? s3[ 7:4] : s3[3:0]; + wire [1:0] s1 = b ? s2[ 3:2] : s2[1:0]; + assign o = a ? s1[1] : s1[0]; endmodule module AL_MAP_LUT5 ( @@ -100,4 +175,18 @@ module AL_MAP_ADDER ( output [1:0] o ); parameter ALUTYPE = "ADD"; + + generate + case (ALUTYPE) + "ADD": assign o = a + b + c; + "SUB": assign o = a - b - c; + "A_LE_B": assign o = a - b - c; + + "ADD_CARRY": assign o = { a, 1'b0 }; + "SUB_CARRY": assign o = { ~a, 1'b0 }; + "A_LE_B_CARRY": assign o = { a, 1'b0 }; + default: assign o = a + b + c; + endcase + endgenerate + endmodule 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"); } |