public final BenkoBox benkoBox;
public final int count;
- public Kill(BenkoBox benkoBox, int count) { this.benkoBox=benkoBox; this.count=count; }
+ public final boolean killOnlyStandingInstructions;
+ public Kill(BenkoBox benkoBox, int count, boolean killOnlyStandingInstructions) {
+ this.benkoBox=benkoBox;
+ this.count=count;
+ this.killOnlyStandingInstructions = killOnlyStandingInstructions;
+ }
public String toString() { return (count>1 ? "["+count+"] " : "") + "kill"; }
}
Tree ttt = ttx.child(i);
if ("Wait".equals(ttt.head())) { tokenIn = true; }
else if ("Nop".equals(ttt.head())) { }
- else if ("Kill".equals(ttt.head())) {
- cb.add(new Instruction.Kill(benkobox, count));
+ else if ("KillStar".equals(ttt.head())) {
+ cb.add(new Instruction.Kill(benkobox, count, true));
+ continue OUTER;
+ } else if ("Kill".equals(ttt.head())) {
+ cb.add(new Instruction.Kill(benkobox, count, false));
continue OUTER;
}
else if ("Discard".equals(ttt.head())) { dataIn = true; latch = false; }
Instruction = Instruction::
(Brack:: "[" (int|(Star::"*"))? ("r")? "]" ws!)?
(Command +/ (ws! "," ws!) ws! ";"!)
-Command = Nop:: "nop"
- | Kill:: "kill"
- | Wait:: "wait"
- | Discard:: "discard"
- | Take:: "take"
- | SendTo:: "sendto" ws! Port
- | Deliver:: "deliver"
- | Ack:: "ack" ws! Port
+Command = Nop:: "nop"
+ | Kill:: "kill"
+ | KillStar:: "kill*"
+ | Wait:: "wait"
+ | Discard:: "discard"
+ | Take:: "take"
+ | SendTo:: "sendto" ws! Port
+ | Deliver:: "deliver"
+ | Ack:: "ack" ws! Port
Source = Port
| ShipSpecific
boolean dataOut = (instr & (1L << (11+1+7+3))) != 0;
boolean tokenOut = (instr & (1L << (11+1+7+4))) != 0;
boolean recycle = (instr & (1L)) != 0;
- if (latch & !dataIn) return new Instruction.Kill(name, count);
+ if (latch & !dataIn) return new Instruction.Kill(name, count, tokenIn);
return new Instruction.Executable(name, dest, count, tokenIn, dataIn,
latch, dataOut, tokenOut, recycle);
}
// Kill is encoded as Execute with the illegal combination (Latch & ~DataIn)
if (d instanceof Instruction.Kill) {
Instruction.Kill k = (Instruction.Kill)d;
- d = new Instruction.Executable(k.benkoBox, null, k.count, false, false, true, false, false, false);
+ d = new Instruction.Executable(k.benkoBox, null, k.count, k.killOnlyStandingInstructions,
+ false, true, false, false, false);
}
if (d instanceof Instruction.Executable) {
super(ship, name);
}
- public void kill(int count) {
+ public void kill(int count, boolean killOnlyStandingInstructions) {
if (currentlyExecuting != null) {
currentlyExecuting = null;
+ if (killOnlyStandingInstructions && currentlyExecuting.count != 0)
+ return;
count--;
}
for(; count > 0; count--) {
return;
}
} else {
+ Instruction.Executable inst = instructions.peek();
+ if (killOnlyStandingInstructions && inst.count != 0)
+ return;
instructions.remove();
}
}
} else if (i instanceof Instruction.Kill) {
InterpreterBenkoBox benkoBox = (InterpreterBenkoBox)(((Instruction.Kill)i).benkoBox);
- ((InstructionPort)benkoBox).kill(((Instruction.Kill)i).count);
+ ((InstructionPort)benkoBox).kill(((Instruction.Kill)i).count,
+ ((Instruction.Kill)i).killOnlyStandingInstructions);
} else {
throw new Error("unsupported: " + i.getClass().getName());
reg parse_instruction;
reg do_recycle;
reg fire_ok;
+ reg kill_only_standing;
reg [(`COUNT_BITS-1):0] kill_count;
reg [(`INSTRUCTION_WIDTH-1):0] instruction;
reg kill_r;
reg kill_a;
- reg [(`COUNT_WIDTH-1):0] kill_d;
+ reg [(`COUNT_WIDTH-1+1):0] kill_d;
reg [(`INSTRUCTION_WIDTH-1):0] kinstruction;
reg instr_rx;
end
end else begin
if (`instruction_is_kill(kinstruction)) begin
- kill_d = `instruction_count(kinstruction);
+ kill_d = { `instruction_bit_kill_only_standing(kinstruction), `instruction_count(kinstruction) };
`onwrite(kill_r, kill_a)
ifull = 0;
end
end else begin
// FIXME: actually don't want to kill partway through an instruction
`onread(kill_r, kill_a)
- kill_count = kill_count + kill_d;
+ kill_only_standing = kill_d[`COUNT_WIDTH];
+ kill_count = kill_count + kill_d[(`COUNT_WIDTH-1):0];
end
- if ((parse_instruction || have_instruction) && (kill_count > 0)) begin
+ if ((parse_instruction || have_instruction) && (kill_count > 0) &&
+ (!kill_only_standing || `instruction_count(instruction)==0))
+ begin
kill_count = kill_count - 1;
have_instruction = 0;
parse_instruction = 0;
`define instruction_bit_dest(instruction) instruction[(`DESTINATION_ADDRESS_BITS):1]
`define instruction_bit_recycle(instruction) instruction[0]
`define instruction_is_kill(i) (`instruction_bit_latch(i) && (!(`instruction_bit_datain(i))))
+`define instruction_bit_kill_only_standing(i) (`instruction_bit_tokenin(i))
`define instruction_count(instruction) instruction[(1+`DESTINATION_ADDRESS_BITS+`COUNT_BITS-1):(1+`DESTINATION_ADDRESS_BITS)]
`define defreg(signame,width,regname) reg width regname; wire width signame; assign signame = regname; initial regname = 0;
--- /dev/null
+#expect 1
+#expect 2
+
+#ship debug : Debug
+#ship fifo : Fifo
+#ship fifo2 : Fifo
+
+debug.in: [*] take, deliver;
+fifo.in: [*] take, deliver;
+
+1: sendto fifo.in;
+
+2: sendto fifo2.in;
+fifo2.in: [*] take, deliver;
+fifo2.out: wait, take, sendto fifo.in;
+
+fifo.out:
+ [*] nop;
+ ack fifo2.out;
+ take, sendto debug.in;
+ take, sendto debug.in;
+ kill*;
+ kill*;
+