mirror of https://github.com/YosysHQ/yosys.git
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:
parent
9534b51277
commit
711df56ad0
|
@ -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))) {
|
||||||
|
|
Loading…
Reference in New Issue