icestorm/icebox/icebox_chipdb.py

253 lines
6.6 KiB
Python
Raw Normal View History

2015-07-18 13:05:02 +02:00
#!/usr/bin/python
#
# 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.
#
from __future__ import division
from __future__ import print_function
import icebox
import getopt, sys, re
ic = icebox.iceconfig()
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 Database Dump for iCE40 HX1K / LP1K
#
#
# Quick File Format Reference:
# ----------------------------
#
2015-07-18 13:07:39 +02:00
# .device DEVICE WIDTH HEIGHT NUM_NETS
2015-07-18 13:06:48 +02:00
#
# declares the device type (e.g. "1k")
#
#
# .pins PACKAGE
2015-07-18 13:07:39 +02:00
# PIN_NUM TILE_X TILE_Y PIO_NUM GLB_NUM
2015-07-18 13:06:48 +02:00
# ...
#
2015-07-18 13:07:39 +02:00
# 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 it drives via wire_gbuf/in
#
#
# .iolatch
# TILE_X TILE_Y
# ...
#
# specifies the IO tiles that drive the latch signal for the bank via wire_gbuf/in
#
#
# .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
2015-07-18 13:06:48 +02:00
#
2015-07-18 13:05:02 +02:00
#
# .io_tile X Y
# .logic_tile X Y
2015-07-18 13:06:48 +02:00
# .ramb_tile X Y
# .ramt_tile X Y
2015-07-18 13:05:02 +02:00
#
# declares the existence of a IO/LOGIC/RAM tile with the given coordinates
#
#
2015-07-18 13:07:39 +02:00
# .io_tile_bits COLUMNS ROWS
# .logic_tile_bits COLUMNS ROWS
# .ramb_tile_bits COLUMNS ROWS
# .ramt_tile_bits COLUMNS ROWS
# FUNCTION_1 CONFIG_BITS_NAMES_1
# FUNCTION_2 CONFIG_BITS_NAMES_2
# ...
#
# declares non-routing configuration bits of IO/LOGIC/RAM tiles
#
#
# .extra_bits
# FUNCTION BANK_NUM ADDR_X ADDR_Y
# ...
#
# declares non-routing global configuration bits
#
#
2015-07-18 13:05:02 +02:00
# .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
#
""")
2015-07-18 13:07:39 +02:00
all_group_segments = ic.group_segments(all_tiles, connect_gb=False)
print(".device 1k %d %d %d" % (ic.max_x+1, ic.max_y+1, len(all_group_segments)))
2015-07-18 13:06:48 +02:00
print()
print(".pins tq144")
pio_to_padin = dict()
for padin, pio in enumerate(ic.padin_pio_db()):
pio_to_padin[pio] = padin
for entry in sorted(ic.pinloc_db()):
pio = (entry[1], entry[2], entry[3])
print("%d %d %d %d %d" % tuple(entry + [pio_to_padin[pio] if pio in pio_to_padin else -1]))
print()
2015-07-18 13:07:39 +02:00
print(".gbufin")
for entry in sorted(ic.gbufin_db()):
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()
2015-07-18 13:05:02 +02:00
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()
2015-07-18 13:06:48 +02:00
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)
2015-07-18 13:05:02 +02:00
print()
2015-07-18 13:07:39 +02:00
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", ic.logic_tiles.keys()[0])
print_tile_nonrouting_bits("io", ic.io_tiles.keys()[0])
print_tile_nonrouting_bits("ramb", ic.ramb_tiles.keys()[0])
print_tile_nonrouting_bits("ramt", ic.ramt_tiles.keys()[0])
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):
2015-07-18 13:05:02 +02:00
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()