aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md6
-rw-r--r--backends/aiger/xaiger.cc9
-rw-r--r--frontends/ilang/ilang_parser.y4
-rw-r--r--frontends/verilog/verilog_parser.y10
-rw-r--r--kernel/rtlil.cc24
-rw-r--r--manual/CHAPTER_CellLib.tex91
-rw-r--r--passes/memory/memory_collect.cc4
-rw-r--r--passes/opt/opt_share.cc15
-rw-r--r--passes/pmgen/ice40_wrapcarry.cc75
-rw-r--r--passes/pmgen/xilinx_dsp.pmg6
-rw-r--r--passes/techmap/abc9.cc69
-rw-r--r--passes/techmap/iopadmap.cc243
-rw-r--r--techlibs/ecp5/cells_ff.vh8
-rw-r--r--techlibs/gowin/cells_map.v365
-rw-r--r--techlibs/gowin/synth_gowin.cc17
-rw-r--r--techlibs/ice40/arith_map.v2
-rw-r--r--techlibs/ice40/cells_map.v19
-rw-r--r--techlibs/ice40/ice40_opt.cc20
-rw-r--r--techlibs/ice40/synth_ice40.cc1
-rw-r--r--techlibs/intel/Makefile.inc2
-rw-r--r--techlibs/intel/arria10gx/cells_arith.v (renamed from techlibs/intel/a10gx/cells_arith.v)0
-rw-r--r--techlibs/intel/arria10gx/cells_map.v (renamed from techlibs/intel/a10gx/cells_map.v)0
-rw-r--r--techlibs/intel/arria10gx/cells_sim.v (renamed from techlibs/intel/a10gx/cells_sim.v)0
-rw-r--r--techlibs/intel/cyclone10lp/cells_arith.v (renamed from techlibs/intel/cyclone10/cells_arith.v)0
-rw-r--r--techlibs/intel/cyclone10lp/cells_map.v (renamed from techlibs/intel/cyclone10/cells_map.v)0
-rw-r--r--techlibs/intel/cyclone10lp/cells_sim.v (renamed from techlibs/intel/cyclone10/cells_sim.v)0
-rw-r--r--techlibs/intel/synth_intel.cc10
-rw-r--r--techlibs/xilinx/cells_map.v8
-rw-r--r--techlibs/xilinx/cells_sim.v797
-rw-r--r--techlibs/xilinx/cells_xtra.py69
-rw-r--r--techlibs/xilinx/cells_xtra.v610
-rw-r--r--techlibs/xilinx/synth_xilinx.cc17
-rw-r--r--tests/arch/gowin/adffs.ys5
-rw-r--r--tests/arch/gowin/init.v224
-rw-r--r--tests/arch/gowin/init.ys74
-rw-r--r--tests/arch/ice40/ice40_opt.ys83
-rw-r--r--tests/arch/ice40/ice40_wrapcarry.ys54
-rw-r--r--tests/arch/ice40/wrapcarry.ys22
-rw-r--r--tests/arch/xilinx/dsp_fastfir.ys69
-rw-r--r--tests/arch/xilinx/macc.sh2
-rw-r--r--tests/opt/bug1525.ys13
-rw-r--r--tests/simple_abc9/abc9.v15
-rw-r--r--tests/techmap/iopadmap.ys99
43 files changed, 2108 insertions, 1053 deletions
diff --git a/README.md b/README.md
index 1ce5d47ea..5cc52e842 100644
--- a/README.md
+++ b/README.md
@@ -364,16 +364,16 @@ Verilog Attributes and non-standard features
it as the external-facing pin of an I/O pad, and prevents ``iopadmap``
from inserting another pad cell on it.
-- The module attribute ``abc_box_id`` specifies a positive integer linking a
+- The module attribute ``abc9_box_id`` specifies a positive integer linking a
blackbox or whitebox definition to a corresponding entry in a `abc9`
box-file.
-- The port attribute ``abc_carry`` marks the carry-in (if an input port) and
+- The port attribute ``abc9_carry`` marks the carry-in (if an input port) and
carry-out (if output port) ports of a box. This information is necessary for
`abc9` to preserve the integrity of carry-chains. Specifying this attribute
onto a bus port will affect only its most significant bit.
-- The port attribute ``abc_arrival`` specifies an integer (for output ports
+- The port attribute ``abc9_arrival`` specifies an integer (for output ports
only) to be used as the arrival time of this sequential port. It can be used,
for example, to specify the clk-to-Q delay of a flip-flop for consideration
during techmapping.
diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc
index 46890b071..627133314 100644
--- a/backends/aiger/xaiger.cc
+++ b/backends/aiger/xaiger.cc
@@ -153,11 +153,6 @@ struct XAigerWriter
if (wire->port_input)
sigmap.add(wire);
- // promote output wires
- for (auto wire : module->wires())
- if (wire->port_output)
- sigmap.add(wire);
-
for (auto wire : module->wires())
{
bool keep = wire->attributes.count("\\keep");
@@ -173,7 +168,7 @@ struct XAigerWriter
}
if (keep)
- keep_bits.insert(bit);
+ keep_bits.insert(wirebit);
if (wire->port_input || keep) {
if (bit != wirebit)
@@ -824,7 +819,7 @@ struct XAigerBackend : public Backend {
log(" write ASCII version of AIGER format\n");
log("\n");
log(" -map <filename>\n");
- log(" write an extra file with port and latch symbols\n");
+ log(" write an extra file with port and box symbols\n");
log("\n");
log(" -vmap <filename>\n");
log(" like -map, but more verbose\n");
diff --git a/frontends/ilang/ilang_parser.y b/frontends/ilang/ilang_parser.y
index b4b9693da..4e0b62edd 100644
--- a/frontends/ilang/ilang_parser.y
+++ b/frontends/ilang/ilang_parser.y
@@ -430,10 +430,14 @@ sigspec:
free($1);
} |
sigspec '[' TOK_INT ']' {
+ if ($3 >= $1->size() || $3 < 0)
+ rtlil_frontend_ilang_yyerror("bit index out of range");
$$ = new RTLIL::SigSpec($1->extract($3));
delete $1;
} |
sigspec '[' TOK_INT ':' TOK_INT ']' {
+ if ($3 >= $1->size() || $3 < 0 || $3 < $5)
+ rtlil_frontend_ilang_yyerror("invalid slice");
$$ = new RTLIL::SigSpec($1->extract($5, $3 - $5 + 1));
delete $1;
} |
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y
index daea3b43a..a30935e0a 100644
--- a/frontends/verilog/verilog_parser.y
+++ b/frontends/verilog/verilog_parser.y
@@ -2242,7 +2242,7 @@ gen_stmt:
ast_stack.back()->children.push_back(node);
ast_stack.push_back(node);
} opt_arg_list ';'{
- ast_stack.pop_back();
+ ast_stack.pop_back();
};
gen_stmt_block:
@@ -2413,19 +2413,19 @@ basic_expr:
append_attr($$, $2);
} |
basic_expr OP_SHL attr basic_expr {
- $$ = new AstNode(AST_SHIFT_LEFT, $1, $4);
+ $$ = new AstNode(AST_SHIFT_LEFT, $1, new AstNode(AST_TO_UNSIGNED, $4));
append_attr($$, $3);
} |
basic_expr OP_SHR attr basic_expr {
- $$ = new AstNode(AST_SHIFT_RIGHT, $1, $4);
+ $$ = new AstNode(AST_SHIFT_RIGHT, $1, new AstNode(AST_TO_UNSIGNED, $4));
append_attr($$, $3);
} |
basic_expr OP_SSHL attr basic_expr {
- $$ = new AstNode(AST_SHIFT_SLEFT, $1, $4);
+ $$ = new AstNode(AST_SHIFT_SLEFT, $1, new AstNode(AST_TO_UNSIGNED, $4));
append_attr($$, $3);
} |
basic_expr OP_SSHR attr basic_expr {
- $$ = new AstNode(AST_SHIFT_SRIGHT, $1, $4);
+ $$ = new AstNode(AST_SHIFT_SRIGHT, $1, new AstNode(AST_TO_UNSIGNED, $4));
append_attr($$, $3);
} |
basic_expr '<' attr basic_expr {
diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc
index bd2fd91a3..7c73f94c8 100644
--- a/kernel/rtlil.cc
+++ b/kernel/rtlil.cc
@@ -783,6 +783,14 @@ namespace {
return v;
}
+ int param_bool(RTLIL::IdString name, bool expected)
+ {
+ int v = param_bool(name);
+ if (v != expected)
+ error(__LINE__);
+ return v;
+ }
+
void param_bits(RTLIL::IdString name, int width)
{
param(name);
@@ -869,13 +877,23 @@ namespace {
return;
}
- if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx))) {
+ if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr))) {
+ param_bool(ID(A_SIGNED));
+ param_bool(ID(B_SIGNED), /*expected=*/false);
+ port(ID::A, param(ID(A_WIDTH)));
+ port(ID::B, param(ID(B_WIDTH)));
+ port(ID::Y, param(ID(Y_WIDTH)));
+ check_expected(/*check_matched_sign=*/false);
+ return;
+ }
+
+ if (cell->type.in(ID($shift), ID($shiftx))) {
param_bool(ID(A_SIGNED));
param_bool(ID(B_SIGNED));
port(ID::A, param(ID(A_WIDTH)));
port(ID::B, param(ID(B_WIDTH)));
port(ID::Y, param(ID(Y_WIDTH)));
- check_expected(false);
+ check_expected(/*check_matched_sign=*/false);
return;
}
@@ -957,7 +975,7 @@ namespace {
port(ID::A, param(ID(A_WIDTH)));
port(ID::B, param(ID(B_WIDTH)));
port(ID::Y, param(ID(Y_WIDTH)));
- check_expected(false);
+ check_expected(/*check_matched_sign=*/false);
return;
}
diff --git a/manual/CHAPTER_CellLib.tex b/manual/CHAPTER_CellLib.tex
index 0106059b6..00a88cc82 100644
--- a/manual/CHAPTER_CellLib.tex
+++ b/manual/CHAPTER_CellLib.tex
@@ -65,6 +65,11 @@ Verilog & Cell Type \\
\label{tab:CellLib_unary}
\end{table}
+For the unary cells that output a logical value ({\tt \$reduce\_and}, {\tt \$reduce\_or},
+{\tt \$reduce\_xor}, {\tt \$reduce\_xnor}, {\tt \$reduce\_bool}, {\tt \$logic\_not}),
+when the \B{Y\_WIDTH} parameter is greater than 1, the output is zero-extended,
+and only the least significant bit varies.
+
Note that {\tt \$reduce\_or} and {\tt \$reduce\_bool} actually represent the same
logic function. But the HDL frontends generate them in different situations. A
{\tt \$reduce\_or} cell is generated when the prefix {\tt |} operator is being used. A
@@ -97,41 +102,6 @@ The width of the output port \B{Y}.
Table~\ref{tab:CellLib_binary} lists all cells for binary RTL operators.
-\subsection{Multiplexers}
-
-Multiplexers are generated by the Verilog HDL frontend for {\tt
-?:}-expressions. Multiplexers are also generated by the {\tt proc} pass to map the decision trees
-from RTLIL::Process objects to logic.
-
-The simplest multiplexer cell type is {\tt \$mux}. Cells of this type have a \B{WIDTH} parameter
-and data inputs \B{A} and \B{B} and a data output \B{Y}, all of the specified width. This cell also
-has a single bit control input \B{S}. If \B{S} is 0 the value from the \B{A} input is sent to
-the output, if it is 1 the value from the \B{B} input is sent to the output. So the {\tt \$mux}
-cell implements the function \lstinline[language=Verilog]; Y = S ? B : A;.
-
-The {\tt \$pmux} cell is used to multiplex between many inputs using a one-hot select signal. Cells
-of this type have a \B{WIDTH} and a \B{S\_WIDTH} parameter and inputs \B{A}, \B{B}, and \B{S} and
-an output \B{Y}. The \B{S} input is \B{S\_WIDTH} bits wide. The \B{A} input and the output are both
-\B{WIDTH} bits wide and the \B{B} input is \B{WIDTH}*\B{S\_WIDTH} bits wide. When all bits of
-\B{S} are zero, the value from \B{A} input is sent to the output. If the $n$'th bit from \B{S} is
-set, the value $n$'th \B{WIDTH} bits wide slice of the \B{B} input is sent to the output. When more
-than one bit from \B{S} is set the output is undefined. Cells of this type are used to model
-``parallel cases'' (defined by using the {\tt parallel\_case} attribute or detected by
-an optimization).
-
-The {\tt \$tribuf} cell is used to implement tristate logic. Cells of this type have a \B{WIDTH}
-parameter and inputs \B{A} and \B{EN} and an output \B{Y}. The \B{A} input and \B{Y} output are
-\B{WIDTH} bits wide, and the \B{EN} input is one bit wide. When \B{EN} is 0, the output \B{Y}
-is not driven. When \B{EN} is 1, the value from \B{A} input is sent to the \B{Y} output. Therefore,
-the {\tt \$tribuf} cell implements the function \lstinline[language=Verilog]; Y = EN ? A : 'bz;.
-
-Behavioural code with cascaded {\tt if-then-else}- and {\tt case}-statements
-usually results in trees of multiplexer cells. Many passes (from various
-optimizations to FSM extraction) heavily depend on these multiplexer trees to
-understand dependencies between signals. Therefore optimizations should not
-break these multiplexer trees (e.g.~by replacing a multiplexer between a
-calculated signal and a constant zero with an {\tt \$and} gate).
-
\begin{table}[t!]
\hfil
\begin{tabular}[t]{ll}
@@ -175,6 +145,57 @@ Verilog & Cell Type \\
\label{tab:CellLib_binary}
\end{table}
+The {\tt \$shl} and {\tt \$shr} cells implement logical shifts, whereas the {\tt \$sshl} and
+{\tt \$sshr} cells implement arithmetic shifts. The {\tt \$shl} and {\tt \$sshl} cells implement
+the same operation. All four of these cells interpret the second operand as unsigned, and require
+\B{B\_SIGNED} to be zero.
+
+Two additional shift operator cells are available that do not directly correspond to any operator
+in Verilog, {\tt \$shift} and {\tt \$shiftx}. The {\tt \$shift} cell performs a right logical shift
+if the second operand is positive (or unsigned), and a left logical shift if it is negative.
+The {\tt \$shiftx} cell performs the same operation as the {\tt \$shift} cell, but the vacated bit
+positions are filled with undef (x) bits, and corresponds to the Verilog indexed part-select expression.
+
+For the binary cells that output a logical value ({\tt \$logic\_and}, {\tt \$logic\_or},
+{\tt \$eqx}, {\tt \$nex}, {\tt \$lt}, {\tt \$le}, {\tt \$eq}, {\tt \$ne}, {\tt \$ge},
+{\tt \$gt}), when the \B{Y\_WIDTH} parameter is greater than 1, the output is zero-extended,
+and only the least significant bit varies.
+
+\subsection{Multiplexers}
+
+Multiplexers are generated by the Verilog HDL frontend for {\tt
+?:}-expressions. Multiplexers are also generated by the {\tt proc} pass to map the decision trees
+from RTLIL::Process objects to logic.
+
+The simplest multiplexer cell type is {\tt \$mux}. Cells of this type have a \B{WIDTH} parameter
+and data inputs \B{A} and \B{B} and a data output \B{Y}, all of the specified width. This cell also
+has a single bit control input \B{S}. If \B{S} is 0 the value from the \B{A} input is sent to
+the output, if it is 1 the value from the \B{B} input is sent to the output. So the {\tt \$mux}
+cell implements the function \lstinline[language=Verilog]; Y = S ? B : A;.
+
+The {\tt \$pmux} cell is used to multiplex between many inputs using a one-hot select signal. Cells
+of this type have a \B{WIDTH} and a \B{S\_WIDTH} parameter and inputs \B{A}, \B{B}, and \B{S} and
+an output \B{Y}. The \B{S} input is \B{S\_WIDTH} bits wide. The \B{A} input and the output are both
+\B{WIDTH} bits wide and the \B{B} input is \B{WIDTH}*\B{S\_WIDTH} bits wide. When all bits of
+\B{S} are zero, the value from \B{A} input is sent to the output. If the $n$'th bit from \B{S} is
+set, the value $n$'th \B{WIDTH} bits wide slice of the \B{B} input is sent to the output. When more
+than one bit from \B{S} is set the output is undefined. Cells of this type are used to model
+``parallel cases'' (defined by using the {\tt parallel\_case} attribute or detected by
+an optimization).
+
+The {\tt \$tribuf} cell is used to implement tristate logic. Cells of this type have a \B{WIDTH}
+parameter and inputs \B{A} and \B{EN} and an output \B{Y}. The \B{A} input and \B{Y} output are
+\B{WIDTH} bits wide, and the \B{EN} input is one bit wide. When \B{EN} is 0, the output \B{Y}
+is not driven. When \B{EN} is 1, the value from \B{A} input is sent to the \B{Y} output. Therefore,
+the {\tt \$tribuf} cell implements the function \lstinline[language=Verilog]; Y = EN ? A : 'bz;.
+
+Behavioural code with cascaded {\tt if-then-else}- and {\tt case}-statements
+usually results in trees of multiplexer cells. Many passes (from various
+optimizations to FSM extraction) heavily depend on these multiplexer trees to
+understand dependencies between signals. Therefore optimizations should not
+break these multiplexer trees (e.g.~by replacing a multiplexer between a
+calculated signal and a constant zero with an {\tt \$and} gate).
+
\subsection{Registers}
D-Type Flip-Flops are represented by {\tt \$dff} cells. These cells have a clock port \B{CLK},
diff --git a/passes/memory/memory_collect.cc b/passes/memory/memory_collect.cc
index 6acbce62f..9dcb3f024 100644
--- a/passes/memory/memory_collect.cc
+++ b/passes/memory/memory_collect.cc
@@ -218,6 +218,10 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory)
mem->setPort("\\RD_DATA", sig_rd_data);
mem->setPort("\\RD_EN", sig_rd_en);
+ // Copy attributes from RTLIL memory to $mem
+ for (auto attr : memory->attributes)
+ mem->attributes[attr.first] = attr.second;
+
for (auto c : memcells)
module->remove(c);
diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc
index 2c456705c..f59f978a6 100644
--- a/passes/opt/opt_share.cc
+++ b/passes/opt/opt_share.cc
@@ -83,7 +83,9 @@ struct ExtSigSpec {
bool operator==(const ExtSigSpec &other) const { return is_signed == other.is_signed && sign == other.sign && sig == other.sig && semantics == other.semantics; }
};
-#define BITWISE_OPS ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_), ID($and), ID($or), ID($xor), ID($xnor)
+#define FINE_BITWISE_OPS ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_)
+
+#define BITWISE_OPS FINE_BITWISE_OPS, ID($and), ID($or), ID($xor), ID($xnor)
#define REDUCTION_OPS ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool), ID($reduce_nand)
@@ -250,14 +252,19 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector<
shared_op->setPort(ID(CO), alu_co.extract(0, conn_width));
}
- shared_op->setParam(ID(Y_WIDTH), conn_width);
+ bool is_fine = shared_op->type.in(FINE_BITWISE_OPS);
+
+ if (!is_fine)
+ shared_op->setParam(ID(Y_WIDTH), conn_width);
if (decode_port(shared_op, ID::A, &assign_map) == operand) {
shared_op->setPort(ID::B, mux_to_oper);
- shared_op->setParam(ID(B_WIDTH), max_width);
+ if (!is_fine)
+ shared_op->setParam(ID(B_WIDTH), max_width);
} else {
shared_op->setPort(ID::A, mux_to_oper);
- shared_op->setParam(ID(A_WIDTH), max_width);
+ if (!is_fine)
+ shared_op->setParam(ID(A_WIDTH), max_width);
}
}
diff --git a/passes/pmgen/ice40_wrapcarry.cc b/passes/pmgen/ice40_wrapcarry.cc
index 69ef3cd82..6e154147f 100644
--- a/passes/pmgen/ice40_wrapcarry.cc
+++ b/passes/pmgen/ice40_wrapcarry.cc
@@ -50,6 +50,14 @@ void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm)
cell->setPort("\\O", st.lut->getPort("\\O"));
cell->setParam("\\LUT", st.lut->getParam("\\LUT_INIT"));
+ for (const auto &a : st.carry->attributes)
+ cell->attributes[stringf("\\SB_CARRY.%s", a.first.c_str())] = a.second;
+ for (const auto &a : st.lut->attributes)
+ cell->attributes[stringf("\\SB_LUT4.%s", a.first.c_str())] = a.second;
+ cell->attributes[ID(SB_LUT4.name)] = Const(st.lut->name.str());
+ if (st.carry->get_bool_attribute(ID::keep) || st.lut->get_bool_attribute(ID::keep))
+ cell->attributes[ID::keep] = true;
+
pm.autoremove(st.carry);
pm.autoremove(st.lut);
}
@@ -62,28 +70,79 @@ struct Ice40WrapCarryPass : public Pass {
log("\n");
log(" ice40_wrapcarry [selection]\n");
log("\n");
- log("Wrap manually instantiated SB_CARRY cells, along with their associated SB_LUTs,\n");
+ log("Wrap manually instantiated SB_CARRY cells, along with their associated SB_LUT4s,\n");
log("into an internal $__ICE40_CARRY_WRAPPER cell for preservation across technology\n");
- log("mapping.");
+ log("mapping.\n");
+ log("\n");
+ log("Attributes on both cells will have their names prefixed with 'SB_CARRY.' or\n");
+ log("'SB_LUT4.' and attached to the wrapping cell.\n");
+ log("A (* keep *) attribute on either cell will be logically OR-ed together.\n");
+ log("\n");
+ log(" -unwrap\n");
+ log(" unwrap $__ICE40_CARRY_WRAPPER cells back into SB_CARRYs and SB_LUT4s,\n");
+ log(" including restoring their attributes.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
+ bool unwrap = false;
+
log_header(design, "Executing ICE40_WRAPCARRY pass (wrap carries).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
- // if (args[argidx] == "-singleton") {
- // singleton_mode = true;
- // continue;
- // }
+ if (args[argidx] == "-unwrap") {
+ unwrap = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
- for (auto module : design->selected_modules())
- ice40_wrapcarry_pm(module, module->selected_cells()).run_ice40_wrapcarry(create_ice40_wrapcarry);
+ for (auto module : design->selected_modules()) {
+ if (!unwrap)
+ ice40_wrapcarry_pm(module, module->selected_cells()).run_ice40_wrapcarry(create_ice40_wrapcarry);
+ else {
+ for (auto cell : module->selected_cells()) {
+ if (cell->type != ID($__ICE40_CARRY_WRAPPER))
+ continue;
+
+ auto carry = module->addCell(NEW_ID, ID(SB_CARRY));
+ carry->setPort(ID(I0), cell->getPort(ID(A)));
+ carry->setPort(ID(I1), cell->getPort(ID(B)));
+ carry->setPort(ID(CI), cell->getPort(ID(CI)));
+ carry->setPort(ID(CO), cell->getPort(ID(CO)));
+ module->swap_names(carry, cell);
+ auto lut_name = cell->attributes.at(ID(SB_LUT4.name), Const(NEW_ID.str())).decode_string();
+ auto lut = module->addCell(lut_name, ID($lut));
+ lut->setParam(ID(WIDTH), 4);
+ lut->setParam(ID(LUT), cell->getParam(ID(LUT)));
+ lut->setPort(ID(A), {cell->getPort(ID(I0)), cell->getPort(ID(A)), cell->getPort(ID(B)), cell->getPort(ID(I3)) });
+ lut->setPort(ID(Y), cell->getPort(ID(O)));
+
+ Const src;
+ for (const auto &a : cell->attributes)
+ if (a.first.begins_with("\\SB_CARRY.\\"))
+ carry->attributes[a.first.c_str() + strlen("\\SB_CARRY.")] = a.second;
+ else if (a.first.begins_with("\\SB_LUT4.\\"))
+ lut->attributes[a.first.c_str() + strlen("\\SB_LUT4.")] = a.second;
+ else if (a.first == ID(src))
+ src = a.second;
+ else if (a.first.in(ID(SB_LUT4.name), ID::keep, ID(module_not_derived)))
+ continue;
+ else
+ log_abort();
+
+ if (!src.empty()) {
+ carry->attributes.insert(std::make_pair(ID(src), src));
+ lut->attributes.insert(std::make_pair(ID(src), src));
+ }
+
+ module->remove(cell);
+ }
+ }
+ }
}
} Ice40WrapCarryPass;
diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg
index 0ba529011..5d3b9c2eb 100644
--- a/passes/pmgen/xilinx_dsp.pmg
+++ b/passes/pmgen/xilinx_dsp.pmg
@@ -347,9 +347,9 @@ match postAdd
index <SigBit> port(postAdd, AB)[0] === sigP[0]
filter GetSize(port(postAdd, AB)) >= GetSize(sigP)
filter port(postAdd, AB).extract(0, GetSize(sigP)) == sigP
- // Check that remainder of AB is a sign-extension
- define <bool> AB_SIGNED (param(postAdd, AB == \A ? \A_SIGNED : \B_SIGNED).as_bool())
- filter port(postAdd, AB).extract_end(GetSize(sigP)) == SigSpec(AB_SIGNED ? sigP[GetSize(sigP)-1] : State::S0, GetSize(port(postAdd, AB))-GetSize(sigP))
+ // Check that remainder of AB is a sign- or zero-extension
+ filter port(postAdd, AB).extract_end(GetSize(sigP)) == SigSpec(sigP[GetSize(sigP)-1], GetSize(port(postAdd, AB))-GetSize(sigP)) || port(postAdd, AB).extract_end(GetSize(sigP)) == SigSpec(State::S0, GetSize(port(postAdd, AB))-GetSize(sigP))
+
set postAddAB AB
optional
endmatch
diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc
index 27106cc5d..8276c3c16 100644
--- a/passes/techmap/abc9.cc
+++ b/passes/techmap/abc9.cc
@@ -94,20 +94,30 @@ void handle_loops(RTLIL::Design *design)
if (cell->output(c.first)) {
SigBit b = c.second.as_bit();
Wire *w = b.wire;
- log_assert(!w->port_input);
- w->port_input = true;
- w = module->wire(stringf("%s.abci", w->name.c_str()));
- if (!w) {
- w = module->addWire(stringf("%s.abci", b.wire->name.c_str()), GetSize(b.wire));
- w->port_output = true;
+ if (w->port_input) {
+ // In this case, hopefully the loop break has been already created
+ // Get the non-prefixed wire
+ Wire *wo = module->wire(stringf("%s.abco", b.wire->name.c_str()));
+ log_assert(wo != nullptr);
+ log_assert(wo->port_output);
+ log_assert(b.offset < GetSize(wo));
+ c.second = RTLIL::SigBit(wo, b.offset);
}
else {
- log_assert(w->port_input);
- log_assert(b.offset < GetSize(w));
+ // Create a new output/input loop break
+ w->port_input = true;
+ w = module->wire(stringf("%s.abco", w->name.c_str()));
+ if (!w) {
+ w = module->addWire(stringf("%s.abco", b.wire->name.c_str()), GetSize(b.wire));
+ w->port_output = true;
+ }
+ else {
+ log_assert(w->port_input);
+ log_assert(b.offset < GetSize(w));
+ }
+ w->set_bool_attribute(ID(abc9_scc_break));
+ c.second = RTLIL::SigBit(w, b.offset);
}
- w->set_bool_attribute(ID(abc9_scc_break));
- module->swap_names(b.wire, w);
- c.second = RTLIL::SigBit(w, b.offset);
}
}
}
@@ -420,24 +430,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
design->selection_stack.pop_back();
- // Now 'unexpose' those wires by undoing
- // the expose operation -- remove them from PO/PI
- // and re-connecting them back together
- for (auto wire : module->wires()) {
- auto it = wire->attributes.find(ID(abc9_scc_break));
- if (it != wire->attributes.end()) {
- wire->attributes.erase(it);
- log_assert(wire->port_output);
- wire->port_output = false;
- RTLIL::Wire *i_wire = module->wire(wire->name.str() + ".abci");
- log_assert(i_wire);
- log_assert(i_wire->port_input);
- i_wire->port_input = false;
- module->connect(i_wire, wire);
- }
- }
- module->fixup_ports();
-
log_header(design, "Executing ABC9.\n");
if (!lut_costs.empty()) {
@@ -781,6 +773,25 @@ clone_lut:
}
}
+ // Now 'unexpose' those wires by undoing
+ // the expose operation -- remove them from PO/PI
+ // and re-connecting them back together
+ for (auto wire : module->wires()) {
+ auto it = wire->attributes.find(ID(abc9_scc_break));
+ if (it != wire->attributes.end()) {
+ wire->attributes.erase(it);
+ log_assert(wire->port_output);
+ wire->port_output = false;
+ std::string name = wire->name.str();
+ RTLIL::Wire *i_wire = module->wire(name.substr(0, GetSize(name) - 5));
+ log_assert(i_wire);
+ log_assert(i_wire->port_input);
+ i_wire->port_input = false;
+ module->connect(i_wire, wire);
+ }
+ }
+ module->fixup_ports();
+
//log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires);
log("ABC RESULTS: input signals: %8d\n", in_wires);
log("ABC RESULTS: output signals: %8d\n", out_wires);
diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc
index c868b9a87..90cfef71e 100644
--- a/passes/techmap/iopadmap.cc
+++ b/passes/techmap/iopadmap.cc
@@ -87,11 +87,11 @@ struct IopadmapPass : public Pass {
{
log_header(design, "Executing IOPADMAP pass (mapping inputs/outputs to IO-PAD cells).\n");
- std::string inpad_celltype, inpad_portname, inpad_portname2;
- std::string outpad_celltype, outpad_portname, outpad_portname2;
- std::string inoutpad_celltype, inoutpad_portname, inoutpad_portname2;
- std::string toutpad_celltype, toutpad_portname, toutpad_portname2, toutpad_portname3;
- std::string tinoutpad_celltype, tinoutpad_portname, tinoutpad_portname2, tinoutpad_portname3, tinoutpad_portname4;
+ std::string inpad_celltype, inpad_portname_o, inpad_portname_pad;
+ std::string outpad_celltype, outpad_portname_i, outpad_portname_pad;
+ std::string inoutpad_celltype, inoutpad_portname_io, inoutpad_portname_pad;
+ std::string toutpad_celltype, toutpad_portname_oe, toutpad_portname_i, toutpad_portname_pad;
+ std::string tinoutpad_celltype, tinoutpad_portname_oe, tinoutpad_portname_o, tinoutpad_portname_i, tinoutpad_portname_pad;
std::string widthparam, nameparam;
pool<pair<IdString, IdString>> ignore;
bool flag_bits = false;
@@ -102,35 +102,35 @@ struct IopadmapPass : public Pass {
std::string arg = args[argidx];
if (arg == "-inpad" && argidx+2 < args.size()) {
inpad_celltype = args[++argidx];
- inpad_portname = args[++argidx];
- split_portname_pair(inpad_portname, inpad_portname2);
+ inpad_portname_o = args[++argidx];
+ split_portname_pair(inpad_portname_o, inpad_portname_pad);
continue;
}
if (arg == "-outpad" && argidx+2 < args.size()) {
outpad_celltype = args[++argidx];
- outpad_portname = args[++argidx];
- split_portname_pair(outpad_portname, outpad_portname2);
+ outpad_portname_i = args[++argidx];
+ split_portname_pair(outpad_portname_i, outpad_portname_pad);
continue;
}
if (arg == "-inoutpad" && argidx+2 < args.size()) {
inoutpad_celltype = args[++argidx];
- inoutpad_portname = args[++argidx];
- split_portname_pair(inoutpad_portname, inoutpad_portname2);
+ inoutpad_portname_io = args[++argidx];
+ split_portname_pair(inoutpad_portname_io, inoutpad_portname_pad);
continue;
}
if (arg == "-toutpad" && argidx+2 < args.size()) {
toutpad_celltype = args[++argidx];
- toutpad_portname = args[++argidx];
- split_portname_pair(toutpad_portname, toutpad_portname2);
- split_portname_pair(toutpad_portname2, toutpad_portname3);
+ toutpad_portname_oe = args[++argidx];
+ split_portname_pair(toutpad_portname_oe, toutpad_portname_i);
+ split_portname_pair(toutpad_portname_i, toutpad_portname_pad);
continue;
}
if (arg == "-tinoutpad" && argidx+2 < args.size()) {
tinoutpad_celltype = args[++argidx];
- tinoutpad_portname = args[++argidx];
- split_portname_pair(tinoutpad_portname, tinoutpad_portname2);
- split_portname_pair(tinoutpad_portname2, tinoutpad_portname3);
- split_portname_pair(tinoutpad_portname3, tinoutpad_portname4);
+ tinoutpad_portname_oe = args[++argidx];
+ split_portname_pair(tinoutpad_portname_oe, tinoutpad_portname_o);
+ split_portname_pair(tinoutpad_portname_o, tinoutpad_portname_i);
+ split_portname_pair(tinoutpad_portname_i, tinoutpad_portname_pad);
continue;
}
if (arg == "-ignore" && argidx+2 < args.size()) {
@@ -161,16 +161,16 @@ struct IopadmapPass : public Pass {
}
extra_args(args, argidx, design);
- if (!inpad_portname2.empty())
- ignore.insert(make_pair(RTLIL::escape_id(inpad_celltype), RTLIL::escape_id(inpad_portname2)));
- if (!outpad_portname2.empty())
- ignore.insert(make_pair(RTLIL::escape_id(outpad_celltype), RTLIL::escape_id(outpad_portname2)));
- if (!inoutpad_portname2.empty())
- ignore.insert(make_pair(RTLIL::escape_id(inoutpad_celltype), RTLIL::escape_id(inoutpad_portname2)));
- if (!toutpad_portname3.empty())
- ignore.insert(make_pair(RTLIL::escape_id(toutpad_celltype), RTLIL::escape_id(toutpad_portname3)));
- if (!tinoutpad_portname4.empty())
- ignore.insert(make_pair(RTLIL::escape_id(tinoutpad_celltype), RTLIL::escape_id(tinoutpad_portname4)));
+ if (!inpad_portname_pad.empty())
+ ignore.insert(make_pair(RTLIL::escape_id(inpad_celltype), RTLIL::escape_id(inpad_portname_pad)));
+ if (!outpad_portname_pad.empty())
+ ignore.insert(make_pair(RTLIL::escape_id(outpad_celltype), RTLIL::escape_id(outpad_portname_pad)));
+ if (!inoutpad_portname_pad.empty())
+ ignore.insert(make_pair(RTLIL::escape_id(inoutpad_celltype), RTLIL::escape_id(inoutpad_portname_pad)));
+ if (!toutpad_portname_pad.empty())
+ ignore.insert(make_pair(RTLIL::escape_id(toutpad_celltype), RTLIL::escape_id(toutpad_portname_pad)));
+ if (!tinoutpad_portname_pad.empty())
+ ignore.insert(make_pair(RTLIL::escape_id(tinoutpad_celltype), RTLIL::escape_id(tinoutpad_portname_pad)));
for (auto module : design->modules())
if (module->get_blackbox_attribute())
@@ -180,34 +180,25 @@ struct IopadmapPass : public Pass {
for (auto module : design->selected_modules())
{
- dict<IdString, pool<int>> skip_wires;
pool<SigBit> skip_wire_bits;
- SigMap sigmap(module);
+ dict<Wire *, dict<int, pair<Cell *, IdString>>> rewrite_bits;
for (auto cell : module->cells())
for (auto port : cell->connections())
if (ignore.count(make_pair(cell->type, port.first)))
- for (auto bit : sigmap(port.second))
+ for (auto bit : port.second)
skip_wire_bits.insert(bit);
if (!toutpad_celltype.empty() || !tinoutpad_celltype.empty())
{
- dict<SigBit, pair<IdString, pool<IdString>>> tbuf_bits;
- pool<pair<IdString, IdString>> norewrites;
- SigMap rewrites;
+ dict<SigBit, Cell *> tbuf_bits;
for (auto cell : module->cells())
if (cell->type == ID($_TBUF_)) {
- SigBit bit = sigmap(cell->getPort(ID::Y).as_bit());
- tbuf_bits[bit].first = cell->name;
+ SigBit bit = cell->getPort(ID::Y).as_bit();
+ tbuf_bits[bit] = cell;
}
- for (auto cell : module->cells())
- for (auto port : cell->connections())
- for (auto bit : sigmap(port.second))
- if (tbuf_bits.count(bit))
- tbuf_bits.at(bit).second.insert(cell->name);
-
for (auto wire : module->selected_wires())
{
if (!wire->port_output)
@@ -216,16 +207,11 @@ struct IopadmapPass : public Pass {
for (int i = 0; i < GetSize(wire); i++)
{
SigBit wire_bit(wire, i);
- SigBit mapped_wire_bit = sigmap(wire_bit);
- if (tbuf_bits.count(mapped_wire_bit) == 0)
+ if (tbuf_bits.count(wire_bit) == 0)
continue;
- if (skip_wire_bits.count(mapped_wire_bit))
- continue;
-
- auto &tbuf_cache = tbuf_bits.at(mapped_wire_bit);
- Cell *tbuf_cell = module->cell(tbuf_cache.first);
+ Cell *tbuf_cell = tbuf_bits.at(wire_bit);
if (tbuf_cell == nullptr)
continue;
@@ -238,37 +224,16 @@ struct IopadmapPass : public Pass {
log("Mapping port %s.%s[%d] using %s.\n", log_id(module), log_id(wire), i, tinoutpad_celltype.c_str());
Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(tinoutpad_celltype));
- Wire *owire = module->addWire(NEW_ID);
- cell->setPort(RTLIL::escape_id(tinoutpad_portname), en_sig);
- cell->setPort(RTLIL::escape_id(tinoutpad_portname2), owire);
- cell->setPort(RTLIL::escape_id(tinoutpad_portname3), data_sig);
- cell->setPort(RTLIL::escape_id(tinoutpad_portname4), wire_bit);
+ cell->setPort(RTLIL::escape_id(tinoutpad_portname_oe), en_sig);
+ cell->setPort(RTLIL::escape_id(tinoutpad_portname_o), wire_bit);
+ cell->setPort(RTLIL::escape_id(tinoutpad_portname_i), data_sig);
cell->attributes[ID::keep] = RTLIL::Const(1);
- for (auto cn : tbuf_cache.second) {
- auto c = module->cell(cn);
- if (c == nullptr)
- continue;
- for (auto port : c->connections()) {
- SigSpec sig = port.second;
- bool newsig = false;
- for (auto &bit : sig)
- if (sigmap(bit) == mapped_wire_bit) {
- bit = owire;
- newsig = true;
- }
- if (newsig)
- c->setPort(port.first, sig);
- }
- }
-
-
module->remove(tbuf_cell);
- skip_wires[wire->name].insert(i);
-
- norewrites.insert(make_pair(cell->name, RTLIL::escape_id(tinoutpad_portname4)));
- rewrites.add(sigmap(wire_bit), owire);
+ skip_wire_bits.insert(wire_bit);
+ if (!tinoutpad_portname_pad.empty())
+ rewrite_bits[wire][i] = make_pair(cell, RTLIL::escape_id(tinoutpad_portname_pad));
continue;
}
@@ -278,50 +243,19 @@ struct IopadmapPass : public Pass {
Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(toutpad_celltype));
- cell->setPort(RTLIL::escape_id(toutpad_portname), en_sig);
- cell->setPort(RTLIL::escape_id(toutpad_portname2), data_sig);
- cell->setPort(RTLIL::escape_id(toutpad_portname3), wire_bit);
+ cell->setPort(RTLIL::escape_id(toutpad_portname_oe), en_sig);
+ cell->setPort(RTLIL::escape_id(toutpad_portname_i), data_sig);
cell->attributes[ID::keep] = RTLIL::Const(1);
- for (auto cn : tbuf_cache.second) {
- auto c = module->cell(cn);
- if (c == nullptr)
- continue;
- for (auto port : c->connections()) {
- SigSpec sig = port.second;
- bool newsig = false;
- for (auto &bit : sig)
- if (sigmap(bit) == mapped_wire_bit) {
- bit = data_sig;
- newsig = true;
- }
- if (newsig)
- c->setPort(port.first, sig);
- }
- }
-
module->remove(tbuf_cell);
- skip_wires[wire->name].insert(i);
+ module->connect(wire_bit, data_sig);
+ skip_wire_bits.insert(wire_bit);
+ if (!toutpad_portname_pad.empty())
+ rewrite_bits[wire][i] = make_pair(cell, RTLIL::escape_id(toutpad_portname_pad));
continue;
}
}
}
-
- if (GetSize(norewrites))
- {
- for (auto cell : module->cells())
- for (auto port : cell->connections())
- {
- if (norewrites.count(make_pair(cell->name, port.first)))
- continue;
-
- SigSpec orig_sig = sigmap(port.second);
- SigSpec new_sig = rewrites(orig_sig);
-
- if (orig_sig != new_sig)
- cell->setPort(port.first, new_sig);
- }
- }
}
for (auto wire : module->selected_wires())
@@ -329,17 +263,11 @@ struct IopadmapPass : public Pass {
if (!wire->port_id)
continue;
- std::string celltype, portname, portname2;
+ std::string celltype, portname_int, portname_pad;
pool<int> skip_bit_indices;
- if (skip_wires.count(wire->name)) {
- if (!flag_bits)
- continue;
- skip_bit_indices = skip_wires.at(wire->name);
- }
-
for (int i = 0; i < GetSize(wire); i++)
- if (skip_wire_bits.count(sigmap(SigBit(wire, i))))
+ if (skip_wire_bits.count(SigBit(wire, i)))
skip_bit_indices.insert(i);
if (GetSize(wire) == GetSize(skip_bit_indices))
@@ -351,8 +279,8 @@ struct IopadmapPass : public Pass {
continue;
}
celltype = inpad_celltype;
- portname = inpad_portname;
- portname2 = inpad_portname2;
+ portname_int = inpad_portname_o;
+ portname_pad = inpad_portname_pad;
} else
if (!wire->port_input && wire->port_output) {
if (outpad_celltype.empty()) {
@@ -360,8 +288,8 @@ struct IopadmapPass : public Pass {
continue;
}
celltype = outpad_celltype;
- portname = outpad_portname;
- portname2 = outpad_portname2;
+ portname_int = outpad_portname_i;
+ portname_pad = outpad_portname_pad;
} else
if (wire->port_input && wire->port_output) {
if (inoutpad_celltype.empty()) {
@@ -369,8 +297,8 @@ struct IopadmapPass : public Pass {
continue;
}
celltype = inoutpad_celltype;
- portname = inoutpad_portname;
- portname2 = inoutpad_portname2;
+ portname_int = inoutpad_portname_io;
+ portname_pad = inoutpad_portname_pad;
} else
log_abort();
@@ -381,29 +309,20 @@ struct IopadmapPass : public Pass {
log("Mapping port %s.%s using %s.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire->name), celltype.c_str());
- RTLIL::Wire *new_wire = NULL;
- if (!portname2.empty()) {
- new_wire = module->addWire(NEW_ID, wire);
- module->swap_names(new_wire, wire);
- wire->attributes.clear();
- }
-
if (flag_bits)
{
for (int i = 0; i < wire->width; i++)
{
- if (skip_bit_indices.count(i)) {
- if (wire->port_output)
- module->connect(SigSpec(new_wire, i), SigSpec(wire, i));
- else
- module->connect(SigSpec(wire, i), SigSpec(new_wire, i));
+ if (skip_bit_indices.count(i))
continue;
- }
+
+ SigBit wire_bit(wire, i);
RTLIL::Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(celltype));
- cell->setPort(RTLIL::escape_id(portname), RTLIL::SigSpec(wire, i));
- if (!portname2.empty())
- cell->setPort(RTLIL::escape_id(portname2), RTLIL::SigSpec(new_wire, i));
+ cell->setPort(RTLIL::escape_id(portname_int), wire_bit);
+
+ if (!portname_pad.empty())
+ rewrite_bits[wire][i] = make_pair(cell, RTLIL::escape_id(portname_pad));
if (!widthparam.empty())
cell->parameters[RTLIL::escape_id(widthparam)] = RTLIL::Const(1);
if (!nameparam.empty())
@@ -414,9 +333,15 @@ struct IopadmapPass : public Pass {
else
{
RTLIL::Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(celltype));
- cell->setPort(RTLIL::escape_id(portname), RTLIL::SigSpec(wire));
- if (!portname2.empty())
- cell->setPort(RTLIL::escape_id(portname2), RTLIL::SigSpec(new_wire));
+ cell->setPort(RTLIL::escape_id(portname_int), RTLIL::SigSpec(wire));
+
+ if (!portname_pad.empty()) {
+ RTLIL::Wire *new_wire = NULL;
+ new_wire = module->addWire(NEW_ID, wire);
+ module->swap_names(new_wire, wire);
+ wire->attributes.clear();
+ cell->setPort(RTLIL::escape_id(portname_pad), RTLIL::SigSpec(new_wire));
+ }
if (!widthparam.empty())
cell->parameters[RTLIL::escape_id(widthparam)] = RTLIL::Const(wire->width);
if (!nameparam.empty())
@@ -424,6 +349,32 @@ struct IopadmapPass : public Pass {
cell->attributes[ID::keep] = RTLIL::Const(1);
}
+ if (!rewrite_bits.count(wire)) {
+ wire->port_id = 0;
+ wire->port_input = false;
+ wire->port_output = false;
+ }
+ }
+
+ for (auto &it : rewrite_bits) {
+ RTLIL::Wire *wire = it.first;
+ RTLIL::Wire *new_wire = module->addWire(NEW_ID, wire);
+ module->swap_names(new_wire, wire);
+ wire->attributes.clear();
+ for (int i = 0; i < wire->width; i++)
+ {
+ SigBit wire_bit(wire, i);
+ if (!it.second.count(i)) {
+ if (wire->port_output)
+ module->connect(SigSpec(new_wire, i), SigSpec(wire, i));
+ else
+ module->connect(SigSpec(wire, i), SigSpec(new_wire, i));
+ } else {
+ auto &new_conn = it.second.at(i);
+ new_conn.first->setPort(new_conn.second, RTLIL::SigSpec(new_wire, i));
+ }
+ }
+
wire->port_id = 0;
wire->port_input = false;
wire->port_output = false;
diff --git a/techlibs/ecp5/cells_ff.vh b/techlibs/ecp5/cells_ff.vh
index 501c1b3b2..6b745f391 100644
--- a/techlibs/ecp5/cells_ff.vh
+++ b/techlibs/ecp5/cells_ff.vh
@@ -1,12 +1,12 @@
// Diamond flip-flops
-module FD1P3AX(input D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .CE(SP), .DI(D), .Q(Q)); endmodule
-module FD1P3AY(input D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .CE(SP), .DI(D), .Q(Q)); endmodule
+module FD1P3AX(input D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(|0), .CE(SP), .DI(D), .Q(Q)); endmodule
+module FD1P3AY(input D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(|0), .CE(SP), .DI(D), .Q(Q)); endmodule
module FD1P3BX(input PD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
module FD1P3DX(input CD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
module FD1P3IX(input CD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
module FD1P3JX(input PD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
-module FD1S3AX(input D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .DI(D), .Q(Q)); endmodule
-module FD1S3AY(input D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .DI(D), .Q(Q)); endmodule
+module FD1S3AX(input D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(|0), .DI(D), .Q(Q)); endmodule
+module FD1S3AY(input D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(|0), .DI(D), .Q(Q)); endmodule
module FD1S3BX(input PD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule
module FD1S3DX(input CD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule
module FD1S3IX(input CD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule
diff --git a/techlibs/gowin/cells_map.v b/techlibs/gowin/cells_map.v
index 9845e56a7..aee912256 100644
--- a/techlibs/gowin/cells_map.v
+++ b/techlibs/gowin/cells_map.v
@@ -1,133 +1,282 @@
+`default_nettype none
//All DFF* have INIT, but the hardware is always initialised to the reset
//value regardless. The parameter is ignored.
-// DFFN D Flip-Flop with Negative-Edge Clock
-module \$_DFF_N_ (input D, C, output Q); DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C)); endmodule
-// DFF D Flip-Flop
-module \$_DFF_P_ (input D, C, output Q); DFF _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C)); endmodule
+// DFFN D Flip-Flop with Negative-Edge Clock
+module \$_DFF_N_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, output Q);
+ generate
+ if (_TECHMAP_WIREINIT_Q_ === 1'b1)
+ DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(1'b0));
+ else
+ DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C));
+ endgenerate
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+
+// DFF D Flip-Flop
+module \$_DFF_P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, output Q);
+ generate
+ if (_TECHMAP_WIREINIT_Q_ === 1'b1)
+ DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(1'b0));
+ else
+ DFF _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C));
+ endgenerate
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
-// DFFE D Flip-Flop with Clock Enable
-module \$_DFFE_PP_ (input D, C, E, output Q); DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E)); endmodule
-module \$_DFFE_PN_ (input D, C, E, output Q); DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E)); endmodule
+// DFFE D Flip-Flop with Clock Enable
+module \$_DFFE_PP_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, E, output Q);
+ generate
+ if (_TECHMAP_WIREINIT_Q_ === 1'b1)
+ DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E), .SET(1'b0));
+ else
+ DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E));
+ endgenerate
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+
+module \$_DFFE_PN_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, E, output Q);
+ generate
+ if (_TECHMAP_WIREINIT_Q_ === 1'b1)
+ DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E), .SET(1'b0));
+ else
+ DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E));
+ endgenerate
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
-// DFFNE D Flip-Flop with Negative-Edge Clock and Clock Enable
-module \$_DFFE_NP_ (input D, C, E, output Q); DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E)); endmodule
-module \$_DFFE_NN_ (input D, C, E, output Q); DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E)); endmodule
+// DFFNE D Flip-Flop with Negative-Edge Clock and Clock Enable
+module \$_DFFE_NP_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, E, output Q);
+ generate
+ if (_TECHMAP_WIREINIT_Q_ === 1'b1)
+ DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E), .SET(1'b0));
+ else
+ DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E));
+ endgenerate
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+
+module \$_DFFE_NN_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, E, output Q);
+ generate
+ if (_TECHMAP_WIREINIT_Q_ === 1'b1)
+ DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E), .SET(1'b0));
+ else
+ DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E));
+ endgenerate
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+
+// DFFR D Flip-Flop with Synchronous Reset
+module \$__DFFS_PN0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
-// DFFR D Flip-Flop with Synchronous Reset
-module \$__DFFS_PN0_ (input D, C, R, output Q); DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R)); endmodule
-module \$__DFFS_PP0_ (input D, C, R, output Q); DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R)); endmodule
+module \$__DFFS_PP0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
-// DFFNR D Flip-Flop with Negative-Edge Clock and Synchronous Reset
-module \$__DFFS_NN0_ (input D, C, R, output Q); DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R)); endmodule
-module \$__DFFS_NP0_ (input D, C, R, output Q); DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R)); endmodule
+// DFFNR D Flip-Flop with Negative-Edge Clock and Synchronous Reset
+module \$__DFFS_NN0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
+module \$__DFFS_NP0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
-// DFFRE D Flip-Flop with Clock Enable and Synchronous Reset
-module \$__DFFSE_PN0 (input D, C, R, E, output Q); DFFRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R), .CE(E)); endmodule
-module \$__DFFSE_PP0 (input D, C, R, E, output Q); DFFRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R), .CE(E)); endmodule
+// DFFRE D Flip-Flop with Clock Enable and Synchronous Reset
+module \$__DFFSE_PN0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
+module \$__DFFSE_PP0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
-// DFFNRE D Flip-Flop with Negative-Edge Clock,Clock Enable, and Synchronous Reset
-module \$__DFFNSE_PN0 (input D, C, R, E, output Q); DFFNRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R), .CE(E)); endmodule
-module \$__DFFNSE_PP0 (input D, C, R, E, output Q); DFFNRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R), .CE(E)); endmodule
+// DFFNRE D Flip-Flop with Negative-Edge Clock,Clock Enable, and Synchronous Reset
+module \$__DFFSE_NN0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFNRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
+module \$__DFFSE_NP0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFNRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
-// DFFS D Flip-Flop with Synchronous Set
-module \$__DFFS_PN1_ (input D, C, R, output Q); DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R)); endmodule
-module \$__DFFS_PP1_ (input D, C, R, output Q); DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R)); endmodule
+// DFFS D Flip-Flop with Synchronous Set
+module \$__DFFS_PN1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
+module \$__DFFS_PP1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
-// DFFNS D Flip-Flop with Negative-Edge Clock and Synchronous Set
-module \$__DFFS_NN1_ (input D, C, R, output Q); DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R)); endmodule
-module \$__DFFS_NP1_ (input D, C, R, output Q); DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R)); endmodule
+// DFFNS D Flip-Flop with Negative-Edge Clock and Synchronous Set
+module \$__DFFS_NN1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
+module \$__DFFS_NP1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
-// DFFSE D Flip-Flop with Clock Enable and Synchronous Set
-module \$__DFFSE_PN1 (input D, C, R, E, output Q); DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R), .CE(E)); endmodule
-module \$__DFFSE_PP1 (input D, C, R, E, output Q); DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R), .CE(E)); endmodule
+// DFFSE D Flip-Flop with Clock Enable and Synchronous Set
+module \$__DFFSE_PN1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
+module \$__DFFSE_PP1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
-// DFFNSE D Flip-Flop with Negative-Edge Clock,Clock Enable,and Synchronous Set
-module \$__DFFSE_NN1 (input D, C, R, E, output Q); DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R), .CE(E)); endmodule
-module \$__DFFSE_NP1 (input D, C, R, E, output Q); DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R), .CE(E)); endmodule
+// DFFNSE D Flip-Flop with Negative-Edge Clock,Clock Enable,and Synchronous Set
+module \$__DFFSE_NN1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
+module \$__DFFSE_NP1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
-// DFFP D Flip-Flop with Asynchronous Preset
-module \$_DFF_PP1_ (input D, C, R, output Q); DFFP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R)); endmodule
-module \$_DFF_PN1_ (input D, C, R, output Q); DFFP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R)); endmodule
+// DFFP D Flip-Flop with Asynchronous Preset
+module \$_DFF_PP1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
+module \$_DFF_PN1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
-// DFFNP D Flip-Flop with Negative-Edge Clock and Asynchronous Preset
-module \$_DFF_NP1_ (input D, C, R, output Q); DFFNP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R)); endmodule
-module \$_DFF_NN1_ (input D, C, R, output Q); DFFNP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R)); endmodule
+// DFFNP D Flip-Flop with Negative-Edge Clock and Asynchronous Preset
+module \$_DFF_NP1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFNP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
+module \$_DFF_NN1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFNP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
-// DFFC D Flip-Flop with Asynchronous Clear
-module \$_DFF_PP0_ (input D, C, R, output Q); DFFC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R)); endmodule
-module \$_DFF_PN0_ (input D, C, R, output Q); DFFC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R)); endmodule
+// DFFC D Flip-Flop with Asynchronous Clear
+module \$_DFF_PP0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
+module \$_DFF_PN0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
-// DFFNC D Flip-Flop with Negative-Edge Clock and Asynchronous Clear
-module \$_DFF_NP0_ (input D, C, R, output Q); DFFNC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R)); endmodule
-module \$_DFF_NN0_ (input D, C, R, output Q); DFFNC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R)); endmodule
+// DFFNC D Flip-Flop with Negative-Edge Clock and Asynchronous Clear
+module \$_DFF_NP0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFNC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
+module \$_DFF_NN0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFNC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
-// DFFPE D Flip-Flop with Clock Enable and Asynchronous Preset
-module \$__DFFE_PP1 (input D, C, R, E, output Q); DFFPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R), .CE(E)); endmodule
-module \$__DFFE_PN1 (input D, C, R, E, output Q); DFFPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R), .CE(E)); endmodule
+// DFFPE D Flip-Flop with Clock Enable and Asynchronous Preset
+module \$__DFFE_PP1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
+module \$__DFFE_PN1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
-// DFFNPE D Flip-Flop with Negative-Edge Clock,Clock Enable, and Asynchronous Preset
-module \$__DFFE_NP1 (input D, C, R, E, output Q); DFFNPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R), .CE(E)); endmodule
-module \$__DFFE_NN1 (input D, C, R, E, output Q); DFFNPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R), .CE(E)); endmodule
+// DFFNPE D Flip-Flop with Negative-Edge Clock,Clock Enable, and Asynchronous Preset
+module \$__DFFE_NP1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFNPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
+module \$__DFFE_NN1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFNPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
-// DFFCE D Flip-Flop with Clock Enable and Asynchronous Clear
-module \$__DFFE_PP0 (input D, C, R, E, output Q); DFFCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R), .CE(E)); endmodule
-module \$__DFFE_PN0 (input D, C, R, E, output Q); DFFCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R), .CE(E)); endmodule
+// DFFCE D Flip-Flop with Clock Enable and Asynchronous Clear
+module \$__DFFE_PP0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
+module \$__DFFE_PN0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
-// DFFNCE D Flip-Flop with Negative-Edge Clock,Clock Enable and Asynchronous Clear
-module \$__DFFE_NP0 (input D, C, R, E, output Q); DFFNCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R), .CE(E)); endmodule
-module \$__DFFE_NN0 (input D, C, R, E, output Q); DFFNCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R), .CE(E)); endmodule
+// DFFNCE D Flip-Flop with Negative-Edge Clock,Clock Enable and Asynchronous Clear
+module \$__DFFE_NP0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFNCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
+module \$__DFFE_NN0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFNCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
module \$lut (A, Y);
- parameter WIDTH = 0;
- parameter LUT = 0;
-
- input [WIDTH-1:0] A;
- output Y;
-
- generate
- if (WIDTH == 1) begin
- LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y),
- .I0(A[0]));
- end else
- if (WIDTH == 2) begin
- LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y),
- .I0(A[0]), .I1(A[1]));
- end else
- if (WIDTH == 3) begin
- LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y),
- .I0(A[0]), .I1(A[1]), .I2(A[2]));
- end else
- if (WIDTH == 4) begin
- LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y),
- .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3]));
- end else
- if (WIDTH == 5) begin
- wire f0, f1;
- \$lut #(.LUT(LUT[15: 0]), .WIDTH(4)) lut0 (.A(A[3:0]), .Y(f0));
- \$lut #(.LUT(LUT[31:16]), .WIDTH(4)) lut1 (.A(A[3:0]), .Y(f1));
- MUX2_LUT5 mux5(.I0(f0), .I1(f1), .S0(A[4]), .O(Y));
- end else
- if (WIDTH == 6) begin
- wire f0, f1;
- \$lut #(.LUT(LUT[31: 0]), .WIDTH(5)) lut0 (.A(A[4:0]), .Y(f0));
- \$lut #(.LUT(LUT[63:32]), .WIDTH(5)) lut1 (.A(A[4:0]), .Y(f1));
- MUX2_LUT6 mux6(.I0(f0), .I1(f1), .S0(A[5]), .O(Y));
- end else
- if (WIDTH == 7) begin
- wire f0, f1;
- \$lut #(.LUT(LUT[63: 0]), .WIDTH(6)) lut0 (.A(A[5:0]), .Y(f0));
- \$lut #(.LUT(LUT[127:64]), .WIDTH(6)) lut1 (.A(A[5:0]), .Y(f1));
- MUX2_LUT7 mux7(.I0(f0), .I1(f1), .S0(A[6]), .O(Y));
- end else
- if (WIDTH == 8) begin
- wire f0, f1;
- \$lut #(.LUT(LUT[127: 0]), .WIDTH(7)) lut0 (.A(A[6:0]), .Y(f0));
- \$lut #(.LUT(LUT[255:128]), .WIDTH(7)) lut1 (.A(A[6:0]), .Y(f1));
- MUX2_LUT8 mux8(.I0(f0), .I1(f1), .S0(A[7]), .O(Y));
- end else begin
- wire _TECHMAP_FAIL_ = 1;
- end
- endgenerate
+ parameter WIDTH = 0;
+ parameter LUT = 0;
+
+ input [WIDTH-1:0] A;
+ output Y;
+
+ generate
+ if (WIDTH == 1) begin
+ LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y),
+ .I0(A[0]));
+ end else
+ if (WIDTH == 2) begin
+ LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y),
+ .I0(A[0]), .I1(A[1]));
+ end else
+ if (WIDTH == 3) begin
+ LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y),
+ .I0(A[0]), .I1(A[1]), .I2(A[2]));
+ end else
+ if (WIDTH == 4) begin
+ LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y),
+ .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3]));
+ end else
+ if (WIDTH == 5) begin
+ wire f0, f1;
+ \$lut #(.LUT(LUT[15: 0]), .WIDTH(4)) lut0 (.A(A[3:0]), .Y(f0));
+ \$lut #(.LUT(LUT[31:16]), .WIDTH(4)) lut1 (.A(A[3:0]), .Y(f1));
+ MUX2_LUT5 mux5(.I0(f0), .I1(f1), .S0(A[4]), .O(Y));
+ end else
+ if (WIDTH == 6) begin
+ wire f0, f1;
+ \$lut #(.LUT(LUT[31: 0]), .WIDTH(5)) lut0 (.A(A[4:0]), .Y(f0));
+ \$lut #(.LUT(LUT[63:32]), .WIDTH(5)) lut1 (.A(A[4:0]), .Y(f1));
+ MUX2_LUT6 mux6(.I0(f0), .I1(f1), .S0(A[5]), .O(Y));
+ end else
+ if (WIDTH == 7) begin
+ wire f0, f1;
+ \$lut #(.LUT(LUT[63: 0]), .WIDTH(6)) lut0 (.A(A[5:0]), .Y(f0));
+ \$lut #(.LUT(LUT[127:64]), .WIDTH(6)) lut1 (.A(A[5:0]), .Y(f1));
+ MUX2_LUT7 mux7(.I0(f0), .I1(f1), .S0(A[6]), .O(Y));
+ end else
+ if (WIDTH == 8) begin
+ wire f0, f1;
+ \$lut #(.LUT(LUT[127: 0]), .WIDTH(7)) lut0 (.A(A[6:0]), .Y(f0));
+ \$lut #(.LUT(LUT[255:128]), .WIDTH(7)) lut1 (.A(A[6:0]), .Y(f1));
+ MUX2_LUT8 mux8(.I0(f0), .I1(f1), .S0(A[7]), .O(Y));
+ end else begin
+ wire _TECHMAP_FAIL_ = 1;
+ end
+ endgenerate
endmodule
diff --git a/techlibs/gowin/synth_gowin.cc b/techlibs/gowin/synth_gowin.cc
index 3c1426414..6cf058f29 100644
--- a/techlibs/gowin/synth_gowin.cc
+++ b/techlibs/gowin/synth_gowin.cc
@@ -67,6 +67,9 @@ struct SynthGowinPass : public ScriptPass
log(" -nowidelut\n");
log(" do not use muxes to implement LUTs larger than LUT4s\n");
log("\n");
+ log(" -noiopads\n");
+ log(" do not emit IOB at top level ports\n");
+ log("\n");
log(" -abc9\n");
log(" use new ABC9 flow (EXPERIMENTAL)\n");
log("\n");
@@ -77,7 +80,7 @@ struct SynthGowinPass : public ScriptPass
}
string top_opt, vout_file;
- bool retime, nobram, nodram, flatten, nodffe, nowidelut, abc9;
+ bool retime, nobram, nodram, flatten, nodffe, nowidelut, abc9, noiopads;
void clear_flags() YS_OVERRIDE
{
@@ -90,6 +93,7 @@ struct SynthGowinPass : public ScriptPass
nodram = false;
nowidelut = false;
abc9 = false;
+ noiopads = false;
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
@@ -144,6 +148,10 @@ struct SynthGowinPass : public ScriptPass
abc9 = true;
continue;
}
+ if (args[argidx] == "-noiopads") {
+ noiopads = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -208,7 +216,7 @@ struct SynthGowinPass : public ScriptPass
if (check_label("map_ffs"))
{
run("dffsr2dff");
- run("dff2dffs");
+ run("dff2dffs -match-init");
run("opt_clean");
if (!nodffe)
run("dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*");
@@ -236,8 +244,9 @@ struct SynthGowinPass : public ScriptPass
run("techmap -map +/gowin/cells_map.v");
run("setundef -undriven -params -zero");
run("hilomap -singleton -hicell VCC V -locell GND G");
- run("iopadmap -bits -inpad IBUF O:I -outpad OBUF I:O "
- "-toutpad TBUF OEN:I:O -tinoutpad IOBUF OEN:O:I:IO", "(unless -noiopads)");
+ if (!noiopads || help_mode)
+ run("iopadmap -bits -inpad IBUF O:I -outpad OBUF I:O "
+ "-toutpad TBUF OEN:I:O -tinoutpad IOBUF OEN:O:I:IO", "(unless -noiopads)");
run("clean");
}
diff --git a/techlibs/ice40/arith_map.v b/techlibs/ice40/arith_map.v
index 26b24db9e..00a07247b 100644
--- a/techlibs/ice40/arith_map.v
+++ b/techlibs/ice40/arith_map.v
@@ -50,7 +50,7 @@ module _80_ice40_alu (A, B, CI, BI, X, Y, CO);
// A[2]: 1111 0000 1111 0000
// A[3]: 1111 1111 0000 0000
.LUT(16'b 0110_1001_1001_0110)
- ) fadd (
+ ) carry (
.A(AA[i]),
.B(BB[i]),
.CI(C[i]),
diff --git a/techlibs/ice40/cells_map.v b/techlibs/ice40/cells_map.v
index 662423f0a..759549e30 100644
--- a/techlibs/ice40/cells_map.v
+++ b/techlibs/ice40/cells_map.v
@@ -61,22 +61,3 @@ module \$lut (A, Y);
endgenerate
endmodule
`endif
-
-`ifndef NO_ADDER
-module \$__ICE40_CARRY_WRAPPER (output CO, O, input A, B, CI, I0, I3);
- parameter LUT = 0;
- SB_CARRY carry (
- .I0(A),
- .I1(B),
- .CI(CI),
- .CO(CO)
- );
- \$lut #(
- .WIDTH(4),
- .LUT(LUT)
- ) lut (
- .A({I0,A,B,I3}),
- .Y(O)
- );
-endmodule
-`endif
diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc
index ea56d3f4d..371ceb623 100644
--- a/techlibs/ice40/ice40_opt.cc
+++ b/techlibs/ice40/ice40_opt.cc
@@ -41,6 +41,11 @@ static void run_ice40_opts(Module *module)
for (auto cell : module->selected_cells())
{
+ if (!cell->type.in("\\SB_LUT4", "\\SB_CARRY", "$__ICE40_CARRY_WRAPPER"))
+ continue;
+ if (cell->has_keep_attr())
+ continue;
+
if (cell->type == "\\SB_LUT4")
{
sb_lut_cells.push_back(cell);
@@ -112,6 +117,21 @@ static void run_ice40_opts(Module *module)
if (GetSize(replacement_output)) {
optimized_co.insert(sigmap(cell->getPort("\\CO")[0]));
+ auto it = cell->attributes.find(ID(SB_LUT4.name));
+ if (it != cell->attributes.end()) {
+ module->rename(cell, it->second.decode_string());
+ decltype(Cell::attributes) new_attr;
+ for (const auto &a : cell->attributes)
+ if (a.first.begins_with("\\SB_LUT4.\\"))
+ new_attr[a.first.c_str() + strlen("\\SB_LUT4.")] = a.second;
+ else if (a.first == ID(src))
+ new_attr.insert(std::make_pair(a.first, a.second));
+ else if (a.first.in(ID(SB_LUT4.name), ID::keep, ID(module_not_derived)))
+ continue;
+ else
+ log_abort();
+ cell->attributes = std::move(new_attr);
+ }
module->connect(cell->getPort("\\CO")[0], replacement_output);
module->design->scratchpad_set_bool("opt.did_something", true);
log("Optimized $__ICE40_CARRY_WRAPPER cell back to logic (without SB_CARRY) %s.%s: CO=%s\n",
diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc
index 901194b06..ed7a16c08 100644
--- a/techlibs/ice40/synth_ice40.cc
+++ b/techlibs/ice40/synth_ice40.cc
@@ -363,6 +363,7 @@ struct SynthIce40Pass : public ScriptPass
else
run(abc + " -dress -lut 4", "(skip if -noabc)");
}
+ run("ice40_wrapcarry -unwrap");
run("techmap -D NO_LUT -map +/ice40/cells_map.v");
run("clean");
run("opt_lut -dlogic SB_CARRY:I0=2:I1=1:CI=0");
diff --git a/techlibs/intel/Makefile.inc b/techlibs/intel/Makefile.inc
index 4e8f423c8..d97a9b58f 100644
--- a/techlibs/intel/Makefile.inc
+++ b/techlibs/intel/Makefile.inc
@@ -7,7 +7,7 @@ $(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_m9k.
$(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_map_m9k.v))
# Add the cell models and mappings for the VQM backend
-families := max10 a10gx cyclonev cyclone10 cycloneiv cycloneive
+families := max10 arria10gx cyclonev cyclone10lp cycloneiv cycloneive
$(foreach family,$(families), $(eval $(call add_share_file,share/intel/$(family),techlibs/intel/$(family)/cells_sim.v)))
$(foreach family,$(families), $(eval $(call add_share_file,share/intel/$(family),techlibs/intel/$(family)/cells_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/arria10gx/cells_arith.v
index 89fb4561f..89fb4561f 100644
--- a/techlibs/intel/a10gx/cells_arith.v
+++ b/techlibs/intel/arria10gx/cells_arith.v
diff --git a/techlibs/intel/a10gx/cells_map.v b/techlibs/intel/arria10gx/cells_map.v
index 1430e8551..1430e8551 100644
--- a/techlibs/intel/a10gx/cells_map.v
+++ b/techlibs/intel/arria10gx/cells_map.v
diff --git a/techlibs/intel/a10gx/cells_sim.v b/techlibs/intel/arria10gx/cells_sim.v
index e892b377e..e892b377e 100644
--- a/techlibs/intel/a10gx/cells_sim.v
+++ b/techlibs/intel/arria10gx/cells_sim.v
diff --git a/techlibs/intel/cyclone10/cells_arith.v b/techlibs/intel/cyclone10lp/cells_arith.v
index 5ae8d6cea..5ae8d6cea 100644
--- a/techlibs/intel/cyclone10/cells_arith.v
+++ b/techlibs/intel/cyclone10lp/cells_arith.v
diff --git a/techlibs/intel/cyclone10/cells_map.v b/techlibs/intel/cyclone10lp/cells_map.v
index c2f6f403c..c2f6f403c 100644
--- a/techlibs/intel/cyclone10/cells_map.v
+++ b/techlibs/intel/cyclone10lp/cells_map.v
diff --git a/techlibs/intel/cyclone10/cells_sim.v b/techlibs/intel/cyclone10lp/cells_sim.v
index f5a8aee2b..f5a8aee2b 100644
--- a/techlibs/intel/cyclone10/cells_sim.v
+++ b/techlibs/intel/cyclone10lp/cells_sim.v
diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc
index e5dc1adc7..c8c690e45 100644
--- a/techlibs/intel/synth_intel.cc
+++ b/techlibs/intel/synth_intel.cc
@@ -36,10 +36,10 @@ struct SynthIntelPass : public ScriptPass {
log("\n");
log("This command runs synthesis for Intel FPGAs.\n");
log("\n");
- log(" -family < max10 | a10gx | cyclone10 | cyclonev | cycloneiv | cycloneive>\n");
+ log(" -family <max10 | arria10gx | cyclone10lp | cyclonev | cycloneiv | cycloneive>\n");
log(" generate the synthesis netlist for the specified family.\n");
log(" MAX10 is the default target if no family argument specified.\n");
- log(" For Cyclone GX devices, use cycloneiv argument; For Cyclone E, use cycloneive.\n");
+ log(" For Cyclone IV GX devices, use cycloneiv argument; for Cyclone IV E, use cycloneive.\n");
log(" Cyclone V and Arria 10 GX devices are experimental.\n");
log("\n");
log(" -top <module>\n");
@@ -148,11 +148,11 @@ struct SynthIntelPass : public ScriptPass {
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 != "arria10gx" &&
family_opt != "cyclonev" &&
family_opt != "cycloneiv" &&
family_opt != "cycloneive" &&
- family_opt != "cyclone10")
+ family_opt != "cyclone10lp")
log_cmd_error("Invalid or no family specified: '%s'\n", family_opt.c_str());
log_header(design, "Executing SYNTH_INTEL pass.\n");
@@ -214,7 +214,7 @@ struct SynthIntelPass : public ScriptPass {
}
if (check_label("map_luts")) {
- if (family_opt == "a10gx" || family_opt == "cyclonev")
+ if (family_opt == "arria10gx" || family_opt == "cyclonev")
run("abc -luts 2:2,3,6:5" + string(retime ? " -dff" : ""));
else
run("abc -lut 4" + string(retime ? " -dff" : ""));
diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v
index a15884ec4..de2068bc5 100644
--- a/techlibs/xilinx/cells_map.v
+++ b/techlibs/xilinx/cells_map.v
@@ -363,3 +363,11 @@ module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1);
else
MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O));
endmodule
+
+module \$__XILINX_TINOUTPAD (input I, OE, output O, inout IO);
+ IOBUF _TECHMAP_REPLACE_ (.I(I), .O(O), .T(~OE), .IO(IO));
+endmodule
+
+module \$__XILINX_TOUTPAD (input I, OE, output O);
+ OBUFT _TECHMAP_REPLACE_ (.I(I), .O(O), .T(~OE));
+endmodule
diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v
index 1be43f9d4..3ed0759db 100644
--- a/techlibs/xilinx/cells_sim.v
+++ b/techlibs/xilinx/cells_sim.v
@@ -471,6 +471,473 @@ module LDPE (
else if (GE && g) Q = D;
endmodule
+// LUTRAM.
+
+// Single port.
+
+module RAM16X1S (
+ output O,
+ input A0, A1, A2, A3,
+ input D,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE
+);
+ parameter [15:0] INIT = 16'h0000;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ wire [3:0] a = {A3, A2, A1, A0};
+ reg [15:0] mem = INIT;
+ assign O = mem[a];
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ always @(posedge clk) if (WE) mem[a] <= D;
+endmodule
+
+module RAM16X1S_1 (
+ output O,
+ input A0, A1, A2, A3,
+ input D,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE
+);
+ parameter [15:0] INIT = 16'h0000;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ wire [3:0] a = {A3, A2, A1, A0};
+ reg [15:0] mem = INIT;
+ assign O = mem[a];
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ always @(negedge clk) if (WE) mem[a] <= D;
+endmodule
+
+module RAM32X1S (
+ output O,
+ input A0, A1, A2, A3, A4,
+ input D,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE
+);
+ parameter [31:0] INIT = 32'h00000000;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ wire [4:0] a = {A4, A3, A2, A1, A0};
+ reg [31:0] mem = INIT;
+ assign O = mem[a];
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ always @(posedge clk) if (WE) mem[a] <= D;
+endmodule
+
+module RAM32X1S_1 (
+ output O,
+ input A0, A1, A2, A3, A4,
+ input D,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE
+);
+ parameter [31:0] INIT = 32'h00000000;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ wire [4:0] a = {A4, A3, A2, A1, A0};
+ reg [31:0] mem = INIT;
+ assign O = mem[a];
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ always @(negedge clk) if (WE) mem[a] <= D;
+endmodule
+
+module RAM64X1S (
+ output O,
+ input A0, A1, A2, A3, A4, A5,
+ input D,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE
+);
+ parameter [63:0] INIT = 64'h0000000000000000;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ wire [5:0] a = {A5, A4, A3, A2, A1, A0};
+ reg [63:0] mem = INIT;
+ assign O = mem[a];
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ always @(posedge clk) if (WE) mem[a] <= D;
+endmodule
+
+module RAM64X1S_1 (
+ output O,
+ input A0, A1, A2, A3, A4, A5,
+ input D,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE
+);
+ parameter [63:0] INIT = 64'h0000000000000000;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ wire [5:0] a = {A5, A4, A3, A2, A1, A0};
+ reg [63:0] mem = INIT;
+ assign O = mem[a];
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ always @(negedge clk) if (WE) mem[a] <= D;
+endmodule
+
+module RAM128X1S (
+ output O,
+ input A0, A1, A2, A3, A4, A5, A6,
+ input D,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE
+);
+ parameter [127:0] INIT = 128'h00000000000000000000000000000000;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ wire [6:0] a = {A6, A5, A4, A3, A2, A1, A0};
+ reg [127:0] mem = INIT;
+ assign O = mem[a];
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ always @(posedge clk) if (WE) mem[a] <= D;
+endmodule
+
+module RAM128X1S_1 (
+ output O,
+ input A0, A1, A2, A3, A4, A5, A6,
+ input D,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE
+);
+ parameter [127:0] INIT = 128'h00000000000000000000000000000000;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ wire [6:0] a = {A6, A5, A4, A3, A2, A1, A0};
+ reg [127:0] mem = INIT;
+ assign O = mem[a];
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ always @(negedge clk) if (WE) mem[a] <= D;
+endmodule
+
+module RAM256X1S (
+ output O,
+ input [7:0] A,
+ input D,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE
+);
+ parameter [255:0] INIT = 256'h0;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ reg [255:0] mem = INIT;
+ assign O = mem[A];
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ always @(posedge clk) if (WE) mem[A] <= D;
+endmodule
+
+module RAM512X1S (
+ output O,
+ input [8:0] A,
+ input D,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE
+);
+ parameter [511:0] INIT = 512'h0;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ reg [511:0] mem = INIT;
+ assign O = mem[A];
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ always @(posedge clk) if (WE) mem[A] <= D;
+endmodule
+
+// Single port, wide.
+
+module RAM16X2S (
+ output O0, O1,
+ input A0, A1, A2, A3,
+ input D0, D1,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE
+);
+ parameter [15:0] INIT_00 = 16'h0000;
+ parameter [15:0] INIT_01 = 16'h0000;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ wire [3:0] a = {A3, A2, A1, A0};
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ reg [15:0] mem0 = INIT_00;
+ reg [15:0] mem1 = INIT_01;
+ assign O0 = mem0[a];
+ assign O1 = mem1[a];
+ always @(posedge clk)
+ if (WE) begin
+ mem0[a] <= D0;
+ mem1[a] <= D1;
+ end
+endmodule
+
+module RAM32X2S (
+ output O0, O1,
+ input A0, A1, A2, A3, A4,
+ input D0, D1,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE
+);
+ parameter [31:0] INIT_00 = 32'h00000000;
+ parameter [31:0] INIT_01 = 32'h00000000;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ wire [4:0] a = {A4, A3, A2, A1, A0};
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ reg [31:0] mem0 = INIT_00;
+ reg [31:0] mem1 = INIT_01;
+ assign O0 = mem0[a];
+ assign O1 = mem1[a];
+ always @(posedge clk)
+ if (WE) begin
+ mem0[a] <= D0;
+ mem1[a] <= D1;
+ end
+endmodule
+
+module RAM64X2S (
+ output O0, O1,
+ input A0, A1, A2, A3, A4, A5,
+ input D0, D1,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE
+);
+ parameter [63:0] INIT_00 = 64'h0000000000000000;
+ parameter [63:0] INIT_01 = 64'h0000000000000000;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ wire [5:0] a = {A5, A3, A2, A1, A0};
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ reg [63:0] mem0 = INIT_00;
+ reg [63:0] mem1 = INIT_01;
+ assign O0 = mem0[a];
+ assign O1 = mem1[a];
+ always @(posedge clk)
+ if (WE) begin
+ mem0[a] <= D0;
+ mem1[a] <= D1;
+ end
+endmodule
+
+module RAM16X4S (
+ output O0, O1, O2, O3,
+ input A0, A1, A2, A3,
+ input D0, D1, D2, D3,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE
+);
+ parameter [15:0] INIT_00 = 16'h0000;
+ parameter [15:0] INIT_01 = 16'h0000;
+ parameter [15:0] INIT_02 = 16'h0000;
+ parameter [15:0] INIT_03 = 16'h0000;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ wire [3:0] a = {A3, A2, A1, A0};
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ reg [15:0] mem0 = INIT_00;
+ reg [15:0] mem1 = INIT_01;
+ reg [15:0] mem2 = INIT_02;
+ reg [15:0] mem3 = INIT_03;
+ assign O0 = mem0[a];
+ assign O1 = mem1[a];
+ assign O2 = mem2[a];
+ assign O3 = mem3[a];
+ always @(posedge clk)
+ if (WE) begin
+ mem0[a] <= D0;
+ mem1[a] <= D1;
+ mem2[a] <= D2;
+ mem3[a] <= D3;
+ end
+endmodule
+
+module RAM32X4S (
+ output O0, O1, O2, O3,
+ input A0, A1, A2, A3, A4,
+ input D0, D1, D2, D3,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE
+);
+ parameter [31:0] INIT_00 = 32'h00000000;
+ parameter [31:0] INIT_01 = 32'h00000000;
+ parameter [31:0] INIT_02 = 32'h00000000;
+ parameter [31:0] INIT_03 = 32'h00000000;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ wire [4:0] a = {A4, A3, A2, A1, A0};
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ reg [31:0] mem0 = INIT_00;
+ reg [31:0] mem1 = INIT_01;
+ reg [31:0] mem2 = INIT_02;
+ reg [31:0] mem3 = INIT_03;
+ assign O0 = mem0[a];
+ assign O1 = mem1[a];
+ assign O2 = mem2[a];
+ assign O3 = mem3[a];
+ always @(posedge clk)
+ if (WE) begin
+ mem0[a] <= D0;
+ mem1[a] <= D1;
+ mem2[a] <= D2;
+ mem3[a] <= D3;
+ end
+endmodule
+
+module RAM16X8S (
+ output [7:0] O,
+ input A0, A1, A2, A3,
+ input [7:0] D,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE
+);
+ parameter [15:0] INIT_00 = 16'h0000;
+ parameter [15:0] INIT_01 = 16'h0000;
+ parameter [15:0] INIT_02 = 16'h0000;
+ parameter [15:0] INIT_03 = 16'h0000;
+ parameter [15:0] INIT_04 = 16'h0000;
+ parameter [15:0] INIT_05 = 16'h0000;
+ parameter [15:0] INIT_06 = 16'h0000;
+ parameter [15:0] INIT_07 = 16'h0000;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ wire [3:0] a = {A3, A2, A1, A0};
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ reg [15:0] mem0 = INIT_00;
+ reg [15:0] mem1 = INIT_01;
+ reg [15:0] mem2 = INIT_02;
+ reg [15:0] mem3 = INIT_03;
+ reg [15:0] mem4 = INIT_04;
+ reg [15:0] mem5 = INIT_05;
+ reg [15:0] mem6 = INIT_06;
+ reg [15:0] mem7 = INIT_07;
+ assign O[0] = mem0[a];
+ assign O[1] = mem1[a];
+ assign O[2] = mem2[a];
+ assign O[3] = mem3[a];
+ assign O[4] = mem4[a];
+ assign O[5] = mem5[a];
+ assign O[6] = mem6[a];
+ assign O[7] = mem7[a];
+ always @(posedge clk)
+ if (WE) begin
+ mem0[a] <= D[0];
+ mem1[a] <= D[1];
+ mem2[a] <= D[2];
+ mem3[a] <= D[3];
+ mem4[a] <= D[4];
+ mem5[a] <= D[5];
+ mem6[a] <= D[6];
+ mem7[a] <= D[7];
+ end
+endmodule
+
+module RAM32X8S (
+ output [7:0] O,
+ input A0, A1, A2, A3, A4,
+ input [7:0] D,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE
+);
+ parameter [31:0] INIT_00 = 32'h00000000;
+ parameter [31:0] INIT_01 = 32'h00000000;
+ parameter [31:0] INIT_02 = 32'h00000000;
+ parameter [31:0] INIT_03 = 32'h00000000;
+ parameter [31:0] INIT_04 = 32'h00000000;
+ parameter [31:0] INIT_05 = 32'h00000000;
+ parameter [31:0] INIT_06 = 32'h00000000;
+ parameter [31:0] INIT_07 = 32'h00000000;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ wire [4:0] a = {A4, A3, A2, A1, A0};
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ reg [31:0] mem0 = INIT_00;
+ reg [31:0] mem1 = INIT_01;
+ reg [31:0] mem2 = INIT_02;
+ reg [31:0] mem3 = INIT_03;
+ reg [31:0] mem4 = INIT_04;
+ reg [31:0] mem5 = INIT_05;
+ reg [31:0] mem6 = INIT_06;
+ reg [31:0] mem7 = INIT_07;
+ assign O[0] = mem0[a];
+ assign O[1] = mem1[a];
+ assign O[2] = mem2[a];
+ assign O[3] = mem3[a];
+ assign O[4] = mem4[a];
+ assign O[5] = mem5[a];
+ assign O[6] = mem6[a];
+ assign O[7] = mem7[a];
+ always @(posedge clk)
+ if (WE) begin
+ mem0[a] <= D[0];
+ mem1[a] <= D[1];
+ mem2[a] <= D[2];
+ mem3[a] <= D[3];
+ mem4[a] <= D[4];
+ mem5[a] <= D[5];
+ mem6[a] <= D[6];
+ mem7[a] <= D[7];
+ end
+endmodule
+
+// Dual port.
+
+module RAM16X1D (
+ output DPO, SPO,
+ input D,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE,
+ input A0, A1, A2, A3,
+ input DPRA0, DPRA1, DPRA2, DPRA3
+);
+ parameter INIT = 16'h0;
+ parameter IS_WCLK_INVERTED = 1'b0;
+ wire [3:0] a = {A3, A2, A1, A0};
+ wire [3:0] dpra = {DPRA3, DPRA2, DPRA1, DPRA0};
+ reg [15: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 RAM16X1D_1 (
+ output DPO, SPO,
+ input D,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE,
+ input A0, A1, A2, A3,
+ input DPRA0, DPRA1, DPRA2, DPRA3
+);
+ parameter INIT = 16'h0;
+ parameter IS_WCLK_INVERTED = 1'b0;
+ wire [3:0] a = {A3, A2, A1, A0};
+ wire [3:0] dpra = {DPRA3, DPRA2, DPRA1, DPRA0};
+ reg [15:0] mem = INIT;
+ assign SPO = mem[a];
+ assign DPO = mem[dpra];
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ always @(negedge clk) if (WE) mem[a] <= D;
+endmodule
+
module RAM32X1D (
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957
(* abc9_arrival=1153 *)
@@ -494,6 +961,29 @@ module RAM32X1D (
always @(posedge clk) if (WE) mem[a] <= D;
endmodule
+module RAM32X1D_1 (
+ // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957
+ (* abc9_arrival=1153 *)
+ output DPO, SPO,
+ input D,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE,
+ input A0, A1, A2, A3, A4,
+ input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4
+);
+ parameter INIT = 32'h0;
+ parameter IS_WCLK_INVERTED = 1'b0;
+ wire [4:0] a = {A4, A3, A2, A1, A0};
+ wire [4:0] dpra = {DPRA4, DPRA3, DPRA2, DPRA1, DPRA0};
+ reg [31:0] mem = INIT;
+ assign SPO = mem[a];
+ assign DPO = mem[dpra];
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ always @(negedge clk) if (WE) mem[a] <= D;
+endmodule
+
module RAM64X1D (
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957
(* abc9_arrival=1153 *)
@@ -517,6 +1007,29 @@ module RAM64X1D (
always @(posedge clk) if (WE) mem[a] <= D;
endmodule
+module RAM64X1D_1 (
+ // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957
+ (* abc9_arrival=1153 *)
+ output DPO, SPO,
+ input D,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input 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 @(negedge clk) if (WE) mem[a] <= D;
+endmodule
+
module RAM128X1D (
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957
(* abc9_arrival=1153 *)
@@ -537,6 +1050,290 @@ module RAM128X1D (
always @(posedge clk) if (WE) mem[A] <= D;
endmodule
+module RAM256X1D (
+ output DPO, SPO,
+ input D,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE,
+ input [7:0] A, DPRA
+);
+ parameter INIT = 256'h0;
+ parameter IS_WCLK_INVERTED = 1'b0;
+ reg [255: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
+
+// Multi port.
+
+module RAM32M (
+ output [1:0] DOA,
+ output [1:0] DOB,
+ output [1:0] DOC,
+ output [1:0] DOD,
+ input [4:0] ADDRA,
+ input [4:0] ADDRB,
+ input [4:0] ADDRC,
+ input [4:0] ADDRD,
+ input [1:0] DIA,
+ input [1:0] DIB,
+ input [1:0] DIC,
+ input [1:0] DID,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE
+);
+ parameter [63:0] INIT_A = 64'h0000000000000000;
+ parameter [63:0] INIT_B = 64'h0000000000000000;
+ parameter [63:0] INIT_C = 64'h0000000000000000;
+ parameter [63:0] INIT_D = 64'h0000000000000000;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ reg [63:0] mem_a = INIT_A;
+ reg [63:0] mem_b = INIT_B;
+ reg [63:0] mem_c = INIT_C;
+ reg [63:0] mem_d = INIT_D;
+ assign DOA = mem_a[2*ADDRA+:2];
+ assign DOB = mem_b[2*ADDRB+:2];
+ assign DOC = mem_c[2*ADDRC+:2];
+ assign DOD = mem_d[2*ADDRD+:2];
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ always @(posedge clk)
+ if (WE) begin
+ mem_a[2*ADDRD+:2] <= DIA;
+ mem_b[2*ADDRD+:2] <= DIB;
+ mem_c[2*ADDRD+:2] <= DIC;
+ mem_d[2*ADDRD+:2] <= DID;
+ end
+endmodule
+
+module RAM32M16 (
+ output [1:0] DOA,
+ output [1:0] DOB,
+ output [1:0] DOC,
+ output [1:0] DOD,
+ output [1:0] DOE,
+ output [1:0] DOF,
+ output [1:0] DOG,
+ output [1:0] DOH,
+ input [4:0] ADDRA,
+ input [4:0] ADDRB,
+ input [4:0] ADDRC,
+ input [4:0] ADDRD,
+ input [4:0] ADDRE,
+ input [4:0] ADDRF,
+ input [4:0] ADDRG,
+ input [4:0] ADDRH,
+ input [1:0] DIA,
+ input [1:0] DIB,
+ input [1:0] DIC,
+ input [1:0] DID,
+ input [1:0] DIE,
+ input [1:0] DIF,
+ input [1:0] DIG,
+ input [1:0] DIH,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE
+);
+ parameter [63:0] INIT_A = 64'h0000000000000000;
+ parameter [63:0] INIT_B = 64'h0000000000000000;
+ parameter [63:0] INIT_C = 64'h0000000000000000;
+ parameter [63:0] INIT_D = 64'h0000000000000000;
+ parameter [63:0] INIT_E = 64'h0000000000000000;
+ parameter [63:0] INIT_F = 64'h0000000000000000;
+ parameter [63:0] INIT_G = 64'h0000000000000000;
+ parameter [63:0] INIT_H = 64'h0000000000000000;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ reg [63:0] mem_a = INIT_A;
+ reg [63:0] mem_b = INIT_B;
+ reg [63:0] mem_c = INIT_C;
+ reg [63:0] mem_d = INIT_D;
+ reg [63:0] mem_e = INIT_E;
+ reg [63:0] mem_f = INIT_F;
+ reg [63:0] mem_g = INIT_G;
+ reg [63:0] mem_h = INIT_H;
+ assign DOA = mem_a[2*ADDRA+:2];
+ assign DOB = mem_b[2*ADDRB+:2];
+ assign DOC = mem_c[2*ADDRC+:2];
+ assign DOD = mem_d[2*ADDRD+:2];
+ assign DOE = mem_e[2*ADDRE+:2];
+ assign DOF = mem_f[2*ADDRF+:2];
+ assign DOG = mem_g[2*ADDRG+:2];
+ assign DOH = mem_h[2*ADDRH+:2];
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ always @(posedge clk)
+ if (WE) begin
+ mem_a[2*ADDRH+:2] <= DIA;
+ mem_b[2*ADDRH+:2] <= DIB;
+ mem_c[2*ADDRH+:2] <= DIC;
+ mem_d[2*ADDRH+:2] <= DID;
+ mem_e[2*ADDRH+:2] <= DIE;
+ mem_f[2*ADDRH+:2] <= DIF;
+ mem_g[2*ADDRH+:2] <= DIG;
+ mem_h[2*ADDRH+:2] <= DIH;
+ end
+endmodule
+
+module RAM64M (
+ output DOA,
+ output DOB,
+ output DOC,
+ output DOD,
+ input [4:0] ADDRA,
+ input [4:0] ADDRB,
+ input [4:0] ADDRC,
+ input [4:0] ADDRD,
+ input DIA,
+ input DIB,
+ input DIC,
+ input DID,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE
+);
+ parameter [63:0] INIT_A = 64'h0000000000000000;
+ parameter [63:0] INIT_B = 64'h0000000000000000;
+ parameter [63:0] INIT_C = 64'h0000000000000000;
+ parameter [63:0] INIT_D = 64'h0000000000000000;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ reg [63:0] mem_a = INIT_A;
+ reg [63:0] mem_b = INIT_B;
+ reg [63:0] mem_c = INIT_C;
+ reg [63:0] mem_d = INIT_D;
+ assign DOA = mem_a[ADDRA];
+ assign DOB = mem_b[ADDRB];
+ assign DOC = mem_c[ADDRC];
+ assign DOD = mem_d[ADDRD];
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ always @(posedge clk)
+ if (WE) begin
+ mem_a[ADDRD] <= DIA;
+ mem_b[ADDRD] <= DIB;
+ mem_c[ADDRD] <= DIC;
+ mem_d[ADDRD] <= DID;
+ end
+endmodule
+
+module RAM64M8 (
+ output DOA,
+ output DOB,
+ output DOC,
+ output DOD,
+ output DOE,
+ output DOF,
+ output DOG,
+ output DOH,
+ input [4:0] ADDRA,
+ input [4:0] ADDRB,
+ input [4:0] ADDRC,
+ input [4:0] ADDRD,
+ input [4:0] ADDRE,
+ input [4:0] ADDRF,
+ input [4:0] ADDRG,
+ input [4:0] ADDRH,
+ input DIA,
+ input DIB,
+ input DIC,
+ input DID,
+ input DIE,
+ input DIF,
+ input DIG,
+ input DIH,
+ (* clkbuf_sink *)
+ (* invertible_pin = "IS_WCLK_INVERTED" *)
+ input WCLK,
+ input WE
+);
+ parameter [63:0] INIT_A = 64'h0000000000000000;
+ parameter [63:0] INIT_B = 64'h0000000000000000;
+ parameter [63:0] INIT_C = 64'h0000000000000000;
+ parameter [63:0] INIT_D = 64'h0000000000000000;
+ parameter [63:0] INIT_E = 64'h0000000000000000;
+ parameter [63:0] INIT_F = 64'h0000000000000000;
+ parameter [63:0] INIT_G = 64'h0000000000000000;
+ parameter [63:0] INIT_H = 64'h0000000000000000;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ reg [63:0] mem_a = INIT_A;
+ reg [63:0] mem_b = INIT_B;
+ reg [63:0] mem_c = INIT_C;
+ reg [63:0] mem_d = INIT_D;
+ reg [63:0] mem_e = INIT_E;
+ reg [63:0] mem_f = INIT_F;
+ reg [63:0] mem_g = INIT_G;
+ reg [63:0] mem_h = INIT_H;
+ assign DOA = mem_a[ADDRA];
+ assign DOB = mem_b[ADDRB];
+ assign DOC = mem_c[ADDRC];
+ assign DOD = mem_d[ADDRD];
+ assign DOE = mem_e[ADDRE];
+ assign DOF = mem_f[ADDRF];
+ assign DOG = mem_g[ADDRG];
+ assign DOH = mem_h[ADDRH];
+ wire clk = WCLK ^ IS_WCLK_INVERTED;
+ always @(posedge clk)
+ if (WE) begin
+ mem_a[ADDRH] <= DIA;
+ mem_b[ADDRH] <= DIB;
+ mem_c[ADDRH] <= DIC;
+ mem_d[ADDRH] <= DID;
+ mem_e[ADDRH] <= DIE;
+ mem_f[ADDRH] <= DIF;
+ mem_g[ADDRH] <= DIG;
+ mem_h[ADDRH] <= DIH;
+ end
+endmodule
+
+// ROM.
+
+module ROM16X1 (
+ output O,
+ input A0, A1, A2, A3
+);
+ parameter [15:0] INIT = 16'h0;
+ assign O = INIT[{A3, A2, A1, A0}];
+endmodule
+
+module ROM32X1 (
+ output O,
+ input A0, A1, A2, A3, A4
+);
+ parameter [31:0] INIT = 32'h0;
+ assign O = INIT[{A4, A3, A2, A1, A0}];
+endmodule
+
+module ROM64X1 (
+ output O,
+ input A0, A1, A2, A3, A4, A5
+);
+ parameter [63:0] INIT = 64'h0;
+ assign O = INIT[{A5, A4, A3, A2, A1, A0}];
+endmodule
+
+module ROM128X1 (
+ output O,
+ input A0, A1, A2, A3, A4, A5, A6
+);
+ parameter [127:0] INIT = 128'h0;
+ assign O = INIT[{A6, A5, A4, A3, A2, A1, A0}];
+endmodule
+
+module ROM256X1 (
+ output O,
+ input A0, A1, A2, A3, A4, A5, A6, A7
+);
+ parameter [255:0] INIT = 256'h0;
+ assign O = INIT[{A7, A6, A5, A4, A3, A2, A1, A0}];
+endmodule
+
+// Shift registers.
+
module SRL16E (
// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904-L905
(* abc9_arrival=1472 *)
diff --git a/techlibs/xilinx/cells_xtra.py b/techlibs/xilinx/cells_xtra.py
index 82e403f78..e4c580b9d 100644
--- a/techlibs/xilinx/cells_xtra.py
+++ b/techlibs/xilinx/cells_xtra.py
@@ -28,40 +28,40 @@ CELLS = [
# - UG974 (Ultrascale)
# CLB -- RAM/ROM.
- Cell('RAM16X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM16X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM32X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM32X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM64X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM64X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM128X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM128X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM256X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM512X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM16X2S', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM32X2S', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM64X2S', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM16X4S', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM32X4S', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM16X8S', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM32X8S', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM16X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM16X1D_1', port_attrs={'WCLK': ['clkbuf_sink']}),
- #Cell('RAM32X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM32X1D_1', port_attrs={'WCLK': ['clkbuf_sink']}),
- #Cell('RAM64X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM64X1D_1', port_attrs={'WCLK': ['clkbuf_sink']}),
- #Cell('RAM128X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM256X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM32M', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM32M16', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM64M', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('RAM64M8', port_attrs={'WCLK': ['clkbuf_sink']}),
- Cell('ROM16X1'),
- Cell('ROM32X1'),
- Cell('ROM64X1'),
- Cell('ROM128X1'),
- Cell('ROM256X1'),
+ # Cell('RAM16X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM16X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM32X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM32X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM64X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM64X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM128X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM128X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM256X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM512X1S', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM16X2S', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM32X2S', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM64X2S', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM16X4S', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM32X4S', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM16X8S', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM32X8S', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM16X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM16X1D_1', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM32X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM32X1D_1', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM64X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM64X1D_1', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM128X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM256X1D', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM32M', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM32M16', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM64M', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('RAM64M8', port_attrs={'WCLK': ['clkbuf_sink']}),
+ # Cell('ROM16X1'),
+ # Cell('ROM32X1'),
+ # Cell('ROM64X1'),
+ # Cell('ROM128X1'),
+ # Cell('ROM256X1'),
# CLB -- registers/latches.
# Virtex 1/2/4/5, Spartan 3.
@@ -372,6 +372,7 @@ CELLS = [
Cell('BUFIO2', port_attrs={'IOCLK': ['clkbuf_driver'], 'DIVCLK': ['clkbuf_driver']}),
Cell('BUFIO2_2CLK', port_attrs={'IOCLK': ['clkbuf_driver'], 'DIVCLK': ['clkbuf_driver']}),
Cell('BUFIO2FB', port_attrs={'O': ['clkbuf_driver']}),
+ Cell('BUFPLL', port_attrs={'IOCLK': ['clkbuf_driver']}),
Cell('BUFPLL_MCB', port_attrs={'IOCLK0': ['clkbuf_driver'], 'IOCLK1': ['clkbuf_driver']}),
# Clock buffers (IO and regional) -- Virtex.
diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v
index 671d16e8a..8ac596459 100644
--- a/techlibs/xilinx/cells_xtra.v
+++ b/techlibs/xilinx/cells_xtra.v
@@ -1,595 +1,5 @@
// Created by cells_xtra.py from Xilinx models
-module RAM16X1S (...);
- parameter [15:0] INIT = 16'h0000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output O;
- input A0;
- input A1;
- input A2;
- input A3;
- input D;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
-endmodule
-
-module RAM16X1S_1 (...);
- parameter [15:0] INIT = 16'h0000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output O;
- input A0;
- input A1;
- input A2;
- input A3;
- input D;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
-endmodule
-
-module RAM32X1S (...);
- parameter [31:0] INIT = 32'h00000000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output O;
- input A0;
- input A1;
- input A2;
- input A3;
- input A4;
- input D;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
-endmodule
-
-module RAM32X1S_1 (...);
- parameter [31:0] INIT = 32'h00000000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output O;
- input A0;
- input A1;
- input A2;
- input A3;
- input A4;
- input D;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
-endmodule
-
-module RAM64X1S (...);
- parameter [63:0] INIT = 64'h0000000000000000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output O;
- input A0;
- input A1;
- input A2;
- input A3;
- input A4;
- input A5;
- input D;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
-endmodule
-
-module RAM64X1S_1 (...);
- parameter [63:0] INIT = 64'h0000000000000000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output O;
- input A0;
- input A1;
- input A2;
- input A3;
- input A4;
- input A5;
- input D;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
-endmodule
-
-module RAM128X1S (...);
- parameter [127:0] INIT = 128'h00000000000000000000000000000000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output O;
- input A0;
- input A1;
- input A2;
- input A3;
- input A4;
- input A5;
- input A6;
- input D;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
-endmodule
-
-module RAM128X1S_1 (...);
- parameter [127:0] INIT = 128'h00000000000000000000000000000000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output O;
- input A0;
- input A1;
- input A2;
- input A3;
- input A4;
- input A5;
- input A6;
- input D;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
-endmodule
-
-module RAM256X1S (...);
- parameter [255:0] INIT = 256'h0;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output O;
- input [7:0] A;
- input D;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
-endmodule
-
-module RAM512X1S (...);
- parameter [511:0] INIT = 512'h0;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output O;
- input [8:0] A;
- input D;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
-endmodule
-
-module RAM16X2S (...);
- parameter [15:0] INIT_00 = 16'h0000;
- parameter [15:0] INIT_01 = 16'h0000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output O0;
- output O1;
- input A0;
- input A1;
- input A2;
- input A3;
- input D0;
- input D1;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
-endmodule
-
-module RAM32X2S (...);
- parameter [31:0] INIT_00 = 32'h00000000;
- parameter [31:0] INIT_01 = 32'h00000000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output O0;
- output O1;
- input A0;
- input A1;
- input A2;
- input A3;
- input A4;
- input D0;
- input D1;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
-endmodule
-
-module RAM64X2S (...);
- parameter [63:0] INIT_00 = 64'h0000000000000000;
- parameter [63:0] INIT_01 = 64'h0000000000000000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output O0;
- output O1;
- input A0;
- input A1;
- input A2;
- input A3;
- input A4;
- input A5;
- input D0;
- input D1;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
-endmodule
-
-module RAM16X4S (...);
- parameter [15:0] INIT_00 = 16'h0000;
- parameter [15:0] INIT_01 = 16'h0000;
- parameter [15:0] INIT_02 = 16'h0000;
- parameter [15:0] INIT_03 = 16'h0000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output O0;
- output O1;
- output O2;
- output O3;
- input A0;
- input A1;
- input A2;
- input A3;
- input D0;
- input D1;
- input D2;
- input D3;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
-endmodule
-
-module RAM32X4S (...);
- parameter [31:0] INIT_00 = 32'h00000000;
- parameter [31:0] INIT_01 = 32'h00000000;
- parameter [31:0] INIT_02 = 32'h00000000;
- parameter [31:0] INIT_03 = 32'h00000000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output O0;
- output O1;
- output O2;
- output O3;
- input A0;
- input A1;
- input A2;
- input A3;
- input A4;
- input D0;
- input D1;
- input D2;
- input D3;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
-endmodule
-
-module RAM16X8S (...);
- parameter [15:0] INIT_00 = 16'h0000;
- parameter [15:0] INIT_01 = 16'h0000;
- parameter [15:0] INIT_02 = 16'h0000;
- parameter [15:0] INIT_03 = 16'h0000;
- parameter [15:0] INIT_04 = 16'h0000;
- parameter [15:0] INIT_05 = 16'h0000;
- parameter [15:0] INIT_06 = 16'h0000;
- parameter [15:0] INIT_07 = 16'h0000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output [7:0] O;
- input A0;
- input A1;
- input A2;
- input A3;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
- input [7:0] D;
-endmodule
-
-module RAM32X8S (...);
- parameter [31:0] INIT_00 = 32'h00000000;
- parameter [31:0] INIT_01 = 32'h00000000;
- parameter [31:0] INIT_02 = 32'h00000000;
- parameter [31:0] INIT_03 = 32'h00000000;
- parameter [31:0] INIT_04 = 32'h00000000;
- parameter [31:0] INIT_05 = 32'h00000000;
- parameter [31:0] INIT_06 = 32'h00000000;
- parameter [31:0] INIT_07 = 32'h00000000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output [7:0] O;
- input A0;
- input A1;
- input A2;
- input A3;
- input A4;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
- input [7:0] D;
-endmodule
-
-module RAM16X1D (...);
- parameter [15:0] INIT = 16'h0000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output DPO;
- output SPO;
- input A0;
- input A1;
- input A2;
- input A3;
- input D;
- input DPRA0;
- input DPRA1;
- input DPRA2;
- input DPRA3;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
-endmodule
-
-module RAM16X1D_1 (...);
- parameter [15:0] INIT = 16'h0000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output DPO;
- output SPO;
- input A0;
- input A1;
- input A2;
- input A3;
- input D;
- input DPRA0;
- input DPRA1;
- input DPRA2;
- input DPRA3;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
-endmodule
-
-module RAM32X1D_1 (...);
- parameter [31:0] INIT = 32'h00000000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output DPO;
- output SPO;
- input A0;
- input A1;
- input A2;
- input A3;
- input A4;
- input D;
- input DPRA0;
- input DPRA1;
- input DPRA2;
- input DPRA3;
- input DPRA4;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
-endmodule
-
-module RAM64X1D_1 (...);
- parameter [63:0] INIT = 64'h0000000000000000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output DPO;
- output SPO;
- input A0;
- input A1;
- input A2;
- input A3;
- input A4;
- input A5;
- input D;
- input DPRA0;
- input DPRA1;
- input DPRA2;
- input DPRA3;
- input DPRA4;
- input DPRA5;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
-endmodule
-
-module RAM256X1D (...);
- parameter [255:0] INIT = 256'h0000000000000000000000000000000000000000000000000000000000000000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output DPO;
- output SPO;
- input [7:0] A;
- input D;
- input [7:0] DPRA;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
-endmodule
-
-module RAM32M (...);
- parameter [63:0] INIT_A = 64'h0000000000000000;
- parameter [63:0] INIT_B = 64'h0000000000000000;
- parameter [63:0] INIT_C = 64'h0000000000000000;
- parameter [63:0] INIT_D = 64'h0000000000000000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output [1:0] DOA;
- output [1:0] DOB;
- output [1:0] DOC;
- output [1:0] DOD;
- input [4:0] ADDRA;
- input [4:0] ADDRB;
- input [4:0] ADDRC;
- input [4:0] ADDRD;
- input [1:0] DIA;
- input [1:0] DIB;
- input [1:0] DIC;
- input [1:0] DID;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
-endmodule
-
-module RAM32M16 (...);
- parameter [63:0] INIT_A = 64'h0000000000000000;
- parameter [63:0] INIT_B = 64'h0000000000000000;
- parameter [63:0] INIT_C = 64'h0000000000000000;
- parameter [63:0] INIT_D = 64'h0000000000000000;
- parameter [63:0] INIT_E = 64'h0000000000000000;
- parameter [63:0] INIT_F = 64'h0000000000000000;
- parameter [63:0] INIT_G = 64'h0000000000000000;
- parameter [63:0] INIT_H = 64'h0000000000000000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output [1:0] DOA;
- output [1:0] DOB;
- output [1:0] DOC;
- output [1:0] DOD;
- output [1:0] DOE;
- output [1:0] DOF;
- output [1:0] DOG;
- output [1:0] DOH;
- input [4:0] ADDRA;
- input [4:0] ADDRB;
- input [4:0] ADDRC;
- input [4:0] ADDRD;
- input [4:0] ADDRE;
- input [4:0] ADDRF;
- input [4:0] ADDRG;
- input [4:0] ADDRH;
- input [1:0] DIA;
- input [1:0] DIB;
- input [1:0] DIC;
- input [1:0] DID;
- input [1:0] DIE;
- input [1:0] DIF;
- input [1:0] DIG;
- input [1:0] DIH;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
-endmodule
-
-module RAM64M (...);
- parameter [63:0] INIT_A = 64'h0000000000000000;
- parameter [63:0] INIT_B = 64'h0000000000000000;
- parameter [63:0] INIT_C = 64'h0000000000000000;
- parameter [63:0] INIT_D = 64'h0000000000000000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output DOA;
- output DOB;
- output DOC;
- output DOD;
- input [5:0] ADDRA;
- input [5:0] ADDRB;
- input [5:0] ADDRC;
- input [5:0] ADDRD;
- input DIA;
- input DIB;
- input DIC;
- input DID;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
-endmodule
-
-module RAM64M8 (...);
- parameter [63:0] INIT_A = 64'h0000000000000000;
- parameter [63:0] INIT_B = 64'h0000000000000000;
- parameter [63:0] INIT_C = 64'h0000000000000000;
- parameter [63:0] INIT_D = 64'h0000000000000000;
- parameter [63:0] INIT_E = 64'h0000000000000000;
- parameter [63:0] INIT_F = 64'h0000000000000000;
- parameter [63:0] INIT_G = 64'h0000000000000000;
- parameter [63:0] INIT_H = 64'h0000000000000000;
- parameter [0:0] IS_WCLK_INVERTED = 1'b0;
- output DOA;
- output DOB;
- output DOC;
- output DOD;
- output DOE;
- output DOF;
- output DOG;
- output DOH;
- input [5:0] ADDRA;
- input [5:0] ADDRB;
- input [5:0] ADDRC;
- input [5:0] ADDRD;
- input [5:0] ADDRE;
- input [5:0] ADDRF;
- input [5:0] ADDRG;
- input [5:0] ADDRH;
- input DIA;
- input DIB;
- input DIC;
- input DID;
- input DIE;
- input DIF;
- input DIG;
- input DIH;
- (* clkbuf_sink *)
- (* invertible_pin = "IS_WCLK_INVERTED" *)
- input WCLK;
- input WE;
-endmodule
-
-module ROM16X1 (...);
- parameter [127:0] INIT = 16'h0000;
- output O;
- input A0;
- input A1;
- input A2;
- input A3;
-endmodule
-
-module ROM32X1 (...);
- parameter [31:0] INIT = 32'h00000000;
- output O;
- input A0;
- input A1;
- input A2;
- input A3;
- input A4;
-endmodule
-
-module ROM64X1 (...);
- parameter [63:0] INIT = 64'h0000000000000000;
- output O;
- input A0;
- input A1;
- input A2;
- input A3;
- input A4;
- input A5;
-endmodule
-
-module ROM128X1 (...);
- parameter [127:0] INIT = 128'h00000000000000000000000000000000;
- output O;
- input A0;
- input A1;
- input A2;
- input A3;
- input A4;
- input A5;
- input A6;
-endmodule
-
-module ROM256X1 (...);
- parameter [255:0] INIT = 256'h0000000000000000000000000000000000000000000000000000000000000000;
- output O;
- input A0;
- input A1;
- input A2;
- input A3;
- input A4;
- input A5;
- input A6;
- input A7;
-endmodule
-
module FDCPE (...);
parameter [0:0] INIT = 1'b0;
parameter [0:0] IS_C_INVERTED = 1'b0;
@@ -5240,9 +4650,13 @@ module RAMB18E1 (...);
parameter IS_RSTRAMB_INVERTED = 1'b0;
parameter IS_RSTREGARSTREG_INVERTED = 1'b0;
parameter IS_RSTREGB_INVERTED = 1'b0;
+ (* abc9_arrival=2454 *)
output [15:0] DOADO;
+ (* abc9_arrival=2454 *)
output [15:0] DOBDO;
+ (* abc9_arrival=2454 *)
output [1:0] DOPADOP;
+ (* abc9_arrival=2454 *)
output [1:0] DOPBDOP;
(* clkbuf_sink *)
(* invertible_pin = "IS_CLKARDCLK_INVERTED" *)
@@ -5452,9 +4866,13 @@ module RAMB36E1 (...);
parameter IS_RSTREGB_INVERTED = 1'b0;
output CASCADEOUTA;
output CASCADEOUTB;
+ (* abc9_arrival=2454 *)
output [31:0] DOADO;
+ (* abc9_arrival=2454 *)
output [31:0] DOBDO;
+ (* abc9_arrival=2454 *)
output [3:0] DOPADOP;
+ (* abc9_arrival=2454 *)
output [3:0] DOPBDOP;
output [7:0] ECCPARITY;
output [8:0] RDADDRECC;
@@ -8527,6 +7945,18 @@ module BUFIO2FB (...);
input I;
endmodule
+module BUFPLL (...);
+ parameter integer DIVIDE = 1;
+ parameter ENABLE_SYNC = "TRUE";
+ (* clkbuf_driver *)
+ output IOCLK;
+ output LOCK;
+ output SERDESSTROBE;
+ input GCLK;
+ input LOCKED;
+ input PLLIN;
+endmodule
+
module BUFPLL_MCB (...);
parameter integer DIVIDE = 2;
parameter LOCK_SRC = "LOCK_TO_0";
diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc
index 3d4a65c5d..2c5686a35 100644
--- a/techlibs/xilinx/synth_xilinx.cc
+++ b/techlibs/xilinx/synth_xilinx.cc
@@ -282,6 +282,7 @@ struct SynthXilinxPass : public ScriptPass
void script() YS_OVERRIDE
{
+ bool do_iopad = iopad || (ise && !noiopad);
std::string ff_map_file;
if (help_mode)
ff_map_file = "+/xilinx/{family}_ff_map.v";
@@ -305,6 +306,8 @@ struct SynthXilinxPass : public ScriptPass
run("proc");
if (flatten || help_mode)
run("flatten", "(with '-flatten')");
+ run("tribuf -logic");
+ run("deminout");
run("opt_expr");
run("opt_clean");
run("check");
@@ -503,6 +506,9 @@ struct SynthXilinxPass : public ScriptPass
}
if (check_label("map_cells")) {
+ // Needs to be done before logic optimization, so that inverters (OE vs T) are handled.
+ if (help_mode || do_iopad)
+ run("iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I -toutpad $__XILINX_TOUTPAD OE:I:O -tinoutpad $__XILINX_TINOUTPAD OE:O:I:IO A:top", "(only if '-iopad' or '-ise' and not '-noiopad')");
std::string techmap_args = "-map +/techmap.v -map +/xilinx/cells_map.v";
if (widemux > 0)
techmap_args += stringf(" -D MIN_MUX_INPUTS=%d", widemux);
@@ -561,15 +567,8 @@ struct SynthXilinxPass : public ScriptPass
}
if (check_label("finalize")) {
- bool do_iopad = iopad || (ise && !noiopad);
- if (help_mode || !noclkbuf) {
- if (help_mode || do_iopad)
- run("clkbufmap -buf BUFG O:I -inpad IBUFG O:I", "(skip if '-noclkbuf', '-inpad' passed if '-iopad' or '-ise' and not '-noiopad')");
- else
- run("clkbufmap -buf BUFG O:I");
- }
- if (help_mode || do_iopad)
- run("iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I A:top", "(only if '-iopad' or '-ise' and not '-noiopad')");
+ if (help_mode || !noclkbuf)
+ run("clkbufmap -buf BUFG O:I ", "(skip if '-noclkbuf')");
if (help_mode || ise)
run("extractinv -inv INV O:I", "(only if '-ise')");
}
diff --git a/tests/arch/gowin/adffs.ys b/tests/arch/gowin/adffs.ys
index fc7ee01f2..87fba83a6 100644
--- a/tests/arch/gowin/adffs.ys
+++ b/tests/arch/gowin/adffs.ys
@@ -34,11 +34,12 @@ proc
equiv_opt -async2sync -assert -map +/gowin/cells_sim.v synth_gowin # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd dffs # Constrain all select calls below inside the top module
-select -assert-count 1 t:DFFS
+select -assert-count 1 t:DFF
+select -assert-count 1 t:LUT2
select -assert-count 4 t:IBUF
select -assert-count 1 t:OBUF
-select -assert-none t:DFFS t:IBUF t:OBUF %% t:* %D
+select -assert-none t:DFF t:LUT2 t:IBUF t:OBUF %% t:* %D
design -load read
diff --git a/tests/arch/gowin/init.v b/tests/arch/gowin/init.v
new file mode 100644
index 000000000..3c30f602d
--- /dev/null
+++ b/tests/arch/gowin/init.v
@@ -0,0 +1,224 @@
+module myDFF (output reg Q, input CLK, D);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(posedge CLK)
+ Q <= D;
+endmodule
+
+module myDFFE (output reg Q, input D, CLK, CE);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(posedge CLK) begin
+ if (CE)
+ Q <= D;
+ end
+endmodule // DFFE (positive clock edge; clock enable)
+
+
+module myDFFS (output reg Q, input D, CLK, SET);
+ parameter [0:0] INIT = 1'b1;
+ initial Q = INIT;
+ always @(posedge CLK) begin
+ if (SET)
+ Q <= 1'b1;
+ else
+ Q <= D;
+ end
+endmodule // DFFS (positive clock edge; synchronous set)
+
+
+module myDFFSE (output reg Q, input D, CLK, CE, SET);
+ parameter [0:0] INIT = 1'b1;
+ initial Q = INIT;
+ always @(posedge CLK) begin
+ if (SET)
+ Q <= 1'b1;
+ else if (CE)
+ Q <= D;
+end
+endmodule // DFFSE (positive clock edge; synchronous set takes precedence over clock enable)
+
+
+module myDFFR (output reg Q, input D, CLK, RESET);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(posedge CLK) begin
+ if (RESET)
+ Q <= 1'b0;
+ else
+ Q <= D;
+ end
+endmodule // DFFR (positive clock edge; synchronous reset)
+
+
+module myDFFRE (output reg Q, input D, CLK, CE, RESET);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(posedge CLK) begin
+ if (RESET)
+ Q <= 1'b0;
+ else if (CE)
+ Q <= D;
+ end
+endmodule // DFFRE (positive clock edge; synchronous reset takes precedence over clock enable)
+
+
+module myDFFP (output reg Q, input D, CLK, PRESET);
+ parameter [0:0] INIT = 1'b1;
+ initial Q = INIT;
+ always @(posedge CLK or posedge PRESET) begin
+ if(PRESET)
+ Q <= 1'b1;
+ else
+ Q <= D;
+ end
+endmodule // DFFP (positive clock edge; asynchronous preset)
+
+
+module myDFFPE (output reg Q, input D, CLK, CE, PRESET);
+ parameter [0:0] INIT = 1'b1;
+ initial Q = INIT;
+ always @(posedge CLK or posedge PRESET) begin
+ if(PRESET)
+ Q <= 1'b1;
+ else if (CE)
+ Q <= D;
+ end
+endmodule // DFFPE (positive clock edge; asynchronous preset; clock enable)
+
+
+module myDFFC (output reg Q, input D, CLK, CLEAR);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(posedge CLK or posedge CLEAR) begin
+ if(CLEAR)
+ Q <= 1'b0;
+ else
+ Q <= D;
+ end
+endmodule // DFFC (positive clock edge; asynchronous clear)
+
+
+module myDFFCE (output reg Q, input D, CLK, CE, CLEAR);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(posedge CLK or posedge CLEAR) begin
+ if(CLEAR)
+ Q <= 1'b0;
+ else if (CE)
+ Q <= D;
+ end
+endmodule // DFFCE (positive clock edge; asynchronous clear; clock enable)
+
+
+module myDFFN (output reg Q, input CLK, D);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(negedge CLK)
+ Q <= D;
+endmodule
+
+module myDFFNE (output reg Q, input D, CLK, CE);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(negedge CLK) begin
+ if (CE)
+ Q <= D;
+ end
+endmodule // DFFNE (negative clock edge; clock enable)
+
+
+module myDFFNS (output reg Q, input D, CLK, SET);
+ parameter [0:0] INIT = 1'b1;
+ initial Q = INIT;
+ always @(negedge CLK) begin
+ if (SET)
+ Q <= 1'b1;
+ else
+ Q <= D;
+ end
+endmodule // DFFNS (negative clock edge; synchronous set)
+
+
+module myDFFNSE (output reg Q, input D, CLK, CE, SET);
+ parameter [0:0] INIT = 1'b1;
+ initial Q = INIT;
+ always @(negedge CLK) begin
+ if (SET)
+ Q <= 1'b1;
+ else if (CE)
+ Q <= D;
+end
+endmodule // DFFNSE (negative clock edge; synchronous set takes precedence over clock enable)
+
+
+module myDFFNR (output reg Q, input D, CLK, RESET);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(negedge CLK) begin
+ if (RESET)
+ Q <= 1'b0;
+ else
+ Q <= D;
+ end
+endmodule // DFFNR (negative clock edge; synchronous reset)
+
+
+module myDFFNRE (output reg Q, input D, CLK, CE, RESET);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(negedge CLK) begin
+ if (RESET)
+ Q <= 1'b0;
+ else if (CE)
+ Q <= D;
+ end
+endmodule // DFFNRE (negative clock edge; synchronous reset takes precedence over clock enable)
+
+
+module myDFFNP (output reg Q, input D, CLK, PRESET);
+ parameter [0:0] INIT = 1'b1;
+ initial Q = INIT;
+ always @(negedge CLK or posedge PRESET) begin
+ if(PRESET)
+ Q <= 1'b1;
+ else
+ Q <= D;
+ end
+endmodule // DFFNP (negative clock edge; asynchronous preset)
+
+
+module myDFFNPE (output reg Q, input D, CLK, CE, PRESET);
+ parameter [0:0] INIT = 1'b1;
+ initial Q = INIT;
+ always @(negedge CLK or posedge PRESET) begin
+ if(PRESET)
+ Q <= 1'b1;
+ else if (CE)
+ Q <= D;
+ end
+endmodule // DFFNPE (negative clock edge; asynchronous preset; clock enable)
+
+
+module myDFFNC (output reg Q, input D, CLK, CLEAR);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(negedge CLK or posedge CLEAR) begin
+ if(CLEAR)
+ Q <= 1'b0;
+ else
+ Q <= D;
+ end
+endmodule // DFFNC (negative clock edge; asynchronous clear)
+
+
+module myDFFNCE (output reg Q, input D, CLK, CE, CLEAR);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(negedge CLK or posedge CLEAR) begin
+ if(CLEAR)
+ Q <= 1'b0;
+ else if (CE)
+ Q <= D;
+ end
+endmodule // DFFNCE (negative clock edge; asynchronous clear; clock enable)
diff --git a/tests/arch/gowin/init.ys b/tests/arch/gowin/init.ys
new file mode 100644
index 000000000..ddc0e4757
--- /dev/null
+++ b/tests/arch/gowin/init.ys
@@ -0,0 +1,74 @@
+read_verilog init.v
+read_verilog -lib +/gowin/cells_sim.v
+design -save read
+
+proc
+flatten
+synth_gowin -run coarse:
+
+# check if all init values are handled
+check -assert -noinit
+# check if every flop mapped correctly
+select -assert-count 1 t:DFF
+select -assert-count 1 t:DFFC
+select -assert-count 1 t:DFFCE
+select -assert-count 1 t:DFFE
+select -assert-count 1 t:DFFN
+select -assert-count 1 t:DFFNC
+select -assert-count 1 t:DFFNCE
+select -assert-count 1 t:DFFNE
+select -assert-count 1 t:DFFNP
+select -assert-count 1 t:DFFNPE
+select -assert-count 1 t:DFFNR
+select -assert-count 1 t:DFFNRE
+select -assert-count 1 t:DFFNS
+select -assert-count 1 t:DFFNSE
+select -assert-count 1 t:DFFP
+select -assert-count 1 t:DFFPE
+select -assert-count 1 t:DFFR
+select -assert-count 1 t:DFFRE
+select -assert-count 1 t:DFFS
+select -assert-count 1 t:DFFSE
+
+delete
+design -load read
+
+# these should synth to a flop with reset
+chparam -set INIT 1 myDFF myDFFN myDFFE myDFFNE
+
+# async should give a warning
+# sync should synth to a mux
+chparam -set INIT 0 myDFF*S* myDFF*P*
+chparam -set INIT 1 myDFF*R* myDFF*C*
+
+proc
+flatten
+synth_gowin -run coarse:
+
+# check the flops mapped as expected
+select -assert-count 1 t:DFF
+select -assert-count 1 t:DFFC
+select -assert-count 1 t:DFFCE
+select -assert-count 1 t:DFFE
+select -assert-count 1 t:DFFN
+select -assert-count 1 t:DFFNC
+select -assert-count 1 t:DFFNCE
+select -assert-count 1 t:DFFNE
+select -assert-count 1 t:DFFNP
+select -assert-count 1 t:DFFNPE
+select -assert-count 0 t:DFFNR
+select -assert-count 0 t:DFFNRE
+select -assert-count 2 t:DFFNS
+select -assert-count 2 t:DFFNSE
+select -assert-count 1 t:DFFP
+select -assert-count 1 t:DFFPE
+select -assert-count 0 t:DFFR
+select -assert-count 0 t:DFFRE
+select -assert-count 2 t:DFFS
+select -assert-count 2 t:DFFSE
+select -assert-count 12 t:LUT2
+
+# check the expected leftover init values
+# this would happen if your reset value is not the initial value
+# which would be weird
+select -assert-count 8 a:init
diff --git a/tests/arch/ice40/ice40_opt.ys b/tests/arch/ice40/ice40_opt.ys
index b17c69c91..5186d4800 100644
--- a/tests/arch/ice40/ice40_opt.ys
+++ b/tests/arch/ice40/ice40_opt.ys
@@ -1,4 +1,24 @@
read_verilog -icells -formal <<EOT
+module \$__ICE40_CARRY_WRAPPER (output CO, O, input A, B, CI, I0, I3);
+ parameter LUT = 0;
+ SB_CARRY carry (
+ .I0(A),
+ .I1(B),
+ .CI(CI),
+ .CO(CO)
+ );
+ \$lut #(
+ .WIDTH(4),
+ .LUT(LUT)
+ ) lut (
+ .A({I0,A,B,I3}),
+ .Y(O)
+ );
+endmodule
+EOT
+design -stash unmap
+
+read_verilog -icells -formal <<EOT
module top(input CI, I0, output [1:0] CO, output O);
wire A = 1'b0, B = 1'b0;
\$__ICE40_CARRY_WRAPPER #(
@@ -20,7 +40,68 @@ module top(input CI, I0, output [1:0] CO, output O);
endmodule
EOT
-equiv_opt -assert -map +/ice40/cells_map.v -map +/ice40/cells_sim.v ice40_opt
+equiv_opt -assert -map %unmap -map +/ice40/cells_sim.v ice40_opt
design -load postopt
select -assert-count 1 t:*
select -assert-count 1 t:$lut
+
+# https://github.com/YosysHQ/yosys/issues/1543
+design -reset
+read_verilog <<EOT
+module delay_element (input wire clk, input wire reset, input wire enable,
+ input wire chainin, output wire chainout, output reg latch);
+
+
+ reg const_zero = 0;
+ reg const_one = 1;
+
+ wire delay_tap;
+
+
+ //carry logic
+ (* keep *) SB_CARRY carry ( .CO(chainout), .I0(const_zero),
+ .I1(const_one), .CI(chainin));
+
+
+ //flip flop latch
+ (* keep *) SB_DFFER flipflop( .Q(latch), .C(clk), .E(enable),
+ .D(delay_tap), .R(reset));
+
+
+ //LUT table
+ // the LUT should just echo the carry in (I3)
+ // carry I0 = LUT I1
+ // carry I1 = LUT I2
+ // carry in = LUT I3
+ // LUT_INIT[0] = 0
+ // LUT_INIT[1] = 0
+ // LUT_INIT[2] = 0
+ // LUT_INIT[3] = 0
+ // LUT_INIT[4] = 0
+ // LUT_INIT[5] = 0
+ // LUT_INIT[6] = 0
+ // LUT_INIT[7] = 0
+ // LUT_INIT[8] = 1
+ // LUT_INIT[9] = 1
+ // LUT_INIT[10] = 1
+ // LUT_INIT[11] = 1
+ // LUT_INIT[12] = 1
+ // LUT_INIT[13] = 1
+ // LUT_INIT[14] = 1
+ // LUT_INIT[15] = 1
+
+ (* keep *) SB_LUT4 lut( .O(delay_tap), .I0(const_zero), .I1(const_zero),
+ .I2(const_one), .I3(chainin));
+
+ //TODO: is this the right way round??
+ defparam lut.LUT_INIT=16'hFF00;
+
+
+endmodule // delay_element
+EOT
+
+synth_ice40
+select -assert-count 1 t:SB_LUT4
+select -assert-count 1 t:SB_CARRY
+select -assert-count 1 t:SB_CARRY a:keep %i
+select -assert-count 1 t:SB_CARRY c:carry %i
diff --git a/tests/arch/ice40/ice40_wrapcarry.ys b/tests/arch/ice40/ice40_wrapcarry.ys
new file mode 100644
index 000000000..fb9fccc3a
--- /dev/null
+++ b/tests/arch/ice40/ice40_wrapcarry.ys
@@ -0,0 +1,54 @@
+read_verilog <<EOT
+module top(input A, B, CI, output O, CO);
+ SB_CARRY carry (
+ .I0(A),
+ .I1(B),
+ .CI(CI),
+ .CO(CO)
+ );
+ SB_LUT4 #(
+ .LUT_INIT(16'b 0110_1001_1001_0110)
+ ) adder (
+ .I0(1'b0),
+ .I1(A),
+ .I2(B),
+ .I3(1'b0),
+ .O(O)
+ );
+endmodule
+EOT
+
+ice40_wrapcarry
+select -assert-count 1 t:$__ICE40_CARRY_WRAPPER
+
+design -reset
+read_verilog <<EOT
+module top(input A, B, CI, output O, CO);
+ (* foo = "bar", answer = 42, keep=0 *)
+ SB_CARRY carry (
+ .I0(A),
+ .I1(B),
+ .CI(CI),
+ .CO(CO)
+ );
+ (* keep, blah="blah", answer = 43 *)
+ SB_LUT4 #(
+ .LUT_INIT(16'b 0110_1001_1001_0110)
+ ) adder (
+ .I0(1'b0),
+ .I1(A),
+ .I2(B),
+ .I3(1'b0),
+ .O(O)
+ );
+endmodule
+EOT
+
+ice40_wrapcarry
+select -assert-count 1 t:$__ICE40_CARRY_WRAPPER
+select -assert-count 0 t:* t:$__ICE40_CARRY_WRAPPER %d
+select -assert-count 1 a:keep=1 a:SB_CARRY.\foo=bar %i a:SB_CARRY.\answer=42 %i a:SB_LUT4.\blah=blah %i a:SB_LUT4.\answer=43 %i
+
+ice40_wrapcarry -unwrap
+select -assert-count 1 c:carry a:src=<<EOT:3 %i a:keep=0 %i a:foo=bar %i a:answer=42 %i
+select -assert-count 1 c:adder a:src=<<EOT:10 %i a:keep=1 %i a:blah=blah %i a:answer=43 %i
diff --git a/tests/arch/ice40/wrapcarry.ys b/tests/arch/ice40/wrapcarry.ys
deleted file mode 100644
index 10c029e68..000000000
--- a/tests/arch/ice40/wrapcarry.ys
+++ /dev/null
@@ -1,22 +0,0 @@
-read_verilog <<EOT
-module top(input A, B, CI, output O, CO);
- SB_CARRY carry (
- .I0(A),
- .I1(B),
- .CI(CI),
- .CO(CO)
- );
- SB_LUT4 #(
- .LUT_INIT(16'b 0110_1001_1001_0110)
- ) adder (
- .I0(1'b0),
- .I1(A),
- .I2(B),
- .I3(1'b0),
- .O(O)
- );
-endmodule
-EOT
-
-ice40_wrapcarry
-select -assert-count 1 t:$__ICE40_CARRY_WRAPPER
diff --git a/tests/arch/xilinx/dsp_fastfir.ys b/tests/arch/xilinx/dsp_fastfir.ys
new file mode 100644
index 000000000..0067a822b
--- /dev/null
+++ b/tests/arch/xilinx/dsp_fastfir.ys
@@ -0,0 +1,69 @@
+read_verilog <<EOT
+// Citation https://github.com/ZipCPU/dspfilters/blob/master/rtl/fastfir.v
+module fastfir_dynamictaps(i_clk, i_reset, i_tap_wr, i_tap, i_ce, i_sample, o_result);
+ wire [30:0] _00_;
+ wire [23:0] _01_;
+ wire [11:0] _02_;
+ wire [30:0] _03_;
+ wire [23:0] _04_;
+ wire [30:0] _05_;
+ wire [23:0] _06_;
+ wire [30:0] _07_;
+ wire [23:0] _08_;
+ wire [11:0] _09_;
+ wire [30:0] _10_;
+ wire [23:0] _11_;
+ wire [30:0] _12_;
+ wire [23:0] _13_;
+ wire [11:0] \fir.FILTER[0].tapk.delayed_sample ;
+ reg [30:0] \fir.FILTER[0].tapk.o_acc = 31'h00000000;
+ wire [11:0] \fir.FILTER[0].tapk.o_sample ;
+ reg [23:0] \fir.FILTER[0].tapk.product ;
+ reg [11:0] \fir.FILTER[0].tapk.tap = 12'h000;
+ wire [11:0] \fir.FILTER[1].tapk.delayed_sample ;
+ wire [30:0] \fir.FILTER[1].tapk.o_acc ;
+ wire [11:0] \fir.FILTER[1].tapk.o_sample ;
+ reg [23:0] \fir.FILTER[1].tapk.product ;
+ reg [11:0] \fir.FILTER[1].tapk.tap = 12'h000;
+ input i_ce;
+ input i_clk;
+ input i_reset;
+ input [11:0] i_sample;
+ input [11:0] i_tap;
+ input i_tap_wr;
+ output [30:0] o_result;
+ reg [30:0] o_result;
+ assign _03_ = 31'h00000000 + { \fir.FILTER[0].tapk.product [23], \fir.FILTER[0].tapk.product [23], \fir.FILTER[0].tapk.product [23], \fir.FILTER[0].tapk.product [23], \fir.FILTER[0].tapk.product [23], \fir.FILTER[0].tapk.product [23], \fir.FILTER[0].tapk.product [23], \fir.FILTER[0].tapk.product };
+ assign _04_ = $signed(\fir.FILTER[0].tapk.tap ) * $signed(i_sample);
+ always @(posedge i_clk)
+ \fir.FILTER[0].tapk.tap <= _02_;
+ always @(posedge i_clk)
+ \fir.FILTER[0].tapk.o_acc <= _00_;
+ always @(posedge i_clk)
+ \fir.FILTER[0].tapk.product <= _01_;
+ assign _02_ = i_tap_wr ? i_tap : \fir.FILTER[0].tapk.tap ;
+ assign _05_ = i_ce ? _03_ : \fir.FILTER[0].tapk.o_acc ;
+ assign _00_ = i_reset ? 31'h00000000 : _05_;
+ assign _06_ = i_ce ? _04_ : \fir.FILTER[0].tapk.product ;
+ assign _01_ = i_reset ? 24'h000000 : _06_;
+ assign _10_ = \fir.FILTER[0].tapk.o_acc + { \fir.FILTER[1].tapk.product [23], \fir.FILTER[1].tapk.product [23], \fir.FILTER[1].tapk.product [23], \fir.FILTER[1].tapk.product [23], \fir.FILTER[1].tapk.product [23], \fir.FILTER[1].tapk.product [23], \fir.FILTER[1].tapk.product [23], \fir.FILTER[1].tapk.product };
+ assign _11_ = $signed(\fir.FILTER[1].tapk.tap ) * $signed(i_sample);
+ always @(posedge i_clk)
+ \fir.FILTER[1].tapk.tap <= _09_;
+ always @(posedge i_clk)
+ o_result <= _07_;
+ always @(posedge i_clk)
+ \fir.FILTER[1].tapk.product <= _08_;
+ assign _09_ = i_tap_wr ? \fir.FILTER[0].tapk.tap : \fir.FILTER[1].tapk.tap ;
+ assign _12_ = i_ce ? _10_ : o_result;
+ assign _07_ = i_reset ? 31'h00000000 : _12_;
+ assign _13_ = i_ce ? _11_ : \fir.FILTER[1].tapk.product ;
+ assign _08_ = i_reset ? 24'h000000 : _13_;
+ assign \fir.FILTER[1].tapk.o_acc = o_result;
+endmodule
+EOT
+
+synth_xilinx
+cd fastfir_dynamictaps
+select -assert-count 2 t:DSP48E1
+select -assert-none t:* t:DSP48E1 %d t:BUFG %d
diff --git a/tests/arch/xilinx/macc.sh b/tests/arch/xilinx/macc.sh
index 2272679ee..154a29848 100644
--- a/tests/arch/xilinx/macc.sh
+++ b/tests/arch/xilinx/macc.sh
@@ -1,3 +1,3 @@
-../../../yosys -qp "synth_xilinx -top macc2; rename -top macc2_uut" macc.v -o macc_uut.v
+../../../yosys -qp "synth_xilinx -top macc2; rename -top macc2_uut" -o macc_uut.v macc.v
iverilog -o test_macc macc_tb.v macc_uut.v macc.v ../../../techlibs/xilinx/cells_sim.v
vvp -N ./test_macc
diff --git a/tests/opt/bug1525.ys b/tests/opt/bug1525.ys
new file mode 100644
index 000000000..972bc0ac7
--- /dev/null
+++ b/tests/opt/bug1525.ys
@@ -0,0 +1,13 @@
+read_verilog << EOF
+module top(...);
+input A1, A2, B, S;
+output O;
+
+assign O = S ? (A1 & B) : (A2 & B);
+
+endmodule
+EOF
+
+simplemap
+opt_share
+dump
diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v
index 64b625efe..de60619d1 100644
--- a/tests/simple_abc9/abc9.v
+++ b/tests/simple_abc9/abc9.v
@@ -218,12 +218,6 @@ module MUXF8(input I0, I1, S, output O);
endmodule
// Citation: https://github.com/alexforencich/verilog-ethernet
-// TODO: yosys -p "synth_xilinx -abc9 -top abc9_test022" abc9.v -q
-// returns before b4321a31
-// Warning: Wire abc9_test022.\m_eth_payload_axis_tkeep [7] is used but has no
-// driver.
-// Warning: Wire abc9_test022.\m_eth_payload_axis_tkeep [3] is used but has no
-// driver.
module abc9_test022
(
input wire clk,
@@ -237,9 +231,6 @@ module abc9_test022
endmodule
// Citation: https://github.com/riscv/riscv-bitmanip
-// TODO: yosys -p "synth_xilinx -abc9 -top abc9_test023" abc9.v -q
-// returns before 14233843
-// Warning: Wire abc9_test023.\dout [1] is used but has no driver.
module abc9_test023 #(
parameter integer N = 2,
parameter integer M = 2
@@ -267,3 +258,9 @@ module abc9_test026(output [3:0] o, p);
assign o = { 1'b1, 1'bx };
assign p = { 1'b1, 1'bx, 1'b0 };
endmodule
+
+module abc9_test030(input [3:0] d, input en, output reg [3:0] q);
+always @*
+ if (en)
+ q <= d;
+endmodule
diff --git a/tests/techmap/iopadmap.ys b/tests/techmap/iopadmap.ys
new file mode 100644
index 000000000..f4345e906
--- /dev/null
+++ b/tests/techmap/iopadmap.ys
@@ -0,0 +1,99 @@
+read_verilog << EOT
+module ibuf ((* iopad_external_pin *) input i, output o); endmodule
+module obuf (input i, (* iopad_external_pin *) output o); endmodule
+module obuft (input i, input oe, (* iopad_external_pin *) output o); endmodule
+module iobuf (input i, input oe, output o, (* iopad_external_pin *) inout io); endmodule
+
+module a(input i, output o);
+assign o = i;
+endmodule
+
+module b(input i, output o);
+assign o = i;
+ibuf b (.i(i), .o(o));
+endmodule
+
+module c(input i, output o);
+obuf b (.i(i), .o(o));
+endmodule
+
+module d(input i, oe, output o, o2, o3);
+assign o = oe ? i : 1'bz;
+assign o2 = o;
+assign o3 = ~o;
+endmodule
+
+module e(input i, oe, inout io, output o2, o3);
+assign io = oe ? i : 1'bz;
+assign o2 = io;
+assign o3 = ~io;
+endmodule
+EOT
+
+opt_clean
+tribuf
+simplemap
+iopadmap -bits -inpad ibuf o:i -outpad obuf i:o -toutpad obuft oe:i:o -tinoutpad iobuf oe:o:i:io
+opt_clean
+
+select -assert-count 1 a/t:ibuf
+select -assert-count 1 a/t:obuf
+select -set ib w:i %a %co a/t:ibuf %i
+select -set ob w:o %a %ci a/t:obuf %i
+select -assert-count 1 @ib
+select -assert-count 1 @ob
+select -assert-count 1 @ib %co %co @ob %i
+
+select -assert-count 1 b/t:ibuf
+select -assert-count 1 b/t:obuf
+select -set ib w:i %a %co b/t:ibuf %i
+select -set ob w:o %a %ci b/t:obuf %i
+select -assert-count 1 @ib
+select -assert-count 1 @ob
+select -assert-count 1 @ib %co %co @ob %i
+
+select -assert-count 1 c/t:ibuf
+select -assert-count 1 c/t:obuf
+select -set ib w:i %a %co c/t:ibuf %i
+select -set ob w:o %a %ci c/t:obuf %i
+select -assert-count 1 @ib
+select -assert-count 1 @ob
+select -assert-count 1 @ib %co %co @ob %i
+
+select -assert-count 2 d/t:ibuf
+select -assert-count 2 d/t:obuf
+select -assert-count 1 d/t:obuft
+select -set ib w:i %a %co d/t:ibuf %i
+select -set oeb w:oe %a %co d/t:ibuf %i
+select -set ob w:o %a %ci d/t:obuft %i
+select -set o2b w:o2 %a %ci d/t:obuf %i
+select -set o3b w:o3 %a %ci d/t:obuf %i
+select -assert-count 1 @ib
+select -assert-count 1 @oeb
+select -assert-count 1 @ob
+select -assert-count 1 @o2b
+select -assert-count 1 @o3b
+select -assert-count 1 @ib %co %co @ob %i
+select -assert-count 1 @oeb %co %co @ob %i
+select -assert-count 1 @ib %co %co @o2b %i
+select -assert-count 1 @ib %co %co t:$_NOT_ %i
+select -assert-count 1 @o3b %ci %ci t:$_NOT_ %i
+
+select -assert-count 2 e/t:ibuf
+select -assert-count 2 e/t:obuf
+select -assert-count 1 e/t:iobuf
+select -set ib w:i %a %co e/t:ibuf %i
+select -set oeb w:oe %a %co e/t:ibuf %i
+select -set iob w:io %a %ci e/t:iobuf %i
+select -set o2b w:o2 %a %ci e/t:obuf %i
+select -set o3b w:o3 %a %ci e/t:obuf %i
+select -assert-count 1 @ib
+select -assert-count 1 @oeb
+select -assert-count 1 @iob
+select -assert-count 1 @o2b
+select -assert-count 1 @o3b
+select -assert-count 1 @ib %co %co @iob %i
+select -assert-count 1 @oeb %co %co @iob %i
+select -assert-count 1 @iob %co %co @o2b %i
+select -assert-count 1 @iob %co %co t:$_NOT_ %i
+select -assert-count 1 @o3b %ci %ci t:$_NOT_ %i