From 84defd3fee71ab48c46fa1ba7c4acd49fba3cc5f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 17 Jun 2018 13:32:38 +0200 Subject: [PATCH] Minor refactoring of BinaryBlobAssembler, fix alignments Signed-off-by: Clifford Wolf --- ice40/bitstream.cc | 2 +- ice40/chip.cc | 8 +- ice40/chip.h | 29 ++++--- ice40/chipdb.py | 188 +++++++++++++++++++++++++++++---------------- 4 files changed, 144 insertions(+), 83 deletions(-) diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc index 91f5ede4..61a6959d 100644 --- a/ice40/bitstream.cc +++ b/ice40/bitstream.cc @@ -31,7 +31,7 @@ const ConfigEntryPOD &find_config(const TileInfoPOD &tile, const std::string &name) { for (int i = 0; i < tile.num_config_entries; i++) { - if (std::string(tile.entries[i].name.ptr()) == name) { + if (std::string(tile.entries[i].name.get()) == name) { return tile.entries[i]; } } diff --git a/ice40/chip.cc b/ice40/chip.cc index 1c854edf..82756531 100644 --- a/ice40/chip.cc +++ b/ice40/chip.cc @@ -153,7 +153,7 @@ BelId Chip::getBelByName(IdString name) const if (bel_by_name.empty()) { for (int i = 0; i < chip_info.num_bels; i++) - bel_by_name[chip_info.bel_data[i].name.ptr()] = i; + bel_by_name[chip_info.bel_data[i].name.get()] = i; } auto it = bel_by_name.find(name); @@ -190,7 +190,7 @@ WireId Chip::getWireBelPin(BelId bel, PortPin pin) const assert(bel != BelId()); int num_bel_wires = chip_info.bel_data[bel.index].num_bel_wires; - const BelWirePOD *bel_wires = chip_info.bel_data[bel.index].bel_wires.ptr(); + const BelWirePOD *bel_wires = chip_info.bel_data[bel.index].bel_wires.get(); for (int i = 0; i < num_bel_wires; i++) if (bel_wires[i].port == pin) { @@ -264,7 +264,7 @@ IdString Chip::getPipName(PipId pip) const BelId Chip::getPackagePinBel(const std::string &pin) const { for (int i = 0; i < package_info->num_pins; i++) { - if (package_info->pins[i].name.ptr() == pin) { + if (package_info->pins[i].name.get() == pin) { BelId id; id.index = package_info->pins[i].bel_index; return id; @@ -277,7 +277,7 @@ std::string Chip::getBelPackagePin(BelId bel) const { for (int i = 0; i < package_info->num_pins; i++) { if (package_info->pins[i].bel_index == bel.index) { - return std::string(package_info->pins[i].name.ptr()); + return std::string(package_info->pins[i].name.get()); } } return ""; diff --git a/ice40/chip.h b/ice40/chip.h index f57f9983..196d169d 100644 --- a/ice40/chip.h +++ b/ice40/chip.h @@ -72,27 +72,30 @@ PortPin portPinFromId(IdString id); // ----------------------------------------------------------------------- +/**** Everything in this section must be kept in sync with chipdb.py ****/ + template struct RelPtr { - int offset; + int32_t offset; - // RelPtr(const T *ptr) : offset(reinterpret_cast(ptr) - - // reinterpret_cast(this)) {} + // void set(const T *ptr) { + // offset = reinterpret_cast(ptr) - reinterpret_cast(this); + // } + + const T*get() const { + return reinterpret_cast(reinterpret_cast(this) + offset); + } const T&operator[](size_t index) const { - return reinterpret_cast(reinterpret_cast(this) + offset)[index]; + return get()[index]; } const T&operator*() const { - return *reinterpret_cast(reinterpret_cast(this) + offset); + return *(get()); } const T*operator->() const { - return reinterpret_cast(reinterpret_cast(this) + offset); - } - - const T*ptr() const { - return reinterpret_cast(reinterpret_cast(this) + offset); + return get(); } }; @@ -109,7 +112,7 @@ struct BelInfoPOD int32_t num_bel_wires; RelPtr bel_wires; int8_t x, y, z; - int8_t filler_0; + int8_t padding_0; } __attribute__((packed)); struct BelPortPOD @@ -222,6 +225,8 @@ extern ChipInfoPOD chip_info_1k; extern ChipInfoPOD chip_info_5k; extern ChipInfoPOD chip_info_8k; +/************************ End of chipdb section. ************************/ + // ----------------------------------------------------------------------- struct BelId @@ -481,7 +486,7 @@ struct Chip IdString getBelName(BelId bel) const { assert(bel != BelId()); - return chip_info.bel_data[bel.index].name.ptr(); + return chip_info.bel_data[bel.index].name.get(); } void bindBel(BelId bel, IdString cell) 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() + print(file=f) + print("};", file=f) -bba = BinaryBlobAssembler() + 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