diff options
-rw-r--r-- | frontends/ilang/ilang_parser.y | 4 | ||||
-rw-r--r-- | frontends/verilog/verilog_parser.y | 10 | ||||
-rw-r--r-- | kernel/rtlil.cc | 24 | ||||
-rw-r--r-- | manual/CHAPTER_CellLib.tex | 91 | ||||
-rw-r--r-- | passes/techmap/abc9.cc | 69 | ||||
-rw-r--r-- | passes/techmap/iopadmap.cc | 243 | ||||
-rw-r--r-- | techlibs/gowin/cells_map.v | 365 | ||||
-rw-r--r-- | techlibs/gowin/synth_gowin.cc | 17 | ||||
-rw-r--r-- | techlibs/xilinx/cells_map.v | 8 | ||||
-rw-r--r-- | techlibs/xilinx/cells_sim.v | 797 | ||||
-rw-r--r-- | techlibs/xilinx/cells_xtra.py | 69 | ||||
-rw-r--r-- | techlibs/xilinx/cells_xtra.v | 610 | ||||
-rw-r--r-- | techlibs/xilinx/synth_xilinx.cc | 17 | ||||
-rw-r--r-- | tests/arch/gowin/adffs.ys | 5 | ||||
-rw-r--r-- | tests/arch/gowin/init.v | 224 | ||||
-rw-r--r-- | tests/arch/gowin/init.ys | 74 | ||||
-rw-r--r-- | tests/arch/xilinx/macc.sh | 2 | ||||
-rw-r--r-- | tests/simple_abc9/abc9.v | 16 | ||||
-rw-r--r-- | tests/techmap/iopadmap.ys | 99 |
19 files changed, 1773 insertions, 971 deletions
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/techmap/abc9.cc b/passes/techmap/abc9.cc index 6b8936958..8f2d45b62 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -89,20 +89,30 @@ void handle_loops(RTLIL::Design *design, RTLIL::Module *module) 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); } } } @@ -354,24 +364,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip design->remove(design->module(ID($__abc9__))); #endif - // 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()) { @@ -705,6 +697,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/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/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 2fda3b8fd..ef963793c 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -479,6 +479,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 *) @@ -502,6 +969,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 *) @@ -525,6 +1015,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 *) @@ -545,6 +1058,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 30be9832c..de262c8ad 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"; @@ -306,6 +307,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"); @@ -504,6 +507,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); @@ -560,15 +566,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')"); run("clean"); 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/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/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v index 961e7605e..8afd0ce96 100644 --- a/tests/simple_abc9/abc9.v +++ b/tests/simple_abc9/abc9.v @@ -259,29 +259,35 @@ assign o = { 1'b1, 1'bx }; assign p = { 1'b1, 1'bx, 1'b0 }; endmodule -module abc9_test029(input clk1, clk2, d, output reg q1, q2); +module abc9_test030(input [3:0] d, input en, output reg [3:0] q); +always @* + if (en) + q <= d; +endmodule + +module abc9_test031(input clk1, clk2, d, output reg q1, q2); always @(posedge clk1) q1 <= d; always @(negedge clk2) q2 <= q1; endmodule -module abc9_test030(input clk, d, r, output reg q); +module abc9_test032(input clk, d, r, output reg q); always @(posedge clk or posedge r) if (r) q <= 1'b0; else q <= d; endmodule -module abc9_test031(input clk, d, r, output reg q); +module abc9_test033(input clk, d, r, output reg q); always @(negedge clk or posedge r) if (r) q <= 1'b1; else q <= d; endmodule -module abc9_test033(input clk, d, output reg q1, q2); +module abc9_test034(input clk, d, output reg q1, q2); always @(posedge clk) q1 <= d; always @(posedge clk) q2 <= q1; endmodule -module abc9_test034(input clk, d, output reg [1:0] q); +module abc9_test035(input clk, d, output reg [1:0] q); always @(posedge clk) q[0] <= d; always @(negedge clk) q[1] <= q[0]; 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 |