== Ports ===========================================================
data in: in1
data in: in2
-
data in: in.swapIfZero
data in: in.swapIfNonZero
data in: in.swapIfNegative
data in: in.swapIfPositive
data in: in.swapIfNonNegative
data in: in.swapIfNonPositive
-
data in: in.muxIfZero
data in: in.muxIfNonZero
data in: in.muxIfNegative
data in: in.muxIfPositive
data in: in.muxIfNonNegative
data in: in.muxIfNonPositive
-
data in: in.deMuxIfZero
data in: in.deMuxIfNonZero
data in: in.deMuxIfNegative
== TeX ==============================================================
-With judicious programming of its BenkoBoxes, this ship can be used to
-implement nearly all forms of selection and branching.
-
-When data is available at the in port, it is examined. Which
-destination the datum has arrived on determines the *condition* the
-datum should be tested for and the *action* which should be taken if
-the condition holds true.
-
-The latter portion of the name of the destination (IfZero,
-If(Non)Positive, If(Non)Negative) determines the condition which the
-datum on the in port is tested for. The former portion (mux, demux,
-swap) determines the *action* to be taken if the condition tests true.
-
- action condition effect
- ------ --------- -------------------------------
- swap false in1->out1 in2->out2
- swap true in2->out1 in1->out2
- mux false in1->out1
- mux true in2->out1
- demux false in1->out1
- demux true in1->out2
-
-In each case, the ship will wait for a datum to be available on all
-input ports (and only those ports) mentioned in the appropriate row of
-the "effect" column above, and will output them on the corresponding
-output ports.
+This ship needs to be updated to use opcode ports \cite{am25}. For a
+general idea of what this ship is supposed to do, see \cite{am17}.
+
+%With judicious programming of its pumps, this ship can be used to
+%implement nearly all forms of selection and branching.
+%
+%When data is available at the in port, it is examined. Which
+%destination the datum has arrived on determines the *condition* the
+%datum should be tested for and the *action* which should be taken if
+%the condition holds true.
+%
+%The latter portion of the name of the destination (IfZero,
+%If(Non)Positive, If(Non)Negative) determines the condition which the
+%datum on the in port is tested for. The former portion (mux, demux,
+%swap) determines the *action* to be taken if the condition tests true.
+%
+%\begin{verbatim}
+% action condition effect
+% ------ --------- -------------------------------
+% swap false in1->out1 in2->out2
+% swap true in2->out1 in1->out2
+% mux false in1->out1
+% mux true in2->out1
+% demux false in1->out1
+% demux true in1->out2
+%\end{verbatim}
+%
+%In each case, the ship will wait for a datum to be available on all
+%input ports (and only those ports) mentioned in the appropriate row of
+%the "effect" column above, and will output them on the corresponding
+%output ports.
== Fleeterpreter ====================================================
private Packet selector;
public void service() {
- if (!box_out1.readyForItemFromShip() || !box_out2.readyForItemFromShip()) return;
+ if (!box_out1.readyForDataFromShip() || !box_out2.readyForDataFromShip()) return;
if (selector == null && !box_in.dataReadyForShip()) return;
if (selector == null) selector = box_in.removePacketForShip();
String port = selector.destination.getDestinationName();
if (port.startsWith("mux") && (!box_in1.dataReadyForShip() || !box_in2.dataReadyForShip())) return;
if (port.startsWith("deMux") && (!box_in1.dataReadyForShip())) return;
- long val = box_in.removeDataForShip();
+ long val = selector.value;
boolean condition = false;
if (port.endsWith("IfZero")) condition = val==0;
if (port.endsWith("IfNonZero")) condition = val!=0;
if (condition) {
box_out1.addDataFromShip(box_in2.removeDataForShip());
box_out2.addDataFromShip(box_in1.removeDataForShip());
+ selector = null;
} else {
box_out1.addDataFromShip(box_in1.removeDataForShip());
box_out2.addDataFromShip(box_in2.removeDataForShip());
+ selector = null;
}
} else if (port.startsWith("mux")) {
box_out1.addDataFromShip(condition ? box_in2.removeDataForShip() : box_in1.removeDataForShip());
+ selector = null;
} else if (port.startsWith("deMux")) {
(condition ? box_out2 : box_out1).addDataFromShip(box_in1.removeDataForShip());
+ selector = null;
}
}
== FPGA ==============================================================
- // FIXME
- reg have_a;
- reg [(`DATAWIDTH-1):0] reg_a;
- reg have_b;
- reg [(`DATAWIDTH-1):0] reg_b;
- reg have_op;
- reg [(`DATAWIDTH-1):0] reg_op;
+ reg have_in1;
+ reg [(`DATAWIDTH-1):0] reg_in1;
+ reg have_in2;
+ reg [(`DATAWIDTH-1):0] reg_in2;
+ reg have_in;
+ reg [(`PACKET_WIDTH-1):0] reg_in;
+ reg have_out1;
+ reg have_out2;
+ reg fire;
+
+ reg zero;
+ reg pos;
+ reg neg;
always @(posedge clk) begin
- if (!have_a) begin
- `onread(in1_r, in1_a) have_a = 1; reg_a = in1_d; end
+
+ if (!have_in1) begin
+ `onread(in1_r, in1_a) have_in1 <= 1; reg_in1 <= in1_d; end
+ end
+ if (!have_in2) begin
+ `onread(in2_r, in2_a) have_in2 <= 1; reg_in2 <= in2_d; end
end
- if (!have_b) begin
- `onread(in2_r, in2_a) have_b = 1; reg_b = in2_d; end
+ if (!have_in) begin
+ `onread(in_r, in_a) have_in <= 1; reg_in <= in_d; end
+ end
+
+ if (have_out1) begin
+ `onwrite(out1_r, out1_a) have_out1 <= 0; end
end
- if (!have_op) begin
- `onread(inOp_r, inOp_a) have_op = 1; reg_op = inOp_d; end
+
+ if (have_out2) begin
+ `onwrite(out2_r, out2_a) have_out2 <= 0; end
end
-
- if (have_a && have_b && have_op) begin
- case (reg_op)
- 0: out_d = reg_a + reg_b;
- 1: out_d = reg_a - reg_b;
- default: out_d = 0;
- endcase
- `onwrite(out_r, out_a)
- have_a = 0;
- have_b = 0;
- have_op = 0;
+
+ if (have_in && !have_out1 && !have_out2) begin
+ zero = reg_in[`DATAWIDTH-1:0] == 0;
+ neg = reg_in[`DATAWIDTH-1];
+ pos = !zero && !neg;
+ case (reg_in[`PACKET_WIDTH-1:`DATAWIDTH])
+ 00: fire = zero;
+ 06: fire = zero;
+ 12: fire = zero;
+ 01: fire = !zero;
+ 07: fire = !zero;
+ 13: fire = !zero;
+ 02: fire = neg;
+ 08: fire = neg;
+ 14: fire = neg;
+ 03: fire = pos;
+ 09: fire = pos;
+ 15: fire = pos;
+ 04: fire = !neg;
+ 16: fire = !neg;
+ 10: fire = !neg;
+ 05: fire = !pos;
+ 11: fire = !pos;
+ 17: fire = !pos;
+ endcase
+
+ if (reg_in[`PACKET_WIDTH-1:`DATAWIDTH] <= 5) begin
+ if (have_in1 && have_in2 && !have_out1 && !have_out2) begin
+ have_out1 <= 1;
+ have_out2 <= 1;
+ have_in1 <= 0;
+ have_in2 <= 0;
+ have_in <= 0;
+ out1_d <= fire ? reg_in2 : reg_in1;
+ out2_d <= fire ? reg_in1 : reg_in2;
+ end
+ end else if (reg_in[`PACKET_WIDTH-1:`DATAWIDTH] <= 11) begin
+ if (fire && have_in2) begin
+ have_out1 <= 1;
+ have_in2 <= 0;
+ out1_d <= in2_d;
+ have_in <= 0;
+ end else if (!fire && have_in1) begin
+ have_out1 <= 1;
+ have_in1 <= 0;
+ out1_d <= in1_d;
+ have_in <= 0;
+ end
+ end else begin
+ if (have_in1) begin
+ if (fire) begin
+ have_out2 <= 1;
+ out2_d <= in1_d;
+ have_in1 <= 0;
+ have_in <= 0;
+ end else begin
+ have_out1 <= 1;
+ out1_d <= in1_d;
+ have_in1 <= 0;
+ have_in <= 0;
+ end
+ end
end
- end
+
+ end
+
end
+== Test ==============================================================================
+#skip
+#ship debug : Debug
+#expect 0
== Contributors =========================================================
Adam Megacz <megacz@cs.berkeley.edu>