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