IP-XACT format

This document is an exploration of the IP-XACT format.

All IP-XACT elements generated for the IR examples are located under examples/ir_examples/[example]/ipxact/antmicro.com/[example] where antmicro.com/[example] represents the vendor/library. They all conform to the 2022 version.

General observations

VLNV

The IP-XACT format enforces the usage of VLNV (vendor, library, name, version) for every single design and component.

<ipxact:vendor>antmicro.com</ipxact:vendor>
<ipxact:library>simple</ipxact:library>
<ipxact:name>lfsr_gen</ipxact:name>
<ipxact:version>1.2</ipxact:version>

For now, Topwrap can only reliably handle the name value, while vendor and version are not used anywhere and their concept is unrecognised in the codebase. Arguably, library could be represented by the name of a user repository.

Special consideration needs to be taken for these values, as the XML schema defines specific allowed characters for some fields, while Topwrap doesn’t sanity-check any fields that accept custom names.

Warning

Later in this document this group of four tags will be represented by <VLNV... /> to avoid repetition.

Multiple versions

There are many versions of the IP-XACT schema, as visible here, on the official page of Accellera - developers of the format.

Version before 2014 and after 2014 use two different XML namespaces for the tags, respectively: spirit: and ipxact:.

Vivado seemingly only supports the 2009(!) specification version.

This means the discrepancies between different versions and incompatibilities between tools must be taken into account.

There are official XSLT templates (bottom of the page) available that can convert any IP-XACT .xml file one version up, using an xslt tool like xsltproc.

Design structure

The IP-XACT format revolves mainly around “components”. This is something that is closest to our IPCoreDescription class and its respective YAML schema:

<?xml version="1.0" encoding="UTF-8"?>
<ipxact:component>
    <VLNV... />
	<ipxact:model>
		<ipxact:instantiations>
			<ipxact:componentInstantiation>
				<ipxact:moduleParameters>
					...
				</ipxact:moduleParameters>
			</ipxact:componentInstantiation>
		</ipxact:instantiations>
		<ipxact:ports>
            ...
		</ipxact:ports>
	</ipxact:model>
	<ipxact:parameters>
		...
	</ipxact:parameters>
</ipxact:component>

A singular component represents a black-box, with the outside world seeing only its ports, buses and parameters. In order to represent its inner design there needs to be a separate design XML file:

<?xml version="1.0" encoding="UTF-8"?>
<ipxact:design>
	<VLNV...  />
	<ipxact:componentInstances>
        ...
	</ipxact:componentInstances>
	<ipxact:adHocConnections>
		<ipxact:adHocConnection>
			<ipxact:name>gen2_gen_out_to_two_mux_gen2</ipxact:name>
			<ipxact:portReferences>
				<ipxact:internalPortReference componentInstanceRef="ip1" portRef="port1"/>
				<ipxact:internalPortReference componentInstanceRef="ip2" portRef="port1"/>
			</ipxact:portReferences>
		</ipxact:adHocConnection>
		...
	</ipxact:adHocConnections>
</ipxact:design>

which later is attached to the component description under the instantiations section, thus making the design an optional property of a module/component.

To describe a top-level wrapper you need both its description as a component, where the external IO is defined, and its design file that describes what other IPs are incorporated by this wrapper.

Parameter passing

IP-XACT introduces a distinction between parameters of a component, and module parameters of the component’s instantiation.

This allows most IP-XACT objects to accept parameters that are only internal to them and are unrelated to the potentially generated RTL. In order to define RTL module parameters, you need to specify them under two separate sections.

Below is an example of defining a paramWIDTH parameter with default value of 64 in a component that gets realised in Verilog as parameter WIDTH = 64;:

Take note of the top-level <ipxact:parameters> tag and the <ipxact:moduleParameters> tag of the component instantiation.

<ipxact:instantiations>
    <ipxact:componentInstantiation>
        <ipxact:name>rtl</ipxact:name>
        <ipxact:displayName>rtl</ipxact:displayName>
        <ipxact:language>Verilog</ipxact:language>
        <ipxact:moduleParameters>
            <ipxact:moduleParameter>
                <ipxact:name>WIDTH</ipxact:name>
                <ipxact:displayName>WIDTH</ipxact:displayName>
                <ipxact:value>paramWIDTH</ipxact:value>
            </ipxact:moduleParameter>
        </ipxact:moduleParameters>
    </ipxact:componentInstantiation>
</ipxact:instantiations>
<ipxact:parameters>
    <ipxact:parameter parameterId="paramWIDTH" resolve="user" type="longint">
        <ipxact:name>paramWIDTH</ipxact:name>
        <ipxact:displayName>paramWIDTH</ipxact:displayName>
        <ipxact:value>64</ipxact:value>
    </ipxact:parameter>
</ipxact:parameters>

In Topwrap, all IP parameters do get realised in the generated Verilog and there is no notion of internal parameters.

File sets

Each component in IP-XACT can contain an ipxact:fileSets section. This is a very exhaustive section about one or more groups of files that this component depends on. The type and purpose of every such file is marked, e.g: verilogSource.

<ipxact:fileSets>
    <ipxact:fileSet>
        <ipxact:name>fs-rtl</ipxact:name>
        <ipxact:file>
            <ipxact:name>../RTL/transmitter.v</ipxact:name>
            <ipxact:fileType>verilogSource</ipxact:fileType>
            <ipxact:logicalName>transmitter_lib</ipxact:logicalName>
        </ipxact:file>
    </ipxact:fileSet>
</ipxact:fileSets>

This concept currently only exists as a --sources CLI flag for topwrap build where all HDL sources are plainly forwarded to the FuseSoC .core. There is no notion of other file dependencies inside IP Core description YAMLs.

Vendor extensions

The IP-XACT format allows storing completely custom data inside most of the tags using the <ipxact:vendorExtensions> group. Topwrap could use them to store additional data about the IPs or designs.

Example theoretical vendor extensions:

<ipxact:vendorExtensions>
    <topwrap:interconnectType>wishbone</topwrap:interconnectType>
    <topwrap:kpm_position x="600" y="180" />
    <topwrap:repo>builtin</topwrap:repo>
</ipxact:vendorExtensions>

Catalogs

Catalogs describe the location and the VLNV identifier of other IP-XACT elements such as components, designs, buses etc. in order to manage and allow access to collections of IP-XACT files. In most cases defining a catalog is not required as all necessary files are automatically located by the used tool.

<ipxact:catalog>
    <VLNV... />
    <ipxact:components>
        <ipxact:ipxactFile>
            <ipxact:vlnv vendor="antmicro.com" library="simple" name="lfsr" version="1.0" />
            <ipxact:name>./antmicro.com/simple/lfsr/lfsr.1.0.xml</ipxact:name>
        </ipxact:ipxactFile>
    </ipxact:components>
    <ipxact:busDefinitions>
        ...
    </ipxact:busDefinitions>
    ...
</ipxact:catalog>

Simple example

This is the simplest IP-XACT example as it contains only plain IP cores with standalone ports, and parameters.

Instance names

Since Topwrap doesn’t verify any user-defined names, an accidental creation of a 2mux.yaml IP Core named 2mux_compressor instantiated with a 2mux name, was possible in the YAML format. Many environments, IP-XACT included, don’t actually allow users to start custom names with a number. The instance name of 2mux had to be changed to two_mux for this purpose.

Parameters

The special syntax of IP-XACT parameters is mostly explained in the Parameter passing section.

Variable widths

If you look at either ips/2mux.yaml or ips/lfsr_gen.yaml you’ll see that there are ports with widths defined by the parameters inside an arithmetic expression:

# ips/2mux.yaml
out:
    - [out, OUT_WIDTH-1, 0]

This is easily realisable in IP-XACT because just like our port widths, they also accept arbitrary arithmetic expressions that can reference other parameters inside them:

<ipxact:port>
    <ipxact:name>out</ipxact:name>
    <ipxact:wire>
        <ipxact:direction>out</ipxact:direction>
        <ipxact:vectors>
            <ipxact:vector>
                <ipxact:left>paramOUT_WIDTH - 1</ipxact:left>
                <ipxact:right>0</ipxact:right>
            </ipxact:vector>
        </ipxact:vectors>
    </ipxact:wire>
</ipxact:port>

Duality of the design description

The design of the Simple example is defined (from the Topwrap’s perspective) purely in the design.yaml file. This is not so simple in IP-XACT, see Design structure.

Mostly this means that the “external” section of our design YAML lands in its own component/IP file and the connections and module instances in a separate one that is attached to the component file as a “design instantiation”.

The generated top-level component for this example and its design (top.design.1.0.xml) are located inside the top directory in the IP-XACT library.

Additionally a “design configuration” file is generated that contains additional configuration information for the main design file. Not much is specified there for this example though.

So finally the original design.yaml ends up becoming 3 interconnected .xml files in IP-XACT.

Connections

Port connections between IP cores, and IP cores and externals are all specified in the XML design file. There isn’t much special about them, they are represented very similarly to our design description yaml connections:

<ipxact:adHocConnection>
    <ipxact:name>gen2_gen_out_to_two_mux_gen2</ipxact:name>
    <ipxact:portReferences>
        <ipxact:internalPortReference componentInstanceRef="gen2" portRef="gen_out"/>
        <ipxact:internalPortReference componentInstanceRef="two_mux" portRef="gen2"/>
    </ipxact:portReferences>
</ipxact:adHocConnection>

Interface example

The key thing about this example is that it uses an interface connection (AXI 4 Stream) between two IPs, an inout port, a constant value supplied to a port and Port slicing.

Info

An interface is a named, predefined collection of logical signals used to transfer information between different IPs or other building blocks. Common interface types include: Wishbone, AXI, AHB, and more.

Topwrap, like SystemVerilog, refers to this concept as an “interface”.

IP-XACT refers to the same concept as a “bus”.

Bus definitions

Custom interfaces in Topwrap are defined using Interface description files.

Custom interfaces are well recognized and supported in IP-XACT. They are represented by two files, a “bus definition” that defines the existence of the interface/bus itself, its name and configurable parameters; and an “abstraction definition” that defines the logical signals of the interface.

It’s possible to have more than one abstraction definition for a given bus definition.

Often times the necessary definitions for a given interface are already publicly available. For example, the IP-XACT bus definitions of all ARM AMBA interfaces are available here in the 2009 version of IP-XACT. For this document, they were up-converted to the 2022 version with the help of XSLT templates.

Format

If not, a custom definition has to be created. Starting with the bus definition:

<ipxact:busDefinition>
  <VLNV... />
  <ipxact:description>This is the AXI4Stream stream bus definition.</ipxact:description>
  <ipxact:directConnection>true</ipxact:directConnection>
  <ipxact:isAddressable>false</ipxact:isAddressable>
</ipxact:busDefinition>

VLNV entries and description are both present at the start, like in all other IP-XACT definitions. Then there are two configuration bools:

  • <ipxact:directConnection> decides if this bus allows direct connection between a manager/initiator and subordinate/targets. Important for “asymmetric buses such as AHB”.

  • <ipxact:isAddressable> decides if this bus is addressable using the address space of the manager side of the bus. e.g. true for AXI4, false for AXI4Stream.

Then to specify the logical signals of the interface, an abstraction definition has to be created:

<ipxact:abstractionDefinition>
	<VLNV... />
	<ipxact:description>This is an RTL Abstraction of the AMBA4/AXI4Stream</ipxact:description>
	<ipxact:busType vendor="amba.com" library="AMBA4" name="AXI4Stream" version="r0p0_1"/>
	<ipxact:ports>
		<ipxact:port>
			<ipxact:logicalName>TREADY</ipxact:logicalName>
			<ipxact:description>indicates that the Receiver can accept a transfer in the current cycle.</ipxact:description>
			<ipxact:wire>
				<ipxact:onInitiator>
					<ipxact:presence>optional</ipxact:presence>
					<ipxact:width>1</ipxact:width>
					<ipxact:direction>in</ipxact:direction>
				</ipxact:onInitiator>
				<ipxact:onTarget>
					<ipxact:presence>optional</ipxact:presence>
					<ipxact:width>1</ipxact:width>
					<ipxact:direction>out</ipxact:direction>
				</ipxact:onTarget>
				<ipxact:defaultValue>1</ipxact:defaultValue>
			</ipxact:wire>
		</ipxact:port>
    </ipxact:ports>
</ipxact:abstractionDefinition>

This is a fragment of the TREADY signal definition of the AXI 4 Stream interface.

There’s the classic VLNV + Description combo at the start, then the associated bus definition is referenced and lastly the signals of the interface are defined.

In IP-XACT, unlike in Topwrap, you can specify different options for signals on both the manager and the subordinate separately, importantly a signal can be required on one side of the bus while being optional on the other. This is currently impossible to represent in Topwrap. The width specification and the default value are not supported either by Topwrap.

Moreover, unlike in Topwrap, in IP-XACT the clock and reset signals are also specified in the definition alongside other signals. They are however marked with special qualifiers that distinguish their roles and enforce certain behaviours.

Example qualifiers:

<ipxact:wire>
    <ipxact:qualifier>
        <ipxact:isClock>true</ipxact:isClock>
        <ipxact:isReset>true</ipxact:isReset>
    </ipxact:qualifier>
</ipxact:wire>

Info

While Topwrap uses the manager and subordinate terms to refer to the roles an IP can assume in the bus connection, IP-XACT pre-2022 uses master, slave and IP-XACT 2022-onwards uses initiator and target respectively.

Interface deduction

Topwrap supports specifying both a regex for each signal and the port prefix for the entire interface in order to automatically group raw ports from HDL sources into interfaces. None of that is possible to represent in IP-XACT, though this information can be stored anyways using Vendor extensions.

Bus instantiation

To use the bus inside a component definition you have to:

  • Add all the physical ports that will get used as the bus signals just like regular ad-hoc ports

  • Map these physical ports to logical ports of the interface

The portMap format

interfaces:
    io:
        type: AXI4Stream
        mode: subordinate
        signals:
            in:
                TDATA: [dat_i, 31, 0]

This fragment of Design description would translate to the below IP-XACT description, assuming the dat_i signal was previously defined in the ad-hoc ports section.

<ipxact:busInterfaces>
    <ipxact:busInterface>
        <ipxact:name>io</ipxact:name>
        <ipxact:busType vendor="amba.com" library="AMBA4" name="AXI4Stream" version="r0p0_1"/>
        <ipxact:abstractionTypes>
            <ipxact:abstractionType>
                <ipxact:abstractionRef vendor="amba.com" library="AMBA4" name="AXI4Stream_rtl" version="r0p0_1"/>
                <ipxact:portMaps>
                    <ipxact:portMap>
                        <ipxact:logicalPort>
                            <ipxact:name>TDATA</ipxact:name>
                        </ipxact:logicalPort>
                        <ipxact:physicalPort>
                            <ipxact:name>dat_i</ipxact:name>
                        </ipxact:physicalPort>
                    </ipxact:portMap>
                </ipxact:portMaps>
            </ipxact:abstractionType>
        <ipxact:abstractionTypes>
        <ipxact:target/>
    </ipxact:busInterface>
</ipxact:busInterfaces>

The <ipxact:busInterfaces> tag is a direct child of the top-level <ipxact:component> tag.

Port slicing is supported as well:

<ipxact:physicalPort>
    <ipxact:name>ctrl_i</ipxact:name>
    <ipxact:partSelect>
        <ipxact:range>
            <ipxact:left>4</ipxact:left>
            <ipxact:right>4</ipxact:right>
        </ipxact:range>
    </ipxact:partSelect>
</ipxact:physicalPort>

Inout ports

This example contains an external inout port raised from one of the IPs. While the Topwrap syntax for specifying inout ports in a design is a bit awkward, in IP-XACT inout ports are represented just like ports with other directions.

Constant assignments

This example also features a constant value (2888) assigned to the noise port of the receiver IP instead of any wire. In IP-XACT this is done similarly to Connections:

<ipxact:adHocConnection>
    <ipxact:name>receiver_0_noise_to_tiedValue</ipxact:name>
    <ipxact:tiedValue>2888</ipxact:tiedValue>
    <ipxact:portReferences>
        <ipxact:internalPortReference componentInstanceRef="receiver_0" portRef="noise"/>
    </ipxact:portReferences>
</ipxact:adHocConnection>

Additionally, the tiedValue can be given by an arithmetic expression that resolves to a constant value.

Hierarchical example

The hierarchical example features deeply nested hierarchies. The purpose of a hierarchical design is to group together into separate levels/modules, connections that could just as well be realised flatly in the top-level.

In Topwrap, all hierarchies are specified in the respective design description file YAML using a special syntax that allows multiple design descriptions to be nested together in a single file.

IP-XACT has no notion of any special syntax for hierarchies, because it doesn’t need to. Due to the architecture of design XMLs being extensions to component XMLs, it’s possible to just generate a component+design pair for every hierarchy and connect them just as if they were regular IPs that happen to have a design available alongside them. This is exactly what was done to represent this example.

Interconnect example

This example features the Interconnect generation functionality of Topwrap.

Specifying interconnects in the Topwrap design description implies dynamic generation of necessary arbiters and bus components during build-time using parameters defined under the interconnect instance key.

IP-XACT doesn’t support such functionality because it’s just a file format and it doesn’t necessarily have any dynamic code associated with it.

Conversion from Topwrap -> IP-XACT should probably just generate the interconnect bus component with the required amount of manager and subordinate ports and package it alongside the generated RTL implementation of routers and arbiters.

Reverse conversion (from the concrete generated IP-XACT interconnect to Topwrap’s interconnect entry) is probably impossible, we can’t know the interconnect specifics to know which type to pick after it’s already generated. However, all this necessary information could be stored in a vendor extension.

The interconnect component

The generated interconnect is located in ./antmicro.com/interconnect/interconnect/wishbone_interconnect1.xml. As mentioned, it has just enough interface ports to connect the two specified managers and two subordinates.

The Wishbone interface definition from opencores.org was used.

The main difference that differentiates the interconnect component from raw interface connections like in the Interface example is the explicit definition and mapping of the address space with the <ipxact:addressSpaces> tag and assignment of each manager port to one or more subordinates.

The extensions used in the bus instance element in the component definition. Focus on the ipxact:addressSpaceRef tag where the base address of this subordinate is specified:

<ipxact:busInterface>
    <ipxact:name>target_1</ipxact:name>
    <ipxact:busType vendor="opencores.org" library="interface" name="wishbone" version="b4"/>
    <ipxact:abstractionTypes>
        ...
    </ipxact:abstractionTypes>
    <ipxact:initiator>
        <ipxact:addressSpaceRef addressSpaceRef="address">
            <ipxact:baseAddress>'h10000</ipxact:baseAddress>
        </ipxact:addressSpaceRef>
    </ipxact:initiator>
</ipxact:busInterface>

The extension used at the top-level in the component definition to map the address space:

<ipxact:addressSpaces>
    <ipxact:addressSpace>
        <ipxact:name>address</ipxact:name>
        <ipxact:range>2**32/8-1</ipxact:range>
        <ipxact:width>8</ipxact:width>
        <ipxact:segments>
            <ipxact:segment>
                <ipxact:name>mem</ipxact:name>
                <ipxact:addressOffset>'h0</ipxact:addressOffset>
                <ipxact:range>'hFFFF+1</ipxact:range>
            </ipxact:segment>
            <ipxact:segment>
                <ipxact:name>dsp</ipxact:name>
                <ipxact:addressOffset>'h10000</ipxact:addressOffset>
                <ipxact:range>'hFF+1</ipxact:range>
            </ipxact:segment>
        </ipxact:segments>
        <ipxact:addressUnitBits>8</ipxact:addressUnitBits>
    </ipxact:addressSpace>
</ipxact:addressSpaces>

The assignment of a manager port to specified subordinates(targets):

<ipxact:busInterface>
    <ipxact:name>manager0</ipxact:name>
    <ipxact:busType vendor="opencores.org" library="interface" name="wishbone" version="b4"/>

    <ipxact:target>
        <ipxact:transparentBridge initiatorRef="target_0"/>
        <ipxact:transparentBridge initiatorRef="target_1"/>
    </ipxact:target>
</ipxact:busInterface>

External interface

In the Topwrap definition of this example, a wishbone_passthrough IP core is used in order to allow the external interface to be connected as a manager to the interconnect. This is due to limitations of the schema and the fact that under the managers key Topwrap expects the IP instance name with the specified manager port, completely disregarding the possibility of it being external.

Other features

Dynamic number of ports/interfaces based on a parameter

This is not possible in IP-XACT. All ports/interfaces and connections need to be explicitly defined. While the amount of bits in a port can vary based on a parameter value, as was presented in Variable widths, higher level concepts such as the number of ports cannot.

Conclusion

In most aspects IP-XACT is a superset of what’s possible to describe in Topwrap, making the Topwrap -> IP-XACT conversion pretty trivial.

Syntax impossible to represent natively in IP-XACT such as:

  • Abstract interconnects without concrete implementation

  • Interface signal name regexes and port prefixes (see Interface deduction)

can even if not implemented, be at least preserved using Vendor extensions.

Other visible issue for this conversion are:

  • VLNV being mandatory for IP-XACT files, but Topwrap containing only the name information

  • Lack of input sanitization of string fields on Topwrap’s side

On the other hand, the conversion from a generic IP-XACT file to Topwrap’s internal representation may prove more tricky and definitely suffer from information loss as the IP-XACT format is packed with more features and elements that are not exactly useful for our purposes and were not even mentioned in this document at all.


Last update: 2024-12-31