CORDIC Coprocessor

The Propeller 2 contains a 54-stage pipelined CORDIC solver that can compute various math functions.

When a cog issues a CORDIC instruction, it must wait for its hub slot, which is 0..7 clocks away, in order to hand off the command to the CORDIC coprocessor. 55 clocks later, results will be available via the GETQX and GETQY instructions, which will wait for the results, in case they haven't arrived yet.

Because each cog's hub slot comes around every 8 clocks and the pipeline is 54 clocks long, it is possible to overlap CORDIC commands, where several commands are initially given to the coprocessor, and then results are read and another command is given, indefinitely, until, at the end, the trailing results are read. One must not have interrupts enabled during such a juggle, or enough clocks could be stolen by the interrupt service routine that one or more of the results could be overwritten before you can read them.

TODO: Reword above

If results are attempted to be read when none are available and no commands are in progress, GETQX/GETQY will only take 2 cycles and the QMT (CORDIC empty) event flag will be set.

Binary Angles

TODO explain binrads For now, see Wikipedia.

Result retrieval

GETQX D {WC/WZ/WCZ} - Get CORDIC result X

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZ0 DDDDDDDDD 000011000 D X[31] Result == 0 2..58 2..58 No

Retrieves the X result from the CORDIC coprocessor into Destination. TODO: What gets written if QMT flag gets set?

If the WC or WCZ effect is specified, the C flag is set to the MSB of the X result.

If the WZ or WCZ effect is specified, the Z flag is set (1) if the X result equals zero, or is cleared (0) if it is non-zero.

GETQY D {WC/WZ/WCZ} - Get CORDIC result Y

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 CZ0 DDDDDDDDD 000011001 D Y[31] Result == 0 2..58 2..58 No

Retrieves the Y result from the CORDIC coprocessor into Destination. TODO: What gets written if QMT flag gets set?

If the WC or WCZ effect is specified, the C flag is set to the MSB of the Y result.

If the WZ or WCZ effect is specified, the Z flag is set (1) if the Y result equals zero, or is cleared (0) if it is non-zero.

Commands

{ SETQ {#}Q }
QROTATE {#}D,{#}S - Rotate 2D vector

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101010 0LI DDDDDDDDD SSSSSSSSS none --- --- 2..9 2..9 No

QROTATE instructs the CORDIC coprocessor to rotate a signed 2D vector by the binary angle in Source. The X component of the vector is given in Destination and if QROTATE is immediately preceded by SETQ, the Q value provides the Y component (otherwise, Y=0).

When it is done, GETQX/GETQY will return the X'/Y' of the rotated vector, respectively.

Mathematically, it performs this operation:

\[\begin{align*} \mathit{QX} \approx D \cos(S) - Q \sin(S)\\ \mathit{QY} \approx D \sin(S) + Q \cos(S) \end{align*}\]

Thus, if Q=0 (as happens when SETQ is not used), QROTATE can be used to compute sine/cosine pairs at a scale given by D. i.e.

    '' Compute sine/cosine for theta, 32 bit precision.
    QROTATE ##$7FFF_FFFF, theta
    ' Can do other stuff while waiting
    GETQX   cosine ' cosine with 32 bit precision
    GETQY   sine ' cosine with 32 bit precision

This is also the same operation as converting a polar vector (length/angle) into a carthesian(X/Y) one:

    '' Convert polar to carthesian
    QROTATE length,angle
    ' Can do other stuff while waiting
    GETQX x
    GETQY y

QVECTOR {#}D,{#}S - Angle and length of 2D vector

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101010 1LI DDDDDDDDD SSSSSSSSS none --- --- 2..9 2..9 No

QROTATE instructs the CORDIC coprocessor to convert a carthesian vector (X/Y) in Destination (X) and Source (Y) into a polar vector (length/angle). When it is done, GETQX will return the angle (as a binary angle) and GETQY will return the length of the vector.

Mathematically:

\[\mathit{QX} \approx \operatorname{atan2}(S,D)\\ \mathit{QY} \approx \sqrt{D^2+S^2}\]

QMUL {#}D,{#}S - Unsigned 32-bit multiply

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101000 0LI DDDDDDDDD SSSSSSSSS none --- --- 2..9 2..9 No

QMUL instructs the CORDIC coprocessor to perform unsigned multiplication of Destination and Source. When it is done, GETQX will return the lower 32 bits of the result and GETQY will return the upper 32 bits.

Note that the lower half of a multiply result is the same regardless of wether the operation is signed or unsigned. Thus QMUL can be used for signed multiplication as-is, as long as the upper half of the result from GETQY isn't needed.

{ SETQ {#}Q }
QDIV {#}D,{#}S - Unsigned divide

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101000 1LI DDDDDDDDD SSSSSSSSS none --- --- 2..9 2..9 No

QDIV instructs the CORDIC coprocessor to perform unsigned division of Destination by Source. If QDIV is immediately preceded by SETQ, the Q value provides the upper 32 bits of a 64-bit dividend.

When it is done, GETQX will return the quotient and GETQY will return the remainder.

{ SETQ {#}Q }
QFRAC {#}D,{#}S - Unsigned divide (fractional)

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101001 0LI DDDDDDDDD SSSSSSSSS none --- --- 2..9 2..9 No

QFRAC instructs the CORDIC coprocessor to perform fractional division of Destination by Source. It works identically to QDIV, except that Destination is the upper 32 bits of the dividend and the optional SETQ value is the bottom 32 bits (zero if no SETQ).

TODO maybe write more here

QSQRT {#}D,{#}S - Square root

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101001 1LI DDDDDDDDD SSSSSSSSS none --- --- 2..9 2..9 No

QSQRT instructs the CORDIC coprocessor to compute the square root of the unsigned 64-bit number formed by Destination (lower half) and Source (upper half).

When it is done, GETQX will return the result, rounded down. ? TODO verify rounding. Also what happens to Y???

QLOG {#}D - Fixed-point logarithm

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 00L DDDDDDDDD 000001110 none --- --- 2..9 2..9 No

QLOG instructs the CORDIC coprocessor to compute the base-2 logarithm of the unsigned 32-bit number in Destination. When it is done, GETQX returns the logarithm, in 5.27 fixed-point format (i.e. the top five bits containing the whole part).

\[\mathit{QX} \approx 2^{27}(\log _{2} D)\]

QEXP {#}D - Fixed-point exponent

Encoding Register
Written
C Flag Z Flag Cycles
(cogexec)
Cycles
(hubexec)
IRQ
Shield
EEEE 1101011 00L DDDDDDDDD 000001111 none --- --- 2..9 2..9 No

QLOG instructs the CORDIC coprocessor to compute two to the power of the 5.27 fixed-point exponent in Destination. When it is done, GETQX returns the result (TODO rounded down?).

\[\mathit{QX} \approx 2^{D/2^{27}}\]