}
}
- void dispatch(Instruction i) {
- Log.dispatch(i);
- long il = writeInstruction(i, debugShip.getDock("in"));
- Path path = debugShip.getDock("in").getPath(i.dock.getInstructionDestination(), null);
- new Packet((InterpreterPath)path, new BitVector(getWordWidth()).set(il), false).send();
- }
-
private Ship createShip(String shipType, String shipname) {
try {
if (ships.get(shipname)!=null) return ships.get(shipname);
public class InterpreterProcess extends FleetProcess implements Runnable {
private Instruction[] instructions;
- public void flush() { }
public synchronized void sendWord(Destination d, BitVector word) {
InterpreterPath path = (InterpreterPath)debugShip.getDock("in").getPath(d, new BitVector(1));
((InterpreterDestination)d).
sendInstruction(i);
}
public Fleet getFleet() { return Interpreter.this; }
- public void sendInstruction(Instruction i) { dispatch(i); }
+ public synchronized void sendInstruction(Instruction i) {
+ Log.dispatch(i);
+ long il = writeInstruction(i, debugShip.getDock("in"));
+ Path path = debugShip.getDock("in").getPath(i.dock.getInstructionDestination(), null);
+ new Packet((InterpreterPath)path, new BitVector(getWordWidth()).set(il), false).send();
+ }
public Dock getDebugInputDock() { return debugShip.getDock("in"); }
public BitVector recvWord() {
try {
public void run() {
try {
while(!isTerminated()) {
- for(InterpreterShip ship : ships.values())
- for(int j=0; j<10; j++)
- synchronized(this) {
- ship._service();
- }
+ flush();
}
for(InterpreterShip ship : ships.values())
ship.reset();
}
}
+ public void flush() {
+ // FIXME: should this run until we detect some sort of "quiescence"? OTOH that might never happen.
+ for(InterpreterShip ship : ships.values())
+ for(int j=0; j<10; j++)
+ if (!isTerminated())
+ synchronized(this) {
+ ship._service();
+ }
+ }
+
public synchronized void step(Dock d) {
((InterpreterDock)d).service();
}
Queue<Instruction> instructions = new LinkedList<Instruction>();
Queue<Packet> dataPackets = new LinkedList<Packet>();
+
+ // HACK
+ private Queue<Instruction> instructionsBackedUpIntoSwitchFabric = new LinkedList<Instruction>();
+
boolean dataReadyForShip = false;
boolean readyForDataFromShip = true;
long dataFromShip;
requeueStageHasTailInstruction = false;
instructions.clear();
dataPackets.clear();
+ instructionsBackedUpIntoSwitchFabric.clear();
dataReadyForShip = false;
readyForDataFromShip = true;
torpedoWaiting = false;
public String toString() { return getDock()+":i"; }
public void addDataFromFabric(Packet p) {
if (p.isToken()) {
+ if (instructionsBackedUpIntoSwitchFabric.size()!=0)
+ throw new RuntimeException("torpedo arrived while instructions were backed up into switch fabric");
if (torpedoWaiting) throw new RuntimeException("two torpedoes collided!");
torpedoWaiting = true;
return;
Instruction inst =
getInterpreter().decodeInstruction(p.getValue(),
InterpreterDock.this /* this is wrong, but harmless */);
-
- // FIXME: this is a bit too conservative. In theory,
- // it's okay to dispatch new instructions to the dock
- // as long as we know that it will reach the updating
- // state without any further input from the outside
- // world -- ie that the instructions which remain to
- // be executed before the requeue stage transitions to
- // the updating state are all "non-blocking" (no moves
- // with Ti=1 or Di=1)
- if (requeueStageInCirculatingState || requeueStageHasTailInstruction)
- throw new RuntimeException("An instruction arrived while the requeue stage was circulating -- "+
- "this means that instructions have backed up into "+
- "the switch fabric, which nearly always risks deadlock! "+
- "Fix your program!"+
- "\n dock: " + InterpreterDock.this +
- "\n instruction: " + inst
- );
- if (inst instanceof Instruction.Tail) {
- requeueStageHasTailInstruction = true;
- return;
- }
- instructions.add(inst);
+ addInstruction(inst);
}
};
public InterpreterDestination dataDestination = new InterpreterDestination(this) {
public int getInstructionFifoSize() { return Integer.MAX_VALUE; }
public Interpreter getInterpreter() { return ((InterpreterShip)getShip()).getInterpreter(); }
+ boolean trace = false;
+
+ private void addInstruction(Instruction inst) {
+ if (requeueStageInCirculatingState || requeueStageHasTailInstruction) {
+ // GROSS HACK
+ instructionsBackedUpIntoSwitchFabric.add(inst);
+ return;
+ }
+ if (inst instanceof Instruction.Tail) {
+ requeueStageHasTailInstruction = true;
+ return;
+ }
+ instructions.add(inst);
+ }
+
protected final void service() {
if (dataReadyForShip || flushing) return;
} else if (instructions.peek() instanceof Instruction.Abort) {
requeueStageInCirculatingState = false;
+ // HACK
+ while (instructionsBackedUpIntoSwitchFabric.size()!=0) {
+ Instruction i = instructionsBackedUpIntoSwitchFabric.remove();
+ addInstruction(i);
+ instructionsBackedUpIntoSwitchFabric.clear();
+ }
break;
} else if (instructions.peek() instanceof Instruction.Flush) {
// flushing logic (must come between dock servicing and subclass)
boolean someflushing = false;
boolean allflushing = true;
+ boolean someempty = false;
for(InterpreterDock d : docks.values()) {
if (!d.isInputDock()) continue;
if (d.flushing) someflushing = true;
else allflushing = false;
+ if (!d.flushing && !d.dataReadyForShip) someempty = true;
}
if (allflushing) {
for(InterpreterDock d : docks.values())
if (d.isInputDock())
d.flushing = false;
return;
- } else if (someflushing) {
+ } else if (someflushing && !someempty) {
for(InterpreterDock d : docks.values())
- if (d.isInputDock() && !d.flushing && d.dataReadyForShip)
+ if (d.isInputDock() && !d.flushing && d.dataReadyForShip) {
+ System.out.println("FLUSH AT " + this);
d.dataReadyForShip = false;
+ }
}
// now pass control to the subclass