📄 designcircuitgenerator.java
字号:
String sm_done = getStateInputForStartSignal(bn, edgePred, sm, block); System.out.println(" inputs "+sm.getInputs()); predicates.addAll(makeFsmInputs(bn, edgePred, exitCond)); // AND the predicate and the statemachine's done signal... block.insertOperator(Operation.AND, "and_"+out, pred_wire, sm_done, out, 1); } return predicates; } /** * This method adds outports to give the FSM access to the predicates * that were calculated inside the block circuit. Both registered and * non-registered versions of the wire can be output. The boolean operand * names are returned in a HashSet. */ HashSet makeFsmInputs(BlockNode bn, BooleanEquation edgePred, HashMap exitCond) { HashSet predicates = new HashSet(); System.out.println(" bn "+bn.getName()+" eq "+edgePred +"\nexitCond hash "+exitCond); // For each boolean operand, create wires for the FSM inputs. Iterator it =((LinkedList)edgePred.listBooleanOperands()).listIterator(); while(it.hasNext()) { boolean makeReg = false, makeNonReg = false; BooleanOperand op = (BooleanOperand) it.next(); String op_name = op.getFullName(); //predicates.add(op_name); // This was adding too many predicates... int defCycle = getOpDefCycle(bn, op_name); /* // For each of the SM cycles... for(int i = 0; i < exitCond.size(); i++) { BooleanEquation cond = (BooleanEquation) exitCond.get(new Integer(i)); if(cond == null) continue; // If the exit condition is equal to the current operand... String condName = cond.toString().replace('~', ' ').trim(); if(condName.equals(op.toString().trim())) { predicates.add(op_name); if(i > defCycle) makeReg = true; else if(i == defCycle) makeNonReg = true; } } */ // danger /* Okay, I don't seem agree with Jeff about whether these should be registered or unregistered. Unless the value used outside of the block (e.g. for start signals), using the unregistered version should be fine. */ makeNonReg = true; if(makeReg && makeNonReg) { // this is not working ... throw new SynthesisException("State machine isn't yet smart enough"+ " to have both registered and non-"+ "registed versions of the same predicate"+ " input!"); } if(makeReg) { // Get the registered wire for the statemachine input. String input = op_name + "_s%" + (defCycle+1); if(!_dpGen.getDpOutWires().contains(op_name)) { _dpGen._circuit.insertOutPort(input, "o_"+op_name, op_name, 1); _dpGen.getDpOutWires().add(op_name); } System.out.println("Making registered FSM input: "+input); } if(makeNonReg) { // Make the non-registered wire for the statemachine input. String input = op_name; if(!_dpGen.getDpOutWires().contains(op_name)) { _dpGen._circuit.insertOutPort(input, "o_"+op_name, op_name, 1); _dpGen.getDpOutWires().add(op_name); } System.out.println("Making non-registered FSM input: "+input); } } return predicates; } /** * Return the last cycle associated with the operand's defining inst. */ private static int getOpDefCycle(BlockNode bn, String operand) { // For each instruction... for(Iterator it = bn.getInstructions().iterator(); it.hasNext(); ) { Instruction inst = (Instruction) it.next(); // If this instruction defines the specified operand... if(inst.getOperand(0).getFullName().equals(operand)) { // Get the last cycle associated with this instruction. int start = inst.getExecClkCnt(); return (start + (int)inst.getRunLength()); } } // If the definition of the operand was not found, throw excpetion! throw new SynthesisException("Operand ("+operand+ ") definition not found!"); } /** * This method makes the control logic for managing the multiple blocks... */ private void makeControlLogic(Circuit block, BlockNode bn, BlockNode exit) { // Add the StateMachine to the sub-circuit. StateMachine sm = newStateMachine(bn); // Create an in port for the start signal. String blkStart = "start_"+bn.getLabel().getFullName(); block.insertInPort(blkStart, "i_"+blkStart, "start", 1); //makeBlockControlInput(bn, entry); HashSet predicates = makeBlockControlOutput(block, bn, sm, exit); LinkedList inputs = new LinkedList(); inputs.add("clk"); inputs.add("reset"); int numCycles = getNumBlockCycles(bn); Set smSet = sm.getInputs().keySet(); predicates.addAll(smSet); inputs.addAll(predicates); block.insertFSM("fsm"+_circuit.getUniqueName(), inputs, sm); // Add outports from the dp to the block for inputs to the FSM... for(Iterator sIt = smSet.iterator(); sIt.hasNext(); ) { String smWire = (String) sIt.next(); // Add an out port to the datapath if it doesn't already exist... if(!_dpGen.getDpOutWires().contains(smWire) && !smWire.equals("start")) { _dpGen._circuit.insertOutPort(smWire, "o_pred_"+smWire, smWire, 1); _dpGen.getDpOutWires().add(smWire); } } String idle = "idle_"+bn.getLabel().getFullName(); block.insertOutPort("s%"+numCycles, "o_idle", idle, 1); _idleWires.add(idle); } private String getStateInputForStartSignal(BlockNode bn, BooleanEquation eq, StateMachine sm, Circuit block) { HashMap cond = sm.getExitConditions(); int cycle = -1; //System.out.println("FSM cond: "+cond); //System.out.println("eq: "+eq); for(int i = 0; i < cond.size(); i++) { BooleanEquation bool = (BooleanEquation)cond.get(new Integer(i)); //System.out.println(" "+bool); if(bool.isEqual(eq)) { //cycle = i+1; cycle = i; break; } } String out = null; if(cycle == -1) { cycle = cond.size()-1; out = "s%"+cycle; } else { out = "s%"+cycle+"_1"; block.insertRegister("reg_s%"+cycle, "s%"+cycle, null, out, 1, 0); } return out; } /** * This method computes the number of cycles that occur in the block node. * It is used to find the size of the state machine. */ static protected int getNumBlockCycles(BlockNode bn) { int max_cycles = 0; for(Iterator it = bn.getInstructions().iterator(); it.hasNext(); ) { Instruction inst = (Instruction) it.next(); int tmp = inst.getExecClkCnt() + (int) inst.getRunLength(); if(max_cycles < tmp) max_cycles = tmp; } return max_cycles+1; // add 1 because "0th" state should be counted. } /** * Return the type of state machine based on the type of scheduling was * performed on the given block node. */ static private StateMachine newStateMachine(BlockNode bn) { if(bn.getIsModuloScheduled()) { int ii = bn.getII(); return new ModuloStateMachine(ii+1, bn); } else { int numCycles = getNumBlockCycles(bn); return new GenericStateMachine(numCycles+1, bn); } } protected void makeConnectionsToRegfile(HashSet add, ArrayList extVars) { // For each block... Iterator blk_it = _topLevelWires.keySet().iterator(); while(blk_it.hasNext()) { String block1 = (String) blk_it.next(); HashSet wires1 = (HashSet) _topLevelWires.get(block1); // For each wire in this block... Iterator wire_it = wires1.iterator(); while(wire_it.hasNext()) { HashMap data_map = new HashMap(); HashMap en_map = new HashMap(); String wire_info = (String) wire_it.next(); int index = wire_info.lastIndexOf('/'); String wire_name = wire_info.substring(0, index); int width = Integer.parseInt(wire_info.substring(index+1)); // If the other blocks contain this wire name, then add them to // the input of the OR operator and delete those wires. int i = 1; Iterator it = _topLevelWires.keySet().iterator(); while(it.hasNext()) { // For each block... String block2 = (String) it.next(); if(!block2.equals(block1)) { // If not looking at same blocks... HashSet wires2 = (HashSet) _topLevelWires.get(block2); if(wires2.contains(wire_info)) { // If both blocks contain the same wire name... data_map.put(block2+"_"+wire_name, new PortTag(null, "in"+i, PortTag.IN, width)); en_map.put(block2+"_"+wire_name+"_we", new PortTag(null, "in"+(i++), PortTag.IN, 1)); wires2.remove(wire_info); } } } // This adds access to the register file. String data_in = null; String en_in = null; if(add.contains(wire_name+"/"+width)) { // Here, the or gate will only have 1 input because the variable // was never stored in the code. data_in = "m_init_"+wire_name; en_in = "init_"+wire_name+"_we"; if(!extVars.contains(wire_name)) throw new SynthesisException("shouldn't have added regfile access -- name: "+wire_name+", external variables: "+extVars); } else { // Here, the or gate will have more than one input because it // was defined at least once. data_in = block1+"_"+wire_name; en_in = block1+"_"+wire_name+"_we"; // If this is a external variable, then make access to the regfile. if(extVars.contains(wire_name)) { data_map.put("m_init_"+wire_name, new PortTag(null, "in"+i, PortTag.IN, width)); en_map.put("init_"+wire_name+"_we", new PortTag(null, "in"+i, PortTag.IN, 1)); } } // If this operand is external, then give it external regfile access. if(extVars.contains(wire_name)) makeRegfileAccess(wire_name, width); // Add the data wires to an OR operator. data_map.put(data_in, new PortTag(null,"in0",PortTag.IN,width)); data_map.put("w_"+wire_name, new PortTag(null, "out", PortTag.OUT, width)); // Add the enable wires to an OR operator. en_map.put(en_in, new PortTag(null,"in0",PortTag.IN,1)); en_map.put("we_"+wire_name, new PortTag(null, "out", PortTag.OUT, 1)); _circuit.insertOperator("or_"+wire_name, Operation.OR, data_map); _circuit.insertOperator("or_"+wire_name+"_we", Operation.OR, en_map); wire_it.remove(); } // Remove the processed block. blk_it.remove(); } } /** * This method gives the user external register file access for the * specified operand. */ void makeRegfileAccess(String operand, int width) { // Create a mux for disabling the init inputs to the design. String zeroOut = _circuit.getUniqueWireName(); _circuit.insertConstant("c_0", 0, zeroOut, width); insertMux(_circuit, "mux_"+operand+_circuit.getUniqueName(), zeroOut, "init_"+operand, "init_"+operand+"_we", "m_init_"+operand, width); // Add inports to the topLevel circuit for initial reg values. if(_buildTop) { int busWidth = RegisterInterfaceGenerator.DATA_BUS_WIDTH; String portOutput = (width == busWidth) ? "init_"+operand : "i_"+operand; _circuit.insertInPort(operand+"_we", "i_"+operand+"_we", "init_"+operand+"_we", 1); _circuit.insertInPort(RegisterInterfaceGenerator.REG_IN, "i_"+operand, portOutput, busWidth); // If the bus width is too wide, then slice it... if(width < busWidth) insertSlice(_circuit, "slice_"+operand, portOutput, 0, width-1, "init_"+operand, busWidth, width); else if(width > busWidth) // If bus is too narrow, exception! throw new SynthesisException("Register is wider than reg bus!"); } else { // Otherwise, just build inports without external wires.. _circuit.insertInPort("i_"+operand+"_we", "init_"+operand+"_we", 1); _circuit.insertInPort("i_"+operand, "init_"+operand, width); } } /* ArrayList getExternalRegs() { return _regfile.getExternals(); } */ /* ArrayList getExtRegInfos() { return _regfile.getExtRegInfos(); } */ HashSet getBusInPorts() { return _memory.getInPorts(); } HashSet getBusOutPorts() { return _memory.getOutPorts(); } class ConnectionPair { ConnectionPair(String wireNameP, int widthP) { wireName = wireNameP; width = widthP; } String wireName; int width; boolean equals(ConnectionPair p) { return (p.wireName.equals(this.wireName) && (p.width == this.width)); } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -