Validation of design

One of topwrap features is to run validation on user’s design which consists of series of checks for errors user may do while creating a design.

class DataflowValidator(dataflow: Dict[str, Any])

The main class that contains all the validation checks. The purpose of validation is to check for common errors the user may make while creating the design and make sure the design can be saved in topwrap yaml format. These functions are called in two cases:

  1. When there is a call from KPM for dataflow_validate (the user has clicked Validate in GUI)

  2. When a user tries to save the design

check_connection_to_subgraph_metanodes() CheckResult

Check for any connections to exposed subgraph metanode ports.

In this context:

  • Exposed port: A port on a subgraph metanode that represents the interface of the subgraph to the external graph. It is visible and accessible from outside the subgraph.

  • Unexposed port: An internal port on a subgraph metanode that is used for internal connections within the subgraph but is not accessible from the external graph.

These metanodes are meant to represent ports of subgraph nodes. Connections to these metanodes should only occur via the unexposed ports. Any connection to an exposed port is considered an error because such connections cannot be represented in the design.

check_duplicate_metanode_names() CheckResult

Check for duplicate names of external metanodes. The name of metanode is in “External Name” property. In design, these external metanodes are referenced by this name so if there are multiple metanodes with the same name it will not be possible to represent them, hence the error.

check_duplicate_node_names() CheckResult

Check for any duplicate IP instance names in the graph (graph represents a hierarchy level). This check prevents from creating multiple nodes with the same “instanceName” in a given graph, since this is invalid in design. There can be multiple nodes with the same “instanceName” in the whole design (on various hierarchy levels).

check_external_in_to_external_out_connections() CheckResult

Check for connections between two external metanodes. In our design format (YAML), connections to external nodes are always represented as port: external, regardless of whether the external node is an input or output. Therefore, connections directly between two external metanodes cannot be represented within this format and are invalid by design.

check_inouts_connections() CheckResult

Check for connections between ports where one of them has an inout direction. Return a warning if such connections exist because in Amaranth inout ports are automatically propagated to the top-level module. This forces us to make a quirky design decisions that have to work around this fact, such as inverting the way inout ports are connected in YAML description.

check_parameters_values() CheckResult

Check if parameters in IP nodes are valid.

This check ensures users are informed of any errors in parameter definitions. While it is possible to save the design with invalid parameters (e.g. save to YAML), such a design cannot be successfully built into Verilog because integer widths of all parameters must be determined during the build process.

A parameter is considered valid if it meets any of the following conditions:

  • It is an instance of int.

  • It has a correct value format, e.g.: 16'h5A5A.

  • It can be evaluated based on other parameters, e.g.:

    ADDR_WIDTH: 32

    DATA_WIDTH: ADDR_WIDTH/4 (evaluates to 8, which is valid).

check_port_to_multiple_external_metanodes() CheckResult

Check for ports that have connections to multiple external metanodes. Design schema allows only one connection between an IPcore/hierarchy port and an external metanode. The connection between the port and external metanode is a single entry, not a list that’s why we can’t add more connections.

check_unconnected_ports_interfaces() CheckResult

Check for unconnected ports or interfaces. This check helps identify any unconnected elements, warning the user about potential oversights or missed connections.

check_unnamed_external_metanodes_with_multiple_conn() CheckResult

Check for external metanodes that are connected to more than one port and don’t have a user-specified name. This is important to check because it is an undefined behavior when saving a design. Currently, when there is a connection to an unnamed metanode in design this metanode will have the name of the port it’s connected to.

validate_kpm_design() Dict[str, List[str]]

Run checks to validate the user-created design in KPM. Checks are designed to inform the user about errors present in his design that make it impossible to save and display warnings about potential issues in the design.

Each check returns the following class:

class CheckResult(check_name: str, status: MessageType, error_count: int = 0, message: str | None = None)

Return type of each validation check

Parameters:
check_name : str

Name of the check

status : MessageType

Check can be return one of three MessageTypes (OK, ERROR, WARNING)

  • OK - this status is set when check was successful

  • WARNING - check have failed but it is possible to represent the graph in design yaml

  • ERROR - it is not possible to represent graph in design yaml

error_count : int

Number of errors if status is not OK

message : str | None

Message describing errors

Tests for validation checks

Tests for the DataflowValidator class are done using various designs that are valid or have some errors in them with the goal to check everything validation functions can do.

Below are all the graphs that are used for testing.

Duplicate IP names

dataflow_duplicate_ip_names()

Dataflow containing two IP cores with the same instance name. This is considered as not possible to represent in design yaml since we can’t distinguish them.

Invalid parameters’ values

dataflow_invalid_parameters_values()

Dataflow containing an IP core with multiple parameters, but it’s impossible to resolve the INVALID NAME!!!.

Connection between external Metanodes

dataflow_ext_in_to_ext_out_connections()

Dataflow containing Metanode<->Metanode connection.

Ports connected to multiple external Metanodes

dataflow_ports_multiple_external_metanodes()

Dataflow containing a port connected to two External Metanodes.

Duplicate Metanode names

dataflow_duplicate_metanode_names()

Dataflow containing two External Output Metanodes with the same “External Name” value.

Duplicate Metanode connected to interface

dataflow_duplicate_external_input_interfaces()

Dataflow containing two External Input Metanodes with the same name. Here connection is to interface instead of port as in the example above.

Unnamed Metanodes

dataflow_unnamed_metanodes()

Dataflow containing unnamed External Input Metanode with multiple connections to it.

Connection between two inout ports

dataflow_inouts_connections()

Dataflow containing a connection between two inout ports.

Unconnected ports in subgraph node

dataflow_unconn_hierarchy()

Dataflow containing subgraph node with two unconnected interfaces.

Connection of subgraph node to multiple External Metanodes

dataflow_subgraph_multiple_external_metanodes()

Dataflow containing subgraph node with connection to two External Output Metanodes.

Connection to subgraph Metanode

dataflow_conn_subgraph_metanode()

Dataflow containing subgraph metanode with connection to exposed interface. It can be seen by selecting the “Edit Subgraph” on subgraph node.

Complex hierarchy graph

dataflow_complex_hierarchy()

Dataflow containing many edge cases such as duplicate subgraph node names, stressing out the capabilities of saving a design.

Duplicate IP cores in subgraph node

dataflow_hier_duplicate_names()

Dataflow containing subgraph node inside which are duplicate IP’s.


Last update: 2024-12-31