package net.sf.orcc.backends.c.dal; import java.util.List; import net.sf.orcc.df.Action; import net.sf.orcc.df.Actor; import net.sf.orcc.df.Port; import net.sf.orcc.graph.Edge; import net.sf.orcc.graph.Graph; import net.sf.orcc.graph.GraphFactory; import net.sf.orcc.graph.Vertex; import net.sf.orcc.util.OrccLogger; /** * Class tries to accurately resolve action priorities * * @author Jani Boutellier */ public class PriorityResolver { Graph localGraph; Graph actorGraph; Actor theActor; boolean debug = false; public PriorityResolver(Actor actor) { this.localGraph = GraphFactory.eINSTANCE.createGraph(); this.actorGraph = GraphFactory.eINSTANCE.createGraph(); this.theActor = actor; } private String makeActionSetString(String prefix, List<Action> actions) { String str = new String(prefix); for (Action a : actions) { str = str.concat(a.getName() + " "); } return str; } public boolean resolve(List<Action> actions, String tokens) { if (debug) { OrccLogger.traceln(makeActionSetString("--- Action Set:", actions)); } if (constructActorGraph(actorGraph, theActor.getActions(), theActor.getActionsOutsideFsm()) == false) { OrccLogger.warnln("Failed to construct actor graph"); return false; } if (constructLocalGraph(localGraph, actorGraph, actions) == false) { OrccLogger.warnln("Failed to construct local graph"); return false; } if (localGraph.getVertices() == null) { OrccLogger.traceln("Local graph contains no vertices"); return false; } Vertex sink = findSink(localGraph); if (sink == null) { OrccLogger.warnln("No sink action found in local graph"); return false; } Vertex source = findSource(localGraph); if (source == null) { OrccLogger.warnln("No source action found local graph"); return false; } if (checkLinearity(localGraph) == false) { return false; } if (checkInputDependency(localGraph, actions, source, sink, tokens) == false) { return false; } return true; } private boolean checkPatternOverLap(Action higherP, Action lowerP) { for (Port p : higherP.getInputPattern().getPorts()) { if (!lowerP.getInputPattern().contains(p)) { OrccLogger.traceln("Action " + lowerP.getName() + " does not have port " + p.getName() + " -- is possibly time-dependent"); return false; } else if (higherP.getInputPattern().getNumTokens(p) > lowerP.getInputPattern().getNumTokens(p)) { OrccLogger.traceln("Action " + lowerP.getName() + " consumes less tokens from port " + p.getName() + " -- is possibly time-dependent"); return false; } } return true; } private boolean checkInputDependency(Graph g, List<Action> actions, Vertex source, Vertex sink, String tokens) { boolean done = false; Vertex v = sink; while (!done) { Action highPri = findActionByName(actions, v.getLabel()); if (v.getPredecessors().size() < 1) { return true; } if (highPri.getInputPattern().getPorts().size() > 0) { Action nextPri = findActionByName(actions, v.getPredecessors().get(0).getLabel()); if (checkPatternOverLap(highPri, nextPri) == false) { return false; } } if (v == source) { done = true; } else { v = v.getPredecessors().get(0); } } return true; } private Action findActionByName(List<Action> actions, String name) { for (Action a : actions) { if (a.getName().equals(name)) { return a; } } OrccLogger.warnln("Could not find action with name " + name); return null; } private Vertex findVertexByName(List<Vertex> vertexes, String name) { for (Vertex v : vertexes) { if (v.getLabel().equals(name)) { return v; } } OrccLogger.warnln("Could not find vertex with name " + name); return null; } private boolean checkLinearity(Graph g) { int predSum = 0; int succSum = 0; int reference = g.getVertices().size() - 1; for (Vertex v : g.getVertices()) { predSum += v.getPredecessors().size(); succSum += v.getSuccessors().size(); } if (predSum != reference) { return false; } if (succSum != reference) { return false; } return true; } private Vertex findSink(Graph g) { for (Vertex v : g.getVertices()) { if (v == null) { break; } if (v.getSuccessors() != null) { if (v.getSuccessors().size() == 0) { return v; } } else { return null; } } return null; } private Vertex findSource(Graph g) { for (Vertex v : g.getVertices()) { if (v == null) { break; } if (v.getPredecessors() != null) { if (v.getPredecessors().size() == 0) { return v; } } else { return null; } } return null; } private boolean constructActorGraph(Graph graph, List<Action> actions, List<Action> outside) { if (debug) { OrccLogger.traceln("<<< building actor graph"); } for (Action a : actions) { Vertex v = GraphFactory.eINSTANCE.createVertex(); v.setLabel(a.getName()); if (debug) { OrccLogger.traceln(" added vertex " + a.getName()); } if (a.hasAttribute("IsPrecededBy")) { String str = a.getValueAsString("IsPrecededBy"); v.setAttribute("IsPrecededBy", str); } graph.add(v); } for (Vertex v : graph.getVertices()) { if (v.hasAttribute("IsPrecededBy")) { String str = v.getValueAsString("IsPrecededBy"); String[] parts = str.split("-"); for (String preceding : parts) { Edge e = GraphFactory.eINSTANCE.createEdge(); e.setSource(v); Vertex t = locateVertex(graph, preceding); if (t == null) { continue; } e.setTarget(t); graph.add(e); if (debug) { OrccLogger.traceln(" added edge " + v.getLabel() + " --> " + t.getLabel()); } } } } for (Action a : outside) { Vertex v = findVertexByName(graph.getVertices(), a.getName()); if (v.getPredecessors().size() == 0 && v.getSuccessors().size() == 0) { if (debug) { OrccLogger.traceln("Processing ut action " + a.getName()); } for (Action b : actions) { if (!a.equals(b)) { Vertex t = findVertexByName(graph.getVertices(), b.getName()); if (t.getSuccessors().size() == 0) { Edge e = GraphFactory.eINSTANCE.createEdge(); e.setSource(t); e.setTarget(v); graph.add(e); if (debug) { OrccLogger.traceln(" added ut edge " + t.getLabel() + " --> " + v.getLabel()); } } } } } } if (debug) { OrccLogger.traceln(">>>"); } return true; } private boolean constructLocalGraph(Graph localGraph, Graph actorGraph, List<Action> actions) { for (Action a : actions) { Vertex v = GraphFactory.eINSTANCE.createVertex(); v.setLabel(a.getName()); if (debug) { OrccLogger.traceln("added vertex " + v.getLabel()); } Action p = discoverClosestPredecessor(actorGraph, v.getLabel(), actions); if (p != null) { if (debug) { OrccLogger.traceln(" that is preceded by " + p.getName()); } v.setAttribute("IsPrecededBy", p.getName()); } localGraph.add(v); } for (Vertex v : localGraph.getVertices()) { if (v.hasAttribute("IsPrecededBy")) { Edge e = GraphFactory.eINSTANCE.createEdge(); e.setSource(v); String preceding = v.getValueAsString("IsPrecededBy"); Vertex t = locateVertex(localGraph, preceding); if (t != null) { if (debug) { OrccLogger.traceln("created edge " + v.getLabel() + " -> " + t.getLabel()); } e.setTarget(t); localGraph.add(e); } } } return true; } private Vertex locateVertex(Graph graph, String preceding) { for (Vertex v : graph.getVertices()) { if (v.getLabel().equals(preceding)) { return v; } } return null; } private Action discoverClosestPredecessor(Graph graph, String origin, List<Action> actions) { int[] distList = new int[256]; for (int i = 0; i < actions.size(); i++) { Action a = actions.get(i); GraphTraverser traverser = new GraphTraverser(graph); int dist = traverser.isPredecessor(origin, a.getName()); if (debug) { OrccLogger.traceln(" predecessor " + a.getName() + " is at distance " + dist); } distList[i] = dist; } int minInd = findMinimum(distList, actions.size()); if (minInd == -1) { return null; } return actions.get(minInd); } private int findMinimum(int[] list, int size) { int min = 20000000; int minInd = -1; for (int i = 0; i < size; i++) { if (list[i] < min && list[i] > 0) { min = list[i]; minInd = i; } } return minInd; } }