fix up Logical pipeline to produce HDL with XLEN=32
[soc.git] / src / soc / fu / logical / main_stage.py
1 # This stage is intended to do most of the work of executing Logical
2 # instructions. This is OR, AND, XOR, POPCNT, PRTY, CMPB, BPERMD, CNTLZ
3 # however input and output stages also perform bit-negation on input(s)
4 # and output, as well as carry and overflow generation.
5 # This module however should not gate the carry or overflow, that's up
6 # to the output stage
7
8 # Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
9 # Copyright (C) 2020, 2021 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
10
11 from nmigen import (Module, Signal, Cat, Repl, Mux, Const, Array)
12 from nmutil.pipemodbase import PipeModBase
13 from nmutil.clz import CLZ
14 from soc.fu.logical.pipe_data import LogicalInputData
15 from soc.fu.logical.bpermd import Bpermd
16 from soc.fu.logical.popcount import Popcount
17 from soc.fu.logical.pipe_data import LogicalOutputData
18 from ieee754.part.partsig import SimdSignal
19 from openpower.decoder.power_enums import MicrOp
20
21 from openpower.decoder.power_fields import DecodeFields
22 from openpower.decoder.power_fieldsn import SignalBitRange
23
24
25 class LogicalMainStage(PipeModBase):
26 def __init__(self, pspec):
27 super().__init__(pspec, "main")
28 self.fields = DecodeFields(SignalBitRange, [self.i.ctx.op.insn])
29 self.fields.create_specs()
30
31 def ispec(self):
32 return LogicalInputData(self.pspec)
33
34 def ospec(self):
35 return LogicalOutputData(self.pspec)
36
37 def elaborate(self, platform):
38 XLEN = self.pspec.XLEN
39 m = Module()
40 comb = m.d.comb
41 op, a, b, o = self.i.ctx.op, self.i.a, self.i.b, self.o.o
42
43 comb += o.ok.eq(1) # overridden if no op activates
44
45 m.submodules.bpermd = bpermd = Bpermd(XLEN)
46 m.submodules.popcount = popcount = Popcount(XLEN)
47
48 ##########################
49 # main switch for logic ops AND, OR and XOR, cmpb, parity, and popcount
50
51 with m.Switch(op.insn_type):
52
53 ###################
54 ###### AND, OR, XOR v3.0B p92-95
55
56 with m.Case(MicrOp.OP_AND):
57 comb += o.data.eq(a & b)
58 with m.Case(MicrOp.OP_OR):
59 comb += o.data.eq(a | b)
60 with m.Case(MicrOp.OP_XOR):
61 comb += o.data.eq(a ^ b)
62
63 ###################
64 ###### cmpb v3.0B p97
65
66 with m.Case(MicrOp.OP_CMPB):
67 l = []
68 for i in range(8):
69 slc = slice(i*8, (i+1)*8)
70 l.append(Repl(a[slc] == b[slc], 8))
71 comb += o.data.eq(Cat(*l))
72
73 ###################
74 ###### popcount v3.0B p97, p98
75
76 with m.Case(MicrOp.OP_POPCNT):
77 comb += popcount.a.eq(a)
78 comb += popcount.b.eq(b)
79 comb += popcount.data_len.eq(op.data_len)
80 comb += o.data.eq(popcount.o)
81
82 ###################
83 ###### parity v3.0B p98
84
85 with m.Case(MicrOp.OP_PRTY):
86 # strange instruction which XORs together the LSBs of each byte
87 par0 = Signal(reset_less=True)
88 par1 = Signal(reset_less=True)
89 comb += par0.eq(Cat(a[0], a[8], a[16], a[24]).xor())
90 if XLEN == 64:
91 comb += par1.eq(Cat(a[32], a[40], a[48], a[56]).xor())
92 with m.If(op.data_len[3] == 1):
93 comb += o.data.eq(par0 ^ par1)
94 with m.Else():
95 comb += o[0].eq(par0)
96 if XLEN == 64:
97 comb += o[32].eq(par1)
98
99 ###################
100 ###### cntlz v3.0B p99
101
102 with m.Case(MicrOp.OP_CNTZ):
103 XO = self.fields.FormX.XO[0:-1]
104 count_right = Signal(reset_less=True)
105 comb += count_right.eq(XO[-1])
106
107 cntz_i = Signal(XLEN, reset_less=True)
108 a32 = Signal(32, reset_less=True)
109 comb += a32.eq(a[0:32])
110
111 with m.If(op.is_32bit):
112 comb += cntz_i.eq(Mux(count_right, a32[::-1], a32))
113 with m.Else():
114 comb += cntz_i.eq(Mux(count_right, a[::-1], a))
115
116 m.submodules.clz = clz = CLZ(XLEN)
117 comb += clz.sig_in.eq(cntz_i)
118 comb += o.data.eq(Mux(op.is_32bit, clz.lz-32, clz.lz))
119
120 ###################
121 ###### bpermd v3.0B p100
122
123 with m.Case(MicrOp.OP_BPERM):
124 comb += bpermd.rs.eq(a)
125 comb += bpermd.rb.eq(b)
126 comb += o.data.eq(bpermd.ra)
127
128 with m.Default():
129 comb += o.ok.eq(0)
130
131 ###### sticky overflow and context, both pass-through #####
132
133 comb += self.o.xer_so.data.eq(self.i.xer_so)
134 comb += self.o.ctx.eq(self.i.ctx)
135
136 return m