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(' '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(' ('Tdel_rec_tri', int): val = T_delay_tri.from_bytes(mv[offset:offset+12]) offset += 12 conf_mux = struct.unpack_from(' (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(' '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")