From ab98f604fd1319e0f42b0c5dc8bb6be5d3d2ba38 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sat, 3 Aug 2019 12:29:30 +0200 Subject: Initial EFINIX support --- techlibs/efinix/Makefile.inc | 6 ++ techlibs/efinix/arith_map.v | 78 +++++++++++++++ techlibs/efinix/cells_map.v | 45 +++++++++ techlibs/efinix/cells_sim.v | 36 +++++++ techlibs/efinix/synth_efinix.cc | 205 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 370 insertions(+) create mode 100644 techlibs/efinix/Makefile.inc create mode 100644 techlibs/efinix/arith_map.v create mode 100644 techlibs/efinix/cells_map.v create mode 100644 techlibs/efinix/cells_sim.v create mode 100644 techlibs/efinix/synth_efinix.cc (limited to 'techlibs/efinix') diff --git a/techlibs/efinix/Makefile.inc b/techlibs/efinix/Makefile.inc new file mode 100644 index 000000000..3f3394c96 --- /dev/null +++ b/techlibs/efinix/Makefile.inc @@ -0,0 +1,6 @@ + +OBJS += techlibs/efinix/synth_efinix.o + +$(eval $(call add_share_file,share/efinix,techlibs/efinix/cells_map.v)) +$(eval $(call add_share_file,share/efinix,techlibs/efinix/arith_map.v)) +$(eval $(call add_share_file,share/efinix,techlibs/efinix/cells_sim.v)) diff --git a/techlibs/efinix/arith_map.v b/techlibs/efinix/arith_map.v new file mode 100644 index 000000000..ae955663c --- /dev/null +++ b/techlibs/efinix/arith_map.v @@ -0,0 +1,78 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2018 Miodrag Milanovic + * Copyright (C) 2012 Clifford Wolf + * + * 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. + * + */ + +(* techmap_celltype = "$alu" *) +module _80_efinix_alu (A, B, CI, BI, X, Y, CO); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] X, Y; + + input CI, BI; + output CO; + + wire _TECHMAP_FAIL_ = Y_WIDTH <= 2; + + wire [Y_WIDTH-1:0] A_buf, B_buf; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); + + 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}; + + EFX_ADD #(.I0_POLARITY(1'b1),.I1_POLARITY(1'b1)) + adder_cin ( + .I0(C[0]), + .I1(1'b1), + .CI(1'b0), + .CO(COx[0]) + ); + + genvar i; + generate for (i = 0; i < Y_WIDTH; i = i + 1) begin: slice + EFX_ADD #(.I0_POLARITY(1'b1),.I1_POLARITY(1'b1)) + adder_i ( + .I0(AA[i]), + .I1(BB[i]), + .CI(C[i+1]), + .O(Y[i]), + .CO(COx[i+1]) + ); + end: slice + endgenerate + + EFX_ADD #(.I0_POLARITY(1'b1),.I1_POLARITY(1'b1)) + adder_cout ( + .I0(1'b0), + .I1(1'b0), + .CI(C[Y_WIDTH+1]), + .O(COx[Y_WIDTH+1]) + ); + assign CO = COx[Y_WIDTH+1]; + /* End implementation */ + assign X = AA ^ BB; +endmodule \ No newline at end of file diff --git a/techlibs/efinix/cells_map.v b/techlibs/efinix/cells_map.v new file mode 100644 index 000000000..70c19635e --- /dev/null +++ b/techlibs/efinix/cells_map.v @@ -0,0 +1,45 @@ +module \$_DFF_N_ (input D, C, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(1'b0), .Q(Q)); endmodule +module \$_DFF_P_ (input D, C, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(1'b0), .Q(Q)); endmodule + +module \$_DFFE_NN_ (input D, C, E, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b0), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(E), .CLK(C), .SR(1'b0), .Q(Q)); endmodule +module \$_DFFE_NP_ (input D, C, E, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(E), .CLK(C), .SR(1'b0), .Q(Q)); endmodule + +module \$_DFFE_PN_ (input D, C, E, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b0), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(E), .CLK(C), .SR(1'b0), .Q(Q)); endmodule +module \$_DFFE_PP_ (input D, C, E, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(E), .CLK(C), .SR(1'b0), .Q(Q)); endmodule + +module \$_DFF_NN0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule +module \$_DFF_NN1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule +module \$_DFF_PN0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule +module \$_DFF_PN1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule + +module \$_DFF_NP0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule +module \$_DFF_NP1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule +module \$_DFF_PP0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule +module \$_DFF_PP1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule + +`ifndef NO_LUT +module \$lut (A, Y); + parameter WIDTH = 0; + parameter LUT = 0; + + input [WIDTH-1:0] A; + output Y; + + generate + if (WIDTH == 1) begin + EFX_LUT4 #(.LUTMASK(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(1'b0), .I2(1'b0), .I3(1'b0)); + end else + if (WIDTH == 2) begin + EFX_LUT4 #(.LUTMASK(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(A[1]), .I2(1'b0), .I3(1'b0)); + end else + if (WIDTH == 3) begin + EFX_LUT4 #(.LUTMASK(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(1'b0)); + end else + if (WIDTH == 4) begin + EFX_LUT4 #(.LUTMASK(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3])); + end else begin + wire _TECHMAP_FAIL_ = 1; + end + endgenerate +endmodule +`endif diff --git a/techlibs/efinix/cells_sim.v b/techlibs/efinix/cells_sim.v new file mode 100644 index 000000000..aaff955a2 --- /dev/null +++ b/techlibs/efinix/cells_sim.v @@ -0,0 +1,36 @@ +module EFX_LUT4( + output O, + input I0, + input I1, + input I2, + input I3 +); + parameter LUTMASK = 16'h0000; +endmodule + +module EFX_ADD( + output O, + output CO, + input I0, + input I1, + input CI +); + parameter I0_POLARITY = 1; + parameter I1_POLARITY = 1; +endmodule + +module EFX_FF( + output Q, + input D, + input CE, + input CLK, + input SR +); + parameter CLK_POLARITY = 1; + parameter CE_POLARITY = 1; + parameter SR_POLARITY = 1; + parameter SR_SYNC = 0; + parameter SR_VALUE = 0; + parameter SR_SYNC_PRIORITY = 0; + parameter D_POLARITY = 1; +endmodule \ No newline at end of file diff --git a/techlibs/efinix/synth_efinix.cc b/techlibs/efinix/synth_efinix.cc new file mode 100644 index 000000000..9c644d363 --- /dev/null +++ b/techlibs/efinix/synth_efinix.cc @@ -0,0 +1,205 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2019 Miodrag Milanovic + * Copyright (C) 2019 Clifford Wolf + * + * 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/register.h" +#include "kernel/celltypes.h" +#include "kernel/rtlil.h" +#include "kernel/log.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct SynthEfinixPass : public ScriptPass +{ + SynthEfinixPass() : ScriptPass("synth_efinix", "synthesis for Efinix FPGAs") { } + + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" synth_efinix [options]\n"); + log("\n"); + log("This command runs synthesis for Efinix FPGAs.\n"); + log("\n"); + log(" -top \n"); + log(" use the specified module as top module\n"); + log("\n"); + log(" -edif \n"); + log(" write the design to the specified EDIF file. writing of an output file\n"); + log(" is omitted if this parameter is not specified.\n"); + log("\n"); + log(" -json \n"); + log(" write the design to the specified JSON file. writing of an output file\n"); + log(" is omitted if this parameter is not specified.\n"); + log("\n"); + log(" -run :\n"); + log(" only run the commands between the labels (see below). an empty\n"); + log(" from label is synonymous to 'begin', and empty to label is\n"); + log(" synonymous to the end of the command list.\n"); + log("\n"); + log(" -noflatten\n"); + log(" do not flatten design before synthesis\n"); + log("\n"); + log(" -retime\n"); + log(" run 'abc' with -dff option\n"); + log("\n"); + log("\n"); + log("The following commands are executed by this synthesis command:\n"); + help_script(); + log("\n"); + } + + string top_opt, edif_file, json_file; + bool flatten, retime; + + void clear_flags() YS_OVERRIDE + { + top_opt = "-auto-top"; + edif_file = ""; + json_file = ""; + flatten = true; + retime = false; + } + + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + string run_from, run_to; + clear_flags(); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + if (args[argidx] == "-top" && argidx+1 < args.size()) { + top_opt = "-top " + args[++argidx]; + continue; + } + if (args[argidx] == "-edif" && argidx+1 < args.size()) { + edif_file = args[++argidx]; + continue; + } + if (args[argidx] == "-json" && argidx+1 < args.size()) { + json_file = args[++argidx]; + continue; + } + if (args[argidx] == "-run" && argidx+1 < args.size()) { + size_t pos = args[argidx+1].find(':'); + if (pos == std::string::npos) + break; + run_from = args[++argidx].substr(0, pos); + run_to = args[argidx].substr(pos+1); + continue; + } + if (args[argidx] == "-noflatten") { + flatten = false; + continue; + } + if (args[argidx] == "-retime") { + retime = true; + continue; + } + break; + } + extra_args(args, argidx, design); + + if (!design->full_selection()) + log_cmd_error("This command only operates on fully selected designs!\n"); + + log_header(design, "Executing SYNTH_EFINIX pass.\n"); + log_push(); + + run_script(design, run_from, run_to); + + log_pop(); + } + + void script() YS_OVERRIDE + { + if (check_label("begin")) + { + run("read_verilog -lib +/efinix/cells_sim.v"); + run(stringf("hierarchy -check %s", help_mode ? "-top " : top_opt.c_str())); + } + + if (flatten && check_label("flatten", "(unless -noflatten)")) + { + run("proc"); + run("flatten"); + run("tribuf -logic"); + run("deminout"); + } + + if (check_label("coarse")) + { + run("synth -run coarse"); + } + + if (check_label("fine")) + { + run("opt -fast -mux_undef -undriven -fine"); + run("memory_map"); + run("opt -undriven -fine"); + run("techmap -map +/techmap.v -map +/efinix/arith_map.v"); + if (retime || help_mode) + run("abc -dff", "(only if -retime)"); + } + + if (check_label("map_ffs")) + { + run("dffsr2dff"); + run("techmap -D NO_LUT -map +/efinix/cells_map.v"); + run("dffinit -strinit SET RESET -ff AL_MAP_SEQ q REGSET -noreinit"); + run("opt_expr -mux_undef"); + run("simplemap"); + } + + if (check_label("map_luts")) + { + run("abc -lut 4"); + run("clean"); + } + + if (check_label("map_cells")) + { + run("techmap -map +/efinix/cells_map.v"); + run("clean"); + } + + if (check_label("check")) + { + run("hierarchy -check"); + run("stat"); + run("check -noinit"); + } + + if (check_label("edif")) + { + if (!edif_file.empty() || help_mode) + run(stringf("write_edif %s", help_mode ? "" : edif_file.c_str())); + } + + if (check_label("json")) + { + if (!json_file.empty() || help_mode) + run(stringf("write_json %s", help_mode ? "" : json_file.c_str())); + } + } +} SynthEfinixPass; + +PRIVATE_NAMESPACE_END -- cgit v1.2.3 From 6e210f26fa97fa65c420534f0ec0e26eeb1b078a Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sat, 3 Aug 2019 14:40:23 +0200 Subject: Custom step to add global clock buffers --- techlibs/efinix/Makefile.inc | 1 + techlibs/efinix/cells_sim.v | 10 +++- techlibs/efinix/efinix_gbuf.cc | 113 ++++++++++++++++++++++++++++++++++++++++ techlibs/efinix/synth_efinix.cc | 6 +++ 4 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 techlibs/efinix/efinix_gbuf.cc (limited to 'techlibs/efinix') diff --git a/techlibs/efinix/Makefile.inc b/techlibs/efinix/Makefile.inc index 3f3394c96..82dfa3cd8 100644 --- a/techlibs/efinix/Makefile.inc +++ b/techlibs/efinix/Makefile.inc @@ -1,5 +1,6 @@ OBJS += techlibs/efinix/synth_efinix.o +OBJS += techlibs/efinix/efinix_gbuf.o $(eval $(call add_share_file,share/efinix,techlibs/efinix/cells_map.v)) $(eval $(call add_share_file,share/efinix,techlibs/efinix/arith_map.v)) diff --git a/techlibs/efinix/cells_sim.v b/techlibs/efinix/cells_sim.v index aaff955a2..2cbf8ae4b 100644 --- a/techlibs/efinix/cells_sim.v +++ b/techlibs/efinix/cells_sim.v @@ -33,4 +33,12 @@ module EFX_FF( parameter SR_VALUE = 0; parameter SR_SYNC_PRIORITY = 0; parameter D_POLARITY = 1; -endmodule \ No newline at end of file +endmodule + +module EFX_GBUFCE ( + input CE, + input I, + output O +); + parameter CE_POLARITY = 1'b1; +endmodule diff --git a/techlibs/efinix/efinix_gbuf.cc b/techlibs/efinix/efinix_gbuf.cc new file mode 100644 index 000000000..50f84c30c --- /dev/null +++ b/techlibs/efinix/efinix_gbuf.cc @@ -0,0 +1,113 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2019 Miodrag Milanovic + * Copyright (C) 2012 Clifford Wolf + * + * 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 void handle_gbufs(Module *module) +{ + SigMap sigmap(module); + + pool clk_bits; + dict rewrite_bits; + vector> pad_bits; + + for (auto cell : module->cells()) + { + if (cell->type == "\\EFX_FF") { + for (auto bit : sigmap(cell->getPort("\\CLK"))) + clk_bits.insert(bit); + } + } + + for (auto wire : vector(module->wires())) + { + if (!wire->port_input) + continue; + + for (int index = 0; index < GetSize(wire); index++) + { + SigBit bit(wire, index); + SigBit canonical_bit = sigmap(bit); + + if (!clk_bits.count(canonical_bit)) + continue; + + Cell *c = module->addCell(NEW_ID, "\\EFX_GBUFCE"); + SigBit new_bit = module->addWire(NEW_ID); + c->setParam("\\CE_POLARITY", State::S1); + c->setPort("\\O", new_bit); + c->setPort("\\CE", State::S1); + pad_bits.push_back(make_pair(c, bit)); + rewrite_bits[canonical_bit] = new_bit; + + log("Added %s cell %s for port bit %s.\n", log_id(c->type), log_id(c), log_signal(bit)); + } + } + + auto rewrite_function = [&](SigSpec &s) { + for (auto &bit : s) { + SigBit canonical_bit = sigmap(bit); + if (rewrite_bits.count(canonical_bit)) + bit = rewrite_bits.at(canonical_bit); + } + }; + + module->rewrite_sigspecs(rewrite_function); + + for (auto &it : pad_bits) + it.first->setPort("\\I", it.second); +} + +struct EfinixGbufPass : public Pass { + EfinixGbufPass() : Pass("efinix_gbuf", "Efinix: insert global clock buffers") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" efinix_gbuf [options] [selection]\n"); + log("\n"); + log("Add Efinix global clock buffers to top module as needed.\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing efinix_gbuf pass (insert global clock buffers).\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"); + + handle_gbufs(module); + } +} EfinixGbufPass; + +PRIVATE_NAMESPACE_END diff --git a/techlibs/efinix/synth_efinix.cc b/techlibs/efinix/synth_efinix.cc index 9c644d363..3f17bafa3 100644 --- a/techlibs/efinix/synth_efinix.cc +++ b/techlibs/efinix/synth_efinix.cc @@ -181,6 +181,12 @@ struct SynthEfinixPass : public ScriptPass run("clean"); } + if (check_label("map_gbuf")) + { + run("efinix_gbuf"); + run("clean"); + } + if (check_label("check")) { run("hierarchy -check"); -- cgit v1.2.3 From cf96f41c6d9c405ddc039a8d0629731924b774ed Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sun, 4 Aug 2019 11:46:36 +0200 Subject: Added bram support --- techlibs/efinix/Makefile.inc | 3 ++ techlibs/efinix/bram.txt | 32 ++++++++++++ techlibs/efinix/brams_map.v | 65 +++++++++++++++++++++++ techlibs/efinix/cells_sim.v | 65 ++++++++++++++++++++++- techlibs/efinix/efinix_determine_init.cc | 89 ++++++++++++++++++++++++++++++++ techlibs/efinix/synth_efinix.cc | 7 +++ 6 files changed, 260 insertions(+), 1 deletion(-) create mode 100644 techlibs/efinix/bram.txt create mode 100644 techlibs/efinix/brams_map.v create mode 100644 techlibs/efinix/efinix_determine_init.cc (limited to 'techlibs/efinix') diff --git a/techlibs/efinix/Makefile.inc b/techlibs/efinix/Makefile.inc index 82dfa3cd8..d0593baec 100644 --- a/techlibs/efinix/Makefile.inc +++ b/techlibs/efinix/Makefile.inc @@ -1,7 +1,10 @@ OBJS += techlibs/efinix/synth_efinix.o OBJS += techlibs/efinix/efinix_gbuf.o +OBJS += techlibs/efinix/efinix_determine_init.o $(eval $(call add_share_file,share/efinix,techlibs/efinix/cells_map.v)) $(eval $(call add_share_file,share/efinix,techlibs/efinix/arith_map.v)) $(eval $(call add_share_file,share/efinix,techlibs/efinix/cells_sim.v)) +$(eval $(call add_share_file,share/efinix,techlibs/efinix/brams_map.v)) +$(eval $(call add_share_file,share/efinix,techlibs/efinix/bram.txt)) \ No newline at end of file diff --git a/techlibs/efinix/bram.txt b/techlibs/efinix/bram.txt new file mode 100644 index 000000000..0b3fd9308 --- /dev/null +++ b/techlibs/efinix/bram.txt @@ -0,0 +1,32 @@ +bram $__EFINIX_5K + init 1 + + abits 8 @a8d16 + dbits 16 @a8d16 + abits 9 @a9d8 + dbits 8 @a9d8 + abits 10 @a10d4 + dbits 4 @a10d4 + abits 11 @a11d2 + dbits 2 @a11d2 + abits 12 @a12d1 + dbits 1 @a12d1 + abits 8 @a8d20 + dbits 20 @a8d20 + abits 9 @a9d10 + dbits 10 @a9d10 + + groups 2 + ports 1 1 + wrmode 1 0 + enable 1 1 + transp 0 2 + clocks 2 3 + clkpol 2 3 +endbram + +match $__EFINIX_5K + min bits 256 + min efficiency 5 + shuffle_enable B +endmatch diff --git a/techlibs/efinix/brams_map.v b/techlibs/efinix/brams_map.v new file mode 100644 index 000000000..9ef01d026 --- /dev/null +++ b/techlibs/efinix/brams_map.v @@ -0,0 +1,65 @@ +module \$__EFINIX_5K (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); + parameter CFG_ABITS = 8; + parameter CFG_DBITS = 20; + parameter CFG_ENABLE_A = 2; + + parameter CLKPOL2 = 1; + parameter CLKPOL3 = 1; + parameter [5119:0] INIT = 5119'bx; + parameter TRANSP2 = 0; + + input CLK2; + input CLK3; + + input [CFG_ABITS-1:0] A1ADDR; + input [CFG_DBITS-1:0] A1DATA; + input [CFG_ENABLE_A-1:0] A1EN; + + input [CFG_ABITS-1:0] B1ADDR; + output [CFG_DBITS-1:0] B1DATA; + input B1EN; + + localparam WRITEMODE_A = TRANSP2 ? "WRITE_FIRST" : "READ_FIRST"; + + EFX_RAM_5K #( + .READ_WIDTH(20), + .WRITE_WIDTH(20), + .OUTPUT_REG(1'b0), + .RCLK_POLARITY(1'b1), + .RE_POLARITY(1'b1), + .WCLK_POLARITY(1'b1), + .WE_POLARITY(1'b1), + .WCLKE_POLARITY(1'b1), + .WRITE_MODE(WRITEMODE_A), + .INIT_0(INIT[ 0*256 +: 256]), + .INIT_1(INIT[ 1*256 +: 256]), + .INIT_2(INIT[ 2*256 +: 256]), + .INIT_3(INIT[ 3*256 +: 256]), + .INIT_4(INIT[ 4*256 +: 256]), + .INIT_5(INIT[ 5*256 +: 256]), + .INIT_6(INIT[ 6*256 +: 256]), + .INIT_7(INIT[ 7*256 +: 256]), + .INIT_8(INIT[ 8*256 +: 256]), + .INIT_9(INIT[ 9*256 +: 256]), + .INIT_A(INIT[10*256 +: 256]), + .INIT_B(INIT[11*256 +: 256]), + .INIT_C(INIT[12*256 +: 256]), + .INIT_D(INIT[13*256 +: 256]), + .INIT_E(INIT[14*256 +: 256]), + .INIT_F(INIT[15*256 +: 256]), + .INIT_10(INIT[16*256 +: 256]), + .INIT_11(INIT[17*256 +: 256]), + .INIT_12(INIT[18*256 +: 256]), + .INIT_13(INIT[19*256 +: 256]) + ) _TECHMAP_REPLACE_ ( + .WDATA(A1DATA), + .WADDR(A1ADDR), + .WE(A1EN), + .WCLK(CLK2), + .WCLKE(1'b1), + .RDATA(B1DATA), + .RADDR(B1ADDR), + .RE(B1EN), + .RCLK(CLK3) + ); +endmodule diff --git a/techlibs/efinix/cells_sim.v b/techlibs/efinix/cells_sim.v index 2cbf8ae4b..8c8f6afaa 100644 --- a/techlibs/efinix/cells_sim.v +++ b/techlibs/efinix/cells_sim.v @@ -35,10 +35,73 @@ module EFX_FF( parameter D_POLARITY = 1; endmodule -module EFX_GBUFCE ( +module EFX_GBUFCE( input CE, input I, output O ); parameter CE_POLARITY = 1'b1; endmodule + +module EFX_RAM_5K( + input [WRITE_WIDTH-1:0] WDATA, + input [WRITE_ADDR_WIDTH-1:0] WADDR, + input WE, + input WCLK, + input WCLKE, + output [READ_WIDTH-1:0] RDATA, + input [READ_ADDR_WIDTH-1:0] RADDR, + input RE, + input RCLK +); + parameter READ_WIDTH = 20; + parameter WRITE_WIDTH = 20; + parameter OUTPUT_REG = 1'b0; + parameter RCLK_POLARITY = 1'b1; + parameter RE_POLARITY = 1'b1; + parameter WCLK_POLARITY = 1'b1; + parameter WE_POLARITY = 1'b1; + parameter WCLKE_POLARITY = 1'b1; + parameter WRITE_MODE = "READ_FIRST"; + parameter INIT_0 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_4 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_5 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_6 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_7 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_8 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_9 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + + localparam READ_ADDR_WIDTH = + (READ_WIDTH == 16) ? 8 : // 256x16 + (READ_WIDTH == 8) ? 9 : // 512x8 + (READ_WIDTH == 4) ? 10 : // 1024x4 + (READ_WIDTH == 2) ? 11 : // 2048x2 + (READ_WIDTH == 1) ? 12 : // 4096x1 + (READ_WIDTH == 20) ? 8 : // 256x20 + (READ_WIDTH == 10) ? 9 : // 512x10 + (READ_WIDTH == 5) ? 10 : -1; // 1024x5 + + localparam WRITE_ADDR_WIDTH = + (WRITE_WIDTH == 16) ? 8 : // 256x16 + (WRITE_WIDTH == 8) ? 9 : // 512x8 + (WRITE_WIDTH == 4) ? 10 : // 1024x4 + (WRITE_WIDTH == 2) ? 11 : // 2048x2 + (WRITE_WIDTH == 1) ? 12 : // 4096x1 + (WRITE_WIDTH == 20) ? 8 : // 256x20 + (WRITE_WIDTH == 10) ? 9 : // 512x10 + (WRITE_WIDTH == 5) ? 10 : -1; // 1024x5 + +endmodule \ No newline at end of file diff --git a/techlibs/efinix/efinix_determine_init.cc b/techlibs/efinix/efinix_determine_init.cc new file mode 100644 index 000000000..54da703ff --- /dev/null +++ b/techlibs/efinix/efinix_determine_init.cc @@ -0,0 +1,89 @@ +/* + * 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 EfinixDetermineInitPass : public Pass { + EfinixDetermineInitPass() : Pass("efinix_determine_init", "Efinix: Determine the init value of cells") { } + void help() YS_OVERRIDE + { + log("\n"); + log(" efinix_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 EFINIX_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 == "\\EFX_RAM_5K") + { + cell->setParam("\\INIT_0", determine_init(cell->getParam("\\INIT_0"))); + cell->setParam("\\INIT_1", determine_init(cell->getParam("\\INIT_1"))); + cell->setParam("\\INIT_2", determine_init(cell->getParam("\\INIT_2"))); + cell->setParam("\\INIT_3", determine_init(cell->getParam("\\INIT_3"))); + cell->setParam("\\INIT_4", determine_init(cell->getParam("\\INIT_4"))); + cell->setParam("\\INIT_5", determine_init(cell->getParam("\\INIT_5"))); + cell->setParam("\\INIT_6", determine_init(cell->getParam("\\INIT_6"))); + cell->setParam("\\INIT_7", determine_init(cell->getParam("\\INIT_7"))); + cell->setParam("\\INIT_8", determine_init(cell->getParam("\\INIT_8"))); + cell->setParam("\\INIT_9", determine_init(cell->getParam("\\INIT_9"))); + cell->setParam("\\INIT_A", determine_init(cell->getParam("\\INIT_A"))); + cell->setParam("\\INIT_B", determine_init(cell->getParam("\\INIT_B"))); + cell->setParam("\\INIT_C", determine_init(cell->getParam("\\INIT_C"))); + cell->setParam("\\INIT_D", determine_init(cell->getParam("\\INIT_D"))); + cell->setParam("\\INIT_E", determine_init(cell->getParam("\\INIT_E"))); + cell->setParam("\\INIT_F", determine_init(cell->getParam("\\INIT_F"))); + cell->setParam("\\INIT_10", determine_init(cell->getParam("\\INIT_10"))); + cell->setParam("\\INIT_11", determine_init(cell->getParam("\\INIT_11"))); + cell->setParam("\\INIT_12", determine_init(cell->getParam("\\INIT_12"))); + cell->setParam("\\INIT_13", determine_init(cell->getParam("\\INIT_13"))); + + cnt++; + } + } + } + log_header(design, "Updated %d cells with determined init value.\n", cnt); + } +} EfinixDetermineInitPass; + +PRIVATE_NAMESPACE_END diff --git a/techlibs/efinix/synth_efinix.cc b/techlibs/efinix/synth_efinix.cc index 3f17bafa3..000a17310 100644 --- a/techlibs/efinix/synth_efinix.cc +++ b/techlibs/efinix/synth_efinix.cc @@ -150,6 +150,13 @@ struct SynthEfinixPass : public ScriptPass run("synth -run coarse"); } + if (check_label("map_bram", "(skip if -nobram)")) + { + run("memory_bram -rules +/efinix/bram.txt"); + run("techmap -map +/efinix/brams_map.v"); + run("efinix_determine_init"); + } + if (check_label("fine")) { run("opt -fast -mux_undef -undriven -fine"); -- cgit v1.2.3 From 8a3329871ba7bab98982a101327b8375cd73344d Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sun, 4 Aug 2019 12:17:55 +0200 Subject: clock for ram trough gbuf --- techlibs/efinix/efinix_gbuf.cc | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'techlibs/efinix') diff --git a/techlibs/efinix/efinix_gbuf.cc b/techlibs/efinix/efinix_gbuf.cc index 50f84c30c..e75fb3f4d 100644 --- a/techlibs/efinix/efinix_gbuf.cc +++ b/techlibs/efinix/efinix_gbuf.cc @@ -38,6 +38,12 @@ static void handle_gbufs(Module *module) for (auto bit : sigmap(cell->getPort("\\CLK"))) clk_bits.insert(bit); } + if (cell->type == "\\EFX_RAM_5K") { + for (auto bit : sigmap(cell->getPort("\\RCLK"))) + clk_bits.insert(bit); + for (auto bit : sigmap(cell->getPort("\\WCLK"))) + clk_bits.insert(bit); + } } for (auto wire : vector(module->wires())) -- cgit v1.2.3 From d51b135e331326032b003934905c17750e116014 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 9 Aug 2019 12:37:10 +0200 Subject: Fix CO --- techlibs/efinix/arith_map.v | 50 ++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 26 deletions(-) (limited to 'techlibs/efinix') diff --git a/techlibs/efinix/arith_map.v b/techlibs/efinix/arith_map.v index ae955663c..ef903171f 100644 --- a/techlibs/efinix/arith_map.v +++ b/techlibs/efinix/arith_map.v @@ -31,7 +31,7 @@ module _80_efinix_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 _TECHMAP_FAIL_ = Y_WIDTH <= 2; @@ -41,38 +41,36 @@ module _80_efinix_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:0] C; - EFX_ADD #(.I0_POLARITY(1'b1),.I1_POLARITY(1'b1)) - adder_cin ( - .I0(C[0]), + EFX_ADD #(.I0_POLARITY(1'b1),.I1_POLARITY(1'b1)) + adder_cin ( + .I0(CI), .I1(1'b1), .CI(1'b0), - .CO(COx[0]) + .CO(C[0]) ); genvar i; generate for (i = 0; i < Y_WIDTH; i = i + 1) begin: slice - EFX_ADD #(.I0_POLARITY(1'b1),.I1_POLARITY(1'b1)) - adder_i ( - .I0(AA[i]), - .I1(BB[i]), - .CI(C[i+1]), - .O(Y[i]), - .CO(COx[i+1]) - ); - end: slice + EFX_ADD #(.I0_POLARITY(1'b1),.I1_POLARITY(1'b1)) + adder_i ( + .I0(AA[i]), + .I1(BB[i]), + .CI(C[i]), + .O(Y[i]), + .CO(C[i+1]) + ); + EFX_ADD #(.I0_POLARITY(1'b1),.I1_POLARITY(1'b1)) + adder_cout ( + .I0(1'b0), + .I1(1'b0), + .CI(C[i+1]), + .O(CO[i]) + ); + end: slice endgenerate - EFX_ADD #(.I0_POLARITY(1'b1),.I1_POLARITY(1'b1)) - adder_cout ( - .I0(1'b0), - .I1(1'b0), - .CI(C[Y_WIDTH+1]), - .O(COx[Y_WIDTH+1]) - ); - assign CO = COx[Y_WIDTH+1]; - /* End implementation */ - assign X = AA ^ BB; + /* End implementation */ + assign X = AA ^ BB; endmodule \ No newline at end of file -- cgit v1.2.3 From b3a91d6508943c8e5656af0a624e6ad115aec9c3 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sun, 11 Aug 2019 08:37:56 +0200 Subject: cleanup --- techlibs/efinix/arith_map.v | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'techlibs/efinix') diff --git a/techlibs/efinix/arith_map.v b/techlibs/efinix/arith_map.v index ef903171f..56e1b039f 100644 --- a/techlibs/efinix/arith_map.v +++ b/techlibs/efinix/arith_map.v @@ -32,6 +32,9 @@ module _80_efinix_alu (A, B, CI, BI, X, Y, CO); input CI, BI; output [Y_WIDTH-1:0] CO; + + wire CIx; + wire [Y_WIDTH-1:0] COx; wire _TECHMAP_FAIL_ = Y_WIDTH <= 2; @@ -41,14 +44,14 @@ module _80_efinix_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:0] C; + wire [Y_WIDTH-1:0] C = { COx, CIx }; EFX_ADD #(.I0_POLARITY(1'b1),.I1_POLARITY(1'b1)) adder_cin ( .I0(CI), .I1(1'b1), .CI(1'b0), - .CO(C[0]) + .CO(CIx) ); genvar i; @@ -59,13 +62,13 @@ module _80_efinix_alu (A, B, CI, BI, X, Y, CO); .I1(BB[i]), .CI(C[i]), .O(Y[i]), - .CO(C[i+1]) + .CO(COx[i]) ); EFX_ADD #(.I0_POLARITY(1'b1),.I1_POLARITY(1'b1)) adder_cout ( .I0(1'b0), .I1(1'b0), - .CI(C[i+1]), + .CI(COx[i]), .O(CO[i]) ); end: slice -- cgit v1.2.3 From 8c8100e0df51401870fba13fccf5240461f76051 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sun, 11 Aug 2019 10:17:49 +0200 Subject: Adding new pass to fix carry chain --- techlibs/efinix/Makefile.inc | 1 + techlibs/efinix/efinix_fixcarry.cc | 122 +++++++++++++++++++++++++++++++++++++ techlibs/efinix/synth_efinix.cc | 1 + 3 files changed, 124 insertions(+) create mode 100644 techlibs/efinix/efinix_fixcarry.cc (limited to 'techlibs/efinix') diff --git a/techlibs/efinix/Makefile.inc b/techlibs/efinix/Makefile.inc index d0593baec..47dadccdd 100644 --- a/techlibs/efinix/Makefile.inc +++ b/techlibs/efinix/Makefile.inc @@ -2,6 +2,7 @@ OBJS += techlibs/efinix/synth_efinix.o OBJS += techlibs/efinix/efinix_gbuf.o OBJS += techlibs/efinix/efinix_determine_init.o +OBJS += techlibs/efinix/efinix_fixcarry.o $(eval $(call add_share_file,share/efinix,techlibs/efinix/cells_map.v)) $(eval $(call add_share_file,share/efinix,techlibs/efinix/arith_map.v)) diff --git a/techlibs/efinix/efinix_fixcarry.cc b/techlibs/efinix/efinix_fixcarry.cc new file mode 100644 index 000000000..b7cd995b8 --- /dev/null +++ b/techlibs/efinix/efinix_fixcarry.cc @@ -0,0 +1,122 @@ +/* + * 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 == "\\EFX_ADD") { + SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\I0")); + SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\I1")); + if (bit_i0 == State::S0 && bit_i1== State::S0) { + SigBit bit_ci = get_bit_or_zero(cell->getPort("\\CI")); + SigBit bit_o = sigmap(cell->getPort("\\O")); + ci_bits.insert(bit_ci); + mapping_bits[bit_ci] = bit_o; + } + } + } + + vector adders_to_fix_cells; + for (auto cell : module->cells()) + { + if (cell->type == "\\EFX_ADD") { + SigBit bit_ci = get_bit_or_zero(cell->getPort("\\CI")); + SigBit bit_i0 = get_bit_or_zero(cell->getPort("\\I0")); + SigBit bit_i1 = get_bit_or_zero(cell->getPort("\\I1")); + 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 CI 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("\\CI")); + 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, "\\EFX_ADD"); + SigBit new_bit = module->addWire(NEW_ID); + c->setParam("\\I0_POLARITY", State::S1); + c->setParam("\\I1_POLARITY", State::S1); + c->setPort("\\I0", bit); + c->setPort("\\I1", State::S1); + c->setPort("\\CI", State::S0); + c->setPort("\\CO", new_bit); + + cell->setPort("\\CI", new_bit); + } +} + +struct EfinixCarryFixPass : public Pass { + EfinixCarryFixPass() : Pass("efinix_fixcarry", "Efinix: fix carry chain") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" efinix_fixcarry [options] [selection]\n"); + log("\n"); + log("Add Efinix adders to fix carry chain if needed.\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing efinix_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); + } +} EfinixCarryFixPass; + +PRIVATE_NAMESPACE_END diff --git a/techlibs/efinix/synth_efinix.cc b/techlibs/efinix/synth_efinix.cc index 000a17310..d64491ca8 100644 --- a/techlibs/efinix/synth_efinix.cc +++ b/techlibs/efinix/synth_efinix.cc @@ -191,6 +191,7 @@ struct SynthEfinixPass : public ScriptPass if (check_label("map_gbuf")) { run("efinix_gbuf"); + run("efinix_fixcarry"); run("clean"); } -- cgit v1.2.3 From e609537e386535047f045bf0b8df7ebc5f23c469 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sun, 11 Aug 2019 10:46:48 +0200 Subject: Fixed data width --- techlibs/efinix/brams_map.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'techlibs/efinix') diff --git a/techlibs/efinix/brams_map.v b/techlibs/efinix/brams_map.v index 9ef01d026..3236f39a5 100644 --- a/techlibs/efinix/brams_map.v +++ b/techlibs/efinix/brams_map.v @@ -22,8 +22,8 @@ module \$__EFINIX_5K (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); localparam WRITEMODE_A = TRANSP2 ? "WRITE_FIRST" : "READ_FIRST"; EFX_RAM_5K #( - .READ_WIDTH(20), - .WRITE_WIDTH(20), + .READ_WIDTH(CFG_DBITS), + .WRITE_WIDTH(CFG_DBITS), .OUTPUT_REG(1'b0), .RCLK_POLARITY(1'b1), .RE_POLARITY(1'b1), -- cgit v1.2.3 From 853c755a0ca67ae0a75b5cf7783e395d9f49f389 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sun, 11 Aug 2019 11:01:46 +0200 Subject: Replaced custom step with setundef --- techlibs/efinix/Makefile.inc | 1 - techlibs/efinix/efinix_determine_init.cc | 89 -------------------------------- techlibs/efinix/synth_efinix.cc | 2 +- 3 files changed, 1 insertion(+), 91 deletions(-) delete mode 100644 techlibs/efinix/efinix_determine_init.cc (limited to 'techlibs/efinix') diff --git a/techlibs/efinix/Makefile.inc b/techlibs/efinix/Makefile.inc index 47dadccdd..f1ce58276 100644 --- a/techlibs/efinix/Makefile.inc +++ b/techlibs/efinix/Makefile.inc @@ -1,7 +1,6 @@ OBJS += techlibs/efinix/synth_efinix.o OBJS += techlibs/efinix/efinix_gbuf.o -OBJS += techlibs/efinix/efinix_determine_init.o OBJS += techlibs/efinix/efinix_fixcarry.o $(eval $(call add_share_file,share/efinix,techlibs/efinix/cells_map.v)) diff --git a/techlibs/efinix/efinix_determine_init.cc b/techlibs/efinix/efinix_determine_init.cc deleted file mode 100644 index 54da703ff..000000000 --- a/techlibs/efinix/efinix_determine_init.cc +++ /dev/null @@ -1,89 +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 EfinixDetermineInitPass : public Pass { - EfinixDetermineInitPass() : Pass("efinix_determine_init", "Efinix: Determine the init value of cells") { } - void help() YS_OVERRIDE - { - log("\n"); - log(" efinix_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 EFINIX_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 == "\\EFX_RAM_5K") - { - cell->setParam("\\INIT_0", determine_init(cell->getParam("\\INIT_0"))); - cell->setParam("\\INIT_1", determine_init(cell->getParam("\\INIT_1"))); - cell->setParam("\\INIT_2", determine_init(cell->getParam("\\INIT_2"))); - cell->setParam("\\INIT_3", determine_init(cell->getParam("\\INIT_3"))); - cell->setParam("\\INIT_4", determine_init(cell->getParam("\\INIT_4"))); - cell->setParam("\\INIT_5", determine_init(cell->getParam("\\INIT_5"))); - cell->setParam("\\INIT_6", determine_init(cell->getParam("\\INIT_6"))); - cell->setParam("\\INIT_7", determine_init(cell->getParam("\\INIT_7"))); - cell->setParam("\\INIT_8", determine_init(cell->getParam("\\INIT_8"))); - cell->setParam("\\INIT_9", determine_init(cell->getParam("\\INIT_9"))); - cell->setParam("\\INIT_A", determine_init(cell->getParam("\\INIT_A"))); - cell->setParam("\\INIT_B", determine_init(cell->getParam("\\INIT_B"))); - cell->setParam("\\INIT_C", determine_init(cell->getParam("\\INIT_C"))); - cell->setParam("\\INIT_D", determine_init(cell->getParam("\\INIT_D"))); - cell->setParam("\\INIT_E", determine_init(cell->getParam("\\INIT_E"))); - cell->setParam("\\INIT_F", determine_init(cell->getParam("\\INIT_F"))); - cell->setParam("\\INIT_10", determine_init(cell->getParam("\\INIT_10"))); - cell->setParam("\\INIT_11", determine_init(cell->getParam("\\INIT_11"))); - cell->setParam("\\INIT_12", determine_init(cell->getParam("\\INIT_12"))); - cell->setParam("\\INIT_13", determine_init(cell->getParam("\\INIT_13"))); - - cnt++; - } - } - } - log_header(design, "Updated %d cells with determined init value.\n", cnt); - } -} EfinixDetermineInitPass; - -PRIVATE_NAMESPACE_END diff --git a/techlibs/efinix/synth_efinix.cc b/techlibs/efinix/synth_efinix.cc index d64491ca8..26a8d4eda 100644 --- a/techlibs/efinix/synth_efinix.cc +++ b/techlibs/efinix/synth_efinix.cc @@ -154,7 +154,7 @@ struct SynthEfinixPass : public ScriptPass { run("memory_bram -rules +/efinix/bram.txt"); run("techmap -map +/efinix/brams_map.v"); - run("efinix_determine_init"); + run("setundef -zero -params t:EFX_RAM_5K"); } if (check_label("fine")) -- cgit v1.2.3 From aa0c37722a99a308e64ea9581111adea2d97e46d Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sun, 11 Aug 2019 11:40:15 +0200 Subject: fix mixing signals on FF mapping --- techlibs/efinix/cells_map.v | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'techlibs/efinix') diff --git a/techlibs/efinix/cells_map.v b/techlibs/efinix/cells_map.v index 70c19635e..0aeab1902 100644 --- a/techlibs/efinix/cells_map.v +++ b/techlibs/efinix/cells_map.v @@ -8,14 +8,14 @@ module \$_DFFE_PN_ (input D, C, E, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE module \$_DFFE_PP_ (input D, C, E, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(E), .CLK(C), .SR(1'b0), .Q(Q)); endmodule module \$_DFF_NN0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule -module \$_DFF_NN1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule +module \$_DFF_NN1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b1), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule module \$_DFF_PN0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule -module \$_DFF_PN1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule +module \$_DFF_PN1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b0), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b1), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule module \$_DFF_NP0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule -module \$_DFF_NP1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule +module \$_DFF_NP1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b0), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b1), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule module \$_DFF_PP0_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule -module \$_DFF_PP1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b1), .SR_VALUE(1'b0), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule +module \$_DFF_PP1_ (input D, C, R, output Q); EFX_FF #(.CLK_POLARITY(1'b1), .CE_POLARITY(1'b1), .SR_POLARITY(1'b1), .D_POLARITY(1'b1), .SR_SYNC(1'b0), .SR_VALUE(1'b1), .SR_SYNC_PRIORITY(1'b1)) _TECHMAP_REPLACE_ (.D(D), .CE(1'b1), .CLK(C), .SR(R), .Q(Q)); endmodule `ifndef NO_LUT module \$lut (A, Y); -- cgit v1.2.3 From ead2b52b5a123e2c93578555de394a7a406e1fa5 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sun, 11 Aug 2019 13:59:39 +0200 Subject: one bit enable signal --- techlibs/efinix/brams_map.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'techlibs/efinix') diff --git a/techlibs/efinix/brams_map.v b/techlibs/efinix/brams_map.v index 3236f39a5..6786ae769 100644 --- a/techlibs/efinix/brams_map.v +++ b/techlibs/efinix/brams_map.v @@ -1,7 +1,7 @@ module \$__EFINIX_5K (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); parameter CFG_ABITS = 8; parameter CFG_DBITS = 20; - parameter CFG_ENABLE_A = 2; + parameter CFG_ENABLE_A = 1; parameter CLKPOL2 = 1; parameter CLKPOL3 = 1; -- cgit v1.2.3 From 2897fe4d09118e37934b7e76f4990cc1d69a0cb5 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sun, 11 Aug 2019 17:05:24 +0200 Subject: Fix formating --- techlibs/efinix/arith_map.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'techlibs/efinix') diff --git a/techlibs/efinix/arith_map.v b/techlibs/efinix/arith_map.v index 56e1b039f..178f57bc5 100644 --- a/techlibs/efinix/arith_map.v +++ b/techlibs/efinix/arith_map.v @@ -33,8 +33,8 @@ module _80_efinix_alu (A, B, CI, BI, X, Y, CO); input CI, BI; output [Y_WIDTH-1:0] CO; - wire CIx; - wire [Y_WIDTH-1:0] COx; + wire CIx; + wire [Y_WIDTH-1:0] COx; wire _TECHMAP_FAIL_ = Y_WIDTH <= 2; -- cgit v1.2.3