6b6f20a896c126d43d2071b7e910e9aca49a5645
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
.logical
.pipe_data
import LogicalOutputData
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 LogicalOutputData(self
.pspec
)
29 def elaborate(self
, platform
):
35 # obtain me and mb fields from instruction.
36 m_fields
= self
.fields
.instrs
['M']
37 md_fields
= self
.fields
.instrs
['MD']
38 mb
= Signal(m_fields
['MB'][0:-1].shape())
39 me
= Signal(m_fields
['ME'][0:-1].shape())
40 mb_extra
= Signal(1, reset_less
=True)
41 comb
+= mb
.eq(m_fields
['MB'][0:-1])
42 comb
+= me
.eq(m_fields
['ME'][0:-1])
43 comb
+= mb_extra
.eq(md_fields
['mb'][0:-1][0])
45 # set up microwatt rotator module
46 m
.submodules
.rotator
= rotator
= Rotator()
50 rotator
.mb_extra
.eq(mb_extra
),
51 rotator
.rs
.eq(self
.i
.rs
),
52 rotator
.ra
.eq(self
.i
.a
),
53 rotator
.shift
.eq(self
.i
.rb
),
54 rotator
.is_32bit
.eq(op
.is_32bit
),
55 rotator
.arith
.eq(op
.is_signed
),
58 comb
+= o
.ok
.eq(1) # defaults to enabled
60 # instruction rotate type
61 mode
= Signal(3, reset_less
=True)
62 with m
.Switch(op
.insn_type
):
63 with m
.Case(InternalOp
.OP_SHL
): comb
+= mode
.eq(0b000)
64 with m
.Case(InternalOp
.OP_SHR
): comb
+= mode
.eq(0b001) # R-shift
65 with m
.Case(InternalOp
.OP_RLC
): comb
+= mode
.eq(0b110) # clear LR
66 with m
.Case(InternalOp
.OP_RLCL
): comb
+= mode
.eq(0b010) # clear L
67 with m
.Case(InternalOp
.OP_RLCR
): comb
+= mode
.eq(0b100) # clear R
69 comb
+= o
.ok
.eq(0) # otherwise disable
71 comb
+= Cat(rotator
.right_shift
,
73 rotator
.clear_right
).eq(mode
)
75 # outputs from the microwatt rotator module
77 comb
+= [o
.data
.eq(rotator
.result_o
),
78 self
.o
.xer_ca
[0].eq(rotator
.carry_out_o
)]
80 ###### sticky overflow and context, both pass-through #####
82 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)