Fix FIRRTL to Verilog process instance subfield assignment.
authorJim Lawson <ucbjrl@berkeley.edu>
Tue, 26 Feb 2019 00:18:13 +0000 (16:18 -0800)
committerJim Lawson <ucbjrl@berkeley.edu>
Tue, 26 Feb 2019 00:18:13 +0000 (16:18 -0800)
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`)

backends/firrtl/firrtl.cc
tests/asicworld/xfirrtl
tests/simple/xfirrtl
tests/tools/autotest.sh

index 0917ecba6940e7a322fe779f42fac8c58c5a859d..88c1038b7ebeb8dec2ed5db61bfaa91f778bd6ff 100644 (file)
@@ -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"));
index c782a2bd6cdf7917ce4b87b862e4e7d244fa377a..08bf4ccd856ab0730474a20883c8a004184d95af 100644 (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_tff_async_reset.v      $adff
 code_hdl_models_uart.v $adff
-code_specman_switch_fabric.v   subfield assignment (bits() <= ...)
 code_tidbits_asyn_reset.v      $adff
 code_tidbits_reg_seq_example.v $adff
 code_verilog_tutorial_always_example.v empty module
index 00e89b3898ab701720fff7f8d37956f9bdc20479..5bc75347b9bf31baedfdc66c3bc3a77de9984ba9 100644 (file)
@@ -12,7 +12,6 @@ multiplier.v  inst id[0] of
 muxtree.v      drops modules
 omsp_dbg_uart.v        $adff
 operators.v    $pow
-paramods.v     subfield assignment (bits() <= ...)
 partsel.v      drops modules
 process.v      drops modules
 realexpr.v     drops modules
index 218edf931786f71fa4157308c1f902550a640f24..99ec3e7cddff5b8ad7242167d9c8201ab0f2fd60 100755 (executable)
@@ -175,7 +175,7 @@ do
                        if [ -n "$firrtl2verilog" ]; 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
-                               $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
                            fi
                        fi