}
    public void cleanUp() {        assert topLevel.isSplitter();        assert ((SIRSplitter) topLevel.contents).getWays() > 0;        final boolean[] deferred_errors = {false};        // check that we have cuts in the correct places        // remove edges that connect to flatnodes not in this ssg        topLevel.accept(new FlatVisitor() {            public void visitNode(FlatNode node) {                if (!flatNodes.contains(node))                    return;                if (node.inputs > 0) {                    for (int i = 0; i < node.incoming.length; i++) {                        assert node.incoming[i] != null;                        if (!flatNodes.contains(node.incoming[i])) {                            node.removeBackEdge(node.incoming[i]);                        }                    }                }                if (node.ways > 0) {                    for (int i = 0; i < node.edges.length; i++) {                        if (node.edges[i] == null) {                            assert i == 0                                    && (node.contents instanceof SIRSplitter || node.contents instanceof SIRJoiner)                                    && node.contents.getParent() instanceof SIRFeedbackLoop;                        } else if (!(flatNodes.contains(node.edges[i]))) {                            node.removeForwardEdge(node.edges[i]);                        }                    }                }            }        }, null, true);        // make sure all nodes have correct number of connections...        topLevel.accept(new FlatVisitor() {                public void visitNode(FlatNode node) {                    if (node.isFilter()) {                    SIRFilter filter = (SIRFilter) node.contents;                    if (filter.getPop() instanceof SIRRangeExpression) {                        System.err                                .println("Error: Dynamic rate found where not expected"                                        + " check that "                                        + filter.toString()                                        + " is only added after another filter.");                        deferred_errors[0] = true;                    } else {                        if (filter.getPopInt() > 0)                            assert node.inputs == 1;                        else // doesn't pop                        if (node.inputs == 1)                            assert node.incoming[0].getWeight(node) == 0;                    }                    if (filter.getPush() instanceof SIRRangeExpression) {                        System.err                                .println("Error: Dynamic rate found where not expected"                                        + " check that "                                        + filter.toString()                                        + " is only added before another filter.");                        deferred_errors[0] = true;                    } else {                        if (filter.getPushInt() > 0)                            assert node.ways == 1;                        else // doesn't push                        if (node.ways == 1)                            assert node.edges[0].getIncomingWeight(node) == 0;                    }                } else if (node.isJoiner()) {                        SIRJoiner joiner = (SIRJoiner) node.contents;                        if (joiner.getWays() != node.inputs) {                            // System.out.println(joiner.getWays() + " != " +                            // node.inputs);                            assert joiner.getSumOfWeights() == 0;                            // create a new null joiner                            SIRJoiner newJoiner = SIRJoiner.create(null,                                                                   SIRJoinType.NULL, node.inputs);                            node.contents = newJoiner;                        }                    } else {                        SIRSplitter splitter = (SIRSplitter) node.contents;                        if (splitter.getWays() != node.ways) {                            int [] weights = splitter.getWeights();                            int nonzero_weights = 0;                            for (int i = 0; i < weights.length; i++) {                                if (weights[i] > 0) nonzero_weights++;                            }                            int nonnull_ways = 0;                            for (int i = 0; i < node.ways; i++) {                                if (node.edges[i] != null) nonnull_ways++;                            }                            assert nonzero_weights == nonnull_ways : "Invalid Splitter: "                                + node                                + " "                                + nonzero_weights + " (" + splitter.getWays() + ") "                                + " != "                                + nonnull_ways + " (" + node.ways + ") ";                        }                    }                }            }, null, true);                assert ! deferred_errors[0] : "Error(s) found in dynamic rate boundary positioning." ;        // check if the number of splitters and joiners is balanced (==)        splitterBalance = 0;        topLevel.accept(new FlatVisitor() {                public void visitNode(FlatNode node) {                    if (node.isJoiner()) {                        splitterBalance--;                    } else if (node.isSplitter()) {                        splitterBalance++;                    }                }            }, null, true);        // splitters and joiners are balanced so return...        if (splitterBalance == 0)            return;        // remove the splitter because it is not needed!!!        if (((SIRSplitter) topLevel.contents).getWays() == 1) {            FlatNode oldTopLevel = topLevel;            assert topLevel.ways == 1 && topLevel.edges.length == 1                && topLevel.edges[0] != null;            topLevel = topLevel.edges[0];            if (topLevel.isFeedbackJoiner()) {                // old top level was feedbackloop joiner                // restore its old configuration with                // null first incoming edge rather than                // removing the edge                topLevel.incoming[0] = null;                topLevel.currentIncoming= 2;            } else {                topLevel.removeBackEdge(oldTopLevel);            }            flatNodes.remove(oldTopLevel);        }        // set up the downstream SSG's prevs hashmap        Iterator nextsIt = nexts.keySet().iterator();        while (nextsIt.hasNext()) {            FlatNode source = (FlatNode) nextsIt.next();            FlatNode dest = (FlatNode) nexts.get(source);            assert dest != null : source.toString();            streamGraph.getParentSSG(dest).addPrev(dest, source);        }        // build the prevSSGs and nextSSGs list, the upstream and downstream        // SSGs        nextsIt = nexts.values().iterator();        while (nextsIt.hasNext()) {            StaticStreamGraph ssg = streamGraph                .getParentSSG(((FlatNode) nextsIt.next()));            if (!nextSSGs.contains(ssg))                nextSSGs.add(ssg);        }        Iterator prevsIt = prevs.values().iterator();        while (prevsIt.hasNext()) {            StaticStreamGraph ssg = streamGraph                .getParentSSG(((FlatNode) prevsIt.next()));            if (!prevSSGs.contains(ssg))                prevSSGs.add(ssg);        }    }