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
5 from nmigen
import (Module
, Signal
, Cat
, Repl
, Mux
, Const
)
6 from nmutil
.pipemodbase
import PipeModBase
7 from soc
.fu
.alu
.pipe_data
import ALUOutputData
8 from soc
.fu
.shift_rot
.pipe_data
import ShiftRotInputData
9 from ieee754
.part
.partsig
import PartitionedSignal
10 from soc
.decoder
.power_enums
import InternalOp
11 from soc
.fu
.shift_rot
.rotator
import Rotator
13 from soc
.decoder
.power_fields
import DecodeFields
14 from soc
.decoder
.power_fieldsn
import SignalBitRange
17 class ShiftRotMainStage(PipeModBase
):
18 def __init__(self
, pspec
):
19 super().__init
__(pspec
, "main")
20 self
.fields
= DecodeFields(SignalBitRange
, [self
.i
.ctx
.op
.insn
])
21 self
.fields
.create_specs()
24 return ShiftRotInputData(self
.pspec
)
27 return ALUOutputData(self
.pspec
) # TODO: ALUIntermediateData
29 def elaborate(self
, platform
):
33 # obtain me and mb fields from instruction.
34 m_fields
= self
.fields
.instrs
['M']
35 md_fields
= self
.fields
.instrs
['MD']
36 mb
= Signal(m_fields
['MB'][0:-1].shape())
37 me
= Signal(m_fields
['ME'][0:-1].shape())
38 mb_extra
= Signal(1, reset_less
=True)
39 comb
+= mb
.eq(m_fields
['MB'][0:-1])
40 comb
+= me
.eq(m_fields
['ME'][0:-1])
41 comb
+= mb_extra
.eq(md_fields
['mb'][0:-1][0])
43 # set up microwatt rotator module
44 m
.submodules
.rotator
= rotator
= Rotator()
48 rotator
.mb_extra
.eq(mb_extra
),
49 rotator
.rs
.eq(self
.i
.rs
),
50 rotator
.ra
.eq(self
.i
.ra
),
51 rotator
.shift
.eq(self
.i
.rb
),
52 rotator
.is_32bit
.eq(self
.i
.ctx
.op
.is_32bit
),
53 rotator
.arith
.eq(self
.i
.ctx
.op
.is_signed
),
56 # instruction rotate type
57 mode
= Signal(3, reset_less
=True)
58 with m
.Switch(self
.i
.ctx
.op
.insn_type
):
59 with m
.Case(InternalOp
.OP_SHL
): comb
+= mode
.eq(0b000)
60 with m
.Case(InternalOp
.OP_SHR
): comb
+= mode
.eq(0b001) # R-shift
61 with m
.Case(InternalOp
.OP_RLC
): comb
+= mode
.eq(0b110) # clear LR
62 with m
.Case(InternalOp
.OP_RLCL
): comb
+= mode
.eq(0b010) # clear L
63 with m
.Case(InternalOp
.OP_RLCR
): comb
+= mode
.eq(0b100) # clear R
65 comb
+= Cat(rotator
.right_shift
,
67 rotator
.clear_right
).eq(mode
)
69 # outputs from the microwatt rotator module
70 comb
+= [self
.o
.o
.eq(rotator
.result_o
),
71 self
.o
.xer_co
.eq(rotator
.carry_out_o
)]
73 ###### sticky overflow and context, both pass-through #####
75 comb
+= self
.o
.xer_so
.data
.eq(self
.i
.so
)
76 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)