reorg
[libreriscv.git] / simple_v_extension / simple_v_chennai_2018.tex
1 \documentclass[slidestop]{beamer}
2 \usepackage{beamerthemesplit}
3 \usepackage{graphics}
4 \usepackage{pstricks}
5
6 \title{Simple-V RISC-V Extension for Vectorisation and SIMD}
7 \author{Luke Kenneth Casson Leighton}
8
9
10 \begin{document}
11
12 \frame{
13 \begin{center}
14 \huge{Simple-V RISC-V Extension for Vectors and SIMD}\\
15 \vspace{32pt}
16 \Large{Flexible Vectorisation}\\
17 \Large{(aka not so Simple-V?)}\\
18 \Large{(aka How to Parallelise the RISC-V ISA)}\\
19 \vspace{24pt}
20 \Large{[proposed for] Chennai 9th RISC-V Workshop}\\
21 \vspace{16pt}
22 \large{\today}
23 \end{center}
24 }
25
26
27 \frame{\frametitle{Credits and Acknowledgements}
28
29 \begin{itemize}
30 \item The Designers of RISC-V\vspace{15pt}
31 \item The RVV Working Group and contributors\vspace{15pt}
32 \item Allen Baum, Jacob Bachmeyer, Xan Phung, Chuanhua Chang,\\
33 Guy Lemurieux, Jonathan Neuschafer, Roger Brussee,
34 and others\vspace{15pt}
35 \item ISA-Dev Group Members\vspace{10pt}
36 \end{itemize}
37 }
38
39
40 \frame{\frametitle{Quick refresher on SIMD}
41
42 \begin{itemize}
43 \item SIMD very easy to implement (and very seductive)\vspace{8pt}
44 \item Parallelism is in the ALU\vspace{8pt}
45 \item Zero-to-Negligeable impact for rest of core\vspace{8pt}
46 \end{itemize}
47 Where SIMD Goes Wrong:\vspace{10pt}
48 \begin{itemize}
49 \item See "SIMD instructions considered harmful"
50 https://sigarch.org/simd-instructions-considered-harmful
51 \item Setup and corner-cases alone are extremely complex.\\
52 Hardware is easy, but software is hell.
53 \item O($N^{6}$) ISA opcode proliferation!\\
54 opcode, elwidth, veclen, src1-src2-dest hi/lo
55 \end{itemize}
56 }
57
58 \frame{\frametitle{Quick refresher on RVV}
59
60 \begin{itemize}
61 \item Extremely powerful (extensible to 256 registers)\vspace{10pt}
62 \item Supports polymorphism, several datatypes (inc. FP16)\vspace{10pt}
63 \item Requires a separate Register File (32 w/ext to 256)\vspace{10pt}
64 \item Implemented as a separate pipeline (no impact on scalar)\vspace{10pt}
65 \end{itemize}
66 However...\vspace{10pt}
67 \begin{itemize}
68 \item 98 percent opcode duplication with rest of RV (CLIP)
69 \item Extending RVV requires customisation not just of h/w:\\
70 gcc, binutils also need customisation (and maintenance)
71 \end{itemize}
72 }
73
74
75 \frame{\frametitle{The Simon Sinek lowdown (Why, How, What)}
76
77 \begin{itemize}
78 \item Why?
79 Implementors need flexibility in vectorisation to optimise for
80 area or performance depending on the scope:
81 embedded DSP, Mobile GPU's, Server CPU's and more.\\
82 Compilers also need flexibility in vectorisation to optimise for cost
83 of pipeline setup, amount of state to context switch
84 and software portability
85 \item How?
86 By marking INT/FP regs as "Vectorised" and
87 adding a level of indirection,
88 SV expresses how existing instructions should act
89 on [contiguous] blocks of registers, in parallel, WITHOUT
90 needing new any actual extra arithmetic opcodes.
91 \item What?
92 Simple-V is an "API" that implicitly extends
93 existing (scalar) instructions with explicit parallelisation\\
94 i.e. SV is actually about parallelism NOT vectors per se.\\
95 Has a lot in common with VLIW (without the actual VLIW).
96 \end{itemize}
97 }
98
99
100 \frame{\frametitle{What's the value of SV? Why adopt it even in non-V?}
101
102 \begin{itemize}
103 \item memcpy becomes much smaller (higher bang-per-buck)
104 \item context-switch (LOAD/STORE multiple): 1-2 instructions
105 \item Compressed instrs further reduces I-cache (etc.)
106 \item Greatly-reduced I-cache load (and less reads)
107 \item Amazingly, SIMD becomes (more) tolerable (no corner-cases)
108 \item Modularity/Abstraction in both the h/w and the toolchain.
109 \item "Reach" of registers accessible by Compressed is enhanced
110 \item Future: double the standard INT/FP register file sizes.
111 \end{itemize}
112 Note:
113 \begin{itemize}
114 \item It's not just about Vectors: it's about instruction effectiveness
115 \item Anything implementor is not interested in HW-optimising,\\
116 let it fall through to exceptions (implement as a trap).
117 \end{itemize}
118 }
119
120
121 \frame{\frametitle{How does Simple-V relate to RVV? What's different?}
122
123 \begin{itemize}
124 \item RVV very heavy-duty (excellent for supercomputing)\vspace{8pt}
125 \item Simple-V abstracts parallelism (based on best of RVV)\vspace{8pt}
126 \item Graded levels: hardware, hybrid or traps (fit impl. need)\vspace{8pt}
127 \item Even Compressed become vectorised (RVV can't)\vspace{8pt}
128 \item No polymorphism in SV (too complex)\vspace{8pt}
129 \end{itemize}
130 What Simple-V is not:\vspace{4pt}
131 \begin{itemize}
132 \item A full supercomputer-level Vector Proposal
133 \item A replacement for RVV (SV is designed to be over-ridden\\
134 by - or augmented to become - RVV)
135 \end{itemize}
136 }
137
138
139 \frame{\frametitle{How is Parallelism abstracted in Simple-V?}
140
141 \begin{itemize}
142 \item Register "typing" turns any op into an implicit Vector op:\\
143 registers are reinterpreted through a level of indirection
144 \item Primarily at the Instruction issue phase (except SIMD)\\
145 Note: it's ok to pass predication through to ALU (like SIMD)
146 \item Standard (and future, and custom) opcodes now parallel\vspace{10pt}
147 \end{itemize}
148 Note: EVERYTHING is parallelised:
149 \begin{itemize}
150 \item All LOAD/STORE (inc. Compressed, Int/FP versions)
151 \item All ALU ops (Int, FP, SIMD, DSP, everything)
152 \item All branches become predication targets (C.FNE added?)
153 \item C.MV of particular interest (s/v, v/v, v/s)
154 \item FCVT, FMV, FSGNJ etc. very similar to C.MV
155 \end{itemize}
156 }
157
158
159 \frame{\frametitle{Implementation Options}
160
161 \begin{itemize}
162 \item Absolute minimum: Exceptions: if CSRs indicate "V", trap.\\
163 (Requires as absolute minimum that CSRs be in H/W)
164 \item Hardware loop, single-instruction issue\\
165 (Do / Don't send through predication to ALU)
166 \item Hardware loop, parallel (multi-instruction) issue\\
167 (Do / Don't send through predication to ALU)
168 \item Hardware loop, full parallel ALU (not recommended)
169 \end{itemize}
170 Notes:\vspace{4pt}
171 \begin{itemize}
172 \item 4 (or more?) options above may be deployed on per-op basis
173 \item SIMD always sends predication bits through to ALU
174 \item Minimum MVL MUST be sufficient to cover regfile LD/ST
175 \item Instr. FIFO may repeatedly split off N scalar ops at a time
176 \end{itemize}
177 }
178 % Instr. FIFO may need its own slide. Basically, the vectorised op
179 % gets pushed into the FIFO, where it is then "processed". Processing
180 % will remove the first set of ops from its vector numbering (taking
181 % predication into account) and shoving them **BACK** into the FIFO,
182 % but MODIFYING the remaining "vectorised" op, subtracting the now
183 % scalar ops from it.
184
185 \frame{\frametitle{Predicated 8-parallel ADD: 1-wide ALU}
186 \begin{center}
187 \includegraphics[height=2.5in]{padd9_alu1.png}\\
188 {\bf \red Predicated adds are shuffled down: 6 cycles in total}
189 \end{center}
190 }
191
192
193 \frame{\frametitle{Predicated 8-parallel ADD: 4-wide ALU}
194 \begin{center}
195 \includegraphics[height=2.5in]{padd9_alu4.png}\\
196 {\bf \red Predicated adds are shuffled down: 4 in 1st cycle, 2 in 2nd}
197 \end{center}
198 }
199
200
201 \frame{\frametitle{Predicated 8-parallel ADD: 3 phase FIFO expansion}
202 \begin{center}
203 \includegraphics[height=2.5in]{padd9_fifo.png}\\
204 {\bf \red First cycle takes first four 1s; second takes the rest}
205 \end{center}
206 }
207
208
209 \frame{\frametitle{How are SIMD Instructions Vectorised?}
210
211 \begin{itemize}
212 \item SIMD ALU(s) primarily unchanged\vspace{6pt}
213 \item Predication is added to each SIMD element\vspace{6pt}
214 \item Predication bits sent in groups to the ALU\vspace{6pt}
215 \item End of Vector enables (additional) predication\\
216 (completely nullifies need for end-case code)
217 \end{itemize}
218 Considerations:\vspace{4pt}
219 \begin{itemize}
220 \item Many SIMD ALUs possible (parallel execution)
221 \item Implementor free to choose (API remains the same)
222 \item Unused ALU units wasted, but s/w DRASTICALLY simpler
223 \item Very long SIMD ALUs could waste significant die area
224 \end{itemize}
225 }
226 % With multiple SIMD ALUs at for example 32-bit wide they can be used
227 % to either issue 64-bit or 128-bit or 256-bit wide SIMD operations
228 % or they can be used to cover several operations on totally different
229 % vectors / registers.
230
231 \frame{\frametitle{Predicated 9-parallel SIMD ADD}
232 \begin{center}
233 \includegraphics[height=2.5in]{padd9_simd.png}\\
234 {\bf \red 4-wide 8-bit SIMD, 4 bits of predicate passed to ALU}
235 \end{center}
236 }
237
238
239 \frame{\frametitle{What's the deal / juice / score?}
240
241 \begin{itemize}
242 \item Standard Register File(s) overloaded with CSR "reg is vector"\\
243 (see pseudocode slides for examples)
244 \item "2nd FP\&INT register bank" possibility (reserved for future)
245 \item Element width (and type?) concepts remain same as RVV\\
246 (CSRs give new size (and meaning?) to elements in registers)
247 \item CSRs are key-value tables (overlaps allowed: v. important)
248 \end{itemize}
249 Key differences from RVV:
250 \begin{itemize}
251 \item Predication in INT regs as a BIT field (max VL=XLEN)
252 \item Minimum VL must be Num Regs - 1 (all regs single LD/ST)
253 \item SV may condense sparse Vecs: RVV lets ALU do predication
254 \item Choice to Zero or skip non-predicated elements
255 \end{itemize}
256 }
257
258
259 \begin{frame}[fragile]
260 \frametitle{ADD pseudocode (or trap, or actual hardware loop)}
261
262 \begin{semiverbatim}
263 function op\_add(rd, rs1, rs2, predr) # add not VADD!
264  int i, id=0, irs1=0, irs2=0;
265  for (i = 0; i < VL; i++)
266   if (ireg[predr] & 1<<i) # predication uses intregs
267    ireg[rd+id] <= ireg[rs1+irs1] + ireg[rs2+irs2];
268 if (reg\_is\_vectorised[rd]) \{ id += 1; \}
269 if (reg\_is\_vectorised[rs1]) \{ irs1 += 1; \}
270 if (reg\_is\_vectorised[rs2]) \{ irs2 += 1; \}
271 \end{semiverbatim}
272
273 \begin{itemize}
274 \item Above is oversimplified: Reg. indirection left out (for clarity).
275 \item SIMD slightly more complex (case above is elwidth = default)
276 \item Scalar-scalar and scalar-vector and vector-vector now all in one
277 \item OoO may choose to push ADDs into instr. queue (v. busy!)
278 \end{itemize}
279 \end{frame}
280
281 % yes it really *is* ADD not VADD. that's the entire point of
282 % this proposal, that *standard* operations are overloaded to
283 % become vectorised-on-demand
284
285
286 \begin{frame}[fragile]
287 \frametitle{Predication-Branch (or trap, or actual hardware loop)}
288
289 \begin{semiverbatim}
290 s1 = reg\_is\_vectorised(src1);
291 s2 = reg\_is\_vectorised(src2);
292 if (!s2 && !s1) goto branch;
293 for (int i = 0; i < VL; ++i)
294 if (cmp(s1 ? reg[src1+i]:reg[src1],
295 s2 ? reg[src2+i]:reg[src2])
296 ireg[rs3] |= 1<<i;
297 \end{semiverbatim}
298
299 \begin{itemize}
300 \item SIMD slightly more complex (case above is elwidth = default)
301 \item If s1 and s2 both scalars, Standard branch occurs
302 \item Predication stored in integer regfile as a bitfield
303 \item Scalar-vector and vector-vector supported
304 \item Overload Branch immediate to be predication target rs3
305 \end{itemize}
306 \end{frame}
307
308 \begin{frame}[fragile]
309 \frametitle{VLD/VLD.S/VLD.X (or trap, or actual hardware loop)}
310
311 \begin{semiverbatim}
312 if (unit-strided) stride = elsize;
313 else stride = areg[as2]; // constant-strided
314 for (int i = 0; i < VL; ++i)
315 if (preg\_enabled[rd] && ([!]preg[rd] & 1<<i))
316 for (int j = 0; j < seglen+1; j++)
317 if (reg\_is\_vectorised[rs2]) offs = vreg[rs2+i]
318 else offs = i*(seglen+1)*stride;
319 vreg[rd+j][i] = mem[sreg[base] + offs + j*stride]
320 \end{semiverbatim}
321
322 \begin{itemize}
323 \item Again: elwidth != default slightly more complex
324 \item rs2 vectorised taken to implicitly indicate VLD.X
325 \end{itemize}
326 \end{frame}
327
328
329 \frame{\frametitle{Predication key-value CSR store}
330
331 \begin{itemize}
332 \item key is int regfile number or FP regfile number (1 bit)\vspace{6pt}
333 \item register to be predicated if referred to (5 bits, key)\vspace{6pt}
334 \item register to store actual predication in (5 bits, value)\vspace{6pt}
335 \item predication is inverted Y/N (1 bit)\vspace{6pt}
336 \item non-predicated elements are to be zero'd Y/N (1 bit)\vspace{6pt}
337 \end{itemize}
338 Notes:\vspace{10pt}
339 \begin{itemize}
340 \item Table should be expanded out for high-speed implementations
341 \item Multiple "keys" (and values) theoretically permitted
342 \item RVV rules about deleting higher-indexed CSRs followed
343 \end{itemize}
344 }
345
346
347 \begin{frame}[fragile]
348 \frametitle{Predication key-value CSR table decoding pseudocode}
349
350 \begin{semiverbatim}
351 struct pred fp\_pred[32];
352 struct pred int\_pred[32];
353
354 for (i = 0; i < 16; i++) // 16 CSRs?
355 tb = int\_pred if CSRpred[i].type == 0 else fp\_pred
356 idx = CSRpred[i].regidx
357 tb[idx].zero = CSRpred[i].zero
358 tb[idx].inv = CSRpred[i].inv
359 tb[idx].predidx = CSRpred[i].predidx
360 tb[idx].enabled = true
361 \end{semiverbatim}
362
363 \begin{itemize}
364 \item All 64 (int and FP) Entries zero'd before setting
365 \item Might be a bit complex to set up (TBD)
366 \end{itemize}
367
368 \end{frame}
369
370
371 \begin{frame}[fragile]
372 \frametitle{Get Predication value pseudocode}
373
374 \begin{semiverbatim}
375 def get\_pred\_val(bool is\_fp\_op, int reg):
376 tb = int\_pred if is\_fp\_op else fp\_pred
377 if (!tb[reg].enabled):
378 return ~0x0 // all ops enabled
379 predidx = tb[reg].predidx // redirection occurs HERE
380 predicate = intreg[predidx] // actual predicate HERE
381 if (tb[reg].inv):
382 predicate = ~predicate // invert ALL bits
383 return predicate
384 \end{semiverbatim}
385
386 \begin{itemize}
387 \item References different (internal) mapping table for INT or FP
388 \item Actual predicate bitmask ALWAYS from the INT regfile
389 \end{itemize}
390
391 \end{frame}
392
393
394 \frame{\frametitle{To Zero or not to place zeros in non-predicated elements?}
395
396 \begin{itemize}
397 \item Zeroing is an implementation optimisation favouring OoO
398 \item Simple implementations may skip non-predicated operations
399 \item Simple implementations explicitly have to destroy data
400 \item Complex implementations may use reg-renames to save power\\
401 Zeroing on predication chains makes optimisation harder
402 \item Compromise: REQUIRE both (specified in predication CSRs).
403 \end{itemize}
404 Considerations:
405 \begin{itemize}
406 \item Complex not really impacted, simple impacted a LOT\\
407 with Zeroing... however it's useful (memzero)
408 \item Non-zero'd overlapping "Vectors" may issue overlapping ops\\
409 (2nd op's predicated elements slot in 1st's non-predicated ops)
410 \item Please don't use Vectors for "security" (use Sec-Ext)
411 \end{itemize}
412 }
413 % with overlapping "vectors" - bearing in mind that "vectors" are
414 % just a remap onto the standard register file, if the top bits of
415 % predication are zero, and there happens to be a second vector
416 % that uses some of the same register file that happens to be
417 % predicated out, the second vector op may be issued *at the same time*
418 % if there are available parallel ALUs to do so.
419
420
421 \frame{\frametitle{Register key-value CSR store}
422
423 \begin{itemize}
424 \item key is int regfile number or FP regfile number (1 bit)
425 \item treated as vector if referred to in op (5 bits, key)
426 \item starting register to actually be used (5 bits, value)
427 \item element bitwidth: default, dflt/2, 8, 16 (2 bits)
428 \item is vector: Y/N (1 bit)
429 \item is packed SIMD: Y/N (1 bit)
430 \item register bank: 0/reserved for future ext. (1 bit)
431 \end{itemize}
432 Notes:
433 \begin{itemize}
434 \item References different (internal) mapping table for INT or FP
435 \item Level of indirection has implications for pipeline latency
436 \item (future) bank bit, no need to extend opcodes: set bank=1,
437 just use normal 5-bit regs, indirection takes care of the rest.
438 \end{itemize}
439 }
440
441
442 \frame{\frametitle{Register element width and packed SIMD}
443
444 Packed SIMD = N:
445 \begin{itemize}
446 \item default: RV32/64/128 opcodes define elwidth = 32/64/128
447 \item default/2: RV32/64/128 opcodes, elwidth = 16/32/64 with
448 top half of register ignored (src), zero'd/s-ext (dest)
449 \item 8 or 16: elwidth = 8 (or 16), similar to default/2
450 \end{itemize}
451 Packed SIMD = Y (default is moot, packing is 1:1)
452 \begin{itemize}
453 \item default/2: 2 elements per register @ opcode-defined bitwidth
454 \item 8 or 16: standard 8 (or 16) packed SIMD
455 \end{itemize}
456 Notes:
457 \begin{itemize}
458 \item Different src/dest widths (and packs) PERMITTED
459 \item RV* already allows (and defines) how RV32 ops work in RV64\\
460 so just logically follow that lead/example.
461 \end{itemize}
462 }
463
464
465 \begin{frame}[fragile]
466 \frametitle{Register key-value CSR table decoding pseudocode}
467
468 \begin{semiverbatim}
469 struct vectorised fp\_vec[32], int\_vec[32]; // 64 in future
470
471 for (i = 0; i < 16; i++) // 16 CSRs?
472 tb = int\_vec if CSRvectortb[i].type == 0 else fp\_vec
473 idx = CSRvectortb[i].regidx
474 tb[idx].elwidth = CSRpred[i].elwidth
475 tb[idx].regidx = CSRpred[i].regidx // indirection
476 tb[idx].isvector = CSRpred[i].isvector
477 tb[idx].packed = CSRpred[i].packed // SIMD or not
478 tb[idx].bank = CSRpred[i].bank // 0 (1=rsvd)
479 \end{semiverbatim}
480
481 \begin{itemize}
482 \item All 32 int (and 32 FP) entries zero'd before setup
483 \item Might be a bit complex to set up (TBD)
484 \end{itemize}
485
486 \end{frame}
487
488
489 \begin{frame}[fragile]
490 \frametitle{ADD pseudocode with redirection, this time}
491
492 \begin{semiverbatim}
493 function op\_add(rd, rs1, rs2) # add not VADD!
494  int i, id=0, irs1=0, irs2=0;
495  rd = int\_vec[rd ].isvector ? int\_vec[rd ].regidx : rd;
496  rs1 = int\_vec[rs1].isvector ? int\_vec[rs1].regidx : rs1;
497  rs2 = int\_vec[rs2].isvector ? int\_vec[rs2].regidx : rs2;
498  predval = get\_pred\_val(FALSE, rd);
499  for (i = 0; i < VL; i++)
500 if (predval \& 1<<i) # predication uses intregs
501    ireg[rd+id] <= ireg[rs1+irs1] + ireg[rs2+irs2];
502 if (int\_vec[rd ].isvector)  \{ id += 1; \}
503 if (int\_vec[rs1].isvector)  \{ irs1 += 1; \}
504 if (int\_vec[rs2].isvector)  \{ irs2 += 1; \}
505 \end{semiverbatim}
506
507 \begin{itemize}
508 \item SIMD (elwidth != default) not covered above
509 \end{itemize}
510 \end{frame}
511
512
513 \frame{\frametitle{Why are overlaps allowed in Regfiles?}
514
515 \begin{itemize}
516 \item Same register(s) can have multiple "interpretations"
517 \item Set "real" register (scalar) without needing to set/unset CSRs.
518 \item xBitManip plus SIMD plus xBitManip = Hi/Lo bitops
519 \item (32-bit GREV plus 4x8-bit SIMD plus 32-bit GREV:\\
520 GREV @ VL=N,wid=32; SIMD @ VL=Nx4,wid=8)
521 \item RGB 565 (video): BEXTW plus 4x8-bit SIMD plus BDEPW\\
522 (BEXT/BDEP @ VL=N,wid=32; SIMD @ VL=Nx4,wid=8)
523 \item Same register(s) can be offset (no need for VSLIDE)\vspace{6pt}
524 \end{itemize}
525 Note:
526 \begin{itemize}
527 \item xBitManip reduces O($N^{6}$) SIMD down to O($N^{3}$)
528 \item Hi-Performance: Macro-op fusion (more pipeline stages?)
529 \end{itemize}
530 }
531
532
533 \frame{\frametitle{C.MV extremely flexible!}
534
535 \begin{itemize}
536 \item scalar-to-vector (w/ no pred): VSPLAT
537 \item scalar-to-vector (w/ dest-pred): Sparse VSPLAT
538 \item scalar-to-vector (w/ 1-bit dest-pred): VINSERT
539 \item vector-to-scalar (w/ [1-bit?] src-pred): VEXTRACT
540 \item vector-to-vector (w/ no pred): Vector Copy
541 \item vector-to-vector (w/ src pred): Vector Gather
542 \item vector-to-vector (w/ dest pred): Vector Scatter
543 \item vector-to-vector (w/ src \& dest pred): Vector Gather/Scatter
544 \end{itemize}
545 \vspace{4pt}
546 Notes:
547 \begin{itemize}
548 \item Surprisingly powerful! Zero-predication even more so
549 \item Same arrangement for FVCT, FMV, FSGNJ etc.
550 \end{itemize}
551 }
552
553
554 \begin{frame}[fragile]
555 \frametitle{MV pseudocode with predication}
556
557 \begin{semiverbatim}
558 function op\_mv(rd, rs) # MV not VMV!
559  rd = int\_vec[rd].isvector ? int\_vec[rd].regidx : rd;
560  rs = int\_vec[rs].isvector ? int\_vec[rs].regidx : rs;
561  ps = get\_pred\_val(FALSE, rs); # predication on src
562  pd = get\_pred\_val(FALSE, rd); # ... AND on dest
563  for (int i = 0, int j = 0; i < VL && j < VL;):
564 if (int\_vec[rs].isvec) while (!(ps \& 1<<i)) i++;
565 if (int\_vec[rd].isvec) while (!(pd \& 1<<j)) j++;
566 ireg[rd+j] <= ireg[rs+i];
567 if (int\_vec[rs].isvec) i++;
568 if (int\_vec[rd].isvec) j++;
569 \end{semiverbatim}
570
571 \begin{itemize}
572 \item elwidth != default not covered above (might be a bit hairy)
573 \item Ending early with 1-bit predication not included (VINSERT)
574 \end{itemize}
575 \end{frame}
576
577
578 \begin{frame}[fragile]
579 \frametitle{VSELECT: stays or goes? Stays if MV.X exists...}
580
581 \begin{semiverbatim}
582 def op_mv_x(rd, rs): # (hypothetical) RV MX.X
583 rs = regfile[rs] # level of indirection (MV.X)
584 regfile[rd] = regfile[rs] # straight regcopy
585 \end{semiverbatim}
586
587 Vectorised version aka "VSELECT":
588
589 \begin{semiverbatim}
590 def op_mv_x(rd, rs): # SV version of MX.X
591 for i in range(VL):
592 rs1 = regfile[rs+i] # indirection
593 regfile[rd+i] = regfile[rs] # straight regcopy
594 \end{semiverbatim}
595
596 \begin{itemize}
597 \item However MV.X does not exist in RV, so neither can VSELECT
598 \item \red SV is not about adding new functionality, only parallelism
599 \end{itemize}
600
601
602 \end{frame}
603
604
605 \frame{\frametitle{Opcodes, compared to RVV}
606
607 \begin{itemize}
608 \item All integer and FP opcodes all removed (no CLIP, FNE)
609 \item VMPOP, VFIRST etc. all removed (use xBitManip)
610 \item VSLIDE removed (use regfile overlaps)
611 \item C.MV covers VEXTRACT VINSERT and VSPLAT (and more)
612 \item Vector (or scalar-vector) copy: use C.MV (MV is a pseudo-op)
613 \item VMERGE: twin predicated C.MVs (one inverted. macro-op'd)
614 \item VSETVL, VGETVL stay (the only ops that do!)
615 \end{itemize}
616 Issues:
617 \begin{itemize}
618 \item VSELECT stays? no MV.X, so no (add with custom ext?)
619 \item VSNE exists, but no FNE (use predication inversion?)
620 \item VCLIP is not in RV* (add with custom ext?)
621 \end{itemize}
622 }
623
624
625 \begin{frame}[fragile]
626 \frametitle{Example c code: DAXPY}
627
628 \begin{semiverbatim}
629 void daxpy(size_t n, double a,
630 const double x[], double y[])
631 \{
632 for (size_t i = 0; i < n; i++) \{
633 y[i] = a*x[i] + y[i];
634 \}
635 \}
636 \end{semiverbatim}
637
638 \begin{itemize}
639 \item See "SIMD Considered Harmful" for SIMD/RVV analysis\\
640 https://sigarch.org/simd-instructions-considered-harmful/
641 \end{itemize}
642
643
644 \end{frame}
645
646
647 \begin{frame}[fragile]
648 \frametitle{RVV DAXPY assembly (RV32V)}
649
650 \begin{semiverbatim}
651 # a0 is n, a1 is ptr to x[0], a2 is ptr to y[0], fa0 is a
652 li t0, 2<<25
653 vsetdcfg t0 # enable 2 64b Fl.Pt. registers
654 loop:
655 setvl t0, a0 # vl = t0 = min(mvl, n)
656 vld v0, a1 # load vector x
657 slli t1, t0, 3 # t1 = vl * 8 (in bytes)
658 vld v1, a2 # load vector y
659 add a1, a1, t1 # increment pointer to x by vl*8
660 vfmadd v1, v0, fa0, v1 # v1 += v0 * fa0 (y = a * x + y)
661 sub a0, a0, t0 # n -= vl (t0)
662 vst v1, a2 # store Y
663 add a2, a2, t1 # increment pointer to y by vl*8
664 bnez a0, loop # repeat if n != 0
665 \end{semiverbatim}
666 \end{frame}
667
668
669 \begin{frame}[fragile]
670 \frametitle{SV DAXPY assembly (RV64D)}
671
672 \begin{semiverbatim}
673 # a0 is n, a1 is ptr to x[0], a2 is ptr to y[0], fa0 is a
674 CSRvect1 = \{type: F, key: a3, val: a3, elwidth: dflt\}
675 CSRvect2 = \{type: F, key: a7, val: a7, elwidth: dflt\}
676 loop:
677 setvl t0, a0, 4 # vl = t0 = min(4, n)
678 ld a3, a1 # load 4 registers a3-6 from x
679 slli t1, t0, 3 # t1 = vl * 8 (in bytes)
680 ld a7, a2 # load 4 registers a7-10 from y
681 add a1, a1, t1 # increment pointer to x by vl*8
682 fmadd a7, a3, fa0, a7 # v1 += v0 * fa0 (y = a * x + y)
683 sub a0, a0, t0 # n -= vl (t0)
684 st a7, a2 # store 4 registers a7-10 to y
685 add a2, a2, t1 # increment pointer to y by vl*8
686 bnez a0, loop # repeat if n != 0
687 \end{semiverbatim}
688 \end{frame}
689
690
691 \frame{\frametitle{Under consideration}
692
693 \begin{itemize}
694 \item Is C.FNE actually needed? Should it be added if it is?
695 \item Element type implies polymorphism. Should it be in SV?
696 \item Should use of registers be allowed to "wrap" (x30 x31 x1 x2)?
697 \item Is detection of all-scalar ops ok (without slowing pipeline)?
698 \item Can VSELECT be removed? (it's really complex)
699 \item Can CLIP be done as a CSR (mode, like elwidth)
700 \item SIMD saturation (etc.) also set as a mode?
701 \item Include src1/src2 predication on Comparison Ops?\\
702 (same arrangement as C.MV, with same flexibility/power)
703 \item 8/16-bit ops is it worthwhile adding a "start offset"? \\
704 (a bit like misaligned addressing... for registers)\\
705 or just use predication to skip start?
706 \end{itemize}
707 }
708
709
710 \frame{\frametitle{What's the downside(s) of SV?}
711 \begin{itemize}
712 \item EVERY register operation is inherently parallelised\\
713 (scalar ops are just vectors of length 1)\vspace{4pt}
714 \item Tightly coupled with the core (instruction issue)\\
715 could be disabled through MISA switch\vspace{4pt}
716 \item An extra pipeline phase almost certainly essential\\
717 for fast low-latency implementations\vspace{4pt}
718 \item With zeroing off, skipping non-predicated elements is hard:\\
719 it is however an optimisation (and could be skipped).\vspace{4pt}
720 \item Setting up the Register/Predication tables (interpreting the\\
721 CSR key-value stores) might be a bit complex to optimise
722 (any change to a CSR key-value entry needs to redo the table)
723 \end{itemize}
724 }
725
726
727 \frame{\frametitle{Is this OK (low latency)? Detect scalar-ops (only)}
728 \begin{center}
729 \includegraphics[height=2.5in]{scalardetect.png}\\
730 {\bf \red Detect when all registers are scalar for a given op}
731 \end{center}
732 }
733
734
735 \frame{\frametitle{Summary}
736
737 \begin{itemize}
738 \item Actually about parallelism, not Vectors (or SIMD) per se\\
739 and NOT about adding new ALU/logic/functionality.
740 \item Only needs 2 actual instructions (plus the CSRs).\\
741 RVV - and "standard" SIMD - require ISA duplication
742 \item Designed for flexibility (graded levels of complexity)
743 \item Huge range of implementor freedom
744 \item Fits RISC-V ethos: achieve more with less
745 \item Reduces SIMD ISA proliferation by 3-4 orders of magnitude \\
746 (without SIMD downsides or sacrificing speed trade-off)
747 \item Covers 98\% of RVV, allows RVV to fit "on top"
748 \item Byproduct of SV is a reduction in code size, power usage
749 etc. (increase efficiency, just like Compressed)
750 \end{itemize}
751 }
752
753
754 \frame{
755 \begin{center}
756 {\Huge The end\vspace{20pt}\\
757 Thank you\vspace{20pt}\\
758 Questions?\vspace{20pt}
759 }
760 \end{center}
761
762 \begin{itemize}
763 \item Discussion: ISA-DEV mailing list
764 \item http://libre-riscv.org/simple\_v\_extension/
765 \end{itemize}
766 }
767
768
769 \end{document}