| #!/usr/bin/env python3 |
| # |
| # Copyright (C) 2015 Clifford Wolf <clifford@clifford.at> |
| # |
| # 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 |
| |
| mode_384 = False |
| mode_lm4k = False |
| mode_5k = False |
| mode_u4k = False |
| mode_8k = False |
| |
| def usage(): |
| print(""" |
| Usage: icebox_chipdb [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 |
| """) |
| 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 <cell-type> |
| # .extra_cell X Y Z <cell-type> |
| # 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() |