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 ============================================================== 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.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 == Test ============================================================================== #skip #ship debug : Debug #expect 0 == Contributors ========================================================= Adam Megacz