Improves the previous commit with a more complete coverage of the cases
authorIris Johnson <iris@modwiz.com>
Fri, 15 Jan 2021 19:59:20 +0000 (13:59 -0600)
committerIris Johnson <iris@modwiz.com>
Fri, 15 Jan 2021 19:59:20 +0000 (13:59 -0600)
backends/cxxrtl/cxxrtl_backend.cc

index 3906ed23552721b5afa552bf9daa09ac6fb27fae..39046bd782f22b520d9ff49b3cee06085b1577ac 100644 (file)
@@ -601,11 +601,10 @@ struct WireType {
        bool is_exact() const { return type == ALIAS || type == CONST; }
 };
 
-// Tests for a SigSpec that is backed by a specific slice of a wire, this is used
-// instead of .is_wire() on clocks because they can be only a portion of an underlying
-// wire
-bool is_wire_slice(const RTLIL::SigSpec& sig) {
-       return sig.is_chunk() && sig.chunks()[0].wire;
+// Tests for a SigSpec that is a valid clock input, clocks have to have a backing wire and be a single bit
+// using this instead of sig.is_wire() solves issues when the clock is a slice instead of a full wire
+bool is_valid_clock(const RTLIL::SigSpec& sig) {
+       return sig.is_chunk() && sig.is_bit() && sig[0].wire;
 }
 
 struct CxxrtlWorker {
@@ -1118,7 +1117,7 @@ struct CxxrtlWorker {
                } else if (is_ff_cell(cell->type)) {
                        log_assert(!for_debug);
                        // Clocks might be slices of larger signals but should only ever be single bit
-                       if (cell->hasPort(ID::CLK) && is_wire_slice(cell->getPort(ID::CLK))) {
+                       if (cell->hasPort(ID::CLK) && is_valid_clock(cell->getPort(ID::CLK))) {
                                // Edge-sensitive logic
                                RTLIL::SigBit clk_bit = cell->getPort(ID::CLK)[0];
                                clk_bit = sigmaps[clk_bit.wire->module](clk_bit);
@@ -2274,7 +2273,7 @@ struct CxxrtlWorker {
        void register_edge_signal(SigMap &sigmap, RTLIL::SigSpec signal, RTLIL::SyncType type)
        {
                signal = sigmap(signal);
-               log_assert(signal.is_wire() && signal.is_bit());
+               log_assert(is_valid_clock(signal));
                log_assert(type == RTLIL::STp || type == RTLIL::STn || type == RTLIL::STe);
 
                RTLIL::SigBit sigbit = signal[0];
@@ -2282,7 +2281,8 @@ struct CxxrtlWorker {
                        edge_types[sigbit] = type;
                else if (edge_types[sigbit] != type)
                        edge_types[sigbit] = RTLIL::STe;
-               edge_wires.insert(signal.as_wire());
+               // Cannot use as_wire because signal might not be a full wire, instead extract the wire from the sigbit
+               edge_wires.insert(sigbit.wire);
        }
 
        void analyze_design(RTLIL::Design *design)
@@ -2363,14 +2363,14 @@ struct CxxrtlWorker {
 
                                // Various DFF cells are treated like posedge/negedge processes, see above for details.
                                if (cell->type.in(ID($dff), ID($dffe), ID($adff), ID($adffe), ID($dffsr), ID($dffsre), ID($sdff), ID($sdffe), ID($sdffce))) {
-                                       if (sigmap(cell->getPort(ID::CLK)).is_wire())
+                                       if (is_valid_clock(cell->getPort(ID::CLK)))
                                                register_edge_signal(sigmap, cell->getPort(ID::CLK),
                                                        cell->parameters[ID::CLK_POLARITY].as_bool() ? RTLIL::STp : RTLIL::STn);
                                }
                                // Similar for memory port cells.
                                if (cell->type.in(ID($memrd), ID($memwr))) {
                                        if (cell->getParam(ID::CLK_ENABLE).as_bool()) {
-                                               if (sigmap(cell->getPort(ID::CLK)).is_wire())
+                                               if (is_valid_clock(cell->getPort(ID::CLK)))
                                                        register_edge_signal(sigmap, cell->getPort(ID::CLK),
                                                                cell->parameters[ID::CLK_POLARITY].as_bool() ? RTLIL::STp : RTLIL::STn);
                                        }
@@ -2380,7 +2380,7 @@ struct CxxrtlWorker {
                                if (cell->type == ID($memwr))
                                        writable_memories.insert(module->memories[cell->getParam(ID::MEMID).decode_string()]);
                                // Collect groups of memory write ports in the same domain.
-                               if (cell->type == ID($memwr) && cell->getParam(ID::CLK_ENABLE).as_bool() && is_wire_slice(cell->getPort(ID::CLK))) {
+                               if (cell->type == ID($memwr) && cell->getParam(ID::CLK_ENABLE).as_bool() && is_valid_clock(cell->getPort(ID::CLK))) {
                                        RTLIL::SigBit clk_bit = sigmap(cell->getPort(ID::CLK))[0];
                                        const RTLIL::Memory *memory = module->memories[cell->getParam(ID::MEMID).decode_string()];
                                        memwr_per_domain[{clk_bit, memory}].insert(cell);
@@ -2392,7 +2392,7 @@ struct CxxrtlWorker {
                        }
                        for (auto cell : module->cells()) {
                                // Collect groups of memory write ports read by every transparent read port.
-                               if (cell->type == ID($memrd) && cell->getParam(ID::CLK_ENABLE).as_bool() && is_wire_slice(cell->getPort(ID::CLK)) &&
+                               if (cell->type == ID($memrd) && cell->getParam(ID::CLK_ENABLE).as_bool() && is_valid_clock(cell->getPort(ID::CLK)) &&
                                    cell->getParam(ID::TRANSPARENT).as_bool()) {
                                        RTLIL::SigBit clk_bit = sigmap(cell->getPort(ID::CLK))[0];
                                        const RTLIL::Memory *memory = module->memories[cell->getParam(ID::MEMID).decode_string()];