From 6b234bf48434153513651b7081188690671f90d0 Mon Sep 17 00:00:00 2001 From: Maciej Kurc Date: Mon, 9 Dec 2019 13:40:05 +0100 Subject: [PATCH 1/7] Added support for having a set of required features in the prjxray db. Signed-off-by: Maciej Kurc --- prjxray/db.py | 27 +++++++++++++++++++++++++++ utils/fasm2frames.py | 5 +++++ 2 files changed, 32 insertions(+) diff --git a/prjxray/db.py b/prjxray/db.py index d0fa2f3a..2700b6be 100644 --- a/prjxray/db.py +++ b/prjxray/db.py @@ -87,6 +87,14 @@ class Database(object): self.tile_types_obj = {} + # Load set of required fasm features for given part. + self.required_features = {} + fname = os.path.join(self.db_root, "required_features.json") + + if os.path.isfile(fname): + with open(fname, "r") as fp: + self.required_features = json.load(fp) + def get_tile_types(self): """ Return list of tile types """ return self.tile_types.keys() @@ -147,3 +155,22 @@ 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() + + # Get a list of required features for all parts + features = set() + if "all" in self.required_features: + features |= set(self.required_features["all"]) + + # TODO: Add a support for required features for a specific part. + + return features diff --git a/utils/fasm2frames.py b/utils/fasm2frames.py index 5551527e..00270475 100755 --- a/utils/fasm2frames.py +++ b/utils/fasm2frames.py @@ -120,6 +120,11 @@ def run( extra_features = fasm.parse_fasm_string( '\n'.join(roi_j['required_features'])) + # Get required features for the part + # TODO: Specify the part explicitly ? + required_features = db.get_required_fasm_features(None) + 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: From 726d744fca17253ffe6cc9a1f4e8e9a0c1a36646 Mon Sep 17 00:00:00 2001 From: Maciej Kurc Date: Tue, 10 Dec 2019 13:20:44 +0100 Subject: [PATCH 2/7] Changed JSON format for required features. Signed-off-by: Maciej Kurc --- prjxray/db.py | 16 +++++++++++++--- utils/fasm2frames.py | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/prjxray/db.py b/prjxray/db.py index 2700b6be..56ea14f0 100644 --- a/prjxray/db.py +++ b/prjxray/db.py @@ -168,9 +168,19 @@ class Database(object): # Get a list of required features for all parts features = set() - if "all" in self.required_features: - features |= set(self.required_features["all"]) + if "always_required" in self.required_features: + features |= set(self.required_features["always_required"]) - # TODO: Add a support for required features for a specific part. + # Append / remove features for the specific part. If a feature string + # starts with "-" then the feature needs not to be present for that + # part. + if part is not None: + for f in self.required_features["per_part_required"][part]: + + if f.startswith("-"): + f = f[1:] + features -= set([f]) + else: + features |= set([f]) return features diff --git a/utils/fasm2frames.py b/utils/fasm2frames.py index 00270475..8776103d 100755 --- a/utils/fasm2frames.py +++ b/utils/fasm2frames.py @@ -120,7 +120,7 @@ def run( extra_features = fasm.parse_fasm_string( '\n'.join(roi_j['required_features'])) - # Get required features for the part + # Get required extra features for the part # TODO: Specify the part explicitly ? required_features = db.get_required_fasm_features(None) extra_features += fasm.parse_fasm_string('\n'.join(required_features)) From 634593ee060215b3ee8918d69be5df62fc16304c Mon Sep 17 00:00:00 2001 From: Maciej Kurc Date: Tue, 10 Dec 2019 13:49:51 +0100 Subject: [PATCH 3/7] Changed the way that required features are to be stored in the db. Signed-off-by: Maciej Kurc --- prjxray/db.py | 43 +++++++++++++++++++++++++++---------------- utils/fasm2frames.py | 11 +++++++++-- 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/prjxray/db.py b/prjxray/db.py index 56ea14f0..daecc2ea 100644 --- a/prjxray/db.py +++ b/prjxray/db.py @@ -42,6 +42,8 @@ class Database(object): self.tile_segbits = {} self.site_types = {} + per_part_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,15 +87,32 @@ 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) + + per_part_features[part] = set(features) + self.tile_types_obj = {} - # Load set of required fasm features for given part. - self.required_features = {} - fname = os.path.join(self.db_root, "required_features.json") + # Find common required features for all supported parts + if len(per_part_features) > 0: + common_features = set.intersection(*per_part_features.values()) + for features in per_part_features.values(): + features -= common_features + else: + common_features = set() - if os.path.isfile(fname): - with open(fname, "r") as fp: - self.required_features = json.load(fp) + self.required_features = { + "always_required": common_features, + "per_part_required": per_part_features + } def get_tile_types(self): """ Return list of tile types """ @@ -171,16 +190,8 @@ class Database(object): if "always_required" in self.required_features: features |= set(self.required_features["always_required"]) - # Append / remove features for the specific part. If a feature string - # starts with "-" then the feature needs not to be present for that - # part. + # Append list of part specific features if part is not None: - for f in self.required_features["per_part_required"][part]: - - if f.startswith("-"): - f = f[1:] - features -= set([f]) - else: - features |= set([f]) + features |= set(self.required_features["per_part_required"][part]) return features diff --git a/utils/fasm2frames.py b/utils/fasm2frames.py index 8776103d..f540fc7e 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, @@ -121,8 +122,7 @@ def run( '\n'.join(roi_j['required_features'])) # Get required extra features for the part - # TODO: Specify the part explicitly ? - required_features = db.get_required_fasm_features(None) + 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) @@ -170,7 +170,13 @@ def main(): db_root_kwargs['required'] = False db_root_kwargs['default'] = os.path.join(database_dir, database) + def_part = os.getenv("XRAY_PART") + parser.add_argument('--db-root', help="Database root.", **db_root_kwargs) + parser.add_argument( + '--part', + default=def_part, + help="Part name. When not given defaults to XRAY_PART env. var.") parser.add_argument( '--sparse', action='store_true', help="Don't zero fill all frames") parser.add_argument( @@ -192,6 +198,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, From a4a033226fe555081563efb7d0e37d56c6f6803a Mon Sep 17 00:00:00 2001 From: Maciej Kurc Date: Tue, 10 Dec 2019 14:38:24 +0100 Subject: [PATCH 4/7] Modified fuzzer 001 to include required features for Zynq parts. Signed-off-by: Maciej Kurc --- fuzzers/001-part-yaml/Makefile | 2 ++ fuzzers/001-part-yaml/xc7z010clg400-1_required_features.fasm | 4 ++++ fuzzers/001-part-yaml/xc7z020clg400-1_required_features.fasm | 3 +++ 3 files changed, 9 insertions(+) create mode 100644 fuzzers/001-part-yaml/xc7z010clg400-1_required_features.fasm create mode 100644 fuzzers/001-part-yaml/xc7z020clg400-1_required_features.fasm 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 From 4d3059982da51822852833efeab11cc62edcd027 Mon Sep 17 00:00:00 2001 From: Maciej Kurc Date: Tue, 10 Dec 2019 14:51:23 +0100 Subject: [PATCH 5/7] Updated fasm2frames test. Signed-off-by: Maciej Kurc --- utils/test_fasm2frames.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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() From 4502fc14e6c8fb1a51bd66430606ce4e219f4f29 Mon Sep 17 00:00:00 2001 From: Maciej Kurc Date: Tue, 10 Dec 2019 17:54:54 +0100 Subject: [PATCH 6/7] fasm2frames parameter "--part" made mandatory if XRAY_PART is not set, removed emitting common features for all parts if the part is not given. Signed-off-by: Maciej Kurc --- prjxray/db.py | 33 ++++++--------------------------- utils/fasm2frames.py | 12 +++++++++--- 2 files changed, 15 insertions(+), 30 deletions(-) diff --git a/prjxray/db.py b/prjxray/db.py index daecc2ea..50ecc6a8 100644 --- a/prjxray/db.py +++ b/prjxray/db.py @@ -42,7 +42,7 @@ class Database(object): self.tile_segbits = {} self.site_types = {} - per_part_features = {} + self.required_features = {} for f in os.listdir(self.db_root): if f.endswith('.json') and f.startswith('tile_type_'): @@ -97,23 +97,10 @@ class Database(object): if len(line) > 0: features.append(line) - per_part_features[part] = set(features) + self.required_features[part] = set(features) self.tile_types_obj = {} - # Find common required features for all supported parts - if len(per_part_features) > 0: - common_features = set.intersection(*per_part_features.values()) - for features in per_part_features.values(): - features -= common_features - else: - common_features = set() - - self.required_features = { - "always_required": common_features, - "per_part_required": per_part_features - } - def get_tile_types(self): """ Return list of tile types """ return self.tile_types.keys() @@ -181,17 +168,9 @@ class Database(object): of fasm features. """ - # No required features in the db, return empty list - if self.required_features is None: + # No required features in the db or part not given, return empty list + if self.required_features is None or part is None: return set() - # Get a list of required features for all parts - features = set() - if "always_required" in self.required_features: - features |= set(self.required_features["always_required"]) - - # Append list of part specific features - if part is not None: - features |= set(self.required_features["per_part_required"][part]) - - return features + # Return list of part specific features + return self.required_features[part] diff --git a/utils/fasm2frames.py b/utils/fasm2frames.py index f540fc7e..1efd2a4e 100755 --- a/utils/fasm2frames.py +++ b/utils/fasm2frames.py @@ -170,13 +170,19 @@ def main(): db_root_kwargs['required'] = False db_root_kwargs['default'] = os.path.join(database_dir, database) - def_part = os.getenv("XRAY_PART") + 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', - default=def_part, - help="Part name. When not given defaults to XRAY_PART env. var.") + 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( From 0d5a596a875e60fe82705cd37ab29b0145d12539 Mon Sep 17 00:00:00 2001 From: Maciej Kurc Date: Tue, 10 Dec 2019 18:39:59 +0100 Subject: [PATCH 7/7] Addressed review comments. Signed-off-by: Maciej Kurc --- prjxray/db.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/prjxray/db.py b/prjxray/db.py index 50ecc6a8..bdc85fc3 100644 --- a/prjxray/db.py +++ b/prjxray/db.py @@ -168,9 +168,9 @@ class Database(object): of fasm features. """ - # No required features in the db or part not given, return empty list - if self.required_features is None or part is None: + # 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[part] + return self.required_features.get(part, set())