add link to STATE discussion
[libreriscv.git] / simple_v_extension / specification.mdwn
1 # Simple-V (Parallelism Extension Proposal) Specification
2
3 * Copyright (C) 2017, 2018, 2019 Luke Kenneth Casson Leighton
4 * Status: DRAFTv0.6
5 * Last edited: 21 jun 2019
6 * Ancillary resource: [[opcodes]]
7 * Ancillary resource: [[sv_prefix_proposal]]
8 * Ancillary resource: [[abridged_spec]]
9 * Ancillary resource: [[vblock_format]]
10 * Ancillary resource: [[appendix]]
11
12 With thanks to:
13
14 * Allen Baum
15 * Bruce Hoult
16 * comp.arch
17 * Jacob Bachmeyer
18 * Guy Lemurieux
19 * Jacob Lifshay
20 * Terje Mathisen
21 * The RISC-V Founders, without whom this all would not be possible.
22
23 [[!toc ]]
24
25 # Summary and Background: Rationale
26
27 Simple-V is a uniform parallelism API for RISC-V hardware that has several
28 unplanned side-effects including code-size reduction, expansion of
29 HINT space and more. The reason for
30 creating it is to provide a manageable way to turn a pre-existing design
31 into a parallel one, in a step-by-step incremental fashion, without adding any new opcodes, thus allowing
32 the implementor to focus on adding hardware where it is needed and necessary.
33 The primary target is for mobile-class 3D GPUs and VPUs, with secondary
34 goals being to reduce executable size (by extending the effectiveness of RV opcodes, RVC in particular) and reduce context-switch latency.
35
36 Critically: **No new instructions are added**. The parallelism (if any
37 is implemented) is implicitly added by tagging *standard* scalar registers
38 for redirection. When such a tagged register is used in any instruction,
39 it indicates that the PC shall **not** be incremented; instead a loop
40 is activated where *multiple* instructions are issued to the pipeline
41 (as determined by a length CSR), with contiguously incrementing register
42 numbers starting from the tagged register. When the last "element"
43 has been reached, only then is the PC permitted to move on. Thus
44 Simple-V effectively sits (slots) *in between* the instruction decode phase
45 and the ALU(s).
46
47 The barrier to entry with SV is therefore very low. The minimum
48 compliant implementation is software-emulation (traps), requiring
49 only the CSRs and CSR tables, and that an exception be thrown if an
50 instruction's registers are detected to have been tagged. The looping
51 that would otherwise be done in hardware is thus carried out in software,
52 instead. Whilst much slower, it is "compliant" with the SV specification,
53 and may be suited for implementation in RV32E and also in situations
54 where the implementor wishes to focus on certain aspects of SV, without
55 unnecessary time and resources into the silicon, whilst also conforming
56 strictly with the API. A good area to punt to software would be the
57 polymorphic element width capability for example.
58
59 Hardware Parallelism, if any, is therefore added at the implementor's
60 discretion to turn what would otherwise be a sequential loop into a
61 parallel one.
62
63 To emphasise that clearly: Simple-V (SV) is *not*:
64
65 * A SIMD system
66 * A SIMT system
67 * A Vectorisation Microarchitecture
68 * A microarchitecture of any specific kind
69 * A mandary parallel processor microarchitecture of any kind
70 * A supercomputer extension
71
72 SV does **not** tell implementors how or even if they should implement
73 parallelism: it is a hardware "API" (Application Programming Interface)
74 that, if implemented, presents a uniform and consistent way to *express*
75 parallelism, at the same time leaving the choice of if, how, how much,
76 when and whether to parallelise operations **entirely to the implementor**.
77
78 # Basic Operation
79
80 The principle of SV is as follows:
81
82 * Standard RV instructions are "prefixed" (extended) through a 48/64
83 bit format (single instruction option) or a variable
84 length VLIW-like prefix (multi or "grouped" option).
85 * The prefix(es) indicate which registers are "tagged" as
86 "vectorised". Predicates can also be added, and element widths
87 overridden on any src or dest register.
88 * A "Vector Length" CSR is set, indicating the span of any future
89 "parallel" operations.
90 * If any operation (a **scalar** standard RV opcode) uses a register
91 that has been so "marked" ("tagged"), a hardware "macro-unrolling loop"
92 is activated, of length VL, that effectively issues **multiple**
93 identical instructions using contiguous sequentially-incrementing
94 register numbers, based on the "tags".
95 * **Whether they be executed sequentially or in parallel or a
96 mixture of both or punted to software-emulation in a trap handler
97 is entirely up to the implementor**.
98
99 In this way an entire scalar algorithm may be vectorised with
100 the minimum of modification to the hardware and to compiler toolchains.
101
102 To reiterate: **There are *no* new opcodes**. The scheme works *entirely*
103 on hidden context that augments *scalar* RISCV instructions.
104
105 # CSRs <a name="csrs"></a>
106
107 * An optional "reshaping" CSR key-value table which remaps from a 1D
108 linear shape to 2D or 3D, including full transposition.
109
110 There are five additional CSRs, available in any privilege level:
111
112 * MVL (the Maximum Vector Length)
113 * VL (which has different characteristics from standard CSRs)
114 * SUBVL (effectively a kind of SIMD)
115 * STATE (containing copies of MVL, VL and SUBVL as well as context information)
116 * PCVBLK (the current operation being executed within a VBLOCK Group)
117
118 For User Mode there are the following CSRs:
119
120 * uePCVBLK (a copy of the sub-execution Program Counter, that is relative
121 to the start of the current VBLOCK Group, set on a trap).
122 * ueSTATE (useful for saving and restoring during context switch,
123 and for providing fast transitions)
124
125 There are also two additional CSRs for Supervisor-Mode:
126
127 * sePCVBLK
128 * seSTATE
129
130 And likewise for M-Mode:
131
132 * mePCVBLK
133 * meSTATE
134
135 The u/m/s CSRs are treated and handled exactly like their (x)epc
136 equivalents. On entry to or exit from a privilege level, the contents of its (x)eSTATE are swapped with STATE.
137
138 Thus for example, a User Mode trap will end up swapping STATE and ueSTATE
139 (on both entry and exit), allowing User Mode traps to have their own
140 Vectorisation Context set up, separated from and unaffected by normal
141 user applications. If an M Mode trap occurs in the middle of the U Mode trap, STATE is swapped with meSTATE, and restored on exit: the U Mode trap continues unaware that the M Mode trap even occurred.
142
143 Likewise, Supervisor Mode may perform context-switches, safe in the
144 knowledge that its Vectorisation State is unaffected by User Mode.
145
146 The access pattern for these groups of CSRs in each mode follows the
147 same pattern for other CSRs that have M-Mode and S-Mode "mirrors":
148
149 * In M-Mode, the S-Mode and U-Mode CSRs are separate and distinct.
150 * In S-Mode, accessing and changing of the M-Mode CSRs is transparently
151 identical
152 to changing the S-Mode CSRs. Accessing and changing the U-Mode
153 CSRs is permitted.
154 * In U-Mode, accessing and changing of the S-Mode and U-Mode CSRs
155 is prohibited.
156
157 An interesting side effect of SV STATE being
158 separate and distinct in S Mode
159 is that
160 Vectorised saving of an entire register file to the stack is a single
161 instruction (through accidental provision of LOAD-MULTI semantics). If the
162 SVPrefix P64-LD-type format is used, LOAD-MULTI may even be done with a
163 single standalone 64 bit opcode (P64 may set up SUBVL, VL and MVL from an
164 immediate field, to cover the full regfile). It can even be predicated, which opens up some very
165 interesting possibilities.
166
167 (x)EPCVBLK CSRs must be treated exactly like their corresponding (x)epc
168 equivalents. See VBLOCK section for details.
169
170 ## MAXVECTORLENGTH (MVL) <a name="mvl" />
171
172 MAXVECTORLENGTH is the same concept as MVL in RVV, except that it
173 is variable length and may be dynamically set. MVL is
174 however limited to the regfile bitwidth XLEN (1-32 for RV32,
175 1-64 for RV64 and so on).
176
177 The reason for setting this limit is so that predication registers, when
178 marked as such, may fit into a single register as opposed to fanning
179 out over several registers. This keeps the hardware implementation a
180 little simpler.
181
182 The other important factor to note is that the actual MVL is internally
183 stored **offset by one**, so that it can fit into only 6 bits (for RV64)
184 and still cover a range up to XLEN bits. Attempts to set MVL to zero will
185 return an exception. This is expressed more clearly in the "pseudocode"
186 section, where there are subtle differences between CSRRW and CSRRWI.
187
188 ## Vector Length (VL) <a name="vl" />
189
190 VSETVL is slightly different from RVV. Similar to RVV, VL is set to be within
191 the range 1 <= VL <= MVL (where MVL in turn is limited to 1 <= MVL <= XLEN)
192
193 VL = rd = MIN(vlen, MVL)
194
195 where 1 <= MVL <= XLEN
196
197 However just like MVL it is important to note that the range for VL has
198 subtle design implications, covered in the "CSR pseudocode" section
199
200 The fixed (specific) setting of VL allows vector LOAD/STORE to be used
201 to switch the entire bank of registers using a single instruction (see
202 Appendix, "Context Switch Example"). The reason for limiting VL to XLEN
203 is down to the fact that predication bits fit into a single register of
204 length XLEN bits.
205
206 The second and most important change is that, within the limits set by
207 MVL, the value passed in **must** be set in VL (and in the
208 destination register).
209
210 This has implication for the microarchitecture, as VL is required to be
211 set (limits from MVL notwithstanding) to the actual value
212 requested. RVV has the option to set VL to an arbitrary value that suits
213 the conditions and the micro-architecture: SV does *not* permit this.
214
215 The reason is so that if SV is to be used for a context-switch or as a
216 substitute for LOAD/STORE-Multiple, the operation can be done with only
217 2-3 instructions (setup of the CSRs, VSETVL x0, x0, #{regfilelen-1},
218 single LD/ST operation). If VL does *not* get set to the register file
219 length when VSETVL is called, then a software-loop would be needed.
220 To avoid this need, VL *must* be set to exactly what is requested
221 (limits notwithstanding).
222
223 Therefore, in turn, unlike RVV, implementors *must* provide
224 pseudo-parallelism (using sequential loops in hardware) if actual
225 hardware-parallelism in the ALUs is not deployed. A hybrid is also
226 permitted (as used in Broadcom's VideoCore-IV) however this must be
227 *entirely* transparent to the ISA.
228
229 The third change is that VSETVL is implemented as a CSR, where the
230 behaviour of CSRRW (and CSRRWI) must be changed to specifically store
231 the *new* value in the destination register, **not** the old value.
232 Where context-load/save is to be implemented in the usual fashion
233 by using a single CSRRW instruction to obtain the old value, the
234 *secondary* CSR must be used (STATE). This CSR by contrast behaves
235 exactly as standard CSRs, and contains more than just VL.
236
237 One interesting side-effect of using CSRRWI to set VL is that this
238 may be done with a single instruction, useful particularly for a
239 context-load/save. There are however limitations: CSRWI's immediate
240 is limited to 0-31 (representing VL=1-32).
241
242 Note that when VL is set to 1, vector operations cease (but not subvector
243 operations: that requires setting SUBVL=1) the hardware loop is reduced
244 to a single element: scalar operations. This is in effect the default,
245 normal operating mode. However it is important to appreciate that this
246 does **not** result in the Register table or SUBVL being disabled. Only
247 when the Register table is empty (P48/64 prefix fields notwithstanding)
248 would SV have no effect.
249
250 ## SUBVL - Sub Vector Length
251
252 This is a "group by quantity" that effectively asks each iteration
253 of the hardware loop to load SUBVL elements of width elwidth at a
254 time. Effectively, SUBVL is like a SIMD multiplier: instead of just 1
255 operation issued, SUBVL operations are issued.
256
257 Another way to view SUBVL is that each element in the VL length vector is
258 now SUBVL times elwidth bits in length and now comprises SUBVL discrete
259 sub operations. An inner SUBVL for-loop within a VL for-loop in effect,
260 with the sub-element increased every time in the innermost loop. This
261 is best illustrated in the (simplified) pseudocode example, in the
262 [[appendix]].
263
264 The primary use case for SUBVL is for 3D FP Vectors. A Vector of 3D
265 coordinates X,Y,Z for example may be loaded and multiplied then stored, per
266 VL element iteration, rather than having to set VL to three times larger.
267
268 Setting this CSR to 0 must raise an exception. Setting it to a value
269 greater than 4 likewise. To see the relationship with STATE, see below.
270
271 The main effect of SUBVL is that predication bits are applied per
272 **group**, rather than by individual element.
273
274 This saves a not insignificant number of instructions when handling 3D
275 vectors, as otherwise a much longer predicate mask would have to be set
276 up with regularly-repeated bit patterns.
277
278 See SUBVL Pseudocode illustration in the [[appendix]], for details.
279
280 ## STATE
281
282 out of date, see http://lists.libre-riscv.org/pipermail/libre-riscv-dev/2019-June/001896.html
283
284 This is a standard CSR that contains sufficient information for a
285 full context save/restore. It contains (and permits setting of):
286
287 * MVL
288 * VL
289 * destoffs - the destination element offset of the current parallel
290 instruction being executed
291 * srcoffs - for twin-predication, the source element offset as well.
292 * SUBVL
293 * svdestoffs - the subvector destination element offset of the current
294 parallel instruction being executed
295 * svsrcoffs - for twin-predication, the subvector source element offset
296 as well.
297
298 Interestingly STATE may hypothetically also be modified to make the
299 immediately-following instruction to skip a certain number of elements,
300 by playing with destoffs and srcoffs (and the subvector offsets as well)
301
302 Setting destoffs and srcoffs is realistically intended for saving state
303 so that exceptions (page faults in particular) may be serviced and the
304 hardware-loop that was being executed at the time of the trap, from
305 user-mode (or Supervisor-mode), may be returned to and continued from
306 exactly where it left off. The reason why this works is because setting
307 User-Mode STATE will not change (not be used) in M-Mode or S-Mode (and
308 is entirely why M-Mode and S-Mode have their own STATE CSRs, meSTATE
309 and seSTATE).
310
311 The format of the STATE CSR is as follows:
312
313 | (29..28 | (27..26) | (25..24) | (23..18) | (17..12) | (11..6) | (5...0) |
314 | ------- | -------- | -------- | -------- | -------- | ------- | ------- |
315 | dsvoffs | ssvoffs | subvl | destoffs | srcoffs | vl | maxvl |
316
317 The relationship between SUBVL and the subvl field is:
318
319 | SUBVL | (25..24) |
320 | ----- | -------- |
321 | 1 | 0b00 |
322 | 2 | 0b01 |
323 | 3 | 0b10 |
324 | 4 | 0b11 |
325
326 When setting this CSR, the following characteristics will be enforced:
327
328 * **MAXVL** will be truncated (after offset) to be within the range 1 to XLEN
329 * **VL** will be truncated (after offset) to be within the range 1 to MAXVL
330 * **SUBVL** which sets a SIMD-like quantity, has only 4 values so there
331 are no changes needed
332 * **srcoffs** will be truncated to be within the range 0 to VL-1
333 * **destoffs** will be truncated to be within the range 0 to VL-1
334 * **ssvoffs** will be truncated to be within the range 0 to SUBVL-1
335 * **dsvoffs** will be truncated to be within the range 0 to SUBVL-1
336
337 NOTE: if the following instruction is not a twin predicated instruction,
338 and destoffs or dsvoffs has been set to non-zero, subsequent execution
339 behaviour is undefined. **USE WITH CARE**.
340
341 ### Hardware rules for when to increment STATE offsets
342
343 The offsets inside STATE are like the indices in a loop, except
344 in hardware. They are also partially (conceptually) similar to a
345 "sub-execution Program Counter". As such, and to allow proper context
346 switching and to define correct exception behaviour, the following rules
347 must be observed:
348
349 * When the VL CSR is set, srcoffs and destoffs are reset to zero.
350 * Each instruction that contains a "tagged" register shall start
351 execution at the *current* value of srcoffs (and destoffs in the case
352 of twin predication)
353 * Unpredicated bits (in nonzeroing mode) shall cause the element operation
354 to skip, incrementing the srcoffs (or destoffs)
355 * On execution of an element operation, Exceptions shall **NOT** cause
356 srcoffs or destoffs to increment.
357 * On completion of the full Vector Loop (srcoffs = VL-1 or destoffs =
358 VL-1 after the last element is executed), both srcoffs and destoffs
359 shall be reset to zero.
360
361 This latter is why srcoffs and destoffs may be stored as values from
362 0 to XLEN-1 in the STATE CSR, because as loop indices they refer to
363 elements. srcoffs and destoffs never need to be set to VL: their maximum
364 operating values are limited to 0 to VL-1.
365
366 The same corresponding rules apply to SUBVL, svsrcoffs and svdestoffs.
367
368 ## MVL and VL Pseudocode
369
370 The pseudo-code for get and set of VL and MVL use the following internal
371 functions as follows:
372
373 set_mvl_csr(value, rd):
374 regs[rd] = STATE.MVL
375 STATE.MVL = MIN(value, STATE.MVL)
376
377 get_mvl_csr(rd):
378 regs[rd] = STATE.VL
379
380 set_vl_csr(value, rd):
381 STATE.VL = MIN(value, STATE.MVL)
382 regs[rd] = STATE.VL # yes returning the new value NOT the old CSR
383 return STATE.VL
384
385 get_vl_csr(rd):
386 regs[rd] = STATE.VL
387 return STATE.VL
388
389 Note that where setting MVL behaves as a normal CSR (returns the old
390 value), unlike standard CSR behaviour, setting VL will return the **new**
391 value of VL **not** the old one.
392
393 For CSRRWI, the range of the immediate is restricted to 5 bits. In order to
394 maximise the effectiveness, an immediate of 0 is used to set VL=1,
395 an immediate of 1 is used to set VL=2 and so on:
396
397 CSRRWI_Set_MVL(value):
398 set_mvl_csr(value+1, x0)
399
400 CSRRWI_Set_VL(value):
401 set_vl_csr(value+1, x0)
402
403 However for CSRRW the following pseudocode is used for MVL and VL,
404 where setting the value to zero will cause an exception to be raised.
405 The reason is that if VL or MVL are set to zero, the STATE CSR is
406 not capable of storing that value.
407
408 CSRRW_Set_MVL(rs1, rd):
409 value = regs[rs1]
410 if value == 0 or value > XLEN:
411 raise Exception
412 set_mvl_csr(value, rd)
413
414 CSRRW_Set_VL(rs1, rd):
415 value = regs[rs1]
416 if value == 0 or value > XLEN:
417 raise Exception
418 set_vl_csr(value, rd)
419
420 In this way, when CSRRW is utilised with a loop variable, the value
421 that goes into VL (and into the destination register) may be used
422 in an instruction-minimal fashion:
423
424 CSRvect1 = {type: F, key: a3, val: a3, elwidth: dflt}
425 CSRvect2 = {type: F, key: a7, val: a7, elwidth: dflt}
426 CSRRWI MVL, 3 # sets MVL == **4** (not 3)
427 j zerotest # in case loop counter a0 already 0
428 loop:
429 CSRRW VL, t0, a0 # vl = t0 = min(mvl, a0)
430 ld a3, a1 # load 4 registers a3-6 from x
431 slli t1, t0, 3 # t1 = vl * 8 (in bytes)
432 ld a7, a2 # load 4 registers a7-10 from y
433 add a1, a1, t1 # increment pointer to x by vl*8
434 fmadd a7, a3, fa0, a7 # v1 += v0 * fa0 (y = a * x + y)
435 sub a0, a0, t0 # n -= vl (t0)
436 st a7, a2 # store 4 registers a7-10 to y
437 add a2, a2, t1 # increment pointer to y by vl*8
438 zerotest:
439 bnez a0, loop # repeat if n != 0
440
441 With the STATE CSR, just like with CSRRWI, in order to maximise the
442 utilisation of the limited bitspace, "000000" in binary represents
443 VL==1, "00001" represents VL==2 and so on (likewise for MVL):
444
445 CSRRW_Set_SV_STATE(rs1, rd):
446 value = regs[rs1]
447 get_state_csr(rd)
448 STATE.MVL = set_mvl_csr(value[11:6]+1)
449 STATE.VL = set_vl_csr(value[5:0]+1)
450 STATE.destoffs = value[23:18]>>18
451 STATE.srcoffs = value[23:18]>>12
452
453 get_state_csr(rd):
454 regs[rd] = (STATE.MVL-1) | (STATE.VL-1)<<6 | (STATE.srcoffs)<<12 |
455 (STATE.destoffs)<<18
456 return regs[rd]
457
458 In both cases, whilst CSR read of VL and MVL return the exact values
459 of VL and MVL respectively, reading and writing the STATE CSR returns
460 those values **minus one**. This is absolutely critical to implement
461 if the STATE CSR is to be used for fast context-switching.
462
463 ## VL, MVL and SUBVL instruction aliases
464
465 This table contains pseudo-assembly instruction aliases. Note the
466 subtraction of 1 from the CSRRWI pseudo variants, to compensate for the
467 reduced range of the 5 bit immediate.
468
469 | alias | CSR |
470 | - | - |
471 | SETVL rd, rs | CSRRW VL, rd, rs |
472 | SETVLi rd, #n | CSRRWI VL, rd, #n-1 |
473 | GETVL rd | CSRRW VL, rd, x0 |
474 | SETMVL rd, rs | CSRRW MVL, rd, rs |
475 | SETMVLi rd, #n | CSRRWI MVL,rd, #n-1 |
476 | GETMVL rd | CSRRW MVL, rd, x0 |
477
478 Note: CSRRC and other bitsetting may still be used, they are however not particularly useful (very obscure).
479
480 ## Register key-value (CAM) table <a name="regcsrtable" />
481
482 *NOTE: in prior versions of SV, this table used to be writable and
483 accessible via CSRs. It is now stored in the VBLOCK instruction format. Note
484 that this table does *not* get applied to the SVPrefix P48/64 format,
485 only to scalar opcodes*
486
487 The purpose of the Register table is three-fold:
488
489 * To mark integer and floating-point registers as requiring "redirection"
490 if it is ever used as a source or destination in any given operation.
491 This involves a level of indirection through a 5-to-7-bit lookup table,
492 such that **unmodified** operands with 5 bits (3 for some RVC ops) may
493 access up to **128** registers.
494 * To indicate whether, after redirection through the lookup table, the
495 register is a vector (or remains a scalar).
496 * To over-ride the implicit or explicit bitwidth that the operation would
497 normally give the register.
498
499 Note: clearly, if an RVC operation uses a 3 bit spec'd register (x8-x15)
500 and the Register table contains entried that only refer to registerd
501 x1-x14 or x16-x31, such operations will *never* activate the VL hardware
502 loop!
503
504 If however the (16 bit) Register table does contain such an entry (x8-x15
505 or x2 in the case of LWSP), that src or dest reg may be redirected
506 anywhere to the *full* 128 register range. Thus, RVC becomes far more
507 powerful and has many more opportunities to reduce code size that in
508 Standard RV32/RV64 executables.
509
510 [[!inline raw="yes" pages="simple_v_extension/reg_table_format" ]]
511
512 i/f is set to "1" to indicate that the redirection/tag entry is to
513 be applied to integer registers; 0 indicates that it is relevant to
514 floating-point registers.
515
516 The 8 bit format is used for a much more compact expression. "isvec"
517 is implicit and, similar to [[sv_prefix_proposal]], the target vector
518 is "regnum<<2", implicitly. Contrast this with the 16-bit format where
519 the target vector is *explicitly* named in bits 8 to 14, and bit 15 may
520 optionally set "scalar" mode.
521
522 Note that whilst SVPrefix adds one extra bit to each of rd, rs1 etc.,
523 and thus the "vector" mode need only shift the (6 bit) regnum by 1 to
524 get the actual (7 bit) register number to use, there is not enough space
525 in the 8 bit format (only 5 bits for regnum) so "regnum<<2" is required.
526
527 vew has the following meanings, indicating that the instruction's
528 operand size is "over-ridden" in a polymorphic fashion:
529
530 | vew | bitwidth |
531 | --- | ------------------- |
532 | 00 | default (XLEN/FLEN) |
533 | 01 | 8 bit |
534 | 10 | 16 bit |
535 | 11 | 32 bit |
536
537 As the above table is a CAM (key-value store) it may be appropriate
538 (faster, implementation-wise) to expand it as follows:
539
540 [[!inline raw="yes" pages="simple_v_extension/reg_table" ]]
541
542 ## Predication Table <a name="predication_csr_table"></a>
543
544 *NOTE: in prior versions of SV, this table used to be writable and
545 accessible via CSRs. It is now stored in the VBLOCK instruction format.
546 The table does **not** apply to SVPrefix opcodes*
547
548 The Predication Table is a key-value store indicating whether, if a
549 given destination register (integer or floating-point) is referred to
550 in an instruction, it is to be predicated. Like the Register table, it
551 is an indirect lookup that allows the RV opcodes to not need modification.
552
553 It is particularly important to note
554 that the *actual* register used can be *different* from the one that is
555 in the instruction, due to the redirection through the lookup table.
556
557 * regidx is the register that in combination with the
558 i/f flag, if that integer or floating-point register is referred to in a
559 (standard RV) instruction results in the lookup table being referenced
560 to find the predication mask to use for this operation.
561 * predidx is the *actual* (full, 7 bit) register to be used for the
562 predication mask.
563 * inv indicates that the predication mask bits are to be inverted
564 prior to use *without* actually modifying the contents of the
565 register from which those bits originated.
566 * zeroing is either 1 or 0, and if set to 1, the operation must
567 place zeros in any element position where the predication mask is
568 set to zero. If zeroing is set to 0, unpredicated elements *must*
569 be left alone. Some microarchitectures may choose to interpret
570 this as skipping the operation entirely. Others which wish to
571 stick more closely to a SIMD architecture may choose instead to
572 interpret unpredicated elements as an internal "copy element"
573 operation (which would be necessary in SIMD microarchitectures
574 that perform register-renaming)
575 * ffirst is a special mode that stops sequential element processing when
576 a data-dependent condition occurs, whether a trap or a conditional test.
577 The handling of each (trap or conditional test) is slightly different:
578 see Instruction sections for further details
579
580 [[!inline raw="yes" pages="simple_v_extension/pred_table_format" ]]
581
582 The 8 bit format is a compact and less expressive variant of the full
583 16 bit format. Using the 8 bit format is very different: the predicate
584 register to use is implicit, and numbering begins inplicitly from x9. The
585 regnum is still used to "activate" predication, in the same fashion as
586 described above.
587
588 The 16 bit Predication CSR Table is a key-value store, so
589 implementation-wise it will be faster to turn the table around (maintain
590 topologically equivalent state). Opportunities then exist to access
591 registers in unary form instead of binary, saving gates and power by
592 only activating "redirection" with a single AND gate, instead of
593 multiple multi-bit XORs (a CAM):
594
595 [[!inline raw="yes" pages="simple_v_extension/pred_table" ]]
596
597 So when an operation is to be predicated, it is the internal state that
598 is used. In Section 6.4.2 of Hwacha's Manual (EECS-2015-262) the following
599 pseudo-code for operations is given, where p is the explicit (direct)
600 reference to the predication register to be used:
601
602 for (int i=0; i<vl; ++i)
603 if ([!]preg[p][i])
604 (d ? vreg[rd][i] : sreg[rd]) =
605 iop(s1 ? vreg[rs1][i] : sreg[rs1],
606 s2 ? vreg[rs2][i] : sreg[rs2]); // for insts with 2 inputs
607
608 This instead becomes an *indirect* reference using the *internal* state
609 table generated from the Predication CSR key-value store, which is used
610 as follows.
611
612 if type(iop) == INT:
613 preg = int_pred_reg[rd]
614 else:
615 preg = fp_pred_reg[rd]
616
617 for (int i=0; i<vl; ++i)
618 predicate, zeroing = get_pred_val(type(iop) == INT, rd):
619 if (predicate && (1<<i))
620 result = iop(s1 ? regfile[rs1+i] : regfile[rs1],
621 s2 ? regfile[rs2+i] : regfile[rs2]);
622 (d ? regfile[rd+i] : regfile[rd]) = result
623 if preg.ffirst and result == 0:
624 VL = i # result was zero, end loop early, return VL
625 return
626 else if (zeroing)
627 (d ? regfile[rd+i] : regfile[rd]) = 0
628
629 Note:
630
631 * d, s1 and s2 are booleans indicating whether destination,
632 source1 and source2 are vector or scalar
633 * key-value CSR-redirection of rd, rs1 and rs2 have NOT been included
634 above, for clarity. rd, rs1 and rs2 all also must ALSO go through
635 register-level redirection (from the Register table) if they are
636 vectors.
637 * fail-on-first mode stops execution early whenever an operation
638 returns a zero value. floating-point results count both
639 positive-zero as well as negative-zero as "fail".
640
641 If written as a function, obtaining the predication mask (and whether
642 zeroing takes place) may be done as follows:
643
644 [[!inline raw="yes" pages="simple_v_extension/get_pred_value" ]]
645
646 Note here, critically, that **only** if the register is marked
647 in its **register** table entry as being "active" does the testing
648 proceed further to check if the **predicate** table entry is
649 also active.
650
651 Note also that this is in direct contrast to branch operations
652 for the storage of comparisions: in these specific circumstances
653 the requirement for there to be an active *register* entry
654 is removed.
655
656 ## Fail-on-First Mode <a name="ffirst-mode"></a>
657
658 ffirst is a special data-dependent predicate mode. There are two
659 variants: one is for faults: typically for LOAD/STORE operations,
660 which may encounter end of page faults during a series of operations.
661 The other variant is comparisons such as FEQ (or the augmented behaviour
662 of Branch), and any operation that returns a result of zero (whether
663 integer or floating-point). In the FP case, this includes negative-zero.
664
665 Note that the execution order must "appear" to be sequential for ffirst
666 mode to work correctly. An in-order architecture must execute the element
667 operations in sequence, whilst an out-of-order architecture must *commit*
668 the element operations in sequence (giving the appearance of in-order
669 execution).
670
671 Note also, that if ffirst mode is needed without predication, a special
672 "always-on" Predicate Table Entry may be constructed by setting
673 inverse-on and using x0 as the predicate register. This
674 will have the effect of creating a mask of all ones, allowing ffirst
675 to be set.
676
677 See [[appendix]] for more details on fail-on-first modes, as well as
678 pseudo-code, below.
679
680 ## REMAP and SHAPE CSRs <a name="remap" />
681
682 See optional [[remap]] section.
683
684 # Instruction Execution Order
685
686 Simple-V behaves as if it is a hardware-level "macro expansion system",
687 substituting and expanding a single instruction into multiple sequential
688 instructions with contiguous and sequentially-incrementing registers.
689 As such, it does **not** modify - or specify - the behaviour and semantics of
690 the execution order: that may be deduced from the **existing** RV
691 specification in each and every case.
692
693 So for example if a particular micro-architecture permits out-of-order
694 execution, and it is augmented with Simple-V, then wherever instructions
695 may be out-of-order then so may the "post-expansion" SV ones.
696
697 If on the other hand there are memory guarantees which specifically
698 prevent and prohibit certain instructions from being re-ordered
699 (such as the Atomicity Axiom, or FENCE constraints), then clearly
700 those constraints **MUST** also be obeyed "post-expansion".
701
702 It should be absolutely clear that SV is **not** about providing new
703 functionality or changing the existing behaviour of a micro-architetural
704 design, or about changing the RISC-V Specification.
705 It is **purely** about compacting what would otherwise be contiguous
706 instructions that use sequentially-increasing register numbers down
707 to the **one** instruction.
708
709 # Instructions <a name="instructions" />
710
711 See [[appendix]] for specific cases where instruction behaviour is
712 augmented. A greatly simplified example is below. Note that this
713 is the ADD implementation, not a separate VADD instruction:
714
715 [[!inline raw="yes" pages="simple_v_extension/simple_add_example" ]]
716
717 Note that several things have been left out of this example.
718 See [[appendix]] for additional examples that show how to add
719 support for additional features (twin predication, elwidth,
720 zeroing, SUBVL etc.)
721
722 # Exceptions
723
724 Exceptions may occur at any time, in any given underlying scalar
725 operation. This implies that context-switching (traps) may occur, and
726 operation must be returned to where it left off. That in turn implies
727 that the full state - including the current parallel element being
728 processed - has to be saved and restored. This is what the **STATE**
729 and **PCVBLK** CSRs are for.
730
731 The implications are that all underlying individual scalar operations
732 "issued" by the parallelisation have to appear to be executed sequentially.
733 The further implications are that if two or more individual element
734 operations are underway, and one with an earlier index causes an exception,
735 it will be necessary for the microarchitecture to **discard** or terminate
736 operations with higher indices. Optimisated microarchitectures could
737 hypothetically store (cache) results, for subsequent replay if appropriate.
738
739 In short: exception handling **MUST** be precise, in-order, and exactly
740 like Standard RISC-V as far as the instruction execution order is
741 concerned, regardless of whether it is PC, PCVBLK, VL or SUBVL that
742 is currently being incremented.
743
744 # Hints
745
746 A "HINT" is an operation that has no effect on architectural state,
747 where its use may, by agreed convention, give advance notification
748 to the microarchitecture: branch prediction notification would be
749 a good example. Usually HINTs are where rd=x0.
750
751 With Simple-V being capable of issuing *parallel* instructions where
752 rd=x0, the space for possible HINTs is expanded considerably. VL
753 could be used to indicate different hints. In addition, if predication
754 is set, the predication register itself could hypothetically be passed
755 in as a *parameter* to the HINT operation.
756
757 No specific hints are yet defined in Simple-V
758
759 # Vector Block Format <a name="vliw-format"></a>
760
761 The VBLOCK Format allows Register, Predication and Vector Length to be contextually associated with a group of RISC-V scalar opcodes. The format is as follows:
762
763 [[!inline raw="yes" pages="simple_v_extension/vblock_format_table" ]]
764
765 For more details, including the CSRs, see ancillary resource: [[vblock_format]]
766
767 # Under consideration <a name="issues"></a>
768
769 See [[discussion]]
770