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
8 # Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
9 # Copyright (C) 2020, 2021 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
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
21 from openpower
.decoder
.power_fields
import DecodeFields
22 from openpower
.decoder
.power_fieldsn
import SignalBitRange
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()
32 return LogicalInputData(self
.pspec
)
35 return LogicalOutputData(self
.pspec
)
37 def elaborate(self
, platform
):
38 XLEN
= self
.pspec
.XLEN
41 op
, a
, b
, o
= self
.i
.ctx
.op
, self
.i
.a
, self
.i
.b
, self
.o
.o
43 comb
+= o
.ok
.eq(1) # overridden if no op activates
45 m
.submodules
.bpermd
= bpermd
= Bpermd(XLEN
)
46 m
.submodules
.popcount
= popcount
= Popcount(XLEN
)
48 ##########################
49 # main switch for logic ops AND, OR and XOR, cmpb, parity, and popcount
51 with m
.Switch(op
.insn_type
):
54 ###### AND, OR, XOR v3.0B p92-95
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
)
66 with m
.Case(MicrOp
.OP_CMPB
):
69 slc
= slice(i
*8, (i
+1)*8)
70 l
.append(Repl(a
[slc
] == b
[slc
], 8))
71 comb
+= o
.data
.eq(Cat(*l
))
74 ###### popcount v3.0B p97, p98
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
)
83 ###### parity v3.0B p98
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())
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
)
97 comb
+= o
[32].eq(par1
)
100 ###### cntlz v3.0B p99
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])
107 cntz_i
= Signal(XLEN
, reset_less
=True)
108 a32
= Signal(32, reset_less
=True)
109 comb
+= a32
.eq(a
[0:32])
111 with m
.If(op
.is_32bit
):
112 comb
+= cntz_i
.eq(Mux(count_right
, a32
[::-1], a32
))
114 comb
+= cntz_i
.eq(Mux(count_right
, a
[::-1], a
))
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
))
121 ###### bpermd v3.0B p100
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
)
131 ###### sticky overflow and context, both pass-through #####
133 comb
+= self
.o
.xer_so
.data
.eq(self
.i
.xer_so
)
134 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)