#!/usr/bin/env python3 # # Copyright (C) 2015 Clifford Wolf # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # import icebox import getopt, sys, re, os mode_384 = False mode_lm4k = False mode_5k = False mode_u4k = False mode_8k = False def usage(): print(""" Usage: %s [options] [bitmap.asc] -3 create chipdb for 384 device -5 create chipdb for 5k device -8 create chipdb for 8k device -4 create chipdb for lm4k device -u create chipdb for u4k device """ % os.path.basename(sys.argv[0])) sys.exit(0) try: opts, args = getopt.getopt(sys.argv[1:], "3584u") except: usage() for o, a in opts: if o == "-8": mode_8k = True elif o == "-5": mode_5k = True elif o == "-3": mode_384 = True elif o == "-4": mode_lm4k = True elif o == "-u": mode_u4k = True else: usage() ic = icebox.iceconfig() if mode_8k: ic.setup_empty_8k() elif mode_5k: ic.setup_empty_5k() elif mode_384: ic.setup_empty_384() elif mode_lm4k: ic.setup_empty_lm4k() elif mode_u4k: ic.setup_empty_u4k() else: ic.setup_empty_1k() all_tiles = set() for x in range(ic.max_x+1): for y in range(ic.max_y+1): if ic.tile(x, y) is not None: all_tiles.add((x, y)) seg_to_net = dict() net_to_segs = list() print("""# # IceBox Chip Database Dump (iCE40 %s) # # # Quick File Format Reference: # ---------------------------- # # .device DEVICE WIDTH HEIGHT NUM_NETS # # declares the device type # # # .pins PACKAGE # PIN_NUM TILE_X TILE_Y PIO_NUM # ... # # associates a package pin with an IO tile and block, and global network # # # .gbufin # TILE_X TILE_Y GLB_NUM # ... # # associates an IO tile with the global network can drive via fabout # # # .gbufpin # TILE_X TILE_Y PIO_NUM GLB_NUM # ... # # associates an IO tile with the global network can drive via the pad # # # .iolatch # TILE_X TILE_Y # ... # # specifies the IO tiles that drive the latch signal for the bank via fabout # # # .ieren # PIO_TILE_X PIO_TILE_Y PIO_NUM IEREN_TILE_X IEREN_TILE_Y IEREN_NUM # ... # # associates an IO block with an IeRen-block # # # .colbuf # SOURCE_TILE_X SOURCE_TILE_Y DEST_TILE_X DEST_TILE_Y # ... # # declares the positions of the column buffers # # # .io_tile X Y # .logic_tile X Y # .ramb_tile X Y # .ramt_tile X Y # .dsp[0..3]_tile X Y # .ipcon_tile X Y # declares the existence of a IO/LOGIC/RAM tile with the given coordinates # # # .io_tile_bits COLUMNS ROWS # .logic_tile_bits COLUMNS ROWS # .ramb_tile_bits COLUMNS ROWS # .ramt_tile_bits COLUMNS ROWS # .dsp[0..3]_tile_bits X Y # .ipcon_tile_bits X Y # FUNCTION_1 CONFIG_BITS_NAMES_1 # FUNCTION_2 CONFIG_BITS_NAMES_2 # ... # # declares non-routing configuration bits of IO/LOGIC/RAM tiles # # # .extra_cell X Y # .extra_cell X Y Z # KEY MULTI-FIELD-VALUE # .... # # declares a special-purpose cell that is not part of the FPGA fabric # # # .extra_bits # FUNCTION BANK_NUM ADDR_X ADDR_Y # ... # # declares non-routing global configuration bits # # # .net NET_INDEX # X1 Y1 name1 # X2 Y2 name2 # ... # # declares a net on the chip and lists its various names in different tiles # # # .buffer X Y DST_NET_INDEX CONFIG_BITS_NAMES # CONFIG_BITS_VALUES_1 SRC_NET_INDEX_1 # CONFIG_BITS_VALUES_2 SRC_NET_INDEX_2 # ... # # declares a buffer in the specified tile # # # .routing X Y DST_NET_INDEX CONFIG_BITS_NAMES # CONFIG_BITS_VALUES_1 SRC_NET_INDEX_1 # CONFIG_BITS_VALUES_2 SRC_NET_INDEX_2 # ... # # declares a routing switch in the specified tile # """ % ic.device) all_group_segments = ic.group_segments(all_tiles, connect_gb=False) print(".device %s %d %d %d" % (ic.device, ic.max_x+1, ic.max_y+1, len(all_group_segments))) print() for key in sorted(icebox.pinloc_db.keys()): key_dev, key_package = key.split("-") if key_dev == ic.device: print(".pins %s" % (key_package)) for entry in sorted(icebox.pinloc_db[key]): print("%s %d %d %d" % entry) print() print(".gbufin") for entry in sorted(ic.gbufin_db()): print(" ".join(["%d" % k for k in entry])) print() print(".gbufpin") for padin, pio in enumerate(ic.padin_pio_db()): entry = pio + (padin,) print(" ".join(["%d" % k for k in entry])) print() print(".iolatch") for entry in sorted(ic.iolatch_db()): print(" ".join(["%d" % k for k in entry])) print() print(".ieren") for entry in sorted(ic.ieren_db()): print(" ".join(["%d" % k for k in entry])) print() print(".colbuf") for entry in sorted(ic.colbuf_db()): print(" ".join(["%d" % k for k in entry])) print() for idx in sorted(ic.io_tiles): print(".io_tile %d %d" % idx) print() for idx in sorted(ic.logic_tiles): print(".logic_tile %d %d" % idx) print() for idx in sorted(ic.ramb_tiles): print(".ramb_tile %d %d" % idx) print() for idx in sorted(ic.ramt_tiles): print(".ramt_tile %d %d" % idx) print() for dsp_idx in range(4): for idx in sorted(ic.dsp_tiles[dsp_idx]): x, y = idx print(".dsp%d_tile %d %d" % (dsp_idx, x, y)) print() for idx in sorted(ic.ipcon_tiles): print(".ipcon_tile %d %d" % idx) print() def print_tile_nonrouting_bits(tile_type, idx): tx = idx[0] ty = idx[1] tile = ic.tile(tx, ty) print(".%s_tile_bits %d %d" % (tile_type, len(tile[0]), len(tile))) function_bits = dict() for entry in ic.tile_db(tx, ty): if not ic.tile_has_entry(tx, ty, entry): continue if entry[1] in ("routing", "buffer"): continue func = ".".join(entry[1:]) function_bits[func] = entry[0] for x in sorted(function_bits): print(" ".join([x] + function_bits[x])) print() print_tile_nonrouting_bits("logic", list(ic.logic_tiles.keys())[0]) print_tile_nonrouting_bits("io", list(ic.io_tiles.keys())[0]) if not mode_384: print_tile_nonrouting_bits("ramb", list(ic.ramb_tiles.keys())[0]) print_tile_nonrouting_bits("ramt", list(ic.ramt_tiles.keys())[0]) if ic.is_ultra(): for dsp_idx in range(4): print_tile_nonrouting_bits("dsp%d" % dsp_idx, list(ic.dsp_tiles[dsp_idx].keys())[0]) print_tile_nonrouting_bits("ipcon", list(ic.ipcon_tiles.keys())[0]) if ic.is_ultra(): print(".extra_cell %d 0 WARMBOOT" % ic.max_x) else: print(".extra_cell 0 0 WARMBOOT") for key in sorted(icebox.warmbootinfo_db[ic.device]): print("%s %s" % (key, " ".join([str(k) for k in icebox.warmbootinfo_db[ic.device][key]]))) print() for pllid in ic.pll_list(): pllinfo = icebox.pllinfo_db[pllid] print(".extra_cell %d %d PLL" % pllinfo["LOC"]) locked_pkgs = [] for entry in icebox.noplls_db: if pllid in icebox.noplls_db[entry]: locked_pkgs.append(entry.split("-")[1]) if len(locked_pkgs) > 0: print("LOCKED %s" % " ".join(sorted(locked_pkgs))) for key in sorted(pllinfo): if key != "LOC": print("%s %s" % (key, " ".join([str(k) for k in pllinfo[key]]))) print() for dsploc in ic.dsp_tiles[0]: x, y = dsploc print(".extra_cell %d %d 0 MAC16" % dsploc) nets = ic.get_dsp_nets_db(x, y) for key in sorted(nets): print("%s %s" % (key, " ".join([str(k) for k in nets[key]]))) cfg = ic.get_dsp_config_db(x, y) for key in sorted(cfg): print("%s %s" % (key, " ".join([str(k) for k in cfg[key]]))) print() if ic.device in icebox.extra_cells_db: for cell in sorted(icebox.extra_cells_db[ic.device]): name, loc = cell x, y, z = loc print(".extra_cell %d %d %d %s" % (x, y, z, name)) cellinfo = icebox.extra_cells_db[ic.device][cell] for key in sorted(cellinfo): print("%s %s" % (key, " ".join([str(k) for k in cellinfo[key]]))) print() if ic.device in icebox.spram_db: for cell in sorted(icebox.spram_db[ic.device]): loc = cell x, y, z = loc print(".extra_cell %d %d %d SPRAM" % (x, y, z)) cellinfo = icebox.spram_db[ic.device][cell] for key in sorted(cellinfo): print("%s %s" % (key, " ".join([str(k) for k in cellinfo[key]]))) print() print(".extra_bits") extra_bits = dict() for idx in sorted(ic.extra_bits_db()): extra_bits[".".join(ic.extra_bits_db()[idx])] = " ".join(["%d" % k for k in idx]) for idx in sorted(extra_bits): print("%s %s" % (idx, extra_bits[idx])) print() for group in sorted(all_group_segments): netidx = len(net_to_segs) net_to_segs.append(group) print(".net %d" % netidx) for seg in group: print("%d %d %s" % seg) assert seg not in seg_to_net seg_to_net[seg] = netidx print() for idx in sorted(all_tiles): db = ic.tile_db(idx[0], idx[1]) db_by_bits = dict() for entry in db: if entry[1] in ("buffer", "routing") and ic.tile_has_net(idx[0], idx[1], entry[2]) and ic.tile_has_net(idx[0], idx[1], entry[3]): bits = tuple([entry[1]] + sorted([bit.replace("!", "") for bit in entry[0]])) db_by_bits.setdefault(bits, list()).append(entry) for bits in sorted(db_by_bits): dst_net = None for entry in sorted(db_by_bits[bits]): assert (idx[0], idx[1], entry[3]) in seg_to_net if dst_net is None: dst_net = seg_to_net[(idx[0], idx[1], entry[3])] else: assert dst_net == seg_to_net[(idx[0], idx[1], entry[3])] print(".%s %d %d %d %s" % (bits[0], idx[0], idx[1], dst_net, " ".join(bits[1:]))) for entry in sorted(db_by_bits[bits]): pattern = "" for bit in bits[1:]: pattern += "1" if bit in entry[0] else "0" assert (idx[0], idx[1], entry[2]) in seg_to_net print("%s %d" % (pattern, seg_to_net[(idx[0], idx[1], entry[2])])) print()