From 788e3e0855c4735baa52288476514084f9f5464c Mon Sep 17 00:00:00 2001 From: Karol Gugala Date: Tue, 14 May 2019 12:25:54 +0200 Subject: [PATCH 1/5] fuzzers: 007: correctly handle input clocks and extended pin names Signed-off-by: Karol Gugala --- fuzzers/007-timing/bel/tim2json.py | 76 +++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 22 deletions(-) diff --git a/fuzzers/007-timing/bel/tim2json.py b/fuzzers/007-timing/bel/tim2json.py index 71c6eef0..0680dea9 100644 --- a/fuzzers/007-timing/bel/tim2json.py +++ b/fuzzers/007-timing/bel/tim2json.py @@ -45,14 +45,29 @@ def clean_bname(bname): return bname -def pin_in_model(pin, model): +def pin_in_model(pin, model, direction=None): + + # strip site location + model = model.split(':')[0] + extended_pin_name = pin + + # some timings reports pins with their directions + # this happens for e.g. CLB reg_init D pin, which + # timing is reported as DIN + if direction is not None: + extended_pin_name = pin + direction if len(pin.split('_')) == 1: # pin name is one word, search it in the model - return pin in model.split('_') + if pin in model.split('_'): + return True, pin + elif extended_pin_name in model.split('_'): + return True, extended_pin_name + else: + return False, None else: # pin name is multi word, search for a string - return pin in model + return (pin in model), pin def remove_pin_from_model(pin, model): @@ -140,50 +155,67 @@ def read_raw_timings(fin, properties, pins, site_pins): # locate pins for pin in pins[slice][site_name][delay_btype_orig]: - if pin_in_model(pin.lower(), speed_model_clean): + orig_pin = pin + pim, pin = pin_in_model( + pin.lower(), speed_model_clean, 'in') + if pim: if pins[slice][site_name][delay_btype_orig][ - pin]['direction'] == 'IN': + orig_pin]['direction'] == 'IN': bel_input = pin if pins[slice][site_name][delay_btype_orig][ - pin]['direction'] == 'OUT': + orig_pin]['direction'] == 'OUT': bel_output = pin if pins[slice][site_name][delay_btype_orig][ - pin]['is_clock']: + orig_pin]['is_clock']: bel_clock = pin speed_model_clean = remove_pin_from_model( pin.lower(), speed_model_clean) # Some speed models describe delays from/to site pins instead of BEL pins + if bel_clock is None: + for pin in site_pins[slice][site_name.lower()]: + orig_pin = pin + pim, pin = pin_in_model( + pin.lower(), speed_model_clean) + if pim: + if site_pins[slice][site_name.lower( + )][orig_pin]['is_clock']: + bel_clock = pin + bel_clock_orig_pin = orig_pin + speed_model_clean = remove_pin_from_model( + pin.lower(), speed_model_clean) + if bel_input is None: # search site inputs for pin in site_pins[slice][site_name.lower()]: - if pin_in_model(pin.lower(), - speed_model_clean): + orig_pin = pin + pim, pin = pin_in_model( + pin.lower(), speed_model_clean, 'in') + if pim: if site_pins[slice][site_name.lower( - )][pin]['direction'] == 'IN': + )][orig_pin]['direction'] == 'IN': bel_input = pin speed_model_clean = remove_pin_from_model( pin.lower(), speed_model_clean) if bel_output is None: for pin in site_pins[slice][site_name.lower()]: - if pin_in_model(pin.lower(), - speed_model_clean): + orig_pin = pin + pim, pin = pin_in_model( + pin.lower(), speed_model_clean) + if pim: if site_pins[slice][site_name.lower( - )][pin]['direction'] == 'OUT': + )][orig_pin]['direction'] == 'OUT': bel_output = pin speed_model_clean = remove_pin_from_model( pin.lower(), speed_model_clean) - if bel_clock is None: - for pin in site_pins[slice][site_name.lower()]: - if pin_in_model(pin.lower(), - speed_model_clean): - if site_pins[slice][site_name.lower( - )][pin]['is_clock']: - bel_clock = pin - speed_model_clean = remove_pin_from_model( - pin.lower(), speed_model_clean) + # if we couldn't find input, check if the clock is the + # only input + if bel_input is None and (bel_clock is not None): + if site_pins[slice][site_name.lower( + )][bel_clock_orig_pin]['direction'] == 'IN': + bel_input = bel_clock # restore speed model name speed_model = delay_btype + speed_model_clean From 757b4bea0cb64c6f57ff5d5c3db8be5e50cb480f Mon Sep 17 00:00:00 2001 From: Karol Gugala Date: Tue, 14 May 2019 12:28:13 +0200 Subject: [PATCH 2/5] utils: makesdf: set timescale to 1ns Signed-off-by: Karol Gugala --- utils/makesdf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/makesdf.py b/utils/makesdf.py index 7659b195..912e37f4 100644 --- a/utils/makesdf.py +++ b/utils/makesdf.py @@ -22,7 +22,7 @@ def produce_sdf(timings, outdir): """ (DELAYFILE (SDFVERSION \"3.0\") - (TIMESCALE 1ps) + (TIMESCALE 1ns) """ for site in sorted(timings[slice]): for bel_type in sorted(timings[slice][site]): From 8d4a94d367ddc51d8eb54edb7bf0c88c5ab6c0e7 Mon Sep 17 00:00:00 2001 From: Karol Gugala Date: Tue, 14 May 2019 12:59:17 +0200 Subject: [PATCH 3/5] sdfmerge: emit only the selected instance of the merged cell Signed-off-by: Karol Gugala --- utils/sdfmerge.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/utils/sdfmerge.py b/utils/sdfmerge.py index 1ad6aa5f..b63cca27 100644 --- a/utils/sdfmerge.py +++ b/utils/sdfmerge.py @@ -19,13 +19,19 @@ def merge(timings_list, site): if site in cell_instance.split(divider): if 'cells' not in merged_timings: merged_timings['cells'] = dict() + if cell not in merged_timings['cells']: + merged_timings['cells'][cell] = dict() + if cell_instance not in merged_timings['cells'][cell]: + merged_timings['cells'][cell][cell_instance] = dict() - if cell in merged_timings['cells']: - assert merged_timings['cells'][cell] == \ - timings['cells'][cell], \ + if cell_instance in merged_timings['cells'][cell][ + cell_instance]: + assert merged_timings['cells'][cell][cell_instance] == \ + timings['cells'][cell][cell_instance], \ "Attempting to merge differing cells" - merged_timings['cells'][cell] = timings['cells'][cell] + merged_timings['cells'][cell][cell_instance] = timings[ + 'cells'][cell][cell_instance] return merged_timings From e1440a56b436f47c9d32680229c4a1dc261c1157 Mon Sep 17 00:00:00 2001 From: Karol Gugala Date: Thu, 16 May 2019 14:52:58 +0200 Subject: [PATCH 4/5] fuzzers: 007: add properties names mappings Signed-off-by: Karol Gugala --- fuzzers/007-timing/bel/Makefile | 2 +- fuzzers/007-timing/bel/properties_map.json | 9 ++++++++ fuzzers/007-timing/bel/tim2json.py | 25 ++++++++++++++++++++-- 3 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 fuzzers/007-timing/bel/properties_map.json diff --git a/fuzzers/007-timing/bel/Makefile b/fuzzers/007-timing/bel/Makefile index 46d32eb8..bf0fa9d8 100644 --- a/fuzzers/007-timing/bel/Makefile +++ b/fuzzers/007-timing/bel/Makefile @@ -7,7 +7,7 @@ build/bel_timings.txt: bash runme.sh build/bel_timings.json: build/bel_timings.txt - python3 tim2json.py --timings=build/bel_timings.txt --json=build/bel_timings.json --properties=build/bel_properties.txt --belpins=build/bel_pins.txt --sitepins=build/tile_pins.txt + python3 tim2json.py --timings=build/bel_timings.txt --json=build/bel_timings.json --properties=build/bel_properties.txt --propertiesmap=properties_map.json --belpins=build/bel_pins.txt --sitepins=build/tile_pins.txt --debug true build/sdf: build/bel_timings.json python ${XRAY_UTILS_DIR}/makesdf.py --json=${PWD}/build/bel_timings.json --sdf=${PWD}/build diff --git a/fuzzers/007-timing/bel/properties_map.json b/fuzzers/007-timing/bel/properties_map.json new file mode 100644 index 00000000..a2de0407 --- /dev/null +++ b/fuzzers/007-timing/bel/properties_map.json @@ -0,0 +1,9 @@ +{ + "ff_init": { + "FFINIT" : "INIT" + }, + "reg_init": { + "FFINIT" : "INIT" + } +} + diff --git a/fuzzers/007-timing/bel/tim2json.py b/fuzzers/007-timing/bel/tim2json.py index 0680dea9..947d2390 100644 --- a/fuzzers/007-timing/bel/tim2json.py +++ b/fuzzers/007-timing/bel/tim2json.py @@ -210,6 +210,17 @@ def read_raw_timings(fin, properties, pins, site_pins): speed_model_clean = remove_pin_from_model( pin.lower(), speed_model_clean) + # check if the input is not a BEL property + if bel_input is None: + # if there is anything not yet decoded + if len(speed_model_clean.split("_")) > 1: + for prop in properties[slice][site_name][ + delay_btype_orig]: + if prop.lower() in speed_model_clean: + bel_input = prop + speed_model_clean = remove_pin_from_model( + prop.lower(), speed_model_clean) + break # if we couldn't find input, check if the clock is the # only input if bel_input is None and (bel_clock is not None): @@ -277,7 +288,7 @@ def read_raw_timings(fin, properties, pins, site_pins): return timings -def read_bel_properties(properties_file): +def read_bel_properties(properties_file, properties_map): properties = dict() with open(properties_file, 'r') as f: @@ -304,6 +315,10 @@ def read_bel_properties(properties_file): # the name always starts with "CONFIG." and ends with ".VALUES" # let's get rid of that prop_name = prop_name[7:-7] + # append name prop name mappings + if bel_name in properties_map: + if prop_name in properties_map[bel_name]: + prop_name = properties_map[bel_name][prop_name] prop_values_count = int(raw_props[prop_loc + 1]) properties[tile][site_name][bel_name][ prop_name] = raw_props[prop_loc + 2:prop_loc + 2 + @@ -387,8 +402,14 @@ def main(): parser.add_argument('--sitepins', type=str, help='Site pins input file') parser.add_argument( '--debug', type=bool, default=False, help='Enable debug json dumps') + parser.add_argument( + '--propertiesmap', type=str, help='Properties names mappings') args = parser.parse_args() - properties = read_bel_properties(args.properties) + + with open(args.propertiesmap, 'r') as fp: + properties_map = json.load(fp) + + properties = read_bel_properties(args.properties, properties_map) if args.debug: with open('debug_prop.json', 'w') as fp: From 683b7562e56d09c96e95c45c1c3165e2ea7652fb Mon Sep 17 00:00:00 2001 From: Karol Gugala Date: Thu, 16 May 2019 19:14:35 +0200 Subject: [PATCH 5/5] fuzzer: 007: bel: handle multiple bit inputs Signed-off-by: Karol Gugala --- fuzzers/007-timing/bel/tim2json.py | 55 ++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/fuzzers/007-timing/bel/tim2json.py b/fuzzers/007-timing/bel/tim2json.py index 947d2390..e9af718f 100644 --- a/fuzzers/007-timing/bel/tim2json.py +++ b/fuzzers/007-timing/bel/tim2json.py @@ -79,9 +79,7 @@ def remove_pin_from_model(pin, model): return "_".join(tmp) else: # pin name is multi word, search for a string - return "_".join( - list(filter(None, - speed_model.replace(pin, '').split('_')))) + return "_".join(list(filter(None, model.replace(pin, '').split('_')))) def read_raw_timings(fin, properties, pins, site_pins): @@ -159,19 +157,18 @@ def read_raw_timings(fin, properties, pins, site_pins): pim, pin = pin_in_model( pin.lower(), speed_model_clean, 'in') if pim: - if pins[slice][site_name][delay_btype_orig][ - orig_pin]['direction'] == 'IN': - bel_input = pin - if pins[slice][site_name][delay_btype_orig][ - orig_pin]['direction'] == 'OUT': - bel_output = pin if pins[slice][site_name][delay_btype_orig][ orig_pin]['is_clock']: bel_clock = pin + elif pins[slice][site_name][delay_btype_orig][ + orig_pin]['direction'] == 'IN': + bel_input = pin + elif pins[slice][site_name][delay_btype_orig][ + orig_pin]['direction'] == 'OUT': + bel_output = pin speed_model_clean = remove_pin_from_model( pin.lower(), speed_model_clean) - # Some speed models describe delays from/to site pins instead of BEL pins if bel_clock is None: for pin in site_pins[slice][site_name.lower()]: orig_pin = pin @@ -185,6 +182,7 @@ def read_raw_timings(fin, properties, pins, site_pins): speed_model_clean = remove_pin_from_model( pin.lower(), speed_model_clean) + # Some speed models describe delays from/to site pins instead of BEL pins if bel_input is None: # search site inputs for pin in site_pins[slice][site_name.lower()]: @@ -224,10 +222,44 @@ def read_raw_timings(fin, properties, pins, site_pins): # if we couldn't find input, check if the clock is the # only input if bel_input is None and (bel_clock is not None): - if site_pins[slice][site_name.lower( + if bel_clock_orig_pin in site_pins[slice][site_name.lower()] and \ + site_pins[slice][site_name.lower( )][bel_clock_orig_pin]['direction'] == 'IN': bel_input = bel_clock + # if we still don't have the input check if the input + # is wider than 1 bit and timing defined for the whole + # port + import re + if bel_input is None: + for pin in pins[slice][site_name][ + delay_btype_orig]: + number = re.search(r'\d+$', pin) + if number is not None: + orig_pin = pin[:-( + len(str(number.group())))] + pim, pin = pin_in_model( + orig_pin.lower(), speed_model_clean) + if not pim: + # some inputs pins are named with unsignificant zeros + # remove ti and try again + orig_pin = orig_pin + str( + int(number.group())) + pim, pin = pin_in_model( + orig_pin.lower(), + speed_model_clean) + + if pim: + bel_input = pin + speed_model_clean = remove_pin_from_model( + orig_pin.lower(), + speed_model_clean) + + # if we still don't have input, give up + if bel_input is None: + delay_loc += 6 + continue + # restore speed model name speed_model = delay_btype + speed_model_clean @@ -255,6 +287,7 @@ def read_raw_timings(fin, properties, pins, site_pins): speed_model_orig]['type'] = btype.upper() timings[slice][bel_location][delay_btype][ speed_model_orig]['input'] = bel_input.upper() + if bel_output is not None: timings[slice][bel_location][delay_btype][ speed_model_orig]['output'] = bel_output.upper(