write_cxxrtl: add support for $sr cell.

Also, fix the semantics of SET/CLR inputs of the $dffsr cell, and
fix the scheduling of async FF cells to consider ARST/SET/CLR->Q
as a forward combinatorial arc.
This commit is contained in:
whitequark 2020-04-05 09:13:13 +00:00
parent 9534b51277
commit 711df56ad0
1 changed files with 35 additions and 27 deletions

View File

@ -193,10 +193,16 @@ static bool is_elidable_cell(RTLIL::IdString type)
ID($mux), ID($concat), ID($slice)); ID($mux), ID($concat), ID($slice));
} }
static bool is_ff_cell(RTLIL::IdString type) static bool is_sync_ff_cell(RTLIL::IdString type)
{ {
return type.in( return type.in(
ID($dff), ID($dffe), ID($adff), ID($dffsr)); ID($dff), ID($dffe));
}
static bool is_ff_cell(RTLIL::IdString type)
{
return is_sync_ff_cell(type) || type.in(
ID($adff), ID($dffsr), ID($sr));
} }
static bool is_internal_cell(RTLIL::IdString type) static bool is_internal_cell(RTLIL::IdString type)
@ -282,7 +288,7 @@ struct FlowGraph {
log_assert(cell->known()); log_assert(cell->known());
for (auto conn : cell->connections()) { for (auto conn : cell->connections()) {
if (cell->output(conn.first)) { if (cell->output(conn.first)) {
if (is_ff_cell(cell->type) || (cell->type == ID($memrd) && cell->getParam(ID(CLK_ENABLE)).as_bool())) if (is_sync_ff_cell(cell->type) || (cell->type == ID($memrd) && cell->getParam(ID(CLK_ENABLE)).as_bool()))
/* non-combinatorial outputs do not introduce defs */; /* non-combinatorial outputs do not introduce defs */;
else if (is_elidable_cell(cell->type)) else if (is_elidable_cell(cell->type))
add_defs(node, conn.second, /*elidable=*/true); add_defs(node, conn.second, /*elidable=*/true);
@ -770,7 +776,7 @@ struct CxxrtlWorker {
f << indent << "}\n"; f << indent << "}\n";
// Flip-flops // Flip-flops
} else if (is_ff_cell(cell->type)) { } else if (is_ff_cell(cell->type)) {
if (cell->getPort(ID(CLK)).is_wire()) { if (cell->hasPort(ID(CLK)) && cell->getPort(ID(CLK)).is_wire()) {
// Edge-sensitive logic // Edge-sensitive logic
RTLIL::SigBit clk_bit = cell->getPort(ID(CLK))[0]; RTLIL::SigBit clk_bit = cell->getPort(ID(CLK))[0];
clk_bit = sigmaps[clk_bit.wire->module](clk_bit); clk_bit = sigmaps[clk_bit.wire->module](clk_bit);
@ -795,8 +801,8 @@ struct CxxrtlWorker {
dec_indent(); dec_indent();
f << indent << "}\n"; f << indent << "}\n";
} }
// Level-sensitive logic if (cell->hasPort(ID(ARST))) {
if (cell->type == ID($adff)) { // Asynchronous reset (entire coarse cell at once)
f << indent << "if ("; f << indent << "if (";
dump_sigspec_rhs(cell->getPort(ID(ARST))); dump_sigspec_rhs(cell->getPort(ID(ARST)));
f << " == value<1> {" << cell->getParam(ID(ARST_POLARITY)).as_bool() << "}) {\n"; f << " == value<1> {" << cell->getParam(ID(ARST_POLARITY)).as_bool() << "}) {\n";
@ -808,28 +814,30 @@ struct CxxrtlWorker {
f << ";\n"; f << ";\n";
dec_indent(); dec_indent();
f << indent << "}\n"; f << indent << "}\n";
} else if (cell->type == ID($dffsr)) { }
f << indent << "if ("; if (cell->hasPort(ID(SET))) {
dump_sigspec_rhs(cell->getPort(ID(CLR))); // Asynchronous set (for individual bits)
f << " == value<1> {" << cell->getParam(ID(CLR_POLARITY)).as_bool() << "}) {\n"; f << indent;
inc_indent(); dump_sigspec_lhs(cell->getPort(ID(Q)));
f << indent; f << " = ";
dump_sigspec_lhs(cell->getPort(ID(Q))); dump_sigspec_lhs(cell->getPort(ID(Q)));
f << " = "; f << ".update(";
dump_const(RTLIL::Const(RTLIL::S0, cell->getParam(ID(WIDTH)).as_int())); dump_const(RTLIL::Const(RTLIL::S1, cell->getParam(ID(WIDTH)).as_int()));
f << ";\n"; f << ", ";
dec_indent();
f << indent << "} else if (";
dump_sigspec_rhs(cell->getPort(ID(SET))); dump_sigspec_rhs(cell->getPort(ID(SET)));
f << " == value<1> {" << cell->getParam(ID(SET_POLARITY)).as_bool() << "}) {\n"; f << (cell->getParam(ID(SET_POLARITY)).as_bool() ? "" : ".bit_not()") << ");\n";
inc_indent(); }
f << indent; if (cell->hasPort(ID(CLR))) {
dump_sigspec_lhs(cell->getPort(ID(Q))); // Asynchronous clear (for individual bits; priority over set)
f << " = "; f << indent;
dump_const(RTLIL::Const(RTLIL::S1, cell->getParam(ID(WIDTH)).as_int())); dump_sigspec_lhs(cell->getPort(ID(Q)));
f << ";\n"; f << " = ";
dec_indent(); dump_sigspec_lhs(cell->getPort(ID(Q)));
f << indent << "}\n"; f << ".update(";
dump_const(RTLIL::Const(RTLIL::S0, cell->getParam(ID(WIDTH)).as_int()));
f << ", ";
dump_sigspec_rhs(cell->getPort(ID(CLR)));
f << (cell->getParam(ID(CLR_POLARITY)).as_bool() ? "" : ".bit_not()") << ");\n";
} }
// Memory ports // Memory ports
} else if (cell->type.in(ID($memrd), ID($memwr))) { } else if (cell->type.in(ID($memrd), ID($memwr))) {