public int olc = 1;
public BitVector dataLatch = new BitVector(getShip().getFleet().getWordWidth());
public InterpreterPath pathLatch = null;
+ public InterpreterPath tapl = null;
public boolean hatchIsOpen = true;
private Instruction executing = null;
private Queue<Instruction> instructions = new LinkedList<Instruction>();
+ private Queue<Instruction> epilogue = new LinkedList<Instruction>();
+ private boolean dataReadyForShip = false;
+ private boolean readyForDataFromShip = true;
+ private long dataFromShip;
+ private boolean torpedoWaiting = false;
protected void reset() {
ilc = 1;
hatchIsOpen = true;
executing = null;
instructions.clear();
+ epilogue.clear();
+ dataReadyForShip = false;
+ readyForDataFromShip = true;
+ tapl = null;
+ torpedoWaiting = false;
}
// Destinations //////////////////////////////////////////////////////////////////////////////
super(ship, bbd);
}
- public void addInstruction(Instruction i) {
- throw new RuntimeException();
- }
-
public Path getPath(Destination d, BitVector signal) { return new InterpreterPath(this, (InterpreterDestination)d, signal); }
public Destination getInstructionDestination() { return instructionDestination; }
public Destination getDataDestination() { return dataDestination; }
// interface to subclass ///////////////////////////////////////////////////////////////////////
/** this will be invoked periodically; should return true to "consume" an instruction, false to leave it executing */
- protected void setDataLatch(long value) { throw new RuntimeException(); }
- protected long peekDataLatch() { throw new RuntimeException(); }
- public boolean dataReadyForShip() { throw new RuntimeException(); }
- public Packet removePacketForShip() { throw new RuntimeException(); }
- public Packet peekPacketForShip() { throw new RuntimeException(); }
- public long removeDataForShip() { throw new RuntimeException(); }
- public final boolean readyForDataFromShip() { throw new RuntimeException(); }
- public void addDataFromShip(long data) { throw new RuntimeException(); }
- public void addDataFromFabric(Packet packet) { throw new RuntimeException(); }
- protected final void addItemFromShip(long data) { throw new RuntimeException(); }
+
+ public boolean dataReadyForShip() { return dataReadyForShip; }
+ public final boolean readyForDataFromShip() { return readyForDataFromShip; }
+
+ public long removeDataForShip() {
+ if (!dataReadyForShip) throw new RuntimeException();
+ dataReadyForShip = false;
+ BitVector bv = dataLatch;
+ long val = 0;
+ for(int i=0; i<bv.length(); i++)
+ if (bv.get(i))
+ val |= (1L << i);
+ return val;
+ }
+ public void addDataFromShip(long data) {
+ if (!readyForDataFromShip()) throw new RuntimeException();
+ readyForDataFromShip = false;
+ dataFromShip = data;
+ }
protected final void service() {
- /*
+
+ if (instructionDestination.packets.size() > 0) {
+ Packet p = instructionDestination.packets.remove();
+ if (p.isToken) {
+ if (torpedoWaiting) throw new RuntimeException("two torpedoes collided!");
+ torpedoWaiting = true;
+ } else {
+ BitVector bv = p.value;
+ long val = 0;
+ for(int i=0; i<bv.length(); i++)
+ if (bv.get(i))
+ val |= (1L << i);
+ epilogue.add(getInterpreter().readInstruction(val, this));
+ }
+ }
+
+ if (hatchIsOpen && epilogue.size() > 0) {
+ Instruction inst = epilogue.remove();
+ if (inst instanceof Instruction.Tail)
+ hatchIsOpen = false;
+ else
+ instructions.add(inst);
+ }
+
+ if (dataReadyForShip) return;
+
if (executing==null && instructions.size() > 0) executing = instructions.remove();
if (executing==null) return;
+ if (executing.looping && hatchIsOpen && olc>0) return;
+
boolean enabled = true;
- if (executing instanceof Instruction.PredicatedInstruction) {
- Instruction.PredicatedInstruction ip = (Instruction.PredicatedInstruction)executing;
- switch(ip.predicate) {
- case IgnoreOLC: enabled = true; break;
- case Default: enabled = loopCounter!=0; break;
- case FlagA: enabled = flag_a; break;
- case FlagB: enabled = flag_b; break;
- //case FlagC: enabled = ; break;
- case NotFlagA: enabled = !flag_a; break;
- case NotFlagB: enabled = !flag_b; break;
- //case NotFlagC: enabled = loopCounter==0; break;
- }
+ switch(executing.predicate) {
+ case IgnoreOLC: enabled = true; break;
+ case Default: enabled = olc>0; break;
+ case FlagA: enabled = flag_a; break;
+ case FlagB: enabled = flag_b; break;
+ case FlagC: enabled = flag_c; break;
+ case NotFlagA: enabled = !flag_a; break;
+ case NotFlagB: enabled = !flag_b; break;
+ case NotFlagC: enabled = !flag_c; break;
+ default: throw new RuntimeException();
+ }
+ if (!enabled) {
+ if (executing.looping && olc>0)
+ instructions.add(executing);
+ executing = null;
+ return;
}
- int oldLoopCounter = loopCounter;
- if (enabled) {
- if (executing instanceof Instruction.Set.OLC.Decrement) loopCounter = Math.max(0, loopCounter-1);
- if (executing instanceof Instruction.Counter) {
- Instruction.Counter ic = (Instruction.Counter)executing;
- if (ic.source == Instruction.Counter.LOOP_COUNTER && ic.dest == Instruction.Counter.DATA_LATCH) {
- setDataLatch(oldLoopCounter); // FIXME: which is correct here?
- } else if (ic.dest == Instruction.Counter.LOOP_COUNTER && ic.source == Instruction.Counter.DATA_LATCH) {
- loopCounter = (int)peekDataLatch();
- } else if (ic.dest == Instruction.Counter.REPEAT_COUNTER && ic.source == Instruction.Counter.DATA_LATCH) {
- // FIXME: is there any way to load the "standing" value?
- repeatCounter = (int)peekDataLatch();
- } else if (ic.dest == Instruction.Counter.LOOP_COUNTER) {
- loopCounter = ic.source;
- } else if (ic.dest == Instruction.Counter.REPEAT_COUNTER && ic.source==Instruction.Counter.STANDING) {
- repeatCounter = -1;
- } else if (ic.dest == Instruction.Counter.REPEAT_COUNTER) {
- repeatCounter = ic.source;
- }
+ if (executing instanceof Instruction.Move) {
+ Instruction.Move move = (Instruction.Move)executing;
- } else if (executing instanceof Instruction.Set.Flags) {
- Instruction.Set.Flags sf = (Instruction.Set.Flags)executing;
- boolean old_c = oldLoopCounter == 0;
- boolean old_a = flag_a;
- boolean old_b = flag_b;
- flag_a =
- (((sf.flag_a & sf.FLAG_A) != 0) ? old_a : false) |
- (((sf.flag_a & sf.FLAG_NOT_A) != 0) ? !old_a : false) |
- (((sf.flag_a & sf.FLAG_B) != 0) ? old_b : false) |
- (((sf.flag_a & sf.FLAG_NOT_B) != 0) ? !old_b : false) |
- (((sf.flag_a & sf.FLAG_C) != 0) ? old_c : false) |
- (((sf.flag_a & sf.FLAG_NOT_C) != 0) ? !old_c : false);
- flag_b =
- (((sf.flag_b & sf.FLAG_A) != 0) ? old_a : false) |
- (((sf.flag_b & sf.FLAG_NOT_A) != 0) ? !old_a : false) |
- (((sf.flag_b & sf.FLAG_B) != 0) ? old_b : false) |
- (((sf.flag_b & sf.FLAG_NOT_B) != 0) ? !old_b : false) |
- (((sf.flag_b & sf.FLAG_C) != 0) ? old_c : false) |
- (((sf.flag_b & sf.FLAG_NOT_C) != 0) ? !old_c : false);
- } else if (executing instanceof Instruction.Set.OLC.Decrement) {
- } else {
- if (!service(executing)) return;
+ if (move.interruptible && torpedoWaiting) {
+ torpedoWaiting = false;
+ executing = null;
+ ilc = 1;
+ olc = 0;
+ if (tapl != null)
+ new Packet(tapl, new BitVector(getInterpreter().getWordWidth()), true).send();
+ hatchIsOpen = true;
+ return;
}
+
+ if (move.dataIn && !isInputDock() && readyForDataFromShip) return;
+ if (move.dataIn && isInputDock() && dataDestination.packets.size()==0) return;
+ if (move.tokenIn && dataDestination.packets.size()==0) return;
}
- if (executing==null) return;
- if ((executing instanceof Instruction.Move) && repeatCounter > 1) {
- repeatCounter--;
- } else if ((executing instanceof Instruction.Move) && repeatCounter == -1) {
- // repeat
- } else if ((executing instanceof Instruction.PredicatedInstruction && ((Instruction.PredicatedInstruction)executing).looping) && oldLoopCounter > 0) {
- addInstruction(executing);
+ if (executing.looping && olc>0)
+ instructions.add(executing);
+
+ if (executing instanceof Instruction.Shift) {
+ Instruction.Shift shift = (Instruction.Shift)executing;
+ for(int i=dataLatch.length()-1; i>=19; i--)
+ dataLatch.set(i, dataLatch.get(i-19));
+ for(int i=18; i>=0; i--)
+ dataLatch.set(i, shift.immediate.get(i));
executing = null;
- } else {
+ return;
+ }
+
+ if (executing instanceof Instruction.Set) {
+ Instruction.Set set = (Instruction.Set)executing;
+ switch(set.dest) {
+ case DataLatch:
+ dataLatch = new BitVector(getInterpreter().getWordWidth()).setAndSignExtend(set.immediate);
+ break;
+ case InnerLoopCounter:
+ switch(set.source) {
+ case Infinity:
+ ilc = -1;
+ break;
+ case DataLatch:
+ ilc = 0;
+ for(int i=0; i<FleetTwoFleet.SET_ILC_FROM_IMMEDIATE.valmaskwidth-1; i++)
+ if (dataLatch.get(i))
+ ilc |= (1 << i);
+ break;
+ case Immediate:
+ ilc = (int)set.immediate;
+ break;
+ default:
+ throw new RuntimeException("FIXME!");
+ }
+ break;
+ case OuterLoopCounter:
+ switch(set.source) {
+ case Decrement:
+ olc = Math.max(0,olc-1);
+ if (olc==0) hatchIsOpen = true;
+ break;
+ case DataLatch:
+ olc = 0;
+ for(int i=0; i<FleetTwoFleet.SET_OLC_FROM_IMMEDIATE.valmaskwidth-1; i++)
+ if (dataLatch.get(i))
+ olc |= (1 << i);
+ if (olc==0) hatchIsOpen = true;
+ break;
+ case Immediate:
+ olc = (int)set.immediate;
+ if (olc==0) hatchIsOpen = true;
+ break;
+ default:
+ throw new RuntimeException("FIXME!");
+ }
+ break;
+
+ case TAPL:
+ tapl = (InterpreterPath)set.path;
+ break;
+
+ case Flags: {
+ boolean new_flag_a = false;
+ boolean new_flag_b = false;
+ for(Predicate p : set.newFlagA)
+ switch(p) {
+ case FlagA: new_flag_a |= flag_a; break;
+ case FlagB: new_flag_a |= flag_b; break;
+ case FlagC: new_flag_a |= flag_c; break;
+ case NotFlagA: new_flag_a |= !flag_a; break;
+ case NotFlagB: new_flag_a |= !flag_b; break;
+ case NotFlagC: new_flag_a |= !flag_c; break;
+ }
+ for(Predicate p : set.newFlagB)
+ switch(p) {
+ case FlagA: new_flag_b |= flag_a; break;
+ case FlagB: new_flag_b |= flag_b; break;
+ case FlagC: new_flag_b |= flag_c; break;
+ case NotFlagA: new_flag_b |= !flag_a; break;
+ case NotFlagB: new_flag_b |= !flag_b; break;
+ case NotFlagC: new_flag_b |= !flag_c; break;
+ }
+ flag_a = new_flag_a;
+ flag_b = new_flag_b;
+ break;
+ }
+ default:
+ throw new RuntimeException("FIXME!");
+ }
executing = null;
+ return;
+ }
+
+ Instruction.Move move = (Instruction.Move)executing;
+
+ // if ILC==0, don't even bother
+ if (ilc==0) { ilc = 1; executing = null; return; }
+
+ if (ilc==-1) { }
+ else if (ilc==1) executing = null;
+ else ilc--;
+
+ Packet p = null;
+ if (move.tokenIn) {
+ p = dataDestination.packets.remove();
+ if (p.path.signal != null) flag_c = p.path.signal.get(0);
+ }
+ if (move.dataIn) {
+ BitVector bv = null;
+ if (isInputDock()) {
+ p = dataDestination.packets.remove();
+ bv = new BitVector(p.value);
+ if (p.path.signal != null) flag_c = p.path.signal.get(0);
+ } else {
+ bv = new BitVector(getInterpreter().getWordWidth()).set(dataFromShip);
+ readyForDataFromShip = true;
+ }
+ if (move.latchData) dataLatch = bv;
+ if (move.latchPath)
+ pathLatch = (InterpreterPath)getInterpreter().getPathByAddr(this, FleetTwoFleet.DISPATCH_PATH.getval(bv));
+ // FIXME: c-flag at output docks
}
- */
+
+ if (move.path != null) pathLatch = (InterpreterPath)move.path;
+
+ if (move.dataOut && isInputDock()) dataReadyForShip = true;
+ if (move.dataOut && !isInputDock())
+ new Packet(pathLatch, new BitVector(dataLatch), true).send();
+ if (move.tokenOut)
+ new Packet(pathLatch, new BitVector(getInterpreter().getWordWidth()), true).send();
+
+ return;
}
}