(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 |
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 |
115 | 19 | RA | 1 | mask | BT | 0 / | XO[0:4] | 0 mode | / |
116 | 19 | BT // | 0 | mask | BB | 1 / | XO[0:4] | 0 mode | / |
117 | 19 | BFT | 1 | mask | BB | 1 M | XO[0:4] | 0 mode | / |
118
119 mode is encoded in XO and is 4 bits
120
121 bit 11=0, bit 19=0
122
123 crrweird: RT, BB, mask.mode
124
125 creg = CR{BB}
126 n0 = mask[0] & (mode[0] == creg[0])
127 n1 = mask[1] & (mode[1] == creg[1])
128 n2 = mask[2] & (mode[2] == creg[2])
129 n3 = mask[3] & (mode[3] == creg[3])
130 result = n0|n1|n2|n3 if M else n0&n1&n2&n3
131 RT[63] = result # MSB0 numbering, 63 is LSB
132 If Rc:
133 CR1 = analyse(RT)
134
135 bit 11=1, bit 19=0
136
137 mtcrweird: BT, RA, mask.mode
138
139 reg = (RA|0)
140 lsb = reg[63] # MSB0 numbering
141 n0 = mask[0] & (mode[0] == lsb)
142 n1 = mask[1] & (mode[1] == lsb)
143 n2 = mask[2] & (mode[2] == lsb)
144 n3 = mask[3] & (mode[3] == lsb)
145 CR{BT} = n0 || n1 || n2 || n3
146
147 bit 11=0, bit 19=1
148
149 crweird: BT, BB, mask.mode
150
151 creg = CR{BB}
152 n0 = mask[0] & (mode[0] == creg[0])
153 n1 = mask[1] & (mode[1] == creg[1])
154 n2 = mask[2] & (mode[2] == creg[2])
155 n3 = mask[3] & (mode[3] == creg[3])
156 CR{BT} = n0 || n1 || n2 || n3
157
158 bit 11=1, bit 19=1
159
160 crweirder: BFT, BB, mask.mode
161
162 creg = CR{BB}
163 n0 = mask[0] & (mode[0] == creg[0])
164 n1 = mask[1] & (mode[1] == creg[1])
165 n2 = mask[2] & (mode[2] == creg[2])
166 n3 = mask[3] & (mode[3] == creg[3])
167 BF = BFT[2:4] # select CR
168 bit = BFT[0:1] # select bit of CR
169 result = n0|n1|n2|n3 if M else n0&n1&n2&n3
170 CR{BF}[bit] = result
171
172 Pseudo-op:
173
174 mtcri BB, mode mtcrweird r0, BB, 0b1111.~mode
175 mtcrset BB, mask mtcrweird r0, BB, mask.0b0000
176 mtcrclr BB, mask mtcrweird r0, BB, mask.0b1111
177
178 # Vectorised versions
179
180 The name "weird" refers to a minor violation of SV rules when it comes to deriving the Vectorised versions of these instructions.
181
182 Normally the progression of the SV for-loop would move on to the next register.
183 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.
184
185 crrweird: RT, BB, mask.mode
186
187 for i in range(VL):
188 if BB.isvec:
189 creg = CR{BB+i}
190 else:
191 creg = CR{BB}
192 n0 = mask[0] & (mode[0] == creg[0])
193 n1 = mask[1] & (mode[1] == creg[1])
194 n2 = mask[2] & (mode[2] == creg[2])
195 n3 = mask[3] & (mode[3] == creg[3])
196 # OR or AND to a single bit
197 result = n0|n1|n2|n3 if M else n0&n1&n2&n3
198 if RT.isvec:
199 # TODO: RT.elwidth override to be also added here
200 # note, yes, really, the CR's elwidth field determines
201 # the bit-packing into the INT!
202 if BB.elwidth == 0b00:
203 # pack 1 result into 64-bit registers
204 iregs[RT+i][0..62] = 0
205 iregs[RT+i][63] = result # sets LSB to result
206 if BB.elwidth == 0b01:
207 # pack 2 results sequentially into INT registers
208 iregs[RT+i//2][0..61] = 0
209 iregs[RT+i//2][63-(i%2)] = result
210 if BB.elwidth == 0b10:
211 # pack 4 results sequentially into INT registers
212 iregs[RT+i//4][0..59] = 0
213 iregs[RT+i//4][63-(i%4)] = result
214 if BB.elwidth == 0b11:
215 # pack 8 results sequentially into INT registers
216 iregs[RT+i//8][0..55] = 0
217 iregs[RT+i//8][63-(i%8)] = result
218 else:
219 iregs[RT][63-i] = result # results also in scalar INT
220
221 Note that:
222
223 * in the scalar case the CR-Vector assessment
224 is stored bit-wise starting at the LSB of the
225 destination scalar INT
226 * in the INT-vector case the result is stored in the
227 LSB of each element in the result vector
228
229 Note that element width overrides are respected on the INT src or destination register, however that it is the CR element-width
230 override that is used to indicate how many bits of CR results
231 are packed/extracted into/from each INT register
232
233 # v3.1 setbc instructions
234
235 there are additional setb conditional instructions in v3.1 (p129)
236
237 RT = (CR[BI] == 1) ? 1 : 0
238
239 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.
240
241 # Predication Examples
242
243 Take the following example:
244
245 r10 = 0b00010
246 sv.mtcrweird/dm=r10/dz cr8.v, 0, 0b0011.0000
247
248 Here, RA is zero, so the source input is zero. The destination
249 is CR Field 8, and the destination predicate mask indicates
250 to target the first two elements. Destination predicate zeroing is
251 enabled, and the destination predicate is only set in the 2nd bit.
252 mask is 0b0011, mode is all zeros.
253
254 Let us first consider what should go into element 0 (CR Field 8):
255
256 * The destination predicate bit is zero, and zeroing is enabled.
257 * Therefore, what is in the source is irrelevant: the result must
258 be zero.
259 * Therefore all four bits of CR Field 8 are therefore set to zero.
260
261 Now the second element, CR Field 9 (CR9):
262
263 * Bit 2 of the destination predicate, r10, is 1. Therefore the computation
264 of the result is relevant.
265 * RA is zero therefore bit 2 is zero. mask is 0b0011 and mode is 0b0000
266 * When calculating n0 thru n3 we get n0=1, n1=2, n2=0, n3=0
267 * Therefore, CR9 is set (using LSB0 ordering) to 0b0011, i.e. to mask.
268
269 It should be clear that this instruction uses bits of the integer
270 predicate to decide whether to set CR Fields to `(mask & ~mode)`
271 or to zero. Thus, in effect, it is the integer predicate that has
272 been copied into the CR Fields.
273
274 By using twin predication, zeroing, and inversion (sm=~r3, dm=r10) for example, it becomes possible to combine two Integers together in
275 order to set bits in CR Fields.
276 Likewise there are dozens of ways that CR Predicates can be used, on the
277 same sv.mtcrweird instruction.