ship: Choice == 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 data in: in.deMuxIfPositive data in: in.deMuxIfNonNegative data in: in.deMuxIfNonPositive data out: out1 data out: out2 == Constants ======================================================== == 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. \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.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("swap") && (!box_in1.dataReadyForShip() || !box_in2.dataReadyForShip())) return; if (port.startsWith("mux") && (!box_in1.dataReadyForShip() || !box_in2.dataReadyForShip())) return; if (port.startsWith("deMux") && (!box_in1.dataReadyForShip())) return; long val = selector.value; boolean condition = false; if (port.endsWith("IfZero")) condition = val==0; if (port.endsWith("IfNonZero")) condition = val!=0; if (port.endsWith("IfPositive")) condition = val>0; if (port.endsWith("IfNegative")) condition = val<0; if (port.endsWith("IfNonPositive")) condition = val<=0; if (port.endsWith("IfNonNegative")) condition = val>=0; if (port.startsWith("swap")) { 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; } } == FleetSim ============================================================== == FPGA ============================================================== 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_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_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_out2) begin `onwrite(out2_r, out2_a) have_out2 <= 0; end end 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 == Contributors ========================================================= Adam Megacz