/*
* Copyright (c) 2009-2011, IETR/INSA of Rennes
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the IETR/INSA of Rennes nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
package net.sf.orcc.frontend;
import static net.sf.orcc.ir.IrFactory.eINSTANCE;
import static net.sf.orcc.util.OrccAttributes.COPY_OF_TOKENS;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import net.sf.orcc.cal.cal.AstAction;
import net.sf.orcc.cal.cal.AstActor;
import net.sf.orcc.cal.cal.AstEntity;
import net.sf.orcc.cal.cal.AstExpression;
import net.sf.orcc.cal.cal.AstPort;
import net.sf.orcc.cal.cal.AstProcedure;
import net.sf.orcc.cal.cal.AstState;
import net.sf.orcc.cal.cal.AstTag;
import net.sf.orcc.cal.cal.ExpressionVariable;
import net.sf.orcc.cal.cal.Function;
import net.sf.orcc.cal.cal.InputPattern;
import net.sf.orcc.cal.cal.OutputPattern;
import net.sf.orcc.cal.cal.RegExp;
import net.sf.orcc.cal.cal.ScheduleFsm;
import net.sf.orcc.cal.cal.Variable;
import net.sf.orcc.cal.cal.VariableReference;
import net.sf.orcc.cal.cal.util.CalSwitch;
import net.sf.orcc.cal.services.Evaluator;
import net.sf.orcc.cal.services.Typer;
import net.sf.orcc.cal.util.Util;
import net.sf.orcc.cal.util.VoidSwitch;
import net.sf.orcc.df.Action;
import net.sf.orcc.df.Actor;
import net.sf.orcc.df.DfFactory;
import net.sf.orcc.df.FSM;
import net.sf.orcc.df.Pattern;
import net.sf.orcc.df.Port;
import net.sf.orcc.df.State;
import net.sf.orcc.df.Tag;
import net.sf.orcc.frontend.schedule.ActionList;
import net.sf.orcc.frontend.schedule.ActionSorter;
import net.sf.orcc.frontend.schedule.FSMBuilder;
import net.sf.orcc.frontend.schedule.RegExpConverter;
import net.sf.orcc.ir.Block;
import net.sf.orcc.ir.BlockBasic;
import net.sf.orcc.ir.BlockWhile;
import net.sf.orcc.ir.Def;
import net.sf.orcc.ir.ExprVar;
import net.sf.orcc.ir.Expression;
import net.sf.orcc.ir.InstAssign;
import net.sf.orcc.ir.InstCall;
import net.sf.orcc.ir.InstLoad;
import net.sf.orcc.ir.InstStore;
import net.sf.orcc.ir.IrFactory;
import net.sf.orcc.ir.OpBinary;
import net.sf.orcc.ir.Procedure;
import net.sf.orcc.ir.Type;
import net.sf.orcc.ir.TypeList;
import net.sf.orcc.ir.Use;
import net.sf.orcc.ir.Var;
import net.sf.orcc.util.OrccUtil;
import net.sf.orcc.util.util.EcoreHelper;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
/**
* This class transforms an AST actor to its IR equivalent.
*
* @author Matthieu Wipliez
*
*/
public class ActorTransformer extends CalSwitch<Actor> {
/**
* count of un-tagged actions
*/
private int untaggedCount;
final StructTransformer structTransformer;
/**
* Creates a new AST to IR transformation.
*/
public ActorTransformer() {
structTransformer = new StructTransformer();
}
/**
* Transforms the given AST Actor to an IR actor.
*
* @param astActor
* the AST of the actor
* @return the actor in IR form
*/
@Override
public Actor caseAstActor(AstActor astActor) {
untaggedCount = 0;
Actor actor = DfFactory.eINSTANCE.createActor();
Frontend.instance.putMapping(astActor, actor);
actor.setFileName(astActor.eResource().getURI().toPlatformString(true));
int lineNumber = Util.getLocation(astActor);
actor.setLineNumber(lineNumber);
// parameters
for (Variable variable : astActor.getParameters()) {
final Var var = (Var) structTransformer.doSwitch(variable);
actor.getParameters().add(var);
}
// state variables
for (Variable variable : astActor.getStateVariables()) {
final Var var = (Var) structTransformer.doSwitch(variable);
actor.getStateVars().add(var);
}
// Create empty stubs for functions and procedures
// This tip will allow to call a function/procedure declared later
for (Function function : astActor.getFunctions()) {
final Procedure procedure = IrFactory.eINSTANCE.createProcedure(
function.getName(), 0, Typer.getType(function));
Frontend.instance.putMapping(function, procedure);
actor.getProcs().add(procedure);
}
for (AstProcedure astProcedure : astActor.getProcedures()) {
final Procedure procedure = IrFactory.eINSTANCE.createProcedure(
astProcedure.getName(), 0, Typer.getType(astProcedure));
Frontend.instance.putMapping(astProcedure, procedure);
actor.getProcs().add(procedure);
}
// Really transform functions / procedures
for (Function function : astActor.getFunctions()) {
structTransformer.doSwitch(function);
}
for (AstProcedure astProcedure : astActor.getProcedures()) {
structTransformer.doSwitch(astProcedure);
}
// transform ports
for (AstPort astPort : astActor.getInputs()) {
final Port port = (Port) structTransformer.doSwitch(astPort);
actor.getInputs().add(port);
}
for (AstPort astPort : astActor.getOutputs()) {
final Port port = (Port) structTransformer.doSwitch(astPort);
actor.getOutputs().add(port);
}
// transform actions
ActionList actions = transformActions(astActor.getActions());
// transform initializes
ActionList initializes = transformActions(astActor.getInitializes());
// sort actions by priority
ActionSorter sorter = new ActionSorter(actions);
ActionList sortedActions = sorter.applyPriority(astActor
.getPriorities());
// transform FSM
ScheduleFsm schedule = astActor.getScheduleFsm();
RegExp scheduleRegExp = astActor.getScheduleRegExp();
if (schedule == null && scheduleRegExp == null) {
actor.getActionsOutsideFsm().addAll(sortedActions.getAllActions());
} else {
FSM fsm = null;
if (schedule != null) {
FSMBuilder builder = new FSMBuilder();
fsm = builder.buildFSM(schedule.getContents(), sortedActions);
// set initial state
AstState initialState = schedule.getInitialState();
State state = (State) Frontend.instance
.getMapping(initialState);
fsm.setInitialState(state);
} else {
RegExpConverter converter = new RegExpConverter(scheduleRegExp);
fsm = converter.convert(sortedActions);
}
actor.getActionsOutsideFsm().addAll(
sortedActions.getUntaggedActions());
actor.setFsm(fsm);
}
// create IR actor
AstEntity entity = (AstEntity) astActor.eContainer();
actor.setName(net.sf.orcc.cal.util.Util.getQualifiedName(entity));
actor.setNative(Util.hasAnnotation("native", entity.getAnnotations()));
Util.transformAnnotations(actor, entity.getAnnotations());
actor.getActions().addAll(actions.getAllActions());
actor.getInitializes().addAll(initializes.getAllActions());
return actor;
}
/**
* Loads tokens from the data that was read and put in portVariable.
*
* @param portVariable
* a local array that contains data.
* @param tokens
* a list of token variables
* @param repeat
* an integer number of repeat (equals to one if there is no
* repeat)
*/
private void actionLoadTokens(StructTransformer transformer,
Procedure procedure, Var portVariable, List<Variable> tokens,
int repeat) {
if (repeat == 1) {
int i = 0;
for (Variable token : tokens) {
// declare a fresh new variable here because we can have one in
// the body and one in the scheduler
Var local = (Var) transformer.doSwitch(token);
procedure.getLocals().add(local);
List<Expression> indexes = new ArrayList<Expression>(1);
indexes.add(eINSTANCE.createExprInt(i));
int lineNumber = portVariable.getLineNumber();
Var irToken = Frontend.instance.getMapping(token);
InstLoad load = eINSTANCE.createInstLoad(lineNumber, irToken,
portVariable, indexes);
procedure.getLast().add(load);
i++;
}
} else if (tokens.size() == 1) {
Variable token = tokens.get(0);
Frontend.instance.putMapping(token, portVariable);
} else {
// creates loop variable and initializes it
Var loopVar = procedure.newTempLocalVariable(
eINSTANCE.createTypeInt(32), "num_repeats");
InstAssign assign = eINSTANCE.createInstAssign(loopVar,
eINSTANCE.createExprInt(0));
procedure.getLast().add(assign);
BlockBasic block = eINSTANCE.createBlockBasic();
int i = 0;
int numTokens = tokens.size();
Type type = ((TypeList) portVariable.getType()).getType();
for (Variable token : tokens) {
// declare a fresh new variable here because we can have one in
// the body and one in the scheduler
Var local = (Var) transformer.doSwitch(token);
procedure.getLocals().add(local);
int lineNumber = portVariable.getLineNumber();
List<Expression> indexes = new ArrayList<Expression>(1);
indexes.add(eINSTANCE.createExprBinary(eINSTANCE
.createExprBinary(eINSTANCE.createExprInt(numTokens),
OpBinary.TIMES,
eINSTANCE.createExprVar(loopVar),
eINSTANCE.createTypeInt(32)), OpBinary.PLUS,
eINSTANCE.createExprInt(i), eINSTANCE.createTypeInt(32)));
Var tmpVar = procedure.newTempLocalVariable(type, "token");
InstLoad load = eINSTANCE.createInstLoad(lineNumber, tmpVar,
portVariable, indexes);
block.add(load);
Var irToken = Frontend.instance.getMapping(token);
indexes = new ArrayList<Expression>(1);
indexes.add(eINSTANCE.createExprVar(loopVar));
InstStore store = eINSTANCE.createInstStore(lineNumber,
irToken, indexes, eINSTANCE.createExprVar(tmpVar));
block.add(store);
i++;
}
// add increment
assign = eINSTANCE.createInstAssign(loopVar, eINSTANCE
.createExprBinary(eINSTANCE.createExprVar(loopVar),
OpBinary.PLUS, eINSTANCE.createExprInt(1),
loopVar.getType()));
block.add(assign);
// create while block
Expression condition = eINSTANCE
.createExprBinary(eINSTANCE.createExprVar(loopVar),
OpBinary.LT, eINSTANCE.createExprInt(repeat),
eINSTANCE.createTypeBool());
List<Block> blocks = new ArrayList<Block>(1);
blocks.add(block);
BlockWhile blockWhile = eINSTANCE.createBlockWhile();
blockWhile.setJoinBlock(eINSTANCE.createBlockBasic());
blockWhile.setCondition(condition);
blockWhile.getBlocks().addAll(blocks);
procedure.getBlocks().add(blockWhile);
}
}
/**
* Assigns tokens to the data that will be written.
*
* @param portVariable
* a local array that will contain data.
* @param values
* a list of AST expressions
* @param repeat
* an integer number of repeat (equals to one if there is no
* repeat)
*/
private void actionStoreTokens(StructTransformer transformer,
Procedure procedure, Var portVariable, List<AstExpression> values,
int repeat) {
if (repeat == 1) {
int i = 0;
for (AstExpression value : values) {
List<Expression> indexes = new ArrayList<Expression>(1);
indexes.add(eINSTANCE.createExprInt(i));
new ExprTransformer(procedure, procedure.getBlocks(),
portVariable, indexes).doSwitch(value);
i++;
}
} else if (values.size() == 1 && needToBeCopied(values.get(0))) {
// assign the expression to a new variable
AstExpression value = values.get(0);
new ExprTransformer(procedure, procedure.getBlocks(), portVariable)
.doSwitch(value);
} else if (values.size() == 1) {
// use directly the port variable
Variable variable = ((ExpressionVariable) values.get(0)).getValue()
.getVariable();
Var old = Frontend.instance.getMapping(variable);
// replace the use/def of the old variable without moving the new
// one from its containing pattern
for (Def def : new ArrayList<Def>(old.getDefs())) {
def.setVariable(portVariable);
}
for (Use use : new ArrayList<Use>(old.getUses())) {
use.setVariable(portVariable);
}
Frontend.instance.putMapping(variable, portVariable);
EcoreUtil.remove(old);
} else {
// creates loop variable and initializes it
Var loopVar = procedure.newTempLocalVariable(
eINSTANCE.createTypeInt(32), "num_repeats");
InstAssign assign = eINSTANCE.createInstAssign(loopVar,
eINSTANCE.createExprInt(0));
procedure.getLast().add(assign);
BlockBasic block = eINSTANCE.createBlockBasic();
int i = 0;
int numTokens = values.size();
Type type = ((TypeList) portVariable.getType()).getType();
for (AstExpression value : values) {
int lineNumber = portVariable.getLineNumber();
List<Expression> indexes = new ArrayList<Expression>(1);
indexes.add(eINSTANCE.createExprVar(loopVar));
// each expression of an output pattern must be of type list
// so they are necessarily variables
Var tmpVar = procedure.newTempLocalVariable(type, "token");
Expression expression = new ExprTransformer(procedure,
procedure.getBlocks(), tmpVar).doSwitch(value);
Use use = ((ExprVar) expression).getUse();
InstLoad load = eINSTANCE.createInstLoad(tmpVar,
use.getVariable(), indexes);
block.add(load);
indexes = new ArrayList<Expression>(1);
indexes.add(eINSTANCE.createExprBinary(eINSTANCE
.createExprBinary(eINSTANCE.createExprInt(numTokens),
OpBinary.TIMES,
eINSTANCE.createExprVar(loopVar),
eINSTANCE.createTypeInt(32)), OpBinary.PLUS,
eINSTANCE.createExprInt(i), eINSTANCE.createTypeInt(32)));
InstStore store = eINSTANCE.createInstStore(lineNumber,
portVariable, indexes, eINSTANCE.createExprVar(tmpVar));
block.add(store);
i++;
}
// add increment
assign = eINSTANCE.createInstAssign(loopVar, eINSTANCE
.createExprBinary(eINSTANCE.createExprVar(loopVar),
OpBinary.PLUS, eINSTANCE.createExprInt(1),
loopVar.getType()));
block.add(assign);
// create while block
Expression condition = eINSTANCE
.createExprBinary(eINSTANCE.createExprVar(loopVar),
OpBinary.LT, eINSTANCE.createExprInt(repeat),
eINSTANCE.createTypeBool());
BlockWhile blockWhile = eINSTANCE.createBlockWhile();
blockWhile.setJoinBlock(eINSTANCE.createBlockBasic());
blockWhile.setCondition(condition);
blockWhile.getBlocks().add(block);
procedure.getBlocks().add(blockWhile);
}
}
/**
* Creates the test for schedulability of the given action.
*
* @param astAction
* an AST action
* @param inputPattern
* input pattern of action
* @param result
* target local variable
*/
private void createActionTest(StructTransformer transformer,
Procedure procedure, AstAction astAction, Pattern peekPattern,
Var result) {
Expression value;
if (astAction.getGuard() == null) {
value = eINSTANCE.createExprBool(true);
} else {
transformInputPatternPeek(transformer, procedure, astAction,
peekPattern);
value = transformGuards(transformer, procedure, astAction
.getGuard().getExpressions());
}
InstAssign assign = eINSTANCE.createInstAssign(result, value);
procedure.getLast().add(assign);
}
/**
* Creates a variable to hold the number of tokens on the given port.
*
* @param port
* a port
* @param numTokens
* number of tokens
* @return the local array created
*/
private Var createPortVariable(int lineNumber, Port port, int numTokens) {
// create the variable to hold the tokens
return eINSTANCE.createVar(lineNumber,
eINSTANCE.createTypeList(numTokens, port.getType()),
port.getName(), true, 0);
}
/**
* Check if an expression need be be copied in the output port variable or
* not.
*
* @param expr
* the given expression
* @return true if the expression need be be copied in the output port
* variable
*/
private boolean needToBeCopied(AstExpression expr) {
// Expressions that are not variables cannot be used directly
if (!(expr instanceof ExpressionVariable)) {
return true;
}
// Global variables have to be copied to the FIFO
Variable variable = ((ExpressionVariable) expr).getValue()
.getVariable();
if (Util.isGlobal(variable)) {
return true;
}
// Input port variables have to be copied as well
Var var = Frontend.instance.getMapping(variable);
if (EcoreHelper.getContainerOfType(var, Pattern.class) != null) {
return true;
}
// Variables used by a procedure have to be copied as well
for (Use use : var.getUses()) {
if (EcoreHelper.getContainerOfType(use, InstCall.class) != null) {
// Mark the variable as a local copy of port variable to allow
// later optimizations (at backend-level)
var.addAttribute(COPY_OF_TOKENS);
return true;
}
}
return false;
}
/**
* Transforms the given AST action and adds it to the given action list.
*
* @param actionList
* an action list
* @param astAction
* an AST action
*/
private void transformAction(AstAction astAction, ActionList actionList) {
int lineNumber = Util.getLocation(astAction);
// transform tag
AstTag astTag = astAction.getTag();
Tag tag;
String name;
if (astTag == null) {
tag = DfFactory.eINSTANCE.createTag();
name = "untagged_" + untaggedCount++;
} else {
tag = DfFactory.eINSTANCE.createTag();
tag.getIdentifiers().addAll(astAction.getTag().getIdentifiers());
name = OrccUtil.toString(tag.getIdentifiers(), "_");
}
Pattern inputPattern = DfFactory.eINSTANCE.createPattern();
Pattern outputPattern = DfFactory.eINSTANCE.createPattern();
Pattern peekPattern = DfFactory.eINSTANCE.createPattern();
// creates scheduler and body
Procedure scheduler = eINSTANCE
.createProcedure("isSchedulable_" + name, lineNumber,
eINSTANCE.createTypeBool());
Procedure body = eINSTANCE.createProcedure(name, lineNumber,
eINSTANCE.createTypeVoid());
// creates IR action
Action action = DfFactory.eINSTANCE.createAction(tag, inputPattern,
outputPattern, peekPattern, scheduler, body);
// transforms action body and scheduler
transformActionBody(astAction, body, inputPattern, outputPattern);
transformActionScheduler(astAction, scheduler, peekPattern);
Util.transformAnnotations(action, astAction.getAnnotations());
// add it to action list
actionList.add(action);
}
/**
* Transforms the body of the given AST action into the given body
* procedure.
*
* @param astAction
* an AST action
* @param body
* the procedure that will contain the body
*/
private void transformActionBody(AstAction astAction, Procedure body,
Pattern inputPattern, Pattern outputPattern) {
StructTransformer transformer = new StructTransformer(body);
for (InputPattern pattern : astAction.getInputs()) {
transformPattern(transformer, body, pattern, inputPattern);
}
transformer.transformLocalVariables(astAction.getVariables());
transformer.transformStatements(astAction.getStatements());
List<OutputPattern> astOutputPattern = astAction.getOutputs();
for (OutputPattern pattern : astOutputPattern) {
transformPattern(transformer, body, pattern, outputPattern);
}
transformer.addReturn(body, null);
}
/**
* Transforms the given list of AST actions to an ActionList of IR actions.
*
* @param actions
* a list of AST actions
* @return an ActionList of IR actions
*/
private ActionList transformActions(List<AstAction> actions) {
ActionList actionList = new ActionList();
for (AstAction astAction : actions) {
transformAction(astAction, actionList);
}
return actionList;
}
/**
* Transforms the scheduling information of the given AST action into the
* given scheduler procedure.
*
* @param astAction
* an AST action
* @param scheduler
* the procedure that will contain the scheduler
* @param inputPattern
* the input pattern filled by
* {@link #fillsInputPattern(AstAction, Pattern)}
*/
private void transformActionScheduler(AstAction astAction,
Procedure scheduler, Pattern peekPattern) {
StructTransformer transformer = new StructTransformer(scheduler);
Var result = scheduler.newTempLocalVariable(eINSTANCE.createTypeBool(),
"result");
if (peekPattern.isEmpty() && astAction.getGuard() == null) {
// the action is always fireable
InstAssign assign = eINSTANCE.createInstAssign(result,
eINSTANCE.createExprBool(true));
scheduler.getLast().add(assign);
} else {
createActionTest(transformer, scheduler, astAction, peekPattern,
result);
}
transformer.addReturn(scheduler, eINSTANCE.createExprVar(result));
}
/**
* Transforms the given guards and assign result the expression g1 && g2 &&
* .. && gn.
*
* @param guards
* list of guard expressions
*/
private Expression transformGuards(StructTransformer transformer,
Procedure procedure, List<AstExpression> guards) {
List<Expression> expressions = AstIrUtil.transformExpressions(
procedure, procedure.getBlocks(), guards);
Iterator<Expression> it = expressions.iterator();
Expression value = it.next();
while (it.hasNext()) {
value = eINSTANCE.createExprBinary(value, OpBinary.LOGIC_AND,
it.next(), eINSTANCE.createTypeBool());
}
return value;
}
/**
* Transforms the input patterns of the given AST action when necessary by
* generating Peek instructions. An input pattern needs to be transformed to
* Peeks when guards reference tokens from the pattern.
*
* @param astAction
* an AST action
*/
private void transformInputPatternPeek(StructTransformer transformer,
Procedure scheduler, final AstAction astAction, Pattern peekPattern) {
final Set<InputPattern> patterns = new HashSet<InputPattern>();
VoidSwitch peekVariables = new VoidSwitch() {
@Override
public Void caseVariableReference(VariableReference reference) {
EObject obj = reference.getVariable().eContainer();
if (obj instanceof InputPattern) {
patterns.add((InputPattern) obj);
}
return null;
}
};
// fills the patterns set by visiting guards
if (astAction.getGuard() != null) {
for (AstExpression guard : astAction.getGuard().getExpressions()) {
peekVariables.doSwitch(guard);
}
}
// add peeks for each pattern of the patterns set
for (InputPattern pattern : patterns) {
transformPattern(transformer, scheduler, pattern, peekPattern);
}
}
/**
* Transforms the given AST input/output pattern of the given action.
*
* @param transformer
* AST to IR transformer
* @param procedure
* procedure to which instructions should be added (body or
* scheduler)
* @param astPattern
* AST input or output pattern
* @param irPattern
* IR input or output pattern
*/
private void transformPattern(StructTransformer transformer,
Procedure procedure, EObject astPattern, Pattern irPattern) {
Port port;
int totalConsumption;
AstExpression astRepeat;
if (astPattern instanceof InputPattern) {
InputPattern pattern = ((InputPattern) astPattern);
astRepeat = pattern.getRepeat();
port = Frontend.instance.getMapping(pattern.getPort());
totalConsumption = pattern.getTokens().size();
} else {
OutputPattern pattern = ((OutputPattern) astPattern);
astRepeat = pattern.getRepeat();
port = Frontend.instance.getMapping(pattern.getPort());
totalConsumption = pattern.getValues().size();
}
// evaluates token consumption
int repeat = 1;
if (astRepeat != null) {
repeat = Evaluator.getIntValue(astRepeat);
totalConsumption *= repeat;
}
irPattern.setNumTokens(port, totalConsumption);
// create port variable
Var variable = createPortVariable(procedure.getLineNumber(), port,
totalConsumption);
irPattern.setVariable(port, variable);
// load/store tokens (depending on the type of pattern)
if (astPattern instanceof InputPattern) {
InputPattern pattern = (InputPattern) astPattern;
List<Variable> tokens = pattern.getTokens();
actionLoadTokens(transformer, procedure, variable, tokens, repeat);
} else {
OutputPattern pattern = (OutputPattern) astPattern;
List<AstExpression> values = pattern.getValues();
actionStoreTokens(transformer, procedure, variable, values, repeat);
}
}
}