Only accept <128 for variable length, only if $shiftx exclusive
authorEddie Hung <eddieh@ece.ubc.ca>
Sat, 16 Mar 2019 15:51:13 +0000 (08:51 -0700)
committerEddie Hung <eddieh@ece.ubc.ca>
Sat, 16 Mar 2019 15:51:13 +0000 (08:51 -0700)
passes/techmap/shregmap.cc
techlibs/xilinx/cells_map.v

index 4b8f8a8280a8c4d3d9d0bbdd2d247b9919a9525f..f893461a066d534151cc2e392d5daaa08de50d90 100644 (file)
@@ -161,6 +161,16 @@ struct ShregmapTechXilinx7 : ShregmapTech
                        }
                }
 
+               // Cannot implement variable-length shift registers
+               // greater than 128 since Q31 cannot be output onto
+               // fabric
+               if (shiftx && GetSize(taps) > 128)
+                       return false;
+
+               // Only map if $shiftx exclusively covers the shift register
+               if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int())
+                       return false;
+
                return true;
        }
 
@@ -173,34 +183,33 @@ struct ShregmapTechXilinx7 : ShregmapTech
                        return true;
 
                Cell* shiftx = it->second;
-
-               auto module = cell->module;
+               auto shiftx_a = shiftx->getPort("\\A").bits();
 
                auto cell_q = cell->getPort("\\Q").as_bit();
 
-               auto shiftx_a = shiftx->getPort("\\A").bits();
                int offset = 0;
+#ifndef NDEBUG
                for (auto bit : shiftx_a) {
                        if (bit == cell_q)
                                break;
                        ++offset;
                }
                offset -= taps.size() - 1;
-               log_assert(offset >= 0);
+               log_assert(offset == 0);
+#endif
                for (size_t i = offset; i < offset + taps.size(); ++i)
                        shiftx_a[i] = cell_q;
+
                // FIXME: Hack to ensure that $shiftx gets optimised away
                //   Without this, Yosys will refuse to optimise away a $shiftx
                //   where \\A 's width is not perfectly \\B_WIDTH ** 2
+               // See YosysHQ/yosys#878
                auto shiftx_bwidth = shiftx->getParam("\\B_WIDTH").as_int();
                shiftx_a.resize(1 << shiftx_bwidth, shiftx_a.back());
                shiftx->setPort("\\A", shiftx_a);
                shiftx->setParam("\\A_WIDTH", shiftx_a.size());
 
-               auto length = module->addWire(NEW_ID, ceil(log2(taps.size())));
-               module->addSub(NEW_ID, shiftx->getPort("\\B"), RTLIL::Const(offset, ceil(log2(offset))), length);
-               cell->setPort("\\L", length);
-
+               cell->setPort("\\L", shiftx->getPort("\\B"));
 
                return true;
        }
index a35b0742bd32060cb6c9237e6293783df4ec1fc4..1d538e2622ad0c04d692795e9a6dfb233bad0a85 100644 (file)
@@ -121,11 +121,7 @@ module \$__SHREG_ (input C, input D, input [31:0] L, input E, output Q);
       else begin
         // No way to create variable length shift registers >128 bits as Q31
         // cannot be output to the fabric...
-        wire [DEPTH-1:-1] c;
-        genvar i;
-        for (i = 0; i < DEPTH; i=i+1)
-            \$__SHREG_ #(.DEPTH(1), .INIT(INIT_R[i]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl (.C(C), .D(c[i-1]), .L(0), .E(E), .Q(c[i]));
-        assign { c[-1], Q } = { D, c[L] };
+        wire _TECHMAP_FAIL_ = 1;
       end
     end
   endgenerate