int threads = KjcOptions.cluster;  HashMap partitionMap = new HashMap();
int hosts = KjcOptions.cluster;  HashMap<SIROperator,Integer> partitionMap = new HashMap<SIROperator,Integer>();
    public static void run(SIRStream str,                           JInterfaceDeclaration[] interfaces,                           SIRInterfaceTable[] interfaceTables,                           SIRStructure[] structs,                           SIRHelper[] helpers,                           SIRGlobal global) {        HashMap[] exec_counts1;        HashMap[] exec_counts2;        boolean doCacheOptimization = KjcOptions.cacheopt;        int code_cache = 16000;        int data_cache = 16000;        // if (debugPrint)        //    System.out.println("Cluster Backend SIRGlobal: "+global);        System.out.println("Entry to Cluster Backend"                           + ((KjcOptions.standalone && KjcOptions.cluster == 1) ? " (uniprocessor)": ""));        // System.out.println("  --cluster parameter is: "+KjcOptions.cluster);        // if (debugPrint)        //     System.out.println("  peekratio is: "+KjcOptions.peekratio);        // System.out.println("  rename1 is: "+KjcOptions.rename1);        // System.out.println("  rename2 is: "+KjcOptions.rename2);        if (debugPrint) {            SIRGlobal[] globals;            if (global != null) {                globals = new SIRGlobal[1];                globals[0] = global;            } else globals = new SIRGlobal[0];            System.err.println("// str on entry to Cluster backend");            SIRToStreamIt.run(str,interfaces,interfaceTables,structs,globals);            System.err.println("// END str on entry to Cluster backend");        }        structures = structs;            //this must be run now, FlatIRToC relies on it!!!        RenameAll.renameAllFilters(str);        // Introduce Multiple Pops where programmer        // didn't take advantage of them        IntroduceMultiPops.doit(str);                // Perform propagation on fields from 'static' sections.        Set<SIRGlobal> statics = new HashSet<SIRGlobal>();        if (global != null)            statics.add(global);        StaticsProp.propagate(str, statics);        if (debugPrint) {            System.err.println("// str after RenameAll and StaticsProp");            SIRGlobal[] globals;            if (global != null) {                globals = new SIRGlobal[1];                globals[0] = global;            } else {                globals = new SIRGlobal[0];            }            SIRToStreamIt.run(str, interfaces, interfaceTables, structs,                              globals);            System.err.println("// END str after RenameAll and StaticsProp");        }        // propagate constants and unroll loop        System.err.print("Running Constant Prop and Unroll...");        // Constant propagate and unroll.        // Set unrolling factor to <= 4 for loops that don't involve        //  any tape operations.        Unroller.setLimitNoTapeLoops(true, 4);            ConstantProp.propagateAndUnroll(str);        System.err.println(" done.");        // do constant propagation on fields        System.err.print("Running Constant Field Propagation...");        ConstantProp.propagateAndUnroll(str, true);        if (debugPrint) {            System.err.println("// str after ConstantProp");            SIRToStreamIt.run(str,interfaces,interfaceTables,structs);            System.err.println("// END str after ConstantProp");        }        // convert round(x) to floor(0.5+x) to avoid obscure errors        RoundToFloor.doit(str);        // add initPath functions        EnqueueToInitPath.doInitPath(str);        // construct stream hierarchy from SIRInitStatements        ConstructSIRTree.doit(str);        //SIRPrinter printer1 = new SIRPrinter();        //str.accept(printer1);        //printer1.close();        //VarDecl Raise to move array assignments up        new VarDeclRaiser().raiseVars(str);        // expand array initializers loaded from a file        ArrayInitExpander.doit(str);        System.err.println(" done.");   // announce end of ConstantProp and Unroll        //System.err.println("Analyzing Branches..");        //new BlockFlattener().flattenBlocks(str);        //new BranchAnalyzer().analyzeBranches(str);        SIRPortal.findMessageStatements(str);        // Unroll and propagate maximally within each (not phased) filter.        // Initially justified as necessary for IncreaseFilterMult which is        // now obsolete.        Optimizer.optimize(str);         if (debugPrint) {            System.err.println("// str after Optimizer");            SIRToStreamIt.run(str,interfaces,interfaceTables,structs);            System.err.println("// END str after Optimizer");        }         // estimate code and local variable size for each filter (and store where???)        Estimator.estimate(str);        // canonicalize stream graph, reorganizing some splits and joins        Lifter.liftAggressiveSync(str);        //StreamItDot.printGraph(str, "before-partition.dot");        // gather application-characterization statistics        if (KjcOptions.stats) {            StatisticsGathering.doit(str);        }        // Flattener is a misnomer here.        // rewrite str for linearreplacement, frequencyreplacement        // redundantreplacement        str = Flattener.doLinearAnalysis(str);        // statespace.        str = Flattener.doStateSpaceAnalysis(str);        // for scheduler, interpret dynamic rates as a constant.        // TODO:        // eventually make a policy that changes dynamic rates <r> to        // to <r.max> or 1000 if <r.max> is dynamic.        // for now:         // to push MPEG through cluster need size of        // apps/benchmarks/mpeg2/input/momessage.m2v in bits rounded        // up to a multiple of 32.        SIRDynamicRateManager.pushConstantPolicy(1000000);        //SIRDynamicRateManager.pushIdentityPolicy();                // Calculate SIRSchedule before increasing multiplicity        StreamItDot.printGraph(str, "before-peekmult.dot");        exec_counts1 = SIRScheduler.getExecutionCounts(str);        // sets filter steady counts, which are needed by cache partitioner        filter_steady_counts = exec_counts1[1];         // Code relating to IncreaseFilterMult removed here.                Optimizer.optimize(str);        Estimator.estimate(str);        // should really be hosts -- how many systems        // will be running this code.        int threads = KjcOptions.cluster;        HashMap partitionMap = new HashMap();        if ( doCacheOptimization ) {            str = new CachePartitioner(str, WorkEstimate.getWorkEstimate(str), 0, code_cache, data_cache).calcPartitions(partitionMap);        }        // Calculate SIRSchedule after increasing multiplicity        StreamItDot.printGraph(str, "after-peekmult.dot");        exec_counts2 = SIRScheduler.getExecutionCounts(str);        // sets filter steady counts, which are needed by cache partitioner        filter_steady_counts = exec_counts2[1];         // code relating to IncreaseFilterMult removed here.                // something to do with profiling?        MarkFilterBoundaries.doit(str);        if (KjcOptions.optfile != null) {            System.err.println("Running User-Defined Transformations...");            str = ManualPartition.doit(str);            System.err.println("User-Defined Transformations End.");            // cluster backend should handle multipops             //RemoveMultiPops.doit(str);        }        System.err.println("Running Partitioning... target number of threads: "+threads);        StreamItDot.printGraph(str, "before-partition.dot");        // actually fuse components if fusion flag is enabled        if (KjcOptions.fusion) {            // turn on dynamic programming if no other partitioning is turned on            if (!KjcOptions.partition_greedy && !KjcOptions.partition_greedier) {                KjcOptions.partition_dp = true;            }                    if ( doCacheOptimization ) {                str = CachePartitioner.doit(str, code_cache, data_cache);            } else {                        str = Partitioner.doit(str, 0, threads, false, false);                // from now on, target however many threads were                // produced by the partitioner                KjcOptions.cluster = Partitioner.countFilters(str);            }            /*              if (str instanceof SIRContainer) {              ((SIRContainer)str).reclaimChildren();              }              str.setParent(null);            */        }        //HashMap partitionMap = new HashMap();        partitionMap.clear();        if ( doCacheOptimization ) {            str = new CachePartitioner(str, WorkEstimate.getWorkEstimate(str), 0, code_cache, data_cache).calcPartitions(partitionMap);            str.setParent(null);             str = new DynamicProgPartitioner(str, WorkEstimate.getWorkEstimate(str), threads, false, false).calcPartitions(partitionMap);           } else {            // if mapping to 1 machine, then just map everyone to            // partition 0 as an optimization (the partitioner would            // do the same thing, but would take longer)            if (threads==1) {                mapToPartitionZero(str, partitionMap);            } else {                // Fix up a bug that might be caused by previous                 // pass of partitioner                str.setParent(null);                 str = new DynamicProgPartitioner(str, WorkEstimate.getWorkEstimate(str), threads, false, false).calcPartitions(partitionMap);               }        }            System.err.println("Done Partitioning...");        Unroller.setLimitNoTapeLoops(false, 0);        if (KjcOptions.sjtopipe) {            SJToPipe.doit(str);        }        StreamItDot.printGraph(str, "after-partition.dot");        //VarDecl Raise to move array assignments up        new VarDeclRaiser().raiseVars(str);            //VarDecl Raise to move peek index up so        //constant prop propagates the peek buffer index        new VarDeclRaiser().raiseVars(str);        // optionally print a version of the source code that we're        // sending to the scheduler        if (KjcOptions.print_partitioned_source) {            new streamit.scheduler2.print.PrintProgram().printProgram(IterFactory.createFactory().createIter(str));         }        //run constrained scheduler        System.err.print("Constrained Scheduler Begin...");        topStreamIter = IterFactory.createFactory().createIter(str);        //topStreamIter = IterFactory.createFineGrainedFactory().createIter(str);        //new streamit.scheduler2.print.PrintGraph().printProgram(topStreamIter);        //new streamit.scheduler2.print.PrintProgram().printProgram(topStreamIter);//        if (KjcOptions.debug) {//            debugOutput(str);//        }        System.err.println(" done.");        // end constrained scheduler        System.err.println("Flattener Begin...");        executionCounts = SIRScheduler.getExecutionCounts(str);        PartitionDot.printScheduleGraph(str, "schedule.dot", executionCounts);        GraphFlattener graphFlattener = new GraphFlattener(str);        //graphFlattener.dumpGraph("flatgraph.dot");        System.err.println("Flattener End.");        //create the execution counts for other passes        createExecutionCounts(str, graphFlattener);                if (debugPrint) {            SIRGlobal[] globals;            if (global != null) {                globals = new SIRGlobal[1];                globals[0] = global;            } else globals = new SIRGlobal[0];            System.err.println("// str before Cluster-specific code");            SIRToStreamIt.run(str,interfaces,interfaceTables,structs,globals);            System.err.println("// END str before Cluster-specific code");        }                // if going to standalone without fusion, expand the main        // method names to include the filter name, so we can identify them        if (KjcOptions.standalone && !KjcOptions.fusion) {            RenameAll.expandFunctionNames(str);        }        ////////////////////////////////////////////////        // the cluster specific code begins here        NodeEnumerator.reset();        graphFlattener.top.accept(new NodeEnumerator(), new HashSet(), true);        graphFlattener.top.accept(new RegisterStreams(), new HashSet(), true);        /*        // Remove globals pass is broken in cluster !!!        if (KjcOptions.removeglobals) {        RemoveGlobals.doit(graphFlattener.top);        }        */        StructureIncludeFile.doit(structures, graphFlattener.top);        /// start output portals        SIRPortal portals[] = SIRPortal.getPortals();        LatencyConstraints.detectConstraints(topStreamIter, portals);            /// end output portals            //VarDecl Raise to move array assignments down?        new VarDeclRaiser().raiseVars(str);        // creating filter2Node        filter2Node = new HashMap<SIROperator,FlatNode>();        graphFlattener.top.accept(                new FlatVisitor() {                  public void visitNode(FlatNode node) {                      filter2Node.put(node.contents,node);                  }                },                null,                true);        DiscoverSchedule d_sched = new DiscoverSchedule();        d_sched.findPhases(graphFlattener.top.contents);        //generating code for partitioned nodes        //ClusterExecutionCode.doit(graphFlattener.top);        System.err.println("Generating cluster code...");        ClusterFusion.setPartitionMap(partitionMap);        if (KjcOptions.fusion) {            graphFlattener.top.accept(new ClusterFusion(), new HashSet(), true);        }        //ClusterCode.setPartitionMap(partitionMap);    // legacy code now no-op        ClusterCode.generateCode(graphFlattener.top);   // thread*.cpp        FusionCode.generateFusionHeader(str, doCacheOptimization); // fusion.h        GenerateGlobalDotH.generateGlobalDotH(global, helpers); // global.h        if (KjcOptions.standalone) {            FusionCode.generateFusionFile(d_sched /*, implicit_mult*/); // fusion.cpp        } else {            GenerateMasterDotCpp.generateMasterDotCpp();    // master.cpp            GenerateGlobalDotCpp.generateGlobalDotCpp(global, helpers); // global.cpp        }        GenerateClusterDotH.generateClusterDotH();      // master.h        GenerateMakefile.generateMakefile(helpers);     // Makefile.cluster        GenerateConfigFile.generateConfigFile();        // cluster-config.txt        GenerateSetupFile.generateSetupFile();          // cluster-setup.txt        GenerateWorkEst.generateWorkEst();        // work-estimate.txt        System.err.println(" done.");            /*        // attempt to find constrained schedule!        Greedy g = new Greedy(d_sched);        for (int w = 0; w < 20; w++) {        int res = g.nextPhase(); // find a constrained phase        if (res > 0) break;        }        for (int w = 0; w < 20; w++) {         g.combineInit();        }        */            System.out.println("Exiting");        System.exit(0);    }