diff options
author | Jim Lawson <ucbjrl@berkeley.edu> | 2019-02-25 16:18:13 -0800 |
---|---|---|
committer | Jim Lawson <ucbjrl@berkeley.edu> | 2019-02-25 16:18:13 -0800 |
commit | 171c425cf9addb61ef3f03596fd26355ed8af76d (patch) | |
tree | e620f9838187ab70fd65b5d6554c3b9252777fd8 /backends | |
parent | c258b99040c8414952a3aceae874dc47563540dc (diff) | |
download | yosys-171c425cf9addb61ef3f03596fd26355ed8af76d.tar.gz yosys-171c425cf9addb61ef3f03596fd26355ed8af76d.tar.bz2 yosys-171c425cf9addb61ef3f03596fd26355ed8af76d.zip |
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`)
Diffstat (limited to 'backends')
-rw-r--r-- | backends/firrtl/firrtl.cc | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 0917ecba6..88c1038b7 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -169,7 +169,6 @@ struct FirrtlWorker return *str == '\\' ? str + 1 : str; } - std::string cellname(RTLIL::Cell *cell) { return fid(cell->name).c_str(); @@ -219,29 +218,42 @@ struct FirrtlWorker if (it->second.size() > 0) { const SigSpec &secondSig = it->second; 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. FDirection dir = getPortFDirection(it->first, instModule); - std::string source, sink; + std::string sourceExpr, sinkExpr; + const SigSpec *sinkSig = nullptr; switch (dir) { case FD_INOUT: log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", cell_type.c_str(), log_signal(it->second)); case FD_OUT: - source = firstName; - sink = secondName; + sourceExpr = firstName; + sinkExpr = secondExpr; + sinkSig = &secondSig; break; case FD_NODIRECTION: log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", cell_type.c_str(), log_signal(it->second)); /* FALL_THROUGH */ case FD_IN: - source = secondName; - sink = firstName; + sourceExpr = secondExpr; + sinkExpr = firstName; break; default: log_error("Instance port %s.%s unrecognized connection direction 0x%x !\n", cell_type.c_str(), log_signal(it->second), dir); 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")); |