mschedhash.java
来自「一种将c高级语言转化给VHDL的编译器」· Java 代码 · 共 1,684 行 · 第 1/5 页
JAVA
1,684 行
public Operand getNewBlock(Operand op, int iiCnt) { HashMap newBlocksForTimes = null; if(!containsKey(op)) { //if this operand is new, make a new HashMap to save times newBlocksForTimes = new HashMap(); put(op, newBlocksForTimes); } else //otherwise get the saved hashmap newBlocksForTimes = (HashMap)get(op); Operand newBlock = null; if((!newBlocksForTimes.containsKey(new Integer(iiCnt)))|| (newBlocksForTimes.get(new Integer(iiCnt)) == null)) { //make a new block or boolean operand for this operand at this //iteration if(op.isBlock()) newBlock = Operand.nextBlock(op.getFullName() + "_" + iiCnt); else if(op.isBoolean()) newBlock = Operand.nextBoolean(op.getFullName() + "_" + iiCnt); else if(op.isAddr()) { newBlock = Operand.nextAddr(op.getFullName() + "_" + iiCnt); //HashMap ptr2IndicesMap = _chipdef.getptr2IndicesMap(); //ptr2IndicesMap.put(newBlock.toString(), ptr2IndicesMap.get(op.toString())); } newBlocksForTimes.put(new Integer(iiCnt), newBlock); } else newBlock = (Operand)newBlocksForTimes.get(new Integer(iiCnt)); return newBlock; } }//end NewBlockCreator /** instantiate the operand creating classes: */ private ModPrimCreator _modPrimCreator = null; private NewBlockCreator _newBlockCreator = null; /** For a more thorough explanation of what this is for, refer to MuxTableGenerator.java. However the predicates used in primal stores in the loop kernal are saved and used in the epilog. The instructions to do this are not added to the schedule until it has been unrolled and is ready for creating the epilog, becuase they will not be used in the kernal or prolog. But since the loads and stores are added to the original kernal, the operand names used in these instructions must be changed separately so that when they are added to the epilog they already have the correct names. This hashmap is used to save those instructions. keys: primals that were stored to in the kernal values: HashSets of instructions needed to evaluate and load the predicates used when storing to these primals */ private HashMap _savedPredSaveStoreInsts = new HashMap(); /** this contains all the instructions from all the hashsets in the above hashmap */ //private HashSet _allLogic = new HashSet(); /** Because I don't want to add multiple loads and stores for each operand for each time it is used, I only want to save it once. But I need to make sure enough loads and stores exist to carry that operand to its last use. Therefore, as I save new loads and stores, I only save a new version of a load and store on the same operand, if it goes further than previous ones, and if one is saved, the old needs to be erased. These hashes are used to help with this. key: operand being transfered value: (deepestLSObject) the actual load-store object that is the deepest--if another deeper one is found, this value will be used, to delete the old one from SaveStoresNLoads (which extends HashSet) (deepestLSObjectDepth) the latest iteration where this operand is used. I need to save this to compare with other uses of this operand to know if I need to save that use instead. */ private HashMap _deepestLSObject = new HashMap(); private HashMap _deepestLSObjectDepth = new HashMap(); //private HashSet _alreadyAdded = new HashSet(); public SaveStoresNLoads() { super(); _modPrimCreator = new ModPrimCreator(); _newBlockCreator = new NewBlockCreator(); } /** As SaveStoresNLoads extends hashset, we can save load store objects in it. This was written to handle our adds in a special way. It checks to see what the deepest use of an operand is, and only adds a new LSObject if the previous LSObject for this operand was less deep or nonexistent. If there is a LSObject for this operand already and it is less deep, the older one must be deleted. */ public boolean add(LSObject newLS) { //depth of the new LSObject: int hisDepth = newLS.startII + newLS.iiDiff; //operand in question: Operand sourceOp = newLS.op; //current deepest use of this operand (if it is used at all): int deepestDepth = -999; if(_deepestLSObjectDepth.containsKey(sourceOp)) deepestDepth = ((Integer)_deepestLSObjectDepth.get(sourceOp)).intValue(); //if the new LSObject is deeper, remove the old one and add the new //one and save it and its depth to the two deepestLSObject hashmaps if(hisDepth > deepestDepth) { LSObject deepestLSObj = (LSObject)_deepestLSObject.get(sourceOp); super.remove(deepestLSObj); super.add(newLS); _deepestLSObjectDepth.put(sourceOp, new Integer(hisDepth)); _deepestLSObject.put(sourceOp, newLS); return true; } return false;//return true only if an LSObject was added } /** this method is called before saving or adding the loads and stores, to save the kernal primal store predicate instructions */ /*public void savePredLogicInsts(HashMap predLogc) { _savedPredSaveStoreInsts = predLogc; //copy the hashmap to the private //var //copy the instructions from all the hashsets into the alllogic //hashset for (Iterator it1 = predLogc.values().iterator(); it1.hasNext();) { HashSet logicSet = (HashSet)it1.next(); _allLogic.addAll(logicSet); } } public void changePredLogicInsts(Operand oldOp, Operand newOp) { for (Iterator it1 = _allLogic.iterator(); it1.hasNext();) { Instruction predLogicInst = (Instruction)it1.next(); if(Store.conforms(predLogicInst)) predLogicInst.replaceOperand(oldOp, newOp); } }*/ /** This is one of the two main methods for this class, and its purpose is to save all necessary information for all loads and stores */ public void saveLS(int iiCnt, int iiDiff, HashSet connVars, MSchedInstObject cObj, float pST) { //if the child instruction is one of the saved predicate instructions //do nothing, because we want to edit these instructions only in //reference to the primal in which they are associated. To understand //what this is all about, please refer to the comments on //"getKernalPreds" in MuxTableGenerator.java. But anyway, it is //important to note here, that the predicate logic instructions are in //the schedule, and if they were edited like normally, it would seem //they are simply successors of the predicate calculation instruction //(which would be something like %tmp_1 = setlt %tmp_2 %const1.0) //and would add loads and stores and change variable names accordingly //when what we want is to store the actual predicate used when storing //a primal, which could be and probably is some version of %tmp_1 from //a much later iteration. Therefore, when we see these instructions //alone, we need to ignore them, but when we see the primal that they //are associated with, then they need to be edited to use the primal's //new version of %tmp_1 //if(!_allLogic.contains(cObj.inst)) { for (Iterator it1 = connVars.iterator(); it1.hasNext();) { Operand op = (Operand)it1.next(); if(op.isPrimal()) continue; //if an operand is primal it does not //need to be loaded and stored //make a new Block operand for this operand at this time Operand newOp = getNewLoadBlock(op, iiCnt + iiDiff); //create a new LSObject for it: LSObject newLS = new LSObject(iiCnt, iiDiff, pST, cObj.inst.type(), op, newOp); //change the child instruction so that it uses the new operand //from the later iteration: cObj.replaceOperand(op, newOp); cObj.changeItPred(op, newOp); //changePredLogicInsts(op, newOp); //if the child instruction is a save to a primal, then the //predicate logic instructions associated with its store must be //edited to use the new operand instead of the old one /*if((Store.conforms(cObj.inst))&& (Store.getDestination(cObj.inst).isPrimal())) { //foreach inst in logic for (Iterator it2 = ((HashSet)_savedPredSaveStoreInsts.get(Store.getDestination(cObj.inst))).iterator(); it2.hasNext();) { Instruction instTmp = (Instruction)it2.next(); //replace op with newOp instTmp.replaceOperand(op, newOp); } }*/ add(newLS); } //} } /** This is the second of the two main methods for this class. Its purpose is to create and add the loads and stores. It will add enough loads and stores to carry a non primal operand from the iteration where its value was defined up until the latest use. If the latest use is 3 iterations later, then three loads and stores must be created. */ public void addLS(int ii) { //foreach saved LSObject in this: for (Iterator it1 = this.iterator(); it1.hasNext();) { LSObject lsObj = (LSObject)it1.next(); //get the operand, type, and the new operand (this is the new one at //the end and not any in the middle): Operand op = lsObj.op; //if(!_alreadyAdded.contains(op)) { Type type = lsObj.type; Operand newOp = lsObj.newOp; //make sure that if the operand is boolean, that the created loads //and stores are type bool: if(op.isBoolean()) type = Type.Bool; int iiCnt = lsObj.startII; int iiDiff = lsObj.iiDiff; //get a modPrim variable: PrimalOperand modPrim = getPrimal(op, iiCnt); float predStopTime = lsObj.parentStopTime; //create the first store: BooleanEquation trueBoolEq = new BooleanEquation(true); Instruction storeInst = Store.create(Operators.STORE, type, modPrim, op, trueBoolEq); _opSel.select(storeInst); MSchedInstObject storeInstObj = new MSchedInstObject(storeInst); //schedule the store to the end of the modulo scheduled block (ii-1) //It must be at the end, to ensure that the loads and stores occur //in different cycles and that the synthesizer will not delete the //load and use the wire going to the store instead--which would make //the instruction using the loaded value happen one iteration too //early. float storeStartTime = ii-1-storeInstObj.getRunLength(); CorrectStartTimes cPredStopTimeS = new CorrectStartTimes(storeInst, _chipdef, !GlobalOptions.packInstructions); float cPredStopTime = cPredStopTimeS.getCorrectedStartTime(storeStartTime); storeInstObj._iiCnt= iiCnt + (int)((cPredStopTime-predStopTime)/ii); scheduleInst(storeInstObj, cPredStopTime, ii); //if the operand needs to be transfered over more than one //iteration, then add all the necessary loads and stores for(int n = iiCnt + 1; n < iiCnt + iiDiff; n++){ //create new block operand (because of the way the operands are //created, if the operand is used between its definition and its //latest use, this will make a specific block variable for those //intermidiate uses): Operand transferOp = getNewLoadBlock(op, n); //create new load: Instruction loadInstT = Load.create(Operators.LOAD, type, transferOp, modPrim, trueBoolEq); _opSel.select(loadInstT); MSchedInstObject loadInstObjT = new MSchedInstObject(loadInstT); //schedule to time 0, iteration n: loadInstObjT._iiCnt=n; scheduleInst(loadInstObjT, 0, ii); //make new modprim: modPrim = getPrimal(op, n); //make new store: storeInst = Store.create(Operators.STORE, type, modPrim, transferOp, trueBoolEq); _opSel.select(storeInst); storeInstObj = new MSchedInstObject(storeInst); //cPredStopTimeS = new CorrectStartTimes(storeInst, _chipdef, // !GlobalOptions.packInstructions); //cPredStopTime = cPredStopTimeS.getCorrectedStartTime(getLoadTime()); //schedule to ii-1 and iteration n: storeInstObj._iiCnt= n + (int)((cPredStopTime-predStopTime)/ii); scheduleInst(storeInstObj, cPredStopTime, ii); } //create final load: Instruction loadInst = Load.create(Operators.LOAD, type, newOp, modPrim, trueBoolEq); _opSel.select(loadInst); MSchedInstObject loadInstObj = new MSchedInstObject(loadInst); //schedule to time 0, and the iteration of the deepest child: loadInstObj._iiCnt= iiCnt + iiDiff; scheduleInst(loadInstObj, 0, ii); //_alreadyAdded.add(op); //} } } /*public void changeBlockNames(HashSet inVars, MSchedInstObject cObj){ for (Iterator it1 = inVars.iterator(); it1.hasNext();) { Operand op = (Operand)it1.next(); if((op.isBlock())||(op.isBoolean())) { Operand newOp = getNewStoreBlock(op); cObj.replaceOperand(op, newOp); } } }*/ /** use the modprimcreator object to make a new primal */ public PrimalOperand getPrimal(Operand op, int iiCnt) { return _modPrimCreator.getPrim(op, iiCnt); /*if(_op2PrimMap.containsKey(op)) return (PrimalOperand)_op2PrimMap.get(op); PrimalOperand newOp = Operand.newPrimal("modPrim" + _primCreateCnt++); _op2PrimMap.put(op, newOp); return newOp;*/ } /** use the modprimcreator object to make a new block (or Boolean) operand */ public Operand getNewLoadBlock(Operand op, int iiCnt) { return _newBlockCreator.getNewBlock(op, iiCnt); /*if(_op2LoadBlockVarMap.containsKey(op)) return (Operand)_op2LoadBlockVarMap.get(op); Operand newOp = null; if(op.isBlock()) newOp = Operand.nextBlock(op.getFullName()); else if(op.isBoolean()) newOp = Operand.nextBoolean(op.getFullName()); _op2LoadBlockVarMap.put(op, newOp); return newOp;*/ }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?