whitespace
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Mon, 26 Oct 2020 08:32:09 +0000 (08:32 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Mon, 26 Oct 2020 08:32:09 +0000 (08:32 +0000)
openpower/sv/masked_vector_chaining.mdwn [new file with mode: 0644]
openpower/sv/predication.mdwn
simple_v_extension/masked_vector_chaining.mdwn [deleted file]

diff --git a/openpower/sv/masked_vector_chaining.mdwn b/openpower/sv/masked_vector_chaining.mdwn
new file mode 100644 (file)
index 0000000..b1a85ab
--- /dev/null
@@ -0,0 +1,53 @@
+[[!tag standards]]
+
+# Example execution of vector chaining through masks stored in integer registers
+
+As described in [bug 213 comment 56](https://bugs.libre-soc.org/show_bug.cgi?id=213#c56)
+and [bug 213 comment 53](https://bugs.libre-soc.org/show_bug.cgi?id=213#c53).
+
+See [Chaining on the Cray-1](http://homepages.inf.ed.ac.uk/cgi/rni/comp-arch.pl?Vect/cray1-ch.html,Vect/cray1-ch-f.html,Vect/menu-cr1.html).
+
+Using the following assembly language:
+
+    # starts with VL = 20
+    vec.cmpw.ge r10, r30, r50
+    andc r12, r10, r11
+    vec.fadds f30, f30, f50, mask=r12
+
+The examples assume a computer with a 4x32-bit SIMD integer pipe and a 4x32-bit SIMD FP pipe and a scalar integer pipe.
+
+For ease of viewing, the following examples combines execution pipelines and the scheduling FUs, which are separate things.
+
+## Treating integer registers as whole registers at the scheduler level (chaining\* doesn't work)
+
+Slow because the `fadds` instructions have to wait for all the `cmpw.ge` and `andc` instructions to complete before any can start executing.
+
+| Cycle | SIMD integer pipe                     | SIMD FP pipe                                     | scalar integer pipe              |
+|-------|---------------------------------------|--------------------------------------------------|----------------------------------|
+| 0     | `r10.0-3 <- cmpw.ge r30-31, r50-51`   | waiting on `r12.0-63`                            | waiting on `r10.0-63`            |
+| 1     | `r10.4-7 <- cmpw.ge r32-33, r52-53`   | waiting on `r12.0-63`                            | waiting on `r10.0-63`            |
+| 2     | `r10.8-11 <- cmpw.ge r34-35, r54-55`  | waiting on `r12.0-63`                            | waiting on `r10.0-63`            |
+| 3     | `r10.12-15 <- cmpw.ge r36-37, r56-57` | waiting on `r12.0-63`                            | waiting on `r10.0-63`            |
+| 4     | `r10.16-19 <- cmpw.ge r38-39, r58-59` | waiting on `r12.0-63`                            | waiting on `r10.0-63`            |
+| 5     |                                       | waiting on `r12.0-63`                            | `r12.0-63 <- andc r10.0-63, r11` |
+| 6     |                                       | `f30-31 <- fadds f30-31, f50-51, mask=r12.0-3`   |                                  |
+| 7     |                                       | `f32-33 <- fadds f32-33, f52-53, mask=r12.4-7`   |                                  |
+| 8     |                                       | `f34-35 <- fadds f34-35, f54-55, mask=r12.8-11`  |                                  |
+| 9     |                                       | `f36-37 <- fadds f36-37, f56-57, mask=r12.12-15` |                                  |
+| 10    |                                       | `f38-39 <- fadds f38-39, f58-59, mask=r12.16-19` |                                  |
+
+## Treating integer registers\* as many single-bit registers at the scheduler level (vector chaining works)
+
+\* or at least the register(s) optimized for usage as masks
+
+Faster because `fadds` instructions only have to wait for their vector lanes' mask bits to complete, rather than all vector lanes.
+
+| Cycle | SIMD integer pipe                     | SIMD FP pipe                                     | scalar integer pipe                      |
+|-------|---------------------------------------|--------------------------------------------------|------------------------------------------|
+| 0     | `r10.0-3 <- cmpw.ge r30-31, r50-51`   | waiting on `r12.0-3`                             | waiting on `r10.0-3`                     |
+| 1     | `r10.4-7 <- cmpw.ge r32-33, r52-53`   | waiting on `r12.0-3`                             | `r12.0-3 <- andc r10.0-3, r11.0-3`       |
+| 2     | `r10.8-11 <- cmpw.ge r34-35, r54-55`  | `f30-31 <- fadds f30-31, f50-51, mask=r12.0-3`   | `r12.4-7 <- andc r10.4-7, r11.4-7`       |
+| 3     | `r10.12-15 <- cmpw.ge r36-37, r56-57` | `f32-33 <- fadds f32-33, f52-53, mask=r12.4-7`   | `r12.8-11 <- andc r10.8-11, r11.8-11`    |
+| 4     | `r10.16-19 <- cmpw.ge r38-39, r58-59` | `f34-35 <- fadds f34-35, f54-55, mask=r12.8-11`  | `r12.12-15 <- andc r10.12-15, r11.12-15` |
+| 5     |                                       | `f36-37 <- fadds f36-37, f56-57, mask=r12.12-15` | `r12.16-19 <- andc r10.16-19, r11.16-19` |
+| 6     |                                       | `f38-39 <- fadds f38-39, f58-59, mask=r12.16-19` |                                          |
index b5168faf490d567ed9185cefd682dced0d30d37f..caeca24e864aab86a41f33c1f0b48f32592dd415 100644 (file)
@@ -2,10 +2,12 @@
 
 <https://bugs.libre-soc.org/show_bug.cgi?id=213>
 
-* idea 1: modify cmp (and other CR generators?) with qualifiers that create single bit prefix vector into int reg
+* idea 1: modify cmp (and other CR generators?) with qualifiers that
+  create single bit prefix vector into int reg
 * idea 2: override CR SO field in vector form to be predicate bit per element
 * idea 3: reading of predicates is from bits of int reg
-* idea 4: SO CR field no longer overflow, contains copy of int reg predicate element bit (passed through).  when OE set?
+* idea 4: SO CR field no longer overflow, contains copy of int reg
+  predicate element bit (passed through).  when OE set?
 
 
 # Requirements
 
 ## CR-based predication proposal
 
-this involves treating each CR as providing one bit of predicate. If there is limited space in SVPrefix it will be a fixed bit (bit 0) otherwise it may be selected (bit 0 to 3 of the CR)
+this involves treating each CR as providing one bit of predicate. If
+there is limited space in SVPrefix it will be a fixed bit (bit 0)
+otherwise it may be selected (bit 0 to 3 of the CR)
 
-the crucial advantage of this proposal is that the Function Units can have one more register (a CR) added as their Read Dependency Hazards just like all the other incoming source registers, and there is no need for a special "Predicate Shadow Function Unit".
+the crucial advantage of this proposal is that the Function Units can
+have one more register (a CR) added as their Read Dependency Hazards
+just like all the other incoming source registers, and there is no need
+for a special "Predicate Shadow Function Unit".
 
-an analysis of changing the element widths (for SIMD) gives the following potential arrangements, for which it is assumed that 2x 32-bit FUs "pair up" for single 64 bit arithmetic, HI32 and LO32 style.
+an analysis of changing the element widths (for SIMD) gives the following
+potential arrangements, for which it is assumed that 2x 32-bit FUs
+"pair up" for single 64 bit arithmetic, HI32 and LO32 style.
 
 * 64-bit operations.  2 FUs and their DM rows "collaborate" 
   - 2x 32-bit source registers gang together for 64 bit input
   - 2x 32-bit output registers likewise for output
   - 1x CR (from the LO32 FU DM side) for a predicate bit
 * 32-bit operations.  2 FUs collaborate 2x32 SIMD style
-  - 2x 32-bit source registers go into separate input halves of the SIMD ALU
+  - 2x 32-bit source registers go into separate input halves of the
+    SIMD ALU
   - 2x 32-bit outputs likewise for output
-  - 2x CRs (one for HI32, one for LO32) for a predicate bit for each of the 2x32bit SIMD pair
+  - 2x CRs (one for HI32, one for LO32) for a predicate bit for each of
+    the 2x32bit SIMD pair
 * 16-bit operations. 2 FUs collaborate 4x16 SIMD style
   - 2x 2x16-bit source registers group together to provide 4x16 inputs
   - likewise for outputs
   - EITHER 2x 2xCRs (2 for HI32, 2 for LO32) provide 4 predicate bits
-  - OR 1x 8xCR "full" port is utilised (on LO32 FU) followed by masking at the ALU behind the FU pair, extracting the required 4 predicate bits
+  - OR 1x 8xCR "full" port is utilised (on LO32 FU) followed by masking
+    at the ALU behind the FU pair, extracting the required 4 predicate bits
 * 8-bit operations. 2 FUs collaborate 8x8 SIMD style
   - 2x 4x8-bit source registers
   - likewise for outputs
-  - 1x 8xCR "full" port is utilised (on LO32 FU) and all 8 bits are passed through to the underlying 64-bit ALU to perform 8x 8-bit predicated operations
+  - 1x 8xCR "full" port is utilised (on LO32 FU) and all 8 bits are
+    passed through to the underlying 64-bit ALU to perform 8x 8-bit
+    predicated operations
 
-a big advantage of this is that unpredicated operations just set the predicate to an immediate of all 1s and the actual ALUs require very little modification.
+a big advantage of this is that unpredicated operations just set the
+predicate to an immediate of all 1s and the actual ALUs require very
+little modification.
 
 ## Scalar (single) integer as predicate, with one DM row
 
 This idea has several disadvantages.
 
-* the single DM entry for the entire 64 bits creates a read hazard that has to be resolved through the addition of a special Shadowing Function Unit.  Only when the entire predicate is available can the die-cancel/ok be pulled on the FU elements each bit covers
-* this situation is exacerbated if one vector creates a predicate mask that is then used to mask immediately following instructions.  Ordinarily (i.e. without the predicate involved), Cray-style "chaining" would be possible.  The single DM entry for the entire predicate mask prohibits this because the subsequent operations can only proceed when the *entire* mask has been computed.
-* Allocation of bits to FUs gets particularly complex for SIMD (elwidth overrides) requiring shift and mask logic that is simply not needed compared to "one-for-one" schemes (above)
+* the single DM entry for the entire 64 bits creates a read hazard
+  that has to be resolved through the addition of a special Shadowing
+  Function Unit.  Only when the entire predicate is available can the
+  die-cancel/ok be pulled on the FU elements each bit covers
+* this situation is exacerbated if one vector creates a predicate
+  mask that is then used to mask immediately following instructions.
+  Ordinarily (i.e. without the predicate involved), Cray-style "chaining"
+  would be possible.  The single DM entry for the entire predicate mask
+  prohibits this because the subsequent operations can only proceed when
+  the *entire* mask has been computed.
+* Allocation of bits to FUs gets particularly complex for SIMD (elwidth
+  overrides) requiring shift and mask logic that is simply not needed
+  compared to "one-for-one" schemes (above)
 
 Overall there is very little in favour of this concept.
 
 ## Scalar (single) integer as predicate with one DM row per bit
 
-The Dependency Matrix logic from the CR proposal favourably applies equally to this proposal.  However there are additional caveats that weigh against it:
+The Dependency Matrix logic from the CR proposal favourably applies
+equally to this proposal.  However there are additional caveats that
+weigh against it:
 
-* Like the single scalar DM entry proposal, the integer scalar register had to be covered also by a single FM entry (for when it is used *as* an integer register).
-* Unlike the same, it must also be covered by a 64-wide suite of bitlevel Dependency Matrix Rows.  These numbers are so massive as to cause some concern.
-* A solution is to introduce a virtual register naming scheme however this slso introduces huge complexity as the register cache has to be capable of swapping reservations from 64 bitlevel to full 64bit scalar level *and* keep the Dependency Matrices synchronised
+* Like the single scalar DM entry proposal, the integer scalar register
+  had to be covered also by a single FM entry (for when it is used *as*
+  an integer register).
+* Unlike the same, it must also be covered by a 64-wide suite of bitlevel
+  Dependency Matrix Rows.  These numbers are so massive as to cause some
+  concern.
+* A solution is to introduce a virtual register naming scheme however
+  this slso introduces huge complexity as the register cache has to be
+  capable of swapping reservations from 64 bitlevel to full 64bit scalar
+  level *and* keep the Dependency Matrices synchronised
 
-it is enormously complex and likely to result in debugging, verification and ongoing maintenance difficulties.
+it is enormously complex and likely to result in debugging, verification
+and ongoing maintenance difficulties.
 
 ## Schemes which split integer regs into chunks
 
-These ideas are based on the principle that each chunk of 8 (or 16) bits of a scalar integer register may be covered by its own DM row.  8 chunks would for example require 8 DM entries.
-
-This would, for vector sizes of 8, solve the "chaining" problem reasonably well even when two FUs (or two clock cycles) were required to deal with 4 elements at a time.  The "compare" that generated the predicate would be ready to go into the first "chunk" of predicate bits whilst the second compare was still being issued.
-
-It would also require a lot smaller DMs than the single-bit-per-element ideas.
-
-The problems start when trying to allocate bits of predicate to units.  Just like the single-DM-row per entire scalar reg case, a shadow-capable Predicate Funxtion Unit is now required (already determined to be costly) except now if there are 8 chunks requiring 8 Predicate FUs *the problem is now made 8x worse*.
-
-Not only that but it is even more complex when trying to bring in virtual register cacheing in order to bring down overall FU-REGs DM row count, although the numbers are much lower: 8x 8-bit chunks of scalar int only requires 8 DM Rows and 8 virtual subdivisions however *this is per in-flight register*.
-
-Out-of-order systems, to be effective, require several operations to be "in-flight" (POWER10 has up to 1,000 in-flight instructions) and if every predicated vector operation needed one 8-chunked scalar register each it becomes exceedingly complex very quickly.
-
-Even more than that, in a predicated chaining scenario, when computing the mask from a vector "compare", the groupings are troublesome to think through how to implement, which is itself a bad sign.  It is suspected that chaining will be complex or adversely affected by certain combinations of element width.
+These ideas are based on the principle that each chunk of 8 (or 16)
+bits of a scalar integer register may be covered by its own DM row.
+8 chunks would for example require 8 DM entries.
+
+This would, for vector sizes of 8, solve the "chaining" problem reasonably
+well even when two FUs (or two clock cycles) were required to deal with
+4 elements at a time.  The "compare" that generated the predicate would
+be ready to go into the first "chunk" of predicate bits whilst the second
+compare was still being issued.
+
+It would also require a lot smaller DMs than the single-bit-per-element
+ideas.
+
+The problems start when trying to allocate bits of predicate to units.
+Just like the single-DM-row per entire scalar reg case, a shadow-capable
+Predicate Funxtion Unit is now required (already determined to be costly)
+except now if there are 8 chunks requiring 8 Predicate FUs *the problem
+is now made 8x worse*.
+
+Not only that but it is even more complex when trying to bring in virtual
+register cacheing in order to bring down overall FU-REGs DM row count,
+although the numbers are much lower: 8x 8-bit chunks of scalar int
+only requires 8 DM Rows and 8 virtual subdivisions however *this is per
+in-flight register*.
+
+Out-of-order systems, to be effective, require several operations to
+be "in-flight" (POWER10 has up to 1,000 in-flight instructions) and if
+every predicated vector operation needed one 8-chunked scalar register
+each it becomes exceedingly complex very quickly.
+
+Even more than that, in a predicated chaining scenario, when computing
+the mask from a vector "compare", the groupings are troublesome to
+think through how to implement, which is itself a bad sign.  It is
+suspected that chaining will be complex or adversely affected by certain
+combinations of element width.
 
 (see [[masked_vector_chaining]])
 
 
-Overall this idea which initially seems to save resources brings together all the least favourable aspects of other proposals and combines all of them!
+Overall this idea which initially seems to save resources brings together
+all the least favourable aspects of other proposals and combines all
+of them!
diff --git a/simple_v_extension/masked_vector_chaining.mdwn b/simple_v_extension/masked_vector_chaining.mdwn
deleted file mode 100644 (file)
index b1a85ab..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-[[!tag standards]]
-
-# Example execution of vector chaining through masks stored in integer registers
-
-As described in [bug 213 comment 56](https://bugs.libre-soc.org/show_bug.cgi?id=213#c56)
-and [bug 213 comment 53](https://bugs.libre-soc.org/show_bug.cgi?id=213#c53).
-
-See [Chaining on the Cray-1](http://homepages.inf.ed.ac.uk/cgi/rni/comp-arch.pl?Vect/cray1-ch.html,Vect/cray1-ch-f.html,Vect/menu-cr1.html).
-
-Using the following assembly language:
-
-    # starts with VL = 20
-    vec.cmpw.ge r10, r30, r50
-    andc r12, r10, r11
-    vec.fadds f30, f30, f50, mask=r12
-
-The examples assume a computer with a 4x32-bit SIMD integer pipe and a 4x32-bit SIMD FP pipe and a scalar integer pipe.
-
-For ease of viewing, the following examples combines execution pipelines and the scheduling FUs, which are separate things.
-
-## Treating integer registers as whole registers at the scheduler level (chaining\* doesn't work)
-
-Slow because the `fadds` instructions have to wait for all the `cmpw.ge` and `andc` instructions to complete before any can start executing.
-
-| Cycle | SIMD integer pipe                     | SIMD FP pipe                                     | scalar integer pipe              |
-|-------|---------------------------------------|--------------------------------------------------|----------------------------------|
-| 0     | `r10.0-3 <- cmpw.ge r30-31, r50-51`   | waiting on `r12.0-63`                            | waiting on `r10.0-63`            |
-| 1     | `r10.4-7 <- cmpw.ge r32-33, r52-53`   | waiting on `r12.0-63`                            | waiting on `r10.0-63`            |
-| 2     | `r10.8-11 <- cmpw.ge r34-35, r54-55`  | waiting on `r12.0-63`                            | waiting on `r10.0-63`            |
-| 3     | `r10.12-15 <- cmpw.ge r36-37, r56-57` | waiting on `r12.0-63`                            | waiting on `r10.0-63`            |
-| 4     | `r10.16-19 <- cmpw.ge r38-39, r58-59` | waiting on `r12.0-63`                            | waiting on `r10.0-63`            |
-| 5     |                                       | waiting on `r12.0-63`                            | `r12.0-63 <- andc r10.0-63, r11` |
-| 6     |                                       | `f30-31 <- fadds f30-31, f50-51, mask=r12.0-3`   |                                  |
-| 7     |                                       | `f32-33 <- fadds f32-33, f52-53, mask=r12.4-7`   |                                  |
-| 8     |                                       | `f34-35 <- fadds f34-35, f54-55, mask=r12.8-11`  |                                  |
-| 9     |                                       | `f36-37 <- fadds f36-37, f56-57, mask=r12.12-15` |                                  |
-| 10    |                                       | `f38-39 <- fadds f38-39, f58-59, mask=r12.16-19` |                                  |
-
-## Treating integer registers\* as many single-bit registers at the scheduler level (vector chaining works)
-
-\* or at least the register(s) optimized for usage as masks
-
-Faster because `fadds` instructions only have to wait for their vector lanes' mask bits to complete, rather than all vector lanes.
-
-| Cycle | SIMD integer pipe                     | SIMD FP pipe                                     | scalar integer pipe                      |
-|-------|---------------------------------------|--------------------------------------------------|------------------------------------------|
-| 0     | `r10.0-3 <- cmpw.ge r30-31, r50-51`   | waiting on `r12.0-3`                             | waiting on `r10.0-3`                     |
-| 1     | `r10.4-7 <- cmpw.ge r32-33, r52-53`   | waiting on `r12.0-3`                             | `r12.0-3 <- andc r10.0-3, r11.0-3`       |
-| 2     | `r10.8-11 <- cmpw.ge r34-35, r54-55`  | `f30-31 <- fadds f30-31, f50-51, mask=r12.0-3`   | `r12.4-7 <- andc r10.4-7, r11.4-7`       |
-| 3     | `r10.12-15 <- cmpw.ge r36-37, r56-57` | `f32-33 <- fadds f32-33, f52-53, mask=r12.4-7`   | `r12.8-11 <- andc r10.8-11, r11.8-11`    |
-| 4     | `r10.16-19 <- cmpw.ge r38-39, r58-59` | `f34-35 <- fadds f34-35, f54-55, mask=r12.8-11`  | `r12.12-15 <- andc r10.12-15, r11.12-15` |
-| 5     |                                       | `f36-37 <- fadds f36-37, f56-57, mask=r12.12-15` | `r12.16-19 <- andc r10.16-19, r11.16-19` |
-| 6     |                                       | `f38-39 <- fadds f38-39, f58-59, mask=r12.16-19` |                                          |