diff --git a/fuzzers/001-part-yaml/Makefile b/fuzzers/001-part-yaml/Makefile index 34aa6e75..70b92fe7 100644 --- a/fuzzers/001-part-yaml/Makefile +++ b/fuzzers/001-part-yaml/Makefile @@ -6,6 +6,7 @@ database: $(SPECIMENS) cp build/specimen_001/part.yaml build/part.yaml python3 -m utils.xyaml build/part.yaml > build/part_no_iobanks.json python3 add_iobanks.py --part_json build/part_no_iobanks.json --iobanks_info build/specimen_001/iobanks.txt > build/part.json + cp ${XRAY_PART}_required_features.fasm build/ 2>/dev/null || true $(SPECIMENS): Makefile.specimen mkdir -p $@ @@ -14,6 +15,7 @@ $(SPECIMENS): Makefile.specimen pushdb: cp build/part.yaml ${XRAY_DATABASE_DIR}/$(XRAY_DATABASE)/${XRAY_PART}.yaml cp build/part.json ${XRAY_DATABASE_DIR}/$(XRAY_DATABASE)/${XRAY_PART}.json + cp build/${XRAY_PART}_required_features.fasm ${XRAY_DATABASE_DIR}/$(XRAY_DATABASE)/${XRAY_PART}_required_features.fasm 2>/dev/null || true run: $(MAKE) clean diff --git a/fuzzers/001-part-yaml/xc7z010clg400-1_required_features.fasm b/fuzzers/001-part-yaml/xc7z010clg400-1_required_features.fasm new file mode 100644 index 00000000..f1cfc1d6 --- /dev/null +++ b/fuzzers/001-part-yaml/xc7z010clg400-1_required_features.fasm @@ -0,0 +1,4 @@ +CFG_CENTER_MID_X67Y32.ALWAYS_ON_PROP1 +CFG_CENTER_MID_X67Y32.ALWAYS_ON_PROP2 +CFG_CENTER_MID_X67Y32.ALWAYS_ON_PROP3 + diff --git a/fuzzers/001-part-yaml/xc7z020clg400-1_required_features.fasm b/fuzzers/001-part-yaml/xc7z020clg400-1_required_features.fasm new file mode 100644 index 00000000..a8b5d226 --- /dev/null +++ b/fuzzers/001-part-yaml/xc7z020clg400-1_required_features.fasm @@ -0,0 +1,3 @@ +CFG_CENTER_MID_X123Y84.ALWAYS_ON_PROP1 +CFG_CENTER_MID_X123Y84.ALWAYS_ON_PROP2 +CFG_CENTER_MID_X123Y84.ALWAYS_ON_PROP3 diff --git a/prjxray/db.py b/prjxray/db.py index d0fa2f3a..bdc85fc3 100644 --- a/prjxray/db.py +++ b/prjxray/db.py @@ -42,6 +42,8 @@ class Database(object): 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() @@ -85,6 +87,18 @@ class Database(object): self.site_types[site_type_name] = os.path.join(self.db_root, f) + if f.endswith('_required_features.fasm'): + part = f[:-len('_required_features.fasm')] + + with open(os.path.join(self.db_root, f), "r") as fp: + features = [] + for line in fp: + line = line.strip() + if len(line) > 0: + features.append(line) + + self.required_features[part] = set(features) + self.tile_types_obj = {} def get_tile_types(self): @@ -147,3 +161,16 @@ class Database(object): 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()) diff --git a/utils/fasm2frames.py b/utils/fasm2frames.py index 5551527e..1efd2a4e 100755 --- a/utils/fasm2frames.py +++ b/utils/fasm2frames.py @@ -81,6 +81,7 @@ def find_pudc_b(db): def run( db_root, + part, filename_in, f_out, sparse=False, @@ -120,6 +121,10 @@ def run( extra_features = fasm.parse_fasm_string( '\n'.join(roi_j['required_features'])) + # Get required extra features for the part + required_features = db.get_required_fasm_features(part) + extra_features += fasm.parse_fasm_string('\n'.join(required_features)) + assembler.parse_fasm_filename(filename_in, extra_features=extra_features) if emit_pudc_b_pullup and not pudc_b_in_use and pudc_b_tile_site is not None: @@ -165,7 +170,19 @@ def main(): db_root_kwargs['required'] = False db_root_kwargs['default'] = os.path.join(database_dir, database) + db_part = os.getenv("XRAY_PART") + db_part_kwargs = {} + if db_part is None: + db_part_kwargs['required'] = True + else: + db_part_kwargs['required'] = False + db_part_kwargs['default'] = db_part + parser.add_argument('--db-root', help="Database root.", **db_root_kwargs) + parser.add_argument( + '--part', + help="Part name. When not given defaults to XRAY_PART env. var.", + **db_part_kwargs) parser.add_argument( '--sparse', action='store_true', help="Don't zero fill all frames") parser.add_argument( @@ -187,6 +204,7 @@ def main(): args = parser.parse_args() run( db_root=args.db_root, + part=args.part, filename_in=args.fn_in, f_out=open(args.fn_out, 'w'), sparse=args.sparse, diff --git a/utils/test_fasm2frames.py b/utils/test_fasm2frames.py index b95631b2..69c32a44 100755 --- a/utils/test_fasm2frames.py +++ b/utils/test_fasm2frames.py @@ -70,7 +70,7 @@ class TestStringMethods(unittest.TestCase): fout = StringIO() fasm2frames.run( - self.filename_test_data('db'), fin.name, fout, **kw) + self.filename_test_data('db'), None, fin.name, fout, **kw) return fout.getvalue()