2018-05-26 20:27:21 +08:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
import sys
|
2018-06-10 00:19:20 +08:00
|
|
|
import re
|
2018-06-14 05:55:18 +08:00
|
|
|
import textwrap
|
2018-07-04 02:14:49 +08:00
|
|
|
import argparse
|
|
|
|
|
|
|
|
parser = argparse.ArgumentParser(description="convert ICE40 chip database")
|
|
|
|
parser.add_argument("filename", type=str, help="chipdb input filename")
|
2018-08-08 23:01:18 +08:00
|
|
|
parser.add_argument("-p", "--constids", type=str, help="path to constids.inc")
|
2018-07-13 03:05:09 +08:00
|
|
|
parser.add_argument("-g", "--gfxh", type=str, help="path to gfx.h")
|
2018-07-30 22:33:49 +08:00
|
|
|
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")
|
2018-07-04 02:14:49 +08:00
|
|
|
args = parser.parse_args()
|
2018-05-26 20:27:21 +08:00
|
|
|
|
|
|
|
dev_name = None
|
|
|
|
dev_width = None
|
|
|
|
dev_height = None
|
|
|
|
num_wires = None
|
|
|
|
|
2018-06-02 21:00:33 +08:00
|
|
|
tiles = dict()
|
|
|
|
|
2018-05-26 20:27:21 +08:00
|
|
|
wire_uphill = dict()
|
|
|
|
wire_downhill = dict()
|
2018-06-06 22:42:42 +08:00
|
|
|
pip_xy = dict()
|
2018-05-26 20:27:21 +08:00
|
|
|
|
2018-06-02 21:00:33 +08:00
|
|
|
bel_name = list()
|
|
|
|
bel_type = list()
|
2018-06-06 22:42:42 +08:00
|
|
|
bel_pos = list()
|
2018-06-10 00:19:20 +08:00
|
|
|
bel_wires = list()
|
2018-06-02 21:00:33 +08:00
|
|
|
|
2018-06-10 16:54:41 +08:00
|
|
|
switches = list()
|
|
|
|
|
2018-06-10 19:24:48 +08:00
|
|
|
ierens = list()
|
|
|
|
|
2018-06-23 00:35:08 +08:00
|
|
|
extra_cells = dict()
|
2018-07-19 17:14:43 +08:00
|
|
|
extra_cell_config = dict()
|
2018-06-13 17:40:28 +08:00
|
|
|
packages = list()
|
2018-11-16 07:04:55 +08:00
|
|
|
glbinfo = dict([(i, {}) for i in range(8)])
|
2018-06-13 17:40:28 +08:00
|
|
|
|
2018-07-22 17:56:51 +08:00
|
|
|
wire_belports = dict()
|
2018-06-02 21:00:33 +08:00
|
|
|
|
|
|
|
wire_names = dict()
|
|
|
|
wire_names_r = dict()
|
2018-06-06 22:42:42 +08:00
|
|
|
wire_xy = dict()
|
2018-06-02 21:00:33 +08:00
|
|
|
|
2018-06-10 17:14:50 +08:00
|
|
|
cbit_re = re.compile(r'B(\d+)\[(\d+)\]')
|
|
|
|
|
2018-08-08 23:01:18 +08:00
|
|
|
constids = dict()
|
2018-06-17 21:46:39 +08:00
|
|
|
tiletypes = dict()
|
2018-06-20 18:50:38 +08:00
|
|
|
wiretypes = dict()
|
2018-06-16 23:53:09 +08:00
|
|
|
|
2018-07-13 03:05:09 +08:00
|
|
|
gfx_wire_ids = dict()
|
2018-08-18 20:14:27 +08:00
|
|
|
gfx_wire_names = list()
|
2018-07-13 03:05:09 +08:00
|
|
|
wire_segments = dict()
|
|
|
|
|
2018-07-30 22:33:49 +08:00
|
|
|
fast_timings = None
|
|
|
|
slow_timings = None
|
|
|
|
|
2018-08-08 23:01:18 +08:00
|
|
|
with open(args.constids) as f:
|
2018-06-16 23:53:09 +08:00
|
|
|
for line in f:
|
2018-08-08 23:17:16 +08:00
|
|
|
if line.startswith("//"):
|
|
|
|
continue
|
2018-06-16 23:53:09 +08:00
|
|
|
line = line.replace("(", " ")
|
|
|
|
line = line.replace(")", " ")
|
|
|
|
line = line.split()
|
|
|
|
if len(line) == 0:
|
|
|
|
continue
|
|
|
|
assert len(line) == 2
|
|
|
|
assert line[0] == "X"
|
2018-08-08 23:01:18 +08:00
|
|
|
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"]
|
2019-06-10 17:30:01 +08:00
|
|
|
constids["LED_DRV_CUR"] = constids["SB_LED_DRV_CUR"]
|
|
|
|
constids["RGB_DRV"] = constids["SB_RGB_DRV"]
|
2018-06-16 23:53:09 +08:00
|
|
|
|
2018-07-13 03:05:09 +08:00
|
|
|
with open(args.gfxh) as f:
|
|
|
|
state = 0
|
|
|
|
for line in f:
|
2018-07-13 04:04:13 +08:00
|
|
|
if state == 0 and line.startswith("enum GfxTileWireId"):
|
2018-07-13 03:05:09 +08:00
|
|
|
state = 1
|
|
|
|
elif state == 1 and line.startswith("};"):
|
|
|
|
state = 0
|
2018-07-13 21:44:39 +08:00
|
|
|
elif state == 1 and (line.startswith("{") or line.strip() == ""):
|
2018-07-13 04:04:13 +08:00
|
|
|
pass
|
2018-07-13 03:05:09 +08:00
|
|
|
elif state == 1:
|
|
|
|
idx = len(gfx_wire_ids)
|
|
|
|
name = line.strip().rstrip(",")
|
|
|
|
gfx_wire_ids[name] = idx
|
2018-08-18 20:14:27 +08:00
|
|
|
gfx_wire_names.append(name)
|
2018-07-13 03:05:09 +08:00
|
|
|
|
2018-08-18 22:20:33 +08:00
|
|
|
def gfx_wire_alias(old, new):
|
|
|
|
assert old in gfx_wire_ids
|
|
|
|
assert new not in gfx_wire_ids
|
|
|
|
gfx_wire_ids[new] = gfx_wire_ids[old]
|
|
|
|
|
|
|
|
# GFX aliases for RAM tiles
|
|
|
|
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_0", "TILE_WIRE_RAM_RADDR_0")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_1", "TILE_WIRE_RAM_RADDR_1")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_2", "TILE_WIRE_RAM_RADDR_2")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_3", "TILE_WIRE_RAM_RADDR_3")
|
|
|
|
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_1_IN_0", "TILE_WIRE_RAM_RADDR_4")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_1_IN_1", "TILE_WIRE_RAM_RADDR_5")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_1_IN_2", "TILE_WIRE_RAM_RADDR_6")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_1_IN_3", "TILE_WIRE_RAM_RADDR_7")
|
|
|
|
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_2_IN_0", "TILE_WIRE_RAM_RADDR_8")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_2_IN_1", "TILE_WIRE_RAM_RADDR_9")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_2_IN_2", "TILE_WIRE_RAM_RADDR_10")
|
|
|
|
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_0", "TILE_WIRE_RAM_WADDR_0")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_1", "TILE_WIRE_RAM_WADDR_1")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_2", "TILE_WIRE_RAM_WADDR_2")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_3", "TILE_WIRE_RAM_WADDR_3")
|
|
|
|
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_1_IN_0", "TILE_WIRE_RAM_WADDR_4")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_1_IN_1", "TILE_WIRE_RAM_WADDR_5")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_1_IN_2", "TILE_WIRE_RAM_WADDR_6")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_1_IN_3", "TILE_WIRE_RAM_WADDR_7")
|
|
|
|
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_2_IN_0", "TILE_WIRE_RAM_WADDR_8")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_2_IN_1", "TILE_WIRE_RAM_WADDR_9")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_2_IN_2", "TILE_WIRE_RAM_WADDR_10")
|
|
|
|
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_3_IN_0", "TILE_WIRE_RAM_MASK_0")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_3_IN_1", "TILE_WIRE_RAM_MASK_1")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_3_IN_2", "TILE_WIRE_RAM_MASK_2")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_3_IN_3", "TILE_WIRE_RAM_MASK_3")
|
|
|
|
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_0", "TILE_WIRE_RAM_MASK_4")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_1", "TILE_WIRE_RAM_MASK_5")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_2", "TILE_WIRE_RAM_MASK_6")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_3", "TILE_WIRE_RAM_MASK_7")
|
|
|
|
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_3_IN_0", "TILE_WIRE_RAM_MASK_8")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_3_IN_1", "TILE_WIRE_RAM_MASK_9")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_3_IN_2", "TILE_WIRE_RAM_MASK_10")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_3_IN_3", "TILE_WIRE_RAM_MASK_11")
|
|
|
|
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_0", "TILE_WIRE_RAM_MASK_12")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_1", "TILE_WIRE_RAM_MASK_13")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_2", "TILE_WIRE_RAM_MASK_14")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_3", "TILE_WIRE_RAM_MASK_15")
|
|
|
|
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_5_IN_0", "TILE_WIRE_RAM_WDATA_0")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_5_IN_1", "TILE_WIRE_RAM_WDATA_1")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_5_IN_2", "TILE_WIRE_RAM_WDATA_2")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_5_IN_3", "TILE_WIRE_RAM_WDATA_3")
|
|
|
|
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_6_IN_0", "TILE_WIRE_RAM_WDATA_4")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_6_IN_1", "TILE_WIRE_RAM_WDATA_5")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_6_IN_2", "TILE_WIRE_RAM_WDATA_6")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_6_IN_3", "TILE_WIRE_RAM_WDATA_7")
|
|
|
|
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_5_IN_0", "TILE_WIRE_RAM_WDATA_8")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_5_IN_1", "TILE_WIRE_RAM_WDATA_9")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_5_IN_2", "TILE_WIRE_RAM_WDATA_10")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_5_IN_3", "TILE_WIRE_RAM_WDATA_11")
|
|
|
|
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_6_IN_0", "TILE_WIRE_RAM_WDATA_12")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_6_IN_1", "TILE_WIRE_RAM_WDATA_13")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_6_IN_2", "TILE_WIRE_RAM_WDATA_14")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_6_IN_3", "TILE_WIRE_RAM_WDATA_15")
|
|
|
|
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_0_OUT", "TILE_WIRE_RAM_RDATA_0")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_1_OUT", "TILE_WIRE_RAM_RDATA_1")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_2_OUT", "TILE_WIRE_RAM_RDATA_2")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_3_OUT", "TILE_WIRE_RAM_RDATA_3")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_4_OUT", "TILE_WIRE_RAM_RDATA_4")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_5_OUT", "TILE_WIRE_RAM_RDATA_5")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_6_OUT", "TILE_WIRE_RAM_RDATA_6")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_7_OUT", "TILE_WIRE_RAM_RDATA_7")
|
|
|
|
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_0_OUT", "TILE_WIRE_RAM_RDATA_8")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_1_OUT", "TILE_WIRE_RAM_RDATA_9")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_2_OUT", "TILE_WIRE_RAM_RDATA_10")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_3_OUT", "TILE_WIRE_RAM_RDATA_11")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_4_OUT", "TILE_WIRE_RAM_RDATA_12")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_5_OUT", "TILE_WIRE_RAM_RDATA_13")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_6_OUT", "TILE_WIRE_RAM_RDATA_14")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_7_OUT", "TILE_WIRE_RAM_RDATA_15")
|
|
|
|
|
|
|
|
gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_CEN", "TILE_WIRE_RAM_RCLKE")
|
|
|
|
gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_CEN", "TILE_WIRE_RAM_WCLKE")
|
|
|
|
gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_CLK", "TILE_WIRE_RAM_RCLK")
|
|
|
|
gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_CLK", "TILE_WIRE_RAM_WCLK")
|
|
|
|
gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_S_R", "TILE_WIRE_RAM_RE")
|
|
|
|
gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_S_R", "TILE_WIRE_RAM_WE")
|
|
|
|
|
|
|
|
# GFX aliases for IO tiles
|
|
|
|
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_0", "TILE_WIRE_IO_0_D_OUT_0")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_1", "TILE_WIRE_IO_0_D_OUT_1")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_0_IN_3", "TILE_WIRE_IO_0_OUT_ENB")
|
|
|
|
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_0_OUT", "TILE_WIRE_IO_0_D_IN_0")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_1_OUT", "TILE_WIRE_IO_0_D_IN_1")
|
|
|
|
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_0", "TILE_WIRE_IO_1_D_OUT_0")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_1", "TILE_WIRE_IO_1_D_OUT_1")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_4_IN_3", "TILE_WIRE_IO_1_OUT_ENB")
|
|
|
|
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_4_OUT", "TILE_WIRE_IO_1_D_IN_0")
|
|
|
|
gfx_wire_alias("TILE_WIRE_LUTFF_5_OUT", "TILE_WIRE_IO_1_D_IN_1")
|
|
|
|
|
|
|
|
gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_CEN", "TILE_WIRE_IO_GLOBAL_CEN")
|
|
|
|
gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_CLK", "TILE_WIRE_IO_GLOBAL_INCLK")
|
|
|
|
gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_S_R", "TILE_WIRE_IO_GLOBAL_OUTCLK")
|
|
|
|
|
|
|
|
gfx_wire_alias("TILE_WIRE_FUNC_GLOBAL_G0", "TILE_WIRE_IO_GLOBAL_LATCH")
|
|
|
|
|
2018-08-18 23:17:01 +08:00
|
|
|
for neigh in "BNL BNR BOT LFT RGT TNL TNR TOP".split():
|
|
|
|
for i in range(8):
|
|
|
|
gfx_wire_alias("TILE_WIRE_NEIGH_OP_%s_%d" % (neigh, i), "TILE_WIRE_LOGIC_OP_%s_%d" % (neigh, i))
|
|
|
|
|
|
|
|
# End of GFX aliases
|
|
|
|
|
|
|
|
|
2018-07-30 22:33:49 +08:00
|
|
|
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:
|
2018-07-30 22:40:56 +08:00
|
|
|
slow_timings = read_timings(args.slow)
|
2018-07-30 22:33:49 +08:00
|
|
|
|
2018-06-17 21:46:39 +08:00
|
|
|
tiletypes["NONE"] = 0
|
|
|
|
tiletypes["LOGIC"] = 1
|
|
|
|
tiletypes["IO"] = 2
|
|
|
|
tiletypes["RAMB"] = 3
|
|
|
|
tiletypes["RAMT"] = 4
|
2018-06-22 22:40:22 +08:00
|
|
|
tiletypes["DSP0"] = 5
|
|
|
|
tiletypes["DSP1"] = 6
|
|
|
|
tiletypes["DSP2"] = 7
|
|
|
|
tiletypes["DSP3"] = 8
|
|
|
|
tiletypes["IPCON"] = 9
|
2018-06-17 21:46:39 +08:00
|
|
|
|
2018-08-04 03:11:12 +08:00
|
|
|
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
|
2018-06-20 18:50:38 +08:00
|
|
|
|
2018-06-10 00:19:20 +08:00
|
|
|
def maj_wire_name(name):
|
2018-06-20 18:50:38 +08:00
|
|
|
if name[2].startswith("lutff_"):
|
|
|
|
return True
|
|
|
|
if name[2].startswith("io_"):
|
|
|
|
return True
|
|
|
|
if name[2].startswith("ram/"):
|
2018-06-10 00:19:20 +08:00
|
|
|
return True
|
2018-06-20 18:50:38 +08:00
|
|
|
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")
|
2018-06-10 00:19:20 +08:00
|
|
|
return False
|
|
|
|
|
2018-08-18 22:20:33 +08:00
|
|
|
def norm_wire_xy(x, y, name):
|
|
|
|
if name.startswith("glb_netwk_"):
|
|
|
|
return None
|
|
|
|
if name.startswith("neigh_op_"):
|
|
|
|
return None
|
|
|
|
if name.startswith("logic_op_"):
|
|
|
|
return None
|
|
|
|
if name.startswith("io_global/latch"):
|
|
|
|
return None
|
|
|
|
return None # FIXME
|
|
|
|
return (x, y)
|
|
|
|
|
2018-06-02 21:00:33 +08:00
|
|
|
def cmp_wire_names(newname, oldname):
|
2018-06-10 00:19:20 +08:00
|
|
|
if maj_wire_name(newname):
|
|
|
|
return True
|
|
|
|
if maj_wire_name(oldname):
|
|
|
|
return False
|
2018-06-20 18:50:38 +08:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2018-06-02 21:00:33 +08:00
|
|
|
return newname < oldname
|
|
|
|
|
2018-06-20 18:50:38 +08:00
|
|
|
def wire_type(name):
|
|
|
|
longname = name
|
2018-08-04 03:11:12 +08:00
|
|
|
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"
|
2018-06-20 18:50:38 +08:00
|
|
|
|
2018-07-31 22:43:19 +08:00
|
|
|
def pipdelay(src_idx, dst_idx, db):
|
2018-07-30 23:17:07 +08:00
|
|
|
if db is None:
|
|
|
|
return 0
|
|
|
|
|
2018-07-31 22:43:19 +08:00
|
|
|
src = wire_names_r[src_idx]
|
|
|
|
dst = wire_names_r[dst_idx]
|
2018-06-20 18:50:38 +08:00
|
|
|
src_type = wire_type(src[2])
|
|
|
|
dst_type = wire_type(dst[2])
|
|
|
|
|
2018-07-31 22:43:19 +08:00
|
|
|
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"]
|
2018-07-30 23:17:07 +08:00
|
|
|
|
2018-07-31 22:43:19 +08:00
|
|
|
if dst[2].startswith("sp4_h_"):
|
|
|
|
return db["Span4Mux_h4.I.O"]
|
|
|
|
else:
|
|
|
|
return db["Span4Mux_v4.I.O"]
|
2018-06-20 18:50:38 +08:00
|
|
|
|
2018-07-31 22:43:19 +08:00
|
|
|
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"]
|
2018-06-20 18:50:38 +08:00
|
|
|
|
2018-07-31 22:43:19 +08:00
|
|
|
if dst[2] in ("fabout", "clk"):
|
|
|
|
return 0 # FIXME?
|
2018-06-20 18:50:38 +08:00
|
|
|
|
2018-07-31 22:43:19 +08:00
|
|
|
if src[2].startswith("glb_netwk_") and dst[2].startswith("glb2local_"):
|
|
|
|
return 0 # FIXME?
|
2018-06-20 18:50:38 +08:00
|
|
|
|
2018-07-31 22:43:19 +08:00
|
|
|
if dst[2] == "carry_in_mux":
|
|
|
|
return db["ICE_CARRY_IN_MUX.carryinitin.carryinitout"]
|
2018-06-20 18:50:38 +08:00
|
|
|
|
2018-07-31 22:43:19 +08:00
|
|
|
if dst[2] in ("lutff_global/clk", "io_global/inclk", "io_global/outclk", "ram/RCLK", "ram/WCLK"):
|
|
|
|
return db["ClkMux.I.O"]
|
2018-06-20 18:50:38 +08:00
|
|
|
|
2018-07-31 22:43:19 +08:00
|
|
|
if dst[2] in ("lutff_global/s_r", "io_global/latch", "ram/RE", "ram/WE"):
|
|
|
|
return db["SRMux.I.O"]
|
2018-06-20 18:50:38 +08:00
|
|
|
|
2018-07-31 22:43:19 +08:00
|
|
|
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"]
|
2018-06-20 18:50:38 +08:00
|
|
|
|
2018-07-31 22:43:19 +08:00
|
|
|
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"]
|
2018-06-20 18:50:38 +08:00
|
|
|
|
2018-08-03 23:37:59 +08:00
|
|
|
if re.match(r"lutff_\d+/in_\d+$", dst[2]):
|
2018-07-31 22:43:19 +08:00
|
|
|
return db["InMux.I.O"]
|
2018-06-20 18:50:38 +08:00
|
|
|
|
2018-08-03 23:37:59 +08:00
|
|
|
if re.match(r"lutff_\d+/in_\d+_lut", dst[2]):
|
|
|
|
return 0
|
|
|
|
|
2018-07-31 22:43:19 +08:00
|
|
|
if re.match(r"ram/(MASK|RADDR|WADDR|WDATA)_", dst[2]):
|
|
|
|
return db["InMux.I.O"]
|
2018-06-20 18:50:38 +08:00
|
|
|
|
2018-08-02 22:28:47 +08:00
|
|
|
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"]
|
|
|
|
|
2018-07-31 22:43:19 +08:00
|
|
|
print(src, dst, src_idx, dst_idx, src_type, dst_type, file=sys.stderr)
|
2018-06-20 18:50:38 +08:00
|
|
|
assert 0
|
|
|
|
|
2018-07-31 22:43:19 +08:00
|
|
|
def wiredelay(wire_idx, db):
|
2018-07-30 23:17:07 +08:00
|
|
|
if db is None:
|
|
|
|
return 0
|
|
|
|
|
2018-07-31 22:43:19 +08:00
|
|
|
wire = wire_names_r[wire_idx]
|
2018-07-30 23:17:07 +08:00
|
|
|
wtype = wire_type(wire[2])
|
2018-06-22 22:40:22 +08:00
|
|
|
|
2018-07-30 23:17:07 +08:00
|
|
|
# FIXME
|
|
|
|
return 0
|
2018-06-22 23:44:26 +08:00
|
|
|
|
2018-06-22 22:40:22 +08:00
|
|
|
def init_tiletypes(device):
|
|
|
|
global num_tile_types, tile_sizes, tile_bits
|
2019-02-23 05:36:19 +08:00
|
|
|
if device in ["5k", "u4k"]:
|
2018-06-22 22:40:22 +08:00
|
|
|
num_tile_types = 10
|
|
|
|
else:
|
|
|
|
num_tile_types = 5
|
2018-06-22 22:54:05 +08:00
|
|
|
tile_sizes = {i: (0, 0) for i in range(num_tile_types)}
|
2018-06-22 22:40:22 +08:00
|
|
|
tile_bits = [[] for _ in range(num_tile_types)]
|
|
|
|
|
2018-07-04 02:14:49 +08:00
|
|
|
with open(args.filename, "r") as f:
|
2018-05-26 20:27:21 +08:00
|
|
|
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]
|
2018-06-22 22:40:22 +08:00
|
|
|
init_tiletypes(dev_name)
|
2018-05-26 20:27:21 +08:00
|
|
|
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":
|
2018-06-06 22:42:42 +08:00
|
|
|
mode = ("buffer", int(line[3]), int(line[1]), int(line[2]))
|
2018-08-02 22:28:47 +08:00
|
|
|
switches.append((int(line[1]), int(line[2]), line[4:], -1))
|
2018-05-26 20:27:21 +08:00
|
|
|
continue
|
|
|
|
|
|
|
|
if line[0] == ".routing":
|
2018-06-06 22:42:42 +08:00
|
|
|
mode = ("routing", int(line[3]), int(line[1]), int(line[2]))
|
2018-08-02 22:28:47 +08:00
|
|
|
switches.append((int(line[1]), int(line[2]), line[4:], -1))
|
2018-05-26 20:27:21 +08:00
|
|
|
continue
|
|
|
|
|
2018-06-02 21:00:33 +08:00
|
|
|
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
|
|
|
|
|
2018-06-22 22:40:22 +08:00
|
|
|
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
|
|
|
|
|
2018-06-10 17:14:50 +08:00
|
|
|
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
|
|
|
|
|
2018-06-22 22:40:22 +08:00
|
|
|
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
|
|
|
|
|
2018-06-10 19:24:48 +08:00
|
|
|
if line[0] == ".ieren":
|
|
|
|
mode = ("ieren",)
|
|
|
|
continue
|
|
|
|
|
2018-06-13 17:40:28 +08:00
|
|
|
if line[0] == ".pins":
|
|
|
|
mode = ("pins", line[1])
|
|
|
|
packages.append((line[1], []))
|
|
|
|
continue
|
|
|
|
|
2018-06-23 00:35:08 +08:00
|
|
|
if line[0] == ".extra_cell":
|
|
|
|
if len(line) >= 5:
|
|
|
|
mode = ("extra_cell", (line[4], int(line[1]), int(line[2]), int(line[3])))
|
2018-07-23 20:03:23 +08:00
|
|
|
elif line[3] == "WARMBOOT":
|
|
|
|
mode = ("extra_cell", (line[3], int(line[1]), int(line[2]), 0))
|
|
|
|
elif line[3] == "PLL":
|
2018-06-23 00:35:08 +08:00
|
|
|
mode = ("extra_cell", (line[3], int(line[1]), int(line[2]), 3))
|
2018-07-23 20:03:23 +08:00
|
|
|
else:
|
|
|
|
assert 0
|
2018-06-23 00:35:08 +08:00
|
|
|
extra_cells[mode[1]] = []
|
|
|
|
continue
|
|
|
|
|
2018-11-16 07:04:55 +08:00
|
|
|
if line[0] == ".gbufin":
|
|
|
|
mode = ("gbufin",)
|
|
|
|
continue
|
|
|
|
|
|
|
|
if line[0] == ".gbufpin":
|
|
|
|
mode = ("gbufpin",)
|
|
|
|
continue
|
|
|
|
|
|
|
|
if line[0] == ".extra_bits":
|
|
|
|
mode = ("extra_bits",)
|
|
|
|
continue
|
|
|
|
|
2018-05-26 20:27:21 +08:00
|
|
|
if (line[0][0] == ".") or (mode is None):
|
|
|
|
mode = None
|
|
|
|
continue
|
|
|
|
|
|
|
|
if mode[0] == "net":
|
2018-06-02 21:00:33 +08:00
|
|
|
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
|
2018-06-06 22:42:42 +08:00
|
|
|
if mode[1] not in wire_xy:
|
|
|
|
wire_xy[mode[1]] = list()
|
2018-08-18 22:20:33 +08:00
|
|
|
wire_xy[mode[1]].append(wname)
|
2018-07-13 03:05:09 +08:00
|
|
|
if mode[1] not in wire_segments:
|
2018-07-16 02:29:32 +08:00
|
|
|
wire_segments[mode[1]] = dict()
|
2018-07-13 03:46:16 +08:00
|
|
|
if ("TILE_WIRE_" + wname[2].upper().replace("/", "_")) in gfx_wire_ids:
|
2018-08-18 22:20:33 +08:00
|
|
|
if (wname[0], wname[1]) not in wire_segments[mode[1]]:
|
|
|
|
wire_segments[mode[1]][(wname[0], wname[1])] = list()
|
|
|
|
wire_segments[mode[1]][(wname[0], wname[1])].append(wname[2])
|
2018-05-26 20:27:21 +08:00
|
|
|
continue
|
|
|
|
|
2018-06-10 23:08:14 +08:00
|
|
|
if mode[0] in ("buffer", "routing"):
|
2018-05-26 20:27:21 +08:00
|
|
|
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)
|
2018-08-03 23:37:59 +08:00
|
|
|
pip_xy[(wire_a, wire_b)] = (mode[2], mode[3], int(line[0], 2), len(switches) - 1, 0)
|
2018-05-26 20:27:21 +08:00
|
|
|
continue
|
|
|
|
|
2018-06-10 17:14:50 +08:00
|
|
|
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))
|
2018-06-13 17:40:28 +08:00
|
|
|
continue
|
2018-06-10 17:14:50 +08:00
|
|
|
|
2018-06-10 19:24:48 +08:00
|
|
|
if mode[0] == "ieren":
|
|
|
|
ierens.append(tuple([int(_) for _ in line]))
|
2018-06-13 17:40:28 +08:00
|
|
|
continue
|
|
|
|
|
|
|
|
if mode[0] == "pins":
|
|
|
|
packages[-1][1].append((line[0], int(line[1]), int(line[2]), int(line[3])))
|
|
|
|
continue
|
|
|
|
|
2018-06-23 00:35:08 +08:00
|
|
|
if mode[0] == "extra_cell":
|
|
|
|
if line[0] == "LOCKED":
|
2018-11-17 17:18:45 +08:00
|
|
|
for pkg in line[1:]:
|
|
|
|
extra_cells[mode[1]].append((("LOCKED_" + pkg), (0, 0, "LOCKED")))
|
2018-06-23 00:35:08 +08:00
|
|
|
else:
|
|
|
|
extra_cells[mode[1]].append((line[0], (int(line[1]), int(line[2]), line[3])))
|
|
|
|
continue
|
|
|
|
|
2018-11-16 07:04:55 +08:00
|
|
|
if mode[0] == "gbufin":
|
|
|
|
idx = int(line[2])
|
|
|
|
glbinfo[idx]['gb_x'] = int(line[0])
|
|
|
|
glbinfo[idx]['gb_y'] = int(line[1])
|
|
|
|
continue
|
|
|
|
|
|
|
|
if mode[0] == "gbufpin":
|
|
|
|
idx = int(line[3])
|
|
|
|
glbinfo[idx]['pi_gb_x'] = int(line[0])
|
|
|
|
glbinfo[idx]['pi_gb_y'] = int(line[1])
|
|
|
|
glbinfo[idx]['pi_gb_pio'] = int(line[2])
|
|
|
|
continue
|
|
|
|
|
|
|
|
if mode[0] == "extra_bits":
|
|
|
|
if line[0].startswith('padin_glb_netwk.'):
|
|
|
|
idx = int(line[0].split('.')[1])
|
|
|
|
glbinfo[idx]['pi_eb_bank'] = int(line[1])
|
|
|
|
glbinfo[idx]['pi_eb_x'] = int(line[2])
|
|
|
|
glbinfo[idx]['pi_eb_y'] = int(line[3])
|
|
|
|
continue
|
|
|
|
|
2018-07-19 18:04:35 +08:00
|
|
|
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()
|
2018-08-03 23:37:59 +08:00
|
|
|
if ("TILE_WIRE_" + wname[2].upper().replace("/", "_")) in gfx_wire_ids:
|
2018-08-18 22:20:33 +08:00
|
|
|
if (wname[0], wname[1]) not in wire_segments[wire_idx]:
|
|
|
|
wire_segments[wire_idx][(wname[0], wname[1])] = list()
|
|
|
|
wire_segments[wire_idx][(wname[0], wname[1])].append(wname[2])
|
2018-08-03 23:37:59 +08:00
|
|
|
return wire_idx
|
2018-07-19 18:04:35 +08:00
|
|
|
|
2018-08-02 22:28:47 +08:00
|
|
|
def add_switch(x, y, bel=-1):
|
|
|
|
switches.append((x, y, [], bel))
|
|
|
|
|
2018-08-03 23:37:59 +08:00
|
|
|
def add_pip(src, dst, flags=0):
|
2018-08-02 22:28:47 +08:00
|
|
|
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)
|
|
|
|
|
2018-08-03 23:37:59 +08:00
|
|
|
pip_xy[(src, dst)] = (x, y, 0, len(switches) - 1, flags)
|
2018-08-02 22:28:47 +08:00
|
|
|
|
2018-06-02 21:00:33 +08:00
|
|
|
def add_bel_input(bel, wire, port):
|
2018-07-22 17:56:51 +08:00
|
|
|
if wire not in wire_belports:
|
|
|
|
wire_belports[wire] = set()
|
|
|
|
wire_belports[wire].add((bel, port))
|
2018-08-08 23:01:18 +08:00
|
|
|
bel_wires[bel].append((constids[port], 0, wire))
|
2018-06-02 21:00:33 +08:00
|
|
|
|
|
|
|
def add_bel_output(bel, wire, port):
|
2018-07-22 17:56:51 +08:00
|
|
|
if wire not in wire_belports:
|
|
|
|
wire_belports[wire] = set()
|
|
|
|
wire_belports[wire].add((bel, port))
|
2018-08-08 23:01:18 +08:00
|
|
|
bel_wires[bel].append((constids[port], 1, wire))
|
2018-06-02 21:00:33 +08:00
|
|
|
|
|
|
|
def add_bel_lc(x, y, z):
|
|
|
|
bel = len(bel_name)
|
2021-02-01 19:23:17 +08:00
|
|
|
bel_name.append((x, y, "lc%d" % z))
|
2018-06-02 21:00:33 +08:00
|
|
|
bel_type.append("ICESTORM_LC")
|
2018-06-06 22:42:42 +08:00
|
|
|
bel_pos.append((x, y, z))
|
2018-06-10 00:19:20 +08:00
|
|
|
bel_wires.append(list())
|
2018-06-02 21:00:33 +08:00
|
|
|
|
|
|
|
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))]
|
|
|
|
|
2018-08-03 23:37:59 +08:00
|
|
|
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)
|
|
|
|
|
2018-06-02 21:00:33 +08:00
|
|
|
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")
|
|
|
|
|
2018-06-10 00:19:20 +08:00
|
|
|
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")
|
2018-06-02 21:00:33 +08:00
|
|
|
|
|
|
|
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")
|
|
|
|
|
2018-08-02 22:28:47 +08:00
|
|
|
# route-through LUTs
|
|
|
|
add_switch(x, y, bel)
|
2018-08-03 23:37:59 +08:00
|
|
|
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)
|
2018-08-02 22:28:47 +08:00
|
|
|
|
2018-06-03 22:16:59 +08:00
|
|
|
def add_bel_io(x, y, z):
|
|
|
|
bel = len(bel_name)
|
2021-02-01 19:23:17 +08:00
|
|
|
bel_name.append((x, y, "io%d" % z))
|
2018-06-03 22:16:59 +08:00
|
|
|
bel_type.append("SB_IO")
|
2018-06-06 22:42:42 +08:00
|
|
|
bel_pos.append((x, y, z))
|
2018-06-10 00:19:20 +08:00
|
|
|
bel_wires.append(list())
|
2018-06-03 22:16:59 +08:00
|
|
|
|
|
|
|
wire_cen = wire_names[(x, y, "io_global/cen")]
|
|
|
|
wire_iclk = wire_names[(x, y, "io_global/inclk")]
|
2018-06-10 23:20:29 +08:00
|
|
|
wire_latch = wire_names[(x, y, "io_global/latch")]
|
|
|
|
wire_oclk = wire_names[(x, y, "io_global/outclk")]
|
2018-06-03 22:16:59 +08:00
|
|
|
|
|
|
|
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")
|
|
|
|
|
2018-11-19 08:49:52 +08:00
|
|
|
for gidx, ginfo in glbinfo.items():
|
|
|
|
if (ginfo['pi_gb_x'], ginfo['pi_gb_y'], ginfo['pi_gb_pio']) == (x,y,z):
|
|
|
|
add_bel_output(bel, wire_names[(x, y, "glb_netwk_%d" % gidx)], "GLOBAL_BUFFER_OUTPUT")
|
|
|
|
|
2018-06-04 18:37:56 +08:00
|
|
|
def add_bel_ram(x, y):
|
|
|
|
bel = len(bel_name)
|
2021-02-01 19:23:17 +08:00
|
|
|
bel_name.append((x, y, "ram"))
|
2018-06-04 18:37:56 +08:00
|
|
|
bel_type.append("ICESTORM_RAM")
|
2018-06-06 22:42:42 +08:00
|
|
|
bel_pos.append((x, y, 0))
|
2018-06-10 00:19:20 +08:00
|
|
|
bel_wires.append(list())
|
2018-06-04 18:37:56 +08:00
|
|
|
|
|
|
|
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")
|
|
|
|
|
2018-07-23 20:03:23 +08:00
|
|
|
def add_bel_gb(xy, x, y, g):
|
|
|
|
if xy[0] != x or xy[1] != y:
|
|
|
|
return
|
|
|
|
|
2018-06-10 22:31:06 +08:00
|
|
|
bel = len(bel_name)
|
2021-02-01 19:23:17 +08:00
|
|
|
bel_name.append((x, y, "gb"))
|
2018-06-10 22:31:06 +08:00
|
|
|
bel_type.append("SB_GB")
|
2018-07-23 20:03:23 +08:00
|
|
|
bel_pos.append((x, y, 2))
|
2018-06-10 22:31:06 +08:00
|
|
|
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")
|
|
|
|
|
2018-06-23 00:35:08 +08:00
|
|
|
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
|
|
|
|
|
2018-07-22 20:42:07 +08:00
|
|
|
def is_ec_pll_clock_output(ec, ec_entry):
|
|
|
|
return ec[0] == 'PLL' and ec_entry[0] in ('PLLOUT_A', 'PLLOUT_B')
|
|
|
|
|
2018-11-19 08:49:52 +08:00
|
|
|
def add_pll_clock_output(bel, ec, entry):
|
|
|
|
# Fabric output
|
|
|
|
io_x, io_y, io_z = entry[1]
|
|
|
|
io_zs = 'io_{}/D_IN_0'.format(io_z)
|
|
|
|
io_z = int(io_z)
|
|
|
|
add_bel_output(bel, wire_names[(io_x, io_y, io_zs)], entry[0])
|
|
|
|
|
|
|
|
# Global output
|
|
|
|
for gidx, ginfo in glbinfo.items():
|
|
|
|
if (ginfo['pi_gb_x'], ginfo['pi_gb_y'], ginfo['pi_gb_pio']) == (io_x, io_y, io_z):
|
|
|
|
add_bel_output(bel, wire_names[(io_x, io_y, "glb_netwk_%d" % gidx)], entry[0] + '_GLOBAL')
|
|
|
|
|
2018-06-23 00:35:08 +08:00
|
|
|
def add_bel_ec(ec):
|
|
|
|
ectype, x, y, z = ec
|
|
|
|
bel = len(bel_name)
|
2018-07-19 17:14:43 +08:00
|
|
|
extra_cell_config[bel] = []
|
2021-02-01 19:23:17 +08:00
|
|
|
bel_name.append((x, y, "%s_%d" % (ectype.lower(), z)))
|
2018-06-23 00:35:08 +08:00
|
|
|
bel_type.append(ectype)
|
|
|
|
bel_pos.append((x, y, z))
|
|
|
|
bel_wires.append(list())
|
|
|
|
for entry in extra_cells[ec]:
|
2018-11-19 08:49:52 +08:00
|
|
|
if is_ec_wire(entry):
|
2018-06-23 00:35:08 +08:00
|
|
|
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])
|
2018-07-22 20:42:07 +08:00
|
|
|
elif is_ec_pll_clock_output(ec, entry):
|
2018-11-19 08:49:52 +08:00
|
|
|
add_pll_clock_output(bel, ec, entry)
|
2018-06-23 00:35:08 +08:00
|
|
|
else:
|
2018-07-19 17:14:43 +08:00
|
|
|
extra_cell_config[bel].append(entry)
|
2019-02-22 04:34:23 +08:00
|
|
|
if ectype == "MAC16":
|
|
|
|
if y == 5:
|
|
|
|
last_dsp_y = 0 # dummy, but the wire is needed
|
|
|
|
elif y == 10:
|
|
|
|
last_dsp_y = 5
|
2019-02-25 19:36:12 +08:00
|
|
|
elif y == 13:
|
|
|
|
last_dsp_y = 5
|
2019-02-22 04:34:23 +08:00
|
|
|
elif y == 15:
|
|
|
|
last_dsp_y = 10
|
|
|
|
elif y == 23:
|
|
|
|
last_dsp_y = 23
|
|
|
|
else:
|
|
|
|
assert False, "unknown DSP y " + str(y)
|
2019-09-03 18:53:43 +08:00
|
|
|
def add_if_new(x, y, name):
|
|
|
|
if (x, y, name) in wire_names:
|
|
|
|
return wire_names[(x, y, name)]
|
|
|
|
else:
|
|
|
|
return add_wire(x, y, name)
|
|
|
|
wire_signextin = add_if_new(x, last_dsp_y, "dsp/signextout")
|
|
|
|
wire_signextout = add_if_new(x, y, "dsp/signextout")
|
|
|
|
wire_accumci = add_if_new(x, last_dsp_y, "dsp/accumco")
|
|
|
|
wire_accumco = add_if_new(x, y, "dsp/accumco")
|
2019-02-22 04:34:23 +08:00
|
|
|
add_bel_input(bel, wire_signextin, "SIGNEXTIN")
|
|
|
|
add_bel_output(bel, wire_signextout, "SIGNEXTOUT")
|
|
|
|
add_bel_input(bel, wire_accumci, "ACCUMCI")
|
|
|
|
add_bel_output(bel, wire_accumco, "ACCUMCO")
|
2018-06-23 00:35:08 +08:00
|
|
|
|
2018-08-02 21:20:43 +08:00
|
|
|
cell_timings = {}
|
2018-08-08 23:01:18 +08:00
|
|
|
tmport_to_constids = {
|
2018-08-02 21:20:43 +08:00
|
|
|
"posedge:clk": "CLK",
|
2018-08-02 22:02:43 +08:00
|
|
|
"ce": "CEN",
|
2018-08-02 21:20:43 +08:00
|
|
|
"sr": "SR",
|
|
|
|
"in0": "I0",
|
|
|
|
"in1": "I1",
|
|
|
|
"in2": "I2",
|
|
|
|
"in3": "I3",
|
|
|
|
"carryin": "CIN",
|
2018-08-02 22:02:43 +08:00
|
|
|
"carryout": "COUT",
|
2018-08-02 21:20:43 +08:00
|
|
|
"lcout": "O",
|
|
|
|
"ltout": "LO",
|
|
|
|
"posedge:RCLK": "RCLK",
|
|
|
|
"posedge:WCLK": "WCLK",
|
|
|
|
"RCLKE": "RCLKE",
|
|
|
|
"RE": "RE",
|
|
|
|
"WCLKE": "WCLKE",
|
|
|
|
"WE": "WE",
|
|
|
|
"posedge:CLOCK": "CLOCK",
|
2018-08-04 14:28:13 +08:00
|
|
|
"posedge:SLEEP": "SLEEP",
|
|
|
|
"USERSIGNALTOGLOBALBUFFER": "USER_SIGNAL_TO_GLOBAL_BUFFER",
|
|
|
|
"GLOBALBUFFEROUTPUT": "GLOBAL_BUFFER_OUTPUT"
|
2018-08-02 21:20:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
for i in range(16):
|
2018-08-08 23:01:18 +08:00
|
|
|
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
|
2018-08-02 21:20:43 +08:00
|
|
|
|
|
|
|
for i in range(11):
|
2018-08-08 23:01:18 +08:00
|
|
|
tmport_to_constids["RADDR[%d]" % i] = "RADDR_%d" % i
|
|
|
|
tmport_to_constids["WADDR[%d]" % i] = "WADDR_%d" % i
|
2018-08-02 21:20:43 +08:00
|
|
|
|
|
|
|
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:
|
2018-08-08 23:01:18 +08:00
|
|
|
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]]
|
2018-08-02 21:20:43 +08:00
|
|
|
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)
|
2018-08-04 14:28:13 +08:00
|
|
|
add_cell_timingdata("SB_GB", "ICE_GB", fast_timings, slow_timings)
|
|
|
|
|
2018-08-02 22:02:43 +08:00
|
|
|
if dev_name != "384":
|
|
|
|
add_cell_timingdata("ICESTORM_RAM", "SB_RAM40_4K", fast_timings, slow_timings)
|
2018-08-02 21:20:43 +08:00
|
|
|
if dev_name == "5k":
|
|
|
|
add_cell_timingdata("SPRAM", "SB_SPRAM256KA", fast_timings, slow_timings)
|
|
|
|
|
|
|
|
|
2018-06-02 21:00:33 +08:00
|
|
|
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)
|
2018-07-23 20:03:23 +08:00
|
|
|
|
2018-06-03 22:16:59 +08:00
|
|
|
if tile_type == "io":
|
|
|
|
for i in range(2):
|
|
|
|
add_bel_io(tile_xy[0], tile_xy[1], i)
|
2018-07-23 20:03:23 +08:00
|
|
|
|
2018-11-16 07:04:55 +08:00
|
|
|
for gidx, ginfo in glbinfo.items():
|
|
|
|
add_bel_gb(tile_xy, ginfo['gb_x'], ginfo['gb_y'], gidx)
|
2018-07-23 20:03:23 +08:00
|
|
|
|
2018-06-04 18:37:56 +08:00
|
|
|
if tile_type == "ramb":
|
|
|
|
add_bel_ram(tile_xy[0], tile_xy[1])
|
2018-06-02 21:00:33 +08:00
|
|
|
|
2018-07-23 20:03:23 +08:00
|
|
|
for ec in sorted(extra_cells.keys()):
|
|
|
|
if ec[1] == tile_xy[0] and ec[2] == tile_xy[1]:
|
|
|
|
add_bel_ec(ec)
|
2018-06-10 22:31:06 +08:00
|
|
|
|
2020-06-29 18:08:21 +08:00
|
|
|
for ec in sorted(extra_cells.keys(), key=lambda ec: (ec[1], ec[2], ec[3], ec[0])):
|
2018-07-24 17:16:33 +08:00
|
|
|
if ec[1] in (0, dev_width - 1) and ec[2] in (0, dev_height - 1):
|
2018-07-23 20:03:23 +08:00
|
|
|
add_bel_ec(ec)
|
2018-06-23 00:35:08 +08:00
|
|
|
|
2018-06-16 23:53:09 +08:00
|
|
|
class BinaryBlobAssembler:
|
2018-06-17 19:32:38 +08:00
|
|
|
def l(self, name, ltype = None, export = False):
|
2018-07-25 03:10:42 +08:00
|
|
|
if ltype is None:
|
|
|
|
print("label %s" % (name,))
|
|
|
|
else:
|
|
|
|
print("label %s %s" % (name, ltype))
|
2018-06-16 23:53:09 +08:00
|
|
|
|
|
|
|
def r(self, name, comment):
|
2018-07-25 03:10:42 +08:00
|
|
|
if comment is None:
|
|
|
|
print("ref %s" % (name,))
|
|
|
|
else:
|
|
|
|
print("ref %s %s" % (name, comment))
|
2018-06-16 23:53:09 +08:00
|
|
|
|
2021-01-28 02:34:41 +08:00
|
|
|
def r_slice(self, name, length, comment):
|
|
|
|
if comment is None:
|
|
|
|
print("ref %s" % (name,))
|
|
|
|
else:
|
|
|
|
print("ref %s %s" % (name, comment))
|
|
|
|
print ("u32 %d" % (length, ))
|
|
|
|
|
2018-06-17 19:32:38 +08:00
|
|
|
def s(self, s, comment):
|
2018-07-26 21:22:52 +08:00
|
|
|
assert "|" not in s
|
|
|
|
print("str |%s| %s" % (s, comment))
|
2018-06-16 23:53:09 +08:00
|
|
|
|
|
|
|
def u8(self, v, comment):
|
2018-07-25 03:10:42 +08:00
|
|
|
if comment is None:
|
|
|
|
print("u8 %d" % (v,))
|
|
|
|
else:
|
|
|
|
print("u8 %d %s" % (v, comment))
|
2018-06-16 23:53:09 +08:00
|
|
|
|
|
|
|
def u16(self, v, comment):
|
2018-07-25 03:10:42 +08:00
|
|
|
if comment is None:
|
|
|
|
print("u16 %d" % (v,))
|
2018-06-16 23:53:09 +08:00
|
|
|
else:
|
2018-07-25 03:10:42 +08:00
|
|
|
print("u16 %d %s" % (v, comment))
|
2018-06-16 23:53:09 +08:00
|
|
|
|
|
|
|
def u32(self, v, comment):
|
2018-07-25 03:10:42 +08:00
|
|
|
if comment is None:
|
|
|
|
print("u32 %d" % (v,))
|
2018-06-16 23:53:09 +08:00
|
|
|
else:
|
2018-07-25 03:10:42 +08:00
|
|
|
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"')
|
2020-06-25 23:11:47 +08:00
|
|
|
bba.pre('#include "embed.h"')
|
2018-07-25 03:10:42 +08:00
|
|
|
bba.pre('NEXTPNR_NAMESPACE_BEGIN')
|
2020-06-25 23:11:47 +08:00
|
|
|
bba.post('EmbeddedFile chipdb_file_%s("ice40/chipdb-%s.bin", chipdb_blob_%s);' % (dev_name, dev_name, dev_name))
|
2018-07-25 03:10:42 +08:00
|
|
|
bba.post('NEXTPNR_NAMESPACE_END')
|
|
|
|
bba.push("chipdb_blob_%s" % dev_name)
|
2018-06-17 22:12:52 +08:00
|
|
|
bba.r("chip_info_%s" % dev_name, "chip_info")
|
2018-05-26 20:27:21 +08:00
|
|
|
|
2018-08-18 20:14:27 +08:00
|
|
|
bba.l("tile_wire_names")
|
|
|
|
for name in gfx_wire_names:
|
|
|
|
bba.s(name, name)
|
|
|
|
|
2018-06-10 00:19:20 +08:00
|
|
|
for bel in range(len(bel_name)):
|
2018-06-16 23:53:09 +08:00
|
|
|
bba.l("bel_wires_%d" % bel, "BelWirePOD")
|
2018-07-31 17:55:25 +08:00
|
|
|
for data in sorted(bel_wires[bel]):
|
|
|
|
bba.u32(data[0], "port")
|
|
|
|
bba.u32(data[1], "type")
|
|
|
|
bba.u32(data[2], "wire_index")
|
2018-06-10 00:19:20 +08:00
|
|
|
|
2018-06-17 22:12:52 +08:00
|
|
|
bba.l("bel_data_%s" % dev_name, "BelInfoPOD")
|
2018-06-02 21:00:33 +08:00
|
|
|
for bel in range(len(bel_name)):
|
2021-02-01 19:23:17 +08:00
|
|
|
bba.s(bel_name[bel][-1], "name")
|
2018-08-08 23:01:18 +08:00
|
|
|
bba.u32(constids[bel_type[bel]], "type")
|
2021-01-28 02:34:41 +08:00
|
|
|
bba.r_slice("bel_wires_%d" % bel, len(bel_wires[bel]), "bel_wires")
|
2018-06-16 23:53:09 +08:00
|
|
|
bba.u8(bel_pos[bel][0], "x")
|
|
|
|
bba.u8(bel_pos[bel][1], "y")
|
|
|
|
bba.u8(bel_pos[bel][2], "z")
|
2018-06-17 19:32:38 +08:00
|
|
|
bba.u8(0, "padding")
|
2018-06-16 23:53:09 +08:00
|
|
|
|
2018-05-26 20:27:21 +08:00
|
|
|
wireinfo = list()
|
2018-06-06 21:13:41 +08:00
|
|
|
pipinfo = list()
|
|
|
|
pipcache = dict()
|
2018-05-26 20:27:21 +08:00
|
|
|
|
|
|
|
for wire in range(num_wires):
|
|
|
|
if wire in wire_uphill:
|
2018-06-06 21:13:41 +08:00
|
|
|
pips = list()
|
|
|
|
for src in wire_uphill[wire]:
|
|
|
|
if (src, wire) not in pipcache:
|
|
|
|
pipcache[(src, wire)] = len(pipinfo)
|
2018-06-17 20:46:10 +08:00
|
|
|
pi = dict()
|
|
|
|
pi["src"] = src
|
|
|
|
pi["dst"] = wire
|
2018-07-30 23:17:07 +08:00
|
|
|
pi["fast_delay"] = pipdelay(src, wire, fast_timings)
|
|
|
|
pi["slow_delay"] = pipdelay(src, wire, slow_timings)
|
2018-06-17 20:46:10 +08:00
|
|
|
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]
|
2018-08-03 23:37:59 +08:00
|
|
|
pi["flags"] = pip_xy[(src, wire)][4]
|
2018-06-17 20:46:10 +08:00
|
|
|
pipinfo.append(pi)
|
2018-06-17 00:42:29 +08:00
|
|
|
pips.append(pipcache[(src, wire)])
|
2018-06-06 21:13:41 +08:00
|
|
|
num_uphill = len(pips)
|
|
|
|
list_uphill = "wire%d_uppips" % wire
|
2018-06-17 20:30:26 +08:00
|
|
|
bba.l(list_uphill, "int32_t")
|
2018-06-17 00:42:29 +08:00
|
|
|
for p in pips:
|
|
|
|
bba.u32(p, None)
|
2018-06-06 21:13:41 +08:00
|
|
|
else:
|
|
|
|
num_uphill = 0
|
2018-06-17 20:30:26 +08:00
|
|
|
list_uphill = None
|
2018-05-26 20:27:21 +08:00
|
|
|
|
|
|
|
if wire in wire_downhill:
|
2018-06-06 21:13:41 +08:00
|
|
|
pips = list()
|
|
|
|
for dst in wire_downhill[wire]:
|
|
|
|
if (wire, dst) not in pipcache:
|
|
|
|
pipcache[(wire, dst)] = len(pipinfo)
|
2018-06-17 20:46:10 +08:00
|
|
|
pi = dict()
|
|
|
|
pi["src"] = wire
|
|
|
|
pi["dst"] = dst
|
2018-07-30 23:17:07 +08:00
|
|
|
pi["fast_delay"] = pipdelay(wire, dst, fast_timings)
|
|
|
|
pi["slow_delay"] = pipdelay(wire, dst, slow_timings)
|
2018-06-17 20:46:10 +08:00
|
|
|
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]
|
2018-08-03 23:37:59 +08:00
|
|
|
pi["flags"] = pip_xy[(wire, dst)][4]
|
2018-06-17 20:46:10 +08:00
|
|
|
pipinfo.append(pi)
|
2018-06-17 00:42:29 +08:00
|
|
|
pips.append(pipcache[(wire, dst)])
|
2018-06-06 21:13:41 +08:00
|
|
|
num_downhill = len(pips)
|
|
|
|
list_downhill = "wire%d_downpips" % wire
|
2018-06-17 20:30:26 +08:00
|
|
|
bba.l(list_downhill, "int32_t")
|
2018-06-17 00:42:29 +08:00
|
|
|
for p in pips:
|
|
|
|
bba.u32(p, None)
|
2018-06-06 21:13:41 +08:00
|
|
|
else:
|
|
|
|
num_downhill = 0
|
2018-06-17 20:30:26 +08:00
|
|
|
list_downhill = None
|
2018-05-26 20:27:21 +08:00
|
|
|
|
2018-07-22 17:56:51 +08:00
|
|
|
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")
|
2018-08-08 23:01:18 +08:00
|
|
|
bba.u32(constids[belport[1]], "port")
|
2018-07-22 17:56:51 +08:00
|
|
|
else:
|
|
|
|
num_bel_pins = 0
|
|
|
|
|
2018-06-17 20:30:26 +08:00
|
|
|
info = dict()
|
2021-02-01 19:23:17 +08:00
|
|
|
info["name"] = wire_names_r[wire][2]
|
|
|
|
info["name_x"] = wire_names_r[wire][0]
|
|
|
|
info["name_y"] = wire_names_r[wire][1]
|
2018-06-17 20:30:26 +08:00
|
|
|
|
|
|
|
info["num_uphill"] = num_uphill
|
|
|
|
info["list_uphill"] = list_uphill
|
|
|
|
|
|
|
|
info["num_downhill"] = num_downhill
|
|
|
|
info["list_downhill"] = list_downhill
|
|
|
|
|
2018-07-22 17:56:51 +08:00
|
|
|
info["num_bel_pins"] = num_bel_pins
|
|
|
|
info["list_bel_pins"] = ("wire%d_bels" % wire) if num_bel_pins > 0 else None
|
|
|
|
|
2018-08-18 22:20:33 +08:00
|
|
|
pos_xy = None
|
|
|
|
first = None
|
2018-08-04 19:33:24 +08:00
|
|
|
|
2018-08-18 22:20:33 +08:00
|
|
|
if wire in wire_xy:
|
|
|
|
for x, y, n in wire_xy[wire]:
|
|
|
|
norm_xy = norm_wire_xy(x, y, n)
|
|
|
|
if norm_xy is None:
|
|
|
|
continue
|
|
|
|
if pos_xy is None:
|
|
|
|
pos_xy = norm_xy
|
|
|
|
first = (x, y, n)
|
|
|
|
elif pos_xy != norm_xy:
|
|
|
|
print("Conflicting positions for wire %s: (%d, %d, %s) -> (%d, %d), (%d, %d, %s) -> (%d, %d)" % \
|
|
|
|
((info["name"],) + first + pos_xy + (x, y, n) + norm_xy), file=sys.stderr)
|
|
|
|
assert 0
|
|
|
|
if (pos_xy is None) and (len(wire_xy[wire]) > 1):
|
|
|
|
# print("Only 'None' positions for wire %s." % info["name"], file=sys.stderr)
|
|
|
|
# assert 0
|
|
|
|
pass
|
2018-06-06 22:42:42 +08:00
|
|
|
|
2018-08-18 22:20:33 +08:00
|
|
|
if pos_xy is None:
|
2018-08-04 19:33:24 +08:00
|
|
|
info["x"] = wire_names_r[wire][0]
|
|
|
|
info["y"] = wire_names_r[wire][1]
|
2018-08-18 22:20:33 +08:00
|
|
|
else:
|
|
|
|
info["x"] = pos_xy[0]
|
|
|
|
info["y"] = pos_xy[1]
|
2018-05-26 20:27:21 +08:00
|
|
|
|
|
|
|
wireinfo.append(info)
|
|
|
|
|
2018-06-13 17:40:28 +08:00
|
|
|
packageinfo = []
|
|
|
|
|
|
|
|
for package in packages:
|
|
|
|
name, pins = package
|
2018-06-13 18:55:08 +08:00
|
|
|
safename = re.sub("[^A-Za-z0-9]", "_", name)
|
2018-06-13 17:40:28 +08:00
|
|
|
pins_info = []
|
|
|
|
for pin in pins:
|
|
|
|
pinname, x, y, z = pin
|
2021-02-01 19:23:17 +08:00
|
|
|
pin_bel = (x, y, "io%d" % z)
|
2018-06-13 17:40:28 +08:00
|
|
|
bel_idx = bel_name.index(pin_bel)
|
2018-06-17 00:42:29 +08:00
|
|
|
pins_info.append((pinname, bel_idx))
|
2018-06-17 21:53:17 +08:00
|
|
|
bba.l("package_%s_pins" % safename, "PackagePinPOD")
|
2018-06-17 00:42:29 +08:00
|
|
|
for pi in pins_info:
|
2018-06-17 19:32:38 +08:00
|
|
|
bba.s(pi[0], "name")
|
2018-06-17 00:42:29 +08:00
|
|
|
bba.u32(pi[1], "bel_index")
|
2018-06-17 21:53:17 +08:00
|
|
|
packageinfo.append((name, len(pins_info), "package_%s_pins" % safename))
|
2018-06-13 17:40:28 +08:00
|
|
|
|
2018-06-10 16:54:41 +08:00
|
|
|
tilegrid = []
|
|
|
|
for y in range(dev_height):
|
|
|
|
for x in range(dev_width):
|
|
|
|
if (x, y) in tiles:
|
2018-06-17 21:46:39 +08:00
|
|
|
tilegrid.append(tiles[x, y].upper())
|
2018-06-10 16:54:41 +08:00
|
|
|
else:
|
2018-06-17 21:46:39 +08:00
|
|
|
tilegrid.append("NONE")
|
2018-06-10 16:54:41 +08:00
|
|
|
|
2018-06-10 17:14:50 +08:00
|
|
|
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)
|
2018-06-17 01:25:37 +08:00
|
|
|
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:
|
2018-06-17 19:32:38 +08:00
|
|
|
bba.u32(0, "padding")
|
|
|
|
elif len(bits) % 2 == 1:
|
|
|
|
bba.u16(0, "padding")
|
2018-06-17 01:25:37 +08:00
|
|
|
centries_info.append((name, len(bits), t, safename))
|
2018-06-17 21:15:49 +08:00
|
|
|
bba.l("tile%d_config" % t, "ConfigEntryPOD")
|
2018-06-17 19:32:38 +08:00
|
|
|
for name, num_bits, t, safename in centries_info:
|
|
|
|
bba.s(name, "name")
|
2021-01-28 02:34:41 +08:00
|
|
|
bba.r_slice("tile%d_%s_bits" % (t, safename), num_bits, "num_bits")
|
2018-06-17 01:25:37 +08:00
|
|
|
if len(centries_info) == 0:
|
2018-06-17 19:32:38 +08:00
|
|
|
bba.u32(0, "padding")
|
2018-06-17 21:15:49 +08:00
|
|
|
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)
|
2018-06-10 17:14:50 +08:00
|
|
|
|
2018-06-17 22:12:52 +08:00
|
|
|
bba.l("wire_data_%s" % dev_name, "WireInfoPOD")
|
2018-07-13 03:05:09 +08:00
|
|
|
for wire, info in enumerate(wireinfo):
|
2022-03-31 03:57:00 +08:00
|
|
|
bba.s(info["name"].replace('/', ':'), "name") # / is used as an IdStringList separator; can't also be within name
|
2021-02-01 19:23:17 +08:00
|
|
|
bba.u8(info["name_x"], "name_x")
|
|
|
|
bba.u8(info["name_y"], "name_y")
|
|
|
|
bba.u16(0, "padding")
|
2021-01-28 02:34:41 +08:00
|
|
|
bba.r_slice(info["list_uphill"], info["num_uphill"], "pips_uphill")
|
|
|
|
bba.r_slice(info["list_downhill"], info["num_downhill"], "pips_downhill")
|
|
|
|
bba.r_slice(info["list_bel_pins"], info["num_bel_pins"], "bel_pins")
|
2018-08-18 22:20:33 +08:00
|
|
|
|
|
|
|
num_segments = 0
|
|
|
|
for segs in wire_segments[wire].values():
|
|
|
|
num_segments += len(segs)
|
|
|
|
|
|
|
|
if num_segments:
|
2021-01-28 02:34:41 +08:00
|
|
|
bba.r_slice("wire_segments_%d" % wire, num_segments, "segments")
|
2018-07-13 03:05:09 +08:00
|
|
|
else:
|
|
|
|
bba.u32(0, "segments")
|
2021-01-28 02:34:41 +08:00
|
|
|
bba.u32(0, "segments_len")
|
2018-07-16 02:29:32 +08:00
|
|
|
|
2018-07-30 23:17:07 +08:00
|
|
|
bba.u32(wiredelay(wire, fast_timings), "fast_delay")
|
|
|
|
bba.u32(wiredelay(wire, slow_timings), "slow_delay")
|
2018-07-30 22:21:03 +08:00
|
|
|
|
2018-06-20 18:50:38 +08:00
|
|
|
bba.u8(info["x"], "x")
|
|
|
|
bba.u8(info["y"], "y")
|
2018-08-05 01:50:49 +08:00
|
|
|
bba.u8(0, "z") # FIXME
|
2018-06-20 18:50:38 +08:00
|
|
|
bba.u8(wiretypes[wire_type(info["name"])], "type")
|
2018-06-17 20:30:26 +08:00
|
|
|
|
2018-07-13 03:05:09 +08:00
|
|
|
for wire in range(num_wires):
|
|
|
|
if len(wire_segments[wire]):
|
|
|
|
bba.l("wire_segments_%d" % wire, "WireSegmentPOD")
|
2018-08-18 22:20:33 +08:00
|
|
|
for xy, segs in sorted(wire_segments[wire].items()):
|
|
|
|
for seg in segs:
|
|
|
|
bba.u8(xy[0], "x")
|
|
|
|
bba.u8(xy[1], "y")
|
|
|
|
bba.u16(gfx_wire_ids["TILE_WIRE_" + seg.upper().replace("/", "_")], "index")
|
2018-07-13 03:05:09 +08:00
|
|
|
|
2018-06-17 22:12:52 +08:00
|
|
|
bba.l("pip_data_%s" % dev_name, "PipInfoPOD")
|
2018-06-17 20:46:10 +08:00
|
|
|
for info in pipinfo:
|
2018-07-16 02:29:32 +08:00
|
|
|
src_seg = -1
|
|
|
|
src_segname = wire_names_r[info["src"]]
|
|
|
|
if (info["x"], info["y"]) in wire_segments[info["src"]]:
|
2018-08-18 22:20:33 +08:00
|
|
|
src_segname = wire_segments[info["src"]][(info["x"], info["y"])][0]
|
2018-07-16 02:29:32 +08:00
|
|
|
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"]]:
|
2018-08-18 22:20:33 +08:00
|
|
|
dst_segname = wire_segments[info["dst"]][(info["x"], info["y"])][0]
|
2018-07-16 02:29:32 +08:00
|
|
|
dst_seg = gfx_wire_ids["TILE_WIRE_" + dst_segname.upper().replace("/", "_")]
|
|
|
|
dst_segname = dst_segname.replace("/", ".")
|
|
|
|
|
2018-07-16 03:41:34 +08:00
|
|
|
# bba.s("X%d/Y%d/%s->%s" % (info["x"], info["y"], src_segname, dst_segname), "name")
|
2018-06-17 20:46:10 +08:00
|
|
|
bba.u32(info["src"], "src")
|
|
|
|
bba.u32(info["dst"], "dst")
|
2018-07-30 22:21:03 +08:00
|
|
|
bba.u32(info["fast_delay"], "fast_delay")
|
|
|
|
bba.u32(info["slow_delay"], "slow_delay")
|
2018-06-17 20:46:10 +08:00
|
|
|
bba.u8(info["x"], "x")
|
|
|
|
bba.u8(info["y"], "y")
|
2018-07-16 02:29:32 +08:00
|
|
|
bba.u16(src_seg, "src_seg")
|
|
|
|
bba.u16(dst_seg, "dst_seg")
|
2018-06-17 20:46:10 +08:00
|
|
|
bba.u16(info["switch_mask"], "switch_mask")
|
|
|
|
bba.u32(info["switch_index"], "switch_index")
|
2018-08-03 23:37:59 +08:00
|
|
|
bba.u32(info["flags"], "flags")
|
2018-06-17 20:46:10 +08:00
|
|
|
|
2018-06-10 16:54:41 +08:00
|
|
|
switchinfo = []
|
|
|
|
for switch in switches:
|
2018-08-02 22:28:47 +08:00
|
|
|
x, y, bits, bel = switch
|
2018-06-10 16:54:41 +08:00
|
|
|
bitlist = []
|
|
|
|
for b in bits:
|
|
|
|
m = cbit_re.match(b)
|
|
|
|
assert m
|
2018-06-17 21:05:17 +08:00
|
|
|
bitlist.append((int(m.group(1)), int(m.group(2))))
|
|
|
|
si = dict()
|
|
|
|
si["x"] = x
|
|
|
|
si["y"] = y
|
|
|
|
si["bits"] = bitlist
|
2018-08-02 22:28:47 +08:00
|
|
|
si["bel"] = bel
|
2018-06-17 21:05:17 +08:00
|
|
|
switchinfo.append(si)
|
|
|
|
|
2018-06-17 21:39:19 +08:00
|
|
|
bba.l("switch_data_%s" % dev_name, "SwitchInfoPOD")
|
2018-06-17 21:05:17 +08:00
|
|
|
for info in switchinfo:
|
|
|
|
bba.u32(len(info["bits"]), "num_bits")
|
2018-08-02 22:28:47 +08:00
|
|
|
bba.u32(info["bel"], "bel")
|
2018-06-17 21:05:17 +08:00
|
|
|
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)
|
2018-06-10 16:54:41 +08:00
|
|
|
|
2018-06-17 21:39:19 +08:00
|
|
|
bba.l("tile_data_%s" % dev_name, "TileInfoPOD")
|
2018-06-17 21:15:49 +08:00
|
|
|
for info in tileinfo:
|
|
|
|
bba.u8(info["cols"], "cols")
|
|
|
|
bba.u8(info["rows"], "rows")
|
2021-01-28 02:34:41 +08:00
|
|
|
bba.u16(0, "padding")
|
|
|
|
bba.r_slice(info["entries"], info["num_entries"], "entries")
|
2018-06-17 21:15:49 +08:00
|
|
|
|
2018-06-17 21:39:19 +08:00
|
|
|
bba.l("ieren_data_%s" % dev_name, "IerenInfoPOD")
|
2018-06-17 21:25:58 +08:00
|
|
|
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")
|
|
|
|
|
2018-06-17 21:39:19 +08:00
|
|
|
if len(ierens) % 2 == 1:
|
|
|
|
bba.u16(0, "padding")
|
|
|
|
|
2018-06-17 22:12:52 +08:00
|
|
|
bba.l("bits_info_%s" % dev_name, "BitstreamInfoPOD")
|
2021-01-28 02:34:41 +08:00
|
|
|
bba.r_slice("tile_data_%s" % dev_name, len(tileinfo), "tiles_nonrouting")
|
|
|
|
bba.r_slice("switch_data_%s" % dev_name, len(switchinfo), "switches")
|
|
|
|
bba.r_slice("ieren_data_%s" % dev_name, len(ierens), "ierens")
|
2018-06-17 21:39:19 +08:00
|
|
|
|
2018-06-17 22:12:52 +08:00
|
|
|
bba.l("tile_grid_%s" % dev_name, "TileType")
|
2018-06-17 21:46:39 +08:00
|
|
|
for t in tilegrid:
|
|
|
|
bba.u32(tiletypes[t], "tiletype")
|
|
|
|
|
2018-07-19 17:14:43 +08:00
|
|
|
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")
|
2021-01-28 02:34:41 +08:00
|
|
|
bba.r_slice("bel%d_config_entries" % bel_idx if len(entries) > 0 else None, len(entries), "entries")
|
2018-07-19 17:14:43 +08:00
|
|
|
|
2018-06-17 22:12:52 +08:00
|
|
|
bba.l("package_info_%s" % dev_name, "PackageInfoPOD")
|
2018-06-17 21:53:17 +08:00
|
|
|
for info in packageinfo:
|
|
|
|
bba.s(info[0], "name")
|
2021-01-28 02:34:41 +08:00
|
|
|
bba.r_slice(info[2], info[1], "pins")
|
2018-06-17 21:53:17 +08:00
|
|
|
|
2018-08-02 21:20:43 +08:00
|
|
|
for cell, timings in sorted(cell_timings.items()):
|
2018-08-08 23:01:18 +08:00
|
|
|
beltype = constids[cell]
|
2018-08-02 21:20:43 +08:00
|
|
|
bba.l("cell_paths_%d" % beltype, "CellPathDelayPOD")
|
|
|
|
for entry in timings:
|
|
|
|
fromport, toport, fast, slow = entry
|
2018-08-08 23:01:18 +08:00
|
|
|
bba.u32(constids[fromport], "from_port")
|
|
|
|
bba.u32(constids[toport], "to_port")
|
2018-08-02 21:20:43 +08:00
|
|
|
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()):
|
2018-08-08 23:01:18 +08:00
|
|
|
beltype = constids[cell]
|
2018-08-02 21:20:43 +08:00
|
|
|
bba.u32(beltype, "type")
|
2021-01-28 02:34:41 +08:00
|
|
|
bba.r_slice("cell_paths_%d" % beltype, len(timings), "path_delays")
|
2018-08-02 21:20:43 +08:00
|
|
|
|
2018-11-16 07:04:55 +08:00
|
|
|
bba.l("global_network_info_%s" % dev_name, "GlobalNetworkInfoPOD")
|
|
|
|
for i in range(len(glbinfo)):
|
|
|
|
for k in ['gb_x', 'gb_y', 'pi_gb_x', 'pi_gb_y', 'pi_gb_pio', 'pi_eb_bank']:
|
|
|
|
bba.u8(glbinfo[i][k], k)
|
|
|
|
for k in ['pi_eb_x', 'pi_eb_y']:
|
|
|
|
bba.u16(glbinfo[i][k], k)
|
|
|
|
bba.u16(0, "padding")
|
|
|
|
|
2018-06-17 22:12:52 +08:00
|
|
|
bba.l("chip_info_%s" % dev_name)
|
|
|
|
bba.u32(dev_width, "dev_width")
|
|
|
|
bba.u32(dev_height, "dev_height")
|
|
|
|
bba.u32(len(switchinfo), "num_switches")
|
2021-01-28 02:34:41 +08:00
|
|
|
bba.r_slice("bel_data_%s" % dev_name, len(bel_name), "bel_data")
|
|
|
|
bba.r_slice("wire_data_%s" % dev_name, num_wires, "wire_data")
|
|
|
|
bba.r_slice("pip_data_%s" % dev_name, len(pipinfo), "pip_data")
|
|
|
|
bba.r_slice("tile_grid_%s" % dev_name, len(tilegrid), "tile_grid")
|
2018-06-17 22:12:52 +08:00
|
|
|
bba.r("bits_info_%s" % dev_name, "bits_info")
|
2021-01-28 02:34:41 +08:00
|
|
|
bba.r_slice("bel_config_%s" % dev_name if len(extra_cell_config) > 0 else None, len(extra_cell_config), "bel_config")
|
|
|
|
bba.r_slice("package_info_%s" % dev_name, len(packageinfo), "packages_data")
|
|
|
|
bba.r_slice("cell_timings_%s" % dev_name, len(cell_timings), "cell_timing")
|
|
|
|
bba.r_slice("global_network_info_%s" % dev_name, len(glbinfo), "global_network_info")
|
|
|
|
bba.r_slice("tile_wire_names", len(gfx_wire_names), "tile_wire_names")
|
2018-06-17 22:12:52 +08:00
|
|
|
|
2018-07-25 03:10:42 +08:00
|
|
|
bba.pop()
|