From dca7371e2621f508be61af0b0ea65c20a31cbc04 Mon Sep 17 00:00:00 2001 From: Daniel Benusovich Date: Sun, 24 Feb 2019 23:10:02 -0800 Subject: [PATCH] Adding Reset. Cleaning Logic for CAM. Still needs tests --- TLB/src/Cam.py | 91 +++++++++++++++++++++++++------------------- TLB/test/test_cam.py | 12 +++++- 2 files changed, 63 insertions(+), 40 deletions(-) diff --git a/TLB/src/Cam.py b/TLB/src/Cam.py index 42b7f028..30783cea 100644 --- a/TLB/src/Cam.py +++ b/TLB/src/Cam.py @@ -1,5 +1,5 @@ from nmigen import Array, Module, Signal -from nmigen.lib.coding import Encoder +from nmigen.lib.coding import Encoder, Decoder from nmigen.compat.fhdl.structure import ClockDomain from CamEntry import CamEntry @@ -14,6 +14,10 @@ from CamEntry import CamEntry # command it will write the given key and data into the given cam entry index. # Entry managment should be performed one level above this block as lookup is # performed within. +# Notes: +# The search, write, and reset operations take one clock cycle to complete. +# Attempting a read before reading the search result will cause +# the read to be ignored. class Cam(): # Arguments: @@ -27,7 +31,9 @@ class Cam(): for x in range(cam_size)) # Input - self.command = Signal(2) # 00 => NA 01 => Read 10 => Write 11 => Search + # 000 => NA 001 => Read 010 => Write 011 => Search + # 100 => Reset 101, 110, 111 => Reserved + self.command = Signal(3) 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 @@ -39,54 +45,61 @@ class Cam(): 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.entry_array + # Decoder is used to select which entry will be written to + m.submodules.decoder = decoder = Decoder(self.cam_size) + # 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) + ] # Set the key value for every CamEntry for index in range(self.cam_size): with m.Switch(self.command): - # Read and Search both read from the CamEntry - with m.Case("-1"): - m.d.comb += self.entry_array[index].command.eq(1) + # Read from a single entry + 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): + m.d.comb += self.data_out.eq(entry_array[index].data) # Write only to one entry - with m.Case("10"): - with m.If(self.address == index): - m.d.comb += self.entry_array[index].command.eq(2) + with m.Case("010"): + # Address is decoded and selects which + # entry will be written to + with m.If(decoder.o[index]): + m.d.comb += entry_array[index].command.eq(2) with m.Else(): - m.d.comb += self.entry_array[index].command.eq(0) - # NA + m.d.comb += entry_array[index].command.eq(0) + # Search all entries + with m.Case("011"): + m.d.comb += entry_array[index].command.eq(1) + # Reset + with m.Case("100"): + m.d.comb += entry_array[index].command.eq(3) + # NA / Reserved with m.Case(): - m.d.comb += self.entry_array[index].command.eq(0) + m.d.comb += entry_array[index].command.eq(0) m.d.comb += [ - self.entry_array[index].key_in.eq(self.key_in), - self.entry_array[index].data_in.eq(self.data_in), - encoder.i[index].eq(self.entry_array[index].match) + 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) ] + # Process out data based on encoder address + with m.If(encoder.n == 0): + m.d.comb += [ + self.data_hit.eq(1), + self.data_out.eq(entry_array[encoder.o].data) + ] + with m.Else(): + m.d.comb += self.data_hit.eq(0) - with m.Switch(self.command): - # Read - with m.Case("01"): - m.d.comb += [ - self.data_hit.eq(0), - self.data_out.eq(self.entry_array[self.address].data) - ] - # Write - with m.Case("10"): - m.d.comb += [ - self.data_hit.eq(0), - self.entry_array[self.address].key_in.eq(self.key_in), - self.entry_array[self.address].data_in.eq(self.data_in) - ] - # NA / Searching - with m.Case(): - with m.If(encoder.n == 0): - m.d.comb += [ - self.data_hit.eq(1), - self.data_out.eq(self.entry_array[encoder.o].data) - ] - with m.Else(): - m.d.comb += self.data_hit.eq(0) - return m diff --git a/TLB/test/test_cam.py b/TLB/test/test_cam.py index c5141a93..2e058634 100644 --- a/TLB/test/test_cam.py +++ b/TLB/test/test_cam.py @@ -79,7 +79,17 @@ def testbench(dut): data_hit = 1 yield from set_cam(dut, command, address, key, data) yield - yield from check_all(dut, data_hit, data, 0, 0) + yield from check_all(dut, data_hit, data, 0, 0) + + # Reset + command = 4 + address = 0 + key = 0 + data = 0 + data_hit = 0 + yield from set_cam(dut, command, address, key, data) + yield + yield from check_all(dut, data_hit, data, 0, 0) yield -- 2.30.2