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 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 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 dualmode(ttyp): for pin in dualmode_pins: mod = codegen.Module() cst = codegen.Constraints() cfg = {pin: 'false'} yield ttyp, mod, cst, cfg
fse['header']['grid'][61][-1][-1], ]), dff(locations), dualmode(fse['header']['grid'][61][0][0]), ) for ttyp, mod, cst, cfg in fuzzers: modmap.setdefault(ttyp, []).append(mod) cstmap.setdefault(ttyp, []).append(cst) cfgmap.setdefault(ttyp, []).append(cfg) modules = [ reduce(lambda a, b: a + b, m, codegen.Module()) for m in zip_longest(*modmap.values(), fillvalue=codegen.Module()) ] constrs = [ reduce(lambda a, b: a + b, c, codegen.Constraints()) for c in zip_longest(*cstmap.values(), fillvalue=codegen.Constraints()) ] configs = [ reduce(lambda a, b: { **a, **b }, c, {}) for c in zip_longest(*cfgmap.values(), fillvalue={}) ] type_re = re.compile(r"inst\d+_([A-Z]+)_([A-Z]+)") empty, hdr, ftr, posp, config = run_pnr(codegen.Module(), codegen.Constraints(), {}) db.cmd_hdr = hdr db.cmd_ftr = ftr
cstmap = {} # Add fuzzers here fuzzers = chain( iob(pin_locations), dff(locations), ) for ttyp, mod, cst in fuzzers: modmap.setdefault(ttyp, []).append(mod) cstmap.setdefault(ttyp, []).append(cst) modules = [ reduce(lambda a, b: a + b, m, codegen.Module()) for m in zip_longest(*modmap.values(), fillvalue=codegen.Module()) ] constrs = [ reduce(lambda a, b: a + b, c, codegen.Constraints()) for c in zip_longest(*cstmap.values(), fillvalue=codegen.Constraints()) ] type_re = re.compile(r"inst\d+_([A-Z]+)_([A-Z]+)") empty, hdr, ftr, posp = run_pnr(codegen.Module(), codegen.Constraints()) db.cmd_hdr = hdr db.cmd_ftr = ftr db.template = empty p = Pool() pnr_res = p.map(lambda param: run_pnr(*param), zip(modules, constrs)) for bitmap, hdr, ftr, posp in pnr_res: seen = {} diff = bitmap ^ empty
def run_pnr(fuzzers, bits): #TODO generalize/parameterize mod = codegen.Module() constr = codegen.Constraints() start = 0 for fuzzer in fuzzers: cb = bits[start:start + fuzzer.cfg_bits] start += fuzzer.cfg_bits fuzzer.primitives(mod, cb) fuzzer.constraints(constr, cb) cfg = codegen.DeviceConfig({ "JTAG regular_io": "false", "SSPI regular_io": "false", "MSPI regular_io": "false", "READY regular_io": "false", "DONE regular_io": "false", "RECONFIG_N regular_io": "false", "MODE regular_io": "false", "CRC_check": "true", "compress": "false", "encryption": "false", "security_bit_enable": "true", "bsram_init_fuse_print": "true", "download_speed": "250/100", "spi_flash_address": "0x00FFF000", "format": "txt", "background_programming": "false", "secure_mode": "false" }) opt = codegen.PnrOptions([]) #"sdf", "oc", "ibs", "posp", "o", #"warning_all", "timing", "reg_not_in_iob"]) pnr = codegen.Pnr() pnr.device = "GW1NR-9-QFN88-6" pnr.partnumber = "GW1NR-LV9QN88C6/I5" with tempfile.TemporaryDirectory() as tmpdir: pnr.outdir = tmpdir with open(tmpdir + "/top.v", "w") as f: mod.write(f) pnr.netlist = tmpdir + "/top.v" with open(tmpdir + "/top.cst", "w") as f: constr.write(f) pnr.cst = tmpdir + "/top.cst" with open(tmpdir + "/device.cfg", "w") as f: cfg.write(f) pnr.cfg = tmpdir + "/device.cfg" with open(tmpdir + "/pnr.cfg", "w") as f: opt.write(f) pnr.opt = tmpdir + "/pnr.cfg" with open(tmpdir + "/run.tcl", "w") as f: pnr.write(f) subprocess.run([gowinhome + "/IDE/bin/gw_sh", tmpdir + "/run.tcl"]) #print(tmpdir); input() try: return bslib.read_bitstream(tmpdir + "/impl/pnr/top.fs")[0] except FileNotFoundError: return None
cstmap = {} # Add fuzzers here fuzzers = chain( iob(pin_locations), dff(locations), ) for ttyp, mod, cst in fuzzers: modmap.setdefault(ttyp, []).append(mod) cstmap.setdefault(ttyp, []).append(cst) modules = [ sum(m, start=codegen.Module()) for m in zip_longest(*modmap.values(), fillvalue=codegen.Module()) ] constrs = [ sum(c, start=codegen.Constraints()) for c in zip_longest(*cstmap.values(), fillvalue=codegen.Constraints()) ] type_re = re.compile(r"inst\d+_([A-Z]+)_([A-Z]+)") empty, hdr, ftr, posp = run_pnr(codegen.Module(), codegen.Constraints()) db.cmd_hdr = hdr db.cmd_ftr = ftr db.template = empty p = Pool() pnr_res = p.map(lambda param: run_pnr(*param), zip(modules, constrs)) for bitmap, hdr, ftr, posp in pnr_res: seen = {} diff = bitmap ^ empty