p.print("  #ifdef __FUSED_"+_s1+"_"+_d1+"\n"); p.print("    TAIL_"+_s1+"_"+_d1+" += "+rem+";\n"); p.print("    #ifndef __NOPEEK_"+_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++) {    p.print("  #ifdef __FUSED_"+_s2+"_"+_d2+"\n"); p.print("    #ifdef __NOPEEK_"+_s2+"_"+_d2+"\n"); p.print("      BUFFER_"+_s2+"_"+_d2+"[HEAD_"+_s2+"_"+_d2+" + "+y+"] = \n"); p.print("    #else\n"); p.print("      BUFFER_"+_s2+"_"+_d2+"[(HEAD_"+_s2+"_"+_d2+" + "+y+") & __BUF_SIZE_MASK_"+_s2+"_"+_d2+"] = \n"); p.print("    #endif\n"); p.print("  #else\n"); p.print("    "+s.producer_name()+".push(\n"); p.print("  #endif\n");    p.print("  #ifdef __FUSED_"+_s1+"_"+_d1+"\n"); p.print("    #ifdef __NOPEEK_"+_s1+"_"+_d1+"\n"); p.print("      BUFFER_"+_s1+"_"+_d1+"[TAIL_"+_s1+"_"+_d1+" + "+offs+"]\n"); p.print("    #else\n"); p.print("      BUFFER_"+_s1+"_"+_d1+"[(TAIL_"+_s1+"_"+_d1+" + "+offs+") & __BUF_SIZE_MASK_"+_s1+"_"+_d1+"]\n"); p.print("    #endif\n"); p.print("  #else\n");  if (ClusterFusion.fusedWith(node).contains(source)) { p.print("    "+in.pop_name()+"()\n"); } else { p.print("    "+in.consumer_name()+".pop()\n"); }  p.print("  #endif\n");    p.print("  #ifdef __FUSED_"+_s2+"_"+_d2+"\n"); p.print("    ; p.print("  #else\n"); p.print("    ); p.print("  #endif\n");  offs++; }
    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 = Util.getBaseType(Util.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);		TabbedPrintWriter p;	StringWriter str; 		str = new StringWriter();        p = new TabbedPrintWriter(str);			ClusterCodeGenerator gen = new ClusterCodeGenerator(splitter, new JFieldDeclaration[0]);	p.print("// init counts: "+init_counts+" steady counts: "+steady_counts+"\n"); 	p.print("\n");	//  +=============================+	//  | Preamble                    |	//  +=============================+     	Vector pre = gen.generatePreamble();	for (int i = 0; i < pre.size(); i++) {	    p.print(pre.elementAt(i).toString());	}	//  +=============================+	//  | Splitter Push               |	//  +=============================+	int sum_of_weights = splitter.getSumOfWeights();	p.print(baseType.toString()+" "+in.push_buffer()+"["+sum_of_weights+"];\n");	p.print("int "+in.push_index()+" = 0;\n");	p.print("\n");	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.print("\n");	//  +=============================+	//  | Splitter Pop                |	//  +=============================+	for (int ch = 0; ch < splitter.getWays(); ch++) {	    NetStream _out = (NetStream)out.elementAt(ch);	    int weight = splitter.getWeight(ch);	    p.print(baseType.toString()+" "+_out.pop_buffer()+"["+weight+"];\n");	    p.print("int "+_out.pop_index()+" = "+weight+";\n");	    p.print("\n");	    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.print("\n");	}		//  +=============================+	//  | Splitter Work               |	//  +=============================+	int _s = in.getSource();	int _d = in.getDest();	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();	    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.print("\n");	p.print("void __splitter_"+thread_id+"_work(int ____n) {\n");	p.print("  for (;____n > 0; ____n--) {\n");		FlatNode source = NodeEnumerator.getFlatNode(in.getSource());	if (splitter.getType().equals(SIRSplitType.DUPLICATE)) {	    p.print("  "+baseType.toString()+" tmp;\n");		    _s = in.getSource();	    _d = in.getDest();	    	    p.print("\n");	    p.print("  #ifdef __FUSED_"+_s+"_"+_d+"\n");	    p.print("    #ifdef __NOPEEK_"+_s+"_"+_d+"\n");	    p.print("    tmp = BUFFER_"+_s+"_"+_d+"[TAIL_"+_s+"_"+_d+"];TAIL_"+_s+"_"+_d+"++;\n");	    p.print("    #else\n");	    p.print("    tmp = BUFFER_"+_s+"_"+_d+"[TAIL_"+_s+"_"+_d+"];TAIL_"+_s+"_"+_d+"++;TAIL_"+_s+"_"+_d+"&=__BUF_SIZE_MASK_"+_s+"_"+_d+";\n");	    p.print("    #endif\n");	    p.print("  #else\n");	    if (ClusterFusion.fusedWith(node).contains(source)) {		p.print("  tmp = "+in.pop_name()+"();\n");	    } else {	    		p.print("  tmp = "+in.consumer_name()+".pop();\n");	    	    }	    p.print("  #endif\n");	    p.print("\n");	    for (int i = 0; i < out.size(); i++) {		NetStream s = (NetStream)out.elementAt(i);				_s = s.getSource();		_d = s.getDest();		p.print("  #ifdef __FUSED_"+_s+"_"+_d+"\n");		p.print("    #ifdef __NOPEEK_"+_s+"_"+_d+"\n");		p.print("    BUFFER_"+_s+"_"+_d+"[HEAD_"+_s+"_"+_d+"]=tmp;HEAD_"+_s+"_"+_d+"++;\n");		p.print("    #else\n");		p.print("    BUFFER_"+_s+"_"+_d+"[HEAD_"+_s+"_"+_d+"]=tmp;HEAD_"+_s+"_"+_d+"++;HEAD_"+_s+"_"+_d+"&=__BUF_SIZE_MASK_"+_s+"_"+_d+";\n");		p.print("    #endif\n");		p.print("  #else\n");		p.print("  "+s.producer_name()+".push(tmp);\n");		p.print("  #endif\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();	    	    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	    		    p.print("  #ifdef __FUSED_"+_s2+"_"+_d2+"\n");		    p.print("    #ifdef __NOPEEK_"+_s2+"_"+_d2+"\n");		    p.print("      BUFFER_"+_s2+"_"+_d2+"[HEAD_"+_s2+"_"+_d2+" + "+y+"] = \n");		    p.print("    #else\n");		    p.print("      BUFFER_"+_s2+"_"+_d2+"[(HEAD_"+_s2+"_"+_d2+" + "+y+") & __BUF_SIZE_MASK_"+_s2+"_"+_d2+"] = \n");		    p.print("    #endif\n");		    p.print("  #else\n");		    p.print("    "+s.producer_name()+".push(\n");		    p.print("  #endif\n");		    // Source		    p.print("  #ifdef __FUSED_"+_s1+"_"+_d1+"\n");		    p.print("    #ifdef __NOPEEK_"+_s1+"_"+_d1+"\n");		    p.print("      BUFFER_"+_s1+"_"+_d1+"[TAIL_"+_s1+"_"+_d1+" + "+offs+"]\n");		    p.print("    #else\n");		    p.print("      BUFFER_"+_s1+"_"+_d1+"[(TAIL_"+_s1+"_"+_d1+" + "+offs+") & __BUF_SIZE_MASK_"+_s1+"_"+_d1+"]\n");		    p.print("    #endif\n");		    p.print("  #else\n");		    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		    p.print("  #ifdef __FUSED_"+_s2+"_"+_d2+"\n");		    p.print("    ; // assignement\n");		    p.print("  #else\n");		    		    p.print("    ); // push()\n");		    p.print("  #endif\n");		    		    		    offs++;		}		p.print("  #ifdef __FUSED_"+_s2+"_"+_d2+"\n");		p.print("    HEAD_"+_s2+"_"+_d2+" += "+num+";\n");		p.print("    #ifndef __NOPEEK_"+_s2+"_"+_d2+"\n");		p.print("    HEAD_"+_s2+"_"+_d2+" &= __BUF_SIZE_MASK_"+_s2+"_"+_d2+";\n");		p.print("    #endif\n");		p.print("  #endif\n");	    }	    p.print("  #ifdef __FUSED_"+_s1+"_"+_d1+"\n");	    p.print("    TAIL_"+_s1+"_"+_d1+" += "+sum+";\n");	    p.print("    #ifndef __NOPEEK_"+_s1+"_"+_d1+"\n");	    p.print("    TAIL_"+_s1+"_"+_d1+" &= __BUF_SIZE_MASK_"+_s1+"_"+_d1+";\n");	    p.print("    #endif\n");	    p.print("  #endif\n");	    	    /*	    int sum = splitter.getSumOfWeights();	    int offs = 0;			    p.print("  "+baseType.toString()+" tmp["+sum+"];\n");	    p.print("\n");	    _s = in.getSource();	    _d = in.getDest();	    	    p.print("  #ifdef __FUSED_"+_s+"_"+_d+"\n");	    for (int y = 0; y < sum; y++) {		p.print("    #ifdef __NOPEEK_"+_s+"_"+_d+"\n");		p.print("    tmp["+y+"] = BUFFER_"+_s+"_"+_d+"[TAIL_"+_s+"_"+_d+"];TAIL_"+_s+"_"+_d+"++;\n");		p.print("    #else\n");		p.print("    tmp["+y+"] = BUFFER_"+_s+"_"+_d+"[TAIL_"+_s+"_"+_d+"];TAIL_"+_s+"_"+_d+"++;TAIL_"+_s+"_"+_d+"&=__BUF_SIZE_MASK_"+_s+"_"+_d+";\n");		p.print("    #endif\n");	    }	    p.print("  #else\n");	    if (ClusterFusion.fusedWith(node).contains(source)) {		for (int y = 0; y < sum; y++) {		    p.print("  tmp["+y+"] = "+in.pop_name()+"();\n");		}	    } else {	    		p.print("  "+in.consumer_name()+".pop_items(tmp, "+sum+");\n");	    }	    p.print("  #endif\n");	    p.print("\n");	    	    for (int i = 0; i < out.size(); i++) {		int num = splitter.getWeight(i);		NetStream s = (NetStream)out.elementAt(i);				_s = s.getSource();		_d = s.getDest();		p.print("  #ifdef __FUSED_"+_s+"_"+_d+"\n");		for (int y = 0; y < num; y++) {		    p.print("    #ifdef __NOPEEK_"+_s+"_"+_d+"\n");		    p.print("    BUFFER_"+_s+"_"+_d+"[HEAD_"+_s+"_"+_d+"]=tmp["+(offs+y)+"];HEAD_"+_s+"_"+_d+"++;\n");		    p.print("    #else\n");		    p.print("    BUFFER_"+_s+"_"+_d+"[HEAD_"+_s+"_"+_d+"]=tmp["+(offs+y)+"];HEAD_"+_s+"_"+_d+"++;HEAD_"+_s+"_"+_d+"&=__BUF_SIZE_MASK_"+_s+"_"+_d+";\n");		    p.print("    #endif\n");		}		p.print("  #else\n");		p.print("  "+s.producer_name()+".push_items(&tmp["+offs+"], "+num+");\n");		p.print("  #endif\n");		offs += num;	    }	    */	}	p.print("  }\n");	p.print("}\n");	p.print("\n");	//  +=============================+	//  | Splitter Work 1k            |	//  +=============================+	p.print("void __splitter_"+thread_id+"_work_1k() {\n");	/*	if (splitter.getType().equals(SIRSplitType.DUPLICATE)) {	    	    p.print("  "+baseType.toString()+" tmp[1000 * "+steady_counts+"];\n");	    p.print("  "+in.consumer_name()+".pop_items(tmp, 1000 * "+steady_counts+");\n");			    for (int i = 0; i < out.size(); i++) {        	NetStream s = (NetStream)out.elementAt(i);				p.print("  "+s.producer_name()+".push_items(tmp, 1000 * "+steady_counts+");\n");	    }	} else {	*/			p.print("  for (int i = 0; i < 1000 * "+steady_counts+"; i++) __splitter_"+thread_id+"_work(1);\n");		p.print("}\n");	p.print("\n");	//  +=============================+	//  | Splitter Main               |	//  +=============================+		p.print("void __splitter_"+thread_id+"_main() {\n");	p.print("  int i, ii;\n");		p.print("  if (__steady_"+thread_id+" == 0) {\n");	p.print("    for (i = 0; i < "+init_counts+"; i++) {\n");	p.print("      check_thread_status(__state_flag_"+thread_id+",__thread_"+thread_id+");\n");	p.print("      __splitter_"+thread_id+"_work(1);\n");	p.print("    }\n");	p.print("  }\n");	p.print("  __steady_"+thread_id+"++;\n");	p.print("  while (__number_of_iterations_"+thread_id+" > 1000) {\n");	p.print("    check_thread_status(__state_flag_"+thread_id+",__thread_"+thread_id+");\n");	p.print("    __splitter_"+thread_id+"_work_1k();\n");	p.print("    __number_of_iterations_"+thread_id+" -= 1000;\n");	p.print("    __steady_"+thread_id+" += 1000;\n");	p.print("    if (__frequency_of_chkpts != 0 && __steady_"+thread_id+" % __frequency_of_chkpts == 0) save_state::save_to_file(__thread_"+thread_id+", __steady_"+thread_id+", __write_thread__"+thread_id+");\n");	p.print("  }\n");		p.print("  for (i = 1; i <= __number_of_iterations_"+thread_id+"; i++, __steady_"+thread_id+"++) {\n");		p.print("    for (ii = 0; ii < "+steady_counts+"; ii++) {\n");	p.print("      check_thread_status(__state_flag_"+thread_id+",__thread_"+thread_id+");\n");	p.print("      __splitter_"+thread_id+"_work(1);\n");	p.print("    }\n");	p.print("    if (__frequency_of_chkpts != 0 && __steady_"+thread_id+" % __frequency_of_chkpts == 0) save_state::save_to_file(__thread_"+thread_id+", __steady_"+thread_id+", __write_thread__"+thread_id+");\n");	p.print("  }\n");	p.print("}\n");	//  +=============================+	//  | Run Function                |	//  +=============================+	Vector run = gen.generateRunFunction(null, "__splitter_"+thread_id+"_main");	for (int i = 0; i < run.size(); i++) {	    p.print(run.elementAt(i).toString());	}	//  +=============================+	//  | Write Splitter to File      |	//  +=============================+		try {	    FileWriter fw = new FileWriter("thread"+thread_id+".cpp");	    fw.write(str.toString());	    fw.close();	}	catch (Exception e) {	    System.err.println("Unable to write splitter code to file thread"+thread_id+".cpp");	}		System.out.println("Code for " + node.contents.getName() +			   " written to thread"+thread_id+".cpp");    }