Merge pull request #1 from antmicro/initial-module-implementation
Initial module implementation
diff --git a/.gitignore/.gitignore b/.gitignore
similarity index 100%
rename from .gitignore/.gitignore
rename to .gitignore
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..d5791ae
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,17 @@
+language: python
+
+matrix:
+ include:
+ - python: 3.5
+ env: TOXENV=py35
+ - python: 3.6
+ env: TOXENV=py36
+ - python: 3.7
+ env: TOXENV=py37
+
+install: pip install tox
+
+script: tox
+
+notifications:
+ email: false
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..db00b77
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,19 @@
+exclude tox.ini
+exclude *.swp
+
+# Include the README
+include *.md
+
+# Include the license file
+include COPYING
+
+include *.txt
+
+recursive-include vtr_xml_utils *.py
+
+# Include the resources files
+recursive-include vtr_xml_utils/resources *.xsl
+recursive-include vtr_xml_utils/resources *.xsd
+
+# Tests
+graft tests
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..ab90481
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1 @@
+lxml
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..8a18954
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,8 @@
+[metadata]
+license_files = COPYING
+
+[bdist_wheel]
+universal=1
+
+[aliases]
+test=pytest
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..da4df12
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,26 @@
+import setuptools
+
+with open("README.md", "r") as fh:
+ long_description = fh.read()
+
+setuptools.setup(
+ name="vtr_xml_utils",
+ version="0.0.1",
+ author="SymbiFlow Authors",
+ author_email="symbiflow@lists.librecores.org",
+ description="A set of Python utilities for working with Verilog to \
+ Routing XML files",
+ long_description=long_description,
+ long_description_content_type="text/markdown",
+ url="https://github.com/SymbiFlow/vtr-xml-utils",
+ packages=setuptools.find_packages(),
+ install_requires=['lxml'],
+ setup_requires=["pytest-runner"],
+ tests_require=["pytest"],
+ include_package_data=True,
+ classifiers=[
+ "Programming Language :: Python :: 3",
+ "License :: OSI Approved :: ISC License",
+ "Operating System :: OS Independent",
+ ],
+)
diff --git a/tests/convert_and_merge_composable_tests/attribute-cleanup.golden.xml b/tests/convert_and_merge_composable_tests/attribute-cleanup.golden.xml
new file mode 100644
index 0000000..4f0a14d
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/attribute-cleanup.golden.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<xml>
+ <tag b="1" c="123" x="abc"/>
+ <tag c="1" d="123" x="abc"/>
+ <tag>
+ <innertag a1="2" a2="2" b1="abc">Hello</innertag>
+ </tag>
+</xml>
diff --git a/tests/convert_and_merge_composable_tests/attribute-cleanup.xml b/tests/convert_and_merge_composable_tests/attribute-cleanup.xml
new file mode 100644
index 0000000..96a33a5
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/attribute-cleanup.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<!-- Clean up attributes
+ * Normalize space around attributes on a tag
+ * Sort the attributes by name
+ * Strip xml:base attribute
+ -->
+<xml>
+ <tag b="1" c="123" x=' abc' />
+ <tag c="1" d=" 123 " x="abc" />
+ <tag>
+ <innertag a2=" 2 " b1="abc " a1="2">Hello</innertag>
+ </tag>
+</xml>
diff --git a/tests/convert_and_merge_composable_tests/composable-interconnect-existing-fasm-mux.golden.xml b/tests/convert_and_merge_composable_tests/composable-interconnect-existing-fasm-mux.golden.xml
new file mode 100644
index 0000000..0df25ac
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/composable-interconnect-existing-fasm-mux.golden.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<xml>
+ <pb_type name="parent">
+ <input name="i0"/>
+ <input name="i1"/>
+ <output name="o"/>
+ <pb_type name="child">
+ <input name="i"/>
+ <output name="o"/>
+ </pb_type>
+ <interconnect>
+ <direct input="COMMON_SLICE.CIN" name="CIN_TO_CARRY0" output="CARRY4_VPR.CIN">
+ <pack_pattern in_port="COMMON_SLICE.CIN" name="CARRYCHAIN" out_port="CARRY4_VPR.CIN"/>
+ <metadata>
+ <meta name="fasm_mux">
+ COMMON_SLICE.CIN = PRECYINIT.CIN
+ </meta>
+ </metadata>
+ </direct>
+ <mux input="COMMON_SLICE.AO5 COMMON_SLICE.AX" name="CARRY_DI0" output="CARRY4_VPR.DI0">
+ <metadata>
+ <meta name="fasm_mux">
+ COMMON_SLICE.AO5 = CARRY4.ACY0
+ COMMON_SLICE.AX = NULL
+ </meta>
+ </metadata>
+ <delay_constant in_port="COMMON_SLICE.AX" max=".105e-9" out_port="CARRY4_VPR.DI0"/>
+ </mux>
+ <mux input="CARRY4_VPR.O3 CARRY4_VPR.CO_FABRIC3 COMMON_SLICE.DO6 COMMON_SLICE.DO5 COMMON_SLICE.DX" name="DFFMUX" output="SLICE_FF.D[3]">
+ <metadata>
+ <meta name="fasm_mux">
+ COMMON_SLICE.DX = DFFMUX.DX
+ COMMON_SLICE.DO5 = DFFMUX.O5
+ COMMON_SLICE.DO6 = DFFMUX.O6
+ CARRY4_VPR.CO_FABRIC3 = DFFMUX.CY
+ CARRY4_VPR.O3 = DFFMUX.XOR
+ </meta>
+ </metadata>
+ </mux>
+ </interconnect>
+ </pb_type>
+</xml>
diff --git a/tests/convert_and_merge_composable_tests/composable-interconnect-existing-fasm-mux.xml b/tests/convert_and_merge_composable_tests/composable-interconnect-existing-fasm-mux.xml
new file mode 100644
index 0000000..6590b67
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/composable-interconnect-existing-fasm-mux.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+<!-- Test the special handling around the fasm_mux metadata doesn't destroy
+ existing values.
+ -->
+<xml>
+ <pb_type name="parent">
+ <input name="i0" />
+ <input name="i1" />
+ <output name="o" />
+
+ <pb_type name="child">
+ <input name="i" />
+ <output name="o" />
+ </pb_type>
+
+ <interconnect>
+ <direct name="CIN_TO_CARRY0" input="COMMON_SLICE.CIN" output="CARRY4_VPR.CIN" >
+ <pack_pattern name="CARRYCHAIN"/>
+ <metadata>
+ <meta name="fasm_mux">
+ COMMON_SLICE.CIN = PRECYINIT.CIN
+ </meta>
+ </metadata>
+ </direct>
+ <mux name="DFFMUX"
+ input="CARRY4_VPR.O3 CARRY4_VPR.CO_FABRIC3 COMMON_SLICE.DO6 COMMON_SLICE.DO5 COMMON_SLICE.DX"
+ output="SLICE_FF.D[3]" >
+ <metadata>
+ <meta name="fasm_mux">
+ COMMON_SLICE.DX = DFFMUX.DX
+ COMMON_SLICE.DO5 = DFFMUX.O5
+ COMMON_SLICE.DO6 = DFFMUX.O6
+ CARRY4_VPR.CO_FABRIC3 = DFFMUX.CY
+ CARRY4_VPR.O3 = DFFMUX.XOR
+ </meta>
+ </metadata>
+ </mux>
+ <mux name="CARRY_DI0" input="COMMON_SLICE.AO5 COMMON_SLICE.AX" output="CARRY4_VPR.DI0" >
+ <delay_constant max=".105e-9" in_port="COMMON_SLICE.AX" out_port="CARRY4_VPR.DI0" />
+ <metadata>
+ <meta name="fasm_mux">
+ COMMON_SLICE.AO5 = CARRY4.ACY0
+ COMMON_SLICE.AX = NULL
+ </meta>
+ </metadata>
+ </mux>
+ </interconnect>
+ </pb_type>
+</xml>
diff --git a/tests/convert_and_merge_composable_tests/composable-interconnect-fasm-mux-levels.golden.xml b/tests/convert_and_merge_composable_tests/composable-interconnect-fasm-mux-levels.golden.xml
new file mode 100644
index 0000000..36509f5
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/composable-interconnect-fasm-mux-levels.golden.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<xml>
+ <pb_type name="parent">
+ <input name="i0"/>
+ <input name="i1"/>
+ <output name="o"/>
+ <pb_type name="blocka">
+ <input name="i"/>
+ <output name="a"/>
+ </pb_type>
+ <pb_type name="blockb">
+ <input name="i"/>
+ <output name="b"/>
+ </pb_type>
+ <pb_type name="blockc" num_pb="2">
+ <input name="i"/>
+ <output name="c"/>
+ </pb_type>
+ <pb_type name="blocko" num_pb="2">
+ <input name="i"/>
+ <output name="o"/>
+ </pb_type>
+ <interconnect>
+ <mux input="blocka.a blockb.b blockc[0].c blockc[1].c" name="outmux" output="blocko.i">
+ <metadata>
+ <meta name="fasm_mux">
+blocka.a : a1
+blockb.b : b1.l1
+blockc[0].c : c0.l1
+blockc[1].c : c1
+</meta>
+ <meta name="fasm_name">fasm_name</meta>
+ </metadata>
+ </mux>
+ <direct input="blocko.o" name="parent-o" output="parent.o"/>
+ </interconnect>
+ </pb_type>
+</xml>
diff --git a/tests/convert_and_merge_composable_tests/composable-interconnect-fasm-mux-levels.xml b/tests/convert_and_merge_composable_tests/composable-interconnect-fasm-mux-levels.xml
new file mode 100644
index 0000000..4c33420
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/composable-interconnect-fasm-mux-levels.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0"?>
+<!-- Test the special handling around the fasm_mux metadata when using
+ composable interconnects and existing metadata. -->
+<xml>
+ <pb_type name="parent">
+ <input name="i0" />
+ <input name="i1" />
+ <output name="o" />
+
+ <pb_type name="blocka">
+ <input name="i" />
+ <output name="a" />
+ </pb_type>
+ <pb_type name="blockb">
+ <input name="i" />
+ <output name="b" />
+ </pb_type>
+ <pb_type name="blockc" num_pb="2">
+ <input name="i" />
+ <output name="c" />
+ </pb_type>
+ <pb_type name="blocko" num_pb="2">
+ <input name="i" />
+ <output name="o" />
+ </pb_type>
+
+ <interconnect>
+ <mux name="outmux">
+ <port type="input" name="a" from="blocka">
+ <metadata>
+ <meta name="fasm_mux">a1</meta>
+ </metadata>
+ </port>
+ <port type="input" name="b" from="blockb">
+ <metadata>
+ <meta name="fasm_mux">b1.l1</meta>
+ </metadata>
+ </port>
+ <port type="input" name="c" from="blockc[0]">
+ <metadata>
+ <meta name="fasm_mux">c0.l1</meta>
+ </metadata>
+ </port>
+ <port type="input" name="c" from="blockc[1]">
+ <metadata>
+ <meta name="fasm_mux">c1</meta>
+ </metadata>
+ </port>
+ <port type="output" from="blocko" name="i" />
+ <metadata>
+ <meta name="fasm_name">fasm_name</meta>
+ </metadata>
+ </mux>
+ <direct>
+ <port type="input" name="o" from="blocko" />
+ <port type="output" name="o" />
+ </direct>
+ </interconnect>
+ </pb_type>
+</xml>
diff --git a/tests/convert_and_merge_composable_tests/composable-interconnect-fasm-mux.golden.xml b/tests/convert_and_merge_composable_tests/composable-interconnect-fasm-mux.golden.xml
new file mode 100644
index 0000000..932b881
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/composable-interconnect-fasm-mux.golden.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<xml>
+ <pb_type name="parent">
+ <input name="i0"/>
+ <input name="i1"/>
+ <output name="o"/>
+ <pb_type name="child">
+ <input name="i"/>
+ <output name="o"/>
+ </pb_type>
+ <interconnect>
+ <mux input="parent.i0 parent.i1" name="mux1" output="child.i">
+ <metadata>
+ <meta name="fasm_mux">
+parent.i0 : a1
+parent.i1 : b1
+</meta>
+ <meta name="fasm_name">fasm_name</meta>
+ </metadata>
+ </mux>
+ <direct input="child.o" name="parent-o" output="parent.o"/>
+ </interconnect>
+ </pb_type>
+</xml>
diff --git a/tests/convert_and_merge_composable_tests/composable-interconnect-fasm-mux.xml b/tests/convert_and_merge_composable_tests/composable-interconnect-fasm-mux.xml
new file mode 100644
index 0000000..741401c
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/composable-interconnect-fasm-mux.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<!-- Test the special handling around the fasm_mux metadata when using
+ composable interconnects. -->
+<xml>
+ <pb_type name="parent">
+ <input name="i0" />
+ <input name="i1" />
+ <output name="o" />
+
+ <pb_type name="child">
+ <input name="i" />
+ <output name="o" />
+ </pb_type>
+
+ <interconnect>
+ <direct>
+ <port type="output" name="o" />
+ <port type="input" from="child" name="o" />
+ </direct>
+ <mux name="mux1">
+ <port type="input" name="i0">
+ <metadata>
+ <meta name="fasm_mux">a1</meta>
+ </metadata>
+ </port>
+ <port type="input" name="i1">
+ <metadata>
+ <meta name="fasm_mux">b1</meta>
+ </metadata>
+ </port>
+ <port type="output" from="child" name="i" />
+ <metadata>
+ <meta name="fasm_name">fasm_name</meta>
+ </metadata>
+ </mux>
+ </interconnect>
+ </pb_type>
+</xml>
diff --git a/tests/convert_and_merge_composable_tests/composable-interconnect-implicit-parent.golden.xml b/tests/convert_and_merge_composable_tests/composable-interconnect-implicit-parent.golden.xml
new file mode 100644
index 0000000..1c662b7
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/composable-interconnect-implicit-parent.golden.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<xml>
+ <pb_type name="parent">
+ <input name="ia1"/>
+ <input name="ia2"/>
+ <input name="ia3"/>
+ <output name="o0"/>
+ <output name="o1"/>
+ <pb_type name="childa">
+ <input name="i1"/>
+ <input name="i2"/>
+ <output name="o"/>
+ </pb_type>
+ <pb_type name="childb">
+ <input name="i"/>
+ <output name="o"/>
+ </pb_type>
+ <pb_type name="childc">
+ <input name="i"/>
+ <output name="o"/>
+ </pb_type>
+ <interconnect>
+ <direct input="parent.ia1" name="childa-i1" output="childa.i1">
+ <pack_pattern in_port="parent.ia1" name="A1" out_port="childa.i1"/>
+ </direct>
+ <mux input="parent.ia2 parent.ia3" name="childa-input-i2" output="childa.i2">
+ <pack_pattern in_port="parent.ia2" name="A2" out_port="childa.i2"/>
+ <pack_pattern in_port="parent.ia3" name="A3" out_port="childa.i2"/>
+ </mux>
+ <direct input="childa.o" name="childb-i" output="childb.i"/>
+ <mux input="childa.o childb.o" name="childc-input" output="childc.i"/>
+ <direct input="childa.o" name="parent-o0" output="parent.o0"/>
+ <mux input="childa.o childb.o childc.o" name="output" output="parent.o1"/>
+ </interconnect>
+ </pb_type>
+</xml>
diff --git a/tests/convert_and_merge_composable_tests/composable-interconnect-implicit-parent.xml b/tests/convert_and_merge_composable_tests/composable-interconnect-implicit-parent.xml
new file mode 100644
index 0000000..089159f
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/composable-interconnect-implicit-parent.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0"?>
+<!--
+ Convert "implicit" parent specification for interconnect tags.
+
+ Convert
+ <interconnect><direct><port type='input' ...><port type='output' ...></direct><YYY../></interconnect>
+ to
+ <interconnect><direct input='...' name='xxx-xxx' output='...'><YYY../></direct></interconnect>
+
+ Convert
+ <interconnect><mux><port type='input' ...><port type='input' ...><port type='output' ...></mux><YYY../></interconnect>
+ to
+ <interconnect><mux input='in1 in2' name='xxx-xxx' output='...'><YYY../></mux></interconnect>
+
+This example below is connected as follows;
+ ┌───────────────────────────────────────────────────────────────────┐
+ │ │
+ │ ┌────────────┐ │
+ ia1│──────>│i1 │ │
+ │ │ │ │
+ │ │ childa o│─┬───────────────────────────────────────────>│o0
+ ia2│──>│╲ │ │ │ │
+ │ │├─>│i2 │ │ │
+ ia3│──>│╱ └────────────┘ │ ┌──────────┐ │
+ │ ├─>│i childb o│─┬──>│╲ │
+ │ │ └──────────┘ │ ││ ┌──────────┐ │
+ │ │ │ │├──>│i childc o│──>│╲ │
+ │ ├──────────────────>││ └──────────┘ ││ │
+ │ │ │ │╱ ││ │
+ │ │ │ ╭────────>│├──>│o1
+ │ │ ╰─────────────╯ ││ │
+ │ │ ││ │
+ │ ╰──────────────────────────────────────>│/ │
+ │ │
+ └───────────────────────────────────────────────────────────────────┘
+ -->
+<xml>
+ <pb_type name="parent">
+ <input name="ia1"/>
+ <input name="ia2"/>
+ <input name="ia3"/>
+ <output name="o0"/>
+ <output name="o1"/>
+ <pb_type name="childa">
+ <input name="i1"/>
+ <input name="i2"/>
+ <output name="o"/>
+ </pb_type>
+ <pb_type name="childb">
+ <input name="i"/>
+ <output name="o"/>
+ </pb_type>
+ <pb_type name="childc">
+ <input name="i"/>
+ <output name="o"/>
+ </pb_type>
+ <interconnect>
+ <!-- Direct parent -> child -->
+ <direct>
+ <port type="input" name="ia1" />
+ <port type="output" from="childa" name="i1" />
+ <pack_pattern name="A1">
+ <port type="input" name="ia1" />
+ <port type="output" from="childa" name="i1" />
+ </pack_pattern>
+ </direct>
+ <!-- Mux parent -> child -->
+ <mux name="childa-input-i2">
+ <port type="input" name="ia2" />
+ <port type="input" name="ia3" />
+ <port type="output" from="childa" name="i2" />
+ <pack_pattern name="A2">
+ <port type="input" name="ia2" />
+ <port type="output" from="childa" name="i2" />
+ </pack_pattern>
+ <pack_pattern name="A3">
+ <port type="input" name="ia3" />
+ <port type="output" from="childa" name="i2" />
+ </pack_pattern>
+ </mux>
+ <!-- Direct parent -> child -->
+ <direct>
+ <port type="input" from="childa" name="o" />
+ <port type="output" name="o0" />
+ </direct>
+ <!-- Direct child -> child -->
+ <direct>
+ <port type="input" from="childa" name="o" />
+ <port type="output" from="childb" name="i" />
+ </direct>
+ <!-- Mux child -> child -->
+ <mux name="childc-input">
+ <port type="input" from="childa" name="o" />
+ <port type="input" from="childb" name="o" />
+ <port type="output" from="childc" name="i" />
+ </mux>
+ <!-- Mux child -> parent -->
+ <mux name="output">
+ <port type="input" from="childa" name="o" />
+ <port type="input" from="childb" name="o" />
+ <port type="input" from="childc" name="o" />
+ <port type="output" name="o1" />
+ </mux>
+ </interconnect>
+ </pb_type>
+</xml>
+
diff --git a/tests/convert_and_merge_composable_tests/composable-interconnect-pack_patterns.golden.xml b/tests/convert_and_merge_composable_tests/composable-interconnect-pack_patterns.golden.xml
new file mode 100644
index 0000000..5921ecf
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/composable-interconnect-pack_patterns.golden.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<xml>
+ <pb_type name="parent">
+ <input name="ia1"/>
+ <input name="ia2"/>
+ <input name="ia3"/>
+ <output name="o0"/>
+ <output name="o1"/>
+ <pb_type name="childa">
+ <input name="i1"/>
+ <input name="i2"/>
+ <output name="o"/>
+ </pb_type>
+ <pb_type name="childb">
+ <input name="i"/>
+ <output name="o"/>
+ </pb_type>
+ <pb_type name="childc">
+ <input name="i"/>
+ <output name="o"/>
+ </pb_type>
+ <interconnect>
+ <direct input="parent.ia1" name="childa-i1" output="childa.i1"/>
+ <mux input="parent.ia2 parent.ia3" name="childa-input-i2" output="childa.i2"/>
+ <direct input="childa.o" name="childb-i" output="childb.i"/>
+ <mux input="childa.o childb.o" name="childc-input" output="childc.i"/>
+ <direct input="childa.o" name="parent-o0" output="parent.o0"/>
+ <mux input="childa.o childb.o childc.o" name="output" output="parent.o1"/>
+ </interconnect>
+ </pb_type>
+</xml>
diff --git a/tests/convert_and_merge_composable_tests/composable-interconnect-pack_patterns.xml b/tests/convert_and_merge_composable_tests/composable-interconnect-pack_patterns.xml
new file mode 100644
index 0000000..5d8a28c
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/composable-interconnect-pack_patterns.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0"?>
+<!--
+ Convert "implicit" parent specification for interconnect tags.
+
+ Convert
+ <interconnect><direct><port type='input' ...><port type='output' ...></direct><YYY../></interconnect>
+ to
+ <interconnect><direct input='...' name='xxx-xxx' output='...'><YYY../></direct></interconnect>
+
+ Convert
+ <interconnect><mux><port type='input' ...><port type='input' ...><port type='output' ...></mux><YYY../></interconnect>
+ to
+ <interconnect><mux input='in1 in2' name='xxx-xxx' output='...'><YYY../></mux></interconnect>
+
+This example below is connected as follows;
+ ┌───────────────────────────────────────────────────────────────────┐
+ │ │
+ │ ┌────────────┐ │
+ ia1│──────>│i1 │ │
+ │ │ │ │
+ │ │ childa o│─┬───────────────────────────────────────────>│o0
+ ia2│──>│╲ │ │ │ │
+ │ │├─>│i2 │ │ │
+ ia3│──>│╱ └────────────┘ │ ┌──────────┐ │
+ │ ├─>│i childb o│─┬──>│╲ │
+ │ │ └──────────┘ │ ││ ┌──────────┐ │
+ │ │ │ │├──>│i childc o│──>│╲ │
+ │ ├──────────────────>││ └──────────┘ ││ │
+ │ │ │ │╱ ││ │
+ │ │ │ ╭────────>│├──>│o1
+ │ │ ╰─────────────╯ ││ │
+ │ │ ││ │
+ │ ╰──────────────────────────────────────>│/ │
+ │ │
+ └───────────────────────────────────────────────────────────────────┘
+ -->
+<xml>
+ <pb_type name="parent">
+ <input name="ia1"/>
+ <input name="ia2"/>
+ <input name="ia3"/>
+ <output name="o0"/>
+ <output name="o1"/>
+ <pb_type name="childa">
+ <input name="i1"/>
+ <input name="i2"/>
+ <output name="o"/>
+ </pb_type>
+ <pb_type name="childb">
+ <input name="i"/>
+ <output name="o"/>
+ </pb_type>
+ <pb_type name="childc">
+ <input name="i"/>
+ <output name="o"/>
+ </pb_type>
+ <interconnect>
+ <!-- Direct parent -> child -->
+ <direct>
+ <port type="input" name="ia1" />
+ <port type="output" from="childa" name="i1" />
+ </direct>
+ <!-- Mux parent -> child -->
+ <mux name="childa-input-i2">
+ <port type="input" name="ia2" />
+ <port type="input" name="ia3" />
+ <port type="output" from="childa" name="i2" />
+ </mux>
+ <!-- Direct parent -> child -->
+ <direct>
+ <port type="input" from="childa" name="o" />
+ <port type="output" name="o0" />
+ </direct>
+ <!-- Direct child -> child -->
+ <direct>
+ <port type="input" from="childa" name="o" />
+ <port type="output" from="childb" name="i" />
+ </direct>
+ <!-- Mux child -> child -->
+ <mux name="childc-input">
+ <port type="input" from="childa" name="o" />
+ <port type="input" from="childb" name="o" />
+ <port type="output" from="childc" name="i" />
+ </mux>
+ <!-- Mux child -> parent -->
+ <mux name="output">
+ <port type="input" from="childa" name="o" />
+ <port type="input" from="childb" name="o" />
+ <port type="input" from="childc" name="o" />
+ <port type="output" name="o1" />
+ </mux>
+ </interconnect>
+ </pb_type>
+</xml>
+
diff --git a/tests/convert_and_merge_composable_tests/composable-loc-implicit-parent.golden.xml b/tests/convert_and_merge_composable_tests/composable-loc-implicit-parent.golden.xml
new file mode 100644
index 0000000..0c90f56
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/composable-loc-implicit-parent.golden.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<xml>
+ <pb_type name="parent">
+ <input name="i" width="2"/>
+ <pinlocations>
+ <loc>
+parent.o
+parent.i[0]
+parent.i[1]
+</loc>
+ </pinlocations>
+ <random>
+ <loc>
+ <port name="o"/>
+ </loc>
+ </random>
+ </pb_type>
+</xml>
diff --git a/tests/convert_and_merge_composable_tests/composable-loc-implicit-parent.xml b/tests/convert_and_merge_composable_tests/composable-loc-implicit-parent.xml
new file mode 100644
index 0000000..e8bc8d2
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/composable-loc-implicit-parent.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<!--
+ Convert
+ <loc ...><port ...><port ...></loc>
+ to
+ <loc ...>BLOCK.PORT BLOCK.PORT</loc>
+ -->
+<xml>
+ <pb_type name="parent">
+ <input name="i" width="2" />
+ <pinlocations>
+ <loc>
+ <port name="o" />
+ <port name="i" bit="0" />
+ <port name="i" bit="1" />
+ </loc>
+ </pinlocations>
+ <random>
+ <loc>
+ <port name="o" />
+ </loc>
+ </random>
+ </pb_type>
+</xml>
diff --git a/tests/convert_and_merge_composable_tests/composable-pb_type-inner.xml b/tests/convert_and_merge_composable_tests/composable-pb_type-inner.xml
new file mode 100644
index 0000000..6d1d5b5
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/composable-pb_type-inner.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<pb_type name="INNER" other_attribute="r">
+ <blif_model>.subckt random</blif_model>
+ <pb_class>lut</pb_class>
+ <other_tag/>
+</pb_type>
diff --git a/tests/convert_and_merge_composable_tests/composable-pb_type-middle.xml b/tests/convert_and_merge_composable_tests/composable-pb_type-middle.xml
new file mode 100644
index 0000000..d4f1f66
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/composable-pb_type-middle.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<pb_type name="MIDDLE" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <pb_type name="middle_inner" num_pb="1">
+ <xi:include href="composable-pb_type-inner.xml" xpointer="xpointer(pb_type/child::node())"/>
+ </pb_type>
+</pb_type>
diff --git a/tests/convert_and_merge_composable_tests/composable-pb_type.golden.xml b/tests/convert_and_merge_composable_tests/composable-pb_type.golden.xml
new file mode 100644
index 0000000..ef10e9d
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/composable-pb_type.golden.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" name="top" num_pb="1">
+ <pb_type name="middle" num_pb="1">
+ <pb_type blif_model=".subckt random" class="lut" name="middle_inner" num_pb="1">
+ <other_tag/>
+ </pb_type>
+ </pb_type>
+ <pb_type blif_model=".subckt random" class="lut" name="top_inner" num_pb="1">
+ <other_tag/>
+ </pb_type>
+</pb_type>
diff --git a/tests/convert_and_merge_composable_tests/composable-pb_type.xml b/tests/convert_and_merge_composable_tests/composable-pb_type.xml
new file mode 100644
index 0000000..ede3b86
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/composable-pb_type.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" ?>
+<pb_type name="top" num_pb="1" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <pb_type name="top_inner" num_pb="1" >
+ <xi:include href="composable-pb_type-inner.xml" xpointer="xpointer(pb_type/child::node())"/>
+ </pb_type>
+ <pb_type name="middle" num_pb="1">
+ <xi:include href="composable-pb_type-middle.xml" xpointer="xpointer(pb_type/child::node())"/>
+ </pb_type>
+</pb_type>
diff --git a/tests/convert_and_merge_composable_tests/explicit-port.golden.xml b/tests/convert_and_merge_composable_tests/explicit-port.golden.xml
new file mode 100644
index 0000000..59cdf12
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/explicit-port.golden.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<xml>
+ <port-value-test o="port-name"/>
+ <port-value-test o="port-name[8]"/>
+ <port-value-test o="port-name[8:4]"/>
+</xml>
diff --git a/tests/convert_and_merge_composable_tests/explicit-port.xml b/tests/convert_and_merge_composable_tests/explicit-port.xml
new file mode 100644
index 0000000..d078fea
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/explicit-port.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<!-- Convert
+ * <port name=XXX> to XXX
+ * <port name=XXX bit=Y> to XXX[Y]
+ * <port name=XXX bit-msb=M bit-lsb=L> to XXX[M:L]
+ -->
+<xml>
+ <port-value-test><port name="port-name" /></port-value-test>
+ <port-value-test><port name="port-name" bit="8" /></port-value-test>
+ <port-value-test><port name="port-name" bit-msb="8" bit-lsb="4" /></port-value-test>
+</xml>
diff --git a/tests/convert_and_merge_composable_tests/full-test-inner.xml b/tests/convert_and_merge_composable_tests/full-test-inner.xml
new file mode 100644
index 0000000..575ddac
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/full-test-inner.xml
@@ -0,0 +1,16 @@
+<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" name="ADDER" num_pb="1">
+ <blif_model>.subckt adder</blif_model>
+ <input name="a" num_pins="1"/>
+ <input name="b" num_pins="1"/>
+ <input name="cin" num_pins="1"/>
+ <output name="cout" num_pins="1"/>
+ <output name="sum" num_pins="1"/>
+ <delay_constant max="300e-12" in_port="a" out_port="cout"/>
+ <delay_constant max="300e-12" in_port="b" out_port="cout"/>
+ <delay_constant max="10e-12" in_port="cin" out_port="cout"/>
+ <delay_constant max="300e-12" in_port="a" out_port="sum"/>
+ <delay_constant max="300e-12" in_port="b" out_port="sum"/>
+ <delay_constant max="300e-12" in_port="cin" out_port="sum"/>
+ <T_setup clock="clk" port="a" value="10e-12"/>
+ <T_clock_to_Q clock="clk" max="10e-12" port="cout"/>
+</pb_type>
diff --git a/tests/convert_and_merge_composable_tests/full-test.golden.xml b/tests/convert_and_merge_composable_tests/full-test.golden.xml
new file mode 100644
index 0000000..dd44989
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/full-test.golden.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0"?>
+<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" name="MULTIPLE_INSTANCE" num_pb="1">
+ <input name="a" num_pins="4"/>
+ <input name="b" num_pins="4"/>
+ <input name="c" num_pins="4"/>
+ <input name="cin" num_pins="1"/>
+ <input name="d" num_pins="4"/>
+ <output name="cout" num_pins="1"/>
+ <output name="sum" num_pins="8"/>
+ <pb_type blif_model=".subckt adder" name="comba" num_pb="4">
+ <input name="a" num_pins="1"/>
+ <input name="b" num_pins="1"/>
+ <input name="cin" num_pins="1"/>
+ <output name="cout" num_pins="1"/>
+ <output name="sum" num_pins="1"/>
+ <delay_constant in_port="comba.a" max="300e-12" out_port="comba.cout"/>
+ <delay_constant in_port="comba.b" max="300e-12" out_port="comba.cout"/>
+ <delay_constant in_port="comba.cin" max="10e-12" out_port="comba.cout"/>
+ <delay_constant in_port="comba.a" max="300e-12" out_port="comba.sum"/>
+ <delay_constant in_port="comba.b" max="300e-12" out_port="comba.sum"/>
+ <delay_constant in_port="comba.cin" max="300e-12" out_port="comba.sum"/>
+ <T_setup clock="clk" port="comba.a" value="10e-12"/>
+ <T_clock_to_Q clock="clk" max="10e-12" port="comba.cout"/>
+ </pb_type>
+ <pb_type blif_model=".subckt adder" name="combb" num_pb="4">
+ <input name="a" num_pins="1"/>
+ <input name="b" num_pins="1"/>
+ <input name="cin" num_pins="1"/>
+ <output name="cout" num_pins="1"/>
+ <output name="sum" num_pins="1"/>
+ <delay_constant in_port="combb.a" max="300e-12" out_port="combb.cout"/>
+ <delay_constant in_port="combb.b" max="300e-12" out_port="combb.cout"/>
+ <delay_constant in_port="combb.cin" max="10e-12" out_port="combb.cout"/>
+ <delay_constant in_port="combb.a" max="300e-12" out_port="combb.sum"/>
+ <delay_constant in_port="combb.b" max="300e-12" out_port="combb.sum"/>
+ <delay_constant in_port="combb.cin" max="300e-12" out_port="combb.sum"/>
+ <T_setup clock="clk" port="combb.a" value="10e-12"/>
+ <T_clock_to_Q clock="clk" max="10e-12" port="combb.cout"/>
+ </pb_type>
+ <interconnect>
+ <direct input="combb[3].cout" name="MULTIPLE_INSTANCE-cout" output="MULTIPLE_INSTANCE.cout"/>
+ <direct input="comba[0].sum" name="MULTIPLE_INSTANCE-sum[0]" output="MULTIPLE_INSTANCE.sum[0]"/>
+ <direct input="comba[1].sum" name="MULTIPLE_INSTANCE-sum[1]" output="MULTIPLE_INSTANCE.sum[1]"/>
+ <direct input="comba[2].sum" name="MULTIPLE_INSTANCE-sum[2]" output="MULTIPLE_INSTANCE.sum[2]"/>
+ <direct input="comba[3].sum" name="MULTIPLE_INSTANCE-sum[3]" output="MULTIPLE_INSTANCE.sum[3]"/>
+ <direct input="combb[0].sum" name="MULTIPLE_INSTANCE-sum[4]" output="MULTIPLE_INSTANCE.sum[4]"/>
+ <direct input="combb[1].sum" name="MULTIPLE_INSTANCE-sum[5]" output="MULTIPLE_INSTANCE.sum[5]"/>
+ <direct input="combb[2].sum" name="MULTIPLE_INSTANCE-sum[6]" output="MULTIPLE_INSTANCE.sum[6]"/>
+ <direct input="combb[3].sum" name="MULTIPLE_INSTANCE-sum[7]" output="MULTIPLE_INSTANCE.sum[7]"/>
+ <direct input="MULTIPLE_INSTANCE.a[0]" name="comba[0]-a" output="comba[0].a"/>
+ <direct input="MULTIPLE_INSTANCE.b[0]" name="comba[0]-b" output="comba[0].b"/>
+ <direct input="MULTIPLE_INSTANCE.cin" name="comba[0]-cin" output="comba[0].cin"/>
+ <direct input="MULTIPLE_INSTANCE.a[1]" name="comba[1]-a" output="comba[1].a"/>
+ <direct input="MULTIPLE_INSTANCE.b[1]" name="comba[1]-b" output="comba[1].b"/>
+ <direct input="MULTIPLE_INSTANCE.cin" name="comba[1]-cin" output="comba[1].cin"/>
+ <direct input="MULTIPLE_INSTANCE.a[2]" name="comba[2]-a" output="comba[2].a"/>
+ <direct input="MULTIPLE_INSTANCE.b[2]" name="comba[2]-b" output="comba[2].b"/>
+ <direct input="MULTIPLE_INSTANCE.cin" name="comba[2]-cin" output="comba[2].cin"/>
+ <direct input="MULTIPLE_INSTANCE.a[3]" name="comba[3]-a" output="comba[3].a"/>
+ <direct input="MULTIPLE_INSTANCE.b[3]" name="comba[3]-b" output="comba[3].b"/>
+ <direct input="MULTIPLE_INSTANCE.cin" name="comba[3]-cin" output="comba[3].cin"/>
+ <direct input="MULTIPLE_INSTANCE.c[0]" name="combb[0]-a" output="combb[0].a"/>
+ <direct input="MULTIPLE_INSTANCE.d[0]" name="combb[0]-b" output="combb[0].b"/>
+ <direct input="comba[0].cout" name="combb[0]-cin" output="combb[0].cin">
+ <pack_pattern in_port="comba[0].cout" name="carry-ADDER" out_port="combb[0].cin"/>
+ </direct>
+ <direct input="MULTIPLE_INSTANCE.c[1]" name="combb[1]-a" output="combb[1].a"/>
+ <direct input="MULTIPLE_INSTANCE.d[1]" name="combb[1]-b" output="combb[1].b"/>
+ <direct input="comba[1].cout" name="combb[1]-cin" output="combb[1].cin">
+ <pack_pattern in_port="comba[1].cout" name="carry-ADDER" out_port="combb[1].cin"/>
+ </direct>
+ <direct input="MULTIPLE_INSTANCE.c[2]" name="combb[2]-a" output="combb[2].a"/>
+ <direct input="MULTIPLE_INSTANCE.d[2]" name="combb[2]-b" output="combb[2].b"/>
+ <direct input="comba[2].cout" name="combb[2]-cin" output="combb[2].cin">
+ <pack_pattern in_port="comba[2].cout" name="carry-ADDER" out_port="combb[2].cin"/>
+ </direct>
+ <direct input="MULTIPLE_INSTANCE.c[3]" name="combb[3]-a" output="combb[3].a"/>
+ <direct input="MULTIPLE_INSTANCE.d[3]" name="combb[3]-b" output="combb[3].b"/>
+ <direct input="comba[3].cout" name="combb[3]-cin" output="combb[3].cin">
+ <pack_pattern in_port="comba[3].cout" name="carry-ADDER" out_port="combb[3].cin"/>
+ </direct>
+ </interconnect>
+</pb_type>
diff --git a/tests/convert_and_merge_composable_tests/full-test.xml b/tests/convert_and_merge_composable_tests/full-test.xml
new file mode 100644
index 0000000..c5a31ef
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/full-test.xml
@@ -0,0 +1,166 @@
+<?xml version='1.0' encoding='utf-8'?>
+<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" name="MULTIPLE_INSTANCE" num_pb="1">
+ <input name="a" num_pins="4"/>
+ <input name="b" num_pins="4"/>
+ <input name="c" num_pins="4"/>
+ <input name="cin" num_pins="1"/>
+ <input name="d" num_pins="4"/>
+ <output name="cout" num_pins="1"/>
+ <output name="sum" num_pins="8"/>
+ <pb_type name="comba" num_pb="4">
+ <xi:include href="full-test-inner.xml" xpointer="xpointer(pb_type/child::node())"/>
+ </pb_type>
+ <pb_type name="combb" num_pb="4">
+ <xi:include href="full-test-inner.xml" xpointer="xpointer(pb_type/child::node())"/>
+ </pb_type>
+ <interconnect>
+ <direct>
+ <port name="a[3]" type="input"/>
+ <port from="comba[3]" name="a" type="output"/>
+ </direct>
+ <direct>
+ <port name="b[3]" type="input"/>
+ <port from="comba[3]" name="b" type="output"/>
+ </direct>
+ <direct>
+ <port name="cin" type="input"/>
+ <port from="comba[0]" name="cin" type="output"/>
+ </direct>
+ <direct>
+ <port name="cin" type="input"/>
+ <port from="comba[1]" name="cin" type="output"/>
+ </direct>
+ <direct>
+ <port name="cin" type="input"/>
+ <port from="comba[2]" name="cin" type="output"/>
+ </direct>
+ <direct>
+ <port name="cin" type="input"/>
+ <port from="comba[3]" name="cin" type="output"/>
+ </direct>
+ <direct>
+ <port from="comba[3]" name="sum" type="input"/>
+ <port name="sum[3]" type="output"/>
+ </direct>
+ <direct>
+ <port name="a[0]" type="input"/>
+ <port from="comba[0]" name="a" type="output"/>
+ </direct>
+ <direct>
+ <port name="b[0]" type="input"/>
+ <port from="comba[0]" name="b" type="output"/>
+ </direct>
+ <direct>
+ <port from="comba[0]" name="sum" type="input"/>
+ <port name="sum[0]" type="output"/>
+ </direct>
+ <direct>
+ <port name="a[1]" type="input"/>
+ <port from="comba[1]" name="a" type="output"/>
+ </direct>
+ <direct>
+ <port name="b[1]" type="input"/>
+ <port from="comba[1]" name="b" type="output"/>
+ </direct>
+ <direct>
+ <port from="comba[1]" name="sum" type="input"/>
+ <port name="sum[1]" type="output"/>
+ </direct>
+ <direct>
+ <port name="a[2]" type="input"/>
+ <port from="comba[2]" name="a" type="output"/>
+ </direct>
+ <direct>
+ <port name="b[2]" type="input"/>
+ <port from="comba[2]" name="b" type="output"/>
+ </direct>
+ <direct>
+ <port from="comba[2]" name="sum" type="input"/>
+ <port name="sum[2]" type="output"/>
+ </direct>
+ <direct>
+ <port name="c[0]" type="input"/>
+ <port from="combb[0]" name="a" type="output"/>
+ </direct>
+ <direct>
+ <port name="d[0]" type="input"/>
+ <port from="combb[0]" name="b" type="output"/>
+ </direct>
+ <direct>
+ <port from="comba[0]" name="cout" type="input"/>
+ <port from="combb[0]" name="cin" type="output"/>
+ <pack_pattern name="ADDER" type="carry">
+ <port from="comba[0]" name="cout" type="input"/>
+ <port from="combb[0]" name="cin" type="output"/>
+ </pack_pattern>
+ </direct>
+ <direct>
+ <port from="combb[0]" name="sum" type="input"/>
+ <port name="sum[4]" type="output"/>
+ </direct>
+ <direct>
+ <port name="c[1]" type="input"/>
+ <port from="combb[1]" name="a" type="output"/>
+ </direct>
+ <direct>
+ <port name="d[1]" type="input"/>
+ <port from="combb[1]" name="b" type="output"/>
+ </direct>
+ <direct>
+ <port from="comba[1]" name="cout" type="input"/>
+ <port from="combb[1]" name="cin" type="output"/>
+ <pack_pattern name="ADDER" type="carry">
+ <port from="comba[1]" name="cout" type="input"/>
+ <port from="combb[1]" name="cin" type="output"/>
+ </pack_pattern>
+ </direct>
+ <direct>
+ <port from="combb[1]" name="sum" type="input"/>
+ <port name="sum[5]" type="output"/>
+ </direct>
+ <direct>
+ <port name="c[2]" type="input"/>
+ <port from="combb[2]" name="a" type="output"/>
+ </direct>
+ <direct>
+ <port name="d[2]" type="input"/>
+ <port from="combb[2]" name="b" type="output"/>
+ </direct>
+ <direct>
+ <port from="comba[2]" name="cout" type="input"/>
+ <port from="combb[2]" name="cin" type="output"/>
+ <pack_pattern name="ADDER" type="carry">
+ <port from="comba[2]" name="cout" type="input"/>
+ <port from="combb[2]" name="cin" type="output"/>
+ </pack_pattern>
+ </direct>
+ <direct>
+ <port from="combb[2]" name="sum" type="input"/>
+ <port name="sum[6]" type="output"/>
+ </direct>
+ <direct>
+ <port name="c[3]" type="input"/>
+ <port from="combb[3]" name="a" type="output"/>
+ </direct>
+ <direct>
+ <port name="d[3]" type="input"/>
+ <port from="combb[3]" name="b" type="output"/>
+ </direct>
+ <direct>
+ <port from="comba[3]" name="cout" type="input"/>
+ <port from="combb[3]" name="cin" type="output"/>
+ <pack_pattern name="ADDER" type="carry">
+ <port from="comba[3]" name="cout" type="input"/>
+ <port from="combb[3]" name="cin" type="output"/>
+ </pack_pattern>
+ </direct>
+ <direct>
+ <port from="combb[3]" name="cout" type="input"/>
+ <port name="cout" type="output"/>
+ </direct>
+ <direct>
+ <port from="combb[3]" name="sum" type="input"/>
+ <port name="sum[7]" type="output"/>
+ </direct>
+ </interconnect>
+</pb_type>
diff --git a/tests/convert_and_merge_composable_tests/pack_pattern-copy-direct-ports.golden.xml b/tests/convert_and_merge_composable_tests/pack_pattern-copy-direct-ports.golden.xml
new file mode 100644
index 0000000..7e983c0
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/pack_pattern-copy-direct-ports.golden.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<xml>
+ <interconnect>
+ <direct input="LUTFF.FCIN" name="SB_CARRY-CI" output="SB_CARRY.CI">
+ <pack_pattern in_port="LUTFF.FCIN" name="CARRYCHAIN" out_port="SB_CARRY.CI"/>
+ </direct>
+ <direct input="SB_FF.D" name="VPR_FF-D" output="VPR_FF.D">
+ <pack_pattern in_port="SB_FF.D" name="A" out_port="VPR_FF.D"/>
+ </direct>
+ </interconnect>
+</xml>
diff --git a/tests/convert_and_merge_composable_tests/pack_pattern-copy-direct-ports.xml b/tests/convert_and_merge_composable_tests/pack_pattern-copy-direct-ports.xml
new file mode 100644
index 0000000..0a23c15
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/pack_pattern-copy-direct-ports.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<!--
+ Convert
+ <direct XXXX><pack_pattern name="xxx"/>
+ to
+ <direct XXXX><pack_pattern name="xxx" XXXX/>
+ -->
+<xml>
+ <interconnect>
+ <direct input="SB_FF.D" name="VPR_FF-D" output="VPR_FF.D">
+ <pack_pattern name="A"/>
+ </direct>
+ <direct>
+ <port type="input" from="LUTFF" name="FCIN"/><port type="output" from="SB_CARRY" name="CI"/>
+ <pack_pattern name="CARRYCHAIN"/>
+ </direct>
+ </interconnect>
+</xml>
diff --git a/tests/convert_and_merge_composable_tests/pack_pattern-merge-type-into-name.golden.xml b/tests/convert_and_merge_composable_tests/pack_pattern-merge-type-into-name.golden.xml
new file mode 100644
index 0000000..f93626e
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/pack_pattern-merge-type-into-name.golden.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<xml>
+ <pb_type>
+ <direct>
+ <pack_pattern name="chain-B"/>
+ </direct>
+ <mux>
+ <pack_pattern name="molecule-A">
+ <innertag/>
+ </pack_pattern>
+ </mux>
+ </pb_type>
+</xml>
diff --git a/tests/convert_and_merge_composable_tests/pack_pattern-merge-type-into-name.xml b/tests/convert_and_merge_composable_tests/pack_pattern-merge-type-into-name.xml
new file mode 100644
index 0000000..040ce3a
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/pack_pattern-merge-type-into-name.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<!--
+ Convert
+ <pack_pattern name="xxx" type="yyy
+ to
+ <pack_pattern name="yyy-xxx"
+
+ The idea is that eventually VPR will be explicit about chain and molecule
+ patterns.
+
+ -->
+<xml>
+ <pb_type>
+ <direct>
+ <pack_pattern name="B" type="chain" />
+ </direct>
+ <mux>
+ <pack_pattern name="A" type="molecule" >
+ <innertag />
+ </pack_pattern>
+ </mux>
+ </pb_type>
+</xml>
diff --git a/tests/convert_and_merge_composable_tests/pack_pattern-strip-from-pb_type-ports.golden.xml b/tests/convert_and_merge_composable_tests/pack_pattern-strip-from-pb_type-ports.golden.xml
new file mode 100644
index 0000000..a6d6a3b
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/pack_pattern-strip-from-pb_type-ports.golden.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<xml>
+ <pb_type>
+ <input name="in1"/>
+ <input name="in2"/>
+ <output name="o1"/>
+ <output name="o2"/>
+ </pb_type>
+</xml>
diff --git a/tests/convert_and_merge_composable_tests/pack_pattern-strip-from-pb_type-ports.xml b/tests/convert_and_merge_composable_tests/pack_pattern-strip-from-pb_type-ports.xml
new file mode 100644
index 0000000..da6866a
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/pack_pattern-strip-from-pb_type-ports.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<!--
+ Strip pack_pattern's from input/output tags on pb_types.
+
+ This allows us to add the pack_pattern annotation at the leaf values which
+ don't have an interconnect. It makes it explicit which ports are involved in
+ the chain (and hence won't end up on fabric).
+
+ -->
+<xml>
+ <pb_type>
+ <input name="in1">
+ <pack_pattern />
+ </input>
+ <input name="in2" />
+ <output name="o1" />
+ <output name="o2">
+ <pack_pattern>
+ <innertag />
+ </pack_pattern>
+ </output>
+ </pb_type>
+</xml>
diff --git a/tests/convert_and_merge_composable_tests/preserve-interconnect.golden.xml b/tests/convert_and_merge_composable_tests/preserve-interconnect.golden.xml
new file mode 100644
index 0000000..59dbb7c
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/preserve-interconnect.golden.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<xml>
+ <pb_type name="parent">
+ <input name="ia1"/>
+ <input name="ia2"/>
+ <input name="ia3"/>
+ <output name="o0"/>
+ <output name="o1"/>
+ <pb_type name="childa">
+ <input name="i1"/>
+ <input name="i2"/>
+ <output name="o"/>
+ </pb_type>
+ <pb_type name="childb">
+ <input name="i"/>
+ <output name="o"/>
+ </pb_type>
+ <pb_type name="childc">
+ <input name="i"/>
+ <output name="o"/>
+ </pb_type>
+ <interconnect>
+ <direct input="parent.ia1" name="childa-i1" output="childa.i1"/>
+ <mux input="parent.ia2 parent.ia3" name="childa-input-i2" output="childa.i2">
+ <pack_pattern in_port="parent.ia2" name="MUX1" output="childa.i2"/>
+ <pack_pattern in_port="parent.ia3" name="MUX2" output="childa.i2"/>
+ </mux>
+ <direct input="childa.o" name="childb-i" output="childb.i"/>
+ <mux input="childa.o childb.o" name="childc-input" output="childc.i"/>
+ <direct input="childa.o" name="parent-o0" output="parent.o0">
+ <pack_pattern in_port="childa.o" name="CARRY" out_port="parent.o0" output="parent.o0"/>
+ </direct>
+ <mux input="childa.o childb.o childc.o" name="output" output="parent.o1"/>
+ </interconnect>
+ </pb_type>
+</xml>
diff --git a/tests/convert_and_merge_composable_tests/preserve-interconnect.xml b/tests/convert_and_merge_composable_tests/preserve-interconnect.xml
new file mode 100644
index 0000000..1053784
--- /dev/null
+++ b/tests/convert_and_merge_composable_tests/preserve-interconnect.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<!-- Make sure existing interconnect values are preserved. -->
+<xml>
+ <pb_type name="parent">
+ <input name="ia1"/>
+ <input name="ia2"/>
+ <input name="ia3"/>
+ <output name="o0"/>
+ <output name="o1"/>
+ <pb_type name="childa">
+ <input name="i1"/>
+ <input name="i2"/>
+ <output name="o"/>
+ </pb_type>
+ <pb_type name="childb">
+ <input name="i"/>
+ <output name="o"/>
+ </pb_type>
+ <pb_type name="childc">
+ <input name="i"/>
+ <output name="o"/>
+ </pb_type>
+ <interconnect>
+ <direct input="parent.ia1" name="childa-i1" output="childa.i1"/>
+ <mux name="childa-input-i2" input="parent.ia2 parent.ia3" output="childa.i2">
+ <pack_pattern name="MUX1" in_port="parent.ia2" output="childa.i2" />
+ <pack_pattern name="MUX2" in_port="parent.ia3" output="childa.i2" />
+ </mux>
+ <direct input="childa.o" name="parent-o0" output="parent.o0">
+ <pack_pattern name="CARRY" in_port="childa.o" output="parent.o0" />
+ </direct>
+ <direct input="childa.o" name="childb-i" output="childb.i"/>
+ <mux name="childc-input" input="childa.o childb.o" output="childc.i"/>
+ <mux name="output" input="childa.o childb.o childc.o" output="parent.o1"/>
+ </interconnect>
+ </pb_type>
+</xml>
diff --git a/tests/test_converting.py b/tests/test_converting.py
new file mode 100644
index 0000000..d6f4e81
--- /dev/null
+++ b/tests/test_converting.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python3
+
+import pytest
+from vtr_xml_utils import convert
+
+
+@pytest.mark.parametrize("testdatafile",
+ convert.get_filenames_containing("*.golden.xml",
+ __file__))
+def test_converting_and_merging_fpga_architecture(testdatafile):
+ inputname = testdatafile.replace('.golden.xml', '.xml')
+ result = convert.vtr_stylize_xml(inputname)
+ with open(testdatafile) as res:
+ golden = res.read()
+ assert result == golden
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..7fcb0fc
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,28 @@
+[tox]
+envlist = py{27,34,35,36,37}
+
+[testenv]
+setenv =
+ PYTHONPATH={toxinidir}/vtr_xml_utils
+basepython =
+ py35: python3.5
+ py36: python3.6
+ py37: python3.7
+deps =
+ check-manifest
+ # If your project uses README.rst, uncomment the following:
+ # readme_renderer
+ flake8
+ pytest
+ lxml
+commands =
+ check-manifest --ignore tox.ini,tests*
+ # This repository uses a Markdown long_description, so the -r flag to
+ # `setup.py check` is not needed. If your project contains a README.rst,
+ # use `python setup.py check -m -r -s` instead.
+ python setup.py check -m -s
+ flake8 .
+ pytest
+[flake8]
+exclude = .tox,*.egg,build,data
+select = E,W,F
diff --git a/vtr_xml_utils/__init__.py b/vtr_xml_utils/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vtr_xml_utils/__init__.py
diff --git a/vtr_xml_utils/__main__.py b/vtr_xml_utils/__main__.py
new file mode 100644
index 0000000..7204119
--- /dev/null
+++ b/vtr_xml_utils/__main__.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python3
+
+from . import convert
+
+import argparse
+import sys
+import os
+
+
+def main(args):
+ if not os.path.isfile(args.input_xml):
+ print("The {} file does not exist or is a directory"
+ .format(args.input_xml))
+ exit(2)
+ elif not os.path.isdir(os.path.dirname(os.path.realpath(args.output))):
+ print("The {} file cannot be created - no such directory"
+ .format(args.output))
+ exit(2)
+ result = convert.vtr_stylize_xml(args.input_xml)
+ with open(args.output, 'w') as out:
+ out.write(result)
+ exit(0)
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(
+ prog='vtr_xml_utils',
+ description="A tool for applying styling changes to the XML files \
+ for Verilog"
+ )
+ parser.add_argument(
+ "input_xml",
+ metavar="input.xml",
+ type=str,
+ help="The path to file that needs to be stylized with XSL files",
+ )
+ parser.add_argument(
+ "--output",
+ "-o",
+ type=str,
+ default="output.xml",
+ help="Output filename default 'output.xml'"
+ )
+
+ args = parser.parse_args()
+ sys.exit(main(args))
diff --git a/vtr_xml_utils/convert.py b/vtr_xml_utils/convert.py
new file mode 100644
index 0000000..d751651
--- /dev/null
+++ b/vtr_xml_utils/convert.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python3
+import lxml.etree as ET
+import pkg_resources
+import os
+from pathlib import Path
+
+
+def get_filenames_containing(pattern, rootdir):
+ return list(set([str(f) for f in
+ Path(os.path.dirname(rootdir)).rglob(pattern)]))
+
+
+def vtr_stylize_xml(xmlfilename: str):
+ """Applies a set of stylesheet rules to the input model or PB type XML file.
+ It also includes the XInclude blocks in the final output.
+
+ Parameters
+ ----------
+ xmlfilename : str
+ The path to the input XML file.
+
+ Returns
+ -------
+ str
+ A string containing formatted XML file, with added parts from the
+ XInclude statements in the original XML.
+ """
+ xslresourcesroot = pkg_resources.resource_filename('vtr_xml_utils',
+ 'resources')
+ xslresourcesroot += '/'
+ converters = [
+ 'identity.xsl',
+ 'convert-pb_type-attributes.xsl',
+ 'convert-port-tag.xsl',
+ 'convert-prefix-port.xsl',
+ 'pack-patterns.xsl',
+ 'remove-duplicate-models.xsl',
+ 'attribute-fixes.xsl',
+ 'sort-tags.xsl']
+ parser = ET.XMLParser(remove_comments=True)
+ etdata = ET.parse(xmlfilename, parser)
+ etdata.xinclude()
+ for c in converters:
+ xslt = ET.parse(xslresourcesroot + c, parser)
+ transform = ET.XSLT(xslt)
+ etdata = transform(etdata)
+ return '<?xml version="1.0"?>\n' \
+ + ET.tostring(etdata, pretty_print=True).decode('utf-8')
diff --git a/vtr_xml_utils/resources/attribute-fixes.xsl b/vtr_xml_utils/resources/attribute-fixes.xsl
new file mode 100644
index 0000000..ed4d65b
--- /dev/null
+++ b/vtr_xml_utils/resources/attribute-fixes.xsl
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <xsl:include href="identity.xsl" />
+
+ <!-- Strip xml:base attribute -->
+ <xsl:template match="@xml:base"/>
+
+ <!-- Normalize space around attributes on a tag -->
+ <xsl:template match="@*">
+ <xsl:copy>
+ <xsl:value-of select="normalize-space( . )" />
+ </xsl:copy>
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <!-- Sort the attributes by name -->
+ <xsl:template match="*">
+ <xsl:copy>
+ <xsl:for-each select="@*[name()!='xml:base']">
+ <xsl:sort select="name( . )"/>
+ <xsl:attribute name="{local-name()}"><xsl:value-of select="normalize-space(.)"/></xsl:attribute>
+ </xsl:for-each>
+ <xsl:apply-templates/>
+ </xsl:copy>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/vtr_xml_utils/resources/convert-pb_type-attributes.xsl b/vtr_xml_utils/resources/convert-pb_type-attributes.xsl
new file mode 100644
index 0000000..0f497ee
--- /dev/null
+++ b/vtr_xml_utils/resources/convert-pb_type-attributes.xsl
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <xsl:include href="identity.xsl" />
+
+ <xsl:template match="pb_type">
+ <xsl:copy>
+ <!--
+ Convert
+ <pb_type><blif_model>XXX</blif_model></pb_type>
+ to
+ <pb_type blif_model="XXX"></pb_type>
+ -->
+ <xsl:if test="blif_model">
+ <xsl:attribute name="blif_model"><xsl:value-of select="blif_model/text()"/></xsl:attribute>
+ </xsl:if>
+ <!--
+ Convert
+ <pb_type><pb_class>XXX</pb_class></pb_type>
+ to
+ <pb_type class="XXX"></pb_type>
+ -->
+ <xsl:if test="pb_class">
+ <xsl:attribute name="class"><xsl:value-of select="pb_class/text()"/></xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates select="@*"/>
+ <xsl:apply-templates select="node()"/>
+ </xsl:copy>
+ </xsl:template>
+
+ <xsl:template match="pb_type/blif_model"/>
+ <xsl:template match="pb_type/pb_class"/>
+
+</xsl:stylesheet>
diff --git a/vtr_xml_utils/resources/convert-port-tag.xsl b/vtr_xml_utils/resources/convert-port-tag.xsl
new file mode 100644
index 0000000..7ee6dc3
--- /dev/null
+++ b/vtr_xml_utils/resources/convert-port-tag.xsl
@@ -0,0 +1,112 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <xsl:include href="identity.xsl" />
+ <!-- template-function: Allow from attribute which gives you a relative to a given pb_type -->
+ <xsl:template name="from-pb_type">
+ <xsl:choose>
+ <xsl:when test="@from='current'"><xsl:value-of select="ancestor::pb_type[1]/@name"/></xsl:when>
+ <xsl:when test="@from"><xsl:value-of select="@from"/></xsl:when>
+ <xsl:otherwise><xsl:value-of select="ancestor::pb_type[1]/@name"/></xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- template-function: Called to convert
+ * <port name=XXX> to XXX
+ * <port name=XXX bit=Y> to XXX[Y]
+ * <port name=XXX bit_msb=M bit_lsb=L> to XXX[M:L]
+ -->
+ <xsl:template name="port-value"><xsl:value-of select="@name"/><xsl:choose><xsl:when test="@bit">[<xsl:value-of select="@bit"/>]</xsl:when><xsl:when test="@bit-msb">[<xsl:value-of select="@bit-msb"/>:<xsl:value-of select="@bit-lsb"/>]</xsl:when><xsl:otherwise></xsl:otherwise></xsl:choose></xsl:template>
+
+ <!-- Testing matcher for the port-value template function -->
+ <xsl:template match="port-value-test/port">
+ <xsl:attribute name="o">
+ <xsl:call-template name="port-value"/>
+ </xsl:attribute>
+ </xsl:template>
+
+ <!--
+ Convert
+ <interconnect><xxx><pack_pattern><port type='input' ...><port type='output' ...></pack_pattern></xxx><YYY../></interconnect>
+ to
+ <interconnect><xxx><pack_pattern in_port="XXXX" out_port="XXXX" /></xxx></interconnect>
+ -->
+ <xsl:template match="pack_pattern/port[@type='input']">
+ <xsl:attribute name="in_port"><xsl:call-template name="from-pb_type"/>.<xsl:call-template name="port-value"/></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="pack_pattern/port[@type='output']">
+ <xsl:attribute name="out_port"><xsl:call-template name="from-pb_type"/>.<xsl:call-template name="port-value"/></xsl:attribute>
+ </xsl:template>
+
+ <!--
+ Convert
+ <interconnect><direct><port type='input' ...><port type='output' ...></direct><YYY../></interconnect>
+ to
+ <interconnect><direct input='...' name='xxx-xxx' output='...'><YYY../></direct></interconnect>
+ -->
+ <xsl:template match="interconnect/direct/port[@type='input']">
+ <xsl:attribute name="input"><xsl:call-template name="from-pb_type"/>.<xsl:call-template name="port-value"/></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="interconnect/direct/port[@type='output']">
+ <xsl:attribute name="name"><xsl:call-template name="from-pb_type"/>-<xsl:call-template name="port-value"/></xsl:attribute>
+ <xsl:attribute name="output"><xsl:call-template name="from-pb_type"/>.<xsl:call-template name="port-value"/></xsl:attribute>
+ </xsl:template>
+
+ <!--
+ Convert
+ <interconnect><mux><port type='input' ...><port type='input' ...><port type='output' ...></mux><YYY../></interconnect>
+ to
+ <interconnect><mux input='in1 in2' name='xxx-xxx' output='...'><YYY../></mux></interconnect>
+ -->
+ <xsl:template match="interconnect/mux/port"></xsl:template>
+ <xsl:template match="interconnect/mux">
+ <xsl:copy>
+ <xsl:attribute name="input">
+ <xsl:for-each select="port[@type='input']">
+ <xsl:call-template name="from-pb_type"/>.<xsl:call-template name="port-value"/>
+ <xsl:if test="position() != last()"><xsl:text> </xsl:text></xsl:if>
+ </xsl:for-each>
+ </xsl:attribute>
+ <xsl:attribute name="output">
+ <xsl:for-each select="port[@type='output']">
+ <xsl:call-template name="from-pb_type"/>.<xsl:call-template name="port-value"/>
+ </xsl:for-each>
+ </xsl:attribute>
+ <xsl:for-each select="@*"><xsl:copy /></xsl:for-each>
+ <xsl:if test="metadata">
+ <metadata><xsl:text>
</xsl:text>
+ <!-- The fasm_mux metadata attribute needs special handling. -->
+ <xsl:if test="*/metadata/meta[@name='fasm_mux']">
+ <meta name="fasm_mux"><xsl:text>
</xsl:text>
+ <xsl:for-each select="port[@type='input']">
+ <xsl:call-template name="from-pb_type"/>.<xsl:call-template name="port-value"/><xsl:text> : </xsl:text><xsl:value-of select="metadata/meta[@name='fasm_mux']" /><xsl:text>
</xsl:text>
+ </xsl:for-each>
+ </meta>
+ </xsl:if>
+ <xsl:for-each select="metadata">
+ <xsl:apply-templates/>
+ </xsl:for-each>
+ </metadata><xsl:text>
</xsl:text>
+ </xsl:if>
+ <xsl:apply-templates/>
+ </xsl:copy>
+ </xsl:template>
+ <xsl:template match="interconnect/mux/metadata"></xsl:template>
+
+ <!--
+ Convert
+ <loc ...><port ...><port ...></loc>
+ to
+ <loc ...>BLOCK.PORT BLOCK.PORT</loc>
+ -->
+ <xsl:template match="pinlocations/loc/port">
+ <xsl:text>
</xsl:text>
+ <xsl:call-template name="from-pb_type"/>.<xsl:call-template name="port-value"/>
+ </xsl:template>
+ <xsl:template match="pinlocations/loc/port[last()]">
+ <xsl:text>
</xsl:text>
+ <xsl:call-template name="from-pb_type"/>.<xsl:call-template name="port-value"/>
+ <xsl:text>
</xsl:text>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/vtr_xml_utils/resources/convert-prefix-port.xsl b/vtr_xml_utils/resources/convert-prefix-port.xsl
new file mode 100644
index 0000000..c7f8867
--- /dev/null
+++ b/vtr_xml_utils/resources/convert-prefix-port.xsl
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <xsl:include href="identity.xsl" />
+
+ <!-- template-function: Allow from attribute which gives you a relative to a given pb_type -->
+ <xsl:template name="parent-pb_type">
+ <xsl:value-of select="ancestor::pb_type[1]/@name"/>
+ </xsl:template>
+
+ <xsl:template match="pack_pattern/@in_port">
+ <xsl:copy />
+ </xsl:template>
+ <xsl:template match="pack_pattern/@out_port">
+ <xsl:copy />
+ </xsl:template>
+
+ <!-- Prefix in_port / out_port values with the parent name. -->
+ <xsl:template match="@out_port[not(contains(.,'.'))]">
+ <xsl:attribute name="out_port"><xsl:call-template name="parent-pb_type"/>.<xsl:value-of select="."/></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="@in_port[not(contains(.,'.'))]">
+ <xsl:attribute name="in_port"><xsl:call-template name="parent-pb_type"/>.<xsl:value-of select="."/></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="@port[not(contains(.,'.'))]">
+ <xsl:attribute name="port"><xsl:call-template name="parent-pb_type"/>.<xsl:value-of select="."/></xsl:attribute>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/vtr_xml_utils/resources/fpga_architecture.xsd b/vtr_xml_utils/resources/fpga_architecture.xsd
new file mode 100644
index 0000000..c5e8908
--- /dev/null
+++ b/vtr_xml_utils/resources/fpga_architecture.xsd
@@ -0,0 +1,874 @@
+<?xml version="1.0"?>
+<!--
+ Copyright 2018 Jeppe Johansen
+
+ XML 1.0 Schema for the FPGA architecture description structure developed based on documentation here:
+ http://vtr-verilog-to-routing.readthedocs.io/en/latest/arch/index.html
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ <!-- Metadata -->
+ <xs:complexType name="meta">
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="metadata">
+ <xs:sequence>
+ <xs:element name="meta" type="meta" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:simpleType name="stringlist">
+ <xs:list itemType="xs:string"/>
+ </xs:simpleType>
+
+ <xs:simpleType name="intlist">
+ <xs:list itemType="xs:int"/>
+ </xs:simpleType>
+
+ <xs:simpleType name="floatlist">
+ <xs:list itemType="xs:float"/>
+ </xs:simpleType>
+
+ <!-- Actual definitions -->
+ <xs:complexType name="port">
+ <xs:attribute name="name" type="xs:string" use="required" />
+ <xs:attribute name="is_clock" type="xs:boolean" />
+ <xs:attribute name="is_non_clock_global" type="xs:boolean" />
+ <xs:attribute name="clock" type="xs:string" />
+ <xs:attribute name="combinational_sink_ports" type="stringlist" />
+ </xs:complexType>
+
+ <xs:complexType name="port_list">
+ <xs:sequence>
+ <xs:element name="port" type="port" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="model">
+ <xs:all>
+ <xs:element name="input_ports" type="port_list" minOccurs="0"/>
+ <xs:element name="output_ports" type="port_list" minOccurs="0"/>
+ </xs:all>
+ <xs:attribute name="name" type="xs:string" use="required" />
+ </xs:complexType>
+
+ <xs:complexType name="models">
+ <xs:sequence>
+ <xs:element name="model" type="model" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="fill">
+ <xs:sequence>
+ <xs:element name="metadata" type="metadata" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="type" type="xs:string" use="required"/>
+ <xs:attribute name="priority" type="xs:int" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="perimeter">
+ <xs:sequence>
+ <xs:element name="metadata" type="metadata" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="type" type="xs:string" use="required"/>
+ <xs:attribute name="priority" type="xs:int" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="corners">
+ <xs:sequence>
+ <xs:element name="metadata" type="metadata" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="type" type="xs:string" use="required"/>
+ <xs:attribute name="priority" type="xs:int" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="single">
+ <xs:sequence>
+ <xs:element name="metadata" type="metadata" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="type" type="xs:string" use="required"/>
+ <xs:attribute name="priority" type="xs:int" use="required"/>
+ <xs:attribute name="x" type="xs:string" use="required"/>
+ <xs:attribute name="y" type="xs:string" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="col">
+ <xs:sequence>
+ <xs:element name="metadata" type="metadata" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="type" type="xs:string" use="required"/>
+ <xs:attribute name="priority" type="xs:int" use="required"/>
+ <xs:attribute name="startx" type="xs:string" use="required"/>
+ <xs:attribute name="repeatx" type="xs:string"/>
+ <xs:attribute name="starty" type="xs:string" default="0"/>
+ <xs:attribute name="incry" type="xs:string" default="h"/>
+ </xs:complexType>
+
+ <xs:complexType name="row">
+ <xs:sequence>
+ <xs:element name="metadata" type="metadata" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="type" type="xs:string" use="required"/>
+ <xs:attribute name="priority" type="xs:int" use="required"/>
+ <xs:attribute name="starty" type="xs:string" use="required"/>
+
+ <xs:attribute name="repeaty" type="xs:string"/>
+ <xs:attribute name="startx" type="xs:string" default="0"/>
+ <xs:attribute name="incrx" type="xs:string" default="w"/>
+ </xs:complexType>
+
+ <xs:complexType name="region">
+ <xs:sequence>
+ <xs:element name="metadata" type="metadata" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="type" type="xs:string" use="required"/>
+ <xs:attribute name="priority" type="xs:int" use="required"/>
+
+ <xs:attribute name="startx" type="xs:string" default="0"/>
+ <xs:attribute name="endx" type="xs:string" default="W-1"/>
+ <xs:attribute name="incrx" type="xs:string" default="w"/>
+ <xs:attribute name="repeatx" type="xs:string"/>
+
+ <xs:attribute name="starty" type="xs:string" default="0"/>
+ <xs:attribute name="endy" type="xs:string" default="H-1"/>
+ <xs:attribute name="incry" type="xs:string" default="h"/>
+ <xs:attribute name="repeaty" type="xs:string"/>
+ </xs:complexType>
+
+ <xs:complexType name="layout_info">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="fill" type="fill"/>
+ <xs:element name="perimeter" type="perimeter"/>
+ <xs:element name="corners" type="corners"/>
+ <xs:element name="single" type="single"/>
+ <xs:element name="col" type="col"/>
+ <xs:element name="row" type="row"/>
+ <xs:element name="region" type="region"/>
+ </xs:choice>
+ </xs:complexType>
+
+ <xs:complexType name="auto_layout">
+ <xs:complexContent>
+ <xs:extension base="layout_info">
+ <xs:attribute name="aspect_ratio" type="xs:float" default="1.0" />
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="fixed_layout">
+ <xs:complexContent>
+ <xs:extension base="layout_info">
+ <xs:attribute name="name" type="xs:string" use="required" />
+ <xs:attribute name="width" type="xs:int" use="required" />
+ <xs:attribute name="height" type="xs:int" use="required" />
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="layout">
+ <xs:choice minOccurs="1">
+ <xs:element name="auto_layout" type="auto_layout" maxOccurs="1"/>
+ <xs:element name="fixed_layout" type="fixed_layout" maxOccurs="unbounded"/>
+ </xs:choice>
+ </xs:complexType>
+
+ <xs:simpleType name="switch_block_type">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="wilton"/>
+ <xs:enumeration value="subset"/>
+ <xs:enumeration value="universal"/>
+ <xs:enumeration value="custom"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="fc_type_enum">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="frac"/>
+ <xs:enumeration value="abs"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="chan_distribution">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="gaussian"/>
+ <xs:enumeration value="uniform"/>
+ <xs:enumeration value="pulse"/>
+ <xs:enumeration value="delta"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="chan_dist">
+ <xs:attribute name="distr" type="chan_distribution" use="required"/>
+ <xs:attribute name="peak" type="xs:float" use="required"/>
+ <xs:attribute name="width" type="xs:float"/>
+ <xs:attribute name="xpeak" type="xs:float"/>
+ <xs:attribute name="dc" type="xs:float"/>
+ </xs:complexType>
+
+ <xs:complexType name="chan_width_distr">
+ <xs:all>
+ <xs:element name="x" type="chan_dist"/>
+ <xs:element name="y" type="chan_dist"/>
+ </xs:all>
+ </xs:complexType>
+
+ <xs:complexType name="device">
+ <xs:all>
+ <xs:element name="sizing">
+ <xs:complexType>
+ <xs:attribute name="R_minW_nmos" type="xs:float" use="required"/>
+ <xs:attribute name="R_minW_pmos" type="xs:float" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="connection_block">
+ <xs:complexType>
+ <xs:attribute name="input_switch_name" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="area">
+ <xs:complexType>
+ <xs:attribute name="grid_logic_tile_area" type="xs:float" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="switch_block">
+ <xs:complexType>
+ <xs:attribute name="type" type="switch_block_type" use="required"/>
+ <xs:attribute name="fs" type="xs:int" default="3"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="chan_width_distr" minOccurs="0" type="chan_width_distr"/>
+ <xs:element name="default_fc" minOccurs="0">
+ <xs:complexType>
+ <xs:attribute name="in_type" type="fc_type_enum" use="required"/>
+ <xs:attribute name="in_val" type="xs:float" use="required"/>
+ <xs:attribute name="out_type" type="fc_type_enum" use="required"/>
+ <xs:attribute name="out_val" type="xs:float" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:all>
+ </xs:complexType>
+
+ <xs:simpleType name="switch_type">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="mux"/>
+ <xs:enumeration value="tristate"/>
+ <xs:enumeration value="pass_gate"/>
+ <xs:enumeration value="short"/>
+ <xs:enumeration value="buffer"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="buf_size">
+ <xs:union memberTypes="xs:float">
+ <xs:simpleType>
+ <xs:restriction base="xs:NMTOKEN">
+ <xs:enumeration value="auto"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+
+ <xs:complexType name="switch">
+ <xs:sequence>
+ <xs:element name="Tdel" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="num_inputs" type="xs:int" use="required"/>
+ <xs:attribute name="delay" type="xs:float" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="type" type="switch_type" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="R" type="xs:float" use="required"/>
+ <xs:attribute name="Cin" type="xs:float" use="required"/>
+ <xs:attribute name="Cinternal" type="xs:float"/>
+ <xs:attribute name="Cout" type="xs:float"/>
+ <xs:attribute name="Tdel" type="xs:float"/>
+ <xs:attribute name="buf_size" type="buf_size" default="auto"/>
+ <xs:attribute name="mux_trans_size" type="xs:float"/>
+ <xs:attribute name="power_buf_size" type="xs:int"/>
+ </xs:complexType>
+
+ <xs:complexType name="switchlist">
+ <xs:sequence>
+ <xs:element name="switch" type="switch" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:simpleType name="pb_type_class">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="lut"/>
+ <xs:enumeration value="flipflop"/>
+ <xs:enumeration value="memory"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="input_equivalent">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="none"/>
+ <xs:enumeration value="full"/>
+ <xs:enumeration value="instance"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="input_port">
+ <xs:sequence>
+ <xs:element name="metadata" type="metadata" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="equivalent" type="input_equivalent" default="none"/>
+ <xs:attribute name="num_pins" type="xs:int" use="required"/>
+ <xs:attribute name="is_non_clock_global" type="xs:boolean"/>
+ <xs:attribute name="port_class" type="xs:string" />
+ </xs:complexType>
+
+ <xs:simpleType name="output_equivalent">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="none"/>
+ <xs:enumeration value="full"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="output_port">
+ <xs:sequence>
+ <xs:element name="metadata" type="metadata" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="equivalent" type="output_equivalent" default="none"/>
+ <xs:attribute name="num_pins" type="xs:int" use="required"/>
+ <xs:attribute name="port_class" type="xs:string" />
+ </xs:complexType>
+
+ <xs:simpleType name="clock_equivalent">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="none"/>
+ <xs:enumeration value="full"/>
+ <xs:enumeration value="instance"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="clock_port">
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="equivalent" type="clock_equivalent" default="none"/>
+ <xs:attribute name="num_pins" type="xs:int" use="required"/>
+ <xs:attribute name="port_class" type="xs:string"/>
+ </xs:complexType>
+
+ <xs:simpleType name="delay_matrix_type">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="min"/>
+ <xs:enumeration value="max"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="delay_matrix">
+ <xs:simpleContent>
+ <xs:extension base="floatlist">
+ <xs:attribute name="type" type="delay_matrix_type" use="required"/>
+ <xs:attribute name="in_port" type="xs:string" use="required"/>
+ <xs:attribute name="out_port" type="xs:string" use="required"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="T_timing_minmax">
+ <xs:attribute name="max" type="xs:float"/>
+ <xs:attribute name="min" type="xs:float"/>
+ <xs:attribute name="in_port" type="xs:string" use="required"/>
+ <xs:attribute name="out_port" type="xs:string" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="T_timing">
+ <xs:attribute name="value" type="xs:float" use="required"/>
+ <xs:attribute name="port" type="xs:string" use="required"/>
+ <xs:attribute name="clock" type="xs:string" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="T_clock_timing">
+ <xs:attribute name="max" type="xs:float"/>
+ <xs:attribute name="min" type="xs:float"/>
+ <xs:attribute name="port" type="xs:string" use="required"/>
+ <xs:attribute name="clock" type="xs:string" use="required"/>
+ </xs:complexType>
+
+ <xs:group name="timing_group">
+ <xs:choice>
+ <xs:element name="delay_constant" type="T_timing_minmax"/>
+ <xs:element name="delay_matrix" type="delay_matrix"/>
+ </xs:choice>
+ </xs:group>
+
+ <xs:group name="timing_group_pbtype">
+ <xs:choice>
+ <xs:group ref="timing_group" minOccurs="0"/>
+ <xs:element name="T_setup" type="T_timing"/>
+ <xs:element name="T_hold" type="T_timing"/>
+ <xs:element name="T_clock_to_Q" type="T_clock_timing"/>
+ </xs:choice>
+ </xs:group>
+
+ <xs:complexType name="interconnect_type">
+ <xs:choice maxOccurs="unbounded">
+ <xs:element name="pack_pattern" type="pack_pattern"/>
+ <xs:group ref="timing_group" minOccurs="0"/>
+ <xs:element name="metadata" type="metadata"/>
+ </xs:choice>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="input" type="stringlist" use="required"/>
+ <xs:attribute name="output" type="stringlist" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="pack_pattern">
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="in_port" type="stringlist" use="required"/>
+ <xs:attribute name="out_port" type="stringlist" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="interconnect">
+ <xs:choice maxOccurs="unbounded">
+ <xs:element name="complete" type="interconnect_type"/>
+ <xs:element name="direct" type="interconnect_type"/>
+ <xs:element name="mux" type="interconnect_type"/>
+ </xs:choice>
+ </xs:complexType>
+
+ <xs:simpleType name="power_estimation_method">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="specify-size"/>
+ <xs:enumeration value="auto-size"/>
+ <xs:enumeration value="pin-toggle"/>
+ <xs:enumeration value="C-internal"/>
+ <xs:enumeration value="absolute"/>
+ <xs:enumeration value="ignore"/>
+ <xs:enumeration value="sum-of-children"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="power_dynamic_power">
+ <xs:attribute name="power_per_instance" type="xs:float"/>
+ <xs:attribute name="C_internal" type="xs:float"/>
+ </xs:complexType>
+
+ <xs:complexType name="power_static_power">
+ <xs:attribute name="power_per_instance" type="xs:float"/>
+ </xs:complexType>
+
+ <xs:complexType name="power_port">
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="energy_per_toggle" type="xs:float" use="required"/>
+ <xs:attribute name="scaled_by_static_prob" type="xs:string"/>
+ <xs:attribute name="scaled_by_static_prob_n" type="xs:string"/>
+ </xs:complexType>
+
+ <xs:complexType name="gpower_local_interconnect">
+ <xs:attribute name="C_wire" type="xs:float" default="0"/>
+ <xs:attribute name="factor" type="xs:float" default="0.5"/>
+ </xs:complexType>
+
+ <xs:complexType name="gpower_buffers">
+ <xs:attribute name="logical_effort_factor" type="xs:float" default="4"/>
+ </xs:complexType>
+
+ <xs:complexType name="gpower_ff_size">
+ <xs:attribute name="FF_size" type="xs:float" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="gpower_LUT_transistor_size">
+ <xs:attribute name="LUT_transistor_size" type="xs:float" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="gpower_mux_transistor_size">
+ <xs:attribute name="mux_transistor_size" type="xs:float" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="gpower_sram">
+ <xs:attribute name="transistors_per_bit" type="xs:float" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="power">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="dynamic_power" type="power_dynamic_power"/>
+ <xs:element name="static_power" type="power_static_power"/>
+ <xs:element name="port" type="power_port"/>
+ </xs:choice>
+ <xs:attribute name="method" type="power_estimation_method" default="auto-size"/>
+ </xs:complexType>
+
+<!-- Global power is very schema-unfriendly. Default values are assigned if the elements
+ holding the attributes aren't present. There is no way for XSD to know that.
+ It could be much better if the <power> tag had all these settings as its own attributes. -->
+ <xs:complexType name="global_power">
+ <xs:choice maxOccurs="unbounded">
+ <xs:element name="local_interconnect" type="gpower_local_interconnect"/>
+ <xs:element name="buffers" type="gpower_buffers"/>
+ <xs:element name="sram" type="gpower_sram"/>
+ <xs:element name="mux_transistor_size" type="gpower_mux_transistor_size"/>
+ <xs:element name="FF_size" type="gpower_ff_size"/>
+ <xs:element name="LUT_transistor_size" type="gpower_LUT_transistor_size"/>
+ </xs:choice>
+ <xs:attribute name="method" type="power_estimation_method" default="auto-size"/>
+ </xs:complexType>
+
+ <xs:simpleType name="pinlocations_pattern">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="spread"/>
+ <xs:enumeration value="spread_inputs_perimeter_outputs"/>
+ <xs:enumeration value="perimeter"/>
+ <xs:enumeration value="custom"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="loc_side">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="left"/>
+ <xs:enumeration value="right"/>
+ <xs:enumeration value="bottom"/>
+ <xs:enumeration value="top"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="loc">
+ <xs:simpleContent>
+ <xs:extension base="stringlist">
+ <xs:attribute name="side" type="loc_side" use="required"/>
+ <xs:attribute name="xoffset" type="xs:int" default="0"/>
+ <xs:attribute name="yoffset" type="xs:int" default="0"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="pinlocations">
+ <xs:sequence>
+ <xs:element name="loc" type="loc" maxOccurs="unbounded" minOccurs="0" />
+ </xs:sequence>
+ <xs:attribute name="pattern" type="pinlocations_pattern"/>
+ </xs:complexType>
+
+ <xs:simpleType name="switchblock_locations_pattern">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="external_full_internal_straight"/>
+ <xs:enumeration value="all"/>
+ <xs:enumeration value="external"/>
+ <xs:enumeration value="internal"/>
+ <xs:enumeration value="none"/>
+ <xs:enumeration value="custom"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="sb_loc_type">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="full"/>
+ <xs:enumeration value="straight"/>
+ <xs:enumeration value="turns"/>
+ <xs:enumeration value="none"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="sb_loc">
+ <xs:attribute name="type" type="sb_loc_type" default="full"/>
+ <xs:attribute name="xoffset" type="xs:int" default="0"/>
+ <xs:attribute name="yoffset" type="xs:int" default="0"/>
+ <xs:attribute name="switch_override" type="xs:string"/>
+ </xs:complexType>
+
+ <xs:complexType name="switchblock_locations">
+ <xs:sequence>
+ <xs:element name="sb_loc" type="sb_loc" maxOccurs="unbounded" minOccurs="0" />
+ </xs:sequence>
+ <xs:attribute name="pattern" type="switchblock_locations_pattern" default="external_full_internal_straight"/>
+ <xs:attribute name="internal_switch" type="xs:string"/>
+ </xs:complexType>
+
+ <xs:complexType name="fc">
+ <xs:sequence>
+ <xs:element name="fc_override" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="fc_type" type="fc_type_enum" use="required"/>
+ <xs:attribute name="fc_val" type="xs:float" use="required"/>
+ <xs:attribute name="port_name" type="xs:string"/>
+ <xs:attribute name="segment_name" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="in_type" type="fc_type_enum" use="required"/>
+ <xs:attribute name="in_val" type="xs:float" use="required"/>
+ <xs:attribute name="out_type" type="fc_type_enum" use="required"/>
+ <xs:attribute name="out_val" type="xs:float" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="mode">
+ <xs:choice maxOccurs="unbounded" minOccurs="0">
+ <xs:element name="pb_type" type="pb_type"/>
+ <xs:element name="interconnect" type="interconnect"/>
+ <xs:element name="pinlocations" type="pinlocations"/>
+ <xs:element name="switchblock_locations" type="switchblock_locations"/>
+ <xs:element name="metadata" type="metadata"/>
+ </xs:choice>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="map">
+ <xs:attribute name="from" type="xs:string" use="required"/>
+ <xs:attribute name="to" type="xs:string" use="required"/>
+ <xs:attribute name="num_pins" type="xs:string"/>
+ </xs:complexType>
+
+ <xs:complexType name="tile_mode">
+ <xs:choice maxOccurs="unbounded" minOccurs="0">
+ <xs:element name="map" type="map"/>
+ </xs:choice>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="equivalent_sites">
+ <xs:choice maxOccurs="unbounded" minOccurs="0">
+ <xs:element name="site"/>
+ </xs:choice>
+ </xs:complexType>
+
+ <xs:complexType name="tile">
+ <xs:choice maxOccurs="unbounded" minOccurs="0">
+ <xs:element name="input" type="input_port"/>
+ <xs:element name="output" type="output_port"/>
+ <xs:element name="clock" type="clock_port"/>
+ <xs:element name="equivalent_sites" type="equivalent_sites"/>
+ <xs:element name="pinlocations" type="pinlocations"/>
+ <xs:element name="fc" type="fc"/>
+ <xs:element name="switchblock_locations" type="switchblock_locations"/>
+ </xs:choice>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="capacity" type="xs:int"/>
+ <xs:attribute name="width" type="xs:int"/>
+ <xs:attribute name="height" type="xs:int"/>
+ <xs:attribute name="area" type="xs:float"/>
+ </xs:complexType>
+
+ <xs:complexType name="tiles">
+ <xs:sequence>
+ <xs:element name="tile" type="tile" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="pb_type">
+ <xs:choice maxOccurs="unbounded" minOccurs="0">
+ <xs:element name="pb_type" type="pb_type"/>
+ <xs:element name="input" type="input_port"/>
+ <xs:element name="output" type="output_port"/>
+ <xs:element name="clock" type="clock_port"/>
+ <xs:element name="metadata" type="metadata"/>
+ <xs:element name="mode" type="mode"/>
+ <xs:element name="interconnect" type="interconnect"/>
+ <xs:group ref="timing_group_pbtype"/>
+ <xs:element name="power" type="power"/>
+ </xs:choice>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="num_pb" type="xs:int"/>
+ <xs:attribute name="blif_model" type="xs:string"/>
+ <xs:attribute name="class" type="pb_type_class"/>
+ </xs:complexType>
+
+ <xs:simpleType name="segment_type">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="bidir"/>
+ <xs:enumeration value="unidir"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="segment_length">
+ <xs:union memberTypes="xs:nonNegativeInteger">
+ <xs:simpleType>
+ <xs:restriction base="xs:NMTOKEN">
+ <xs:enumeration value="longline"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+
+ <xs:complexType name="complexblocklist">
+ <xs:sequence>
+ <xs:element name="pb_type" type="pb_type" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="segment_block">
+ <xs:simpleContent>
+ <xs:extension base="intlist">
+ <xs:attribute name="type" type="xs:string" use="required" fixed="pattern"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="segment_mux">
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="segment_wire_switch">
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+
+<!-- Segment type relies on the "type" attr to determine the required children.
+ XSD 1.1 provides an <alternative> tag to check some attribute and choose a sub-type.
+ Segment wire_switches and opin_switches correspond to switch names.
+ XSD 1.1 also provides a <keyref> tag which asserts a correspondence to some value
+ at an XPath.
+ Being able to use these tags requires some work in the parser generator.
+ Therefore, for now, further validation about segments should be implemented in the postprocessor. -->
+ <xs:complexType name="segment">
+ <xs:choice maxOccurs="unbounded">
+ <xs:element name="sb" type="segment_block"/>
+ <xs:element name="cb" type="segment_block"/>
+ <xs:element name="mux" type="segment_mux"/>
+ <xs:element name="wire_switch" type="segment_wire_switch"/>
+ <xs:element name="opin_switch" type="segment_wire_switch"/>
+ </xs:choice>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="length" type="segment_length" use="required"/>
+ <xs:attribute name="type" type="segment_type" use="required"/>
+ <xs:attribute name="freq" type="xs:float" use="required"/>
+ <xs:attribute name="Rmetal" type="xs:float" use="required"/>
+ <xs:attribute name="Cmetal" type="xs:float" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="segmentlist">
+ <xs:sequence>
+ <xs:element name="segment" type="segment" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="direct">
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="from_pin" type="xs:string" use="required"/>
+ <xs:attribute name="to_pin" type="xs:string" use="required"/>
+ <xs:attribute name="x_offset" type="xs:int" use="required"/>
+ <xs:attribute name="y_offset" type="xs:int" use="required"/>
+ <xs:attribute name="z_offset" type="xs:int" use="required"/>
+ <xs:attribute name="switch_name" type="xs:string"/>
+ </xs:complexType>
+
+ <xs:complexType name="directlist">
+ <xs:sequence>
+ <xs:element name="direct" type="direct" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:simpleType name="switchblock_location_type">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="EVERYWHERE"/>
+ <xs:enumeration value="PERIMETER"/>
+ <xs:enumeration value="CORNER"/>
+ <xs:enumeration value="FRINGE"/>
+ <xs:enumeration value="CORE"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="switchblock_location">
+ <xs:attribute name="type" type="switchblock_location_type" use="required"/>
+ </xs:complexType>
+
+ <xs:simpleType name="switchblock_type">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="bidir"/>
+ <xs:enumeration value="unidir"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="func_type">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="lt"/>
+ <xs:enumeration value="lr"/>
+ <xs:enumeration value="lb"/>
+ <xs:enumeration value="tr"/>
+ <xs:enumeration value="tb"/>
+ <xs:enumeration value="tl"/>
+ <xs:enumeration value="rb"/>
+ <xs:enumeration value="rl"/>
+ <xs:enumeration value="rt"/>
+ <xs:enumeration value="bl"/>
+ <xs:enumeration value="bt"/>
+ <xs:enumeration value="br"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="switchblock_func">
+ <xs:sequence>
+ <xs:element name="func" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="type" type="func_type" use="required" />
+ <xs:attribute name="formula" type="xs:string" use="required" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="wireconn_connection">
+ <xs:attribute name="type" type="xs:string" use="required"/>
+ <xs:attribute name="switchpoint" type="xs:string" use="required"/>
+ </xs:complexType>
+
+<!-- It would be better to change the string or int lists here to use whitespace as a
+ delimiter instead of commas, so they can be expressed as <xs:list>s instead of
+ just strings. -->
+ <xs:complexType name="wireconn">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="from" type="wireconn_connection" maxOccurs="unbounded"/>
+ <xs:element name="to" type="wireconn_connection" maxOccurs="unbounded"/>
+ </xs:choice>
+ <xs:attribute name="num_conns_type" type="xs:string" use="required"/>
+ <xs:attribute name="from_type" type="xs:string"/>
+ <xs:attribute name="to_type" type="xs:string"/>
+ <xs:attribute name="from_switchpoint" type="xs:string"/>
+ <xs:attribute name="to_switchpoint" type="xs:string"/>
+ </xs:complexType>
+
+ <xs:complexType name="switchblock">
+ <xs:sequence>
+ <xs:element name="switchblock_location" type="switchblock_location"/>
+ <xs:element name="switchfuncs" type="switchblock_func"/>
+ <xs:element name="wireconn" type="wireconn" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="type" type="switchblock_type" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="switchblocklist">
+ <xs:sequence>
+ <xs:element name="switchblock" type="switchblock" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="clock">
+ <xs:attribute name="C_wire" type="xs:float"/>
+ <xs:attribute name="C_wire_per_m" type="xs:float"/>
+ <xs:attribute name="buffer_size" type="buf_size"/>
+ </xs:complexType>
+
+ <xs:complexType name="clocks">
+ <xs:sequence>
+ <xs:element name="clock" type="clock" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:element name="architecture">
+ <xs:complexType>
+ <xs:all>
+ <xs:element name="models" type="models"/>
+ <xs:element name="layout" type="layout"/>
+ <xs:element name="device" type="device"/>
+ <xs:element name="switchlist" type="switchlist"/>
+ <xs:element name="segmentlist" type="segmentlist"/>
+ <xs:element name="switchblocklist" type="switchblocklist" minOccurs="0"/>
+ <xs:element name="complexblocklist" type="complexblocklist"/>
+ <xs:element name="directlist" type="directlist" minOccurs="0"/>
+ <xs:element name="power" type="global_power" minOccurs="0"/>
+ <xs:element name="clocks" type="clocks" minOccurs="0"/>
+ <xs:element name="tiles" type="tiles" minOccurs="0"/>
+ </xs:all>
+ </xs:complexType>
+ </xs:element>
+
+</xs:schema>
diff --git a/vtr_xml_utils/resources/identity.xsl b/vtr_xml_utils/resources/identity.xsl
new file mode 100644
index 0000000..23ff094
--- /dev/null
+++ b/vtr_xml_utils/resources/identity.xsl
@@ -0,0 +1,30 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+ <xsl:output method="xml" indent="yes"/>
+ <xsl:strip-space elements="*"/>
+
+ <xsl:template match="@*">
+ <xsl:copy/>
+ </xsl:template>
+
+ <xsl:template match="*">
+ <xsl:copy>
+ <xsl:apply-templates select="@*"/>
+ <xsl:apply-templates/>
+ </xsl:copy>
+ </xsl:template>
+
+ <xsl:template match="text()|processing-instruction()">
+ <xsl:copy>
+ <xsl:apply-templates select="text()|processing-instruction()"/>
+ </xsl:copy>
+ </xsl:template>
+
+ <xsl:param name="strip_comments" select="''" />
+ <xsl:template match="comment()">
+ <xsl:choose>
+ <xsl:when test="$strip_comments"></xsl:when>
+ <xsl:otherwise><xsl:copy /></xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/vtr_xml_utils/resources/pack-patterns.xsl b/vtr_xml_utils/resources/pack-patterns.xsl
new file mode 100644
index 0000000..0203b5c
--- /dev/null
+++ b/vtr_xml_utils/resources/pack-patterns.xsl
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <xsl:include href="identity.xsl" />
+
+ <!--
+ Strip pack_pattern's from input/output tags on pb_types.
+ -->
+ <xsl:template match="pb_type/input/pack_pattern"/>
+ <xsl:template match="pb_type/output/pack_pattern"/>
+
+ <!--
+ Convert
+ <pack_pattern name="xxx" type="yyy"
+ to
+ <pack_pattern name="yyy-xxx"
+ -->
+ <xsl:template match="pack_pattern/@type"/>
+ <xsl:template match="pack_pattern[@type]/@name">
+ <xsl:attribute name="name">
+ <xsl:value-of select="../@type"/>-<xsl:value-of select="../@name"/>
+ </xsl:attribute>
+ </xsl:template>
+ <xsl:template match="pack_pattern[not(@type)]/@name">
+ <xsl:copy />
+ </xsl:template>
+ <xsl:template match="pack_pattern/*">
+ <xsl:copy />
+ </xsl:template>
+
+ <!--
+ Convert
+ <interconnect><direct input="IN" output="OUT"><pack_pattern name="PACK"/></direct></interconnect>
+ to
+ <interconnect><direct input="IN" output="OUT"><pack_pattern name="PACK" in_port="IN" out_port="OUT"/></direct></interconnect>
+ -->
+ <xsl:template match="direct[@input and @output]/pack_pattern">
+ <xsl:copy>
+ <xsl:attribute name="in_port"><xsl:value-of select="../@input" /></xsl:attribute>
+ <xsl:attribute name="out_port"><xsl:value-of select="../@output" /></xsl:attribute>
+ <xsl:apply-templates select="@*"></xsl:apply-templates>
+ </xsl:copy>
+ <xsl:apply-templates/>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/vtr_xml_utils/resources/packed_netlist.xsd b/vtr_xml_utils/resources/packed_netlist.xsd
new file mode 100644
index 0000000..90631af
--- /dev/null
+++ b/vtr_xml_utils/resources/packed_netlist.xsd
@@ -0,0 +1,80 @@
+<?xml version="1.0"?>
+<!--
+ Copyright 2018 Jeppe Johansen
+
+ XML 1.0 Schema for packed netlist format developed based on documentation here:
+ http://vtr-verilog-to-routing.readthedocs.io/en/latest/vpr/file_formats.html#packed-netlist-format-net
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ <xs:complexType name="named_value">
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="port">
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="port_rotation_map">
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="port_group" mixed="true">
+ <xs:sequence>
+ <xs:element name="port" type="port" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="block">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="inputs">
+ <xs:complexType mixed="true">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="port" type="port"/>
+ <xs:element name="port_rotation_map" type="port_rotation_map"/>
+ </xs:choice>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="outputs" type="port_group"/>
+ <xs:element name="clocks" type="port_group"/>
+ <xs:element name="attributes">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="attribute" type="named_value" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="parameters">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="parameter" type="named_value" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="block" type="block"/>
+ </xs:choice>
+
+ <xs:attribute name="name" type="xs:string"/>
+ <xs:attribute name="instance" type="xs:string"/>
+ <xs:attribute name="mode" type="xs:string"/>
+ <xs:attribute name="architecture_id" type="xs:string"/>
+ <xs:attribute name="atom_netlist_id" type="xs:string"/>
+ <xs:attribute name="pb_type_num_modes" type="xs:integer"/>
+ </xs:complexType>
+
+ <xs:element name="block" type="block"/>
+
+</xs:schema>
diff --git a/vtr_xml_utils/resources/remove-duplicate-models.xsl b/vtr_xml_utils/resources/remove-duplicate-models.xsl
new file mode 100644
index 0000000..3166d53
--- /dev/null
+++ b/vtr_xml_utils/resources/remove-duplicate-models.xsl
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <xsl:include href="identity.xsl" />
+
+ <!-- Remove duplicate model nodes -->
+ <xsl:key name="model-by-name" match="model" use="@name" />
+ <xsl:template match="models">
+ <models>
+ <xsl:for-each select="model[count(. | key('model-by-name', @name)[1]) = 1]">
+ <xsl:copy>
+ <xsl:attribute name="name"><xsl:value-of select="@name"/></xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:copy>
+ </xsl:for-each>
+ </models>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/vtr_xml_utils/resources/routing_resource.xsd b/vtr_xml_utils/resources/routing_resource.xsd
new file mode 100644
index 0000000..f890844
--- /dev/null
+++ b/vtr_xml_utils/resources/routing_resource.xsd
@@ -0,0 +1,280 @@
+<?xml version="1.0"?>
+<!--
+ Copyright 2018 Jeppe Johansen
+
+ XML 1.0 Schema for rr_graph structure developed based on documentation here:
+ http://vtr-verilog-to-routing.readthedocs.io/en/latest/vpr/file_formats.html#routing-resource-graph-file-format-xml
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ <xs:complexType name="channel">
+ <xs:attribute name="chan_width_max" type="xs:int" use="required"/>
+ <xs:attribute name="x_min" type="xs:int" use="required"/>
+ <xs:attribute name="y_min" type="xs:int" use="required"/>
+ <xs:attribute name="x_max" type="xs:int" use="required"/>
+ <xs:attribute name="y_max" type="xs:int" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="x_list">
+ <xs:attribute name="index" type="xs:unsignedInt" use="required"/>
+ <xs:attribute name="info" type="xs:int" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="y_list">
+ <xs:attribute name="index" type="xs:unsignedInt" use="required"/>
+ <xs:attribute name="info" type="xs:int" use="required"/>
+ </xs:complexType>
+
+ <xs:simpleType name="switch_type">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="mux"/>
+ <xs:enumeration value="tristate"/>
+ <xs:enumeration value="pass_gate"/>
+ <xs:enumeration value="short"/>
+ <xs:enumeration value="buffer"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="timing">
+ <xs:attribute name="R" type="xs:float"/>
+ <xs:attribute name="Cin" type="xs:float"/>
+ <xs:attribute name="Cinternal" type="xs:float"/>
+ <xs:attribute name="Cout" type="xs:float"/>
+ <xs:attribute name="Tdel" type="xs:float"/>
+ </xs:complexType>
+
+ <xs:complexType name="sizing">
+ <xs:attribute name="mux_trans_size" type="xs:float" use="required"/>
+ <xs:attribute name="buf_size" type="xs:float" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="switch">
+ <xs:all>
+ <xs:element name="timing" type="timing" minOccurs="0"/>
+ <xs:element name="sizing" type="sizing"/>
+ </xs:all>
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="type" type="switch_type"/>
+ </xs:complexType>
+
+ <xs:complexType name="segment_timing">
+ <xs:attribute name="R_per_meter" type="xs:float"/>
+ <xs:attribute name="C_per_meter" type="xs:float"/>
+ </xs:complexType>
+
+ <xs:complexType name="segment">
+ <xs:all>
+ <xs:element name="timing" type="segment_timing" minOccurs="0"/>
+ </xs:all>
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="pin">
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="ptc" type="xs:int" use="required"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="pin_class">
+ <xs:sequence>
+ <xs:element name="pin" type="pin" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="type" type="pin_type" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="meta">
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="metadata">
+ <xs:sequence>
+ <xs:element name="meta" type="meta" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="block_type">
+ <xs:sequence>
+ <xs:element name="pin_class" type="pin_class" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="width" type="xs:int" use="required"/>
+ <xs:attribute name="height" type="xs:int" use="required"/>
+ </xs:complexType>
+
+ <xs:simpleType name="pin_type">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="OPEN"/>
+ <xs:enumeration value="OUTPUT"/>
+ <xs:enumeration value="INPUT"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="grid_loc">
+ <xs:attribute name="x" type="xs:int" use="required"/>
+ <xs:attribute name="y" type="xs:int" use="required"/>
+ <xs:attribute name="block_type_id" type="xs:int" use="required"/>
+ <xs:attribute name="width_offset" type="xs:int" use="required"/>
+ <xs:attribute name="height_offset" type="xs:int" use="required"/>
+ </xs:complexType>
+
+ <xs:simpleType name="node_type">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="CHANX"/>
+ <xs:enumeration value="CHANY"/>
+ <xs:enumeration value="SOURCE"/>
+ <xs:enumeration value="SINK"/>
+ <xs:enumeration value="OPIN"/>
+ <xs:enumeration value="IPIN"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="node_direction">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="INC_DIR"/>
+ <xs:enumeration value="DEC_DIR"/>
+ <xs:enumeration value="BI_DIR"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="loc_side">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="LEFT"/>
+ <xs:enumeration value="RIGHT"/>
+ <xs:enumeration value="TOP"/>
+ <xs:enumeration value="BOTTOM"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="node_loc">
+ <xs:attribute name="xlow" type="xs:int" use="required"/>
+ <xs:attribute name="ylow" type="xs:int" use="required"/>
+ <xs:attribute name="xhigh" type="xs:int" use="required"/>
+ <xs:attribute name="yhigh" type="xs:int" use="required"/>
+ <xs:attribute name="side" type="loc_side"/>
+ <xs:attribute name="ptc" type="xs:int" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="node_timing">
+ <xs:attribute name="R" type="xs:float" use="required"/>
+ <xs:attribute name="C" type="xs:float" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="node_segment">
+ <xs:attribute name="segment_id" type="xs:int" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="node">
+ <xs:all>
+ <xs:element name="loc" type="node_loc"/>
+ <xs:element name="timing" type="node_timing" minOccurs="0"/>
+ <xs:element name="segment" type="node_segment" minOccurs="0"/>
+ <xs:element name="metadata" type="metadata" minOccurs="0"/>
+ </xs:all>
+ <xs:attribute name="id" type="xs:unsignedInt" use="required"/>
+ <xs:attribute name="type" type="node_type" use="required"/>
+ <xs:attribute name="direction" type="node_direction"/>
+ <xs:attribute name="capacity" type="xs:unsignedInt" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="edge">
+ <xs:all>
+ <xs:element name="metadata" type="metadata" minOccurs="0"/>
+ </xs:all>
+ <xs:attribute name="id" type="xs:unsignedInt"/>
+ <xs:attribute name="src_node" type="xs:unsignedInt" use="required"/>
+ <xs:attribute name="sink_node" type="xs:unsignedInt" use="required"/>
+ <xs:attribute name="switch_id" type="xs:unsignedInt" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="channels">
+ <xs:sequence>
+ <xs:element name="channel" type="channel"/>
+ <xs:element name="x_list" type="x_list" maxOccurs="unbounded"/>
+ <xs:element name="y_list" type="y_list" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="switches">
+ <xs:sequence>
+ <xs:element name="switch" type="switch" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="segments">
+ <xs:sequence>
+ <xs:element name="segment" type="segment" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="block_types">
+ <xs:sequence>
+ <xs:element name="block_type" type="block_type" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="grid_locs">
+ <xs:sequence>
+ <xs:element name="grid_loc" type="grid_loc" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="rr_nodes">
+ <xs:choice maxOccurs="unbounded">
+ <xs:element name="node" type="node"/>
+ </xs:choice>
+ </xs:complexType>
+
+ <xs:complexType name="rr_edges">
+ <xs:choice maxOccurs="unbounded">
+ <xs:element name="edge" type="edge"/>
+ </xs:choice>
+ </xs:complexType>
+
+ <xs:complexType name="bin_nodes">
+ <xs:attribute name="file" type="xs:string"/>
+ </xs:complexType>
+
+ <xs:complexType name="connection_box">
+ <xs:attribute name="id" type="xs:int"/>
+ <xs:attribute name="name" type="xs:string"/>
+ </xs:complexType>
+
+ <xs:complexType name="connection_boxes">
+ <xs:sequence>
+ <xs:element name="connection_box" type="connection_box" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="x_dim" type="xs:int"/>
+ <xs:attribute name="y_dim" type="xs:int"/>
+ <xs:attribute name="num_boxes" type="xs:int"/>
+ </xs:complexType>
+
+ <xs:element name="rr_graph">
+ <xs:complexType>
+ <xs:all>
+ <xs:element name="binary_nodes_and_edges" type="bin_nodes" minOccurs="0"/>
+ <xs:element name="connection_boxes" type="connection_boxes" minOccurs="0"/>
+ <xs:element name="channels" type="channels"/>
+ <xs:element name="switches" type="switches"/>
+ <xs:element name="segments" type="segments"/>
+ <xs:element name="block_types" type="block_types"/>
+ <xs:element name="grid" type="grid_locs"/>
+ <xs:element name="rr_nodes" type="rr_nodes"/>
+ <xs:element name="rr_edges" type="rr_edges"/>
+ </xs:all>
+
+ <xs:attribute name="tool_name" type="xs:string"/>
+ <xs:attribute name="tool_version" type="xs:string"/>
+ <xs:attribute name="tool_comment" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+
+</xs:schema>
diff --git a/vtr_xml_utils/resources/sort-tags.xsl b/vtr_xml_utils/resources/sort-tags.xsl
new file mode 100644
index 0000000..3507bd8
--- /dev/null
+++ b/vtr_xml_utils/resources/sort-tags.xsl
@@ -0,0 +1,35 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+ <xsl:include href="identity.xsl" />
+
+ <!-- Sort <pb_type><clock> by "name" attribute -->
+ <!-- Sort <pb_type><input> by "name" attribute -->
+ <!-- Sort <pb_type><output> by "name" attribute -->
+ <xsl:template match="pb_type">
+ <xsl:copy>
+ <xsl:apply-templates select="@*"/>
+ <xsl:apply-templates select="clock">
+ <xsl:sort select="@name" order="ascending"/>
+ </xsl:apply-templates>
+ <xsl:apply-templates select="input">
+ <xsl:sort select="@name" order="ascending"/>
+ </xsl:apply-templates>
+ <xsl:apply-templates select="output">
+ <xsl:sort select="@name" order="ascending"/>
+ </xsl:apply-templates>
+ <xsl:apply-templates select="pb_type">
+ <xsl:sort select="@name" order="ascending"/>
+ </xsl:apply-templates>
+ <xsl:apply-templates select="*[not(self::clock or self::input or self::output or self::pb_type)]"/>
+ </xsl:copy>
+ </xsl:template>
+ <!-- Sort <interconnect><XXX> tags by output - direct first then muxes, finally input -->
+ <xsl:template match="interconnect">
+ <xsl:copy>
+ <xsl:apply-templates>
+ <xsl:sort select="concat(@output, name(), @input)" order="ascending"/>
+ </xsl:apply-templates>
+ </xsl:copy>
+ </xsl:template>
+
+</xsl:stylesheet>