nextpnr/ice40/chipdb.py
Clifford Wolf 3b5c33d685 Move WireInfoPOD into ChipDB binary blob
Signed-off-by: Clifford Wolf <clifford@clifford.at>
2018-06-17 14:30:26 +02:00

774 lines
25 KiB
Python

#!/usr/bin/env python3
import sys
import re
import textwrap
endianness = "le"
compact_output = True
dev_name = None
dev_width = None
dev_height = None
num_wires = None
tiles = dict()
wire_uphill = dict()
wire_downhill = dict()
pip_xy = dict()
bel_name = list()
bel_type = list()
bel_pos = list()
bel_wires = list()
switches = list()
ierens = list()
packages = list()
wire_uphill_belport = dict()
wire_downhill_belports = dict()
wire_names = dict()
wire_names_r = dict()
wire_xy = dict()
num_tile_types = 5
tile_sizes = {_: (0, 0) for _ in range(num_tile_types)}
tile_bits = [[] for _ in range(num_tile_types)]
cbit_re = re.compile(r'B(\d+)\[(\d+)\]')
portpins = dict()
beltypes = dict()
with open("ice40/portpins.inc") as f:
for line in f:
line = line.replace("(", " ")
line = line.replace(")", " ")
line = line.split()
if len(line) == 0:
continue
assert len(line) == 2
assert line[0] == "X"
idx = len(portpins) + 1
portpins[line[1]] = idx
beltypes["ICESTORM_LC"] = 1
beltypes["ICESTORM_RAM"] = 2
beltypes["SB_IO"] = 3
beltypes["SB_GB"] = 4
def maj_wire_name(name):
if re.match(r"lutff_\d/(in|out)", name[2]):
return True
return False
def cmp_wire_names(newname, oldname):
if maj_wire_name(newname):
return True
if maj_wire_name(oldname):
return False
return newname < oldname
with open(sys.argv[1], "r") as f:
mode = None
for line in f:
line = line.split()
if len(line) == 0 or line[0] == "#":
continue
if line[0] == ".device":
dev_name = line[1]
dev_width = int(line[2])
dev_height = int(line[3])
num_wires = int(line[4])
continue
if line[0] == ".net":
mode = ("net", int(line[1]))
continue
if line[0] == ".buffer":
mode = ("buffer", int(line[3]), int(line[1]), int(line[2]))
switches.append((line[3], int(line[1]), int(line[2]), line[4:]))
continue
if line[0] == ".routing":
mode = ("routing", int(line[3]), int(line[1]), int(line[2]))
switches.append((line[3], int(line[1]), int(line[2]), line[4:]))
continue
if line[0] == ".io_tile":
tiles[(int(line[1]), int(line[2]))] = "io"
mode = None
continue
if line[0] == ".logic_tile":
tiles[(int(line[1]), int(line[2]))] = "logic"
mode = None
continue
if line[0] == ".ramb_tile":
tiles[(int(line[1]), int(line[2]))] = "ramb"
mode = None
continue
if line[0] == ".ramt_tile":
tiles[(int(line[1]), int(line[2]))] = "ramt"
mode = None
continue
if line[0] == ".logic_tile_bits":
mode = ("bits", 1)
tile_sizes[1] = (int(line[1]), int(line[2]))
continue
if line[0] == ".io_tile_bits":
mode = ("bits", 2)
tile_sizes[2] = (int(line[1]), int(line[2]))
continue
if line[0] == ".ramb_tile_bits":
mode = ("bits", 3)
tile_sizes[3] = (int(line[1]), int(line[2]))
continue
if line[0] == ".ramt_tile_bits":
mode = ("bits", 4)
tile_sizes[4] = (int(line[1]), int(line[2]))
continue
if line[0] == ".ieren":
mode = ("ieren",)
continue
if line[0] == ".pins":
mode = ("pins", line[1])
packages.append((line[1], []))
continue
if (line[0][0] == ".") or (mode is None):
mode = None
continue
if mode[0] == "net":
wname = (int(line[0]), int(line[1]), line[2])
wire_names[wname] = mode[1]
if (mode[1] not in wire_names_r) or cmp_wire_names(wname, wire_names_r[mode[1]]):
wire_names_r[mode[1]] = wname
if mode[1] not in wire_xy:
wire_xy[mode[1]] = list()
wire_xy[mode[1]].append((int(line[0]), int(line[1])))
continue
if mode[0] in ("buffer", "routing"):
wire_a = int(line[1])
wire_b = mode[1]
if wire_a not in wire_downhill:
wire_downhill[wire_a] = set()
if wire_b not in wire_uphill:
wire_uphill[wire_b] = set()
wire_downhill[wire_a].add(wire_b)
wire_uphill[wire_b].add(wire_a)
pip_xy[(wire_a, wire_b)] = (mode[2], mode[3], int(line[0], 2), len(switches) - 1)
continue
if mode[0] == "bits":
name = line[0]
bits = []
for b in line[1:]:
m = cbit_re.match(b)
assert m
bits.append((int(m.group(1)), int(m.group(2))))
tile_bits[mode[1]].append((name, bits))
continue
if mode[0] == "ieren":
ierens.append(tuple([int(_) for _ in line]))
continue
if mode[0] == "pins":
packages[-1][1].append((line[0], int(line[1]), int(line[2]), int(line[3])))
continue
def add_bel_input(bel, wire, port):
if wire not in wire_downhill_belports:
wire_downhill_belports[wire] = set()
wire_downhill_belports[wire].add((bel, port))
bel_wires[bel].append((wire, port))
def add_bel_output(bel, wire, port):
assert wire not in wire_uphill_belport
wire_uphill_belport[wire] = (bel, port)
bel_wires[bel].append((wire, port))
def add_bel_lc(x, y, z):
bel = len(bel_name)
bel_name.append("X%d/Y%d/lc%d" % (x, y, z))
bel_type.append("ICESTORM_LC")
bel_pos.append((x, y, z))
bel_wires.append(list())
wire_cen = wire_names[(x, y, "lutff_global/cen")]
wire_clk = wire_names[(x, y, "lutff_global/clk")]
wire_s_r = wire_names[(x, y, "lutff_global/s_r")]
if z == 0:
wire_cin = wire_names[(x, y, "carry_in_mux")]
else:
wire_cin = wire_names[(x, y, "lutff_%d/cout" % (z-1))]
wire_in_0 = wire_names[(x, y, "lutff_%d/in_0" % z)]
wire_in_1 = wire_names[(x, y, "lutff_%d/in_1" % z)]
wire_in_2 = wire_names[(x, y, "lutff_%d/in_2" % z)]
wire_in_3 = wire_names[(x, y, "lutff_%d/in_3" % z)]
wire_out = wire_names[(x, y, "lutff_%d/out" % z)]
wire_cout = wire_names[(x, y, "lutff_%d/cout" % z)]
wire_lout = wire_names[(x, y, "lutff_%d/lout" % z)] if z < 7 else None
add_bel_input(bel, wire_cen, "CEN")
add_bel_input(bel, wire_clk, "CLK")
add_bel_input(bel, wire_s_r, "SR")
add_bel_input(bel, wire_cin, "CIN")
add_bel_input(bel, wire_in_0, "I0")
add_bel_input(bel, wire_in_1, "I1")
add_bel_input(bel, wire_in_2, "I2")
add_bel_input(bel, wire_in_3, "I3")
add_bel_output(bel, wire_out, "O")
add_bel_output(bel, wire_cout, "COUT")
if wire_lout is not None:
add_bel_output(bel, wire_lout, "LO")
def add_bel_io(x, y, z):
bel = len(bel_name)
bel_name.append("X%d/Y%d/io%d" % (x, y, z))
bel_type.append("SB_IO")
bel_pos.append((x, y, z))
bel_wires.append(list())
wire_cen = wire_names[(x, y, "io_global/cen")]
wire_iclk = wire_names[(x, y, "io_global/inclk")]
wire_latch = wire_names[(x, y, "io_global/latch")]
wire_oclk = wire_names[(x, y, "io_global/outclk")]
wire_din_0 = wire_names[(x, y, "io_%d/D_IN_0" % z)]
wire_din_1 = wire_names[(x, y, "io_%d/D_IN_1" % z)]
wire_dout_0 = wire_names[(x, y, "io_%d/D_OUT_0" % z)]
wire_dout_1 = wire_names[(x, y, "io_%d/D_OUT_1" % z)]
wire_out_en = wire_names[(x, y, "io_%d/OUT_ENB" % z)]
add_bel_input(bel, wire_cen, "CLOCK_ENABLE")
add_bel_input(bel, wire_iclk, "INPUT_CLK")
add_bel_input(bel, wire_oclk, "OUTPUT_CLK")
add_bel_input(bel, wire_latch, "LATCH_INPUT_VALUE")
add_bel_output(bel, wire_din_0, "D_IN_0")
add_bel_output(bel, wire_din_1, "D_IN_1")
add_bel_input(bel, wire_dout_0, "D_OUT_0")
add_bel_input(bel, wire_dout_1, "D_OUT_1")
add_bel_input(bel, wire_out_en, "OUTPUT_ENABLE")
def add_bel_ram(x, y):
bel = len(bel_name)
bel_name.append("X%d/Y%d/ram" % (x, y))
bel_type.append("ICESTORM_RAM")
bel_pos.append((x, y, 0))
bel_wires.append(list())
if (x, y, "ram/WE") in wire_names:
# iCE40 1K-style memories
y0, y1 = y, y+1
else:
# iCE40 8K-style memories
y1, y0 = y, y+1
for i in range(16):
add_bel_input (bel, wire_names[(x, y0 if i < 8 else y1, "ram/MASK_%d" % i)], "MASK_%d" % i)
add_bel_input (bel, wire_names[(x, y0 if i < 8 else y1, "ram/WDATA_%d" % i)], "WDATA_%d" % i)
add_bel_output(bel, wire_names[(x, y0 if i < 8 else y1, "ram/RDATA_%d" % i)], "RDATA_%d" % i)
for i in range(11):
add_bel_input(bel, wire_names[(x, y0, "ram/WADDR_%d" % i)], "WADDR_%d" % i)
add_bel_input(bel, wire_names[(x, y1, "ram/RADDR_%d" % i)], "RADDR_%d" % i)
add_bel_input(bel, wire_names[(x, y0, "ram/WCLK")], "WCLK")
add_bel_input(bel, wire_names[(x, y0, "ram/WCLKE")], "WCLKE")
add_bel_input(bel, wire_names[(x, y0, "ram/WE")], "WE")
add_bel_input(bel, wire_names[(x, y1, "ram/RCLK")], "RCLK")
add_bel_input(bel, wire_names[(x, y1, "ram/RCLKE")], "RCLKE")
add_bel_input(bel, wire_names[(x, y1, "ram/RE")], "RE")
def add_bel_gb(x, y, g):
bel = len(bel_name)
bel_name.append("X%d/Y%d/gb" % (x, y))
bel_type.append("SB_GB")
bel_pos.append((x, y, 0))
bel_wires.append(list())
add_bel_input(bel, wire_names[(x, y, "fabout")], "USER_SIGNAL_TO_GLOBAL_BUFFER")
add_bel_output(bel, wire_names[(x, y, "glb_netwk_%d" % g)], "GLOBAL_BUFFER_OUTPUT")
for tile_xy, tile_type in sorted(tiles.items()):
if tile_type == "logic":
for i in range(8):
add_bel_lc(tile_xy[0], tile_xy[1], i)
if tile_type == "io":
for i in range(2):
add_bel_io(tile_xy[0], tile_xy[1], i)
if tile_type == "ramb":
add_bel_ram(tile_xy[0], tile_xy[1])
if dev_name == "1k":
add_bel_gb( 7, 0, 0)
add_bel_gb( 7, 17, 1)
add_bel_gb(13, 9, 2)
add_bel_gb( 0, 9, 3)
add_bel_gb( 6, 17, 4)
add_bel_gb( 6, 0, 5)
add_bel_gb( 0, 8, 6)
add_bel_gb(13, 8, 7)
elif dev_name == "5k":
add_bel_gb(13, 0, 0)
add_bel_gb(13, 31, 1)
add_bel_gb(19, 31, 2)
add_bel_gb( 6, 31, 3)
add_bel_gb(12, 31, 4)
add_bel_gb(12, 0, 5)
add_bel_gb( 6, 0, 6)
add_bel_gb(19, 0, 7)
elif dev_name == "8k":
add_bel_gb(33, 16, 7)
add_bel_gb( 0, 16, 6)
add_bel_gb(17, 33, 1)
add_bel_gb(17, 0, 0)
add_bel_gb( 0, 17, 3)
add_bel_gb(33, 17, 2)
add_bel_gb(16, 0, 5)
add_bel_gb(16, 33, 4)
elif dev_name == "384":
add_bel_gb( 7, 4, 7)
add_bel_gb( 0, 4, 6)
add_bel_gb( 4, 9, 1)
add_bel_gb( 4, 0, 0)
add_bel_gb( 0, 5, 3)
add_bel_gb( 7, 5, 2)
add_bel_gb( 3, 0, 5)
add_bel_gb( 3, 9, 4)
class BinaryBlobAssembler:
def __init__(self, cname, endianness, ctype = "unsigned char"):
assert endianness in ["le", "be"]
self.cname = cname
self.ctype = ctype
self.endianness = endianness
self.finalized = False
self.data = bytearray()
self.comments = dict()
self.labels = dict()
self.exports = set()
self.labels_byaddr = dict()
self.ltypes_byaddr = dict()
self.strings = dict()
self.refs = dict()
def l(self, name, ltype = None, export = False):
assert not self.finalized
assert name not in self.labels
assert len(self.data) not in self.labels_byaddr
self.labels[name] = len(self.data)
if ltype is not None:
self.ltypes_byaddr[len(self.data)] = ltype
self.labels_byaddr[len(self.data)] = name
if export:
assert ltype is not None
self.exports.add(len(self.data))
def r(self, name, comment):
assert not self.finalized
assert len(self.data) % 4 == 0
assert len(self.data) not in self.refs
if name is not None:
self.refs[len(self.data)] = (name, comment)
self.data.append(0)
self.data.append(0)
self.data.append(0)
self.data.append(0)
if (name is None) and (comment is not None):
self.comments[len(self.data)] = comment + " (null reference)"
def s(self, s, comment):
assert not self.finalized
if s not in self.strings:
index = len(self.strings)
self.strings[s] = index
else:
index = self.strings[s]
self.r("str%d" % index, '%s: "%s"' % (comment, s))
def u8(self, v, comment):
assert not self.finalized
self.data.append(v)
if comment is not None:
self.comments[len(self.data)] = comment
def u16(self, v, comment):
assert not self.finalized
assert len(self.data) % 2 == 0
if self.endianness == "le":
self.data.append(v & 255)
self.data.append((v >> 8) & 255)
elif self.endianness == "be":
self.data.append((v >> 8) & 255)
self.data.append(v & 255)
else:
assert 0
if comment is not None:
self.comments[len(self.data)] = comment
def u32(self, v, comment):
assert not self.finalized
assert len(self.data) % 4 == 0
if self.endianness == "le":
self.data.append(v & 255)
self.data.append((v >> 8) & 255)
self.data.append((v >> 16) & 255)
self.data.append((v >> 24) & 255)
elif self.endianness == "be":
self.data.append((v >> 24) & 255)
self.data.append((v >> 16) & 255)
self.data.append((v >> 8) & 255)
self.data.append(v & 255)
else:
assert 0
if comment is not None:
self.comments[len(self.data)] = comment
def finalize(self):
assert not self.finalized
for s, index in self.strings.items():
self.l("str%d" % index, "char")
for c in s:
self.data.append(ord(c))
self.data.append(0)
self.finalized = True
cursor = 0
while cursor < len(self.data):
if cursor in self.refs:
v = self.labels[self.refs[cursor][0]] - cursor
if self.endianness == "le":
self.data[cursor+0] = (v & 255)
self.data[cursor+1] = ((v >> 8) & 255)
self.data[cursor+2] = ((v >> 16) & 255)
self.data[cursor+3] = ((v >> 24) & 255)
elif self.endianness == "be":
self.data[cursor+0] = ((v >> 24) & 255)
self.data[cursor+1] = ((v >> 16) & 255)
self.data[cursor+2] = ((v >> 8) & 255)
self.data[cursor+3] = (v & 255)
else:
assert 0
cursor += 4
else:
cursor += 1
def write_verbose_c(self, f):
assert self.finalized
print("%s %s[%d] = {" % (self.ctype, self.cname, len(self.data)), file=f)
cursor = 0
bytecnt = 0
while cursor < len(self.data):
if cursor in self.comments:
if bytecnt == 0:
print(" ", end="", file=f)
print(" // %s" % self.comments[cursor], file=f)
bytecnt = 0
if cursor in self.labels_byaddr:
if bytecnt != 0:
print(file=f)
if cursor in self.exports:
print("#define %s ((%s*)(%s+%d))" % (self.labels_byaddr[cursor], self.ltypes_byaddr[cursor], self.cname, cursor), file=f)
else:
print(" // [%d] %s" % (cursor, self.labels_byaddr[cursor]), file=f)
bytecnt = 0
if cursor in self.refs:
if bytecnt != 0:
print(file=f)
print(" ", end="", file=f)
print(" %-4s" % ("%d," % self.data[cursor+0]), end="", file=f)
print(" %-4s" % ("%d," % self.data[cursor+1]), end="", file=f)
print(" %-4s" % ("%d," % self.data[cursor+2]), end="", file=f)
print(" %-4s" % ("%d," % self.data[cursor+3]), end="", file=f)
print(" // [%d] %s (reference to %s)" % (cursor, self.refs[cursor][1], self.refs[cursor][0]), file=f)
bytecnt = 0
cursor += 4
else:
if bytecnt == 0:
print(" ", end="", file=f)
print(" %-4s" % ("%d," % self.data[cursor]), end=("" if bytecnt < 15 else "\n"), file=f)
bytecnt = (bytecnt + 1) & 15
cursor += 1
if bytecnt != 0:
print(file=f)
print("};", file=f)
def write_compact_c(self, f):
assert self.finalized
print("%s %s[%d] = {" % (self.ctype, self.cname, len(self.data)), file=f)
column = 0
for v in self.data:
if column == 0:
print(" ", end="", file=f)
column += 2
s = "%d," % v
print(s, end="", file=f)
column += len(s)
if column > 75:
print(file=f)
column = 0
if column != 0:
print(file=f)
for cursor in self.exports:
print("#define %s ((%s*)(%s+%d))" % (self.labels_byaddr[cursor], self.ltypes_byaddr[cursor], self.cname, cursor), file=f)
print("};", file=f)
bba = BinaryBlobAssembler("binblob_%s" % dev_name, endianness, "static uint8_t")
print('#include "nextpnr.h"')
print('namespace {')
print('USING_NEXTPNR_NAMESPACE')
index = 0
for bel in range(len(bel_name)):
bba.l("bel_wires_%d" % bel, "BelWirePOD")
for i in range(len(bel_wires[bel])):
bba.u32(bel_wires[bel][i][0], "wire_index")
bba.u32(portpins[bel_wires[bel][i][1]], "port")
index += 1
bba.l("bel_data", "BelInfoPOD", export=True)
for bel in range(len(bel_name)):
bba.s(bel_name[bel], "name")
bba.u32(beltypes[bel_type[bel]], "type")
bba.u32(len(bel_wires[bel]), "num_bel_wires")
bba.r("bel_wires_%d" % bel, "bel_wires")
bba.u8(bel_pos[bel][0], "x")
bba.u8(bel_pos[bel][1], "y")
bba.u8(bel_pos[bel][2], "z")
bba.u8(0, "padding")
wireinfo = list()
pipinfo = list()
pipcache = dict()
for wire in range(num_wires):
if wire in wire_uphill:
pips = list()
for src in wire_uphill[wire]:
if (src, wire) not in pipcache:
pipcache[(src, wire)] = len(pipinfo)
pipinfo.append(" {%d, %d, 1, %d, %d, %d, %d}" % (src, wire, pip_xy[(src, wire)][0], pip_xy[(src, wire)][1], pip_xy[(src, wire)][2], pip_xy[(src, wire)][3]))
pips.append(pipcache[(src, wire)])
num_uphill = len(pips)
list_uphill = "wire%d_uppips" % wire
bba.l(list_uphill, "int32_t")
for p in pips:
bba.u32(p, None)
else:
num_uphill = 0
list_uphill = None
if wire in wire_downhill:
pips = list()
for dst in wire_downhill[wire]:
if (wire, dst) not in pipcache:
pipcache[(wire, dst)] = len(pipinfo)
pipinfo.append(" {%d, %d, 1, %d, %d, %d, %d}" % (wire, dst, pip_xy[(wire, dst)][0], pip_xy[(wire, dst)][1], pip_xy[(wire, dst)][2], pip_xy[(wire, dst)][3]))
pips.append(pipcache[(wire, dst)])
num_downhill = len(pips)
list_downhill = "wire%d_downpips" % wire
bba.l(list_downhill, "int32_t")
for p in pips:
bba.u32(p, None)
else:
num_downhill = 0
list_downhill = None
if wire in wire_downhill_belports:
num_bels_downhill = len(wire_downhill_belports[wire])
bba.l("wire%d_downbels" % wire, "BelPortPOD")
for belport in wire_downhill_belports[wire]:
bba.u32(belport[0], "bel_index")
bba.u32(portpins[belport[1]], "port")
else:
num_bels_downhill = 0
info = dict()
info["name"] = "X%d/Y%d/%s" % wire_names_r[wire]
info["num_uphill"] = num_uphill
info["list_uphill"] = list_uphill
info["num_downhill"] = num_downhill
info["list_downhill"] = list_downhill
info["num_bels_downhill"] = num_bels_downhill
info["list_bels_downhill"] = ("wire%d_downbels" % wire) if num_bels_downhill > 0 else None
if wire in wire_uphill_belport:
info["uphill_bel"] = wire_uphill_belport[wire][0]
info["uphill_pin"] = portpins[wire_uphill_belport[wire][1]]
else:
info["uphill_bel"] = -1
info["uphill_pin"] = 0
avg_x, avg_y = 0, 0
if wire in wire_xy:
for x, y in wire_xy[wire]:
avg_x += x
avg_y += y
avg_x /= len(wire_xy[wire])
avg_y /= len(wire_xy[wire])
info["x"] = int(round(avg_x))
info["y"] = int(round(avg_y))
wireinfo.append(info)
packageinfo = []
for package in packages:
name, pins = package
safename = re.sub("[^A-Za-z0-9]", "_", name)
pins_info = []
for pin in pins:
pinname, x, y, z = pin
pin_bel = "X%d/Y%d/io%d" % (x, y, z)
bel_idx = bel_name.index(pin_bel)
pins_info.append((pinname, bel_idx))
bba.l("package_%s_pins" % safename, "PackagePinPOD", export=True)
for pi in pins_info:
bba.s(pi[0], "name")
bba.u32(pi[1], "bel_index")
packageinfo.append('{"%s", %d, package_%s_pins}' % (name, len(pins_info), safename))
tilegrid = []
for y in range(dev_height):
for x in range(dev_width):
if (x, y) in tiles:
tilegrid.append("TILE_%s" % (tiles[x, y].upper()))
else:
tilegrid.append("TILE_NONE")
tileinfo = []
for t in range(num_tile_types):
centries_info = []
for cb in tile_bits[t]:
name, bits = cb
safename = re.sub("[^A-Za-z0-9]", "_", name)
bba.l("tile%d_%s_bits" % (t, safename), "ConfigBitPOD")
for row, col in bits:
bba.u8(row, "row")
bba.u8(col, "col")
if len(bits) == 0:
bba.u32(0, "padding")
elif len(bits) % 2 == 1:
bba.u16(0, "padding")
centries_info.append((name, len(bits), t, safename))
bba.l("tile%d_config" % t, "ConfigEntryPOD", export=True)
for name, num_bits, t, safename in centries_info:
bba.s(name, "name")
bba.u32(num_bits, "num_bits")
bba.r("tile%d_%s_bits" % (t, safename), "num_bits")
if len(centries_info) == 0:
bba.u32(0, "padding")
tileinfo.append("{%d, %d, %d, tile%d_config}" % (tile_sizes[t][0], tile_sizes[t][1], len(centries_info), t))
bba.l("wire_data_%s" % dev_name, "WireInfoPOD", export=True)
for info in wireinfo:
bba.s(info["name"], "name")
bba.u32(info["num_uphill"], "num_uphill")
bba.u32(info["num_downhill"], "num_downhill")
bba.r(info["list_uphill"], "pips_uphill")
bba.r(info["list_downhill"], "pips_downhill")
bba.u32(info["num_bels_downhill"], "num_bels_downhill")
bba.u32(info["uphill_bel"], "bel_uphill.bel_index")
bba.u32(info["uphill_pin"], "bel_uphill.port")
bba.r(info["list_bels_downhill"], "bels_downhill")
bba.u16(info["x"], "x")
bba.u16(info["y"], "y")
bba.finalize()
if compact_output:
bba.write_compact_c(sys.stdout)
else:
bba.write_verbose_c(sys.stdout)
print("static PipInfoPOD pip_data_%s[%d] = {" % (dev_name, len(pipinfo)))
print(" " + ",\n ".join(pipinfo))
print("};")
switchinfo = []
switchid = 0
for switch in switches:
dst, x, y, bits = switch
bitlist = []
for b in bits:
m = cbit_re.match(b)
assert m
bitlist.append("{%d, %d}" % (int(m.group(1)), int(m.group(2))))
cbits = ", ".join(bitlist)
switchinfo.append("{%d, %d, %d, {%s}}" % (x, y, len(bits), cbits))
switchid += 1
print("static SwitchInfoPOD switch_data_%s[%d] = {" % (dev_name, len(switchinfo)))
print(" " + ",\n ".join(switchinfo))
print("};")
print("static TileInfoPOD tile_data_%s[%d] = {" % (dev_name, num_tile_types))
print(" " + ",\n ".join(tileinfo))
print("};")
iereninfo = []
for ieren in ierens:
iereninfo.append("{%d, %d, %d, %d, %d, %d}" % ieren)
print("static IerenInfoPOD ieren_data_%s[%d] = {" % (dev_name, len(iereninfo)))
print(" " + ",\n ".join(iereninfo))
print("};")
print("static BitstreamInfoPOD bits_info_%s = {" % dev_name)
print(" %d, %d, tile_data_%s, switch_data_%s, ieren_data_%s" % (len(switchinfo), len(iereninfo), dev_name, dev_name, dev_name))
print("};")
print("static TileType tile_grid_%s[%d] = {" % (dev_name, len(tilegrid)))
print(" " + ",\n ".join(tilegrid))
print("};")
print("static PackageInfoPOD package_info_%s[%d] = {" % (dev_name, len(packageinfo)))
print(" " + ",\n ".join(packageinfo))
print("};")
print('}')
print('NEXTPNR_NAMESPACE_BEGIN')
print("ChipInfoPOD chip_info_%s = {" % dev_name)
print(" %d, %d, %d, %d, %d, %d, %d," % (dev_width, dev_height, len(bel_name), num_wires, len(pipinfo), len(switchinfo), len(packageinfo)))
print(" bel_data, wire_data_%s, pip_data_%s," % (dev_name, dev_name))
print(" tile_grid_%s, &bits_info_%s, package_info_%s" % (dev_name, dev_name, dev_name))
print("};")
print('NEXTPNR_NAMESPACE_END')