(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 (free of all Hazards inter-element but not inter-group).
154 With Reduction literally creating Dependency
155 Hazards on every element-level sub-instruction it is pretty clear that setting
156 `hphint` *at all* would cause data corruption. However `sv.add *r0, *r4, *r0`
157 for example clearly leaves room for four parallel elements. Programmers must
158 be aware of this and exercise caution.
159
160 ## Data-dependent Fail-on-first
161
162 Data-dependent fail-on-first is CR-field-driven and is completely separate
163 and distinct from LD/ST Fail-First (also known as Fault-First). Note in
164 each case the assumption is that vector elements are required to appear
165 to be executed in sequential Program Order. When REMAP is not active,
166 element 0 would be the first.
167
168 Data-driven (CR-field-driven) fail-on-first activates when Rc=1 or other
169 CR-creating operation produces a result (including cmp). Similar to
170 Branch-Conditional,
171 an analysis of the CR is performed and if the test fails, the
172 vector operation terminates and discards all element operations **at and
173 above the current one**, and VL is truncated to either the *previous*
174 element or the current one, depending on whether VLi (VL "inclusive")
175 is clear or set, respectively.
176
177 Thus the new VL comprises a contiguous vector of results, all of which
178 pass the testing criteria (equal to zero, less than zero etc as defined
179 by the CR-bit test).
180
181 *Note: when VLi is clear, the behaviour at first seems counter-intuitive.
182 A result is calculated but if the test fails it is prohibited from being
183 actually written. This becomes intuitive again when it is remembered
184 that the length that VL is set to is the number of *written* elements, and
185 only when VLI is set will the current element be included in that count.*
186
187 The CR-based data-driven fail-on-first is "new" and not found in ARM SVE
188 or RVV. At the same time it is "old" because it is almost identical to
189 a generalised form of Z80's `CPIR` instruction. It is extremely useful
190 for reducing instruction count, however requires speculative execution
191 involving modifications of VL to get high performance implementations.
192 An additional mode (RC1=1) effectively turns what would otherwise be an
193 arithmetic operation into a type of `cmp`. The CR is stored (and the
194 CR.eq bit tested against the `inv` field). If the CR.eq bit is equal to
195 `inv` then the Vector is truncated and the loop ends.
196
197 VLi is only available as an option when `Rc=0` (or for instructions
198 which do not have Rc). When set, the current element is always also
199 included in the count (the new length that VL will be set to). This may
200 be useful in combination with "inv" to truncate the Vector to *exclude*
201 elements that fail a test, or, in the case of implementations of strncpy,
202 to include the terminating zero.
203
204 In CR-based data-driven fail-on-first there is only the option to select
205 and test one bit of each CR (just as with branch BO). For more complex
206 tests this may be insufficient. If that is the case, a vectorised crop
207 such as crand, cror or [[sv/cr_int_predication]] crweirder may be used,
208 and ffirst applied to the crop instead of to the arithmetic vector. Note
209 that crops are covered by the [[sv/cr_ops]] Mode format.
210
211 Use of Fail-on-first with Vertical-First Mode is not prohibited but is
212 not really recommended. The effect of truncating VL
213 may have unintended and unexpected consequences on subsequent instructions.
214 VLi set will be fine: it is when VLi is clear that problems may be faced.
215
216 *Programmer's note: `VLi` is only accessible in normal operations which in
217 turn limits the CR field bit-testing to only `EQ/NE`. [[sv/cr_ops]] are
218 not so limited. Thus it is possible to use for example `sv.cror/ff=gt/vli
219 *0,*0,*0`, which is not a `nop` because it allows Fail-First Mode to
220 perform a test and truncate VL.*
221
222 *Hardware implementor's note: effective Sequential Program Order must
223 be preserved. Speculative Execution is perfectly permitted as long as
224 the speculative elements are held back from writing to register files
225 (kept in Resevation Stations), until such time as the relevant CR Field
226 bit(s) has been analysed. All Speculative elements sequentially beyond
227 the test-failure point **MUST** be cancelled. This is no different from
228 standard Out-of-Order Execution and the modification effort to efficiently
229 support Data-Dependent Fail-First within a pre-existing Multi-Issue
230 Out-of-Order Engine is anticipated to be minimal. In-Order systems on
231 the other hand are expected, unavoidably, to be low-performance*.
232
233 Two extremely important aspects of ffirst are:
234
235 * LDST ffirst may never set VL equal to zero. This because on the first
236 element an exception must be raised "as normal".
237 * CR-based data-dependent ffirst on the other hand **can** set VL equal
238 to zero. When VL is set
239 zero due to the first element failing the CR bit-test, all subsequent
240 vectorised operations are effectively `nops` which is
241 *precisely the desired and intended behaviour*.
242
243 The second crucial aspect, compared to LDST Ffirst:
244
245 * LD/ST Failfirst may (beyond the initial first element
246 conditions) truncate VL for any architecturally suitable reason. Beyond
247 the first element LD/ST Failfirst is arbitrarily speculative and 100%
248 non-deterministic.
249 * CR-based data-dependent first on the other hand MUST NOT truncate VL
250 arbitrarily to a length decided by the hardware: VL MUST only be
251 truncated based explicitly on whether a test fails. This because it is
252 a precise Deterministic test on which algorithms can and will rely.
253
254 **Floating-point Exceptions**
255
256 When Floating-point exceptions are enabled VL must be truncated at
257 the point where the Exception appears not to have occurred. If `VLi`
258 is set then VL must include the faulting element, and thus the faulting
259 element will always raise its exception. If however `VLi` is clear then
260 VL **excludes** the faulting element and thus the exception will **never**
261 be raised.
262
263 Although very strongly discouraged the Exception Mode that permits
264 Floating Point Exception notification to arrive too late to unwind
265 is permitted (under protest, due it violating the otherwise 100%
266 Deterministic nature of Data-dependent Fail-first).
267
268 **Use of lax FP Exception Notification Mode could result in parallel
269 computations proceeding with invalid results that have to be explicitly
270 detected, whereas with the strict FP Execption Mode enabled, FFirst
271 truncates VL, allows subsequent parallel computation to avoid the
272 exceptions entirely**
273
274 ## Data-dependent fail-first on CR operations (crand etc)
275
276 Operations that actually produce or alter CR Field as a result have
277 their own SVP64 Mode, described in [[sv/cr_ops]].
278
279 [[!tag standards]]
280
281 --------
282
283 \newpage{}
284