xml: Improve xslt transform.

Continue to improve the `xmlsort.xsl` script to be a tool which merges a
modified FPGA architecture.

Currently it also converts a more composable format and converts it into
the format that VtR accepts. Eventually the hope is that upstream VtR
will accept this composable format in the future. See;
https://github.com/verilog-to-routing/vtr-verilog-to-routing/issues/272

Signed-off-by: Tim 'mithro' Ansell <me@mith.ro>
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..09dae54
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(convert_and_merge_composable_tests)
diff --git a/convert_and_merge_composable_fpga_architecture.xsl b/convert_and_merge_composable_fpga_architecture.xsl
new file mode 100644
index 0000000..24b9628
--- /dev/null
+++ b/convert_and_merge_composable_fpga_architecture.xsl
@@ -0,0 +1,170 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+  <xsl:output method="xml" indent="yes"/>
+  <xsl:strip-space elements="*"/>
+
+  <!-- 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: 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>
+
+  <!-- Root match -->
+  <xsl:template match="/">
+    <xsl:apply-templates/>
+  </xsl:template>
+
+  <!-- Normalize space around attributes on a tag -->
+  <xsl:template match="@*">
+    <xsl:copy>
+      <xsl:value-of select="normalize-space( . )" />
+    </xsl:copy>
+  </xsl:template>
+
+  <!-- Sort the attributes by name -->
+  <xsl:template match="*">
+    <xsl:copy>
+      <xsl:apply-templates select="@*" >
+	<xsl:sort select="name()"/>
+      </xsl:apply-templates>
+      <xsl:apply-templates/>
+    </xsl:copy>
+  </xsl:template>
+
+  <!-- Strip xml:base attribute -->
+  <xsl:template match="@xml:base"/>
+
+  <!--
+    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/@name">
+    <xsl:attribute name="name">
+      <xsl:value-of select="../@type"/>-<xsl:value-of select="../@name"/>
+    </xsl:attribute>
+  </xsl:template>
+
+  <!-- Prefix in_port / out_port values with the parent name. -->
+  <xsl:template match="@out_port">
+    <xsl:attribute name="out_port"><xsl:call-template name="from-pb_type"/>.<xsl:value-of select="."/></xsl:attribute>
+  </xsl:template>
+  <xsl:template match="@in_port">
+    <xsl:attribute name="in_port"><xsl:call-template name="from-pb_type"/>.<xsl:value-of select="."/></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><direct><pack_pattern><port type='input' ...><port type='output' ...></pack_pattern></direct><YYY../></interconnect>
+    to
+      <interconnect><direct><pack_pattern in_port="XXXX" out_port="XXXX" /></direct></interconnect>
+    -->
+  <xsl:template match="interconnect/direct/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="interconnect/direct/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><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">
+    <xsl:copy>
+      <xsl:attribute name="name">
+        <xsl:value-of select="@name" />
+      </xsl:attribute>
+      <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:if test="position() != last()"><xsl:text> </xsl:text></xsl:if>
+        </xsl:for-each>
+      </xsl:attribute>
+      <metadata>
+        <meta name="fasm_mux">
+          <xsl:for-each select="port[@type='input']"><xsl:text>
+            </xsl:text><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:for-each><xsl:text>
+        </xsl:text>
+        </meta>
+        <xsl:for-each select="metadata">
+          <xsl:apply-templates/>
+        </xsl:for-each>
+      </metadata>
+    </xsl:copy>
+  </xsl:template>
+
+  <!--
+    Convert
+      <loc ...><port ...><port ...></loc>
+    to
+      <loc ...>BLOCK.PORT BLOCK.PORT</loc>
+    -->
+  <xsl:template match="loc/port"><xsl:text>
+      </xsl:text><xsl:call-template name="from-pb_type"/>.<xsl:call-template name="port-value"/>
+  </xsl:template>
+  <xsl:template match="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>
+
+  <!-- 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:template match="text()|comment()|processing-instruction()">
+    <xsl:copy/>
+  </xsl:template>
+
+</xsl:stylesheet>
diff --git a/convert_and_merge_composable_tests/CMakeLists.txt b/convert_and_merge_composable_tests/CMakeLists.txt
new file mode 100644
index 0000000..3786bf8
--- /dev/null
+++ b/convert_and_merge_composable_tests/CMakeLists.txt
@@ -0,0 +1,9 @@
+include("xsl_tests.cmake")
+xsl_golden_test(NAME "attribute-cleanup")
+xsl_golden_test(NAME "composable-interconnect-fasm-mux-levels")
+xsl_golden_test(NAME "composable-interconnect-fasm-mux")
+xsl_golden_test(NAME "composable-interconnect-implicit-parent")
+xsl_golden_test(NAME "composable-loc-implicit-parent")
+xsl_golden_test(NAME "pack_pattern-merge-type-into-name")
+xsl_golden_test(NAME "pack_pattern-strip-from-pb_type-ports")
+xsl_golden_test(NAME "xml-explicit-port")
diff --git a/convert_and_merge_composable_tests/attribute-cleanup.golden.xml b/convert_and_merge_composable_tests/attribute-cleanup.golden.xml
new file mode 100644
index 0000000..4f0a14d
--- /dev/null
+++ b/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/convert_and_merge_composable_tests/attribute-cleanup.xml b/convert_and_merge_composable_tests/attribute-cleanup.xml
new file mode 100644
index 0000000..decb65e
--- /dev/null
+++ b/convert_and_merge_composable_tests/attribute-cleanup.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   a2="2"   b1="abc"    a1="2">Hello</innertag>
+ </tag>
+</xml>
diff --git a/convert_and_merge_composable_tests/composable-interconnect-fasm-mux-levels.golden.xml b/convert_and_merge_composable_tests/composable-interconnect-fasm-mux-levels.golden.xml
new file mode 100644
index 0000000..064a7be
--- /dev/null
+++ b/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 name="outmux" input="blocka.a blockb.b blockc[0].c blockc[1].c" output="blocko.i">
+        <metadata>
+          <meta name="fasm_mux">
+            blocka.a : a1
+            blockb.b : b1
+            blockc[0].c : c0
+            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/convert_and_merge_composable_tests/composable-interconnect-fasm-mux-levels.xml b/convert_and_merge_composable_tests/composable-interconnect-fasm-mux-levels.xml
new file mode 100644
index 0000000..b3f7424
--- /dev/null
+++ b/convert_and_merge_composable_tests/composable-interconnect-fasm-mux-levels.xml
@@ -0,0 +1,58 @@
+<?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 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</meta>
+     </metadata>
+    </port>
+    <port type="input" name="c" from="blockc[0]">
+     <metadata>
+      <meta name="fasm_mux">c0</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/convert_and_merge_composable_tests/composable-interconnect-fasm-mux.xml b/convert_and_merge_composable_tests/composable-interconnect-fasm-mux.xml
new file mode 100644
index 0000000..a52d9a7
--- /dev/null
+++ b/convert_and_merge_composable_tests/composable-interconnect-fasm-mux.xml
@@ -0,0 +1,36 @@
+<?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>
+    <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/convert_and_merge_composable_tests/composable-interconnect-implicit-parent.xml b/convert_and_merge_composable_tests/composable-interconnect-implicit-parent.xml
new file mode 100644
index 0000000..a9ab9f5
--- /dev/null
+++ b/convert_and_merge_composable_tests/composable-interconnect-implicit-parent.xml
@@ -0,0 +1,25 @@
+<?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>
+    <port type="output" name="o" />
+    <port type="input" from="child" name="o" />
+   </direct>
+   <mux name="mux1">
+    <port type="input" name="i0" />
+    <port type="input" name="i1" />
+    <port type="output" from="child" name="i" />
+   </mux>
+ </interconnect>
+ </pb_type>
+</xml>
diff --git a/convert_and_merge_composable_tests/composable-loc-implicit-parent.xml b/convert_and_merge_composable_tests/composable-loc-implicit-parent.xml
new file mode 100644
index 0000000..d148f05
--- /dev/null
+++ b/convert_and_merge_composable_tests/composable-loc-implicit-parent.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<xml>
+ <pb_type name="parent">
+  <input name="i" width="2" />
+  <loc>
+   <port name="o" />
+   <port name="i" bit="0" />
+   <port name="i" bit="1" />
+  </loc>
+ </pb_type>
+</xml>
diff --git a/convert_and_merge_composable_tests/pack_pattern-merge-type-into-name.golden.xml b/convert_and_merge_composable_tests/pack_pattern-merge-type-into-name.golden.xml
new file mode 100644
index 0000000..34abd19
--- /dev/null
+++ b/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="carry-B"/>
+    </direct>
+    <mux>
+      <pack_pattern name="pack-A">
+        <innertag/>
+      </pack_pattern>
+    </mux>
+  </pb_type>
+</xml>
diff --git a/convert_and_merge_composable_tests/pack_pattern-merge-type-into-name.xml b/convert_and_merge_composable_tests/pack_pattern-merge-type-into-name.xml
new file mode 100644
index 0000000..ae102ea
--- /dev/null
+++ b/convert_and_merge_composable_tests/pack_pattern-merge-type-into-name.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<xml>
+ <pb_type>
+  <direct>
+   <pack_pattern name="B" type="carry" />
+  </direct>
+  <mux>
+   <pack_pattern name="A" type="pack">
+    <innertag />
+   </pack_pattern>
+  </mux>
+ </pb_type>
+</xml>
diff --git a/convert_and_merge_composable_tests/pack_pattern-strip-from-pb_type-ports.golden.xml b/convert_and_merge_composable_tests/pack_pattern-strip-from-pb_type-ports.golden.xml
new file mode 100644
index 0000000..a6d6a3b
--- /dev/null
+++ b/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/convert_and_merge_composable_tests/pack_pattern-strip-from-pb_type-ports.xml b/convert_and_merge_composable_tests/pack_pattern-strip-from-pb_type-ports.xml
new file mode 100644
index 0000000..988de09
--- /dev/null
+++ b/convert_and_merge_composable_tests/pack_pattern-strip-from-pb_type-ports.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<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/convert_and_merge_composable_tests/xml-explicit-port.golden.xml b/convert_and_merge_composable_tests/xml-explicit-port.golden.xml
new file mode 100644
index 0000000..2bd3d8f
--- /dev/null
+++ b/convert_and_merge_composable_tests/xml-explicit-port.golden.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<xml>
+port-name
+port-name[8]
+port-name[8:4]
+</xml>
diff --git a/convert_and_merge_composable_tests/xml-explicit-port.xml b/convert_and_merge_composable_tests/xml-explicit-port.xml
new file mode 100644
index 0000000..a58530f
--- /dev/null
+++ b/convert_and_merge_composable_tests/xml-explicit-port.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<xml>
+  <port name="port-name" />
+  <port name="port-name" bit="8" />
+  <port name="port-name" bit_msb="8" bit_lsb="4" />
+</xml>
diff --git a/convert_and_merge_composable_tests/xsl_tests.cmake b/convert_and_merge_composable_tests/xsl_tests.cmake
new file mode 100644
index 0000000..65d02d1
--- /dev/null
+++ b/convert_and_merge_composable_tests/xsl_tests.cmake
@@ -0,0 +1,44 @@
+# Creating new target to call all the added tests
+add_custom_target(all_xsl_tests ALL)
+
+function(XSL_GOLDEN_TEST)
+  # ~~~
+  # XSL_GOLDEN_TEST(
+  #   NAME name
+  #   TOP_MODULE name
+  #   )
+  # ~~~
+  #
+  # This function is to test both the pb_type XML generation. It will call V2X_TEST_GENERIC multiple times first with the field TYPE set to `pb_type`
+  # then with `model`
+  #
+  # NAME name of the test.
+  # TOP_MODULE name of the top verilog module that has to be tested.
+  #
+  # Usage: v2x_test_model(NAME <test_name> TOP_MODULE <top_module.v>) (All fields are required)
+
+  set(oneValueArgs NAME TOP_MODULE)
+  cmake_parse_arguments(
+    XSL_GOLDEN_TEST
+    "${options}"
+    "${oneValueArgs}"
+    "${multiValueArgs}"
+    ${ARGN}
+  )
+
+  set(NAME ${XSL_GOLDEN_TEST_NAME})
+  set(TOP_MODULE ${XSL_GOLDEN_TEST_TOP_MODULE})
+
+  set(INPUT_XML ${NAME}.xml)
+  add_file_target(FILE ${INPUT_XML} SCANNER_TYPE xml)
+
+  set(ACTUAL_XML ${NAME}.actual.xml)
+  xml_canonicalize_merge(NAME merge_${ACTUAL_XML} FILE ${INPUT_XML} OUTPUT ${ACTUAL_XML})
+
+  set(GOLDEN_XML ${NAME}.golden.xml)
+  add_file_target(FILE ${GOLDEN_XML} SCANNER_TYPE xml)
+
+  diff(NAME diff_${NAME} GOLDEN ${GOLDEN_XML} ACTUAL ${ACTUAL_XML})
+
+  add_dependencies(all_xsl_tests diff_${NAME})
+endfunction(XSL_GOLDEN_TEST)
diff --git a/xmlsort.xsl b/xmlsort.xsl
deleted file mode 100644
index 49c1749..0000000
--- a/xmlsort.xsl
+++ /dev/null
@@ -1,83 +0,0 @@
-<?xml version="1.0"?>
-<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
-
-  <xsl:output method="xml" indent="yes"/>
-  <xsl:strip-space elements="*"/>
-
-  <xsl:template match="/">
-    <xsl:apply-templates/>
-  </xsl:template>
-
-  <xsl:template match="*">
-    <xsl:copy>
-      <!-- Sort the attributes by name and remove the xml:base attribute -->
-      <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>
-
-  <!-- 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>
-
-  <!--
-    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>
-
-  <!--
-    Convert
-      <interconnect><XXX><port type='input' ...><port type='output' ...></XXX><YYY../></interconnect>
-    to
-      <interconnect><XXX input='...' output='...'><YYY../></XXX></interconnect>
-    -->
-  <xsl:template match="interconnect/*/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/*/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
-      <loc ...><port ...><port ...></loc>
-    to
-      <loc ...>BLOCK.PORT BLOCK.PORT</loc>
-    -->
-  <xsl:template match="loc/port"><xsl:text>
-      </xsl:text><xsl:call-template name="from-pb_type"/>.<xsl:call-template name="port-value"/>
-  </xsl:template>
-  <xsl:template match="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>
-
-  <!-- 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:template match="text()|comment()|processing-instruction()">
-    <xsl:copy/>
-  </xsl:template>
-
-</xsl:stylesheet>