package net.sf.orcc.backends.c.dal;
import net.sf.orcc.df.Action;
import net.sf.orcc.df.Actor;
import net.sf.orcc.df.Connection;
import net.sf.orcc.df.Pattern;
import net.sf.orcc.df.Port;
import net.sf.orcc.df.Network;
import net.sf.orcc.ir.Type;
import net.sf.orcc.util.OrccLogger;
/**
* Class for optimizing the code generation for
* individual actors
*
* @author Jani Boutellier
*
*/
public class ActorOptimizer {
public void optimizeOutput(Network network, boolean outputBuffering, int fifoSize) {
for (Actor actor : network.getAllActors()) {
boolean isSDF = false;
if (actor.getMoC() != null) {
isSDF = actor.getMoC().isSDF();
}
if (outputBuffering && !isSDF) {
} else {
for (Port port : actor.getOutputs()) {
port.setNumTokensProduced(-port.getNumTokensProduced());
}
}
}
}
public void optimizeInput(Network network, boolean inputBuffering, int fifoSize) {
for (Actor actor : network.getAllActors()) {
boolean isSDF = false;
if (actor.getMoC() != null) {
isSDF = actor.getMoC().isSDF();
}
if (inputBuffering && !isSDF) {
} else {
actor.addAttribute("variableInputPattern");
}
}
}
private int sizeOf(Type type) {
if (type.isFloat()) {
return 4;
} else if (type.isInt() || type.isUint()){
if (type.getSizeInBits() > 16) {
return 4;
} else if (type.getSizeInBits() > 8) {
return 2;
}
}
return 1;
}
private String printConnection(Connection conn) {
return new String(conn.getSource().getAdapter(Actor.class).getName() +
"->" + conn.getTarget().getAdapter(Actor.class).getName());
}
private void setTokenSizeAndRate(Connection conn, Port port, int rate) {
Integer sz = new Integer(sizeOf(port.getType()));
conn.setAttribute("TokenSize", sz);
conn.setAttribute("TokenRate", rate);
}
public void computeTokenSizes(Network network) {
for (Connection conn : network.getConnections()) {
Actor actor = conn.getTarget().getAdapter(Actor.class);
for (Port port : actor.getInputs()) {
if (conn.getTargetPort().equals(port)) {
setTokenSizeAndRate(conn, port, port.getNumTokensConsumed());
}
}
}
for (Connection conn : network.getConnections()) {
if (!conn.hasAttribute("TokenSize")) {
Actor actor = conn.getSource().getAdapter(Actor.class);
for (Port port : actor.getOutputs()) {
if (conn.getSourcePort().equals(port)) {
setTokenSizeAndRate(conn, port, -port.getNumTokensProduced());
}
}
}
if (conn.hasAttribute("TokenSize")) {
Actor actor = conn.getSource().getAdapter(Actor.class);
for (Port port : actor.getOutputs()) {
if (conn.getSourcePort().equals(port)) {
int thisTokenSize = sizeOf(port.getType());
int initialTokens = getInitialTokens(actor, port) /
(-port.getNumTokensProduced());
conn.setAttribute("InitialTokens", initialTokens);
Integer oldTokenSize = ((Integer)
conn.getValueAsObject("TokenSize"));
if (oldTokenSize == null) {
OrccLogger.warnln("Connection " +
printConnection(conn) +
" token size is null");
} else if (thisTokenSize != oldTokenSize.intValue()) {
OrccLogger.warnln("Connection " +
printConnection(conn) +
" has a r/w data size mismatch: " +
thisTokenSize + " vs " +
oldTokenSize.intValue());
}
}
}
}
}
}
private int getInitialTokens(Actor actor, Port port) {
if (actor.getInitializes() != null) {
for (Action i : actor.getInitializes()) {
Pattern pat = i.getOutputPattern();
if (pat.getNumTokensMap().containsKey(port)) {
int tokens = pat.getNumTokensMap().get(port).intValue();
OrccLogger.traceln(tokens + " initial samples detected in "
+ actor.getName() + "_" + port.getName());
return tokens;
}
}
}
return 0;
}
}