(no commit message)
[libreriscv.git] / openpower / sv / cr_int_predication.mdwn
1 [[!tag standards]]
2
3 # New instructions for CR/INT predication
4
5 See:
6
7 * main bugreport for crweirds
8 <https://bugs.libre-soc.org/show_bug.cgi?id=533>
9 * <https://bugs.libre-soc.org/show_bug.cgi?id=527>
10 * <https://bugs.libre-soc.org/show_bug.cgi?id=569>
11 * <https://bugs.libre-soc.org/show_bug.cgi?id=558#c47>
12
13 Rationale:
14
15 Condition Registers are conceptually perfect for use as predicate masks, the only problem being that typical Vector ISAs have quite comprehensive mask-based instructions: set-before-first, popcount and much more. In fact many Vector ISAs can use Vectors *as* masks, consequently the entire Vector ISA is available for use in creating masks. This is not practical for SV given the premise to minimise adding of instructions.
16
17 With the scalar OpenPOWER v3.0B ISA having already popcnt, cntlz and others normally seen in Vector Mask operations it makes sense to allow *both* scalar integers *and* CR-Vectors to be predicate masks. That in turn means that much more comprehensive interaction between CRs and scalar Integers is required.
18
19 The opportunity is therefore taken to also augment CR logical arithmetic as well, using a mask-based paradigm that takes into consideration multiple bits of each CR (eq/lt/gt/ov). v3.0B Scalar CR instructions (crand, crxor) only allow a single bit calculation.
20
21 Basic concept:
22
23 * CR-based instructions that perform simple AND/OR/XOR from all four bits
24 of a CR to create a single bit value (0/1) in an integer register
25 * Inverse of the same, taking a single bit value (0/1) from an integer
26 register to selectively target all four bits of a given CR
27 * CR-to-CR version of the same, allowing multiple bits to be AND/OR/XORed
28 in one hit.
29 * Vectorisation of the same
30
31 Purpose:
32
33 * To provide a merged version of what is currently a multi-sequence of
34 CR operations (crand, cror, crxor) with mfcr and mtcrf, reducing
35 instruction count.
36 * To provide a vectorised version of the same, suitable for advanced
37 predication
38
39 Side-effects:
40
41 * mtcrweird when RA=0 is a means to set or clear arbitrary CR bits
42 using immediates embedded within the instruction.
43
44 (Twin) Predication interactions:
45
46 * INT twin predication with zeroing is a way to copy an integer into CRs without necessarily needing the INT register (RA). if it is, it is effectively ANDed (or negate-and-ANDed) with the INT Predicate
47 * CR twin predication with zeroing is likewise a way to interact with the incoming integer
48
49 this gets particularly powerful if data-dependent predication is also enabled. further explanation is below.
50
51 # Bit ordering.
52
53 IBM chose MSB0 for the OpenPOWER v3.0B specification. This makes things slightly hair-raising. Our desire initially is therefore to follow the logical progression from the defined behaviour of `mtcr` and `mfcr` etc.
54 In [[isa/sprset]] we see the pseudocode for `mtcrf` for example:
55
56 mtcrf FXM,RS
57
58 do n = 0 to 7
59 if FXM[n] = 1 then
60 CR[4*n+32:4*n+35] <- (RS)[4*n+32:4*n+35]
61
62 This places (according to a mask schedule) `CR0` into MSB0-numbered bits 32-35 of the target Integer register `RS`, these bits of `RS` being the 31st down to the 28th. Unfortunately, even when not Vectorised, this inserts CR numbering inversions on each batch of 8 CRs, massively complicating matters. Predication when using CRs would have to be morphed to this (unacceptably complex) behaviour:
63
64 for i in range(VL):
65 if INTpredmode:
66 predbit = (r3)[63-i] # IBM MSB0 spec sigh
67 else:
68 # completely incomprehensible vertical numbering
69 n = (7-(i%8)) | (i & ~0x7) # total mess
70 CRpredicate = CR{n} # select CR0, CR1, ....
71 predbit = CRpredicate[offs] # select eq..ov bit
72
73 Which is nowhere close to matching the straightforward obvious case:
74
75 for i in range(VL):
76 if INTpredmode:
77 predbit = (r3)[63-i] # IBM MSB0 spec sigh
78 else:
79 CRpredicate = CR{i} # start at CR0, work up
80 predbit = CRpredicate[offs]
81
82 In other words unless we do something about this, when we transfer bits from an Integer Predicate into a Vector of CRs, our numbering of CRs, when enumerating them in a CR Vector, would be **CR7** CR6 CR5.... CR0 **CR15** CR14 CR13... CR8 **CR23** CR22 etc. **not** the more natural and obvious CR0 CR1 ... CR23.
83
84 Therefore the instructions below need to **redefine** the relationship so that CR numbers (CR0, CR1) sequentially match the arithmetically-ordered bits of Integer registers. By `arithmetic` this is deduced from the fact that the instruction `addi r3, r0, 1` will result in the **LSB** (numbered 63 in IBM MSB0 order) of r3 being set to 1 and all other bits set to zero. We therefore refer, below, to this LSB as "Arithmetic bit 0", and it is this bit which is used - defined - as being the first bit used in Integer predication (on element 0).
85
86 Below is some pseudocode that, given a CR offset `offs` to represent `CR.eq` thru to `CR.ov` respectively, will copy the INT predicate bits in the correct order into the first 8 CRs:
87
88 do n = 0 to 7
89 CR[4*n+32+offs] <- (RS)[63-n]
90
91 Assuming that `offs` is set to `CR.eq` this results in:
92
93 * Arithmetic bit 0 (the LSB, numbered 63 in IBM MSB0 terminology)
94 of RS being inserted into CR0.eq
95 * Arithmetic bit 1 of RS being inserted into CR1.eq
96 * ...
97 * Arithmetic bit 7 of RS being inserted into CR7.eq
98
99 To clarify, then: all instructions below do **NOT** follow the IBM convention, they follow the natural sequence CR0 CR1 instead, using `CR{fieldnum}` to refer to the individual CR Fields. However it is critically important to note that the offsets **in** a CR field
100 (`CR.eq` for example) continue to follow the v3.0B definition and convention.
101
102
103 # Instruction form and pseudocode
104
105 Note that `CR{n}` refers to `CR0` when `n=0` and consequently, for CR0-7, is defined, in v3.0B pseudocode, as:
106
107 CR{7-n} = CR[32+n*4:35+n*4]
108
109 Instruction format:
110
111 |0-5|6-10 |11|12-15|16-18|19-20|21-25 |26-30 |31|name |
112 |---|---- |--|-----|-----|-----|----- |----- |--|---- |
113 |19 |RT | |mask |BB | |XO[0:4]|XO[5:9]|/ | |
114 |19 |RT |0 |mask |BB | 0 M |XO[0:4]|0 mode |Rc|crrweird |
115 |19 |RA |1 |mask |BT | 0 / |XO[0:4]|0 mode |/ |mtcrweird |
116 |19 |BT //|0 |mask |BB | 1 / |XO[0:4]|0 mode |/ |crweird |
117 |19 |BFT |1 |mask |BB | 1 M |XO[0:4]|0 mode |/ |crweirder |
118
119 **crrweird**
120
121 mode is encoded in XO and is 4 bits
122
123 bit 11=0, bit 19=0
124
125 crrweird: RT, BB, mask.mode
126
127 creg = CR{BB}
128 n0 = mask[0] & (mode[0] == creg[0])
129 n1 = mask[1] & (mode[1] == creg[1])
130 n2 = mask[2] & (mode[2] == creg[2])
131 n3 = mask[3] & (mode[3] == creg[3])
132 result = n0|n1|n2|n3 if M else n0&n1&n2&n3
133 RT[63] = result # MSB0 numbering, 63 is LSB
134 If Rc:
135 CR0 = analyse(RT)
136
137 This is a [[openpower/sv/normal]] SVP64 type operation and as
138 such can use Rc=1 and RC1 Data-dependent Mode capability
139
140 **mtcrweird**
141
142 bit 11=1, bit 19=0
143
144 mtcrweird: BT, RA, mask.mode
145
146 reg = (RA|0)
147 lsb = reg[63] # MSB0 numbering
148 n0 = mask[0] & (mode[0] == lsb)
149 n1 = mask[1] & (mode[1] == lsb)
150 n2 = mask[2] & (mode[2] == lsb)
151 n3 = mask[3] & (mode[3] == lsb)
152 CR{BT} = n0 || n1 || n2 || n3
153
154 This is a [[openpower/sv/cr_ops]] SVP64 type operation that has
155 3-bit Data-dependent and 3-bit Predicate-result capability
156 (BT is 3 bits)
157
158 **crweird**
159
160 bit 11=0, bit 19=1
161
162 crweird: BT, BB, mask.mode
163
164 creg = CR{BB}
165 n0 = mask[0] & (mode[0] == creg[0])
166 n1 = mask[1] & (mode[1] == creg[1])
167 n2 = mask[2] & (mode[2] == creg[2])
168 n3 = mask[3] & (mode[3] == creg[3])
169 CR{BT} = n0 || n1 || n2 || n3
170
171 This is a [[openpower/sv/cr_ops]] SVP64 type operation that has
172 3-bit Data-dependent and 3-bit Predicate-result capability
173 (BT is 3 bits)
174
175 **crweirder**
176
177 bit 11=1, bit 19=1
178
179 crweirder: BFT, BB, mask.mode
180
181 creg = CR{BB}
182 n0 = mask[0] & (mode[0] == creg[0])
183 n1 = mask[1] & (mode[1] == creg[1])
184 n2 = mask[2] & (mode[2] == creg[2])
185 n3 = mask[3] & (mode[3] == creg[3])
186 BF = BFT[2:4] # select CR
187 bit = BFT[0:1] # select bit of CR
188 result = n0|n1|n2|n3 if M else n0&n1&n2&n3
189 CR{BF}[bit] = result
190
191 This is a [[openpower/sv/cr_ops]] SVP64 type operation that has
192 5-bit Data-dependent and 5-bit Predicate-result capability
193 (BFT is 5 bits)
194
195 **Example Pseudo-ops:**
196
197 mtcri BB, mode mtcrweird r0, BB, 0b1111.~mode
198 mtcrset BB, mask mtcrweird r0, BB, mask.0b0000
199 mtcrclr BB, mask mtcrweird r0, BB, mask.0b1111
200
201 # Vectorised versions
202
203 The name "weird" refers to a minor violation of SV rules when it comes to deriving the Vectorised versions of these instructions.
204
205 Normally the progression of the SV for-loop would move on to the next register.
206 Instead however in the scalar case these instructions **remain in the same register** and insert or transfer between **bits** of the scalar integer source or destination.
207
208 crrweird: RT, BB, mask.mode
209
210 for i in range(VL):
211 if BB.isvec:
212 creg = CR{BB+i}
213 else:
214 creg = CR{BB}
215 n0 = mask[0] & (mode[0] == creg[0])
216 n1 = mask[1] & (mode[1] == creg[1])
217 n2 = mask[2] & (mode[2] == creg[2])
218 n3 = mask[3] & (mode[3] == creg[3])
219 # OR or AND to a single bit
220 result = n0|n1|n2|n3 if M else n0&n1&n2&n3
221 if RT.isvec:
222 # TODO: RT.elwidth override to be also added here
223 # note, yes, really, the CR's elwidth field determines
224 # the bit-packing into the INT!
225 if BB.elwidth == 0b00:
226 # pack 1 result into 64-bit registers
227 iregs[RT+i][0..62] = 0
228 iregs[RT+i][63] = result # sets LSB to result
229 if BB.elwidth == 0b01:
230 # pack 2 results sequentially into INT registers
231 iregs[RT+i//2][0..61] = 0
232 iregs[RT+i//2][63-(i%2)] = result
233 if BB.elwidth == 0b10:
234 # pack 4 results sequentially into INT registers
235 iregs[RT+i//4][0..59] = 0
236 iregs[RT+i//4][63-(i%4)] = result
237 if BB.elwidth == 0b11:
238 # pack 8 results sequentially into INT registers
239 iregs[RT+i//8][0..55] = 0
240 iregs[RT+i//8][63-(i%8)] = result
241 else:
242 iregs[RT][63-i] = result # results also in scalar INT
243
244 Note that:
245
246 * in the scalar case the CR-Vector assessment
247 is stored bit-wise starting at the LSB of the
248 destination scalar INT
249 * in the INT-vector case the result is stored in the
250 LSB of each element in the result vector
251
252 Note that element width overrides are respected on the INT src or destination register, however that it is the CR element-width
253 override that is used to indicate how many bits of CR results
254 are packed/extracted into/from each INT register
255
256 # v3.1 setbc instructions
257
258 there are additional setb conditional instructions in v3.1 (p129)
259
260 RT = (CR[BI] == 1) ? 1 : 0
261
262 which also negate that, and also return -1 / 0. these are similar to crweird but not the same purpose. most notable is that crweird acts on CR fields rather than the entire 32 bit CR.
263
264 # Predication Examples
265
266 Take the following example:
267
268 r10 = 0b00010
269 sv.mtcrweird/dm=r10/dz cr8.v, 0, 0b0011.0000
270
271 Here, RA is zero, so the source input is zero. The destination
272 is CR Field 8, and the destination predicate mask indicates
273 to target the first two elements. Destination predicate zeroing is
274 enabled, and the destination predicate is only set in the 2nd bit.
275 mask is 0b0011, mode is all zeros.
276
277 Let us first consider what should go into element 0 (CR Field 8):
278
279 * The destination predicate bit is zero, and zeroing is enabled.
280 * Therefore, what is in the source is irrelevant: the result must
281 be zero.
282 * Therefore all four bits of CR Field 8 are therefore set to zero.
283
284 Now the second element, CR Field 9 (CR9):
285
286 * Bit 2 of the destination predicate, r10, is 1. Therefore the computation
287 of the result is relevant.
288 * RA is zero therefore bit 2 is zero. mask is 0b0011 and mode is 0b0000
289 * When calculating n0 thru n3 we get n0=1, n1=2, n2=0, n3=0
290 * Therefore, CR9 is set (using LSB0 ordering) to 0b0011, i.e. to mask.
291
292 It should be clear that this instruction uses bits of the integer
293 predicate to decide whether to set CR Fields to `(mask & ~mode)`
294 or to zero. Thus, in effect, it is the integer predicate that has
295 been copied into the CR Fields.
296
297 By using twin predication, zeroing, and inversion (sm=~r3, dm=r10) for example, it becomes possible to combine two Integers together in
298 order to set bits in CR Fields.
299 Likewise there are dozens of ways that CR Predicates can be used, on the
300 same sv.mtcrweird instruction.