aboutsummaryrefslogtreecommitdiffstats
path: root/ice40/chipdb.py
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2018-06-17 13:32:38 +0200
committerClifford Wolf <clifford@clifford.at>2018-06-17 13:32:38 +0200
commit84defd3fee71ab48c46fa1ba7c4acd49fba3cc5f (patch)
tree704b423a2e4232de7619e41ac2df7d7192bd03f0 /ice40/chipdb.py
parent69e5bc5030f43d24683c677d93b8fc1e27b48972 (diff)
downloadnextpnr-84defd3fee71ab48c46fa1ba7c4acd49fba3cc5f.tar.gz
nextpnr-84defd3fee71ab48c46fa1ba7c4acd49fba3cc5f.tar.bz2
nextpnr-84defd3fee71ab48c46fa1ba7c4acd49fba3cc5f.zip
Minor refactoring of BinaryBlobAssembler, fix alignments
Signed-off-by: Clifford Wolf <clifford@clifford.at>
Diffstat (limited to 'ice40/chipdb.py')
-rw-r--r--ice40/chipdb.py190
1 files changed, 123 insertions, 67 deletions
diff --git a/ice40/chipdb.py b/ice40/chipdb.py
index bb10304b..082afc2f 100644
--- a/ice40/chipdb.py
+++ b/ice40/chipdb.py
@@ -5,6 +5,7 @@ import re
import textwrap
endianness = "le"
+compact_output = True
dev_name = None
dev_width = None
@@ -366,23 +367,36 @@ elif dev_name == "384":
add_bel_gb( 3, 9, 4)
class BinaryBlobAssembler:
- def __init__(self):
+ 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):
+ 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
self.refs[len(self.data)] = (name, comment)
self.data.append(0)
@@ -390,23 +404,28 @@ class BinaryBlobAssembler:
self.data.append(0)
self.data.append(0)
- def s(self, v, comment):
- for i in range(len(v)):
- self.data.append(ord(v[i]))
- self.data.append(0)
- if comment is not None:
- self.comments[len(self.data)] = comment
+ 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):
- if endianness == "le":
+ 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 endianness == "be":
+ elif self.endianness == "be":
self.data.append((v >> 8) & 255)
self.data.append(v & 255)
else:
@@ -415,12 +434,14 @@ class BinaryBlobAssembler:
self.comments[len(self.data)] = comment
def u32(self, v, comment):
- if endianness == "le":
+ 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 endianness == "be":
+ elif self.endianness == "be":
self.data.append((v >> 24) & 255)
self.data.append((v >> 16) & 255)
self.data.append((v >> 8) & 255)
@@ -430,53 +451,95 @@ class BinaryBlobAssembler:
if comment is not None:
self.comments[len(self.data)] = comment
- def write_c(self, f):
+ 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="")
- print(" // %s" % self.comments[cursor])
+ print(" ", end="", file=f)
+ print(" // %s" % self.comments[cursor], file=f)
bytecnt = 0
if cursor in self.labels_byaddr:
if bytecnt != 0:
- print()
- if cursor in self.ltypes_byaddr:
- print("#define %s ((%s*)(binblob_%s+%d))" % (self.labels_byaddr[cursor], self.ltypes_byaddr[cursor], dev_name, cursor))
+ 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]))
+ print(" // [%d] %s" % (cursor, self.labels_byaddr[cursor]), file=f)
bytecnt = 0
if cursor in self.refs:
- v = self.labels[self.refs[cursor][0]] - cursor
if bytecnt != 0:
- print()
- print(" ", end="")
- if endianness == "le":
- print(" %3d," % (v & 255), end="")
- print(" %3d," % ((v >> 8) & 255), end="")
- print(" %3d," % ((v >> 16) & 255), end="")
- print(" %3d," % ((v >> 24) & 255), end="")
- elif endianness == "be":
- print(" %3d," % (v & 255), end="")
- print(" %3d," % ((v >> 8) & 255), end="")
- print(" %3d," % ((v >> 16) & 255), end="")
- print(" %3d," % ((v >> 24) & 255), end="")
- else:
- assert 0
- print(" // [%d] %s (reference to %s)" % (cursor, self.refs[cursor][1], self.refs[cursor][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="")
- print(" %3d," % self.data[cursor], end=("" if bytecnt < 15 else "\n"))
+ 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()
-
-bba = BinaryBlobAssembler()
+ 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 {')
@@ -490,20 +553,16 @@ for bel in range(len(bel_name)):
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.l("bel_name_%d" % bel, "char")
- bba.s(bel_name[bel], "name: %s" % bel_name[bel])
-
-bba.l("bel_data", "BelInfoPOD")
-for bel in range(len(bel_name)):
- bba.r("bel_name_%d" % 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, "filler")
+ bba.u8(0, "padding")
wireinfo = list()
pipinfo = list()
@@ -519,7 +578,7 @@ for wire in range(num_wires):
pips.append(pipcache[(src, wire)])
num_uphill = len(pips)
list_uphill = "wire%d_uppips" % wire
- bba.l(list_uphill, "int32_t")
+ bba.l(list_uphill, "int32_t", export=True)
for p in pips:
bba.u32(p, None)
else:
@@ -535,7 +594,7 @@ for wire in range(num_wires):
pips.append(pipcache[(wire, dst)])
num_downhill = len(pips)
list_downhill = "wire%d_downpips" % wire
- bba.l(list_downhill, "int32_t")
+ bba.l(list_downhill, "int32_t", export=True)
for p in pips:
bba.u32(p, None)
else:
@@ -544,7 +603,7 @@ for wire in range(num_wires):
if wire in wire_downhill_belports:
num_bels_downhill = len(wire_downhill_belports[wire])
- bba.l("wire%d_downbels" % wire, "BelPortPOD")
+ bba.l("wire%d_downbels" % wire, "BelPortPOD", export=True)
for belport in wire_downhill_belports[wire]:
bba.u32(belport[0], "bel_index")
bba.u32(portpins[belport[1]], "port")
@@ -585,12 +644,9 @@ for package in packages:
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.l("package_%s_pins_%s" % (safename, pi[0]), "char")
- bba.s(pi[0], None)
- bba.l("package_%s_pins" % safename, "PackagePinPOD")
- for pi in pins_info:
- bba.r("package_%s_pins_%s" % (safename, pi[0]), "name")
+ bba.s(pi[0], "name")
bba.u32(pi[1], "bel_index")
packageinfo.append('{"%s", %d, package_%s_pins}' % (name, len(pins_info), safename))
@@ -613,24 +669,24 @@ for t in range(num_tile_types):
bba.u8(row, "row")
bba.u8(col, "col")
if len(bits) == 0:
- bba.u8(0, "dummy")
+ bba.u32(0, "padding")
+ elif len(bits) % 2 == 1:
+ bba.u16(0, "padding")
centries_info.append((name, len(bits), t, safename))
- for name, _, t, safename in centries_info:
- if ("str_%s" % safename) not in bba.labels:
- bba.l("str_%s" % safename, "char")
- bba.s(name, None)
- bba.l("tile%d_config" % t, "ConfigEntryPOD")
- for _, num_bits, t, safename in centries_info:
- bba.r("str_%s" % safename, "name")
+ 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.u8(0, "dummy")
+ bba.u32(0, "padding")
tileinfo.append("{%d, %d, %d, tile%d_config}" % (tile_sizes[t][0], tile_sizes[t][1], len(centries_info), t))
-print("static uint8_t binblob_%s[] = {" % dev_name)
-bba.write_c(sys.stdout)
-print("};")
+bba.finalize()
+if compact_output:
+ bba.write_compact_c(sys.stdout)
+else:
+ bba.write_verbose_c(sys.stdout)
switchinfo = []
switchid = 0