Convert instruction info from tuple to namedtuple
[soc.git] / src / soc / TLB / AddressEncoder.py
1 from nmigen import Module, Signal, Elaboratable
2 from nmigen.lib.coding import Encoder, PriorityEncoder
3
4 class AddressEncoder(Elaboratable):
5 """Address Encoder
6
7 The purpose of this module is to take in a vector and
8 encode the bits that are one hot into an address. This module
9 combines both nmigen's Encoder and PriorityEncoder and will state
10 whether the input line has a single bit hot, multiple bits hot,
11 or no bits hot. The output line will always have the lowest value
12 address output.
13
14 Usage:
15 The output is valid when either single or multiple match is high.
16 Otherwise output is 0.
17 """
18 def __init__(self, width):
19 """ Arguments:
20 * width: The desired length of the input vector
21 """
22 # Internal
23 self.encoder = Encoder(width)
24 self.p_encoder = PriorityEncoder(width)
25
26 # Input
27 self.i = Signal(width)
28
29 # Output
30 self.single_match = Signal(1)
31 self.multiple_match = Signal(1)
32 self.o = Signal(max=width)
33
34 def elaborate(self, platform=None):
35 m = Module()
36
37 # Add internal submodules
38 m.submodules.encoder = self.encoder
39 m.submodules.p_encoder = self.p_encoder
40
41 m.d.comb += [
42 self.encoder.i.eq(self.i),
43 self.p_encoder.i.eq(self.i)
44 ]
45
46 # Steps:
47 # 1. check if the input vector is non-zero
48 # 2. if non-zero, check if single match or multiple match
49 # 3. set output line to be lowest value address output
50
51 # If the priority encoder recieves an input of 0
52 # If n is 1 then the output is not valid
53 with m.If(self.p_encoder.n):
54 m.d.comb += [
55 self.single_match.eq(0),
56 self.multiple_match.eq(0),
57 self.o.eq(0)
58 ]
59 # If the priority encoder recieves an input > 0
60 with m.Else():
61 # Multiple Match if encoder n is invalid
62 with m.If(self.encoder.n):
63 m.d.comb += [
64 self.single_match.eq(0),
65 self.multiple_match.eq(1)
66 ]
67 # Single Match if encoder n is valid
68 with m.Else():
69 m.d.comb += [
70 self.single_match.eq(1),
71 self.multiple_match.eq(0)
72 ]
73 # Always set output based on priority encoder output
74 m.d.comb += self.o.eq(self.p_encoder.o)
75 return m