/*
* 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.df.transform;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import net.sf.orcc.df.Action;
import net.sf.orcc.df.Actor;
import net.sf.orcc.df.Connection;
import net.sf.orcc.df.DfFactory;
import net.sf.orcc.df.Entity;
import net.sf.orcc.df.Instance;
import net.sf.orcc.df.Network;
import net.sf.orcc.df.Pattern;
import net.sf.orcc.df.Port;
import net.sf.orcc.df.util.DfVisitor;
import net.sf.orcc.graph.Edge;
import net.sf.orcc.graph.Vertex;
import net.sf.orcc.ir.BlockBasic;
import net.sf.orcc.ir.IrFactory;
import net.sf.orcc.ir.Procedure;
import net.sf.orcc.ir.Type;
import net.sf.orcc.ir.Var;
import net.sf.orcc.ir.util.IrUtil;
import net.sf.orcc.util.SwitchUtil;
import net.sf.orcc.util.Void;
import org.eclipse.emf.ecore.util.EcoreUtil;
/**
* Adds broadcast actors when needed.
*
* @author Matthieu Wipliez
* @author Herve Yviquel
*
*/
public class BroadcastAdder extends DfVisitor<Void> {
private static DfFactory dfFactory = DfFactory.eINSTANCE;
private static IrFactory irFactory = IrFactory.eINSTANCE;
protected Network network;
@Override
public Void caseInstance(Instance instance) {
handle(instance);
return doSwitch(instance.getEntity());
}
@Override
public Void caseNetwork(Network network) {
this.network = network;
// make a copy of the existing vertex set because the set returned is
// modified when broadcasts are added
List<Vertex> vertexSet = new ArrayList<Vertex>(network.getVertices());
for (Vertex vertex : vertexSet) {
if (vertex instanceof Network) {
new BroadcastAdder().doSwitch(vertex);
} else {
doSwitch(vertex);
}
}
handle(network);
return SwitchUtil.DONE;
}
@Override
public Void casePort(Port port) {
List<Edge> connections = new ArrayList<Edge>(port.getOutgoing());
if (connections.size() > 1) {
createBroadcast(network.getSimpleName(), port, connections);
}
return null;
}
protected void createBroadcast(String id, Port port,
List<? extends Edge> outList) {
// Add broadcast vertex
Actor bcast = dfFactory.createActor();
bcast.setName(id + "_" + port.getName());
Instance instance = dfFactory.createInstance(id + "_" + port.getName()
+ "_bcast", bcast);
network.add(instance);
Type portVarType = irFactory.createTypeList(1, port.getType());
Pattern inputPattern = dfFactory.createPattern();
Pattern outputPattern = dfFactory.createPattern();
Port input = dfFactory.createPort(EcoreUtil.copy(port.getType()),
"input");
bcast.getInputs().add(input);
// Creates a connection between the vertex and the broadcast
Connection conn = (Connection) outList.get(0);
Connection incoming = dfFactory.createConnection(conn.getSource(),
conn.getSourcePort(), instance, input,
EcoreUtil.copyAll(conn.getAttributes()));
incoming.getAttributes()
.addAll(EcoreUtil.copyAll(conn.getAttributes()));
network.getConnections().add(incoming);
inputPattern.setNumTokens(input, 1);
inputPattern.setVariable(input,
irFactory.createVar(portVarType, "input", true, 0));
// Change the source of the other connections
int i = 0;
for (Edge edge : outList) {
Port output = dfFactory.createPort(EcoreUtil.copy(port.getType()),
"output_" + i);
bcast.getOutputs().add(output);
Connection connection = (Connection) edge;
connection.setSourcePort(output);
connection.setSource(instance);
outputPattern.setNumTokens(output, 1);
outputPattern.setVariable(output,
irFactory.createVar(portVarType, "output_" + i, true, 0));
i++;
}
// Create body of the broadcast
Procedure body = irFactory.createProcedure("copy", 0,
irFactory.createTypeVoid());
Var tmpVar = body.newTempLocalVariable(IrUtil.copy(port.getType()),
"tmp");
BlockBasic block = IrUtil.getLast(body.getBlocks());
block.add(irFactory.createInstLoad(tmpVar,
inputPattern.getVariable(input), 0));
for (Port output : bcast.getOutputs()) {
block.add(irFactory.createInstStore(
outputPattern.getVariable(output), 0, tmpVar));
}
// Create the scheduler
Procedure scheduler = irFactory.createProcedure("isSchedulable_copy",
0, irFactory.createTypeBool());
BlockBasic block2 = IrUtil.getLast(scheduler.getBlocks());
block2.add(irFactory.createInstReturn(irFactory.createExprBool(true)));
Action copy = dfFactory.createAction("copy", inputPattern,
outputPattern, dfFactory.createPattern(), scheduler, body);
bcast.getActions().add(copy);
bcast.getActionsOutsideFsm().add(copy);
}
protected void handle(Vertex vertex) {
Entity entity = vertex.getAdapter(Entity.class);
Map<Port, List<Connection>> outMap = entity.getOutgoingPortMap();
for (Port srcPort : outMap.keySet()) {
List<Connection> outList = outMap.get(srcPort);
if (outList.size() > 1) {
createBroadcast(entity.getSimpleName(), srcPort, outList);
}
}
}
}