Add timing information from dly files

This commit is contained in:
Miodrag Milanovic 2025-05-27 15:21:14 +02:00
parent eb77def664
commit 91eca20d10
6 changed files with 1723 additions and 237 deletions

2
.gitignore vendored
View File

@ -1,3 +1,5 @@
#python #python
__pycache__/ __pycache__/
*.pyc *.pyc
*.tar.gz
/delay/

577
decompress.py Normal file
View File

@ -0,0 +1,577 @@
import zlib
import struct
from dataclasses import dataclass
from typing import List
@dataclass
class T_delay_tri:
min: int
typ: int
max: int
@staticmethod
def from_bytes(data: bytes) -> 'T_delay_tri':
min_val, typ_val, max_val = struct.unpack('<3i', data)
return T_delay_tri(min_val, typ_val, max_val)
@dataclass
class T_delay:
rise: T_delay_tri
fall: T_delay_tri
@staticmethod
def from_bytes(data: bytes) -> 'T_delay':
rise = T_delay_tri.from_bytes(data[:12])
fall = T_delay_tri.from_bytes(data[12:24])
return T_delay(rise, fall)
@dataclass
class Tpin_pair:
i: int
o_or_clk: int # Represents either 'o' or 'clk' depending on the boolean case
@staticmethod
def from_bytes(data: bytes) -> 'Tpin_pair':
i_val, o_or_clk_val = struct.unpack('<2h', data)
return Tpin_pair(i_val, o_or_clk_val)
@dataclass
class Tentry_rec:
pins: Tpin_pair
entry_no: int
@staticmethod
def from_bytes(data: bytes) -> 'Tentry_rec':
pins = Tpin_pair.from_bytes(data[:4])
entry_no = struct.unpack('<h', data[4:6])[0]
return Tentry_rec(pins, entry_no)
@dataclass
class Tdel_entry:
key: int
edge1: int
edge2: int
time1: T_delay_tri
time2: T_delay_tri
@staticmethod
def from_bytes(data: bytes) -> 'Tdel_entry':
key, edge1, edge2 = struct.unpack('<3i', data[:12])
time1 = T_delay_tri.from_bytes(data[12:24])
time2 = T_delay_tri.from_bytes(data[24:36])
return Tdel_entry(key, edge1, edge2, time1, time2)
@dataclass
class TRAM_del_rec:
iopath: List[Tentry_rec]
setuphold: List[Tentry_rec]
width: List[Tentry_rec]
del_entry: List[Tdel_entry]
@staticmethod
def from_bytes(data: bytes) -> 'TRAM_del_rec':
offset = 0
iopath = [Tentry_rec.from_bytes(data[offset + i*6:offset + (i+1)*6]) for i in range(3001)]
offset += 3001 * 6
setuphold = [Tentry_rec.from_bytes(data[offset + i*6:offset + (i+1)*6]) for i in range(8001)]
offset += 8001 * 6
width = [Tentry_rec.from_bytes(data[offset + i*6:offset + (i+1)*6]) for i in range(51)]
offset += 51 * 6
del_entry = [Tdel_entry.from_bytes(data[offset + i*36:offset + (i+1)*36]) for i in range(101)]
return TRAM_del_rec(iopath, setuphold, width, del_entry)
@dataclass
class Tdel_rec:
val: T_delay
conf_mux: int
name: str
x: int
y: int
plane: int
dir: int
inv: int
cnt: int
con_type: int
@staticmethod
def from_bytes(data: memoryview, offset: int) -> ('Tdel_rec', int):
val = T_delay.from_bytes(data[offset:offset + 24])
offset += 24
conf_mux = struct.unpack_from('<i', data, offset)[0]
offset += 4
strlen = data[offset]
offset += 1
name = data[offset:offset + strlen].decode('ascii')
offset += 23 # alignment added as well
x, y, plane, dir, inv, cnt = struct.unpack_from('<6i', data, offset)
offset += 24
con_type_val = data[offset]
offset += 4
return Tdel_rec(val, conf_mux, name, x, y, plane, dir, inv, cnt, con_type_val), offset
@dataclass
class Tdel_rec_tri:
val: T_delay_tri
conf_mux: int
name: str
x: int
y: int
@staticmethod
def from_bytes(mv: memoryview, offset: int) -> ('Tdel_rec_tri', int):
val = T_delay_tri.from_bytes(mv[offset:offset+12])
offset += 12
conf_mux = struct.unpack_from('<i', mv, offset)[0]
offset += 4
strlen = mv[offset]
offset += 1
name = mv[offset:offset + strlen].decode('ascii')
offset += 23
x, y = struct.unpack_from('<2i', mv, offset)
offset += 8
return Tdel_rec_tri(val, conf_mux, name, x, y), offset
def read_SB_del_tile_arr_from_bytes(mv: memoryview, offset: int) -> (List, int):
SB_del_tile_arr = []
for i1 in range(4): # [1..4]
level1 = []
for i2 in range(8): # [1..8]
level2 = []
for i3 in range(4): # [1..4]
level3 = []
for i4 in range(12): # [1..12]
level4 = []
for i5 in range(5): # [0..4]
level5 = []
for i6 in range(8): # [0..7]
chunk = mv[offset:offset + 24]
if len(chunk) < 24:
raise EOFError("Unexpected end of data")
delay = T_delay.from_bytes(chunk)
offset += 24
level5.append(delay)
level4.append(level5)
level3.append(level4)
level2.append(level3)
level1.append(level2)
SB_del_tile_arr.append(level1)
return SB_del_tile_arr, offset
@dataclass
class ExtraTimingDelays:
skew_report_del: int
fix_skew_del: int
del_rec_0: Tdel_rec
del_min_route_SB: Tdel_rec
del_violation_common: Tdel_rec_tri
del_dummy: Tdel_rec
del_Hold_D_L: Tdel_rec_tri
del_Hold_RAM: Tdel_rec_tri
del_Setup_D_L: Tdel_rec_tri
del_Setup_RAM: Tdel_rec_tri
del_Hold_SN_RN: Tdel_rec_tri
del_Setup_SN_RN: Tdel_rec_tri
del_Hold_RN_SN: Tdel_rec_tri
del_Setup_RN_SN: Tdel_rec_tri
del_bot_couty2: Tdel_rec
del_bot_glb_couty2: Tdel_rec
del_bot_SB_couty2: Tdel_rec
del_bot_pouty2: Tdel_rec
del_bot_glb_pouty2: Tdel_rec
del_bot_SB_pouty2: Tdel_rec
del_left_couty2: Tdel_rec
del_left_glb_couty2: Tdel_rec
del_left_SB_couty2: Tdel_rec
del_left_pouty2: Tdel_rec
del_left_glb_pouty2: Tdel_rec
del_left_SB_pouty2: Tdel_rec
del_inp: List[Tdel_rec]
del_CPE_out_mux: List[Tdel_rec]
del_CPE_CP_Q: Tdel_rec
del_CPE_S_Q: Tdel_rec
del_CPE_R_Q: Tdel_rec
del_CPE_D_Q: Tdel_rec
del_RAM_CLK_DO: Tdel_rec
del_GLBOUT_sb_big: Tdel_rec
del_sb_drv: Tdel_rec
del_CP_carry_path: Tdel_rec
del_CP_prop_path: Tdel_rec
del_special_RAM_I: Tdel_rec
del_RAMO_xOBF: Tdel_rec
del_GLBOUT_IO_SEL: Tdel_rec
del_IO_SEL_Q_out: Tdel_rec
del_IO_SEL_Q_in: Tdel_rec
in_delayline_per_stage: Tdel_rec
out_delayline_per_stage: Tdel_rec
del_IBF: Tdel_rec
del_OBF: Tdel_rec
del_r_OBF: Tdel_rec
del_TOBF_ctrl: Tdel_rec
del_LVDS_IBF: Tdel_rec
del_LVDS_OBF: Tdel_rec
del_LVDS_r_OBF: Tdel_rec
del_LVDS_TOBF_ctrl: Tdel_rec
del_CP_clkin: Tdel_rec
del_CP_enin: Tdel_rec
del_preplace: Tdel_rec
del_CPE_timing_mod: List[Tdel_rec]
@staticmethod
def from_bytes(mv: memoryview, offset: int) -> ('ExtraTimingDelays', int):
skew_report_del, fix_skew_del = struct.unpack_from('<2i', mv, offset)
offset += 8
del_rec_0, offset = Tdel_rec.from_bytes(mv, offset)
del_min_route_SB, offset = Tdel_rec.from_bytes(mv, offset)
del_violation_common, offset = Tdel_rec_tri.from_bytes(mv, offset)
del_dummy, offset = Tdel_rec.from_bytes(mv, offset)
del_Hold_D_L, offset = Tdel_rec_tri.from_bytes(mv, offset)
del_Hold_RAM, offset = Tdel_rec_tri.from_bytes(mv, offset)
del_Setup_D_L, offset = Tdel_rec_tri.from_bytes(mv, offset)
del_Setup_RAM, offset = Tdel_rec_tri.from_bytes(mv, offset)
del_Hold_SN_RN, offset = Tdel_rec_tri.from_bytes(mv, offset)
del_Setup_SN_RN, offset = Tdel_rec_tri.from_bytes(mv, offset)
del_Hold_RN_SN, offset = Tdel_rec_tri.from_bytes(mv, offset)
del_Setup_RN_SN, offset = Tdel_rec_tri.from_bytes(mv, offset)
del_bot_couty2, offset = Tdel_rec.from_bytes(mv, offset)
del_bot_glb_couty2, offset = Tdel_rec.from_bytes(mv, offset)
del_bot_SB_couty2, offset = Tdel_rec.from_bytes(mv, offset)
del_bot_pouty2, offset = Tdel_rec.from_bytes(mv, offset)
del_bot_glb_pouty2, offset = Tdel_rec.from_bytes(mv, offset)
del_bot_SB_pouty2, offset = Tdel_rec.from_bytes(mv, offset)
del_left_couty2, offset = Tdel_rec.from_bytes(mv, offset)
del_left_glb_couty2, offset = Tdel_rec.from_bytes(mv, offset)
del_left_SB_couty2, offset = Tdel_rec.from_bytes(mv, offset)
del_left_pouty2, offset = Tdel_rec.from_bytes(mv, offset)
del_left_glb_pouty2, offset = Tdel_rec.from_bytes(mv, offset)
del_left_SB_pouty2, offset = Tdel_rec.from_bytes(mv, offset)
del_inp = []
for _ in range(8):
rec, offset = Tdel_rec.from_bytes(mv, offset)
del_inp.append(rec)
del_CPE_out_mux = []
for _ in range(4):
rec, offset = Tdel_rec.from_bytes(mv, offset)
del_CPE_out_mux.append(rec)
del_CPE_CP_Q, offset = Tdel_rec.from_bytes(mv, offset)
del_CPE_S_Q, offset = Tdel_rec.from_bytes(mv, offset)
del_CPE_R_Q, offset = Tdel_rec.from_bytes(mv, offset)
del_CPE_D_Q, offset = Tdel_rec.from_bytes(mv, offset)
del_RAM_CLK_DO, offset = Tdel_rec.from_bytes(mv, offset)
del_GLBOUT_sb_big, offset = Tdel_rec.from_bytes(mv, offset)
del_sb_drv, offset = Tdel_rec.from_bytes(mv, offset)
del_CP_carry_path, offset = Tdel_rec.from_bytes(mv, offset)
del_CP_prop_path, offset = Tdel_rec.from_bytes(mv, offset)
del_special_RAM_I, offset = Tdel_rec.from_bytes(mv, offset)
del_RAMO_xOBF, offset = Tdel_rec.from_bytes(mv, offset)
del_GLBOUT_IO_SEL, offset = Tdel_rec.from_bytes(mv, offset)
del_IO_SEL_Q_out, offset = Tdel_rec.from_bytes(mv, offset)
del_IO_SEL_Q_in, offset = Tdel_rec.from_bytes(mv, offset)
in_delayline_per_stage, offset = Tdel_rec.from_bytes(mv, offset)
out_delayline_per_stage, offset = Tdel_rec.from_bytes(mv, offset)
del_IBF, offset = Tdel_rec.from_bytes(mv, offset)
del_OBF, offset = Tdel_rec.from_bytes(mv, offset)
del_r_OBF, offset = Tdel_rec.from_bytes(mv, offset)
del_TOBF_ctrl, offset = Tdel_rec.from_bytes(mv, offset)
del_LVDS_IBF, offset = Tdel_rec.from_bytes(mv, offset)
del_LVDS_OBF, offset = Tdel_rec.from_bytes(mv, offset)
del_LVDS_r_OBF, offset = Tdel_rec.from_bytes(mv, offset)
del_LVDS_TOBF_ctrl, offset = Tdel_rec.from_bytes(mv, offset)
del_CP_clkin, offset = Tdel_rec.from_bytes(mv, offset)
del_CP_enin, offset = Tdel_rec.from_bytes(mv, offset)
del_preplace, offset = Tdel_rec.from_bytes(mv, offset)
del_CPE_timing_mod = []
for _ in range(42):
rec, offset = Tdel_rec.from_bytes(mv, offset)
del_CPE_timing_mod.append(rec)
return ExtraTimingDelays(
skew_report_del, fix_skew_del,
del_rec_0, del_min_route_SB,
del_violation_common, del_dummy,
del_Hold_D_L, del_Hold_RAM, del_Setup_D_L, del_Setup_RAM,
del_Hold_SN_RN, del_Setup_SN_RN, del_Hold_RN_SN, del_Setup_RN_SN,
del_bot_couty2, del_bot_glb_couty2, del_bot_SB_couty2,
del_bot_pouty2, del_bot_glb_pouty2, del_bot_SB_pouty2,
del_left_couty2, del_left_glb_couty2, del_left_SB_couty2,
del_left_pouty2, del_left_glb_pouty2, del_left_SB_pouty2,
del_inp, del_CPE_out_mux,
del_CPE_CP_Q, del_CPE_S_Q, del_CPE_R_Q, del_CPE_D_Q,
del_RAM_CLK_DO, del_GLBOUT_sb_big, del_sb_drv,
del_CP_carry_path, del_CP_prop_path,
del_special_RAM_I, del_RAMO_xOBF,
del_GLBOUT_IO_SEL, del_IO_SEL_Q_out, del_IO_SEL_Q_in,
in_delayline_per_stage, out_delayline_per_stage,
del_IBF, del_OBF, del_r_OBF, del_TOBF_ctrl,
del_LVDS_IBF, del_LVDS_OBF, del_LVDS_r_OBF, del_LVDS_TOBF_ctrl,
del_CP_clkin, del_CP_enin, del_preplace,
del_CPE_timing_mod
), offset
def read_IM_del_tile_arr_from_bytes(mv: memoryview, offset: int) -> (List, int):
result = []
for i1 in range(2): # [1..2]
level1 = []
for i2 in range(8): # [1..8]
level2 = []
for i3 in range(8): # [1..8]
level3 = []
for i4 in range(12): # [1..12]
level4 = []
for i5 in range(8): # [0..7]
delay = T_delay.from_bytes(mv[offset:offset+24])
offset += 24
level4.append(delay)
level3.append(level4)
level2.append(level3)
level1.append(level2)
result.append(level1)
return result, offset
def read_OM_del_tile_arr_from_bytes(mv: memoryview, offset: int) -> (List, int):
result = []
for i1 in range(8): # [1..8]
level1 = []
for i2 in range(8): # [1..8]
level2 = []
for i3 in range(4): # [9..12]
level3 = []
for i4 in range(4): # [0..3]
delay = T_delay.from_bytes(mv[offset:offset+24])
offset += 24
level3.append(delay)
level2.append(level3)
level1.append(level2)
result.append(level1)
return result, offset
def read_CPE_del_tile_arr_from_bytes(mv: memoryview, offset: int) -> (List, int):
result = []
for i1 in range(10): # [0..9]
level1 = []
for i2 in range(19): # [1..19]
level2 = []
for i3 in range(10): # [1..10]
rec, offset = Tdel_rec.from_bytes(mv, offset)
level2.append(rec)
level1.append(level2)
result.append(level1)
return result, offset
def read_SB_del_rim_arr_from_bytes(mv: memoryview, offset: int) -> (List, int):
result = []
for i1 in range(165): # [-2..162]
level1 = []
for i2 in range(4): # [1..4]
level2 = []
for i3 in range(12): # [1..12]
level3 = []
for i4 in range(5): # [0..4]
level4 = []
for i5 in range(8): # [0..7]
delay = T_delay.from_bytes(mv[offset:offset+24])
offset += 24
level4.append(delay)
level3.append(level4)
level2.append(level3)
level1.append(level2)
result.append(level1)
return result, offset
def read_Edge_del_arr_from_bytes(mv: memoryview, offset: int) -> (List, int):
result = []
for i1 in range(165): # [-2..162]
level1 = []
for i2 in range(4): # [1..4]
level2 = []
for i3 in range(24): # [1..24]
level3 = []
for i4 in range(8): # [1..8]
delay = T_delay.from_bytes(mv[offset:offset+24])
offset += 24
level3.append(delay)
level2.append(level3)
level1.append(level2)
result.append(level1)
return result, offset
def read_IO_SEL_del_arr_from_bytes(mv: memoryview, offset: int) -> (List, int):
result = []
for i1 in range(11): # [1..11]
level1 = []
for i2 in range(4): # [1..4]
delay = T_delay.from_bytes(mv[offset:offset+24])
offset += 24
level1.append(delay)
result.append(level1)
return result, offset
def read_CLKIN_del_arr_from_bytes(mv: memoryview, offset: int) -> (List, int):
result = []
for i1 in range(7):
level1 = []
for i2 in range(4):
delay = T_delay.from_bytes(mv[offset:offset + 24])
offset += 24
level1.append(delay)
result.append(level1)
return result, offset
def read_GLBOUT_del_arr_from_bytes(mv: memoryview, offset: int) -> (List, int):
result = []
for i1 in range(28):
level1 = []
for i2 in range(8):
delay = T_delay.from_bytes(mv[offset:offset + 24])
offset += 24
level1.append(delay)
result.append(level1)
return result, offset
def read_PLL_del_arr_from_bytes(mv: memoryview, offset: int) -> (List, int):
result = []
for i1 in range(7):
level1 = []
for i2 in range(6):
delay = T_delay.from_bytes(mv[offset:offset + 24])
offset += 24
level1.append(delay)
result.append(level1)
return result, offset
def read_Tentry_rec_from_bytes(data: memoryview, offset: int) -> ('Tentry_rec', int):
pins_i, pins_val, entry_no = struct.unpack_from('<3h', data, offset)
return Tentry_rec(Tpin_pair(pins_i, pins_val), entry_no), offset + 6
def read_Tdel_entry_from_bytes(data: memoryview, offset: int) -> ('Tdel_entry', int):
key, edge1, edge2 = struct.unpack_from('<3i', data, offset)
time1 = T_delay_tri.from_bytes(data[offset + 12:offset + 24])
time2 = T_delay_tri.from_bytes(data[offset + 24:offset + 36])
return Tdel_entry(key, edge1, edge2, time1, time2), offset + 36
def read_TRAM_del_rec_from_bytes(mv: memoryview, offset: int) -> (TRAM_del_rec, int):
iopath = []
for _ in range(3001):
entry, offset = read_Tentry_rec_from_bytes(mv, offset)
iopath.append(entry)
setuphold = []
for _ in range(8001):
entry, offset = read_Tentry_rec_from_bytes(mv, offset)
setuphold.append(entry)
width = []
for _ in range(51):
entry, offset = read_Tentry_rec_from_bytes(mv, offset)
width.append(entry)
del_entry = []
for _ in range(101):
entry, offset = read_Tdel_entry_from_bytes(mv, offset)
del_entry.append(entry)
offset += 2 # alignment added
return TRAM_del_rec(iopath, setuphold, width, del_entry), offset
def read_IO_SEL_io_coef_from_bytes(mv: memoryview, offset: int) -> (list, int):
result = []
for i1 in range(4): # [1..4]
row = []
for i2 in range(27): # [1..27]
value = struct.unpack_from('<d', mv, offset)[0] # '<d' = little-endian double
offset += 8
row.append(value)
result.append(row)
return result, offset
@dataclass
class Tdel_all_rec:
SB_del_tile_arr: List[List[List[List[List[List[T_delay]]]]]]
IM_del_tile_arr: List[List[List[List[List[T_delay]]]]]
OM_del_tile_arr: List[List[List[List[T_delay]]]]
CPE_del_tile_arr: List[List[List[Tdel_rec]]]
SB_del_rim_arr: List[List[List[List[List[T_delay]]]]]
Edge_del_arr: List[List[List[List[T_delay]]]]
IO_SEL_del_arr: List[List[T_delay]]
CLKIN_del_arr: List[List[T_delay]]
GLBOUT_del_arr: List[List[T_delay]]
PLL_del_arr: List[List[T_delay]]
FPGA_ram_del_1: TRAM_del_rec
FPGA_ram_del_2: TRAM_del_rec
FPGA_ram_del_3: TRAM_del_rec
IO_SEL_io_coef: list[list[float]]
timing_delays: ExtraTimingDelays
@staticmethod
def from_bytes(data: bytes) -> 'Tdel_all_rec':
offset = 0
sb_del_tile_arr, offset = read_SB_del_tile_arr_from_bytes(data, offset)
im, offset = read_IM_del_tile_arr_from_bytes(data, offset)
om, offset = read_OM_del_tile_arr_from_bytes(data, offset)
cpe, offset = read_CPE_del_tile_arr_from_bytes(data, offset)
sb_del_rim, offset = read_SB_del_rim_arr_from_bytes(data, offset)
edge, offset = read_Edge_del_arr_from_bytes(data, offset)
io_sel, offset = read_IO_SEL_del_arr_from_bytes(data, offset)
clkin, offset = read_CLKIN_del_arr_from_bytes(data, offset)
glbout, offset = read_GLBOUT_del_arr_from_bytes(data, offset)
pll_del, offset = read_PLL_del_arr_from_bytes(data, offset)
fpga_ram_del_1, offset = read_TRAM_del_rec_from_bytes(data, offset)
fpga_ram_del_2, offset = read_TRAM_del_rec_from_bytes(data, offset)
fpga_ram_del_3, offset = read_TRAM_del_rec_from_bytes(data, offset)
io_sel_coef, offset = read_IO_SEL_io_coef_from_bytes(data, offset)
timing_delays, offset = ExtraTimingDelays.from_bytes(data, offset)
return Tdel_all_rec(sb_del_tile_arr, im, om, cpe, sb_del_rim, edge, io_sel, clkin, glbout, pll_del, fpga_ram_del_1, fpga_ram_del_2, fpga_ram_del_3,io_sel_coef, timing_delays)
def decompress_file(input_path, output_path):
with open(input_path, 'rb') as f_in:
compressed_data = f_in.read()
try:
decompressed_data = zlib.decompress(compressed_data)
except zlib.error as e:
print(f"Decompression failed: {e}")
return
all = Tdel_all_rec.from_bytes(decompressed_data)
#print(all.GLBOUT_del_arr)
with open(output_path, 'wb') as f_out:
f_out.write(decompressed_data)
# Example usage
#decompress_file("cc_best_eco_dly.dly", "cc_best_eco_dly.bin")
#decompress_file("cc_best_lpr_dly.dly", "cc_best_lpr_dly.bin")
#decompress_file("cc_best_spd_dly.dly", "cc_best_spd_dly.bin")
#
#decompress_file("cc_typ_eco_dly.dly", "cc_typ_eco_dly.bin")
#decompress_file("cc_typ_lpr_dly.dly", "cc_typ_lpr_dly.bin")
#decompress_file("cc_typ_spd_dly.dly", "cc_typ_spd_dly.bin")
#
#decompress_file("cc_worst_eco_dly.dly", "cc_worst_eco_dly.bin")
#decompress_file("cc_worst_lpr_dly.dly", "cc_worst_lpr_dly.bin")
decompress_file("cc_worst_spd_dly.dly", "cc_worst_spd_dly.bin")

16
delay.sh Executable file
View File

@ -0,0 +1,16 @@
#!/bin/bash
set -e
ARCHIVE="cc-toolchain-linux.tar.gz"
rm -rf delay
mkdir -p delay
wget -O "$ARCHIVE" "https://colognechip.com/downloads/cc-toolchain-linux.tar.gz"
tar --extract \
--file="$ARCHIVE" \
--wildcards \
--strip-components=3 \
--directory=delay \
'cc-toolchain-linux/bin/p_r/*.dly'

View File

@ -17,9 +17,11 @@
# #
import die import die
import os
from die import Die from die import Die
from dataclasses import dataclass from dataclasses import dataclass
from typing import List, Dict from typing import List, Dict
from timing import decompress_timing
@dataclass(eq=True, order=True) @dataclass(eq=True, order=True)
class Pad: class Pad:
@ -36,6 +38,37 @@ class Bank:
die : str die : str
bank: str bank: str
@dataclass
class TimingDelay:
min : int
typ : int
max : int
def __add__(self, other):
if not isinstance(other, TimingDelay):
return NotImplemented
return TimingDelay(self.min + other.min, self.typ + other.typ, self.max + other.max)
def __sub__(self, other):
if not isinstance(other, TimingDelay):
return NotImplemented
return TimingDelay(self.min - other.min, self.typ - other.typ, self.max - other.max)
@dataclass
class Timing:
rise : TimingDelay
fall : TimingDelay
def __add__(self, other):
if not isinstance(other, Timing):
return NotImplemented
return Timing(self.rise + other.rise, self.fall + other.fall)
def __sub__(self, other):
if not isinstance(other, Timing):
return NotImplemented
return Timing(self.rise - other.rise, self.fall - other.fall)
@dataclass @dataclass
class Chip: class Chip:
name : str name : str
@ -178,3 +211,268 @@ def get_all_devices():
def get_device(name): def get_device(name):
return CCGM1_DEVICES[name] return CCGM1_DEVICES[name]
def convert_delay(d):
return Timing(TimingDelay(d.rise.min, d.rise.typ, d.rise.max), TimingDelay(d.fall.min, d.fall.typ, d.fall.max))
def convert_delay_val(d):
return Timing(TimingDelay(d.min, d.typ, d.max), TimingDelay(d.min, d.typ, d.max))
def convert_ram_delay(d):
return Timing(TimingDelay(d.time1.min, d.time1.typ, d.time1.max), TimingDelay(d.time2.min, d.time2.typ, d.time2.max))
def check_dly_available():
current_dir = os.path.dirname(os.path.abspath(__file__))
return os.path.exists(os.path.join(current_dir, "..", "delay", "cc_worst_spd_dly.dly"))
def get_timings(name):
val = dict()
current_dir = os.path.dirname(os.path.abspath(__file__))
timing_data = decompress_timing(os.path.join(current_dir, "..", "delay", f"cc_{name}_dly.dly"))
for i1 in range(4): # [1..4]
for i2 in range(8): # [1..8]
for i3 in range(4): # [1..4]
for i4 in range(12): # [1..12]
for i5 in range(5): # [0..4]
for i6 in range(8): # [0..7]
d = timing_data.SB_del_tile_arr[i1][i2][i3][i4][i5][i6]
if d.rise.min == 123456: # not connected
continue
x = i2+1
y = i3+1
y = 2*y if (x % 2 == 0) else 2*y-1
name = f"sb_del_t{i1+1}_x{x}_y{y}_p{i4+1}_d{i5}_s{i6}"
val[name] = convert_delay(d)
for i1 in range(2): # [1..2]
for i2 in range(8): # [1..8]
for i3 in range(8): # [1..8]
for i4 in range(12): # [1..12]
for i5 in range(8): # [0..7]
d = timing_data.IM_del_tile_arr[i1][i2][i3][i4][i5]
if d.rise.min == 123456: # not connected
continue
name = f"im_x{i2+1}_y{i3+1}_p{i4+1}_d{i5}_path{i1+1}"
val[name] = convert_delay(d)
for i1 in range(8): # [1..8]
for i2 in range(8): # [1..8]
for i3 in range(4): # [9..12]
for i4 in range(4): # [0..3]
d = timing_data.OM_del_tile_arr[i1][i2][i3][i4]
if d.rise.min == 123456: # not connected
continue
name = f"om_x{i1+1}_y{i2+1}_p{i3+9}_d{i4}"
val[name] = convert_delay(d)
for i1 in range(10): # [0..9]
for i2 in range(19): # [1..19]
for i3 in range(10): # [1..10]
d = timing_data.CPE_del_tile_arr[i1][i2][i3]
if d.name == "CPE": # not used
continue
val[d.name] = convert_delay(d.val)
for i1 in range(165): # [-2..162]
for i2 in range(4): # [1..4]
for i3 in range(12): # [1..12]
for i4 in range(5): # [0..4]
for i5 in range(8): # [0..7]
d = timing_data.SB_del_rim_arr[i1][i2][i3][i4][i5]
if d.rise.min == 123456: # not connected
continue
name = f"sb_rim_xy{i1-2}_s{i2+1}_p{i3+1}_d{i4}_s{i5}"
val[name] = convert_delay(d)
inputs_all = [ 'CLOCK0','CLOCK1','CLOCK2','CLOCK3',
'SB_P1', 'SB_P2', 'SB_P3', 'SB_P4', 'SB_P5', 'SB_P6', 'SB_P7', 'SB_P8']
inputs_left_bot = [ 'MDIE_P1', 'MDIE_P2', 'MDIE_P3', 'MDIE_P4', 'MDIE_P5', 'MDIE_P6', 'MDIE_P7', 'MDIE_P8' ]
inputs_right_top = [ 'COUTX', 'COUTY1', 'COUTY2', 'POUTX', 'POUTY1', 'POUTY2', 'RAM_O1', 'RAM_O2' ]
inputs_bot = [ 'P_CINY1', 'P_CINY2', 'P_PINY1', 'P_PINY2']
outputs_right_top = [ 'MDIE_P1', 'MDIE_P2', 'MDIE_P3', 'MDIE_P4', 'MDIE_P5', 'MDIE_P6', 'MDIE_P7', 'MDIE_P8' ]
outputs_left_bot = [ 'CINX', 'CINY1', 'CINY2', 'PINX', 'PINY1', 'PINY2', 'DUMMY', 'DUMMY']
for i1 in range(165): # [-2..162]
for i2 in range(4): # [1..4]
inputs = inputs_all
outputs = []
match i2:
case 0 | 1 : # right, top
inputs += inputs_right_top
inputs += [ 'DUMMY', 'DUMMY', 'DUMMY' ,'DUMMY']
outputs += outputs_right_top
case 2: # left
inputs += inputs_left_bot
inputs += [ 'DUMMY', 'DUMMY', 'DUMMY' ,'DUMMY']
outputs += outputs_left_bot
case 3: # bottom
inputs += inputs_left_bot + inputs_bot
outputs += outputs_left_bot
for i3 in range(24): # [1..24]
for i4 in range(8): # [1..8]
d = timing_data.Edge_del_arr[i1][i2][i3][i4]
if d.rise.min == 123456: # not connected
continue
name = f"edge_xy{i1-2}_s{i2+1}_{inputs[i3]}_{outputs[i4]}"
val[name] = convert_delay(d)
inputs = [ 'CLOCK0','CLOCK1','CLOCK2','CLOCK3','OUT1_I','OUT2_I','OUT3_I','OUT4_I','GPIO_IN','RESET','DDR_I']
outputs = [ 'IN1_O','IN2_O','GPIO_OUT','GPIO_EN' ]
for i1 in range(11): # [1..11]
for i2 in range(4): # [1..4]
d = timing_data.IO_SEL_del_arr[i1][i2]
if d.rise.min == 123456: # not connected
continue
name = f"io_sel_{inputs[i1]}_{outputs[i2]}"
val[name] = convert_delay(d)
inputs = [ 'CLK0_I','CLK1_I','CLK2_I','CLK3_I','SERDES_CLK','SPI_CLK','JTAG_CLK']
outputs = [ 'CLK_OUT0','CLK_OUT1','CLK_OUT2','CLK_OUT3' ]
for i1 in range(7): # [1..7]
for i2 in range(4): # [1..4]
d = timing_data.CLKIN_del_arr[i1][i2]
if d.rise.min == 123456: # not connected
continue
name = f"clkin_{inputs[i1]}_{outputs[i2]}"
val[name] = convert_delay(d)
inputs = [ 'CLK0_0','CLK90_0','CLK180_0','CLK270_0','CLKREF_0',
'CLK0_1','CLK90_1','CLK180_1','CLK270_1','CLKREF_1',
'CLK0_2','CLK90_2','CLK180_2','CLK270_2','CLKREF_2',
'CLK0_3','CLK90_3','CLK180_3','CLK270_3','CLKREF_3',
'U_CLK0','U_CLK1','U_CLK2','U_CLK3',
'U_FB0', 'U_FB1', 'U_FB2', 'U_FB3' ]
outputs = [ 'CLOCK0','CLOCK1','CLOCK2','CLOCK3',
'CLK_FB0','CLK_FB1','CLK_FB2','CLK_FB3']
for i1 in range(28): # [1..28]
for i2 in range(8): # [1..8]
d = timing_data.GLBOUT_del_arr[i1][i2]
if d.rise.min == 123456: # not connected
continue
name = f"glbout_{inputs[i1]}_{outputs[i2]}"
val[name] = convert_delay(d)
# All feedback delays calculated are same, we just take one
val["glbout_FEEDBACK_delay"] = val["glbout_CLK0_0_CLK_FB0"] - val["glbout_CLK0_0_CLOCK0"]
inputs = ['clk_ref_i','clock_core0_i','adpll_enable_i','adpll_status_read_i','locked_steady_reset_i','autn_en_i','reset_n_i']
outputs = ['clk_core0_o','clk_core90_o','clk_core180_o','clk_core270_o', 'pll_locked_o', 'pll_locked_steady_o']
for i1 in range(7): # [1..7]
for i2 in range(6): # [1..6]
d = timing_data.PLL_del_arr[i1][i2]
if d.rise.min == 123456: # not connected
continue
name = f"pll_{inputs[i1]}_{outputs[i2]}"
val[name] = convert_delay(d)
for i in range(1,15):
item = timing_data.FPGA_ram_del_1.del_entry[i]
name = "RAM_NOECC_"
match item.key:
case 1:
name += f"IOPATH_{i}"
case 2:
name += f"SETUPHOLD_{i-3}"
case 4:
name += "WIDTH"
val[name] = convert_ram_delay(timing_data.FPGA_ram_del_1.del_entry[i])
val["RAM_NOECC_IOPATH_4"] = Timing(TimingDelay(0,0,0), TimingDelay(0,0,0))
for i in range(1,16):
item = timing_data.FPGA_ram_del_2.del_entry[i]
name = "RAM_ECC_"
match item.key:
case 1:
name += f"IOPATH_{i}"
case 2:
name += f"SETUPHOLD_{i-4}"
case 4:
name += "WIDTH"
val[name] = convert_ram_delay(timing_data.FPGA_ram_del_2.del_entry[i])
for i in range(1,16):
item = timing_data.FPGA_ram_del_3.del_entry[i]
name = "RAM_REG_"
match item.key:
case 1:
name += f"IOPATH_{i}"
case 2:
name += f"SETUPHOLD_{i-4}"
case 4:
name += "WIDTH"
val[name] = convert_ram_delay(timing_data.FPGA_ram_del_3.del_entry[i])
#val["del_rec_0"] = convert_delay(timing_data.timing_delays.del_rec_0.val)
val["del_min_route_SB"] = convert_delay(timing_data.timing_delays.del_min_route_SB.val)
val["del_violation_common"] = convert_delay_val(timing_data.timing_delays.del_violation_common.val)
val["del_dummy"] = convert_delay(timing_data.timing_delays.del_dummy.val)
val["del_Hold_D_L"] = convert_delay_val(timing_data.timing_delays.del_Hold_D_L.val)
val["del_Setup_D_L"] = convert_delay_val(timing_data.timing_delays.del_Setup_D_L.val)
val["del_Hold_RAM"] = convert_delay_val(timing_data.timing_delays.del_Hold_RAM.val)
val["del_Setup_RAM"] = convert_delay_val(timing_data.timing_delays.del_Setup_RAM.val)
val["del_Hold_SN_RN"] = convert_delay_val(timing_data.timing_delays.del_Hold_SN_RN.val)
val["del_Setup_SN_RN"] = convert_delay_val(timing_data.timing_delays.del_Setup_SN_RN.val)
val["del_Hold_RN_SN"] = convert_delay_val(timing_data.timing_delays.del_Hold_RN_SN.val)
val["del_Setup_RN_SN"] = convert_delay_val(timing_data.timing_delays.del_Setup_RN_SN.val)
val["del_bot_couty2"] = convert_delay(timing_data.timing_delays.del_bot_couty2.val)
val["del_bot_glb_couty2"] = convert_delay(timing_data.timing_delays.del_bot_glb_couty2.val)
val["del_bot_SB_couty2"] = convert_delay(timing_data.timing_delays.del_bot_SB_couty2.val)
val["del_bot_pouty2"] = convert_delay(timing_data.timing_delays.del_bot_pouty2.val)
val["del_bot_glb_pouty2"] = convert_delay(timing_data.timing_delays.del_bot_glb_pouty2.val)
val["del_bot_SB_pouty2"] = convert_delay(timing_data.timing_delays.del_bot_SB_pouty2.val)
val["del_left_couty2"] = convert_delay(timing_data.timing_delays.del_left_couty2.val)
val["del_left_glb_couty2"] = convert_delay(timing_data.timing_delays.del_left_glb_couty2.val)
val["del_left_SB_couty2"] = convert_delay(timing_data.timing_delays.del_left_SB_couty2.val)
val["del_left_pouty2"] = convert_delay(timing_data.timing_delays.del_left_pouty2.val)
val["del_left_glb_pouty2"] = convert_delay(timing_data.timing_delays.del_left_glb_pouty2.val)
val["del_left_SB_pouty2"] = convert_delay(timing_data.timing_delays.del_left_SB_pouty2.val)
val["del_CPE_CP_Q"] = convert_delay(timing_data.timing_delays.del_CPE_CP_Q.val)
val["del_CPE_S_Q"] = convert_delay(timing_data.timing_delays.del_CPE_S_Q.val)
val["del_CPE_R_Q"] = convert_delay(timing_data.timing_delays.del_CPE_R_Q.val)
val["del_CPE_D_Q"] = convert_delay(timing_data.timing_delays.del_CPE_D_Q.val)
val["del_RAM_CLK_DO"] = convert_delay(timing_data.timing_delays.del_RAM_CLK_DO.val)
val["del_GLBOUT_sb_big"] = convert_delay(timing_data.timing_delays.del_GLBOUT_sb_big.val)
val["del_sb_drv"] = convert_delay(timing_data.timing_delays.del_sb_drv.val)
val["del_CP_carry_path"] = convert_delay(timing_data.timing_delays.del_CP_carry_path.val)
val["del_CP_prop_path"] = convert_delay(timing_data.timing_delays.del_CP_prop_path.val)
val["del_special_RAM_I"] = convert_delay(timing_data.timing_delays.del_special_RAM_I.val)
val["del_RAMO_xOBF"] = convert_delay(timing_data.timing_delays.del_RAMO_xOBF.val)
val["del_GLBOUT_IO_SEL"] = convert_delay(timing_data.timing_delays.del_GLBOUT_IO_SEL.val)
val["del_IO_SEL_Q_out"] = convert_delay(timing_data.timing_delays.del_IO_SEL_Q_out.val)
val["del_IO_SEL_Q_in"] = convert_delay(timing_data.timing_delays.del_IO_SEL_Q_in.val)
val["in_delayline_per_stage"] = convert_delay(timing_data.timing_delays.in_delayline_per_stage.val)
val["out_delayline_per_stage"] = convert_delay(timing_data.timing_delays.out_delayline_per_stage.val)
val["del_IBF"] = convert_delay(timing_data.timing_delays.del_IBF.val)
val["del_OBF"] = convert_delay(timing_data.timing_delays.del_OBF.val)
val["del_r_OBF"] = convert_delay(timing_data.timing_delays.del_r_OBF.val)
val["del_TOBF_ctrl"] = convert_delay(timing_data.timing_delays.del_TOBF_ctrl.val)
val["del_LVDS_IBF"] = convert_delay(timing_data.timing_delays.del_LVDS_IBF.val)
val["del_LVDS_OBF"] = convert_delay(timing_data.timing_delays.del_LVDS_OBF.val)
val["del_ddel_LVDS_r_OBFummy"] = convert_delay(timing_data.timing_delays.del_LVDS_r_OBF.val)
val["del_LVDS_TOBF_ctrl"] = convert_delay(timing_data.timing_delays.del_LVDS_TOBF_ctrl.val)
val["del_CP_clkin"] = convert_delay(timing_data.timing_delays.del_CP_clkin.val)
val["del_CP_enin"] = convert_delay(timing_data.timing_delays.del_CP_enin.val)
#val["del_preplace"] = convert_delay(timing_data.timing_delays.del_preplace.val)
return val

View File

@ -105,6 +105,19 @@ def is_edge_io(x,y):
def is_ram(x,y): def is_ram(x,y):
return x in [33,65,97,129] and y in [1,17,33,49,65,81,97,113] return x in [33,65,97,129] and y in [1,17,33,49,65,81,97,113]
def get_full_tile_loc_str(x,y):
tile_x = ((x-1)+16) % 8 + 1
tile_y = ((y-1)+16) % 8 + 1
tile = ((((x+16-1) // 8)+2) % 4) + 1
return f"t{tile}_x{tile_x}_y{tile_y}"
def get_tile_loc_str(x,y):
tile_x = ((x-1)+16) % 8 + 1
tile_y = ((y-1)+16) % 8 + 1
return f"x{tile_x}_y{tile_y}"
@dataclass @dataclass
class IOName: class IOName:
bank : str bank : str
@ -207,6 +220,7 @@ class MUX:
invert: bool invert: bool
visible: bool visible: bool
config: bool config: bool
delay: str
@dataclass @dataclass
class Location: class Location:
@ -218,6 +232,7 @@ class Connection:
x : int x : int
y : int y : int
name : str name : str
delay: str
@dataclass(eq=True, order=True) @dataclass(eq=True, order=True)
class TileInfo: class TileInfo:
@ -906,6 +921,10 @@ PRIMITIVES_PINS = {
Pin("FRD_ADDRX[14]", PinType.OUTPUT,"RAM_WIRE"), Pin("FRD_ADDRX[14]", PinType.OUTPUT,"RAM_WIRE"),
Pin("FRD_ADDR[15]", PinType.OUTPUT,"RAM_WIRE"), Pin("FRD_ADDR[15]", PinType.OUTPUT,"RAM_WIRE"),
Pin("FRD_ADDRX[15]", PinType.OUTPUT,"RAM_WIRE"), Pin("FRD_ADDRX[15]", PinType.OUTPUT,"RAM_WIRE"),
Pin("CLOCK1", PinType.INPUT,"RAM_WIRE"),
Pin("CLOCK2", PinType.INPUT,"RAM_WIRE"),
Pin("CLOCK3", PinType.INPUT,"RAM_WIRE"),
Pin("CLOCK4", PinType.INPUT,"RAM_WIRE"),
], ],
"SERDES" : [ "SERDES" : [
Pin("TX_DETECT_RX_I", PinType.INPUT,"SERDES_WIRE"), Pin("TX_DETECT_RX_I", PinType.INPUT,"SERDES_WIRE"),
@ -2565,9 +2584,9 @@ def get_endpoints_for_type(type):
def get_mux_connections_for_type(type): def get_mux_connections_for_type(type):
muxes = [] muxes = []
def create_mux(src, dst, bits, value, invert, name = None, visible = True, config = False): def create_mux(src, dst, bits, value, invert, name = None, visible = True, config = False, delay = ""):
name = dst if name is None else name name = dst if name is None else name
muxes.append(MUX(src, dst, name, bits, value, invert, visible, config)) muxes.append(MUX(src, dst, name, bits, value, invert, visible, config, delay))
if "CPE" in type: if "CPE" in type:
# CPE # CPE
@ -2588,58 +2607,60 @@ def get_mux_connections_for_type(type):
if "SB_BIG" in type: if "SB_BIG" in type:
# SB_BIG # SB_BIG
for p in range(1,13): for p in range(1,13):
delay = f"sb_del_t1_x1_y1"
plane = f"{p:02d}" plane = f"{p:02d}"
# Per Y output mux # Per Y output mux
for i in range(1,5): for i in range(1,5):
create_mux(f"SB_BIG.P{plane}.D0", f"SB_BIG.P{plane}.Y{i}", 3, 0, True) create_mux(f"SB_BIG.P{plane}.D0", f"SB_BIG.P{plane}.Y{i}", 3, 0, True, delay="del_dummy")
create_mux(f"SB_BIG.P{plane}.YDIAG", f"SB_BIG.P{plane}.Y{i}", 3, 1, True) create_mux(f"SB_BIG.P{plane}.YDIAG", f"SB_BIG.P{plane}.Y{i}", 3, 1, True, delay=f"{delay}_p{p}_d1_s1")
create_mux(f"SB_BIG.P{plane}.D2_{i}", f"SB_BIG.P{plane}.Y{i}", 3, 2, True) create_mux(f"SB_BIG.P{plane}.D2_{i}", f"SB_BIG.P{plane}.Y{i}", 3, 2, True, delay="del_dummy")
create_mux(f"SB_BIG.P{plane}.D3_{i}", f"SB_BIG.P{plane}.Y{i}", 3, 3, True) create_mux(f"SB_BIG.P{plane}.D3_{i}", f"SB_BIG.P{plane}.Y{i}", 3, 3, True, delay="del_dummy")
create_mux(f"SB_BIG.P{plane}.D4_{i}", f"SB_BIG.P{plane}.Y{i}", 3, 4, True) create_mux(f"SB_BIG.P{plane}.D4_{i}", f"SB_BIG.P{plane}.Y{i}", 3, 4, True, delay="del_dummy")
create_mux(f"SB_BIG.P{plane}.D5_{i}", f"SB_BIG.P{plane}.Y{i}", 3, 5, True) create_mux(f"SB_BIG.P{plane}.D5_{i}", f"SB_BIG.P{plane}.Y{i}", 3, 5, True, delay="del_dummy")
create_mux(f"SB_BIG.P{plane}.D6_{i}", f"SB_BIG.P{plane}.Y{i}", 3, 6, True) create_mux(f"SB_BIG.P{plane}.D6_{i}", f"SB_BIG.P{plane}.Y{i}", 3, 6, True, delay="del_dummy")
create_mux(f"SB_BIG.P{plane}.D7_{i}", f"SB_BIG.P{plane}.Y{i}", 3, 7, True) create_mux(f"SB_BIG.P{plane}.D7_{i}", f"SB_BIG.P{plane}.Y{i}", 3, 7, True, delay="del_dummy")
# YDIAG output mux # YDIAG output mux
create_mux(f"SB_BIG.P{plane}.Y1", f"SB_BIG.P{plane}.YDIAG", 3, 0, True) create_mux(f"SB_BIG.P{plane}.Y1", f"SB_BIG.P{plane}.YDIAG", 3, 0, True, delay=f"{delay}_p{p}_d0_s0")
create_mux(f"SB_BIG.P{plane}.Y2", f"SB_BIG.P{plane}.YDIAG", 3, 1, True) create_mux(f"SB_BIG.P{plane}.Y2", f"SB_BIG.P{plane}.YDIAG", 3, 1, True, delay=f"{delay}_p{p}_d0_s1")
create_mux(f"SB_BIG.P{plane}.Y3", f"SB_BIG.P{plane}.YDIAG", 3, 2, True) create_mux(f"SB_BIG.P{plane}.Y3", f"SB_BIG.P{plane}.YDIAG", 3, 2, True, delay=f"{delay}_p{p}_d0_s2")
create_mux(f"SB_BIG.P{plane}.Y4", f"SB_BIG.P{plane}.YDIAG", 3, 3, True) create_mux(f"SB_BIG.P{plane}.Y4", f"SB_BIG.P{plane}.YDIAG", 3, 3, True, delay=f"{delay}_p{p}_d0_s3")
create_mux(f"SB_BIG.P{plane}.X34", f"SB_BIG.P{plane}.YDIAG", 3, 4, True) create_mux(f"SB_BIG.P{plane}.X34", f"SB_BIG.P{plane}.YDIAG", 3, 4, True, delay="del_dummy")
create_mux(f"SB_BIG.P{plane}.X14", f"SB_BIG.P{plane}.YDIAG", 3, 5, True) create_mux(f"SB_BIG.P{plane}.X14", f"SB_BIG.P{plane}.YDIAG", 3, 5, True, delay="del_dummy")
create_mux(f"SB_BIG.P{plane}.X12", f"SB_BIG.P{plane}.YDIAG", 3, 6, True) create_mux(f"SB_BIG.P{plane}.X12", f"SB_BIG.P{plane}.YDIAG", 3, 6, True, delay="del_dummy")
create_mux(f"SB_BIG.P{plane}.X23", f"SB_BIG.P{plane}.YDIAG", 3, 7, True) create_mux(f"SB_BIG.P{plane}.X23", f"SB_BIG.P{plane}.YDIAG", 3, 7, True, delay="del_dummy")
for i in range(1,5): for i in range(1,5):
create_mux(f"SB_DRIVE.P{plane}.D{i}.IN", f"SB_DRIVE.P{plane}.D{i}.OUT", 1, 1, True, f"SB_DRIVE.P{plane}.D{i}") create_mux(f"SB_DRIVE.P{plane}.D{i}.IN", f"SB_DRIVE.P{plane}.D{i}.OUT", 1, 1, True, f"SB_DRIVE.P{plane}.D{i}", delay="del_sb_drv")
create_mux(f"SB_DRIVE.P{plane}.D{i}.IN", f"SB_DRIVE.P{plane}.D{i}.OUT_NOINV", 1, 1, False, f"SB_DRIVE.P{plane}.D{i}") create_mux(f"SB_DRIVE.P{plane}.D{i}.IN", f"SB_DRIVE.P{plane}.D{i}.OUT_NOINV", 1, 1, False, f"SB_DRIVE.P{plane}.D{i}", delay="del_sb_drv")
if "SB_SML" in type: if "SB_SML" in type:
# SB_SML # SB_SML
for p in range(1,13): for p in range(1,13):
delay = f"sb_del_t1_x1_y1"
plane = f"{p:02d}" plane = f"{p:02d}"
# Per Y output mux # Per Y output mux
for i in range(1,5): for i in range(1,5):
create_mux(f"SB_SML.P{plane}.D0", f"SB_SML.P{plane}.Y{i}_int", 2, 0, False, f"SB_SML.P{plane}.Y{i}") create_mux(f"SB_SML.P{plane}.D0", f"SB_SML.P{plane}.Y{i}_int", 2, 0, False, f"SB_SML.P{plane}.Y{i}", delay="del_dummy")
create_mux(f"SB_SML.P{plane}.YDIAG_int",f"SB_SML.P{plane}.Y{i}_int", 2, 1, False, f"SB_SML.P{plane}.Y{i}") create_mux(f"SB_SML.P{plane}.YDIAG_int",f"SB_SML.P{plane}.Y{i}_int", 2, 1, False, f"SB_SML.P{plane}.Y{i}", delay=f"{delay}_p{p}_d1_s1")
create_mux(f"SB_SML.P{plane}.D2_{i}", f"SB_SML.P{plane}.Y{i}_int", 2, 2, False, f"SB_SML.P{plane}.Y{i}") create_mux(f"SB_SML.P{plane}.D2_{i}", f"SB_SML.P{plane}.Y{i}_int", 2, 2, False, f"SB_SML.P{plane}.Y{i}", delay="del_dummy")
create_mux(f"SB_SML.P{plane}.D3_{i}", f"SB_SML.P{plane}.Y{i}_int", 2, 3, False, f"SB_SML.P{plane}.Y{i}") create_mux(f"SB_SML.P{plane}.D3_{i}", f"SB_SML.P{plane}.Y{i}_int", 2, 3, False, f"SB_SML.P{plane}.Y{i}", delay="del_dummy")
# YDIAG output mux # YDIAG output mux
create_mux(f"SB_SML.P{plane}.Y1_int", f"SB_SML.P{plane}.YDIAG_int", 3, 0, False, f"SB_SML.P{plane}.YDIAG") create_mux(f"SB_SML.P{plane}.Y1_int", f"SB_SML.P{plane}.YDIAG_int", 3, 0, False, f"SB_SML.P{plane}.YDIAG", delay=f"{delay}_p{p}_d0_s0")
create_mux(f"SB_SML.P{plane}.Y2_int", f"SB_SML.P{plane}.YDIAG_int", 3, 1, False, f"SB_SML.P{plane}.YDIAG") create_mux(f"SB_SML.P{plane}.Y2_int", f"SB_SML.P{plane}.YDIAG_int", 3, 1, False, f"SB_SML.P{plane}.YDIAG", delay=f"{delay}_p{p}_d0_s1")
create_mux(f"SB_SML.P{plane}.Y3_int", f"SB_SML.P{plane}.YDIAG_int", 3, 2, False, f"SB_SML.P{plane}.YDIAG") create_mux(f"SB_SML.P{plane}.Y3_int", f"SB_SML.P{plane}.YDIAG_int", 3, 2, False, f"SB_SML.P{plane}.YDIAG", delay=f"{delay}_p{p}_d0_s2")
create_mux(f"SB_SML.P{plane}.Y4_int", f"SB_SML.P{plane}.YDIAG_int", 3, 3, False, f"SB_SML.P{plane}.YDIAG") create_mux(f"SB_SML.P{plane}.Y4_int", f"SB_SML.P{plane}.YDIAG_int", 3, 3, False, f"SB_SML.P{plane}.YDIAG", delay=f"{delay}_p{p}_d0_s3")
create_mux(f"SB_SML.P{plane}.X34", f"SB_SML.P{plane}.YDIAG_int", 3, 4, False, f"SB_SML.P{plane}.YDIAG") create_mux(f"SB_SML.P{plane}.X34", f"SB_SML.P{plane}.YDIAG_int", 3, 4, False, f"SB_SML.P{plane}.YDIAG", delay="del_dummy")
create_mux(f"SB_SML.P{plane}.X14", f"SB_SML.P{plane}.YDIAG_int", 3, 5, False, f"SB_SML.P{plane}.YDIAG") create_mux(f"SB_SML.P{plane}.X14", f"SB_SML.P{plane}.YDIAG_int", 3, 5, False, f"SB_SML.P{plane}.YDIAG", delay="del_dummy")
create_mux(f"SB_SML.P{plane}.X12", f"SB_SML.P{plane}.YDIAG_int", 3, 6, False, f"SB_SML.P{plane}.YDIAG") create_mux(f"SB_SML.P{plane}.X12", f"SB_SML.P{plane}.YDIAG_int", 3, 6, False, f"SB_SML.P{plane}.YDIAG", delay="del_dummy")
create_mux(f"SB_SML.P{plane}.X23", f"SB_SML.P{plane}.YDIAG_int", 3, 7, False, f"SB_SML.P{plane}.YDIAG") create_mux(f"SB_SML.P{plane}.X23", f"SB_SML.P{plane}.YDIAG_int", 3, 7, False, f"SB_SML.P{plane}.YDIAG", delay="del_dummy")
create_mux(f"SB_SML.P{plane}.Y1_int", f"SB_SML.P{plane}.Y1", 1, 1, True, f"SB_SML.P{plane}.Y1_INT", False) create_mux(f"SB_SML.P{plane}.Y1_int", f"SB_SML.P{plane}.Y1", 1, 1, True, f"SB_SML.P{plane}.Y1_INT", False, delay="del_dummy")
create_mux(f"SB_SML.P{plane}.Y2_int", f"SB_SML.P{plane}.Y2", 1, 1, True, f"SB_SML.P{plane}.Y2_INT", False) create_mux(f"SB_SML.P{plane}.Y2_int", f"SB_SML.P{plane}.Y2", 1, 1, True, f"SB_SML.P{plane}.Y2_INT", False, delay="del_dummy")
create_mux(f"SB_SML.P{plane}.Y3_int", f"SB_SML.P{plane}.Y3", 1, 1, True, f"SB_SML.P{plane}.Y3_INT", False) create_mux(f"SB_SML.P{plane}.Y3_int", f"SB_SML.P{plane}.Y3", 1, 1, True, f"SB_SML.P{plane}.Y3_INT", False, delay="del_dummy")
create_mux(f"SB_SML.P{plane}.Y4_int", f"SB_SML.P{plane}.Y4", 1, 1, True, f"SB_SML.P{plane}.Y4_INT", False) create_mux(f"SB_SML.P{plane}.Y4_int", f"SB_SML.P{plane}.Y4", 1, 1, True, f"SB_SML.P{plane}.Y4_INT", False, delay="del_dummy")
create_mux(f"SB_SML.P{plane}.YDIAG_int", f"SB_SML.P{plane}.YDIAG", 1, 1, True, f"SB_SML.P{plane}.YDIAG_INT", False) create_mux(f"SB_SML.P{plane}.YDIAG_int", f"SB_SML.P{plane}.YDIAG", 1, 1, True, f"SB_SML.P{plane}.YDIAG_INT", False, delay="del_dummy")
#if "GPIO" in type: #if "GPIO" in type:
# # GPIO # # GPIO
@ -2653,225 +2674,225 @@ def get_mux_connections_for_type(type):
if "LES" in type: if "LES" in type:
for p in range(1,9): for p in range(1,9):
create_mux(f"LES.SB_Y3.P{p}", "LES.SB_Y3_SEL1_int", 3, p-1, False, "LES.SB_Y3_SEL1") create_mux(f"LES.SB_Y3.P{p}", "LES.SB_Y3_SEL1_int", 3, p-1, False, "LES.SB_Y3_SEL1", delay="del_dummy")
create_mux(f"LES.MDIE1.P{p}", "LES.MDIE1_SEL1_int", 3, p-1, False, "LES.MDIE1_SEL1") create_mux(f"LES.MDIE1.P{p}", "LES.MDIE1_SEL1_int", 3, p-1, False, "LES.MDIE1_SEL1", delay="del_dummy")
create_mux(f"LES.SB_Y3.P{p}", "LES.SB_Y3_SEL2_int", 3, p-1, False, "LES.SB_Y3_SEL2") create_mux(f"LES.SB_Y3.P{p}", "LES.SB_Y3_SEL2_int", 3, p-1, False, "LES.SB_Y3_SEL2", delay="del_dummy")
create_mux(f"LES.MDIE1.P{p}", "LES.MDIE1_SEL2_int", 3, p-1, False, "LES.MDIE1_SEL2") create_mux(f"LES.MDIE1.P{p}", "LES.MDIE1_SEL2_int", 3, p-1, False, "LES.MDIE1_SEL2", delay="del_dummy")
for i in range(4): for i in range(4):
create_mux(f"LES.CLOCK{i}", "LES.CLOCK_SEL1_int", 2, i, False, "LES.CLOCK_SEL1") create_mux(f"LES.CLOCK{i}", "LES.CLOCK_SEL1_int", 2, i, False, "LES.CLOCK_SEL1", delay="del_dummy")
create_mux(f"LES.CLOCK{i}", "LES.CLOCK_SEL2_int", 2, i, False, "LES.CLOCK_SEL2") create_mux(f"LES.CLOCK{i}", "LES.CLOCK_SEL2_int", 2, i, False, "LES.CLOCK_SEL2", delay="del_dummy")
create_mux("LES.SB_Y3_SEL1_int", "LES.CPE_CINX", 2, 1, False, "LES.CINX_SEL") create_mux("LES.SB_Y3_SEL1_int", "LES.CPE_CINX", 2, 1, False, "LES.CINX_SEL", delay="del_left_SB_couty2")
create_mux("LES.MDIE1_SEL1_int", "LES.CPE_CINX", 2, 2, False, "LES.CINX_SEL") create_mux("LES.MDIE1_SEL1_int", "LES.CPE_CINX", 2, 2, False, "LES.CINX_SEL", delay="del_left_couty2")
create_mux("LES.CLOCK_SEL1_int", "LES.CPE_CINX", 2, 3, False, "LES.CINX_SEL") create_mux("LES.CLOCK_SEL1_int", "LES.CPE_CINX", 2, 3, False, "LES.CINX_SEL", delay="del_left_glb_couty2")
create_mux("LES.SB_Y3_SEL2_int", "LES.CPE_PINX", 2, 1, False, "LES.PINX_SEL") create_mux("LES.SB_Y3_SEL2_int", "LES.CPE_PINX", 2, 1, False, "LES.PINX_SEL", delay="del_left_SB_pouty2")
create_mux("LES.MDIE1_SEL2_int", "LES.CPE_PINX", 2, 2, False, "LES.PINX_SEL") create_mux("LES.MDIE1_SEL2_int", "LES.CPE_PINX", 2, 2, False, "LES.PINX_SEL", delay="del_left_pouty2")
create_mux("LES.CLOCK_SEL2_int", "LES.CPE_PINX", 2, 3, False, "LES.PINX_SEL") create_mux("LES.CLOCK_SEL2_int", "LES.CPE_PINX", 2, 3, False, "LES.PINX_SEL", delay="del_left_glb_pouty2")
if "BES" in type: if "BES" in type:
for p in range(1,9): for p in range(1,9):
create_mux(f"BES.SB_Y4.P{p}", "BES.SB_Y4_SEL1_int", 3, p-1, False, "BES.SB_Y4_SEL1") create_mux(f"BES.SB_Y4.P{p}", "BES.SB_Y4_SEL1_int", 3, p-1, False, "BES.SB_Y4_SEL1", delay="del_dummy")
create_mux(f"BES.MDIE2.P{p}", "BES.MDIE2_SEL1_int", 3, p-1, False, "BES.MDIE2_SEL1") create_mux(f"BES.MDIE2.P{p}", "BES.MDIE2_SEL1_int", 3, p-1, False, "BES.MDIE2_SEL1", delay="del_dummy")
create_mux(f"BES.SB_Y4.P{p}", "BES.SB_Y4_SEL2_int", 3, p-1, False, "BES.SB_Y4_SEL2") create_mux(f"BES.SB_Y4.P{p}", "BES.SB_Y4_SEL2_int", 3, p-1, False, "BES.SB_Y4_SEL2", delay="del_dummy")
create_mux(f"BES.MDIE2.P{p}", "BES.MDIE2_SEL2_int", 3, p-1, False, "BES.MDIE2_SEL2") create_mux(f"BES.MDIE2.P{p}", "BES.MDIE2_SEL2_int", 3, p-1, False, "BES.MDIE2_SEL2", delay="del_dummy")
create_mux(f"BES.SB_Y4.P{p}", "BES.SB_Y4_SEL3_int", 3, p-1, False, "BES.SB_Y4_SEL3") create_mux(f"BES.SB_Y4.P{p}", "BES.SB_Y4_SEL3_int", 3, p-1, False, "BES.SB_Y4_SEL3", delay="del_dummy")
create_mux(f"BES.MDIE2.P{p}", "BES.MDIE2_SEL3_int", 3, p-1, False, "BES.MDIE2_SEL3") create_mux(f"BES.MDIE2.P{p}", "BES.MDIE2_SEL3_int", 3, p-1, False, "BES.MDIE2_SEL3", delay="del_dummy")
create_mux(f"BES.SB_Y4.P{p}", "BES.SB_Y4_SEL4_int", 3, p-1, False, "BES.SB_Y4_SEL4") create_mux(f"BES.SB_Y4.P{p}", "BES.SB_Y4_SEL4_int", 3, p-1, False, "BES.SB_Y4_SEL4", delay="del_dummy")
create_mux(f"BES.MDIE2.P{p}", "BES.MDIE2_SEL4_int", 3, p-1, False, "BES.MDIE2_SEL4") create_mux(f"BES.MDIE2.P{p}", "BES.MDIE2_SEL4_int", 3, p-1, False, "BES.MDIE2_SEL4", delay="del_dummy")
for i in range(4): for i in range(4):
create_mux(f"BES.CLOCK{i}", "BES.CLOCK_SEL1_int", 2, i, False, "BES.CLOCK_SEL1") create_mux(f"BES.CLOCK{i}", "BES.CLOCK_SEL1_int", 2, i, False, "BES.CLOCK_SEL1", delay="del_dummy")
create_mux(f"BES.CLOCK{i}", "BES.CLOCK_SEL2_int", 2, i, False, "BES.CLOCK_SEL2") create_mux(f"BES.CLOCK{i}", "BES.CLOCK_SEL2_int", 2, i, False, "BES.CLOCK_SEL2", delay="del_dummy")
create_mux(f"BES.CLOCK{i}", "BES.CLOCK_SEL3_int", 2, i, False, "BES.CLOCK_SEL3") create_mux(f"BES.CLOCK{i}", "BES.CLOCK_SEL3_int", 2, i, False, "BES.CLOCK_SEL3", delay="del_dummy")
create_mux(f"BES.CLOCK{i}", "BES.CLOCK_SEL4_int", 2, i, False, "BES.CLOCK_SEL4") create_mux(f"BES.CLOCK{i}", "BES.CLOCK_SEL4_int", 2, i, False, "BES.CLOCK_SEL4", delay="del_dummy")
create_mux("BES.SB_Y4_SEL1_int", "BES.CPE_CINY1_int", 2, 1, False, "BES.CINY1_SEL") create_mux("BES.SB_Y4_SEL1_int", "BES.CPE_CINY1_int", 2, 1, False, "BES.CINY1_SEL", delay="del_bot_SB_couty2")
create_mux("BES.MDIE2_SEL1_int", "BES.CPE_CINY1_int", 2, 2, False, "BES.CINY1_SEL") create_mux("BES.MDIE2_SEL1_int", "BES.CPE_CINY1_int", 2, 2, False, "BES.CINY1_SEL", delay="del_bot_couty2")
create_mux("BES.CLOCK_SEL1_int", "BES.CPE_CINY1_int", 2, 3, False, "BES.CINY1_SEL") create_mux("BES.CLOCK_SEL1_int", "BES.CPE_CINY1_int", 2, 3, False, "BES.CINY1_SEL", delay="del_bot_glb_couty2")
create_mux("BES.SB_Y4_SEL2_int", "BES.CPE_PINY1_int", 2, 1, False, "BES.PINY1_SEL") create_mux("BES.SB_Y4_SEL2_int", "BES.CPE_PINY1_int", 2, 1, False, "BES.PINY1_SEL", delay="del_bot_SB_pouty2")
create_mux("BES.MDIE2_SEL2_int", "BES.CPE_PINY1_int", 2, 2, False, "BES.PINY1_SEL") create_mux("BES.MDIE2_SEL2_int", "BES.CPE_PINY1_int", 2, 2, False, "BES.PINY1_SEL", delay="del_bot_pouty2")
create_mux("BES.CLOCK_SEL2_int", "BES.CPE_PINY1_int", 2, 3, False, "BES.PINY1_SEL") create_mux("BES.CLOCK_SEL2_int", "BES.CPE_PINY1_int", 2, 3, False, "BES.PINY1_SEL", delay="del_bot_glb_pouty2")
create_mux("BES.SB_Y4_SEL3_int", "BES.CPE_CINY2_int", 2, 1, False, "BES.CINY2_SEL") create_mux("BES.SB_Y4_SEL3_int", "BES.CPE_CINY2_int", 2, 1, False, "BES.CINY2_SEL", delay="del_bot_SB_couty2")
create_mux("BES.MDIE2_SEL3_int", "BES.CPE_CINY2_int", 2, 2, False, "BES.CINY2_SEL") create_mux("BES.MDIE2_SEL3_int", "BES.CPE_CINY2_int", 2, 2, False, "BES.CINY2_SEL", delay="del_bot_couty2")
create_mux("BES.CLOCK_SEL3_int", "BES.CPE_CINY2_int", 2, 3, False, "BES.CINY2_SEL") create_mux("BES.CLOCK_SEL3_int", "BES.CPE_CINY2_int", 2, 3, False, "BES.CINY2_SEL", delay="del_bot_glb_couty2")
create_mux("BES.SB_Y4_SEL4_int", "BES.CPE_PINY2_int", 2, 1, False, "BES.PINY2_SEL") create_mux("BES.SB_Y4_SEL4_int", "BES.CPE_PINY2_int", 2, 1, False, "BES.PINY2_SEL", delay="del_bot_SB_pouty2")
create_mux("BES.MDIE2_SEL4_int", "BES.CPE_PINY2_int", 2, 2, False, "BES.PINY2_SEL") create_mux("BES.MDIE2_SEL4_int", "BES.CPE_PINY2_int", 2, 2, False, "BES.PINY2_SEL", delay="del_bot_pouty2")
create_mux("BES.CLOCK_SEL4_int", "BES.CPE_PINY2_int", 2, 3, False, "BES.PINY2_SEL") create_mux("BES.CLOCK_SEL4_int", "BES.CPE_PINY2_int", 2, 3, False, "BES.PINY2_SEL", delay="del_bot_glb_pouty2")
create_mux("BES.CPE_CINY1_int", "BES.CPE_CINY1", 1, 0, False, "BES.P_CINY1") create_mux("BES.CPE_CINY1_int", "BES.CPE_CINY1", 1, 0, False, "BES.P_CINY1", delay="del_dummy")
create_mux("BES.P_CINY1", "BES.CPE_CINY1", 1, 1, False, "BES.P_CINY1") create_mux("BES.P_CINY1", "BES.CPE_CINY1", 1, 1, False, "BES.P_CINY1", delay="del_dummy")
create_mux("BES.CPE_PINY1_int", "BES.CPE_PINY1", 1, 0, False, "BES.P_PINY1") create_mux("BES.CPE_PINY1_int", "BES.CPE_PINY1", 1, 0, False, "BES.P_PINY1", delay="del_dummy")
create_mux("BES.P_PINY1", "BES.CPE_PINY1", 1, 1, False, "BES.P_PINY1") create_mux("BES.P_PINY1", "BES.CPE_PINY1", 1, 1, False, "BES.P_PINY1", delay="del_dummy")
create_mux("BES.CPE_CINY2_int", "BES.CPE_CINY2", 1, 0, False, "BES.P_CINY2") create_mux("BES.CPE_CINY2_int", "BES.CPE_CINY2", 1, 0, False, "BES.P_CINY2", delay="del_dummy")
create_mux("BES.P_CINY2", "BES.CPE_CINY2", 1, 1, False, "BES.P_CINY2") create_mux("BES.P_CINY2", "BES.CPE_CINY2", 1, 1, False, "BES.P_CINY2", delay="del_dummy")
create_mux("BES.CPE_PINY2_int", "BES.CPE_PINY2", 1, 0, False, "BES.P_PINY2") create_mux("BES.CPE_PINY2_int", "BES.CPE_PINY2", 1, 0, False, "BES.P_PINY2", delay="del_dummy")
create_mux("BES.P_PINY2", "BES.CPE_PINY2", 1, 1, False, "BES.P_PINY2") create_mux("BES.P_PINY2", "BES.CPE_PINY2", 1, 1, False, "BES.P_PINY2", delay="del_dummy")
if "RES" in type: if "RES" in type:
for sel in range(4): for sel in range(4):
create_mux("RES.CPE_RAM_O1", f"RES.SIG_SEL{sel+1}_int", 3, 0, False, f"RES.SIG_SEL{sel+1}") create_mux("RES.CPE_RAM_O1", f"RES.SIG_SEL{sel+1}_int", 3, 0, False, f"RES.SIG_SEL{sel+1}", delay="del_dummy")
create_mux("RES.CPE_RAM_O2", f"RES.SIG_SEL{sel+1}_int", 3, 1, False, f"RES.SIG_SEL{sel+1}") create_mux("RES.CPE_RAM_O2", f"RES.SIG_SEL{sel+1}_int", 3, 1, False, f"RES.SIG_SEL{sel+1}", delay="del_dummy")
create_mux("RES.CPE_COUTX", f"RES.SIG_SEL{sel+1}_int", 3, 2, False, f"RES.SIG_SEL{sel+1}") create_mux("RES.CPE_COUTX", f"RES.SIG_SEL{sel+1}_int", 3, 2, False, f"RES.SIG_SEL{sel+1}", delay="del_dummy")
create_mux("RES.CPE_POUTX", f"RES.SIG_SEL{sel+1}_int", 3, 3, False, f"RES.SIG_SEL{sel+1}") create_mux("RES.CPE_POUTX", f"RES.SIG_SEL{sel+1}_int", 3, 3, False, f"RES.SIG_SEL{sel+1}", delay="del_dummy")
for i in range(4): for i in range(4):
create_mux(f"RES.CLOCK{i}", f"RES.SIG_SEL{sel+1}_int", 3, 4 + i, False, f"RES.SIG_SEL{sel+1}") create_mux(f"RES.CLOCK{i}", f"RES.SIG_SEL{sel+1}_int", 3, 4 + i, False, f"RES.SIG_SEL{sel+1}", delay="del_dummy")
for p in range(1,9): for p in range(1,9):
create_mux(f"RES.SB_Y1.P{p}", f"RES.MDIE1.P{p}", 1, 0, False, f"RES.SEL_MDIE{p}") create_mux(f"RES.SB_Y1.P{p}", f"RES.MDIE1.P{p}", 1, 0, False, f"RES.SEL_MDIE{p}", delay="del_dummy")
sel = (p - 1) // 2 + 1 sel = (p - 1) // 2 + 1
create_mux(f"RES.SIG_SEL{sel}_int", f"RES.MDIE1.P{p}", 1, 1, False, f"RES.SEL_MDIE{p}") create_mux(f"RES.SIG_SEL{sel}_int", f"RES.MDIE1.P{p}", 1, 1, False, f"RES.SEL_MDIE{p}", delay="del_dummy")
if "TES" in type: if "TES" in type:
for sel in range(4): for sel in range(4):
create_mux("TES.CPE_RAM_O1", f"TES.SIG_SEL{sel+1}_int", 3, 0, False, f"TES.SIG_SEL{sel+1}") create_mux("TES.CPE_RAM_O1", f"TES.SIG_SEL{sel+1}_int", 3, 0, False, f"TES.SIG_SEL{sel+1}", delay="del_dummy")
create_mux("TES.CPE_RAM_O2", f"TES.SIG_SEL{sel+1}_int", 3, 1, False, f"TES.SIG_SEL{sel+1}") create_mux("TES.CPE_RAM_O2", f"TES.SIG_SEL{sel+1}_int", 3, 1, False, f"TES.SIG_SEL{sel+1}", delay="del_dummy")
create_mux("TES.CPE_COUTY1", f"TES.SIG_SEL{sel+1}_int", 3, 2, False, f"TES.SIG_SEL{sel+1}") create_mux("TES.CPE_COUTY1", f"TES.SIG_SEL{sel+1}_int", 3, 2, False, f"TES.SIG_SEL{sel+1}", delay="del_dummy")
create_mux("TES.CPE_POUTY1", f"TES.SIG_SEL{sel+1}_int", 3, 3, False, f"TES.SIG_SEL{sel+1}") create_mux("TES.CPE_POUTY1", f"TES.SIG_SEL{sel+1}_int", 3, 3, False, f"TES.SIG_SEL{sel+1}", delay="del_dummy")
create_mux("TES.CPE_COUTY2", f"TES.SIG_SEL{sel+1}_int", 3, 4, False, f"TES.SIG_SEL{sel+1}") create_mux("TES.CPE_COUTY2", f"TES.SIG_SEL{sel+1}_int", 3, 4, False, f"TES.SIG_SEL{sel+1}", delay="del_dummy")
create_mux("TES.CPE_POUTY2", f"TES.SIG_SEL{sel+1}_int", 3, 5, False, f"TES.SIG_SEL{sel+1}") create_mux("TES.CPE_POUTY2", f"TES.SIG_SEL{sel+1}_int", 3, 5, False, f"TES.SIG_SEL{sel+1}", delay="del_dummy")
clk = 0 if sel < 2 else 2 clk = 0 if sel < 2 else 2
create_mux(f"TES.CLOCK{clk+0}", f"TES.SIG_SEL{sel+1}_int", 3, 6, False, f"TES.SIG_SEL{sel+1}") create_mux(f"TES.CLOCK{clk+0}", f"TES.SIG_SEL{sel+1}_int", 3, 6, False, f"TES.SIG_SEL{sel+1}", delay="del_dummy")
create_mux(f"TES.CLOCK{clk+1}", f"TES.SIG_SEL{sel+1}_int", 3, 7, False, f"TES.SIG_SEL{sel+1}") create_mux(f"TES.CLOCK{clk+1}", f"TES.SIG_SEL{sel+1}_int", 3, 7, False, f"TES.SIG_SEL{sel+1}", delay="del_dummy")
for p in range(1,9): for p in range(1,9):
create_mux(f"TES.SB_Y2.P{p}", f"TES.MDIE2.P{p}", 1, 0, False, f"TES.SEL_MDIE{p}") create_mux(f"TES.SB_Y2.P{p}", f"TES.MDIE2.P{p}", 1, 0, False, f"TES.SEL_MDIE{p}", delay="del_dummy")
sel = (p - 1) // 2 + 1 sel = (p - 1) // 2 + 1
create_mux(f"TES.SIG_SEL{sel}_int", f"TES.MDIE2.P{p}", 1, 1, False, f"TES.SEL_MDIE{p}") create_mux(f"TES.SIG_SEL{sel}_int", f"TES.MDIE2.P{p}", 1, 1, False, f"TES.SEL_MDIE{p}", delay="del_dummy")
if "PLL" in type: if "PLL" in type:
# CLKIN # CLKIN
create_mux("CLKIN.CLK0", "CLKIN.CLK_REF_INT0", 3, 0, False, "CLKIN.REF0", config=True) create_mux("CLKIN.CLK0", "CLKIN.CLK_REF_INT0", 3, 0, False, "CLKIN.REF0", config=True, delay="clkin_CLK0_I_CLK_OUT0")
create_mux("CLKIN.CLK1", "CLKIN.CLK_REF_INT0", 3, 1, False, "CLKIN.REF0", config=True) create_mux("CLKIN.CLK1", "CLKIN.CLK_REF_INT0", 3, 1, False, "CLKIN.REF0", config=True, delay="clkin_CLK1_I_CLK_OUT0")
create_mux("CLKIN.CLK2", "CLKIN.CLK_REF_INT0", 3, 2, False, "CLKIN.REF0", config=True) create_mux("CLKIN.CLK2", "CLKIN.CLK_REF_INT0", 3, 2, False, "CLKIN.REF0", config=True, delay="clkin_CLK2_I_CLK_OUT0")
create_mux("CLKIN.CLK3", "CLKIN.CLK_REF_INT0", 3, 3, False, "CLKIN.REF0", config=True) create_mux("CLKIN.CLK3", "CLKIN.CLK_REF_INT0", 3, 3, False, "CLKIN.REF0", config=True, delay="clkin_CLK3_I_CLK_OUT0")
create_mux("CLKIN.SER_CLK", "CLKIN.CLK_REF_INT0", 3, 4, False, "CLKIN.REF0", config=True) create_mux("CLKIN.SER_CLK", "CLKIN.CLK_REF_INT0", 3, 4, False, "CLKIN.REF0", config=True, delay="clkin_SERDES_CLK_CLK_OUT0")
create_mux("CLKIN.CLK_REF_INT0", "CLKIN.CLK_REF_0", 1, 0, False, "CLKIN.REF0_INV", config=True) create_mux("CLKIN.CLK_REF_INT0", "CLKIN.CLK_REF_0", 1, 0, False, "CLKIN.REF0_INV", config=True, delay="del_dummy")
create_mux("CLKIN.CLK0", "CLKIN.CLK_REF_INT1", 3, 0, False, "CLKIN.REF1", config=True) create_mux("CLKIN.CLK0", "CLKIN.CLK_REF_INT1", 3, 0, False, "CLKIN.REF1", config=True, delay="clkin_CLK0_I_CLK_OUT1")
create_mux("CLKIN.CLK1", "CLKIN.CLK_REF_INT1", 3, 1, False, "CLKIN.REF1", config=True) create_mux("CLKIN.CLK1", "CLKIN.CLK_REF_INT1", 3, 1, False, "CLKIN.REF1", config=True, delay="clkin_CLK1_I_CLK_OUT1")
create_mux("CLKIN.CLK2", "CLKIN.CLK_REF_INT1", 3, 2, False, "CLKIN.REF1", config=True) create_mux("CLKIN.CLK2", "CLKIN.CLK_REF_INT1", 3, 2, False, "CLKIN.REF1", config=True, delay="clkin_CLK2_I_CLK_OUT1")
create_mux("CLKIN.CLK3", "CLKIN.CLK_REF_INT1", 3, 3, False, "CLKIN.REF1", config=True) create_mux("CLKIN.CLK3", "CLKIN.CLK_REF_INT1", 3, 3, False, "CLKIN.REF1", config=True, delay="clkin_CLK3_I_CLK_OUT1")
create_mux("CLKIN.SER_CLK", "CLKIN.CLK_REF_INT1", 3, 4, False, "CLKIN.REF1", config=True) create_mux("CLKIN.SER_CLK", "CLKIN.CLK_REF_INT1", 3, 4, False, "CLKIN.REF1", config=True, delay="clkin_SERDES_CLK_CLK_OUT1")
create_mux("CLKIN.CLK_REF_INT1", "CLKIN.CLK_REF_1", 1, 0, False, "CLKIN.REF1_INV", config=True) create_mux("CLKIN.CLK_REF_INT1", "CLKIN.CLK_REF_1", 1, 0, False, "CLKIN.REF1_INV", config=True, delay="del_dummy")
create_mux("CLKIN.CLK0", "CLKIN.CLK_REF_INT2", 3, 0, False, "CLKIN.REF2", config=True) create_mux("CLKIN.CLK0", "CLKIN.CLK_REF_INT2", 3, 0, False, "CLKIN.REF2", config=True, delay="clkin_CLK0_I_CLK_OUT2")
create_mux("CLKIN.CLK1", "CLKIN.CLK_REF_INT2", 3, 1, False, "CLKIN.REF2", config=True) create_mux("CLKIN.CLK1", "CLKIN.CLK_REF_INT2", 3, 1, False, "CLKIN.REF2", config=True, delay="clkin_CLK1_I_CLK_OUT2")
create_mux("CLKIN.CLK2", "CLKIN.CLK_REF_INT2", 3, 2, False, "CLKIN.REF2", config=True) create_mux("CLKIN.CLK2", "CLKIN.CLK_REF_INT2", 3, 2, False, "CLKIN.REF2", config=True, delay="clkin_CLK2_I_CLK_OUT2")
create_mux("CLKIN.CLK3", "CLKIN.CLK_REF_INT2", 3, 3, False, "CLKIN.REF2", config=True) create_mux("CLKIN.CLK3", "CLKIN.CLK_REF_INT2", 3, 3, False, "CLKIN.REF2", config=True, delay="clkin_CLK3_I_CLK_OUT2")
create_mux("CLKIN.SER_CLK", "CLKIN.CLK_REF_INT2", 3, 4, False, "CLKIN.REF2", config=True) create_mux("CLKIN.SER_CLK", "CLKIN.CLK_REF_INT2", 3, 4, False, "CLKIN.REF2", config=True, delay="clkin_SERDES_CLK_CLK_OUT2")
create_mux("CLKIN.CLK_REF_INT2", "CLKIN.CLK_REF_2", 1, 0, False, "CLKIN.REF2_INV", config=True) create_mux("CLKIN.CLK_REF_INT2", "CLKIN.CLK_REF_2", 1, 0, False, "CLKIN.REF2_INV", config=True, delay="del_dummy")
create_mux("CLKIN.CLK0", "CLKIN.CLK_REF_INT3", 3, 0, False, "CLKIN.REF3", config=True) create_mux("CLKIN.CLK0", "CLKIN.CLK_REF_INT3", 3, 0, False, "CLKIN.REF3", config=True, delay="clkin_CLK0_I_CLK_OUT3")
create_mux("CLKIN.CLK1", "CLKIN.CLK_REF_INT3", 3, 1, False, "CLKIN.REF3", config=True) create_mux("CLKIN.CLK1", "CLKIN.CLK_REF_INT3", 3, 1, False, "CLKIN.REF3", config=True, delay="clkin_CLK1_I_CLK_OUT3")
create_mux("CLKIN.CLK2", "CLKIN.CLK_REF_INT3", 3, 2, False, "CLKIN.REF3", config=True) create_mux("CLKIN.CLK2", "CLKIN.CLK_REF_INT3", 3, 2, False, "CLKIN.REF3", config=True, delay="clkin_CLK2_I_CLK_OUT3")
create_mux("CLKIN.CLK3", "CLKIN.CLK_REF_INT3", 3, 3, False, "CLKIN.REF3", config=True) create_mux("CLKIN.CLK3", "CLKIN.CLK_REF_INT3", 3, 3, False, "CLKIN.REF3", config=True, delay="clkin_CLK3_I_CLK_OUT3")
create_mux("CLKIN.SER_CLK", "CLKIN.CLK_REF_INT3", 3, 4, False, "CLKIN.REF3", config=True) create_mux("CLKIN.SER_CLK", "CLKIN.CLK_REF_INT3", 3, 4, False, "CLKIN.REF3", config=True, delay="clkin_SERDES_CLK_CLK_OUT3")
create_mux("CLKIN.CLK_REF_INT3", "CLKIN.CLK_REF_3", 1, 0, False, "CLKIN.REF3_INV", config=True) create_mux("CLKIN.CLK_REF_INT3", "CLKIN.CLK_REF_3", 1, 0, False, "CLKIN.REF3_INV", config=True, delay="del_dummy")
# GLBOUT # GLBOUT
create_mux("GLBOUT.CLK_REF_OUT0", "GLBOUT.CLK_INT_0", 3, 0, False, "GLBOUT.GLB0", config=True) create_mux("GLBOUT.CLK_REF_OUT0", "GLBOUT.CLK_INT_0", 3, 0, False, "GLBOUT.GLB0", config=True, delay="glbout_CLKREF_0_CLOCK0")
create_mux("GLBOUT.CLK0_1", "GLBOUT.CLK_INT_0", 3, 1, False, "GLBOUT.GLB0", config=True) create_mux("GLBOUT.CLK0_1", "GLBOUT.CLK_INT_0", 3, 1, False, "GLBOUT.GLB0", config=True, delay="glbout_CLK0_1_CLOCK0")
create_mux("GLBOUT.CLK0_2", "GLBOUT.CLK_INT_0", 3, 2, False, "GLBOUT.GLB0", config=True) create_mux("GLBOUT.CLK0_2", "GLBOUT.CLK_INT_0", 3, 2, False, "GLBOUT.GLB0", config=True, delay="glbout_CLK0_2_CLOCK0")
create_mux("GLBOUT.CLK0_3", "GLBOUT.CLK_INT_0", 3, 3, False, "GLBOUT.GLB0", config=True) create_mux("GLBOUT.CLK0_3", "GLBOUT.CLK_INT_0", 3, 3, False, "GLBOUT.GLB0", config=True, delay="glbout_CLK0_3_CLOCK0")
create_mux("GLBOUT.CLK0_0", "GLBOUT.CLK_INT_0", 3, 4, False, "GLBOUT.GLB0", config=True) create_mux("GLBOUT.CLK0_0", "GLBOUT.CLK_INT_0", 3, 4, False, "GLBOUT.GLB0", config=True, delay="glbout_CLK0_0_CLOCK0")
create_mux("GLBOUT.CLK90_0", "GLBOUT.CLK_INT_0", 3, 5, False, "GLBOUT.GLB0", config=True) create_mux("GLBOUT.CLK90_0", "GLBOUT.CLK_INT_0", 3, 5, False, "GLBOUT.GLB0", config=True, delay="glbout_CLK90_0_CLOCK0")
create_mux("GLBOUT.CLK180_0", "GLBOUT.CLK_INT_0", 3, 6, False, "GLBOUT.GLB0", config=True) create_mux("GLBOUT.CLK180_0", "GLBOUT.CLK_INT_0", 3, 6, False, "GLBOUT.GLB0", config=True, delay="glbout_CLK180_0_CLOCK0")
create_mux("GLBOUT.CLK270_0", "GLBOUT.CLK_INT_0", 3, 7, False, "GLBOUT.GLB0", config=True) create_mux("GLBOUT.CLK270_0", "GLBOUT.CLK_INT_0", 3, 7, False, "GLBOUT.GLB0", config=True, delay="glbout_CLK270_0_CLOCK0")
create_mux("GLBOUT.CLK_INT_0", "GLBOUT.CLK_SEL_INT_0", 1, 0, False, "GLBOUT.USR_GLB0", config=True) create_mux("GLBOUT.CLK_INT_0", "GLBOUT.CLK_SEL_INT_0", 1, 0, False, "GLBOUT.USR_GLB0", config=True, delay="del_dummy")
create_mux("GLBOUT.USR_GLB0", "GLBOUT.CLK_SEL_INT_0", 1, 1, False, "GLBOUT.USR_GLB0", config=True) create_mux("GLBOUT.USR_GLB0", "GLBOUT.CLK_SEL_INT_0", 1, 1, False, "GLBOUT.USR_GLB0", config=True, delay="glbout_U_CLK0_CLOCK0")
create_mux("GLBOUT.CLK_SEL_INT_0", "GLBOUT.GLB0", 1, 1, False, "GLBOUT.GLB0_EN", config=True) create_mux("GLBOUT.CLK_SEL_INT_0", "GLBOUT.GLB0", 1, 1, False, "GLBOUT.GLB0_EN", config=True, delay="del_dummy")
create_mux("GLBOUT.GLB0", "GLBOUT.FB_INT_0", 2, 0, False, "GLBOUT.FB0", config=True) create_mux("GLBOUT.GLB0", "GLBOUT.FB_INT_0", 2, 0, False, "GLBOUT.FB0", config=True, delay="glbout_FEEDBACK_delay")
create_mux("GLBOUT.GLB1", "GLBOUT.FB_INT_0", 2, 1, False, "GLBOUT.FB0", config=True) create_mux("GLBOUT.GLB1", "GLBOUT.FB_INT_0", 2, 1, False, "GLBOUT.FB0", config=True, delay="glbout_FEEDBACK_delay")
create_mux("GLBOUT.GLB2", "GLBOUT.FB_INT_0", 2, 2, False, "GLBOUT.FB0", config=True) create_mux("GLBOUT.GLB2", "GLBOUT.FB_INT_0", 2, 2, False, "GLBOUT.FB0", config=True, delay="glbout_FEEDBACK_delay")
create_mux("GLBOUT.GLB3", "GLBOUT.FB_INT_0", 2, 3, False, "GLBOUT.FB0", config=True) create_mux("GLBOUT.GLB3", "GLBOUT.FB_INT_0", 2, 3, False, "GLBOUT.FB0", config=True, delay="glbout_FEEDBACK_delay")
create_mux("GLBOUT.FB_INT_0", "GLBOUT.CLK_FB0", 1, 0, False, "GLBOUT.USR_FB0", config=True) create_mux("GLBOUT.FB_INT_0", "GLBOUT.CLK_FB0", 1, 0, False, "GLBOUT.USR_FB0", config=True, delay="del_dummy")
create_mux("GLBOUT.USR_FB0", "GLBOUT.CLK_FB0", 1, 1, False, "GLBOUT.USR_FB0", config=True) create_mux("GLBOUT.USR_FB0", "GLBOUT.CLK_FB0", 1, 1, False, "GLBOUT.USR_FB0", config=True, delay="glbout_U_FB0_CLK_FB0")
create_mux("GLBOUT.CLK_REF_OUT1", "GLBOUT.CLK_INT_1", 3, 0, False, "GLBOUT.GLB1", config=True) create_mux("GLBOUT.CLK_REF_OUT1", "GLBOUT.CLK_INT_1", 3, 0, False, "GLBOUT.GLB1", config=True, delay="glbout_CLKREF_1_CLOCK1")
create_mux("GLBOUT.CLK90_0", "GLBOUT.CLK_INT_1", 3, 1, False, "GLBOUT.GLB1", config=True) create_mux("GLBOUT.CLK90_0", "GLBOUT.CLK_INT_1", 3, 1, False, "GLBOUT.GLB1", config=True, delay="glbout_CLK90_0_CLOCK1")
create_mux("GLBOUT.CLK90_2", "GLBOUT.CLK_INT_1", 3, 2, False, "GLBOUT.GLB1", config=True) create_mux("GLBOUT.CLK90_2", "GLBOUT.CLK_INT_1", 3, 2, False, "GLBOUT.GLB1", config=True, delay="glbout_CLK90_2_CLOCK1")
create_mux("GLBOUT.CLK90_3", "GLBOUT.CLK_INT_1", 3, 3, False, "GLBOUT.GLB1", config=True) create_mux("GLBOUT.CLK90_3", "GLBOUT.CLK_INT_1", 3, 3, False, "GLBOUT.GLB1", config=True, delay="glbout_CLK90_3_CLOCK1")
create_mux("GLBOUT.CLK0_1", "GLBOUT.CLK_INT_1", 3, 4, False, "GLBOUT.GLB1", config=True) create_mux("GLBOUT.CLK0_1", "GLBOUT.CLK_INT_1", 3, 4, False, "GLBOUT.GLB1", config=True, delay="glbout_CLK0_1_CLOCK1")
create_mux("GLBOUT.CLK90_1", "GLBOUT.CLK_INT_1", 3, 5, False, "GLBOUT.GLB1", config=True) create_mux("GLBOUT.CLK90_1", "GLBOUT.CLK_INT_1", 3, 5, False, "GLBOUT.GLB1", config=True, delay="glbout_CLK90_1_CLOCK1")
create_mux("GLBOUT.CLK180_1", "GLBOUT.CLK_INT_1", 3, 6, False, "GLBOUT.GLB1", config=True) create_mux("GLBOUT.CLK180_1", "GLBOUT.CLK_INT_1", 3, 6, False, "GLBOUT.GLB1", config=True, delay="glbout_CLK180_1_CLOCK1")
create_mux("GLBOUT.CLK270_1", "GLBOUT.CLK_INT_1", 3, 7, False, "GLBOUT.GLB1", config=True) create_mux("GLBOUT.CLK270_1", "GLBOUT.CLK_INT_1", 3, 7, False, "GLBOUT.GLB1", config=True, delay="glbout_CLK270_1_CLOCK1")
create_mux("GLBOUT.CLK_INT_1", "GLBOUT.CLK_SEL_INT_1", 1, 0, False, "GLBOUT.USR_GLB1", config=True) create_mux("GLBOUT.CLK_INT_1", "GLBOUT.CLK_SEL_INT_1", 1, 0, False, "GLBOUT.USR_GLB1", config=True, delay="del_dummy")
create_mux("GLBOUT.USR_GLB1", "GLBOUT.CLK_SEL_INT_1", 1, 1, False, "GLBOUT.USR_GLB1", config=True) create_mux("GLBOUT.USR_GLB1", "GLBOUT.CLK_SEL_INT_1", 1, 1, False, "GLBOUT.USR_GLB1", config=True, delay="glbout_U_CLK1_CLOCK1")
create_mux("GLBOUT.CLK_SEL_INT_1", "GLBOUT.GLB1", 1, 1, False, "GLBOUT.GLB1_EN", config=True) create_mux("GLBOUT.CLK_SEL_INT_1", "GLBOUT.GLB1", 1, 1, False, "GLBOUT.GLB1_EN", config=True, delay="del_dummy")
create_mux("GLBOUT.GLB0", "GLBOUT.FB_INT_1", 2, 0, False, "GLBOUT.FB1", config=True) create_mux("GLBOUT.GLB0", "GLBOUT.FB_INT_1", 2, 0, False, "GLBOUT.FB1", config=True, delay="glbout_FEEDBACK_delay")
create_mux("GLBOUT.GLB1", "GLBOUT.FB_INT_1", 2, 1, False, "GLBOUT.FB1", config=True) create_mux("GLBOUT.GLB1", "GLBOUT.FB_INT_1", 2, 1, False, "GLBOUT.FB1", config=True, delay="glbout_FEEDBACK_delay")
create_mux("GLBOUT.GLB2", "GLBOUT.FB_INT_1", 2, 2, False, "GLBOUT.FB1", config=True) create_mux("GLBOUT.GLB2", "GLBOUT.FB_INT_1", 2, 2, False, "GLBOUT.FB1", config=True, delay="glbout_FEEDBACK_delay")
create_mux("GLBOUT.GLB3", "GLBOUT.FB_INT_1", 2, 3, False, "GLBOUT.FB1", config=True) create_mux("GLBOUT.GLB3", "GLBOUT.FB_INT_1", 2, 3, False, "GLBOUT.FB1", config=True, delay="glbout_FEEDBACK_delay")
create_mux("GLBOUT.FB_INT_1", "GLBOUT.CLK_FB1", 1, 0, False, "GLBOUT.USR_FB1", config=True) create_mux("GLBOUT.FB_INT_1", "GLBOUT.CLK_FB1", 1, 0, False, "GLBOUT.USR_FB1", config=True, delay="del_dummy")
create_mux("GLBOUT.USR_FB1", "GLBOUT.CLK_FB1", 1, 1, False, "GLBOUT.USR_FB1", config=True) create_mux("GLBOUT.USR_FB1", "GLBOUT.CLK_FB1", 1, 1, False, "GLBOUT.USR_FB1", config=True, delay="glbout_U_FB1_CLK_FB1")
create_mux("GLBOUT.CLK_REF_OUT2", "GLBOUT.CLK_INT_2", 3, 0, False, "GLBOUT.GLB2", config=True) create_mux("GLBOUT.CLK_REF_OUT2", "GLBOUT.CLK_INT_2", 3, 0, False, "GLBOUT.GLB2", config=True, delay="glbout_CLKREF_2_CLOCK2")
create_mux("GLBOUT.CLK180_0", "GLBOUT.CLK_INT_2", 3, 1, False, "GLBOUT.GLB2", config=True) create_mux("GLBOUT.CLK180_0", "GLBOUT.CLK_INT_2", 3, 1, False, "GLBOUT.GLB2", config=True, delay="glbout_CLK180_0_CLOCK2")
create_mux("GLBOUT.CLK180_1", "GLBOUT.CLK_INT_2", 3, 2, False, "GLBOUT.GLB2", config=True) create_mux("GLBOUT.CLK180_1", "GLBOUT.CLK_INT_2", 3, 2, False, "GLBOUT.GLB2", config=True, delay="glbout_CLK180_1_CLOCK2")
create_mux("GLBOUT.CLK180_3", "GLBOUT.CLK_INT_2", 3, 3, False, "GLBOUT.GLB2", config=True) create_mux("GLBOUT.CLK180_3", "GLBOUT.CLK_INT_2", 3, 3, False, "GLBOUT.GLB2", config=True, delay="glbout_CLK180_3_CLOCK2")
create_mux("GLBOUT.CLK0_2", "GLBOUT.CLK_INT_2", 3, 4, False, "GLBOUT.GLB2", config=True) create_mux("GLBOUT.CLK0_2", "GLBOUT.CLK_INT_2", 3, 4, False, "GLBOUT.GLB2", config=True, delay="glbout_CLK0_2_CLOCK2")
create_mux("GLBOUT.CLK90_2", "GLBOUT.CLK_INT_2", 3, 5, False, "GLBOUT.GLB2", config=True) create_mux("GLBOUT.CLK90_2", "GLBOUT.CLK_INT_2", 3, 5, False, "GLBOUT.GLB2", config=True, delay="glbout_CLK90_2_CLOCK2")
create_mux("GLBOUT.CLK180_2", "GLBOUT.CLK_INT_2", 3, 6, False, "GLBOUT.GLB2", config=True) create_mux("GLBOUT.CLK180_2", "GLBOUT.CLK_INT_2", 3, 6, False, "GLBOUT.GLB2", config=True, delay="glbout_CLK180_2_CLOCK2")
create_mux("GLBOUT.CLK270_2", "GLBOUT.CLK_INT_2", 3, 7, False, "GLBOUT.GLB2", config=True) create_mux("GLBOUT.CLK270_2", "GLBOUT.CLK_INT_2", 3, 7, False, "GLBOUT.GLB2", config=True, delay="glbout_CLK270_2_CLOCK2")
create_mux("GLBOUT.CLK_INT_2", "GLBOUT.CLK_SEL_INT_2", 1, 0, False, "GLBOUT.USR_GLB2", config=True) create_mux("GLBOUT.CLK_INT_2", "GLBOUT.CLK_SEL_INT_2", 1, 0, False, "GLBOUT.USR_GLB2", config=True, delay="del_dummy")
create_mux("GLBOUT.USR_GLB2", "GLBOUT.CLK_SEL_INT_2", 1, 1, False, "GLBOUT.USR_GLB2", config=True) create_mux("GLBOUT.USR_GLB2", "GLBOUT.CLK_SEL_INT_2", 1, 1, False, "GLBOUT.USR_GLB2", config=True)
create_mux("GLBOUT.CLK_SEL_INT_2", "GLBOUT.GLB2", 1, 1, False, "GLBOUT.GLB2_EN", config=True) create_mux("GLBOUT.CLK_SEL_INT_2", "GLBOUT.GLB2", 1, 1, False, "GLBOUT.GLB2_EN", config=True, delay="del_dummy")
create_mux("GLBOUT.GLB0", "GLBOUT.FB_INT_2", 2, 0, False, "GLBOUT.FB2", config=True) create_mux("GLBOUT.GLB0", "GLBOUT.FB_INT_2", 2, 0, False, "GLBOUT.FB2", config=True, delay="glbout_FEEDBACK_delay")
create_mux("GLBOUT.GLB1", "GLBOUT.FB_INT_2", 2, 1, False, "GLBOUT.FB2", config=True) create_mux("GLBOUT.GLB1", "GLBOUT.FB_INT_2", 2, 1, False, "GLBOUT.FB2", config=True, delay="glbout_FEEDBACK_delay")
create_mux("GLBOUT.GLB2", "GLBOUT.FB_INT_2", 2, 2, False, "GLBOUT.FB2", config=True) create_mux("GLBOUT.GLB2", "GLBOUT.FB_INT_2", 2, 2, False, "GLBOUT.FB2", config=True, delay="glbout_FEEDBACK_delay")
create_mux("GLBOUT.GLB3", "GLBOUT.FB_INT_2", 2, 3, False, "GLBOUT.FB2", config=True) create_mux("GLBOUT.GLB3", "GLBOUT.FB_INT_2", 2, 3, False, "GLBOUT.FB2", config=True, delay="glbout_FEEDBACK_delay")
create_mux("GLBOUT.FB_INT_2", "GLBOUT.CLK_FB2", 1, 0, False, "GLBOUT.USR_FB2", config=True) create_mux("GLBOUT.FB_INT_2", "GLBOUT.CLK_FB2", 1, 0, False, "GLBOUT.USR_FB2", config=True, delay="del_dummy")
create_mux("GLBOUT.USR_FB2", "GLBOUT.CLK_FB2", 1, 1, False, "GLBOUT.USR_FB2", config=True) create_mux("GLBOUT.USR_FB2", "GLBOUT.CLK_FB2", 1, 1, False, "GLBOUT.USR_FB2", config=True, delay="glbout_U_FB2_CLK_FB2")
create_mux("GLBOUT.CLK_REF_OUT3", "GLBOUT.CLK_INT_3", 3, 0, False, "GLBOUT.GLB3", config=True) create_mux("GLBOUT.CLK_REF_OUT3", "GLBOUT.CLK_INT_3", 3, 0, False, "GLBOUT.GLB3", config=True, delay="glbout_CLKREF_3_CLOCK3")
create_mux("GLBOUT.CLK270_0", "GLBOUT.CLK_INT_3", 3, 1, False, "GLBOUT.GLB3", config=True) create_mux("GLBOUT.CLK270_0", "GLBOUT.CLK_INT_3", 3, 1, False, "GLBOUT.GLB3", config=True, delay="glbout_CLK270_0_CLOCK3")
create_mux("GLBOUT.CLK270_1", "GLBOUT.CLK_INT_3", 3, 2, False, "GLBOUT.GLB3", config=True) create_mux("GLBOUT.CLK270_1", "GLBOUT.CLK_INT_3", 3, 2, False, "GLBOUT.GLB3", config=True, delay="glbout_CLK270_1_CLOCK3")
create_mux("GLBOUT.CLK270_2", "GLBOUT.CLK_INT_3", 3, 3, False, "GLBOUT.GLB3", config=True) create_mux("GLBOUT.CLK270_2", "GLBOUT.CLK_INT_3", 3, 3, False, "GLBOUT.GLB3", config=True, delay="glbout_CLK270_2_CLOCK3")
create_mux("GLBOUT.CLK0_3", "GLBOUT.CLK_INT_3", 3, 4, False, "GLBOUT.GLB3", config=True) create_mux("GLBOUT.CLK0_3", "GLBOUT.CLK_INT_3", 3, 4, False, "GLBOUT.GLB3", config=True, delay="glbout_CLK0_3_CLOCK3")
create_mux("GLBOUT.CLK90_3", "GLBOUT.CLK_INT_3", 3, 5, False, "GLBOUT.GLB3", config=True) create_mux("GLBOUT.CLK90_3", "GLBOUT.CLK_INT_3", 3, 5, False, "GLBOUT.GLB3", config=True, delay="glbout_CLK90_3_CLOCK3")
create_mux("GLBOUT.CLK180_3", "GLBOUT.CLK_INT_3", 3, 6, False, "GLBOUT.GLB3", config=True) create_mux("GLBOUT.CLK180_3", "GLBOUT.CLK_INT_3", 3, 6, False, "GLBOUT.GLB3", config=True, delay="glbout_CLK180_3_CLOCK3")
create_mux("GLBOUT.CLK270_3", "GLBOUT.CLK_INT_3", 3, 7, False, "GLBOUT.GLB3", config=True) create_mux("GLBOUT.CLK270_3", "GLBOUT.CLK_INT_3", 3, 7, False, "GLBOUT.GLB3", config=True, delay="glbout_CLK270_3_CLOCK3")
create_mux("GLBOUT.CLK_INT_3", "GLBOUT.CLK_SEL_INT_3", 1, 0, False, "GLBOUT.USR_GLB3", config=True) create_mux("GLBOUT.CLK_INT_3", "GLBOUT.CLK_SEL_INT_3", 1, 0, False, "GLBOUT.USR_GLB3", config=True, delay="del_dummy")
create_mux("GLBOUT.USR_GLB3", "GLBOUT.CLK_SEL_INT_3", 1, 1, False, "GLBOUT.USR_GLB3", config=True) create_mux("GLBOUT.USR_GLB3", "GLBOUT.CLK_SEL_INT_3", 1, 1, False, "GLBOUT.USR_GLB3", config=True, delay="glbout_U_CLK3_CLOCK3")
create_mux("GLBOUT.CLK_SEL_INT_3", "GLBOUT.GLB3", 1, 1, False, "GLBOUT.GLB3_EN", config=True) create_mux("GLBOUT.CLK_SEL_INT_3", "GLBOUT.GLB3", 1, 1, False, "GLBOUT.GLB3_EN", config=True, delay="del_dummy")
create_mux("GLBOUT.GLB0", "GLBOUT.FB_INT_3", 2, 0, False, "GLBOUT.FB3", config=True) create_mux("GLBOUT.GLB0", "GLBOUT.FB_INT_3", 2, 0, False, "GLBOUT.FB3", config=True, delay="glbout_FEEDBACK_delay")
create_mux("GLBOUT.GLB1", "GLBOUT.FB_INT_3", 2, 1, False, "GLBOUT.FB3", config=True) create_mux("GLBOUT.GLB1", "GLBOUT.FB_INT_3", 2, 1, False, "GLBOUT.FB3", config=True, delay="glbout_FEEDBACK_delay")
create_mux("GLBOUT.GLB2", "GLBOUT.FB_INT_3", 2, 2, False, "GLBOUT.FB3", config=True) create_mux("GLBOUT.GLB2", "GLBOUT.FB_INT_3", 2, 2, False, "GLBOUT.FB3", config=True, delay="glbout_FEEDBACK_delay")
create_mux("GLBOUT.GLB3", "GLBOUT.FB_INT_3", 2, 3, False, "GLBOUT.FB3", config=True) create_mux("GLBOUT.GLB3", "GLBOUT.FB_INT_3", 2, 3, False, "GLBOUT.FB3", config=True, delay="glbout_FEEDBACK_delay")
create_mux("GLBOUT.FB_INT_3", "GLBOUT.CLK_FB3", 1, 0, False, "GLBOUT.USR_FB3", config=True) create_mux("GLBOUT.FB_INT_3", "GLBOUT.CLK_FB3", 1, 0, False, "GLBOUT.USR_FB3", config=True, delay="del_dummy")
create_mux("GLBOUT.USR_FB3", "GLBOUT.CLK_FB3", 1, 1, False, "GLBOUT.USR_FB3", config=True) create_mux("GLBOUT.USR_FB3", "GLBOUT.CLK_FB3", 1, 1, False, "GLBOUT.USR_FB3", config=True, delay="glbout_U_FB3_CLK_FB3")
# PLL # PLL
create_mux("CLKIN.CLK_REF_0", "GLBOUT.CLK_REF_OUT0", 1, 0, False, "PLL0.USR_CLK_OUT", config=True) create_mux("CLKIN.CLK_REF_0", "GLBOUT.CLK_REF_OUT0", 1, 0, False, "PLL0.USR_CLK_OUT", config=True, delay="del_dummy")
create_mux("CLKIN.CLK_REF_1", "GLBOUT.CLK_REF_OUT1", 1, 0, False, "PLL1.USR_CLK_OUT", config=True) create_mux("CLKIN.CLK_REF_1", "GLBOUT.CLK_REF_OUT1", 1, 0, False, "PLL1.USR_CLK_OUT", config=True, delay="del_dummy")
create_mux("CLKIN.CLK_REF_2", "GLBOUT.CLK_REF_OUT2", 1, 0, False, "PLL2.USR_CLK_OUT", config=True) create_mux("CLKIN.CLK_REF_2", "GLBOUT.CLK_REF_OUT2", 1, 0, False, "PLL2.USR_CLK_OUT", config=True, delay="del_dummy")
create_mux("CLKIN.CLK_REF_3", "GLBOUT.CLK_REF_OUT3", 1, 0, False, "PLL3.USR_CLK_OUT", config=True) create_mux("CLKIN.CLK_REF_3", "GLBOUT.CLK_REF_OUT3", 1, 0, False, "PLL3.USR_CLK_OUT", config=True, delay="del_dummy")
create_mux("PLL0.USR_CLK_REF", "GLBOUT.CLK_REF_OUT0", 1, 1, False, "PLL0.USR_CLK_OUT", config=True) create_mux("PLL0.USR_CLK_REF", "GLBOUT.CLK_REF_OUT0", 1, 1, False, "PLL0.USR_CLK_OUT", config=True, delay="del_dummy")
create_mux("PLL1.USR_CLK_REF", "GLBOUT.CLK_REF_OUT1", 1, 1, False, "PLL1.USR_CLK_OUT", config=True) create_mux("PLL1.USR_CLK_REF", "GLBOUT.CLK_REF_OUT1", 1, 1, False, "PLL1.USR_CLK_OUT", config=True, delay="del_dummy")
create_mux("PLL2.USR_CLK_REF", "GLBOUT.CLK_REF_OUT2", 1, 1, False, "PLL2.USR_CLK_OUT", config=True) create_mux("PLL2.USR_CLK_REF", "GLBOUT.CLK_REF_OUT2", 1, 1, False, "PLL2.USR_CLK_OUT", config=True, delay="del_dummy")
create_mux("PLL3.USR_CLK_REF", "GLBOUT.CLK_REF_OUT3", 1, 1, False, "PLL3.USR_CLK_OUT", config=True) create_mux("PLL3.USR_CLK_REF", "GLBOUT.CLK_REF_OUT3", 1, 1, False, "PLL3.USR_CLK_OUT", config=True, delay="del_dummy")
return muxes return muxes
@ -2986,10 +3007,10 @@ class Die:
self.gpio_to_loc[f"GPIO_{io.bank}_{io.port}[{io.num}]"] = Location(x, y) self.gpio_to_loc[f"GPIO_{io.bank}_{io.port}[{io.num}]"] = Location(x, y)
self.io_pad_names[io.bank][io.port][io.num] = Location(x, y) self.io_pad_names[io.bank][io.port][io.num] = Location(x, y)
def create_conn(self, src_x,src_y, src, dst_x, dst_y, dst): def create_conn(self, src_x,src_y, src, dst_x, dst_y, dst, delay=""):
key_val = f"{src_x + self.offset_x}/{src_y + self.offset_y}/{src}" key_val = f"{src_x + self.offset_x}/{src_y + self.offset_y}/{src}"
key = Connection(src_x + self.offset_x, src_y + self.offset_y, src) key = Connection(src_x + self.offset_x, src_y + self.offset_y, src, "")
item = Connection(dst_x + self.offset_x, dst_y + self.offset_y, dst) item = Connection(dst_x + self.offset_x, dst_y + self.offset_y, dst, delay)
if key_val not in self.conn: if key_val not in self.conn:
self.conn[key_val] = list() self.conn[key_val] = list()
self.conn[key_val].append(key) self.conn[key_val].append(key)
@ -3016,17 +3037,18 @@ class Die:
return list() return list()
def create_cpe(self, x,y): def create_cpe(self, x,y):
self.create_conn(x,y,"IM.P01.Y", x,y,"CPE.IN1") delay = f"im_{get_tile_loc_str(x,y)}"
self.create_conn(x,y,"IM.P02.Y", x,y,"CPE.IN2") self.create_conn(x,y,"IM.P01.Y", x,y,"CPE.IN1", f"{delay}_p1_d0_path2") # TODO: fix, d0 used only
self.create_conn(x,y,"IM.P03.Y", x,y,"CPE.IN3") self.create_conn(x,y,"IM.P02.Y", x,y,"CPE.IN2", f"{delay}_p2_d0_path2")
self.create_conn(x,y,"IM.P04.Y", x,y,"CPE.IN4") self.create_conn(x,y,"IM.P03.Y", x,y,"CPE.IN3", f"{delay}_p3_d0_path2")
self.create_conn(x,y,"IM.P05.Y", x,y,"CPE.IN5") self.create_conn(x,y,"IM.P04.Y", x,y,"CPE.IN4", f"{delay}_p4_d0_path2")
self.create_conn(x,y,"IM.P06.Y", x,y,"CPE.IN6") self.create_conn(x,y,"IM.P05.Y", x,y,"CPE.IN5", f"{delay}_p5_d0_path2")
self.create_conn(x,y,"IM.P07.Y", x,y,"CPE.IN7") self.create_conn(x,y,"IM.P06.Y", x,y,"CPE.IN6", f"{delay}_p6_d0_path2")
self.create_conn(x,y,"IM.P08.Y", x,y,"CPE.IN8") self.create_conn(x,y,"IM.P07.Y", x,y,"CPE.IN7", f"{delay}_p7_d0_path2")
self.create_conn(x,y,"IM.P09.Y", x,y,"CPE.CLK") self.create_conn(x,y,"IM.P08.Y", x,y,"CPE.IN8", f"{delay}_p8_d0_path2")
self.create_conn(x,y,"IM.P10.Y", x,y,"CPE.EN") self.create_conn(x,y,"IM.P09.Y", x,y,"CPE.CLK", f"{delay}_p9_d0_path2")
self.create_conn(x,y,"IM.P11.Y", x,y,"CPE.SR") self.create_conn(x,y,"IM.P10.Y", x,y,"CPE.EN", f"{delay}_p10_d0_path2")
self.create_conn(x,y,"IM.P11.Y", x,y,"CPE.SR", f"{delay}_p11_d0_path2")
if is_cpe(x,y-1): if is_cpe(x,y-1):
self.create_conn(x,y-1,"CPE.COUTY1", x,y,"CPE.CINY1") self.create_conn(x,y-1,"CPE.COUTY1", x,y,"CPE.CINY1")
self.create_conn(x,y-1,"CPE.COUTY2", x,y,"CPE.CINY2") self.create_conn(x,y-1,"CPE.COUTY2", x,y,"CPE.CINY2")
@ -3042,22 +3064,23 @@ class Die:
# D0 - D3 are from nearby SBs # D0 - D3 are from nearby SBs
offset = 2 if is_sb(x,y) else 1 offset = 2 if is_sb(x,y) else 1
self.create_conn(x-offset,y,f"{get_sb_type(x-offset,y)}.P{plane}.Y1", x,y,f"IM.P{plane}.D0") delay = f"im_{get_tile_loc_str(x,y)}_p{p}"
self.create_conn(x,y-offset,f"{get_sb_type(x,y-offset)}.P{plane}.Y2", x,y,f"IM.P{plane}.D1") self.create_conn(x-offset,y,f"{get_sb_type(x-offset,y)}.P{plane}.Y1", x,y,f"IM.P{plane}.D0", f"{delay}_d0_path1")
self.create_conn(x+offset,y,f"{get_sb_type(x+offset,y)}.P{plane}.Y3", x,y,f"IM.P{plane}.D2") self.create_conn(x,y-offset,f"{get_sb_type(x,y-offset)}.P{plane}.Y2", x,y,f"IM.P{plane}.D1", f"{delay}_d1_path1")
self.create_conn(x,y+offset,f"{get_sb_type(x,y+offset)}.P{plane}.Y4", x,y,f"IM.P{plane}.D3") self.create_conn(x+offset,y,f"{get_sb_type(x+offset,y)}.P{plane}.Y3", x,y,f"IM.P{plane}.D2", f"{delay}_d2_path1")
self.create_conn(x,y+offset,f"{get_sb_type(x,y+offset)}.P{plane}.Y4", x,y,f"IM.P{plane}.D3", f"{delay}_d3_path1")
# D4 and D5 are from diagonal INMUX # D4 and D5 are from diagonal INMUX
if is_cpe(x-1,y-1): if is_cpe(x-1,y-1):
self.create_conn(x-1,y-1,f"IM.P{plane}.Y", x,y,f"IM.P{plane}.D4") self.create_conn(x-1,y-1,f"IM.P{plane}.Y", x,y,f"IM.P{plane}.D4", f"{delay}_d4_path1")
if is_cpe(x+1,y+1): if is_cpe(x+1,y+1):
self.create_conn(x+1,y+1,f"IM.P{plane}.Y", x,y,f"IM.P{plane}.D5") self.create_conn(x+1,y+1,f"IM.P{plane}.Y", x,y,f"IM.P{plane}.D5", f"{delay}_d5_path1")
# D6 and D7 are from alternate planes # D6 and D7 are from alternate planes
alt = f"{alt_plane(0,p):02d}" alt = f"{alt_plane(0,p):02d}"
self.create_conn(x,y,f"IM.P{alt}.Y", x,y,f"IM.P{plane}.D6") self.create_conn(x,y,f"IM.P{alt}.Y", x,y,f"IM.P{plane}.D6", f"{delay}_d6_path1")
alt = f"{alt_plane(1,p):02d}" alt = f"{alt_plane(1,p):02d}"
self.create_conn(x,y,f"IM.P{alt}.Y", x,y,f"IM.P{plane}.D7") self.create_conn(x,y,f"IM.P{alt}.Y", x,y,f"IM.P{plane}.D7", f"{delay}_d7_path1")
def create_sb(self, x,y): def create_sb(self, x,y):
x_0,y_0 = base_loc(x,y) x_0,y_0 = base_loc(x,y)
@ -3065,6 +3088,7 @@ class Die:
for p in range(1,13): for p in range(1,13):
plane = f"{p:02d}" plane = f"{p:02d}"
delay = f"sb_del_{get_full_tile_loc_str(x,y)}"
# Handling input D0 # Handling input D0
if is_cpe(x,y): if is_cpe(x,y):
# Core section SBs are connected to CPE # Core section SBs are connected to CPE
@ -3074,10 +3098,10 @@ class Die:
y_cpe = y_0 + (1 if (p-1) & 1 else 0) y_cpe = y_0 + (1 if (p-1) & 1 else 0)
# alternate patterns for lower-left SB(1,1) and upper-right SB(2,2) # alternate patterns for lower-left SB(1,1) and upper-right SB(2,2)
out = [ 2, 1, 2, 1, 1, 2, 1, 2] if x & 1 else [ 1, 2, 1, 2, 2, 1, 2, 1] out = [ 2, 1, 2, 1, 1, 2, 1, 2] if x & 1 else [ 1, 2, 1, 2, 2, 1, 2, 1]
self.create_conn(x_cpe,y_cpe,f"CPE.OUT{out[p-1]}", x,y,f"{sb_type}.P{plane}.D0") self.create_conn(x_cpe,y_cpe,f"CPE.OUT{out[p-1]}", x,y,f"{sb_type}.P{plane}.D0", f"{delay}_p{p}_d0_s0")
else: else:
# planes 9..12 # planes 9..12
self.create_conn(x,y,f"OM.P{plane}.Y", x,y,f"{sb_type}.P{plane}.D0") self.create_conn(x,y,f"OM.P{plane}.Y", x,y,f"{sb_type}.P{plane}.D0", f"{delay}_p{p}_d0_s0")
# Handling GPIO connections is done in create_io # Handling GPIO connections is done in create_io
# Handling inputs D2_* till D7_* # Handling inputs D2_* till D7_*
distances = [2, 4, 8, 12, 16, 20] if is_sb_big(x,y) else [2, 4] distances = [2, 4, 8, 12, 16, 20] if is_sb_big(x,y) else [2, 4]
@ -3106,20 +3130,20 @@ class Die:
src = f"SB_DRIVE.P{plane}.D{direction+1}.OUT" src = f"SB_DRIVE.P{plane}.D{direction+1}.OUT"
else: else:
src = f"SB_DRIVE.P{plane}.D{direction+1}.OUT_NOINV" src = f"SB_DRIVE.P{plane}.D{direction+1}.OUT_NOINV"
self.create_conn(sb_x,sb_y, src, x,y,f"{get_sb_type(x,y)}.P{plane}.D{i+2}_{direction+1}") self.create_conn(sb_x,sb_y, src, x,y,f"{get_sb_type(x,y)}.P{plane}.D{i+2}_{direction+1}", f"{delay}_p{p}_d{direction+1}_s{i+2}")
if is_sb_big(x,y): if is_sb_big(x,y):
for direction in range(4): for direction in range(4):
self.create_conn(x,y, f"{get_sb_type(x,y)}.P{plane}.Y{direction+1}", x,y,f"SB_DRIVE.P{plane}.D{direction+1}.IN") self.create_conn(x,y, f"{get_sb_type(x,y)}.P{plane}.Y{direction+1}", x,y,f"SB_DRIVE.P{plane}.D{direction+1}.IN", delay="del_dummy")
# Diagonal inputs # Diagonal inputs
# X12 and X34 on edges are unconnected # X12 and X34 on edges are unconnected
if is_sb(x-1,y-1): if is_sb(x-1,y-1):
self.create_conn(x-1,y-1,f"{get_sb_type(x-1,y-1)}.P{plane}.YDIAG", x,y,f"{get_sb_type(x,y)}.P{plane}.X12") self.create_conn(x-1,y-1,f"{get_sb_type(x-1,y-1)}.P{plane}.YDIAG", x,y,f"{get_sb_type(x,y)}.P{plane}.X12", f"{delay}_p{p}_d0_s6")
if is_sb(x+1,y+1): if is_sb(x+1,y+1):
self.create_conn(x+1,y+1,f"{get_sb_type(x+1,y+1)}.P{plane}.YDIAG", x,y,f"{get_sb_type(x,y)}.P{plane}.X34") self.create_conn(x+1,y+1,f"{get_sb_type(x+1,y+1)}.P{plane}.YDIAG", x,y,f"{get_sb_type(x,y)}.P{plane}.X34", f"{delay}_p{p}_d0_s4")
self.create_conn(x,y,f"{get_sb_type(x,y)}.P{prev_plane(p):02d}.YDIAG", x,y,f"{get_sb_type(x,y)}.P{plane}.X14") self.create_conn(x,y,f"{get_sb_type(x,y)}.P{prev_plane(p):02d}.YDIAG", x,y,f"{get_sb_type(x,y)}.P{plane}.X14", f"{delay}_p{p}_d0_s5")
self.create_conn(x,y,f"{get_sb_type(x,y)}.P{next_plane(p):02d}.YDIAG", x,y,f"{get_sb_type(x,y)}.P{plane}.X23") self.create_conn(x,y,f"{get_sb_type(x,y)}.P{next_plane(p):02d}.YDIAG", x,y,f"{get_sb_type(x,y)}.P{plane}.X23", f"{delay}_p{p}_d0_s7")
def create_outmux(self, x,y): def create_outmux(self, x,y):
x_0,y_0 = base_loc(x,y) x_0,y_0 = base_loc(x,y)
@ -3127,10 +3151,11 @@ class Die:
plane = f"{p:02d}" plane = f"{p:02d}"
# alternating patters depending of plane and outmux position # alternating patters depending of plane and outmux position
outputs = [2, 2, 1, 1] if p % 2 == x & 1 else [1, 1, 2, 2] outputs = [2, 2, 1, 1] if p % 2 == x & 1 else [1, 1, 2, 2]
self.create_conn(x_0, y_0, f"CPE.OUT{outputs[0]}", x,y, f"OM.P{plane}.D0") delay = f"om_{get_tile_loc_str(x,y)}"
self.create_conn(x_0, y_0+1, f"CPE.OUT{outputs[1]}", x,y, f"OM.P{plane}.D1") self.create_conn(x_0, y_0, f"CPE.OUT{outputs[0]}", x,y, f"OM.P{plane}.D0", f"{delay}_p{p}_d0")
self.create_conn(x_0+1, y_0, f"CPE.OUT{outputs[2]}", x,y, f"OM.P{plane}.D2") self.create_conn(x_0, y_0+1, f"CPE.OUT{outputs[1]}", x,y, f"OM.P{plane}.D1", f"{delay}_p{p}_d1")
self.create_conn(x_0+1, y_0+1, f"CPE.OUT{outputs[3]}", x,y, f"OM.P{plane}.D3") self.create_conn(x_0+1, y_0, f"CPE.OUT{outputs[2]}", x,y, f"OM.P{plane}.D2", f"{delay}_p{p}_d2")
self.create_conn(x_0+1, y_0+1, f"CPE.OUT{outputs[3]}", x,y, f"OM.P{plane}.D3", f"{delay}_p{p}_d3")
def get_pin_real_name(self, prim_name, pin): def get_pin_real_name(self, prim_name, pin):
prim_type = prim_name prim_type = prim_name
@ -3149,7 +3174,7 @@ class Die:
if c.output == RAM_OUTPUT: if c.output == RAM_OUTPUT:
self.create_conn(loc_x + c.rel_x, loc_y + c.rel_y, f"CPE.RAM_O{c.pin_num}", loc_x, loc_y, f"{name}") self.create_conn(loc_x + c.rel_x, loc_y + c.rel_y, f"CPE.RAM_O{c.pin_num}", loc_x, loc_y, f"{name}")
else: else:
self.create_conn(loc_x, loc_y, f"{name}", loc_x + c.rel_x, loc_y + c.rel_y, f"CPE.RAM_I{c.pin_num}") self.create_conn(loc_x, loc_y, f"{name}", loc_x + c.rel_x, loc_y + c.rel_y, f"CPE.RAM_I{c.pin_num}", delay="del_special_RAM_I")
def create_io(self, x,y): def create_io(self, x,y):
cpe_x, cpe_y = gpio_x, gpio_y = sb_x, sb_y = x, y cpe_x, cpe_y = gpio_x, gpio_y = sb_x, sb_y = x, y
@ -3200,10 +3225,10 @@ class Die:
if not alt: if not alt:
self.create_ram_io_conn("GPIO", "GPIO", x, y) self.create_ram_io_conn("GPIO", "GPIO", x, y)
self.create_conn(PLL_X_POS, PLL_Y_POS, "GLBOUT.GLB0", gpio_x, gpio_y, "GPIO.CLOCK1") self.create_conn(PLL_X_POS, PLL_Y_POS, "GLBOUT.GLB0", gpio_x, gpio_y, "GPIO.CLOCK1", "del_GLBOUT_IO_SEL")
self.create_conn(PLL_X_POS, PLL_Y_POS, "GLBOUT.GLB1", gpio_x, gpio_y, "GPIO.CLOCK2") self.create_conn(PLL_X_POS, PLL_Y_POS, "GLBOUT.GLB1", gpio_x, gpio_y, "GPIO.CLOCK2", "del_GLBOUT_IO_SEL")
self.create_conn(PLL_X_POS, PLL_Y_POS, "GLBOUT.GLB2", gpio_x, gpio_y, "GPIO.CLOCK3") self.create_conn(PLL_X_POS, PLL_Y_POS, "GLBOUT.GLB2", gpio_x, gpio_y, "GPIO.CLOCK3", "del_GLBOUT_IO_SEL")
self.create_conn(PLL_X_POS, PLL_Y_POS, "GLBOUT.GLB3", gpio_x, gpio_y, "GPIO.CLOCK4") self.create_conn(PLL_X_POS, PLL_Y_POS, "GLBOUT.GLB3", gpio_x, gpio_y, "GPIO.CLOCK4", "del_GLBOUT_IO_SEL")
def create_pll(self): def create_pll(self):
# GPIO_W2_A[8] CLK0 # GPIO_W2_A[8] CLK0
@ -3248,7 +3273,7 @@ class Die:
# Clock#2: p2, p6,p10 # Clock#2: p2, p6,p10
# Clock#3: p3, p7,p11 # Clock#3: p3, p7,p11
# Clock#4: p4, p8,p12 # Clock#4: p4, p8,p12
self.create_conn(PLL_X_POS, PLL_Y_POS, f"GLBOUT.GLB{(p-1) & 3}", x,y,f"SB_BIG.P{plane}.{inp}") self.create_conn(PLL_X_POS, PLL_Y_POS, f"GLBOUT.GLB{(p-1) & 3}", x,y,f"SB_BIG.P{plane}.{inp}", "del_GLBOUT_sb_big")
# Connecting Global Mesh signals to Switch Boxes # Connecting Global Mesh signals to Switch Boxes
# Left edge # Left edge
@ -3389,6 +3414,10 @@ class Die:
def create_ram(self, x, y): def create_ram(self, x, y):
self.create_ram_io_conn("RAM", "RAM", x, y) self.create_ram_io_conn("RAM", "RAM", x, y)
self.create_conn(PLL_X_POS, PLL_Y_POS, "GLBOUT.GLB0", x, y, "RAM.CLOCK1")
self.create_conn(PLL_X_POS, PLL_Y_POS, "GLBOUT.GLB1", x, y, "RAM.CLOCK2")
self.create_conn(PLL_X_POS, PLL_Y_POS, "GLBOUT.GLB2", x, y, "RAM.CLOCK3")
self.create_conn(PLL_X_POS, PLL_Y_POS, "GLBOUT.GLB3", x, y, "RAM.CLOCK4")
def create_in_die_connections(self, conn): def create_in_die_connections(self, conn):
self.conn = conn self.conn = conn

564
gatemate/timing.py Normal file
View File

@ -0,0 +1,564 @@
#
# prjpeppercorn -- GateMate FPGAs Bitstream Documentation and Tools
#
# Copyright (C) 2024 The Project Peppercorn Authors.
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
import zlib
import struct
from dataclasses import dataclass
from typing import List
@dataclass
class T_delay_tri:
min: int
typ: int
max: int
@staticmethod
def from_bytes(data: bytes) -> 'T_delay_tri':
min_val, typ_val, max_val = struct.unpack('<3i', data)
return T_delay_tri(min_val, typ_val, max_val)
@dataclass
class T_delay:
rise: T_delay_tri
fall: T_delay_tri
@staticmethod
def from_bytes(data: bytes) -> 'T_delay':
rise = T_delay_tri.from_bytes(data[:12])
fall = T_delay_tri.from_bytes(data[12:24])
return T_delay(rise, fall)
@dataclass
class Tpin_pair:
i: int
o_or_clk: int # Represents either 'o' or 'clk' depending on the boolean case
@dataclass
class Tentry_rec:
pins: Tpin_pair
entry_no: int
@dataclass
class Tdel_entry:
key: int
edge1: int
edge2: int
time1: T_delay_tri
time2: T_delay_tri
@dataclass
class TRAM_del_rec:
iopath: List[Tentry_rec]
setuphold: List[Tentry_rec]
width: List[Tentry_rec]
del_entry: List[Tdel_entry]
@dataclass
class Tdel_rec:
val: T_delay
conf_mux: int
name: str
x: int
y: int
plane: int
dir: int
inv: int
cnt: int
con_type: int
@staticmethod
def from_bytes(data: memoryview, offset: int) -> ('Tdel_rec', int):
val = T_delay.from_bytes(data[offset:offset + 24])
offset += 24
conf_mux = struct.unpack_from('<i', data, offset)[0]
offset += 4
strlen = data[offset]
offset += 1
name = data[offset:offset + strlen].decode('ascii')
offset += 23 # alignment added as well
x, y, plane, dir, inv, cnt = struct.unpack_from('<6i', data, offset)
offset += 24
con_type_val = data[offset]
offset += 4
return Tdel_rec(val, conf_mux, name, x, y, plane, dir, inv, cnt, con_type_val), offset
@dataclass
class Tdel_rec_tri:
val: T_delay_tri
conf_mux: int
name: str
x: int
y: int
@staticmethod
def from_bytes(mv: memoryview, offset: int) -> ('Tdel_rec_tri', int):
val = T_delay_tri.from_bytes(mv[offset:offset+12])
offset += 12
conf_mux = struct.unpack_from('<i', mv, offset)[0]
offset += 4
strlen = mv[offset]
offset += 1
name = mv[offset:offset + strlen].decode('ascii')
offset += 23
x, y = struct.unpack_from('<2i', mv, offset)
offset += 8
return Tdel_rec_tri(val, conf_mux, name, x, y), offset
def read_SB_del_tile_arr_from_bytes(mv: memoryview, offset: int) -> (List, int):
SB_del_tile_arr = []
for i1 in range(4): # [1..4]
level1 = []
for i2 in range(8): # [1..8]
level2 = []
for i3 in range(4): # [1..4]
level3 = []
for i4 in range(12): # [1..12]
level4 = []
for i5 in range(5): # [0..4]
level5 = []
for i6 in range(8): # [0..7]
chunk = mv[offset:offset + 24]
if len(chunk) < 24:
raise EOFError("Unexpected end of data")
delay = T_delay.from_bytes(chunk)
offset += 24
level5.append(delay)
level4.append(level5)
level3.append(level4)
level2.append(level3)
level1.append(level2)
SB_del_tile_arr.append(level1)
return SB_del_tile_arr, offset
@dataclass
class ExtraTimingDelays:
skew_report_del: int
fix_skew_del: int
del_rec_0: Tdel_rec
del_min_route_SB: Tdel_rec
del_violation_common: Tdel_rec_tri
del_dummy: Tdel_rec
del_Hold_D_L: Tdel_rec_tri
del_Hold_RAM: Tdel_rec_tri
del_Setup_D_L: Tdel_rec_tri
del_Setup_RAM: Tdel_rec_tri
del_Hold_SN_RN: Tdel_rec_tri
del_Setup_SN_RN: Tdel_rec_tri
del_Hold_RN_SN: Tdel_rec_tri
del_Setup_RN_SN: Tdel_rec_tri
del_bot_couty2: Tdel_rec
del_bot_glb_couty2: Tdel_rec
del_bot_SB_couty2: Tdel_rec
del_bot_pouty2: Tdel_rec
del_bot_glb_pouty2: Tdel_rec
del_bot_SB_pouty2: Tdel_rec
del_left_couty2: Tdel_rec
del_left_glb_couty2: Tdel_rec
del_left_SB_couty2: Tdel_rec
del_left_pouty2: Tdel_rec
del_left_glb_pouty2: Tdel_rec
del_left_SB_pouty2: Tdel_rec
del_inp: List[Tdel_rec]
del_CPE_out_mux: List[Tdel_rec]
del_CPE_CP_Q: Tdel_rec
del_CPE_S_Q: Tdel_rec
del_CPE_R_Q: Tdel_rec
del_CPE_D_Q: Tdel_rec
del_RAM_CLK_DO: Tdel_rec
del_GLBOUT_sb_big: Tdel_rec
del_sb_drv: Tdel_rec
del_CP_carry_path: Tdel_rec
del_CP_prop_path: Tdel_rec
del_special_RAM_I: Tdel_rec
del_RAMO_xOBF: Tdel_rec
del_GLBOUT_IO_SEL: Tdel_rec
del_IO_SEL_Q_out: Tdel_rec
del_IO_SEL_Q_in: Tdel_rec
in_delayline_per_stage: Tdel_rec
out_delayline_per_stage: Tdel_rec
del_IBF: Tdel_rec
del_OBF: Tdel_rec
del_r_OBF: Tdel_rec
del_TOBF_ctrl: Tdel_rec
del_LVDS_IBF: Tdel_rec
del_LVDS_OBF: Tdel_rec
del_LVDS_r_OBF: Tdel_rec
del_LVDS_TOBF_ctrl: Tdel_rec
del_CP_clkin: Tdel_rec
del_CP_enin: Tdel_rec
del_preplace: Tdel_rec
del_CPE_timing_mod: List[Tdel_rec]
@staticmethod
def from_bytes(mv: memoryview, offset: int) -> ('ExtraTimingDelays', int):
skew_report_del, fix_skew_del = struct.unpack_from('<2i', mv, offset)
offset += 8
del_rec_0, offset = Tdel_rec.from_bytes(mv, offset)
del_min_route_SB, offset = Tdel_rec.from_bytes(mv, offset)
del_violation_common, offset = Tdel_rec_tri.from_bytes(mv, offset)
del_dummy, offset = Tdel_rec.from_bytes(mv, offset)
del_Hold_D_L, offset = Tdel_rec_tri.from_bytes(mv, offset)
del_Hold_RAM, offset = Tdel_rec_tri.from_bytes(mv, offset)
del_Setup_D_L, offset = Tdel_rec_tri.from_bytes(mv, offset)
del_Setup_RAM, offset = Tdel_rec_tri.from_bytes(mv, offset)
del_Hold_SN_RN, offset = Tdel_rec_tri.from_bytes(mv, offset)
del_Setup_SN_RN, offset = Tdel_rec_tri.from_bytes(mv, offset)
del_Hold_RN_SN, offset = Tdel_rec_tri.from_bytes(mv, offset)
del_Setup_RN_SN, offset = Tdel_rec_tri.from_bytes(mv, offset)
del_bot_couty2, offset = Tdel_rec.from_bytes(mv, offset)
del_bot_glb_couty2, offset = Tdel_rec.from_bytes(mv, offset)
del_bot_SB_couty2, offset = Tdel_rec.from_bytes(mv, offset)
del_bot_pouty2, offset = Tdel_rec.from_bytes(mv, offset)
del_bot_glb_pouty2, offset = Tdel_rec.from_bytes(mv, offset)
del_bot_SB_pouty2, offset = Tdel_rec.from_bytes(mv, offset)
del_left_couty2, offset = Tdel_rec.from_bytes(mv, offset)
del_left_glb_couty2, offset = Tdel_rec.from_bytes(mv, offset)
del_left_SB_couty2, offset = Tdel_rec.from_bytes(mv, offset)
del_left_pouty2, offset = Tdel_rec.from_bytes(mv, offset)
del_left_glb_pouty2, offset = Tdel_rec.from_bytes(mv, offset)
del_left_SB_pouty2, offset = Tdel_rec.from_bytes(mv, offset)
del_inp = []
for _ in range(8):
rec, offset = Tdel_rec.from_bytes(mv, offset)
del_inp.append(rec)
del_CPE_out_mux = []
for _ in range(4):
rec, offset = Tdel_rec.from_bytes(mv, offset)
del_CPE_out_mux.append(rec)
del_CPE_CP_Q, offset = Tdel_rec.from_bytes(mv, offset)
del_CPE_S_Q, offset = Tdel_rec.from_bytes(mv, offset)
del_CPE_R_Q, offset = Tdel_rec.from_bytes(mv, offset)
del_CPE_D_Q, offset = Tdel_rec.from_bytes(mv, offset)
del_RAM_CLK_DO, offset = Tdel_rec.from_bytes(mv, offset)
del_GLBOUT_sb_big, offset = Tdel_rec.from_bytes(mv, offset)
del_sb_drv, offset = Tdel_rec.from_bytes(mv, offset)
del_CP_carry_path, offset = Tdel_rec.from_bytes(mv, offset)
del_CP_prop_path, offset = Tdel_rec.from_bytes(mv, offset)
del_special_RAM_I, offset = Tdel_rec.from_bytes(mv, offset)
del_RAMO_xOBF, offset = Tdel_rec.from_bytes(mv, offset)
del_GLBOUT_IO_SEL, offset = Tdel_rec.from_bytes(mv, offset)
del_IO_SEL_Q_out, offset = Tdel_rec.from_bytes(mv, offset)
del_IO_SEL_Q_in, offset = Tdel_rec.from_bytes(mv, offset)
in_delayline_per_stage, offset = Tdel_rec.from_bytes(mv, offset)
out_delayline_per_stage, offset = Tdel_rec.from_bytes(mv, offset)
del_IBF, offset = Tdel_rec.from_bytes(mv, offset)
del_OBF, offset = Tdel_rec.from_bytes(mv, offset)
del_r_OBF, offset = Tdel_rec.from_bytes(mv, offset)
del_TOBF_ctrl, offset = Tdel_rec.from_bytes(mv, offset)
del_LVDS_IBF, offset = Tdel_rec.from_bytes(mv, offset)
del_LVDS_OBF, offset = Tdel_rec.from_bytes(mv, offset)
del_LVDS_r_OBF, offset = Tdel_rec.from_bytes(mv, offset)
del_LVDS_TOBF_ctrl, offset = Tdel_rec.from_bytes(mv, offset)
del_CP_clkin, offset = Tdel_rec.from_bytes(mv, offset)
del_CP_enin, offset = Tdel_rec.from_bytes(mv, offset)
del_preplace, offset = Tdel_rec.from_bytes(mv, offset)
del_CPE_timing_mod = []
for _ in range(42):
rec, offset = Tdel_rec.from_bytes(mv, offset)
del_CPE_timing_mod.append(rec)
return ExtraTimingDelays(
skew_report_del, fix_skew_del,
del_rec_0, del_min_route_SB,
del_violation_common, del_dummy,
del_Hold_D_L, del_Hold_RAM, del_Setup_D_L, del_Setup_RAM,
del_Hold_SN_RN, del_Setup_SN_RN, del_Hold_RN_SN, del_Setup_RN_SN,
del_bot_couty2, del_bot_glb_couty2, del_bot_SB_couty2,
del_bot_pouty2, del_bot_glb_pouty2, del_bot_SB_pouty2,
del_left_couty2, del_left_glb_couty2, del_left_SB_couty2,
del_left_pouty2, del_left_glb_pouty2, del_left_SB_pouty2,
del_inp, del_CPE_out_mux,
del_CPE_CP_Q, del_CPE_S_Q, del_CPE_R_Q, del_CPE_D_Q,
del_RAM_CLK_DO, del_GLBOUT_sb_big, del_sb_drv,
del_CP_carry_path, del_CP_prop_path,
del_special_RAM_I, del_RAMO_xOBF,
del_GLBOUT_IO_SEL, del_IO_SEL_Q_out, del_IO_SEL_Q_in,
in_delayline_per_stage, out_delayline_per_stage,
del_IBF, del_OBF, del_r_OBF, del_TOBF_ctrl,
del_LVDS_IBF, del_LVDS_OBF, del_LVDS_r_OBF, del_LVDS_TOBF_ctrl,
del_CP_clkin, del_CP_enin, del_preplace,
del_CPE_timing_mod
), offset
def read_IM_del_tile_arr_from_bytes(mv: memoryview, offset: int) -> (List, int):
result = []
for i1 in range(2): # [1..2]
level1 = []
for i2 in range(8): # [1..8]
level2 = []
for i3 in range(8): # [1..8]
level3 = []
for i4 in range(12): # [1..12]
level4 = []
for i5 in range(8): # [0..7]
delay = T_delay.from_bytes(mv[offset:offset+24])
offset += 24
level4.append(delay)
level3.append(level4)
level2.append(level3)
level1.append(level2)
result.append(level1)
return result, offset
def read_OM_del_tile_arr_from_bytes(mv: memoryview, offset: int) -> (List, int):
result = []
for i1 in range(8): # [1..8]
level1 = []
for i2 in range(8): # [1..8]
level2 = []
for i3 in range(4): # [9..12]
level3 = []
for i4 in range(4): # [0..3]
delay = T_delay.from_bytes(mv[offset:offset+24])
offset += 24
level3.append(delay)
level2.append(level3)
level1.append(level2)
result.append(level1)
return result, offset
def read_CPE_del_tile_arr_from_bytes(mv: memoryview, offset: int) -> (List, int):
result = []
for i1 in range(10): # [0..9]
level1 = []
for i2 in range(19): # [1..19]
level2 = []
for i3 in range(10): # [1..10]
rec, offset = Tdel_rec.from_bytes(mv, offset)
level2.append(rec)
level1.append(level2)
result.append(level1)
return result, offset
def read_SB_del_rim_arr_from_bytes(mv: memoryview, offset: int) -> (List, int):
result = []
for i1 in range(165): # [-2..162]
level1 = []
for i2 in range(4): # [1..4]
level2 = []
for i3 in range(12): # [1..12]
level3 = []
for i4 in range(5): # [0..4]
level4 = []
for i5 in range(8): # [0..7]
delay = T_delay.from_bytes(mv[offset:offset+24])
offset += 24
level4.append(delay)
level3.append(level4)
level2.append(level3)
level1.append(level2)
result.append(level1)
return result, offset
def read_Edge_del_arr_from_bytes(mv: memoryview, offset: int) -> (List, int):
result = []
for i1 in range(165): # [-2..162]
level1 = []
for i2 in range(4): # [1..4]
level2 = []
for i3 in range(24): # [1..24]
level3 = []
for i4 in range(8): # [1..8]
delay = T_delay.from_bytes(mv[offset:offset+24])
offset += 24
level3.append(delay)
level2.append(level3)
level1.append(level2)
result.append(level1)
return result, offset
def read_IO_SEL_del_arr_from_bytes(mv: memoryview, offset: int) -> (List, int):
result = []
for i1 in range(11): # [1..11]
level1 = []
for i2 in range(4): # [1..4]
delay = T_delay.from_bytes(mv[offset:offset+24])
offset += 24
level1.append(delay)
result.append(level1)
return result, offset
def read_CLKIN_del_arr_from_bytes(mv: memoryview, offset: int) -> (List, int):
result = []
for i1 in range(7):
level1 = []
for i2 in range(4):
delay = T_delay.from_bytes(mv[offset:offset + 24])
offset += 24
level1.append(delay)
result.append(level1)
return result, offset
def read_GLBOUT_del_arr_from_bytes(mv: memoryview, offset: int) -> (List, int):
result = []
for i1 in range(28):
level1 = []
for i2 in range(8):
delay = T_delay.from_bytes(mv[offset:offset + 24])
offset += 24
level1.append(delay)
result.append(level1)
return result, offset
def read_PLL_del_arr_from_bytes(mv: memoryview, offset: int) -> (List, int):
result = []
for i1 in range(7):
level1 = []
for i2 in range(6):
delay = T_delay.from_bytes(mv[offset:offset + 24])
offset += 24
level1.append(delay)
result.append(level1)
return result, offset
def read_Tentry_rec_from_bytes(data: memoryview, offset: int) -> ('Tentry_rec', int):
pins_i, pins_val, entry_no = struct.unpack_from('<3h', data, offset)
return Tentry_rec(Tpin_pair(pins_i, pins_val), entry_no), offset + 6
def read_Tdel_entry_from_bytes(data: memoryview, offset: int) -> ('Tdel_entry', int):
key, edge1, edge2 = struct.unpack_from('<3i', data, offset)
time1 = T_delay_tri.from_bytes(data[offset + 12:offset + 24])
time2 = T_delay_tri.from_bytes(data[offset + 24:offset + 36])
return Tdel_entry(key, edge1, edge2, time1, time2), offset + 36
def read_TRAM_del_rec_from_bytes(mv: memoryview, offset: int) -> (TRAM_del_rec, int):
iopath = []
for _ in range(3001):
entry, offset = read_Tentry_rec_from_bytes(mv, offset)
iopath.append(entry)
setuphold = []
for _ in range(8001):
entry, offset = read_Tentry_rec_from_bytes(mv, offset)
setuphold.append(entry)
width = []
for _ in range(51):
entry, offset = read_Tentry_rec_from_bytes(mv, offset)
width.append(entry)
del_entry = []
offset += 2 # alignment added
for _ in range(101):
entry, offset = read_Tdel_entry_from_bytes(mv, offset)
del_entry.append(entry)
return TRAM_del_rec(iopath, setuphold, width, del_entry), offset
def read_IO_SEL_io_coef_from_bytes(mv: memoryview, offset: int) -> (list, int):
result = []
for i1 in range(4): # [1..4]
row = []
for i2 in range(27): # [1..27]
value = struct.unpack_from('<d', mv, offset)[0] # '<d' = little-endian double
offset += 8
row.append(value)
result.append(row)
return result, offset
@dataclass
class Tdel_all_rec:
SB_del_tile_arr: List[List[List[List[List[List[T_delay]]]]]]
IM_del_tile_arr: List[List[List[List[List[T_delay]]]]]
OM_del_tile_arr: List[List[List[List[T_delay]]]]
CPE_del_tile_arr: List[List[List[Tdel_rec]]]
SB_del_rim_arr: List[List[List[List[List[T_delay]]]]]
Edge_del_arr: List[List[List[List[T_delay]]]]
IO_SEL_del_arr: List[List[T_delay]]
CLKIN_del_arr: List[List[T_delay]]
GLBOUT_del_arr: List[List[T_delay]]
PLL_del_arr: List[List[T_delay]]
FPGA_ram_del_1: TRAM_del_rec
FPGA_ram_del_2: TRAM_del_rec
FPGA_ram_del_3: TRAM_del_rec
IO_SEL_io_coef: list[list[float]]
timing_delays: ExtraTimingDelays
@staticmethod
def from_bytes(data: bytes) -> 'Tdel_all_rec':
offset = 0
sb_del_tile_arr, offset = read_SB_del_tile_arr_from_bytes(data, offset)
im, offset = read_IM_del_tile_arr_from_bytes(data, offset)
om, offset = read_OM_del_tile_arr_from_bytes(data, offset)
cpe, offset = read_CPE_del_tile_arr_from_bytes(data, offset)
sb_del_rim, offset = read_SB_del_rim_arr_from_bytes(data, offset)
edge, offset = read_Edge_del_arr_from_bytes(data, offset)
io_sel, offset = read_IO_SEL_del_arr_from_bytes(data, offset)
clkin, offset = read_CLKIN_del_arr_from_bytes(data, offset)
glbout, offset = read_GLBOUT_del_arr_from_bytes(data, offset)
pll_del, offset = read_PLL_del_arr_from_bytes(data, offset)
fpga_ram_del_1, offset = read_TRAM_del_rec_from_bytes(data, offset)
fpga_ram_del_2, offset = read_TRAM_del_rec_from_bytes(data, offset)
fpga_ram_del_3, offset = read_TRAM_del_rec_from_bytes(data, offset)
io_sel_coef, offset = read_IO_SEL_io_coef_from_bytes(data, offset)
timing_delays, offset = ExtraTimingDelays.from_bytes(data, offset)
return Tdel_all_rec(sb_del_tile_arr, im, om, cpe, sb_del_rim, edge, io_sel, clkin, glbout, pll_del, fpga_ram_del_1, fpga_ram_del_2, fpga_ram_del_3,io_sel_coef, timing_delays)
def decompress_timing(input_path) -> 'Tdel_all_rec':
with open(input_path, 'rb') as f_in:
compressed_data = f_in.read()
try:
decompressed_data = zlib.decompress(compressed_data)
except zlib.error as e:
print(f"Decompression failed: {e}")
return
return Tdel_all_rec.from_bytes(decompressed_data)
# Example usage
#decompress_timing("cc_best_eco_dly.dly")
#decompress_timing("cc_best_lpr_dly.dly")
#decompress_timing("cc_best_spd_dly.dly")
#
#decompress_timing("cc_typ_eco_dly.dly")
#decompress_timing("cc_typ_lpr_dly.dly")
#decompress_timing("cc_typ_spd_dly.dly")
#
#decompress_timing("cc_worst_eco_dly.dly")
#decompress_timing("cc_worst_lpr_dly.dly")
#decompress_timing("cc_worst_spd_dly.dly")