whoops code not quite right
[libreriscv.git] / 3d_gpu / architecture / decoder.mdwn
1 # Decoder
2
3 <http://bugs.libre-riscv.org/show_bug.cgi?id=186>
4
5 The decoder is in charge of translating the POWER instruction stream into operations that can be handled by our backend. It will have an extra input bit, set via a MSR, that will switch on GPU instructions.
6
7 Source code: <https://git.libre-riscv.org/?p=soc.git;a=tree;f=src/soc/decoder;hb=HEAD>
8
9 # POWER
10
11 The decoder has been written in python, to parse straight CSV files and other information taken directly from the Power ISA Standards PDF files. This significantly reduces the possibility of manual transcription errors and greatly reduces code size. Based on Anton Blanchard's excellent microwatt design, these tables are in [[openpower/isatables]] which includes links to download the csv files.
12
13 The top level decoder object recursively drops through progressive levels of case statement groups, covering additional portions of the incoming instruction bits. More on this technique - for which python and nmigen were *specifically* and strategically chosen - is outlined here <http://lists.libre-riscv.org/pipermail/libre-riscv-dev/2020-March/004882.html>
14
15 ## Link to Function Units
16
17 The Decoder (PowerDecode2) knows which registers are needed, however what
18 it does not know is:
19
20 * which Register file ports to connect to (this is defined by regspecs)
21 * the order of those regfile ports (again: defined by regspecs)
22
23 Neither do the Phase-aware Function Units (derived from MultiCompUnit)
24 themselves know anything about the PowerDecoder, and they certainly
25 do not know when a given instruction will need to tell *them* to read
26 RA, or RB. For example: negation of RA only requires one operand,
27 where add RA, RB requires two. Who tells whom that information, when
28 the ALU's job is simply to add, and the Decoder's job is simply to decode?
29
30 This is where a special function called "rdflags()" comes into play.
31 rdflags works closely in conjunction with regspecs and the PowerDecoder2,
32 in each Function Unit's "pipe\_data.py" file. It defines the flags that
33 determine, from current instruction, whether the Function Unit actually
34 *wants* any given Register Read Ports activated or not.
35
36 That dynamically-determined information will then actively disable
37 (or allow) Register file Read requests (rd.req) on a per-port basis.
38
39 * [[architecture/regfiles]]
40 * [CompUnits](https://git.libre-soc.org/?p=soc.git;a=blob;f=src/soc/fu/compunits/compunits.py;hb=HEAD)
41 * [ALU pipe_data.py specification](https://git.libre-soc.org/?p=soc.git;a=blob;f=src/soc/fu/alu/pipe_data.py;hb=HEAD)
42
43 ## Fixed point instructions
44
45 - addi, addis, mulli - fairly straightforward - extract registers and immediate and translate to the appropriate op
46 - addic, addic., subfic - similar to above, but now carry needs to be saved somewhere
47 - add[o][.], subf[o][.], adde\*, subfe\*, addze\*, neg\*, mullw\*, divw\* - These are more fun. They need to set the carry (if . is present) and overflow (if o is present) flags, as well as taking in the carry flag for the extended versions.
48 - addex - uses the overflow flag as a carry in, and if CY is set to 1, sets overflow like it would carry.
49 - cmp, cmpi - sets bits of the selected comparison result register based on whether the comparison result was greater than, less than, or equal to
50 - andi., ori, andis., oris, xori, xoris - similar to above, though the and versions set the flags in CR0
51 - and\*, or\*, xor\*, nand\*, eqv\*, andc\*, orc\* - similar to the register-register arithmetic instructions above
52
53