blob: c1632dfa08976d3377a75ca4ad98fbafabf97d4e [file] [log] [blame]
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (C) 2017-2020 The Project X-Ray Authors.
#
# Use of this source code is governed by a ISC-style
# license that can be found in the LICENSE file or at
# https://opensource.org/licenses/ISC
#
# SPDX-License-Identifier: ISC
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)