Allow the formal engine to perform a same-cycle result in the ALU
[soc.git] / src / soc / fu / logical / bpermd.py
1 from nmigen import Elaboratable, Signal, Module, Repl, Cat, Const, Array
2 from nmigen.cli import main
3
4
5 class Bpermd(Elaboratable):
6 """
7 from POWERISA v3.1 p105, chaper 3
8
9 This class does a Bit Permute on a Doubleword
10
11 permd RA,RS,RB
12
13 do i = 0 to 7
14 index ← (RS)[8*i:8*i+7]
15 If index < 64
16 then perm[i] ← (RB)[index]
17 else permi[i] ← 0
18 RA ←56[0] || perm[0:7]
19
20 Eight permuted bits are produced. For each permutedbit i where i
21 ranges from 0 to 7 and for each byte i of RS, do the following.
22
23 If byte i of RS is less than 64, permuted bit i is set to
24 the bit of RB specified by byte i of RS; otherwise
25 permuted bit i is set to 0.
26
27 The permuted bits are placed in the least-significant byte of RA,
28 and the remaining bits are filled with 0s.
29
30 Special Registers Altered:
31 None
32
33 Programming Note:
34
35 The fact that the permuted bit is 0 if the corresponding index value
36 exceeds 63 permits the permuted bits to be selected from a 128-bit
37 quantity, using a single index register. For example, assume that
38 the 128-bit quantity Q, from which the permuted bits are to be
39 selected, is in registers r2 (high-order 64 bits of Q) and r3
40 (low-order 64 bits of Q), that the index values are in register r1,
41 with each byte of r1 containing a value in the range 0:127, and that
42 each byte of register r4 contains the value 64. The following code
43 sequence selects eight permuted bits from Q and places them into
44 the low-order byteof r6.
45
46 bpermd r6,r1,r2 # select from high-order half of Q
47 xor r0,r1,r4 # adjust index values
48 bpermd r5,r0,r3 # select from low-order half of Q
49 or r6,r6,r5 # merge the two selections
50 """
51
52 def __init__(self, width):
53 self.width = width
54 self.rs = Signal(width, reset_less=True)
55 self.ra = Signal(width, reset_less=True)
56 self.rb = Signal(width, reset_less=True)
57
58 def elaborate(self, platform):
59 m = Module()
60 perm = Signal(self.width, reset_less=True)
61 rb64 = [Signal(1, reset_less=True, name=f"rb64_{i}") for i in range(64)]
62 for i in range(64):
63 m.d.comb += rb64[i].eq(self.rb[63-i])
64 rb64 = Array(rb64)
65 for i in range(8):
66 index = self.rs[8*i:8*i+8]
67 idx = Signal(8, name=f"idx_{i}", reset_less=True)
68 m.d.comb += idx.eq(index)
69 with m.If(idx < 64):
70 m.d.comb += perm[i].eq(rb64[idx])
71 m.d.comb += self.ra[0:8].eq(perm)
72 return m
73
74
75 if __name__ == "__main__":
76 bperm = Bpermd(width=64)
77 main(bperm, ports=[bperm.rs, bperm.ra, bperm.rb])