1 # This stage is intended to do most of the work of executing the ALU
2 # instructions. This would be like the additions, logical operations,
3 # and shifting, as well as carry and overflow generation. This module
4 # however should not gate the carry or overflow, that's up to the
6 from nmigen
import (Module
, Signal
, Cat
, Repl
, Mux
, Const
)
7 from nmutil
.pipemodbase
import PipeModBase
8 from soc
.alu
.pipe_data
import ALUOutputData
9 from soc
.shift_rot
.pipe_data
import ShiftRotInputData
10 from ieee754
.part
.partsig
import PartitionedSignal
11 from soc
.decoder
.power_enums
import InternalOp
12 from soc
.shift_rot
.rotator
import Rotator
14 from soc
.decoder
.power_fields
import DecodeFields
15 from soc
.decoder
.power_fieldsn
import SignalBitRange
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()
25 return ShiftRotInputData(self
.pspec
)
28 return ALUOutputData(self
.pspec
) # TODO: ALUIntermediateData
30 def elaborate(self
, platform
):
34 # obtain me and mb fields from instruction.
35 m_fields
= self
.fields
.instrs
['M']
36 md_fields
= self
.fields
.instrs
['MD']
37 mb
= Signal(m_fields
['MB'][0:-1].shape())
38 me
= Signal(m_fields
['ME'][0:-1].shape())
40 comb
+= mb
.eq(m_fields
['MB'][0:-1])
41 comb
+= me
.eq(m_fields
['ME'][0:-1])
42 comb
+= mb_extra
.eq(md_fields
['mb'][0:-1][0])
44 # set up microwatt rotator module
45 m
.submodules
.rotator
= rotator
= Rotator()
49 rotator
.mb_extra
.eq(mb_extra
),
50 rotator
.rs
.eq(self
.i
.rs
),
51 rotator
.ra
.eq(self
.i
.ra
),
52 rotator
.shift
.eq(self
.i
.rb
),
53 rotator
.is_32bit
.eq(self
.i
.ctx
.op
.is_32bit
),
54 rotator
.arith
.eq(self
.i
.ctx
.op
.is_signed
),
57 # instruction rotate type
58 with m
.Switch(self
.i
.ctx
.op
.insn_type
):
59 with m
.Case(InternalOp
.OP_SHL
):
60 comb
+= [rotator
.right_shift
.eq(0),
61 rotator
.clear_left
.eq(0),
62 rotator
.clear_right
.eq(0)]
63 with m
.Case(InternalOp
.OP_SHR
):
64 comb
+= [rotator
.right_shift
.eq(1),
65 rotator
.clear_left
.eq(0),
66 rotator
.clear_right
.eq(0)]
67 with m
.Case(InternalOp
.OP_RLC
):
68 comb
+= [rotator
.right_shift
.eq(0),
69 rotator
.clear_left
.eq(1),
70 rotator
.clear_right
.eq(1)]
71 with m
.Case(InternalOp
.OP_RLCL
):
72 comb
+= [rotator
.right_shift
.eq(0),
73 rotator
.clear_left
.eq(1),
74 rotator
.clear_right
.eq(0)]
75 with m
.Case(InternalOp
.OP_RLCR
):
76 comb
+= [rotator
.right_shift
.eq(0),
77 rotator
.clear_left
.eq(0),
78 rotator
.clear_right
.eq(1)]
80 # outputs from the microwatt rotator module
81 comb
+= [self
.o
.o
.eq(rotator
.result_o
),
82 self
.o
.carry_out
.eq(rotator
.carry_out_o
)]
84 ###### sticky overflow and context, both pass-through #####
86 comb
+= self
.o
.so
.eq(self
.i
.so
)
87 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)