mirror of
https://github.com/YosysHQ/yosys
synced 2025-06-06 06:03:23 +00:00
Add new $check
cell to represent assertions with a message.
This commit is contained in:
parent
e1a59ba80b
commit
c7bf0e3b8f
12 changed files with 516 additions and 306 deletions
|
@ -1008,7 +1008,7 @@ void dump_cell_expr_binop(std::ostream &f, std::string indent, RTLIL::Cell *cell
|
|||
|
||||
void dump_cell_expr_print(std::ostream &f, std::string indent, const RTLIL::Cell *cell)
|
||||
{
|
||||
Fmt fmt = {};
|
||||
Fmt fmt;
|
||||
fmt.parse_rtlil(cell);
|
||||
std::vector<VerilogFmtArg> args = fmt.emit_verilog();
|
||||
|
||||
|
@ -1041,6 +1041,23 @@ void dump_cell_expr_print(std::ostream &f, std::string indent, const RTLIL::Cell
|
|||
f << stringf(");\n");
|
||||
}
|
||||
|
||||
void dump_cell_expr_check(std::ostream &f, std::string indent, const RTLIL::Cell *cell)
|
||||
{
|
||||
std::string flavor = cell->getParam(ID(FLAVOR)).decode_string();
|
||||
if (flavor == "assert")
|
||||
f << stringf("%s" "assert (", indent.c_str());
|
||||
else if (flavor == "assume")
|
||||
f << stringf("%s" "assume (", indent.c_str());
|
||||
else if (flavor == "live")
|
||||
f << stringf("%s" "assert (eventually ", indent.c_str());
|
||||
else if (flavor == "fair")
|
||||
f << stringf("%s" "assume (eventually ", indent.c_str());
|
||||
else if (flavor == "cover")
|
||||
f << stringf("%s" "cover (", indent.c_str());
|
||||
dump_sigspec(f, cell->getPort(ID::A));
|
||||
f << stringf(");\n");
|
||||
}
|
||||
|
||||
bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
|
||||
{
|
||||
if (cell->type == ID($_NOT_)) {
|
||||
|
@ -1814,6 +1831,39 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
|
|||
return true;
|
||||
}
|
||||
|
||||
if (cell->type == ID($check))
|
||||
{
|
||||
// Sync $check cells are accumulated and handled in dump_module.
|
||||
if (cell->getParam(ID::TRG_ENABLE).as_bool())
|
||||
return true;
|
||||
|
||||
f << stringf("%s" "always @*\n", indent.c_str());
|
||||
|
||||
f << stringf("%s" " if (", indent.c_str());
|
||||
dump_sigspec(f, cell->getPort(ID::EN));
|
||||
f << stringf(") begin\n");
|
||||
|
||||
std::string flavor = cell->getParam(ID::FLAVOR).decode_string();
|
||||
if (flavor == "assert" || flavor == "assume") {
|
||||
Fmt fmt;
|
||||
fmt.parse_rtlil(cell);
|
||||
if (!fmt.parts.empty()) {
|
||||
f << stringf("%s" " if (!", indent.c_str());
|
||||
dump_sigspec(f, cell->getPort(ID::A));
|
||||
f << stringf(")\n");
|
||||
dump_cell_expr_print(f, indent + " ", cell);
|
||||
}
|
||||
} else {
|
||||
f << stringf("%s" " /* message omitted */\n", indent.c_str());
|
||||
}
|
||||
|
||||
dump_cell_expr_check(f, indent + " ", cell);
|
||||
|
||||
f << stringf("%s" " end\n", indent.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// FIXME: $fsm
|
||||
|
||||
return false;
|
||||
|
@ -1903,7 +1953,7 @@ 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<const RTLIL::Cell*> &cells)
|
||||
void dump_sync_effect(std::ostream &f, std::string indent, const RTLIL::SigSpec &trg, const RTLIL::Const &polarity, std::vector<const RTLIL::Cell*> &cells)
|
||||
{
|
||||
if (trg.size() == 0) {
|
||||
f << stringf("%s" "initial begin\n", indent.c_str());
|
||||
|
@ -1927,9 +1977,29 @@ void dump_sync_print(std::ostream &f, std::string indent, const RTLIL::SigSpec &
|
|||
for (auto cell : cells) {
|
||||
f << stringf("%s" " if (", indent.c_str());
|
||||
dump_sigspec(f, cell->getPort(ID::EN));
|
||||
f << stringf(")\n");
|
||||
f << stringf(") begin\n");
|
||||
|
||||
dump_cell_expr_print(f, indent + " ", cell);
|
||||
if (cell->type == ID($print)) {
|
||||
dump_cell_expr_print(f, indent + " ", cell);
|
||||
} else if (cell->type == ID($check)) {
|
||||
std::string flavor = cell->getParam(ID::FLAVOR).decode_string();
|
||||
if (flavor == "assert" || flavor == "assume") {
|
||||
Fmt fmt;
|
||||
fmt.parse_rtlil(cell);
|
||||
if (!fmt.parts.empty()) {
|
||||
f << stringf("%s" " if (!", indent.c_str());
|
||||
dump_sigspec(f, cell->getPort(ID::A));
|
||||
f << stringf(")\n");
|
||||
dump_cell_expr_print(f, indent + " ", cell);
|
||||
}
|
||||
} else {
|
||||
f << stringf("%s" " /* message omitted */\n", indent.c_str());
|
||||
}
|
||||
|
||||
dump_cell_expr_check(f, indent + " ", cell);
|
||||
}
|
||||
|
||||
f << stringf("%s" " end\n", indent.c_str());
|
||||
}
|
||||
|
||||
f << stringf("%s" "end\n", indent.c_str());
|
||||
|
@ -2182,7 +2252,7 @@ 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<const RTLIL::Cell*>> sync_print_cells;
|
||||
std::map<std::pair<RTLIL::SigSpec, RTLIL::Const>, std::vector<const RTLIL::Cell*>> sync_effect_cells;
|
||||
|
||||
reg_wires.clear();
|
||||
reset_auto_counter(module);
|
||||
|
@ -2214,8 +2284,8 @@ 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);
|
||||
if (cell->type.in(ID($print), ID($check)) && cell->getParam(ID::TRG_ENABLE).as_bool()) {
|
||||
sync_effect_cells[make_pair(cell->getPort(ID::TRG), cell->getParam(ID::TRG_POLARITY))].push_back(cell);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2274,8 +2344,8 @@ 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 : sync_effect_cells)
|
||||
dump_sync_effect(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