From f0f29956d70ccf70e1a3b52113a646c030ef89df Mon Sep 17 00:00:00 2001 From: Keith Rothman <537074+litghost@users.noreply.github.com> Date: Tue, 12 Feb 2019 17:25:52 -0800 Subject: [PATCH 1/3] Add FASM features that are outside ROI grid, but inside used frames. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com> --- minitests/roi_harness/create_design_json.py | 41 +++++++++++++++++++++ minitests/roi_harness/runme.sh | 6 ++- settings/artix7.sh | 2 +- 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/minitests/roi_harness/create_design_json.py b/minitests/roi_harness/create_design_json.py index 1d127f70..09553d93 100644 --- a/minitests/roi_harness/create_design_json.py +++ b/minitests/roi_harness/create_design_json.py @@ -2,6 +2,7 @@ import json import csv import argparse import sys +import fasm from prjxray.db import Database from prjxray.roi import Roi from prjxray.util import get_db_root @@ -24,6 +25,7 @@ def main(): parser.add_argument('--design_txt', required=True) parser.add_argument('--design_info_txt', required=True) parser.add_argument('--pad_wires', required=True) + parser.add_argument('--design_fasm', required=True) args = parser.parse_args() @@ -51,6 +53,7 @@ def main(): y2=j['info']['GRID_Y_MAX'], ) + with open(args.pad_wires) as f: for l in f: parts = l.strip().split(' ') @@ -70,6 +73,44 @@ def main(): set_port_wires(j['ports'], name, pin, wires_outside_roi) + frames_in_use = set() + for tile in roi.gen_tiles(): + gridinfo = grid.gridinfo_at_tilename(tile) + + for bit in gridinfo.bits.values(): + frames_in_use.add(bit.base_address) + + required_features = [] + for fasm_line in fasm.parse_fasm_filename(args.design_fasm): + if fasm_line.annotations: + for annotation in fasm_line.annotations: + if annotation.name != 'unknown_segment': + continue + + unknown_base_address = int(annotation.value, 0) + + assert unknown_base_address not in frames_in_use, "Found unknown bit in base address 0x{:08x}".format(unknown_base_address) + + if not fasm_line.set_feature: + continue + + tile = fasm_line.set_feature.feature.split('.')[0] + + loc = grid.loc_of_tilename(tile) + gridinfo = grid.gridinfo_at_tilename(tile) + + base_address_in_roi = False + for bit in gridinfo.bits.values(): + if bit.base_address in frames_in_use: + base_address_in_roi = True + + not_in_roi = not roi.tile_in_roi(loc) + + if not_in_roi and base_address_in_roi: + required_features.append(fasm_line) + + j['required_features'] = fasm.fasm_tuple_to_string(required_features, canonical=True) + json.dump(j, sys.stdout, indent=2, sort_keys=True) diff --git a/minitests/roi_harness/runme.sh b/minitests/roi_harness/runme.sh index 3435f15f..e72162d8 100755 --- a/minitests/roi_harness/runme.sh +++ b/minitests/roi_harness/runme.sh @@ -63,7 +63,11 @@ ${XRAY_BITREAD} -F $XRAY_ROI_FRAMES -o design.bits -z -y design.bit ${XRAY_SEGPRINT} -zd design.bits >design.segp python3 ${XRAY_DIR}/utils/bit2fasm.py --verbose design.bit > design.fasm python3 ${XRAY_DIR}/utils/fasm2frames.py design.fasm design.frm -python3 ../create_design_json.py --design_info_txt design_info.txt --design_txt design.txt --pad_wires design_pad_wires.txt > design.json +python3 ../create_design_json.py \ + --design_info_txt design_info.txt \ + --design_txt design.txt \ + --pad_wires design_pad_wires.txt \ + --design_fasm design.fasm > design.json # Hack to get around weird clock error related to clk net not found # Remove following lines: diff --git a/settings/artix7.sh b/settings/artix7.sh index b6d90a2f..a20f9fec 100644 --- a/settings/artix7.sh +++ b/settings/artix7.sh @@ -9,7 +9,7 @@ export XRAY_ROI_TILEGRID="SLICE_X0Y0:SLICE_X65Y99 SLICE_X0Y100:SLICE_X57Y149 RAM # These settings must remain in sync export XRAY_ROI="SLICE_X0Y100:SLICE_X35Y149 RAMB18_X0Y40:RAMB18_X0Y59 RAMB36_X0Y20:RAMB36_X0Y29 DSP48_X0Y40:DSP48_X0Y59 IOB_X0Y100:IOB_X0Y149" # Most of CMT X0Y2. -export XRAY_ROI_GRID_X1="0" +export XRAY_ROI_GRID_X1="10" export XRAY_ROI_GRID_X2="58" # Include VBRK / VTERM export XRAY_ROI_GRID_Y1="0" From 8387eb8c32a339dd4df6a893e18e60b40a8e5fba Mon Sep 17 00:00:00 2001 From: Keith Rothman <537074+litghost@users.noreply.github.com> Date: Tue, 12 Feb 2019 17:37:30 -0800 Subject: [PATCH 2/3] Update FASM tools to use new required_features. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com> --- minitests/roi_harness/create_design_json.py | 7 ++- prjxray/fasm_assembler.py | 67 +++++++++++++-------- utils/fasm2frames.py | 32 ++++++++-- 3 files changed, 73 insertions(+), 33 deletions(-) diff --git a/minitests/roi_harness/create_design_json.py b/minitests/roi_harness/create_design_json.py index 09553d93..861b1a78 100644 --- a/minitests/roi_harness/create_design_json.py +++ b/minitests/roi_harness/create_design_json.py @@ -53,7 +53,6 @@ def main(): y2=j['info']['GRID_Y_MAX'], ) - with open(args.pad_wires) as f: for l in f: parts = l.strip().split(' ') @@ -89,7 +88,8 @@ def main(): unknown_base_address = int(annotation.value, 0) - assert unknown_base_address not in frames_in_use, "Found unknown bit in base address 0x{:08x}".format(unknown_base_address) + assert unknown_base_address not in frames_in_use, "Found unknown bit in base address 0x{:08x}".format( + unknown_base_address) if not fasm_line.set_feature: continue @@ -109,7 +109,8 @@ def main(): if not_in_roi and base_address_in_roi: required_features.append(fasm_line) - j['required_features'] = fasm.fasm_tuple_to_string(required_features, canonical=True) + j['required_features'] = fasm.fasm_tuple_to_string( + required_features, canonical=True) json.dump(j, sys.stdout, indent=2, sort_keys=True) diff --git a/prjxray/fasm_assembler.py b/prjxray/fasm_assembler.py index c756212f..8c04c006 100644 --- a/prjxray/fasm_assembler.py +++ b/prjxray/fasm_assembler.py @@ -1,6 +1,5 @@ import fasm from prjxray import bitstream -from prjxray import grid class FasmLookupError(Exception): @@ -142,34 +141,50 @@ class FasmAssembler(object): bits.base_address + bits.frames): self.frames_in_use.add(frame) - def parse_fasm_filename(self, filename): + def add_fasm_line(self, line, missing_features): + if not line.set_feature: + return + + line_strs = tuple(fasm.fasm_line_to_string(line)) + assert len(line_strs) == 1 + line_str = line_strs[0] + + parts = line.set_feature.feature.split('.') + tile = parts[0] + feature = '.'.join(parts[1:]) + + # canonical_features flattens multibit feature enables to only + # single bit features, which is what enable_feature expects. + # + # canonical_features also filters out features that are not enabled, + # which are no-ops. + for flat_set_feature in fasm.canonical_features(line.set_feature): + address = 0 + if flat_set_feature.start is not None: + address = flat_set_feature.start + + try: + self.enable_feature(tile, feature, address, line_str) + except FasmLookupError as e: + missing_features.append(str(e)) + + def parse_fasm_filename(self, filename, extra_features=[]): missing_features = [] for line in fasm.parse_fasm_filename(filename): - if not line.set_feature: - continue + self.add_fasm_line(line, missing_features) - line_strs = tuple(fasm.fasm_line_to_string(line)) - assert len(line_strs) == 1 - line_str = line_strs[0] - - parts = line.set_feature.feature.split('.') - tile = parts[0] - feature = '.'.join(parts[1:]) - - # canonical_features flattens multibit feature enables to only - # single bit features, which is what enable_feature expects. - # - # canonical_features also filters out features that are not enabled, - # which are no-ops. - for flat_set_feature in fasm.canonical_features(line.set_feature): - address = 0 - if flat_set_feature.start is not None: - address = flat_set_feature.start - - try: - self.enable_feature(tile, feature, address, line_str) - except FasmLookupError as e: - missing_features.append(str(e)) + for line in extra_features: + self.add_fasm_line(line, missing_features) if missing_features: raise FasmLookupError('\n'.join(missing_features)) + + def mark_roi_frames(self, roi): + for tile in roi.gen_tiles(): + gridinfo = self.grid.gridinfo_at_tilename(tile) + + for block_type in gridinfo.bits: + bits = gridinfo.bits[block_type] + for frame in range(bits.base_address, + bits.base_address + bits.frames): + self.frames_in_use.add(frame) diff --git a/utils/fasm2frames.py b/utils/fasm2frames.py index 1faf86b3..09db914f 100755 --- a/utils/fasm2frames.py +++ b/utils/fasm2frames.py @@ -2,12 +2,15 @@ from __future__ import print_function +import fasm import argparse +import json import os import os.path from prjxray import fasm_assembler -from prjxray import db +from prjxray.db import Database +from prjxray.roi import Roi class FASMSyntaxError(SyntaxError): @@ -51,9 +54,26 @@ def dump_frm(f, frames): '0x%08X ' % addr + ','.join(['0x%08X' % w for w in words]) + '\n') -def run(db_root, filename_in, f_out, sparse=False, debug=False): - assembler = fasm_assembler.FasmAssembler(db.Database(db_root)) - assembler.parse_fasm_filename(filename_in) +def run(db_root, filename_in, f_out, sparse=False, roi=None, debug=False): + db = Database(db_root) + assembler = fasm_assembler.FasmAssembler(db) + + if roi: + with open(roi) as f: + roi_j = json.load(f) + x1 = roi_j['info']['GRID_X_MIN'] + x2 = roi_j['info']['GRID_X_MAX'] + y1 = roi_j['info']['GRID_Y_MIN'] + y2 = roi_j['info']['GRID_Y_MAX'] + + assembler.mark_roi_frames(Roi(db=db, x1=x1, x2=x2, y1=y1, y2=y2)) + + if 'required_features' in roi_j: + extra_features = fasm.parse_fasm_string(roi_j['required_features']) + else: + extra_features = [] + + assembler.parse_fasm_filename(filename_in, extra_features=extra_features) frames = assembler.get_frames(sparse=sparse) if debug: @@ -80,6 +100,9 @@ def main(): parser.add_argument('--db-root', help="Database root.", **db_root_kwargs) parser.add_argument( '--sparse', action='store_true', help="Don't zero fill all frames") + parser.add_argument( + '--roi', + help="ROI design.json file defining which tiles are within the ROI.") parser.add_argument( '--debug', action='store_true', help="Print debug dump") parser.add_argument('fn_in', help='Input FPGA assembly (.fasm) file') @@ -95,6 +118,7 @@ def main(): filename_in=args.fn_in, f_out=open(args.fn_out, 'w'), sparse=args.sparse, + roi=args.roi, debug=args.debug) From b1c822cb982f903bcc8a02f7f0bb7a07308ca6cf Mon Sep 17 00:00:00 2001 From: Keith Rothman <537074+litghost@users.noreply.github.com> Date: Thu, 14 Feb 2019 08:27:43 -0800 Subject: [PATCH 3/3] Fix review comments. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com> --- minitests/roi_harness/create_design_json.py | 24 ++++++++++----------- minitests/roi_harness/runme.sh | 1 - utils/fasm2frames.py | 7 +++--- utils/segprint.py | 2 +- 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/minitests/roi_harness/create_design_json.py b/minitests/roi_harness/create_design_json.py index 861b1a78..86b9b919 100644 --- a/minitests/roi_harness/create_design_json.py +++ b/minitests/roi_harness/create_design_json.py @@ -29,28 +29,28 @@ def main(): args = parser.parse_args() - j = {} - j['ports'] = [] - j['info'] = {} + design_json = {} + design_json['ports'] = [] + design_json['info'] = {} with open(args.design_txt) as f: for d in csv.DictReader(f, delimiter=' '): - j['ports'].append(d) + design_json['ports'].append(d) with open(args.design_info_txt) as f: for l in f: name, value = l.strip().split(' = ') - j['info'][name] = int(value) + design_json['info'][name] = int(value) db = Database(get_db_root()) grid = db.grid() roi = Roi( db=db, - x1=j['info']['GRID_X_MIN'], - y1=j['info']['GRID_Y_MIN'], - x2=j['info']['GRID_X_MAX'], - y2=j['info']['GRID_Y_MAX'], + x1=design_json['info']['GRID_X_MIN'], + y1=design_json['info']['GRID_Y_MIN'], + x2=design_json['info']['GRID_X_MAX'], + y2=design_json['info']['GRID_Y_MAX'], ) with open(args.pad_wires) as f: @@ -70,7 +70,7 @@ def main(): if not roi.tile_in_roi(loc): wires_outside_roi.append(wire) - set_port_wires(j['ports'], name, pin, wires_outside_roi) + set_port_wires(design_json['ports'], name, pin, wires_outside_roi) frames_in_use = set() for tile in roi.gen_tiles(): @@ -109,10 +109,10 @@ def main(): if not_in_roi and base_address_in_roi: required_features.append(fasm_line) - j['required_features'] = fasm.fasm_tuple_to_string( + design_json['required_features'] = fasm.fasm_tuple_to_string( required_features, canonical=True) - json.dump(j, sys.stdout, indent=2, sort_keys=True) + json.dump(design_json, sys.stdout, indent=2, sort_keys=True) if __name__ == '__main__': diff --git a/minitests/roi_harness/runme.sh b/minitests/roi_harness/runme.sh index e72162d8..2e2e96ff 100755 --- a/minitests/roi_harness/runme.sh +++ b/minitests/roi_harness/runme.sh @@ -60,7 +60,6 @@ ${XRAY_VIVADO} -mode batch -source ../runme.tcl test -z "$(fgrep CRITICAL vivado.log)" ${XRAY_BITREAD} -F $XRAY_ROI_FRAMES -o design.bits -z -y design.bit -${XRAY_SEGPRINT} -zd design.bits >design.segp python3 ${XRAY_DIR}/utils/bit2fasm.py --verbose design.bit > design.fasm python3 ${XRAY_DIR}/utils/fasm2frames.py design.fasm design.frm python3 ../create_design_json.py \ diff --git a/utils/fasm2frames.py b/utils/fasm2frames.py index 09db914f..a30da868 100755 --- a/utils/fasm2frames.py +++ b/utils/fasm2frames.py @@ -58,6 +58,7 @@ def run(db_root, filename_in, f_out, sparse=False, roi=None, debug=False): db = Database(db_root) assembler = fasm_assembler.FasmAssembler(db) + extra_features = [] if roi: with open(roi) as f: roi_j = json.load(f) @@ -68,10 +69,8 @@ def run(db_root, filename_in, f_out, sparse=False, roi=None, debug=False): assembler.mark_roi_frames(Roi(db=db, x1=x1, x2=x2, y1=y1, y2=y2)) - if 'required_features' in roi_j: - extra_features = fasm.parse_fasm_string(roi_j['required_features']) - else: - extra_features = [] + if 'required_features' in roi_j: + extra_features = fasm.parse_fasm_string(roi_j['required_features']) assembler.parse_fasm_filename(filename_in, extra_features=extra_features) frames = assembler.get_frames(sparse=sparse) diff --git a/utils/segprint.py b/utils/segprint.py index 05475f7a..af62c181 100755 --- a/utils/segprint.py +++ b/utils/segprint.py @@ -47,7 +47,7 @@ def get_database(db, tile_type, bit_only=False, verbose=False): parts = l.split() name = parts[0] - if parts[1] == 'always' or parts[1] == 'hint': + if parts[1] == 'always' or parts[1] == 'hint' or parts[1] == 'default': if bit_only: return tagbits = []