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