/* * Copyright (c) 2009, 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.simulators.slow; import java.util.List; import net.sf.orcc.OrccRuntimeException; import net.sf.orcc.df.Action; import net.sf.orcc.df.Actor; import net.sf.orcc.df.Pattern; import net.sf.orcc.df.Port; import net.sf.orcc.ir.Arg; import net.sf.orcc.ir.ArgByVal; import net.sf.orcc.ir.Expression; import net.sf.orcc.ir.Procedure; import net.sf.orcc.ir.Type; import net.sf.orcc.ir.TypeList; import net.sf.orcc.ir.Var; import net.sf.orcc.ir.util.ActorInterpreter; import net.sf.orcc.ir.util.ValueUtil; import net.sf.orcc.simulators.util.RuntimeExpressionEvaluator; import net.sf.orcc.util.Attribute; import net.sf.orcc.util.util.EcoreHelper; import org.eclipse.emf.ecore.EObject; /** * This class defines an actor that can be interpreted by calling * {@link #initialize()} and {@link #schedule()}. It consists in an action * scheduler, an FSM state, and a node interpreter. * * @author Pierre-Laurent Lagalaye * */ public class ConnectedActorInterpreter extends ActorInterpreter { /** * Creates an actor interpreter dedicated to the simulator. * * @param actor * the actor to interpret */ public ConnectedActorInterpreter(Actor actor) { super(actor); exprInterpreter = new RuntimeExpressionEvaluator(); } @Override protected Object callNativeProcedure(Procedure procedure, List<Arg> arguments) { int numParams = arguments.size(); Class<?>[] parameterTypes = new Class<?>[numParams]; Object[] args = new Object[numParams]; int i = 0; for (Arg arg : arguments) { if (arg.isByVal()) { Expression expr = ((ArgByVal) arg).getValue(); args[i] = exprInterpreter.doSwitch(expr); parameterTypes[i] = args[i].getClass(); } i++; } // get packageName and containerName for calling the correct native // function EObject entity = procedure.eContainer(); String name = EcoreHelper.getFeature(entity, "name"); int index = name.lastIndexOf('.'); if (index != -1) { name = "net.sf.orcc.simulators.runtime." + name.substring(0, index) + ".impl" + name.substring(index); } try { Class<?> clasz = Class.forName(name); return clasz.getMethod(procedure.getName(), parameterTypes).invoke( null, args); } catch (Exception e) { throw new OrccRuntimeException( "Native procedure call Exception for " + procedure.getName(), e); } } @Override protected boolean checkOutputPattern(Pattern outputPattern) { boolean hasRooms = true; if (outputPattern != null) { for (Port port : outputPattern.getPorts()) { // check only connected output ports Attribute attr = port.getAttribute("fifo"); if (attr != null) { @SuppressWarnings("unchecked") List<SimulatorFifo> fifos = (List<SimulatorFifo>) attr .getObjectValue(); Integer nbOfTokens = outputPattern.getNumTokens(port); for (SimulatorFifo fifo : fifos) { hasRooms &= fifo.hasRoom(nbOfTokens); } } } } return hasRooms; } @Override @SuppressWarnings("unchecked") public void execute(Action action) { // allocate patterns Pattern inputPattern = action.getInputPattern(); Pattern outputPattern = action.getOutputPattern(); allocatePattern(inputPattern); allocatePattern(outputPattern); for (Port port : inputPattern.getPorts()) { int numTokens = inputPattern.getNumTokens(port); // a schedulable action can't have unconnected ports // (@see #isSchedulable()) SimulatorFifo fifo = (SimulatorFifo) port.getAttribute("fifo") .getObjectValue(); Var variable = inputPattern.getVariable(port); Type type = ((TypeList) variable.getType()).getInnermostType(); Object array = variable.getValue(); for (int i = 0; i < numTokens; i++) { Object value = fifo.read(); ValueUtil.set(type, array, value, i); } } // Interpret the whole action doSwitch(action.getBody()); for (Port port : outputPattern.getPorts()) { // write tokens only on connected output ports Attribute attr = port.getAttribute("fifo"); if (attr != null) { List<SimulatorFifo> fifos = (List<SimulatorFifo>) attr .getObjectValue(); int numTokens = outputPattern.getNumTokens(port); Var variable = outputPattern.getVariable(port); Type type = ((TypeList) variable.getType()).getInnermostType(); Object array = variable.getValue(); for (int i = 0; i < numTokens; i++) { Object value = ValueUtil.get(type, array, i); for (SimulatorFifo fifo : fifos) { fifo.write(value); } } } } } @Override protected boolean isSchedulable(Action action) { Pattern pattern = action.getInputPattern(); // check tokens for (Port port : pattern.getPorts()) { Attribute att = port.getAttribute("fifo"); if (att == null) { // this port is not connected, consequently this action cannot // be scheduled return false; } SimulatorFifo fifo = (SimulatorFifo) att.getObjectValue(); boolean hasTok = fifo.hasTokens(pattern.getNumTokens(port)); if (!hasTok) { return false; } } // allocates peeked variables pattern = action.getPeekPattern(); for (Port port : pattern.getPorts()) { int numTokens = pattern.getNumTokens(port); SimulatorFifo fifo = (SimulatorFifo) port.getAttribute(0) .getObjectValue(); Var peeked = pattern.getVariable(port); if (peeked != null) { peeked.setValue(ValueUtil.createArray((TypeList) peeked .getType())); } Type type = ((TypeList) peeked.getType()).getInnermostType(); Object array = peeked.getValue(); for (int i = 0; i < numTokens; i++) { Object value = fifo.peek(i); ValueUtil.set(type, array, value, i); } } Object result = doSwitch(action.getScheduler()); return ValueUtil.isTrue(result); } @Override public String toString() { return "interpreter for actor " + actor.getName(); } }