X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=openpower%2Fsv%2Foverview.mdwn;h=9f37c0198a2187f20dfd4eccf9afc034714c135b;hb=35bbedd4f0a77290c27730201112c2222636ee6a;hp=aa0498a0e09a6331a72fc450b465046ebd23b6cd;hpb=8d177c36b72a86bb389bff8b2a237ada9c2fb7f6;p=libreriscv.git diff --git a/openpower/sv/overview.mdwn b/openpower/sv/overview.mdwn index aa0498a0e..9f37c0198 100644 --- a/openpower/sv/overview.mdwn +++ b/openpower/sv/overview.mdwn @@ -5,15 +5,25 @@ This document provides an overview and introduction as to why SV (a [[!wikipedia Cray]]-style Vector augmentation to [[!wikipedia OpenPOWER]]) exists, and how it works. +**Sponsored by NLnet under the Privacy and Enhanced Trust Programme** + Links: +* This page: [http://libre-soc.org/openpower/sv/overview](http://libre-soc.org/openpower/sv/overview) +* [FOSDEM2021 SimpleV for OpenPOWER](https://fosdem.org/2021/schedule/event/the_libresoc_project_simple_v_vectorisation/) +* FOSDEM2021 presentation * [[discussion]] and [bugreport](https://bugs.libre-soc.org/show_bug.cgi?id=556) feel free to add comments, questions. * [[SV|sv]] * [[sv/svp64]] +* [x86 REP instruction](https://c9x.me/x86/html/file_module_x86_id_279.html): + a useful way to quickly understand that the core of the SV concept + is not new. +* [Article about register tagging](http://science.lpnu.ua/sites/default/files/journal-paper/2019/jul/17084/volum3number1text-9-16_1.pdf) showing + that tagging is not a new idea either. Register tags + are also used in the Mill Architecture. -Contents: [[!toc]] @@ -39,6 +49,10 @@ the typical dimensions that result in such massive proliferation: * Conversion between bitwidths (FP16-FP32-64) * Signed/unsigned * HI/LO swizzle (Audio L/R channels) + - HI/LO selection on src 1 + - selection on src 2 + - selection on dest + - Example: AndesSTAR Audio DSP * Saturation (Clamping at max range) These typically are multiplied up to produce explicit opcodes numbering @@ -55,13 +69,14 @@ Unlike in SIMD, powers of two limitations are not involved in the ISA or in the assembly code. SimpleV takes the Cray style Vector principle and applies it in the -abstract to a Scalar ISA, in the process allowing register file size -increases using "tagging" (similar to how x86 originally extended +abstract to a Scalar ISA in the same way that x86 used to do its "REP" instruction. In the process, "context" is applied, allowing amongst other things +a register file size +increase using "tagging" (similar to how x86 originally extended registers from 32 to 64 bit). ## SV -The fundamentals are: +The fundamentals are (just like x86 "REP"): * The Program Counter (PC) gains a "Sub Counter" context (Sub-PC) * Vectorisation pauses the PC and runs a Sub-PC loop from 0 to VL-1 @@ -281,7 +296,7 @@ in Vector ISAs: and the destination a vector, and having no predicate set or having multiple bits set. * VSELECT is provided by setting up (at least one of) the sources as a - vector, using a single bit in olthe predicate, and the destination as + vector, using a single bit in the predicate, and the destination as a scalar. All of this capability and coverage without even adding one single actual @@ -458,7 +473,7 @@ element width. Our first simple loop thus becomes: src1 = get_polymorphed_reg(RA, srcwid, i) src2 = get_polymorphed_reg(RB, srcwid, i) result = src1 + src2 # actual add here - set_polymorphed_reg(rd, destwid, i, result) + set_polymorphed_reg(RT, destwid, i, result) With this loop, if elwidth=16 and VL=3 the first 48 bits of the target register will contain three 16 bit addition results, and the upper 16 @@ -504,12 +519,15 @@ clarity and assumes significant working knowledge of OpenPOWER, with arbitrary insertions of 7-index here and 3-bitindex there, the decision to pick LE was extremely easy. -Without such a decision, if two words are packed as elements into a -64 bit register, what does this mean? Should they be inverted so that -the lower indexed element goes into the HI or the LO word? should the -8 bytes of each register be inverted? Should the bytes in each element -be inverted? Should the element indexing loop order be broken onto discontiguous chunks such as 32107654 rather than 01234567, and if so at what granilsrity of discontinuity? These are all equally valid and legitimate interpretations -of what constitutes "BE" and they all cause merry mayhem. +Without such a decision, if two words are packed as elements into a 64 +bit register, what does this mean? Should they be inverted so that the +lower indexed element goes into the HI or the LO word? should the 8 +bytes of each register be inverted? Should the bytes in each element +be inverted? Should the element indexing loop order be broken onto +discontiguous chunks such as 32107654 rather than 01234567, and if so +at what granularity of discontinuity? These are all equally valid and +legitimate interpretations of what constitutes "BE" and they all cause +merry mayhem. The decision was therefore made: the c typedef union is the canonical definition, and its members are defined as being in LE order. From there, @@ -530,18 +548,23 @@ are over-ridden to different widths? For example, FP16 arithmetic is not accurate enough and may introduce rounding errors when up-converted to FP32 output. The rule is therefore set: - The operation MUST take place at the larger of the two widths. + The operation MUST take place effectively at infinite precision: + actual precision determined by the operation and the operand widths In pseudocode this is: for i = 0 to VL-1: src1 = get_polymorphed_reg(RA, srcwid, i) src2 = get_polymorphed_reg(RB, srcwid, i) - opwidth = max(srcwid, destwid) + opwidth = max(srcwid, destwid) # usually result = op_add(src1, src2, opwidth) # at max width set_polymorphed_reg(rd, destwid, i, result) -It will turn out that under some conditions the combination of the +In reality the source and destination widths determine the actual required +precision in a given ALU. The reason for setting "effectively" infinite precision +is illustrated for example by Saturated-multiply, where if the internal precision was insufficient it would not be possible to correctly determine the maximum clip range had been exceeded. + +Thus it will turn out that under some conditions the combination of the extension of the source registers followed by truncation of the result gets rid of bits that didn't matter, and the operation might as well have taken place at the narrower width and could save resources that way. @@ -568,8 +591,8 @@ be first read at their overridden bitwidth and *then* sign-extended: src2 = get_polymorphed_reg(RB, srcwid, i) opwidth = max(srcwid, destwid) # srces known to be less than result width - src1 = sign_extend(src1, srcwid, destwid) - src2 = sign_extend(src2, srcwid, destwid) + src1 = sign_extend(src1, srcwid, opwidth) + src2 = sign_extend(src2, srcwid, opwidth) result = op_signed(src1, src2, opwidth) # at max width set_polymorphed_reg(rd, destwid, i, result) @@ -591,11 +614,11 @@ truncated. Only then can the arithmetic saturation condition be detected: # unsigned add result = op_add(src1, src2, opwidth) # at max width # now saturate (unsigned) - sat = max(result, (1<