mirror of https://github.com/openXC7/prjxray.git
Add BLOCK_RAM segments support.
Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
This commit is contained in:
parent
ce482565fc
commit
1d42f21e3d
|
|
@ -1,5 +1,5 @@
|
||||||
import os.path
|
import os.path
|
||||||
import json
|
import simplejson as json
|
||||||
from prjxray import grid
|
from prjxray import grid
|
||||||
from prjxray import tile
|
from prjxray import tile
|
||||||
from prjxray import tile_segbits
|
from prjxray import tile_segbits
|
||||||
|
|
@ -51,6 +51,11 @@ class Database(object):
|
||||||
if not os.path.isfile(segbits):
|
if not os.path.isfile(segbits):
|
||||||
segbits = None
|
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(
|
ppips = os.path.join(
|
||||||
self.db_root, 'ppips_{}.db'.format(tile_type))
|
self.db_root, 'ppips_{}.db'.format(tile_type))
|
||||||
if not os.path.isfile(ppips):
|
if not os.path.isfile(ppips):
|
||||||
|
|
@ -69,6 +74,7 @@ class Database(object):
|
||||||
|
|
||||||
self.tile_types[tile_type.upper()] = tile.TileDbs(
|
self.tile_types[tile_type.upper()] = tile.TileDbs(
|
||||||
segbits=segbits,
|
segbits=segbits,
|
||||||
|
block_ram_segbits=block_ram_segbits,
|
||||||
ppips=ppips,
|
ppips=ppips,
|
||||||
mask=mask,
|
mask=mask,
|
||||||
tile_type=tile_type_file,
|
tile_type=tile_type_file,
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ class FasmDisassembler(object):
|
||||||
self.decode_warnings = set()
|
self.decode_warnings = set()
|
||||||
|
|
||||||
def find_features_in_tile(
|
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)
|
gridinfo = self.grid.gridinfo_at_tilename(tile_name)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -69,7 +69,7 @@ class FasmDisassembler(object):
|
||||||
self.decode_warnings.add(gridinfo.tile_type)
|
self.decode_warnings.add(gridinfo.tile_type)
|
||||||
return
|
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:
|
for frame, bit in ones_matched:
|
||||||
if frame not in solved_bitdata:
|
if frame not in solved_bitdata:
|
||||||
solved_bitdata[frame] = set()
|
solved_bitdata[frame] = set()
|
||||||
|
|
@ -94,7 +94,7 @@ class FasmDisassembler(object):
|
||||||
# Iterate over all tiles that use this frame.
|
# Iterate over all tiles that use this frame.
|
||||||
for bits_info in self.segment_map.segment_info_for_frame(frame):
|
for bits_info in self.segment_map.segment_info_for_frame(frame):
|
||||||
# Don't examine a tile twice
|
# 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
|
continue
|
||||||
|
|
||||||
# Check if this frame has any data for the relevant tile.
|
# Check if this frame has any data for the relevant tile.
|
||||||
|
|
@ -107,10 +107,11 @@ class FasmDisassembler(object):
|
||||||
if not any_column:
|
if not any_column:
|
||||||
continue
|
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(
|
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):
|
bitdata, verbose=verbose):
|
||||||
if fasm_line not in emitted_features:
|
if fasm_line not in emitted_features:
|
||||||
emitted_features.add(fasm_line)
|
emitted_features.add(fasm_line)
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,9 @@ class BlockType(enum.Enum):
|
||||||
|
|
||||||
|
|
||||||
GridLoc = namedtuple('GridLoc', 'grid_x grid_y')
|
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')
|
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):
|
class Grid(object):
|
||||||
|
|
@ -28,14 +28,6 @@ class Grid(object):
|
||||||
self.tilegrid = tilegrid
|
self.tilegrid = tilegrid
|
||||||
self.loc = {}
|
self.loc = {}
|
||||||
self.tileinfo = {}
|
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:
|
for tile in self.tilegrid:
|
||||||
tileinfo = self.tilegrid[tile]
|
tileinfo = self.tilegrid[tile]
|
||||||
|
|
@ -45,12 +37,6 @@ class Grid(object):
|
||||||
|
|
||||||
bits = {}
|
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:
|
if 'bits' in tileinfo:
|
||||||
for k in tileinfo['bits']:
|
for k in tileinfo['bits']:
|
||||||
segment_type = BlockType(k)
|
segment_type = BlockType(k)
|
||||||
|
|
@ -63,7 +49,6 @@ class Grid(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
self.tileinfo[tile] = GridInfo(
|
self.tileinfo[tile] = GridInfo(
|
||||||
segment=tileinfo['segment'] if 'segment' in tileinfo else None,
|
|
||||||
bits=bits,
|
bits=bits,
|
||||||
sites=tileinfo['sites'],
|
sites=tileinfo['sites'],
|
||||||
tile_type=tileinfo['type'],
|
tile_type=tileinfo['type'],
|
||||||
|
|
@ -102,9 +87,9 @@ class Grid(object):
|
||||||
|
|
||||||
def iter_all_frames(self):
|
def iter_all_frames(self):
|
||||||
for tile, tileinfo in self.tileinfo.items():
|
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(
|
yield BitsInfo(
|
||||||
segment_type=segment_type,
|
block_type=block_type,
|
||||||
tile=tile,
|
tile=tile,
|
||||||
bits=bits,
|
bits=bits,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ from collections import namedtuple
|
||||||
import json
|
import json
|
||||||
from prjxray import lib
|
from prjxray import lib
|
||||||
""" Database files available for a tile """
|
""" 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 = namedtuple(
|
||||||
'Pip', 'name net_to net_from can_invert is_directional is_pseudo')
|
'Pip', 'name net_to net_from can_invert is_directional is_pseudo')
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from prjxray import bitstream
|
from prjxray import bitstream
|
||||||
|
from prjxray.grid import BlockType
|
||||||
import enum
|
import enum
|
||||||
|
import functools
|
||||||
|
|
||||||
|
|
||||||
class PsuedoPipType(enum.Enum):
|
class PsuedoPipType(enum.Enum):
|
||||||
|
|
@ -75,31 +77,39 @@ class TileSegbits(object):
|
||||||
|
|
||||||
if tile_db.segbits is not None:
|
if tile_db.segbits is not None:
|
||||||
with open(tile_db.segbits) as f:
|
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:
|
if tile_db.block_ram_segbits is not None:
|
||||||
sidx = feature.rfind('[')
|
with open(tile_db.block_ram_segbits) as f:
|
||||||
eidx = feature.rfind(']')
|
self.segbits[BlockType.BLOCK_RAM] = read_segbits(f)
|
||||||
|
|
||||||
if sidx != -1:
|
for block_type in self.segbits:
|
||||||
assert eidx != -1
|
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:
|
base_feature = feature[:sidx]
|
||||||
self.feature_addresses[base_feature] = {}
|
|
||||||
|
|
||||||
self.feature_addresses[base_feature][int(
|
if base_feature not in self.feature_addresses:
|
||||||
feature[sidx + 1:eidx])] = feature
|
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.
|
""" Return matching features for tile bits data (grid.Bits) and bitdata.
|
||||||
|
|
||||||
See bitstream.load_bitdata for details on bitdata structure.
|
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
|
match = True
|
||||||
for query_bit in segbit:
|
for query_bit in segbit:
|
||||||
frame = bits.base_address + query_bit.word_column
|
frame = bits.base_address + query_bit.word_column
|
||||||
|
|
@ -134,15 +144,12 @@ class TileSegbits(object):
|
||||||
if feature in self.ppips:
|
if feature in self.ppips:
|
||||||
return
|
return
|
||||||
|
|
||||||
if address == 0 and feature in self.segbits:
|
for block_type in self.segbits:
|
||||||
for bit in self.segbits[feature]:
|
if address == 0 and feature in self.segbits[block_type]:
|
||||||
yield bit
|
for bit in self.segbits[block_type][feature]:
|
||||||
else:
|
yield bit
|
||||||
for bit in self.segbits[self.feature_addresses[feature][address]]:
|
return
|
||||||
yield bit
|
|
||||||
|
|
||||||
def frames(self, bits):
|
block_type, feature = self.feature_addresses[feature][address]
|
||||||
""" Iterate over frames this tile uses for a given bit location. """
|
for bit in self.segbits[block_type][feature]:
|
||||||
for query_bits in self.segbits.values():
|
yield bit
|
||||||
for bit in query_bits:
|
|
||||||
yield bits.base_address + bit.word_column
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue