Add signals for single bit flags in major.csv
[soc.git] / src / decoder / power_major_decoder.py
1 from nmigen import Module, Elaboratable, Signal
2 import csv
3 import os
4 from enum import Enum, unique
5
6
7 @unique
8 class Function(Enum):
9 ALU = 0
10 LDST = 1
11
12
13 @unique
14 class InternalOp(Enum):
15 OP_ADD = 0
16 OP_AND = 1
17 OP_B = 2
18 OP_BC = 3
19 OP_CMP = 4
20 OP_LOAD = 5
21 OP_MUL_L64 = 6
22 OP_OR = 7
23 OP_RLC = 8
24 OP_STORE = 9
25 OP_TDI = 10
26 OP_XOR = 11
27
28
29 @unique
30 class In1Sel(Enum):
31 RA = 0
32 RA_OR_ZERO = 1
33 NONE = 2
34 SPR = 3
35
36
37 @unique
38 class In2Sel(Enum):
39 CONST_SI = 0
40 CONST_SI_HI = 1
41 CONST_UI = 2
42 CONST_UI_HI = 3
43 CONST_LI = 4
44 CONST_BD = 5
45 CONST_SH32 = 6
46 RB = 7
47
48
49 @unique
50 class In3Sel(Enum):
51 NONE = 0
52 RS = 1
53
54
55 @unique
56 class OutSel(Enum):
57 RT = 0
58 RA = 1
59 NONE = 2
60 SPR = 3
61
62
63 # names of the fields in major.csv that don't correspond to an enum
64 single_bit_flags = ['CR in', 'CR out', 'inv A', 'inv out', 'cry in',
65 'cry out', 'BR', 'sgn ext', 'upd', 'rsrv', '32b',
66 'sgn', 'lk', 'sgl pipe']
67
68
69 def get_signal_name(name):
70 return name.lower().replace(' ', '_')
71
72
73 def get_csv(name):
74 file_dir = os.path.dirname(os.path.realpath(__file__))
75 with open(os.path.join(file_dir, name)) as csvfile:
76 reader = csv.DictReader(csvfile)
77 return list(reader)
78
79
80 major_opcodes = get_csv("major.csv")
81
82
83 class PowerMajorDecoder(Elaboratable):
84 def __init__(self):
85 self.opcode_in = Signal(6, reset_less=True)
86
87 self.function_unit = Signal(Function, reset_less=True)
88 self.internal_op = Signal(InternalOp, reset_less=True)
89 self.in1_sel = Signal(In1Sel, reset_less=True)
90 self.in2_sel = Signal(In2Sel, reset_less=True)
91 self.in3_sel = Signal(In3Sel, reset_less=True)
92 self.out_sel = Signal(OutSel, reset_less=True)
93 for bit in single_bit_flags:
94 name = get_signal_name(bit)
95 setattr(self, name,
96 Signal(reset_less=True, name=name))
97
98 def elaborate(self, platform):
99 m = Module()
100 comb = m.d.comb
101
102 with m.Switch(self.opcode_in):
103 for row in major_opcodes:
104 opcode = int(row['opcode'])
105 with m.Case(opcode):
106 comb += self.function_unit.eq(Function[row['unit']])
107 comb += self.internal_op.eq(InternalOp[row['internal op']])
108 comb += self.in1_sel.eq(In1Sel[row['in1']])
109 comb += self.in2_sel.eq(In2Sel[row['in2']])
110 comb += self.in3_sel.eq(In3Sel[row['in3']])
111 comb += self.out_sel.eq(OutSel[row['out']])
112 for bit in single_bit_flags:
113 sig = getattr(self, get_signal_name(bit))
114 comb += sig.eq(int(row[bit]))
115 return m
116
117 def ports(self):
118 regular =[self.opcode_in,
119 self.function_unit,
120 self.in1_sel,
121 self.in2_sel,
122 self.in3_sel,
123 self.out_sel,
124 self.internal_op]
125 single_bit_ports = [getattr(self, get_signal_name(x))
126 for x in single_bit_flags]
127 return regular + single_bit_ports