1815431a839bbaa941abd7767ebc263c18d1c267
[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 from nmigen import (Module, Signal, Cat, Repl, Mux, Const, Array)
9 from nmutil.pipemodbase import PipeModBase
10 from nmutil.clz import CLZ
11 from soc.fu.logical.pipe_data import LogicalInputData
12 from soc.fu.logical.bpermd import Bpermd
13 from soc.fu.logical.popcount import Popcount
14 from soc.fu.logical.pipe_data import LogicalOutputData
15 from ieee754.part.partsig import PartitionedSignal
16 from soc.decoder.power_enums import InternalOp
17
18 from soc.decoder.power_fields import DecodeFields
19 from soc.decoder.power_fieldsn import SignalBitRange
20
21
22 class LogicalMainStage(PipeModBase):
23 def __init__(self, pspec):
24 super().__init__(pspec, "main")
25 self.fields = DecodeFields(SignalBitRange, [self.i.ctx.op.insn])
26 self.fields.create_specs()
27
28 def ispec(self):
29 return LogicalInputData(self.pspec)
30
31 def ospec(self):
32 return LogicalOutputData(self.pspec)
33
34 def elaborate(self, platform):
35 m = Module()
36 comb = m.d.comb
37 op, a, b, o = self.i.ctx.op, self.i.a, self.i.b, self.o.o
38
39 comb += o.ok.eq(1) # overridden if no op activates
40
41 m.submodules.bpermd = bpermd = Bpermd(64)
42 m.submodules.popcount = popcount = Popcount()
43
44 ##########################
45 # main switch for logic ops AND, OR and XOR, cmpb, parity, and popcount
46
47 with m.Switch(op.insn_type):
48
49 ###### AND, OR, XOR #######
50 with m.Case(InternalOp.OP_AND):
51 comb += o.data.eq(a & b)
52 with m.Case(InternalOp.OP_OR):
53 comb += o.data.eq(a | b)
54 with m.Case(InternalOp.OP_XOR):
55 comb += o.data.eq(a ^ b)
56
57 ###### cmpb #######
58 with m.Case(InternalOp.OP_CMPB):
59 l = []
60 for i in range(8):
61 slc = slice(i*8, (i+1)*8)
62 l.append(Repl(a[slc] == b[slc], 8))
63 comb += o.data.eq(Cat(*l))
64
65 ###### popcount #######
66 with m.Case(InternalOp.OP_POPCNT):
67 comb += popcount.a.eq(a)
68 comb += popcount.b.eq(b)
69 comb += popcount.data_len.eq(op.data_len)
70 comb += o.data.eq(popcount.o)
71
72 ###### parity #######
73 with m.Case(InternalOp.OP_PRTY):
74 # strange instruction which XORs together the LSBs of each byte
75 par0 = Signal(reset_less=True)
76 par1 = Signal(reset_less=True)
77 comb += par0.eq(Cat(a[0], a[8], a[16], a[24]).xor())
78 comb += par1.eq(Cat(a[32], a[40], a[48], a[56]).xor())
79 with m.If(op.data_len[3] == 1):
80 comb += o.data.eq(par0 ^ par1)
81 with m.Else():
82 comb += o[0].eq(par0)
83 comb += o[32].eq(par1)
84
85 ###### cntlz #######
86 with m.Case(InternalOp.OP_CNTZ):
87 XO = self.fields.FormX.XO[0:-1]
88 count_right = Signal(reset_less=True)
89 comb += count_right.eq(XO[-1])
90
91 cntz_i = Signal(64, reset_less=True)
92 a32 = Signal(32, reset_less=True)
93 comb += a32.eq(a[0:32])
94
95 with m.If(op.is_32bit):
96 comb += cntz_i.eq(Mux(count_right, a32[::-1], a32))
97 with m.Else():
98 comb += cntz_i.eq(Mux(count_right, a[::-1], a))
99
100 m.submodules.clz = clz = CLZ(64)
101 comb += clz.sig_in.eq(cntz_i)
102 comb += o.data.eq(Mux(op.is_32bit, clz.lz-32, clz.lz))
103
104 ###### bpermd #######
105 with m.Case(InternalOp.OP_BPERM):
106 comb += bpermd.rs.eq(a)
107 comb += bpermd.rb.eq(b)
108 comb += o.data.eq(bpermd.ra)
109
110 with m.Default():
111 comb += o.ok.eq(0)
112
113 ###### context, pass-through #####
114
115 comb += self.o.ctx.eq(self.i.ctx)
116
117 return m