Fix FIRRTL to Verilog process instance subfield assignment.

Don't emit subfield assignments: bits(x, y, z) <= ... - but instead, add them to the reverse-wire-map where they'll be treated at the end of the module.
Enable tests which were disabled due to incorrect treatment of subfields.
Assume the `$firrtl2verilog` variable contains any additional switches to control verilog generation (i.e. `--no-dedup -X mverilog`)
This commit is contained in:
Jim Lawson 2019-02-25 16:18:13 -08:00
parent c258b99040
commit 171c425cf9
4 changed files with 21 additions and 11 deletions

View File

@ -169,7 +169,6 @@ struct FirrtlWorker
return *str == '\\' ? str + 1 : str; return *str == '\\' ? str + 1 : str;
} }
std::string cellname(RTLIL::Cell *cell) std::string cellname(RTLIL::Cell *cell)
{ {
return fid(cell->name).c_str(); return fid(cell->name).c_str();
@ -219,29 +218,42 @@ struct FirrtlWorker
if (it->second.size() > 0) { if (it->second.size() > 0) {
const SigSpec &secondSig = it->second; const SigSpec &secondSig = it->second;
const std::string firstName = cell_name + "." + make_id(it->first); const std::string firstName = cell_name + "." + make_id(it->first);
const std::string secondName = make_expr(secondSig); const std::string secondExpr = make_expr(secondSig);
// Find the direction for this port. // Find the direction for this port.
FDirection dir = getPortFDirection(it->first, instModule); FDirection dir = getPortFDirection(it->first, instModule);
std::string source, sink; std::string sourceExpr, sinkExpr;
const SigSpec *sinkSig = nullptr;
switch (dir) { switch (dir) {
case FD_INOUT: case FD_INOUT:
log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", cell_type.c_str(), log_signal(it->second)); log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", cell_type.c_str(), log_signal(it->second));
case FD_OUT: case FD_OUT:
source = firstName; sourceExpr = firstName;
sink = secondName; sinkExpr = secondExpr;
sinkSig = &secondSig;
break; break;
case FD_NODIRECTION: case FD_NODIRECTION:
log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", cell_type.c_str(), log_signal(it->second)); log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", cell_type.c_str(), log_signal(it->second));
/* FALL_THROUGH */ /* FALL_THROUGH */
case FD_IN: case FD_IN:
source = secondName; sourceExpr = secondExpr;
sink = firstName; sinkExpr = firstName;
break; break;
default: default:
log_error("Instance port %s.%s unrecognized connection direction 0x%x !\n", cell_type.c_str(), log_signal(it->second), dir); log_error("Instance port %s.%s unrecognized connection direction 0x%x !\n", cell_type.c_str(), log_signal(it->second), dir);
break; break;
} }
wire_exprs.push_back(stringf("\n%s%s <= %s", indent.c_str(), sink.c_str(), source.c_str())); // Check for subfield assignment.
std::string bitsString = "bits(";
if (sinkExpr.substr(0, bitsString.length()) == bitsString ) {
if (sinkSig == nullptr)
log_error("Unknown subfield %s.%s\n", cell_type.c_str(), sinkExpr.c_str());
// Don't generate the assignment here.
// Add the source and sink to the "reverse_wire_map" and we'll output the assignment
// as part of the coalesced subfield assignments for this wire.
register_reverse_wire_map(sourceExpr, *sinkSig);
} else {
wire_exprs.push_back(stringf("\n%s%s <= %s", indent.c_str(), sinkExpr.c_str(), sourceExpr.c_str()));
}
} }
} }
wire_exprs.push_back(stringf("\n")); wire_exprs.push_back(stringf("\n"));

View File

@ -6,7 +6,6 @@ code_hdl_models_d_latch_gates.v combinational loop
code_hdl_models_dff_async_reset.v $adff code_hdl_models_dff_async_reset.v $adff
code_hdl_models_tff_async_reset.v $adff code_hdl_models_tff_async_reset.v $adff
code_hdl_models_uart.v $adff code_hdl_models_uart.v $adff
code_specman_switch_fabric.v subfield assignment (bits() <= ...)
code_tidbits_asyn_reset.v $adff code_tidbits_asyn_reset.v $adff
code_tidbits_reg_seq_example.v $adff code_tidbits_reg_seq_example.v $adff
code_verilog_tutorial_always_example.v empty module code_verilog_tutorial_always_example.v empty module

View File

@ -12,7 +12,6 @@ multiplier.v inst id[0] of
muxtree.v drops modules muxtree.v drops modules
omsp_dbg_uart.v $adff omsp_dbg_uart.v $adff
operators.v $pow operators.v $pow
paramods.v subfield assignment (bits() <= ...)
partsel.v drops modules partsel.v drops modules
process.v drops modules process.v drops modules
realexpr.v drops modules realexpr.v drops modules

View File

@ -175,7 +175,7 @@ do
if [ -n "$firrtl2verilog" ]; then if [ -n "$firrtl2verilog" ]; then
if test -z "$xfirrtl" || ! grep "$fn" "$xfirrtl" ; then if test -z "$xfirrtl" || ! grep "$fn" "$xfirrtl" ; then
"$toolsdir"/../../yosys -b "firrtl" -o ${bn}_ref.fir -f "$frontend $include_opts" -p "prep -nordff; proc; opt; memory; opt; fsm; opt -full -fine; pmuxtree" ${bn}_ref.v "$toolsdir"/../../yosys -b "firrtl" -o ${bn}_ref.fir -f "$frontend $include_opts" -p "prep -nordff; proc; opt; memory; opt; fsm; opt -full -fine; pmuxtree" ${bn}_ref.v
$firrtl2verilog -i ${bn}_ref.fir -o ${bn}_ref.fir.v -X verilog $firrtl2verilog -i ${bn}_ref.fir -o ${bn}_ref.fir.v
test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.fir.v test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.fir.v
fi fi
fi fi