Add copyright to files in fu/ that I was the primary author on
[soc.git] / src / soc / fu / shift_rot / main_stage.py
1 # This stage is intended to do most of the work of executing shift
2 # instructions, as well as carry and overflow generation. This module
3 # however should not gate the carry or overflow, that's up to the
4 # output stage
5 # Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
6 from nmigen import (Module, Signal, Cat, Repl, Mux, Const)
7 from nmutil.pipemodbase import PipeModBase
8 from soc.fu.logical.pipe_data import LogicalOutputData
9 from soc.fu.shift_rot.pipe_data import ShiftRotInputData
10 from ieee754.part.partsig import PartitionedSignal
11 from soc.decoder.power_enums import MicrOp
12 from soc.fu.shift_rot.rotator import Rotator
13
14 from soc.decoder.power_fields import DecodeFields
15 from soc.decoder.power_fieldsn import SignalBitRange
16
17
18 class ShiftRotMainStage(PipeModBase):
19 def __init__(self, pspec):
20 super().__init__(pspec, "main")
21 self.fields = DecodeFields(SignalBitRange, [self.i.ctx.op.insn])
22 self.fields.create_specs()
23
24 def ispec(self):
25 return ShiftRotInputData(self.pspec)
26
27 def ospec(self):
28 return LogicalOutputData(self.pspec)
29
30 def elaborate(self, platform):
31 m = Module()
32 comb = m.d.comb
33 op = self.i.ctx.op
34 o = self.o.o
35
36 # NOTE: the sh field immediate is read in by PowerDecode2
37 # (actually DecodeRB), whereupon by way of rb "immediate" mode
38 # it ends up in self.i.rb.
39
40 # obtain me and mb fields from instruction.
41 m_fields = self.fields.instrs['M']
42 md_fields = self.fields.instrs['MD']
43 mb = Signal(m_fields['MB'][0:-1].shape())
44 me = Signal(m_fields['ME'][0:-1].shape())
45 mb_extra = Signal(1, reset_less=True)
46 comb += mb.eq(m_fields['MB'][0:-1])
47 comb += me.eq(m_fields['ME'][0:-1])
48 comb += mb_extra.eq(md_fields['mb'][0:-1][0])
49
50 # set up microwatt rotator module
51 m.submodules.rotator = rotator = Rotator()
52 comb += [
53 rotator.me.eq(me),
54 rotator.mb.eq(mb),
55 rotator.mb_extra.eq(mb_extra),
56 rotator.rs.eq(self.i.rs),
57 rotator.ra.eq(self.i.a),
58 rotator.shift.eq(self.i.rb), # can also be sh (in immediate mode)
59 rotator.is_32bit.eq(op.is_32bit),
60 rotator.arith.eq(op.is_signed),
61 ]
62
63 comb += o.ok.eq(1) # defaults to enabled
64
65 # instruction rotate type
66 mode = Signal(4, reset_less=True)
67 with m.Switch(op.insn_type):
68 with m.Case(MicrOp.OP_SHL): comb += mode.eq(0b0000) # L-shift
69 with m.Case(MicrOp.OP_SHR): comb += mode.eq(0b0001) # R-shift
70 with m.Case(MicrOp.OP_RLC): comb += mode.eq(0b0110) # clear LR
71 with m.Case(MicrOp.OP_RLCL): comb += mode.eq(0b0010) # clear L
72 with m.Case(MicrOp.OP_RLCR): comb += mode.eq(0b0100) # clear R
73 with m.Case(MicrOp.OP_EXTSWSLI): comb += mode.eq(0b1000) # L-ext
74 with m.Default():
75 comb += o.ok.eq(0) # otherwise disable
76
77 comb += Cat(rotator.right_shift,
78 rotator.clear_left,
79 rotator.clear_right,
80 rotator.sign_ext_rs).eq(mode)
81
82 # outputs from the microwatt rotator module
83 comb += [o.data.eq(rotator.result_o),
84 self.o.xer_ca.data.eq(Repl(rotator.carry_out_o, 2))]
85
86 ###### sticky overflow and context, both pass-through #####
87
88 comb += self.o.ctx.eq(self.i.ctx)
89
90 return m