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:
litghost 2019-02-04 07:37:52 -08:00 committed by GitHub
commit f78ec45bda
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 57 additions and 51 deletions

View File

@ -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,

View 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

View File

@ -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,
)

View File

@ -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')

View File

@ -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