def write_posp(f): belre = re.compile(r"R(\d+)C(\d+)_(SLICE|IOB)(\w)") namere = re.compile(r"\W+") for name, cell in ctx.cells: row, col, typ, idx = belre.match(cell.bel).groups() row = int(row) col = int(col) name = namere.sub('_', name) if typ == 'SLICE': idx = int(idx) cls = idx // 2 side = ['A', 'B'][idx % 2] lutname = name + "_LUT" f.write(f"{lutname} PLACE_R{row}C{col}[{cls}][{side}]\n") lut = codegen.Primitive("LUT4", lutname) #lut.params["INIT"] = f"16'b{val:016b}" lut.portmap['F'] = f"R{row}C{col}_F{idx}" lut.portmap['I0'] = f"R{row}C{col}_A{idx}" lut.portmap['I1'] = f"R{row}C{col}_B{idx}" lut.portmap['I2'] = f"R{row}C{col}_C{idx}" lut.portmap['I3'] = f"R{row}C{col}_D{idx}" mod.wires.update(lut.portmap.values()) mod.primitives[lutname] = lut if int(cell.params['FF_USED'], 2): dffname = name + "_DFF" f.write(f"{dffname} PLACE_R{row}C{col}[{cls}][{side}]\n") lut = codegen.Primitive("DFF", dffname) lut.portmap['D'] = f"R{row}C{col}_F{idx}" lut.portmap['Q'] = f"R{row}C{col}_Q{idx}" lut.portmap['CLK'] = f"R{row}C{col}_CLK{idx}" mod.wires.update(lut.portmap.values()) mod.primitives[dffname] = lut elif typ == 'IOB': if row == 1: edge = 'T' num = col elif col == 1: edge = 'L' num = row elif col == 47: #TODO parameterize edge = 'R' num = row else: edge = 'B' num = col f.write(f"{name} PLACE_IO{edge}{num}[{idx}]\n") iob = codegen.Primitive("IOBUF", name) iob.portmap['I'] = f"R{row}C{col}_I{idx}" iob.portmap['O'] = f"R{row}C{col}_O{idx}" iob.portmap['IO'] = f"R{row}C{col}_IO{idx}" iob.portmap['OEN'] = f"R{row}C{col}_OEN{idx}" mod.wires.update(iob.portmap.values()) mod.inouts.add(f"R{row}C{col}_IO{idx}") mod.primitives[name] = iob
def dff(locations): for ttyp in range(12, 17): # for each tile type mod = codegen.Module() cst = codegen.Constraints() try: # get all tiles of this type # iter causes the loop to not repeat the same locs per cls locs = iter(locations[ttyp]) except KeyError: continue for cls in range(3): # for each cls for typ, port in dffmap.items(): # for each bel type try: loc = next(locs) # get the next unused tile except StopIteration: yield ttyp, mod, cst, {} locs = iter(locations[ttyp]) loc = next(locs) mod = codegen.Module() cst = codegen.Constraints() lutname = make_name("DUMMY", "LUT4") lut = codegen.Primitive("LUT4", lutname) lut.params["INIT"] = "16'hffff" lut.portmap['F'] = lutname + "_F" lut.portmap['I0'] = lutname + "_I0" lut.portmap['I1'] = lutname + "_I1" lut.portmap['I2'] = lutname + "_I2" lut.portmap['I3'] = lutname + "_I3" mod.wires.update(lut.portmap.values()) mod.primitives[lutname] = lut name = make_name("DFF", typ) dff = codegen.Primitive(typ, name) dff.portmap['CLK'] = name + "_CLK" dff.portmap['D'] = lutname + "_F" dff.portmap['Q'] = name + "_Q" if port: dff.portmap[port] = name + "_" + port mod.wires.update(dff.portmap.values()) mod.primitives[name] = dff row = loc[0] + 1 col = loc[1] + 1 cst.cells[lutname] = f"R{row}C{col}[{cls}]" cst.cells[name] = f"R{row}C{col}[{cls}]" yield ttyp, mod, cst, {}
def primitives(self, mod, bits): "Generate verilog for a LUT4 and DFF" for location, bits in self.location_chunks(bits): if bits[0]: name = self.location_to_name(location) location_a = location + "[A]_LUT" name_a_lut = self.location_to_name(location_a) lut = codegen.Primitive("LUT4", name_a_lut) lut.params["INIT"] = "16'hffff" lut.portmap['F'] = name_a_lut + "_F" lut.portmap['I0'] = name_a_lut + "_I0" lut.portmap['I1'] = name_a_lut + "_I1" lut.portmap['I2'] = name_a_lut + "_I2" lut.portmap['I3'] = name_a_lut + "_I3" mod.wires.update(lut.portmap.values()) mod.primitives[name_a_lut] = lut location_b = location + "[B]_LUT" name_b_lut = self.location_to_name(location_b) lut = codegen.Primitive("LUT4", name_b_lut) lut.params["INIT"] = "16'hffff" lut.portmap['F'] = name_b_lut + "_F" lut.portmap['I0'] = name_b_lut + "_I0" lut.portmap['I1'] = name_b_lut + "_I1" lut.portmap['I2'] = name_b_lut + "_I2" lut.portmap['I3'] = name_b_lut + "_I3" mod.wires.update(lut.portmap.values()) mod.primitives[name_b_lut] = lut location_a = location + "[A]_DFF" name_a_dff = self.location_to_name(location_a) dff = codegen.Primitive("DFF", name_a_dff) dff.portmap['CLK'] = name + "_CLK" # share clk dff.portmap['D'] = name_a_lut + "_F" dff.portmap['Q'] = name_a_dff + "_Q" mod.wires.update(dff.portmap.values()) mod.primitives[name_a_dff] = dff location_a = location + "[B]_DFF" name_b_dff = self.location_to_name(location_a) dff = codegen.Primitive("DFF", name_b_dff) dff.portmap['CLK'] = name + "_CLK" dff.portmap['D'] = name_b_lut + "_F" dff.portmap['Q'] = name_b_dff + "_Q" mod.wires.update(dff.portmap.values()) mod.primitives[name_b_dff] = dff
def iob(locations, corners): cnt = Counter() # keep track of how many runs are needed for ttyp, tiles in locations.items(): # for each tile of this type mod = codegen.Module() cst = codegen.Constraints() # get bels in this ttyp bels = {name[-1] for loc in tiles.values() for name in loc} locs = tiles.copy() for pin in bels: # [A, B, C, D, ...] for typ, conn in iobmap.items(): # find the next location that has pin # or make a new module for tile, names in locs.items(): name = tile + pin if name in names: del locs[tile] loc = name break else: # no usable tiles yield ttyp, mod, cst, {} cnt[ttyp] += 1 locs = tiles.copy() mod = codegen.Module() cst = codegen.Constraints() for tile, names in locs.items(): name = tile + pin if name in names: del locs[tile] loc = name break name = make_name("IOB", typ) iob = codegen.Primitive(typ, name) for port in chain.from_iterable(conn.values()): iob.portmap[port] = name + "_" + port for direction, wires in conn.items(): wnames = [name + "_" + w for w in wires] getattr(mod, direction).update(wnames) mod.primitives[name] = iob cst.ports[name] = loc yield ttyp, mod, cst, {} cnt[ttyp] += 1 # insert dummie in the corners to detect the bank enable bits runs = cnt.most_common(1)[0][1] for n in range(runs): for ttyp in corners: mod = codegen.Module() cst = codegen.Constraints() cfg = {} yield ttyp, mod, cst, cfg
def primitives(self, mod, bits): "Generate verilog for an IOB at this location" for location, bits in self.location_chunks(bits): if bits[0]: name = "IOB{}".format(location) dff = codegen.Primitive(self.kind, name) for port in chain.from_iterable(self.ports.values()): dff.portmap[port] = name + "_" + port for direction, wires in self.ports.items(): wnames = [name + "_" + w for w in wires] getattr(mod, direction).update(wnames) mod.primitives[name] = dff
def primitives(self, mod, bits): "Generate verilog for a DFF at this location" for location, bits in self.location_chunks(bits): prim, port = self.ffmap[tuple(bits)] name = self.location_to_name(location) dff = codegen.Primitive(prim, name) dff.portmap['CLK'] = name + "_CLK" dff.portmap['D'] = name + "_F" dff.portmap['Q'] = name + "_Q" dff.portmap['CE'] = name + "_CE" dff.portmap[port] = name + "_" + port mod.wires.update(dff.portmap.values()) mod.primitives[name] = dff
def primitives(self, mod, bits): "Generate verilog for LUT4s" for location, bits in self.location_chunks(bits): name = self.location_to_name(location) lut = codegen.Primitive("LUT4", name) lut.params["INIT"] = np_to_vector(1 ^ bits) # inverted lut.portmap['F'] = name + "_F" lut.portmap['I0'] = name + "_I0" lut.portmap['I1'] = name + "_I1" lut.portmap['I2'] = name + "_I2" lut.portmap['I3'] = name + "_I3" mod.wires.update(lut.portmap.values()) mod.primitives[name] = lut
def primitives(self, mod, bits): "Generate verilog for LUT4s" for location, bits in self.location_chunks(bits): name = self.location_to_name(location) lut = codegen.Primitive("LUT4", name) lut.params["INIT"] = "16'h0000" lut.portmap['F'] = name + "_F" neigh = self.neighbours(location) for i, ne, bit in zip(count(), neigh, bits): if bit: ne_name = self.location_to_name(ne) lut.portmap['I{}'.format(i)] = ne_name + "_F" else: lut.portmap['I{}'.format(i)] = name + "_I{}".format(i) mod.wires.update(lut.portmap.values()) mod.primitives[name] = lut
def iob(locations): for ttyp, tiles in locations.items(): # for each tile of this type mod = codegen.Module() cst = codegen.Constraints() # get bels in this ttyp bels = {name[-1] for loc in tiles.values() for name in loc} locs = tiles.copy() for pin in bels: # [A, B, C, D, ...] for typ, conn in iobmap.items(): # find the next location that has pin # or make a new module for tile, names in locs.items(): name = tile + pin if name in names: del locs[tile] loc = name break else: # no usable tiles yield ttyp, mod, cst locs = tiles.copy() mod = codegen.Module() cst = codegen.Constraints() for tile, names in locs.items(): name = tile + pin if name in names: del locs[tile] loc = name break name = make_name("IOB", typ) iob = codegen.Primitive(typ, name) for port in chain.from_iterable(conn.values()): iob.portmap[port] = name + "_" + port for direction, wires in conn.items(): wnames = [name + "_" + w for w in wires] getattr(mod, direction).update(wnames) mod.primitives[name] = iob cst.ports[name] = loc yield ttyp, mod, cst
def tile2verilog(dbrow, dbcol, bels, pips, mod, db): # db is 0-based, floorplanner is 1-based row = dbrow + 1 col = dbcol + 1 aliases = db.grid[dbrow][dbcol].aliases for dest, src in chain(pips.items(), aliases.items()): srcg = chipdb.wire2global(row, col, db, src) destg = chipdb.wire2global(row, col, db, dest) mod.wires.update({srcg, destg}) mod.assigns.append((destg, srcg)) belre = re.compile(r"(IOB|LUT|DFF|BANK|CFG)(\w*)") for bel, flags in bels.items(): typ, idx = belre.match(bel).groups() if typ == "LUT": val = sum(1 << f for f in flags) name = f"R{row}C{col}_LUT4_{idx}" lut = codegen.Primitive("LUT4", name) lut.params["INIT"] = f"16'b{val:016b}" lut.portmap['F'] = f"R{row}C{col}_F{idx}" lut.portmap['I0'] = f"R{row}C{col}_A{idx}" lut.portmap['I1'] = f"R{row}C{col}_B{idx}" lut.portmap['I2'] = f"R{row}C{col}_C{idx}" lut.portmap['I3'] = f"R{row}C{col}_D{idx}" mod.wires.update(lut.portmap.values()) mod.primitives[name] = lut elif typ == "DFF": kind, = flags # DFF only have one flag idx = int(idx) port = dffmap[kind] name = f"R{row}C{col}_{typ}E_{idx}" dff = codegen.Primitive(kind + "E", name) dff.portmap['CLK'] = f"R{row}C{col}_CLK{idx//2}" dff.portmap['D'] = f"R{row}C{col}_F{idx}" dff.portmap['Q'] = f"R{row}C{col}_Q{idx}" dff.portmap['CE'] = f"R{row}C{col}_CE{idx//2}" if port: dff.portmap[port] = f"R{row}C{col}_LSR{idx//2}" mod.wires.update(dff.portmap.values()) mod.primitives[name] = dff elif typ == "IOB": try: kind, = flags.intersection(iobmap.keys()) except ValueError: continue portmap = db.grid[dbrow][dbcol].bels[bel].portmap name = f"R{row}C{col}_{kind}_{idx}" wires = set(iobmap[kind]['wires']) ports = set(chain.from_iterable(iobmap[kind].values())) - wires iob = codegen.Primitive(kind, name) for port in wires: wname = portmap[port] iob.portmap[port] = f"R{row}C{col}_{wname}" for port in ports: iob.portmap[port] = f"R{row}C{col}_{port}{idx}" for wires in iobmap[kind]['wires']: wnames = [f"R{row}C{col}_{portmap[w]}" for w in wires] mod.wires.update(wnames) for direction in ['inputs', 'outputs', 'inouts']: for wires in iobmap[kind].get(direction, []): wnames = [f"R{row}C{col}_{w}{idx}" for w in wires] getattr(mod, direction).update(wnames) mod.primitives[name] = iob gnd = codegen.Primitive("GND", "mygnd") gnd.portmap["G"] = "VSS" mod.primitives["mygnd"] = gnd vcc = codegen.Primitive("VCC", "myvcc") vcc.portmap["V"] = "VCC" mod.primitives["myvcc"] = vcc