merge decoder page into existing documentation page
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 9 Jun 2020 21:26:32 +0000 (22:26 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 9 Jun 2020 21:26:32 +0000 (22:26 +0100)
3d_gpu/architecture/decoder.mdwn
Documentation/SOC/index.mdwn

index eb1c6c8d70525fcfc01b22ae887d04b4081281aa..975336e61507c9eb04b8d5b70ba4b43fd80171a4 100644 (file)
@@ -50,4 +50,86 @@ That dynamically-determined information will then actively disable
  - andi., ori, andis., oris, xori, xoris - similar to above, though the and versions set the flags in CR0
  - and\*, or\*, xor\*, nand\*, eqv\*, andc\*, orc\* - similar to the register-register arithmetic instructions above
 
+# Decoder internals
+
+The Decoder uses a class called PowerOp which get instantiated
+for every instruction. PowerOp class instantiation has member signals
+whose values get set respectively for each instruction.
+
+We use Python Enums to help with common decoder values.
+Below is the POWER add insruction.
+
+| opcode       | unit | internal op | in1 | in2 | in3  | out | CR in | CR out | inv A | inv out | cry in | cry out | ldst len | BR | sgn ext | upd | rsrv | 32b | sgn | rc | lk | sgl pipe | comment | form |
+|--------------|------|-------------|-----|-----|------|-----|-------|--------|-------|---------|--------|---------|----------|----|---------|-----|------|-----|-----|----|----|----------|---------|------|
+| 0b0100001010 | ALU  | OP_ADD      | RA  | RB  | NONE | RT  | 0     | 0      | 0     | 0       | ZERO   | 0       | NONE     | 0  | 0       | 0   | 0    | 0   | 0   | RC | 0  | 0        | add     | XO   |
+
+Here is an example of a toy multiplexer that sets various fields in the
+PowerOP signal class to the correct values for the add instruction when
+select is set equal to 1.  This should give you a feel for how we work with
+enums and PowerOP.
+
+    from nmigen import Module, Elaboratable, Signal, Cat, Mux
+    from soc.decoder.power_enums import (Function, Form, InternalOp,
+                             In1Sel, In2Sel, In3Sel, OutSel, RC, LdstLen,
+                             CryIn, get_csv, single_bit_flags,
+                             get_signal_name, default_values)
+    from soc.decoder.power_fields import DecodeFields
+    from soc.decoder.power_fieldsn import SigDecode, SignalBitRange
+    from soc.decoder.power_decoder import PowerOp
+    
+    class Op_Add_Example(Elaboratable):
+        def __init__(self):
+            self.select = Signal(reset_less=True)
+            self.op_add = PowerOp()
+        
+        def elaborate(self, platform):
+            m = Module()
+            op_add = self.op_add
+    
+            with m.If(self.select == 1):
+                m.d.comb += op_add.function_unit.eq(Function.ALU)
+                m.d.comb += op_add.form.eq(Form.XO)
+                m.d.comb += op_add.internal_op.eq(InternalOp.OP_ADD)
+                m.d.comb += op_add.in1_sel.eq(In1Sel.RA)
+                m.d.comb += op_add.in2_sel.eq(In2Sel.RB)
+                m.d.comb += op_add.in3_sel.eq(In3Sel.NONE)
+                m.d.comb += op_add.out_sel.eq(OutSel.RT)
+                m.d.comb += op_add.rc_sel.eq(RC.RC)
+                m.d.comb += op_add.ldst_len.eq(LdstLen.NONE)
+                m.d.comb += op_add.cry_in.eq(CryIn.ZERO)
+            
+            return m
+    
+    from nmigen.back import verilog
+    verilog_file = "op_add_example.v"
+    top = Op_Add_Example()
+    f = open(verilog_file, "w")
+    verilog = verilog.convert(top, name='top', strip_internal_attrs=True,
+                              ports=top.op_add.ports())
+    f.write(verilog)
+    print(f"Verilog Written to: {verilog_file}")
+
+The [actual POWER9 Decoder](https://git.libre-soc.org/?p=soc.git;a=blob;f=src/soc/decoder/power_decoder2.py;hb=HEAD)
+uses this principle, in conjunction with reading the information shown
+in the table above from CSV files (as opposed to hardcoding them in
+python source).  These [[CSV files|openpower/isatables]],
+being machine-readable in a wide variety
+of programming languages, are conveniently available for use by
+other projects well beyond just this SOC.
+
+This also demonstrates one of the design aspects taken in this project: to
+*combine* the power of python's full capabilities in order to create
+advanced dynamically generated HDL, rather than (as done with MyHDL)
+limit python code to a subset of its full capabilities.
+
+The CSV Files are loaded by
+[power_decoder.py](https://git.libre-soc.org/?p=soc.git;a=blob;f=src/soc/decoder/power_decoder.py;hb=HEAD)
+and are used to construct a hierarchical cascade of switch statements.  The original code came from
+[microwatt](https://github.com/antonblanchard/microwatt/blob/master/decode1.vhdl)
+where the original hardcoded cascade can be seen.
+
+The docstring for power_decoder.py gives more details: each level in the hierarchy, just as in the original decode1.vhdl, will take slices of the instruction bitpattern, match against it, and if successful will continue with further subdecoders until a line is met that contains the required Operand Information (a PowerOp) exactly as shown at the top of this page.
+
+In this way, different sections of the instruction are successively decoded (major opcode, then minor opcode, then sub-patterns under those) until the required instruction is fully recognised, and the hierarchical cascade of switch patterns results in a flat interpretation being produced that is useful internally. 
+
 
index 502b690304b18b413893e783170285a950340d67..26c45d581f21ee528278ed0c20f5374ec8a0b6d5 100644 (file)
@@ -3,84 +3,4 @@ The SOC is designed to be compliant with POWER 3.0B with somewhere near
 
 # Decoder
 
-The Decoder uses a class called PowerOp which get instantiated
-for every instruction. PowerOp class instantiation has member signals
-whose values get set respectively for each instruction.
-
-We use Python Enums to help with common decoder values.
-Below is the POWER add insruction.
-
-| opcode       | unit | internal op | in1 | in2 | in3  | out | CR in | CR out | inv A | inv out | cry in | cry out | ldst len | BR | sgn ext | upd | rsrv | 32b | sgn | rc | lk | sgl pipe | comment | form |
-|--------------|------|-------------|-----|-----|------|-----|-------|--------|-------|---------|--------|---------|----------|----|---------|-----|------|-----|-----|----|----|----------|---------|------|
-| 0b0100001010 | ALU  | OP_ADD      | RA  | RB  | NONE | RT  | 0     | 0      | 0     | 0       | ZERO   | 0       | NONE     | 0  | 0       | 0   | 0    | 0   | 0   | RC | 0  | 0        | add     | XO   |
-
-Here is an example of a toy multiplexer that sets various fields in the
-PowerOP signal class to the correct values for the add instruction when
-select is set equal to 1.  This should give you a feel for how we work with
-enums and PowerOP.
-
-    from nmigen import Module, Elaboratable, Signal, Cat, Mux
-    from soc.decoder.power_enums import (Function, Form, InternalOp,
-                             In1Sel, In2Sel, In3Sel, OutSel, RC, LdstLen,
-                             CryIn, get_csv, single_bit_flags,
-                             get_signal_name, default_values)
-    from soc.decoder.power_fields import DecodeFields
-    from soc.decoder.power_fieldsn import SigDecode, SignalBitRange
-    from soc.decoder.power_decoder import PowerOp
-    
-    class Op_Add_Example(Elaboratable):
-        def __init__(self):
-            self.select = Signal(reset_less=True)
-            self.op_add = PowerOp()
-        
-        def elaborate(self, platform):
-            m = Module()
-            op_add = self.op_add
-    
-            with m.If(self.select == 1):
-                m.d.comb += op_add.function_unit.eq(Function.ALU)
-                m.d.comb += op_add.form.eq(Form.XO)
-                m.d.comb += op_add.internal_op.eq(InternalOp.OP_ADD)
-                m.d.comb += op_add.in1_sel.eq(In1Sel.RA)
-                m.d.comb += op_add.in2_sel.eq(In2Sel.RB)
-                m.d.comb += op_add.in3_sel.eq(In3Sel.NONE)
-                m.d.comb += op_add.out_sel.eq(OutSel.RT)
-                m.d.comb += op_add.rc_sel.eq(RC.RC)
-                m.d.comb += op_add.ldst_len.eq(LdstLen.NONE)
-                m.d.comb += op_add.cry_in.eq(CryIn.ZERO)
-            
-            return m
-    
-    from nmigen.back import verilog
-    verilog_file = "op_add_example.v"
-    top = Op_Add_Example()
-    f = open(verilog_file, "w")
-    verilog = verilog.convert(top, name='top', strip_internal_attrs=True,
-                              ports=top.op_add.ports())
-    f.write(verilog)
-    print(f"Verilog Written to: {verilog_file}")
-
-The [actual POWER9 Decoder](https://git.libre-soc.org/?p=soc.git;a=blob;f=src/soc/decoder/power_decoder2.py;hb=HEAD)
-uses this principle, in conjunction with reading the information shown
-in the table above from CSV files (as opposed to hardcoding them in
-python source).  These [[CSV files|openpower/isatables]],
-being machine-readable in a wide variety
-of programming languages, are conveniently available for use by
-other projects well beyond just this SOC.
-
-This also demonstrates one of the design aspects taken in this project: to
-*combine* the power of python's full capabilities in order to create
-advanced dynamically generated HDL, rather than (as done with MyHDL)
-limit python code to a subset of its full capabilities.
-
-The CSV Files are loaded by
-[power_decoder.py](https://git.libre-soc.org/?p=soc.git;a=blob;f=src/soc/decoder/power_decoder.py;hb=HEAD)
-and are used to construct a hierarchical cascade of switch statements.  The original code came from
-[microwatt](https://github.com/antonblanchard/microwatt/blob/master/decode1.vhdl)
-where the original hardcoded cascade can be seen.
-
-The docstring for power_decoder.py gives more details: each level in the hierarchy, just as in the original decode1.vhdl, will take slices of the instruction bitpattern, match against it, and if successful will continue with further subdecoders until a line is met that contains the required Operand Information (a PowerOp) exactly as shown at the top of this page.
-
-In this way, different sections of the instruction are successively decoded (major opcode, then minor opcode, then sub-patterns under those) until the required instruction is fully recognised, and the hierarchical cascade of switch patterns results in a flat interpretation being produced that is useful internally. 
-
-
+The page on the decoder is here: [[architecture/decoder]]