summaryrefslogtreecommitdiff
path: root/techlibs
diff options
context:
space:
mode:
Diffstat (limited to 'techlibs')
-rwxr-xr-xtechlibs/achronix/Makefile.inc6
-rwxr-xr-xtechlibs/achronix/speedster22i/cells_arith.v65
-rwxr-xr-xtechlibs/achronix/speedster22i/cells_map.v72
-rwxr-xr-xtechlibs/achronix/speedster22i/cells_sim.v80
-rwxr-xr-xtechlibs/achronix/synth_achronix.cc188
-rw-r--r--techlibs/common/Makefile.inc1
-rw-r--r--techlibs/common/dff2ff.v14
-rw-r--r--techlibs/common/prep.cc32
-rw-r--r--techlibs/common/simcells.v38
-rw-r--r--techlibs/common/simlib.v48
-rw-r--r--techlibs/common/synth.cc21
-rw-r--r--techlibs/coolrunner2/Makefile.inc8
-rw-r--r--techlibs/coolrunner2/cells_latch.v19
-rw-r--r--techlibs/coolrunner2/cells_sim.v310
-rw-r--r--techlibs/coolrunner2/coolrunner2_sop.cc320
-rw-r--r--techlibs/coolrunner2/synth_coolrunner2.cc202
-rw-r--r--techlibs/coolrunner2/tff_extract.v41
-rw-r--r--techlibs/coolrunner2/xc2_dff.lib31
-rw-r--r--techlibs/easic/Makefile.inc3
-rw-r--r--techlibs/easic/synth_easic.cc188
-rw-r--r--techlibs/ecp5/Makefile.inc8
-rw-r--r--techlibs/ecp5/arith_map.v79
-rw-r--r--techlibs/ecp5/cells_map.v135
-rw-r--r--techlibs/ecp5/cells_sim.v448
-rw-r--r--techlibs/ecp5/dram.txt16
-rw-r--r--techlibs/ecp5/drams_map.v28
-rw-r--r--techlibs/ecp5/synth_ecp5.cc331
-rw-r--r--techlibs/gowin/cells_sim.v48
-rw-r--r--techlibs/gowin/synth_gowin.cc10
-rw-r--r--techlibs/greenpak4/Makefile.inc6
-rw-r--r--techlibs/greenpak4/cells_blackbox.v18
-rw-r--r--techlibs/greenpak4/cells_latch.v15
-rw-r--r--techlibs/greenpak4/cells_map.v165
-rw-r--r--techlibs/greenpak4/cells_sim.v462
-rw-r--r--techlibs/greenpak4/cells_sim_ams.v110
-rw-r--r--techlibs/greenpak4/cells_sim_digital.v794
-rw-r--r--techlibs/greenpak4/cells_sim_wip.v136
-rw-r--r--techlibs/greenpak4/greenpak4_counters.cc442
-rw-r--r--techlibs/greenpak4/greenpak4_dffinv.cc25
-rw-r--r--techlibs/greenpak4/synth_greenpak4.cc15
-rw-r--r--techlibs/ice40/cells_map.v2
-rw-r--r--techlibs/ice40/cells_sim.v436
-rw-r--r--techlibs/ice40/ice40_ffinit.cc4
-rw-r--r--techlibs/ice40/ice40_ffssr.cc4
-rw-r--r--techlibs/ice40/ice40_opt.cc38
-rw-r--r--techlibs/ice40/synth_ice40.cc74
-rw-r--r--techlibs/intel/Makefile.inc24
-rw-r--r--techlibs/intel/a10gx/cells_arith.v65
-rw-r--r--techlibs/intel/a10gx/cells_map.v53
-rw-r--r--techlibs/intel/a10gx/cells_sim.v59
-rw-r--r--techlibs/intel/common/altpll_bb.v366
-rw-r--r--techlibs/intel/common/brams.txt33
-rw-r--r--techlibs/intel/common/brams_map.v93
-rw-r--r--techlibs/intel/common/m9k_bb.v70
-rw-r--r--techlibs/intel/cyclone10/cells_arith.v65
-rw-r--r--techlibs/intel/cyclone10/cells_map.v109
-rw-r--r--techlibs/intel/cyclone10/cells_sim.v137
-rw-r--r--techlibs/intel/cycloneiv/cells_arith.v97
-rw-r--r--techlibs/intel/cycloneiv/cells_map.v93
-rw-r--r--techlibs/intel/cycloneiv/cells_sim.v299
-rw-r--r--techlibs/intel/cycloneive/arith_map.v99
-rw-r--r--techlibs/intel/cycloneive/cells_map.v109
-rw-r--r--techlibs/intel/cycloneive/cells_sim.v292
-rw-r--r--techlibs/intel/cyclonev/cells_arith.v65
-rw-r--r--techlibs/intel/cyclonev/cells_map.v162
-rw-r--r--techlibs/intel/cyclonev/cells_sim.v144
-rw-r--r--techlibs/intel/max10/cells_arith.v65
-rw-r--r--techlibs/intel/max10/cells_map.v93
-rw-r--r--techlibs/intel/max10/cells_sim.v292
-rw-r--r--techlibs/intel/synth_intel.cc270
-rw-r--r--techlibs/xilinx/Makefile.inc2
-rw-r--r--techlibs/xilinx/brams_init.py16
-rw-r--r--techlibs/xilinx/cells_map.v2
-rw-r--r--techlibs/xilinx/cells_sim.v30
-rw-r--r--techlibs/xilinx/drams_bb.v20
-rw-r--r--techlibs/xilinx/lut2lut.v65
-rw-r--r--techlibs/xilinx/synth_xilinx.cc43
77 files changed, 7801 insertions, 1067 deletions
diff --git a/techlibs/achronix/Makefile.inc b/techlibs/achronix/Makefile.inc
new file mode 100755
index 00000000..994cf001
--- /dev/null
+++ b/techlibs/achronix/Makefile.inc
@@ -0,0 +1,6 @@
+
+OBJS += techlibs/achronix/synth_achronix.o
+
+$(eval $(call add_share_file,share/achronix/speedster22i/,techlibs/achronix/speedster22i/cells_sim.v))
+$(eval $(call add_share_file,share/achronix/speedster22i/,techlibs/achronix/speedster22i/cells_map.v))
+
diff --git a/techlibs/achronix/speedster22i/cells_arith.v b/techlibs/achronix/speedster22i/cells_arith.v
new file mode 100755
index 00000000..e2194cbd
--- /dev/null
+++ b/techlibs/achronix/speedster22i/cells_arith.v
@@ -0,0 +1,65 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+
+// NOTE: This is still WIP.
+(* techmap_celltype = "$alu" *)
+module _80_altera_max10_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 [Y_WIDTH-1:0] CO;
+ output CO;
+
+ wire _TECHMAP_FAIL_ = Y_WIDTH <= 4;
+
+ 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:0] C = {CO, CI};
+ wire [Y_WIDTH+1:0] COx;
+ wire [Y_WIDTH+1:0] C = {COx, CI};
+
+ /* Start implementation */
+ (* keep *) fiftyfivenm_lcell_comb #(.lut_mask(16'b0000_0000_1010_1010), .sum_lutc_input("cin")) carry_start (.cout(COx[0]), .dataa(C[0]), .datab(1'b1), .datac(1'b1), .datad(1'b1));
+
+ genvar i;
+ generate for (i = 0; i < Y_WIDTH; i = i + 1) begin: slice
+ if(i==Y_WIDTH-1) begin
+ (* keep *) fiftyfivenm_lcell_comb #(.lut_mask(16'b1111_0000_1110_0000), .sum_lutc_input("cin")) carry_end (.combout(COx[Y_WIDTH]), .dataa(1'b1), .datab(1'b1), .datac(1'b1), .datad(1'b1), .cin(C[Y_WIDTH]));
+ assign CO = COx[Y_WIDTH];
+ end
+ else
+ fiftyfivenm_lcell_comb #(.lut_mask(16'b1001_0110_1110_1000), .sum_lutc_input("cin")) arith_cell (.combout(Y[i]), .cout(COx[i+1]), .dataa(AA[i]), .datab(BB[i]), .datac(1'b1), .datad(1'b1), .cin(C[i+1]));
+ end: slice
+ endgenerate
+ /* End implementation */
+ assign X = AA ^ BB;
+
+endmodule
diff --git a/techlibs/achronix/speedster22i/cells_map.v b/techlibs/achronix/speedster22i/cells_map.v
new file mode 100755
index 00000000..95f5d59c
--- /dev/null
+++ b/techlibs/achronix/speedster22i/cells_map.v
@@ -0,0 +1,72 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+// > c60k28 (Viacheslav, VT) [at] yandex [dot] com
+// > Achronix eFPGA technology mapping. User must first simulate the generated \
+// > netlist before going to test it on board/custom chip.
+
+// > Input/Output buffers <
+// Input buffer map
+module \$__inpad (input I, output O);
+ PADIN _TECHMAP_REPLACE_ (.padout(O), .padin(I));
+endmodule
+// Output buffer map
+module \$__outpad (input I, output O);
+ PADOUT _TECHMAP_REPLACE_ (.padout(O), .padin(I), .oe(1'b1));
+endmodule
+// > end buffers <
+
+// > Look-Up table <
+// > VT: I still think Achronix folks would have choosen a better \
+// > logic architecture.
+// LUT Map
+module \$lut (A, Y);
+ parameter WIDTH = 0;
+ parameter LUT = 0;
+ input [WIDTH-1:0] A;
+ output Y;
+ generate
+ if (WIDTH == 1) begin
+ // VT: This is not consistent and ACE will complain: assign Y = ~A[0];
+ LUT4 #(.lut_function({4{LUT}})) _TECHMAP_REPLACE_
+ (.dout(Y), .din0(A[0]), .din1(1'b0), .din2(1'b0), .din3(1'b0));
+ end else
+ if (WIDTH == 2) begin
+ LUT4 #(.lut_function({4{LUT}})) _TECHMAP_REPLACE_
+ (.dout(Y), .din0(A[0]), .din1(A[1]), .din2(1'b0), .din3(1'b0));
+ end else
+ if(WIDTH == 3) begin
+ LUT4 #(.lut_function({2{LUT}})) _TECHMAP_REPLACE_
+ (.dout(Y), .din0(A[0]), .din1(A[1]), .din2(A[2]), .din3(1'b0));
+ end else
+ if(WIDTH == 4) begin
+ LUT4 #(.lut_function(LUT)) _TECHMAP_REPLACE_
+ (.dout(Y), .din0(A[0]), .din1(A[1]), .din2(A[2]), .din3(A[3]));
+ end else
+ wire _TECHMAP_FAIL_ = 1;
+ endgenerate
+endmodule
+// > end LUT <
+
+// > Flops <
+// DFF flop
+module \$_DFF_P_ (input D, C, output Q);
+ DFF _TECHMAP_REPLACE_
+ (.q(Q), .d(D), .ck(C));
+endmodule
+
diff --git a/techlibs/achronix/speedster22i/cells_sim.v b/techlibs/achronix/speedster22i/cells_sim.v
new file mode 100755
index 00000000..da23fed7
--- /dev/null
+++ b/techlibs/achronix/speedster22i/cells_sim.v
@@ -0,0 +1,80 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+// > c60k28 (Viacheslav, VT) [at] yandex [dot] com
+// > Achronix eFPGA technology sim models. User must first simulate the generated \
+// > netlist before going to test it on board/custom chip.
+// > Changelog: 1) Removed unused VCC/GND modules
+// > 2) Altera comments here (?). Removed.
+// > 3) Reusing LUT sim model, removed wrong wires and parameters.
+
+module PADIN (output padout, input padin);
+ assign padout = padin;
+endmodule
+
+module PADOUT (output padout, input padin, input oe);
+ assign padout = padin;
+ assign oe = oe;
+endmodule
+
+module LUT4 (output dout,
+ input din0, din1, din2, din3);
+
+parameter [15:0] lut_function = 16'hFFFF;
+reg combout_rt;
+wire dataa_w;
+wire datab_w;
+wire datac_w;
+wire datad_w;
+
+assign dataa_w = din0;
+assign datab_w = din1;
+assign datac_w = din2;
+assign datad_w = din3;
+
+function lut_data;
+input [15:0] mask;
+input dataa, datab, datac, datad;
+reg [7:0] s3;
+reg [3:0] s2;
+reg [1:0] s1;
+ begin
+ s3 = datad ? mask[15:8] : mask[7:0];
+ s2 = datac ? s3[7:4] : s3[3:0];
+ s1 = datab ? s2[3:2] : s2[1:0];
+ lut_data = dataa ? s1[1] : s1[0];
+ end
+endfunction
+
+always @(dataa_w or datab_w or datac_w or datad_w or cin_w) begin
+ combout_rt = lut_data(lut_function, dataa_w, datab_w,
+ datac_w, datad_w);
+end
+assign dout = combout_rt & 1'b1;
+endmodule
+
+module DFF (output q,
+ input d, ck);
+ reg q;
+ always @(posedge ck)
+ q <= d;
+
+endmodule
+
+
+
diff --git a/techlibs/achronix/synth_achronix.cc b/techlibs/achronix/synth_achronix.cc
new file mode 100755
index 00000000..92b10781
--- /dev/null
+++ b/techlibs/achronix/synth_achronix.cc
@@ -0,0 +1,188 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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 SynthAchronixPass : public ScriptPass {
+ SynthAchronixPass() : ScriptPass("synth_achronix", "synthesis for Acrhonix Speedster22i FPGAs.") { }
+
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" synth_achronix [options]\n");
+ log("\n");
+ log("This command runs synthesis for Achronix Speedster eFPGAs. This work is still experimental.\n");
+ log("\n");
+ log(" -top <module>\n");
+ log(" use the specified module as top module (default='top')\n");
+ log("\n");
+ log(" -vout <file>\n");
+ log(" write the design to the specified Verilog netlist file. writing of an\n");
+ log(" output file is omitted if this parameter is not specified.\n");
+ log("\n");
+ log(" -run <from_label>:<to_label>\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, family_opt, vout_file;
+ bool retime, flatten;
+
+ void clear_flags() YS_OVERRIDE
+ {
+ top_opt = "-auto-top";
+ vout_file = "";
+ retime = false;
+ flatten = true;
+ }
+
+ void execute(std::vector<std::string> 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] == "-vout" && argidx+1 < args.size()) {
+ vout_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] == "-flatten") {
+ flatten = true;
+ continue;
+ }
+ if (args[argidx] == "-retime") {
+ retime = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ if (!design->full_selection())
+ log_cmd_error("This comannd only operates on fully selected designs!\n");
+
+ log_header(design, "Executing SYNTH_ACHRONIX pass.\n");
+ log_push();
+
+ run_script(design, run_from, run_to);
+
+ log_pop();
+ }
+
+ void script() YS_OVERRIDE
+ {
+ if (check_label("begin"))
+ {
+ run("read_verilog -sv -lib +/achronix/speedster22i/cells_sim.v");
+ run(stringf("hierarchy -check %s", help_mode ? "-top <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 -full");
+ run("memory_map");
+ run("opt -undriven -fine");
+ run("dffsr2dff");
+ run("dff2dffe -direct-match $_DFF_*");
+ run("opt -fine");
+ run("techmap -map +/techmap.v");
+ run("opt -full");
+ run("clean -purge");
+ run("setundef -undriven -zero");
+ if (retime || help_mode)
+ run("abc -markgroups -dff", "(only if -retime)");
+ }
+
+ if (check_label("map_luts"))
+ {
+ run("abc -lut 4" + string(retime ? " -dff" : ""));
+ run("clean");
+ }
+
+ if (check_label("map_cells"))
+ {
+ run("iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I");
+ run("techmap -map +/achronix/speedster22i/cells_map.v");
+ // VT: not done yet run("dffinit -highlow -ff DFF q power_up");
+ run("clean -purge");
+ }
+
+ if (check_label("check"))
+ {
+ run("hierarchy -check");
+ run("stat");
+ run("check -noinit");
+ }
+
+ if (check_label("vout"))
+ {
+ if (!vout_file.empty() || help_mode)
+ run(stringf("write_verilog -nodec -attr2comment -defparam -renameprefix syn_ %s",
+ help_mode ? "<file-name>" : vout_file.c_str()));
+ }
+ }
+} SynthAchronixPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/common/Makefile.inc b/techlibs/common/Makefile.inc
index 236d6c55..ab961ac0 100644
--- a/techlibs/common/Makefile.inc
+++ b/techlibs/common/Makefile.inc
@@ -24,5 +24,6 @@ $(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/pmux2mux.v))
$(eval $(call add_share_file,share,techlibs/common/adff2dff.v))
+$(eval $(call add_share_file,share,techlibs/common/dff2ff.v))
$(eval $(call add_share_file,share,techlibs/common/cells.lib))
diff --git a/techlibs/common/dff2ff.v b/techlibs/common/dff2ff.v
new file mode 100644
index 00000000..2dc4d20d
--- /dev/null
+++ b/techlibs/common/dff2ff.v
@@ -0,0 +1,14 @@
+(* techmap_celltype = "$dff" *)
+module dff2ff (CLK, D, Q);
+ parameter WIDTH = 1;
+ parameter CLK_POLARITY = 1;
+
+ input CLK;
+ input [WIDTH-1:0] D;
+ output reg [WIDTH-1:0] Q;
+
+ wire [1023:0] _TECHMAP_DO_ = "proc;;";
+
+ always @($global_clock)
+ Q <= D;
+endmodule
diff --git a/techlibs/common/prep.cc b/techlibs/common/prep.cc
index 71534983..897f37db 100644
--- a/techlibs/common/prep.cc
+++ b/techlibs/common/prep.cc
@@ -29,7 +29,7 @@ struct PrepPass : public ScriptPass
{
PrepPass() : ScriptPass("prep", "generic synthesis script") { }
- virtual void help() YS_OVERRIDE
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -55,15 +55,16 @@ struct PrepPass : public ScriptPass
log("\n");
log(" -memx\n");
log(" simulate verilog simulation behavior for out-of-bounds memory accesses\n");
- log(" using the 'memory_memx' pass. This option implies -nordff.\n");
+ log(" using the 'memory_memx' pass.\n");
log("\n");
log(" -nomem\n");
log(" do not run any of the memory_* passes\n");
log("\n");
- log(" -nordff\n");
- log(" passed to 'memory_dff'. prohibits merging of FFs into memory read ports\n");
+ log(" -rdff\n");
+ log(" do not pass -nordff to 'memory_dff'. This enables merging of FFs into\n");
+ log(" memory read ports.\n");
log("\n");
- log(" -nokeepdc\n");
+ log(" -nokeepdc\n");
log(" do not call opt_* with -keepdc\n");
log("\n");
log(" -run <from_label>[:<to_label>]\n");
@@ -77,13 +78,12 @@ struct PrepPass : public ScriptPass
log("\n");
}
- string top_module, fsm_opts, memory_opts;
- bool autotop, flatten, ifxmode, memxmode, nomemmode, nokeepdc;
+ string top_module, fsm_opts;
+ bool autotop, flatten, ifxmode, memxmode, nomemmode, nokeepdc, nordff;
- virtual void clear_flags() YS_OVERRIDE
+ void clear_flags() YS_OVERRIDE
{
top_module.clear();
- memory_opts.clear();
autotop = false;
flatten = false;
@@ -91,9 +91,10 @@ struct PrepPass : public ScriptPass
memxmode = false;
nomemmode = false;
nokeepdc = false;
+ nordff = true;
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
string run_from, run_to;
@@ -129,7 +130,6 @@ struct PrepPass : public ScriptPass
}
if (args[argidx] == "-memx") {
memxmode = true;
- memory_opts += " -nordff";
continue;
}
if (args[argidx] == "-nomem") {
@@ -137,7 +137,11 @@ struct PrepPass : public ScriptPass
continue;
}
if (args[argidx] == "-nordff") {
- memory_opts += " -nordff";
+ nordff = true;
+ continue;
+ }
+ if (args[argidx] == "-rdff") {
+ nordff = false;
continue;
}
if (args[argidx] == "-nokeepdc") {
@@ -159,7 +163,7 @@ struct PrepPass : public ScriptPass
log_pop();
}
- virtual void script() YS_OVERRIDE
+ void script() YS_OVERRIDE
{
if (check_label("begin"))
@@ -196,7 +200,7 @@ struct PrepPass : public ScriptPass
run(memxmode ? "wreduce -memx" : "wreduce");
}
if (!nomemmode) {
- run("memory_dff" + (help_mode ? " [-nordff]" : memory_opts));
+ run(string("memory_dff") + (help_mode ? " [-nordff]" : nordff ? " -nordff" : ""));
if (help_mode || memxmode)
run("memory_memx", "(if -memx)");
run("opt_clean");
diff --git a/techlibs/common/simcells.v b/techlibs/common/simcells.v
index e770c545..937512e7 100644
--- a/techlibs/common/simcells.v
+++ b/techlibs/common/simcells.v
@@ -175,6 +175,44 @@ endmodule
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
+//- $_ANDNOT_ (A, B, Y)
+//-
+//- A 2-input AND-NOT gate.
+//-
+//- Truth table: A B | Y
+//- -----+---
+//- 0 0 | 0
+//- 0 1 | 0
+//- 1 0 | 1
+//- 1 1 | 0
+//-
+module \$_ANDNOT_ (A, B, Y);
+input A, B;
+output Y;
+assign Y = A & (~B);
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ORNOT_ (A, B, Y)
+//-
+//- A 2-input OR-NOT gate.
+//-
+//- Truth table: A B | Y
+//- -----+---
+//- 0 0 | 1
+//- 0 1 | 0
+//- 1 0 | 1
+//- 1 1 | 1
+//-
+module \$_ORNOT_ (A, B, Y);
+input A, B;
+output Y;
+assign Y = A | (~B);
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
//- $_MUX_ (A, B, S, Y)
//-
//- A 2-input MUX gate.
diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v
index 2c4db1ac..8e43fe05 100644
--- a/techlibs/common/simlib.v
+++ b/techlibs/common/simlib.v
@@ -1305,6 +1305,30 @@ endmodule
// --------------------------------------------------------
+module \$live (A, EN);
+
+input A, EN;
+
+endmodule
+
+// --------------------------------------------------------
+
+module \$fair (A, EN);
+
+input A, EN;
+
+endmodule
+
+// --------------------------------------------------------
+
+module \$cover (A, EN);
+
+input A, EN;
+
+endmodule
+
+// --------------------------------------------------------
+
module \$initstate (Y);
output reg Y = 1;
@@ -1346,6 +1370,30 @@ endmodule
// --------------------------------------------------------
+module \$allconst (Y);
+
+parameter WIDTH = 0;
+
+output [WIDTH-1:0] Y;
+
+assign Y = 'bx;
+
+endmodule
+
+// --------------------------------------------------------
+
+module \$allseq (Y);
+
+parameter WIDTH = 0;
+
+output [WIDTH-1:0] Y;
+
+assign Y = 'bx;
+
+endmodule
+
+// --------------------------------------------------------
+
module \$equiv (A, B, Y);
input A, B;
diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc
index 11ebe533..efb21475 100644
--- a/techlibs/common/synth.cc
+++ b/techlibs/common/synth.cc
@@ -29,7 +29,7 @@ struct SynthPass : public ScriptPass
{
SynthPass() : ScriptPass("synth", "generic synthesis script") { }
- virtual void help() YS_OVERRIDE
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -64,6 +64,9 @@ struct SynthPass : public ScriptPass
log(" -nordff\n");
log(" passed to 'memory'. prohibits merging of FFs into memory read ports\n");
log("\n");
+ log(" -noshare\n");
+ log(" do not run SAT-based resource sharing\n");
+ log("\n");
log(" -run <from_label>[:<to_label>]\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");
@@ -76,9 +79,9 @@ struct SynthPass : public ScriptPass
}
string top_module, fsm_opts, memory_opts;
- bool autotop, flatten, noalumacc, nofsm, noabc;
+ bool autotop, flatten, noalumacc, nofsm, noabc, noshare;
- virtual void clear_flags() YS_OVERRIDE
+ void clear_flags() YS_OVERRIDE
{
top_module.clear();
fsm_opts.clear();
@@ -89,9 +92,10 @@ struct SynthPass : public ScriptPass
noalumacc = false;
nofsm = false;
noabc = false;
+ noshare = false;
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
string run_from, run_to;
clear_flags();
@@ -142,6 +146,10 @@ struct SynthPass : public ScriptPass
memory_opts += " -nordff";
continue;
}
+ if (args[argidx] == "-noshare") {
+ noshare = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -157,7 +165,7 @@ struct SynthPass : public ScriptPass
log_pop();
}
- virtual void script() YS_OVERRIDE
+ void script() YS_OVERRIDE
{
if (check_label("begin"))
{
@@ -186,7 +194,8 @@ struct SynthPass : public ScriptPass
run("wreduce");
if (!noalumacc)
run("alumacc");
- run("share");
+ if (!noshare)
+ run("share");
run("opt");
if (!nofsm)
run("fsm" + fsm_opts);
diff --git a/techlibs/coolrunner2/Makefile.inc b/techlibs/coolrunner2/Makefile.inc
new file mode 100644
index 00000000..d62c9960
--- /dev/null
+++ b/techlibs/coolrunner2/Makefile.inc
@@ -0,0 +1,8 @@
+
+OBJS += techlibs/coolrunner2/synth_coolrunner2.o
+OBJS += techlibs/coolrunner2/coolrunner2_sop.o
+
+$(eval $(call add_share_file,share/coolrunner2,techlibs/coolrunner2/cells_latch.v))
+$(eval $(call add_share_file,share/coolrunner2,techlibs/coolrunner2/cells_sim.v))
+$(eval $(call add_share_file,share/coolrunner2,techlibs/coolrunner2/tff_extract.v))
+$(eval $(call add_share_file,share/coolrunner2,techlibs/coolrunner2/xc2_dff.lib))
diff --git a/techlibs/coolrunner2/cells_latch.v b/techlibs/coolrunner2/cells_latch.v
new file mode 100644
index 00000000..f1e19da3
--- /dev/null
+++ b/techlibs/coolrunner2/cells_latch.v
@@ -0,0 +1,19 @@
+module $_DLATCH_P_(input E, input D, output Q);
+ LDCP _TECHMAP_REPLACE_ (
+ .D(D),
+ .G(E),
+ .Q(Q),
+ .PRE(1'b0),
+ .CLR(1'b0)
+ );
+endmodule
+
+module $_DLATCH_N_(input E, input D, output Q);
+ LDCP_N _TECHMAP_REPLACE_ (
+ .D(D),
+ .G(E),
+ .Q(Q),
+ .PRE(1'b0),
+ .CLR(1'b0)
+ );
+endmodule
diff --git a/techlibs/coolrunner2/cells_sim.v b/techlibs/coolrunner2/cells_sim.v
new file mode 100644
index 00000000..562fb1ef
--- /dev/null
+++ b/techlibs/coolrunner2/cells_sim.v
@@ -0,0 +1,310 @@
+module IBUF(input I, output O);
+ assign O = I;
+endmodule
+
+module IOBUFE(input I, input E, output O, inout IO);
+ assign O = IO;
+ assign IO = E ? I : 1'bz;
+endmodule
+
+module ANDTERM(IN, IN_B, OUT);
+ parameter TRUE_INP = 0;
+ parameter COMP_INP = 0;
+
+ input [TRUE_INP-1:0] IN;
+ input [COMP_INP-1:0] IN_B;
+ output reg OUT;
+
+ integer i;
+
+ always @(*) begin
+ OUT = 1;
+ for (i = 0; i < TRUE_INP; i=i+1)
+ OUT = OUT & IN[i];
+ for (i = 0; i < COMP_INP; i=i+1)
+ OUT = OUT & ~IN_B[i];
+ end
+endmodule
+
+module ORTERM(IN, OUT);
+ parameter WIDTH = 0;
+
+ input [WIDTH-1:0] IN;
+ output reg OUT;
+
+ integer i;
+
+ always @(*) begin
+ OUT = 0;
+ for (i = 0; i < WIDTH; i=i+1) begin
+ OUT = OUT | IN[i];
+ end
+ end
+endmodule
+
+module MACROCELL_XOR(IN_PTC, IN_ORTERM, OUT);
+ parameter INVERT_OUT = 0;
+
+ input IN_PTC;
+ input IN_ORTERM;
+ output wire OUT;
+
+ wire xor_intermed;
+
+ assign OUT = INVERT_OUT ? ~xor_intermed : xor_intermed;
+ assign xor_intermed = IN_ORTERM ^ IN_PTC;
+endmodule
+
+module FDCP (C, PRE, CLR, D, Q);
+ parameter INIT = 0;
+
+ input C, PRE, CLR, D;
+ output reg Q;
+
+ initial begin
+ Q <= INIT;
+ end
+
+ always @(posedge C, posedge PRE, posedge CLR) begin
+ if (CLR == 1)
+ Q <= 0;
+ else if (PRE == 1)
+ Q <= 1;
+ else
+ Q <= D;
+ end
+endmodule
+
+module FDCP_N (C, PRE, CLR, D, Q);
+ parameter INIT = 0;
+
+ input C, PRE, CLR, D;
+ output reg Q;
+
+ initial begin
+ Q <= INIT;
+ end
+
+ always @(negedge C, posedge PRE, posedge CLR) begin
+ if (CLR == 1)
+ Q <= 0;
+ else if (PRE == 1)
+ Q <= 1;
+ else
+ Q <= D;
+ end
+endmodule
+
+module LDCP (G, PRE, CLR, D, Q);
+ parameter INIT = 0;
+
+ input G, PRE, CLR, D;
+ output reg Q;
+
+ initial begin
+ Q <= INIT;
+ end
+
+ always @* begin
+ if (CLR == 1)
+ Q <= 0;
+ else if (G == 1)
+ Q <= D;
+ else if (PRE == 1)
+ Q <= 1;
+ end
+endmodule
+
+module LDCP_N (G, PRE, CLR, D, Q);
+ parameter INIT = 0;
+
+ input G, PRE, CLR, D;
+ output reg Q;
+
+ initial begin
+ Q <= INIT;
+ end
+
+ always @* begin
+ if (CLR == 1)
+ Q <= 0;
+ else if (G == 0)
+ Q <= D;
+ else if (PRE == 1)
+ Q <= 1;
+ end
+endmodule
+
+module BUFG(I, O);
+ input I;
+ output O;
+
+ assign O = I;
+endmodule
+
+module BUFGSR(I, O);
+ parameter INVERT = 0;
+
+ input I;
+ output O;
+
+ assign O = INVERT ? ~I : I;
+endmodule
+
+module BUFGTS(I, O);
+ parameter INVERT = 0;
+
+ input I;
+ output O;
+
+ assign O = INVERT ? ~I : I;
+endmodule
+
+module FDDCP (C, PRE, CLR, D, Q);
+ parameter INIT = 0;
+
+ input C, PRE, CLR, D;
+ output reg Q;
+
+ initial begin
+ Q <= INIT;
+ end
+
+ always @(posedge C, negedge C, posedge PRE, posedge CLR) begin
+ if (CLR == 1)
+ Q <= 0;
+ else if (PRE == 1)
+ Q <= 1;
+ else
+ Q <= D;
+ end
+endmodule
+
+module FTCP (C, PRE, CLR, T, Q);
+ parameter INIT = 0;
+
+ input C, PRE, CLR, T;
+ output wire Q;
+ reg Q_;
+
+ initial begin
+ Q_ <= INIT;
+ end
+
+ always @(posedge C, posedge PRE, posedge CLR) begin
+ if (CLR == 1)
+ Q_ <= 0;
+ else if (PRE == 1)
+ Q_ <= 1;
+ else if (T == 1)
+ Q_ <= ~Q_;
+ end
+
+ assign Q = Q_;
+endmodule
+
+module FTCP_N (C, PRE, CLR, T, Q);
+ parameter INIT = 0;
+
+ input C, PRE, CLR, T;
+ output wire Q;
+ reg Q_;
+
+ initial begin
+ Q_ <= INIT;
+ end
+
+ always @(negedge C, posedge PRE, posedge CLR) begin
+ if (CLR == 1)
+ Q_ <= 0;
+ else if (PRE == 1)
+ Q_ <= 1;
+ else if (T == 1)
+ Q_ <= ~Q_;
+ end
+
+ assign Q = Q_;
+endmodule
+
+module FTDCP (C, PRE, CLR, T, Q);
+ parameter INIT = 0;
+
+ input C, PRE, CLR, T;
+ output wire Q;
+ reg Q_;
+
+ initial begin
+ Q_ <= INIT;
+ end
+
+ always @(posedge C, negedge C, posedge PRE, posedge CLR) begin
+ if (CLR == 1)
+ Q_ <= 0;
+ else if (PRE == 1)
+ Q_ <= 1;
+ else if (T == 1)
+ Q_ <= ~Q_;
+ end
+
+ assign Q = Q_;
+endmodule
+
+module FDCPE (C, PRE, CLR, D, Q, CE);
+ parameter INIT = 0;
+
+ input C, PRE, CLR, D, CE;
+ output reg Q;
+
+ initial begin
+ Q <= INIT;
+ end
+
+ always @(posedge C, posedge PRE, posedge CLR) begin
+ if (CLR == 1)
+ Q <= 0;
+ else if (PRE == 1)
+ Q <= 1;
+ else if (CE == 1)
+ Q <= D;
+ end
+endmodule
+
+module FDCPE_N (C, PRE, CLR, D, Q, CE);
+ parameter INIT = 0;
+
+ input C, PRE, CLR, D, CE;
+ output reg Q;
+
+ initial begin
+ Q <= INIT;
+ end
+
+ always @(negedge C, posedge PRE, posedge CLR) begin
+ if (CLR == 1)
+ Q <= 0;
+ else if (PRE == 1)
+ Q <= 1;
+ else if (CE == 1)
+ Q <= D;
+ end
+endmodule
+
+module FDDCPE (C, PRE, CLR, D, Q, CE);
+ parameter INIT = 0;
+
+ input C, PRE, CLR, D, CE;
+ output reg Q;
+
+ initial begin
+ Q <= INIT;
+ end
+
+ always @(posedge C, negedge C, posedge PRE, posedge CLR) begin
+ if (CLR == 1)
+ Q <= 0;
+ else if (PRE == 1)
+ Q <= 1;
+ else if (CE == 1)
+ Q <= D;
+ end
+endmodule
diff --git a/techlibs/coolrunner2/coolrunner2_sop.cc b/techlibs/coolrunner2/coolrunner2_sop.cc
new file mode 100644
index 00000000..48da0d8a
--- /dev/null
+++ b/techlibs/coolrunner2/coolrunner2_sop.cc
@@ -0,0 +1,320 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2017 Robert Ou <rqou@robertou.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
+
+struct Coolrunner2SopPass : public Pass {
+ Coolrunner2SopPass() : Pass("coolrunner2_sop", "break $sop cells into ANDTERM/ORTERM cells") { }
+ void help() YS_OVERRIDE
+ {
+ log("\n");
+ log(" coolrunner2_sop [options] [selection]\n");
+ log("\n");
+ log("Break $sop cells into ANDTERM/ORTERM cells.\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ log_header(design, "Executing COOLRUNNER2_SOP pass (break $sop cells into ANDTERM/ORTERM cells).\n");
+ extra_args(args, 1, design);
+
+ for (auto module : design->selected_modules())
+ {
+ pool<Cell*> cells_to_remove;
+ SigMap sigmap(module);
+
+ // Find all the $_NOT_ cells
+ dict<SigBit, tuple<SigBit, Cell*>> not_cells;
+ for (auto cell : module->selected_cells())
+ {
+ if (cell->type == "$_NOT_")
+ {
+ auto not_input = sigmap(cell->getPort("\\A")[0]);
+ auto not_output = sigmap(cell->getPort("\\Y")[0]);
+ not_cells[not_input] = tuple<SigBit, Cell*>(not_output, cell);
+ }
+ }
+
+ // Find wires that need to become special product terms
+ dict<SigBit, pool<tuple<Cell*, std::string>>> special_pterms_no_inv;
+ dict<SigBit, pool<tuple<Cell*, std::string>>> special_pterms_inv;
+ for (auto cell : module->selected_cells())
+ {
+ if (cell->type == "\\FDCP" || cell->type == "\\FDCP_N" || cell->type == "\\FDDCP" ||
+ cell->type == "\\FTCP" || cell->type == "\\FTCP_N" || cell->type == "\\FTDCP" ||
+ cell->type == "\\FDCPE" || cell->type == "\\FDCPE_N" || cell->type == "\\FDDCPE" ||
+ cell->type == "\\LDCP" || cell->type == "\\LDCP_N")
+ {
+ if (cell->hasPort("\\PRE"))
+ special_pterms_no_inv[sigmap(cell->getPort("\\PRE")[0])].insert(
+ tuple<Cell*, const char *>(cell, "\\PRE"));
+ if (cell->hasPort("\\CLR"))
+ special_pterms_no_inv[sigmap(cell->getPort("\\CLR")[0])].insert(
+ tuple<Cell*, const char *>(cell, "\\CLR"));
+ if (cell->hasPort("\\CE"))
+ special_pterms_no_inv[sigmap(cell->getPort("\\CE")[0])].insert(
+ tuple<Cell*, const char *>(cell, "\\CE"));
+
+ if (cell->hasPort("\\C"))
+ special_pterms_inv[sigmap(cell->getPort("\\C")[0])].insert(
+ tuple<Cell*, const char *>(cell, "\\C"));
+ if (cell->hasPort("\\G"))
+ special_pterms_inv[sigmap(cell->getPort("\\G")[0])].insert(
+ tuple<Cell*, const char *>(cell, "\\G"));
+ }
+ }
+
+ // Process $sop cells
+ for (auto cell : module->selected_cells())
+ {
+ if (cell->type == "$sop")
+ {
+ // Read the inputs/outputs/parameters of the $sop cell
+ auto sop_inputs = sigmap(cell->getPort("\\A"));
+ auto sop_output = sigmap(cell->getPort("\\Y"))[0];
+ auto sop_depth = cell->getParam("\\DEPTH").as_int();
+ auto sop_width = cell->getParam("\\WIDTH").as_int();
+ auto sop_table = cell->getParam("\\TABLE");
+
+ // Check for a $_NOT_ at the output
+ bool has_invert = false;
+ if (not_cells.count(sop_output))
+ {
+ auto not_cell = not_cells.at(sop_output);
+
+ has_invert = true;
+ sop_output = std::get<0>(not_cell);
+
+ // remove the $_NOT_ cell because it gets folded into the xor
+ cells_to_remove.insert(std::get<1>(not_cell));
+ }
+
+ // Check for special P-term usage
+ bool is_special_pterm = false;
+ bool special_pterm_can_invert = false;
+ if (special_pterms_no_inv.count(sop_output) || special_pterms_inv.count(sop_output))
+ {
+ is_special_pterm = true;
+ if (!special_pterms_no_inv[sop_output].size())
+ special_pterm_can_invert = true;
+ }
+
+ // Construct AND cells
+ pool<SigBit> intermed_wires;
+ for (int i = 0; i < sop_depth; i++) {
+ // Wire for the output
+ auto and_out = module->addWire(NEW_ID);
+ intermed_wires.insert(and_out);
+
+ // Signals for the inputs
+ pool<SigBit> and_in_true;
+ pool<SigBit> and_in_comp;
+ for (int j = 0; j < sop_width; j++)
+ {
+ if (sop_table[2 * (i * sop_width + j) + 0])
+ {
+ and_in_comp.insert(sop_inputs[j]);
+ }
+ if (sop_table[2 * (i * sop_width + j) + 1])
+ {
+ and_in_true.insert(sop_inputs[j]);
+ }
+ }
+
+ // Construct the cell
+ auto and_cell = module->addCell(NEW_ID, "\\ANDTERM");
+ and_cell->setParam("\\TRUE_INP", GetSize(and_in_true));
+ and_cell->setParam("\\COMP_INP", GetSize(and_in_comp));
+ and_cell->setPort("\\OUT", and_out);
+ and_cell->setPort("\\IN", and_in_true);
+ and_cell->setPort("\\IN_B", and_in_comp);
+ }
+
+ if (sop_depth == 1)
+ {
+ // If there is only one term, don't construct an OR cell. Directly construct the XOR gate
+ auto xor_cell = module->addCell(NEW_ID, "\\MACROCELL_XOR");
+ xor_cell->setParam("\\INVERT_OUT", has_invert);
+ xor_cell->setPort("\\IN_PTC", *intermed_wires.begin());
+ xor_cell->setPort("\\OUT", sop_output);
+
+ // Special P-term handling
+ if (is_special_pterm)
+ {
+ if (!has_invert || special_pterm_can_invert)
+ {
+ // Can connect the P-term directly to the special term sinks
+ for (auto x : special_pterms_inv[sop_output])
+ std::get<0>(x)->setPort(std::get<1>(x), *intermed_wires.begin());
+ for (auto x : special_pterms_no_inv[sop_output])
+ std::get<0>(x)->setPort(std::get<1>(x), *intermed_wires.begin());
+ }
+
+ if (has_invert)
+ {
+ if (special_pterm_can_invert)
+ {
+ log_assert(special_pterms_no_inv[sop_output].size() == 0);
+
+ for (auto x : special_pterms_inv[sop_output])
+ {
+ auto cell = std::get<0>(x);
+ // Need to invert the polarity of the cell
+ if (cell->type == "\\FDCP") cell->type = "\\FDCP_N";
+ else if (cell->type == "\\FDCP_N") cell->type = "\\FDCP";
+ else if (cell->type == "\\FTCP") cell->type = "\\FTCP_N";
+ else if (cell->type == "\\FTCP_N") cell->type = "\\FTCP";
+ else if (cell->type == "\\FDCPE") cell->type = "\\FDCPE_N";
+ else if (cell->type == "\\FDCPE_N") cell->type = "\\FDCPE";
+ else if (cell->type == "\\LDCP") cell->type = "\\LDCP_N";
+ else if (cell->type == "\\LDCP_N") cell->type = "\\LDCP";
+ else log_assert(!"Internal error! Bad cell type!");
+ }
+ }
+ else
+ {
+ // Need to construct a feed-through term
+ auto feedthrough_out = module->addWire(NEW_ID);
+ auto feedthrough_cell = module->addCell(NEW_ID, "\\ANDTERM");
+ feedthrough_cell->setParam("\\TRUE_INP", 1);
+ feedthrough_cell->setParam("\\COMP_INP", 0);
+ feedthrough_cell->setPort("\\OUT", feedthrough_out);
+ feedthrough_cell->setPort("\\IN", sop_output);
+ feedthrough_cell->setPort("\\IN_B", SigSpec());
+
+ for (auto x : special_pterms_inv[sop_output])
+ std::get<0>(x)->setPort(std::get<1>(x), feedthrough_out);
+ for (auto x : special_pterms_no_inv[sop_output])
+ std::get<0>(x)->setPort(std::get<1>(x), feedthrough_out);
+ }
+ }
+ }
+ }
+ else
+ {
+ // Wire from OR to XOR
+ auto or_to_xor_wire = module->addWire(NEW_ID);
+
+ // Construct the OR cell
+ auto or_cell = module->addCell(NEW_ID, "\\ORTERM");
+ or_cell->setParam("\\WIDTH", sop_depth);
+ or_cell->setPort("\\IN", intermed_wires);
+ or_cell->setPort("\\OUT", or_to_xor_wire);
+
+ // Construct the XOR cell
+ auto xor_cell = module->addCell(NEW_ID, "\\MACROCELL_XOR");
+ xor_cell->setParam("\\INVERT_OUT", has_invert);
+ xor_cell->setPort("\\IN_ORTERM", or_to_xor_wire);
+ xor_cell->setPort("\\OUT", sop_output);
+
+ if (is_special_pterm)
+ {
+ // Need to construct a feed-through term
+ auto feedthrough_out = module->addWire(NEW_ID);
+ auto feedthrough_cell = module->addCell(NEW_ID, "\\ANDTERM");
+ feedthrough_cell->setParam("\\TRUE_INP", 1);
+ feedthrough_cell->setParam("\\COMP_INP", 0);
+ feedthrough_cell->setPort("\\OUT", feedthrough_out);
+ feedthrough_cell->setPort("\\IN", sop_output);
+ feedthrough_cell->setPort("\\IN_B", SigSpec());
+
+ for (auto x : special_pterms_inv[sop_output])
+ std::get<0>(x)->setPort(std::get<1>(x), feedthrough_out);
+ for (auto x : special_pterms_no_inv[sop_output])
+ std::get<0>(x)->setPort(std::get<1>(x), feedthrough_out);
+ }
+ }
+
+ // Finally, remove the $sop cell
+ cells_to_remove.insert(cell);
+ }
+ }
+
+ // In some cases we can get a FF feeding straight into an FF. This is not possible, so we need to insert
+ // some AND/XOR cells in the middle to make it actually work.
+
+ // Find all the FF outputs
+ pool<SigBit> sig_fed_by_ff;
+ for (auto cell : module->selected_cells())
+ {
+ if (cell->type == "\\FDCP" || cell->type == "\\FDCP_N" || cell->type == "\\FDDCP" ||
+ cell->type == "\\LDCP" || cell->type == "\\LDCP_N" ||
+ cell->type == "\\FTCP" || cell->type == "\\FTCP_N" || cell->type == "\\FTDCP" ||
+ cell->type == "\\FDCPE" || cell->type == "\\FDCPE_N" || cell->type == "\\FDDCPE")
+ {
+ auto output = sigmap(cell->getPort("\\Q")[0]);
+ sig_fed_by_ff.insert(output);
+ }
+ }
+
+ // Look at all the FF inputs
+ for (auto cell : module->selected_cells())
+ {
+ if (cell->type == "\\FDCP" || cell->type == "\\FDCP_N" || cell->type == "\\FDDCP" ||
+ cell->type == "\\LDCP" || cell->type == "\\LDCP_N" ||
+ cell->type == "\\FTCP" || cell->type == "\\FTCP_N" || cell->type == "\\FTDCP" ||
+ cell->type == "\\FDCPE" || cell->type == "\\FDCPE_N" || cell->type == "\\FDDCPE")
+ {
+ SigBit input;
+ if (cell->type == "\\FTCP" || cell->type == "\\FTCP_N" || cell->type == "\\FTDCP")
+ input = sigmap(cell->getPort("\\T")[0]);
+ else
+ input = sigmap(cell->getPort("\\D")[0]);
+
+ if (sig_fed_by_ff[input])
+ {
+ printf("Buffering input to \"%s\"\n", cell->name.c_str());
+
+ auto and_to_xor_wire = module->addWire(NEW_ID);
+ auto xor_to_ff_wire = module->addWire(NEW_ID);
+
+ auto and_cell = module->addCell(NEW_ID, "\\ANDTERM");
+ and_cell->setParam("\\TRUE_INP", 1);
+ and_cell->setParam("\\COMP_INP", 0);
+ and_cell->setPort("\\OUT", and_to_xor_wire);
+ and_cell->setPort("\\IN", input);
+ and_cell->setPort("\\IN_B", SigSpec());
+
+ auto xor_cell = module->addCell(NEW_ID, "\\MACROCELL_XOR");
+ xor_cell->setParam("\\INVERT_OUT", false);
+ xor_cell->setPort("\\IN_PTC", and_to_xor_wire);
+ xor_cell->setPort("\\OUT", xor_to_ff_wire);
+
+ if (cell->type == "\\FTCP" || cell->type == "\\FTCP_N" || cell->type == "\\FTDCP")
+ cell->setPort("\\T", xor_to_ff_wire);
+ else
+ cell->setPort("\\D", xor_to_ff_wire);
+ }
+ }
+ }
+
+ // Actually do the removal now that we aren't iterating
+ for (auto cell : cells_to_remove)
+ {
+ module->remove(cell);
+ }
+ }
+ }
+} Coolrunner2SopPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/coolrunner2/synth_coolrunner2.cc b/techlibs/coolrunner2/synth_coolrunner2.cc
new file mode 100644
index 00000000..a5dac356
--- /dev/null
+++ b/techlibs/coolrunner2/synth_coolrunner2.cc
@@ -0,0 +1,202 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2017 Robert Ou <rqou@robertou.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/register.h"
+#include "kernel/celltypes.h"
+#include "kernel/rtlil.h"
+#include "kernel/log.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct SynthCoolrunner2Pass : public ScriptPass
+{
+ SynthCoolrunner2Pass() : ScriptPass("synth_coolrunner2", "synthesis for Xilinx Coolrunner-II CPLDs") { }
+
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" synth_coolrunner2 [options]\n");
+ log("\n");
+ log("This command runs synthesis for Coolrunner-II CPLDs. This work is experimental.\n");
+ log("It is intended to be used with https://github.com/azonenberg/openfpga as the\n");
+ log("place-and-route.\n");
+ log("\n");
+ log(" -top <module>\n");
+ log(" use the specified module as top module (default='top')\n");
+ log("\n");
+ log(" -json <file>\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 <from_label>:<to_label>\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, json_file;
+ bool flatten, retime;
+
+ void clear_flags() YS_OVERRIDE
+ {
+ top_opt = "-auto-top";
+ json_file = "";
+ flatten = true;
+ retime = false;
+ }
+
+ void execute(std::vector<std::string> 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] == "-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 comannd only operates on fully selected designs!\n");
+
+ log_header(design, "Executing SYNTH_COOLRUNNER2 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 +/coolrunner2/cells_sim.v");
+ run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
+ }
+
+ if (check_label("flatten", "(unless -noflatten)") && flatten)
+ {
+ run("proc");
+ run("flatten");
+ run("tribuf -logic");
+ }
+
+ if (check_label("coarse"))
+ {
+ run("synth -run coarse");
+ }
+
+ if (check_label("fine"))
+ {
+ run("opt -fast -full");
+ run("techmap");
+ run("techmap -map +/coolrunner2/cells_latch.v");
+ run("dfflibmap -prepare -liberty +/coolrunner2/xc2_dff.lib");
+ }
+
+ if (check_label("map_tff"))
+ {
+ // This is quite hacky. By telling abc that it can only use AND and XOR gates, abc will try and use XOR
+ // gates "whenever possible." This will hopefully cause toggle flip-flop structures to turn into an XOR
+ // connected to a D flip-flop. We then match on these and convert them into XC2 TFF cells.
+ run("abc -g AND,XOR");
+ run("clean");
+ run("extract -map +/coolrunner2/tff_extract.v");
+ }
+
+ if (check_label("map_pla"))
+ {
+ run("abc -sop -I 40 -P 56");
+ run("clean");
+ }
+
+ if (check_label("map_cells"))
+ {
+ run("dfflibmap -liberty +/coolrunner2/xc2_dff.lib");
+ run("dffinit -ff FDCP Q INIT");
+ run("dffinit -ff FDCP_N Q INIT");
+ run("dffinit -ff FTCP Q INIT");
+ run("dffinit -ff FTCP_N Q INIT");
+ run("dffinit -ff LDCP Q INIT");
+ run("dffinit -ff LDCP_N Q INIT");
+ run("coolrunner2_sop");
+ run("iopadmap -bits -inpad IBUF O:I -outpad IOBUFE I:IO -inoutpad IOBUFE O:IO -toutpad IOBUFE E:I:IO -tinoutpad IOBUFE E:O:I:IO");
+ run("attrmvcp -attr src -attr LOC t:IOBUFE n:*");
+ run("attrmvcp -attr src -attr LOC -driven t:IBUF n:*");
+ run("splitnets");
+ run("clean");
+ }
+
+ if (check_label("check"))
+ {
+ run("hierarchy -check");
+ run("stat");
+ run("check -noinit");
+ }
+
+ if (check_label("json"))
+ {
+ if (!json_file.empty() || help_mode)
+ run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));
+ }
+
+ log_pop();
+ }
+} SynthCoolrunner2Pass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/coolrunner2/tff_extract.v b/techlibs/coolrunner2/tff_extract.v
new file mode 100644
index 00000000..b4237dd1
--- /dev/null
+++ b/techlibs/coolrunner2/tff_extract.v
@@ -0,0 +1,41 @@
+module FTCP (C, PRE, CLR, T, Q);
+ input C, PRE, CLR, T;
+ output wire Q;
+
+ wire xorout;
+
+ $_XOR_ xorgate (
+ .A(T),
+ .B(Q),
+ .Y(xorout),
+ );
+
+ $_DFFSR_PPP_ dff (
+ .C(C),
+ .D(xorout),
+ .Q(Q),
+ .S(PRE),
+ .R(CLR),
+ );
+endmodule
+
+module FTCP_N (C, PRE, CLR, T, Q);
+ input C, PRE, CLR, T;
+ output wire Q;
+
+ wire xorout;
+
+ $_XOR_ xorgate (
+ .A(T),
+ .B(Q),
+ .Y(xorout),
+ );
+
+ $_DFFSR_NPP_ dff (
+ .C(C),
+ .D(xorout),
+ .Q(Q),
+ .S(PRE),
+ .R(CLR),
+ );
+endmodule
diff --git a/techlibs/coolrunner2/xc2_dff.lib b/techlibs/coolrunner2/xc2_dff.lib
new file mode 100644
index 00000000..b578493a
--- /dev/null
+++ b/techlibs/coolrunner2/xc2_dff.lib
@@ -0,0 +1,31 @@
+library(xc2_dff) {
+ cell(FDCP) {
+ area: 1;
+ ff("IQ", "IQN") { clocked_on: C;
+ next_state: D;
+ clear: "CLR";
+ preset: "PRE"; }
+ pin(C) { direction: input;
+ clock: true; }
+ pin(D) { direction: input; }
+ pin(Q) { direction: output;
+ function: "IQ"; }
+ pin(CLR) { direction: input; }
+ pin(PRE) { direction: input; }
+ }
+
+ cell(FDCP_N) {
+ area: 1;
+ ff("IQ", "IQN") { clocked_on: "!C";
+ next_state: D;
+ clear: "CLR";
+ preset: "PRE"; }
+ pin(C) { direction: input;
+ clock: true; }
+ pin(D) { direction: input; }
+ pin(Q) { direction: output;
+ function: "IQ"; }
+ pin(CLR) { direction: input; }
+ pin(PRE) { direction: input; }
+ }
+}
diff --git a/techlibs/easic/Makefile.inc b/techlibs/easic/Makefile.inc
new file mode 100644
index 00000000..fb05a8a8
--- /dev/null
+++ b/techlibs/easic/Makefile.inc
@@ -0,0 +1,3 @@
+
+OBJS += techlibs/easic/synth_easic.o
+
diff --git a/techlibs/easic/synth_easic.cc b/techlibs/easic/synth_easic.cc
new file mode 100644
index 00000000..b5ed93be
--- /dev/null
+++ b/techlibs/easic/synth_easic.cc
@@ -0,0 +1,188 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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 SynthEasicPass : public ScriptPass
+{
+ SynthEasicPass() : ScriptPass("synth_easic", "synthesis for eASIC platform") { }
+
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" synth_easic [options]\n");
+ log("\n");
+ log("This command runs synthesis for eASIC platform.\n");
+ log("\n");
+ log(" -top <module>\n");
+ log(" use the specified module as top module\n");
+ log("\n");
+ log(" -vlog <file>\n");
+ log(" write the design to the specified structural Verilog file. writing of\n");
+ log(" an output file is omitted if this parameter is not specified.\n");
+ log("\n");
+ log(" -etools <path>\n");
+ log(" set path to the eTools installation. (default=/opt/eTools)\n");
+ log("\n");
+ log(" -run <from_label>:<to_label>\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, vlog_file, etools_path;
+ bool flatten, retime;
+
+ void clear_flags() YS_OVERRIDE
+ {
+ top_opt = "-auto-top";
+ vlog_file = "";
+ etools_path = "/opt/eTools";
+ flatten = true;
+ retime = false;
+ }
+
+ void execute(std::vector<std::string> 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] == "-vlog" && argidx+1 < args.size()) {
+ vlog_file = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-etools" && argidx+1 < args.size()) {
+ etools_path = 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 comannd only operates on fully selected designs!\n");
+
+ log_header(design, "Executing SYNTH_EASIC pass.\n");
+ log_push();
+
+ run_script(design, run_from, run_to);
+
+ log_pop();
+ }
+
+ void script() YS_OVERRIDE
+ {
+ string phys_clk_lib = stringf("%s/data_ruby28/design_libs/logical/timing/gp/n3x_phys_clk_0v893ff125c.lib", etools_path.c_str());
+ string logic_lut_lib = stringf("%s/data_ruby28/design_libs/logical/timing/gp/n3x_logic_lut_0v893ff125c.lib", etools_path.c_str());
+
+ if (check_label("begin"))
+ {
+ run(stringf("read_liberty -lib %s", help_mode ? "<etools_phys_clk_lib>" : phys_clk_lib.c_str()));
+ run(stringf("read_liberty -lib %s", help_mode ? "<etools_logic_lut_lib>" : logic_lut_lib.c_str()));
+ run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
+ }
+
+ if (flatten && check_label("flatten", "(unless -noflatten)"))
+ {
+ run("proc");
+ run("flatten");
+ }
+
+ 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");
+ run("opt -fast");
+ if (retime || help_mode) {
+ run("abc -dff", " (only if -retime)");
+ run("opt_clean", "(only if -retime)");
+ }
+ }
+
+ if (check_label("map"))
+ {
+ run(stringf("dfflibmap -liberty %s", help_mode ? "<etools_phys_clk_lib>" : phys_clk_lib.c_str()));
+ run(stringf("abc -liberty %s", help_mode ? "<etools_logic_lut_lib>" : logic_lut_lib.c_str()));
+ run("opt_clean");
+ }
+
+ if (check_label("check"))
+ {
+ run("hierarchy -check");
+ run("stat");
+ run("check -noinit");
+ }
+
+ if (check_label("vlog"))
+ {
+ if (!vlog_file.empty() || help_mode)
+ run(stringf("write_verilog -noexpr -attr2comment %s", help_mode ? "<file-name>" : vlog_file.c_str()));
+ }
+ }
+} SynthEasicPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/ecp5/Makefile.inc b/techlibs/ecp5/Makefile.inc
new file mode 100644
index 00000000..9d324734
--- /dev/null
+++ b/techlibs/ecp5/Makefile.inc
@@ -0,0 +1,8 @@
+
+OBJS += techlibs/ecp5/synth_ecp5.o
+
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_sim.v))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/drams_map.v))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/dram.txt))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/arith_map.v))
diff --git a/techlibs/ecp5/arith_map.v b/techlibs/ecp5/arith_map.v
new file mode 100644
index 00000000..1094c5f8
--- /dev/null
+++ b/techlibs/ecp5/arith_map.v
@@ -0,0 +1,79 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2018 David Shah <dave@ds0.me>
+ *
+ * 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_ecp5_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 [Y_WIDTH-1:0] 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));
+
+ function integer round_up2;
+ input integer N;
+ begin
+ round_up2 = ((N + 1) / 2) * 2;
+ end
+ endfunction
+
+ localparam Y_WIDTH2 = round_up2(Y_WIDTH);
+
+ wire [Y_WIDTH2-1:0] AA = A_buf;
+ wire [Y_WIDTH2-1:0] BB = BI ? ~B_buf : B_buf;
+ wire [Y_WIDTH2-1:0] C = {CO, CI};
+ wire [Y_WIDTH2-1:0] FCO, Y1;
+
+ genvar i;
+ generate for (i = 0; i < Y_WIDTH2; i = i + 2) begin:slice
+ CCU2C #(
+ .INIT0(16'b0110011010101010),
+ .INIT1(16'b0110011010101010),
+ .INJECT1_0("NO"),
+ .INJECT1_1("NO")
+ ) ccu2c_i (
+ .CIN(C[i]),
+ .A0(AA[i]), .B0(BB[i]), .C0(1'b0), .D0(1'b1),
+ .A1(AA[i+1]), .B1(BB[i+1]), .C1(1'b0), .D1(1'b1),
+ .S0(Y[i]), .S1(Y1[i]),
+ .COUT(FCO[i])
+ );
+
+ assign CO[i] = (AA[i] && BB[i]) || (C[i] && (AA[i] || BB[i]));
+ if (i+1 < Y_WIDTH) begin
+ assign CO[i+1] = FCO[i];
+ assign Y[i+1] = Y1[i];
+ end
+ end endgenerate
+
+ assign X = AA ^ BB;
+endmodule
diff --git a/techlibs/ecp5/cells_map.v b/techlibs/ecp5/cells_map.v
new file mode 100644
index 00000000..48162a4d
--- /dev/null
+++ b/techlibs/ecp5/cells_map.v
@@ -0,0 +1,135 @@
+module \$_DFF_N_ (input D, C, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
+module \$_DFF_P_ (input D, C, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
+
+module \$_DFFE_NN_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("INV"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
+module \$_DFFE_PN_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("INV"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
+
+module \$_DFFE_NP_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
+module \$_DFFE_PP_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
+
+module \$_DFF_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$_DFF_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$_DFF_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$_DFF_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+
+module \$_DFF_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$_DFF_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$_DFF_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$_DFF_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+
+module \$__DFFS_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFS_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFS_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFS_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+
+module \$__DFFS_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFS_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFS_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFS_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+
+module \$__DFFE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+
+module \$__DFFE_NP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+
+module \$__DFFSE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFSE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFSE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFSE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+
+module \$__DFFSE_NP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFSE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFSE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFSE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .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
+ LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y),
+ .A(A[0]), .B(1'b0), .C(1'b0), .D(1'b0));
+ end else
+ if (WIDTH == 2) begin
+ LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y),
+ .A(A[0]), .B(A[1]), .C(1'b0), .D(1'b0));
+ end else
+ if (WIDTH == 3) begin
+ LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(1'b0));
+ end else
+ if (WIDTH == 4) begin
+ LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+ `ifndef NO_PFUMUX
+ end else
+ if (WIDTH == 5) begin
+ wire f0, f1;
+ LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+ LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+ PFUMX mux5(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(Y));
+ end else
+ if (WIDTH == 6) begin
+ wire f0, f1, f2, f3, g0, g1;
+ LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+ LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+
+ LUT4 #(.INIT(LUT[47:32])) lut2 (.Z(f2),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+ LUT4 #(.INIT(LUT[63:48])) lut3 (.Z(f3),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+
+ PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(g0));
+ PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[4]), .Z(g1));
+ L6MUX21 mux6 (.D0(g0), .D1(g1), .SD(A[5]), .Z(Y));
+ end else
+ if (WIDTH == 7) begin
+ wire f0, f1, f2, f3, f4, f5, f6, f7, g0, g1, g2, g3, h0, h1;
+ LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+ LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+
+ LUT4 #(.INIT(LUT[47:32])) lut2 (.Z(f2),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+ LUT4 #(.INIT(LUT[63:48])) lut3 (.Z(f3),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+
+ LUT4 #(.INIT(LUT[79:64])) lut4 (.Z(f4),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+ LUT4 #(.INIT(LUT[95:80])) lut5 (.Z(f5),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+
+ LUT4 #(.INIT(LUT[111: 96])) lut6 (.Z(f6),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+ LUT4 #(.INIT(LUT[127:112])) lut7 (.Z(f7),
+ .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
+
+ PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(g0));
+ PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[4]), .Z(g1));
+ PFUMX mux52(.ALUT(f5), .BLUT(f4), .C0(A[4]), .Z(g2));
+ PFUMX mux53(.ALUT(f7), .BLUT(f6), .C0(A[4]), .Z(g3));
+ L6MUX21 mux60 (.D0(g0), .D1(g1), .SD(A[5]), .Z(h0));
+ L6MUX21 mux61 (.D0(g2), .D1(g3), .SD(A[5]), .Z(h1));
+ L6MUX21 mux7 (.D0(h0), .D1(h1), .SD(A[6]), .Z(Y));
+ `endif
+ end else begin
+ wire _TECHMAP_FAIL_ = 1;
+ end
+ endgenerate
+endmodule
+`endif
diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v
new file mode 100644
index 00000000..1700694e
--- /dev/null
+++ b/techlibs/ecp5/cells_sim.v
@@ -0,0 +1,448 @@
+// ---------------------------------------
+
+module LUT4(input A, B, C, D, output Z);
+ parameter [15:0] INIT = 16'h0000;
+ 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 Z = A ? s1[1] : s1[0];
+endmodule
+
+// ---------------------------------------
+
+module L6MUX21 (input D0, D1, SD, output Z);
+ assign Z = SD ? D1 : D0;
+endmodule
+
+// ---------------------------------------
+
+module CCU2C(input CIN, A0, B0, C0, D0, A1, B1, C1, D1,
+ output S0, S1, COUT);
+
+ parameter [15:0] INIT0 = 16'h0000;
+ parameter [15:0] INIT1 = 16'h0000;
+ parameter INJECT1_0 = "YES";
+ parameter INJECT1_1 = "YES";
+
+ // First half
+ wire LUT4_0, LUT2_0;
+ LUT4 #(.INIT(INIT0)) lut4_0(.A(A0), .B(B0), .C(C0), .D(D0), .Z(LUT4_0));
+ LUT2 #(.INIT(INIT0[3:0])) lut2_0(.A(A0), .B(B0), .Z(LUT2_0));
+
+ wire gated_cin_0 = (INJECT1_0 == "YES") ? 1'b0 : CIN;
+ assign S0 = LUT4_0 ^ gated_cin_0;
+
+ wire gated_lut2_0 = (INJECT1_0 == "YES") ? 1'b0 : LUT2_0;
+ wire cout_0 = (~LUT4_0 & gated_lut2_0) | (LUT4_0 & CIN);
+
+ // Second half
+ wire LUT4_1, LUT2_1;
+ LUT4 #(.INIT(INIT1)) lut4_1(.A(A1), .B(B1), .C(C1), .D(D1), .Z(LUT4_1));
+ LUT2 #(.INIT(INIT1[3:0])) lut2_1(.A(A1), .B(B1), .Z(LUT2_1));
+
+ wire gated_cin_1 = (INJECT1_1 == "YES") ? 1'b0 : cout_0;
+ assign S1 = LUT4_1 ^ gated_cin_1;
+
+ wire gated_lut2_1 = (INJECT1_1 == "YES") ? 1'b0 : LUT2_1;
+ assign COUT = (~LUT4_1 & gated_lut2_1) | (LUT4_1 & cout_0);
+
+endmodule
+
+// ---------------------------------------
+
+module TRELLIS_RAM16X2 (
+ input DI0, DI1,
+ input WAD0, WAD1, WAD2, WAD3,
+ input WRE, WCK,
+ input RAD0, RAD1, RAD2, RAD3,
+ output DO0, DO1
+);
+ parameter WCKMUX = "WCK";
+ parameter WREMUX = "WRE";
+ parameter INITVAL_0 = 16'h0000;
+ parameter INITVAL_1 = 16'h0000;
+
+ reg [1:0] mem[15:0];
+
+ integer i;
+ initial begin
+ for (i = 0; i < 16; i = i + 1)
+ mem[i] <= {INITVAL_1[i], INITVAL_0[i]};
+ end
+
+ wire muxwck = (WCKMUX == "INV") ? ~WCK : WCK;
+
+ reg muxwre;
+ always @(*)
+ case (WREMUX)
+ "1": muxwre = 1'b1;
+ "0": muxwre = 1'b0;
+ "INV": muxwre = ~WRE;
+ default: muxwre = WRE;
+ endcase
+
+
+ always @(posedge muxwck)
+ if (muxwre)
+ mem[{WAD3, WAD2, WAD1, WAD0}] <= {DI1, DI0};
+
+ assign {DO1, DO0} = mem[{RAD3, RAD2, RAD1, RAD0}];
+endmodule
+
+// ---------------------------------------
+
+module PFUMX (input ALUT, BLUT, C0, output Z);
+ assign Z = C0 ? ALUT : BLUT;
+endmodule
+
+// ---------------------------------------
+
+module TRELLIS_DPR16X4 (
+ input [3:0] DI,
+ input [3:0] WAD,
+ input WRE, WCK,
+ input [3:0] RAD,
+ output [3:0] DO
+);
+ parameter WCKMUX = "WCK";
+ parameter WREMUX = "WRE";
+ parameter [63:0] INITVAL = 64'h0000000000000000;
+
+ reg [3:0] mem[15:0];
+
+ integer i;
+ initial begin
+ for (i = 0; i < 16; i = i + 1)
+ mem[i] <= {INITVAL[i+3], INITVAL[i+2], INITVAL[i+1], INITVAL[i]};
+ end
+
+ wire muxwck = (WCKMUX == "INV") ? ~WCK : WCK;
+
+ reg muxwre;
+ always @(*)
+ case (WREMUX)
+ "1": muxwre = 1'b1;
+ "0": muxwre = 1'b0;
+ "INV": muxwre = ~WRE;
+ default: muxwre = WRE;
+ endcase
+
+ always @(posedge muxwck)
+ if (muxwre)
+ mem[WAD] <= DI;
+
+ assign DO = mem[RAD];
+endmodule
+
+// ---------------------------------------
+
+module DPR16X4C (
+ input [3:0] DI,
+ input WCK, WRE,
+ input [3:0] RAD,
+ input [3:0] WAD,
+ output [3:0] DO
+);
+ // For legacy Lattice compatibility, INITIVAL is a hex
+ // string rather than a numeric parameter
+ parameter INITVAL = "0x0000000000000000";
+
+ function [63:0] convert_initval;
+ input [143:0] hex_initval;
+ reg done;
+ reg [63:0] temp;
+ reg [7:0] char;
+ integer i;
+ begin
+ done = 1'b0;
+ temp = 0;
+ for (i = 0; i < 16; i = i + 1) begin
+ if (!done) begin
+ char = hex_initval[8*i +: 8];
+ if (char == "x") begin
+ done = 1'b1;
+ end else begin
+ if (char >= "0" && char <= "9")
+ temp[4*i +: 4] = char - "0";
+ else if (char >= "A" && char <= "F")
+ temp[4*i +: 4] = 10 + char - "A";
+ else if (char >= "a" && char <= "f")
+ temp[4*i +: 4] = 10 + char - "a";
+ end
+ end
+ end
+ convert_initval = temp;
+ end
+ endfunction
+
+ localparam conv_initval = convert_initval(INITVAL);
+
+ reg [3:0] ram[0:15];
+ integer i;
+ initial begin
+ for (i = 0; i < 15; i = i + 1) begin
+ ram[i] <= conv_initval[4*i +: 4];
+ end
+ end
+
+ always @(posedge WCK)
+ if (WRE)
+ ram[WAD] <= DI;
+
+ assign DO = ram[RAD];
+
+endmodule
+
+// ---------------------------------------
+
+module LUT2(input A, B, output Z);
+ parameter [3:0] INIT = 4'h0;
+ wire [1:0] s1 = B ? INIT[ 3:2] : INIT[1:0];
+ assign Z = A ? s1[1] : s1[0];
+endmodule
+
+// ---------------------------------------
+
+module TRELLIS_FF(input CLK, LSR, CE, DI, output reg Q);
+ parameter GSR = "ENABLED";
+ parameter [127:0] CEMUX = "1";
+ parameter CLKMUX = "CLK";
+ parameter LSRMUX = "LSR";
+ parameter SRMODE = "LSR_OVER_CE";
+ parameter REGSET = "RESET";
+
+ reg muxce;
+ always @(*)
+ case (CEMUX)
+ "1": muxce = 1'b1;
+ "0": muxce = 1'b0;
+ "INV": muxce = ~CE;
+ default: muxce = CE;
+ endcase
+
+ wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR;
+ wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK;
+
+ localparam srval = (REGSET == "SET") ? 1'b1 : 1'b0;
+
+ initial Q = srval;
+
+ generate
+ if (SRMODE == "ASYNC") begin
+ always @(posedge muxclk, posedge muxlsr)
+ if (muxlsr)
+ Q <= srval;
+ else if (muxce)
+ Q <= DI;
+ end else begin
+ always @(posedge muxclk)
+ if (muxlsr)
+ Q <= srval;
+ else if (muxce)
+ Q <= DI;
+ end
+ endgenerate
+endmodule
+
+// ---------------------------------------
+
+module OBZ(input I, T, output O);
+assign O = T ? 1'bz : I;
+endmodule
+
+// ---------------------------------------
+
+module IB(input I, output O);
+assign O = I;
+endmodule
+
+// ---------------------------------------
+
+module TRELLIS_IO(
+ inout B,
+ input I,
+ input T,
+ output O
+);
+ parameter DIR = "INPUT";
+
+ generate
+ if (DIR == "INPUT") begin
+ assign B = 1'bz;
+ assign O = B;
+ end else if (DIR == "OUTPUT") begin
+ assign B = T ? 1'bz : I;
+ assign O = 1'bx;
+ end else if (DIR == "INOUT") begin
+ assign B = T ? 1'bz : I;
+ assign O = B;
+ end else begin
+ ERROR_UNKNOWN_IO_MODE error();
+ end
+ endgenerate
+
+endmodule
+
+// ---------------------------------------
+
+module OB(input I, output O);
+assign O = I;
+endmodule
+
+// ---------------------------------------
+
+module BB(input I, T, output O, inout B);
+assign B = T ? 1'bz : I;
+assign O = B;
+endmodule
+
+// ---------------------------------------
+
+module INV(input A, output Z);
+ assign Z = !A;
+endmodule
+
+// ---------------------------------------
+
+module TRELLIS_SLICE(
+ input A0, B0, C0, D0,
+ input A1, B1, C1, D1,
+ input M0, M1,
+ input FCI, FXA, FXB,
+
+ input CLK, LSR, CE,
+ input DI0, DI1,
+
+ input WD0, WD1,
+ input WAD0, WAD1, WAD2, WAD3,
+ input WRE, WCK,
+
+ output F0, Q0,
+ output F1, Q1,
+ output FCO, OFX0, OFX1,
+
+ output WDO0, WDO1, WDO2, WDO3,
+ output WADO0, WADO1, WADO2, WADO3
+);
+
+ parameter MODE = "LOGIC";
+ parameter GSR = "ENABLED";
+ parameter SRMODE = "LSR_OVER_CE";
+ parameter [127:0] CEMUX = "1";
+ parameter CLKMUX = "CLK";
+ parameter LSRMUX = "LSR";
+ parameter LUT0_INITVAL = 16'h0000;
+ parameter LUT1_INITVAL = 16'h0000;
+ parameter REG0_SD = "0";
+ parameter REG1_SD = "0";
+ parameter REG0_REGSET = "RESET";
+ parameter REG1_REGSET = "RESET";
+ parameter [127:0] CCU2_INJECT1_0 = "NO";
+ parameter [127:0] CCU2_INJECT1_1 = "NO";
+ parameter WREMUX = "WRE";
+
+ function [15:0] permute_initval;
+ input [15:0] initval;
+ integer i;
+ begin
+ for (i = 0; i < 16; i = i + 1) begin
+ permute_initval[{i[0], i[2], i[1], i[3]}] = initval[i];
+ end
+ end
+ endfunction
+
+ generate
+ if (MODE == "LOGIC") begin
+ // LUTs
+ LUT4 #(
+ .INIT(LUT0_INITVAL)
+ ) lut4_0 (
+ .A(A0), .B(B0), .C(C0), .D(D0),
+ .Z(F0)
+ );
+ LUT4 #(
+ .INIT(LUT1_INITVAL)
+ ) lut4_1 (
+ .A(A1), .B(B1), .C(C1), .D(D1),
+ .Z(F1)
+ );
+ // LUT expansion muxes
+ PFUMX lut5_mux (.ALUT(F1), .BLUT(F0), .C0(M0), .Z(OFX0));
+ L6MUX21 lutx_mux (.D0(FXA), .D1(FXB), .SD(M1), .Z(OFX1));
+ end else if (MODE == "CCU2") begin
+ CCU2C #(
+ .INIT0(LUT0_INITVAL),
+ .INIT1(LUT1_INITVAL),
+ .INJECT1_0(CCU2_INJECT1_0),
+ .INJECT1_1(CCU2_INJECT1_1)
+ ) ccu2c_i (
+ .CIN(FCI),
+ .A0(A0), .B0(B0), .C0(C0), .D0(D0),
+ .A1(A1), .B1(B1), .C1(C1), .D1(D1),
+ .S0(F0), .S1(F1),
+ .COUT(FCO)
+ );
+ end else if (MODE == "RAMW") begin
+ assign WDO0 = C1;
+ assign WDO1 = A1;
+ assign WDO2 = D1;
+ assign WDO3 = B1;
+ assign WADO0 = D0;
+ assign WADO1 = B0;
+ assign WADO2 = C0;
+ assign WADO3 = A0;
+ end else if (MODE == "DPRAM") begin
+ TRELLIS_RAM16X2 #(
+ .INITVAL_0(permute_initval(LUT0_INITVAL)),
+ .INITVAL_1(permute_initval(LUT1_INITVAL)),
+ .WREMUX(WREMUX)
+ ) ram_i (
+ .DI0(WD0), .DI1(WD1),
+ .WAD0(WAD0), .WAD1(WAD1), .WAD2(WAD2), .WAD3(WAD3),
+ .WRE(WRE), .WCK(WCK),
+ .RAD0(D0), .RAD1(B0), .RAD2(C0), .RAD3(A0),
+ .DO0(F0), .DO1(F1)
+ );
+ // TODO: confirm RAD and INITVAL ordering
+ // DPRAM mode contract?
+ always @(*) begin
+ assert(A0==A1);
+ assert(B0==B1);
+ assert(C0==C1);
+ assert(D0==D1);
+ end
+ end else begin
+ ERROR_UNKNOWN_SLICE_MODE error();
+ end
+ endgenerate
+
+ // FF input selection muxes
+ wire muxdi0 = (REG0_SD == "1") ? DI0 : M0;
+ wire muxdi1 = (REG1_SD == "1") ? DI1 : M1;
+ // Flipflops
+ TRELLIS_FF #(
+ .GSR(GSR),
+ .CEMUX(CEMUX),
+ .CLKMUX(CLKMUX),
+ .LSRMUX(LSRMUX),
+ .SRMODE(SRMODE),
+ .REGSET(REG0_REGSET)
+ ) ff_0 (
+ .CLK(CLK), .LSR(LSR), .CE(CE),
+ .DI(muxdi0),
+ .Q(Q0)
+ );
+ TRELLIS_FF #(
+ .GSR(GSR),
+ .CEMUX(CEMUX),
+ .CLKMUX(CLKMUX),
+ .LSRMUX(LSRMUX),
+ .SRMODE(SRMODE),
+ .REGSET(REG1_REGSET)
+ ) ff_1 (
+ .CLK(CLK), .LSR(LSR), .CE(CE),
+ .DI(muxdi1),
+ .Q(Q1)
+ );
+endmodule
+
diff --git a/techlibs/ecp5/dram.txt b/techlibs/ecp5/dram.txt
new file mode 100644
index 00000000..b3252fa9
--- /dev/null
+++ b/techlibs/ecp5/dram.txt
@@ -0,0 +1,16 @@
+bram $__TRELLIS_DPR16X4
+ init 1
+ abits 4
+ dbits 4
+ groups 2
+ ports 1 1
+ wrmode 0 1
+ enable 0 1
+ transp 0 0
+ clocks 0 1
+ clkpol 0 2
+endbram
+
+match $__TRELLIS_DPR16X4
+ make_outreg
+endmatch
diff --git a/techlibs/ecp5/drams_map.v b/techlibs/ecp5/drams_map.v
new file mode 100644
index 00000000..3b3de831
--- /dev/null
+++ b/techlibs/ecp5/drams_map.v
@@ -0,0 +1,28 @@
+module \$__TRELLIS_DPR16X4 (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
+ parameter [63:0] INIT = 64'bx;
+ parameter CLKPOL2 = 1;
+ input CLK1;
+
+ input [3:0] A1ADDR;
+ output [3:0] A1DATA;
+
+ input [3:0] B1ADDR;
+ input [3:0] B1DATA;
+ input B1EN;
+
+ localparam WCKMUX = CLKPOL2 ? "WCK" : "INV";
+
+ TRELLIS_DPR16X4 #(
+ .INITVAL(INIT),
+ .WCKMUX(WCKMUX),
+ .WREMUX("WRE")
+ ) _TECHMAP_REPLACE_ (
+ .RAD(A1ADDR),
+ .DO(A1DATA),
+
+ .WAD(B1ADDR),
+ .DI(B1DATA),
+ .WCK(CLK1),
+ .WRE(B1EN)
+ );
+endmodule
diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc
new file mode 100644
index 00000000..a13dd8d4
--- /dev/null
+++ b/techlibs/ecp5/synth_ecp5.cc
@@ -0,0 +1,331 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2018 Clifford Wolf <dave@ds0.me>
+ *
+ * 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 SynthEcp5Pass : public ScriptPass
+{
+ SynthEcp5Pass() : ScriptPass("synth_ecp5", "synthesis for ECP5 FPGAs") { }
+
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" synth_ecp5 [options]\n");
+ log("\n");
+ log("This command runs synthesis for ECP5 FPGAs.\n");
+ log("\n");
+ log(" -top <module>\n");
+ log(" use the specified module as top module\n");
+ log("\n");
+ log(" -blif <file>\n");
+ log(" write the design to the specified BLIF file. writing of an output file\n");
+ log(" is omitted if this parameter is not specified.\n");
+ log("\n");
+ log(" -edif <file>\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 <file>\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 <from_label>:<to_label>\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(" -noccu2\n");
+ log(" do not use CCU2 cells in output netlist\n");
+ log("\n");
+ log(" -nodffe\n");
+ log(" do not use flipflops with CE in output netlist\n");
+ log("\n");
+ log(" -nobram\n");
+ log(" do not use BRAM cells in output netlist\n");
+ log("\n");
+ log(" -nodram\n");
+ log(" do not use distributed RAM cells in output netlist\n");
+ log("\n");
+ log(" -nomux\n");
+ log(" do not use PFU muxes to implement LUTs larger than LUT4s\n");
+ log("\n");
+ log(" -abc2\n");
+ log(" run two passes of 'abc' for slightly improved logic density\n");
+ log("\n");
+ log(" -vpr\n");
+ log(" generate an output netlist (and BLIF file) suitable for VPR\n");
+ log(" (this feature is experimental and incomplete)\n");
+ log("\n");
+ log("\n");
+ log("The following commands are executed by this synthesis command:\n");
+ help_script();
+ log("\n");
+ }
+
+ string top_opt, blif_file, edif_file, json_file;
+ bool noccu2, nodffe, nobram, nodram, nomux, flatten, retime, abc2, vpr;
+
+ void clear_flags() YS_OVERRIDE
+ {
+ top_opt = "-auto-top";
+ blif_file = "";
+ edif_file = "";
+ json_file = "";
+ noccu2 = false;
+ nodffe = false;
+ nobram = false;
+ nodram = false;
+ nomux = false;
+ flatten = true;
+ retime = false;
+ abc2 = false;
+ vpr = false;
+ }
+
+ void execute(std::vector<std::string> 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] == "-blif" && argidx+1 < args.size()) {
+ blif_file = 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] == "-flatten") {
+ flatten = true;
+ continue;
+ }
+ if (args[argidx] == "-noflatten") {
+ flatten = false;
+ continue;
+ }
+ if (args[argidx] == "-retime") {
+ retime = true;
+ continue;
+ }
+ if (args[argidx] == "-noccu2") {
+ noccu2 = true;
+ continue;
+ }
+ if (args[argidx] == "-nodffe") {
+ nodffe = true;
+ continue;
+ }
+ if (args[argidx] == "-nobram") {
+ nobram = true;
+ continue;
+ }
+ if (args[argidx] == "-nodram") {
+ nodram = true;
+ continue;
+ }
+ if (args[argidx] == "-nomux") {
+ nomux = true;
+ continue;
+ }
+ if (args[argidx] == "-abc2") {
+ abc2 = true;
+ continue;
+ }
+ if (args[argidx] == "-vpr") {
+ vpr = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ if (!design->full_selection())
+ log_cmd_error("This comannd only operates on fully selected designs!\n");
+
+ log_header(design, "Executing SYNTH_ECP5 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 +/ecp5/cells_sim.v");
+ run(stringf("hierarchy -check %s", help_mode ? "-top <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 (!nobram && check_label("bram", "(skip if -nobram)"))
+ {
+ //TODO
+#if 0
+ run("memory_bram -rules +/ecp5/brams.txt");
+ run("techmap -map +/ecp5/brams_map.v");
+#endif
+ }
+
+ if (!nodram && check_label("dram", "(skip if -nodram)"))
+ {
+ run("memory_bram -rules +/ecp5/dram.txt");
+ run("techmap -map +/ecp5/drams_map.v");
+ }
+
+ if (check_label("fine"))
+ {
+ run("opt -fast -mux_undef -undriven -fine");
+ run("memory_map");
+ run("opt -undriven -fine");
+ if (noccu2)
+ run("techmap");
+ else
+ run("techmap -map +/techmap.v -map +/ecp5/arith_map.v");
+ if (retime || help_mode)
+ run("abc -dff", "(only if -retime)");
+ }
+
+ if (check_label("map_ffs"))
+ {
+ run("dffsr2dff");
+ run("dff2dffs");
+ run("opt_clean");
+ if (!nodffe)
+ run("dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*");
+ run("techmap -D NO_LUT -map +/ecp5/cells_map.v");
+ run("opt_expr -mux_undef");
+ run("simplemap");
+ // TODO
+#if 0
+ run("ecp5_ffinit");
+#endif
+ }
+
+ if (check_label("map_luts"))
+ {
+ if (abc2 || help_mode) {
+ run("abc", " (only if -abc2)");
+ }
+ //TODO
+#if 0
+ run("techmap -map +/ecp5/latches_map.v");
+#endif
+ if (nomux)
+ run("abc -lut 4");
+ else
+ run("abc -lut 4:7");
+ run("clean");
+ }
+
+ if (check_label("map_cells"))
+ {
+ if (vpr)
+ run("techmap -D NO_LUT -map +/ecp5/cells_map.v");
+ else
+ run("techmap -map +/ecp5/cells_map.v", "(with -D NO_LUT in vpr mode)");
+
+ run("clean");
+ }
+
+ if (check_label("check"))
+ {
+ run("hierarchy -check");
+ run("stat");
+ run("check -noinit");
+ }
+
+ if (check_label("blif"))
+ {
+ if (!blif_file.empty() || help_mode) {
+ if (vpr || help_mode) {
+ run(stringf("opt_clean -purge"),
+ " (vpr mode)");
+ run(stringf("write_blif -attr -cname -conn -param %s",
+ help_mode ? "<file-name>" : blif_file.c_str()),
+ " (vpr mode)");
+ }
+ if (!vpr)
+ run(stringf("write_blif -gates -attr -param %s",
+ help_mode ? "<file-name>" : blif_file.c_str()),
+ " (non-vpr mode)");
+ }
+ }
+
+ if (check_label("edif"))
+ {
+ if (!edif_file.empty() || help_mode)
+ run(stringf("write_edif %s", help_mode ? "<file-name>" : edif_file.c_str()));
+ }
+
+ if (check_label("json"))
+ {
+ if (!json_file.empty() || help_mode)
+ run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));
+ }
+ }
+} SynthEcp5Pass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/gowin/cells_sim.v b/techlibs/gowin/cells_sim.v
index 3a09c157..94794262 100644
--- a/techlibs/gowin/cells_sim.v
+++ b/techlibs/gowin/cells_sim.v
@@ -1,51 +1,59 @@
module LUT1(output F, input I0);
- parameter [1:0] INIT = 0;
- assign F = I0 ? INIT[1] : INIT[0];
+ parameter [1:0] INIT = 0;
+ assign F = I0 ? INIT[1] : INIT[0];
endmodule
module LUT2(output F, input I0, I1);
- parameter [3:0] INIT = 0;
- wire [ 1: 0] s1 = I1 ? INIT[ 3: 2] : INIT[ 1: 0];
- assign F = I0 ? s1[1] : s1[0];
+ parameter [3:0] INIT = 0;
+ wire [ 1: 0] s1 = I1 ? INIT[ 3: 2] : INIT[ 1: 0];
+ assign F = I0 ? s1[1] : s1[0];
endmodule
module LUT3(output F, input I0, I1, I2);
- parameter [7:0] INIT = 0;
- wire [ 3: 0] s2 = I2 ? INIT[ 7: 4] : INIT[ 3: 0];
- wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
- assign F = I0 ? s1[1] : s1[0];
+ parameter [7:0] INIT = 0;
+ wire [ 3: 0] s2 = I2 ? INIT[ 7: 4] : INIT[ 3: 0];
+ wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
+ assign F = I0 ? s1[1] : s1[0];
endmodule
module LUT4(output F, input I0, I1, I2, I3);
- parameter [15:0] INIT = 0;
- wire [ 7: 0] s3 = I3 ? INIT[15: 8] : INIT[ 7: 0];
- wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
- wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
- assign F = I0 ? s1[1] : s1[0];
+ parameter [15:0] INIT = 0;
+ wire [ 7: 0] s3 = I3 ? INIT[15: 8] : INIT[ 7: 0];
+ wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
+ wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
+ assign F = I0 ? s1[1] : s1[0];
endmodule
module DFF (output reg Q, input CLK, D);
- always @(posedge C)
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(posedge CLK)
Q <= D;
endmodule
module DFFN (output reg Q, input CLK, D);
- always @(negedge C)
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(negedge CLK)
Q <= D;
endmodule
module VCC(output V);
- assign V = 1;
+ assign V = 1;
endmodule
module GND(output G);
- assign G = 0;
+ assign G = 0;
endmodule
module IBUF(output O, input I);
- assign O = I;
+ assign O = I;
endmodule
module OBUF(output O, input I);
- assign O = I;
+ assign O = I;
+endmodule
+
+module GSR (input GSRI);
+ wire GSRO = GSRI;
endmodule
diff --git a/techlibs/gowin/synth_gowin.cc b/techlibs/gowin/synth_gowin.cc
index 129ab839..793f345b 100644
--- a/techlibs/gowin/synth_gowin.cc
+++ b/techlibs/gowin/synth_gowin.cc
@@ -29,7 +29,7 @@ struct SynthGowinPass : public ScriptPass
{
SynthGowinPass() : ScriptPass("synth_gowin", "synthesis for Gowin FPGAs") { }
- virtual void help() YS_OVERRIDE
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -61,14 +61,14 @@ struct SynthGowinPass : public ScriptPass
string top_opt, vout_file;
bool retime;
- virtual void clear_flags() YS_OVERRIDE
+ void clear_flags() YS_OVERRIDE
{
top_opt = "-auto-top";
vout_file = "";
retime = false;
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
string run_from, run_to;
clear_flags();
@@ -111,7 +111,7 @@ struct SynthGowinPass : public ScriptPass
log_pop();
}
- virtual void script() YS_OVERRIDE
+ void script() YS_OVERRIDE
{
if (check_label("begin"))
{
@@ -169,7 +169,7 @@ struct SynthGowinPass : public ScriptPass
if (check_label("vout"))
{
if (!vout_file.empty() || help_mode)
- run(stringf("write_verilog -attr2comment -defparam -renameprefix gen %s",
+ run(stringf("write_verilog -nodec -attr2comment -defparam -renameprefix gen %s",
help_mode ? "<file-name>" : vout_file.c_str()));
}
}
diff --git a/techlibs/greenpak4/Makefile.inc b/techlibs/greenpak4/Makefile.inc
index 1c9871e2..b43fb751 100644
--- a/techlibs/greenpak4/Makefile.inc
+++ b/techlibs/greenpak4/Makefile.inc
@@ -1,8 +1,12 @@
OBJS += techlibs/greenpak4/synth_greenpak4.o
-OBJS += techlibs/greenpak4/greenpak4_counters.o
OBJS += techlibs/greenpak4/greenpak4_dffinv.o
+$(eval $(call add_share_file,share/greenpak4,techlibs/greenpak4/cells_blackbox.v))
+$(eval $(call add_share_file,share/greenpak4,techlibs/greenpak4/cells_latch.v))
$(eval $(call add_share_file,share/greenpak4,techlibs/greenpak4/cells_map.v))
$(eval $(call add_share_file,share/greenpak4,techlibs/greenpak4/cells_sim.v))
+$(eval $(call add_share_file,share/greenpak4,techlibs/greenpak4/cells_sim_ams.v))
+$(eval $(call add_share_file,share/greenpak4,techlibs/greenpak4/cells_sim_digital.v))
+$(eval $(call add_share_file,share/greenpak4,techlibs/greenpak4/cells_sim_wip.v))
$(eval $(call add_share_file,share/greenpak4,techlibs/greenpak4/gp_dff.lib))
diff --git a/techlibs/greenpak4/cells_blackbox.v b/techlibs/greenpak4/cells_blackbox.v
new file mode 100644
index 00000000..1895b90d
--- /dev/null
+++ b/techlibs/greenpak4/cells_blackbox.v
@@ -0,0 +1,18 @@
+module \$__COUNT_ (CE, CLK, OUT, POUT, RST, UP);
+
+ input wire CE;
+ input wire CLK;
+ output reg OUT;
+ output reg[WIDTH-1:0] POUT;
+ input wire RST;
+ input wire UP;
+
+ parameter COUNT_TO = 1;
+ parameter RESET_MODE = "RISING";
+ parameter RESET_TO_MAX = "1";
+ parameter HAS_POUT = 0;
+ parameter HAS_CE = 0;
+ parameter WIDTH = 8;
+ parameter DIRECTION = "DOWN";
+
+endmodule
diff --git a/techlibs/greenpak4/cells_latch.v b/techlibs/greenpak4/cells_latch.v
new file mode 100644
index 00000000..2ccdd203
--- /dev/null
+++ b/techlibs/greenpak4/cells_latch.v
@@ -0,0 +1,15 @@
+module $_DLATCH_P_(input E, input D, output Q);
+ GP_DLATCH _TECHMAP_REPLACE_ (
+ .D(D),
+ .nCLK(!E),
+ .Q(Q)
+ );
+endmodule
+
+module $_DLATCH_N_(input E, input D, output Q);
+ GP_DLATCH _TECHMAP_REPLACE_ (
+ .D(D),
+ .nCLK(E),
+ .Q(Q)
+ );
+endmodule
diff --git a/techlibs/greenpak4/cells_map.v b/techlibs/greenpak4/cells_map.v
index 111a77a1..b971a51f 100644
--- a/techlibs/greenpak4/cells_map.v
+++ b/techlibs/greenpak4/cells_map.v
@@ -50,6 +50,58 @@ module GP_DFFRI(input D, CLK, nRST, output reg nQ);
);
endmodule
+module GP_DLATCHS(input D, nCLK, nSET, output reg Q);
+ parameter [0:0] INIT = 1'bx;
+ GP_DLATCHSR #(
+ .INIT(INIT),
+ .SRMODE(1'b1),
+ ) _TECHMAP_REPLACE_ (
+ .D(D),
+ .nCLK(nCLK),
+ .nSR(nSET),
+ .Q(Q)
+ );
+endmodule
+
+module GP_DLATCHR(input D, nCLK, nRST, output reg Q);
+ parameter [0:0] INIT = 1'bx;
+ GP_DLATCHSR #(
+ .INIT(INIT),
+ .SRMODE(1'b0),
+ ) _TECHMAP_REPLACE_ (
+ .D(D),
+ .nCLK(nCLK),
+ .nSR(nRST),
+ .Q(Q)
+ );
+endmodule
+
+module GP_DLATCHSI(input D, nCLK, nSET, output reg nQ);
+ parameter [0:0] INIT = 1'bx;
+ GP_DLATCHSRI #(
+ .INIT(INIT),
+ .SRMODE(1'b1),
+ ) _TECHMAP_REPLACE_ (
+ .D(D),
+ .nCLK(nCLK),
+ .nSR(nSET),
+ .nQ(nQ)
+ );
+endmodule
+
+module GP_DLATCHRI(input D, nCLK, nRST, output reg nQ);
+ parameter [0:0] INIT = 1'bx;
+ GP_DLATCHSRI #(
+ .INIT(INIT),
+ .SRMODE(1'b0),
+ ) _TECHMAP_REPLACE_ (
+ .D(D),
+ .nCLK(nCLK),
+ .nSR(nRST),
+ .nQ(nQ)
+ );
+endmodule
+
module GP_OBUFT(input IN, input OE, output OUT);
GP_IOBUF _TECHMAP_REPLACE_ (
.IN(IN),
@@ -92,3 +144,116 @@ module \$lut (A, Y);
end
endgenerate
endmodule
+
+module \$__COUNT_ (CE, CLK, OUT, POUT, RST, UP);
+
+ input wire CE;
+ input wire CLK;
+ output reg OUT;
+ output reg[WIDTH-1:0] POUT;
+ input wire RST;
+ input wire UP;
+
+ parameter COUNT_TO = 1;
+ parameter RESET_MODE = "RISING";
+ parameter RESET_TO_MAX = 0;
+ parameter HAS_POUT = 0;
+ parameter HAS_CE = 0;
+ parameter WIDTH = 8;
+ parameter DIRECTION = "DOWN";
+
+ //If we have a DIRECTION other than DOWN fail... GP_COUNTx_ADV is not supported yet
+ if(DIRECTION != "DOWN") begin
+ initial begin
+ $display("ERROR: \$__COUNT_ support for GP_COUNTx_ADV is not yet implemented. This counter should never have been extracted (bug in extract_counter pass?).");
+ $finish;
+ end
+ end
+
+ //If counter is more than 14 bits wide, complain (also shouldn't happen)
+ else if(WIDTH > 14) begin
+ initial begin
+ $display("ERROR: \$__COUNT_ support for cascaded counters is not yet implemented. This counter should never have been extracted (bug in extract_counter pass?).");
+ $finish;
+ end
+ end
+
+ //If counter is more than 8 bits wide and has parallel output, we have a problem
+ else if(WIDTH > 8 && HAS_POUT) begin
+ initial begin
+ $display("ERROR: \$__COUNT_ support for 9-14 bit counters with parallel output is not yet implemented. This counter should never have been extracted (bug in extract_counter pass?).");
+ $finish;
+ end
+ end
+
+ //Looks like a legal counter! Do something with it
+ else if(WIDTH <= 8) begin
+ if(HAS_CE) begin
+ wire ce_not;
+ GP_INV ceinv(
+ .IN(CE),
+ .OUT(ce_not)
+ );
+ GP_COUNT8_ADV #(
+ .COUNT_TO(COUNT_TO),
+ .RESET_MODE(RESET_MODE),
+ .RESET_VALUE(RESET_TO_MAX ? "COUNT_TO" : "ZERO"),
+ .CLKIN_DIVIDE(1)
+ ) _TECHMAP_REPLACE_ (
+ .CLK(CLK),
+ .RST(RST),
+ .OUT(OUT),
+ .UP(1'b0), //always count down for now
+ .KEEP(ce_not),
+ .POUT(POUT)
+ );
+ end
+ else begin
+ GP_COUNT8 #(
+ .COUNT_TO(COUNT_TO),
+ .RESET_MODE(RESET_MODE),
+ .CLKIN_DIVIDE(1)
+ ) _TECHMAP_REPLACE_ (
+ .CLK(CLK),
+ .RST(RST),
+ .OUT(OUT),
+ .POUT(POUT)
+ );
+ end
+ end
+
+ else begin
+ if(HAS_CE) begin
+ wire ce_not;
+ GP_INV ceinv(
+ .IN(CE),
+ .OUT(ce_not)
+ );
+ GP_COUNT14_ADV #(
+ .COUNT_TO(COUNT_TO),
+ .RESET_MODE(RESET_TO_MAX ? "COUNT_TO" : "ZERO"),
+ .RESET_VALUE("COUNT_TO"),
+ .CLKIN_DIVIDE(1)
+ ) _TECHMAP_REPLACE_ (
+ .CLK(CLK),
+ .RST(RST),
+ .OUT(OUT),
+ .UP(1'b0), //always count down for now
+ .KEEP(ce_not),
+ .POUT(POUT)
+ );
+ end
+ else begin
+ GP_COUNT14 #(
+ .COUNT_TO(COUNT_TO),
+ .RESET_MODE(RESET_MODE),
+ .CLKIN_DIVIDE(1)
+ ) _TECHMAP_REPLACE_ (
+ .CLK(CLK),
+ .RST(RST),
+ .OUT(OUT)
+ );
+ end
+ end
+
+endmodule
diff --git a/techlibs/greenpak4/cells_sim.v b/techlibs/greenpak4/cells_sim.v
index 80746be0..221bee69 100644
--- a/techlibs/greenpak4/cells_sim.v
+++ b/techlibs/greenpak4/cells_sim.v
@@ -1,461 +1,5 @@
`timescale 1ns/1ps
-module GP_2LUT(input IN0, IN1, output OUT);
- parameter [3:0] INIT = 0;
- assign OUT = INIT[{IN1, IN0}];
-endmodule
-
-module GP_3LUT(input IN0, IN1, IN2, output OUT);
- parameter [7:0] INIT = 0;
- assign OUT = INIT[{IN2, IN1, IN0}];
-endmodule
-
-module GP_4LUT(input IN0, IN1, IN2, IN3, output OUT);
- parameter [15:0] INIT = 0;
- assign OUT = INIT[{IN3, IN2, IN1, IN0}];
-endmodule
-
-module GP_ABUF(input wire IN, output wire OUT);
-
- assign OUT = IN;
-
- //cannot simulate mixed signal IP
-
-endmodule
-
-module GP_ACMP(input wire PWREN, input wire VIN, input wire VREF, output reg OUT);
-
- parameter BANDWIDTH = "HIGH";
- parameter VIN_ATTEN = 1;
- parameter VIN_ISRC_EN = 0;
- parameter HYSTERESIS = 0;
-
- initial OUT = 0;
-
- //cannot simulate mixed signal IP
-
-endmodule
-
-module GP_BANDGAP(output reg OK);
- parameter AUTO_PWRDN = 1;
- parameter CHOPPER_EN = 1;
- parameter OUT_DELAY = 100;
-
- //cannot simulate mixed signal IP
-
-endmodule
-
-module GP_COUNT8(input CLK, input wire RST, output reg OUT);
-
- parameter RESET_MODE = "RISING";
-
- parameter COUNT_TO = 8'h1;
- parameter CLKIN_DIVIDE = 1;
-
- //more complex hard IP blocks are not supported for simulation yet
-
- reg[7:0] count = COUNT_TO;
-
- //Combinatorially output whenever we wrap low
- always @(*) begin
- OUT <= (count == 8'h0);
- end
-
- //POR or SYSRST reset value is COUNT_TO. Datasheet is unclear but conversations w/ Silego confirm.
- //Runtime reset value is clearly 0 except in count/FSM cells where it's configurable but we leave at 0 for now.
- //Datasheet seems to indicate that reset is asynchronous, but for now we model as sync due to Yosys issues...
- always @(posedge CLK) begin
-
- count <= count - 1'd1;
-
- if(count == 0)
- count <= COUNT_TO;
-
- /*
- if((RESET_MODE == "RISING") && RST)
- count <= 0;
- if((RESET_MODE == "FALLING") && !RST)
- count <= 0;
- if((RESET_MODE == "BOTH") && RST)
- count <= 0;
- */
- end
-
-endmodule
-
-module GP_COUNT14(input CLK, input wire RST, output reg OUT);
-
- parameter RESET_MODE = "RISING";
-
- parameter COUNT_TO = 14'h1;
- parameter CLKIN_DIVIDE = 1;
-
- //more complex hard IP blocks are not supported for simulation yet
-
-endmodule
-
-module GP_COUNT8_ADV(input CLK, input RST, output reg OUT,
- input UP, input KEEP);
-
- parameter RESET_MODE = "RISING";
- parameter RESET_VALUE = "ZERO";
-
- parameter COUNT_TO = 8'h1;
- parameter CLKIN_DIVIDE = 1;
-
- //more complex hard IP blocks are not supported for simulation yet
-
-endmodule
-
-module GP_COUNT14_ADV(input CLK, input RST, output reg OUT,
- input UP, input KEEP);
-
- parameter RESET_MODE = "RISING";
- parameter RESET_VALUE = "ZERO";
-
- parameter COUNT_TO = 14'h1;
- parameter CLKIN_DIVIDE = 1;
-
- //more complex hard IP blocks are not supported for simulation yet
-
-endmodule
-
-module GP_DAC(input[7:0] DIN, input wire VREF, output reg VOUT);
-
- initial VOUT = 0;
-
- //analog hard IP is not supported for simulation
-
-endmodule
-
-module GP_DELAY(input IN, output reg OUT);
-
- parameter DELAY_STEPS = 1;
- parameter GLITCH_FILTER = 0;
-
- initial OUT = 0;
-
- generate
-
- //TODO: These delays are PTV dependent! For now, hard code 3v3 timing
- //Change simulation-mode delay depending on global Vdd range (how to specify this?)
- always @(*) begin
- case(DELAY_STEPS)
- 1: #166 OUT = IN;
- 2: #318 OUT = IN;
- 2: #471 OUT = IN;
- 3: #622 OUT = IN;
- default: begin
- $display("ERROR: GP_DELAY must have DELAY_STEPS in range [1,4]");
- $finish;
- end
- endcase
- end
-
- endgenerate
-
-endmodule
-
-module GP_DFF(input D, CLK, output reg Q);
- parameter [0:0] INIT = 1'bx;
- initial Q = INIT;
- always @(posedge CLK) begin
- Q <= D;
- end
-endmodule
-
-module GP_DFFI(input D, CLK, output reg nQ);
- parameter [0:0] INIT = 1'bx;
- initial nQ = INIT;
- always @(posedge CLK) begin
- nQ <= ~D;
- end
-endmodule
-
-module GP_DFFR(input D, CLK, nRST, output reg Q);
- parameter [0:0] INIT = 1'bx;
- initial Q = INIT;
- always @(posedge CLK, negedge nRST) begin
- if (!nRST)
- Q <= 1'b0;
- else
- Q <= D;
- end
-endmodule
-
-module GP_DFFRI(input D, CLK, nRST, output reg nQ);
- parameter [0:0] INIT = 1'bx;
- initial nQ = INIT;
- always @(posedge CLK, negedge nRST) begin
- if (!nRST)
- nQ <= 1'b1;
- else
- nQ <= ~D;
- end
-endmodule
-
-module GP_DFFS(input D, CLK, nSET, output reg Q);
- parameter [0:0] INIT = 1'bx;
- initial Q = INIT;
- always @(posedge CLK, negedge nSET) begin
- if (!nSET)
- Q <= 1'b1;
- else
- Q <= D;
- end
-endmodule
-
-module GP_DFFSI(input D, CLK, nSET, output reg nQ);
- parameter [0:0] INIT = 1'bx;
- initial nQ = INIT;
- always @(posedge CLK, negedge nSET) begin
- if (!nSET)
- nQ <= 1'b0;
- else
- nQ <= ~D;
- end
-endmodule
-
-module GP_DFFSR(input D, CLK, nSR, output reg Q);
- parameter [0:0] INIT = 1'bx;
- parameter [0:0] SRMODE = 1'bx;
- initial Q = INIT;
- always @(posedge CLK, negedge nSR) begin
- if (!nSR)
- Q <= SRMODE;
- else
- Q <= D;
- end
-endmodule
-
-module GP_DFFSRI(input D, CLK, nSR, output reg nQ);
- parameter [0:0] INIT = 1'bx;
- parameter [0:0] SRMODE = 1'bx;
- initial nQ = INIT;
- always @(posedge CLK, negedge nSR) begin
- if (!nSR)
- nQ <= ~SRMODE;
- else
- nQ <= ~D;
- end
-endmodule
-
-module GP_EDGEDET(input IN, output reg OUT);
-
- parameter EDGE_DIRECTION = "RISING";
- parameter DELAY_STEPS = 1;
- parameter GLITCH_FILTER = 0;
-
- //not implemented for simulation
-
-endmodule
-
-module GP_IBUF(input IN, output OUT);
- assign OUT = IN;
-endmodule
-
-module GP_IOBUF(input IN, input OE, output OUT, inout IO);
- assign OUT = IO;
- assign IO = OE ? IN : 1'bz;
-endmodule
-
-module GP_INV(input IN, output OUT);
- assign OUT = ~IN;
-endmodule
-
-module GP_LFOSC(input PWRDN, output reg CLKOUT);
-
- parameter PWRDN_EN = 0;
- parameter AUTO_PWRDN = 0;
- parameter OUT_DIV = 1;
-
- initial CLKOUT = 0;
-
- //auto powerdown not implemented for simulation
- //output dividers not implemented for simulation
-
- always begin
- if(PWRDN)
- CLKOUT = 0;
- else begin
- //half period of 1730 Hz
- #289017;
- CLKOUT = ~CLKOUT;
- end
- end
-
-endmodule
-
-module GP_OBUF(input IN, output OUT);
- assign OUT = IN;
-endmodule
-
-module GP_OBUFT(input IN, input OE, output OUT);
- assign OUT = OE ? IN : 1'bz;
-endmodule
-
-module GP_PGA(input wire VIN_P, input wire VIN_N, input wire VIN_SEL, output reg VOUT);
-
- parameter GAIN = 1;
- parameter INPUT_MODE = "SINGLE";
-
- initial VOUT = 0;
-
- //cannot simulate mixed signal IP
-
-endmodule
-
-module GP_PGEN(input wire nRST, input wire CLK, output reg OUT);
- initial OUT = 0;
- parameter PATTERN_DATA = 16'h0;
- parameter PATTERN_LEN = 5'd16;
-
- reg[3:0] count = 0;
- always @(posedge CLK) begin
- if(!nRST)
- OUT <= PATTERN_DATA[0];
-
- else begin
- count <= count + 1;
- OUT <= PATTERN_DATA[count];
-
- if( (count + 1) == PATTERN_LEN)
- count <= 0;
- end
- end
-
-endmodule
-
-module GP_POR(output reg RST_DONE);
- parameter POR_TIME = 500;
-
- initial begin
- RST_DONE = 0;
-
- if(POR_TIME == 4)
- #4000;
- else if(POR_TIME == 500)
- #500000;
- else begin
- $display("ERROR: bad POR_TIME for GP_POR cell");
- $finish;
- end
-
- RST_DONE = 1;
-
- end
-
-endmodule
-
-module GP_RCOSC(input PWRDN, output reg CLKOUT_HARDIP, output reg CLKOUT_FABRIC);
-
- parameter PWRDN_EN = 0;
- parameter AUTO_PWRDN = 0;
- parameter HARDIP_DIV = 1;
- parameter FABRIC_DIV = 1;
- parameter OSC_FREQ = "25k";
-
- initial CLKOUT_HARDIP = 0;
- initial CLKOUT_FABRIC = 0;
-
- //output dividers not implemented for simulation
- //auto powerdown not implemented for simulation
-
- always begin
- if(PWRDN) begin
- CLKOUT_HARDIP = 0;
- CLKOUT_FABRIC = 0;
- end
- else begin
-
- if(OSC_FREQ == "25k") begin
- //half period of 25 kHz
- #20000;
- end
-
- else begin
- //half period of 2 MHz
- #250;
- end
-
- CLKOUT_HARDIP = ~CLKOUT_HARDIP;
- CLKOUT_FABRIC = ~CLKOUT_FABRIC;
- end
- end
-
-endmodule
-
-module GP_RINGOSC(input PWRDN, output reg CLKOUT_HARDIP, output reg CLKOUT_FABRIC);
-
- parameter PWRDN_EN = 0;
- parameter AUTO_PWRDN = 0;
- parameter HARDIP_DIV = 1;
- parameter FABRIC_DIV = 1;
-
- initial CLKOUT_HARDIP = 0;
- initial CLKOUT_FABRIC = 0;
-
- //output dividers not implemented for simulation
- //auto powerdown not implemented for simulation
-
- always begin
- if(PWRDN) begin
- CLKOUT_HARDIP = 0;
- CLKOUT_FABRIC = 0;
- end
- else begin
- //half period of 27 MHz
- #18.518;
- CLKOUT_HARDIP = ~CLKOUT_HARDIP;
- CLKOUT_FABRIC = ~CLKOUT_FABRIC;
- end
- end
-
-endmodule
-
-module GP_SHREG(input nRST, input CLK, input IN, output OUTA, output OUTB);
-
- parameter OUTA_TAP = 1;
- parameter OUTA_INVERT = 0;
- parameter OUTB_TAP = 1;
-
- reg[15:0] shreg = 0;
-
- always @(posedge CLK, negedge nRST) begin
-
- if(!nRST)
- shreg = 0;
-
- else
- shreg <= {shreg[14:0], IN};
-
- end
-
- assign OUTA = (OUTA_INVERT) ? ~shreg[OUTA_TAP - 1] : shreg[OUTA_TAP - 1];
- assign OUTB = shreg[OUTB_TAP - 1];
-
-endmodule
-
-//keep constraint needed to prevent optimization since we have no outputs
-(* keep *)
-module GP_SYSRESET(input RST);
- parameter RESET_MODE = "EDGE";
- parameter EDGE_SPEED = 4;
-
- //cannot simulate whole system reset
-
-endmodule
-
-module GP_VDD(output OUT);
- assign OUT = 1;
-endmodule
-
-module GP_VREF(input VIN, output reg VOUT);
- parameter VIN_DIV = 1;
- parameter VREF = 0;
- //cannot simulate mixed signal IP
-endmodule
-
-module GP_VSS(output OUT);
- assign OUT = 0;
-endmodule
+`include "cells_sim_ams.v"
+`include "cells_sim_digital.v"
+`include "cells_sim_wip.v"
diff --git a/techlibs/greenpak4/cells_sim_ams.v b/techlibs/greenpak4/cells_sim_ams.v
new file mode 100644
index 00000000..7f8b3de3
--- /dev/null
+++ b/techlibs/greenpak4/cells_sim_ams.v
@@ -0,0 +1,110 @@
+`timescale 1ns/1ps
+
+/*
+ This file contains analog / mixed signal cells, or other things that are not possible to fully model
+ in behavioral Verilog.
+
+ It also contains some stuff like oscillators that use non-synthesizeable constructs such as delays.
+ TODO: do we want a third file for those cells?
+ */
+
+module GP_ABUF(input wire IN, output wire OUT);
+
+ assign OUT = IN;
+
+ //must be 1, 5, 20, 50
+ //values >1 only available with Vdd > 2.7V
+ parameter BANDWIDTH_KHZ = 1;
+
+endmodule
+
+module GP_ACMP(input wire PWREN, input wire VIN, input wire VREF, output reg OUT);
+
+ parameter BANDWIDTH = "HIGH";
+ parameter VIN_ATTEN = 1;
+ parameter VIN_ISRC_EN = 0;
+ parameter HYSTERESIS = 0;
+
+ initial OUT = 0;
+
+endmodule
+
+module GP_BANDGAP(output reg OK);
+ parameter AUTO_PWRDN = 1;
+ parameter CHOPPER_EN = 1;
+ parameter OUT_DELAY = 100;
+
+endmodule
+
+module GP_DAC(input[7:0] DIN, input wire VREF, output reg VOUT);
+
+ initial VOUT = 0;
+
+ //analog hard IP is not supported for simulation
+
+endmodule
+
+module GP_LFOSC(input PWRDN, output reg CLKOUT);
+
+ parameter PWRDN_EN = 0;
+ parameter AUTO_PWRDN = 0;
+ parameter OUT_DIV = 1;
+
+ initial CLKOUT = 0;
+
+ //auto powerdown not implemented for simulation
+ //output dividers not implemented for simulation
+
+ always begin
+ if(PWRDN)
+ CLKOUT = 0;
+ else begin
+ //half period of 1730 Hz
+ #289017;
+ CLKOUT = ~CLKOUT;
+ end
+ end
+
+endmodule
+
+module GP_PGA(input wire VIN_P, input wire VIN_N, input wire VIN_SEL, output reg VOUT);
+
+ parameter GAIN = 1;
+ parameter INPUT_MODE = "SINGLE";
+
+ initial VOUT = 0;
+
+ //cannot simulate mixed signal IP
+
+endmodule
+
+module GP_PWRDET(output reg VDD_LOW);
+ initial VDD_LOW = 0;
+endmodule
+
+module GP_VREF(input VIN, output reg VOUT);
+ parameter VIN_DIV = 1;
+ parameter VREF = 0;
+ //cannot simulate mixed signal IP
+endmodule
+
+module GP_POR(output reg RST_DONE);
+ parameter POR_TIME = 500;
+
+ initial begin
+ RST_DONE = 0;
+
+ if(POR_TIME == 4)
+ #4000;
+ else if(POR_TIME == 500)
+ #500000;
+ else begin
+ $display("ERROR: bad POR_TIME for GP_POR cell");
+ $finish;
+ end
+
+ RST_DONE = 1;
+
+ end
+
+endmodule
diff --git a/techlibs/greenpak4/cells_sim_digital.v b/techlibs/greenpak4/cells_sim_digital.v
new file mode 100644
index 00000000..43d35d08
--- /dev/null
+++ b/techlibs/greenpak4/cells_sim_digital.v
@@ -0,0 +1,794 @@
+`timescale 1ns/1ps
+
+/*
+ This file contains simulation models for GreenPAK cells which are possible to fully model using synthesizeable
+ behavioral Verilog constructs only.
+ */
+
+module GP_2LUT(input IN0, IN1, output OUT);
+ parameter [3:0] INIT = 0;
+ assign OUT = INIT[{IN1, IN0}];
+endmodule
+
+module GP_3LUT(input IN0, IN1, IN2, output OUT);
+ parameter [7:0] INIT = 0;
+ assign OUT = INIT[{IN2, IN1, IN0}];
+endmodule
+
+module GP_4LUT(
+ input wire IN0,
+ input wire IN1,
+ input wire IN2,
+ input wire IN3,
+ output wire OUT);
+
+ parameter [15:0] INIT = 0;
+ assign OUT = INIT[{IN3, IN2, IN1, IN0}];
+endmodule
+
+module GP_CLKBUF(input wire IN, output wire OUT);
+ assign OUT = IN;
+endmodule
+
+module GP_COUNT14(input CLK, input wire RST, output reg OUT);
+
+ parameter RESET_MODE = "RISING";
+
+ parameter COUNT_TO = 14'h1;
+ parameter CLKIN_DIVIDE = 1;
+
+ reg[13:0] count = COUNT_TO;
+
+ initial begin
+ if(CLKIN_DIVIDE != 1) begin
+ $display("ERROR: CLKIN_DIVIDE values other than 1 not implemented");
+ $finish;
+ end
+ end
+
+ //Combinatorially output underflow flag whenever we wrap low
+ always @(*) begin
+ OUT <= (count == 14'h0);
+ end
+
+ //POR or SYSRST reset value is COUNT_TO. Datasheet is unclear but conversations w/ Silego confirm.
+ //Runtime reset value is clearly 0 except in count/FSM cells where it's configurable but we leave at 0 for now.
+ generate
+ case(RESET_MODE)
+
+ "RISING": begin
+ always @(posedge CLK, posedge RST) begin
+ if(RST)
+ count <= 0;
+ else begin
+ count <= count - 1'd1;
+ if(count == 0)
+ count <= COUNT_TO;
+ end
+ end
+ end
+
+ "FALLING": begin
+ always @(posedge CLK, negedge RST) begin
+ if(!RST)
+ count <= 0;
+ else begin
+ count <= count - 1'd1;
+ if(count == 0)
+ count <= COUNT_TO;
+ end
+ end
+ end
+
+ "BOTH": begin
+ initial begin
+ $display("Both-edge reset mode for GP_COUNT14 not implemented");
+ $finish;
+ end
+ end
+
+ "LEVEL": begin
+ always @(posedge CLK, posedge RST) begin
+ if(RST)
+ count <= 0;
+
+ else begin
+ count <= count - 1'd1;
+ if(count == 0)
+ count <= COUNT_TO;
+ end
+ end
+ end
+
+ default: begin
+ initial begin
+ $display("Invalid RESET_MODE on GP_COUNT14");
+ $finish;
+ end
+ end
+
+ endcase
+ endgenerate
+
+endmodule
+
+module GP_COUNT14_ADV(input CLK, input RST, output reg OUT,
+ input UP, input KEEP, output reg[7:0] POUT);
+
+ parameter RESET_MODE = "RISING";
+ parameter RESET_VALUE = "ZERO";
+
+ parameter COUNT_TO = 14'h1;
+ parameter CLKIN_DIVIDE = 1;
+
+ initial begin
+ if(CLKIN_DIVIDE != 1) begin
+ $display("ERROR: CLKIN_DIVIDE values other than 1 not implemented");
+ $finish;
+ end
+ end
+
+ reg[13:0] count = COUNT_TO;
+
+ //Combinatorially output underflow flag whenever we wrap low
+ always @(*) begin
+ if(UP)
+ OUT <= (count == 14'h3fff);
+ else
+ OUT <= (count == 14'h0);
+ POUT <= count[7:0];
+ end
+
+ //POR or SYSRST reset value is COUNT_TO. Datasheet is unclear but conversations w/ Silego confirm.
+ //Runtime reset value is clearly 0 except in count/FSM cells where it's configurable but we leave at 0 for now.
+ generate
+ case(RESET_MODE)
+
+ "RISING": begin
+ always @(posedge CLK, posedge RST) begin
+
+ //Resets
+ if(RST) begin
+ if(RESET_VALUE == "ZERO")
+ count <= 0;
+ else
+ count <= COUNT_TO;
+ end
+
+ else if(KEEP) begin
+ end
+ else if(UP) begin
+ count <= count + 1'd1;
+ if(count == 14'h3fff)
+ count <= COUNT_TO;
+ end
+ else begin
+ count <= count - 1'd1;
+
+ if(count == 0)
+ count <= COUNT_TO;
+ end
+
+ end
+ end
+
+ "FALLING": begin
+ always @(posedge CLK, negedge RST) begin
+
+ //Resets
+ if(!RST) begin
+ if(RESET_VALUE == "ZERO")
+ count <= 0;
+ else
+ count <= COUNT_TO;
+ end
+
+ else if(KEEP) begin
+ end
+ else if(UP) begin
+ count <= count + 1'd1;
+ if(count == 14'h3fff)
+ count <= COUNT_TO;
+ end
+ else begin
+ count <= count - 1'd1;
+
+ if(count == 0)
+ count <= COUNT_TO;
+ end
+
+ end
+ end
+
+ "BOTH": begin
+ initial begin
+ $display("Both-edge reset mode for GP_COUNT14_ADV not implemented");
+ $finish;
+ end
+ end
+
+ "LEVEL": begin
+ always @(posedge CLK, posedge RST) begin
+
+ //Resets
+ if(RST) begin
+ if(RESET_VALUE == "ZERO")
+ count <= 0;
+ else
+ count <= COUNT_TO;
+ end
+
+ else begin
+
+ if(KEEP) begin
+ end
+ else if(UP) begin
+ count <= count + 1'd1;
+ if(count == 14'h3fff)
+ count <= COUNT_TO;
+ end
+ else begin
+ count <= count - 1'd1;
+
+ if(count == 0)
+ count <= COUNT_TO;
+ end
+
+ end
+
+ end
+ end
+
+ default: begin
+ initial begin
+ $display("Invalid RESET_MODE on GP_COUNT14_ADV");
+ $finish;
+ end
+ end
+
+ endcase
+ endgenerate
+
+endmodule
+
+module GP_COUNT8_ADV(input CLK, input RST, output reg OUT,
+ input UP, input KEEP, output reg[7:0] POUT);
+
+ parameter RESET_MODE = "RISING";
+ parameter RESET_VALUE = "ZERO";
+
+ parameter COUNT_TO = 8'h1;
+ parameter CLKIN_DIVIDE = 1;
+
+ reg[7:0] count = COUNT_TO;
+
+ initial begin
+ if(CLKIN_DIVIDE != 1) begin
+ $display("ERROR: CLKIN_DIVIDE values other than 1 not implemented");
+ $finish;
+ end
+ end
+
+ //Combinatorially output underflow flag whenever we wrap low
+ always @(*) begin
+ if(UP)
+ OUT <= (count == 8'hff);
+ else
+ OUT <= (count == 8'h0);
+ POUT <= count;
+ end
+
+ //POR or SYSRST reset value is COUNT_TO. Datasheet is unclear but conversations w/ Silego confirm.
+ //Runtime reset value is clearly 0 except in count/FSM cells where it's configurable but we leave at 0 for now.
+ generate
+ case(RESET_MODE)
+
+ "RISING": begin
+ always @(posedge CLK, posedge RST) begin
+
+ //Resets
+ if(RST) begin
+ if(RESET_VALUE == "ZERO")
+ count <= 0;
+ else
+ count <= COUNT_TO;
+ end
+
+ //Main counter
+ else if(KEEP) begin
+ end
+ else if(UP) begin
+ count <= count + 1'd1;
+ if(count == 8'hff)
+ count <= COUNT_TO;
+ end
+ else begin
+ count <= count - 1'd1;
+
+ if(count == 0)
+ count <= COUNT_TO;
+ end
+
+ end
+ end
+
+ "FALLING": begin
+ always @(posedge CLK, negedge RST) begin
+
+ //Resets
+ if(!RST) begin
+ if(RESET_VALUE == "ZERO")
+ count <= 0;
+ else
+ count <= COUNT_TO;
+ end
+
+ //Main counter
+ else if(KEEP) begin
+ end
+ else if(UP) begin
+ count <= count + 1'd1;
+ if(count == 8'hff)
+ count <= COUNT_TO;
+ end
+ else begin
+ count <= count - 1'd1;
+
+ if(count == 0)
+ count <= COUNT_TO;
+ end
+
+ end
+ end
+
+ "BOTH": begin
+ initial begin
+ $display("Both-edge reset mode for GP_COUNT8_ADV not implemented");
+ $finish;
+ end
+ end
+
+ "LEVEL": begin
+ always @(posedge CLK, posedge RST) begin
+
+ //Resets
+ if(RST) begin
+ if(RESET_VALUE == "ZERO")
+ count <= 0;
+ else
+ count <= COUNT_TO;
+ end
+
+ else begin
+
+ if(KEEP) begin
+ end
+ else if(UP) begin
+ count <= count + 1'd1;
+ if(count == 8'hff)
+ count <= COUNT_TO;
+ end
+ else begin
+ count <= count - 1'd1;
+
+ if(count == 0)
+ count <= COUNT_TO;
+ end
+ end
+
+ end
+ end
+
+ default: begin
+ initial begin
+ $display("Invalid RESET_MODE on GP_COUNT8_ADV");
+ $finish;
+ end
+ end
+
+ endcase
+ endgenerate
+
+endmodule
+
+module GP_COUNT8(
+ input wire CLK,
+ input wire RST,
+ output reg OUT,
+ output reg[7:0] POUT);
+
+ parameter RESET_MODE = "RISING";
+
+ parameter COUNT_TO = 8'h1;
+ parameter CLKIN_DIVIDE = 1;
+
+ initial begin
+ if(CLKIN_DIVIDE != 1) begin
+ $display("ERROR: CLKIN_DIVIDE values other than 1 not implemented");
+ $finish;
+ end
+ end
+
+ reg[7:0] count = COUNT_TO;
+
+ //Combinatorially output underflow flag whenever we wrap low
+ always @(*) begin
+ OUT <= (count == 8'h0);
+ POUT <= count;
+ end
+
+ //POR or SYSRST reset value is COUNT_TO. Datasheet is unclear but conversations w/ Silego confirm.
+ //Runtime reset value is clearly 0 except in count/FSM cells where it's configurable but we leave at 0 for now.
+ generate
+ case(RESET_MODE)
+
+ "RISING": begin
+ always @(posedge CLK, posedge RST) begin
+ if(RST)
+ count <= 0;
+ else begin
+ count <= count - 1'd1;
+ if(count == 0)
+ count <= COUNT_TO;
+ end
+ end
+ end
+
+ "FALLING": begin
+ always @(posedge CLK, negedge RST) begin
+ if(!RST)
+ count <= 0;
+ else begin
+ count <= count - 1'd1;
+ if(count == 0)
+ count <= COUNT_TO;
+ end
+ end
+ end
+
+ "BOTH": begin
+ initial begin
+ $display("Both-edge reset mode for GP_COUNT8 not implemented");
+ $finish;
+ end
+ end
+
+ "LEVEL": begin
+ always @(posedge CLK, posedge RST) begin
+ if(RST)
+ count <= 0;
+
+ else begin
+ count <= count - 1'd1;
+ if(count == 0)
+ count <= COUNT_TO;
+ end
+ end
+ end
+
+ default: begin
+ initial begin
+ $display("Invalid RESET_MODE on GP_COUNT8");
+ $finish;
+ end
+ end
+
+ endcase
+ endgenerate
+
+endmodule
+
+module GP_DCMPREF(output reg[7:0]OUT);
+ parameter[7:0] REF_VAL = 8'h00;
+ initial OUT = REF_VAL;
+endmodule
+
+module GP_DCMPMUX(input[1:0] SEL, input[7:0] IN0, input[7:0] IN1, input[7:0] IN2, input[7:0] IN3, output reg[7:0] OUTA, output reg[7:0] OUTB);
+
+ always @(*) begin
+ case(SEL)
+ 2'd00: begin
+ OUTA <= IN0;
+ OUTB <= IN3;
+ end
+
+ 2'd01: begin
+ OUTA <= IN1;
+ OUTB <= IN2;
+ end
+
+ 2'd02: begin
+ OUTA <= IN2;
+ OUTB <= IN1;
+ end
+
+ 2'd03: begin
+ OUTA <= IN3;
+ OUTB <= IN0;
+ end
+
+ endcase
+ end
+endmodule
+
+module GP_DELAY(input IN, output reg OUT);
+
+ parameter DELAY_STEPS = 1;
+ parameter GLITCH_FILTER = 0;
+
+ initial OUT = 0;
+
+ generate
+
+ if(GLITCH_FILTER) begin
+ initial begin
+ $display("ERROR: GP_DELAY glitch filter mode not implemented");
+ $finish;
+ end
+ end
+
+ //TODO: These delays are PTV dependent! For now, hard code 3v3 timing
+ //Change simulation-mode delay depending on global Vdd range (how to specify this?)
+ always @(*) begin
+ case(DELAY_STEPS)
+ 1: #166 OUT = IN;
+ 2: #318 OUT = IN;
+ 2: #471 OUT = IN;
+ 3: #622 OUT = IN;
+ default: begin
+ $display("ERROR: GP_DELAY must have DELAY_STEPS in range [1,4]");
+ $finish;
+ end
+ endcase
+ end
+
+ endgenerate
+
+endmodule
+
+module GP_DFF(input D, CLK, output reg Q);
+ parameter [0:0] INIT = 1'bx;
+ initial Q = INIT;
+ always @(posedge CLK) begin
+ Q <= D;
+ end
+endmodule
+
+module GP_DFFI(input D, CLK, output reg nQ);
+ parameter [0:0] INIT = 1'bx;
+ initial nQ = INIT;
+ always @(posedge CLK) begin
+ nQ <= ~D;
+ end
+endmodule
+
+module GP_DFFR(input D, CLK, nRST, output reg Q);
+ parameter [0:0] INIT = 1'bx;
+ initial Q = INIT;
+ always @(posedge CLK, negedge nRST) begin
+ if (!nRST)
+ Q <= 1'b0;
+ else
+ Q <= D;
+ end
+endmodule
+
+module GP_DFFRI(input D, CLK, nRST, output reg nQ);
+ parameter [0:0] INIT = 1'bx;
+ initial nQ = INIT;
+ always @(posedge CLK, negedge nRST) begin
+ if (!nRST)
+ nQ <= 1'b1;
+ else
+ nQ <= ~D;
+ end
+endmodule
+
+module GP_DFFS(input D, CLK, nSET, output reg Q);
+ parameter [0:0] INIT = 1'bx;
+ initial Q = INIT;
+ always @(posedge CLK, negedge nSET) begin
+ if (!nSET)
+ Q <= 1'b1;
+ else
+ Q <= D;
+ end
+endmodule
+
+module GP_DFFSI(input D, CLK, nSET, output reg nQ);
+ parameter [0:0] INIT = 1'bx;
+ initial nQ = INIT;
+ always @(posedge CLK, negedge nSET) begin
+ if (!nSET)
+ nQ <= 1'b0;
+ else
+ nQ <= ~D;
+ end
+endmodule
+
+module GP_DFFSR(input D, CLK, nSR, output reg Q);
+ parameter [0:0] INIT = 1'bx;
+ parameter [0:0] SRMODE = 1'bx;
+ initial Q = INIT;
+ always @(posedge CLK, negedge nSR) begin
+ if (!nSR)
+ Q <= SRMODE;
+ else
+ Q <= D;
+ end
+endmodule
+
+module GP_DFFSRI(input D, CLK, nSR, output reg nQ);
+ parameter [0:0] INIT = 1'bx;
+ parameter [0:0] SRMODE = 1'bx;
+ initial nQ = INIT;
+ always @(posedge CLK, negedge nSR) begin
+ if (!nSR)
+ nQ <= ~SRMODE;
+ else
+ nQ <= ~D;
+ end
+endmodule
+
+module GP_DLATCH(input D, input nCLK, output reg Q);
+ parameter [0:0] INIT = 1'bx;
+ initial Q = INIT;
+ always @(*) begin
+ if(!nCLK)
+ Q <= D;
+ end
+endmodule
+
+module GP_DLATCHI(input D, input nCLK, output reg nQ);
+ parameter [0:0] INIT = 1'bx;
+ initial nQ = INIT;
+ always @(*) begin
+ if(!nCLK)
+ nQ <= ~D;
+ end
+endmodule
+
+module GP_DLATCHR(input D, input nCLK, input nRST, output reg Q);
+ parameter [0:0] INIT = 1'bx;
+ initial Q = INIT;
+ always @(*) begin
+ if(!nRST)
+ Q <= 1'b0;
+ else if(!nCLK)
+ Q <= D;
+ end
+endmodule
+
+module GP_DLATCHRI(input D, input nCLK, input nRST, output reg nQ);
+ parameter [0:0] INIT = 1'bx;
+ initial nQ = INIT;
+ always @(*) begin
+ if(!nRST)
+ nQ <= 1'b1;
+ else if(!nCLK)
+ nQ <= ~D;
+ end
+endmodule
+
+module GP_DLATCHS(input D, input nCLK, input nSET, output reg Q);
+ parameter [0:0] INIT = 1'bx;
+ initial Q = INIT;
+ always @(*) begin
+ if(!nSET)
+ Q <= 1'b1;
+ else if(!nCLK)
+ Q <= D;
+ end
+endmodule
+
+module GP_DLATCHSI(input D, input nCLK, input nSET, output reg nQ);
+ parameter [0:0] INIT = 1'bx;
+ initial nQ = INIT;
+ always @(*) begin
+ if(!nSET)
+ nQ <= 1'b0;
+ else if(!nCLK)
+ nQ <= ~D;
+ end
+endmodule
+
+module GP_DLATCHSR(input D, input nCLK, input nSR, output reg Q);
+ parameter [0:0] INIT = 1'bx;
+ parameter[0:0] SRMODE = 1'bx;
+ initial Q = INIT;
+ always @(*) begin
+ if(!nSR)
+ Q <= SRMODE;
+ else if(!nCLK)
+ Q <= D;
+ end
+endmodule
+
+module GP_DLATCHSRI(input D, input nCLK, input nSR, output reg nQ);
+ parameter [0:0] INIT = 1'bx;
+ parameter[0:0] SRMODE = 1'bx;
+ initial nQ = INIT;
+ always @(*) begin
+ if(!nSR)
+ nQ <= ~SRMODE;
+ else if(!nCLK)
+ nQ <= ~D;
+ end
+endmodule
+
+module GP_IBUF(input IN, output OUT);
+ assign OUT = IN;
+endmodule
+
+module GP_IOBUF(input IN, input OE, output OUT, inout IO);
+ assign OUT = IO;
+ assign IO = OE ? IN : 1'bz;
+endmodule
+
+module GP_INV(input IN, output OUT);
+ assign OUT = ~IN;
+endmodule
+
+module GP_OBUF(input IN, output OUT);
+ assign OUT = IN;
+endmodule
+
+module GP_OBUFT(input IN, input OE, output OUT);
+ assign OUT = OE ? IN : 1'bz;
+endmodule
+
+module GP_PGEN(input wire nRST, input wire CLK, output reg OUT);
+ initial OUT = 0;
+ parameter PATTERN_DATA = 16'h0;
+ parameter PATTERN_LEN = 5'd16;
+
+ localparam COUNT_MAX = PATTERN_LEN - 1'h1;
+
+ reg[3:0] count = 0;
+ always @(posedge CLK, negedge nRST) begin
+
+ if(!nRST)
+ count <= 0;
+
+ else begin
+ count <= count - 1'h1;
+ if(count == 0)
+ count <= COUNT_MAX;
+ end
+ end
+
+ always @(*)
+ OUT = PATTERN_DATA[count];
+
+endmodule
+
+module GP_SHREG(input nRST, input CLK, input IN, output OUTA, output OUTB);
+
+ parameter OUTA_TAP = 1;
+ parameter OUTA_INVERT = 0;
+ parameter OUTB_TAP = 1;
+
+ reg[15:0] shreg = 0;
+
+ always @(posedge CLK, negedge nRST) begin
+
+ if(!nRST)
+ shreg = 0;
+
+ else
+ shreg <= {shreg[14:0], IN};
+
+ end
+
+ assign OUTA = (OUTA_INVERT) ? ~shreg[OUTA_TAP - 1] : shreg[OUTA_TAP - 1];
+ assign OUTB = shreg[OUTB_TAP - 1];
+
+endmodule
+
+module GP_VDD(output OUT);
+ assign OUT = 1;
+endmodule
+
+module GP_VSS(output OUT);
+ assign OUT = 0;
+endmodule
diff --git a/techlibs/greenpak4/cells_sim_wip.v b/techlibs/greenpak4/cells_sim_wip.v
new file mode 100644
index 00000000..5261b12d
--- /dev/null
+++ b/techlibs/greenpak4/cells_sim_wip.v
@@ -0,0 +1,136 @@
+
+//Cells still in this file have INCOMPLETE simulation models, need to finish them
+
+module GP_DCMP(input[7:0] INP, input[7:0] INN, input CLK, input PWRDN, output reg GREATER, output reg EQUAL);
+ parameter PWRDN_SYNC = 1'b0;
+ parameter CLK_EDGE = "RISING";
+ parameter GREATER_OR_EQUAL = 1'b0;
+
+ //TODO implement power-down mode
+
+ initial GREATER = 0;
+ initial EQUAL = 0;
+
+ wire clk_minv = (CLK_EDGE == "RISING") ? CLK : ~CLK;
+ always @(posedge clk_minv) begin
+ if(GREATER_OR_EQUAL)
+ GREATER <= (INP >= INN);
+ else
+ GREATER <= (INP > INN);
+
+ EQUAL <= (INP == INN);
+ end
+
+endmodule
+
+module GP_EDGEDET(input IN, output reg OUT);
+
+ parameter EDGE_DIRECTION = "RISING";
+ parameter DELAY_STEPS = 1;
+ parameter GLITCH_FILTER = 0;
+
+ //not implemented for simulation
+
+endmodule
+
+module GP_RCOSC(input PWRDN, output reg CLKOUT_HARDIP, output reg CLKOUT_FABRIC);
+
+ parameter PWRDN_EN = 0;
+ parameter AUTO_PWRDN = 0;
+ parameter HARDIP_DIV = 1;
+ parameter FABRIC_DIV = 1;
+ parameter OSC_FREQ = "25k";
+
+ initial CLKOUT_HARDIP = 0;
+ initial CLKOUT_FABRIC = 0;
+
+ //output dividers not implemented for simulation
+ //auto powerdown not implemented for simulation
+
+ always begin
+ if(PWRDN) begin
+ CLKOUT_HARDIP = 0;
+ CLKOUT_FABRIC = 0;
+ end
+ else begin
+
+ if(OSC_FREQ == "25k") begin
+ //half period of 25 kHz
+ #20000;
+ end
+
+ else begin
+ //half period of 2 MHz
+ #250;
+ end
+
+ CLKOUT_HARDIP = ~CLKOUT_HARDIP;
+ CLKOUT_FABRIC = ~CLKOUT_FABRIC;
+ end
+ end
+
+endmodule
+
+module GP_RINGOSC(input PWRDN, output reg CLKOUT_HARDIP, output reg CLKOUT_FABRIC);
+
+ parameter PWRDN_EN = 0;
+ parameter AUTO_PWRDN = 0;
+ parameter HARDIP_DIV = 1;
+ parameter FABRIC_DIV = 1;
+
+ initial CLKOUT_HARDIP = 0;
+ initial CLKOUT_FABRIC = 0;
+
+ //output dividers not implemented for simulation
+ //auto powerdown not implemented for simulation
+
+ always begin
+ if(PWRDN) begin
+ CLKOUT_HARDIP = 0;
+ CLKOUT_FABRIC = 0;
+ end
+ else begin
+ //half period of 27 MHz
+ #18.518;
+ CLKOUT_HARDIP = ~CLKOUT_HARDIP;
+ CLKOUT_FABRIC = ~CLKOUT_FABRIC;
+ end
+ end
+
+endmodule
+
+module GP_SPI(
+ input SCK,
+ inout SDAT,
+ input CSN,
+ input[7:0] TXD_HIGH,
+ input[7:0] TXD_LOW,
+ output reg[7:0] RXD_HIGH,
+ output reg[7:0] RXD_LOW,
+ output reg INT);
+
+ initial RXD_HIGH = 0;
+ initial RXD_LOW = 0;
+ initial INT = 0;
+
+ parameter DATA_WIDTH = 8; //byte or word width
+ parameter SPI_CPHA = 0; //SPI clock phase
+ parameter SPI_CPOL = 0; //SPI clock polarity
+ parameter DIRECTION = "INPUT"; //SPI data direction (either input to chip or output to host)
+ //parallel output to fabric not yet implemented
+
+ //TODO: write sim model
+ //TODO: SPI SDIO control... can we use ADC output while SPI is input??
+ //TODO: clock sync
+
+endmodule
+
+//keep constraint needed to prevent optimization since we have no outputs
+(* keep *)
+module GP_SYSRESET(input RST);
+ parameter RESET_MODE = "EDGE";
+ parameter EDGE_SPEED = 4;
+
+ //cannot simulate whole system reset
+
+endmodule
diff --git a/techlibs/greenpak4/greenpak4_counters.cc b/techlibs/greenpak4/greenpak4_counters.cc
deleted file mode 100644
index 998bb73b..00000000
--- a/techlibs/greenpak4/greenpak4_counters.cc
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
- * yosys -- Yosys Open SYnthesis Suite
- *
- * Copyright (C) 2016 Clifford Wolf <clifford@clifford.at>
- *
- * 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"
-#include "kernel/modtools.h"
-
-USING_YOSYS_NAMESPACE
-PRIVATE_NAMESPACE_BEGIN
-
-//get the list of cells hooked up to at least one bit of a given net
-pool<Cell*> get_other_cells(const RTLIL::SigSpec& port, ModIndex& index, Cell* src)
-{
- pool<Cell*> rval;
- for(auto b : port)
- {
- pool<ModIndex::PortInfo> ports = index.query_ports(b);
- for(auto x : ports)
- {
- if(x.cell == src)
- continue;
- rval.insert(x.cell);
- }
- }
- return rval;
-}
-
-//return true if there is a full-width bus connection from cell a port ap to cell b port bp
-//if other_conns_allowed is false, then we require a strict point to point connection (no other links)
-bool is_full_bus(
- const RTLIL::SigSpec& sig,
- ModIndex& index,
- Cell* a,
- RTLIL::IdString ap,
- Cell* b,
- RTLIL::IdString bp,
- bool other_conns_allowed = false)
-{
- for(auto s : sig)
- {
- pool<ModIndex::PortInfo> ports = index.query_ports(s);
- bool found_a = false;
- bool found_b = false;
- for(auto x : ports)
- {
- if( (x.cell == a) && (x.port == ap) )
- found_a = true;
- else if( (x.cell == b) && (x.port == bp) )
- found_b = true;
- else if(!other_conns_allowed)
- return false;
- }
-
- if( (!found_a) || (!found_b) )
- return false;
- }
-
- return true;
-}
-
-//return true if the signal connects to one port only (nothing on the other end)
-bool is_unconnected(const RTLIL::SigSpec& port, ModIndex& index)
-{
- for(auto b : port)
- {
- pool<ModIndex::PortInfo> ports = index.query_ports(b);
- if(ports.size() > 1)
- return false;
- }
-
- return true;
-}
-
-struct CounterExtraction
-{
- int width; //counter width
- RTLIL::Wire* rwire; //the register output
- bool has_reset; //true if we have a reset
- RTLIL::SigSpec rst; //reset pin
- int count_value; //value we count from
- RTLIL::SigSpec clk; //clock signal
- RTLIL::SigSpec outsig; //counter output signal
- RTLIL::Cell* count_mux; //counter mux
- RTLIL::Cell* count_reg; //counter register
- RTLIL::Cell* underflow_inv; //inverter reduction for output-underflow detect
-};
-
-//attempt to extract a counter centered on the given cell
-int greenpak4_counters_tryextract(ModIndex& index, Cell *cell, CounterExtraction& extract)
-{
- SigMap& sigmap = index.sigmap;
-
- //GreenPak does not support counters larger than 14 bits so immediately skip anything bigger
- int a_width = cell->getParam("\\A_WIDTH").as_int();
- extract.width = a_width;
- if(a_width > 14)
- return 1;
-
- //Second input must be a single bit
- int b_width = cell->getParam("\\B_WIDTH").as_int();
- if(b_width != 1)
- return 2;
-
- //Both inputs must be unsigned, so don't extract anything with a signed input
- bool a_sign = cell->getParam("\\A_SIGNED").as_bool();
- bool b_sign = cell->getParam("\\B_SIGNED").as_bool();
- if(a_sign || b_sign)
- return 3;
-
- //To be a counter, one input of the ALU must be a constant 1
- //TODO: can A or B be swapped in synthesized RTL or is B always the 1?
- const RTLIL::SigSpec b_port = sigmap(cell->getPort("\\B"));
- if(!b_port.is_fully_const() || (b_port.as_int() != 1) )
- return 4;
-
- //BI and CI must be constant 1 as well
- const RTLIL::SigSpec bi_port = sigmap(cell->getPort("\\BI"));
- if(!bi_port.is_fully_const() || (bi_port.as_int() != 1) )
- return 5;
- const RTLIL::SigSpec ci_port = sigmap(cell->getPort("\\CI"));
- if(!ci_port.is_fully_const() || (ci_port.as_int() != 1) )
- return 6;
-
- //CO and X must be unconnected (exactly one connection to each port)
- if(!is_unconnected(sigmap(cell->getPort("\\CO")), index))
- return 7;
- if(!is_unconnected(sigmap(cell->getPort("\\X")), index))
- return 8;
-
- //Y must have exactly one connection, and it has to be a $mux cell.
- //We must have a direct bus connection from our Y to their A.
- const RTLIL::SigSpec aluy = sigmap(cell->getPort("\\Y"));
- pool<Cell*> y_loads = get_other_cells(aluy, index, cell);
- if(y_loads.size() != 1)
- return 9;
- Cell* count_mux = *y_loads.begin();
- extract.count_mux = count_mux;
- if(count_mux->type != "$mux")
- return 10;
- if(!is_full_bus(aluy, index, cell, "\\Y", count_mux, "\\A"))
- return 11;
-
- //B connection of the mux is our underflow value
- const RTLIL::SigSpec underflow = sigmap(count_mux->getPort("\\B"));
- if(!underflow.is_fully_const())
- return 12;
- extract.count_value = underflow.as_int();
-
- //S connection of the mux must come from an inverter (need not be the only load)
- const RTLIL::SigSpec muxsel = sigmap(count_mux->getPort("\\S"));
- extract.outsig = muxsel;
- pool<Cell*> muxsel_conns = get_other_cells(muxsel, index, count_mux);
- Cell* underflow_inv = NULL;
- for(auto c : muxsel_conns)
- {
- if(c->type != "$logic_not")
- continue;
- if(!is_full_bus(muxsel, index, c, "\\Y", count_mux, "\\S", true))
- continue;
-
- underflow_inv = c;
- break;
- }
- if(underflow_inv == NULL)
- return 13;
- extract.underflow_inv = underflow_inv;
-
- //Y connection of the mux must have exactly one load, the counter's internal register
- const RTLIL::SigSpec muxy = sigmap(count_mux->getPort("\\Y"));
- pool<Cell*> muxy_loads = get_other_cells(muxy, index, count_mux);
- if(muxy_loads.size() != 1)
- return 14;
- Cell* count_reg = *muxy_loads.begin();
- extract.count_reg = count_reg;
- if(count_reg->type == "$dff")
- extract.has_reset = false;
- else if(count_reg->type == "$adff")
- {
- extract.has_reset = true;
-
- //Verify ARST_VALUE is zero and ARST_POLARITY is 1
- //TODO: infer an inverter to make it 1 if necessary, so we can support negative level resets?
- if(count_reg->getParam("\\ARST_POLARITY").as_int() != 1)
- return 22;
- if(count_reg->getParam("\\ARST_VALUE").as_int() != 0)
- return 23;
-
- //Save the reset
- extract.rst = sigmap(count_reg->getPort("\\ARST"));
- }
- //TODO: support synchronous reset
- else
- return 15;
- if(!is_full_bus(muxy, index, count_mux, "\\Y", count_reg, "\\D"))
- return 16;
-
- //TODO: Verify count_reg CLK_POLARITY is 1
-
- //Register output must have exactly two loads, the inverter and ALU
- const RTLIL::SigSpec cnout = sigmap(count_reg->getPort("\\Q"));
- pool<Cell*> cnout_loads = get_other_cells(cnout, index, count_reg);
- if(cnout_loads.size() != 2)
- return 17;
- if(!is_full_bus(cnout, index, count_reg, "\\Q", underflow_inv, "\\A", true))
- return 18;
- if(!is_full_bus(cnout, index, count_reg, "\\Q", cell, "\\A", true))
- return 19;
-
- //Look up the clock from the register
- extract.clk = sigmap(count_reg->getPort("\\CLK"));
-
- //Register output net must have an INIT attribute equal to the count value
- extract.rwire = cnout.as_wire();
- if(extract.rwire->attributes.find("\\init") == extract.rwire->attributes.end())
- return 20;
- int rinit = extract.rwire->attributes["\\init"].as_int();
- if(rinit != extract.count_value)
- return 21;
-
- return 0;
-}
-
-void greenpak4_counters_worker(
- ModIndex& index,
- Cell *cell,
- unsigned int& total_counters,
- pool<Cell*>& cells_to_remove)
-{
- SigMap& sigmap = index.sigmap;
-
- //Core of the counter must be an ALU
- if (cell->type != "$alu")
- return;
-
- //A input is the count value. Check if it has COUNT_EXTRACT set.
- //If it's not a wire, don't even try
- auto port = sigmap(cell->getPort("\\A"));
- if(!port.is_wire())
- return;
- RTLIL::Wire* a_wire = port.as_wire();
- bool force_extract = false;
- bool never_extract = false;
- string count_reg_src = a_wire->attributes["\\src"].decode_string().c_str();
- if(a_wire->attributes.find("\\COUNT_EXTRACT") != a_wire->attributes.end())
- {
- pool<string> sa = a_wire->get_strpool_attribute("\\COUNT_EXTRACT");
- string extract_value;
- if(sa.size() >= 1)
- {
- extract_value = *sa.begin();
- log(" Signal %s declared at %s has COUNT_EXTRACT = %s\n",
- log_id(a_wire),
- count_reg_src.c_str(),
- extract_value.c_str());
-
- if(extract_value == "FORCE")
- force_extract = true;
- else if(extract_value == "NO")
- never_extract = true;
- else if(extract_value == "AUTO")
- {} //default
- else
- log_error(" Illegal COUNT_EXTRACT value %s (must be one of FORCE, NO, AUTO)\n",
- extract_value.c_str());
- }
- }
-
- //If we're explicitly told not to extract, don't infer a counter
- if(never_extract)
- return;
-
- //Attempt to extract a counter
- CounterExtraction extract;
- int reason = greenpak4_counters_tryextract(index, cell, extract);
-
- //Nonzero code - we could not find a matchable counter.
- //Do nothing, unless extraction was forced in which case give an error
- if(reason != 0)
- {
- static const char* reasons[24]=
- {
- "no problem", //0
- "counter is larger than 14 bits", //1
- "counter does not count by one", //2
- "counter uses signed math", //3
- "counter does not count by one", //4
- "ALU is not a subtractor", //5
- "ALU is not a subtractor", //6
- "ALU ports used outside counter", //7
- "ALU ports used outside counter", //8
- "ALU output used outside counter", //9
- "ALU output is not a mux", //10
- "ALU output is not full bus", //11
- "Underflow value is not constant", //12
- "No underflow detector found", //13
- "Mux output is used outside counter", //14
- "Counter reg is not DFF/ADFF", //15
- "Counter input is not full bus", //16
- "Count register is used outside counter", //17
- "Register output is not full bus", //18
- "Register output is not full bus", //19
- "No init value found", //20
- "Underflow value is not equal to init value", //21
- "Reset polarity is not positive", //22
- "Reset is not to zero" //23
- };
-
- if(force_extract)
- {
- log_error(
- "Counter extraction is set to FORCE on register %s, but a counter could not be inferred (%s)\n",
- log_id(a_wire),
- reasons[reason]);
- }
- return;
- }
-
- //Figure out the final cell type based on the counter size
- string celltype = "\\GP_COUNT8";
- if(extract.width > 8)
- celltype = "\\GP_COUNT14";
-
- //Log it
- total_counters ++;
- string reset_type = "non-resettable";
- if(extract.has_reset)
- {
- //TODO: support other kind of reset
- reset_type = "async resettable";
- }
- log(" Found %d-bit %s down counter (from %d) for register %s declared at %s\n",
- extract.width,
- reset_type.c_str(),
- extract.count_value,
- log_id(extract.rwire->name),
- count_reg_src.c_str());
-
- //Wipe all of the old connections to the ALU
- cell->unsetPort("\\A");
- cell->unsetPort("\\B");
- cell->unsetPort("\\BI");
- cell->unsetPort("\\CI");
- cell->unsetPort("\\CO");
- cell->unsetPort("\\X");
- cell->unsetPort("\\Y");
- cell->unsetParam("\\A_SIGNED");
- cell->unsetParam("\\A_WIDTH");
- cell->unsetParam("\\B_SIGNED");
- cell->unsetParam("\\B_WIDTH");
- cell->unsetParam("\\Y_WIDTH");
-
- //Change the cell type
- cell->type = celltype;
-
- //Hook up resets
- if(extract.has_reset)
- {
- //TODO: support other kinds of reset
- cell->setParam("\\RESET_MODE", RTLIL::Const("LEVEL"));
- cell->setPort("\\RST", extract.rst);
- }
- else
- {
- cell->setParam("\\RESET_MODE", RTLIL::Const("RISING"));
- cell->setPort("\\RST", RTLIL::SigSpec(false));
- }
-
- //Hook up other stuff
- cell->setParam("\\CLKIN_DIVIDE", RTLIL::Const(1));
- cell->setParam("\\COUNT_TO", RTLIL::Const(extract.count_value));
-
- cell->setPort("\\CLK", extract.clk);
- cell->setPort("\\OUT", extract.outsig);
-
- //Delete the cells we've replaced (let opt_clean handle deleting the now-redundant wires)
- cells_to_remove.insert(extract.count_mux);
- cells_to_remove.insert(extract.count_reg);
- cells_to_remove.insert(extract.underflow_inv);
-}
-
-struct Greenpak4CountersPass : public Pass {
- Greenpak4CountersPass() : Pass("greenpak4_counters", "Extract GreenPak4 counter cells") { }
- virtual void help()
- {
- // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
- log("\n");
- log(" greenpak4_counters [options] [selection]\n");
- log("\n");
- log("This pass converts non-resettable or async resettable down counters to GreenPak4\n");
- log("counter cells (All other GreenPak4 counter modes must be instantiated manually.)\n");
- log("\n");
- }
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
- {
- log_header(design, "Executing GREENPAK4_COUNTERS pass (mapping counters to hard IP blocks).\n");
-
- size_t argidx;
- for (argidx = 1; argidx < args.size(); argidx++)
- {
- // if (args[argidx] == "-v") {
- // continue;
- // }
- break;
- }
- extra_args(args, argidx, design);
-
- //Extract all of the counters we could find
- unsigned int total_counters = 0;
- for (auto module : design->selected_modules())
- {
- pool<Cell*> cells_to_remove;
-
- ModIndex index(module);
- for (auto cell : module->selected_cells())
- greenpak4_counters_worker(index, cell, total_counters, cells_to_remove);
-
- for(auto cell : cells_to_remove)
- module->remove(cell);
- }
-
- if(total_counters)
- log("Extracted %u counters\n", total_counters);
- }
-} Greenpak4CountersPass;
-
-PRIVATE_NAMESPACE_END
diff --git a/techlibs/greenpak4/greenpak4_dffinv.cc b/techlibs/greenpak4/greenpak4_dffinv.cc
index ff63958e..d57e978a 100644
--- a/techlibs/greenpak4/greenpak4_dffinv.cc
+++ b/techlibs/greenpak4/greenpak4_dffinv.cc
@@ -26,6 +26,7 @@ PRIVATE_NAMESPACE_BEGIN
void invert_gp_dff(Cell *cell, bool invert_input)
{
string cell_type = cell->type.str();
+ bool cell_type_latch = cell_type.find("LATCH") != string::npos;
bool cell_type_i = cell_type.find('I') != string::npos;
bool cell_type_r = cell_type.find('R') != string::npos;
bool cell_type_s = cell_type.find('S') != string::npos;
@@ -79,25 +80,28 @@ void invert_gp_dff(Cell *cell, bool invert_input)
cell_type_i = true;
}
- cell->type = stringf("\\GP_DFF%s%s%s", cell_type_s ? "S" : "", cell_type_r ? "R" : "", cell_type_i ? "I" : "");
+ if(cell_type_latch)
+ cell->type = stringf("\\GP_DLATCH%s%s%s", cell_type_s ? "S" : "", cell_type_r ? "R" : "", cell_type_i ? "I" : "");
+ else
+ cell->type = stringf("\\GP_DFF%s%s%s", cell_type_s ? "S" : "", cell_type_r ? "R" : "", cell_type_i ? "I" : "");
log("Merged %s inverter into cell %s.%s: %s -> %s\n", invert_input ? "input" : "output",
log_id(cell->module), log_id(cell), cell_type.c_str()+1, log_id(cell->type));
}
struct Greenpak4DffInvPass : public Pass {
- Greenpak4DffInvPass() : Pass("greenpak4_dffinv", "merge greenpak4 inverters and DFFs") { }
- virtual void help()
+ Greenpak4DffInvPass() : Pass("greenpak4_dffinv", "merge greenpak4 inverters and DFF/latches") { }
+ void help() YS_OVERRIDE
{
log("\n");
log(" greenpak4_dffinv [options] [selection]\n");
log("\n");
- log("Merge GP_INV cells with GP_DFF* cells.\n");
+ log("Merge GP_INV cells with GP_DFF* and GP_DLATCH* cells.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
- log_header(design, "Executing GREENPAK4_DFFINV pass (merge synchronous set/reset into FF cells).\n");
+ log_header(design, "Executing GREENPAK4_DFFINV pass (merge input/output inverters into FF/latch cells).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@@ -120,6 +124,15 @@ struct Greenpak4DffInvPass : public Pass {
gp_dff_types.insert("\\GP_DFFSR");
gp_dff_types.insert("\\GP_DFFSRI");
+ gp_dff_types.insert("\\GP_DLATCH");
+ gp_dff_types.insert("\\GP_DLATCHI");
+ gp_dff_types.insert("\\GP_DLATCHR");
+ gp_dff_types.insert("\\GP_DLATCHRI");
+ gp_dff_types.insert("\\GP_DLATCHS");
+ gp_dff_types.insert("\\GP_DLATCHSI");
+ gp_dff_types.insert("\\GP_DLATCHSR");
+ gp_dff_types.insert("\\GP_DLATCHSRI");
+
for (auto module : design->selected_modules())
{
SigMap sigmap(module);
diff --git a/techlibs/greenpak4/synth_greenpak4.cc b/techlibs/greenpak4/synth_greenpak4.cc
index 10e2a149..b91d5273 100644
--- a/techlibs/greenpak4/synth_greenpak4.cc
+++ b/techlibs/greenpak4/synth_greenpak4.cc
@@ -29,13 +29,15 @@ struct SynthGreenPAK4Pass : public ScriptPass
{
SynthGreenPAK4Pass() : ScriptPass("synth_greenpak4", "synthesis for GreenPAK4 FPGAs") { }
- virtual void help() YS_OVERRIDE
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" synth_greenpak4 [options]\n");
log("\n");
log("This command runs synthesis for GreenPAK4 FPGAs. This work is experimental.\n");
+ log("It is intended to be used with https://github.com/azonenberg/openfpga as the\n");
+ log("place-and-route.\n");
log("\n");
log(" -top <module>\n");
log(" use the specified module as top module (default='top')\n");
@@ -68,7 +70,7 @@ struct SynthGreenPAK4Pass : public ScriptPass
string top_opt, part, json_file;
bool flatten, retime;
- virtual void clear_flags() YS_OVERRIDE
+ void clear_flags() YS_OVERRIDE
{
top_opt = "-auto-top";
part = "SLG46621V";
@@ -77,7 +79,7 @@ struct SynthGreenPAK4Pass : public ScriptPass
retime = false;
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
string run_from, run_to;
clear_flags();
@@ -131,7 +133,7 @@ struct SynthGreenPAK4Pass : public ScriptPass
log_pop();
}
- virtual void script() YS_OVERRIDE
+ void script() YS_OVERRIDE
{
if (check_label("begin"))
{
@@ -153,12 +155,13 @@ struct SynthGreenPAK4Pass : public ScriptPass
if (check_label("fine"))
{
- run("greenpak4_counters");
+ run("extract_counter -pout GP_DCMP,GP_DAC -maxwidth 14");
run("clean");
run("opt -fast -mux_undef -undriven -fine");
run("memory_map");
run("opt -undriven -fine");
run("techmap");
+ run("techmap -map +/greenpak4/cells_latch.v");
run("dfflibmap -prepare -liberty +/greenpak4/gp_dff.lib");
run("opt -fast");
if (retime || help_mode)
@@ -201,8 +204,6 @@ struct SynthGreenPAK4Pass : public ScriptPass
if (!json_file.empty() || help_mode)
run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));
}
-
- log_pop();
}
} SynthGreenPAK4Pass;
diff --git a/techlibs/ice40/cells_map.v b/techlibs/ice40/cells_map.v
index 0227ffad..d0ddfd02 100644
--- a/techlibs/ice40/cells_map.v
+++ b/techlibs/ice40/cells_map.v
@@ -27,6 +27,7 @@ module \$__DFFE_NP1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (
module \$__DFFE_PP0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule
module \$__DFFE_PP1 (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule
+`ifndef NO_LUT
module \$lut (A, Y);
parameter WIDTH = 0;
parameter LUT = 0;
@@ -55,3 +56,4 @@ module \$lut (A, Y);
end
endgenerate
endmodule
+`endif
diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v
index 7778b551..9f73aeb0 100644
--- a/techlibs/ice40/cells_sim.v
+++ b/techlibs/ice40/cells_sim.v
@@ -1,6 +1,6 @@
-`define SB_DFF_REG reg Q = 0;
-// `define SB_DFF_REG reg Q;
+`define SB_DFF_REG reg Q = 0
+// `define SB_DFF_REG reg Q
// SiliconBlue IO Cells
@@ -132,21 +132,18 @@ endmodule
// Positive Edge SiliconBlue FF Cells
-module SB_DFF (output Q, input C, D);
- `SB_DFF_REG
+module SB_DFF (output `SB_DFF_REG, input C, D);
always @(posedge C)
Q <= D;
endmodule
-module SB_DFFE (output Q, input C, E, D);
- `SB_DFF_REG
+module SB_DFFE (output `SB_DFF_REG, input C, E, D);
always @(posedge C)
if (E)
Q <= D;
endmodule
-module SB_DFFSR (output Q, input C, R, D);
- `SB_DFF_REG
+module SB_DFFSR (output `SB_DFF_REG, input C, R, D);
always @(posedge C)
if (R)
Q <= 0;
@@ -154,8 +151,7 @@ module SB_DFFSR (output Q, input C, R, D);
Q <= D;
endmodule
-module SB_DFFR (output Q, input C, R, D);
- `SB_DFF_REG
+module SB_DFFR (output `SB_DFF_REG, input C, R, D);
always @(posedge C, posedge R)
if (R)
Q <= 0;
@@ -163,8 +159,7 @@ module SB_DFFR (output Q, input C, R, D);
Q <= D;
endmodule
-module SB_DFFSS (output Q, input C, S, D);
- `SB_DFF_REG
+module SB_DFFSS (output `SB_DFF_REG, input C, S, D);
always @(posedge C)
if (S)
Q <= 1;
@@ -172,8 +167,7 @@ module SB_DFFSS (output Q, input C, S, D);
Q <= D;
endmodule
-module SB_DFFS (output Q, input C, S, D);
- `SB_DFF_REG
+module SB_DFFS (output `SB_DFF_REG, input C, S, D);
always @(posedge C, posedge S)
if (S)
Q <= 1;
@@ -181,8 +175,7 @@ module SB_DFFS (output Q, input C, S, D);
Q <= D;
endmodule
-module SB_DFFESR (output Q, input C, E, R, D);
- `SB_DFF_REG
+module SB_DFFESR (output `SB_DFF_REG, input C, E, R, D);
always @(posedge C)
if (E) begin
if (R)
@@ -192,8 +185,7 @@ module SB_DFFESR (output Q, input C, E, R, D);
end
endmodule
-module SB_DFFER (output Q, input C, E, R, D);
- `SB_DFF_REG
+module SB_DFFER (output `SB_DFF_REG, input C, E, R, D);
always @(posedge C, posedge R)
if (R)
Q <= 0;
@@ -201,8 +193,7 @@ module SB_DFFER (output Q, input C, E, R, D);
Q <= D;
endmodule
-module SB_DFFESS (output Q, input C, E, S, D);
- `SB_DFF_REG
+module SB_DFFESS (output `SB_DFF_REG, input C, E, S, D);
always @(posedge C)
if (E) begin
if (S)
@@ -212,8 +203,7 @@ module SB_DFFESS (output Q, input C, E, S, D);
end
endmodule
-module SB_DFFES (output Q, input C, E, S, D);
- `SB_DFF_REG
+module SB_DFFES (output `SB_DFF_REG, input C, E, S, D);
always @(posedge C, posedge S)
if (S)
Q <= 1;
@@ -223,21 +213,18 @@ endmodule
// Negative Edge SiliconBlue FF Cells
-module SB_DFFN (output Q, input C, D);
- `SB_DFF_REG
+module SB_DFFN (output `SB_DFF_REG, input C, D);
always @(negedge C)
Q <= D;
endmodule
-module SB_DFFNE (output Q, input C, E, D);
- `SB_DFF_REG
+module SB_DFFNE (output `SB_DFF_REG, input C, E, D);
always @(negedge C)
if (E)
Q <= D;
endmodule
-module SB_DFFNSR (output Q, input C, R, D);
- `SB_DFF_REG
+module SB_DFFNSR (output `SB_DFF_REG, input C, R, D);
always @(negedge C)
if (R)
Q <= 0;
@@ -245,8 +232,7 @@ module SB_DFFNSR (output Q, input C, R, D);
Q <= D;
endmodule
-module SB_DFFNR (output Q, input C, R, D);
- `SB_DFF_REG
+module SB_DFFNR (output `SB_DFF_REG, input C, R, D);
always @(negedge C, posedge R)
if (R)
Q <= 0;
@@ -254,8 +240,7 @@ module SB_DFFNR (output Q, input C, R, D);
Q <= D;
endmodule
-module SB_DFFNSS (output Q, input C, S, D);
- `SB_DFF_REG
+module SB_DFFNSS (output `SB_DFF_REG, input C, S, D);
always @(negedge C)
if (S)
Q <= 1;
@@ -263,8 +248,7 @@ module SB_DFFNSS (output Q, input C, S, D);
Q <= D;
endmodule
-module SB_DFFNS (output Q, input C, S, D);
- `SB_DFF_REG
+module SB_DFFNS (output `SB_DFF_REG, input C, S, D);
always @(negedge C, posedge S)
if (S)
Q <= 1;
@@ -272,8 +256,7 @@ module SB_DFFNS (output Q, input C, S, D);
Q <= D;
endmodule
-module SB_DFFNESR (output Q, input C, E, R, D);
- `SB_DFF_REG
+module SB_DFFNESR (output `SB_DFF_REG, input C, E, R, D);
always @(negedge C)
if (E) begin
if (R)
@@ -283,8 +266,7 @@ module SB_DFFNESR (output Q, input C, E, R, D);
end
endmodule
-module SB_DFFNER (output Q, input C, E, R, D);
- `SB_DFF_REG
+module SB_DFFNER (output `SB_DFF_REG, input C, E, R, D);
always @(negedge C, posedge R)
if (R)
Q <= 0;
@@ -292,8 +274,7 @@ module SB_DFFNER (output Q, input C, E, R, D);
Q <= D;
endmodule
-module SB_DFFNESS (output Q, input C, E, S, D);
- `SB_DFF_REG
+module SB_DFFNESS (output `SB_DFF_REG, input C, E, S, D);
always @(negedge C)
if (E) begin
if (S)
@@ -303,8 +284,7 @@ module SB_DFFNESS (output Q, input C, E, S, D);
end
endmodule
-module SB_DFFNES (output Q, input C, E, S, D);
- `SB_DFF_REG
+module SB_DFFNES (output `SB_DFF_REG, input C, E, S, D);
always @(negedge C, posedge S)
if (S)
Q <= 1;
@@ -677,7 +657,12 @@ module ICESTORM_LC (
parameter [0:0] SET_NORESET = 0;
parameter [0:0] ASYNC_SR = 0;
- wire COUT = CARRY_ENABLE ? (I1 && I2) || ((I1 || I2) && CIN) : 1'bx;
+ parameter [0:0] CIN_CONST = 0;
+ parameter [0:0] CIN_SET = 0;
+
+ wire mux_cin = CIN_CONST ? CIN_SET : CIN;
+
+ assign COUT = CARRY_ENABLE ? (I1 && I2) || ((I1 || I2) && mux_cin) : 1'bx;
wire [7:0] lut_s3 = I3 ? LUT_INIT[15:8] : LUT_INIT[7:0];
wire [3:0] lut_s2 = I2 ? lut_s3[ 7:4] : lut_s3[3:0];
@@ -881,3 +866,368 @@ module SB_WARMBOOT (
input S0
);
endmodule
+
+// UltraPlus feature cells
+(* blackbox *)
+module SB_MAC16 (
+ input CLK,
+ input CE,
+ input [15:0] C,
+ input [15:0] A,
+ input [15:0] B,
+ input [15:0] D,
+ input AHOLD,
+ input BHOLD,
+ input CHOLD,
+ input DHOLD,
+ input IRSTTOP,
+ input IRSTBOT,
+ input ORSTTOP,
+ input ORSTBOT,
+ input OLOADTOP,
+ input OLOADBOT,
+ input ADDSUBTOP,
+ input ADDSUBBOT,
+ input OHOLDTOP,
+ input OHOLDBOT,
+ input CI,
+ input ACCUMCI,
+ input SIGNEXTIN,
+ output [31:0] O,
+ output CO,
+ output ACCUMCO,
+ output SIGNEXTOUT
+);
+parameter NEG_TRIGGER = 1'b0;
+parameter C_REG = 1'b0;
+parameter A_REG = 1'b0;
+parameter B_REG = 1'b0;
+parameter D_REG = 1'b0;
+parameter TOP_8x8_MULT_REG = 1'b0;
+parameter BOT_8x8_MULT_REG = 1'b0;
+parameter PIPELINE_16x16_MULT_REG1 = 1'b0;
+parameter PIPELINE_16x16_MULT_REG2 = 1'b0;
+parameter TOPOUTPUT_SELECT = 2'b00;
+parameter TOPADDSUB_LOWERINPUT = 2'b00;
+parameter TOPADDSUB_UPPERINPUT = 1'b0;
+parameter TOPADDSUB_CARRYSELECT = 2'b00;
+parameter BOTOUTPUT_SELECT = 2'b00;
+parameter BOTADDSUB_LOWERINPUT = 2'b00;
+parameter BOTADDSUB_UPPERINPUT = 1'b0;
+parameter BOTADDSUB_CARRYSELECT = 2'b00;
+parameter MODE_8x8 = 1'b0;
+parameter A_SIGNED = 1'b0;
+parameter B_SIGNED = 1'b0;
+endmodule
+
+(* blackbox *)
+module SB_SPRAM256KA(
+ input [13:0] ADDRESS,
+ input [15:0] DATAIN,
+ input [3:0] MASKWREN,
+ input WREN,
+ input CHIPSELECT,
+ input CLOCK,
+ input STANDBY,
+ input SLEEP,
+ input POWEROFF,
+ output [15:0] DATAOUT
+);
+endmodule
+
+(* blackbox *)
+module SB_HFOSC(
+ input CLKHFPU,
+ input CLKHFEN,
+ output CLKHF
+);
+parameter CLKHF_DIV = "0b00";
+endmodule
+
+(* blackbox *)
+module SB_LFOSC(
+ input CLKLFPU,
+ input CLKLFEN,
+ output CLKLF
+);
+endmodule
+
+(* blackbox *)
+module SB_RGBA_DRV(
+ input CURREN,
+ input RGBLEDEN,
+ input RGB0PWM,
+ input RGB1PWM,
+ input RGB2PWM,
+ output RGB0,
+ output RGB1,
+ output RGB2
+);
+parameter CURRENT_MODE = "0b0";
+parameter RGB0_CURRENT = "0b000000";
+parameter RGB1_CURRENT = "0b000000";
+parameter RGB2_CURRENT = "0b000000";
+endmodule
+
+(* blackbox *)
+module SB_I2C(
+ input SBCLKI,
+ input SBRWI,
+ input SBSTBI,
+ input SBADRI7,
+ input SBADRI6,
+ input SBADRI5,
+ input SBADRI4,
+ input SBADRI3,
+ input SBADRI2,
+ input SBADRI1,
+ input SBADRI0,
+ input SBDATI7,
+ input SBDATI6,
+ input SBDATI5,
+ input SBDATI4,
+ input SBDATI3,
+ input SBDATI2,
+ input SBDATI1,
+ input SBDATI0,
+ input SCLI,
+ input SDAI,
+ output SBDATO7,
+ output SBDATO6,
+ output SBDATO5,
+ output SBDATO4,
+ output SBDATO3,
+ output SBDATO2,
+ output SBDATO1,
+ output SBDATO0,
+ output SBACKO,
+ output I2CIRQ,
+ output I2CWKUP,
+ output SCLO, //inout in the SB verilog library, but output in the VHDL and PDF libs and seemingly in the HW itself
+ output SCLOE,
+ output SDAO,
+ output SDAOE
+);
+parameter I2C_SLAVE_INIT_ADDR = "0b1111100001";
+parameter BUS_ADDR74 = "0b0001";
+endmodule
+
+(* blackbox *)
+module SB_SPI (
+ input SBCLKI,
+ input SBRWI,
+ input SBSTBI,
+ input SBADRI7,
+ input SBADRI6,
+ input SBADRI5,
+ input SBADRI4,
+ input SBADRI3,
+ input SBADRI2,
+ input SBADRI1,
+ input SBADRI0,
+ input SBDATI7,
+ input SBDATI6,
+ input SBDATI5,
+ input SBDATI4,
+ input SBDATI3,
+ input SBDATI2,
+ input SBDATI1,
+ input SBDATI0,
+ input MI,
+ input SI,
+ input SCKI,
+ input SCSNI,
+ output SBDATO7,
+ output SBDATO6,
+ output SBDATO5,
+ output SBDATO4,
+ output SBDATO3,
+ output SBDATO2,
+ output SBDATO1,
+ output SBDATO0,
+ output SBACKO,
+ output SPIIRQ,
+ output SPIWKUP,
+ output SO,
+ output SOE,
+ output MO,
+ output MOE,
+ output SCKO, //inout in the SB verilog library, but output in the VHDL and PDF libs and seemingly in the HW itself
+ output SCKOE,
+ output MCSNO3,
+ output MCSNO2,
+ output MCSNO1,
+ output MCSNO0,
+ output MCSNOE3,
+ output MCSNOE2,
+ output MCSNOE1,
+ output MCSNOE0
+);
+parameter BUS_ADDR74 = "0b0000";
+endmodule
+
+(* blackbox *)
+module SB_LEDDA_IP(
+ input LEDDCS,
+ input LEDDCLK,
+ input LEDDDAT7,
+ input LEDDDAT6,
+ input LEDDDAT5,
+ input LEDDDAT4,
+ input LEDDDAT3,
+ input LEDDDAT2,
+ input LEDDDAT1,
+ input LEDDDAT0,
+ input LEDDADDR3,
+ input LEDDADDR2,
+ input LEDDADDR1,
+ input LEDDADDR0,
+ input LEDDDEN,
+ input LEDDEXE,
+ input LEDDRST,
+ output PWMOUT0,
+ output PWMOUT1,
+ output PWMOUT2,
+ output LEDDON
+);
+endmodule
+
+(* blackbox *)
+module SB_FILTER_50NS(
+ input FILTERIN,
+ output FILTEROUT
+);
+endmodule
+
+module SB_IO_I3C (
+ inout PACKAGE_PIN,
+ input LATCH_INPUT_VALUE,
+ input CLOCK_ENABLE,
+ input INPUT_CLK,
+ input OUTPUT_CLK,
+ input OUTPUT_ENABLE,
+ input D_OUT_0,
+ input D_OUT_1,
+ output D_IN_0,
+ output D_IN_1,
+ input PU_ENB,
+ input WEAK_PU_ENB
+);
+ parameter [5:0] PIN_TYPE = 6'b000000;
+ parameter [0:0] PULLUP = 1'b0;
+ parameter [0:0] WEAK_PULLUP = 1'b0;
+ parameter [0:0] NEG_TRIGGER = 1'b0;
+ parameter IO_STANDARD = "SB_LVCMOS";
+
+`ifndef BLACKBOX
+ reg dout, din_0, din_1;
+ reg din_q_0, din_q_1;
+ reg dout_q_0, dout_q_1;
+ reg outena_q;
+
+ generate if (!NEG_TRIGGER) begin
+ always @(posedge INPUT_CLK) if (CLOCK_ENABLE) din_q_0 <= PACKAGE_PIN;
+ always @(negedge INPUT_CLK) if (CLOCK_ENABLE) din_q_1 <= PACKAGE_PIN;
+ always @(posedge OUTPUT_CLK) if (CLOCK_ENABLE) dout_q_0 <= D_OUT_0;
+ always @(negedge OUTPUT_CLK) if (CLOCK_ENABLE) dout_q_1 <= D_OUT_1;
+ always @(posedge OUTPUT_CLK) if (CLOCK_ENABLE) outena_q <= OUTPUT_ENABLE;
+ end else begin
+ always @(negedge INPUT_CLK) if (CLOCK_ENABLE) din_q_0 <= PACKAGE_PIN;
+ always @(posedge INPUT_CLK) if (CLOCK_ENABLE) din_q_1 <= PACKAGE_PIN;
+ always @(negedge OUTPUT_CLK) if (CLOCK_ENABLE) dout_q_0 <= D_OUT_0;
+ always @(posedge OUTPUT_CLK) if (CLOCK_ENABLE) dout_q_1 <= D_OUT_1;
+ always @(negedge OUTPUT_CLK) if (CLOCK_ENABLE) outena_q <= OUTPUT_ENABLE;
+ end endgenerate
+
+ always @* begin
+ if (!PIN_TYPE[1] || !LATCH_INPUT_VALUE)
+ din_0 = PIN_TYPE[0] ? PACKAGE_PIN : din_q_0;
+ din_1 = din_q_1;
+ end
+
+ // work around simulation glitches on dout in DDR mode
+ reg outclk_delayed_1;
+ reg outclk_delayed_2;
+ always @* outclk_delayed_1 <= OUTPUT_CLK;
+ always @* outclk_delayed_2 <= outclk_delayed_1;
+
+ always @* begin
+ if (PIN_TYPE[3])
+ dout = PIN_TYPE[2] ? !dout_q_0 : D_OUT_0;
+ else
+ dout = (outclk_delayed_2 ^ NEG_TRIGGER) || PIN_TYPE[2] ? dout_q_0 : dout_q_1;
+ end
+
+ assign D_IN_0 = din_0, D_IN_1 = din_1;
+
+ generate
+ if (PIN_TYPE[5:4] == 2'b01) assign PACKAGE_PIN = dout;
+ if (PIN_TYPE[5:4] == 2'b10) assign PACKAGE_PIN = OUTPUT_ENABLE ? dout : 1'bz;
+ if (PIN_TYPE[5:4] == 2'b11) assign PACKAGE_PIN = outena_q ? dout : 1'bz;
+ endgenerate
+`endif
+endmodule
+
+module SB_IO_OD (
+ inout PACKAGEPIN,
+ input LATCHINPUTVALUE,
+ input CLOCKENABLE,
+ input INPUTCLK,
+ input OUTPUTCLK,
+ input OUTPUTENABLE,
+ input DOUT1,
+ input DOUT0,
+ output DIN1,
+ output DIN0
+);
+ parameter [5:0] PIN_TYPE = 6'b000000;
+ parameter [0:0] NEG_TRIGGER = 1'b0;
+
+`ifndef BLACKBOX
+ reg dout, din_0, din_1;
+ reg din_q_0, din_q_1;
+ reg dout_q_0, dout_q_1;
+ reg outena_q;
+
+ generate if (!NEG_TRIGGER) begin
+ always @(posedge INPUTCLK) if (CLOCKENABLE) din_q_0 <= PACKAGEPIN;
+ always @(negedge INPUTCLK) if (CLOCKENABLE) din_q_1 <= PACKAGEPIN;
+ always @(posedge OUTPUTCLK) if (CLOCKENABLE) dout_q_0 <= DOUT0;
+ always @(negedge OUTPUTCLK) if (CLOCKENABLE) dout_q_1 <= DOUT1;
+ always @(posedge OUTPUTCLK) if (CLOCKENABLE) outena_q <= OUTPUTENABLE;
+ end else begin
+ always @(negedge INPUTCLK) if (CLOCKENABLE) din_q_0 <= PACKAGEPIN;
+ always @(posedge INPUTCLK) if (CLOCKENABLE) din_q_1 <= PACKAGEPIN;
+ always @(negedge OUTPUTCLK) if (CLOCKENABLE) dout_q_0 <= DOUT0;
+ always @(posedge OUTPUTCLK) if (CLOCKENABLE) dout_q_1 <= DOUT1;
+ always @(negedge OUTPUTCLK) if (CLOCKENABLE) outena_q <= OUTPUTENABLE;
+ end endgenerate
+
+ always @* begin
+ if (!PIN_TYPE[1] || !LATCHINPUTVALUE)
+ din_0 = PIN_TYPE[0] ? PACKAGEPIN : din_q_0;
+ din_1 = din_q_1;
+ end
+
+ // work around simulation glitches on dout in DDR mode
+ reg outclk_delayed_1;
+ reg outclk_delayed_2;
+ always @* outclk_delayed_1 <= OUTPUTCLK;
+ always @* outclk_delayed_2 <= outclk_delayed_1;
+
+ always @* begin
+ if (PIN_TYPE[3])
+ dout = PIN_TYPE[2] ? !dout_q_0 : DOUT0;
+ else
+ dout = (outclk_delayed_2 ^ NEG_TRIGGER) || PIN_TYPE[2] ? dout_q_0 : dout_q_1;
+ end
+
+ assign DIN0 = din_0, DIN1 = din_1;
+
+ generate
+ if (PIN_TYPE[5:4] == 2'b01) assign PACKAGEPIN = dout ? 1'bz : 1'b0;
+ if (PIN_TYPE[5:4] == 2'b10) assign PACKAGEPIN = OUTPUTENABLE ? (dout ? 1'bz : 1'b0) : 1'bz;
+ if (PIN_TYPE[5:4] == 2'b11) assign PACKAGEPIN = outena_q ? (dout ? 1'bz : 1'b0) : 1'bz;
+ endgenerate
+`endif
+endmodule
diff --git a/techlibs/ice40/ice40_ffinit.cc b/techlibs/ice40/ice40_ffinit.cc
index c914b20e..3089d893 100644
--- a/techlibs/ice40/ice40_ffinit.cc
+++ b/techlibs/ice40/ice40_ffinit.cc
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
struct Ice40FfinitPass : public Pass {
Ice40FfinitPass() : Pass("ice40_ffinit", "iCE40: handle FF init values") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -35,7 +35,7 @@ struct Ice40FfinitPass : public Pass {
log("nonzero init values.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing ICE40_FFINIT pass (implement FF init values).\n");
diff --git a/techlibs/ice40/ice40_ffssr.cc b/techlibs/ice40/ice40_ffssr.cc
index 9afbc0fc..668df09d 100644
--- a/techlibs/ice40/ice40_ffssr.cc
+++ b/techlibs/ice40/ice40_ffssr.cc
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
struct Ice40FfssrPass : public Pass {
Ice40FfssrPass() : Pass("ice40_ffssr", "iCE40: merge synchronous set/reset into FF cells") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
log("\n");
log(" ice40_ffssr [options] [selection]\n");
@@ -33,7 +33,7 @@ struct Ice40FfssrPass : public Pass {
log("Merge synchronous set/reset $_MUX_ cells into iCE40 FFs.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing ICE40_FFSSR pass (merge synchronous set/reset into FF cells).\n");
diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc
index ae72f5d6..16274005 100644
--- a/techlibs/ice40/ice40_opt.cc
+++ b/techlibs/ice40/ice40_opt.cc
@@ -26,6 +26,13 @@
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 run_ice40_opts(Module *module, bool unlut_mode)
{
pool<SigBit> optimized_co;
@@ -45,7 +52,11 @@ static void run_ice40_opts(Module *module, bool unlut_mode)
SigSpec non_const_inputs, replacement_output;
int count_zeros = 0, count_ones = 0;
- SigBit inbit[3] = {cell->getPort("\\I0"), cell->getPort("\\I1"), cell->getPort("\\CI")};
+ SigBit inbit[3] = {
+ get_bit_or_zero(cell->getPort("\\I0")),
+ get_bit_or_zero(cell->getPort("\\I1")),
+ get_bit_or_zero(cell->getPort("\\CI"))
+ };
for (int i = 0; i < 3; i++)
if (inbit[i].wire == nullptr) {
if (inbit[i] == State::S1)
@@ -63,8 +74,8 @@ static void run_ice40_opts(Module *module, bool unlut_mode)
replacement_output = non_const_inputs;
if (GetSize(replacement_output)) {
- optimized_co.insert(sigmap(cell->getPort("\\CO")));
- module->connect(cell->getPort("\\CO"), replacement_output);
+ optimized_co.insert(sigmap(cell->getPort("\\CO")[0]));
+ module->connect(cell->getPort("\\CO")[0], replacement_output);
module->design->scratchpad_set_bool("opt.did_something", true);
log("Optimized away SB_CARRY cell %s.%s: CO=%s\n",
log_id(module), log_id(cell), log_signal(replacement_output));
@@ -78,10 +89,10 @@ static void run_ice40_opts(Module *module, bool unlut_mode)
{
SigSpec inbits;
- inbits.append(cell->getPort("\\I0"));
- inbits.append(cell->getPort("\\I1"));
- inbits.append(cell->getPort("\\I2"));
- inbits.append(cell->getPort("\\I3"));
+ inbits.append(get_bit_or_zero(cell->getPort("\\I0")));
+ inbits.append(get_bit_or_zero(cell->getPort("\\I1")));
+ inbits.append(get_bit_or_zero(cell->getPort("\\I2")));
+ inbits.append(get_bit_or_zero(cell->getPort("\\I3")));
sigmap.apply(inbits);
if (unlut_mode)
@@ -104,8 +115,13 @@ static void run_ice40_opts(Module *module, bool unlut_mode)
cell->setParam("\\LUT", cell->getParam("\\LUT_INIT"));
cell->unsetParam("\\LUT_INIT");
- cell->setPort("\\A", SigSpec({cell->getPort("\\I3"), cell->getPort("\\I2"), cell->getPort("\\I1"), cell->getPort("\\I0")}));
- cell->setPort("\\Y", cell->getPort("\\O"));
+ cell->setPort("\\A", SigSpec({
+ get_bit_or_zero(cell->getPort("\\I3")),
+ get_bit_or_zero(cell->getPort("\\I2")),
+ get_bit_or_zero(cell->getPort("\\I1")),
+ get_bit_or_zero(cell->getPort("\\I0"))
+ }));
+ cell->setPort("\\Y", cell->getPort("\\O")[0]);
cell->unsetPort("\\I0");
cell->unsetPort("\\I1");
cell->unsetPort("\\I2");
@@ -120,7 +136,7 @@ static void run_ice40_opts(Module *module, bool unlut_mode)
struct Ice40OptPass : public Pass {
Ice40OptPass() : Pass("ice40_opt", "iCE40: perform simple optimizations") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -140,7 +156,7 @@ struct Ice40OptPass : public Pass {
log("mapped SB_LUT4 cells back to logic.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
string opt_expr_args = "-mux_undef -undriven";
bool unlut_mode = false;
diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc
index 2533d3af..b0687e5e 100644
--- a/techlibs/ice40/synth_ice40.cc
+++ b/techlibs/ice40/synth_ice40.cc
@@ -29,7 +29,7 @@ struct SynthIce40Pass : public ScriptPass
{
SynthIce40Pass() : ScriptPass("synth_ice40", "synthesis for iCE40 FPGAs") { }
- virtual void help() YS_OVERRIDE
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -38,14 +38,18 @@ struct SynthIce40Pass : public ScriptPass
log("This command runs synthesis for iCE40 FPGAs.\n");
log("\n");
log(" -top <module>\n");
- log(" use the specified module as top module (default='top')\n");
+ log(" use the specified module as top module\n");
log("\n");
log(" -blif <file>\n");
log(" write the design to the specified BLIF file. writing of an output file\n");
log(" is omitted if this parameter is not specified.\n");
log("\n");
log(" -edif <file>\n");
- log(" write the design to the specified edif file. writing of an output file\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 <file>\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 <from_label>:<to_label>\n");
@@ -62,34 +66,44 @@ struct SynthIce40Pass : public ScriptPass
log(" -nocarry\n");
log(" do not use SB_CARRY cells in output netlist\n");
log("\n");
+ log(" -nodffe\n");
+ log(" do not use SB_DFFE* cells in output netlist\n");
+ log("\n");
log(" -nobram\n");
log(" do not use SB_RAM40_4K* cells in output netlist\n");
log("\n");
log(" -abc2\n");
log(" run two passes of 'abc' for slightly improved logic density\n");
log("\n");
+ log(" -vpr\n");
+ log(" generate an output netlist (and BLIF file) suitable for VPR\n");
+ log(" (this feature is experimental and incomplete)\n");
+ log("\n");
log("\n");
log("The following commands are executed by this synthesis command:\n");
help_script();
log("\n");
}
- string top_opt, blif_file, edif_file;
- bool nocarry, nobram, flatten, retime, abc2;
+ string top_opt, blif_file, edif_file, json_file;
+ bool nocarry, nodffe, nobram, flatten, retime, abc2, vpr;
- virtual void clear_flags() YS_OVERRIDE
+ void clear_flags() YS_OVERRIDE
{
top_opt = "-auto-top";
blif_file = "";
edif_file = "";
+ json_file = "";
nocarry = false;
+ nodffe = false;
nobram = false;
flatten = true;
retime = false;
abc2 = false;
+ vpr = false;
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
string run_from, run_to;
clear_flags();
@@ -109,6 +123,10 @@ struct SynthIce40Pass : public ScriptPass
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)
@@ -133,6 +151,10 @@ struct SynthIce40Pass : public ScriptPass
nocarry = true;
continue;
}
+ if (args[argidx] == "-nodffe") {
+ nodffe = true;
+ continue;
+ }
if (args[argidx] == "-nobram") {
nobram = true;
continue;
@@ -141,6 +163,10 @@ struct SynthIce40Pass : public ScriptPass
abc2 = true;
continue;
}
+ if (args[argidx] == "-vpr") {
+ vpr = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -156,7 +182,7 @@ struct SynthIce40Pass : public ScriptPass
log_pop();
}
- virtual void script() YS_OVERRIDE
+ void script() YS_OVERRIDE
{
if (check_label("begin"))
{
@@ -200,8 +226,9 @@ struct SynthIce40Pass : public ScriptPass
if (check_label("map_ffs"))
{
run("dffsr2dff");
- run("dff2dffe -direct-match $_DFF_*");
- run("techmap -map +/ice40/cells_map.v");
+ if (!nodffe)
+ run("dff2dffe -direct-match $_DFF_*");
+ run("techmap -D NO_LUT -map +/ice40/cells_map.v");
run("opt_expr -mux_undef");
run("simplemap");
run("ice40_ffinit");
@@ -222,7 +249,11 @@ struct SynthIce40Pass : public ScriptPass
if (check_label("map_cells"))
{
- run("techmap -map +/ice40/cells_map.v");
+ if (vpr)
+ run("techmap -D NO_LUT -map +/ice40/cells_map.v");
+ else
+ run("techmap -map +/ice40/cells_map.v", "(with -D NO_LUT in vpr mode)");
+
run("clean");
}
@@ -235,8 +266,19 @@ struct SynthIce40Pass : public ScriptPass
if (check_label("blif"))
{
- if (!blif_file.empty() || help_mode)
- run(stringf("write_blif -gates -attr -param %s", help_mode ? "<file-name>" : blif_file.c_str()));
+ if (!blif_file.empty() || help_mode) {
+ if (vpr || help_mode) {
+ run(stringf("opt_clean -purge"),
+ " (vpr mode)");
+ run(stringf("write_blif -attr -cname -conn -param %s",
+ help_mode ? "<file-name>" : blif_file.c_str()),
+ " (vpr mode)");
+ }
+ if (!vpr)
+ run(stringf("write_blif -gates -attr -param %s",
+ help_mode ? "<file-name>" : blif_file.c_str()),
+ " (non-vpr mode)");
+ }
}
if (check_label("edif"))
@@ -244,6 +286,12 @@ struct SynthIce40Pass : public ScriptPass
if (!edif_file.empty() || help_mode)
run(stringf("write_edif %s", help_mode ? "<file-name>" : edif_file.c_str()));
}
+
+ if (check_label("json"))
+ {
+ if (!json_file.empty() || help_mode)
+ run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));
+ }
}
} SynthIce40Pass;
diff --git a/techlibs/intel/Makefile.inc b/techlibs/intel/Makefile.inc
new file mode 100644
index 00000000..ec7cea37
--- /dev/null
+++ b/techlibs/intel/Makefile.inc
@@ -0,0 +1,24 @@
+
+OBJS += techlibs/intel/synth_intel.o
+
+$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/m9k_bb.v))
+$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/altpll_bb.v))
+$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams.txt))
+$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_map.v))
+$(eval $(call add_share_file,share/intel/max10,techlibs/intel/max10/cells_sim.v))
+$(eval $(call add_share_file,share/intel/a10gx,techlibs/intel/a10gx/cells_sim.v))
+$(eval $(call add_share_file,share/intel/cyclonev,techlibs/intel/cyclonev/cells_sim.v))
+$(eval $(call add_share_file,share/intel/cyclone10,techlibs/intel/cyclone10/cells_sim.v))
+$(eval $(call add_share_file,share/intel/cycloneiv,techlibs/intel/cycloneiv/cells_sim.v))
+$(eval $(call add_share_file,share/intel/cycloneive,techlibs/intel/cycloneive/cells_sim.v))
+$(eval $(call add_share_file,share/intel/max10,techlibs/intel/max10/cells_map.v))
+$(eval $(call add_share_file,share/intel/a10gx,techlibs/intel/a10gx/cells_map.v))
+$(eval $(call add_share_file,share/intel/cyclonev,techlibs/intel/cyclonev/cells_map.v))
+$(eval $(call add_share_file,share/intel/cyclone10,techlibs/intel/cyclone10/cells_map.v))
+$(eval $(call add_share_file,share/intel/cycloneiv,techlibs/intel/cycloneiv/cells_map.v))
+$(eval $(call add_share_file,share/intel/cycloneive,techlibs/intel/cycloneive/cells_map.v))
+#$(eval $(call add_share_file,share/intel/max10,techlibs/intel/max10/arith_map.v))
+#$(eval $(call add_share_file,share/intel/a10gx,techlibs/intel/a10gx/arith_map.v))
+#$(eval $(call add_share_file,share/intel/cycloneiv,techlibs/intel/cycloneiv/arith_map.v))
+#$(eval $(call add_share_file,share/intel/cycloneive,techlibs/intel/cycloneive/arith_map.v))
+
diff --git a/techlibs/intel/a10gx/cells_arith.v b/techlibs/intel/a10gx/cells_arith.v
new file mode 100644
index 00000000..89fb4561
--- /dev/null
+++ b/techlibs/intel/a10gx/cells_arith.v
@@ -0,0 +1,65 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+
+// NOTE: This is still WIP.
+(* techmap_celltype = "$alu" *)
+module _80_altera_a10gx_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 [Y_WIDTH-1:0] CO;
+ output CO;
+
+ wire _TECHMAP_FAIL_ = Y_WIDTH <= 4;
+
+ 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:0] C = {CO, CI};
+ wire [Y_WIDTH+1:0] COx;
+ wire [Y_WIDTH+1:0] C = {COx, CI};
+
+ /* Start implementation */
+ (* keep *) fiftyfivenm_lcell_comb #(.lut_mask(16'b0000_0000_1010_1010), .sum_lutc_input("cin")) carry_start (.cout(COx[0]), .dataa(C[0]), .datab(1'b1), .datac(1'b1), .datad(1'b1));
+
+ genvar i;
+ generate for (i = 0; i < Y_WIDTH; i = i + 1) begin: slice
+ if(i==Y_WIDTH-1) begin
+ (* keep *) fiftyfivenm_lcell_comb #(.lut_mask(16'b1111_0000_1110_0000), .sum_lutc_input("cin")) carry_end (.combout(COx[Y_WIDTH]), .dataa(1'b1), .datab(1'b1), .datac(1'b1), .datad(1'b1), .cin(C[Y_WIDTH]));
+ assign CO = COx[Y_WIDTH];
+ end
+ else
+ fiftyfivenm_lcell_comb #(.lut_mask(16'b1001_0110_1110_1000), .sum_lutc_input("cin")) arith_cell (.combout(Y[i]), .cout(COx[i+1]), .dataa(AA[i]), .datab(BB[i]), .datac(1'b1), .datad(1'b1), .cin(C[i+1]));
+ end: slice
+ endgenerate
+ /* End implementation */
+ assign X = AA ^ BB;
+
+endmodule
diff --git a/techlibs/intel/a10gx/cells_map.v b/techlibs/intel/a10gx/cells_map.v
new file mode 100644
index 00000000..1430e855
--- /dev/null
+++ b/techlibs/intel/a10gx/cells_map.v
@@ -0,0 +1,53 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+// Input buffer map
+module \$__inpad (input I, output O);
+ twentynm_io_ibuf _TECHMAP_REPLACE_ (.o(O), .i(I), .ibar(1'b0));
+endmodule
+
+// Output buffer map
+module \$__outpad (input I, output O);
+ twentynm_io_obuf _TECHMAP_REPLACE_ (.o(O), .i(I), .oe(1'b1));
+endmodule
+
+// LUT Map
+module \$lut (A, Y);
+ parameter WIDTH = 0;
+ parameter LUT = 0;
+ input [WIDTH-1:0] A;
+ output Y;
+ generate
+ if (WIDTH == 1) begin
+ assign Y = ~A[0]; // Not need to spend 1 logic cell for such an easy function
+ end else
+ if (WIDTH == 2) begin
+ twentynm_lcell_comb #(.lut_mask({16{LUT}}), .shared_arith("off"), .extended_lut("off"))
+ _TECHMAP_REPLACE_ (.combout(Y), .dataa(A[0]), .datab(A[1]), .datac(1'b1),.datad(1'b1), .datae(1'b1), .dataf(1'b1), .datag(1'b1));
+ end /*else
+ if(WIDTH == 3) begin
+ fiftyfivenm_lcell_comb #(.lut_mask({2{LUT}}), .sum_lutc_input("datac")) _TECHMAP_REPLACE_ (.combout(Y), .dataa(A[0]), .datab(A[1]), .datac(A[2]),.datad(1'b1));
+ end else
+ if(WIDTH == 4) begin
+ fiftyfivenm_lcell_comb #(.lut_mask(LUT), .sum_lutc_input("datac")) _TECHMAP_REPLACE_ (.combout(Y), .dataa(A[0]), .datab(A[1]), .datac(A[2]),.datad(A[3]));
+ end*/ else
+ wire _TECHMAP_FAIL_ = 1;
+ endgenerate
+endmodule //
+
+
diff --git a/techlibs/intel/a10gx/cells_sim.v b/techlibs/intel/a10gx/cells_sim.v
new file mode 100644
index 00000000..e892b377
--- /dev/null
+++ b/techlibs/intel/a10gx/cells_sim.v
@@ -0,0 +1,59 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+module VCC (output V);
+ assign V = 1'b1;
+endmodule // VCC
+
+module GND (output G);
+ assign G = 1'b0;
+endmodule // GND
+
+/* Altera Arria 10 GX devices Input Buffer Primitive */
+module twentynm_io_ibuf (output o, input i, input ibar);
+ assign ibar = ibar;
+ assign o = i;
+endmodule // twentynm_io_ibuf
+
+/* Altera Arria 10 GX devices Output Buffer Primitive */
+module twentynm_io_obuf (output o, input i, input oe);
+ assign o = i;
+ assign oe = oe;
+endmodule // twentynm_io_obuf
+
+/* Altera Arria 10 GX LUT Primitive */
+module twentynm_lcell_comb (output combout, cout, sumout,
+ input dataa, datab, datac, datad,
+ input datae, dataf, datag, cin,
+ input sharein);
+
+parameter lut_mask = 64'hFFFFFFFFFFFFFFFF;
+parameter dont_touch = "off";
+parameter lpm_type = "twentynm_lcell_comb";
+parameter shared_arith = "off";
+parameter extended_lut = "off";
+
+// TODO: This is still WIP
+initial begin
+ $display("Simulation model is still under investigation\n");
+end
+
+endmodule // twentynm_lcell_comb
+
+
+
diff --git a/techlibs/intel/common/altpll_bb.v b/techlibs/intel/common/altpll_bb.v
new file mode 100644
index 00000000..d2e6a364
--- /dev/null
+++ b/techlibs/intel/common/altpll_bb.v
@@ -0,0 +1,366 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+/* No clearbox model */
+`ifdef NO_CLEARBOX
+(* blackbox *)
+module altpll
+ ( inclk,
+ fbin,
+ pllena,
+ clkswitch,
+ areset,
+ pfdena,
+ clkena,
+ extclkena,
+ scanclk,
+ scanaclr,
+ scanclkena,
+ scanread,
+ scanwrite,
+ scandata,
+ phasecounterselect,
+ phaseupdown,
+ phasestep,
+ configupdate,
+ fbmimicbidir,
+ clk,
+ extclk,
+ clkbad,
+ enable0,
+ enable1,
+ activeclock,
+ clkloss,
+ locked,
+ scandataout,
+ scandone,
+ sclkout0,
+ sclkout1,
+ phasedone,
+ vcooverrange,
+ vcounderrange,
+ fbout,
+ fref,
+ icdrclk,
+ c0,
+ c1,
+ c2,
+ c3,
+ c4);
+
+ parameter intended_device_family = "MAX 10";
+ parameter operation_mode = "NORMAL";
+ parameter pll_type = "AUTO";
+ parameter qualify_conf_done = "OFF";
+ parameter compensate_clock = "CLK0";
+ parameter scan_chain = "LONG";
+ parameter primary_clock = "inclk0";
+ parameter inclk0_input_frequency = 1000;
+ parameter inclk1_input_frequency = 0;
+ parameter gate_lock_signal = "NO";
+ parameter gate_lock_counter = 0;
+ parameter lock_high = 1;
+ parameter lock_low = 0;
+ parameter valid_lock_multiplier = 1;
+ parameter invalid_lock_multiplier = 5;
+ parameter switch_over_type = "AUTO";
+ parameter switch_over_on_lossclk = "OFF" ;
+ parameter switch_over_on_gated_lock = "OFF" ;
+ parameter enable_switch_over_counter = "OFF";
+ parameter switch_over_counter = 0;
+ parameter feedback_source = "EXTCLK0" ;
+ parameter bandwidth = 0;
+ parameter bandwidth_type = "UNUSED";
+ parameter lpm_hint = "UNUSED";
+ parameter spread_frequency = 0;
+ parameter down_spread = "0.0";
+ parameter self_reset_on_gated_loss_lock = "OFF";
+ parameter self_reset_on_loss_lock = "OFF";
+ parameter lock_window_ui = "0.05";
+ parameter width_clock = 6;
+ parameter width_phasecounterselect = 4;
+ parameter charge_pump_current_bits = 9999;
+ parameter loop_filter_c_bits = 9999;
+ parameter loop_filter_r_bits = 9999;
+ parameter scan_chain_mif_file = "UNUSED";
+ parameter clk9_multiply_by = 1;
+ parameter clk8_multiply_by = 1;
+ parameter clk7_multiply_by = 1;
+ parameter clk6_multiply_by = 1;
+ parameter clk5_multiply_by = 1;
+ parameter clk4_multiply_by = 1;
+ parameter clk3_multiply_by = 1;
+ parameter clk2_multiply_by = 1;
+ parameter clk1_multiply_by = 1;
+ parameter clk0_multiply_by = 1;
+ parameter clk9_divide_by = 1;
+ parameter clk8_divide_by = 1;
+ parameter clk7_divide_by = 1;
+ parameter clk6_divide_by = 1;
+ parameter clk5_divide_by = 1;
+ parameter clk4_divide_by = 1;
+ parameter clk3_divide_by = 1;
+ parameter clk2_divide_by = 1;
+ parameter clk1_divide_by = 1;
+ parameter clk0_divide_by = 1;
+ parameter clk9_phase_shift = "0";
+ parameter clk8_phase_shift = "0";
+ parameter clk7_phase_shift = "0";
+ parameter clk6_phase_shift = "0";
+ parameter clk5_phase_shift = "0";
+ parameter clk4_phase_shift = "0";
+ parameter clk3_phase_shift = "0";
+ parameter clk2_phase_shift = "0";
+ parameter clk1_phase_shift = "0";
+ parameter clk0_phase_shift = "0";
+
+ parameter clk9_duty_cycle = 50;
+ parameter clk8_duty_cycle = 50;
+ parameter clk7_duty_cycle = 50;
+ parameter clk6_duty_cycle = 50;
+ parameter clk5_duty_cycle = 50;
+ parameter clk4_duty_cycle = 50;
+ parameter clk3_duty_cycle = 50;
+ parameter clk2_duty_cycle = 50;
+ parameter clk1_duty_cycle = 50;
+ parameter clk0_duty_cycle = 50;
+
+ parameter clk9_use_even_counter_mode = "OFF";
+ parameter clk8_use_even_counter_mode = "OFF";
+ parameter clk7_use_even_counter_mode = "OFF";
+ parameter clk6_use_even_counter_mode = "OFF";
+ parameter clk5_use_even_counter_mode = "OFF";
+ parameter clk4_use_even_counter_mode = "OFF";
+ parameter clk3_use_even_counter_mode = "OFF";
+ parameter clk2_use_even_counter_mode = "OFF";
+ parameter clk1_use_even_counter_mode = "OFF";
+ parameter clk0_use_even_counter_mode = "OFF";
+ parameter clk9_use_even_counter_value = "OFF";
+ parameter clk8_use_even_counter_value = "OFF";
+ parameter clk7_use_even_counter_value = "OFF";
+ parameter clk6_use_even_counter_value = "OFF";
+ parameter clk5_use_even_counter_value = "OFF";
+ parameter clk4_use_even_counter_value = "OFF";
+ parameter clk3_use_even_counter_value = "OFF";
+ parameter clk2_use_even_counter_value = "OFF";
+ parameter clk1_use_even_counter_value = "OFF";
+ parameter clk0_use_even_counter_value = "OFF";
+
+ parameter clk2_output_frequency = 0;
+ parameter clk1_output_frequency = 0;
+ parameter clk0_output_frequency = 0;
+
+ parameter vco_min = 0;
+ parameter vco_max = 0;
+ parameter vco_center = 0;
+ parameter pfd_min = 0;
+ parameter pfd_max = 0;
+ parameter m_initial = 1;
+ parameter m = 0;
+ parameter n = 1;
+ parameter m2 = 1;
+ parameter n2 = 1;
+ parameter ss = 0;
+ parameter l0_high = 1;
+ parameter l1_high = 1;
+ parameter g0_high = 1;
+ parameter g1_high = 1;
+ parameter g2_high = 1;
+ parameter g3_high = 1;
+ parameter e0_high = 1;
+ parameter e1_high = 1;
+ parameter e2_high = 1;
+ parameter e3_high = 1;
+ parameter l0_low = 1;
+ parameter l1_low = 1;
+ parameter g0_low = 1;
+ parameter g1_low = 1;
+ parameter g2_low = 1;
+ parameter g3_low = 1;
+ parameter e0_low = 1;
+ parameter e1_low = 1;
+ parameter e2_low = 1;
+ parameter e3_low = 1;
+ parameter l0_initial = 1;
+ parameter l1_initial = 1;
+ parameter g0_initial = 1;
+ parameter g1_initial = 1;
+ parameter g2_initial = 1;
+ parameter g3_initial = 1;
+ parameter e0_initial = 1;
+ parameter e1_initial = 1;
+ parameter e2_initial = 1;
+ parameter e3_initial = 1;
+ parameter l0_mode = "bypass";
+ parameter l1_mode = "bypass";
+ parameter g0_mode = "bypass";
+ parameter g1_mode = "bypass";
+ parameter g2_mode = "bypass";
+ parameter g3_mode = "bypass";
+ parameter e0_mode = "bypass";
+ parameter e1_mode = "bypass";
+ parameter e2_mode = "bypass";
+ parameter e3_mode = "bypass";
+ parameter l0_ph = 0;
+ parameter l1_ph = 0;
+ parameter g0_ph = 0;
+ parameter g1_ph = 0;
+ parameter g2_ph = 0;
+ parameter g3_ph = 0;
+ parameter e0_ph = 0;
+ parameter e1_ph = 0;
+ parameter e2_ph = 0;
+ parameter e3_ph = 0;
+ parameter m_ph = 0;
+ parameter l0_time_delay = 0;
+ parameter l1_time_delay = 0;
+ parameter g0_time_delay = 0;
+ parameter g1_time_delay = 0;
+ parameter g2_time_delay = 0;
+ parameter g3_time_delay = 0;
+ parameter e0_time_delay = 0;
+ parameter e1_time_delay = 0;
+ parameter e2_time_delay = 0;
+ parameter e3_time_delay = 0;
+ parameter m_time_delay = 0;
+ parameter n_time_delay = 0;
+ parameter extclk3_counter = "e3" ;
+ parameter extclk2_counter = "e2" ;
+ parameter extclk1_counter = "e1" ;
+ parameter extclk0_counter = "e0" ;
+ parameter clk9_counter = "c9" ;
+ parameter clk8_counter = "c8" ;
+ parameter clk7_counter = "c7" ;
+ parameter clk6_counter = "c6" ;
+ parameter clk5_counter = "l1" ;
+ parameter clk4_counter = "l0" ;
+ parameter clk3_counter = "g3" ;
+ parameter clk2_counter = "g2" ;
+ parameter clk1_counter = "g1" ;
+ parameter clk0_counter = "g0" ;
+ parameter enable0_counter = "l0";
+ parameter enable1_counter = "l0";
+ parameter charge_pump_current = 2;
+ parameter loop_filter_r = "1.0";
+ parameter loop_filter_c = 5;
+ parameter vco_post_scale = 0;
+ parameter vco_frequency_control = "AUTO";
+ parameter vco_phase_shift_step = 0;
+ parameter lpm_type = "altpll";
+
+ parameter port_clkena0 = "PORT_CONNECTIVITY";
+ parameter port_clkena1 = "PORT_CONNECTIVITY";
+ parameter port_clkena2 = "PORT_CONNECTIVITY";
+ parameter port_clkena3 = "PORT_CONNECTIVITY";
+ parameter port_clkena4 = "PORT_CONNECTIVITY";
+ parameter port_clkena5 = "PORT_CONNECTIVITY";
+ parameter port_extclkena0 = "PORT_CONNECTIVITY";
+ parameter port_extclkena1 = "PORT_CONNECTIVITY";
+ parameter port_extclkena2 = "PORT_CONNECTIVITY";
+ parameter port_extclkena3 = "PORT_CONNECTIVITY";
+ parameter port_extclk0 = "PORT_CONNECTIVITY";
+ parameter port_extclk1 = "PORT_CONNECTIVITY";
+ parameter port_extclk2 = "PORT_CONNECTIVITY";
+ parameter port_extclk3 = "PORT_CONNECTIVITY";
+ parameter port_clk0 = "PORT_CONNECTIVITY";
+ parameter port_clk1 = "PORT_CONNECTIVITY";
+ parameter port_clk2 = "PORT_CONNECTIVITY";
+ parameter port_clk3 = "PORT_CONNECTIVITY";
+ parameter port_clk4 = "PORT_CONNECTIVITY";
+ parameter port_clk5 = "PORT_CONNECTIVITY";
+ parameter port_clk6 = "PORT_CONNECTIVITY";
+ parameter port_clk7 = "PORT_CONNECTIVITY";
+ parameter port_clk8 = "PORT_CONNECTIVITY";
+ parameter port_clk9 = "PORT_CONNECTIVITY";
+ parameter port_scandata = "PORT_CONNECTIVITY";
+ parameter port_scandataout = "PORT_CONNECTIVITY";
+ parameter port_scandone = "PORT_CONNECTIVITY";
+ parameter port_sclkout1 = "PORT_CONNECTIVITY";
+ parameter port_sclkout0 = "PORT_CONNECTIVITY";
+ parameter port_clkbad0 = "PORT_CONNECTIVITY";
+ parameter port_clkbad1 = "PORT_CONNECTIVITY";
+ parameter port_activeclock = "PORT_CONNECTIVITY";
+ parameter port_clkloss = "PORT_CONNECTIVITY";
+ parameter port_inclk1 = "PORT_CONNECTIVITY";
+ parameter port_inclk0 = "PORT_CONNECTIVITY";
+ parameter port_fbin = "PORT_CONNECTIVITY";
+ parameter port_fbout = "PORT_CONNECTIVITY";
+ parameter port_pllena = "PORT_CONNECTIVITY";
+ parameter port_clkswitch = "PORT_CONNECTIVITY";
+ parameter port_areset = "PORT_CONNECTIVITY";
+ parameter port_pfdena = "PORT_CONNECTIVITY";
+ parameter port_scanclk = "PORT_CONNECTIVITY";
+ parameter port_scanaclr = "PORT_CONNECTIVITY";
+ parameter port_scanread = "PORT_CONNECTIVITY";
+ parameter port_scanwrite = "PORT_CONNECTIVITY";
+ parameter port_enable0 = "PORT_CONNECTIVITY";
+ parameter port_enable1 = "PORT_CONNECTIVITY";
+ parameter port_locked = "PORT_CONNECTIVITY";
+ parameter port_configupdate = "PORT_CONNECTIVITY";
+ parameter port_phasecounterselect = "PORT_CONNECTIVITY";
+ parameter port_phasedone = "PORT_CONNECTIVITY";
+ parameter port_phasestep = "PORT_CONNECTIVITY";
+ parameter port_phaseupdown = "PORT_CONNECTIVITY";
+ parameter port_vcooverrange = "PORT_CONNECTIVITY";
+ parameter port_vcounderrange = "PORT_CONNECTIVITY";
+ parameter port_scanclkena = "PORT_CONNECTIVITY";
+ parameter using_fbmimicbidir_port = "ON";
+
+ input [1:0] inclk;
+ input fbin;
+ input pllena;
+ input clkswitch;
+ input areset;
+ input pfdena;
+ input clkena;
+ input extclkena;
+ input scanclk;
+ input scanaclr;
+ input scanclkena;
+ input scanread;
+ input scanwrite;
+ input scandata;
+ input phasecounterselect;
+ input phaseupdown;
+ input phasestep;
+ input configupdate;
+ inout fbmimicbidir;
+
+
+ output [width_clock-1:0] clk;
+ output [3:0] extclk;
+ output [1:0] clkbad;
+ output enable0;
+ output enable1;
+ output activeclock;
+ output clkloss;
+ output locked;
+ output scandataout;
+ output scandone;
+ output sclkout0;
+ output sclkout1;
+ output phasedone;
+ output vcooverrange;
+ output vcounderrange;
+ output fbout;
+ output fref;
+ output icdrclk;
+ output c0, c1, c2, c3, c4;
+
+endmodule // altpll
+`endif
diff --git a/techlibs/intel/common/brams.txt b/techlibs/intel/common/brams.txt
new file mode 100644
index 00000000..3bf21afc
--- /dev/null
+++ b/techlibs/intel/common/brams.txt
@@ -0,0 +1,33 @@
+bram $__M9K_ALTSYNCRAM_SINGLEPORT_FULL
+ init 1
+ abits 13 @M1
+ dbits 1 @M1
+ abits 12 @M2
+ dbits 2 @M2
+ abits 11 @M3
+ dbits 4 @M3
+ abits 10 @M4
+ dbits 8 @M4
+ abits 10 @M5
+ dbits 9 @M5
+ abits 9 @M6
+ dbits 16 @M6
+ abits 9 @M7
+ dbits 18 @M7
+ abits 8 @M8
+ dbits 32 @M8
+ abits 8 @M9
+ dbits 36 @M9
+ groups 2
+ ports 1 1
+ wrmode 0 1
+ enable 1 1
+ transp 0 0
+ clocks 2 3
+ clkpol 2 3
+endbram
+
+match $__M9K_ALTSYNCRAM_SINGLEPORT_FULL
+ min efficiency 2
+ make_transp
+endmatch
diff --git a/techlibs/intel/common/brams_map.v b/techlibs/intel/common/brams_map.v
new file mode 100644
index 00000000..fae4af2a
--- /dev/null
+++ b/techlibs/intel/common/brams_map.v
@@ -0,0 +1,93 @@
+module \$__M9K_ALTSYNCRAM_SINGLEPORT_FULL (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+
+ parameter CFG_ABITS = 8;
+ parameter CFG_DBITS = 36;
+ parameter ABITS = "1";
+ parameter DBITS = "1";
+ parameter CLKPOL2 = 1;
+ parameter CLKPOL3 = 1;
+
+ input CLK2;
+ input CLK3;
+ //Read data
+ output [CFG_DBITS-1:0] A1DATA;
+ input [CFG_ABITS-1:0] A1ADDR;
+ input A1EN;
+ //Write data
+ output [CFG_DBITS-1:0] B1DATA;
+ input [CFG_ABITS-1:0] B1ADDR;
+ input B1EN;
+
+ wire [CFG_DBITS-1:0] B1DATA_t;
+
+ localparam MODE = CFG_DBITS == 1 ? 1:
+ CFG_DBITS == 2 ? 2:
+ CFG_DBITS == 4 ? 3:
+ CFG_DBITS == 8 ? 4:
+ CFG_DBITS == 9 ? 5:
+ CFG_DBITS == 16 ? 6:
+ CFG_DBITS == 18 ? 7:
+ CFG_DBITS == 32 ? 8:
+ CFG_DBITS == 36 ? 9:
+ 'bx;
+
+ localparam NUMWORDS = CFG_DBITS == 1 ? 8192:
+ CFG_DBITS == 2 ? 4096:
+ CFG_DBITS == 4 ? 2048:
+ CFG_DBITS == 8 ? 1024:
+ CFG_DBITS == 9 ? 1024:
+ CFG_DBITS == 16 ? 512:
+ CFG_DBITS == 18 ? 512:
+ CFG_DBITS == 32 ? 256:
+ CFG_DBITS == 36 ? 256:
+ 'bx;
+
+ altsyncram #(.clock_enable_input_b ("ALTERNATE" ),
+ .clock_enable_input_a ("ALTERNATE" ),
+ .clock_enable_output_b ("NORMAL" ),
+ .clock_enable_output_a ("NORMAL" ),
+ .wrcontrol_aclr_a ("NONE" ),
+ .indata_aclr_a ("NONE" ),
+ .address_aclr_a ("NONE" ),
+ .outdata_aclr_a ("NONE" ),
+ .outdata_reg_a ("UNREGISTERED"),
+ .operation_mode ("SINGLE_PORT" ),
+ .intended_device_family ("CYCLONE IVE" ),
+ .outdata_reg_a ("UNREGISTERED"),
+ .lpm_type ("altsyncram" ),
+ .init_type ("unused" ),
+ .ram_block_type ("AUTO" ),
+ .lpm_hint ("ENABLE_RUNTIME_MOD=NO"), // Forced value
+ .power_up_uninitialized ("FALSE"),
+ .read_during_write_mode_port_a ("NEW_DATA_NO_NBE_READ"), // Forced value
+ .width_byteena_a (1), // Forced value
+ .numwords_b ( NUMWORDS ),
+ .numwords_a ( NUMWORDS ),
+ .widthad_b ( CFG_ABITS ),
+ .width_b ( CFG_DBITS ),
+ .widthad_a ( CFG_ABITS ),
+ .width_a ( CFG_DBITS )
+ ) _TECHMAP_REPLACE_ (
+ .data_a(B1DATA),
+ .address_a(B1ADDR),
+ .wren_a(B1EN),
+ .rden_a(A1EN),
+ .q_a(A1DATA),
+ .data_b(1'b0),
+ .address_b(0),
+ .wren_b(1'b0),
+ .rden_b(1'b0),
+ .q_b(1'b0),
+ .clock0(CLK2),
+ .clock1(1'b1), // Unused in single port mode
+ .clocken0(1'b1),
+ .clocken1(1'b1),
+ .clocken2(1'b1),
+ .clocken3(1'b1),
+ .aclr0(1'b0),
+ .aclr1(1'b0),
+ .addressstall_a(1'b0),
+ .addressstall_b(1'b0));
+
+endmodule
+
diff --git a/techlibs/intel/common/m9k_bb.v b/techlibs/intel/common/m9k_bb.v
new file mode 100644
index 00000000..b18a752f
--- /dev/null
+++ b/techlibs/intel/common/m9k_bb.v
@@ -0,0 +1,70 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+(* blackbox *)
+module altsyncram(data_a, address_a, wren_a, rden_a, q_a, data_b, address_b, wren_b, rden_b,
+ q_b, clock0, clock1, clocken0, clocken1, clocken2, clocken3, aclr0, aclr1,
+ addressstall_a, addressstall_b);
+
+ parameter clock_enable_input_b = "ALTERNATE";
+ parameter clock_enable_input_a = "ALTERNATE";
+ parameter clock_enable_output_b = "NORMAL";
+ parameter clock_enable_output_a = "NORMAL";
+ parameter wrcontrol_aclr_a = "NONE";
+ parameter indata_aclr_a = "NONE";
+ parameter address_aclr_a = "NONE";
+ parameter outdata_aclr_a = "NONE";
+ parameter outdata_reg_a = "UNREGISTERED";
+ parameter operation_mode = "SINGLE_PORT";
+ parameter intended_device_family = "MAX 10 FPGA";
+ parameter outdata_reg_a = "UNREGISTERED";
+ parameter lpm_type = "altsyncram";
+ parameter init_type = "unused";
+ parameter ram_block_type = "AUTO";
+ parameter lpm_hint = "ENABLE_RUNTIME_MOD=NO";
+ parameter power_up_uninitialized = "FALSE";
+ parameter read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ";
+ parameter width_byteena_a = 1;
+ parameter numwords_b = 0;
+ parameter numwords_a = 0;
+ parameter widthad_b = 1;
+ parameter width_b = 1;
+ parameter widthad_a = 1;
+ parameter width_a = 1;
+
+ // Port A declarations
+ output [35:0] q_a;
+ input [35:0] data_a;
+ input [7:0] address_a;
+ input wren_a;
+ input rden_a;
+ // Port B declarations
+ output [35:0] q_b;
+ input [35:0] data_b;
+ input [7:0] address_b;
+ input wren_b;
+ input rden_b;
+ // Control signals
+ input clock0, clock1;
+ input clocken0, clocken1, clocken2, clocken3;
+ input aclr0, aclr1;
+ input addressstall_a;
+ input addressstall_b;
+ // TODO: Implement the correct simulation model
+
+endmodule // altsyncram
diff --git a/techlibs/intel/cyclone10/cells_arith.v b/techlibs/intel/cyclone10/cells_arith.v
new file mode 100644
index 00000000..5ae8d6ce
--- /dev/null
+++ b/techlibs/intel/cyclone10/cells_arith.v
@@ -0,0 +1,65 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+
+// NOTE: This is still WIP.
+(* techmap_celltype = "$alu" *)
+module _80_altera_a10gx_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 [Y_WIDTH-1:0] CO;
+ output CO;
+
+ wire _TECHMAP_FAIL_ = Y_WIDTH <= 4;
+
+ 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:0] C = {CO, CI};
+ wire [Y_WIDTH+1:0] COx;
+ wire [Y_WIDTH+1:0] C = {COx, CI};
+
+ /* Start implementation */
+ (* keep *) cyclone10lp_lcell_comb #(.lut_mask(16'b0000_0000_1010_1010), .sum_lutc_input("cin")) carry_start (.cout(COx[0]), .dataa(C[0]), .datab(1'b1), .datac(1'b1), .datad(1'b1));
+
+ genvar i;
+ generate for (i = 0; i < Y_WIDTH; i = i + 1) begin: slice
+ if(i==Y_WIDTH-1) begin
+ (* keep *) cyclone10lp_lcell_comb #(.lut_mask(16'b1111_0000_1110_0000), .sum_lutc_input("cin")) carry_end (.combout(COx[Y_WIDTH]), .dataa(1'b1), .datab(1'b1), .datac(1'b1), .datad(1'b1), .cin(C[Y_WIDTH]));
+ assign CO = COx[Y_WIDTH];
+ end
+ else
+ cyclone10lp_lcell_comb #(.lut_mask(16'b1001_0110_1110_1000), .sum_lutc_input("cin")) arith_cell (.combout(Y[i]), .cout(COx[i+1]), .dataa(AA[i]), .datab(BB[i]), .datac(1'b1), .datad(1'b1), .cin(C[i+1]));
+ end: slice
+ endgenerate
+ /* End implementation */
+ assign X = AA ^ BB;
+
+endmodule
diff --git a/techlibs/intel/cyclone10/cells_map.v b/techlibs/intel/cyclone10/cells_map.v
new file mode 100644
index 00000000..c2f6f403
--- /dev/null
+++ b/techlibs/intel/cyclone10/cells_map.v
@@ -0,0 +1,109 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+// > c60k28 (Viacheslav, VT) [at] yandex [dot] com
+// > Intel FPGA technology mapping. User must first simulate the generated \
+// > netlist before going to test it on board.
+// > Changelog: 1) The missing power_up parameter in the techmap introduces a problem in Quartus mapper. Fixed.
+
+// Normal mode DFF negedge clk, negedge reset
+module \$_DFF_N_ (input D, C, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+endmodule
+// Normal mode DFF
+module \$_DFF_P_ (input D, C, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+endmodule
+
+// Async Active Low Reset DFF
+module \$_DFF_PN0_ (input D, C, R, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up("power_up")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+endmodule
+// Async Active High Reset DFF
+module \$_DFF_PP0_ (input D, C, R, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ wire R_i = ~ R;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R_i), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+endmodule
+
+module \$__DFFE_PP0 (input D, C, E, R, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ wire E_i = ~ E;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0));
+endmodule
+
+// Input buffer map
+module \$__inpad (input I, output O);
+ cyclone10lp_io_ibuf _TECHMAP_REPLACE_ (.o(O), .i(I), .ibar(1'b0));
+endmodule
+
+// Output buffer map
+module \$__outpad (input I, output O);
+ cyclone10lp_io_obuf _TECHMAP_REPLACE_ (.o(O), .i(I), .oe(1'b1));
+endmodule
+
+// LUT Map
+/* 0 -> datac
+ 1 -> cin */
+module \$lut (A, Y);
+ parameter WIDTH = 0;
+ parameter LUT = 0;
+ input [WIDTH-1:0] A;
+ output Y;
+ generate
+ if (WIDTH == 1) begin
+ assign Y = ~A[0]; // Not need to spend 1 logic cell for such an easy function
+ end else
+ if (WIDTH == 2) begin
+ cyclone10lp_lcell_comb #(.lut_mask({4{LUT}}),
+ .sum_lutc_input("datac")) _TECHMAP_REPLACE_ (.combout(Y),
+ .dataa(A[0]),
+ .datab(A[1]),
+ .datac(1'b1),
+ .datad(1'b1));
+ end else
+ if(WIDTH == 3) begin
+ cyclone10lp_lcell_comb #(.lut_mask({2{LUT}}),
+ .sum_lutc_input("datac")) _TECHMAP_REPLACE_ (.combout(Y),
+ .dataa(A[0]),
+ .datab(A[1]),
+ .datac(A[2]),
+ .datad(1'b1));
+ end else
+ if(WIDTH == 4) begin
+ cyclone10lp_lcell_comb #(.lut_mask(LUT),
+ .sum_lutc_input("datac")) _TECHMAP_REPLACE_ (.combout(Y),
+ .dataa(A[0]),
+ .datab(A[1]),
+ .datac(A[2]),
+ .datad(A[3]));
+ end else
+ wire _TECHMAP_FAIL_ = 1;
+ endgenerate
+
+endmodule
+
+
diff --git a/techlibs/intel/cyclone10/cells_sim.v b/techlibs/intel/cyclone10/cells_sim.v
new file mode 100644
index 00000000..f5a8aee2
--- /dev/null
+++ b/techlibs/intel/cyclone10/cells_sim.v
@@ -0,0 +1,137 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+module VCC (output V);
+ assign V = 1'b1;
+endmodule // VCC
+
+module GND (output G);
+ assign G = 1'b0;
+endmodule // GND
+
+/* Altera Cyclone 10 LP devices Input Buffer Primitive */
+module cyclone10lp_io_ibuf
+ (output o, input i, input ibar);
+ assign ibar = ibar;
+ assign o = i;
+endmodule // cyclone10lp_io_ibuf
+
+/* Altera Cyclone 10 LP devices Output Buffer Primitive */
+module cyclone10lp_io_obuf
+ (output o, input i, input oe);
+ assign o = i;
+ assign oe = oe;
+endmodule // cyclone10lp_io_obuf
+
+/* Altera Cyclone IV (E) 4-input non-fracturable LUT Primitive */
+module cyclone10lp_lcell_comb
+ (output combout, cout,
+ input dataa, datab, datac, datad, cin);
+
+ /* Internal parameters which define the behaviour
+ of the LUT primitive.
+ lut_mask define the lut function, can be expressed in 16-digit bin or hex.
+ sum_lutc_input define the type of LUT (combinational | arithmetic).
+ dont_touch for retiming || carry options.
+ lpm_type for WYSIWYG */
+
+ parameter lut_mask = 16'hFFFF;
+ parameter dont_touch = "off";
+ parameter lpm_type = "cyclone10lp_lcell_comb";
+ parameter sum_lutc_input = "datac";
+
+ reg [1:0] lut_type;
+ reg cout_rt;
+ reg combout_rt;
+ wire dataa_w;
+ wire datab_w;
+ wire datac_w;
+ wire datad_w;
+ wire cin_w;
+
+ assign dataa_w = dataa;
+ assign datab_w = datab;
+ assign datac_w = datac;
+ assign datad_w = datad;
+
+ function lut_data;
+ input [15:0] mask;
+ input dataa, datab, datac, datad;
+ reg [7:0] s3;
+ reg [3:0] s2;
+ reg [1:0] s1;
+ begin
+ s3 = datad ? mask[15:8] : mask[7:0];
+ s2 = datac ? s3[7:4] : s3[3:0];
+ s1 = datab ? s2[3:2] : s2[1:0];
+ lut_data = dataa ? s1[1] : s1[0];
+ end
+
+ endfunction
+
+ initial begin
+ if (sum_lutc_input == "datac") lut_type = 0;
+ else
+ if (sum_lutc_input == "cin") lut_type = 1;
+ else begin
+ $error("Error in sum_lutc_input. Parameter %s is not a valid value.\n", sum_lutc_input);
+ $finish();
+ end
+ end
+
+ always @(dataa_w or datab_w or datac_w or datad_w or cin_w) begin
+ if (lut_type == 0) begin // logic function
+ combout_rt = lut_data(lut_mask, dataa_w, datab_w,
+ datac_w, datad_w);
+ end
+ else if (lut_type == 1) begin // arithmetic function
+ combout_rt = lut_data(lut_mask, dataa_w, datab_w,
+ cin_w, datad_w);
+ end
+ cout_rt = lut_data(lut_mask, dataa_w, datab_w, cin_w, 'b0);
+ end
+
+ assign combout = combout_rt & 1'b1;
+ assign cout = cout_rt & 1'b1;
+
+endmodule // cyclone10lp_lcell_comb
+
+/* Altera D Flip-Flop Primitive */
+module dffeas
+ (output q,
+ input d, clk, clrn, prn, ena,
+ input asdata, aload, sclr, sload);
+
+ // Timing simulation is not covered
+ parameter power_up="dontcare";
+ parameter is_wysiwyg="false";
+
+ reg q_tmp;
+ wire reset;
+ reg [7:0] debug_net;
+
+ assign reset = (prn && sclr && ~clrn && ena);
+ assign q = q_tmp & 1'b1;
+
+ always @(posedge clk, posedge aload) begin
+ if(reset) q_tmp <= 0;
+ else q_tmp <= d;
+ end
+ assign q = q_tmp;
+
+endmodule // dffeas
diff --git a/techlibs/intel/cycloneiv/cells_arith.v b/techlibs/intel/cycloneiv/cells_arith.v
new file mode 100644
index 00000000..010a4b5d
--- /dev/null
+++ b/techlibs/intel/cycloneiv/cells_arith.v
@@ -0,0 +1,97 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+
+// NOTE: This is still WIP.
+(* techmap_celltype = "$alu" *)
+/* Uncomment this for LCU????
+module _80_cycloneiv_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 [Y_WIDTH-1:0] CO;
+ 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:0] C = {CO, CI};
+ wire [Y_WIDTH+1:0] COx;
+ wire [Y_WIDTH+1:0] C = {COx, CI};
+
+ /* Start implementation */
+ //cycloneiv_lcell_comb #(.lut_mask(16'b0000_0000_1010_1010), .sum_lutc_input("cin")) carry_start (.cout(COx[0]), .dataa(C[0]), .datab(1'b1), .datac(1'b1), .datad(1'b1));
+ /*
+ genvar i;
+ generate for (i = 0; i < Y_WIDTH; i = i + 1) begin: slice
+ if(i==Y_WIDTH-1)
+ (* keep *) cycloneiv_lcell_comb #(.lut_mask(16'b1111_0000_1110_0000), .sum_lutc_input("cin")) carry_end (.combout(CO), .dataa(1'b1), .datab(1'b1), .datac(1'b1), .datad(1'b1), .cin(C[Y_WIDTH]));
+ //assign CO = COx[Y_WIDTH];
+ else
+ cycloneiv_lcell_comb #(.lut_mask(16'b1001_0110_1110_1000), .sum_lutc_input("cin")) arith_cell (.combout(Y[i]), .cout(COx[i+1]), .dataa(AA[i]), .datab(BB[i]), .datac(1'b1), .datad(1'b1), .cin(C[i+1]));
+ end: slice
+ endgenerate
+ /* End implementation */
+ /*assign X = AA ^ BB;
+
+endmodule*/
+module _80_cycloneiv_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 [Y_WIDTH:0] CO;
+
+ wire _TECHMAP_FAIL_ = Y_WIDTH < 6;
+
+ 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:0] C = {CO, CI};
+
+ cycloneiv_lcell_comb #(.lut_mask(16'b0110_0110_1000_1000), .sum_lutc_input("cin")) carry_start (.cout(CO[0]), .dataa(BB[0]), .datab(1'b1), .datac(1'b1), .datad(1'b1));
+ genvar i;
+ generate for (i = 1; i < Y_WIDTH; i = i + 1) begin:slice
+ cycloneiv_lcell_comb #(.lut_mask(16'b0101_1010_0101_0000), .sum_lutc_input("cin")) arith_cell (.combout(Y[i]), .cout(CO[i]), .dataa(BB[i]), .datab(1'b1), .datac(1'b1), .datad(1'b1), .cin(C[i]));
+ end endgenerate
+
+ assign X = AA ^ BB;
+endmodule
diff --git a/techlibs/intel/cycloneiv/cells_map.v b/techlibs/intel/cycloneiv/cells_map.v
new file mode 100644
index 00000000..19148843
--- /dev/null
+++ b/techlibs/intel/cycloneiv/cells_map.v
@@ -0,0 +1,93 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+// > c60k28 (Viacheslav, VT) [at] yandex [dot] com
+// > Intel FPGA technology mapping. User must first simulate the generated \
+// > netlist before going to test it on board.
+// > Changelog: 1) The missing power_up parameter in the techmap introduces a problem in Quartus mapper. Fixed.
+
+// Normal mode DFF negedge clk, negedge reset
+module \$_DFF_N_ (input D, C, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+endmodule
+// Normal mode DFF
+module \$_DFF_P_ (input D, C, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+endmodule
+
+// Async Active Low Reset DFF
+module \$_DFF_PN0_ (input D, C, R, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up("power_up")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+endmodule
+// Async Active High Reset DFF
+module \$_DFF_PP0_ (input D, C, R, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ wire R_i = ~ R;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R_i), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+endmodule
+
+module \$__DFFE_PP0 (input D, C, E, R, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ wire E_i = ~ E;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0));
+endmodule
+
+// Input buffer map
+module \$__inpad (input I, output O);
+ cycloneiv_io_ibuf _TECHMAP_REPLACE_ (.o(O), .i(I), .ibar(1'b0));
+endmodule
+
+// Output buffer map
+module \$__outpad (input I, output O);
+ cycloneiv_io_obuf _TECHMAP_REPLACE_ (.o(O), .i(I), .oe(1'b1));
+endmodule
+
+// LUT Map
+/* 0 -> datac
+ 1 -> cin */
+module \$lut (A, Y);
+ parameter WIDTH = 0;
+ parameter LUT = 0;
+ input [WIDTH-1:0] A;
+ output Y;
+ generate
+ if (WIDTH == 1) begin
+ assign Y = ~A[0]; // Not need to spend 1 logic cell for such an easy function
+ end else
+ if (WIDTH == 2) begin
+ cycloneiv_lcell_comb #(.lut_mask({4{LUT}}), .sum_lutc_input("datac")) _TECHMAP_REPLACE_ (.combout(Y), .dataa(A[0]), .datab(A[1]), .datac(1'b1),.datad(1'b1));
+ end else
+ if(WIDTH == 3) begin
+ cycloneiv_lcell_comb #(.lut_mask({2{LUT}}), .sum_lutc_input("datac")) _TECHMAP_REPLACE_ (.combout(Y), .dataa(A[0]), .datab(A[1]), .datac(A[2]),.datad(1'b1));
+ end else
+ if(WIDTH == 4) begin
+ cycloneiv_lcell_comb #(.lut_mask(LUT), .sum_lutc_input("datac")) _TECHMAP_REPLACE_ (.combout(Y), .dataa(A[0]), .datab(A[1]), .datac(A[2]),.datad(A[3]));
+ end else
+ wire _TECHMAP_FAIL_ = 1;
+ endgenerate
+endmodule //
+
+
diff --git a/techlibs/intel/cycloneiv/cells_sim.v b/techlibs/intel/cycloneiv/cells_sim.v
new file mode 100644
index 00000000..2af2ab99
--- /dev/null
+++ b/techlibs/intel/cycloneiv/cells_sim.v
@@ -0,0 +1,299 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+
+module VCC (output V);
+ assign V = 1'b1;
+endmodule // VCC
+
+module GND (output G);
+ assign G = 1'b0;
+endmodule // GND
+
+/* Altera Cyclone IV (GX) devices Input Buffer Primitive */
+module cycloneiv_io_ibuf
+ (output o, input i, input ibar);
+ assign ibar = ibar;
+ assign o = i;
+endmodule // fiftyfivenm_io_ibuf
+
+/* Altera Cyclone IV (GX) devices Output Buffer Primitive */
+module cycloneiv_io_obuf
+ (output o, input i, input oe);
+ assign o = i;
+ assign oe = oe;
+endmodule // fiftyfivenm_io_obuf
+
+/* Altera Cyclone IV (GX) 4-input non-fracturable LUT Primitive */
+module cycloneiv_lcell_comb
+ (output combout, cout,
+ input dataa, datab, datac, datad, cin);
+
+ /* Internal parameters which define the behaviour
+ of the LUT primitive.
+ lut_mask define the lut function, can be expressed in 16-digit bin or hex.
+ sum_lutc_input define the type of LUT (combinational | arithmetic).
+ dont_touch for retiming || carry options.
+ lpm_type for WYSIWYG */
+
+ parameter lut_mask = 16'hFFFF;
+ parameter dont_touch = "off";
+ parameter lpm_type = "cycloneiv_lcell_comb";
+ parameter sum_lutc_input = "datac";
+
+ reg [1:0] lut_type;
+ reg cout_rt;
+ reg combout_rt;
+ wire dataa_w;
+ wire datab_w;
+ wire datac_w;
+ wire datad_w;
+ wire cin_w;
+
+ assign dataa_w = dataa;
+ assign datab_w = datab;
+ assign datac_w = datac;
+ assign datad_w = datad;
+
+ function lut_data;
+ input [15:0] mask;
+ input dataa, datab, datac, datad;
+ reg [7:0] s3;
+ reg [3:0] s2;
+ reg [1:0] s1;
+ begin
+ s3 = datad ? mask[15:8] : mask[7:0];
+ s2 = datac ? s3[7:4] : s3[3:0];
+ s1 = datab ? s2[3:2] : s2[1:0];
+ lut_data = dataa ? s1[1] : s1[0];
+ end
+
+ endfunction
+
+ initial begin
+ if (sum_lutc_input == "datac") lut_type = 0;
+ else
+ if (sum_lutc_input == "cin") lut_type = 1;
+ else begin
+ $error("Error in sum_lutc_input. Parameter %s is not a valid value.\n", sum_lutc_input);
+ $finish();
+ end
+ end
+
+ always @(dataa_w or datab_w or datac_w or datad_w or cin_w) begin
+ if (lut_type == 0) begin // logic function
+ combout_rt = lut_data(lut_mask, dataa_w, datab_w,
+ datac_w, datad_w);
+ end
+ else if (lut_type == 1) begin // arithmetic function
+ combout_rt = lut_data(lut_mask, dataa_w, datab_w,
+ cin_w, datad_w);
+ end
+ cout_rt = lut_data(lut_mask, dataa_w, datab_w, cin_w, 'b0);
+ end
+
+ assign combout = combout_rt & 1'b1;
+ assign cout = cout_rt & 1'b1;
+
+endmodule // cycloneiv_lcell_comb
+
+/* Altera D Flip-Flop Primitive */
+module dffeas
+ (output q,
+ input d, clk, clrn, prn, ena,
+ input asdata, aload, sclr, sload);
+
+ // Timing simulation is not covered
+ parameter power_up="dontcare";
+ parameter is_wysiwyg="false";
+
+ reg q_tmp;
+ wire reset;
+ reg [7:0] debug_net;
+
+ assign reset = (prn && sclr && ~clrn && ena);
+ assign q = q_tmp & 1'b1;
+
+ always @(posedge clk, posedge aload) begin
+ if(reset) q_tmp <= 0;
+ else q_tmp <= d;
+ end
+ assign q = q_tmp;
+
+endmodule // dffeas
+
+/* Cyclone IV GX altpll clearbox model */
+(* blackbox *)
+module cycloneiv_pll
+ (inclk,
+ fbin,
+ fbout,
+ clkswitch,
+ areset,
+ pfdena,
+ scanclk,
+ scandata,
+ scanclkena,
+ configupdate,
+ clk,
+ phasecounterselect,
+ phaseupdown,
+ phasestep,
+ clkbad,
+ activeclock,
+ locked,
+ scandataout,
+ scandone,
+ phasedone,
+ vcooverrange,
+ vcounderrange,
+ fref,
+ icdrclk);
+
+ parameter operation_mode = "normal";
+ parameter pll_type = "auto";
+ parameter compensate_clock = "clock0";
+ parameter inclk0_input_frequency = 0;
+ parameter inclk1_input_frequency = 0;
+ parameter self_reset_on_loss_lock = "off";
+ parameter switch_over_type = "auto";
+ parameter switch_over_counter = 1;
+ parameter enable_switch_over_counter = "off";
+ parameter bandwidth = 0;
+ parameter bandwidth_type = "auto";
+ parameter use_dc_coupling = "false";
+ parameter lock_high = 0;
+ parameter lock_low = 0;
+ parameter lock_window_ui = "0.05";
+ parameter test_bypass_lock_detect = "off";
+ parameter clk0_output_frequency = 0;
+ parameter clk0_multiply_by = 0;
+ parameter clk0_divide_by = 0;
+ parameter clk0_phase_shift = "0";
+ parameter clk0_duty_cycle = 50;
+ parameter clk1_output_frequency = 0;
+ parameter clk1_multiply_by = 0;
+ parameter clk1_divide_by = 0;
+ parameter clk1_phase_shift = "0";
+ parameter clk1_duty_cycle = 50;
+ parameter clk2_output_frequency = 0;
+ parameter clk2_multiply_by = 0;
+ parameter clk2_divide_by = 0;
+ parameter clk2_phase_shift = "0";
+ parameter clk2_duty_cycle = 50;
+ parameter clk3_output_frequency = 0;
+ parameter clk3_multiply_by = 0;
+ parameter clk3_divide_by = 0;
+ parameter clk3_phase_shift = "0";
+ parameter clk3_duty_cycle = 50;
+ parameter clk4_output_frequency = 0;
+ parameter clk4_multiply_by = 0;
+ parameter clk4_divide_by = 0;
+ parameter clk4_phase_shift = "0";
+ parameter clk4_duty_cycle = 50;
+ parameter pfd_min = 0;
+ parameter pfd_max = 0;
+ parameter vco_min = 0;
+ parameter vco_max = 0;
+ parameter vco_center = 0;
+ // Advanced user parameters
+ parameter m_initial = 1;
+ parameter m = 0;
+ parameter n = 1;
+ parameter c0_high = 1;
+ parameter c0_low = 1;
+ parameter c0_initial = 1;
+ parameter c0_mode = "bypass";
+ parameter c0_ph = 0;
+ parameter c1_high = 1;
+ parameter c1_low = 1;
+ parameter c1_initial = 1;
+ parameter c1_mode = "bypass";
+ parameter c1_ph = 0;
+ parameter c2_high = 1;
+ parameter c2_low = 1;
+ parameter c2_initial = 1;
+ parameter c2_mode = "bypass";
+ parameter c2_ph = 0;
+ parameter c3_high = 1;
+ parameter c3_low = 1;
+ parameter c3_initial = 1;
+ parameter c3_mode = "bypass";
+ parameter c3_ph = 0;
+ parameter c4_high = 1;
+ parameter c4_low = 1;
+ parameter c4_initial = 1;
+ parameter c4_mode = "bypass";
+ parameter c4_ph = 0;
+ parameter m_ph = 0;
+ parameter clk0_counter = "unused";
+ parameter clk1_counter = "unused";
+ parameter clk2_counter = "unused";
+ parameter clk3_counter = "unused";
+ parameter clk4_counter = "unused";
+ parameter c1_use_casc_in = "off";
+ parameter c2_use_casc_in = "off";
+ parameter c3_use_casc_in = "off";
+ parameter c4_use_casc_in = "off";
+ parameter m_test_source = -1;
+ parameter c0_test_source = -1;
+ parameter c1_test_source = -1;
+ parameter c2_test_source = -1;
+ parameter c3_test_source = -1;
+ parameter c4_test_source = -1;
+ parameter vco_multiply_by = 0;
+ parameter vco_divide_by = 0;
+ parameter vco_post_scale = 1;
+ parameter vco_frequency_control = "auto";
+ parameter vco_phase_shift_step = 0;
+ parameter charge_pump_current = 10;
+ parameter loop_filter_r = "1.0";
+ parameter loop_filter_c = 0;
+ parameter pll_compensation_delay = 0;
+ parameter lpm_type = "cycloneiv_pll";
+ parameter phase_counter_select_width = 3;
+
+ input [1:0] inclk;
+ input fbin;
+ input clkswitch;
+ input areset;
+ input pfdena;
+ input [phase_counter_select_width - 1:0] phasecounterselect;
+ input phaseupdown;
+ input phasestep;
+ input scanclk;
+ input scanclkena;
+ input scandata;
+ input configupdate;
+
+ output [4:0] clk;
+ output [1:0] clkbad;
+ output activeclock;
+ output locked;
+ output scandataout;
+ output scandone;
+ output fbout;
+ output phasedone;
+ output vcooverrange;
+ output vcounderrange;
+ output fref;
+ output icdrclk;
+
+endmodule // cycloneive_pll
+
+
diff --git a/techlibs/intel/cycloneive/arith_map.v b/techlibs/intel/cycloneive/arith_map.v
new file mode 100644
index 00000000..b3a11272
--- /dev/null
+++ b/techlibs/intel/cycloneive/arith_map.v
@@ -0,0 +1,99 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+/* TODO: Describe the following mode */
+module fa
+ (input a_c,
+ input b_c,
+ input cin_c,
+ output cout_t,
+ output sum_x);
+
+ wire a_c;
+ wire b_c;
+ wire cout_t;
+ wire cin_c;
+ wire sum_x;
+ wire VCC;
+
+ assign VCC = 1'b1;
+
+ cycloneiv_lcell_comb gen_sum_0 (.combout(sum_x),
+ .dataa(a_c),
+ .datab(b_c),
+ .datac(cin_c),
+ .datad(VCC));
+ defparam syn__05_.lut_mask = 16'b1001011010010110;
+ defparam syn__05_.sum_lutc_input = "datac";
+
+ cycloneiv_lcell_comb gen_cout_0 (.combout(cout_t),
+ .dataa(cin_c),
+ .datab(b_c),
+ .datac(a_c),
+ .datad(VCC));
+ defparam syn__06_.lut_mask = 16'b1110000011100000;
+ defparam syn__06_.sum_lutc_input = "datac";
+
+endmodule // fa
+
+module f_stage();
+
+endmodule // f_stage
+
+module f_end();
+
+endmodule // f_end
+
+module _80_cycloneive_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 [Y_WIDTH:0] CO;
+
+ wire _TECHMAP_FAIL_ = Y_WIDTH < 5;
+
+ 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:0] C = {CO, CI};
+
+ fa f0 (.a_c(AA[0]),
+ .b_c(BB[0]),
+ .cin_c(C[0]),
+ .cout_t(C0[1]),
+ .sum_x(Y[0]));
+
+ genvar i;
+ generate for (i = 1; i < Y_WIDTH; i = i + 1) begin:slice
+ cycloneive_lcell_comb #(.lut_mask(16'b0101_1010_0101_0000), .sum_lutc_input("cin")) arith_cell (.combout(Y[i]), .cout(CO[i]), .dataa(BB[i]), .datab(1'b1), .datac(1'b1), .datad(1'b1), .cin(C[i]));
+ end endgenerate
+
+ assign X = AA ^ BB;
+
+endmodule
diff --git a/techlibs/intel/cycloneive/cells_map.v b/techlibs/intel/cycloneive/cells_map.v
new file mode 100644
index 00000000..abeb92ee
--- /dev/null
+++ b/techlibs/intel/cycloneive/cells_map.v
@@ -0,0 +1,109 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+// > c60k28 (Viacheslav, VT) [at] yandex [dot] com
+// > Intel FPGA technology mapping. User must first simulate the generated \
+// > netlist before going to test it on board.
+// > Changelog: 1) The missing power_up parameter in the techmap introduces a problem in Quartus mapper. Fixed.
+
+// Normal mode DFF negedge clk, negedge reset
+module \$_DFF_N_ (input D, C, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+endmodule
+// Normal mode DFF
+module \$_DFF_P_ (input D, C, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+endmodule
+
+// Async Active Low Reset DFF
+module \$_DFF_PN0_ (input D, C, R, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up("power_up")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+endmodule
+// Async Active High Reset DFF
+module \$_DFF_PP0_ (input D, C, R, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ wire R_i = ~ R;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R_i), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+endmodule
+
+module \$__DFFE_PP0 (input D, C, E, R, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ wire E_i = ~ E;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0));
+endmodule
+
+// Input buffer map
+module \$__inpad (input I, output O);
+ cycloneive_io_ibuf _TECHMAP_REPLACE_ (.o(O), .i(I), .ibar(1'b0));
+endmodule
+
+// Output buffer map
+module \$__outpad (input I, output O);
+ cycloneive_io_obuf _TECHMAP_REPLACE_ (.o(O), .i(I), .oe(1'b1));
+endmodule
+
+// LUT Map
+/* 0 -> datac
+ 1 -> cin */
+module \$lut (A, Y);
+ parameter WIDTH = 0;
+ parameter LUT = 0;
+ input [WIDTH-1:0] A;
+ output Y;
+ generate
+ if (WIDTH == 1) begin
+ assign Y = ~A[0]; // Not need to spend 1 logic cell for such an easy function
+ end else
+ if (WIDTH == 2) begin
+ cycloneive_lcell_comb #(.lut_mask({4{LUT}}),
+ .sum_lutc_input("datac")) _TECHMAP_REPLACE_ (.combout(Y),
+ .dataa(A[0]),
+ .datab(A[1]),
+ .datac(1'b1),
+ .datad(1'b1));
+ end else
+ if(WIDTH == 3) begin
+ cycloneive_lcell_comb #(.lut_mask({2{LUT}}),
+ .sum_lutc_input("datac")) _TECHMAP_REPLACE_ (.combout(Y),
+ .dataa(A[0]),
+ .datab(A[1]),
+ .datac(A[2]),
+ .datad(1'b1));
+ end else
+ if(WIDTH == 4) begin
+ cycloneive_lcell_comb #(.lut_mask(LUT),
+ .sum_lutc_input("datac")) _TECHMAP_REPLACE_ (.combout(Y),
+ .dataa(A[0]),
+ .datab(A[1]),
+ .datac(A[2]),
+ .datad(A[3]));
+ end else
+ wire _TECHMAP_FAIL_ = 1;
+ endgenerate
+
+endmodule
+
+
diff --git a/techlibs/intel/cycloneive/cells_sim.v b/techlibs/intel/cycloneive/cells_sim.v
new file mode 100644
index 00000000..f17b86fd
--- /dev/null
+++ b/techlibs/intel/cycloneive/cells_sim.v
@@ -0,0 +1,292 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+module VCC (output V);
+ assign V = 1'b1;
+endmodule // VCC
+
+module GND (output G);
+ assign G = 1'b0;
+endmodule // GND
+
+/* Altera Cyclone IV (E) devices Input Buffer Primitive */
+module cycloneive_io_ibuf
+ (output o, input i, input ibar);
+ assign ibar = ibar;
+ assign o = i;
+endmodule // fiftyfivenm_io_ibuf
+
+/* Altera Cyclone IV (E) devices Output Buffer Primitive */
+module cycloneive_io_obuf
+ (output o, input i, input oe);
+ assign o = i;
+ assign oe = oe;
+endmodule // fiftyfivenm_io_obuf
+
+/* Altera Cyclone IV (E) 4-input non-fracturable LUT Primitive */
+module cycloneive_lcell_comb
+ (output combout, cout,
+ input dataa, datab, datac, datad, cin);
+
+ /* Internal parameters which define the behaviour
+ of the LUT primitive.
+ lut_mask define the lut function, can be expressed in 16-digit bin or hex.
+ sum_lutc_input define the type of LUT (combinational | arithmetic).
+ dont_touch for retiming || carry options.
+ lpm_type for WYSIWYG */
+
+ parameter lut_mask = 16'hFFFF;
+ parameter dont_touch = "off";
+ parameter lpm_type = "cycloneive_lcell_comb";
+ parameter sum_lutc_input = "datac";
+
+ reg [1:0] lut_type;
+ reg cout_rt;
+ reg combout_rt;
+ wire dataa_w;
+ wire datab_w;
+ wire datac_w;
+ wire datad_w;
+ wire cin_w;
+
+ assign dataa_w = dataa;
+ assign datab_w = datab;
+ assign datac_w = datac;
+ assign datad_w = datad;
+
+ function lut_data;
+ input [15:0] mask;
+ input dataa, datab, datac, datad;
+ reg [7:0] s3;
+ reg [3:0] s2;
+ reg [1:0] s1;
+ begin
+ s3 = datad ? mask[15:8] : mask[7:0];
+ s2 = datac ? s3[7:4] : s3[3:0];
+ s1 = datab ? s2[3:2] : s2[1:0];
+ lut_data = dataa ? s1[1] : s1[0];
+ end
+
+ endfunction
+
+ initial begin
+ if (sum_lutc_input == "datac") lut_type = 0;
+ else
+ if (sum_lutc_input == "cin") lut_type = 1;
+ else begin
+ $error("Error in sum_lutc_input. Parameter %s is not a valid value.\n", sum_lutc_input);
+ $finish();
+ end
+ end
+
+ always @(dataa_w or datab_w or datac_w or datad_w or cin_w) begin
+ if (lut_type == 0) begin // logic function
+ combout_rt = lut_data(lut_mask, dataa_w, datab_w,
+ datac_w, datad_w);
+ end
+ else if (lut_type == 1) begin // arithmetic function
+ combout_rt = lut_data(lut_mask, dataa_w, datab_w,
+ cin_w, datad_w);
+ end
+ cout_rt = lut_data(lut_mask, dataa_w, datab_w, cin_w, 'b0);
+ end
+
+ assign combout = combout_rt & 1'b1;
+ assign cout = cout_rt & 1'b1;
+
+endmodule // cycloneive_lcell_comb
+
+/* Altera D Flip-Flop Primitive */
+module dffeas
+ (output q,
+ input d, clk, clrn, prn, ena,
+ input asdata, aload, sclr, sload);
+
+ // Timing simulation is not covered
+ parameter power_up="dontcare";
+ parameter is_wysiwyg="false";
+
+ reg q_tmp;
+ wire reset;
+ reg [7:0] debug_net;
+
+ assign reset = (prn && sclr && ~clrn && ena);
+ assign q = q_tmp & 1'b1;
+
+ always @(posedge clk, posedge aload) begin
+ if(reset) q_tmp <= 0;
+ else q_tmp <= d;
+ end
+ assign q = q_tmp;
+
+endmodule // dffeas
+
+/* Cyclone IV E altpll clearbox model */
+(* blackbox *)
+module cycloneive_pll
+ (inclk,
+ fbin,
+ fbout,
+ clkswitch,
+ areset,
+ pfdena,
+ scanclk,
+ scandata,
+ scanclkena,
+ configupdate,
+ clk,
+ phasecounterselect,
+ phaseupdown,
+ phasestep,
+ clkbad,
+ activeclock,
+ locked,
+ scandataout,
+ scandone,
+ phasedone,
+ vcooverrange,
+ vcounderrange);
+
+ parameter operation_mode = "normal";
+ parameter pll_type = "auto";
+ parameter compensate_clock = "clock0";
+ parameter inclk0_input_frequency = 0;
+ parameter inclk1_input_frequency = 0;
+ parameter self_reset_on_loss_lock = "off";
+ parameter switch_over_type = "auto";
+ parameter switch_over_counter = 1;
+ parameter enable_switch_over_counter = "off";
+ parameter bandwidth = 0;
+ parameter bandwidth_type = "auto";
+ parameter use_dc_coupling = "false";
+ parameter lock_high = 0;
+ parameter lock_low = 0;
+ parameter lock_window_ui = "0.05";
+ parameter test_bypass_lock_detect = "off";
+ parameter clk0_output_frequency = 0;
+ parameter clk0_multiply_by = 0;
+ parameter clk0_divide_by = 0;
+ parameter clk0_phase_shift = "0";
+ parameter clk0_duty_cycle = 50;
+ parameter clk1_output_frequency = 0;
+ parameter clk1_multiply_by = 0;
+ parameter clk1_divide_by = 0;
+ parameter clk1_phase_shift = "0";
+ parameter clk1_duty_cycle = 50;
+ parameter clk2_output_frequency = 0;
+ parameter clk2_multiply_by = 0;
+ parameter clk2_divide_by = 0;
+ parameter clk2_phase_shift = "0";
+ parameter clk2_duty_cycle = 50;
+ parameter clk3_output_frequency = 0;
+ parameter clk3_multiply_by = 0;
+ parameter clk3_divide_by = 0;
+ parameter clk3_phase_shift = "0";
+ parameter clk3_duty_cycle = 50;
+ parameter clk4_output_frequency = 0;
+ parameter clk4_multiply_by = 0;
+ parameter clk4_divide_by = 0;
+ parameter clk4_phase_shift = "0";
+ parameter clk4_duty_cycle = 50;
+ parameter pfd_min = 0;
+ parameter pfd_max = 0;
+ parameter vco_min = 0;
+ parameter vco_max = 0;
+ parameter vco_center = 0;
+ // Advanced user parameters
+ parameter m_initial = 1;
+ parameter m = 0;
+ parameter n = 1;
+ parameter c0_high = 1;
+ parameter c0_low = 1;
+ parameter c0_initial = 1;
+ parameter c0_mode = "bypass";
+ parameter c0_ph = 0;
+ parameter c1_high = 1;
+ parameter c1_low = 1;
+ parameter c1_initial = 1;
+ parameter c1_mode = "bypass";
+ parameter c1_ph = 0;
+ parameter c2_high = 1;
+ parameter c2_low = 1;
+ parameter c2_initial = 1;
+ parameter c2_mode = "bypass";
+ parameter c2_ph = 0;
+ parameter c3_high = 1;
+ parameter c3_low = 1;
+ parameter c3_initial = 1;
+ parameter c3_mode = "bypass";
+ parameter c3_ph = 0;
+ parameter c4_high = 1;
+ parameter c4_low = 1;
+ parameter c4_initial = 1;
+ parameter c4_mode = "bypass";
+ parameter c4_ph = 0;
+ parameter m_ph = 0;
+ parameter clk0_counter = "unused";
+ parameter clk1_counter = "unused";
+ parameter clk2_counter = "unused";
+ parameter clk3_counter = "unused";
+ parameter clk4_counter = "unused";
+ parameter c1_use_casc_in = "off";
+ parameter c2_use_casc_in = "off";
+ parameter c3_use_casc_in = "off";
+ parameter c4_use_casc_in = "off";
+ parameter m_test_source = -1;
+ parameter c0_test_source = -1;
+ parameter c1_test_source = -1;
+ parameter c2_test_source = -1;
+ parameter c3_test_source = -1;
+ parameter c4_test_source = -1;
+ parameter vco_multiply_by = 0;
+ parameter vco_divide_by = 0;
+ parameter vco_post_scale = 1;
+ parameter vco_frequency_control = "auto";
+ parameter vco_phase_shift_step = 0;
+ parameter charge_pump_current = 10;
+ parameter loop_filter_r = "1.0";
+ parameter loop_filter_c = 0;
+ parameter pll_compensation_delay = 0;
+ parameter lpm_type = "cycloneive_pll";
+ parameter phase_counter_select_width = 3;
+
+ input [1:0] inclk;
+ input fbin;
+ input clkswitch;
+ input areset;
+ input pfdena;
+ input [phase_counter_select_width - 1:0] phasecounterselect;
+ input phaseupdown;
+ input phasestep;
+ input scanclk;
+ input scanclkena;
+ input scandata;
+ input configupdate;
+
+ output [4:0] clk;
+ output [1:0] clkbad;
+ output activeclock;
+ output locked;
+ output scandataout;
+ output scandone;
+ output fbout;
+ output phasedone;
+ output vcooverrange;
+ output vcounderrange;
+
+endmodule // cycloneive_pll
diff --git a/techlibs/intel/cyclonev/cells_arith.v b/techlibs/intel/cyclonev/cells_arith.v
new file mode 100644
index 00000000..89fb4561
--- /dev/null
+++ b/techlibs/intel/cyclonev/cells_arith.v
@@ -0,0 +1,65 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+
+// NOTE: This is still WIP.
+(* techmap_celltype = "$alu" *)
+module _80_altera_a10gx_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 [Y_WIDTH-1:0] CO;
+ output CO;
+
+ wire _TECHMAP_FAIL_ = Y_WIDTH <= 4;
+
+ 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:0] C = {CO, CI};
+ wire [Y_WIDTH+1:0] COx;
+ wire [Y_WIDTH+1:0] C = {COx, CI};
+
+ /* Start implementation */
+ (* keep *) fiftyfivenm_lcell_comb #(.lut_mask(16'b0000_0000_1010_1010), .sum_lutc_input("cin")) carry_start (.cout(COx[0]), .dataa(C[0]), .datab(1'b1), .datac(1'b1), .datad(1'b1));
+
+ genvar i;
+ generate for (i = 0; i < Y_WIDTH; i = i + 1) begin: slice
+ if(i==Y_WIDTH-1) begin
+ (* keep *) fiftyfivenm_lcell_comb #(.lut_mask(16'b1111_0000_1110_0000), .sum_lutc_input("cin")) carry_end (.combout(COx[Y_WIDTH]), .dataa(1'b1), .datab(1'b1), .datac(1'b1), .datad(1'b1), .cin(C[Y_WIDTH]));
+ assign CO = COx[Y_WIDTH];
+ end
+ else
+ fiftyfivenm_lcell_comb #(.lut_mask(16'b1001_0110_1110_1000), .sum_lutc_input("cin")) arith_cell (.combout(Y[i]), .cout(COx[i+1]), .dataa(AA[i]), .datab(BB[i]), .datac(1'b1), .datad(1'b1), .cin(C[i+1]));
+ end: slice
+ endgenerate
+ /* End implementation */
+ assign X = AA ^ BB;
+
+endmodule
diff --git a/techlibs/intel/cyclonev/cells_map.v b/techlibs/intel/cyclonev/cells_map.v
new file mode 100644
index 00000000..bd60d4e1
--- /dev/null
+++ b/techlibs/intel/cyclonev/cells_map.v
@@ -0,0 +1,162 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+// > c60k28 (Viacheslav, VT) [at] yandex [dot] com
+// > Intel FPGA technology mapping. User must first simulate the generated \
+// > netlist before going to test it on board.
+// > Changelog: 1) The missing power_up parameter in the techmap introduces a problem in Quartus mapper. Fixed.
+// 2) Cyclone V 7-input LUT function was wrong implemented. Removed abc option to map this function \
+// and added the explanation in this file instead. Such function needs to be implemented.
+
+// Normal mode DFF negedge clk, negedge reset
+module \$_DFF_N_ (input D, C, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+endmodule
+// Normal mode DFF
+module \$_DFF_P_ (input D, C, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+endmodule
+
+// Async Active Low Reset DFF
+module \$_DFF_PN0_ (input D, C, R, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up("power_up")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+endmodule
+// Async Active High Reset DFF
+module \$_DFF_PP0_ (input D, C, R, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ wire R_i = ~ R;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R_i), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+endmodule
+
+module \$__DFFE_PP0 (input D, C, E, R, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ wire E_i = ~ E;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0));
+endmodule
+
+// Input buffer map
+module \$__inpad (input I, output O);
+ cyclonev_io_ibuf _TECHMAP_REPLACE_ (.o(O), .i(I), .ibar(1'b0));
+endmodule
+
+// Output buffer map
+module \$__outpad (input I, output O);
+ cyclonev_io_obuf _TECHMAP_REPLACE_ (.o(O), .i(I), .oe(1'b1));
+endmodule
+
+// LUT Map
+module \$lut (A, Y);
+ parameter WIDTH = 0;
+ parameter LUT = 0;
+ input [WIDTH-1:0] A;
+ output Y;
+ wire VCC;
+ wire GND;
+ assign {VCC,GND} = {1'b1,1'b0};
+
+ generate
+ if (WIDTH == 1) begin
+ assign Y = ~A[0]; // Not need to spend 1 logic cell for such an easy function
+ end
+ else
+ if (WIDTH == 2) begin
+ cyclonev_lcell_comb #(.lut_mask({16{LUT}}), .shared_arith("off"), .extended_lut("off"))
+ _TECHMAP_REPLACE_
+ (.combout(Y),
+ .dataa(A[0]),
+ .datab(A[1]),
+ .datac(VCC),
+ .datad(VCC),
+ .datae(VCC),
+ .dataf(VCC),
+ .datag(VCC));
+ end
+ else
+ if(WIDTH == 3) begin
+ cyclonev_lcell_comb #(.lut_mask({8{LUT}}), .shared_arith("off"), .extended_lut("off"))
+ _TECHMAP_REPLACE_
+ (.combout(Y),
+ .dataa(A[0]),
+ .datab(A[1]),
+ .datac(A[2]),
+ .datad(VCC),
+ .datae(VCC),
+ .dataf(VCC),
+ .datag(VCC));
+ end
+ else
+ if(WIDTH == 4) begin
+ cyclonev_lcell_comb #(.lut_mask({4{LUT}}), .shared_arith("off"), .extended_lut("off"))
+ _TECHMAP_REPLACE_
+ (.combout(Y),
+ .dataa(A[0]),
+ .datab(A[1]),
+ .datac(A[2]),
+ .datad(A[3]),
+ .datae(VCC),
+ .dataf(VCC),
+ .datag(VCC));
+ end
+ else
+ if(WIDTH == 5) begin
+ cyclonev_lcell_comb #(.lut_mask({2{LUT}}), .shared_arith("off"), .extended_lut("off"))
+ _TECHMAP_REPLACE_
+ (.combout(Y),
+ .dataa(A[0]),
+ .datab(A[1]),
+ .datac(A[2]),
+ .datad(A[3]),
+ .datae(A[4]),
+ .dataf(VCC),
+ .datag(VCC));
+ end
+ else
+ if(WIDTH == 6) begin
+ cyclonev_lcell_comb #(.lut_mask(LUT), .shared_arith("off"), .extended_lut("off"))
+ _TECHMAP_REPLACE_
+ (.combout(Y),
+ .dataa(A[0]),
+ .datab(A[1]),
+ .datac(A[2]),
+ .datad(A[3]),
+ .datae(A[4]),
+ .dataf(A[5]),
+ .datag(VCC));
+ end
+ /*else
+ if(WIDTH == 7) begin
+ TODO: There's not a just 7-input function on Cyclone V, see the following note:
+ **Extended LUT Mode**
+ Use extended LUT mode to implement a specific set of 7-input functions. The set must
+ be a 2-to-1 multiplexer fed by two arbitrary 5-input functions sharing four inputs.
+ [source](Device Interfaces and Integration Basics for Cyclone V Devices).
+ end*/
+ else
+ wire _TECHMAP_FAIL_ = 1;
+ endgenerate
+endmodule // lut
+
+
diff --git a/techlibs/intel/cyclonev/cells_sim.v b/techlibs/intel/cyclonev/cells_sim.v
new file mode 100644
index 00000000..5ecdabcf
--- /dev/null
+++ b/techlibs/intel/cyclonev/cells_sim.v
@@ -0,0 +1,144 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+module VCC (output V);
+ assign V = 1'b1;
+endmodule // VCC
+
+module GND (output G);
+ assign G = 1'b0;
+endmodule // GND
+
+/* Altera Cyclone V devices Input Buffer Primitive */
+module cyclonev_io_ibuf
+ (output o, input i, input ibar);
+ assign ibar = ibar;
+ assign o = i;
+endmodule // cyclonev_io_ibuf
+
+/* Altera Cyclone V devices Output Buffer Primitive */
+module cyclonev_io_obuf
+ (output o, input i, input oe);
+ assign o = i;
+ assign oe = oe;
+endmodule // cyclonev_io_obuf
+
+/* Altera Cyclone V LUT Primitive */
+module cyclonev_lcell_comb
+ (output combout, cout, sumout, shareout,
+ input dataa, datab, datac, datad,
+ input datae, dataf, datag, cin,
+ input sharein);
+
+ parameter lut_mask = 64'hFFFFFFFFFFFFFFFF;
+ parameter dont_touch = "off";
+ parameter lpm_type = "cyclonev_lcell_comb";
+ parameter shared_arith = "off";
+ parameter extended_lut = "off";
+
+ // Internal variables
+ // Sub mask for fragmented LUTs
+ wire [15:0] mask_a, mask_b, mask_c, mask_d;
+ // Independant output for fragmented LUTs
+ wire output_0, output_1, output_2, output_3;
+ // Extended mode uses mux to define the output
+ wire mux_0, mux_1;
+ // Input for hold the shared LUT mode value
+ wire shared_lut_alm;
+
+ // Simulation model of 4-input LUT
+ function lut4;
+ input [15:0] mask;
+ input dataa, datab, datac, datad;
+ reg [7:0] s3;
+ reg [3:0] s2;
+ reg [1:0] s1;
+ begin
+ s3 = datad ? mask[15:8] : mask[7:0];
+ s2 = datac ? s3[7:4] : s3[3:0];
+ s1 = datab ? s2[3:2] : s2[1:0];
+ lut4 = dataa ? s1[1] : s1[0];
+ end
+ endfunction // lut4
+
+ // Simulation model of 5-input LUT
+ function lut5;
+ input [31:0] mask; // wp-01003.pdf, page 3: "a 5-LUT can be built with two 4-LUTs and a multiplexer.
+ input dataa, datab, datac, datad, datae;
+ reg upper_lut_value;
+ reg lower_lut_value;
+ begin
+ upper_lut_value = lut4(mask[31:16], dataa, datab, datac, datad);
+ lower_lut_value = lut4(mask[15:0], dataa, datab, datac, datad);
+ lut5 = (datae) ? upper_mask_value : lower_mask_value;
+ end
+ endfunction // lut5
+
+ // Simulation model of 6-input LUT
+ function lut6;
+ input [63:0] mask;
+ input dataa, datab, datac, datad, datae, dataf;
+ reg upper_lut_value;
+ reg lower_lut_value;
+ begin
+ upper_lut_value = lut5(mask[63:32], dataa, datab, datac, datad, datae);
+ lower_lut_value = lut5(mask[31:0], dataa, datab, datac, datad, datae);
+ lut6 = (dataf) ? upper_mask_value : lower_mask_value;
+ end
+ endfunction // lut6
+
+ assign {mask_a, mask_b, mask_c, mask_d} = {lut_mask[15:0], lut_mask[31:16], lut_mask[47:32], lut_mask[63:48]};
+
+ always @(*) begin
+ if(extended_lut == "on")
+ shared_lut_alm = datag;
+ else
+ shared_lut_alm = datac;
+ // Build the ALM behaviour
+ out_0 = lut4(mask_a, dataa, datab, datac, datad);
+ out_1 = lut4(mask_b, dataa, datab, shared_lut_alm, datad);
+ out_2 = lut4(mask_c, dataa, datab, datac, datad);
+ out_3 = lut4(mask_d, dataa, datab, shared_lut_alm, datad);
+ end
+endmodule // cyclonev_lcell_comb
+
+
+/* Altera D Flip-Flop Primitive */
+module dffeas
+ (output q,
+ input d, clk, clrn, prn, ena,
+ input asdata, aload, sclr, sload);
+
+ // Timing simulation is not covered
+ parameter power_up="dontcare";
+ parameter is_wysiwyg="false";
+
+ reg q_tmp;
+ wire reset;
+ reg [7:0] debug_net;
+
+ assign reset = (prn && sclr && ~clrn && ena);
+ assign q = q_tmp & 1'b1;
+
+ always @(posedge clk, posedge aload) begin
+ if(reset) q_tmp <= 0;
+ else q_tmp <= d;
+ end
+ assign q = q_tmp;
+
+endmodule // dffeas
diff --git a/techlibs/intel/max10/cells_arith.v b/techlibs/intel/max10/cells_arith.v
new file mode 100644
index 00000000..e2194cbd
--- /dev/null
+++ b/techlibs/intel/max10/cells_arith.v
@@ -0,0 +1,65 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+
+// NOTE: This is still WIP.
+(* techmap_celltype = "$alu" *)
+module _80_altera_max10_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 [Y_WIDTH-1:0] CO;
+ output CO;
+
+ wire _TECHMAP_FAIL_ = Y_WIDTH <= 4;
+
+ 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:0] C = {CO, CI};
+ wire [Y_WIDTH+1:0] COx;
+ wire [Y_WIDTH+1:0] C = {COx, CI};
+
+ /* Start implementation */
+ (* keep *) fiftyfivenm_lcell_comb #(.lut_mask(16'b0000_0000_1010_1010), .sum_lutc_input("cin")) carry_start (.cout(COx[0]), .dataa(C[0]), .datab(1'b1), .datac(1'b1), .datad(1'b1));
+
+ genvar i;
+ generate for (i = 0; i < Y_WIDTH; i = i + 1) begin: slice
+ if(i==Y_WIDTH-1) begin
+ (* keep *) fiftyfivenm_lcell_comb #(.lut_mask(16'b1111_0000_1110_0000), .sum_lutc_input("cin")) carry_end (.combout(COx[Y_WIDTH]), .dataa(1'b1), .datab(1'b1), .datac(1'b1), .datad(1'b1), .cin(C[Y_WIDTH]));
+ assign CO = COx[Y_WIDTH];
+ end
+ else
+ fiftyfivenm_lcell_comb #(.lut_mask(16'b1001_0110_1110_1000), .sum_lutc_input("cin")) arith_cell (.combout(Y[i]), .cout(COx[i+1]), .dataa(AA[i]), .datab(BB[i]), .datac(1'b1), .datad(1'b1), .cin(C[i+1]));
+ end: slice
+ endgenerate
+ /* End implementation */
+ assign X = AA ^ BB;
+
+endmodule
diff --git a/techlibs/intel/max10/cells_map.v b/techlibs/intel/max10/cells_map.v
new file mode 100644
index 00000000..6d604e07
--- /dev/null
+++ b/techlibs/intel/max10/cells_map.v
@@ -0,0 +1,93 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+// > c60k28 (Viacheslav, VT) [at] yandex [dot] com
+// > Intel FPGA technology mapping. User must first simulate the generated \
+// > netlist before going to test it on board.
+// > Changelog: 1) The missing power_up parameter in the techmap introduces a problem in Quartus mapper. Fixed.
+
+// Normal mode DFF negedge clk, negedge reset
+module \$_DFF_N_ (input D, C, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+endmodule
+// Normal mode DFF
+module \$_DFF_P_ (input D, C, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(1'b1), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+endmodule
+
+// Async Active Low Reset DFF
+module \$_DFF_PN0_ (input D, C, R, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up("power_up")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+endmodule
+// Async Active High Reset DFF
+module \$_DFF_PP0_ (input D, C, R, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ wire R_i = ~ R;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R_i), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(1'b0), .sload(1'b0));
+endmodule
+
+module \$__DFFE_PP0 (input D, C, E, R, output Q);
+ parameter WYSIWYG="TRUE";
+ parameter power_up=1'bx;
+ wire E_i = ~ E;
+ dffeas #(.is_wysiwyg(WYSIWYG), .power_up(power_up)) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .clrn(R), .prn(1'b1), .ena(1'b1), .asdata(1'b0), .aload(1'b0), .sclr(E_i), .sload(1'b0));
+endmodule
+
+// Input buffer map
+module \$__inpad (input I, output O);
+ fiftyfivenm_io_ibuf _TECHMAP_REPLACE_ (.o(O), .i(I), .ibar(1'b0));
+endmodule
+
+// Output buffer map
+module \$__outpad (input I, output O);
+ fiftyfivenm_io_obuf _TECHMAP_REPLACE_ (.o(O), .i(I), .oe(1'b1));
+endmodule
+
+// LUT Map
+/* 0 -> datac
+ 1 -> cin */
+module \$lut (A, Y);
+ parameter WIDTH = 0;
+ parameter LUT = 0;
+ input [WIDTH-1:0] A;
+ output Y;
+ generate
+ if (WIDTH == 1) begin
+ assign Y = ~A[0]; // Not need to spend 1 logic cell for such an easy function
+ end else
+ if (WIDTH == 2) begin
+ fiftyfivenm_lcell_comb #(.lut_mask({4{LUT}}), .sum_lutc_input("datac")) _TECHMAP_REPLACE_ (.combout(Y), .dataa(A[0]), .datab(A[1]), .datac(1'b1),.datad(1'b1));
+ end else
+ if(WIDTH == 3) begin
+ fiftyfivenm_lcell_comb #(.lut_mask({2{LUT}}), .sum_lutc_input("datac")) _TECHMAP_REPLACE_ (.combout(Y), .dataa(A[0]), .datab(A[1]), .datac(A[2]),.datad(1'b1));
+ end else
+ if(WIDTH == 4) begin
+ fiftyfivenm_lcell_comb #(.lut_mask(LUT), .sum_lutc_input("datac")) _TECHMAP_REPLACE_ (.combout(Y), .dataa(A[0]), .datab(A[1]), .datac(A[2]),.datad(A[3]));
+ end else
+ wire _TECHMAP_FAIL_ = 1;
+ endgenerate
+endmodule //
+
+
diff --git a/techlibs/intel/max10/cells_sim.v b/techlibs/intel/max10/cells_sim.v
new file mode 100644
index 00000000..98673596
--- /dev/null
+++ b/techlibs/intel/max10/cells_sim.v
@@ -0,0 +1,292 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+
+module VCC (output V);
+ assign V = 1'b1;
+endmodule // VCC
+
+module GND (output G);
+ assign G = 1'b0;
+endmodule // GND
+
+/* Altera MAX10 devices Input Buffer Primitive */
+module fiftyfivenm_io_ibuf
+ (output o, input i, input ibar);
+ assign ibar = ibar;
+ assign o = i;
+endmodule // fiftyfivenm_io_ibuf
+
+/* Altera MAX10 devices Output Buffer Primitive */
+module fiftyfivenm_io_obuf
+ (output o, input i, input oe);
+ assign o = i;
+ assign oe = oe;
+endmodule // fiftyfivenm_io_obuf
+
+/* Altera MAX10 4-input non-fracturable LUT Primitive */
+module fiftyfivenm_lcell_comb
+ (output combout, cout,
+ input dataa, datab, datac, datad, cin);
+
+ /* Internal parameters which define the behaviour
+ of the LUT primitive.
+ lut_mask define the lut function, can be expressed in 16-digit bin or hex.
+ sum_lutc_input define the type of LUT (combinational | arithmetic).
+ dont_touch for retiming || carry options.
+ lpm_type for WYSIWYG */
+
+ parameter lut_mask = 16'hFFFF;
+ parameter dont_touch = "off";
+ parameter lpm_type = "fiftyfivenm_lcell_comb";
+ parameter sum_lutc_input = "datac";
+
+ reg [1:0] lut_type;
+ reg cout_rt;
+ reg combout_rt;
+ wire dataa_w;
+ wire datab_w;
+ wire datac_w;
+ wire datad_w;
+ wire cin_w;
+
+ assign dataa_w = dataa;
+ assign datab_w = datab;
+ assign datac_w = datac;
+ assign datad_w = datad;
+
+ function lut_data;
+ input [15:0] mask;
+ input dataa, datab, datac, datad;
+ reg [7:0] s3;
+ reg [3:0] s2;
+ reg [1:0] s1;
+ begin
+ s3 = datad ? mask[15:8] : mask[7:0];
+ s2 = datac ? s3[7:4] : s3[3:0];
+ s1 = datab ? s2[3:2] : s2[1:0];
+ lut_data = dataa ? s1[1] : s1[0];
+ end
+
+ endfunction
+
+ initial begin
+ if (sum_lutc_input == "datac") lut_type = 0;
+ else
+ if (sum_lutc_input == "cin") lut_type = 1;
+ else begin
+ $error("Error in sum_lutc_input. Parameter %s is not a valid value.\n", sum_lutc_input);
+ $finish();
+ end
+ end
+
+ always @(dataa_w or datab_w or datac_w or datad_w or cin_w) begin
+ if (lut_type == 0) begin // logic function
+ combout_rt = lut_data(lut_mask, dataa_w, datab_w,
+ datac_w, datad_w);
+ end
+ else if (lut_type == 1) begin // arithmetic function
+ combout_rt = lut_data(lut_mask, dataa_w, datab_w,
+ cin_w, datad_w);
+ end
+ cout_rt = lut_data(lut_mask, dataa_w, datab_w, cin_w, 'b0);
+ end
+
+ assign combout = combout_rt & 1'b1;
+ assign cout = cout_rt & 1'b1;
+
+endmodule // fiftyfivenm_lcell_comb
+
+/* Altera D Flip-Flop Primitive */
+module dffeas
+ (output q,
+ input d, clk, clrn, prn, ena,
+ input asdata, aload, sclr, sload);
+
+ // Timing simulation is not covered
+ parameter power_up="dontcare";
+ parameter is_wysiwyg="false";
+
+ reg q_tmp;
+ wire reset;
+ reg [7:0] debug_net;
+
+ assign reset = (prn && sclr && ~clrn && ena);
+ assign q = q_tmp & 1'b1;
+
+ always @(posedge clk, posedge aload) begin
+ if(reset) q_tmp <= 0;
+ else q_tmp <= d;
+ end
+ assign q = q_tmp;
+
+endmodule // dffeas
+
+/* MAX10 altpll clearbox model */
+(* blackbox *)
+module fiftyfivenm_pll
+ (inclk,
+ fbin,
+ fbout,
+ clkswitch,
+ areset,
+ pfdena,
+ scanclk,
+ scandata,
+ scanclkena,
+ configupdate,
+ clk,
+ phasecounterselect,
+ phaseupdown,
+ phasestep,
+ clkbad,
+ activeclock,
+ locked,
+ scandataout,
+ scandone,
+ phasedone,
+ vcooverrange,
+ vcounderrange);
+
+ parameter operation_mode = "normal";
+ parameter pll_type = "auto";
+ parameter compensate_clock = "clock0";
+ parameter inclk0_input_frequency = 0;
+ parameter inclk1_input_frequency = 0;
+ parameter self_reset_on_loss_lock = "off";
+ parameter switch_over_type = "auto";
+ parameter switch_over_counter = 1;
+ parameter enable_switch_over_counter = "off";
+ parameter bandwidth = 0;
+ parameter bandwidth_type = "auto";
+ parameter use_dc_coupling = "false";
+ parameter lock_high = 0;
+ parameter lock_low = 0;
+ parameter lock_window_ui = "0.05";
+ parameter test_bypass_lock_detect = "off";
+ parameter clk0_output_frequency = 0;
+ parameter clk0_multiply_by = 0;
+ parameter clk0_divide_by = 0;
+ parameter clk0_phase_shift = "0";
+ parameter clk0_duty_cycle = 50;
+ parameter clk1_output_frequency = 0;
+ parameter clk1_multiply_by = 0;
+ parameter clk1_divide_by = 0;
+ parameter clk1_phase_shift = "0";
+ parameter clk1_duty_cycle = 50;
+ parameter clk2_output_frequency = 0;
+ parameter clk2_multiply_by = 0;
+ parameter clk2_divide_by = 0;
+ parameter clk2_phase_shift = "0";
+ parameter clk2_duty_cycle = 50;
+ parameter clk3_output_frequency = 0;
+ parameter clk3_multiply_by = 0;
+ parameter clk3_divide_by = 0;
+ parameter clk3_phase_shift = "0";
+ parameter clk3_duty_cycle = 50;
+ parameter clk4_output_frequency = 0;
+ parameter clk4_multiply_by = 0;
+ parameter clk4_divide_by = 0;
+ parameter clk4_phase_shift = "0";
+ parameter clk4_duty_cycle = 50;
+ parameter pfd_min = 0;
+ parameter pfd_max = 0;
+ parameter vco_min = 0;
+ parameter vco_max = 0;
+ parameter vco_center = 0;
+ // Advanced user parameters
+ parameter m_initial = 1;
+ parameter m = 0;
+ parameter n = 1;
+ parameter c0_high = 1;
+ parameter c0_low = 1;
+ parameter c0_initial = 1;
+ parameter c0_mode = "bypass";
+ parameter c0_ph = 0;
+ parameter c1_high = 1;
+ parameter c1_low = 1;
+ parameter c1_initial = 1;
+ parameter c1_mode = "bypass";
+ parameter c1_ph = 0;
+ parameter c2_high = 1;
+ parameter c2_low = 1;
+ parameter c2_initial = 1;
+ parameter c2_mode = "bypass";
+ parameter c2_ph = 0;
+ parameter c3_high = 1;
+ parameter c3_low = 1;
+ parameter c3_initial = 1;
+ parameter c3_mode = "bypass";
+ parameter c3_ph = 0;
+ parameter c4_high = 1;
+ parameter c4_low = 1;
+ parameter c4_initial = 1;
+ parameter c4_mode = "bypass";
+ parameter c4_ph = 0;
+ parameter m_ph = 0;
+ parameter clk0_counter = "unused";
+ parameter clk1_counter = "unused";
+ parameter clk2_counter = "unused";
+ parameter clk3_counter = "unused";
+ parameter clk4_counter = "unused";
+ parameter c1_use_casc_in = "off";
+ parameter c2_use_casc_in = "off";
+ parameter c3_use_casc_in = "off";
+ parameter c4_use_casc_in = "off";
+ parameter m_test_source = -1;
+ parameter c0_test_source = -1;
+ parameter c1_test_source = -1;
+ parameter c2_test_source = -1;
+ parameter c3_test_source = -1;
+ parameter c4_test_source = -1;
+ parameter vco_multiply_by = 0;
+ parameter vco_divide_by = 0;
+ parameter vco_post_scale = 1;
+ parameter vco_frequency_control = "auto";
+ parameter vco_phase_shift_step = 0;
+ parameter charge_pump_current = 10;
+ parameter loop_filter_r = "1.0";
+ parameter loop_filter_c = 0;
+ parameter pll_compensation_delay = 0;
+ parameter lpm_type = "fiftyfivenm_pll";
+ parameter phase_counter_select_width = 3;
+
+ input [1:0] inclk;
+ input fbin;
+ input clkswitch;
+ input areset;
+ input pfdena;
+ input [phase_counter_select_width - 1:0] phasecounterselect;
+ input phaseupdown;
+ input phasestep;
+ input scanclk;
+ input scanclkena;
+ input scandata;
+ input configupdate;
+ output [4:0] clk;
+ output [1:0] clkbad;
+ output activeclock;
+ output locked;
+ output scandataout;
+ output scandone;
+ output fbout;
+ output phasedone;
+ output vcooverrange;
+ output vcounderrange;
+
+endmodule // cycloneive_pll
diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc
new file mode 100644
index 00000000..d74f295e
--- /dev/null
+++ b/techlibs/intel/synth_intel.cc
@@ -0,0 +1,270 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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 SynthIntelPass : public ScriptPass {
+ SynthIntelPass() : ScriptPass("synth_intel", "synthesis for Intel (Altera) FPGAs.") { }
+
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" synth_intel [options]\n");
+ log("\n");
+ log("This command runs synthesis for Intel FPGAs.\n");
+ log("\n");
+ log(" -family < max10 | a10gx | cyclone10 | cyclonev | cycloneiv | cycloneive>\n");
+ log(" generate the synthesis netlist for the specified family.\n");
+ log(" MAX10 is the default target if not family argument specified.\n");
+ log(" For Cyclone GX devices, use cycloneiv argument; For Cyclone E, use cycloneive.\n");
+ log(" Cyclone V and Arria 10 GX devices are experimental, use it with a10gx argument.\n");
+ log("\n");
+ log(" -top <module>\n");
+ log(" use the specified module as top module (default='top')\n");
+ log("\n");
+ log(" -vqm <file>\n");
+ log(" write the design to the specified Verilog Quartus Mapping File. Writing of an\n");
+ log(" output file is omitted if this parameter is not specified.\n");
+ log("\n");
+ log(" -vpr <file>\n");
+ log(" write BLIF files for VPR flow experiments. The synthesized BLIF output file is not\n");
+ log(" compatible with the Quartus flow. Writing of an\n");
+ log(" output file is omitted if this parameter is not specified.\n");
+ log("\n");
+ log(" -run <from_label>:<to_label>\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(" -noiopads\n");
+ log(" do not use altsyncram cells in output netlist\n");
+ log("\n");
+ log(" -nobram\n");
+ log(" do not use altsyncram cells in output netlist\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("The following commands are executed by this synthesis command:\n");
+ help_script();
+ log("\n");
+ }
+
+ string top_opt, family_opt, vout_file, blif_file;
+ bool retime, flatten, nobram, noiopads;
+
+ void clear_flags() YS_OVERRIDE
+ {
+ top_opt = "-auto-top";
+ family_opt = "max10";
+ vout_file = "";
+ blif_file = "";
+ retime = false;
+ flatten = true;
+ nobram = false;
+ noiopads = false;
+ }
+
+ void execute(std::vector<std::string> 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] == "-family" && argidx+1 < args.size()) {
+ family_opt = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-top" && argidx+1 < args.size()) {
+ top_opt = "-top " + args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-vqm" && argidx+1 < args.size()) {
+ vout_file = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-vpr" && argidx+1 < args.size()) {
+ blif_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] == "-noiopads") {
+ noiopads = true;
+ continue;
+ }
+ if (args[argidx] == "-nobram") {
+ nobram = true;
+ continue;
+ }
+ if (args[argidx] == "-flatten") {
+ flatten = true;
+ 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");
+ if (family_opt != "max10" && family_opt !="a10gx" && family_opt != "cyclonev" && family_opt !="cycloneiv" && family_opt !="cycloneive" && family_opt != "cyclone10")
+ log_cmd_error("Invalid or not family specified: '%s'\n", family_opt.c_str());
+
+ log_header(design, "Executing SYNTH_INTEL pass.\n");
+ log_push();
+
+ run_script(design, run_from, run_to);
+
+ log_pop();
+ }
+
+ void script() YS_OVERRIDE
+ {
+ if (check_label("begin"))
+ {
+ if(check_label("family") && family_opt=="max10")
+ run("read_verilog -sv -lib +/intel/max10/cells_sim.v");
+ else if(check_label("family") && family_opt=="a10gx")
+ run("read_verilog -sv -lib +/intel/a10gx/cells_sim.v");
+ else if(check_label("family") && family_opt=="cyclonev")
+ run("read_verilog -sv -lib +/intel/cyclonev/cells_sim.v");
+ else if(check_label("family") && family_opt=="cyclone10")
+ run("read_verilog -sv -lib +/intel/cyclone10/cells_sim.v");
+ else if(check_label("family") && family_opt=="cycloneiv")
+ run("read_verilog -sv -lib +/intel/cycloneiv/cells_sim.v");
+ else
+ run("read_verilog -sv -lib +/intel/cycloneive/cells_sim.v");
+ // Misc and common cells
+ run("read_verilog -sv -lib +/intel/common/m9k_bb.v");
+ run("read_verilog -sv -lib +/intel/common/altpll_bb.v");
+ run(stringf("hierarchy -check %s", help_mode ? "-top <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 (!nobram && check_label("bram", "(skip if -nobram)"))
+ {
+ run("memory_bram -rules +/intel/common/brams.txt");
+ run("techmap -map +/intel/common/brams_map.v");
+ }
+
+ if (check_label("fine"))
+ {
+ run("opt -fast -mux_undef -undriven -fine -full");
+ run("memory_map");
+ run("opt -undriven -fine");
+ run("dffsr2dff");
+ run("dff2dffe -direct-match $_DFF_*");
+ run("opt -fine");
+ run("techmap -map +/techmap.v");
+ run("opt -full");
+ run("clean -purge");
+ run("setundef -undriven -zero");
+ if (retime || help_mode)
+ run("abc -markgroups -dff", "(only if -retime)");
+ }
+
+ if (check_label("map_luts"))
+ {
+ if(family_opt=="a10gx" || family_opt=="cyclonev")
+ run("abc -luts 2:2,3,6:5" + string(retime ? " -dff" : ""));
+ else
+ run("abc -lut 4" + string(retime ? " -dff" : ""));
+ run("clean");
+ }
+
+ if (check_label("map_cells"))
+ {
+ if (!noiopads)
+ run("iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I", "(unless -noiopads)");
+ if(family_opt=="max10")
+ run("techmap -map +/intel/max10/cells_map.v");
+ else if(family_opt=="a10gx")
+ run("techmap -map +/intel/a10gx/cells_map.v");
+ else if(family_opt=="cyclonev")
+ run("techmap -map +/intel/cyclonev/cells_map.v");
+ else if(family_opt=="cyclone10")
+ run("techmap -map +/intel/cyclone10/cells_map.v");
+ else if(family_opt=="cycloneiv")
+ run("techmap -map +/intel/cycloneiv/cells_map.v");
+ else
+ run("techmap -map +/intel/cycloneive/cells_map.v");
+ run("dffinit -highlow -ff dffeas q power_up");
+ run("clean -purge");
+ }
+
+ if (check_label("check"))
+ {
+ run("hierarchy -check");
+ run("stat");
+ run("check -noinit");
+ }
+
+ if (check_label("vqm"))
+ {
+ if (!vout_file.empty() || help_mode)
+ run(stringf("write_verilog -attr2comment -defparam -nohex -decimal -renameprefix syn_ %s",
+ help_mode ? "<file-name>" : vout_file.c_str()));
+ }
+
+ if (check_label("vpr"))
+ {
+ if (!blif_file.empty() || help_mode)
+ {
+ run(stringf("opt_clean -purge"));
+ run(stringf("write_blif %s", help_mode ? "<file-name>" : blif_file.c_str()));
+ }
+ }
+ }
+} SynthIntelPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc
index 5f09ffb0..887ea27d 100644
--- a/techlibs/xilinx/Makefile.inc
+++ b/techlibs/xilinx/Makefile.inc
@@ -27,8 +27,8 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/brams_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/brams_bb.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams.txt))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams_map.v))
-$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams_bb.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut2lut.v))
$(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_36.vh))
$(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_32.vh))
diff --git a/techlibs/xilinx/brams_init.py b/techlibs/xilinx/brams_init.py
index e787b1f7..d46a2b4f 100644
--- a/techlibs/xilinx/brams_init.py
+++ b/techlibs/xilinx/brams_init.py
@@ -2,27 +2,27 @@
with open("techlibs/xilinx/brams_init_18.vh", "w") as f:
for i in range(8):
- init_snippets = ["INIT[%3d*9+8]" % (k+256*i,) for k in range(255, -1, -1)]
+ init_snippets = [" INIT[%3d*9+8]" % (k+256*i,) for k in range(255, -1, -1)]
for k in range(4, 256, 4):
init_snippets[k] = "\n " + init_snippets[k]
- print(".INITP_%02X({%s})," % (i, ", ".join(init_snippets)), file=f)
+ print(".INITP_%02X({%s})," % (i, ",".join(init_snippets)), file=f)
for i in range(64):
- init_snippets = ["INIT[%3d*9 +: 8]" % (k+32*i,) for k in range(31, -1, -1)]
+ init_snippets = [" INIT[%3d*9 +: 8]" % (k+32*i,) for k in range(31, -1, -1)]
for k in range(4, 32, 4):
init_snippets[k] = "\n " + init_snippets[k]
- print(".INIT_%02X({%s})," % (i, ", ".join(init_snippets)), file=f)
+ print(".INIT_%02X({%s})," % (i, ",".join(init_snippets)), file=f)
with open("techlibs/xilinx/brams_init_36.vh", "w") as f:
for i in range(16):
- init_snippets = ["INIT[%3d*9+8]" % (k+256*i,) for k in range(255, -1, -1)]
+ init_snippets = [" INIT[%3d*9+8]" % (k+256*i,) for k in range(255, -1, -1)]
for k in range(4, 256, 4):
init_snippets[k] = "\n " + init_snippets[k]
- print(".INITP_%02X({%s})," % (i, ", ".join(init_snippets)), file=f)
+ print(".INITP_%02X({%s})," % (i, ",".join(init_snippets)), file=f)
for i in range(128):
- init_snippets = ["INIT[%3d*9 +: 8]" % (k+32*i,) for k in range(31, -1, -1)]
+ init_snippets = [" INIT[%3d*9 +: 8]" % (k+32*i,) for k in range(31, -1, -1)]
for k in range(4, 32, 4):
init_snippets[k] = "\n " + init_snippets[k]
- print(".INIT_%02X({%s})," % (i, ", ".join(init_snippets)), file=f)
+ print(".INIT_%02X({%s})," % (i, ",".join(init_snippets)), file=f)
with open("techlibs/xilinx/brams_init_16.vh", "w") as f:
for i in range(64):
diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v
index 8e5a83ce..0771be0b 100644
--- a/techlibs/xilinx/cells_map.v
+++ b/techlibs/xilinx/cells_map.v
@@ -15,6 +15,7 @@ module \$_DFF_NP1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(
module \$_DFF_PN1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule
module \$_DFF_PP1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule
+`ifndef NO_LUT
module \$lut (A, Y);
parameter WIDTH = 0;
parameter LUT = 0;
@@ -82,3 +83,4 @@ module \$lut (A, Y);
end
endgenerate
endmodule
+`endif
diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v
index 1f114a22..eba17ac9 100644
--- a/techlibs/xilinx/cells_sim.v
+++ b/techlibs/xilinx/cells_sim.v
@@ -156,3 +156,33 @@ module FDPE (output reg Q, input C, CE, D, PRE);
endcase endgenerate
endmodule
+module RAM64X1D (
+ output DPO, SPO,
+ input D, WCLK, WE,
+ input A0, A1, A2, A3, A4, A5,
+ input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5
+);
+ parameter INIT = 64'h0;
+ parameter IS_WCLK_INVERTED = 1'b0;
+ wire [5:0] a = {A5, A4, A3, A2, A1, A0};
+ wire [5:0] dpra = {DPRA5, DPRA4, DPRA3, DPRA2, DPRA1, DPRA0};
+ reg [63:0] mem = INIT;
+ assign SPO = mem[a];
+ assign DPO = mem[dpra];
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ always @(posedge clk) if (WE) mem[a] <= D;
+endmodule
+
+module RAM128X1D (
+ output DPO, SPO,
+ input D, WCLK, WE,
+ input [6:0] A, DPRA
+);
+ parameter INIT = 128'h0;
+ parameter IS_WCLK_INVERTED = 1'b0;
+ reg [127:0] mem = INIT;
+ assign SPO = mem[A];
+ assign DPO = mem[DPRA];
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ always @(posedge clk) if (WE) mem[A] <= D;
+endmodule
diff --git a/techlibs/xilinx/drams_bb.v b/techlibs/xilinx/drams_bb.v
deleted file mode 100644
index 11168fe1..00000000
--- a/techlibs/xilinx/drams_bb.v
+++ /dev/null
@@ -1,20 +0,0 @@
-
-module RAM64X1D (
- output DPO, SPO,
- input D, WCLK, WE,
- input A0, A1, A2, A3, A4, A5,
- input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5
-);
- parameter INIT = 64'h0;
- parameter IS_WCLK_INVERTED = 1'b0;
-endmodule
-
-module RAM128X1D (
- output DPO, SPO,
- input D, WCLK, WE,
- input [6:0] A, DPRA
-);
- parameter INIT = 128'h0;
- parameter IS_WCLK_INVERTED = 1'b0;
-endmodule
-
diff --git a/techlibs/xilinx/lut2lut.v b/techlibs/xilinx/lut2lut.v
new file mode 100644
index 00000000..061ad204
--- /dev/null
+++ b/techlibs/xilinx/lut2lut.v
@@ -0,0 +1,65 @@
+module LUT1(output O, input I0);
+ parameter [1:0] INIT = 0;
+ \$lut #(
+ .WIDTH(1),
+ .LUT(INIT)
+ ) _TECHMAP_REPLACE_ (
+ .A(I0),
+ .Y(O)
+ );
+endmodule
+
+module LUT2(output O, input I0, I1);
+ parameter [3:0] INIT = 0;
+ \$lut #(
+ .WIDTH(2),
+ .LUT(INIT)
+ ) _TECHMAP_REPLACE_ (
+ .A({I1, I0}),
+ .Y(O)
+ );
+endmodule
+
+module LUT3(output O, input I0, I1, I2);
+ parameter [7:0] INIT = 0;
+ \$lut #(
+ .WIDTH(3),
+ .LUT(INIT)
+ ) _TECHMAP_REPLACE_ (
+ .A({I2, I1, I0}),
+ .Y(O)
+ );
+endmodule
+
+module LUT4(output O, input I0, I1, I2, I3);
+ parameter [15:0] INIT = 0;
+ \$lut #(
+ .WIDTH(4),
+ .LUT(INIT)
+ ) _TECHMAP_REPLACE_ (
+ .A({I3, I2, I1, I0}),
+ .Y(O)
+ );
+endmodule
+
+module LUT5(output O, input I0, I1, I2, I3, I4);
+ parameter [31:0] INIT = 0;
+ \$lut #(
+ .WIDTH(5),
+ .LUT(INIT)
+ ) _TECHMAP_REPLACE_ (
+ .A({I4, I3, I2, I1, I0}),
+ .Y(O)
+ );
+endmodule
+
+module LUT6(output O, input I0, I1, I2, I3, I4, I5);
+ parameter [63:0] INIT = 0;
+ \$lut #(
+ .WIDTH(6),
+ .LUT(INIT)
+ ) _TECHMAP_REPLACE_ (
+ .A({I5, I4, I3, I2, I1, I0}),
+ .Y(O)
+ );
+endmodule
diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc
index e7ec1e6e..590fe61d 100644
--- a/techlibs/xilinx/synth_xilinx.cc
+++ b/techlibs/xilinx/synth_xilinx.cc
@@ -34,9 +34,11 @@ bool check_label(bool &active, std::string run_from, std::string run_to, std::st
return active;
}
-struct SynthXilinxPass : public Pass {
+struct SynthXilinxPass : public Pass
+{
SynthXilinxPass() : Pass("synth_xilinx", "synthesis for Xilinx FPGAs") { }
- virtual void help()
+
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -53,6 +55,14 @@ struct SynthXilinxPass : public Pass {
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(" -blif <file>\n");
+ log(" write the design to the specified BLIF file. writing of an output file\n");
+ log(" is omitted if this parameter is not specified.\n");
+ log("\n");
+ log(" -vpr\n");
+ log(" generate an output netlist (and BLIF file) suitable for VPR\n");
+ log(" (this feature is experimental and incomplete)\n");
+ log("\n");
log(" -run <from_label>:<to_label>\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");
@@ -71,7 +81,6 @@ struct SynthXilinxPass : public Pass {
log(" read_verilog -lib +/xilinx/cells_sim.v\n");
log(" read_verilog -lib +/xilinx/cells_xtra.v\n");
log(" read_verilog -lib +/xilinx/brams_bb.v\n");
- log(" read_verilog -lib +/xilinx/drams_bb.v\n");
log(" hierarchy -check -top <top>\n");
log("\n");
log(" flatten: (only if -flatten)\n");
@@ -103,7 +112,7 @@ struct SynthXilinxPass : public Pass {
log(" clean\n");
log("\n");
log(" map_cells:\n");
- log(" techmap -map +/xilinx/cells_map.v\n");
+ log(" techmap -map +/xilinx/cells_map.v (with -D NO_LUT in vpr mode)\n");
log(" dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT\n");
log(" clean\n");
log("\n");
@@ -115,14 +124,19 @@ struct SynthXilinxPass : public Pass {
log(" edif: (only if -edif)\n");
log(" write_edif <file-name>\n");
log("\n");
+ log(" blif: (only if -blif)\n");
+ log(" write_blif <file-name>\n");
+ log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string top_opt = "-auto-top";
std::string edif_file;
+ std::string blif_file;
std::string run_from, run_to;
bool flatten = false;
bool retime = false;
+ bool vpr = false;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@@ -135,6 +149,10 @@ struct SynthXilinxPass : public Pass {
edif_file = args[++argidx];
continue;
}
+ if (args[argidx] == "-blif" && argidx+1 < args.size()) {
+ blif_file = args[++argidx];
+ continue;
+ }
if (args[argidx] == "-run" && argidx+1 < args.size()) {
size_t pos = args[argidx+1].find(':');
if (pos == std::string::npos)
@@ -151,6 +169,10 @@ struct SynthXilinxPass : public Pass {
retime = true;
continue;
}
+ if (args[argidx] == "-vpr") {
+ vpr = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -168,7 +190,6 @@ struct SynthXilinxPass : public Pass {
Pass::call(design, "read_verilog -lib +/xilinx/cells_sim.v");
Pass::call(design, "read_verilog -lib +/xilinx/cells_xtra.v");
Pass::call(design, "read_verilog -lib +/xilinx/brams_bb.v");
- Pass::call(design, "read_verilog -lib +/xilinx/drams_bb.v");
Pass::call(design, stringf("hierarchy -check %s", top_opt.c_str()));
}
@@ -214,7 +235,10 @@ struct SynthXilinxPass : public Pass {
if (check_label(active, run_from, run_to, "map_cells"))
{
- Pass::call(design, "techmap -map +/xilinx/cells_map.v");
+ if (vpr)
+ Pass::call(design, "techmap -D NO_LUT -map +/xilinx/cells_map.v");
+ else
+ Pass::call(design, "techmap -map +/xilinx/cells_map.v");
Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT");
Pass::call(design, "clean");
}
@@ -231,6 +255,11 @@ struct SynthXilinxPass : public Pass {
if (!edif_file.empty())
Pass::call(design, stringf("write_edif %s", edif_file.c_str()));
}
+ if (check_label(active, run_from, run_to, "blif"))
+ {
+ if (!blif_file.empty())
+ Pass::call(design, stringf("write_blif %s", edif_file.c_str()));
+ }
log_pop();
}