Copy edit update 005
authorJoshua Harlan Lifton <joshua.harlan.lifton@gmail.com>
Fri, 8 Feb 2019 03:19:37 +0000 (19:19 -0800)
committerJoshua Harlan Lifton <joshua.harlan.lifton@gmail.com>
Fri, 8 Feb 2019 03:19:37 +0000 (19:19 -0800)
updates/005_2018dec14_simd_without_simd.mdwn

index 65487291e7197b538af29710b756546dc6ce274b..b33158fa628860ca19d9cd75a619118a6aeb6852 100644 (file)
-# Microarchitectural Design by Osmosis
-
-In a series of different descriptions and evaluations, a picture is
-beginning to emerge of a suitable microarchitecture, as the process
-of talking on [videos](https://youtu.be/DoZrGJIltgU), and 
-[writing out thoughts](https://groups.google.com/forum/#!topic/comp.arch/2kYGFU4ppow)
-and then talking about the resultant feedback
-[elsewhere](http://lists.libre-riscv.org/pipermail/libre-riscv-dev/2018-December/000261.html)
-begins to crystallise, without overloading any one group of people.
-
-There are several things to remember about this design: the primary being
-that it is not explicitly intended as a discrete GPU (although one could
-be made), it is primarily for a battery-operated efficient hand-held device,
-where it happens to just about pass on, say, a low to mid-range chromebook.
-Power consumption *for the entire chip* is targetted at 2.5 watts.
-
-We learned quite quickly that, paradoxically, even a mobile embedded 3D
-GPU *requires* extreme numbers of registers (128 floating-point registers)
-because it is handling vectors (or quads as they are called), and even
-pixel data in floating-point format is also 4 32-bit numbers (including
-the transparency).  So where a "normal" RISC processor has 32 registers,
-a GPU typically has to have 4 times that amount simply because it is
-dealing with 4 lots of numbers simultaneously.  If you don't do this,
-then that data has to go back down to memory (even to L1 cache), and, as the
-L1 cache runs a CAM, it's guaranteed to be power-hungry.
-
-128 registers brings some unique challenges not normally faced by general
-purpose CPUs, and when it becomes possible (or a requirement) to access
-even down to the byte level of those 64-bit registers as "elements" in
-a vector operation, it is even more challenging.  Recall Mitch Alsup's
-scoreboard dependency floorplan (reproduced with kind permission, here):
-
-{{mitch_ld_st_augmentation.jpg}}
-
-There are two key Dependency Matrices here: on the left is the Function
-Unit (rows) to Register File (columns), where you can see at the bottom
-in the CDC 6600 the Register File is divided down into A, B and X.
-On the right is the Function Unit to Function Unit dependency matrix,
-which ensures that each FU only starts its arithmetic operations when
-its dependent FUs have created the results it needs.  Thus, that Matrix
-expresses source register to destination register dependencies.
-
-Now let's do something hair-raising.  Let's do two crazed things at once:
+Spread over various [videos](https://youtu.be/DoZrGJIltgU),
+[writings](https://groups.google.com/forum/#!topic/comp.arch/2kYGFU4ppow),
+and [mailing list
+discussions](http://lists.libre-riscv.org/pipermail/libre-riscv-dev/2018-December/000261.html),
+a picture is beginning to emerge of a suibable microarchitecture.
+
+There are several things to remember about this design, the primary
+being that it is not explicitly intended as a discrete GPU (although
+one could be made). Instead, it is primarily for a battery-operated,
+power-efficient hand-held device, where it happens to just about pass
+on, say, a low to mid-range chromebook.  Power consumption *for the
+entire chip* is targetted at 2.5 watts.
+
+We learned quite quickly that, paradoxically, even a mobile embedded
+3D GPU *requires* extreme an number of registers (128 floating-point
+registers) because it is handling vectors (or quads as they are
+called), and even pixel data, in floating-point format, which means
+four 32-bit numbers (including the transparency).  So, where a
+"normal" RISC processor has 32 registers, a GPU typically has to have
+four times that many simply because it is dealing with four lots of
+numbers simultaneously.  If you don't do this, then that data has to
+go back down to memory (even to L1 cache), and, as the L1 cache runs a
+CAM, it's guaranteed to be power-hungry.
+
+Dealing with 128 registers brings some unique challenges not normally
+faced by general purpose CPUs, and when it becomes possible (or a
+requirement) to access even down to the byte level of those 64-bit
+registers as "elements" in a vector operation, it is even more
+challenging.  Recall Mitch Alsup's scoreboard dependency floorplan
+(reproduced with kind permission, here):
+
+{mitch-ld-st-augmentation | link}
+
+There are two key dependency matrices here: on the left is the
+function unit (rows) to register file (columns), where you can see at
+the bottom in the CDC 6600 the register file is divided down into A, B
+and X.  On the right is the function unit to function unit dependency
+matrix, which ensures that each function unit only starts its
+arithmetic operations when its dependent function units have created
+the results it needs.  Thus, that matrix expresses source register to
+destination register dependencies.
+
+Now, let's do something hair-raising.  Let's do two crazed things at once:
 increase the number of registers to a whopping 256 total (128 floating
 point and 128 integer), and at the same time allow those 64-bit registers
 to be broken down into **eight** separate 8-bit values... *and allow
 increase the number of registers to a whopping 256 total (128 floating
 point and 128 integer), and at the same time allow those 64-bit registers
 to be broken down into **eight** separate 8-bit values... *and allow
-Function Unit dependencies to exist on them*!
-
-What would happen if we did not properly take this into account in the
-design is that an 8-bit ADD would require us to "lock" say Register R5
-(all 64 bits of it), absolutely preventing and prohibiting the other 7
-bytes of R5 from being used, until such time as that extremely small
-8-bit ADD had completed.  Such a design would be laughed at, its
-performance would be so low.  Only one 8-bit ADD per clock cycle, when
-Intel has recently added 512-bit SIMD??
-
-So this is a diagram of a proposed solution.  What if, when an 8-bit
-operation needs to do a calculation to go into the 1st byte, the other
-7 bytes have their own **completely separate** dependency lines, in
-the Register and Function Unit Matrices?  It looks like this:
-
-{{reorder_alias_bytemask_scheme.png}}
-
-So if you recall from the previous updates about Scoreboards, it's not
-the "scoreboard" that's the key, it's these Register to Function Unit
-and FU to FU Dependency Matrices that are the misunderstood key.
-So let's explain this diagram.  Firstly, in purple in the bottom left
-is a massive matrix of FU to FU, just as with the standard CDC 6600,
-except now there are separate 32-bit FUs, 16-bit FUs, and 8-bit FUs.
-In this way, we can have 32-bit ADD depending on and waiting for
-an 8-bit computation, or 16-bit MUL on a 32-bit SQRT and so on.  Nothing
-immediately obviously different there.
+function unit dependencies to exist on them*!
+
+If we didn't properly take this into account in the design, then an
+8-bit ADD would require us to "lock", say, Register R5 (all 64 bits of
+it), absolutely preventing and prohibiting the other seven bytes of R5
+from being used, until such time as that extremely small 8-bit ADD had
+completed.  Such a design would be laughed at, its performance would
+be so low.  Only one 8-bit ADD per clock cycle, when Intel has
+recently added 512-bit [SIMD](https://en.wikipedia.org/wiki/SIMD)?
+
+Here's a proposed solution.  What if, when an 8-bit operation needs to
+do a calculation to go into the first byte, the other seven bytes have
+their own **completely separate** dependency lines in the register and
+function unit matrices? It looks like this:
+
+{reorder-alias-bytemask-scheme | link}
+
+If you recall from the [previous updates about
+scoreboards](https://www.crowdsupply.com/libre-risc-v/m-class/updates),
+it's not the "scoreboard" that's the key, it's these register to
+function unit and function unit to function unit dependency matrices
+that are the misunderstood key.  Let's explain the above diagram.
+Firstly, in purple in the bottom left, is a massive matrix of function
+units to function units, just as with the standard CDC 6600, except
+now there are separate 32-bit function units, 16-bit function units,
+and 8-bit function units.  In this way, we can have a 32-bit ADD
+depending on and waiting for an 8-bit computation, or a 16-bit MUL on
+a 32-bit SQRT and so on.  Nothing obviously different there.
 
 Likewise, in the bottom right, in red, we see matrices that have
 
 Likewise, in the bottom right, in red, we see matrices that have
-FU along rows, and Registers along the columns, exactly again as with
-the CDC 6600 standard scoreboard: however, again, we note that
-because there are separate 32-bit FUs and separate 16-bit and 8-bit
-FUs, there are *three* separate sets of FU-to-Register Matrices.
-Also, note that these are separate, where they would be expected
-to be grouped together.  Except, they're *not* independent, and that's
-where the diagram at the top (middle) comes in.
+function units along rows, and registers along the columns, exactly
+again as with the CDC 6600 standard scoreboard. However, again, we
+note that because there are separate 32-bit function units and
+separate 16-bit and 8-bit function units, there are *three* separate
+sets of function unit to register matrices.  Also, note that these are
+separate, where they would be expected to be grouped together.
+Except, they're *not* independent, and that's where the diagram at the
+top (middle) comes in.
 
 The diagram at the top says, in words, "if you need a 32-bit register
 
 The diagram at the top says, in words, "if you need a 32-bit register
-for an operation (using a 32-bit Function Unit), the 16-bit and 8-bit
-Function Units *also* connected to that exact same register **must**
-be prevented from occuring.  Also, if you need 8 bits of a register,
+for an operation (using a 32-bit function unit), the 16-bit and 8-bit
+function units *also* connected to that exact same register **must**
+be prevented from occurring.  Also, if you need eight bits of a register,
 whilst it does not prevent the other bytes of the register from being
 used, it *does* prevent the overlapping 16-bit portion **and the 32-bit
 whilst it does not prevent the other bytes of the register from being
 used, it *does* prevent the overlapping 16-bit portion **and the 32-bit
-and the 64-bit** portions of that same named register from being used".
+and the 64-bit** portions of that same named register from being used."
 
 
-This is absolutely essential to understand, this "cascading" relationship.
-Need Register R1 (all of it), you **cannot** go and allocate any of that
-register for use in any 32-bit, 16-bit or 8-bit operations.  This is
-common sense!  However, if you use the lowest byte (byte 1), you can still
-use the top three 16-bit portions of R1, and you can also still use byte 2.
-This is also common sense!
+This "cascading" relationship is absolutely essential to understand.
+If you need register R1 (all of it), you **cannot** go and allocate
+any of that register for use in any 32-bit, 16-bit, or 8-bit
+operations.  This is common sense!  However, if you use the lowest
+byte (byte 1), you can still use the top three 16-bit portions of R1,
+and you can also still use byte 2.  This is also common sense!
 
 So in fact, it's actually quite simple, and this "cascade" is simply and
 
 So in fact, it's actually quite simple, and this "cascade" is simply and
-easily propagated down to the Function Unit Dependency Matrices, stopping
+easily propagated down to the function unit dependency matrices, stopping
 32-bit operations from overwriting 8-bit and vice-versa.
 
 32-bit operations from overwriting 8-bit and vice-versa.
 
-# Virtual Registers
-
-The fourth part is the grid in green, in the top left corner.  This is
-a "virtual" to "real" one-bit table.  It's here because the size of
-these matrices is so enormous that there is deep concern about the line
-driver strength, as well as the actual size.  128 registers means
-that one single gate, when it goes high or low, has to "drive" the
-input of 128 other gates.  That takes longer and longer to do, the higher
-the number of gates, so it becomes a critical factor in determining the
-maximum speed of the entire processor.  We will have to keep an eye
-on this.
-
-So, to keep the FU to Register matrix size down, this "virtual" register
-concept was introduced.  Only one bit in each row of the green table
-may be active: it says, for example, "IR1 actually represents that there
-is an instruction being executed using R3".  This does mean however that
-if this table is not high enough (not enough IRs), the processor has to
-stall until an instruction is completed, so that one register becomes
-free.  Again, another thing to keep an eye on, in simulations.
-
-# Refinements
-
-The second major concern is the purple matrix: the FU-to-FU one.  Basically
-where previously we would have FU1 cover all ADDs, FU2 would cover all MUL
-operations, FU3 covers BRANCH and so on, now we have to multiply those
-numbers by **four** (64-bit ops, 32-bit ops, 16-bit and 8), which in turn
-means that the size of the FU-to-FU Matrix has gone up by a staggering
-**sixteen** times.  This is not really acceptable, so we have to do something
-different.
-
-So the refinement is based on an observation that 16-bit operations of
-course may be constructed from 8-bit values, and that 64-bit operations
-can be constructed from 32-bit ones.  So, what if we skipped the
-cascade on 64 and 16 bit, and made the cascade out of just 32-bit and 8-bit?
-Then, very simply, the top half of a 64-bit source register is allocated
-to one Function Unit, the bottom half to the one next to it, and when it
-comes to actually passing the source registers to the relevant ALU, take
-from *both* FUs.
-
-The primary focus is on 32-bit (single-precision floating-point) performance
-anyway, for 3D, so if 64-bit operations happen to have half the number of
-Reservation Stations / Function Units, and block more often, we actually
-don't mind so much.  Also, we can still apply the same "banks" trick on
-the Register File, except this time with 4-way multiplexing on 32-bit
-wide banks, and 4x4 crossbars on the bytes as well:
-
-{{register_file_multiplexing.jpg}}
-
-To cope with 16-bit operations, pairs of 8-bit values in adjacent Function
-Units are reserved.  Likewise for 64-bit operations, the 8-bit crossbars
+### Virtual Registers
+
+The fourth part of the above diagram is the grid in green, in the top
+left corner.  This is a "virtual" to "real" one-bit table.  It's here
+because the size of these matrices is so enormous that there is deep
+concern about the line driver strength, as well as the actual size.
+128 registers means that one single gate, when it goes high or low,
+has to "drive" the input of 128 other gates.  That takes longer and
+longer to do, the higher the number of gates, so it becomes a critical
+factor in determining the maximum speed of the entire processor.  We
+will have to keep an eye on this.
+
+So, to keep the function unit to register matrix size down, this
+"virtual" register concept was introduced.  Only one bit in each row
+of the green table may be active: it says, for example, "IR1 actually
+represents that there is an instruction being executed using R3."
+This does mean, however, that if this table is not high enough (not
+enough IRs), the processor has to stall until an instruction is
+completed, so that one register becomes free.  Again, another thing to
+keep an eye on, in simulations.
+
+### Refinements
+
+The second major concern is the purple matrix, the function unit to
+function unit one.  Basically, where previously we would have FU1
+cover all ADDs, FU2 would cover all MUL operations, FU3 covers BRANCH,
+and so on, now we have to multiply those numbers by **four** (64-bit
+ops, 32-bit ops, 16-bit, and 8), which in turn means that the size of
+the FU-to-FU matrix has gone up by a staggering **sixteen** times.
+This is not really acceptable, so we have to do something different.
+
+The refinement is based on an observation that 16-bit operations of
+course may be constructed from 8-bit values, and that 64-bit
+operations can be constructed from 32-bit ones.  So, what if we
+skipped the cascade on 64 and 16 bit, and made the cascade out of just
+32-bit and 8-bit?  Then, very simply, the top half of a 64-bit source
+register is allocated to one function unit, the bottom half to the one
+next to it, and when it comes to actually passing the source registers
+to the relevant ALU, take from *both* function units.
+
+For 3D, the primary focus is on 32-bit (single-precision
+floating-point) performance anyway, so if 64-bit operations happen to
+have half the number of reservation stations / function units, and
+block more often, we actually don't mind so much.  Also, we can still
+apply the same "banks" trick on the register file, except this time
+with four-way multiplexing on 32-bit wide banks, and 4 x 4 crossbars
+on the bytes as well:
+
+{register-file-multiplexing | link}
+
+To cope with 16-bit operations, pairs of 8-bit values in adjacent function
+units are reserved.  Likewise for 64-bit operations, the 8-bit crossbars
 are not used, and pairs of 32-bit source values in adjacent Function Units
 are not used, and pairs of 32-bit source values in adjacent Function Units
-in the *32-bit* FU area are reserved.
+in the *32-bit* function unit area are reserved.
 
 
-However, the gate count in such a staggered crossbar arrangement is insane:
-bear in mind that this will be 3R1W or 2R1W (2 or 3 reads, 1 write per
-register), and that means **three** sets of crossbars, comprising **four**
-banks, with effectively 16 byte to 16 byte routing.
+However, the gate count in such a staggered crossbar arrangement is
+insane: bear in mind that this will be 3R1W or 2R1W (2 or 3 reads, 1
+write per register), and that means **three** sets of crossbars,
+comprising **four** banks, with effectively 16 byte to 16 byte
+routing.
 
 It's too much - so in later updates, this will be explored further.
 
 It's too much - so in later updates, this will be explored further.