3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-09-15 14:11:29 +00:00

ast: translate $display/$write tasks in always blocks to new $print cell.

This commit is contained in:
whitequark 2020-11-29 14:34:17 +00:00 committed by Marcelina Kościelnicka
parent 9f8e039a4b
commit d5c9953c09
5 changed files with 115 additions and 19 deletions

View file

@ -693,8 +693,80 @@ struct AST_INTERNAL::ProcessGenerator
ast->input_error("Found parameter declaration in block without label!\n");
break;
case AST_NONE:
case AST_TCALL:
if (ast->str == "$display" || ast->str == "$displayb" || ast->str == "$displayh" || ast->str == "$displayo" ||
ast->str == "$write" || ast->str == "$writeb" || ast->str == "$writeh" || ast->str == "$writeo") {
std::stringstream sstr;
sstr << ast->str << "$" << ast->filename << ":" << ast->location.first_line << "$" << (autoidx++);
RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($print));
cell->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", ast->filename.c_str(), ast->location.first_line, ast->location.first_column, ast->location.last_line, ast->location.last_column);
RTLIL::SigSpec triggers;
RTLIL::Const polarity;
for (auto sync : proc->syncs) {
if (sync->type == RTLIL::STp) {
triggers.append(sync->signal);
polarity.bits.push_back(RTLIL::S1);
} else if (sync->type == RTLIL::STn) {
triggers.append(sync->signal);
polarity.bits.push_back(RTLIL::S0);
}
}
cell->parameters[ID::TRG_WIDTH] = triggers.size();
cell->parameters[ID::TRG_ENABLE] = !triggers.empty();
cell->parameters[ID::TRG_POLARITY] = polarity;
cell->setPort(ID::TRG, triggers);
Wire *wire = current_module->addWire(sstr.str() + "_EN", 1);
wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", ast->filename.c_str(), ast->location.first_line, ast->location.first_column, ast->location.last_line, ast->location.last_column);
cell->setPort(ID::EN, wire);
proc->root_case.actions.push_back(SigSig(wire, false));
current_case->actions.push_back(SigSig(wire, true));
int default_base = 10;
if (ast->str.back() == 'b')
default_base = 2;
else if (ast->str.back() == 'o')
default_base = 8;
else if (ast->str.back() == 'h')
default_base = 16;
std::vector<VerilogFmtArg> args;
for (auto node : ast->children) {
int width;
bool is_signed;
node->detectSignWidth(width, is_signed, nullptr);
VerilogFmtArg arg = {};
arg.filename = node->filename;
arg.first_line = node->location.first_line;
if (node->type == AST_CONSTANT && node->is_string) {
arg.type = VerilogFmtArg::STRING;
arg.str = node->bitsAsConst().decode_string();
// and in case this will be used as an argument...
arg.sig = node->bitsAsConst();
arg.signed_ = false;
} else {
arg.type = VerilogFmtArg::INTEGER;
arg.sig = node->genRTLIL();
arg.signed_ = is_signed;
}
args.push_back(arg);
}
Fmt fmt = {};
fmt.parse_verilog(args, /*sformat_like=*/false, default_base, /*task_name=*/ast->str, current_module->name);
if (ast->str.substr(0, 8) == "$display")
fmt.append_string("\n");
fmt.emit_rtlil(cell);
} else if (!ast->str.empty()) {
log_file_error(ast->filename, ast->location.first_line, "Found unsupported invocation of system task `%s'!\n", ast->str.c_str());
}
break;
case AST_NONE:
case AST_FOR:
break;