| import os.path | |
| import simplejson as json | |
| from utils import grid | |
| from utils import tile | |
| from utils import tile_segbits | |
| from utils import site_type | |
| from utils import connections | |
| def get_available_databases(prjxray_root): | |
| """ Return set of available directory to databases given the root directory | |
| of prjxray-db | |
| """ | |
| db_types = set() | |
| for d in os.listdir(prjxray_root): | |
| if d.startswith("."): | |
| continue | |
| dpath = os.path.join(prjxray_root, d) | |
| if os.path.exists(os.path.join(dpath, "settings.sh")): | |
| db_types.add(dpath) | |
| return db_types | |
| class Database(object): | |
| def __init__(self, db_root, part): | |
| """ Create project x-ray Database at given db_root. | |
| db_root: Path to directory containing settings.sh, *.db, tilegrid.json and | |
| tileconn.json | |
| """ | |
| self.db_root = db_root | |
| self.part = part | |
| # tilegrid.json JSON object | |
| self.tilegrid = None | |
| self.tileconn = None | |
| self.tile_types = None | |
| self.tile_types = {} | |
| self.tile_segbits = {} | |
| self.site_types = {} | |
| self.required_features = {} | |
| for f in os.listdir(self.db_root): | |
| if f.endswith('.json') and f.startswith('tile_type_'): | |
| tile_type = f[len('tile_type_'):-len('.json')].lower() | |
| segbits = os.path.join(self.db_root, | |
| 'segbits_{}.db'.format(tile_type)) | |
| 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): | |
| ppips = None | |
| mask = os.path.join(self.db_root, | |
| 'mask_{}.db'.format(tile_type)) | |
| if not os.path.isfile(mask): | |
| mask = None | |
| tile_type_file = os.path.join( | |
| self.db_root, | |
| 'tile_type_{}.json'.format(tile_type.upper())) | |
| if not os.path.isfile(tile_type_file): | |
| tile_type_file = None | |
| 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, | |
| ) | |
| if f.endswith('.json') and f.startswith('site_type_'): | |
| site_type_name = f[len('site_type_'):-len('.json')] | |
| self.site_types[site_type_name] = os.path.join(self.db_root, f) | |
| required_features_path = os.path.join(self.db_root, self.part, | |
| "required_features.fasm") | |
| if os.path.isfile(required_features_path): | |
| with open(required_features_path, "r") as fp: | |
| features = [] | |
| for line in fp: | |
| line = line.strip() | |
| if len(line) > 0: | |
| features.append(line) | |
| self.required_features[self.part] = set(features) | |
| self.tile_types_obj = {} | |
| def get_tile_types(self): | |
| """ Return list of tile types """ | |
| return self.tile_types.keys() | |
| def get_tile_type(self, tile_type): | |
| """ Return Tile object for given tilename. """ | |
| if tile_type not in self.tile_types_obj: | |
| self.tile_types_obj[tile_type] = tile.Tile( | |
| tile_type, self.tile_types[tile_type]) | |
| return self.tile_types_obj[tile_type] | |
| def _read_tilegrid(self): | |
| """ Read tilegrid database if not already read. """ | |
| if not self.tilegrid: | |
| with open(os.path.join(self.db_root, self.part, | |
| 'tilegrid.json')) as f: | |
| self.tilegrid = json.load(f) | |
| def _read_tileconn(self): | |
| """ Read tileconn database if not already read. """ | |
| if not self.tileconn: | |
| with open(os.path.join(self.db_root, self.part, | |
| 'tileconn.json')) as f: | |
| self.tileconn = json.load(f) | |
| def grid(self): | |
| """ Return Grid object for database. """ | |
| self._read_tilegrid() | |
| return grid.Grid(self, self.tilegrid) | |
| def _read_tile_types(self): | |
| for tile_type, db in self.tile_types.items(): | |
| with open(db.tile_type) as f: | |
| self.tile_types[tile_type] = json.load(f) | |
| def connections(self): | |
| self._read_tilegrid() | |
| self._read_tileconn() | |
| self._read_tile_types() | |
| tile_wires = dict((tile_type, db['wires']) | |
| for tile_type, db in self.tile_types.items()) | |
| return connections.Connections(self.tilegrid, self.tileconn, | |
| tile_wires) | |
| def get_site_types(self): | |
| return self.site_types.keys() | |
| def get_site_type(self, site_type_name): | |
| with open(self.site_types[site_type_name]) as f: | |
| site_type_data = json.load(f) | |
| return site_type.SiteType(site_type_data) | |
| def get_tile_segbits(self, tile_type): | |
| if tile_type not in self.tile_segbits: | |
| self.tile_segbits[tile_type] = tile_segbits.TileSegbits( | |
| self.tile_types[tile_type.upper()]) | |
| return self.tile_segbits[tile_type] | |
| def get_required_fasm_features(self, part=None): | |
| """ | |
| Assembles a set of required fasm features for given part. Returns a list | |
| of fasm features. | |
| """ | |
| # No required features in the db, return empty list | |
| if self.required_features is None: | |
| return set() | |
| # Return list of part specific features | |
| return self.required_features.get(part, set()) |