xml: Use multiple passes in convert and merge script.

Signed-off-by: Tim 'mithro' Ansell <me@mith.ro>
diff --git a/attribute-fixes.xsl b/attribute-fixes.xsl
new file mode 100644
index 0000000..87c976b
--- /dev/null
+++ b/attribute-fixes.xsl
@@ -0,0 +1,27 @@
+<?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: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/convert_and_merge_composable_fpga_architecture.xsl b/convert-port-tag.xsl
similarity index 61%
rename from convert_and_merge_composable_fpga_architecture.xsl
rename to convert-port-tag.xsl
index a8879db..8e0e1d8 100644
--- a/convert_and_merge_composable_fpga_architecture.xsl
+++ b/convert-port-tag.xsl
@@ -1,8 +1,7 @@
 <?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: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">
@@ -14,9 +13,9 @@
   </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]
+     * <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>
 
@@ -27,62 +26,17 @@
     </xsl:attribute>
   </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
+      <interconnect><xxx><pack_pattern><port type='input' ...><port type='output' ...></pack_pattern></xxx><YYY../></interconnect>
     to
-       <pack_pattern name="yyy-xxx"
+      <interconnect><xxx><pack_pattern in_port="XXXX" out_port="XXXX" /></xxx></interconnect>
     -->
-  <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 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[not(@type)]/@name">
-    <xsl:copy />
-  </xsl:template>
-  <xsl:template match="pack_pattern/*">
-    <xsl:copy />
-  </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 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>
 
   <!--
@@ -99,28 +53,6 @@
     <xsl:attribute name="output"><xsl:call-template name="from-pb_type"/>.<xsl:call-template name="port-value"/></xsl:attribute>
   </xsl:template>
 
-  <xsl:template match="direct/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>
-
-  <!--
-    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><mux><port type='input' ...><port type='input' ...><port type='output' ...></mux><YYY../></interconnect>
@@ -177,29 +109,4 @@
       </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: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:template match="text()|processing-instruction()">
-    <xsl:copy/>
-  </xsl:template>
-
 </xsl:stylesheet>
diff --git a/convert-prefix-port.xsl b/convert-prefix-port.xsl
new file mode 100644
index 0000000..d4c4b4a
--- /dev/null
+++ b/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">
+    <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">
+    <xsl:attribute name="in_port"><xsl:call-template name="parent-pb_type"/>.<xsl:value-of select="."/></xsl:attribute>
+  </xsl:template>
+  <xsl:template match="@port">
+    <xsl:attribute name="port"><xsl:call-template name="parent-pb_type"/>.<xsl:value-of select="."/></xsl:attribute>
+  </xsl:template>
+
+</xsl:stylesheet>
diff --git a/convert_and_merge_composable_fpga_architecture.sh b/convert_and_merge_composable_fpga_architecture.sh
new file mode 100755
index 0000000..2647c4c
--- /dev/null
+++ b/convert_and_merge_composable_fpga_architecture.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+set -euo pipefail
+
+TOP_DIR=$(git rev-parse --show-toplevel)
+XSLTPROC_CMD="${XSLTPROC} --nomkdir --nonet --xinclude ${XSLTPROC_PARAMS}"
+${XSLTPROC_CMD} ${TOP_DIR}/common/xml/identity.xsl "$@"				  | \
+	${XSLTPROC_CMD} ${TOP_DIR}/common/xml/convert-prefix-port.xsl		- | \
+	${XSLTPROC_CMD} ${TOP_DIR}/common/xml/convert-port-tag.xsl		- | \
+	${XSLTPROC_CMD} ${TOP_DIR}/common/xml/pack-patterns.xsl	 		- | \
+	${XSLTPROC_CMD} ${TOP_DIR}/common/xml/remove-duplicate-models.xsl 	- | \
+	${XSLTPROC_CMD} ${TOP_DIR}/common/xml/attribute-fixes.xsl 		- | \
+	cat
diff --git a/convert_and_merge_composable_tests/CMakeLists.txt b/convert_and_merge_composable_tests/CMakeLists.txt
index 7a6f5de..17e79c3 100644
--- a/convert_and_merge_composable_tests/CMakeLists.txt
+++ b/convert_and_merge_composable_tests/CMakeLists.txt
@@ -7,6 +7,7 @@
 xsl_golden_test(NAME "composable-interconnect-pack_patterns")
 xsl_golden_test(NAME "composable-loc-implicit-parent")
 xsl_golden_test(NAME "explicit-port")
+xsl_golden_test(NAME "pack_pattern-copy-direct-ports")
 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 "preserve-interconnect")
diff --git a/convert_and_merge_composable_tests/attribute-cleanup.xml b/convert_and_merge_composable_tests/attribute-cleanup.xml
index ed9a595..96a33a5 100644
--- a/convert_and_merge_composable_tests/attribute-cleanup.xml
+++ b/convert_and_merge_composable_tests/attribute-cleanup.xml
@@ -5,9 +5,9 @@
    * Strip xml:base attribute
   -->
 <xml>
- <tag b="1"  c="123"  x="abc" />
- <tag c="1"  d="123"  x="abc" />
+ <tag b="1"  c="123"  x=' abc' />
+ <tag c="1"  d=" 123 "  x="abc" />
  <tag>
-  <innertag   a2="2"   b1="abc"    a1="2">Hello</innertag>
+  <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
index c103723..58b70bc 100644
--- 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
@@ -21,7 +21,7 @@
       <output name="o"/>
     </pb_type>
     <interconnect>
-      <mux input="blocka.a blockb.b blockc[0].c blockc[1].c" output="blocko.i" name="outmux">
+      <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
diff --git a/convert_and_merge_composable_tests/composable-interconnect-fasm-mux.golden.xml b/convert_and_merge_composable_tests/composable-interconnect-fasm-mux.golden.xml
index 21c5cb3..3e72333 100644
--- a/convert_and_merge_composable_tests/composable-interconnect-fasm-mux.golden.xml
+++ b/convert_and_merge_composable_tests/composable-interconnect-fasm-mux.golden.xml
@@ -9,8 +9,8 @@
       <output name="o"/>
     </pb_type>
     <interconnect>
-      <direct name="parent-o" output="parent.o" input="child.o"/>
-      <mux input="parent.i0 parent.i1" output="child.i" name="mux1">
+      <direct input="child.o" name="parent-o" output="parent.o"/>
+      <mux input="parent.i0 parent.i1" name="mux1" output="child.i">
         <metadata>
           <meta name="fasm_mux">
                 parent.i0 : a1
diff --git a/convert_and_merge_composable_tests/composable-interconnect-implicit-parent.golden.xml b/convert_and_merge_composable_tests/composable-interconnect-implicit-parent.golden.xml
index 12abd36..745ae0e 100644
--- a/convert_and_merge_composable_tests/composable-interconnect-implicit-parent.golden.xml
+++ b/convert_and_merge_composable_tests/composable-interconnect-implicit-parent.golden.xml
@@ -21,16 +21,16 @@
     </pb_type>
     <interconnect>
       <direct input="parent.ia1" name="childa-i1" output="childa.i1">
-        <pack_pattern name="A1" in_port="parent.ia1" out_port="childa.i1"/>
+        <pack_pattern in_port="parent.ia1" name="A1" out_port="childa.i1"/>
       </direct>
-      <mux input="parent.ia2 parent.ia3" output="childa.i2" name="childa-input-i2">
-        <pack_pattern name="A2" in_port="parent.ia2" out_port="childa.i2"/>
-        <pack_pattern name="A3" in_port="parent.ia3" out_port="childa.i2"/>
+      <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="parent-o0" output="parent.o0"/>
       <direct input="childa.o" name="childb-i" output="childb.i"/>
-      <mux input="childa.o childb.o" output="childc.i" name="childc-input"/>
-      <mux input="childa.o childb.o childc.o" output="parent.o1" name="output"/>
+      <mux input="childa.o childb.o" name="childc-input" output="childc.i"/>
+      <mux input="childa.o childb.o childc.o" name="output" output="parent.o1"/>
     </interconnect>
   </pb_type>
 </xml>
diff --git a/convert_and_merge_composable_tests/composable-interconnect-pack_patterns.golden.xml b/convert_and_merge_composable_tests/composable-interconnect-pack_patterns.golden.xml
index ae06303..7285175 100644
--- a/convert_and_merge_composable_tests/composable-interconnect-pack_patterns.golden.xml
+++ b/convert_and_merge_composable_tests/composable-interconnect-pack_patterns.golden.xml
@@ -21,11 +21,11 @@
     </pb_type>
     <interconnect>
       <direct input="parent.ia1" name="childa-i1" output="childa.i1"/>
-      <mux input="parent.ia2 parent.ia3" output="childa.i2" name="childa-input-i2"/>
+      <mux input="parent.ia2 parent.ia3" name="childa-input-i2" output="childa.i2"/>
       <direct input="childa.o" name="parent-o0" output="parent.o0"/>
       <direct input="childa.o" name="childb-i" output="childb.i"/>
-      <mux input="childa.o childb.o" output="childc.i" name="childc-input"/>
-      <mux input="childa.o childb.o childc.o" output="parent.o1" name="output"/>
+      <mux input="childa.o childb.o" name="childc-input" output="childc.i"/>
+      <mux input="childa.o childb.o childc.o" name="output" output="parent.o1"/>
     </interconnect>
   </pb_type>
 </xml>
diff --git a/convert_and_merge_composable_tests/full-test-inner.xml b/convert_and_merge_composable_tests/full-test-inner.xml
index 5b44106..1c5ea86 100644
--- a/convert_and_merge_composable_tests/full-test-inner.xml
+++ b/convert_and_merge_composable_tests/full-test-inner.xml
@@ -10,4 +10,6 @@
   <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/convert_and_merge_composable_tests/full-test.golden.xml b/convert_and_merge_composable_tests/full-test.golden.xml
index c94d281..5190d3b 100644
--- a/convert_and_merge_composable_tests/full-test.golden.xml
+++ b/convert_and_merge_composable_tests/full-test.golden.xml
@@ -19,6 +19,8 @@
     <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"/>
@@ -32,6 +34,8 @@
     <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="MULTIPLE_INSTANCE.a[3]" name="comba[3]-a" output="comba[3].a"/>
@@ -53,25 +57,25 @@
     <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 name="carry-ADDER" in_port="comba[0].cout" out_port="combb[0].cin"/>
+      <pack_pattern in_port="comba[0].cout" name="carry-ADDER" out_port="combb[0].cin"/>
     </direct>
     <direct input="combb[0].sum" name="MULTIPLE_INSTANCE-sum[4]" output="MULTIPLE_INSTANCE.sum[4]"/>
     <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 name="carry-ADDER" in_port="comba[1].cout" out_port="combb[1].cin"/>
+      <pack_pattern in_port="comba[1].cout" name="carry-ADDER" out_port="combb[1].cin"/>
     </direct>
     <direct input="combb[1].sum" name="MULTIPLE_INSTANCE-sum[5]" output="MULTIPLE_INSTANCE.sum[5]"/>
     <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 name="carry-ADDER" in_port="comba[2].cout" out_port="combb[2].cin"/>
+      <pack_pattern in_port="comba[2].cout" name="carry-ADDER" out_port="combb[2].cin"/>
     </direct>
     <direct input="combb[2].sum" name="MULTIPLE_INSTANCE-sum[6]" output="MULTIPLE_INSTANCE.sum[6]"/>
     <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 name="carry-ADDER" in_port="comba[3].cout" out_port="combb[3].cin"/>
+      <pack_pattern in_port="comba[3].cout" name="carry-ADDER" out_port="combb[3].cin"/>
     </direct>
     <direct input="combb[3].cout" name="MULTIPLE_INSTANCE-cout" output="MULTIPLE_INSTANCE.cout"/>
     <direct input="combb[3].sum" name="MULTIPLE_INSTANCE-sum[7]" output="MULTIPLE_INSTANCE.sum[7]"/>
diff --git a/convert_and_merge_composable_tests/pack_pattern-copy-direct-ports.golden.xml b/convert_and_merge_composable_tests/pack_pattern-copy-direct-ports.golden.xml
new file mode 100644
index 0000000..39b63f7
--- /dev/null
+++ b/convert_and_merge_composable_tests/pack_pattern-copy-direct-ports.golden.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<xml>
+  <interconnect>
+    <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>
+    <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>
+  </interconnect>
+</xml>
diff --git a/convert_and_merge_composable_tests/preserve-interconnect.golden.xml b/convert_and_merge_composable_tests/preserve-interconnect.golden.xml
index 8023868..24310f9 100644
--- a/convert_and_merge_composable_tests/preserve-interconnect.golden.xml
+++ b/convert_and_merge_composable_tests/preserve-interconnect.golden.xml
@@ -21,16 +21,16 @@
     </pb_type>
     <interconnect>
       <direct input="parent.ia1" name="childa-i1" output="childa.i1"/>
-      <mux input="parent.ia2 parent.ia3" output="childa.i2" name="childa-input-i2">
-        <pack_pattern in_port="parent.parent.ia2" name="MUX1" output="childa.i2"/>
-        <pack_pattern in_port="parent.parent.ia3" name="MUX2" output="childa.i2"/>
+      <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="parent-o0" output="parent.o0">
-        <pack_pattern in_port="parent.childa.o" name="CARRY" output="parent.o0"/>
+        <pack_pattern in_port="childa.o" name="CARRY" out_port="parent.o0" output="parent.o0"/>
       </direct>
       <direct input="childa.o" name="childb-i" output="childb.i"/>
-      <mux input="childa.o childb.o" output="childc.i" name="childc-input"/>
-      <mux input="childa.o childb.o childc.o" output="parent.o1" name="output"/>
+      <mux input="childa.o childb.o" name="childc-input" output="childc.i"/>
+      <mux input="childa.o childb.o childc.o" name="output" output="parent.o1"/>
     </interconnect>
   </pb_type>
 </xml>
diff --git a/identity.xsl b/identity.xsl
new file mode 100644
index 0000000..23ff094
--- /dev/null
+++ b/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/pack-patterns.xsl b/pack-patterns.xsl
new file mode 100644
index 0000000..0203b5c
--- /dev/null
+++ b/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/remove-duplicate-models.xsl b/remove-duplicate-models.xsl
new file mode 100644
index 0000000..3166d53
--- /dev/null
+++ b/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>