2 # Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
3 # Copyright (C) 2020 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
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
9 from nmigen
import (Module
, Signal
, Cat
, Repl
, Mux
, Const
)
10 from nmutil
.pipemodbase
import PipeModBase
11 from soc
.fu
.alu
.pipe_data
import ALUOutputData
12 from soc
.fu
.shift_rot
.pipe_data
import ShiftRotInputData
13 from ieee754
.part
.partsig
import PartitionedSignal
14 from soc
.decoder
.power_enums
import MicrOp
15 from soc
.fu
.shift_rot
.rotator
import Rotator
17 from soc
.decoder
.power_fields
import DecodeFields
18 from soc
.decoder
.power_fieldsn
import SignalBitRange
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()
28 return ShiftRotInputData(self
.pspec
)
31 return ALUOutputData(self
.pspec
)
33 def elaborate(self
, platform
):
39 # NOTE: the sh field immediate is read in by PowerDecode2
40 # (actually DecodeRB), whereupon by way of rb "immediate" mode
41 # it ends up in self.i.rb.
43 # obtain me and mb fields from instruction.
44 m_fields
= self
.fields
.instrs
['M']
45 md_fields
= self
.fields
.instrs
['MD']
46 mb
= Signal(m_fields
['MB'][0:-1].shape())
47 me
= Signal(m_fields
['ME'][0:-1].shape())
48 mb_extra
= Signal(1, reset_less
=True)
49 comb
+= mb
.eq(m_fields
['MB'][0:-1])
50 comb
+= me
.eq(m_fields
['ME'][0:-1])
51 comb
+= mb_extra
.eq(md_fields
['mb'][0:-1][0])
53 # set up microwatt rotator module
54 m
.submodules
.rotator
= rotator
= Rotator()
58 rotator
.mb_extra
.eq(mb_extra
),
59 rotator
.rs
.eq(self
.i
.rs
),
60 rotator
.ra
.eq(self
.i
.a
),
61 rotator
.shift
.eq(self
.i
.rb
), # can also be sh (in immediate mode)
62 rotator
.is_32bit
.eq(op
.is_32bit
),
63 rotator
.arith
.eq(op
.is_signed
),
66 comb
+= o
.ok
.eq(1) # defaults to enabled
68 # instruction rotate type
69 mode
= Signal(4, reset_less
=True)
70 with m
.Switch(op
.insn_type
):
71 with m
.Case(MicrOp
.OP_SHL
): comb
+= mode
.eq(0b0000) # L-shift
72 with m
.Case(MicrOp
.OP_SHR
): comb
+= mode
.eq(0b0001) # R-shift
73 with m
.Case(MicrOp
.OP_RLC
): comb
+= mode
.eq(0b0110) # clear LR
74 with m
.Case(MicrOp
.OP_RLCL
): comb
+= mode
.eq(0b0010) # clear L
75 with m
.Case(MicrOp
.OP_RLCR
): comb
+= mode
.eq(0b0100) # clear R
76 with m
.Case(MicrOp
.OP_EXTSWSLI
): comb
+= mode
.eq(0b1000) # L-ext
78 comb
+= o
.ok
.eq(0) # otherwise disable
80 comb
+= Cat(rotator
.right_shift
,
83 rotator
.sign_ext_rs
).eq(mode
)
85 # outputs from the microwatt rotator module
86 comb
+= [o
.data
.eq(rotator
.result_o
),
87 self
.o
.xer_ca
.data
.eq(Repl(rotator
.carry_out_o
, 2))]
89 ###### sticky overflow and context, both pass-through #####
91 comb
+= self
.o
.xer_so
.data
.eq(self
.i
.xer_so
)
92 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)