mirror of https://github.com/openXC7/prjxray.git
140 lines
4.7 KiB
Python
140 lines
4.7 KiB
Python
from prjxray import segment_map
|
|
from prjxray.grid_types import BlockType, GridLoc, GridInfo, BitAlias, Bits, BitsInfo, ClockRegion
|
|
from prjxray.tile_segbits_alias import TileSegbitsAlias
|
|
import re
|
|
|
|
CLOCK_REGION_RE = re.compile('X([0-9])Y([0-9])')
|
|
|
|
|
|
class Grid(object):
|
|
""" Object that represents grid for a given database.
|
|
|
|
Provides methods to inspect grid by name or location. Also provides mapping
|
|
of segment offsets for particular grid locations and their tile types.
|
|
"""
|
|
|
|
def __init__(self, db, tilegrid):
|
|
self.db = db
|
|
self.tilegrid = tilegrid
|
|
self.loc = {}
|
|
self.tileinfo = {}
|
|
|
|
clock_regions = {}
|
|
|
|
for tile in self.tilegrid:
|
|
tileinfo = self.tilegrid[tile]
|
|
grid_loc = GridLoc(tileinfo['grid_x'], tileinfo['grid_y'])
|
|
assert grid_loc not in self.loc
|
|
self.loc[grid_loc] = tile
|
|
|
|
bits = {}
|
|
|
|
if 'bits' in tileinfo:
|
|
for k in tileinfo['bits']:
|
|
segment_type = BlockType(k)
|
|
base_address = int(tileinfo['bits'][k]['baseaddr'], 0)
|
|
|
|
alias = None
|
|
if 'alias' in tileinfo['bits'][k]:
|
|
alias = BitAlias(
|
|
tile_type=tileinfo['bits'][k]['alias']['type'],
|
|
start_offset=tileinfo['bits'][k]['alias']
|
|
['start_offset'],
|
|
sites=tileinfo['bits'][k]['alias']['sites'],
|
|
)
|
|
|
|
bits[segment_type] = Bits(
|
|
base_address=base_address,
|
|
frames=tileinfo['bits'][k]['frames'],
|
|
offset=tileinfo['bits'][k]['offset'],
|
|
words=tileinfo['bits'][k]['words'],
|
|
alias=alias,
|
|
)
|
|
|
|
clock_region = None
|
|
if 'clock_region' in tileinfo:
|
|
if tileinfo['clock_region'] is not None:
|
|
if tileinfo['clock_region'] not in clock_regions:
|
|
m = CLOCK_REGION_RE.fullmatch(tileinfo['clock_region'])
|
|
assert m is not None, tileinfo['clock_region']
|
|
|
|
clock_regions[tileinfo['clock_region']] = ClockRegion(
|
|
name=tileinfo['clock_region'],
|
|
x=int(m.group(1)),
|
|
y=int(m.group(2)))
|
|
|
|
clock_region = clock_regions[tileinfo['clock_region']]
|
|
|
|
self.tileinfo[tile] = GridInfo(
|
|
bits=bits,
|
|
sites=tileinfo['sites'],
|
|
prohibited_sites=tileinfo['prohibited_sites'],
|
|
tile_type=tileinfo['type'],
|
|
pin_functions=tileinfo.get('pin_functions', {}),
|
|
clock_region=clock_region,
|
|
)
|
|
|
|
x, y = zip(*self.loc.keys())
|
|
self._dims = (min(x), max(x), min(y), max(y))
|
|
|
|
def tiles(self):
|
|
""" Return list of tiles. """
|
|
return self.tileinfo.keys()
|
|
|
|
def tile_locations(self):
|
|
""" Return list of tile locations. """
|
|
return self.loc.keys()
|
|
|
|
def dims(self):
|
|
""" Returns (x_min, x_max, y_min, y_max) for given Grid. """
|
|
return self._dims
|
|
|
|
def is_populated(self, grid_loc):
|
|
return grid_loc in self.loc
|
|
|
|
def loc_of_tilename(self, tilename):
|
|
tileinfo = self.tilegrid[tilename]
|
|
return GridLoc(tileinfo['grid_x'], tileinfo['grid_y'])
|
|
|
|
def tilename_at_loc(self, grid_loc):
|
|
return self.loc[grid_loc]
|
|
|
|
def gridinfo_at_loc(self, grid_loc):
|
|
return self.tileinfo[self.loc[grid_loc]]
|
|
|
|
def gridinfo_at_tilename(self, tilename):
|
|
return self.tileinfo[tilename]
|
|
|
|
def iter_all_frames(self):
|
|
for tile, tileinfo in self.tileinfo.items():
|
|
for block_type, bits in tileinfo.bits.items():
|
|
yield BitsInfo(
|
|
block_type=block_type,
|
|
tile=tile,
|
|
bits=bits,
|
|
)
|
|
|
|
def get_segment_map(self):
|
|
return segment_map.SegmentMap(self)
|
|
|
|
def tile_key(self, tilename):
|
|
gridinfo = self.gridinfo_at_tilename(tilename)
|
|
loc = self.loc_of_tilename(tilename)
|
|
tile_type = gridinfo.tile_type
|
|
|
|
return (tile_type, loc.grid_x, -loc.grid_y)
|
|
|
|
def get_tile_segbits_at_tilename(self, tilename):
|
|
gridinfo = self.gridinfo_at_tilename(tilename)
|
|
|
|
# Check to see if alias is present
|
|
any_alias = False
|
|
for block_type, bits in gridinfo.bits.items():
|
|
if bits.alias is not None:
|
|
any_alias = True
|
|
|
|
if any_alias:
|
|
return TileSegbitsAlias(self.db, gridinfo.tile_type, gridinfo.bits)
|
|
else:
|
|
return self.db.get_tile_segbits(gridinfo.tile_type)
|