Updating the bram + clocking + tiles.
diff --git a/dump_bram.java b/dump_bram.java
index 501a66c..381a4de 100644
--- a/dump_bram.java
+++ b/dump_bram.java
@@ -220,23 +220,100 @@
                                        }
                                    }
                                }
-
+                               boolean pins_used = false, d_grounded = true;
                                for (EDIFPortInst epi : eci.getPortInsts()) {
-                                   if (epi.isOutput() && epi.getNet() != null)
+                                   if (epi.isOutput() && epi.getNet() != null) {
                                        tfeat.add(name + "." + epi.getName() + ".USED");
+                                   }
                                }
-
+                               for (SitePinInst spi : si.getSitePinInsts()) {
+                                   if (!spi.getName().startsWith("DIN"))
+                                       continue;
+                                   if (spi.getNet() != null) {
+                                       pins_used = true;
+                                       if (!spi.getNet().isStaticNet())
+                                           d_grounded = false;
+                                   }
+                               }
+                               if (pins_used && d_grounded)
+                                   tfeat.add(name + ".D_NOT_USED");
+                               //if (c_grounded)
+                               //    tfeat.add(name + ".C_NOT_USED");
                                break;
                            }
                        }
 
+                   } else if (si.getSiteTypeEnum() == SiteTypeEnum.URAM288) {
+                       Cell c = si.getCell("URAM_288K_INST");
+                       if (c == null || c.getType() == null)
+                           continue;
+                       String name = site_index_in_tile(si.getTile(), si.getSite());
+                       tfeat.add("URAM.IN_USE");
+                       tfeat.add(name + ".IN_USE");
+                       String[] enum_props = {"BWE_MODE_A", "BWE_MODE_B", "EN_AUTO_SLEEP_MODE", "EN_ECC_RD_A", "EN_ECC_RD_B",
+                               "EN_ECC_WR_A", "EN_ECC_WR_B", "IREG_PRE_A", "IREG_PRE_B", "OREG_A", "OREG_B", "OREG_ECC_A", "OREG_ECC_B", "REG_CAS_A",
+                               "REG_CAS_B", "RST_MODE_A", "RST_MODE_B", "USE_EXT_CE_A", "USE_EXT_CE_B"};
+                       for (String p : enum_props) {
+                           EDIFPropertyValue ep = c.getProperty(p);
+                           if (ep == null)
+                               continue;
+                           String v = ep.getValue();
+                           int base_pos = v.indexOf("'b");
+                           if (base_pos != -1)
+                               v = v.substring(base_pos + 2);
+                           tfeat.add(name + "." + p + "." + v);
+                       }
+
+                       var all_props = c.getProperties();
+                       for (var e : all_props.entrySet()) {
+                           String prop_name = e.getKey().getName();
+                           if (prop_name.startsWith("IS_") && prop_name.endsWith("_INVERTED")) {
+                               String pinname = prop_name.substring(3, prop_name.length() - 9);
+                               if (c.getLogicalPinMapping(pinname) == null)
+                                    continue;
+                               Net n = si.getNetFromSiteWire(c.getSiteWireNameFromLogicalPin(pinname));
+                               if (n == null || n.isStaticNet())
+                                   continue;
+                               String v = e.getValue().getValue();
+                               int base_pos = v.indexOf("'b");
+                               if (base_pos != -1)
+                                   v = v.substring(base_pos + 2);
+                               tfeat.add(name + "." + pinname + "INV." + v);
+                           }
+                       }
+
+                       String[] word_props = {"SELF_ADDR_A", "SELF_ADDR_B", "SELF_MASK_A", "SELF_MASK_B"};
+                       for (String p : word_props) {
+                           if (c.getProperty(p) != null) {
+                               long lval = LUTTools.getInitValue(c.getProperty(p).getValue());
+                               for (int i = 0; i < 11; i++) {
+                                   boolean is_inv = p.contains("_MASK_");
+                                   if (((lval >> i) & 0x1) == (is_inv ? 0 : 1))
+                                       tfeat.add(name + "." + p + (is_inv ? "_INV" : "") + "[" + i + "]");
+                               }
+                           }
+                       }
+                       EDIFPropertyValue asl = c.getProperty("AUTO_SLEEP_LATENCY");
+                       if (asl != null) {
+                           int a = Integer.parseInt(asl.getValue());
+                           for (int i = 0; i < 4; i++)
+                               if (((a >> i) & 0x1) == 1) {
+                                   tfeat.add(name + ".AUTO_SLEEP_LATENCY[" + i + "]");
+                               }
+                       }
+
+                       for (EDIFPortInst epi : c.getEDIFCellInst().getPortInsts()) {
+                           if (epi.isOutput() && epi.getNet() != null)
+                               tfeat.add(name + "." + epi.getName() + ".USED");
+                       }
                    }
                 }
                 FileWriter vf = new FileWriter(f.getAbsolutePath().replace(".dcp", ".features"), false);
                 PrintWriter v = new PrintWriter(vf);
                 for (Tile t : des.getDevice().getAllTiles()) {
                     TileTypeEnum tt = t.getTileTypeEnum();
-                    if (tt == TileTypeEnum.BRAM || tt == TileTypeEnum.DSP || tt == TileTypeEnum.DSP_L || tt == TileTypeEnum.DSP_R) {
+                    if (tt == TileTypeEnum.BRAM || tt == TileTypeEnum.DSP || tt == TileTypeEnum.DSP_L || tt == TileTypeEnum.DSP_R ||
+                        tt == TileTypeEnum.URAM_URAM_FT || tt == TileTypeEnum.URAM_URAM_DELAY_FT) {
                         String tname = t.getName() + ":" + tt.toString();
                         if (!pips_by_tile.containsKey(tname) && !sitefeatures_by_tile.containsKey(tname))
                             continue;
diff --git a/dump_clocking.java b/dump_clocking.java
index f611410..0a31017 100644
--- a/dump_clocking.java
+++ b/dump_clocking.java
@@ -17,7 +17,10 @@
 import com.xilinx.rapidwright.design.*;
 import com.xilinx.rapidwright.design.tools.LUTTools;
 import com.xilinx.rapidwright.device.*;
+import com.xilinx.rapidwright.edif.EDIFName;
+import com.xilinx.rapidwright.edif.EDIFPort;
 import com.xilinx.rapidwright.edif.EDIFPortInst;
+import org.python.bouncycastle.crypto.tls.DefaultTlsCipherFactory;
 
 import java.io.File;
 import java.io.FileWriter;
@@ -69,6 +72,56 @@
         return inv;
     }
 
+    static boolean is_node_inverted(Net n, Node cursor) {
+        HashMap<Node, PIP> pip_uphill = new HashMap<>();
+        for (PIP p : n.getPIPs()) {
+            pip_uphill.putIfAbsent(p.getEndNode(), p);
+            if (p.isBidirectional()) {
+                pip_uphill.putIfAbsent(p.getStartNode(), p);
+            }
+        }
+        boolean inv = false;
+       while (pip_uphill.containsKey(cursor)) {
+            PIP p = pip_uphill.get(cursor);
+            String name = p.getTile().getName() + "/" + p.getTile().getTileTypeEnum().toString() + "." + p.getStartWireName() + (p.isBidirectional() ? "<<->>" : "->>") + p.getEndWireName();
+            if (inverted_pips.contains(name))
+                inv = !inv;
+            //System.out.println(name + " " + inv);
+            if (p.isBidirectional() && p.getStartNode().equals(cursor))
+                cursor = p.getEndNode();
+            else
+                cursor = p.getStartNode();
+        }
+        return inv;
+    }
+
+    static int get_clock_depth(Net n, Node cursor) {
+        HashMap<Node, PIP> pip_uphill = new HashMap<>();
+        for (PIP p : n.getPIPs()) {
+            pip_uphill.putIfAbsent(p.getEndNode(), p);
+            if (p.isBidirectional()) {
+                pip_uphill.putIfAbsent(p.getStartNode(), p);
+            }
+        }
+        int distr_count = 0;
+        while (pip_uphill.containsKey(cursor)) {
+            PIP p = pip_uphill.get(cursor);
+            String name = p.getTile().getName() + "/" + p.getTile().getTileTypeEnum().toString() + "." + p.getStartWireName() + (p.isBidirectional() ? "<<->>" : "->>") + p.getEndWireName();
+           // System.out.println("   " + name);
+            if (p.isBidirectional() && p.getStartNode().equals(cursor))
+                cursor = p.getEndNode();
+            else
+                cursor = p.getStartNode();
+            if (cursor.getWireName().contains("DISTR"))
+                distr_count++;
+            //System.out.println(" <---" + cursor.getTile().getName() + "/" + cursor.getWireName());
+        }
+        //System.out.println("distr count: " + distr_count);
+        return distr_count;
+    }
+
+
+
     public static void main(String[] args) throws IOException {
 
 
@@ -92,6 +145,7 @@
 
                     if (n.getSource() != null)
                         uphill.put(n.getSource().getConnectedNode(), null);
+                    int max_distr_depth = 0;
                     for (PIP p : n.getPIPs()) {
                         if (!p.isBidirectional()) {
                             uphill.put(p.getEndNode(), p);
@@ -112,9 +166,28 @@
                                     if (!sitefeatures_by_tile.containsKey(tile))
                                         sitefeatures_by_tile.put(tile, new ArrayList<>());
                                     sitefeatures_by_tile.get(tile).add(site + ".BUFCE_LEAF.IN_USE");
+
+
+                                    if (n.getName().startsWith("leaf_delay_")) {
+                                        int count = 0;
+                                        for (PIP p2 : n.getPIPs()) {
+                                            if (p2.getEndWireName().startsWith("CLK_LEAF_SITES_") && p2.getEndWireName().endsWith("_CLK_LEAF") && p2.getStartWireName().endsWith("_CLK_IN"))
+                                                ++count;
+                                        }
+                                        if (count == 1) {
+                                            int value = Integer.parseInt(n.getName().split("_")[2]);
+                                            sitefeatures_by_tile.get(tile).add(site + ".BUFCE_LEAF.DELAY_TAP_" + value);
+                                        }
+                                        if (is_node_inverted(n, p.getStartNode())) {
+                                            sitefeatures_by_tile.get(tile).add(site + ".BUFCE_LEAF.IINV.1");
+                                        }
+                                    }
                                 }
                             }
                         }
+                        if (p.getStartWire().getWireName().contains("BUFCE_ROW_FSR") && p.getStartWire().getWireName().endsWith("CLK_IN")) {
+                            max_distr_depth = Math.max(max_distr_depth, get_clock_depth(n, p.getStartNode()));
+                        }
                     }
 
                     for (Node node : allnodes) {
@@ -123,16 +196,19 @@
                             if (wtt == TileTypeEnum.RCLK_BRAM_INTF_L || wtt == TileTypeEnum.RCLK_BRAM_INTF_TD_L || wtt == TileTypeEnum.RCLK_BRAM_INTF_TD_R ||
                                     wtt == TileTypeEnum.RCLK_CLEL_L_L || wtt == TileTypeEnum.RCLK_CLEL_L || wtt == TileTypeEnum.RCLK_CLEL_L_R ||
                                     wtt == TileTypeEnum.RCLK_CLEM_CLKBUF_L || wtt == TileTypeEnum.RCLK_CLEM_L || wtt == TileTypeEnum.RCLK_DSP_INTF_L ||
-                                    wtt == TileTypeEnum.RCLK_CLEM_R || wtt == TileTypeEnum.RCLK_CLEL_R) {
-                                if (w.getWireName().startsWith("CLK_TEST_BUF_SITE_") || w.getWireName().startsWith("CLK_HROUTE_CORE_OPT")) {
+                                    wtt == TileTypeEnum.RCLK_DSP_INTF_R || wtt == TileTypeEnum.RCLK_RCLK_URAM_INTF_L_FT ||
+                                    wtt == TileTypeEnum.RCLK_CLEM_R || wtt == TileTypeEnum.RCLK_CLEL_R || wtt == TileTypeEnum.GTH_QUAD_RIGHT) {
+                                if (w.getWireName().startsWith("CLK_TEST_BUF_SITE_") || w.getWireName().startsWith("CLK_HROUTE_CORE_OPT") ||
+                                    w.getWireName().startsWith("CLK_VDISTR_BOT") || w.getWireName().startsWith("CLK_VDISTR_TOP") ||
+                                        w.getWireName().startsWith("CLK_VROUTE_BOT") || w.getWireName().startsWith("CLK_VROUTE_TOP")) {
                                     String tile = w.getTile().getName() + ":" + w.getTile().getTileTypeEnum().toString();
                                     if (!pips_by_tile.containsKey(tile))
                                         pips_by_tile.put(tile, new ArrayList<>());
                                     pips_by_tile.get(tile).add("WIRE." + w.getWireName() + ".USED");
-
                                 }
                             }
-                            if (wtt == TileTypeEnum.RCLK_DSP_INTF_CLKBUF_L || wtt == TileTypeEnum.RCLK_CLEM_CLKBUF_L || wtt == TileTypeEnum.RCLK_BRAM_INTF_L) {
+                            if (wtt == TileTypeEnum.RCLK_DSP_INTF_CLKBUF_L || wtt == TileTypeEnum.RCLK_CLEM_CLKBUF_L || wtt == TileTypeEnum.RCLK_BRAM_INTF_L ||
+                                wtt == TileTypeEnum.RCLK_RCLK_XIPHY_INNER_FT || wtt == TileTypeEnum.RCLK_HDIO  || wtt == TileTypeEnum.GTH_QUAD_RIGHT) {
                                 if (w.getWireName().startsWith("CLK_HROUTE") || w.getWireName().startsWith("CLK_HDISTR")) {
                                     String tile = w.getTile().getName() + ":" + w.getTile().getTileTypeEnum().toString();
                                     if (!pips_by_tile.containsKey(tile))
@@ -176,6 +252,16 @@
                         } else {
                             pips_by_tile.get(tile).add("PIP." + p.getEndWireName() + "." + p.getStartWireName());
                         }
+                        if (n.getName().contains("clk_dly_fuzz") && p.getStartWire().getWireName().contains("BUFCE_ROW_FSR") && p.getStartWire().getWireName().endsWith("CLK_IN")) {
+                            int depth = get_clock_depth(n, p.getStartNode());
+                            int tap = max_distr_depth - depth;
+                            String bufce_name = site_index_in_tile(p.getTile(), p.getStartNode().getSitePin().getSite());
+                            for (int i = 0; i < 3; i++) {
+                                if (((tap >> i) & 0x1) == 1) {
+                                    pips_by_tile.get(tile).add(bufce_name + ".COMP_DELAY_TAP[" + i + "]");
+                                }
+                            }
+                        }
                     }
                 }
                 for (SiteInst si : des.getSiteInsts()) {
@@ -207,6 +293,11 @@
                                 }
                             }
                         }
+                    } else if (si.getSiteTypeEnum() == SiteTypeEnum.BUFCE_ROW_FSR) {
+                        for (Cell c : si.getCells()) {
+                            if (c.getType().equals("<LOCKED>"))
+                                System.out.println(c.getBELName());
+                        }
                     } else if (si.getSiteTypeEnum() == SiteTypeEnum.BUFGCE || si.getSiteTypeEnum() == SiteTypeEnum.BUFGCE_DIV) {
                         String name = site_index_in_tile(si.getTile(), si.getSite());
                         for (Cell c : si.getCells()) {
@@ -221,9 +312,13 @@
                                         v = v.substring(base_pos + 2);
                                     if (propname.startsWith("IS_") && propname.endsWith("_INVERTED")) {
                                         String pinname = propname.substring(3, propname.length() - 9);
-                                        if (pinname.equals("I"))
+                                        if (pinname.equals("I")) {
                                             if (is_sink_inverted(si.getSitePinInst("CLK_IN")))
                                                 v = (v.equals("1") ? "0" : "1");
+                                            String sw = c.getSiteWireNameFromLogicalPin(pinname);
+                                            if (sw == null || si.getNetFromSiteWire(sw) == null || si.getNetFromSiteWire(sw).isStaticNet())
+                                                continue;
+                                        }
                                         tfeat.add(name + "." + si.getSiteTypeEnum().toString() + "." + pinname + "INV." + v);
                                     } else if ((si.getSiteTypeEnum() == SiteTypeEnum.BUFGCE && propname.equals("CE_TYPE")) || propname.equals("BUFGCE_DIVIDE")) {
                                         tfeat.add(name +  "." + si.getSiteTypeEnum().toString() + "." + propname + "." + v);
@@ -245,9 +340,13 @@
                                         v = v.substring(base_pos + 2);
                                     if (propname.startsWith("IS_") && propname.endsWith("_INVERTED")) {
                                         String pinname = propname.substring(3, propname.length() - 9);
-                                        if (pinname.equals("I0") || pinname.equals("I1"))
+                                        if (pinname.equals("I0") || pinname.equals("I1")) {
+                                            String sw = c.getSiteWireNameFromLogicalPin(pinname);
+                                            if (sw == null || si.getNetFromSiteWire(sw) == null || si.getNetFromSiteWire(sw).isStaticNet())
+                                                continue;
                                             if (is_sink_inverted(si.getSitePinInst("CLK_" + pinname)))
                                                 v = (v.equals("1") ? "0" : "1");
+                                        }
                                         tfeat.add(name + "." + si.getSiteTypeEnum().toString() + "." + pinname + "INV." + v);
                                     } else if (propname.equals("INIT_OUT") || propname.startsWith("PRESELECT_")) {
                                         tfeat.add(name +  "." + si.getSiteTypeEnum().toString() + "." + propname + "." + v);
@@ -255,6 +354,88 @@
                                 }
                             }
                         }
+                    } else if (si.getSiteTypeEnum() == SiteTypeEnum.MMCM) {
+                        String name = site_index_in_tile(si.getTile(), si.getSite());
+                        Cell c = si.getCell("MMCM");
+                        if (c == null || c.getType() == null)
+                            continue;
+                        tfeat.add(name + ".IN_USE");
+                        var all_props = c.getProperties();
+                        for (var e : all_props.entrySet()) {
+                            String propname = e.getKey().getName();
+                            String v = e.getValue().getValue();
+                            int base_pos = v.indexOf("'b");
+                            if (base_pos != -1)
+                                v = v.substring(base_pos + 2);
+                            if (propname.startsWith("IS_") && propname.endsWith("_INVERTED")) {
+                                String pinname = propname.substring(3, propname.length() - 9);
+                                if (pinname.equals("CLKIN1") || pinname.equals("CLKIN2") || pinname.equals("CLKFBIN"))
+                                    continue;
+                                String sw = c.getSiteWireNameFromLogicalPin(pinname);
+                                if (sw == null || si.getNetFromSiteWire(sw) == null || si.getNetFromSiteWire(sw).isStaticNet())
+                                    continue;
+                                tfeat.add(name + "." + si.getSiteTypeEnum().toString() + "." + pinname + "INV." + v);
+                            } else if (propname.equals("COMPENSATION")) {
+                                tfeat.add(name +  "." + si.getSiteTypeEnum().toString() + "." + propname + "." + v);
+                            }
+                        }
+                    } else if (si.getSiteTypeEnum() == SiteTypeEnum.PLL) {
+                        String name = site_index_in_tile(si.getTile(), si.getSite());
+                        Cell c = si.getCell("PLL");
+                        if (c == null || c.getType() == null)
+                            continue;
+                        tfeat.add(name + ".IN_USE");
+                        var all_props = c.getProperties();
+                        for (var e : all_props.entrySet()) {
+                            String propname = e.getKey().getName();
+                            String v = e.getValue().getValue();
+                            int base_pos = v.indexOf("'b");
+                            if (base_pos != -1)
+                                v = v.substring(base_pos + 2);
+                            if (propname.startsWith("IS_") && propname.endsWith("_INVERTED")) {
+                                String pinname = propname.substring(3, propname.length() - 9);
+                                if (pinname.equals("CLKIN") || pinname.equals("CLKFBIN"))
+                                    continue;
+                                String sw = c.getSiteWireNameFromLogicalPin(pinname);
+                                if (sw == null || si.getNetFromSiteWire(sw) == null || si.getNetFromSiteWire(sw).isStaticNet())
+                                    continue;
+                                tfeat.add(name + "." + si.getSiteTypeEnum().toString() + "." + pinname + "INV." + v);
+                            } else if (propname.equals("COMPENSATION")) {
+                                tfeat.add(name +  "." + si.getSiteTypeEnum().toString() + "." + propname + "." + v);
+                            }
+                        }
+                    }
+                }
+                for (Tile t : des.getDevice().getAllTiles()) {
+                    if (t.getTileTypeEnum() != TileTypeEnum.RCLK_HPIO_L)
+                        continue;
+                    boolean dci_used = false;
+                    Tile[] io_tiles = {des.getDevice().getTile(t.getRow()+30, t.getColumn()), des.getDevice().getTile(t.getRow()-1, t.getColumn())};
+                    for (Tile iot : io_tiles) {
+                        for (Site s : iot.getSites()) {
+                            SiteInst si = des.getSiteInstFromSite(s);
+                            if (si == null)
+                                continue;
+                            Cell pad = si.getCell(si.getBEL("PAD"));
+                            if (pad == null)
+                                continue;
+                            EDIFPort p = des.getTopEDIFCell().getPort(pad.getName());
+                            if (des.getTopEDIFCell().getNet(pad.getName()) == null)
+                                continue;
+                            var prop = des.getTopEDIFCell().getNet(pad.getName()).getProperties();
+                            if (prop == null || !prop.containsKey(new EDIFName("IOSTANDARD")))
+                                continue;
+                            String iostd = prop.get(new EDIFName("IOSTANDARD")).getValue();
+                            if (iostd.contains("POD12_DCI") && !f.getName().contains("ipi")) // FIXME: find out why this loses bits
+                                dci_used = true;
+                        }
+                    }
+                    if (dci_used) {
+                        String tile = t.getName() + ":" + t.getTileTypeEnum().toString();
+                        if (!sitefeatures_by_tile.containsKey(tile))
+                            sitefeatures_by_tile.put(tile, new ArrayList<>());
+                        ArrayList<String> tfeat = sitefeatures_by_tile.get(tile);
+                        tfeat.add("POD12_DCI_USED");
                     }
                 }
                 FileWriter vf = new FileWriter(f.getAbsolutePath().replace(".dcp", ".features"), false);
@@ -263,8 +444,11 @@
                     TileTypeEnum tt = t.getTileTypeEnum();
                     if (tt == TileTypeEnum.RCLK_INT_L|| tt == TileTypeEnum.RCLK_CLEM_L || tt == TileTypeEnum.RCLK_INT_R || tt == TileTypeEnum.RCLK_CLEM_CLKBUF_L || tt == TileTypeEnum.RCLK_CLEM_R ||
                             tt == TileTypeEnum.RCLK_DSP_INTF_L || tt == TileTypeEnum.RCLK_BRAM_L || tt == TileTypeEnum.RCLK_BRAM_R || tt == TileTypeEnum.RCLK_BRAM_INTF_L ||
+                            tt == TileTypeEnum.RCLK_DSP_INTF_R || tt == TileTypeEnum.RCLK_DSP_CLKBUF_L || tt == TileTypeEnum.RCLK_RCLK_XIPHY_INNER_FT || tt == TileTypeEnum.RCLK_RCLK_INTF_XIPHY_LEFT_L_FT ||
+                            tt == TileTypeEnum.RCLK_HDIO || tt == TileTypeEnum.RCLK_HPIO_L || tt == TileTypeEnum.RCLK_HPIO_R ||
                             tt == TileTypeEnum.RCLK_CLEL_L || tt == TileTypeEnum.RCLK_CLEL_R || tt == TileTypeEnum.RCLK_CLEL_L_L || tt == TileTypeEnum.RCLK_CLEL_L_R ||
-                            tt == TileTypeEnum.RCLK_DSP_INTF_CLKBUF_L || tt == TileTypeEnum.RCLK_BRAM_INTF_TD_L || tt == TileTypeEnum.RCLK_BRAM_INTF_TD_R || tt == TileTypeEnum.CMT_L || tt == TileTypeEnum.CMT_RIGHT) {
+                            tt == TileTypeEnum.RCLK_DSP_INTF_CLKBUF_L || tt == TileTypeEnum.RCLK_BRAM_INTF_TD_L || tt == TileTypeEnum.RCLK_BRAM_INTF_TD_R || tt == TileTypeEnum.CMT_L || tt == TileTypeEnum.CMT_RIGHT ||
+                            tt == TileTypeEnum.RCLK_RCLK_URAM_INTF_L_FT || tt == TileTypeEnum.GTH_QUAD_RIGHT) {
                         String tname = t.getName() + ":" + tt.toString();
                         if (!pips_by_tile.containsKey(tname) && !sitefeatures_by_tile.containsKey(tname))
                             continue;
diff --git a/dump_tiles.java b/dump_tiles.java
index d135469..1be82ab 100644
--- a/dump_tiles.java
+++ b/dump_tiles.java
@@ -36,5 +36,6 @@
             }
             v.println();
         }
+        vf.close();
     }
 }