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