p.print("    "+((NetStream)out.elementAt(y)).producer_name()+".push(tmp);\n");
p.print("    "+ out.get(y).producer_name()+".push(tmp);\n");
    public static void generateSplitter(FlatNode node) {                SIRSplitter splitter = (SIRSplitter)node.contents;        if (splitter.getSumOfWeights() == 0) {            // The splitter is not doing any work                    return;        }        int init_counts, steady_counts;        Integer init_int = (Integer)ClusterBackend.initExecutionCounts.get(node);        if (init_int==null) {            init_counts = 0;        } else {            init_counts = init_int.intValue();        }        steady_counts = ((Integer)ClusterBackend.steadyExecutionCounts.get(node)).intValue();        CType baseType = CommonUtils.getBaseType(CommonUtils.getOutputType(node));        int thread_id = NodeEnumerator.getSIROperatorId(node.contents);        Vector in_v = (Vector)RegisterStreams.getNodeInStreams(node.contents);        NetStream in = (NetStream)in_v.elementAt(0);        Vector out = (Vector)RegisterStreams.getNodeOutStreams(node.contents);            CodegenPrintWriter p = null;        try {            p = new CodegenPrintWriter(new FileWriter("thread"+thread_id+".cpp"));        } catch (IOException e) {            e.printStackTrace();            System.exit(1);        }        ClusterCodeGenerator gen = new ClusterCodeGenerator(splitter, new JFieldDeclaration[0]);        p.println("// init counts: "+init_counts+" steady counts: "+steady_counts);         p.newLine();        //  +=============================+        //  | Preamble                    |        //  +=============================+             FlatIRToCluster f2c = new FlatIRToCluster(p);        gen.generatePreamble(f2c,p);        p.println("void save_peek_buffer__"+thread_id+"(object_write_buffer *buf) {}");        p.println("void load_peek_buffer__"+thread_id+"(object_write_buffer *buf) {}");        p.newLine();	p.println("void save_file_pointer__"+thread_id+"(object_write_buffer *buf) {}");	p.println("void load_file_pointer__"+thread_id+"(object_write_buffer *buf) {}");        p.newLine();        //  +=============================+        //  | Splitter Push               |        //  +=============================+        int sum_of_weights = splitter.getSumOfWeights();	if (! KjcOptions.standalone) { 	//p.print("#ifndef __CLUSTER_STANDALONE\n");        p.print(baseType.toString()+" "+in.push_buffer()+"["+sum_of_weights+"];\n");        p.print("int "+in.push_index()+" = 0;\n");        p.newLine();        p.print("void "+in.push_name()+"("+baseType.toString()+" data) {\n");        if (splitter.getType().equals(SIRSplitType.DUPLICATE)) {            for (int i = 0; i < out.size(); i++) {                NetStream s = (NetStream)out.elementAt(i);                      FlatNode dest = NodeEnumerator.getFlatNode(s.getDest());                if (ClusterFusion.fusedWith(node).contains(dest)) {                    p.print("  "+s.push_name()+"(data);\n");                } else {                    p.print("  "+s.producer_name()+".push(data);\n");                }            }               } else {            p.print("  "+in.push_buffer()+"["+in.push_index()+"++] = data;\n");            p.print("  if ("+in.push_index()+" == "+sum_of_weights+") {\n");            int offs = 0;                    for (int i = 0; i < out.size(); i++) {                int num = splitter.getWeight(i);                NetStream s = (NetStream)out.elementAt(i);                FlatNode dest = NodeEnumerator.getFlatNode(s.getDest());                if (ClusterFusion.fusedWith(node).contains(dest)) {                    for (int y = 0; y < num; y++) {                        p.print("  "+s.push_name()+"("+in.push_buffer()+"["+(offs+y)+"]);\n");                    }                } else {                    p.print("    "+s.producer_name()+".push_items(&"+in.push_buffer()+"["+offs+"], "+num+");\n");                }                offs += num;            }            p.print("    "+in.push_index()+" = 0;\n");            p.print("  }\n");        }        p.print("}\n");        p.newLine();        //  +=============================+        //  | Splitter Pop                |        //  +=============================+        int split_ways = splitter.getWays();        for (int ch = 0; ch < split_ways; ch++) {            int weight = splitter.getWeight(ch);            if (weight == 0) { // this deals with the odd case of a 0 weight                 ch--;          // which will have no coresponding output edge                split_ways--;  // in the graph.                continue;            }            NetStream _out = (NetStream)out.elementAt(ch);            p.print(baseType.toString()+" "+_out.pop_buffer()+"["+weight+"];\n");            p.print("int "+_out.pop_index()+" = "+weight+";\n");            p.newLine();            p.print(baseType.toString()+" "+_out.pop_name()+"() {\n");            if (splitter.getType().equals(SIRSplitType.DUPLICATE)) {                p.print("    "+baseType.toString()+" tmp = "+in.consumer_name()+".pop();\n");                for (int y = 0; y < splitter.getWays(); y++) {                    if (y != ch) {                        p.print("    "+((NetStream)out.elementAt(y)).producer_name()+".push(tmp);\n");                    }                }                p.print("    return tmp;\n");                    } else {                int sum = splitter.getSumOfWeights();                int offs = 0;                        p.print("  "+baseType.toString()+" tmp["+sum+"];\n");                p.print("  if ("+_out.pop_index()+" == "+splitter.getWeight(ch)+") {\n");                        p.print("    "+in.consumer_name()+".pop_items(tmp, "+sum+");\n");                        for (int y = 0; y < out.size(); y++) {                    int num = splitter.getWeight(y);                    NetStream s = (NetStream)out.elementAt(y);                    if (y == ch) {                        p.print("    memcpy(&tmp["+offs+"], "+_out.pop_buffer()+", "+num+" * sizeof("+baseType.toString()+"));\n");                    } else {                        p.print("    "+s.producer_name()+".push_items(&tmp["+offs+"], "+num+");\n");                    }                    offs += num;                }                p.print("    "+_out.pop_index()+" = 0;\n");                p.print("  }\n");                p.print("  return "+_out.pop_buffer()+"["+_out.pop_index()+"++];\n");            }            p.print("}\n");            p.newLine();        }    	//p.print("#endif // __CLUSTER_STANDALONE\n");	}        //  +=============================+        //  | Splitter Work               |        //  +=============================+        int _s = in.getSource();        int _d = in.getDest();        if (FixedBufferTape.isFixedBuffer(_s,_d)) {        //p.print("#ifdef __FUSED_"+_s+"_"+_d+"\n");        p.print("extern "+baseType.toString()+" BUFFER_"+_s+"_"+_d+"[];\n");        p.print("extern int HEAD_"+_s+"_"+_d+";\n");        p.print("extern int TAIL_"+_s+"_"+_d+";\n");        //p.print("#endif\n");        }                for (int o = 0; o < out.size(); o++) {            _s = ((NetStream)out.elementAt(o)).getSource();            _d = ((NetStream)out.elementAt(o)).getDest();            if (FixedBufferTape.isFixedBuffer(_s,_d)) {            //p.print("#ifdef __FUSED_"+_s+"_"+_d+"\n");            p.print("extern "+baseType.toString()+" BUFFER_"+_s+"_"+_d+"[];\n");            p.print("extern int HEAD_"+_s+"_"+_d+";\n");            p.print("extern int TAIL_"+_s+"_"+_d+";\n");            //p.print("#endif\n");            }        }        p.newLine();        p.print("void __splitter_"+thread_id+"_work(int ____n) {\n");        p.print("  " + baseType.toString() + " tmp;\n");        p.print("  for (;____n > 0; ____n--) {\n");            FlatNode source = NodeEnumerator.getFlatNode(in.getSource());        if (splitter.getType().equals(SIRSplitType.DUPLICATE)) {            _s = in.getSource();            _d = in.getDest();                  if (FixedBufferTape.isFixedBuffer(_s, _d)) {                if (!FixedBufferTape.needsModularBuffer(_s, _d)) {                    p.print("    tmp = BUFFER_" + _s + "_" + _d + "[TAIL_" + _s                            + "_" + _d + "];TAIL_" + _s + "_" + _d + "++;\n");                } else {                    p.print("    tmp = BUFFER_" + _s + "_" + _d + "[TAIL_" + _s                            + "_" + _d + "];TAIL_" + _s + "_" + _d + "++;TAIL_"                            + _s + "_" + _d + "&=__BUF_SIZE_MASK_" + _s + "_"                            + _d + ";\n");                }            } else {                p.print("  " + baseType.toString() + " tmp;\n");                p.newLine();                if (ClusterFusion.fusedWith(node).contains(source)) {                    p.print("  tmp = " + in.pop_name() + "();\n");                } else {                    p.print("  tmp = " + in.consumer_name() + ".pop();\n");                }            }            p.newLine();            for (int i = 0; i < out.size(); i++) {                NetStream s = (NetStream)out.elementAt(i);                      _s = s.getSource();                _d = s.getDest();                if (FixedBufferTape.isFixedBuffer(_s, _d)) {                    if (!FixedBufferTape.needsModularBuffer(_s, _d)) {                        p.print("    BUFFER_" + _s + "_" + _d + "[HEAD_" + _s                                + "_" + _d + "]=tmp;\n    HEAD_" + _s + "_"                                + _d + "++;\n");                    } else {                        p.print("    BUFFER_" + _s + "_" + _d + "[HEAD_" + _s                                + "_" + _d + "]=tmp;\n    HEAD_" + _s + "_"                                + _d + "++;HEAD_" + _s + "_" + _d                                + "&=__BUF_SIZE_MASK_" + _s + "_" + _d + ";\n");                    }                } else {                    p.print("  " + s.producer_name() + ".push(tmp);\n");                }            }                } else if (splitter.getType().equals(SIRSplitType.ROUND_ROBIN) ||                   splitter.getType().equals(SIRSplitType.WEIGHTED_RR)) {                    int sum = splitter.getSumOfWeights();            int offs = 0;            int _s1 = in.getSource();            int _d1 = in.getDest();	    // depending on the weight unroll fully or by some constant factor            if (sum > 128) {                // big weight do not unroll everything!!                for (int i = 0; i < out.size(); i++) {                    int num = splitter.getWeight(i);                    NetStream s = (NetStream)out.elementAt(i);                                      int _s2 = s.getSource();                    int _d2 = s.getDest();                            //p.println("// ClusterCode_2");		    		    int step = 8;                    p.print("  for (int k = 0; k < "+num/step+"; k++) {\n");                                for (int y = 0; y < step; y++) {                                    // Destination                        if (FixedBufferTape.isFixedBuffer(_s2,_d2)) {                        //p.print("  #ifdef __FUSED_"+_s2+"_"+_d2+"\n");                        if (! FixedBufferTape.needsModularBuffer(_s2,_d2)) {                         //p.print("    #ifdef __NOMOD_"+_s2+"_"+_d2+"\n");                        p.print("      BUFFER_"+_s2+"_"+_d2+"[HEAD_"+_s2+"_"+_d2+" + "+y+"] = ");                        //p.print("    #else\n");                        } else {                        p.print("      BUFFER_"+_s2+"_"+_d2+"[(HEAD_"+_s2+"_"+_d2+" + "+y+") & __BUF_SIZE_MASK_"+_s2+"_"+_d2+"] = ");                        //p.print("    #endif\n");                        }                         } else {                        //p.print("  #else\n");                        p.print("    "+s.producer_name()+".push(\n");                        //p.print("  #endif\n");                        }                                                // Source                        if (FixedBufferTape.isFixedBuffer(_s1,_d1)) {                        //p.print("  #ifdef __FUSED_"+_s1+"_"+_d1+"\n");                        if (! FixedBufferTape.needsModularBuffer(_s1,_d1)) {                        //p.print("    #ifdef __NOMOD_"+_s1+"_"+_d1+"\n");                        p.print("BUFFER_"+_s1+"_"+_d1+"[TAIL_"+_s1+"_"+_d1+" + "+y+"]\n");                        //p.print("    #else\n");                        } else {                        p.print("BUFFER_"+_s1+"_"+_d1+"[(TAIL_"+_s1+"_"+_d1+" + "+y+") & __BUF_SIZE_MASK_"+_s1+"_"+_d1+"]\n");                        //p.print("    #endif\n");                        }                        //p.print("  #else\n");                        } else {                        if (ClusterFusion.fusedWith(node).contains(source)) {                            p.print("    "+in.pop_name()+"()\n");                        } else {                                    p.print("    "+in.consumer_name()+".pop()\n");                        }                                    //p.print("  #endif\n");                        }                        // Close Assignement to Dest or Push Operator                        if (FixedBufferTape.isFixedBuffer(_s2,_d2)) {                        //p.print("  #ifdef __FUSED_"+_s2+"_"+_d2+"\n");                        p.print("    ; // assignement\n");                        //p.print("  #else\n");                                   } else {                        p.print("    ); // push()\n");                        //p.print("  #endif\n");                        }                    }                    if (FixedBufferTape.isFixedBuffer(_s2,_d2)) {                    //p.print("  #ifdef __FUSED_"+_s2+"_"+_d2+"\n");                    p.print("    HEAD_"+_s2+"_"+_d2+" += "+step+";\n");                    if (FixedBufferTape.needsModularBuffer(_s2,_d2)) {                    //p.print("    #ifndef __NOMOD_"+_s2+"_"+_d2+"\n");                    p.print("    HEAD_"+_s2+"_"+_d2+" &= __BUF_SIZE_MASK_"+_s2+"_"+_d2+";\n");                    //p.print("    #endif\n");                    }                    //p.print("  #endif\n");                    }                    if (FixedBufferTape.isFixedBuffer(_s1,_d1)) {                    //p.print("  #ifdef __FUSED_"+_s1+"_"+_d1+"\n");                    p.print("    TAIL_"+_s1+"_"+_d1+" += "+step+";\n");                    if (FixedBufferTape.needsModularBuffer(_s1,_d1)) {                    //p.print("    #ifndef __NOMOD_"+_s1+"_"+_d1+"\n");                    p.print("    TAIL_"+_s1+"_"+_d1+" &= __BUF_SIZE_MASK_"+_s1+"_"+_d1+";\n");                    //p.print("    #endif\n");                    }                    //p.print("  #endif\n");                    }                    p.print("  }\n");                    // remainder                    int rem = num % step;                    for (int y = 0; y < rem; y++) {                                    // Destination                        if (FixedBufferTape.isFixedBuffer(_s2,_d2)) {                        //p.print("  #ifdef __FUSED_"+_s2+"_"+_d2+"\n");                        if (! FixedBufferTape.needsModularBuffer(_s2,_d2)) {                        //p.print("    #ifdef __NOMOD_"+_s2+"_"+_d2+"\n");                        p.print("      BUFFER_"+_s2+"_"+_d2+"[HEAD_"+_s2+"_"+_d2+" + "+y+"] = \n");                        //p.print("    #else\n");                        } else {                        p.print("      BUFFER_"+_s2+"_"+_d2+"[(HEAD_"+_s2+"_"+_d2+" + "+y+") & __BUF_SIZE_MASK_"+_s2+"_"+_d2+"] = \n");                        //p.print("    #endif\n");                        }                        //p.print("  #else\n");                        } else {                        p.print("    "+s.producer_name()+".push(\n");                        //p.print("  #endif\n");                        }                        // Source                        if (FixedBufferTape.isFixedBuffer(_s1,_d1)) {                        //p.print("  #ifdef __FUSED_"+_s1+"_"+_d1+"\n");                        if (! FixedBufferTape.needsModularBuffer(_s1,_d1)) {                        //p.print("    #ifdef __NOMOD_"+_s1+"_"+_d1+"\n");                        p.print("      BUFFER_"+_s1+"_"+_d1+"[TAIL_"+_s1+"_"+_d1+" + "+y+"]\n");                        //p.print("    #else\n");                        } else {                        p.print("      BUFFER_"+_s1+"_"+_d1+"[(TAIL_"+_s1+"_"+_d1+" + "+y+") & __BUF_SIZE_MASK_"+_s1+"_"+_d1+"]\n");                        p.print("    #endif\n");                        }                        //p.print("  #else\n");                        } else {                        if (ClusterFusion.fusedWith(node).contains(source)) {                            p.print("    "+in.pop_name()+"()\n");                        } else {                                    p.print("    "+in.consumer_name()+".pop()\n");                        }                                    //p.print("  #endif\n");                        }                        // Close Assignement to Dest or Push Operator                        if (FixedBufferTape.isFixedBuffer(_s2,_d2)) {                        //p.print("  #ifdef __FUSED_"+_s2+"_"+_d2+"\n");                        p.print("    ; // assignement\n");                        //p.print("  #else\n");                          } else {                        p.print("    ); // push()\n");                        //p.print("  #endif\n");                        }                    }                    if (FixedBufferTape.isFixedBuffer(_s2,_d2)) {                    //p.print("  #ifdef __FUSED_"+_s2+"_"+_d2+"\n");                    p.print("    HEAD_"+_s2+"_"+_d2+" += "+rem+";\n");                    if (FixedBufferTape.needsModularBuffer(_s2,_d2)) {                    //p.print("    #ifndef __NOMOD_"+_s2+"_"+_d2+"\n");                    p.print("    HEAD_"+_s2+"_"+_d2+" &= __BUF_SIZE_MASK_"+_s2+"_"+_d2+";\n");                    //p.print("    #endif\n");                    }                    //p.print("  #endif\n");                    }                    if (FixedBufferTape.isFixedBuffer(_s1,_d1)) {                    //p.print("  #ifdef __FUSED_"+_s1+"_"+_d1+"\n");                    p.print("    TAIL_"+_s1+"_"+_d1+" += "+rem+";\n");                    if (FixedBufferTape.needsModularBuffer(_s1,_d1)) {                    //p.print("    #ifndef __NOMOD_"+_s1+"_"+_d1+"\n");                    p.print("    TAIL_"+_s1+"_"+_d1+" &= __BUF_SIZE_MASK_"+_s1+"_"+_d1+";\n");                    //p.print("    #endif\n");                    }                    //p.print("  #endif\n");                    }                }                    } else {                        for (int i = 0; i < out.size(); i++) {                    int num = splitter.getWeight(i);                    NetStream s = (NetStream)out.elementAt(i);                                      int _s2 = s.getSource();                    int _d2 = s.getDest();                                for (int y = 0; y < num; y++) {                                    // Destination                        if (FixedBufferTape.isFixedBuffer(_s2,_d2)) {                        //p.print("  #ifdef __FUSED_"+_s2+"_"+_d2+"\n");                        if (! FixedBufferTape.needsModularBuffer(_s2,_d2)) {                        //p.print("    #ifdef __NOMOD_"+_s2+"_"+_d2+"\n");                        p.print("      BUFFER_"+_s2+"_"+_d2+"[HEAD_"+_s2+"_"+_d2+" + "+y+"] = \n");                        //p.print("    #else\n");                        } else {                        p.print("      BUFFER_"+_s2+"_"+_d2+"[(HEAD_"+_s2+"_"+_d2+" + "+y+") & __BUF_SIZE_MASK_"+_s2+"_"+_d2+"] = \n");                        //p.print("    #endif\n");                        }                        //p.print("  #else\n");                        } else {                        p.print("    "+s.producer_name()+".push(\n");                        //p.print("  #endif\n");                        }                        // Source                        if (FixedBufferTape.isFixedBuffer(_s1,_d1)) {                        //p.print("  #ifdef __FUSED_"+_s1+"_"+_d1+"\n");                        if (! FixedBufferTape.needsModularBuffer(_s1,_d1)) {                        //p.print("    #ifdef __NOMOD_"+_s1+"_"+_d1+"\n");                        p.print("      BUFFER_"+_s1+"_"+_d1+"[TAIL_"+_s1+"_"+_d1+" + "+offs+"]\n");                        //p.print("    #else\n");                        } else {                        p.print("      BUFFER_"+_s1+"_"+_d1+"[(TAIL_"+_s1+"_"+_d1+" + "+offs+") & __BUF_SIZE_MASK_"+_s1+"_"+_d1+"]\n");                        //p.print("    #endif\n");                        }                        //p.print("  #else\n");                        } else {                        if (ClusterFusion.fusedWith(node).contains(source)) {                            p.print("    "+in.pop_name()+"()\n");                        } else {                                    p.print("    "+in.consumer_name()+".pop()\n");                        }                                    //p.print("  #endif\n");                        }                        // Close Assignement to Dest or Push Operator                        if (FixedBufferTape.isFixedBuffer(_s2,_d2)) {                        //p.print("  #ifdef __FUSED_"+_s2+"_"+_d2+"\n");                        p.print("    ; // assignment\n");                        //p.print("  #else\n");                        } else {                        p.print("    ); // push()\n");                        //p.print("  #endif\n");                        }                        offs++;                    }                    if (FixedBufferTape.isFixedBuffer(_s2,_d2)) {                    //p.print("  #ifdef __FUSED_"+_s2+"_"+_d2+"\n");                    p.print("    HEAD_"+_s2+"_"+_d2+" += "+num+";\n");                    if (FixedBufferTape.needsModularBuffer(_s2,_d2)) {                    //p.print("    #ifndef __NOMOD_"+_s2+"_"+_d2+"\n");                    p.print("    HEAD_"+_s2+"_"+_d2+" &= __BUF_SIZE_MASK_"+_s2+"_"+_d2+";\n");                    //p.print("    #endif\n");                    }                    //p.print("  #endif\n");                    }                }                if (FixedBufferTape.isFixedBuffer(_s1,_d1)) {                //p.print("  #ifdef __FUSED_"+_s1+"_"+_d1+"\n");                p.print("    TAIL_"+_s1+"_"+_d1+" += "+sum+";\n");                if (FixedBufferTape.needsModularBuffer(_s1,_d1)) {                //p.print("    #ifndef __NOMOD_"+_s1+"_"+_d1+"\n");                p.print("    TAIL_"+_s1+"_"+_d1+" &= __BUF_SIZE_MASK_"+_s1+"_"+_d1+";\n");                //p.print("    #endif\n");                }                //p.print("  #endif\n");                }           }        }        p.print("  }\n");        p.print("}\n");        p.newLine();        //  +=============================+        //  | Splitter Main               |        //  +=============================+        //  +=============================+        //  | Run Function                |        //  +=============================+        Vector<String> run = gen.generateRunFunction(null, "__splitter_"                + thread_id + "_main", new Vector<String>());        for (int i = 0; i < run.size(); i++) {            p.print(run.elementAt(i).toString());        }        //  +=============================+        //  | Write Splitter to File      |        //  +=============================+            try {            p.close();        }        catch (Exception e) {            System.err.println("Unable to write splitter code to file thread"+thread_id+".cpp");        }            if (ClusterBackend.debugPrint)            System.out.println("Code for " + node.contents.getName() +                               " written to thread"+thread_id+".cpp");    }