dcache.py commit first full tranlation pass, about five percent left
[soc.git] / src / soc / fu / cr / main_stage.py
1 # This stage is intended to do Condition Register instructions (and ISEL)
2 # and output, as well as carry and overflow generation.
3 # NOTE: with the exception of mtcrf and mfcr, we really should be doing
4 # the field decoding which
5 # selects which bits of CR are to be read / written, back in the
6 # decoder / insn-isue, have both self.i.cr and self.o.cr
7 # be broken down into 4-bit-wide "registers", with their
8 # own "Register File" (indexed by bt, ba and bb),
9 # exactly how INT regs are done (by RA, RB, RS and RT)
10 # however we are pushed for time so do it as *one* register.
11
12 from nmigen import (Module, Signal, Cat, Repl, Mux, Const, Array)
13 from nmutil.pipemodbase import PipeModBase
14 from soc.fu.cr.pipe_data import CRInputData, CROutputData
15 from soc.decoder.power_enums import MicrOp
16
17 from soc.decoder.power_fields import DecodeFields
18 from soc.decoder.power_fieldsn import SignalBitRange
19
20
21 class CRMainStage(PipeModBase):
22 def __init__(self, pspec):
23 super().__init__(pspec, "main")
24 self.fields = DecodeFields(SignalBitRange, [self.i.ctx.op.insn])
25 self.fields.create_specs()
26
27 def ispec(self):
28 return CRInputData(self.pspec)
29
30 def ospec(self):
31 return CROutputData(self.pspec)
32
33 def elaborate(self, platform):
34 m = Module()
35 comb = m.d.comb
36 op = self.i.ctx.op
37 a, b, full_cr = self.i.a, self.i.b, self.i.full_cr
38 cr_a, cr_b, cr_c = self.i.cr_a, self.i.cr_b, self.i.cr_c
39 cr_o, full_cr_o, rt_o = self.o.cr, self.o.full_cr, self.o.o
40
41 xl_fields = self.fields.FormXL
42 xfx_fields = self.fields.FormXFX
43
44 # Generate the mask for mtcrf, mtocrf, and mfocrf
45 # replicate every fxm field in the insn to 4-bit, as a mask
46 FXM = xfx_fields.FXM[0:-1]
47 mask = Signal(32, reset_less=True)
48 comb += mask.eq(Cat(*[Repl(FXM[i], 4) for i in range(8)]))
49
50 # Generate array of bits for cr_a, cr_b and cr_c
51 cr_a_arr = Array([cr_a[i] for i in range(4)])
52 cr_b_arr = Array([cr_b[i] for i in range(4)])
53 cr_o_arr = Array([cr_o[i] for i in range(4)])
54
55 with m.Switch(op.insn_type):
56 ##### mcrf #####
57 with m.Case(MicrOp.OP_MCRF):
58 # MCRF copies the 4 bits of crA to crB (for instance
59 # copying cr2 to cr1)
60 # Since it takes in a 4 bit cr, and outputs a 4 bit
61 # cr, we don't have to do anything special
62 comb += cr_o.eq(cr_a)
63 comb += cr_o.ok.eq(1) # indicate "this CR has changed"
64
65 # ##### crand, cror, crnor etc. #####
66 with m.Case(MicrOp.OP_CROP):
67 # crand/cror and friends get decoded to the same opcode, but
68 # one of the fields inside the instruction is a 4 bit lookup
69 # table. This lookup table gets indexed by bits a and b from
70 # the CR to determine what the resulting bit should be.
71
72 # Grab the lookup table for cr_op type instructions
73 lut = Signal(4, reset_less=True)
74 # There's no field, just have to grab it directly from the insn
75 comb += lut.eq(op.insn[6:10])
76
77 # Get the bit selector fields from the
78 # instruction. This operation takes in the little CR
79 # bitfields, so these fields need to get truncated to
80 # the least significant 2 bits
81 BT = xl_fields.BT[0:-1]
82 BA = xl_fields.BA[0:-1]
83 BB = xl_fields.BB[0:-1]
84 bt = Signal(2, reset_less=True)
85 ba = Signal(2, reset_less=True)
86 bb = Signal(2, reset_less=True)
87
88 # Stupid bit ordering stuff. Because POWER.
89 comb += bt.eq(3-BT[0:2])
90 comb += ba.eq(3-BA[0:2])
91 comb += bb.eq(3-BB[0:2])
92
93 # Extract the two input bits from the CRs
94 bit_a = Signal(reset_less=True)
95 bit_b = Signal(reset_less=True)
96 comb += bit_a.eq(cr_a_arr[ba])
97 comb += bit_b.eq(cr_b_arr[bb])
98
99 # look up the output bit in the lookup table
100 bit_o = Signal()
101 comb += bit_o.eq(Mux(bit_b,
102 Mux(bit_a, lut[3], lut[1]),
103 Mux(bit_a, lut[2], lut[0])))
104
105 # may have one bit modified by OP_CROP. copy the other 3
106 comb += cr_o.data.eq(cr_c)
107 # insert the (index-targetted) output bit into 4-bit CR output
108 comb += cr_o_arr[bt].eq(bit_o)
109 comb += cr_o.ok.eq(1) # indicate "this CR has changed"
110
111 ##### mtcrf #####
112 with m.Case(MicrOp.OP_MTCRF):
113 # mtocrf and mtcrf are essentially identical
114 # put input (RA) - mask-selected - into output CR, leave
115 # rest of CR alone.
116 comb += full_cr_o.data.eq((a[0:32] & mask) | (full_cr & ~mask))
117 comb += full_cr_o.ok.eq(1) # indicate "this CR has changed"
118
119 # ##### mfcr #####
120 with m.Case(MicrOp.OP_MFCR):
121 # Ugh. mtocrf and mtcrf have one random bit differentiating
122 # them. This bit is not in any particular field, so this
123 # extracts that bit from the instruction
124 move_one = Signal(reset_less=True)
125 comb += move_one.eq(op.insn[20])
126
127 # mfocrf
128 with m.If(move_one):
129 # output register RT
130 comb += rt_o.data.eq(full_cr & mask)
131 # mfcrf
132 with m.Else():
133 # output register RT
134 comb += rt_o.data.eq(full_cr)
135 comb += rt_o.ok.eq(1) # indicate "INT reg changed"
136
137 # ##### isel #####
138 with m.Case(MicrOp.OP_ISEL):
139 # just like in branch, CR0-7 is incoming into cr_a, we
140 # need to select from the last 2 bits of BC
141 a_fields = self.fields.FormA
142 BC = a_fields.BC[0:-1][0:2]
143 cr_bits = Array([cr_a[3-i] for i in range(4)])
144
145 # The bit of (cr_a=CR0-7) selected by BC
146 cr_bit = Signal(reset_less=True)
147 comb += cr_bit.eq(cr_bits[BC])
148
149 # select a or b as output
150 comb += rt_o.eq(Mux(cr_bit, a, b))
151 comb += rt_o.ok.eq(1) # indicate "INT reg changed"
152
153 with m.Case(MicrOp.OP_SETB):
154 with m.If(cr_a[3]):
155 comb += rt_o.data.eq(-1)
156 with m.Elif(cr_a[2]):
157 comb += rt_o.data.eq(1)
158 with m.Else():
159 comb += rt_o.data.eq(0)
160 comb += rt_o.ok.eq(1)
161
162 comb += self.o.ctx.eq(self.i.ctx)
163
164 return m