mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-24 01:25:33 +00:00
verilog_backend: emit sync $print
cells with same triggers together
Sort by PRIORITY, ensuring output order.
This commit is contained in:
parent
f9d38253c5
commit
04582f2fb7
5 changed files with 297 additions and 274 deletions
|
@ -1006,6 +1006,41 @@ void dump_cell_expr_binop(std::ostream &f, std::string indent, RTLIL::Cell *cell
|
|||
f << stringf(";\n");
|
||||
}
|
||||
|
||||
void dump_cell_expr_print(std::ostream &f, std::string indent, RTLIL::Cell *cell)
|
||||
{
|
||||
Fmt fmt = {};
|
||||
fmt.parse_rtlil(cell);
|
||||
std::vector<VerilogFmtArg> args = fmt.emit_verilog();
|
||||
|
||||
f << stringf("%s" "$write(", indent.c_str());
|
||||
bool first = true;
|
||||
for (auto &arg : args) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
f << ", ";
|
||||
}
|
||||
switch (arg.type) {
|
||||
case VerilogFmtArg::STRING:
|
||||
dump_const(f, RTLIL::Const(arg.str));
|
||||
break;
|
||||
case VerilogFmtArg::INTEGER:
|
||||
f << (arg.signed_ ? "$signed(" : "$unsigned(");
|
||||
dump_sigspec(f, arg.sig);
|
||||
f << ")";
|
||||
break;
|
||||
case VerilogFmtArg::TIME:
|
||||
if (arg.realtime)
|
||||
f << "$realtime";
|
||||
else
|
||||
f << "$time";
|
||||
break;
|
||||
default: log_abort();
|
||||
}
|
||||
}
|
||||
f << stringf(");\n");
|
||||
}
|
||||
|
||||
bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
|
||||
{
|
||||
if (cell->type == ID($_NOT_)) {
|
||||
|
@ -1756,58 +1791,17 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
|
|||
|
||||
if (cell->type == ID($print))
|
||||
{
|
||||
Fmt fmt = {};
|
||||
fmt.parse_rtlil(cell);
|
||||
std::vector<VerilogFmtArg> args = fmt.emit_verilog();
|
||||
// Sync $print cells are accumulated and handled in dump_module.
|
||||
if (cell->getParam(ID::TRG_ENABLE).as_bool())
|
||||
return true;
|
||||
|
||||
if (cell->getParam(ID::TRG_ENABLE).as_bool()) {
|
||||
f << stringf("%s" "always @(", indent.c_str());
|
||||
for (size_t i = 0; i < (size_t)cell->getParam(ID::TRG_WIDTH).as_int(); i++) {
|
||||
if (i != 0)
|
||||
f << " or ";
|
||||
if (cell->getParam(ID::TRG_POLARITY)[i])
|
||||
f << "posedge ";
|
||||
else
|
||||
f << "negedge ";
|
||||
dump_sigspec(f, cell->getPort(ID::TRG)[i]);
|
||||
}
|
||||
f << ")\n";
|
||||
} else {
|
||||
f << stringf("%s" "always @*\n", indent.c_str());
|
||||
}
|
||||
f << stringf("%s" "always @*\n", indent.c_str());
|
||||
|
||||
f << stringf("%s" " if (", indent.c_str());
|
||||
dump_sigspec(f, cell->getPort(ID::EN));
|
||||
f << stringf(")\n");
|
||||
|
||||
f << stringf("%s" " $write(", indent.c_str());
|
||||
bool first = true;
|
||||
for (auto &arg : args) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
f << ", ";
|
||||
}
|
||||
switch (arg.type) {
|
||||
case VerilogFmtArg::STRING:
|
||||
dump_const(f, RTLIL::Const(arg.str));
|
||||
break;
|
||||
case VerilogFmtArg::INTEGER:
|
||||
f << (arg.signed_ ? "$signed(" : "$unsigned(");
|
||||
dump_sigspec(f, arg.sig);
|
||||
f << ")";
|
||||
break;
|
||||
case VerilogFmtArg::TIME:
|
||||
if (arg.realtime)
|
||||
f << "$realtime";
|
||||
else
|
||||
f << "$time";
|
||||
break;
|
||||
default: log_abort();
|
||||
}
|
||||
}
|
||||
f << stringf(");\n");
|
||||
|
||||
dump_cell_expr_print(f, indent + " ", cell);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1899,6 +1893,34 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell)
|
|||
}
|
||||
}
|
||||
|
||||
void dump_sync_print(std::ostream &f, std::string indent, const RTLIL::SigSpec &trg, const RTLIL::Const &polarity, std::vector<RTLIL::Cell*> &cells)
|
||||
{
|
||||
f << stringf("%s" "always @(", indent.c_str());
|
||||
for (int i = 0; i < trg.size(); i++) {
|
||||
if (i != 0)
|
||||
f << " or ";
|
||||
if (polarity[i])
|
||||
f << "posedge ";
|
||||
else
|
||||
f << "negedge ";
|
||||
dump_sigspec(f, trg[i]);
|
||||
}
|
||||
f << ") begin\n";
|
||||
|
||||
std::sort(cells.begin(), cells.end(), [](const RTLIL::Cell *a, const RTLIL::Cell *b) {
|
||||
return a->getParam(ID::PRIORITY).as_int() > b->getParam(ID::PRIORITY).as_int();
|
||||
});
|
||||
for (auto cell : cells) {
|
||||
f << stringf("%s" " if (", indent.c_str());
|
||||
dump_sigspec(f, cell->getPort(ID::EN));
|
||||
f << stringf(")\n");
|
||||
|
||||
dump_cell_expr_print(f, indent + " ", cell);
|
||||
}
|
||||
|
||||
f << stringf("%s" "end\n", indent.c_str());
|
||||
}
|
||||
|
||||
void dump_conn(std::ostream &f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
|
||||
{
|
||||
if (simple_lhs) {
|
||||
|
@ -2080,6 +2102,8 @@ void dump_process(std::ostream &f, std::string indent, RTLIL::Process *proc, boo
|
|||
|
||||
void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
|
||||
{
|
||||
std::map<std::pair<RTLIL::SigSpec, RTLIL::Const>, std::vector<RTLIL::Cell*>> sync_print_cells;
|
||||
|
||||
reg_wires.clear();
|
||||
reset_auto_counter(module);
|
||||
active_module = module;
|
||||
|
@ -2110,6 +2134,11 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
|
|||
std::set<std::pair<RTLIL::Wire*,int>> reg_bits;
|
||||
for (auto cell : module->cells())
|
||||
{
|
||||
if (cell->type == ID($print) && cell->getParam(ID::TRG_ENABLE).as_bool()) {
|
||||
sync_print_cells[make_pair(cell->getPort(ID::TRG), cell->getParam(ID::TRG_POLARITY))].push_back(cell);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!RTLIL::builtin_ff_cell_types().count(cell->type) || !cell->hasPort(ID::Q) || cell->type.in(ID($ff), ID($_FF_)))
|
||||
continue;
|
||||
|
||||
|
@ -2165,6 +2194,9 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
|
|||
for (auto cell : module->cells())
|
||||
dump_cell(f, indent + " ", cell);
|
||||
|
||||
for (auto &it : sync_print_cells)
|
||||
dump_sync_print(f, indent + " ", it.first.first, it.first.second, it.second);
|
||||
|
||||
for (auto it = module->processes.begin(); it != module->processes.end(); ++it)
|
||||
dump_process(f, indent + " ", it->second);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue