From 1d42f21e3d2c8d426fae5ce2bca2869e0f9638d0 Mon Sep 17 00:00:00 2001 From: Keith Rothman <537074+litghost@users.noreply.github.com> Date: Sat, 2 Feb 2019 07:39:25 -0800 Subject: [PATCH 1/3] Add BLOCK_RAM segments support. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com> --- prjxray/db.py | 8 +++++- prjxray/fasm_disassembler.py | 11 ++++---- prjxray/grid.py | 23 +++------------ prjxray/tile.py | 2 +- prjxray/tile_segbits.py | 55 ++++++++++++++++++++---------------- 5 files changed, 49 insertions(+), 50 deletions(-) diff --git a/prjxray/db.py b/prjxray/db.py index 4a886e17..d222d237 100644 --- a/prjxray/db.py +++ b/prjxray/db.py @@ -1,5 +1,5 @@ import os.path -import json +import simplejson as json from prjxray import grid from prjxray import tile from prjxray import tile_segbits @@ -51,6 +51,11 @@ class Database(object): if not os.path.isfile(segbits): segbits = None + block_ram_segbits = os.path.join( + self.db_root, 'segbits_{}.block_ram.db'.format(tile_type)) + if not os.path.isfile(block_ram_segbits): + block_ram_segbits = None + ppips = os.path.join( self.db_root, 'ppips_{}.db'.format(tile_type)) if not os.path.isfile(ppips): @@ -69,6 +74,7 @@ class Database(object): self.tile_types[tile_type.upper()] = tile.TileDbs( segbits=segbits, + block_ram_segbits=block_ram_segbits, ppips=ppips, mask=mask, tile_type=tile_type_file, diff --git a/prjxray/fasm_disassembler.py b/prjxray/fasm_disassembler.py index 4d841831..ff4112d2 100644 --- a/prjxray/fasm_disassembler.py +++ b/prjxray/fasm_disassembler.py @@ -38,7 +38,7 @@ class FasmDisassembler(object): self.decode_warnings = set() def find_features_in_tile( - self, tile_name, bits, solved_bitdata, bitdata, verbose=False): + self, tile_name, block_type, bits, solved_bitdata, bitdata, verbose=False): gridinfo = self.grid.gridinfo_at_tilename(tile_name) try: @@ -69,7 +69,7 @@ class FasmDisassembler(object): self.decode_warnings.add(gridinfo.tile_type) return - for ones_matched, feature in tile_segbits.match_bitdata(bits, bitdata): + for ones_matched, feature in tile_segbits.match_bitdata(block_type, bits, bitdata): for frame, bit in ones_matched: if frame not in solved_bitdata: solved_bitdata[frame] = set() @@ -94,7 +94,7 @@ class FasmDisassembler(object): # Iterate over all tiles that use this frame. for bits_info in self.segment_map.segment_info_for_frame(frame): # Don't examine a tile twice - if bits_info.tile in tiles_checked: + if (bits_info.tile, bits_info.block_type) in tiles_checked: continue # Check if this frame has any data for the relevant tile. @@ -107,10 +107,11 @@ class FasmDisassembler(object): if not any_column: continue - tiles_checked.add(bits_info.tile) + tiles_checked.add((bits_info.tile, bits_info.block_type)) for fasm_line in self.find_features_in_tile( - bits_info.tile, bits_info.bits, solved_bitdata, + bits_info.tile, bits_info.block_type, + bits_info.bits, solved_bitdata, bitdata, verbose=verbose): if fasm_line not in emitted_features: emitted_features.add(fasm_line) diff --git a/prjxray/grid.py b/prjxray/grid.py index 3acde582..7cbd6f3e 100644 --- a/prjxray/grid.py +++ b/prjxray/grid.py @@ -12,9 +12,9 @@ class BlockType(enum.Enum): GridLoc = namedtuple('GridLoc', 'grid_x grid_y') -GridInfo = namedtuple('GridInfo', 'segment bits sites tile_type') +GridInfo = namedtuple('GridInfo', 'bits sites tile_type') Bits = namedtuple('Bits', 'base_address frames offset words') -BitsInfo = namedtuple('BitsInfo', 'segment_type tile bits') +BitsInfo = namedtuple('BitsInfo', 'block_type tile bits') class Grid(object): @@ -28,14 +28,6 @@ class Grid(object): self.tilegrid = tilegrid self.loc = {} self.tileinfo = {} - # Map of segment name to tiles in that segment - self.segments = {} - - # Map of (base_address, segment type) -> segment name - self.base_addresses = {} - - # Map of base_address -> (segment type, segment name) - self.base_addresses = {} for tile in self.tilegrid: tileinfo = self.tilegrid[tile] @@ -45,12 +37,6 @@ class Grid(object): bits = {} - if 'segment' in tileinfo: - if tileinfo['segment'] not in self.segments: - self.segments[tileinfo['segment']] = [] - - self.segments[tileinfo['segment']].append(tile) - if 'bits' in tileinfo: for k in tileinfo['bits']: segment_type = BlockType(k) @@ -63,7 +49,6 @@ class Grid(object): ) self.tileinfo[tile] = GridInfo( - segment=tileinfo['segment'] if 'segment' in tileinfo else None, bits=bits, sites=tileinfo['sites'], tile_type=tileinfo['type'], @@ -102,9 +87,9 @@ class Grid(object): def iter_all_frames(self): for tile, tileinfo in self.tileinfo.items(): - for segment_type, bits in tileinfo.bits.items(): + for block_type, bits in tileinfo.bits.items(): yield BitsInfo( - segment_type=segment_type, + block_type=block_type, tile=tile, bits=bits, ) diff --git a/prjxray/tile.py b/prjxray/tile.py index f8b4770b..0f6c5c38 100644 --- a/prjxray/tile.py +++ b/prjxray/tile.py @@ -2,7 +2,7 @@ from collections import namedtuple import json from prjxray import lib """ Database files available for a tile """ -TileDbs = namedtuple('TileDbs', 'segbits ppips mask tile_type') +TileDbs = namedtuple('TileDbs', 'segbits block_ram_segbits ppips mask tile_type') Pip = namedtuple( 'Pip', 'name net_to net_from can_invert is_directional is_pseudo') diff --git a/prjxray/tile_segbits.py b/prjxray/tile_segbits.py index 8472c9f8..bf496977 100644 --- a/prjxray/tile_segbits.py +++ b/prjxray/tile_segbits.py @@ -1,6 +1,8 @@ from collections import namedtuple from prjxray import bitstream +from prjxray.grid import BlockType import enum +import functools class PsuedoPipType(enum.Enum): @@ -75,31 +77,39 @@ class TileSegbits(object): if tile_db.segbits is not None: with open(tile_db.segbits) as f: - self.segbits = read_segbits(f) + self.segbits[BlockType.CLB_IO_CLK] = read_segbits(f) - for feature in self.segbits: - sidx = feature.rfind('[') - eidx = feature.rfind(']') + if tile_db.block_ram_segbits is not None: + with open(tile_db.block_ram_segbits) as f: + self.segbits[BlockType.BLOCK_RAM] = read_segbits(f) - if sidx != -1: - assert eidx != -1 + for block_type in self.segbits: + for feature in self.segbits[block_type]: + sidx = feature.rfind('[') + eidx = feature.rfind(']') - base_feature = feature[:sidx] + if sidx != -1: + assert eidx != -1 - if base_feature not in self.feature_addresses: - self.feature_addresses[base_feature] = {} + base_feature = feature[:sidx] - self.feature_addresses[base_feature][int( - feature[sidx + 1:eidx])] = feature + if base_feature not in self.feature_addresses: + self.feature_addresses[base_feature] = {} - def match_bitdata(self, bits, bitdata): + self.feature_addresses[base_feature][int( + feature[sidx + 1:eidx])] = (block_type, feature) + + def match_bitdata(self, block_type, bits, bitdata): """ Return matching features for tile bits data (grid.Bits) and bitdata. See bitstream.load_bitdata for details on bitdata structure. """ - for feature, segbit in self.segbits.items(): + if block_type not in self.segbits: + raise StopIteration() + + for feature, segbit in self.segbits[block_type].items(): match = True for query_bit in segbit: frame = bits.base_address + query_bit.word_column @@ -134,15 +144,12 @@ class TileSegbits(object): if feature in self.ppips: return - if address == 0 and feature in self.segbits: - for bit in self.segbits[feature]: - yield bit - else: - for bit in self.segbits[self.feature_addresses[feature][address]]: - yield bit + for block_type in self.segbits: + if address == 0 and feature in self.segbits[block_type]: + for bit in self.segbits[block_type][feature]: + yield bit + return - def frames(self, bits): - """ Iterate over frames this tile uses for a given bit location. """ - for query_bits in self.segbits.values(): - for bit in query_bits: - yield bits.base_address + bit.word_column + block_type, feature = self.feature_addresses[feature][address] + for bit in self.segbits[block_type][feature]: + yield bit From fcc21c99899260e0f10a165af3d2bd383c32d370 Mon Sep 17 00:00:00 2001 From: Keith Rothman <537074+litghost@users.noreply.github.com> Date: Sat, 2 Feb 2019 07:39:52 -0800 Subject: [PATCH 2/3] Run make format. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com> --- prjxray/fasm_disassembler.py | 16 +++++++++++----- prjxray/tile.py | 3 ++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/prjxray/fasm_disassembler.py b/prjxray/fasm_disassembler.py index ff4112d2..e11d2803 100644 --- a/prjxray/fasm_disassembler.py +++ b/prjxray/fasm_disassembler.py @@ -38,7 +38,13 @@ class FasmDisassembler(object): self.decode_warnings = set() def find_features_in_tile( - self, tile_name, block_type, bits, solved_bitdata, bitdata, verbose=False): + self, + tile_name, + block_type, + bits, + solved_bitdata, + bitdata, + verbose=False): gridinfo = self.grid.gridinfo_at_tilename(tile_name) try: @@ -69,7 +75,8 @@ class FasmDisassembler(object): self.decode_warnings.add(gridinfo.tile_type) return - for ones_matched, feature in tile_segbits.match_bitdata(block_type, bits, bitdata): + for ones_matched, feature in tile_segbits.match_bitdata(block_type, + bits, bitdata): for frame, bit in ones_matched: if frame not in solved_bitdata: solved_bitdata[frame] = set() @@ -110,9 +117,8 @@ class FasmDisassembler(object): tiles_checked.add((bits_info.tile, bits_info.block_type)) for fasm_line in self.find_features_in_tile( - bits_info.tile, bits_info.block_type, - bits_info.bits, solved_bitdata, - bitdata, verbose=verbose): + bits_info.tile, bits_info.block_type, bits_info.bits, + solved_bitdata, bitdata, verbose=verbose): if fasm_line not in emitted_features: emitted_features.add(fasm_line) yield fasm_line diff --git a/prjxray/tile.py b/prjxray/tile.py index 0f6c5c38..94c4fc4a 100644 --- a/prjxray/tile.py +++ b/prjxray/tile.py @@ -2,7 +2,8 @@ from collections import namedtuple import json from prjxray import lib """ Database files available for a tile """ -TileDbs = namedtuple('TileDbs', 'segbits block_ram_segbits ppips mask tile_type') +TileDbs = namedtuple( + 'TileDbs', 'segbits block_ram_segbits ppips mask tile_type') Pip = namedtuple( 'Pip', 'name net_to net_from can_invert is_directional is_pseudo') From 9042849c666e88caa3a209f904e0865037b2ed95 Mon Sep 17 00:00:00 2001 From: Keith Rothman <537074+litghost@users.noreply.github.com> Date: Sat, 2 Feb 2019 07:46:59 -0800 Subject: [PATCH 3/3] Use return of StopIteration. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com> --- prjxray/tile_segbits.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prjxray/tile_segbits.py b/prjxray/tile_segbits.py index bf496977..69ab8318 100644 --- a/prjxray/tile_segbits.py +++ b/prjxray/tile_segbits.py @@ -107,7 +107,7 @@ class TileSegbits(object): """ if block_type not in self.segbits: - raise StopIteration() + return for feature, segbit in self.segbits[block_type].items(): match = True