Deducing interfaces¶
This section describes how inferring interfaces works when using topwrap parse
with --iface-deduce
, --iface
or --use-yosys
options.
The problem can be described as follows: given a set of signals, infer what interfaces are present in this set and assign signals to appropriate interfaces. Interface names and types (AXI4, AXI Stream, Wishbone, etc.) are, in the general case, not given in advance. Algorithm implemented in topwrap works roughly as follows:
Split the given signal set into disjoint subsets of signals based on common prefixes in their names
For a given subset, try to pair each signal name (as it appears in the RTL) with the name of an interface signal (as it is defined in the specification of a particular interface). This pairing is called “a matching”. Matching with signals from all defined interfaces is tried.
For a given subset and matched interface, infer the interface direction (master/slave) based on the direction of some signal in this set.
Compute score for each matching, e.g. if signal names contain
cyc
,stb
andack
(and possibly more) it’s likely that this set is a Wishbone interface. Among all interfaces, interface that has the highest matching score is selected.
Step 1. - splitting ports into subsets¶
First, all ports of a module are grouped into disjoint subsets. Execution of this step differs based on the options supplied to topwrap parse
:
with
--iface
the user supplies topwrap with interface names - ports with names starting with a given interface name will be put in the same subset.with
--use-yosys
grouping is done by parsing the RTL source withyosys
, where ports have attributes in the form of(* interface="interface_name" *)
. Ports with the sameinterface_name
will be put in the same subset.with
--iface-deduce
grouping is done by computing longest common prefixes among all ports. This is done with the help of a trie and only allows prefixes that would split the port name on an underscore (e.g. inunder_score
valid prefixes are an empty string,under
andunder_score
) or a camel-case word boundary (e.g. inwordBoundary
valid prefixes are an empty string,word
andwordBoundary
). As with user-supplied prefixes, ports with names starting with a given prefix will be put in the same subset.
Step 2. - matching ports with interface signal names¶
Given a subset of ports from a previous step, this step tries to match a regexp from an interface definition YAML for a given interface signal to one of the port names and returns a collection of pairs: RTL port + interface port.
For example, when matching against AXI4, a port named axi_a_arvalid
should match to an interface port named ARVALID
in the interface definition YAML.
This operation is performed for all defined interfaces per a given subset of ports so the overall result of this step is a collection of matchings.
For most interfaces these matching will be poor - e.g. axi_a_arvalid
or other AXI4 signals won’t match to most Wishbone interface signals, but an interface that a human would usually assign to a given set of signals will have the most signals matched.
Step 3. - inferring interface direction¶
This step picks a representative RTL signal from a single signal matching from the previous step and checks its direction against direction of the corresponding interface signal in interface definition YAML - if it’s the same then it’s a master interface (since the convention in interface description files is to describe signals from the master’s perspective), otherwise it’s a slave.
Step 4. - computing interface matching score¶
This step computes a score for each matching returned by step 2. This score is based on the number of matched/unmatched optional/required signals in each matching.
Not matching some signals in a given group (from step 1.) is heavily penalized to encourage selecting interface that “fits” a given group best. For example, AXI Lite is a subset of AXI4, so a set of signals that should be assigned AXI4 interface could very well fit the description of AXI Lite, but this mechanism discourages selecting such matching in favor of selecting the other.
Not matching some signals of a given interface (from interface description YAML) is also penalized. Inverting the previous example, a set of signals that should be assigned AXI Lite interface could very well fit the description of AXI4, but because it’s missing a few AXI4 signals so selecting this matching is discouraged in favor of selecting the other.
Good scoring function¶
A well-behaving scoring function should satisfy some properties to ensure that the best “fitting” interface is selected. To describe these we introduce the following terminology:
>
/>=
/==
should be read as “must have a greater/greater or equal/equal score than”.Partial matching means matching where some rtl signals haven’t been matched to interface signals, full matching means matching where all have been matched.
Current implementation when used with default config values satisfies these properties:
full matching with N+1 signals matched (same type) == full matching with N signals matched (same type)
full matching with N signals matched (same type) > partial matching with N signals matched (same type)
partial matching with N+1 signals matched (same type) > partial matching with N signals matched (same type)
full matching with N+1 required, M+1 optional signals >= full matching with N+1 optional, M optional signals >= full matching with N required, M+1 optional signals >= full matching with N required, M optional signals
Properties 2-4 generally ensure that interfaces with more signals matched are favored more over those with less signals matched. Property 1. follows from the current implementation and is not needed in all implementations.
Full details can be found in the implementation itself.