Skip to content

Commit

Permalink
util: refactor to improve error handling
Browse files Browse the repository at this point in the history
Signed-off-by: Vitor Bandeira <vvbandeira@precisioninno.com>
  • Loading branch information
Vitor Bandeira committed Jul 30, 2024
1 parent e4d13ec commit 02f6dd4
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 86 deletions.
99 changes: 48 additions & 51 deletions flow/util/genRuleFile.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,57 +10,50 @@
import sys
import requests

def get_golden(platform, design, api_base_url):
try:
response = requests.get(api_base_url+f"/golden?platform={platform}&design={design}&variant=base")

# Check if the request was successful (status code 200)
if response.status_code == 200 and "error" not in response.json():
# Parse the JSON response
data = response.json()
def request_db(url):
response = requests.get(url)
if response.json() is None:
print(f"Got 'None' while expecting a JSON from {url}")
return None
# Check if the request was successful (status code 200)
if response.status_code == 200 and "error" not in response.json():
# Parse the JSON response
data = response.json()
return data
else:
print("API request failed", response)
exit(1)

return data, None
else:
print("API request failed")
return None, "API request failed"
except Exception as e:
print(f"An error occurred: {str(e)}")
return None, f"An error occurred: {str(e)}"

def get_metrics(commitSHA, platform, design, api_base_url):
try:
response = requests.get(api_base_url+f"/commit?commitSHA={commitSHA}&platform={platform}&design={design}&variant=base")
def get_golden(platform, design, api_base_url):
url = f"/golden?platform={platform}&design={design}&variant=base"
return request_db(api_base_url+url)

# Check if the request was successful (status code 200)
if response.status_code == 200 and "error" not in response.json():
# Parse the JSON response
data = response.json()

return data, None
else:
print("API request failed")
return None, "API request failed"
except Exception as e:
print(f"An error occurred: {str(e)}")
return None, f"An error occurred: {str(e)}"
def get_metrics(commitSHA, platform, design, api_base_url):
url = f"/commit?commitSHA={commitSHA}&platform={platform}&design={design}&variant=base"
return request_db(api_base_url+url)


def update_rules(designDir, variant, golden_metrics, overwrite):
if overwrite:
gen_rule_file(designDir, # design directory
True, # update
False, # tighten
False, # failing
variant, # variant
golden_metrics # metrics needed for update, default is {} in case of file
)
gen_rule_file(designDir, # design directory
True, # update
False, # tighten
False, # failing
variant, # variant
golden_metrics # metrics needed for update, default is {} in case of file
)
else:
gen_rule_file(designDir, # design directory
False, # update
True, # tighten
False, # failing
variant, # variant
golden_metrics # metrics needed for update, default is {} in case of file
)
gen_rule_file(designDir, # design directory
False, # update
True, # tighten
False, # failing
variant, # variant
golden_metrics # metrics needed for update, default is {} in case of file
)


def gen_rule_file(design_dir, update, tighten, failing, variant, golden_metrics={}):
original_directory = getcwd()
Expand Down Expand Up @@ -211,18 +204,20 @@ def gen_rule_file(design_dir, update, tighten, failing, variant, golden_metrics=

period = float(sub(r'^.*: ', '', period_list[0]))
if len(period_list) != 1:
print(f'[WARNING] Multiple clocks not supported. Will use first clock: {period_list[0]}.')
print(
f'[WARNING] Multiple clocks not supported. Will use first clock: {period_list[0]}.')

format_str = '| {:45} | {:8} | {:8} | {:8} |\n'
change_str = ''
for field, option in rules_dict.items():
if field not in metrics.keys():
print(f"[ERROR] Metric {field} not found in "
f"metrics file: {metrics_file} or golden metrics.")
f"metrics file: {metrics_file} or golden metrics.")
sys.exit(1)

if isinstance(metrics[field], str):
print(f"[WARNING] Skipping string field {field} = {metrics[field]}")
print(
f"[WARNING] Skipping string field {field} = {metrics[field]}")
continue

if len(period_list) != 1 and field == 'globalroute__timing__clock__slack':
Expand Down Expand Up @@ -262,7 +257,7 @@ def gen_rule_file(design_dir, update, tighten, failing, variant, golden_metrics=
rule_value + option['min_max_sum'], option['min_max_sum'])
else:
print(f"[ERROR] Metric {field} has 'min_max' field but no "
"'min_max_direct' or 'min_max_sum' field.")
"'min_max_direct' or 'min_max_sum' field.")
sys.exit(1)

if rule_value is None:
Expand Down Expand Up @@ -304,7 +299,7 @@ def gen_rule_file(design_dir, update, tighten, failing, variant, golden_metrics=
if update and old_rule['value'] != rule_value:
UPDATE = True
change_str += format_str.format(field, old_rule['value'],
rule_value, 'Updating')
rule_value, 'Updating')

if not UPDATE:
rule_value = old_rule['value']
Expand All @@ -319,9 +314,10 @@ def gen_rule_file(design_dir, update, tighten, failing, variant, golden_metrics=
with open(rules_file, 'w') as f:
print('[INFO] writing', abspath(rules_file))
json.dump(rules, f, indent=4)

chdir(original_directory)


if __name__ == "__main__":
parser = argparse.ArgumentParser(
description='Generates or updates rules file for CI.')
Expand Down Expand Up @@ -353,8 +349,9 @@ def gen_rule_file(design_dir, update, tighten, failing, variant, golden_metrics=

if not args.update and not args.tighten and not args.failing:
print('[ERROR] Please select at least one of '
'-u/--update, -t/--tighten, -f/--failing.')
'-u/--update, -t/--tighten, -f/--failing.')
parser.print_help()
sys.exit(1)

gen_rule_file(args.dir, args.update, args.tighten, args.failing, args.variant)

gen_rule_file(args.dir, args.update, args.tighten,
args.failing, args.variant)
84 changes: 49 additions & 35 deletions flow/util/updateRules.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
from datetime import datetime
import json
import argparse
import re
import os
import requests
from genRuleFile import get_golden
from genRuleFile import update_rules
from genRuleFile import get_metrics

# make sure the working dir is flow/
os.chdir(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..'))

# Create the argument parser
parser = argparse.ArgumentParser(description='Process some integers.')

parser.add_argument('--keyFile', type=str, help='Service account credentials key file')
parser.add_argument('--overwrite', action='store_true', default=False, help='Overwrite the golden metrics')
parser.add_argument('--apiURL', type=str, default="http://localhost:80", help='Set API Base URL to get golden metrics')
parser.add_argument('--commitSHA', type=str, default="", help='commit for the metrics used to update the rules')
parser.add_argument('--keyFile',
type=str,
help='Service account credentials key file')
parser.add_argument('--overwrite',
action='store_true',
default=False,
help='Overwrite the golden metrics')
parser.add_argument('--apiURL',
type=str,
default="http://localhost:80",
help='Set API Base URL to get golden metrics')
parser.add_argument('--commitSHA',
type=str,
default="",
help='commit for the metrics used to update the rules')

# Parse the arguments
args = parser.parse_args()
Expand All @@ -29,34 +31,46 @@
with open(args.keyFile) as fp:
cred = credentials.Certificate(json.load(fp))

firebase_admin.initialize_app(cred)
# Initialize Firestore client
db = firestore.client()

api_base_url = args.apiURL
# make sure the working dir is flow/
os.chdir(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..'))

runFilename = f'rules-base.json'
platforms = list()
for root, dirs, files in os.walk('platforms'):
for dir_name in dirs:
if dir_name not in ['common', 'sky130hd_fakestack', 'sky130ram', 'sky130io']:
platforms.append(dir_name)
break

output = ''
for designsDir, dirs, files in sorted(os.walk('designs', topdown=False)):

dirList = designsDir.split(os.sep)
if len(dirList) != 3:
continue

dataFile = os.path.join(designsDir, f'rules-base.json')
if not os.path.exists(dataFile):
continue

platform = dirList[1]
if platform not in platforms:
continue

design = dirList[2]
test = '{} {}'.format(platform, design)
dataFile = os.path.join(designsDir, runFilename)
if os.path.exists(dataFile) and (platform != 'sky130hd_fakestack' or platform != 'src'):
metrics, error_metrics = get_metrics(args.commitSHA, # commit
platform, # platform
design, # design
api_base_url # backend url
)
if error_metrics:
print("failed to update rule for", platform, design)
continue
update_rules(designsDir, # design directory
"base", # variant
metrics, # metrics needed for update, default is {} in case of file
args.overwrite # overwrite flag, default is false
)
metrics = get_metrics(args.commitSHA, # commit
platform, # platform
design, # design
args.apiURL # backend url
)
if metrics is None:
output += f"Failed to update rule for {platform}/{design}\n"
continue

update_rules(designsDir, # design directory
"base", # variant
metrics, # metrics needed for update, default is {} in case of file
args.overwrite # overwrite flag, default is false
)

print()
print(output)

0 comments on commit 02f6dd4

Please sign in to comment.