📄 datapathcircuitgenerator.java
字号:
TypeOperand type_op = Cast.getType(inst); int target_width = type_op.getType().getWidth(); int source_width = inst.type().getWidth(); String op_name = "op_"+inst.operator+dpCircuit.getParent().getUniqueName(); Operation op = library.select(inst); String wire_name; if (op != null) { /* // I don't think I can use this one... dpCircuit.insertOperator(op, op_name, getOpName(dpCircuit, inst, source, false, bn), target.getFullName(), inst.type().getWidth()); */ // this feels like a kludge... if (op.getName().equals("tr_dcast")) { Operation my_op = Operation.SLICE; HashMap map = new HashMap(); String source_name = getOpName(dpCircuit, inst, source, false, bn); map.put(source_name, new PortTag(null, "in0", PortTag.IN, source_width)); String const1_name = dpCircuit.getUniqueWireName(); dpCircuit.insertConstant("c_"+(target_width-1), (target_width-1), const1_name, source_width); map.put(const1_name, new PortTag(null, "in1", PortTag.IN, source_width)); String const2_name = dpCircuit.getUniqueWireName(); dpCircuit.insertConstant("c_"+(0), (0), const2_name, source_width); map.put(const2_name, new PortTag(null, "in2", PortTag.IN, source_width)); String target_name = target.getFullName(); map.put(target_name, new PortTag(null, "out", PortTag.OUT, target_width)); dpCircuit.insertOperator(op_name, my_op, map); } else if (op.getName().equals("tr_ucast")) { // source only matters if (type_op.getType().isSigned()) { // first we slice Operation slice = Operation.SLICE; HashMap slice_map = new HashMap(); String source_name = getOpName(dpCircuit, inst, source, false, bn); slice_map.put(source_name, new PortTag(null, "in0", PortTag.IN, source_width)); String slice_const1 = dpCircuit.getUniqueWireName(); dpCircuit.insertConstant("c_"+(source_width-1), (source_width-1), slice_const1, source_width); slice_map.put(slice_const1, new PortTag(null, "in1", PortTag.IN, source_width)); String slice_const2 = dpCircuit.getUniqueWireName(); dpCircuit.insertConstant("c_"+(source_width-2), (source_width-2), slice_const2, source_width); slice_map.put(slice_const2, new PortTag(null, "in2", PortTag.IN, source_width)); String top_bit = dpCircuit.getUniqueWireName("topbit"); slice_map.put(top_bit, new PortTag(null, "out", PortTag.OUT, 1)); // 1 bit dpCircuit.insertOperator(op_name+"_slice", slice, slice_map); // Then mux Operation mux = Operation.MUX; HashMap mux_map = new HashMap(); mux_map.put(top_bit, new PortTag(null, "s", PortTag.IN, 1)); // top_bit is the selector String mux_const1 = dpCircuit.getUniqueWireName(); int mux_const_width = target_width - source_width; dpCircuit.insertConstant("c_0", BigInteger.ZERO, mux_const1, mux_const_width); mux_map.put(mux_const1, new PortTag(null, "in0", PortTag.IN, mux_const_width)); String mux_const2 = dpCircuit.getUniqueWireName(); BigInteger neg_value = new BigInteger("2").pow(mux_const_width).subtract(BigInteger.ONE); dpCircuit.insertConstant("c_neg", neg_value, mux_const2, mux_const_width); mux_map.put(mux_const2, new PortTag(null, "in1", PortTag.IN, mux_const_width)); String mux_out = dpCircuit.getUniqueWireName("consts"); mux_map.put(mux_out, new PortTag(null, "out", PortTag.OUT, mux_const_width)); dpCircuit.insertOperator(op_name+"_mux", mux, mux_map); // now concat Operation concat = Operation.CONCAT; HashMap concat_map = new HashMap(); concat_map.put(mux_out, new PortTag(null, "in0", PortTag.IN, mux_const_width)); concat_map.put(source_name, new PortTag(null, "in1", PortTag.IN, source_width)); String target_name = target.getFullName(); concat_map.put(target_name, new PortTag(null, "out", PortTag.OUT, target_width)); dpCircuit.insertOperator(op_name, concat, concat_map); } else { Operation my_op = Operation.CONCAT; HashMap map = new HashMap(); String source_name = getOpName(dpCircuit, inst, source, false, bn); map.put(source_name, new PortTag(null, "in0", PortTag.IN, source_width)); String const1_name = dpCircuit.getUniqueWireName(); dpCircuit.insertConstant("c_"+0, 0, const1_name, target_width - source_width); map.put(const1_name, new PortTag(null, "in1", PortTag.IN, source_width)); String target_name = target.getFullName(); map.put(target_name, new PortTag(null, "out", PortTag.OUT, target_width)); dpCircuit.insertOperator(op_name, my_op, map); } } else { HashMap map = new HashMap(); String source_name = getOpName(dpCircuit, inst, source, false, bn); map.put(source_name, new PortTag(null, "in0", PortTag.IN, source_width)); String target_name = target.getFullName(); map.put(target_name, new PortTag(null, "out", PortTag.OUT, target_width)); dpCircuit.insertOperator(op_name, op, map); } } else { // throw exception ... throw new SynthesisException("Unknown cast operator "+inst); } } /** * This method implements the load operator in the datapath logic. Its * simple in that it only makes IN ports from the regfile to the datapath. * It then relies on other operators to build a register if the value is * not immediately consumed by any instruction. If the value is only * immediately consumed then no registers will be connected by the * consuming instructions. */ private void caseLoad(Circuit dpCircuit, Instruction inst, BlockNode bn) { Circuit block = dpCircuit.getParent(); Operand source = Load.getSource(inst); Operand target = Load.getResult(inst); String primal = source.getFullName(); String local = target.getFullName(); int width = inst.type().getWidth(); // Deal with all the types of operands! if(target.isPrimal()) throw new SynthesisException("register copy not allowed..."); if(source.isConstant() || source.isBlock()) { // Create a buffer... String in = getOpName(dpCircuit, inst, source, false, bn); String out = target.getFullName(); insertBuf(dpCircuit, "buf_"+dpCircuit.getUniqueName(), in, out, width); return; } else if(!source.isPrimal()) { // Error! throw new SynthesisException("Unhandled operand for load"); } String blk_primal = primal+block.getUniqueName(); if(!_dpInWires.contains(primal)) { dpCircuit.insertInPort(blk_primal, "i_"+primal, primal, width); _dpInWires.add(primal); // Has a primal already been loaded? If not, make a path of // wires and ports to the regfile. _regfile.addRegister(primal, "w_"+primal, "we_"+primal, "r_"+primal, width, 0); } if(!_blkWires.contains(primal)) { block.insertInPort("r_"+primal, "i_"+primal, blk_primal, width); _blkWires.add(primal); } } /** * This method implements the select operator in the datapath logic. */ private void caseSelect(Circuit dpCircuit, Instruction inst, BlockNode bn) { Operand source1 = Select.getVal1(inst); Operand source2 = Select.getVal2(inst); Operand condition = Select.getCondition(inst); Operand target = Select.getResult(inst); String out = target.getFullName(); boolean isPrimalResult = target.isPrimal(); if(isPrimalResult) throw new SynthesisException("caseSelect: primal result found."); // Build a mux or buffer depending on how the conditional evaluates. if(condition == BooleanOperand.TRUE) { // Create a buffer with the 1st input. String in0 = getOpName(dpCircuit, inst, source1, false, bn); insertBuf(dpCircuit, "buf_"+inst.operator+dpCircuit.getUniqueName(), in0, out, inst.type().getWidth()); } else if(condition == BooleanOperand.FALSE) { // Create a buffer with the 2nd input. String in1 = getOpName(dpCircuit, inst, source2, false, bn); insertBuf(dpCircuit, "buf_"+inst.operator+dpCircuit.getUniqueName(), in1, out, inst.type().getWidth()); } else if (source1 == source2) { System.out.println("WARNING: mux with identical inputs"); // Create a buffer with the 1st input. String in0 = getOpName(dpCircuit, inst, source1, false, bn); insertBuf(dpCircuit, "buf_"+inst.operator+dpCircuit.getUniqueName(), in0, out, inst.type().getWidth()); } else { // Create a mux because the conditional isn't known yet... String in0 = getOpName(dpCircuit, inst, source2, false, bn); String in1 = getOpName(dpCircuit, inst, source1, false, bn); String sel = getOpName(dpCircuit, inst, condition, false, bn); String name = "mux_"+inst.operator+dpCircuit.getUniqueName(); insertMux(dpCircuit, name, in0, in1, sel, out, inst.type().getWidth()); } } /** * This method implements a store operator in the datapath logic. */ private void caseStore(Circuit dpCircuit, Instruction inst, BlockNode bn) { Circuit blockCircuit = dpCircuit.getParent(); Operand source = Store.getValue(inst); Operand target = Store.getDestination(inst); boolean isPrimalCopy = source.isPrimal(); if(isPrimalCopy) // Primal copies are not allowed! throw new SynthesisException("register copy not allowed..."); // If this is a store to a block, then just use a buffer... if(target.isBlock() || target.isAddr()) { String in = getOpName(dpCircuit, inst, source, false, bn); String out = target.getFullName(); insertBuf(dpCircuit, "buf"+dpCircuit.getUniqueName(), in, out, inst.type().getWidth()); return; } // jt -- ugh // In this case there should only be one. String blkEn = inst.getOperand(0).getFullName()+"_we"; String dataOut = makeDataMuxLogic(dpCircuit, inst, blkEn, bn); // Save the mux output and write enable to connect to outports later. // The write enable wire is just the mux_out string plus "_en" added // to the end. The mux output and write enable will be added at the // same time, so only one element needs to be added to the hashmap. ConnectionPair predAndWidth = new ConnectionPair(blkEn, inst.type().getWidth()); _blockOutWires.put(dataOut, predAndWidth); } /** * This method implements test operations (i.e. setgt, setlt, ...) in * the datapath logic. */ private void caseTest(Circuit dpCircuit, Instruction inst, BlockNode bn) { Operand source1 = Test.getVal1(inst); Operand source2 = Test.getVal2(inst); Operation op = library.select(inst); if (op != null) { String op_name = "op_" + inst.operator+dpCircuit.getUniqueName(); HashMap map = new HashMap(); map.put(getOpName(dpCircuit, inst, source1, false, bn), new PortTag(null, "in0", PortTag.IN, inst.type().getWidth())); map.put(getOpName(dpCircuit, inst, source2, false, bn), new PortTag(null, "in1", PortTag.IN, inst.type().getWidth())); map.put(inst.getOperand(0).getFullName(), new PortTag(null, "out", PortTag.OUT, 1)); dpCircuit.insertOperator(op_name, op, map); } else { // throw exception ... throw new SynthesisException("Unknown test operator "+inst); } } /** * This method implements unary operations (not, ...) in the datapath. */ private void caseUnary(Circuit dpCircuit, Instruction inst, BlockNode bn) { Operand source = Unary.getVal(inst); Operand target = Unary.getResult(inst); String op_name = "op_"+inst.operator+dpCircuit.getParent().getUniqueName(); Operation op = library.select(inst); if (op != null) { dpCircuit.insertOperator(op, op_name, getOpName(dpCircuit, inst, source, false, bn), target.getFullName(), inst.type().getWidth()); } else { // throw exception ... throw new SynthesisException("Unknown unary operator "+inst); } } /** * This method creates an in port from the block level to the dataflow * level. It gives the state associated with this instruction. */ private String insertStateInputFromSM(Circuit dp, int startCycle, float runLength) { String cycle = "s%"+(int)(startCycle+runLength); // CHANGE: the following won't work with multiple blocks?? // this had to be done because getPortByName() returns some // odd results... if ( dp.getPortByName(getCircuitName(dp)+"_0."+"i_"+cycle+".0") != null ) { return cycle; } insertInPort(dp, cycle, "i_"+cycle, cycle, 1); return cycle; } private String insertStateInputFromSM(Circuit dp, Instruction inst) { return insertStateInputFromSM(dp, inst.getExecClkCnt(), inst.getRunLength()); } /** * This method connects the definition of an operand to its use in the * current cycle. Pipeline registers (or a single register) are added * if necessary. A string is returned with the name of the wire. */ public String makeOpConnection(Circuit dp, String operand, int cur_cycle, BlockNode bn, boolean isPredicate, boolean isAddress) { String wire_name = null; Instruction def_inst = null; int def_end_cycle = -1; Operand result = null; // this looks really bad -- it needs to be fixed. /* Why do we need to search through all the instructions? What about the def-use hashes? Why can't we have the instruction? */ // Find the most recent def of the current operand. for(Iterator it = bn.getInstructions().iterator(); it.hasNext(); ) { Instruction i_inst = (Instruction) it.next(); int i_start_cycle = i_inst.getExecClkCnt(); int i_end_cycle = i_start_cycle + (int)i_inst.getRunLength(); // Don't check any instructions that are scheduled later than // the current instruction. if(i_start_cycle > cur_cycle) break; // but don't look at operands that aren't available yet if(i_end_cycle > cur_cycle) continue; // identify the instruction def Operand i_result = AStore.conforms(i_inst) ? AStore.getAddrDestination(i_inst) : i_inst.getOperand(0); if(i_result.toString().equals(operand)) { def_inst = i_inst; def_end_cycle = i_end_cycle; result = i_result; } } //System.out.println(" Op "+operand); //System.out.println("def_end_cycle "+def_end_cycle+" cur_cycle "+cur_cycle); if(def_end_cycle == cur_cycle) { // This is where immediate consumption of the LHS operand occurs. // So, no registers are needed. if(Load.conforms(def_inst)) wire_name = Load.getSource(def_inst).getFullName(); else if(ALoad.conforms(def_inst)) wire_name = ALoad.getPrimalSource(def_inst).getFullName()+"_"+ ALoad.getResult(def_inst).getFullName(); /* wire_name = def_inst.getOperand(2).getFullName()+"_"+ def_inst.getOperand(0).getFullName(); */ else wire_name = result.getFullName(); } else if((def_end_cycle < cur_cycle) && (def_end_cycle >= 0)) { // This is where delayed consumption of the LHS operand occurs.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -