aboutsummaryrefslogtreecommitdiffstats
path: root/backends/cxxrtl
diff options
context:
space:
mode:
authorwhitequark <whitequark@whitequark.org>2020-04-05 09:13:13 +0000
committerwhitequark <whitequark@whitequark.org>2020-04-09 04:08:36 +0000
commit711df56ad0174f5f437bcdb1939bc0153e2d051e (patch)
tree1619478f5c55250ba305bce97f2c342af00bc7cc /backends/cxxrtl
parent9534b512770063baa48d862a375ec7a924766866 (diff)
downloadyosys-711df56ad0174f5f437bcdb1939bc0153e2d051e.tar.gz
yosys-711df56ad0174f5f437bcdb1939bc0153e2d051e.tar.bz2
yosys-711df56ad0174f5f437bcdb1939bc0153e2d051e.zip
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.
Diffstat (limited to 'backends/cxxrtl')
-rw-r--r--backends/cxxrtl/cxxrtl.cc62
1 files changed, 35 insertions, 27 deletions
diff --git a/backends/cxxrtl/cxxrtl.cc b/backends/cxxrtl/cxxrtl.cc
index e2c33c3d7..49b9e2ddf 100644
--- a/backends/cxxrtl/cxxrtl.cc
+++ b/backends/cxxrtl/cxxrtl.cc
@@ -193,10 +193,16 @@ static bool is_elidable_cell(RTLIL::IdString type)
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(
- 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)
@@ -282,7 +288,7 @@ struct FlowGraph {
log_assert(cell->known());
for (auto conn : cell->connections()) {
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 */;
else if (is_elidable_cell(cell->type))
add_defs(node, conn.second, /*elidable=*/true);
@@ -770,7 +776,7 @@ struct CxxrtlWorker {
f << indent << "}\n";
// Flip-flops
} 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
RTLIL::SigBit clk_bit = cell->getPort(ID(CLK))[0];
clk_bit = sigmaps[clk_bit.wire->module](clk_bit);
@@ -795,8 +801,8 @@ struct CxxrtlWorker {
dec_indent();
f << indent << "}\n";
}
- // Level-sensitive logic
- if (cell->type == ID($adff)) {
+ if (cell->hasPort(ID(ARST))) {
+ // Asynchronous reset (entire coarse cell at once)
f << indent << "if (";
dump_sigspec_rhs(cell->getPort(ID(ARST)));
f << " == value<1> {" << cell->getParam(ID(ARST_POLARITY)).as_bool() << "}) {\n";
@@ -808,28 +814,30 @@ struct CxxrtlWorker {
f << ";\n";
dec_indent();
f << indent << "}\n";
- } else if (cell->type == ID($dffsr)) {
- f << indent << "if (";
- dump_sigspec_rhs(cell->getPort(ID(CLR)));
- f << " == value<1> {" << cell->getParam(ID(CLR_POLARITY)).as_bool() << "}) {\n";
- inc_indent();
- f << indent;
- dump_sigspec_lhs(cell->getPort(ID(Q)));
- f << " = ";
- dump_const(RTLIL::Const(RTLIL::S0, cell->getParam(ID(WIDTH)).as_int()));
- f << ";\n";
- dec_indent();
- f << indent << "} else if (";
+ }
+ if (cell->hasPort(ID(SET))) {
+ // Asynchronous set (for individual bits)
+ f << indent;
+ dump_sigspec_lhs(cell->getPort(ID(Q)));
+ f << " = ";
+ dump_sigspec_lhs(cell->getPort(ID(Q)));
+ f << ".update(";
+ dump_const(RTLIL::Const(RTLIL::S1, cell->getParam(ID(WIDTH)).as_int()));
+ f << ", ";
dump_sigspec_rhs(cell->getPort(ID(SET)));
- f << " == value<1> {" << cell->getParam(ID(SET_POLARITY)).as_bool() << "}) {\n";
- inc_indent();
- f << indent;
- dump_sigspec_lhs(cell->getPort(ID(Q)));
- f << " = ";
- dump_const(RTLIL::Const(RTLIL::S1, cell->getParam(ID(WIDTH)).as_int()));
- f << ";\n";
- dec_indent();
- f << indent << "}\n";
+ f << (cell->getParam(ID(SET_POLARITY)).as_bool() ? "" : ".bit_not()") << ");\n";
+ }
+ if (cell->hasPort(ID(CLR))) {
+ // Asynchronous clear (for individual bits; priority over set)
+ f << indent;
+ dump_sigspec_lhs(cell->getPort(ID(Q)));
+ f << " = ";
+ dump_sigspec_lhs(cell->getPort(ID(Q)));
+ 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
} else if (cell->type.in(ID($memrd), ID($memwr))) {