Created a new patch script that corrects the CDL netlists for
four cells in the sky130_fd_sc_hd library that incorrectly tie
together the midpoint of two sets of two series transistors in
parallel.
diff --git a/VERSION b/VERSION
index 819d259..5e952e4 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.0.346
+1.0.347
diff --git a/sky130/Makefile.in b/sky130/Makefile.in
index 35dc218..1e0748c 100644
--- a/sky130/Makefile.in
+++ b/sky130/Makefile.in
@@ -1356,6 +1356,7 @@
 			filter=custom/scripts/fix_device_models.py \
 		-cdl %l/latest/cells/*/*.cdl ignore=topography compile-only \
 			filter=custom/scripts/fix_sparecell_cdl.py \
+			filter=custom/scripts/fix_serxtors_cdl.py \
 			sort=../common/sort_pdkfiles.py \
 		-lef %l/latest/cells/*/*.lef \
 			exclude=*.magic.lef,sky130_ef_sc_hd.lef lefopts=-toplayer \
diff --git a/sky130/custom/scripts/fix_serxtors_cdl.py b/sky130/custom/scripts/fix_serxtors_cdl.py
new file mode 100755
index 0000000..62bf205
--- /dev/null
+++ b/sky130/custom/scripts/fix_serxtors_cdl.py
@@ -0,0 +1,137 @@
+#!/usr/bin/env python3
+#
+# fix_serxtors_cdl ---
+#
+# This script fixes problems in SkyWater HD library cells CDL netlists
+# where transistor gates in series use M=2 incorrectly.
+# The topology on the left is what is implemented in the CDL, while the
+# topology on the right is what's actually in the layout:
+#
+#               |   |               |   |
+#               |   |               |   |
+#             ---   ---           ---   ---
+#             |       |           |       |
+#           --|       |--       --|       |--
+#             |       |           |       |
+#             ---   ---           ---   ---
+#               |   |               |   |
+#               |---|               |   |
+#               |   |               |   |
+#             ---   ---           ---   ---
+#             |       |           |       |
+#           --|       |--       --|       |--
+#             |       |           |       |
+#             ---   ---           ---   ---
+#               |   |               |   |
+#               |   |               |   |
+#
+# The four (known) cells with this error are (sky130_fd_sc_hd__ +):
+# a21o_4, o21a_4, a21bo_4, and a211o_4.
+
+# This script is a filter to be run by setting the name of this script as
+# the value to "filter=" for the model install in the sky130 Makefile.
+
+import re
+import os
+import sys
+
+def filter(inname, outname):
+
+    # Read input
+    try:
+        with open(inname, 'r') as inFile:
+            spitext = inFile.read()
+            # (Don't) unwrap continuation lines
+            # spilines = spitext.replace('\n+', ' ').splitlines()
+            spilines = spitext.splitlines()
+    except:
+        print('fix_serxtors_cdl.py: failed to open ' + inname + ' for reading.', file=sys.stderr)
+        return 1
+
+    errcells = [
+	'sky130_fd_sc_hd__a21o_4',
+	'sky130_fd_sc_hd__o21a_4',
+	'sky130_fd_sc_hd__a21bo_4',
+	'sky130_fd_sc_hd__a211o_4']
+
+    fixedlines = []
+    modified = False
+    inmacro = False
+    extor = False
+
+    # NOTE:  All occurrences of this error are at pin A1
+    # and the node is always "sndA1" ("s" for "series")
+
+    for line in spilines:
+        if inmacro == True:
+            if '.ENDS ' in line:
+                inmacro = False
+                fixedlines.append(line)
+            elif inmacro == True and 'sndA1' in line:
+                extor = True
+                fixedline = line.replace(' m=2', '')
+                fixedlines.append(fixedline)
+                saveline = fixedline.replace('sndA1', 'snd2A1')
+                modified = True
+            elif extor == True:
+                fixedlines.append(line)
+                fixedlines.append(saveline)
+                fixedlines.append(line)
+                extor = False
+            else:
+                fixedlines.append(line)
+        elif '.SUBCKT ' in line:
+            for cell in errcells:
+                if cell in line:
+                    inmacro = True
+            fixedlines.append(line)
+        else:
+            fixedlines.append(line)
+
+    # Write output
+    if outname == None:
+        for i in fixedlines:
+            print(i)
+    else:
+        # If the output is a symbolic link but no modifications have been made,
+        # then leave it alone.  If it was modified, then remove the symbolic
+        # link before writing.
+        if os.path.islink(outname):
+            if not modified:
+                return 0
+            else:
+                os.unlink(outname)
+        try:
+            with open(outname, 'w') as outFile:
+                for i in fixedlines:
+                    print(i, file=outFile)
+        except:
+            print('fix_serxtors_cdl.py: failed to open ' + outname + ' for writing.', file=sys.stderr)
+            return 1
+
+
+if __name__ == '__main__':
+
+    # This script expects to get one or two arguments.  One argument is
+    # mandatory and is the input file.  The other argument is optional and
+    # is the output file.  The output file and input file may be the same
+    # name, in which case the original input is overwritten.
+
+    options = []
+    arguments = []
+    for item in sys.argv[1:]:
+        if item.find('-', 0) == 0:
+            options.append(item[1:])
+        else:
+            arguments.append(item)
+
+    if len(arguments) > 0:
+        infilename = arguments[0]
+
+    if len(arguments) > 1:
+        outfilename = arguments[1]
+    else:
+        outfilename = None
+
+    result = filter(infilename, outfilename)
+    sys.exit(result)
diff --git a/sky130/sky130.json b/sky130/sky130.json
index 5767096..8daa31f 100644
--- a/sky130/sky130.json
+++ b/sky130/sky130.json
@@ -92,16 +92,16 @@
         "magic": "MAGIC_COMMIT"
     },
     "reference": {
-        "open_pdks": "82d61e2c9c265c0f0e994233cd2d024c90adb45f",
-        "magic": "7905e15ae3b66ed26349fb701b475ef93b566de5",
+        "open_pdks": "a56526bfe45971322526978132b059d43ddd3a02",
+        "magic": "eecdc3c6421d42a031e98023567a0f3694ba47f4",
         "skywater_pdk": "f70d8ca46961ff92719d8870a18a076370b85f6c",
         "sky130_osu_sc_t12": "ac90ef0c622a9377a16b5218d9da3ac4169eeaaf",
         "sky130_osu_sc_t15": "95d1c19abb47e1b2945847acb4e817b1b8417c43",
         "sky130_osu_sc_t18": "aa2b509f3c8f32ea94fdb55ac9768754667c1658",
         "sky130_sram_macros": "c2333394e0b0b9d9d71185678a8d8087715d5e3b",
         "sky130_ml_xx_hd": "6eb3b0718552b034f1bf1870285ff135e3fb2dcb",
-        "xschem_sky130": "5949895a0214f3471f16850297ea15e34a564edd",
-        "klayout_sky130": "85165d907f6b68e73bb25b9982cca20a87c98686",
-        "precheck_sky130": "07ace967fbe88e33844bf046bd9d30e1679580b7"
+        "xschem_sky130": "35af1ae750d109b78533399a3cb639be5a3f50e4",
+        "klayout_sky130": "40fe0f615dbc3f50aa394bd9ed7df3577e295b9d",
+        "precheck_sky130": "76cf0a9bb0407cae712b253f9dd291167568e712"
     }
 }
\ No newline at end of file