(no commit message)
[libreriscv.git] / openpower / sv / overview.mdwn
index 85f7e9038f8803bab44196a0b035d516f8126931..e272fb012c3ea8a98e25ff673d4b776701fe257e 100644 (file)
@@ -1,10 +1,14 @@
 # SV Overview
 
+**SV is in DRAFT STATUS**. SV has not yet been submitted to the OpenPOWER Foundation ISA WG for review.
+
 This document provides an overview and introduction as to why SV (a
-Cray-style Vector augmentation to OpenPOWER) exists, and how it works.
+[[!wikipedia Cray]]-style Vector augmentation to [[!wikipedia OpenPOWER]]) exists, and how it works.
 
 Links:
 
+* This page: [http://libre-soc.org/openpower/sv/overview](http://libre-soc.org/openpower/sv/overview)
+* [FOSDEM2021 SimpleV for OpenPOWER](https://fosdem.org/2021/schedule/event/the_libresoc_project_simple_v_vectorisation/)
 * [[discussion]] and
   [bugreport](https://bugs.libre-soc.org/show_bug.cgi?id=556)
   feel free to add comments, questions.
@@ -37,6 +41,10 @@ the typical dimensions that result in such massive proliferation:
 * Conversion between bitwidths (FP16-FP32-64)
 * Signed/unsigned
 * HI/LO swizzle (Audio L/R channels)
+   - HI/LO selection on src 1
+   - selection on src 2
+   - selection on dest
+   - Example: AndesSTAR Audio DSP 
 * Saturation (Clamping at max range)
 
 These typically are multiplied up to produce explicit opcodes numbering
@@ -279,7 +287,7 @@ in Vector ISAs:
   and the destination a vector, and having no predicate set or having
   multiple bits set.
 * VSELECT is provided by setting up (at least one of) the sources as a
-  vector, using a single bit in olthe predicate, and the destination as
+  vector, using a single bit in the predicate, and the destination as
   a scalar.
 
 All of this capability and coverage without even adding one single actual
@@ -464,10 +472,9 @@ bits will be *unaltered*.
 
 Note that things such as zero/sign-extension (and predication) have
 been left out to illustrate the elwidth concept. Also note that it turns
-out to be important to perform the operation at the maximum bitwidth -
-`max(srcwid, destwid)` - such that any truncation, rounding errors or
+out to be important to perform the operation internally at effectively an *infinite* bitwidth such that any truncation, rounding errors or
 other artefacts may all be ironed out.  This turns out to be important
-when applying Saturation for Audio DSP workloads.
+when applying Saturation for Audio DSP workloads, particularly for multiply and IEEE754 FP rounding.  By "infinite" this is conceptual only: in reality, the application of the different truncations and width-extensions set a fixed deterministic practical limit on the internal precision needed, on a per-operation basis.
 
 Other than that, element width overrides, which can be applied to *either*
 source or destination or both, are pretty straightforward, conceptually.
@@ -503,12 +510,15 @@ clarity and assumes significant working knowledge of OpenPOWER, with
 arbitrary insertions of 7-index here and 3-bitindex there, the decision
 to pick LE was extremely easy.
 
-Without such a decision, if two words are packed as elements into a
-64 bit register, what does this mean? Should they be inverted so that
-the lower indexed element goes into the HI or the LO word? should the
-8 bytes of each register be inverted? Should the bytes in each element
-be inverted? Should the element indexing loop order be broken onto discontiguous chunks such as 32107654 rather than 01234567, and if so at what granilsrity of discontinuity? These are all equally valid and legitimate interpretations
-of what constitutes "BE" and they all cause merry mayhem.
+Without such a decision, if two words are packed as elements into a 64
+bit register, what does this mean? Should they be inverted so that the
+lower indexed element goes into the HI or the LO word? should the 8
+bytes of each register be inverted? Should the bytes in each element
+be inverted? Should the element indexing loop order be broken onto
+discontiguous chunks such as 32107654 rather than 01234567, and if so
+at what granularity of discontinuity? These are all equally valid and
+legitimate interpretations of what constitutes "BE" and they all cause
+merry mayhem.
 
 The decision was therefore made: the c typedef union is the canonical
 definition, and its members are defined as being in LE order. From there,
@@ -519,6 +529,7 @@ as long as the results produced conform to the elwidth pseudocode.
 
 * <https://developer.arm.com/documentation/ddi0406/c/Application-Level-Architecture/Application-Level-Memory-Model/Endian-support/Endianness-in-Advanced-SIMD?lang=en>
 * <https://stackoverflow.com/questions/24045102/how-does-endianness-work-with-simd-registers>
+* <https://llvm.org/docs/BigEndianNEON.html>
 
 
 ## Source and Destination overrides
@@ -528,18 +539,23 @@ are over-ridden to different widths?  For example, FP16 arithmetic is
 not accurate enough and may introduce rounding errors when up-converted
 to FP32 output.  The rule is therefore set:
 
-    The operation MUST take place at the larger of the two widths.
+    The operation MUST take place effectively at infinite precision:
+    actual precision determined by the operation and the operand widths
 
 In pseudocode this is:
 
     for i = 0 to VL-1:
        src1 = get_polymorphed_reg(RA, srcwid, i)
        src2 = get_polymorphed_reg(RB, srcwid, i)
-       opwidth = max(srcwid, destwid)
+       opwidth = max(srcwid, destwid) # usually
        result = op_add(src1, src2, opwidth) # at max width
        set_polymorphed_reg(rd, destwid, i, result)
 
-It will turn out that under some conditions the combination of the
+In reality the source and destination widths determine the actual required
+precision in a given ALU.  The reason for setting "effectively" infinite precision
+is illustrated for example by Saturated-multiply, where if the internal precision was insufficient it would not be possible to correctly determine the maximum clip range had been exceeded.
+
+Thus it will turn out that under some conditions the combination of the
 extension of the source registers followed by truncation of the result
 gets rid of bits that didn't matter, and the operation might as well have
 taken place at the narrower width and could save resources that way.
@@ -566,8 +582,8 @@ be first read at their overridden bitwidth and *then* sign-extended:
        src2 = get_polymorphed_reg(RB, srcwid, i)
        opwidth = max(srcwid, destwid)
        # srces known to be less than result width
-       src1 = sign_extend(src1, srcwid, destwid)
-       src2 = sign_extend(src2, srcwid, destwid)
+       src1 = sign_extend(src1, srcwid, opwidth)
+       src2 = sign_extend(src2, srcwid, opwidth)
        result = op_signed(src1, src2, opwidth) # at max width
        set_polymorphed_reg(rd, destwid, i, result)
 
@@ -593,7 +609,7 @@ truncated.  Only then can the arithmetic saturation condition be detected:
        set_polymorphed_reg(rd, destwid, i, sat)
        # set sat overflow
        if Rc=1:
-          CR.ov = (sat != result)
+          CR[i].ov = (sat != result)
 
 So the actual computation took place at the larger width, but was
 post-analysed as an unsigned operation.  If however "signed" saturation
@@ -621,7 +637,7 @@ truncating down to 8 bit for example.
        opwidth = max(srcwid, destwid)
        # logical op, signed has no meaning
        result = op_xor(src1, src2, opwidth)
-       # now saturate (unsigned)
+       # now saturate (signed)
        sat = max(result, (1<<destwid-1)-1)
        sat = min(result, -(1<<destwid-1))
        set_polymorphed_reg(rd, destwid, i, sat)