From f0b33caf3e1b2c6ad64e2ce4e38064c8692d72e8 Mon Sep 17 00:00:00 2001 From: Daniel Benusovich Date: Sun, 3 Mar 2019 21:47:02 -0800 Subject: [PATCH] Update CAM to represent and actual CAM. No more key! --- TLB/src/Cam.py | 39 ++++++++++++++++++++------------------- TLB/test/test_cam.py | 36 +++++++++++++++++++----------------- 2 files changed, 39 insertions(+), 36 deletions(-) diff --git a/TLB/src/Cam.py b/TLB/src/Cam.py index 62b5462a..4fc9ccfe 100644 --- a/TLB/src/Cam.py +++ b/TLB/src/Cam.py @@ -1,6 +1,5 @@ from nmigen import Array, Module, Signal from nmigen.lib.coding import Encoder, Decoder -from nmigen.compat.fhdl.structure import ClockDomain from nmigen.cli import main #, verilog from CamEntry import CamEntry @@ -25,44 +24,47 @@ class Cam(): the read to be ignored. """ - def __init__(self, key_size, data_size, cam_size): + def __init__(self data_size, cam_size): """ Arguments: - * key_size: (bit count) The size of the key * data_size: (bit count) The size of the data * cam_size: (entry count) The number of entries int he CAM """ + # Internal self.cam_size = cam_size - self.entry_array = Array(CamEntry(key_size, data_size) \ + self.encoder = Encoder(cam_size) + self.decoder = Decoder(cam_size) + self.entry_array = Array(CamEntry(data_size) \ for x in range(cam_size)) # Input # 000 => NA 001 => Read 010 => Write 011 => Search # 100 => Reset 101, 110, 111 => Reserved - self.command = Signal(3) + self.command = Signal(3) + self.enable = Signal(1) + self.data_in = Signal(data_size) # The data to be written + self.data_mask = Signal(data_size) # mask for ternary writes + self.write_enable = Signal(1) # write self.address = Signal(max=cam_size) # address of CAM Entry to write/read - self.key_in = Signal(key_size) # The key to search for or to be written - self.data_in = Signal(key_size) # The data to be written - + # Output self.data_hit = Signal(1) # Denotes a key data pair was stored at key_in self.data_out = Signal(data_size) # The data mapped to by key_in def elaborate(self, platform=None): m = Module() - # Encoder is used to selecting what data is output when searching - m.submodules.encoder = encoder = Encoder(self.cam_size) + m.submodules += self.encoder # Decoder is used to select which entry will be written to - m.submodules.decoder = decoder = Decoder(self.cam_size) + m.submodules += self.decoder # Don't forget to add all entries to the submodule list entry_array = self.entry_array m.submodules += entry_array # Decoder logic m.d.comb += [ - decoder.i.eq(self.address), - decoder.n.eq(0) + self.decoder.i.eq(self.address), + self.decoder.n.eq(0) ] # Set the key value for every CamEntry @@ -72,13 +74,13 @@ class Cam(): with m.Case("0-1"): m.d.comb += entry_array[index].command.eq(1) # Only read if an encoder value is not ready - with m.If(decoder.o[index] & encoder.n): + with m.If(self.decoder.o[index] & self.encoder.n): m.d.comb += self.data_out.eq(entry_array[index].data) # Write only to one entry with m.Case("010"): # Address is decoded and selects which # entry will be written to - with m.If(decoder.o[index]): + with m.If(self.decoder.o[index]): m.d.comb += entry_array[index].command.eq(2) with m.Else(): m.d.comb += entry_array[index].command.eq(0) @@ -93,16 +95,15 @@ class Cam(): m.d.comb += entry_array[index].command.eq(0) m.d.comb += [ - entry_array[index].key_in.eq(self.key_in), entry_array[index].data_in.eq(self.data_in), - encoder.i[index].eq(entry_array[index].match) + self.encoder.i[index].eq(entry_array[index].match) ] # Process out data based on encoder address - with m.If(encoder.n == 0): + with m.If(self.encoder.n == 0): m.d.comb += [ self.data_hit.eq(1), - self.data_out.eq(entry_array[encoder.o].data) + self.data_out.eq(entry_array[self.encoder.o].data) ] with m.Else(): m.d.comb += self.data_hit.eq(0) diff --git a/TLB/test/test_cam.py b/TLB/test/test_cam.py index 2e058634..b3ce3572 100644 --- a/TLB/test/test_cam.py +++ b/TLB/test/test_cam.py @@ -8,10 +8,9 @@ from Cam import Cam from test_helper import assert_eq, assert_ne -def set_cam(dut, c, a, k, d): +def set_cam(dut, c, a, d): yield dut.command.eq(c) yield dut.address.eq(a) - yield dut.key_in.eq(k) yield dut.data_in.eq(d) yield @@ -38,63 +37,66 @@ def testbench(dut): # NA command = 0 address = 0 - key = 0 data = 0 data_hit = 0 - yield from set_cam(dut, command, address, key, data) + yield from set_cam(dut, command, address, data) yield from check_data_hit(dut, data_hit, 0) # Search command = 3 address = 0 - key = 0 data = 0 data_hit = 0 - yield from set_cam(dut, command, address, key, data) + yield from set_cam(dut, command, address, data) yield from check_data_hit(dut, data_hit, 0) # Write Entry 0 command = 2 address = 0 - key = 5 data = 4 data_hit = 0 - yield from set_cam(dut, command, address, key, data) + yield from set_cam(dut, command, address, data) yield from check_data_hit(dut, data_hit, 0) # Read Entry 0 command = 1 address = 0 - key = 0 data = 4 data_hit = 0 - yield from set_cam(dut, command, address, key, data) + yield from set_cam(dut, command, address, data) yield from check_all(dut, data_hit, data, 0, 0) - # Search + # Search Hit command = 3 address = 0 - key = 5 data = 4 data_hit = 1 - yield from set_cam(dut, command, address, key, data) + yield from set_cam(dut, command, address, data) yield yield from check_all(dut, data_hit, data, 0, 0) + # Search Miss + command = 3 + address = 0 + data = 5 + data_hit = 0 + yield from set_cam(dut, command, address, data) + yield + yield from check_all(dut, data_hit, data, 0, 1) + # Reset command = 4 address = 0 - key = 0 data = 0 data_hit = 0 - yield from set_cam(dut, command, address, key, data) + yield from set_cam(dut, command, address, data) yield - yield from check_all(dut, data_hit, data, 0, 0) + yield from check_all(dut, data_hit, data, 0, 0) yield if __name__ == "__main__": - dut = Cam(4, 4, 4) + dut = Cam(4, 4) run_simulation(dut, testbench(dut), vcd_name="Waveforms/cam_test.vcd") print("Cam Unit Test Success") \ No newline at end of file -- 2.30.2