Newer
Older
AlgebraicDataflowArchitectureModel / AlgebraicDataflowArchitectureModel / src / algorithms / DataTransferModelAnalyzer.java
package algorithms;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;

import models.*;
import models.algebra.*;
import models.dataConstraintModel.*;
import models.dataFlowModel.*;

/**
 * Algorithms to analyze data transfer model.
 * 
 * @author Nitta
 *
 */
public class DataTransferModelAnalyzer {
	/**
	 * Create data flow graph annotated with node attributes that indicate whether each resource state needs to be stored.
	 * @param model a data transfer model
	 * @return annotated data flow graph
	 */
	static public DataFlowGraph createDataFlowGraphWithStateStoringAttribute(DataTransferModel model) {
		DataFlowGraph graph = model.getDataFlowGraph();
		Collection<Channel> channels = new HashSet<>(model.getIOChannels());
		channels.addAll(model.getChannels());
		for (Channel channel: channels) {
			for (ChannelMember member: ((DataTransferChannel) channel).getOutputChannelMembers()) {
				boolean toBeStored = !member.getStateTransition().isRightUnary();		// The state does not need to be stored if the state transition function is right unary.
				for (Node node: graph.getNodes()) {
					if (((ResourceNode) node).getResource().equals(member.getResource())) {
						setStoreAttribute((ResourceNode) node, toBeStored);
					}
				}
			}
		}
		for (Node node: graph.getNodes()) {
			HashSet<Channel> inChannels = new HashSet<>();
			for(Edge inEdge: ((ResourceNode) node).getInEdges()) {
				inChannels.add(((DataFlowEdge) inEdge).getChannel());
			}
			if ((inChannels.size() > 1)) {
				// If the resource has multiple input channels, then the state of the resource needs to be stored.
				setStoreAttribute((ResourceNode) node, true);
			} else if (((ResourceNode) node).getAttribute() == null) {
				setStoreAttribute((ResourceNode) node, false);
			}
		}
		return graph;
	}

	static private void setStoreAttribute(ResourceNode node, boolean toBeStored) {
		NodeAttribute attr = node.getAttribute();
		StoreAttribute store;
		if (attr != null && attr instanceof NodeAttribute) {
			store = (StoreAttribute) attr;
			store.setNeeded(store.isNeeded() || toBeStored);
		} else {
			store = new StoreAttribute();
			store.setNeeded(toBeStored);
			node.setAttribute(store);
		}
	}

	/**
	 * Annotate data flow graph with edge attributes that indicate selectable data transfer methods.
	 * @param graph a data flow graph
	 * @return annotated data flow graph
	 */
	static public DataFlowGraph annotateWithSelectableDataTransferAttiribute(DataFlowGraph graph) {
		List<Node> nodes = new ArrayList<>(graph.getNodes());
		// set push only attributes
		for (Node n: graph.getNodes()) {
			if (nodes.contains(n) && ((StoreAttribute) ((ResourceNode) n).getAttribute()).isNeeded()) {
				nodes.remove(n);
				trackEdges(n, nodes);
			}
		}
		// set push/pull attributes to the remaining edges
		for (Edge e : graph.getEdges()) {
			if (((DataFlowEdge) e).getAttribute() == null) {
				PushPullAttribute ppat = new PushPullAttribute();
				ppat.addOption(PushPullValue.PUSHorPULL);
				ppat.addOption(PushPullValue.PUSH);
				ppat.addOption(PushPullValue.PULL);
				((DataFlowEdge) e).setAttribute(ppat);
			}
		}
		return graph;
	}

	static private void trackEdges(Node n, List<Node> nodes) {
		// recursively set push only attributes to input side edges
		for (Edge e : ((ResourceNode) n).getInEdges()) {
			PushPullAttribute ppat = new PushPullAttribute();
			ppat.addOption(PushPullValue.PUSH);
			((DataFlowEdge) e).setAttribute(ppat);
			Node n2 = e.getSource();
			if (nodes.contains(n2)) {
				nodes.remove(n2);
				trackEdges(n2, nodes);
			}
		}
	}
}