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