📄 datapathcircuitgenerator.java
字号:
// So, create as many pipeline registers as required. // Get the width of the operand. int width = 0; if(isPredicate) // Predicate logic is boolean, so of width 1. width = 1; else if(isAddress) // Address width should be separate from others. width = ADDR_WIDTH; else if(Cast.conforms(def_inst)) if (operand.equals(Cast.getResult(def_inst).toString())) width = Cast.getType(def_inst).getType().getWidth(); else width = def_inst.type().getWidth(); else // Otherwise, width is variable. width = def_inst.type().getWidth(); if(isPipelined()) { // Add pipeline registers... // CHANGE: is this wire name correct??? //wire_name = def_inst.getOperand(0).getFullName()+"_"+ //(cur_cycle-def_end_cycle); wire_name = result.getFullName()+"_"+cur_cycle; String in_name = null; if(Load.conforms(def_inst)) in_name = Load.getSource(def_inst).getFullName(); else if(ALoad.conforms(def_inst)) in_name = ALoad.getPrimalSource(def_inst).getFullName() + "_" + result.getFullName(); else in_name = result.getFullName(); insertPipelineRegisters(dp,"reg_"+result.getFullName(), in_name, width, cur_cycle - def_end_cycle); } else { // Add a single register because this design isn't pipelined... wire_name=result.getFullName()+"_s%"+(def_end_cycle+1); String in_name = null; if(Load.conforms(def_inst)) in_name = Load.getSource(def_inst).getFullName(); else if(ALoad.conforms(def_inst)) in_name = ALoad.getPrimalSource(def_inst).getFullName() + "_" + result.getFullName(); else in_name = result.getFullName(); if(!_dpRegisters.containsKey(result.getFullName())) { dp.insertRegister("reg_"+result.getFullName(), in_name, insertStateInputFromSM(dp, def_inst), wire_name, width, 0); _dpRegisters.put(result.getFullName(), null); } } } else { // Error case where no previous definitions of the operand were found. throw new SynthesisException("ERROR in makeOpConnection() -- "+ "no previous DEFINITION found:\n"+operand+ ", cur:" + cur_cycle); } return wire_name; } public String makeOpConnection(Circuit dp, String operand, int cur_cycle, BlockNode bn, boolean isPredicate) { return makeOpConnection(dp, operand, cur_cycle, bn, isPredicate, false); } /** * This method determines how to set up the data (whether the data is * in the form of a constant or block or primal) and then follows * through by generating it. This method determines whether a register * is needed between whatever the connection is--this is much more * simplified in that registers are only created here, and then, only * if they are needed. They are only needed if the LHS operand isn't * immediately consumed. */ protected String getOpName(Circuit dp, Instruction cur_inst, Operand operand, boolean isStore, BlockNode bn, boolean isAddress) { String wire_name = null; int width; //System.out.println("getOpName inst "+cur_inst+" op "+operand); //System.out.println(" isStore "+isStore); if (isAddress) width = ADDR_WIDTH; else if (Cast.conforms(cur_inst)) { // cast needs its own special case :( if (operand == Cast.getResult(cur_inst)) { width = Cast.getType(cur_inst).getType().getWidth(); } else { width = cur_inst.type().getWidth(); } } else { // common case width = cur_inst.type().getWidth(); } // jlt old method //int width = (isAddress) ? ADDR_WIDTH : cur_inst.type().getWidth(); /* ?? Future method ? int width = (isAddress) ? MemoryInterfaceGenerator.ADDR_WIDTH : cur_inst.type().getWidth(); */ if (operand.isBlock()) { wire_name = makeOpConnection(dp, operand.toString(), cur_inst.getExecClkCnt(), bn, false, isAddress); } else if(operand.isAddr()) { wire_name = makeOpConnection(dp, operand.toString(), cur_inst.getExecClkCnt(), bn, false, isAddress); } else if(operand.isBoolean()) { wire_name = makeOpConnection(dp, operand.toString(), cur_inst.getExecClkCnt(), bn, true, isAddress); } else if( operand.isConstant() ) { // If the operand is a constant, then create a constant... /* if(ALoad.conforms(cur_inst)) wire_name = dp.getParent().getUniqueWireName(); else */ wire_name = dp.getUniqueWireName(); // Depending on the type of the operand, insert the specific constant if(operand.isFloatConstant()) dp.insertConstant("c_"+((FloatConstantOperand)operand).getValue(), ((FloatConstantOperand)operand).getValue(), wire_name, width); else if(operand.isDoubleConstant()) dp.insertConstant("c_"+((DoubleConstantOperand)operand).getValue(), ((DoubleConstantOperand)operand).getValue(), wire_name, width); else if(operand.isIntConstant()) dp.insertConstant("c_"+((IntConstantOperand)operand).getValue(), ((IntConstantOperand)operand).getValue(), wire_name, width); else throw new SynthesisException("getOpName() -- type not yet supported"); } else if (operand.isPrimal()) { throw new SynthesisException("getOpName(): primal found..."); } else { System.out.println("getOpName -- type of operand not yet supported"); System.out.println(" "+cur_inst); throw new SynthesisException(); } //System.out.println(" wire_name "+wire_name); // Create a port out, if this is a store instruction. if(isStore && !_dpOutWires.contains(wire_name)) { String portIn = wire_name; /* Here Jeff gets a unique wire name, but does not use it for the next request of that same wire. So, this is an incorrect implementation. I have modified it so that it will use the same name always and we will leave the unique wire for another day. jlt -- does this really belong here? If an instruction is a store, it can take care of this itself... Why push the work to this function? wire_name = dp.getParent().getUniqueWireName(); dp.insertOutPort(portIn, "o_"+portIn, wire_name, width); */ dp.insertOutPort(portIn, "o_"+portIn, portIn, width); _dpOutWires.add(portIn); } return wire_name; } protected String getOpName(Circuit dp, Instruction cur_inst, Operand operand, boolean isStore, BlockNode bn) { return getOpName(dp, cur_inst, operand, isStore, bn, false); } /** * This method makes all of the current block's out ports. It does this * after creating the datapath to take care of the case where a STORE * writes to the same variable during different cycles. */ private HashSet makeBlockOutPorts(Circuit block) { Set entries = _blockOutWires.entrySet(); String data_port_input = null; String en_port_input = null; HashSet processed = new HashSet(); HashSet wiresToRegfile = new HashSet(); for(Iterator i1 = entries.iterator(); i1.hasNext(); ) { int n_added = 0; Map.Entry e1 = (Map.Entry) i1.next(); // Skip this entry if already processed. if(processed.contains(e1)) continue; HashMap data_map = new HashMap(); HashMap en_map = new HashMap(); // Separate the state info from the key; save the operand info. String wirename = (String)e1.getKey(); String operand1 = wirename.replaceFirst("_s%[0-9]+$", ""); String state1 = wirename.substring(wirename.lastIndexOf("_s%")); // Get the info on the connecting wire. ConnectionPair pair = (ConnectionPair) e1.getValue(); String pred = pair.wireName; int width = pair.width; // Find all matching map values (operands) and put them in another // map to add to an OR operator. for(Iterator i2 = entries.iterator(); i2.hasNext(); ) { Map.Entry e2 = (Map.Entry) i2.next(); String wirename2 = (String)e2.getKey(); String operand2 = wirename2.replaceFirst("_s%[0-9]+$", ""); String state2 = wirename2.substring(wirename2.lastIndexOf("_s%")); // If the operands are the same, but not necessarily the cycle... // then add the mux outputs to the inputs of the OR gate. if(operand1.equals(operand2)) { data_map.put(e2.getKey(), new PortTag(null, (String)e2.getKey(), PortTag.IN, width)); en_map.put(operand1+"_"+state2+"_we", new PortTag(null, operand1+"_"+state2+"_we", PortTag.IN, 1)); processed.add(e2); n_added++; } } // If only one input was added, then don't create an OR gate, just // an OUT port. if(n_added == 1) { // Name the input wires to the OUT port. data_port_input = (String) e1.getKey(); en_port_input = pred; // Add the OUT ports. String block_name = getCircuitName(block); block.insertOutPort(data_port_input, "o_"+operand1, block_name+"_"+operand1, width); block.insertOutPort(en_port_input, "o_"+operand1+"_we", block_name+"_"+operand1+"_we", 1); String addWireName = operand1+"/"+width; wiresToRegfile.add(addWireName); //ConnectionPair cp = new ConnectionPair(operand1, width); //wiresToRegfile.add(cp); _regfile.addRegister(operand1, "w_"+operand1, "we_"+operand1, "r_"+operand1, width, 0); } else if(n_added > 1) { // Shouldn't allow multiple stores to the same primal in the same // hyperblock... throw new SynthesisException("2+ stores to primal in hyperblock!" + "\n Primal = " + operand1); } // Remove the current map entry now that it has been processed. i1.remove(); } return wiresToRegfile; } /** * This method takes a boolean equation (representing the predicate) and * generates the logic for the circuit. This is usually used for store * operations... */ protected String makePredicateLogic(Circuit graph, BooleanEquation eq, int cycle, BlockNode bn) { if(!predHasBeenDefined(eq, cycle, bn)) { System.out.println("PREDICATE NOT DEFINED! "+eq+" -- cycle: "+cycle); return (String) null; } LinkedList or_inputs = new LinkedList(); for(ListIterator iter = eq.getTwoLevel().listIterator();iter.hasNext(); ) { LinkedList and_inputs = new LinkedList(); LinkedList list = (LinkedList) iter.next(); for(ListIterator list_iter = list.listIterator(); list_iter.hasNext(); ) { String invOut = null; BooleanOp term = (BooleanOp)list_iter.next(); String operand = term.getOp().toString(); String toAdd = makeOpConnection(graph, operand, cycle, bn, true); String name = null; if(term.getSense() == false) { // CHANGE: the following is a hack! there doesn't yet appear // to be a way around this...How do i fix this???? if(term.getOp().getBoolName().trim().startsWith("(BOOLEAN) %")) { int last = term.getOp().getBoolName().lastIndexOf('%'); name = term.getOp().getBoolName().substring(last+1); invOut = "inv%"+name; // invOut = "dp_inv_"+term.getOp().getBoolName(); } else { throw new SynthesisException("ERROR boolean mismatch: " + invOut); } if(!_dpInvWires.contains(invOut)) { graph.insertOperator(Operation.NOT, invOut, toAdd, invOut, 1); _dpInvWires.add(invOut); } } and_inputs.add((term.getSense()) ? toAdd : invOut); } String lower = makeLogicTree(graph, Operation.AND, and_inputs, 1); or_inputs.add(lower); } // Return the output from the logic tree made from the OR list. String out = makeLogicTree(graph, Operation.OR, or_inputs, 1); _predicateWires.put(eq.toString(), out); return out; } /** * This method checks whether an operand has been defined previous to the * given cycle. It returns true if it has been defined and false otherwise. */ static protected boolean hasBeenDefined(String operand, int cycle, BlockNode bn) { // Find the last definition of the operand before it's use in the // current cycle. Iterator it = bn.getInstructions().iterator(); while(it.hasNext()) { Instruction i = (Instruction) it.next(); // If this inst finishes before the cycle when the use occurs... int end_cycle = i.getExecClkCnt() + (int) i.getRunLength(); if(end_cycle < cycle) // If this inst defines the operand... if(i.getOperand(0).toString().trim().equals(operand)) return true; } return false; } /** * This method checks whether a boolean equation has been defined previous * to the given cycle. It returns true if all parts of the boolean equation * have been defined and false otherwise. */ static protected boolean predHasBeenDefined(BooleanEquation be, int cycle, BlockNode bn) { // For each BooleanOp in the BooleanEquation, check if it has been // defined. If any BooleanOp has not been defined, then return false. for(ListIterator iter = be.getTwoLevel().listIterator();iter.hasNext(); ) { Iterator list_iter = ((LinkedList)iter.next()).listIterator(); while(list_iter.hasNext()) { String operand = ((BooleanOp)list_iter.next()).getOp().getBoolName(); if(!hasBeenDefined(operand, cycle, bn)) return false; } } return true; } /** * This method creates 'num' pipeline registers after the input wire. * The names of the wires out of each pipeline register begin with * the specified 'name' and end with a number specifying the pipeline * register stage. */ public void insertPipelineRegisters(Circuit circuit, String name, String input, int width, int num) { // Create the connected pipeline registers. for(int i = 1; i <= num; i++) { if(!_dpRegisters.containsKey(name+"_"+i)) { String in = (i == 1) ? input : name+"_"+(i-1); String out = name+"_"+i; circuit.insertRegister(name+"_"+i, in, null, out, width, 0); _dpRegisters.put(name+"_"+i, null); } } } HashMap getPredicateWires() { return _predicateWires; } HashSet getDpOutWires() { return _dpOutWires; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -