Rule Checking¶
Rule checks are executed as the final stage of the workflow, allowing automated tests to be run against the fully elaborated design to introspect it and check for problems. The checking system is designed to be extensible, with rules being automatically detected and integrated at runtime.
Existing Checks¶
BLADE includes a number of built-in checks, documentation for these can be found separately:
Waiving Rule Violations¶
As BLADE’s rule checks are automated, it may be possible for false-positives to arise - this may occur when rules are particularly strict, and easily broken. Rather than force the developer to weaken the check, BLADE provides a waiver mechanism to say that a particular issue can be ignored - this will downgrade the violation (critical or not) into just a warning.
Paths to waiver files can be provided as a list when calling build_project by using the waivers argument. Every waiver file is combined into a single waiver list which is then used by the checker framework.
A waiver file is nothing more than a list of MD5 hashes which represent particular error conditions, comments can be used to make the file more readable and specify what each hash excludes:
# My Waiver File
# Comments can be used by starting the line with a '#'
36905f88444d24d110bb319d9469fa2a
7a176aa0bf1b1a2574d5214cc1e3cf1b # Comments can also be placed after a hash
The waiver hash is calculated from a number of properties:
The DesignFormat node that the violation was raised from;
The name of the checker that raised the violation;
The exact message included in the violation.
If the node is changed, or the name of the check changes, or the message that the check includes within the violation changes then the waiver will be invalidated and the violation will be raised to an error once again.
Note
Not all properties of the DesignFormat node are included within the hash. Specifically any values stored within the ‘attributes’ dictionary are ignored, this is because absolute paths may appear within the values and these will change between different systems and different users.
Creating New Checks¶
Two types are defined for flagging rule violations:
RuleViolation- is a ‘recoverable’ violation, that is one that doesn’t prevent further checks taking place. For example it might be used to flag that a particular register is not accessible through a parent address map aperture.CriticalRuleViolation- is an ‘unrecoverable’ violation, that is one that prevents further analysis from taking place. For example it might be that the project appears corrupted, and cannot be analysed.
The two types of violation should be used in different ways - RuleViolations should be returned in a list at the end of the check, whilst CriticalRuleViolations should be treated as exceptions and should be raised as soon as they are detected (e.g. raise CriticalRuleViolation(...)).
Both types of violation can carry a message and a node - the node should be set equal to whatever DesignFormat object is the root cause of the violation (if known).
Rules should be stored under blade/checkers as their own Python file. At runtime, the checker framework will import all Python files it discovers under this path and register any functions beginning with check_. The function should take a single argument of the DFProject and return a list of RuleViolations - for example:
def check_unique_names(project: DFProject):
# Create an array to capture violations
violations = []
# Pickup all root nodes
roots = project.getAllPrincipalNodes()
# Raise a critical violation if the project is empty
if len(roots) == 0:
raise CriticalRuleViolation("Project is empty!", node=project)
# Otherwise check that no two names of root nodes are the same
found = []
for obj in roots:
if obj.id.strip().lower() in found:
violations.append(RuleViolation(
f"Duplicate name detected: {obj.id}", node=obj
))
else:
found.append(obj.id.strip().lower())
# Return the list of violations
return violations
API¶
-
blade.checker.perform_checks(project: designformat.project.DFProject, waiver_files: list)¶ Perform a number of checks on the elaborated design
Rules can be defined to check that the design is sane, for example that all registers attached to a block are accessible through the aperture declared in the address map. Rules should not generally raise exceptions, unless a critical error is detected, instead they should capture a RuleViolation which will be logged. For a critical violation where the rest of the check would be invalid, the check should raise a CriticalRuleViolation. This approach allows the project to be saved to disk, but still captures any failures that have occurred.
- Parameters
project – The DesignFormat project
waiver_files – A list of paths to waiver files which can be used to downgrade errors to warnings
- Returns
List of all RuleViolation objects returned by checkers
- Return type
list
-
blade.checker.violation_id(node: designformat.base.DFBase, project: designformat.project.DFProject, checker: str, message: str)¶ Generate an identifier for a rule violation used in waiving errors.
To allow certain rule violations to be waived, the checker generates a unique identifier for each case. A waiver file can then be provided that instructs the tool to lower the error level to just a warning.
- Parameters
node – The node on which the violation has occurred.
project – The top level DFProject containing the node.
checker – Name of the checker raising the error.
message – The violation message being waived.
- Returns
A unique identifier for the rule violation
- Return type
str
-
exception
blade.checkers.common.CriticalRuleViolation(message, node)¶ Custom exception type for reporting critical rule violations - this should be used when a violation is so critical that it aborts the rest of the check
-
class
blade.checkers.common.RuleViolation(message, node)¶ A non-critical rule violation which are collected as a check runs