move pipelines to pipe dir
[soc.git] / src / soc / pipe / logical / bperm.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 """This class does a Bit Permute on a Doubleword
7
8 X-form bpermd RA,RS,RB]
9
10 Eight permuted bits are produced. For each permuted bit i where i ranges
11 from 0 to 7 and for each byte i of RS, do the following. If byte i of RS
12 is less than 64, permuted bit i is setto the bit of RB specified by byte
13 i of RS; otherwise permuted bit i is set to 0. The permuted bits are
14 placed in the least-significantbyte of RA, and the remaining bits are
15 filled with 0s.
16 Special Registers Altered: None
17
18 Programming note:
19 The fact that the permuted bit is 0 if the corresponding index value
20 exceeds 63 permits the permuted bits to be selected from a 128-bit
21 quantity, using a single index register. For example, assume that the
22 128-bit quantity Q, from which the permuted bits are to be selected, is
23 in registers r2(high-order 64 bits of Q) and r3 (low-order 64 bits of Q),
24 that the index values are in register r1, with each byte of r1 containing
25 a value in the range 0:127, and that each byte of register r4 contains
26 the value 64. The following code sequence selects eight permuted bits
27 from Q and places them into the low-order byte of r6.
28 """
29
30 def __init__(self, width):
31 self.width = width
32 self.rs = Signal(width, reset_less=True)
33 self.ra = Signal(width, reset_less=True)
34 self.rb = Signal(width, reset_less=True)
35
36 def elaborate(self, platform):
37 m = Module()
38 perm = Signal(self.width, reset_less=True)
39 rb64 = [Signal(1, reset_less=True, name=f"rb64_{i}") for i in range(64)]
40 for i in range(64):
41 m.d.comb += rb64[i].eq(self.rb[i])
42 rb64 = Array(rb64)
43 for i in range(8):
44 index = self.rs[8*i:8*i+8]
45 idx = Signal(8, name=f"idx_{i}", reset_less=True)
46 m.d.comb += idx.eq(index)
47 with m.If(idx < 64):
48 m.d.comb += perm[i].eq(rb64[idx])
49 m.d.comb += self.ra[0:8].eq(perm)
50 return m
51
52
53 if __name__ == "__main__":
54 bperm = Bpermd(width=64)
55 main(bperm, ports=[bperm.rs, bperm.ra, bperm.rb])