move rotator mode assignments as requested by lkcl
[soc.git] / src / soc / fu / shift_rot / 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 most of the work of executing shift
6 # instructions, as well as carry and overflow generation. This module
7 # however should not gate the carry or overflow, that's up to the
8 # output stage
9 from nmigen import (Module, Signal, Cat, Repl, Mux, Const)
10 from nmutil.pipemodbase import PipeModBase
11 from soc.fu.shift_rot.pipe_data import (ShiftRotOutputData,
12 ShiftRotInputData)
13 from nmutil.lut import BitwiseLut
14 from openpower.decoder.power_enums import MicrOp
15 from soc.fu.shift_rot.rotator import Rotator
16
17 from openpower.decoder.power_fields import DecodeFields
18 from openpower.decoder.power_fieldsn import SignalBitRange
19
20
21 class ShiftRotMainStage(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 ShiftRotInputData(self.pspec)
29
30 def ospec(self):
31 return ShiftRotOutputData(self.pspec)
32
33 def elaborate(self, platform):
34 m = Module()
35 comb = m.d.comb
36 op = self.i.ctx.op
37 o = self.o.o
38
39 bitwise_lut = BitwiseLut(input_count=3, width=64)
40 m.submodules.bitwise_lut = bitwise_lut
41 comb += bitwise_lut.inputs[0].eq(self.i.rb)
42 comb += bitwise_lut.inputs[1].eq(self.i.ra)
43 comb += bitwise_lut.inputs[2].eq(self.i.rc)
44
45 # NOTE: the sh field immediate is read in by PowerDecode2
46 # (actually DecodeRB), whereupon by way of rb "immediate" mode
47 # it ends up in self.i.rb.
48
49 # obtain me and mb fields from instruction.
50 m_fields = self.fields.instrs['M']
51 md_fields = self.fields.instrs['MD']
52 mb = Signal(m_fields['MB'][0:-1].shape())
53 me = Signal(m_fields['ME'][0:-1].shape())
54 mb_extra = Signal(1, reset_less=True)
55 comb += mb.eq(m_fields['MB'][0:-1])
56 comb += me.eq(m_fields['ME'][0:-1])
57 comb += mb_extra.eq(md_fields['mb'][0:-1][0])
58
59 # set up microwatt rotator module
60 m.submodules.rotator = rotator = Rotator()
61 comb += [
62 rotator.me.eq(me),
63 rotator.mb.eq(mb),
64 rotator.mb_extra.eq(mb_extra),
65 rotator.rs.eq(self.i.rs),
66 rotator.ra.eq(self.i.a),
67 rotator.shift.eq(self.i.rb), # can also be sh (in immediate mode)
68 rotator.is_32bit.eq(op.is_32bit),
69 rotator.arith.eq(op.is_signed),
70 ]
71
72 comb += o.ok.eq(1) # defaults to enabled
73
74 # instruction rotate type
75 mode = Signal(4, reset_less=True)
76 comb += Cat(rotator.right_shift,
77 rotator.clear_left,
78 rotator.clear_right,
79 rotator.sign_ext_rs).eq(mode)
80
81 # outputs from the microwatt rotator module
82 comb += [o.data.eq(rotator.result_o),
83 self.o.xer_ca.data.eq(Repl(rotator.carry_out_o, 2))]
84
85 with m.Switch(op.insn_type):
86 with m.Case(MicrOp.OP_SHL):
87 comb += mode.eq(0b0000) # L-shift
88 with m.Case(MicrOp.OP_SHR):
89 comb += mode.eq(0b0001) # R-shift
90 with m.Case(MicrOp.OP_RLC):
91 comb += mode.eq(0b0110) # clear LR
92 with m.Case(MicrOp.OP_RLCL):
93 comb += mode.eq(0b0010) # clear L
94 with m.Case(MicrOp.OP_RLCR):
95 comb += mode.eq(0b0100) # clear R
96 with m.Case(MicrOp.OP_EXTSWSLI):
97 comb += mode.eq(0b1000) # L-ext
98 with m.Case(MicrOp.OP_TERNLOG):
99 # TODO: this only works for ternaryi, change to get lut value
100 # from register when we implement other variants
101 comb += bitwise_lut.lut.eq(self.fields.FormTLI.TLI[:])
102 comb += o.data.eq(bitwise_lut.output)
103 comb += self.o.xer_ca.data.eq(0)
104 with m.Default():
105 comb += o.ok.eq(0) # otherwise disable
106
107 ###### sticky overflow and context, both pass-through #####
108
109 comb += self.o.xer_so.data.eq(self.i.xer_so)
110 comb += self.o.ctx.eq(self.i.ctx)
111
112 return m