The SOC is designed to be compliant with POWER 3.0B with somewhere near 300 instructions excluding Vector instructions. # Decoder The Decoder currently 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, being machine-readable in a wide variety of programming languages, are therefore much more convenient for use by other projects beyond 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.