(no commit message)
[libreriscv.git] / openpower / sv / svp64_quirks.mdwn
index 1acf572e346615466a9561d5a6565776b75416c5..43d7249df22871f5bf4e230c0bd6acd6501e1873 100644 (file)
@@ -3,16 +3,18 @@
 [[!toc]]
 
 SVP64 is designed around fundamental and inviolate RISC principles.
-This gives a uniformity and regularity to the ISA which was why RISC
-as a concept became popular. It is just that nobody has ever considered
-applying the RISC concept to a *Vector* ISA before.
+This gives a uniformity and regularity to the ISA, making implementation
+straightforward, which was why RISC
+as a concept became popular.
 
 1. There are no actual Vector instructions: Scalar instructions
    are the sole exclusive bedrock.
 2. No scalar instruction ever deviates in its encoding or meaning
    just because it is prefixed (semantic caveats below)
-3. A hardware-level for-loop makes vector elements 100% synonymous
-   with scalar instructions (the suffix)
+3. A hardware-level for-loop (the prefix) makes vector elements
+   100% synonymous with scalar instructions (the suffix)
+4. Exactly as with Scalar RISC ISAs, the uniformity does produce
+   "holes" in the encoding or some strange combinations.
 
 How can a Vector ISA even exist when no actual Vector instructions
 are permitted to be added? It comes down to the strict RISC abstraction.
@@ -119,7 +121,11 @@ actually come up with legitimate use.
 
 Branch is the one and only place where the Scalar
 (non-prefixed) operations differ from the Vector (element)
-instructions, as explained in a separate section.
+instructions (as explained in a separate section) although
+a case could be made for the perspective that they are identical,
+but the defaults for new parameters in the Scalar case makes branch
+identical to Power ISA v3.1 Scalar branches.
+
 The
 RM bits can be used for other purposes because the Arithmetic modes
 make no sense at all for a Branch.
@@ -189,7 +195,8 @@ when combined with Saturation, given that LD/ST operations have byte,
 halfword, word, dword and quad variants. The interaction between these
 widths as part of the actual operation, and the source and destination
 elwidth overrides, was particularly obtuse and hard to derive: some care
-and attention is advised, here, when reading the specification.
+and attention is advised, here, when reading the specification,
+especially on arithmetic loads (lbarx, lharx etc.)
 
 **Non-vectorised**
 
@@ -203,10 +210,10 @@ Nemory Management
 instructions, these make no sense to Vectorise.
 
 However, it is really quite important to not be tempted to conclude that
-just because these instructions are un-vectoriseable, the opcode space
+just because these instructions are un-vectoriseable, the Prefix opcode space
 must be free for reiterpretation and use for other purposes. This would
 be a serious mistake because a future revision of the specification
-might *retire* the Scalar instruction, replace it with another.
+might *retire* the Scalar instruction, and, worse, replace it with another.
 Again this comes down to being quite strict about the rules: only Scalar
 instructions get Vectorised: there are *no* actual explicit Vector
 instructions.
@@ -223,7 +230,55 @@ for the type of operation (Branch, CRs, Memory, Arithmetic),
 and each Category has its own relevant but
 ultimately rational quirks.
 
-# Single Predication
+# Abstraction between Prefix and Suffix
+
+In the introduction paragraph, a great fuss was made emphasising that
+the Prefix is kept separate from the Suffix.  The whole idea there is
+that a Multi-issue Decoder and subsequent pipelines would in no way have
+"back-propagation" of state that can only be determined far too late.
+This *has* been preserved, however there is a hiccup.
+
+Examining the Power ISA 3.1 a 64-bit Prefix was introduced, EXT001.
+The encoding of the prefix has 6 bits that are dedicated to letting
+the hardware know what the remainder of the Prefix bits mean: how they
+are formatted, even without having to examine the Suffix to which
+they are applied.
+
+SVP64 has such pressure on its 24-bit encoding that it was simply
+not possible to perform the same trick used by Power ISA 3.1 Prefixing.
+Therefore, rather unfortunately, it becomes necessary to perform
+a *partial decoding* of the v3.0 Suffix before the 24-bit SVP64 RM
+Fields may be identified.  Fortunately this is straightforward, and
+does not rely on any outside state, and even more fortunately
+for a Multi-Issue Execution decoder, the length 32/64 is also
+easy to identify by looking for the EXT001 pattern. Once identified
+the 32/64 bits may be passed independently to multiple Decoders in
+parallel.
+
+# Predication
+
+Predication is entirely missing from the Power ISA.
+Adding it would be a costly mistake because it cannot be retrofitted
+to an ISA without literally duplicating all instructions. Prefixing
+is about the only sane way to go.
+
+CR Fields as predicate masks could be spread across multiple register
+file entries, making them costly to read in one hit. Therefore the
+possibility exists that an instruction element writing to a CR Field
+could *overwrite* the Predicate mask CR Vector during the middle of
+a for-loop.
+
+Clearly this is bad, so don't do it.  If there are potential issues
+they can be avoided by using the crweird instructions to get CR Field
+bits into an Integer GPR (r3, r10 or r30) and use that GPR as a
+Predicate mask instead.
+
+Even in Vertical-First Mode, which is a single Scalar instruction executed
+with "offset" registers (in effect), the rule still applies: don't write
+to the same register being used as the predicate, it's `UNDEFINED`
+behaviour.
+
+## Single Predication
 
 So named because there is a Twin Predication concept as well, Single
 Predication is also unlike other Vector ISAs because it allows zeroing
@@ -257,7 +312,7 @@ element indices getting "out-of-sync" even though the Predicate Mask
 is the same because the behaviour is different when zeros in the
 Predicate are encountered.
 
-# Twin Predication
+## Twin Predication
 
 Twin Predication is an entirely new concept not present in any commercial
 Vector ISA of the past forty years.  To explain how normal Single-predication
@@ -364,6 +419,11 @@ One key difference is that LR is only updated if certain additional
 conditions are met, whereas Scalar `bclrl` for example unconditionally
 overwrites LR.
 
+Another is that the Vectorised Branch-Conditional instructions are the
+only ones where there are side-effects on predication when skipping
+is enabled. This is so as to be able to use CTR to count down
+*masked-out* elements.
+
 Well over 500 Vectorised branch instructions exist in SVP64 due to the
 number of options available: close integration and interaction with
 the base Scalar Branch was unavoidable in order to create Conditional
@@ -414,6 +474,12 @@ of user expectations, particularly for LD/ST where exceptions
 would normally be expected to be raised, Fail-First provides for
 avoidance of those exceptions.
 
+For Hardware implementers, a standard Out-of-Order micro-architecture
+allows for Cancellation of speculatively-executed elements that extended
+beyond the Vector Truncation point.  In-order systems will have a slightly
+harder time and may choose to execute one element only at a time, reducing
+performance as a result.
+
 # OE=1
 
 The hardware cost of Sticky Overflow in a parallel environment is immense.
@@ -464,3 +530,113 @@ Mode.  Instructions could modify CR Fields currently being used as Predicate
 Masks: detecting this is so horrendous for hardware resource utilisation
 and hardware complexity that, again, the decision is made to relax these
 constraints and for Software to take that into account.
+
+# Floating-Point "Single" becomes "Half"
+
+In several places in the Power ISA there are operations that are on
+32-bit quantities in 64-bit registers.  The best example is FP which
+has 64-bit operations (`fadd`) and 32-bit operations (`fadds` or
+FP Add "single").  Element-width overrides it would seem to
+be unnecessary, under these circumstances.
+
+However, it is not possible for `fadds` to fit two elements into
+64-bit: that breaks the simplicity of SVP64.
+Bear in mind that the FP32 bits are spread out across a 64
+bit register in FP64 format.  The solution here was to consider the
+"s" at the end of each instruction
+to mean "half of the element's width". Thus, `sv.fadds/ew=32`
+actually stores an FP16 spread out across the 32 bits of an
+element, in FP32 format, where `sv.fadd/ew=32` stores a full
+FP32 result into the full 32 bits.
+
+Where this breaks down is when attempting to do half-width on
+BF16 or FP16 operations: there does not exist a BF8 or an IEEE754 FP8
+format, so these (`sv.fadds/ew=8`) should be avoided.
+
+# Vertical-First and Subvectors
+
+Documented in the [[sv/setvl]] page, Vertical-First goes through
+elements second instructions first and requires an explicit
+[[sv/svstep]] instruction to move to the next element,
+(whereas Horizontal-First
+loops through elements in full first before moving on to
+the next instruction): *Subvectors are considered "elements"*
+in Vertical-First Mode.
+
+This is conceptually quite easy to keep in mind that a Vertical-First
+instruction does one element at a time, and when SUBVL is set,
+that "element" in essence becomes a vec2/3/4.
+
+# Swizzle and Pack/Unpack
+
+These are both so weird it's best to just read the pages in full
+and pay attention: [[sv/mv.swizzle]] and [[sv/mv.vec]].
+Swizzle Moves only engage with vec2/3/4, *reordering* the copying
+of the sub-vector elements (including allowing repeats and skips)
+based on an immediate supplied by the instruction.  The fun
+comes when Pack/Unpack are enabled, and it is really important
+to be aware how the Arrays of vec2/3/4 become re-ordered
+*and swizzled at the same time*.
+
+Pack/Unpack started out as 
+[[sv/mv.vec]] but became its own distinct Mode over time.
+The main thing to keep in mind about Pack/Unpack
+is that it engages a swap of the ordering of the VL-SUBVL
+nested for-loops, in exactly the same way that Matrix REMAP
+can do.
+When Pack or Unpack is enabled it is the SUBVL for-loop
+that becomes outermost.  A bit of thought shows that this is
+a 2D "Transpose" where Dimension X is VL and Dimension Y is SUBVL.
+However *both* source *and* destination may be independently
+"Transposed", which makes no sense at all until the fact that
+Swizzle can have a *different SUBVL* is taken into account.
+
+Basically Pack/Unpack covers everything that VSX `vpkpx` and
+other ops can do, and then some: Saturation included, for arithmetic ops.
+
+# LD/ST with zero-immediate vs mapreduce mode
+
+LD/ST operations with a zero immediate effectively means that on a
+Vector operation the element index to offset the memory location is
+multiplied by zero.  Thus, a sequence of LD operations will load from
+the exact same address, and likewise STs to the exact same address.
+
+Ordinarily this would make absolutely no sense whatsoever, except
+that Power ISA has cache-inhibited LD/STs (Power ISA v.1, Book III,
+1.6.1, p1033), for accessing memory-mapped
+peripherals and other crucial uses.  Thus, *despite not being a mapreduce mode*,
+zero-immediates cause multiple hits on the same element.
+
+Mapreduce mode is not actually mapreduce at all: it is
+a relaxation of the normal rule where if the destination is a Scalar the
+Vector for-looping is not terminated on first write to the destination.
+Instead, the developer is expected to exploit the strict Program Order,
+make one of the sources the same as that Scalar destination, effectively
+making that Scalar register an "Accumulator", thus creating the *appearance*
+(effect) of Simple-V having a mapreduce capability, when in fact it is
+more of an artefact.
+
+LD/ST zero-immediate has similar quirky overwriting as the "mapreduce"
+mode, but actually requires the registers to be Vectors.  It is simply
+a mathematical artefact of multiplying by zero, which happens to be
+useful for cache-inhibited operations.
+
+# Limited space in LD/ST Mode
+
+As pointed out in the [[sv/ldst]] page there is limited space in only
+5 mode bits to fully express all potential modes of operation.
+
+* LD/ST Immediate has no individual control over src/dest zeroing,
+  whereas LD/ST Indexed does.
+* LD/ST Immediate has no Saturated Pack/Unpack (Arithmetic Mode does)
+* LD/ST Indexed has no Pack/Unpack (REMAP may be used instead)
+
+These are not insurmountable problems: there do exist workarounds.
+For example it is possible to set up Matrix REMAP to perform the same
+job as Pack/Unpack, at which point the LD/ST "Saturation" mode may
+be used, saving on costly intermediary registers at double the LD
+width.  Also, although potentially costly it may be possible to
+use Indexed Mode after using `svstep` to compute a sequence of
+Indices, then activate either `sz` or `dz` as required, as a workaround
+for LDST Immediate only having `zz`.
+