mirror of https://github.com/openXC7/prjxray.git
Merge pull request #600 from litghost/add_block_ram_to_prjxray_fasm
Add block ram segbits support to prjxray FASM
This commit is contained in:
commit
f78ec45bda
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -38,7 +38,13 @@ 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 +75,8 @@ 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 +101,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,11 +114,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,
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ 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')
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
return
|
||||
|
||||
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
|
||||
|
|
|
|||
Loading…
Reference in New Issue