Source code for fvm.toolchains.questa_pkg.parsers.parse_design_rpt

# Copyright 2024-2026 Universidad de Sevilla
# SPDX-License-Identifier: Apache-2.0

"""Parsers for friendliness score"""
import re
import math

[docs] def get_design_summary(filename): """Extracts the design summary section from a design report file.""" summary = [] found = False with open(filename, "r", encoding="utf-8") as f: # Get all lines between "Design Summary" and # "User-specified Constant Bits" for line in f: if "Design Summary" in line: found = True if found: summary.append(line) if "User-specified Constant Bits" in line: break return summary
[docs] def parse_design_summary(summary): """Parses the design summary section and returns a list of lists with category, statistic, count""" data = [] for line in summary: match = re.match(r'^( {0,2})(.*\S)\s+(\d+)$', line) if match: # Capture leading spaces to determine category level leading_spaces = match.group(1) category = 'Subcategory' if len(leading_spaces) == 2 else 'Top-level' statistic = match.group(2).strip() count = int(match.group(3)) data.append([category, statistic, count]) elif "Storage Structures" in line: # This is a special case because it depends on what is below category = "Top-level" statistic = "Storage Structures" count = 'see below' data.append([category, statistic, count]) return data
[docs] def update_storage_structures(data): """Updates the 'Storage Structures' row with the total number of storage structures found in the design summary.""" # Since the report doesn't include the total number of storage structures, # let's add it total = 0 # Get the total search_terms = ["Counters", "FSMs", "RAMs"] for row in data: for term in search_terms: if term in row[1] : total += row[2] # Update the relevant field for row in data: if "Storage Structures" in row[1]: row[2] = total return data
[docs] def data_from_design_summary(filename): """Extracts and parses the design summary from a design report file.""" summary = get_design_summary(filename) data = parse_design_summary(summary) data = update_storage_structures(data) return data
[docs] def difficulty_score(data): """Computes an overall formal difficulty score according to a weighted operation of the number of elements in the design. Currently the operation is just a sum but it could be an exponential function in the future""" SCORE_WEIGHTS = { 'Clocks' : 500, 'Resets' : 250, 'Control Point Bits' : 4, 'State Bits' : 5, 'Counters' : 40, 'FSMs' : 80, 'RAMs' : 100 } difficulty = 0 for row in data: for term, weight in SCORE_WEIGHTS.items(): if term in row[1]: #print(f'found:{row=}') if row[1] in ['Clocks', 'Resets']: number = row[2] - 1 else: number = row[2] difficulty += number*weight return difficulty
[docs] def difficulty_to_friendliness(difficulty): """Converts difficulty score to a friendliness percentage""" DECAY = 0.00008 # Makes the exponential decay slower percentage = 100 / (math.log(DECAY*difficulty+1) + 1) return percentage
[docs] def friendliness_score(data): """Computes the friendliness score""" return difficulty_to_friendliness(difficulty_score(data))