/** * generate the switch code for 1 data item given the list of destinations we do not want to * duplicate items until neccessary, so we have to keep track of all the routes and then generate * the switch code this way we can route multiple dests per route instruction */ protected void generateSwitchCode(FlatNode fire, List<FlatNode> dests) { assert !(layout.getIdentities().contains(fire)); // should only have one previous HashMap<ComputeNode, ComputeNode> prev = new HashMap<ComputeNode, ComputeNode>(); HashMap<ComputeNode, HashSet> next = new HashMap<ComputeNode, HashSet>(); ListIterator<FlatNode> destsIt = dests.listIterator(); while (destsIt.hasNext()) { FlatNode dest = destsIt.next(); assert dest != null; assert !(layout.getIdentities().contains(dest)); // System.out.println(" Dest: " + dest + " " + layout.getTile(dest)); ComputeNode[] hops = layout .router .getRoute(ssg, layout.getComputeNode(fire), layout.getComputeNode(dest)) .toArray(new ComputeNode[0]); assert hops.length > 1 : "Error: Bad Layout (could not find route from " + fire.toString() + " -> " + dest.toString(); // for (int i = 0; i < hops.length; i++) // System.out.println(" " + hops[i]); // add to fire's next if (!next.containsKey(layout.getComputeNode(fire))) next.put(layout.getComputeNode(fire), new HashSet()); next.get(layout.getComputeNode(fire)).add(hops[1]); // add to all other previous, next for (int i = 1; i < hops.length - 1; i++) { if (prev.containsKey(hops[i])) if (prev.get(hops[i]) != hops[i - 1]) Utils.fail("More than one previous tile for a single data item"); prev.put(hops[i], hops[i - 1]); if (!next.containsKey(hops[i])) next.put(hops[i], new HashSet()); next.get(hops[i]).add(hops[i + 1]); } // add the last step, plus the dest to the dest map if (prev.containsKey(hops[hops.length - 1])) if (prev.get(hops[hops.length - 1]) != hops[hops.length - 2]) Utils.fail("More than one previous tile for a single data item (2)"); prev.put(hops[hops.length - 1], hops[hops.length - 2]); if (!next.containsKey(hops[hops.length - 1])) next.put(hops[hops.length - 1], new HashSet()); next.get(hops[hops.length - 1]).add(hops[hops.length - 1]); } // create the appropriate amount of routing instructions int elements = Util.getTypeSize(CommonUtils.getOutputType(fire)); for (int i = 0; i < elements; i++) asm(layout.getComputeNode(fire), prev, next); }
public static SIRJoiner create(SIRContainer parent, SIRJoinType type, JExpression[] weights) { if (type == SIRJoinType.NULL) { return new SIRJoiner(parent, type, Utils.initLiteralArray(weights.length, 0), true); } else if (type == SIRJoinType.WEIGHTED_RR) { return createWeightedRR(parent, weights); } else if (type == SIRJoinType.ROUND_ROBIN) { JExpression weight = (weights.length > 0 ? weights[0] : new JIntLiteral(1)); return createUniformRR(parent, weight); } else { Utils.fail("Unrecognized joiner type."); return null; } }
/** consume the data and return the number of items produced * */ protected int fireMe( FlatNode fire, SimulationCounter counters, HashMap<FlatNode, Integer> executionCounts) { if (fire.contents instanceof SIRFilter) { // decrement the schedule execution counter decrementExecutionCounts(fire, executionCounts, counters); // consume the date from the buffer counters.decrementBufferCount(fire, consumedItems(fire, counters, executionCounts)); // for a steady state execution return the normal push int ret = ((SIRFilter) fire.contents).getPushInt(); // if the filter is a two stage, and it has not fired // return the initPush() unless the initWork does nothing if (initSimulation && !counters.hasFired(fire) && fire.contents instanceof SIRTwoStageFilter) ret = ((SIRTwoStageFilter) fire.contents).getInitPushInt(); else if (!initSimulation && KjcOptions.ratematch) { // we are ratematching so produce all the data on the one firing. ret *= ssg.getMult(fire, false); } // now this node has fired counters.setFired(fire); return ret; } else if (fire.contents instanceof SIRJoiner) { return fireJoiner(fire, counters, executionCounts); } Utils.fail("Trying to fire a non-filter or joiner"); return -1; }
/** * Tests whether or not this has the same type and the same weights as obj. This can return true * for splitters with different numbers of outputs if the type is not a weighted round robin. */ public boolean equals(SIRJoiner obj) { if (type != SIRJoinType.WEIGHTED_RR || obj.type != SIRJoinType.WEIGHTED_RR) { return type == obj.type; } else { return Utils.equalArrays(getWeights(), obj.getWeights()); } }
/** Constructs a joiner with given parent, type and n number of inputs. */ public static SIRJoiner create(SIRContainer parent, SIRJoinType type, int n) { if (type == SIRJoinType.COMBINE) { // fill weights with 1 return new SIRJoiner(parent, type, Utils.initLiteralArray(n, 1), true); } else if (type == SIRJoinType.NULL) { // for null type, fill with zero weights return new SIRJoiner(parent, type, Utils.initLiteralArray(n, 0), true); } else if (type == SIRJoinType.WEIGHTED_RR) { // if making a weighted round robin, should use other constructor Utils.fail("Need to specify weights for weighted round robin"); return null; } else if (type == SIRJoinType.ROUND_ROBIN) { // if making a round robin, should use other constructor Utils.fail("Need to specify weight for uniform round robin"); return null; } else { Utils.fail("Unreckognized joiner type."); return null; } }
/** Give that a node has just fired, update the simulation state * */ protected void decrementExecutionCounts( FlatNode fire, HashMap<FlatNode, Integer> executionCounts, SimulationCounter counters) { // decrement one from the execution count int oldVal = executionCounts.get(fire).intValue(); if (oldVal - 1 < 0) Utils.fail("Executed too much"); // if we are ratematching the node only fires once but only do this // for filters if (!initSimulation && KjcOptions.ratematch && fire.contents instanceof SIRFilter) { executionCounts.put(fire, new Integer(0)); } else executionCounts.put(fire, new Integer(oldVal - 1)); }
protected SIRStream doCut( LinkedList<PartitionRecord> partitions, PartitionRecord curPartition, int x1, int x2, int xPivot, int tileLimit, int tPivot, SIRStream str) { // there's a division at this <yPivot>. We'll // return result of a horizontal cut. int[] arr = {1 + (xPivot - x1), x2 - xPivot}; PartitionGroup pg = PartitionGroup.createFromArray(arr); SIRContainer result; // might have either pipeline or feedback loop at this point... if (str instanceof SIRPipeline) { result = RefactorPipeline.addHierarchicalChildren((SIRPipeline) str, pg); } else if (str instanceof SIRFeedbackLoop) { // if we have a feedbackloop, then factored is // just the original, since it will have only // two children result = (SIRContainer) str; } else { result = null; Utils.fail("Unrecognized stream type: " + str); } // recurse up and down SIRStream top = traceback(partitions, curPartition, x1, xPivot, tPivot, result.get(0)); // mark that we have a partition here curPartition = new PartitionRecord(); partitions.add(curPartition); SIRStream bot = traceback(partitions, curPartition, xPivot + 1, x2, tileLimit - tPivot, result.get(1)); // mutate ourselves if we haven't been mutated yet result.set(0, top); result.set(1, bot); // all done return result; }
/** Throws an exception (NOT SUPPORTED YET) */ public JExpression analyse(CExpressionContext context) throws PositionedError { at.dms.util.Utils.fail("Analysis of SIR nodes not supported yet."); return this; }
/* * Generates JVM bytecode to evaluate this expression. NOT SUPPORTED YET. * * @param code the bytecode sequence * @param discardValue discard the result of the evaluation ? */ public void genCode(CodeSequence code, boolean discardValue) { at.dms.util.Utils.fail("Codegen of SIR nodes not supported yet."); }
/** This is for creating a round robin with uniform weights across the stream. */ public static SIRJoiner createUniformRR(SIRContainer parent, JExpression weight) { // make a uniform rr joiner return new SIRJoiner( parent, SIRJoinType.WEIGHTED_RR, Utils.initArray(Math.max(parent.size(), 1), weight), true); }
/** * Constructs a weighted round-robin joiner with the given parent and weights. Here the number of * weights must match the number of weights in the splitjoin. */ public static SIRJoiner createWeightedRR(SIRContainer parent, JExpression[] weights) { return new SIRJoiner(parent, SIRJoinType.WEIGHTED_RR, weights, Utils.isUniform(weights)); }
/** * If this is a joiner that has equal weight per way, then rescale the weights to be of the given * <extent> */ public void rescale(int extent) { if (uniform) { this.weights = Utils.initArray(extent, weights[0]); } }
/** Generates a sequence of bytescodes - NOT SUPPORTED YET. */ public void genCode(CodeSequence code) { at.dms.util.Utils.fail("Codegen of SIR nodes not supported yet."); }
/** Analyses the statement (semantically) - NOT SUPPORTED YET. */ public void analyse(CBodyContext context) throws PositionedError { at.dms.util.Utils.fail("Analysis of SIR nodes not supported yet."); }
/* * File reader code currently works by using fread. * * The File* is declared outside any function / method. * * This code follows the model in the library of stalling (not pushing) * at end of file (detected by fread returning 0). * */ private static void genFileReaderWork( SIRFileReader filter, Tape outputTape, int selfID, CodegenPrintWriter p) { if (KjcOptions.asciifileio) { System.err.println("Error: -asciifileio not supported in cluster backend."); System.err.println("Exiting..."); System.exit(1); } String theType = "" + filter.getOutputType(); // dispatch to special routine for bit type if (theType.equals("bit")) { genFileReaderWorkBit(filter, outputTape, selfID, p); return; } // get source and destination ids of outgoing tape Tape out = RegisterStreams.getFilterOutStream(filter); int s = out.getSource(); int d = out.getDest(); // template code to generate, using symbolic free vars above. StringBuilder sb = new StringBuilder(); sb.append("\n int __index;\n"); sb.append(" for (__index=0; __index < ____n; __index++) {\n"); if (KjcOptions.compressed) { sb.append(" unsigned char __temp = 0;\n"); sb.append(" FileReader_read(__file_descr__"); sb.append(selfID); sb.append(", &__temp, 1);\n"); sb.append(" PUSH(__temp);\n"); sb.append(" unsigned int __frame_size = __temp;\n"); sb.append(" FileReader_read(__file_descr__"); sb.append(selfID); sb.append(", &__temp, 1);\n"); sb.append(" PUSH(__temp);\n"); sb.append(" __frame_size <<= 8;\n"); sb.append(" __frame_size += __temp;\n"); sb.append(" FileReader_read(__file_descr__"); sb.append(selfID); sb.append(", &__temp, 1);\n"); sb.append(" PUSH(__temp);\n"); sb.append(" __frame_size <<= 8;\n"); sb.append(" __frame_size += __temp;\n"); sb.append(" FileReader_read(__file_descr__"); sb.append(selfID); sb.append(", &__temp, 1);\n"); sb.append(" PUSH(__temp);\n"); sb.append(" __frame_size <<= 8;\n"); sb.append(" __frame_size += __temp;\n"); // the frame size includes the four bytes used to state the frame size sb.append(" FileReader_read(__file_descr__"); sb.append(selfID); sb.append(", (void *)(BUFFER + HEAD), __frame_size - 4);\n"); sb.append(" HEAD += __frame_size - 4;\n"); } else { sb.append(" PUSH(FileReader_read<"); sb.append(theType); sb.append(">(__file_descr__"); sb.append(selfID); sb.append("));\n"); } sb.append(" }\n"); String template = sb.toString(); /* " #ifdef FUSED" + "\n" + " #ifdef NOMOD" + "\n" + " // read directly into buffer" + "\n" + " if (fread(&(BUFFER[HEAD]), sizeof(BUFFER[HEAD]), ____n, FILEREADER)) {" + "\n" + " HEAD+=____n;" + "\n" + " }" + "\n" + " #else" + "\n" + " // wraparound buffer, might have to read in two pieces (but never" + "\n" + " // more, since we would overwrote what we already wrote on this call)" + "\n" + " if (HEAD+____n <= __BUF_SIZE_MASK) {" + "\n" + " // no overflow" + "\n" + " if (fread(&(BUFFER[HEAD]), sizeof(BUFFER[HEAD]), ____n, FILEREADER)) {" + "\n" + " HEAD+=____n;" + "\n" + " }" + "\n" + " } else {" + "\n" + " // overflow, need two pieces" + "\n" + " int piece1 = __BUF_SIZE_MASK - HEAD;" + "\n" + " int piece2 = ____n - piece1;" + "\n" + " if (fread(&(BUFFER[HEAD]), sizeof(BUFFER[HEAD]), piece1, FILEREADER)) {" + "\n" + " if (fread(&(BUFFER[0]), sizeof(BUFFER[HEAD]), piece2, FILEREADER)) {" + "\n" + " HEAD+=____n;" + "\n" + " HEAD&=__BUF_SIZE_MASK;" + "\n" + " }" + "\n" + " }" + "\n" + " }" + "\n" + " #endif" + "\n" + " #else" + "\n" + " // read as a block" + "\n" + " TYPE __buffer[____n];" + "\n" + " int __index;" + "\n" + " if (fread(__buffer, sizeof(__buffer[0]), ____n, FILEREADER)) {" + "\n" + " for (__index=0; __index < ____n; __index++) {" + "\n" + " // should move push out of loop, but not clear if mult-push implemented yet" + "\n" + " PUSH(__buffer[__index]);" + "\n" + " }" + "\n" + " }" + "\n" + " #endif"; */ // set values of free variables String TYPE = theType; String FILEREADER = fpName(filter); String FUSED = "__FUSED_" + s + "_" + d; String NOMOD = "__NOMOD_" + s + "_" + d; String BUFFER = "BUFFER_" + s + "_" + d; String HEAD = "HEAD_" + s + "_" + d; String BUF_SIZE_MASK = "__BUF_SIZE_MASK_" + s + "_" + d; String PUSH = outputTape.getPushName(); // replace templates with correct values template = Utils.replaceAll(template, "TYPE", TYPE); template = Utils.replaceAll(template, "FILEREADER", FILEREADER); template = Utils.replaceAll(template, "FUSED", FUSED); template = Utils.replaceAll(template, "NOMOD", NOMOD); template = Utils.replaceAll(template, "BUFFER", BUFFER); template = Utils.replaceAll(template, "HEAD", HEAD); template = Utils.replaceAll(template, "BUF_SIZE_MASK", BUF_SIZE_MASK); template = Utils.replaceAll(template, "PUSH", PUSH); // output code p.println(template); }