4f83a99d91c445fe92b56524b7d98cb7eb8583ba
[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.pipe_data import get_pspec_draft_bitmanip
12 from soc.fu.shift_rot.pipe_data import (ShiftRotOutputData,
13 ShiftRotInputData)
14 from nmutil.lut import BitwiseLut
15 from nmutil.grev import GRev
16 from openpower.decoder.power_enums import MicrOp
17 from soc.fu.shift_rot.rotator import Rotator
18
19 from openpower.decoder.power_fields import DecodeFields
20 from openpower.decoder.power_fieldsn import SignalBitRange
21
22
23 class ShiftRotMainStage(PipeModBase):
24 def __init__(self, pspec):
25 super().__init__(pspec, "main")
26 self.draft_bitmanip = get_pspec_draft_bitmanip(pspec)
27 self.fields = DecodeFields(SignalBitRange, [self.i.ctx.op.insn])
28 self.fields.create_specs()
29
30 def ispec(self):
31 return ShiftRotInputData(self.pspec)
32
33 def ospec(self):
34 return ShiftRotOutputData(self.pspec)
35
36 def elaborate(self, platform):
37 XLEN = self.pspec.XLEN
38 m = Module()
39 comb = m.d.comb
40 op = self.i.ctx.op
41 o = self.o.o
42
43 bitwise_lut = None
44 grev = None
45 if self.draft_bitmanip:
46 bitwise_lut = BitwiseLut(input_count=3, width=XLEN)
47 m.submodules.bitwise_lut = bitwise_lut
48 comb += bitwise_lut.inputs[0].eq(self.i.rb)
49 comb += bitwise_lut.inputs[1].eq(self.i.ra)
50 comb += bitwise_lut.inputs[2].eq(self.i.rc)
51 # 6 == log2(64) because we have 64-bit values
52 grev = GRev(log2_width=(XLEN-1).bit_length())
53 m.submodules.grev = grev
54 with m.If(op.is_32bit):
55 # 32-bit, so input is lower 32-bits zero-extended
56 comb += grev.input.eq(self.i.ra[0:32])
57 # 32-bit, so we only feed in log2(32) == 5 bits
58 comb += grev.chunk_sizes.eq(self.i.rb[0:5])
59 with m.Else():
60 comb += grev.input.eq(self.i.ra)
61 comb += grev.chunk_sizes.eq(self.i.rb)
62
63 # NOTE: the sh field immediate is read in by PowerDecode2
64 # (actually DecodeRB), whereupon by way of rb "immediate" mode
65 # it ends up in self.i.rb.
66
67 # obtain me and mb fields from instruction.
68 m_fields = self.fields.instrs['M']
69 md_fields = self.fields.instrs['MD']
70 mb = Signal(m_fields['MB'][0:-1].shape())
71 me = Signal(m_fields['ME'][0:-1].shape())
72 mb_extra = Signal(1, reset_less=True)
73 comb += mb.eq(m_fields['MB'][0:-1])
74 comb += me.eq(m_fields['ME'][0:-1])
75 comb += mb_extra.eq(md_fields['mb'][0:-1][0])
76
77 # set up microwatt rotator module
78 m.submodules.rotator = rotator = Rotator(XLEN)
79 comb += [
80 rotator.me.eq(me),
81 rotator.mb.eq(mb),
82 rotator.mb_extra.eq(mb_extra),
83 rotator.rs.eq(self.i.rs),
84 rotator.ra.eq(self.i.a),
85 rotator.shift.eq(self.i.rb), # can also be sh (in immediate mode)
86 rotator.is_32bit.eq(op.is_32bit),
87 rotator.arith.eq(op.is_signed),
88 ]
89
90 comb += o.ok.eq(1) # defaults to enabled
91
92 # instruction rotate type
93 mode = Signal(4, reset_less=True)
94 comb += Cat(rotator.right_shift,
95 rotator.clear_left,
96 rotator.clear_right,
97 rotator.sign_ext_rs).eq(mode)
98
99 # outputs from the microwatt rotator module
100 comb += [o.data.eq(rotator.result_o),
101 self.o.xer_ca.data.eq(Repl(rotator.carry_out_o, 2))]
102
103 with m.Switch(op.insn_type):
104 with m.Case(MicrOp.OP_SHL):
105 comb += mode.eq(0b0000) # L-shift
106 with m.Case(MicrOp.OP_SHR):
107 comb += mode.eq(0b0001) # R-shift
108 with m.Case(MicrOp.OP_RLC):
109 comb += mode.eq(0b0110) # clear LR
110 with m.Case(MicrOp.OP_RLCL):
111 comb += mode.eq(0b0010) # clear L
112 with m.Case(MicrOp.OP_RLCR):
113 comb += mode.eq(0b0100) # clear R
114 with m.Case(MicrOp.OP_EXTSWSLI):
115 comb += mode.eq(0b1000) # L-ext
116 if self.draft_bitmanip:
117 with m.Case(MicrOp.OP_TERNLOG):
118 # TODO: this only works for ternlogi, change to get lut
119 # value from register when we implement other variants
120 comb += bitwise_lut.lut.eq(self.fields.FormTLI.TLI[:])
121 comb += o.data.eq(bitwise_lut.output)
122 comb += self.o.xer_ca.data.eq(0)
123 with m.Case(MicrOp.OP_GREV):
124 comb += o.data.eq(grev.output)
125 comb += self.o.xer_ca.data.eq(0)
126 with m.Default():
127 comb += o.ok.eq(0) # otherwise disable
128
129 ###### sticky overflow and context, both pass-through #####
130
131 comb += self.o.xer_so.data.eq(self.i.xer_so)
132 comb += self.o.ctx.eq(self.i.ctx)
133
134 return m