Merge remote-tracking branch 'origin/master' into xaig_dff

This commit is contained in:
Eddie Hung 2019-12-06 23:22:52 -08:00
commit a46a7e8a67
19 changed files with 1771 additions and 969 deletions

View File

@ -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;
} |

View File

@ -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 {

View File

@ -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;
}

View File

@ -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},

View File

@ -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);

View File

@ -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;

View File

@ -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
// 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
// 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
// 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
// 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
// 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 \$_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
// 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
// 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
// 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
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
// 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
// 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
// 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
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
// 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
// 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
// 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
// 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
// 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
// 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
// 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
// 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
// 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
// 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
// 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
// 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
// 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
// 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
// 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
// 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
// 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
// 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
// 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
// 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
// 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
// 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 #(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 #(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 #(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 #(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;
parameter WIDTH = 0;
parameter LUT = 0;
input [WIDTH-1:0] A;
output Y;
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
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

View File

@ -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");
}

View File

@ -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

View File

@ -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 *)

View File

@ -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.

View File

@ -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";

View File

@ -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");

View File

@ -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

224
tests/arch/gowin/init.v Normal file
View File

@ -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)

74
tests/arch/gowin/init.ys Normal file
View File

@ -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

View File

@ -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

View File

@ -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

99
tests/techmap/iopadmap.ys Normal file
View File

@ -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