@Override public Boolean caseProcedure(Procedure procedure) { this.procedure = procedure; // Test if The procedure contains a BlockWhile before size - 1 int blockSize = procedure.getBlocks().size(); if (blockSize > 1) { Block block = procedure.getBlocks().get(blockSize - 2); if (block.isBlockWhile()) { // If it is check if an additional loop should be added doSwitch(block); } else { return true; } } return false; }
private boolean isSinlgeReturnBlock(Block block) { if (block.isBlockBasic()) { BlockBasic basic = (BlockBasic) block; if (basic.getInstructions().size() == 1) { Instruction instruction = basic.getInstructions().get(0); if (instruction.isInstReturn()) { return true; } } } return false; }
@Override public Void caseAction(Action action) { // FIXME: Do not detect a pathological case for the moment, // extra clock cycles for (Port port : action.getOutputPattern().getPorts()) { int size = action.getOutputPattern().getNumTokensMap().get(port); if (size > 1) { Var newVar = newPortToVarMap.get(port); Var var = action.getOutputPattern().getPortToVarMap().get(port); EList<Use> uses = var.getUses(); while (!uses.isEmpty()) { uses.get(0).setVariable(newVar); } EList<Def> defs = var.getDefs(); while (!defs.isEmpty()) { defs.get(0).setVariable(newVar); } // Create the Block while for the repeat BlockWhile whileBlock = IrFactory.eINSTANCE.createBlockWhile(); whileBlock.setJoinBlock(IrFactory.eINSTANCE.createBlockBasic()); // Create the condition Type type = IrFactory.eINSTANCE.createTypeInt(32); Var index = IrFactory.eINSTANCE.createVar(type, "rp_Index_" + port.getName(), true, 0); action.getBody().getLocals().add(index); ExprVar condE0 = IrFactory.eINSTANCE.createExprVar(index); ExprInt condE1 = IrFactory.eINSTANCE.createExprInt(size); ExprBinary whileCond = IrFactory.eINSTANCE.createExprBinary( condE0, OpBinary.LT, condE1, IrFactory.eINSTANCE.createTypeBool()); whileBlock.setCondition(whileCond); // Create an if block with a pin Status as condition Var pinStatus = IrFactory.eINSTANCE.createVar( IrFactory.eINSTANCE.createTypeBool(), "portStatus_" + port.getName(), true, 0); action.getBody().getLocals().add(pinStatus); // Add portStatus to the first block of the while BlockBasic firstWhileBlock = IrFactory.eINSTANCE.createBlockBasic(); InstPortStatus portStatus = XronosIrUtil.createInstPortStatus(pinStatus, port); firstWhileBlock.add(portStatus); whileBlock.getBlocks().add(firstWhileBlock); BlockIf blockIf = IrFactory.eINSTANCE.createBlockIf(); blockIf.setJoinBlock(IrFactory.eINSTANCE.createBlockBasic()); ExprVar ifCond = IrFactory.eINSTANCE.createExprVar(pinStatus); blockIf.setCondition(ifCond); // ----------------------------------------------------------- // Then Block // Create While blockBasic BlockBasic thenBlock = IrFactory.eINSTANCE.createBlockBasic(); // Create a Load instruction Type tmpLoadType = IrUtil.copy(port.getType()); Var tmpLoad = IrFactory.eINSTANCE.createVar(tmpLoadType, "tmp_rp_" + port.getName(), true, 0); action.getBody().getLocals().add(tmpLoad); ExprVar loadIndex = IrFactory.eINSTANCE.createExprVar(index); InstLoad load = IrFactory.eINSTANCE.createInstLoad( tmpLoad, newVar, Arrays.asList((Expression) loadIndex)); thenBlock.add(load); // Create the Port Write instruction InstPortWrite portWrite = XronosIrUtil.createInstPortWrite(port, tmpLoad, false); thenBlock.add(portWrite); // Create the instruction assign with index++ ExprVar assignE0 = IrFactory.eINSTANCE.createExprVar(index); ExprInt assignE1 = IrFactory.eINSTANCE.createExprInt(1); ExprBinary assignValue = IrFactory.eINSTANCE.createExprBinary( assignE0, OpBinary.PLUS, assignE1, IrFactory.eINSTANCE.createTypeInt()); InstAssign assignIndex = IrFactory.eINSTANCE.createInstAssign(index, assignValue); thenBlock.add(assignIndex); // ----------------------------------------------------------- // Add to thenBlocks the thenBlock blockIf.getThenBlocks().add(thenBlock); // Add the ifBlock to the Block While whileBlock.getBlocks().add(blockIf); // Create a Block Basic with rp_Index_ to 0 BlockBasic initRpIndex = IrFactory.eINSTANCE.createBlockBasic(); InstAssign rpAssignZero = IrFactory.eINSTANCE.createInstAssign(index, 0); initRpIndex.add(rpAssignZero); // Add the BlockWhile to the body of the procedure int indexBlock = action.getBody().getBlocks().size(); Block lastBlock = action.getBody().getBlocks().get(indexBlock - 1); if (isSinlgeReturnBlock(lastBlock)) { action.getBody().getBlocks().add(indexBlock - 1, initRpIndex); action.getBody().getBlocks().add(indexBlock, whileBlock); } else { if (lastBlock.isBlockBasic()) { BlockBasic basic = (BlockBasic) lastBlock; int instrSize = basic.getInstructions().size(); if (basic.getInstructions().get(instrSize - 1).isInstReturn()) { Instruction returnInst = basic.getInstructions().get(instrSize - 1); BlockBasic newLastBlock = IrFactory.eINSTANCE.createBlockBasic(); newLastBlock.add(returnInst); action.getBody().getBlocks().add(initRpIndex); action.getBody().getBlocks().add(whileBlock); action.getBody().getBlocks().add(newLastBlock); } } } } } return null; }