(no commit message)
[libreriscv.git] / openpower / sv / normal.mdwn
1 [[!tag standards]]
2
3 # Normal SVP64 Modes, for Arithmetic and Logical Operations
4
5 * <https://bugs.libre-soc.org/show_bug.cgi?id=574>
6 * <https://bugs.libre-soc.org/show_bug.cgi?id=558#c47>
7 * <https://bugs.libre-soc.org/show_bug.cgi?id=936>
8 * [[svp64]]
9
10 Normal SVP64 Mode covers Arithmetic and Logical operations
11 to provide suitable additional behaviour. The Mode
12 field is bits 19-23 of the [[svp64]] RM Field.
13
14 Table of contents:
15
16 [[!toc]]
17
18 # Mode
19
20 Mode is an augmentation of SV behaviour, providing additional
21 functionality. Some of these alterations are element-based (saturation), others involve post-analysis (predicate result) and others are Vector-based (mapreduce, fail-on-first).
22
23 [[sv/ldst]],
24 [[sv/cr_ops]] and [[sv/branches]] are covered separately: the following
25 Modes apply to Arithmetic and Logical SVP64 operations:
26
27 * **simple** mode is straight vectorisation. no augmentations: the vector comprises an array of independently created results.
28 * **ffirst** or data-dependent fail-on-first: see separate section. the vector may be truncated depending on certain criteria.
29 *VL is altered as a result*.
30 * **sat mode** or saturation: clamps each element result to a min/max rather than overflows / wraps. allows signed and unsigned clamping for both INT
31 and FP.
32 * **reduce mode**. if used correctly, a mapreduce (or a prefix sum)
33 is performed. see [[svp64/appendix]].
34 note that there are comprehensive caveats when using this mode.
35 * **pred-result** will test the result (CR testing selects a bit of CR and inverts it, just like branch conditional testing) and if the test fails it
36 is as if the
37 *destination* predicate bit was zero even before starting the operation.
38 When Rc=1 the CR element however is still stored in the CR regfile, even if the test failed. See appendix for details.
39
40 Note that ffirst and reduce modes are not anticipated to be high-performance in some implementations. ffirst due to interactions with VL, and reduce due to it requiring additional operations to produce a result. simple, saturate and pred-result are however inter-element independent and may easily be parallelised to give high performance, regardless of the value of VL.
41
42 The Mode table for Arithmetic and Logical operations
43 is laid out as follows:
44
45 | 0-1 | 2 | 3 4 | description |
46 | --- | --- |---------|-------------------------- |
47 | 00 | 0 | dz sz | simple mode |
48 | 00 | 1 | 0 RG | scalar reduce mode (mapreduce) |
49 | 00 | 1 | 1 / | reserved |
50 | 01 | inv | CR-bit | Rc=1: ffirst CR sel |
51 | 01 | inv | VLi RC1 | Rc=0: ffirst z/nonz |
52 | 10 | N | dz sz | sat mode: N=0/1 u/s |
53 | 11 | inv | CR-bit | Rc=1: pred-result CR sel |
54 | 11 | inv | zz RC1 | Rc=0: pred-result z/nonz |
55
56 Fields:
57
58 * **sz / dz** if predication is enabled will put zeros into the dest (or as src in the case of twin pred) when the predicate bit is zero. otherwise the element is ignored or skipped, depending on context.
59 * **zz**: both sz and dz are set equal to this flag
60 * **inv CR bit** just as in branches (BO) these bits allow testing of a CR bit and whether it is set (inv=0) or unset (inv=1)
61 * **RG** inverts the Vector Loop order (VL-1 downto 0) rather
62 than the normal 0..VL-1
63 * **N** sets signed/unsigned saturation.
64 * **RC1** as if Rc=1, enables access to `VLi`.
65 * **VLi** VL inclusive: in fail-first mode, the truncation of
66 VL *includes* the current element at the failure point rather
67 than excludes it from the count.
68
69 For LD/ST Modes, see [[sv/ldst]]. For Condition Registers
70 see [[sv/cr_ops]].
71 For Branch modes, see [[sv/branches]].
72
73 # Rounding, clamp and saturate
74
75 See [[av_opcodes]] for relevant opcodes and use-cases.
76
77 To help ensure that audio quality is not compromised by overflow,
78 "saturation" is provided, as well as a way to detect when saturation
79 occurred if desired (Rc=1). When Rc=1 there will be a *vector* of CRs,
80 one CR per element in the result (Note: this is different from VSX which
81 has a single CR per block).
82
83 When N=0 the result is saturated to within the maximum range of an
84 unsigned value. For integer ops this will be 0 to 2^elwidth-1. Similar
85 logic applies to FP operations, with the result being saturated to
86 maximum rather than returning INF, and the minimum to +0.0
87
88 When N=1 the same occurs except that the result is saturated to the min
89 or max of a signed result, and for FP to the min and max value rather
90 than returning +/- INF.
91
92 When Rc=1, the CR "overflow" bit is set on the CR associated with the
93 element, to indicate whether saturation occurred. Note that due to
94 the hugely detrimental effect it has on parallel processing, XER.SO is
95 **ignored** completely and is **not** brought into play here. The CR
96 overflow bit is therefore simply set to zero if saturation did not occur,
97 and to one if it did.
98
99 Note also that saturate on operations that set OE=1 must raise an
100 Illegal Instruction due to the conflicting use of the CR.so bit for
101 storing if
102 saturation occurred. Integer Operations that produce a Carry-Out (CA, CA32):
103 these two bits will be `UNDEFINED` if saturation is also requested.
104
105 Note that the operation takes place at the maximum bitwidth (max of
106 src and dest elwidth) and that truncation occurs to the range of the
107 dest elwidth.
108
109 *Programmer's Note: Post-analysis of the Vector of CRs to find out if any given element hit
110 saturation may be done using a mapreduced CR op (cror), or by using the
111 new crrweird instruction with Rc=1, which will transfer the required
112 CR bits to a scalar integer and update CR0, which will allow testing
113 the scalar integer for nonzero. see [[sv/cr_int_predication]]*
114
115 # Reduce mode
116
117 Reduction in SVP64 is similar in essence to other Vector Processing
118 ISAs, but leverages the underlying scalar Base v3.0B operations.
119 Thus it is more a convention that the programmer may utilise to give
120 the appearance and effect of a Horizontal Vector Reduction. Due
121 to the unusual decoupling it is also possible to perform
122 prefix-sum (Fibonacci Series) in certain circumstances. Details are in the [[svp64/appendix]]
123
124 Reduce Mode should not be confused with Parallel Reduction [[sv/remap]].
125 As explained in the [[sv/appendix]] Reduce Mode switches off the check
126 which would normally stop looping if the result register is scalar.
127 Thus, the result scalar register, if also used as a source scalar,
128 may be used to perform sequential accumulation. This *deliberately*
129 sets up a chain
130 of Register Hazard Dependencies, whereas Parallel Reduce [[sv/remap]]
131 deliberately issues a Tree-Schedule of operations that may be parallelised.
132
133 # Fail-on-first
134
135 Data-dependent fail-on-first has two distinct variants: one for LD/ST,
136 the other for arithmetic operations (actually, CR-driven). Note in each
137 case the assumption is that vector elements are required to appear to be
138 executed in sequential Program Order. When REMAP is not active,
139 element 0 would be the first.
140
141 Data-driven (CR-driven) fail-on-first activates when Rc=1 or other
142 CR-creating operation produces a result (including cmp). Similar to
143 branch, an analysis of the CR is performed and if the test fails, the
144 vector operation terminates and discards all element operations at and
145 above the current one, and VL is truncated to either
146 the *previous* element or the current one, depending on whether
147 VLi (VL "inclusive") is set.
148
149 Thus the new VL comprises a contiguous vector of results,
150 all of which pass the testing criteria (equal to zero, less than zero etc
151 as defined by the CR-bit test).
152
153 The CR-based data-driven fail-on-first is "new" and not found in ARM
154 SVE or RVV. At the same time it is "old" because it is almost
155 identical to a generalised form of Z80's `CPIR` instruction.
156 It is extremely useful for reducing instruction count,
157 however requires speculative execution involving modifications of VL
158 to get high performance implementations. An additional mode (RC1=1)
159 effectively turns what would otherwise be an arithmetic operation
160 into a type of `cmp`. The CR is stored (and the CR.eq bit tested
161 against the `inv` field).
162 If the CR.eq bit is equal to `inv` then the Vector is truncated and
163 the loop ends.
164
165 VLi is only available as an option when `Rc=0` (or for instructions
166 which do not have Rc). When set, the current element is always
167 also included in the count (the new length that VL will be set to).
168 This may be useful in combination with "inv" to truncate the Vector
169 to *exclude* elements that fail a test, or, in the case of implementations
170 of strncpy, to include the terminating zero.
171
172 In CR-based data-driven fail-on-first there is only the option to select
173 and test one bit of each CR (just as with branch BO). For more complex
174 tests this may be insufficient. If that is the case, a vectorised crop
175 such as crand, cror or [[sv/cr_int_predication]] crweirder may be used,
176 and ffirst applied to the crop instead of to
177 the arithmetic vector. Note that crops are covered by
178 the [[sv/cr_ops]] Mode format.
179
180 *Programmer's note: `VLi` is only accessible in normal operations
181 which in turn limits the CR field bit-testing to only `EQ/NE`.
182 [[sv/cr_ops]] are not so limited. Thus it is possible to use for
183 example `sv.cror/ff=gt/vli *0,*0,*0`, which is not a `nop` because
184 it allows Fail-First Mode to perform a test and truncate VL.*
185
186 Two extremely important aspects of ffirst are:
187
188 * LDST ffirst may never set VL equal to zero. This because on the first
189 element an exception must be raised "as normal".
190 * CR-based data-dependent ffirst on the other hand **can** set VL equal
191 to zero. This is the only means in the entirety of SV that VL may be set
192 to zero (with the exception of via the SV.STATE SPR). When VL is set
193 zero due to the first element failing the CR bit-test, all subsequent
194 vectorised operations are effectively `nops` which is
195 *precisely the desired and intended behaviour*.
196
197 The second crucial aspect, compared to LDST Ffirst:
198
199 * LD/ST Failfirst may (beyond the initial first element
200 conditions) truncate VL for any architecturally
201 suitable reason. Beyond the first element LD/ST Failfirst is
202 arbitrarily speculative and 100% non-deterministic.
203 * CR-based data-dependent first on the other hand MUST NOT truncate VL
204 arbitrarily to a length decided by the hardware: VL MUST only be
205 truncated based explicitly on whether a test fails.
206 This because it is a precise Deterministic test on which algorithms
207 can and will will rely.
208
209 **Floating-point Exceptions**
210
211 When Floating-point exceptions are enabled VL must be truncated at
212 the point where the Exception appears not to have occurred. If `VLi`
213 is set then VL must include the faulting element, and thus the
214 faulting element will always raise its exception. If however `VLi`
215 is clear then VL **excludes** the faulting element and thus the
216 exception will **never** be raised.
217
218 Although very strongly
219 discouraged the Exception Mode that permits Floating Point Exception
220 notification to arrive too late to unwind is permitted
221 (under protest, due it violating
222 the otherwise 100% Deterministic nature of Data-dependent Fail-first).
223
224 **Use of lax FP Exception Notification Mode could result in parallel
225 computations proceeding with invalid results that have to be explicitly
226 detected, whereas with the strict FP Execption Mode enabled, FFirst
227 truncates VL, allows subsequent parallel computation to avoid
228 the exceptions entirely**
229
230 ## Data-dependent fail-first on CR operations (crand etc)
231
232 Operations that actually produce or alter CR Field as a result
233 have their own SVP64 Mode, described
234 in [[sv/cr_ops]].
235
236 # pred-result mode
237
238 This mode merges common CR testing with predication, saving on instruction
239 count. Below is the pseudocode excluding predicate zeroing and elwidth
240 overrides. Note that the pseudocode for [[sv/cr_ops]] is slightly different.
241
242 for i in range(VL):
243 # predication test, skip all masked out elements.
244 if predicate_masked_out(i):
245 continue
246 result = op(iregs[RA+i], iregs[RB+i])
247 CRnew = analyse(result) # calculates eq/lt/gt
248 # Rc=1 always stores the CR
249 if Rc=1 or RC1:
250 crregs[offs+i] = CRnew
251 # now test CR, similar to branch
252 if RC1 or CRnew[BO[0:1]] != BO[2]:
253 continue # test failed: cancel store
254 # result optionally stored but CR always is
255 iregs[RT+i] = result
256
257 The reason for allowing the CR element to be stored is so that
258 post-analysis of the CR Vector may be carried out. For example:
259 Saturation may have occurred (and been prevented from updating, by the
260 test) but it is desirable to know *which* elements fail saturation.
261
262 Note that RC1 Mode basically turns all operations into `cmp`. The
263 calculation is performed but it is only the CR that is written. The
264 element result is *always* discarded, never written (just like `cmp`).
265
266 Note that predication is still respected: predicate zeroing is slightly
267 different: elements that fail the CR test *or* are masked out are zero'd.
268