e4f1d784936cd03592ced596bd7a97f064e1551f
[soc.git] / TLB / CamEntry.py
1 from nmigen import Module, Signal
2 from nmigen.compat.fhdl.structure import If
3 from nmigen.compat.sim import run_simulation
4
5 class CamEntry:
6 def __init__(self, key_size, data_size):
7 # Internal
8 self.key = Signal(key_size)
9
10 # Input
11 self.write = Signal(1) # Read => 0 Write => 1
12 self.key_in = Signal(key_size) # Reference key for the CAM
13 self.data_in = Signal(data_size) # Data input when writing
14
15 # Output
16 self.match = Signal(1) # Result of the internal/input key comparison
17 self.data = Signal(data_size)
18
19
20 def get_fragment(self, platform=None):
21 m = Module()
22 with m.If(self.write == 1):
23 m.d.sync += [
24 self.key.eq(self.key_in),
25 self.data.eq(self.data_in),
26 self.match.eq(1)
27 ]
28 with m.Else():
29 with m.If(self.key_in == self.key):
30 m.d.sync += self.match.eq(0)
31 with m.Else():
32 m.d.sync += self.match.eq(1)
33
34 return m
35
36 #########
37 # TESTING
38 ########
39
40 # This function allows for the easy setting of values to the Cam Entry
41 # unless the key is incorrect
42 # Arguments:
43 # dut: The CamEntry being tested
44 # w (write): Read (0) or Write (1)
45 # k (key): The key to be set
46 # d (data): The data to be set
47 def set_cam(dut, w, k, d):
48 yield dut.write.eq(w)
49 yield dut.key_in.eq(k)
50 yield dut.data_in.eq(d)
51 yield
52
53 # Verifies the given values via the requested operation
54 # Arguments:
55 # pre (Prefix): Appended to the front of the assert statement
56 # e (Expected): The expected value
57 # out (Output): The output result
58 # op (Operation): (0 => ==), (1 => !=)
59 def check(pre, e, out, op):
60 if(op == 0):
61 yield
62 assert out == e, pre + " Output " + str(out) + " Expected " + str(e)
63 else:
64 yield
65 assert out != e, pre + " Output " + str(out) + " Expected " + str(e)
66
67 # Checks the key state of the CAM entry
68 # Arguments:
69 # dut: The CamEntry being tested
70 # k (Key): The expected key
71 # op (Operation): (0 => ==), (1 => !=)
72 def check_key(dut, k, op):
73 out_k = yield dut.key
74 check("K", out_k, k, op)
75
76 # Checks the data state of the CAM entry
77 # Arguments:
78 # dut: The CamEntry being tested
79 # d (Data): The expected data
80 # op (Operation): (0 => ==), (1 => !=)
81 def check_data(dut, d, op):
82 out_d = yield dut.data
83 check("D", out_d, d, op)
84
85 # Checks the match state of the CAM entry
86 # Arguments:
87 # dut: The CamEntry being tested
88 # m (Match): The expected match
89 # op (Operation): (0 => ==), (1 => !=)
90 def check_match(dut, m, op):
91 out_m = yield dut.match
92 check("M", out_m, m, op)
93
94 # Checks the state of the CAM entry
95 # Arguments:
96 # dut: The CamEntry being tested
97 # k (key): The expected key
98 # d (data): The expected data
99 # m (match): The expected match
100 # kop (Operation): The operation for the key assertion (0 => ==), (1 => !=)
101 # dop (Operation): The operation for the data assertion (0 => ==), (1 => !=)
102 # mop (Operation): The operation for the match assertion (0 => ==), (1 => !=)
103 def check_all(dut, k, d, m, kop, dop, mop):
104 yield from check_key(dut, k, kop)
105 yield from check_data(dut, d, dop)
106 yield from check_match(dut, m, mop)
107
108 # This testbench goes through the paces of testing the CamEntry module
109 # It is done by writing and then reading various combinations of key/data pairs
110 # and reading the results with varying keys to verify the resulting stored
111 # data is correct.
112 def testbench(dut):
113 # Check write
114 write = 1
115 key = 1
116 data = 1
117 match = 1
118 yield from set_cam(dut, write, key, data)
119 yield from check_all(dut, key, data, match, 0, 0, 0)
120
121 # Check read miss
122 write = 0
123 key = 2
124 data = 1
125 match = 0
126 yield from set_cam(dut, write, key, data)
127 yield from check_all(dut, key, data, match, 1, 0, 0)
128
129 # Check read hit
130 write = 0
131 key = 1
132 data = 1
133 match = 1
134 yield from set_cam(dut, write, key, data)
135 yield from check_all(dut, key, data, match, 0, 0, 0)
136
137 # Check write
138 write = 1
139 key = 2
140 data = 5
141 match = 1
142 yield from set_cam(dut, write, key, data)
143 yield from check_all(dut, key, data, match, 0, 0, 0)
144
145 yield
146
147 if __name__ == "__main__":
148 dut = CamEntry(4, 4)
149 run_simulation(dut, testbench(dut), vcd_name="Waveforms/cam_entry_test.vcd")