From: adam Date: Tue, 28 Aug 2007 00:24:34 +0000 (+0100) Subject: updates to many ships X-Git-Url: http://git.megacz.com/?a=commitdiff_plain;h=b55b374db178bc75ef08a9fd93987b37f8749e8e;p=fleet.git updates to many ships --- diff --git a/ships/Alu1.ship b/ships/Alu1.ship index 5eb32fd..41f988b 100644 --- a/ships/Alu1.ship +++ b/ships/Alu1.ship @@ -3,19 +3,30 @@ ship: Alu1 == Ports =========================================================== data in: in data in: inOp -data in: inOp.x -data in: inOp.y -data in: inOp.z + constant NEG: 0 + constant INC: 1 + constant DEC: 2 + constant ABS: 3 data out: out -== Constants ======================================================== -NEG: -INC: -DEC: -ABS: - == TeX ============================================================== + +{\tt Alu1} is a ``one-input'' arithmetic logic unit. It includes +logic for performing arithmetic operations on a single argument. +Currently this includes +negate ({\sc neg}), +increment ({\sc inc}), +decrement ({\sc dec}), and +absolute value ({\sc abs}). + +\subsection*{Semantics} + +When a value is present at each of {\tt in} and {\tt inOp}, these two +values are consumed. Based on the value consumed at {\tt inOp}, the +requested operation is performed on the value consumed from {\tt in}. +The result of this operation is then made available at {\tt out}. + == Fleeterpreter ==================================================== public void service() { if (box_in.dataReadyForShip() && box_inOp.dataReadyForShip() && box_out.readyForDataFromShip()) { diff --git a/ships/Alu2.ship b/ships/Alu2.ship index 1020acf..30ed60c 100644 --- a/ships/Alu2.ship +++ b/ships/Alu2.ship @@ -13,15 +13,31 @@ data out: out == TeX ============================================================== -This ship is a two-input arithmetic unit. It features several -opcodes, such as {\tt ADD} and {\tt SUB}. In my opinion, it is -niftycool. -FIXME: implement all the link bit stuff +{\tt Alu2} is a ``two-input'' arithmetic logic unit. It includes +logic for performing arithmetic operations on a pair of arguments. +Currently this includes +addition ({\sc add}), +subtraction ({\sc sub}), +maximum ({\sc max}), and +minimum ({\sc min}). -Use carry-in bit to create a selector? Perhaps a waste of an ALU. +\subsection*{Semantics} -Flags: zero, negative, overflow, ? +When a value is present at each of {\tt in1}, {\tt in2} and {\tt +inOp}, these three values are consumed. Based on the value consumed +at {\tt inOp}, the requested operation is performed on the values +consumed from {\tt in1} and {\tt in2}. The result of this operation +is then made available at {\tt out}. + +\subsection*{To Do} + +The {\it link bit} and other features of \cite{ies31} are not yet +implemented. + +The carry-in, carry-out, zero-test, negative-test, and overflow-test +flags typically present in a conventional processor ALU are also not +yet implemented. == Fleeterpreter ==================================================== public long resolveLiteral(String literal) { diff --git a/ships/Alu3.ship b/ships/Alu3.ship index b3f892a..025d7eb 100644 --- a/ships/Alu3.ship +++ b/ships/Alu3.ship @@ -9,13 +9,38 @@ data out: out1 shortcut to: in1 data out: out2 shortcut to: in2 -data out: out3 - shortcut to: in3 data out: outBits == Constants ======================================================== == TeX ============================================================== +{\tt Alu3} is a three-input adder which produces a pair of outputs in +carry-save form. It has no opcode input. + +This ship also contains a private ``bit fifo'' similar to the {\tt +BitFifo} ship, except that only the dequeueing (output) interface is +exposed to the programmer. Each addition operation performed causes +the lowest bit of the {\it save} output to be enqueued into the bit +fifo. This can be used to produce a very efficient multiplier; see +the test case for this ship for more details. + +\subsection*{Semantics} + +When a value is present at each of {\tt in1}, {\tt in2} and {\tt in3}, +these three values are consumed. The {\it carry} result of carry-save +addition is placed in {\tt out1}, and the {\it save} result of +carry-save addition is placed in {\tt out2}. + +\subsection*{To Do} + +Is the second output supposed to be shifted? + +Provide a way to clear/flush the internal bitfifo. + +Do we even need this? Can we do the same thing with {\tt Lut3} and +{\tt BitFifo} together? + + == Fleeterpreter ==================================================== boolean mode = false; BitFifo.BitStorage outBits = new BitFifo.BitStorage(74); @@ -30,19 +55,16 @@ public void service() { box_in3.dataReadyForShip() && outBits.hasSpace(1) && box_out1.readyForDataFromShip() && - box_out2.readyForDataFromShip() && - box_out3.readyForDataFromShip()) { + box_out2.readyForDataFromShip()) { long v1 = box_in1.removeDataForShip(); long v2 = box_in2.removeDataForShip(); long v3 = box_in3.removeDataForShip(); long o1, o2, o3; o1 = ((v1 & v2) | (v2 & v3) | (v1 & v3))/* << 1*/; o2 = (v1 ^ v2 ^ v3) >> 1; - o3 = 0; outBits.add((v1 ^ v2 ^ v3) & 0x1L, 1); box_out1.addDataFromShip(o1); box_out2.addDataFromShip(o2); - box_out3.addDataFromShip(o3); } } @@ -59,7 +81,6 @@ public void service() { reg [(`DATAWIDTH-1):0] keep_in3; initial keep_in3 = 0; reg have_out1; initial have_out1 = 0; reg have_out2; initial have_out2 = 0; - reg have_out3; initial have_out3 = 0; reg [73:0] bitstorage; initial bitstorage = 0; reg [7:0] bitstorage_count; initial bitstorage_count = 0; reg wrote; initial wrote = 0; @@ -76,8 +97,6 @@ public void service() { `onwrite(out1_r, out1_a) have_out1 <= 0; end end else if (have_out2) begin `onwrite(out2_r, out2_a) have_out2 <= 0; end - end else if (have_out3) begin - `onwrite(out3_r, out3_a) have_out3 <= 0; end end else if (!have_in1) begin `onread(in1_r, in1_a) have_in1 <= 1; keep_in1 <= in1_d; end end else if (!have_in2) begin @@ -89,12 +108,10 @@ public void service() { out2_d <= { 1'b0, (keep_in1[(`DATAWIDTH-1):1] ^ keep_in2[(`DATAWIDTH-1):1] ^ keep_in3[(`DATAWIDTH-1):1]) }; - out3_d <= 0; bitstorage[bitstorage_count] = (keep_in1[0] ^ keep_in2[0] ^ keep_in3[0]); bitstorage_count <= bitstorage_count+1; have_out1 <= 1; have_out2 <= 1; - have_out3 <= 1; have_in1 <= 0; have_in2 <= 0; have_in3 <= 0; @@ -162,7 +179,6 @@ alu3.in2: [1] notify lut3.out; [*] take, deliver, notify lut3.out; alu3.in3: literal 0; deliver; [*] take, deliver; alu3.out1: [74] take, sendto alu3.in1; alu3.out2: [74] take, sendto alu3.in3; -alu3.out3: [74] take; alu3.outBits: [*] take, sendto debug.in; diff --git a/ships/BitFifo.ship b/ships/BitFifo.ship index 359ce87..0349b0c 100644 --- a/ships/BitFifo.ship +++ b/ships/BitFifo.ship @@ -7,6 +7,7 @@ in: inOp constant msbFirst: ....................................0 constant drop: .............................uuuuuu.. constant take: .......................uuuuuu........ + out: out in: outOp constant lsbFirst: ....................................1 @@ -23,32 +24,54 @@ The BitFifo internally stores some number of bits in a fifo structure. Its capacity is guaranteed to be at least two full machine words or more. -Bits are enqueued by providing a word at the {\tt in} port and a count -at the {\tt inOp} port (ports are named this way to take advantage of -the switch fabric opcode mechanism). The {\tt inOp} count may be -positive, negative, or zero. - -If the {\tt inOp} count is positive, a word will be taken from the -{\tt in} port and its {\tt count} least significant bits will be -enqueued most-significant-bit first. - -If the {\tt inOp} count is zero, a word will be {\it discarded} from -the {\tt in} port and a duplicate copy of the bit at the {\it tail} of -the fifo is enqueued. If the fifo is empty, an undefined bit will be -enqueued. This mechanism is used for sign-extending words. - -If the {\tt inOp} count is negative, a word will be taken from the -{\tt in} port and its {\tt |count|} most significant bits will be -enqueued least-significant-bit first. - -Whenever a full word is present in the fifo, it will be made available -for dequeueing at the {\tt out} port. - -\begin{verbatim} -FIXMEs -- previously I noted that it would be nice to be able to dequeue bits - without consuming them (ie copy-out). What was this needed for? -\end{verbatim} +\subsection*{Enqueueing} + +Bits are enqueued by providing a word at the {\tt in} port and a code +word at the {\tt inOp} port (ports are named this way to take +advantage of the switch fabric opcode mechanism). As shown in the +constant diagram, this code word has fields {\tt lsbFirst}, {\tt +msbFirst}, {\tt drop}, and {\tt take}. + +When a word is consumed from {\tt in}, it is ``oriented'' in either +Most Significant Bit First ({\tt msbFirst}) or Least Significant Bit +First ({\tt lsbFirst}) depending on whether or not these flags are +set. Based on this orientation, the first {\tt drop} bits are +discarded. Then the next {\tt take} bits are enqueued into the fifo. +Any remaining bits are discarded. Attempting to drop or take beyond +the end of a word produces undefined results. + +\subsection*{Dequeueing} + +Bits are dequeued by providing a code word at the {\tt outOp} port +(despite its name, this is actually an {\it input port}). As shown in +the constant diagram, this code word has fields {\tt lsbFirst}, {\tt +msbFirst}, {\tt signExtend}, {\tt drop}, {\tt take}, and {\tt copy} +fields. + +Before additional processing, {\tt drop} bits are discarded from the +head of the fifo. Next, bits are dequeued into an empty word-width +register. If the {\tt msbFirst} flag is set, bits will be deposited +into this register starting with the most significant bit of the +register and working towards the least significant bit. If the {\tt +lsbFirst} flag is set, bits will be deposited into this register +starting with the {\it least} significant bit of the register and +working towards the {\it most} significant bit. The number of bits +dequeued is specified by the {\tt take} field. If the {\tt copy} +field is specified instead, the bits will be {\it copied} out of the +fifo rather than being removed. + +Finally, if the {\tt signExtend} bit is set, all bits in the register +which were not filled by bits dequeued from the fifo will be filled +with a copy of {\it the last bit dequeued from the fifo}. + +As a final addendum to the above, whenever a request arrives at {\tt +outOp} which requires more bits than are available in the fifo, the +operation will wait until enough bits are present. + +\subsection*{To Do} + +The text above regarding sign extending and dequeueing +msbFirst/lsbFirst is wrong. == Fleeterpreter ==================================================== diff --git a/ships/Choice.ship b/ships/Choice.ship index 6a14d09..eb56a40 100644 --- a/ships/Choice.ship +++ b/ships/Choice.ship @@ -3,21 +3,18 @@ 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 @@ -32,34 +29,37 @@ data out: out2 == TeX ============================================================== -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. +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 ==================================================== diff --git a/ships/Debug.ship b/ships/Debug.ship index 360997d..e1af16d 100644 --- a/ships/Debug.ship +++ b/ships/Debug.ship @@ -6,15 +6,19 @@ data in: in == Constants ======================================================== == TeX ============================================================== -\begin{verbatim} -TODO: have some way to log multiple separate streams; use sibling - ports to deliver an opcode +This ship is used for debugging. It has only one port, {\tt in}. +Programmers should send debug report values to this port. How such +values are reported back to the programmer doing the debugging is left +unspecified. -TODO: have a way to programmatically read back the output of the debug - ship? +\subsection*{To Do} -\end{verbatim} +Provide an {\tt inOp} port and use opcode ports \cite{am25} to +effectively allow multiple independent ``debug streams'' + +Provide a way to programmatically read back the output of the debug +ship. == Fleeterpreter ==================================================== public void service() { diff --git a/ships/Fifo.ship b/ships/Fifo.ship index 0b93764..875565e 100644 --- a/ships/Fifo.ship +++ b/ships/Fifo.ship @@ -2,10 +2,20 @@ ship: Fifo == Ports =========================================================== data in: in + data out: out == Constants ======================================================== + == TeX ============================================================== + +The {\tt Fifo} ship is a simple fifo. Values delivered to the {\tt +in} port are enqueued into the fifo, and values which arrive at the +end of the fifo are provided to the {\tt out} port. + +The internal capacity of the fifo is unspecified, but guaranteed to be +at least 16 words. + == Fleeterpreter ==================================================== private Queue fifo = new LinkedList(); public void service() { diff --git a/ships/Lut3.ship b/ships/Lut3.ship index 3274fe9..25056ee 100644 --- a/ships/Lut3.ship +++ b/ships/Lut3.ship @@ -387,8 +387,8 @@ alu.in: [*] take, deliver; alu.out: clog; - (*) wait, take, sendto lut.inLut; - (*) sendto alu.in; + wait, take, sendto lut.inLut, requeue forever; + sendto alu.in, requeue forever; unclog; // acks from debug ship trigger new truth tables diff --git a/ships/Stack.ship b/ships/Stack.ship index 7febad6..aca2883 100644 --- a/ships/Stack.ship +++ b/ships/Stack.ship @@ -9,16 +9,30 @@ data out: pop == TeX ============================================================== A stack ship with capacity for at least 32 elements. -Push operations are executed as soon as an inbound datum is {\tt -deliver}ed on the {\tt push} port. Completion of a push can be -confirmed by sending a {\tt notify} token from the {\tt push} port. +Push operations are executed as soon as an inbound datum is delivered +to the {\tt push} port. Completion of a push can be confirmed by +sending a {\tt notify} token from the {\tt push} port. Pop operations are executed no earlier than the time at which the {\tt pop} port attempts to {\tt take} data from the ship. When the stack becomes full, it will simply not process any new {\tt push} operations. When the stack becomes empty, it will simply not -process any new {\tt pop} operations. +process any new {\tt pop} operations. Phrased another way, if a {\tt +pop} is issued to an empty stack, that operation will wait for a {\tt +push} to occur; at some point after that, the {\tt pop} will proceed +to pop the pushed value. There is no ``underflow'' or ``overflow.'' + +\subsection*{To Do} + +There is some difficulty here when it comes to arbitration -- does the +execution of the instruction after the {\tt deliver} to the {\tt push} +port indicate that the value has been safely pushed? This is much +tricker than it seems. + +Perhaps there should be a single port, {\tt operation}, to which +either a {\sc PUSH} or {\sc POP} command is sent. This would simplify +the arbitration issues. == Fleeterpreter ==================================================== private ArrayList stack = new ArrayList();