1 # This stage is intended to do Condition Register instructions
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.
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 InternalOp
17 from soc
.decoder
.power_fields
import DecodeFields
18 from soc
.decoder
.power_fieldsn
import SignalBitRange
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()
28 return CRInputData(self
.pspec
)
31 return CROutputData(self
.pspec
)
33 def elaborate(self
, platform
):
37 a
, cr
= self
.i
.a
, self
.i
.cr
38 xl_fields
= self
.fields
.FormXL
39 xfx_fields
= self
.fields
.FormXFX
40 # default: cr_o remains same as cr input unless modified, below
41 cr_o
= Signal
.like(cr
)
44 ##### prepare inputs / temp #####
46 # Generate array for cr input so bits can be selected
47 cr_arr
= Array([Signal(name
=f
"cr_arr_{i}") for i
in range(32)])
49 comb
+= cr_arr
[i
].eq(cr
[31-i
])
51 # Generate array for cr output so the bit to write to can be
52 # selected by a signal
53 cr_out_arr
= Array([Signal(name
=f
"cr_out_{i}") for i
in range(32)])
55 comb
+= cr_o
[31-i
].eq(cr_out_arr
[i
])
56 comb
+= cr_out_arr
[i
].eq(cr_arr
[i
])
58 # Generate the mask for mtcrf, mtocrf, and mfocrf
59 # replicate every fxm field in the insn to 4-bit, as a mask
60 FXM
= xfx_fields
.FXM
[0:-1]
61 mask
= Signal(32, reset_less
=True)
62 comb
+= mask
.eq(Cat(*[Repl(FXM
[i
], 4) for i
in range(8)]))
64 #################################
65 ##### main switch statement #####
67 with m
.Switch(op
.insn_type
):
69 with m
.Case(InternalOp
.OP_MCRF
):
70 # MCRF copies the 4 bits of crA to crB (for instance
72 BF
= xl_fields
.BF
[0:-1] # destination CR
73 BFA
= xl_fields
.BFA
[0:-1] # source CR
74 bf
= Signal(BF
.shape(), reset_less
=True)
75 bfa
= Signal(BFA
.shape(), reset_less
=True)
76 # use temporary signals because ilang output is insane otherwise
81 comb
+= cr_out_arr
[bf
*4 + i
].eq(cr_arr
[bfa
*4 + i
])
83 ##### crand, cror, crnor etc. #####
84 with m
.Case(InternalOp
.OP_CROP
):
85 # crand/cror and friends get decoded to the same opcode, but
86 # one of the fields inside the instruction is a 4 bit lookup
87 # table. This lookup table gets indexed by bits a and b from
88 # the CR to determine what the resulting bit should be.
90 # Grab the lookup table for cr_op type instructions
91 lut
= Signal(4, reset_less
=True)
92 # There's no field, just have to grab it directly from the insn
93 comb
+= lut
.eq(op
.insn
[6:10])
95 # Get the bit selector fields from the instruction
96 BT
= xl_fields
.BT
[0:-1]
97 BA
= xl_fields
.BA
[0:-1]
98 BB
= xl_fields
.BB
[0:-1]
99 bt
= Signal(BT
.shape(), reset_less
=True)
100 ba
= Signal(BA
.shape(), reset_less
=True)
101 bb
= Signal(BB
.shape(), reset_less
=True)
102 # use temporary signals because ilang output is insane otherwise
103 # also when accessing LUT
108 # Extract the two input bits from the CR
109 bit_a
= Signal(reset_less
=True)
110 bit_b
= Signal(reset_less
=True)
111 comb
+= bit_a
.eq((1<<(31-ba
) & cr
) != 0)
112 comb
+= bit_b
.eq((1<<(31-bb
) & cr
) != 0)
114 # Use the two input bits to look up the result in the LUT
115 bit_out
= Signal(reset_less
=True)
116 comb
+= bit_out
.eq(Mux(bit_b
,
117 Mux(bit_a
, lut
[3], lut
[1]),
118 Mux(bit_a
, lut
[2], lut
[0])))
119 # Set the output to the result above
120 mask_
= Signal(32, reset_less
=True)
121 comb
+= mask_
.eq(1<<(31-bt
))
122 comb
+= cr_o
.eq(Mux(bit_out
, mask_
, 0) |
(~mask_
& cr
))
125 with m
.Case(InternalOp
.OP_MTCRF
):
126 # mtocrf and mtcrf are essentially identical
127 # put input (RA) - mask-selected - into output CR, leave
129 comb
+= cr_o
.eq((a
[0:32] & mask
) |
(cr
& ~mask
))
132 with m
.Case(InternalOp
.OP_MFCR
):
133 # Ugh. mtocrf and mtcrf have one random bit differentiating
134 # them. This bit is not in any particular field, so this
135 # extracts that bit from the instruction
136 move_one
= Signal(reset_less
=True)
137 comb
+= move_one
.eq(op
.insn
[20])
141 comb
+= self
.o
.o
.eq(cr
& mask
) # output register RT
144 comb
+= self
.o
.o
.eq(cr
) # output register RT
147 comb
+= self
.o
.cr
.eq(cr_o
)
148 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)