(no commit message)
[libreriscv.git] / Documentation / SOC / index.mdwn
1 The SOC is designed to be compliant with POWER 3.0B with somewhere near
2 300 instructions excluding Vector instructions.
3
4 # Decoder
5
6 The Decoder currently uses a class called PowerOp which get instantiated
7 for every instruction. PowerOp class instantiation has member signals
8 whose values get set respectively for each instruction.
9
10 We use Python Enums to help with common decoder values.
11 Below is the POWER add insruction.
12
13 | 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 |
14 |--------------|------|-------------|-----|-----|------|-----|-------|--------|-------|---------|--------|---------|----------|----|---------|-----|------|-----|-----|----|----|----------|---------|------|
15 | 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 |
16
17 Here is an example of a toy multiplexer that sets various fields in the
18 PowerOP signal class to the correct values for the add instruction when
19 select is set equal to 1. This should give you a feel for how we work with
20 enums and PowerOP.
21
22 from nmigen import Module, Elaboratable, Signal, Cat, Mux
23 from soc.decoder.power_enums import (Function, Form, InternalOp,
24 In1Sel, In2Sel, In3Sel, OutSel, RC, LdstLen,
25 CryIn, get_csv, single_bit_flags,
26 get_signal_name, default_values)
27 from soc.decoder.power_fields import DecodeFields
28 from soc.decoder.power_fieldsn import SigDecode, SignalBitRange
29 from soc.decoder.power_decoder import PowerOp
30
31 class Op_Add_Example(Elaboratable):
32 def __init__(self):
33 self.select = Signal(reset_less=True)
34 self.op_add = PowerOp()
35
36 def elaborate(self, platform):
37 m = Module()
38 op_add = self.op_add
39
40 with m.If(self.select == 1):
41 m.d.comb += op_add.function_unit.eq(Function.ALU)
42 m.d.comb += op_add.form.eq(Form.XO)
43 m.d.comb += op_add.internal_op.eq(InternalOp.OP_ADD)
44 m.d.comb += op_add.in1_sel.eq(In1Sel.RA)
45 m.d.comb += op_add.in2_sel.eq(In2Sel.RB)
46 m.d.comb += op_add.in3_sel.eq(In3Sel.NONE)
47 m.d.comb += op_add.out_sel.eq(OutSel.RT)
48 m.d.comb += op_add.rc_sel.eq(RC.RC)
49 m.d.comb += op_add.ldst_len.eq(LdstLen.NONE)
50 m.d.comb += op_add.cry_in.eq(CryIn.ZERO)
51
52 return m
53
54 from nmigen.back import verilog
55 verilog_file = "op_add_example.v"
56 top = Op_Add_Example()
57 f = open(verilog_file, "w")
58 verilog = verilog.convert(top, name='top', strip_internal_attrs=True,
59 ports=top.op_add.ports())
60 f.write(verilog)
61 print(f"Verilog Written to: {verilog_file}")
62
63 The [actual POWER9 Decoder](https://git.libre-soc.org/?p=soc.git;a=blob;f=src/soc/decoder/power_decoder2.py;hb=HEAD)
64 uses this principle, in conjunction with reading the information shown
65 in the table above from CSV files (as opposed to hardcoding them in
66 python source). These [[CSV files|openpower/isatables]],
67 being machine-readable in a wide variety
68 of programming languages, are conveniently available for use by
69 other projects well beyond just this SOC.
70
71 This also demonstrates one of the design aspects taken in this project: to
72 *combine* the power of python's full capabilities in order to create
73 advanced dynamically generated HDL, rather than (as done with MyHDL)
74 limit python code to a subset of its full capabilities.
75
76 The CSV Files are loaded by
77 [power_decoder.py](https://git.libre-soc.org/?p=soc.git;a=blob;f=src/soc/decoder/power_decoder.py;hb=HEAD)
78 and are usedto construct a hierarchical cascade of switch statements. The original code came from
79 [microwatt](https://github.com/antonblanchard/microwatt/blob/master/decode1.vhdl)
80 where the original hardcoded cascade can be seen.
81
82 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.
83
84 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.
85
86