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