package datapath.graph.operations;
import datapath.graph.OperationVisitor;
import datapath.graph.type.Type;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
*
* @author jh
*/
public abstract class Operation {
private Set<Operation> usage;
private Set<Predicate> predicates;
private static int lastOp = 0;
private int number;
private int executionOrdinal;
private int schedule;
private boolean executionOrdinalSet;
protected String debugMessage;
private int visit;
private static int nextVisit;
private Type type;
protected Operation() {
usage = new HashSet<Operation>();
predicates = new HashSet<Predicate>();
number = lastOp++;
debugMessage = "";
executionOrdinalSet = false;
schedule = -1;
}
public boolean isHardwareOperation() {
return true;
}
public static void nextVisit() {
nextVisit++;
}
public void setVisited() {
visit = nextVisit;
}
public boolean isVisited() {
return visit == nextVisit;
}
public abstract void replace(Operation oldOp, Operation newOp);
/**
* Adds a use of this operation by the given operation.
* @param op
*/
public void addUse(Operation op) {
usage.add(op);
}
public int getSchedule() {
return schedule;
}
public void setSchedule(int schedule) {
this.schedule = schedule;
}
/**
* Returns the type of the output data of this operation
* @return
*/
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
public int getExecutionOrdinal() {
//assert executionOrdinalSet : "execution ordinal not set"+this;
return executionOrdinal;
}
public void setExecutionOrdinal(int executionOrdinal) {
this.executionOrdinal = executionOrdinal;
executionOrdinalSet = true;
}
public void addPredicate(Predicate pred) {
predicates.add(pred);
pred.addUse(this);
}
public void removeUse(Operation op) {
//assert usage.contains(op);
usage.remove(op);
}
public String getDisplayName() {
return "OP" + number + ":" +
(executionOrdinalSet ? executionOrdinal : "-1") + ":" +
getOutputBitsize() + "bit" + ":" + schedule;
}
public int getNumber() {
return number;
}
public String getDisplayLabel() {
return this.getClass().getName();
}
@Override
public String toString() {
return "OP" + number + " " + getDisplayLabel();
}
public Set<Operation> getUse() {
return Collections.unmodifiableSet(usage);
}
@Deprecated
public Set<Operation> getUse(boolean skipControl) {
Set<Operation> use = new HashSet<Operation>();
for (Operation op : usage) {
if (!skipControl || op.isHardwareOperation()) {
use.add(op);
} else {
use.addAll(op.getUse(skipControl));
}
}
return use;
}
public Set<Predicate> getPredicates() {
return predicates;
}
public void setDebugMessage(String message) {
debugMessage = message;
}
public String getDebugMessage() {
return debugMessage;
}
public void visit(OperationVisitor visitor) {
visitor.visit(this);
}
public void postOrderUpwardVisit(OperationVisitor visitor) {
this.setVisited();
for (Operation op : dependsOnOperations(true)) {
if (!op.isVisited()) {
op.postOrderUpwardVisit(visitor);
}
}
this.visit(visitor);
}
public void postOrderDownwardVisit(OperationVisitor visitor) {
this.setVisited();
for (Operation op : getUse()) {
if (!op.isVisited()) {
op.postOrderUpwardVisit(visitor);
}
}
this.visit(visitor);
}
public boolean isSigned() {
if(type == null)
return false;
return type.isSigned();
}
/**
* Returns <code>true</code> if the operation has a fixed delay.
* @return
*/
public boolean isFixedDelay() {
return true;
}
public int getDelay() {
return 0;
}
/**
* Returns 1 if the output is buffered, 0 if the output is used combinatorical.
* @return
*/
public int getStageDelay() {
return 1;
}
public int getOutputBitsize() {
if(type == null)
return 0;
return type.getBitsize();
}
public abstract Set<Operation> dependsOnOperations(boolean includeBackedges);
}