diff --git a/xc7/arch.cc b/xc7/arch.cc index c4178b0a..90f8d821 100644 --- a/xc7/arch.cc +++ b/xc7/arch.cc @@ -442,44 +442,14 @@ BelId Arch::getBelByLocation(Loc loc) const BelRange Arch::getBelsByTile(int x, int y) const { BelRange br; - - br.b.cursor = Arch::getBelByLocation(Loc(x, y, 0)).index; - br.e.cursor = br.b.cursor; - - if (br.e.cursor != -1) { - while (br.e.cursor < chip_info->num_bels && chip_info->bel_data[br.e.cursor].x == x && - chip_info->bel_data[br.e.cursor].y == y) - br.e.cursor++; - } - + NPNR_ASSERT("TODO"); return br; } PortType Arch::getBelPinType(BelId bel, IdString pin) const { NPNR_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.get(); - - if (num_bel_wires < 7) { - for (int i = 0; i < num_bel_wires; i++) { - if (bel_wires[i].port == pin.index) - return PortType(bel_wires[i].type); - } - } else { - int b = 0, e = num_bel_wires - 1; - while (b <= e) { - int i = (b + e) / 2; - if (bel_wires[i].port == pin.index) - return PortType(bel_wires[i].type); - if (bel_wires[i].port > pin.index) - e = i - 1; - else - b = i + 1; - } - } - + NPNR_ASSERT("TODO"); return PORT_INOUT; } diff --git a/xc7/arch.h b/xc7/arch.h index 699d357e..0dd08949 100644 --- a/xc7/arch.h +++ b/xc7/arch.h @@ -64,210 +64,6 @@ template <> struct hash NEXTPNR_NAMESPACE_BEGIN -/**** Everything in this section must be kept in sync with chipdb.py ****/ - -template struct RelPtr -{ - int32_t offset; - - // 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 get()[index]; } - - const T &operator*() const { return *(get()); } - - const T *operator->() const { return get(); } -}; - -NPNR_PACKED_STRUCT(struct BelWirePOD { - int32_t port; - int32_t type; - int32_t wire_index; -}); - -NPNR_PACKED_STRUCT(struct BelInfoPOD { - RelPtr name; - int32_t type; - int32_t num_bel_wires; - RelPtr bel_wires; - int8_t x, y, z; - int8_t padding_0; -}); - -NPNR_PACKED_STRUCT(struct BelPortPOD { - int32_t bel_index; - int32_t port; -}); - -NPNR_PACKED_STRUCT(struct PipInfoPOD { - enum PipFlags : uint32_t - { - FLAG_NONE = 0, - FLAG_ROUTETHRU = 1, - FLAG_NOCARRY = 2 - }; - - // RelPtr name; - int32_t src, dst; - int32_t fast_delay; - int32_t slow_delay; - int8_t x, y; - int16_t src_seg, dst_seg; - int16_t switch_mask; - int32_t switch_index; - PipFlags flags; -}); - -NPNR_PACKED_STRUCT(struct WireSegmentPOD { - int8_t x, y; - int16_t index; -}); - -NPNR_PACKED_STRUCT(struct WireInfoPOD { - enum WireType : int8_t - { - WIRE_TYPE_NONE = 0, - WIRE_TYPE_GLB2LOCAL = 1, - WIRE_TYPE_GLB_NETWK = 2, - WIRE_TYPE_LOCAL = 3, - WIRE_TYPE_LUTFF_IN = 4, - WIRE_TYPE_LUTFF_IN_LUT = 5, - WIRE_TYPE_LUTFF_LOUT = 6, - WIRE_TYPE_LUTFF_OUT = 7, - WIRE_TYPE_LUTFF_COUT = 8, - WIRE_TYPE_LUTFF_GLOBAL = 9, - WIRE_TYPE_CARRY_IN_MUX = 10, - WIRE_TYPE_SP4_V = 11, - WIRE_TYPE_SP4_H = 12, - WIRE_TYPE_SP12_V = 13, - WIRE_TYPE_SP12_H = 14 - }; - - RelPtr name; - int32_t num_uphill, num_downhill; - RelPtr pips_uphill, pips_downhill; - - int32_t num_bel_pins; - RelPtr bel_pins; - - int32_t num_segments; - RelPtr segments; - - int32_t fast_delay; - int32_t slow_delay; - - int8_t x, y, z; - WireType type; -}); - -NPNR_PACKED_STRUCT(struct PackagePinPOD { - RelPtr name; - int32_t bel_index; -}); - -NPNR_PACKED_STRUCT(struct PackageInfoPOD { - RelPtr name; - int32_t num_pins; - RelPtr pins; -}); - -enum TileType : uint32_t -{ - TILE_NONE = 0, - TILE_LOGIC = 1, - TILE_IO = 2, - TILE_RAMB = 3, - TILE_RAMT = 4, - TILE_DSP0 = 5, - TILE_DSP1 = 6, - TILE_DSP2 = 7, - TILE_DSP3 = 8, - TILE_IPCON = 9 -}; - -NPNR_PACKED_STRUCT(struct ConfigBitPOD { int8_t row, col; }); - -NPNR_PACKED_STRUCT(struct ConfigEntryPOD { - RelPtr name; - int32_t num_bits; - RelPtr bits; -}); - -NPNR_PACKED_STRUCT(struct TileInfoPOD { - int8_t cols, rows; - int16_t num_config_entries; - RelPtr entries; -}); - -static const int max_switch_bits = 5; - -NPNR_PACKED_STRUCT(struct SwitchInfoPOD { - int32_t num_bits; - int32_t bel; - int8_t x, y; - ConfigBitPOD cbits[max_switch_bits]; -}); - -NPNR_PACKED_STRUCT(struct IerenInfoPOD { - int8_t iox, ioy, ioz; - int8_t ierx, iery, ierz; -}); - -NPNR_PACKED_STRUCT(struct BitstreamInfoPOD { - int32_t num_switches, num_ierens; - RelPtr tiles_nonrouting; - RelPtr switches; - RelPtr ierens; -}); - -NPNR_PACKED_STRUCT(struct BelConfigEntryPOD { - RelPtr entry_name; - RelPtr cbit_name; - int8_t x, y; - int16_t padding; -}); - -// Stores mapping between bel parameters and config bits, -// for extra cells where this mapping is non-trivial -NPNR_PACKED_STRUCT(struct BelConfigPOD { - int32_t bel_index; - int32_t num_entries; - RelPtr entries; -}); - -NPNR_PACKED_STRUCT(struct CellPathDelayPOD { - int32_t from_port; - int32_t to_port; - int32_t fast_delay; - int32_t slow_delay; -}); - -NPNR_PACKED_STRUCT(struct CellTimingPOD { - int32_t type; - int32_t num_paths; - RelPtr path_delays; -}); - -NPNR_PACKED_STRUCT(struct ChipInfoPOD { - int32_t width, height; - int32_t num_bels, num_wires, num_pips; - int32_t num_switches, num_belcfgs, num_packages; - int32_t num_timing_cells; - RelPtr bel_data; - RelPtr wire_data; - RelPtr pip_data; - RelPtr tile_grid; - RelPtr bits_info; - RelPtr bel_config; - RelPtr packages_data; - RelPtr cell_timing; -}); - struct TorcInfo { TorcInfo(BaseCtx *ctx, const std::string &inDeviceName, const std::string &inPackageName); @@ -339,8 +135,6 @@ struct TorcInfo }; extern std::unique_ptr torc_info; -/************************ End of chipdb section. ************************/ - struct BelIterator { int cursor; @@ -485,9 +279,6 @@ struct ArchArgs struct Arch : BaseCtx { - bool fast_part; - const ChipInfoPOD *chip_info; - const PackageInfoPOD *package_info; int width; int height; diff --git a/xc7/chains.cc b/xc7/chains.cc index be1d6762..819df184 100644 --- a/xc7/chains.cc +++ b/xc7/chains.cc @@ -77,7 +77,7 @@ class ChainConstrainer bool start_of_chain = true; std::vector chains; std::vector tile; - const int max_length = (ctx->chip_info->height - 2) * 8 - 2; + const int max_length = (torc_info->height - 2) * 8 - 2; auto curr_cell = carryc.cells.begin(); while (curr_cell != carryc.cells.end()) { CellInfo *cell = *curr_cell; diff --git a/xc7/chipdb.py b/xc7/chipdb.py deleted file mode 100644 index 7bdf82f0..00000000 --- a/xc7/chipdb.py +++ /dev/null @@ -1,1280 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import re -import textwrap -import argparse - -parser = argparse.ArgumentParser(description="convert ICE40 chip database") -parser.add_argument("filename", type=str, help="chipdb input filename") -parser.add_argument("-p", "--constids", type=str, help="path to constids.inc") -parser.add_argument("-g", "--gfxh", type=str, help="path to gfx.h") -parser.add_argument("--fast", type=str, help="path to timing data for fast part") -parser.add_argument("--slow", type=str, help="path to timing data for slow part") -args = parser.parse_args() - -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() - -extra_cells = dict() -extra_cell_config = dict() -packages = list() - -wire_belports = dict() - -wire_names = dict() -wire_names_r = dict() -wire_xy = dict() - -cbit_re = re.compile(r'B(\d+)\[(\d+)\]') - -constids = dict() -tiletypes = dict() -wiretypes = dict() - -gfx_wire_ids = dict() -wire_segments = dict() - -fast_timings = None -slow_timings = None - -with open(args.constids) as f: - for line in f: - if line.startswith("//"): - continue - line = line.replace("(", " ") - line = line.replace(")", " ") - line = line.split() - if len(line) == 0: - continue - assert len(line) == 2 - assert line[0] == "X" - idx = len(constids) + 1 - constids[line[1]] = idx - -constids["PLL"] = constids["ICESTORM_PLL"] -constids["WARMBOOT"] = constids["SB_WARMBOOT"] -constids["MAC16"] = constids["ICESTORM_DSP"] -constids["HFOSC"] = constids["ICESTORM_HFOSC"] -constids["LFOSC"] = constids["ICESTORM_LFOSC"] -constids["I2C"] = constids["SB_I2C"] -constids["SPI"] = constids["SB_SPI"] -constids["LEDDA_IP"] = constids["SB_LEDDA_IP"] -constids["RGBA_DRV"] = constids["SB_RGBA_DRV"] -constids["SPRAM"] = constids["ICESTORM_SPRAM"] - -with open(args.gfxh) as f: - state = 0 - for line in f: - if state == 0 and line.startswith("enum GfxTileWireId"): - state = 1 - elif state == 1 and line.startswith("};"): - state = 0 - elif state == 1 and (line.startswith("{") or line.strip() == ""): - pass - elif state == 1: - idx = len(gfx_wire_ids) - name = line.strip().rstrip(",") - gfx_wire_ids[name] = idx - -def read_timings(filename): - db = dict() - with open(filename) as f: - cell = None - for line in f: - line = line.split() - if len(line) == 0: - continue - if line[0] == "CELL": - cell = line[1] - if line[0] == "IOPATH": - key = "%s.%s.%s" % (cell, line[1], line[2]) - v1 = line[3].split(":")[2] - v2 = line[4].split(":")[2] - v1 = 0 if v1 == "*" else float(v1) - v2 = 0 if v2 == "*" else float(v2) - db[key] = max(v1, v2) - return db - -if args.fast is not None: - fast_timings = read_timings(args.fast) - -if args.slow is not None: - slow_timings = read_timings(args.slow) - -tiletypes["NONE"] = 0 -tiletypes["LOGIC"] = 1 -tiletypes["IO"] = 2 -tiletypes["RAMB"] = 3 -tiletypes["RAMT"] = 4 -tiletypes["DSP0"] = 5 -tiletypes["DSP1"] = 6 -tiletypes["DSP2"] = 7 -tiletypes["DSP3"] = 8 -tiletypes["IPCON"] = 9 - -wiretypes["NONE"] = 0 -wiretypes["GLB2LOCAL"] = 1 -wiretypes["GLB_NETWK"] = 2 -wiretypes["LOCAL"] = 3 -wiretypes["LUTFF_IN"] = 4 -wiretypes["LUTFF_IN_LUT"] = 5 -wiretypes["LUTFF_LOUT"] = 6 -wiretypes["LUTFF_OUT"] = 7 -wiretypes["LUTFF_COUT"] = 8 -wiretypes["LUTFF_GLOBAL"] = 9 -wiretypes["CARRY_IN_MUX"] = 10 -wiretypes["SP4_V"] = 11 -wiretypes["SP4_H"] = 12 -wiretypes["SP12_V"] = 13 -wiretypes["SP12_H"] = 14 - -def maj_wire_name(name): - if name[2].startswith("lutff_"): - return True - if name[2].startswith("io_"): - return True - if name[2].startswith("ram/"): - return True - if name[2].startswith("sp4_h_r_"): - return name[2] in ("sp4_h_r_0", "sp4_h_r_1", "sp4_h_r_2", "sp4_h_r_3", "sp4_h_r_4", "sp4_h_r_5", - "sp4_h_r_6", "sp4_h_r_7", "sp4_h_r_8", "sp4_h_r_9", "sp4_h_r_10", "sp4_h_r_11") - if name[2].startswith("sp4_v_b_"): - return name[2] in ("sp4_v_b_0", "sp4_v_b_1", "sp4_v_b_2", "sp4_v_b_3", "sp4_v_b_4", "sp4_v_b_5", - "sp4_v_b_6", "sp4_v_b_7", "sp4_v_b_8", "sp4_v_b_9", "sp4_v_b_10", "sp4_v_b_11") - if name[2].startswith("sp12_h_r_"): - return name[2] in ("sp12_h_r_0", "sp12_h_r_1") - if name[2].startswith("sp12_v_b_"): - return name[2] in ("sp12_v_b_0", "sp12_v_b_1") - return False - -def cmp_wire_names(newname, oldname): - if maj_wire_name(newname): - return True - if maj_wire_name(oldname): - return False - - if newname[2].startswith("sp") and oldname[2].startswith("sp"): - m1 = re.match(r".*_(\d+)$", newname[2]) - m2 = re.match(r".*_(\d+)$", oldname[2]) - if m1 and m2: - idx1 = int(m1.group(1)) - idx2 = int(m2.group(1)) - if idx1 != idx2: - return idx1 < idx2 - - return newname < oldname - -def wire_type(name): - longname = name - name = name.split('/') - - if name[0].startswith("X") and name[1].startswith("Y"): - name = name[2:] - - if name[0].startswith("sp4_v_") or name[0].startswith("sp4_r_v_") or name[0].startswith("span4_vert_"): - return "SP4_V" - - if name[0].startswith("sp4_h_") or name[0].startswith("span4_horz_"): - return "SP4_H" - - if name[0].startswith("sp12_v_") or name[0].startswith("span12_vert_"): - return "SP12_V" - - if name[0].startswith("sp12_h_") or name[0].startswith("span12_horz_"): - return "SP12_H" - - if name[0].startswith("glb2local"): - return "GLB2LOCAL" - - if name[0].startswith("glb_netwk_"): - return "GLB_NETWK" - - if name[0].startswith("local_"): - return "LOCAL" - - if name[0].startswith("lutff_"): - if name[1].startswith("in_"): - return "LUTFF_IN_LUT" if name[1].endswith("_lut") else "LUTFF_IN" - - if name[1] == "lout": - return "LUTFF_LOUT" - if name[1] == "out": - return "LUTFF_OUT" - if name[1] == "cout": - return "LUTFF_COUT" - - if name[0] == "ram": - if name[1].startswith("RADDR_"): - return "LUTFF_IN" - if name[1].startswith("WADDR_"): - return "LUTFF_IN" - if name[1].startswith("WDATA_"): - return "LUTFF_IN" - if name[1].startswith("MASK_"): - return "LUTFF_IN" - if name[1].startswith("RDATA_"): - return "LUTFF_OUT" - if name[1] in ("WCLK", "WCLKE", "WE", "RCLK", "RCLKE", "RE"): - return "LUTFF_GLOBAL" - - if name[0].startswith("io_"): - if name[1].startswith("D_IN_") or name[1] == "OUT_ENB": - return "LUTFF_IN" - if name[1].startswith("D_OUT_"): - return "LUTFF_OUT" - if name[0] == "fabout": - return "LUTFF_IN" - - if name[0] == "lutff_global" or name[0] == "io_global": - return "LUTFF_GLOBAL" - - if name[0] == "carry_in_mux": - return "CARRY_IN_MUX" - - if name[0] == "carry_in": - return "LUTFF_COUT" - - if name[0].startswith("neigh_op_"): - return "NONE" - - if name[0].startswith("padin_"): - return "NONE" - - # print("No type for wire: %s (%s)" % (longname, name), file=sys.stderr) - # assert 0 - - return "NONE" - -def pipdelay(src_idx, dst_idx, db): - if db is None: - return 0 - - src = wire_names_r[src_idx] - dst = wire_names_r[dst_idx] - src_type = wire_type(src[2]) - dst_type = wire_type(dst[2]) - - if dst[2].startswith("sp4_") or dst[2].startswith("span4_"): - if src[2].startswith("sp12_") or src[2].startswith("span12_"): - return db["Sp12to4.I.O"] - - if src[2].startswith("span4_"): - return db["IoSpan4Mux.I.O"] - - if dst[2].startswith("sp4_h_"): - return db["Span4Mux_h4.I.O"] - else: - return db["Span4Mux_v4.I.O"] - - if dst[2].startswith("sp12_") or dst[2].startswith("span12_"): - if dst[2].startswith("sp12_h_"): - return db["Span12Mux_h12.I.O"] - else: - return db["Span12Mux_v12.I.O"] - - if dst[2] in ("fabout", "clk"): - return 0 # FIXME? - - if src[2].startswith("glb_netwk_") and dst[2].startswith("glb2local_"): - return 0 # FIXME? - - if dst[2] == "carry_in_mux": - return db["ICE_CARRY_IN_MUX.carryinitin.carryinitout"] - - if dst[2] in ("lutff_global/clk", "io_global/inclk", "io_global/outclk", "ram/RCLK", "ram/WCLK"): - return db["ClkMux.I.O"] - - if dst[2] in ("lutff_global/s_r", "io_global/latch", "ram/RE", "ram/WE"): - return db["SRMux.I.O"] - - if dst[2] in ("lutff_global/cen", "io_global/cen", "ram/RCLKE", "ram/WCLKE"): - return db["CEMux.I.O"] - - if dst[2].startswith("local_"): - return db["LocalMux.I.O"] - - if src[2].startswith("local_") and dst[2] in ("io_0/D_OUT_0", "io_0/D_OUT_1", "io_0/OUT_ENB", "io_1/D_OUT_0", "io_1/D_OUT_1", "io_1/OUT_ENB"): - return db["IoInMux.I.O"] - - if re.match(r"lutff_\d+/in_\d+$", dst[2]): - return db["InMux.I.O"] - - if re.match(r"lutff_\d+/in_\d+_lut", dst[2]): - return 0 - - if re.match(r"ram/(MASK|RADDR|WADDR|WDATA)_", dst[2]): - return db["InMux.I.O"] - - if re.match(r"lutff_\d+/out", dst[2]): - if re.match(r"lutff_\d+/in_0", src[2]): - return db["LogicCell40.in0.lcout"] - if re.match(r"lutff_\d+/in_1", src[2]): - return db["LogicCell40.in1.lcout"] - if re.match(r"lutff_\d+/in_2", src[2]): - return db["LogicCell40.in2.lcout"] - if re.match(r"lutff_\d+/in_3", src[2]): - return db["LogicCell40.in3.lcout"] - - print(src, dst, src_idx, dst_idx, src_type, dst_type, file=sys.stderr) - assert 0 - -def wiredelay(wire_idx, db): - if db is None: - return 0 - - wire = wire_names_r[wire_idx] - wtype = wire_type(wire[2]) - - # FIXME - return 0 - -def init_tiletypes(device): - global num_tile_types, tile_sizes, tile_bits - if device == "5k": - num_tile_types = 10 - else: - num_tile_types = 5 - tile_sizes = {i: (0, 0) for i in range(num_tile_types)} - tile_bits = [[] for _ in range(num_tile_types)] - -with open(args.filename, "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] - init_tiletypes(dev_name) - 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((int(line[1]), int(line[2]), line[4:], -1)) - continue - - if line[0] == ".routing": - mode = ("routing", int(line[3]), int(line[1]), int(line[2])) - switches.append((int(line[1]), int(line[2]), line[4:], -1)) - 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] == ".dsp0_tile": - tiles[(int(line[1]), int(line[2]))] = "dsp0" - mode = None - continue - - if line[0] == ".dsp1_tile": - tiles[(int(line[1]), int(line[2]))] = "dsp1" - mode = None - continue - - if line[0] == ".dsp2_tile": - tiles[(int(line[1]), int(line[2]))] = "dsp2" - mode = None - continue - - if line[0] == ".dsp3_tile": - tiles[(int(line[1]), int(line[2]))] = "dsp3" - mode = None - continue - - if line[0] == ".ipcon_tile": - tiles[(int(line[1]), int(line[2]))] = "ipcon" - 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] == ".dsp0_tile_bits": - mode = ("bits", 5) - tile_sizes[5] = (int(line[1]), int(line[2])) - continue - - if line[0] == ".dsp1_tile_bits": - mode = ("bits", 6) - tile_sizes[6] = (int(line[1]), int(line[2])) - continue - - if line[0] == ".dsp2_tile_bits": - mode = ("bits", 7) - tile_sizes[7] = (int(line[1]), int(line[2])) - continue - - if line[0] == ".dsp3_tile_bits": - mode = ("bits", 8) - tile_sizes[8] = (int(line[1]), int(line[2])) - continue - - if line[0] == ".ipcon_tile_bits": - mode = ("bits", 9) - tile_sizes[9] = (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] == ".extra_cell": - if len(line) >= 5: - mode = ("extra_cell", (line[4], int(line[1]), int(line[2]), int(line[3]))) - elif line[3] == "WARMBOOT": - mode = ("extra_cell", (line[3], int(line[1]), int(line[2]), 0)) - elif line[3] == "PLL": - mode = ("extra_cell", (line[3], int(line[1]), int(line[2]), 3)) - else: - assert 0 - extra_cells[mode[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]))) - if mode[1] not in wire_segments: - wire_segments[mode[1]] = dict() - if ("TILE_WIRE_" + wname[2].upper().replace("/", "_")) in gfx_wire_ids: - wire_segments[mode[1]][(wname[0], wname[1])] = wname[2] - 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, 0) - 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 - - if mode[0] == "extra_cell": - if line[0] == "LOCKED": - extra_cells[mode[1]].append((("LOCKED_" + line[1]), (0, 0, "LOCKED"))) - else: - extra_cells[mode[1]].append((line[0], (int(line[1]), int(line[2]), line[3]))) - continue - -def add_wire(x, y, name): - global num_wires - wire_idx = num_wires - num_wires = num_wires + 1 - wname = (x, y, name) - wire_names[wname] = wire_idx - wire_names_r[wire_idx] = wname - wire_segments[wire_idx] = dict() - if ("TILE_WIRE_" + wname[2].upper().replace("/", "_")) in gfx_wire_ids: - wire_segments[wire_idx][(wname[0], wname[1])] = wname[2] - return wire_idx - -def add_switch(x, y, bel=-1): - switches.append((x, y, [], bel)) - -def add_pip(src, dst, flags=0): - x, y, _, _ = switches[-1] - - if src not in wire_downhill: - wire_downhill[src] = set() - wire_downhill[src].add(dst) - - if dst not in wire_uphill: - wire_uphill[dst] = set() - wire_uphill[dst].add(src) - - pip_xy[(src, dst)] = (x, y, 0, len(switches) - 1, flags) - -# Add virtual padin wires -for i in range(8): - add_wire(0, 0, "padin_%d" % i) - -def add_bel_input(bel, wire, port): - if wire not in wire_belports: - wire_belports[wire] = set() - wire_belports[wire].add((bel, port)) - bel_wires[bel].append((constids[port], 0, wire)) - -def add_bel_output(bel, wire, port): - if wire not in wire_belports: - wire_belports[wire] = set() - wire_belports[wire].add((bel, port)) - bel_wires[bel].append((constids[port], 1, wire)) - -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 = add_wire(x, y, "lutff_%d/in_0_lut" % z) - wire_in_1 = add_wire(x, y, "lutff_%d/in_1_lut" % z) - wire_in_2 = add_wire(x, y, "lutff_%d/in_2_lut" % z) - wire_in_3 = add_wire(x, y, "lutff_%d/in_3_lut" % 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") - - # route-through LUTs - add_switch(x, y, bel) - add_pip(wire_in_0, wire_out, 1) - add_pip(wire_in_1, wire_out, 1) - add_pip(wire_in_2, wire_out, 1) - add_pip(wire_in_3, wire_out, 1) - - # LUT permutation pips - for i in range(4): - add_switch(x, y, bel) - for j in range(4): - if (i == j) or ((i, j) == (1, 2)) or ((i, j) == (2, 1)): - flags = 0 - else: - flags = 2 - add_pip(wire_names[(x, y, "lutff_%d/in_%d" % (z, i))], - wire_names[(x, y, "lutff_%d/in_%d_lut" % (z, j))], flags) - -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(xy, x, y, g): - if xy[0] != x or xy[1] != y: - return - - bel = len(bel_name) - bel_name.append("X%d/Y%d/gb" % (x, y)) - bel_type.append("SB_GB") - bel_pos.append((x, y, 2)) - 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") - -def is_ec_wire(ec_entry): - return ec_entry[1] in wire_names - -def is_ec_output(ec_entry): - wirename = ec_entry[1][2] - if "O_" in wirename or "slf_op_" in wirename: return True - if "neigh_op_" in wirename: return True - if "glb_netwk_" in wirename: return True - return False - -def is_ec_pll_clock_output(ec, ec_entry): - return ec[0] == 'PLL' and ec_entry[0] in ('PLLOUT_A', 'PLLOUT_B') - -def add_bel_ec(ec): - ectype, x, y, z = ec - bel = len(bel_name) - extra_cell_config[bel] = [] - bel_name.append("X%d/Y%d/%s_%d" % (x, y, ectype.lower(), z)) - bel_type.append(ectype) - bel_pos.append((x, y, z)) - bel_wires.append(list()) - for entry in extra_cells[ec]: - if is_ec_wire(entry) and "glb_netwk_" not in entry[1][2]: # TODO: osc glb output conflicts with GB - if is_ec_output(entry): - add_bel_output(bel, wire_names[entry[1]], entry[0]) - else: - add_bel_input(bel, wire_names[entry[1]], entry[0]) - elif is_ec_pll_clock_output(ec, entry): - x, y, z = entry[1] - z = 'io_{}/D_IN_0'.format(z) - add_bel_output(bel, wire_names[(x, y, z)], entry[0]) - else: - extra_cell_config[bel].append(entry) - -cell_timings = {} -tmport_to_constids = { - "posedge:clk": "CLK", - "ce": "CEN", - "sr": "SR", - "in0": "I0", - "in1": "I1", - "in2": "I2", - "in3": "I3", - "carryin": "CIN", - "carryout": "COUT", - "lcout": "O", - "ltout": "LO", - "posedge:RCLK": "RCLK", - "posedge:WCLK": "WCLK", - "RCLKE": "RCLKE", - "RE": "RE", - "WCLKE": "WCLKE", - "WE": "WE", - "posedge:CLOCK": "CLOCK", - "posedge:SLEEP": "SLEEP", - "USERSIGNALTOGLOBALBUFFER": "USER_SIGNAL_TO_GLOBAL_BUFFER", - "GLOBALBUFFEROUTPUT": "GLOBAL_BUFFER_OUTPUT" -} - -for i in range(16): - tmport_to_constids["RDATA[%d]" % i] = "RDATA_%d" % i - tmport_to_constids["WDATA[%d]" % i] = "WDATA_%d" % i - tmport_to_constids["MASK[%d]" % i] = "MASK_%d" % i - tmport_to_constids["DATAOUT[%d]" % i] = "DATAOUT_%d" % i - -for i in range(11): - tmport_to_constids["RADDR[%d]" % i] = "RADDR_%d" % i - tmport_to_constids["WADDR[%d]" % i] = "WADDR_%d" % i - -def add_cell_timingdata(bel_type, timing_cell, fast_db, slow_db): - timing_entries = [] - database = slow_db if slow_db is not None else fast_db - for key in database.keys(): - skey = key.split(".") - if skey[0] == timing_cell: - if skey[1] in tmport_to_constids and skey[2] in tmport_to_constids: - iport = tmport_to_constids[skey[1]] - oport = tmport_to_constids[skey[2]] - fastdel = fast_db[key] if fast_db is not None else 0 - slowdel = slow_db[key] if slow_db is not None else 0 - timing_entries.append((iport, oport, fastdel, slowdel)) - cell_timings[bel_type] = timing_entries - -add_cell_timingdata("ICESTORM_LC", "LogicCell40", fast_timings, slow_timings) -add_cell_timingdata("SB_GB", "ICE_GB", fast_timings, slow_timings) - -if dev_name != "384": - add_cell_timingdata("ICESTORM_RAM", "SB_RAM40_4K", fast_timings, slow_timings) -if dev_name == "5k": - add_cell_timingdata("SPRAM", "SB_SPRAM256KA", fast_timings, slow_timings) - - -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 dev_name == "1k": - add_bel_gb(tile_xy, 7, 0, 0) - add_bel_gb(tile_xy, 7, 17, 1) - add_bel_gb(tile_xy, 13, 9, 2) - add_bel_gb(tile_xy, 0, 9, 3) - add_bel_gb(tile_xy, 6, 17, 4) - add_bel_gb(tile_xy, 6, 0, 5) - add_bel_gb(tile_xy, 0, 8, 6) - add_bel_gb(tile_xy, 13, 8, 7) - elif dev_name == "5k": - add_bel_gb(tile_xy, 13, 0, 0) - add_bel_gb(tile_xy, 13, 31, 1) - add_bel_gb(tile_xy, 19, 31, 2) - add_bel_gb(tile_xy, 6, 31, 3) - add_bel_gb(tile_xy, 12, 31, 4) - add_bel_gb(tile_xy, 12, 0, 5) - add_bel_gb(tile_xy, 6, 0, 6) - add_bel_gb(tile_xy, 19, 0, 7) - elif dev_name == "8k": - add_bel_gb(tile_xy, 33, 16, 7) - add_bel_gb(tile_xy, 0, 16, 6) - add_bel_gb(tile_xy, 17, 33, 1) - add_bel_gb(tile_xy, 17, 0, 0) - add_bel_gb(tile_xy, 0, 17, 3) - add_bel_gb(tile_xy, 33, 17, 2) - add_bel_gb(tile_xy, 16, 0, 5) - add_bel_gb(tile_xy, 16, 33, 4) - elif dev_name == "384": - add_bel_gb(tile_xy, 7, 4, 7) - add_bel_gb(tile_xy, 0, 4, 6) - add_bel_gb(tile_xy, 4, 9, 1) - add_bel_gb(tile_xy, 4, 0, 0) - add_bel_gb(tile_xy, 0, 5, 3) - add_bel_gb(tile_xy, 7, 5, 2) - add_bel_gb(tile_xy, 3, 0, 5) - add_bel_gb(tile_xy, 3, 9, 4) - - if tile_type == "ramb": - add_bel_ram(tile_xy[0], tile_xy[1]) - - for ec in sorted(extra_cells.keys()): - if ec[1] == tile_xy[0] and ec[2] == tile_xy[1]: - add_bel_ec(ec) - -for ec in sorted(extra_cells.keys()): - if ec[1] in (0, dev_width - 1) and ec[2] in (0, dev_height - 1): - add_bel_ec(ec) - -class BinaryBlobAssembler: - def l(self, name, ltype = None, export = False): - if ltype is None: - print("label %s" % (name,)) - else: - print("label %s %s" % (name, ltype)) - - def r(self, name, comment): - if comment is None: - print("ref %s" % (name,)) - else: - print("ref %s %s" % (name, comment)) - - def s(self, s, comment): - assert "|" not in s - print("str |%s| %s" % (s, comment)) - - def u8(self, v, comment): - if comment is None: - print("u8 %d" % (v,)) - else: - print("u8 %d %s" % (v, comment)) - - def u16(self, v, comment): - if comment is None: - print("u16 %d" % (v,)) - else: - print("u16 %d %s" % (v, comment)) - - def u32(self, v, comment): - if comment is None: - print("u32 %d" % (v,)) - else: - print("u32 %d %s" % (v, comment)) - - def pre(self, s): - print("pre %s" % s) - - def post(self, s): - print("post %s" % s) - - def push(self, name): - print("push %s" % name) - - def pop(self): - print("pop") - -bba = BinaryBlobAssembler() -bba.pre('#include "nextpnr.h"') -bba.pre('NEXTPNR_NAMESPACE_BEGIN') -bba.post('NEXTPNR_NAMESPACE_END') -bba.push("chipdb_blob_%s" % dev_name) -bba.r("chip_info_%s" % dev_name, "chip_info") - -for bel in range(len(bel_name)): - bba.l("bel_wires_%d" % bel, "BelWirePOD") - for data in sorted(bel_wires[bel]): - bba.u32(data[0], "port") - bba.u32(data[1], "type") - bba.u32(data[2], "wire_index") - -bba.l("bel_data_%s" % dev_name, "BelInfoPOD") -for bel in range(len(bel_name)): - bba.s(bel_name[bel], "name") - bba.u32(constids[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) - pi = dict() - pi["src"] = src - pi["dst"] = wire - pi["fast_delay"] = pipdelay(src, wire, fast_timings) - pi["slow_delay"] = pipdelay(src, wire, slow_timings) - pi["x"] = pip_xy[(src, wire)][0] - pi["y"] = pip_xy[(src, wire)][1] - pi["switch_mask"] = pip_xy[(src, wire)][2] - pi["switch_index"] = pip_xy[(src, wire)][3] - pi["flags"] = pip_xy[(src, wire)][4] - pipinfo.append(pi) - 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) - pi = dict() - pi["src"] = wire - pi["dst"] = dst - pi["fast_delay"] = pipdelay(wire, dst, fast_timings) - pi["slow_delay"] = pipdelay(wire, dst, slow_timings) - pi["x"] = pip_xy[(wire, dst)][0] - pi["y"] = pip_xy[(wire, dst)][1] - pi["switch_mask"] = pip_xy[(wire, dst)][2] - pi["switch_index"] = pip_xy[(wire, dst)][3] - pi["flags"] = pip_xy[(wire, dst)][4] - pipinfo.append(pi) - 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_belports: - num_bel_pins = len(wire_belports[wire]) - bba.l("wire%d_bels" % wire, "BelPortPOD") - for belport in sorted(wire_belports[wire]): - bba.u32(belport[0], "bel_index") - bba.u32(constids[belport[1]], "port") - else: - num_bel_pins = 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_bel_pins"] = num_bel_pins - info["list_bel_pins"] = ("wire%d_bels" % wire) if num_bel_pins > 0 else None - - if wire in wire_xy: - avg_x, avg_y = 0, 0 - - 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)) - else: - info["x"] = wire_names_r[wire][0] - info["y"] = wire_names_r[wire][1] - - 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") - for pi in pins_info: - bba.s(pi[0], "name") - bba.u32(pi[1], "bel_index") - packageinfo.append((name, len(pins_info), "package_%s_pins" % safename)) - -tilegrid = [] -for y in range(dev_height): - for x in range(dev_width): - if (x, y) in tiles: - tilegrid.append(tiles[x, y].upper()) - else: - tilegrid.append("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") - 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") - ti = dict() - ti["cols"] = tile_sizes[t][0] - ti["rows"] = tile_sizes[t][1] - ti["num_entries"] = len(centries_info) - ti["entries"] = "tile%d_config" % t - tileinfo.append(ti) - -bba.l("wire_data_%s" % dev_name, "WireInfoPOD") -for wire, info in enumerate(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_bel_pins"], "num_bel_pins") - bba.r(info["list_bel_pins"], "bel_pins") - bba.u32(len(wire_segments[wire]), "num_segments") - if len(wire_segments[wire]): - bba.r("wire_segments_%d" % wire, "segments") - else: - bba.u32(0, "segments") - - bba.u32(wiredelay(wire, fast_timings), "fast_delay") - bba.u32(wiredelay(wire, slow_timings), "slow_delay") - - bba.u8(info["x"], "x") - bba.u8(info["y"], "y") - bba.u8(0, "z") # FIXME - bba.u8(wiretypes[wire_type(info["name"])], "type") - -for wire in range(num_wires): - if len(wire_segments[wire]): - bba.l("wire_segments_%d" % wire, "WireSegmentPOD") - for xy, seg in sorted(wire_segments[wire].items()): - bba.u8(xy[0], "x") - bba.u8(xy[1], "y") - bba.u16(gfx_wire_ids["TILE_WIRE_" + seg.upper().replace("/", "_")], "index") - -bba.l("pip_data_%s" % dev_name, "PipInfoPOD") -for info in pipinfo: - src_seg = -1 - src_segname = wire_names_r[info["src"]] - if (info["x"], info["y"]) in wire_segments[info["src"]]: - src_segname = wire_segments[info["src"]][(info["x"], info["y"])] - src_seg = gfx_wire_ids["TILE_WIRE_" + src_segname.upper().replace("/", "_")] - src_segname = src_segname.replace("/", ".") - - dst_seg = -1 - dst_segname = wire_names_r[info["dst"]] - if (info["x"], info["y"]) in wire_segments[info["dst"]]: - dst_segname = wire_segments[info["dst"]][(info["x"], info["y"])] - dst_seg = gfx_wire_ids["TILE_WIRE_" + dst_segname.upper().replace("/", "_")] - dst_segname = dst_segname.replace("/", ".") - - # bba.s("X%d/Y%d/%s->%s" % (info["x"], info["y"], src_segname, dst_segname), "name") - bba.u32(info["src"], "src") - bba.u32(info["dst"], "dst") - bba.u32(info["fast_delay"], "fast_delay") - bba.u32(info["slow_delay"], "slow_delay") - bba.u8(info["x"], "x") - bba.u8(info["y"], "y") - bba.u16(src_seg, "src_seg") - bba.u16(dst_seg, "dst_seg") - bba.u16(info["switch_mask"], "switch_mask") - bba.u32(info["switch_index"], "switch_index") - bba.u32(info["flags"], "flags") - -switchinfo = [] -for switch in switches: - x, y, bits, bel = switch - bitlist = [] - for b in bits: - m = cbit_re.match(b) - assert m - bitlist.append((int(m.group(1)), int(m.group(2)))) - si = dict() - si["x"] = x - si["y"] = y - si["bits"] = bitlist - si["bel"] = bel - switchinfo.append(si) - -bba.l("switch_data_%s" % dev_name, "SwitchInfoPOD") -for info in switchinfo: - bba.u32(len(info["bits"]), "num_bits") - bba.u32(info["bel"], "bel") - bba.u8(info["x"], "x") - bba.u8(info["y"], "y") - for i in range(5): - if i < len(info["bits"]): - bba.u8(info["bits"][i][0], "row<%d>" % i) - bba.u8(info["bits"][i][1], "col<%d>" % i) - else: - bba.u8(0, "row<%d> (unused)" % i) - bba.u8(0, "col<%d> (unused)" % i) - -bba.l("tile_data_%s" % dev_name, "TileInfoPOD") -for info in tileinfo: - bba.u8(info["cols"], "cols") - bba.u8(info["rows"], "rows") - bba.u16(info["num_entries"], "num_entries") - bba.r(info["entries"], "entries") - -bba.l("ieren_data_%s" % dev_name, "IerenInfoPOD") -for ieren in ierens: - bba.u8(ieren[0], "iox") - bba.u8(ieren[1], "ioy") - bba.u8(ieren[2], "ioz") - bba.u8(ieren[3], "ierx") - bba.u8(ieren[4], "iery") - bba.u8(ieren[5], "ierz") - -if len(ierens) % 2 == 1: - bba.u16(0, "padding") - -bba.l("bits_info_%s" % dev_name, "BitstreamInfoPOD") -bba.u32(len(switchinfo), "num_switches") -bba.u32(len(ierens), "num_ierens") -bba.r("tile_data_%s" % dev_name, "tiles_nonrouting") -bba.r("switch_data_%s" % dev_name, "switches") -bba.r("ieren_data_%s" % dev_name, "ierens") - -bba.l("tile_grid_%s" % dev_name, "TileType") -for t in tilegrid: - bba.u32(tiletypes[t], "tiletype") - -for bel_idx, entries in sorted(extra_cell_config.items()): - if len(entries) > 0: - bba.l("bel%d_config_entries" % bel_idx, "BelConfigEntryPOD") - for entry in entries: - bba.s(entry[0], "entry_name") - bba.s(entry[1][2], "cbit_name") - bba.u8(entry[1][0], "x") - bba.u8(entry[1][1], "y") - bba.u16(0, "padding") - -if len(extra_cell_config) > 0: - bba.l("bel_config_%s" % dev_name, "BelConfigPOD") - for bel_idx, entries in sorted(extra_cell_config.items()): - bba.u32(bel_idx, "bel_index") - bba.u32(len(entries), "num_entries") - bba.r("bel%d_config_entries" % bel_idx if len(entries) > 0 else None, "entries") - -bba.l("package_info_%s" % dev_name, "PackageInfoPOD") -for info in packageinfo: - bba.s(info[0], "name") - bba.u32(info[1], "num_pins") - bba.r(info[2], "pins") - -for cell, timings in sorted(cell_timings.items()): - beltype = constids[cell] - bba.l("cell_paths_%d" % beltype, "CellPathDelayPOD") - for entry in timings: - fromport, toport, fast, slow = entry - bba.u32(constids[fromport], "from_port") - bba.u32(constids[toport], "to_port") - bba.u32(fast, "fast_delay") - bba.u32(slow, "slow_delay") - -bba.l("cell_timings_%s" % dev_name, "CellTimingPOD") -for cell, timings in sorted(cell_timings.items()): - beltype = constids[cell] - bba.u32(beltype, "type") - bba.u32(len(timings), "num_paths") - bba.r("cell_paths_%d" % beltype, "path_delays") - -bba.l("chip_info_%s" % dev_name) -bba.u32(dev_width, "dev_width") -bba.u32(dev_height, "dev_height") -bba.u32(len(bel_name), "num_bels") -bba.u32(num_wires, "num_wires") -bba.u32(len(pipinfo), "num_pips") -bba.u32(len(switchinfo), "num_switches") -bba.u32(len(extra_cell_config), "num_belcfgs") -bba.u32(len(packageinfo), "num_packages") -bba.u32(len(cell_timings), "num_timing_cells") -bba.r("bel_data_%s" % dev_name, "bel_data") -bba.r("wire_data_%s" % dev_name, "wire_data") -bba.r("pip_data_%s" % dev_name, "pip_data") -bba.r("tile_grid_%s" % dev_name, "tile_grid") -bba.r("bits_info_%s" % dev_name, "bits_info") -bba.r("bel_config_%s" % dev_name if len(extra_cell_config) > 0 else None, "bel_config") -bba.r("package_info_%s" % dev_name, "packages_data") -bba.r("cell_timings_%s" % dev_name, "cell_timing") - -bba.pop() diff --git a/xc7/main.cc b/xc7/main.cc index cac9a397..4b3dec47 100644 --- a/xc7/main.cc +++ b/xc7/main.cc @@ -87,8 +87,6 @@ void Xc7CommandHandler::customBitstream(Context *ctx) void Xc7CommandHandler::setupArchContext(Context *ctx) { - // if (vm.count("tmfuzz")) - // ice40DelayFuzzerMain(ctx); } std::unique_ptr Xc7CommandHandler::createContext() diff --git a/xc7/tmfuzz.py b/xc7/tmfuzz.py deleted file mode 100644 index 4ec2a546..00000000 --- a/xc7/tmfuzz.py +++ /dev/null @@ -1,357 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# ../nextpnr-ice40 --hx8k --tmfuzz > tmfuzz_hx8k.txt -# ../nextpnr-ice40 --lp8k --tmfuzz > tmfuzz_lp8k.txt -# ../nextpnr-ice40 --up5k --tmfuzz > tmfuzz_up5k.txt - -import numpy as np -import matplotlib.pyplot as plt -from collections import defaultdict - -device = "hx8k" -# device = "lp8k" -# device = "up5k" - -sel_src_type = "LUTFF_OUT" -sel_dst_type = "LUTFF_IN_LUT" - -#%% Read fuzz data - -src_dst_pairs = defaultdict(lambda: 0) - -delay_data = list() -all_delay_data = list() - -delay_map_sum = np.zeros((41, 41)) -delay_map_sum2 = np.zeros((41, 41)) -delay_map_count = np.zeros((41, 41)) - -same_tile_delays = list() -neighbour_tile_delays = list() - -type_delta_data = dict() - -with open("tmfuzz_%s.txt" % device, "r") as f: - for line in f: - line = line.split() - - if line[0] == "dst": - dst_xy = (int(line[1]), int(line[2])) - dst_type = line[3] - dst_wire = line[4] - - src_xy = (int(line[1]), int(line[2])) - src_type = line[3] - src_wire = line[4] - - delay = int(line[5]) - estdelay = int(line[6]) - - all_delay_data.append((delay, estdelay)) - - src_dst_pairs[src_type, dst_type] += 1 - - dx = dst_xy[0] - src_xy[0] - dy = dst_xy[1] - src_xy[1] - - if src_type == sel_src_type and dst_type == sel_dst_type: - if dx == 0 and dy == 0: - same_tile_delays.append(delay) - - elif abs(dx) <= 1 and abs(dy) <= 1: - neighbour_tile_delays.append(delay) - - else: - delay_data.append((delay, estdelay, dx, dy, 0, 0, 0)) - - relx = 20 + dst_xy[0] - src_xy[0] - rely = 20 + dst_xy[1] - src_xy[1] - - if (0 <= relx <= 40) and (0 <= rely <= 40): - delay_map_sum[relx, rely] += delay - delay_map_sum2[relx, rely] += delay*delay - delay_map_count[relx, rely] += 1 - - if dst_type == sel_dst_type: - if src_type not in type_delta_data: - type_delta_data[src_type] = list() - - type_delta_data[src_type].append((dx, dy, delay)) - -delay_data = np.array(delay_data) -all_delay_data = np.array(all_delay_data) -max_delay = np.max(delay_data[:, 0:2]) - -mean_same_tile_delays = np.mean(neighbour_tile_delays) -mean_neighbour_tile_delays = np.mean(neighbour_tile_delays) - -print("Avg same tile delay: %.2f (%.2f std, N=%d)" % \ - (mean_same_tile_delays, np.std(same_tile_delays), len(same_tile_delays))) -print("Avg neighbour tile delay: %.2f (%.2f std, N=%d)" % \ - (mean_neighbour_tile_delays, np.std(neighbour_tile_delays), len(neighbour_tile_delays))) - -#%% Apply simple low-weight bluring to fill gaps - -for i in range(0): - neigh_sum = np.zeros((41, 41)) - neigh_sum2 = np.zeros((41, 41)) - neigh_count = np.zeros((41, 41)) - - for x in range(41): - for y in range(41): - for p in range(-1, 2): - for q in range(-1, 2): - if p == 0 and q == 0: - continue - if 0 <= (x+p) <= 40: - if 0 <= (y+q) <= 40: - neigh_sum[x, y] += delay_map_sum[x+p, y+q] - neigh_sum2[x, y] += delay_map_sum2[x+p, y+q] - neigh_count[x, y] += delay_map_count[x+p, y+q] - - delay_map_sum += 0.1 * neigh_sum - delay_map_sum2 += 0.1 * neigh_sum2 - delay_map_count += 0.1 * neigh_count - -delay_map = delay_map_sum / delay_map_count -delay_map_std = np.sqrt(delay_map_count*delay_map_sum2 - delay_map_sum**2) / delay_map_count - -#%% Print src-dst-pair summary - -print("Src-Dst-Type pair summary:") -for cnt, src, dst in sorted([(v, k[0], k[1]) for k, v in src_dst_pairs.items()]): - print("%20s %20s %5d%s" % (src, dst, cnt, " *" if src == sel_src_type and dst == sel_dst_type else "")) -print() - -#%% Plot estimate vs actual delay - -plt.figure(figsize=(8, 3)) -plt.title("Estimate vs Actual Delay") -plt.plot(all_delay_data[:, 0], all_delay_data[:, 1], ".") -plt.plot(delay_data[:, 0], delay_data[:, 1], ".") -plt.plot([0, max_delay], [0, max_delay], "k") -plt.ylabel("Estimated Delay") -plt.xlabel("Actual Delay") -plt.grid() -plt.show() - -#%% Plot delay heatmap and std dev heatmap - -plt.figure(figsize=(9, 3)) -plt.subplot(121) -plt.title("Actual Delay Map") -plt.imshow(delay_map) -plt.colorbar() -plt.subplot(122) -plt.title("Standard Deviation") -plt.imshow(delay_map_std) -plt.colorbar() -plt.show() - -#%% Generate Model #0 - -def nonlinearPreprocessor0(dx, dy): - dx, dy = abs(dx), abs(dy) - values = [1.0] - values.append(dx + dy) - return np.array(values) - -A = np.zeros((41*41, len(nonlinearPreprocessor0(0, 0)))) -b = np.zeros(41*41) - -index = 0 -for x in range(41): - for y in range(41): - if delay_map_count[x, y] > 0: - A[index, :] = nonlinearPreprocessor0(x-20, y-20) - b[index] = delay_map[x, y] - index += 1 - -model0_params, _, _, _ = np.linalg.lstsq(A, b) -print("Model #0 parameters:", model0_params) - -model0_map = np.zeros((41, 41)) -for x in range(41): - for y in range(41): - v = np.dot(model0_params, nonlinearPreprocessor0(x-20, y-20)) - model0_map[x, y] = v - -plt.figure(figsize=(9, 3)) -plt.subplot(121) -plt.title("Model #0 Delay Map") -plt.imshow(model0_map) -plt.colorbar() -plt.subplot(122) -plt.title("Model #0 Error Map") -plt.imshow(model0_map - delay_map) -plt.colorbar() -plt.show() - -for i in range(delay_data.shape[0]): - dx = delay_data[i, 2] - dy = delay_data[i, 3] - delay_data[i, 4] = np.dot(model0_params, nonlinearPreprocessor0(dx, dy)) - -plt.figure(figsize=(8, 3)) -plt.title("Model #0 vs Actual Delay") -plt.plot(delay_data[:, 0], delay_data[:, 4], ".") -plt.plot(delay_map.flat, model0_map.flat, ".") -plt.plot([0, max_delay], [0, max_delay], "k") -plt.ylabel("Model #0 Delay") -plt.xlabel("Actual Delay") -plt.grid() -plt.show() - -print("In-sample RMS error: %f" % np.sqrt(np.nanmean((delay_map - model0_map)**2))) -print("Out-of-sample RMS error: %f" % np.sqrt(np.nanmean((delay_data[:, 0] - delay_data[:, 4])**2))) -print() - -#%% Generate Model #1 - -def nonlinearPreprocessor1(dx, dy): - dx, dy = abs(dx), abs(dy) - values = [1.0] - values.append(dx + dy) # 1-norm - values.append((dx**2 + dy**2)**(1/2)) # 2-norm - values.append((dx**3 + dy**3)**(1/3)) # 3-norm - return np.array(values) - -A = np.zeros((41*41, len(nonlinearPreprocessor1(0, 0)))) -b = np.zeros(41*41) - -index = 0 -for x in range(41): - for y in range(41): - if delay_map_count[x, y] > 0: - A[index, :] = nonlinearPreprocessor1(x-20, y-20) - b[index] = delay_map[x, y] - index += 1 - -model1_params, _, _, _ = np.linalg.lstsq(A, b) -print("Model #1 parameters:", model1_params) - -model1_map = np.zeros((41, 41)) -for x in range(41): - for y in range(41): - v = np.dot(model1_params, nonlinearPreprocessor1(x-20, y-20)) - model1_map[x, y] = v - -plt.figure(figsize=(9, 3)) -plt.subplot(121) -plt.title("Model #1 Delay Map") -plt.imshow(model1_map) -plt.colorbar() -plt.subplot(122) -plt.title("Model #1 Error Map") -plt.imshow(model1_map - delay_map) -plt.colorbar() -plt.show() - -for i in range(delay_data.shape[0]): - dx = delay_data[i, 2] - dy = delay_data[i, 3] - delay_data[i, 5] = np.dot(model1_params, nonlinearPreprocessor1(dx, dy)) - -plt.figure(figsize=(8, 3)) -plt.title("Model #1 vs Actual Delay") -plt.plot(delay_data[:, 0], delay_data[:, 5], ".") -plt.plot(delay_map.flat, model1_map.flat, ".") -plt.plot([0, max_delay], [0, max_delay], "k") -plt.ylabel("Model #1 Delay") -plt.xlabel("Actual Delay") -plt.grid() -plt.show() - -print("In-sample RMS error: %f" % np.sqrt(np.nanmean((delay_map - model1_map)**2))) -print("Out-of-sample RMS error: %f" % np.sqrt(np.nanmean((delay_data[:, 0] - delay_data[:, 5])**2))) -print() - -#%% Generate Model #2 - -def nonlinearPreprocessor2(v): - return np.array([1, v, np.sqrt(v)]) - -A = np.zeros((41*41, len(nonlinearPreprocessor2(0)))) -b = np.zeros(41*41) - -index = 0 -for x in range(41): - for y in range(41): - if delay_map_count[x, y] > 0: - A[index, :] = nonlinearPreprocessor2(model1_map[x, y]) - b[index] = delay_map[x, y] - index += 1 - -model2_params, _, _, _ = np.linalg.lstsq(A, b) -print("Model #2 parameters:", model2_params) - -model2_map = np.zeros((41, 41)) -for x in range(41): - for y in range(41): - v = np.dot(model1_params, nonlinearPreprocessor1(x-20, y-20)) - v = np.dot(model2_params, nonlinearPreprocessor2(v)) - model2_map[x, y] = v - -plt.figure(figsize=(9, 3)) -plt.subplot(121) -plt.title("Model #2 Delay Map") -plt.imshow(model2_map) -plt.colorbar() -plt.subplot(122) -plt.title("Model #2 Error Map") -plt.imshow(model2_map - delay_map) -plt.colorbar() -plt.show() - -for i in range(delay_data.shape[0]): - dx = delay_data[i, 2] - dy = delay_data[i, 3] - delay_data[i, 6] = np.dot(model2_params, nonlinearPreprocessor2(delay_data[i, 5])) - -plt.figure(figsize=(8, 3)) -plt.title("Model #2 vs Actual Delay") -plt.plot(delay_data[:, 0], delay_data[:, 6], ".") -plt.plot(delay_map.flat, model2_map.flat, ".") -plt.plot([0, max_delay], [0, max_delay], "k") -plt.ylabel("Model #2 Delay") -plt.xlabel("Actual Delay") -plt.grid() -plt.show() - -print("In-sample RMS error: %f" % np.sqrt(np.nanmean((delay_map - model2_map)**2))) -print("Out-of-sample RMS error: %f" % np.sqrt(np.nanmean((delay_data[:, 0] - delay_data[:, 6])**2))) -print() - -#%% Generate deltas for different source net types - -type_deltas = dict() - -print("Delay deltas for different src types:") -for src_type in sorted(type_delta_data.keys()): - deltas = list() - - for dx, dy, delay in type_delta_data[src_type]: - dx = abs(dx) - dy = abs(dy) - - if dx > 1 or dy > 1: - est = model0_params[0] + model0_params[1] * (dx + dy) - else: - est = mean_neighbour_tile_delays - deltas.append(delay - est) - - print("%15s: %8.2f (std %6.2f)" % (\ - src_type, np.mean(deltas), np.std(deltas))) - - type_deltas[src_type] = np.mean(deltas) - -#%% Print C defs of model parameters - -print("--snip--") -print("%d, %d, %d," % (mean_neighbour_tile_delays, 128 * model0_params[0], 128 * model0_params[1])) -print("%d, %d, %d, %d," % (128 * model1_params[0], 128 * model1_params[1], 128 * model1_params[2], 128 * model1_params[3])) -print("%d, %d, %d," % (128 * model2_params[0], 128 * model2_params[1], 128 * model2_params[2])) -print("%d, %d, %d, %d" % (type_deltas["LOCAL"], type_deltas["LUTFF_IN"], \ - (type_deltas["SP4_H"] + type_deltas["SP4_V"]) / 2, - (type_deltas["SP12_H"] + type_deltas["SP12_V"]) / 2)) -print("--snap--")