mirror of https://github.com/openXC7/prjxray.git
Merge pull request #857 from antmicro/fuzzer_007_ff_sr_to_q
Fixed fuzzer 007 to make it extract missing timings for FFs
This commit is contained in:
commit
0f37f0c294
|
|
@ -6,8 +6,16 @@ clean:
|
|||
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 --propertiesmap=properties_map.json --belpins=build/bel_pins.txt --sitepins=build/tile_pins.txt --debug true
|
||||
build/fixup_timings: build/bel_timings.txt
|
||||
python3 fixup_timings_txt.py --txtin build/bel_timings.txt --txtout build/bel_timings.txt --site RAMBFIFO36E1 --slice BRAM_L --type timings
|
||||
python3 fixup_timings_txt.py --txtin build/bel_timings.txt --txtout build/bel_timings.txt --site RAMBFIFO36E1 --slice BRAM_R --type timings
|
||||
python3 fixup_timings_txt.py --txtin build/bel_pins.txt --txtout build/bel_pins.txt --site RAMBFIFO36E1 --slice BRAM_L --type pins
|
||||
python3 fixup_timings_txt.py --txtin build/bel_pins.txt --txtout build/bel_pins.txt --site RAMBFIFO36E1 --slice BRAM_R --type pins
|
||||
python3 fixup_timings_txt.py --txtin build/bel_properties.txt --txtout build/bel_properties.txt --site RAMBFIFO36E1 --slice BRAM_L --type properties
|
||||
python3 fixup_timings_txt.py --txtin build/bel_properties.txt --txtout build/bel_properties.txt --site RAMBFIFO36E1 --slice BRAM_R --type properties
|
||||
|
||||
build/bel_timings.json: build/fixup_timings
|
||||
python3 tim2json.py --timings=build/bel_timings.txt --json=build/bel_timings.json --properties=build/bel_properties.txt --propertiesmap=properties_map.json --pinaliasmap=pin_alias_map.json --belpins=build/bel_pins.txt --sitepins=build/tile_pins.txt --debug true
|
||||
|
||||
build/sdf: build/bel_timings.json
|
||||
python3 ${XRAY_UTILS_DIR}/makesdf.py --json=${PWD}/build/bel_timings.json --sdf=${PWD}/build
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
# BEL timings fuzzer
|
||||
|
||||
This fuzzer is suppose to extract all the BEL timings for Xilinx 7-series FPGAs.
|
||||
The extracted timings are saved as SDF files.
|
||||
Single SDF file is produced for every FPGA tile type.
|
||||
|
||||
## Fuzzer flow
|
||||
|
||||
Fuzzer flow is the following:
|
||||
|
||||
Vivado/`runme.tcl` -> `fixup_timings_txt.py` -> `tim2json.py` -> `makesdf.py` -> `sdfmerge.py`
|
||||
|
||||
The fuzzer uses Vivado tcl script to read all the FPGA timings data.
|
||||
This data is dumped to a text file.
|
||||
Beside timings data the tcl scipt dumps the following information:
|
||||
|
||||
* Sites pins
|
||||
* BELs pins
|
||||
* BELs attributes
|
||||
|
||||
The tcl script iterates over every BEL for all the sites in each tile type.
|
||||
The timings, pins and attributes are dumped in the same hierarchy.
|
||||
This hierarchy is used by the `tim2json` script to process the txt dump.
|
||||
Main task of the `tim2json` script is to figure out what the dumped timings mean and what paths do they describe.
|
||||
This is done by parsing the string timings, searching the BEL/Sites pins and BEL attributes.
|
||||
Since for some pins there was no naming convention, the names are provided directly via `pin_alias_map.json`.
|
||||
|
||||
Some BELs (e.g. BRAMs) reports the timings with incorrect site name.
|
||||
To work around this issue the `fixup_timings_txt.py` script is used to flatten the timings dump file.
|
||||
As a result all the timings for a selected tile are squashed into one site.
|
||||
|
||||
### Text files format
|
||||
|
||||
The files dumped by the Vivado scrips have the following format:
|
||||
|
||||
Each line starts with a tile name, proceeded by a number of sites in the tile.
|
||||
After the tiles count, each tile info is placed.
|
||||
The tile info starts with a tile name followed by number of BELs in the tile.
|
||||
The bels number is followed by BEL entries.
|
||||
Each BEL entry starts with BEL name followed by a number of entries.
|
||||
The entries differ between the file types:
|
||||
|
||||
* timings file: each timing entry starts with entry name followed by 5 timings values
|
||||
* properties file: each properties entry starts with property name followed by a number of possible property values, followed by a list of the possible property values
|
||||
* pins file: each pin entry starts with pin name, followed by pin direction (IN/OUT), followed by 0 or 1 flag saying if the pin is a clock pin
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
|
||||
|
||||
def fix_line(line, site, filetype):
|
||||
"""
|
||||
Squashes the entries for multiple sites into one.
|
||||
This is required when entries are defined for a different
|
||||
site than they are reported.
|
||||
Such situation happend e.g.
|
||||
for BRAM_[LR]. All the entries are defined for RAMBFIFO36E1,
|
||||
while they are reported for RAMB18E1 or FIFO18E1
|
||||
|
||||
Parameters
|
||||
----------
|
||||
line: str
|
||||
raw dump file line
|
||||
site: str
|
||||
site to which all the entries will be squashed
|
||||
filetype: str
|
||||
entries type. One of [timings, pins, properties]
|
||||
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
line with squashed entries
|
||||
"""
|
||||
|
||||
assert filetype in [
|
||||
"timings", "pins", "properties"
|
||||
], "Unsupported filetype"
|
||||
|
||||
line = line.split()
|
||||
newline = list()
|
||||
sites_count = int(line[1])
|
||||
newline.append(line[0])
|
||||
# we'll emit only one site
|
||||
newline.append("1")
|
||||
newline.append(site)
|
||||
newline.append("1")
|
||||
newline.append(site)
|
||||
entries = list()
|
||||
all_entries = 0
|
||||
loc = 2
|
||||
for site in range(0, sites_count):
|
||||
bels_count = int(line[loc + 1])
|
||||
loc += 2
|
||||
for bel in range(0, bels_count):
|
||||
entries_count = int(line[loc + 1])
|
||||
loc += 2
|
||||
all_entries += entries_count
|
||||
for entry in range(0, entries_count):
|
||||
if filetype == 'timings':
|
||||
for delay_word in range(0, 6):
|
||||
entries.append(line[loc])
|
||||
loc += 1
|
||||
elif filetype == 'pins':
|
||||
for pin_word in range(0, 3):
|
||||
entries.append(line[loc])
|
||||
loc += 1
|
||||
elif filetype == 'properties':
|
||||
entries.append(line[loc])
|
||||
loc += 1
|
||||
values_count = int(line[loc])
|
||||
entries.append(line[loc])
|
||||
loc += 1
|
||||
for value in range(0, values_count):
|
||||
entries.append(line[loc])
|
||||
loc += 1
|
||||
newline.append(str(all_entries))
|
||||
newline.extend(entries)
|
||||
return " ".join(newline) + "\n"
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--txtin', type=str, help='Input text file')
|
||||
parser.add_argument('--txtout', type=str, help='Output text file')
|
||||
parser.add_argument(
|
||||
'--site',
|
||||
type=str,
|
||||
help='Site to which the entries should be squashed')
|
||||
parser.add_argument(
|
||||
'--slice', type=str, help='Slice for which the entries shall be fixed')
|
||||
parser.add_argument(
|
||||
'--type', type=str, choices=['timings', 'pins', 'properties'])
|
||||
|
||||
args = parser.parse_args()
|
||||
lines = list()
|
||||
|
||||
with open(args.txtin, 'r') as fp:
|
||||
for line in fp:
|
||||
if line.startswith(args.slice):
|
||||
line = fix_line(line, args.site, args.type)
|
||||
lines.append(line)
|
||||
|
||||
with open(args.txtout, 'w') as fp:
|
||||
for line in lines:
|
||||
fp.write(line)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
{
|
||||
"ff_init": {
|
||||
"Q": {
|
||||
"names" : ["QL", "QH"],
|
||||
"is_property_related" : true
|
||||
}
|
||||
},
|
||||
"reg_init": {
|
||||
"Q": {
|
||||
"names" : ["QL", "QH"],
|
||||
"is_property_related" : true
|
||||
}
|
||||
},
|
||||
"rambfifo36e1" : {
|
||||
"RSTRAMARSTRAMLRST" : {
|
||||
"names" : ["rstramarstl"],
|
||||
"is_property_related" : false
|
||||
},
|
||||
"ADDRARDADDRU0" : {
|
||||
"names" : ["addrau"],
|
||||
"is_property_related" : false
|
||||
},
|
||||
"ADDRARDADDRL15" : {
|
||||
"names" : ["addra15l"],
|
||||
"is_property_related" : false
|
||||
},
|
||||
"RSTRAMARSTRAMU" : {
|
||||
"names" : ["rstramau"],
|
||||
"is_property_related" : false
|
||||
},
|
||||
"ADDRBWRADDRU0" : {
|
||||
"names" : ["addrbu"],
|
||||
"is_property_related" : false
|
||||
},
|
||||
"ADDRBWRADDRL15" : {
|
||||
"names" : ["addrb15l"],
|
||||
"is_property_related" : false
|
||||
},
|
||||
"WEBWEU0" : {
|
||||
"names" : ["webu"],
|
||||
"is_property_related" : false
|
||||
},
|
||||
"DOADO0" : {
|
||||
"names" : ["doadol", "doadou"],
|
||||
"is_property_related" : false
|
||||
},
|
||||
"DOBDO0" : {
|
||||
"names" : ["dobdol", "dobdou"],
|
||||
"is_property_related" : false
|
||||
},
|
||||
"DOPADOP0" : {
|
||||
"names" : ["dopadopl", "dopadopu"],
|
||||
"is_property_related" : false
|
||||
},
|
||||
"DOPBDOP0" : {
|
||||
"names" : ["dopbdopl", "dopbdopu"],
|
||||
"is_property_related" : false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -45,11 +45,120 @@ def clean_bname(bname):
|
|||
return bname
|
||||
|
||||
|
||||
def pin_in_model(pin, model, direction=None):
|
||||
def find_aliased_pin(pin, model, pin_aliases):
|
||||
"""
|
||||
Searches for aliased pins in the timing model.
|
||||
The check is done using data from pin_aliases dictionary.
|
||||
The dictionary has an entry for each aliased pin.
|
||||
Each entry has two fields:
|
||||
|
||||
* names : a list of all the possible aliases
|
||||
* is_property_related: a flag saying if the alias is in fact
|
||||
pin name combined with BEL property (e.g. Q[LH] pins
|
||||
in FF - in this case the pin name is Q [original name],
|
||||
but is named Q[LH] in the timing model. The suffix
|
||||
determines polarity of the FF's set/reset input).
|
||||
|
||||
If is_property_related is set the function returns the original
|
||||
pin name, aliased name is returned otherwise.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
pin: str
|
||||
Pin name to look for
|
||||
model: str
|
||||
Timing model
|
||||
pin_aliases: dict
|
||||
A dict of list of aliases for given bel/site
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool, str
|
||||
|
||||
The first bool value is set to true if pin is found
|
||||
in the timing model, false otherwise.
|
||||
|
||||
The second returned value is found pin name. If pin
|
||||
is not found None is returned
|
||||
|
||||
>>> find_aliased_pin("a", "a_b_some_test_string", None)
|
||||
(False, None)
|
||||
|
||||
>>> find_aliased_pin("d", "din_dout_setup", {"D": {"names" : ["din"], "is_property_related" : False}})
|
||||
(True, 'din')
|
||||
|
||||
>>> find_aliased_pin("d", "din_dout_setup", {"D": {"names" : ["din"], "is_property_related" : True}})
|
||||
(True, 'd')
|
||||
|
||||
>>> find_aliased_pin("d", "din_dout_setup", {"D": {"names" : ["notdin"], "is_property_related" : True}})
|
||||
(False, None)
|
||||
"""
|
||||
if (pin_aliases is not None) and (pin.upper() in pin_aliases):
|
||||
for alias in pin_aliases[pin.upper()]['names']:
|
||||
single_word_alias = (len(alias.split('_')) == 1)
|
||||
pin_alias = alias.lower()
|
||||
if single_word_alias:
|
||||
model_to_check = model.split('_')
|
||||
else:
|
||||
model_to_check = model
|
||||
if pin_alias in model_to_check:
|
||||
if pin_aliases[pin.upper()]['is_property_related']:
|
||||
return True, pin.lower()
|
||||
else:
|
||||
return True, pin_alias
|
||||
|
||||
return False, None
|
||||
|
||||
|
||||
def pin_in_model(pin, pin_aliases, model, direction=None):
|
||||
"""
|
||||
Checks if a given pin belongs to the model.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
pin: str
|
||||
Pin name to look for
|
||||
pin_aliases: dict
|
||||
A dict of list of aliases for given bel/site
|
||||
model: str
|
||||
Timing model name
|
||||
direction: str
|
||||
Optional pin direction suffix [IN|OUT]
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool, str
|
||||
|
||||
The first returned value is set to true if pin is found,
|
||||
false otherwise.
|
||||
|
||||
The second returned value contains found pin name. If the
|
||||
pin is not found, None is returned.
|
||||
|
||||
>>> pin_in_model("d", None, "ff_init_din_q", "in")
|
||||
(True, 'din')
|
||||
|
||||
>>> pin_in_model("q", None, "ff_init_clk_q", None)
|
||||
(True, 'q')
|
||||
|
||||
>>> pin_in_model("q", {"Q": {"names" : ["QL", "QH"], "is_property_related" : True}}, "ff_init_clk_ql", None)
|
||||
(True, 'q')
|
||||
|
||||
>>> pin_in_model("logic_out", None, "my_cell_i_logic_out", None)
|
||||
(True, 'logic_out')
|
||||
|
||||
>>> pin_in_model("logic_out", {"LOGIC_OUT": {"names" : ["LOGIC_O", "O"], "is_property_related" : False}}, "my_cell_i_logic_o", None)
|
||||
(True, 'logic_o')
|
||||
|
||||
>>> pin_in_model("logic_out", {"LOGIC_OUT": {"names" : ["LOGIC_O", "O"], "is_property_related" : False}}, "my_cell_i_o", None)
|
||||
(True, 'o')
|
||||
"""
|
||||
|
||||
# strip site location
|
||||
model = model.split(':')[0]
|
||||
extended_pin_name = pin
|
||||
aliased_pin, aliased_pin_name = find_aliased_pin(
|
||||
pin.upper(), model, pin_aliases)
|
||||
|
||||
# some timings reports pins with their directions
|
||||
# this happens for e.g. CLB reg_init D pin, which
|
||||
|
|
@ -63,26 +172,62 @@ def pin_in_model(pin, model, direction=None):
|
|||
return True, pin
|
||||
elif extended_pin_name in model.split('_'):
|
||||
return True, extended_pin_name
|
||||
elif aliased_pin:
|
||||
return True, aliased_pin_name
|
||||
else:
|
||||
return False, None
|
||||
else:
|
||||
# pin name is multi word, search for a string
|
||||
return (pin in model), pin
|
||||
if pin in model:
|
||||
return True, pin
|
||||
elif aliased_pin:
|
||||
return True, aliased_pin_name
|
||||
else:
|
||||
return False, None
|
||||
|
||||
|
||||
def remove_pin_from_model(pin, model):
|
||||
"""
|
||||
Removes the pin from model name if present.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
|
||||
pin: str
|
||||
Pin name
|
||||
mode: str
|
||||
Timing model name
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
||||
str
|
||||
Updated timing model name
|
||||
|
||||
>>> remove_pin_from_model("q", "ff_init_d_q")
|
||||
'ff_init_d'
|
||||
>>> remove_pin_from_model("q", "ff_init_d_ql")
|
||||
'ff_init_d_ql'
|
||||
>>> remove_pin_from_model("logic_out", "ff_init_d_logic_out")
|
||||
'ff_init_d'
|
||||
>>> remove_pin_from_model("logic_out", "ff_init_d_second_out")
|
||||
'ff_init_d_second_out'
|
||||
"""
|
||||
|
||||
if len(pin.split('_')) == 1:
|
||||
# pin name is one word, search it in the model
|
||||
tmp = model.split('_')
|
||||
tmp.remove(pin)
|
||||
return "_".join(tmp)
|
||||
if pin in tmp:
|
||||
tmp.remove(pin)
|
||||
return "_".join(tmp)
|
||||
else:
|
||||
return model
|
||||
else:
|
||||
# pin name is multi word, search for a string
|
||||
return "_".join(list(filter(None, model.replace(pin, '').split('_'))))
|
||||
|
||||
|
||||
def read_raw_timings(fin, properties, pins, site_pins):
|
||||
def read_raw_timings(fin, properties, pins, site_pins, pin_alias_map):
|
||||
|
||||
timings = dict()
|
||||
with open(fin, "r") as f:
|
||||
|
|
@ -150,15 +295,21 @@ def read_raw_timings(fin, properties, pins, site_pins):
|
|||
if speed_model.startswith(delay_btype):
|
||||
speed_model_clean = speed_model[len(delay_btype):]
|
||||
|
||||
# Get pin alias map
|
||||
pin_aliases = pin_alias_map.get(delay_btype, None)
|
||||
|
||||
# locate pins
|
||||
for pin in pins[slice][site_name][delay_btype_orig]:
|
||||
orig_pin = pin
|
||||
pim, pin = pin_in_model(
|
||||
pin.lower(), speed_model_clean, 'in')
|
||||
pin.lower(), pin_aliases, speed_model_clean,
|
||||
'in')
|
||||
|
||||
if pim:
|
||||
if pins[slice][site_name][delay_btype_orig][
|
||||
orig_pin]['is_clock']:
|
||||
bel_clock = pin
|
||||
bel_clock_orig_pin = orig_pin
|
||||
elif pins[slice][site_name][delay_btype_orig][
|
||||
orig_pin]['direction'] == 'IN':
|
||||
bel_input = pin
|
||||
|
|
@ -168,11 +319,13 @@ 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_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)
|
||||
pin.lower(), pin_aliases,
|
||||
speed_model_clean)
|
||||
if pim:
|
||||
if site_pins[slice][site_name.lower(
|
||||
)][orig_pin]['is_clock']:
|
||||
|
|
@ -181,13 +334,13 @@ 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()]:
|
||||
orig_pin = pin
|
||||
pim, pin = pin_in_model(
|
||||
pin.lower(), speed_model_clean, 'in')
|
||||
pin.lower(), pin_aliases,
|
||||
speed_model_clean, 'in')
|
||||
if pim:
|
||||
if site_pins[slice][site_name.lower(
|
||||
)][orig_pin]['direction'] == 'IN':
|
||||
|
|
@ -199,7 +352,8 @@ def read_raw_timings(fin, properties, pins, site_pins):
|
|||
for pin in site_pins[slice][site_name.lower()]:
|
||||
orig_pin = pin
|
||||
pim, pin = pin_in_model(
|
||||
pin.lower(), speed_model_clean)
|
||||
pin.lower(), pin_aliases,
|
||||
speed_model_clean)
|
||||
if pim:
|
||||
if site_pins[slice][site_name.lower(
|
||||
)][orig_pin]['direction'] == 'OUT':
|
||||
|
|
@ -207,6 +361,15 @@ def read_raw_timings(fin, properties, pins, site_pins):
|
|||
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. This applies only to combinational paths
|
||||
if (sequential is None) and (bel_input is None) and (
|
||||
bel_clock is not None):
|
||||
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
|
||||
|
||||
# check if the input is not a BEL property
|
||||
if bel_input is None:
|
||||
# if there is anything not yet decoded
|
||||
|
|
@ -218,38 +381,38 @@ def read_raw_timings(fin, properties, pins, site_pins):
|
|||
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):
|
||||
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:
|
||||
if (bel_input is None) or (bel_output 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())))]
|
||||
orig_pin_full = pin
|
||||
pim, pin = pin_in_model(
|
||||
orig_pin.lower(), speed_model_clean)
|
||||
orig_pin.lower(), pin_aliases,
|
||||
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(),
|
||||
orig_pin.lower(), pin_aliases,
|
||||
speed_model_clean)
|
||||
|
||||
if pim:
|
||||
bel_input = pin
|
||||
if pins[slice][site_name][delay_btype_orig][orig_pin_full]['direction'] == 'IN' \
|
||||
and bel_input is None:
|
||||
bel_input = pin
|
||||
if pins[slice][site_name][delay_btype_orig][orig_pin_full]['direction'] == 'OUT' \
|
||||
and bel_output is None:
|
||||
bel_output = pin
|
||||
speed_model_clean = remove_pin_from_model(
|
||||
orig_pin.lower(),
|
||||
speed_model_clean)
|
||||
|
|
@ -263,7 +426,8 @@ def read_raw_timings(fin, properties, pins, site_pins):
|
|||
speed_model = delay_btype + speed_model_clean
|
||||
|
||||
if sequential is not None:
|
||||
if bel_output is None and bel_clock is None:
|
||||
if bel_output is None and bel_clock is None or \
|
||||
bel_output is None and bel_clock == bel_input:
|
||||
delay_loc += 6
|
||||
continue
|
||||
else:
|
||||
|
|
@ -439,11 +603,16 @@ def main():
|
|||
'--debug', type=bool, default=False, help='Enable debug json dumps')
|
||||
parser.add_argument(
|
||||
'--propertiesmap', type=str, help='Properties names mappings')
|
||||
parser.add_argument(
|
||||
'--pinaliasmap', type=str, help='Pin name alias mappings')
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.propertiesmap, 'r') as fp:
|
||||
properties_map = json.load(fp)
|
||||
|
||||
with open(args.pinaliasmap, 'r') as fp:
|
||||
pin_alias_map = json.load(fp)
|
||||
|
||||
properties = read_bel_properties(args.properties, properties_map)
|
||||
|
||||
if args.debug:
|
||||
|
|
@ -460,7 +629,8 @@ def main():
|
|||
with open('debug_site_pins.json', 'w') as fp:
|
||||
json.dump(site_pins, fp, indent=4, sort_keys=True)
|
||||
|
||||
timings = read_raw_timings(args.timings, properties, pins, site_pins)
|
||||
timings = read_raw_timings(
|
||||
args.timings, properties, pins, site_pins, pin_alias_map)
|
||||
with open(args.json, 'w') as fp:
|
||||
json.dump(timings, fp, indent=4, sort_keys=True)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue