start adding bitmanip FU
[soc.git] / src / soc / fu / bitmanip / main_stage.py
1 # License: LGPLv3+
2 # Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
3 # Copyright (C) 2020 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
4 # Copyright (C) 2021 Jacob Lifshay <programmerjake@gmail.com>
5
6 # This stage is intended to do most of the work of executing bitmanip
7 # instructions, as well as overflow generation. This module however should not
8 # gate the overflow, that's up to the output stage
9 from nmigen.hdl.dsl import Module
10 from nmutil.pipemodbase import PipeModBase
11 from soc.fu.bitmanip.pipe_data import (BitManipOutputData,
12 BitManipInputData)
13 from openpower.decoder.power_enums import MicrOp
14 from openpower.decoder.power_fields import DecodeFields
15 from openpower.decoder.power_fieldsn import SignalBitRange
16 from nmutil.lut import BitwiseLut
17
18
19 class BitManipMainStage(PipeModBase):
20 def __init__(self, pspec):
21 super().__init__(pspec, "main")
22 self.fields = DecodeFields(SignalBitRange, [self.i.ctx.op.insn])
23 self.fields.create_specs()
24
25 def ispec(self):
26 return BitManipInputData(self.pspec)
27
28 def ospec(self):
29 return BitManipOutputData(self.pspec)
30
31 def elaborate(self, platform):
32 m = Module()
33 comb = m.d.comb
34 op = self.i.ctx.op
35 o = self.o.o
36
37 bitwise_lut = BitwiseLut(input_count=3, width=64)
38 m.submodules.bitwise_lut = bitwise_lut
39 comb += bitwise_lut.inputs[0].eq(self.i.rb)
40 comb += bitwise_lut.inputs[1].eq(self.i.ra)
41 comb += bitwise_lut.inputs[2].eq(self.i.rc)
42
43 comb += o.ok.eq(1) # defaults to enabled
44
45 with m.Switch(op.insn_type):
46 with m.Case(MicrOp.OP_TERNLOG):
47 # TODO: this only works for ternaryi, change to get lut value
48 # from register when we implement other variants
49 comb += bitwise_lut.lut.eq(self.fields.FormTLI.TLI)
50 comb += o.data.eq(bitwise_lut.output)
51 with m.Default():
52 comb += o.ok.eq(0) # otherwise disable
53
54 ###### sticky overflow and context, both pass-through #####
55
56 comb += self.o.xer_so.data.eq(self.i.xer_so)
57 comb += self.o.ctx.eq(self.i.ctx)
58
59 return m