Remove wen term and shift If blocks to remove NOT need
[soc.git] / TLB / src / Cam.py
index b15dd275963356ced0c5fe686a40ddf6b6478cf1..3606234b1180c96324480bb71d13ca73150d6b41 100644 (file)
@@ -1,8 +1,10 @@
 from nmigen import Array, Module, Signal
-from nmigen.lib.coding import PriorityEncoder, Decoder
+from nmigen.lib.coding import Decoder
 from nmigen.cli import main #, verilog
 
 from CamEntry import CamEntry
+from AddressEncoder import AddressEncoder
+from VectorAssembler import VectorAssembler
 
 class Cam():
     """ Content Addressable Memory (CAM)
@@ -32,18 +34,19 @@ class Cam():
 
         # Internal
         self.cam_size = cam_size
-        self.encoder = PriorityEncoder(cam_size)
+        self.encoder = AddressEncoder(cam_size)
         self.decoder = Decoder(cam_size)
         self.entry_array = Array(CamEntry(data_size) \
                             for x in range(cam_size))
+        self.vector_assembler = VectorAssembler(cam_size)
 
         # Input
         self.enable = Signal(1)
-        self.write_enable = Signal(1) 
+        self.write_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.address_in = Signal(max=cam_size) # address of CAM Entry to write
-        
+
         # Output
         self.read_warning = Signal(1) # High when a read interrupts a write
         self.single_match = Signal(1) # High when there is only one match
@@ -52,13 +55,14 @@ class Cam():
 
     def elaborate(self, platform=None):
         m = Module()
-        # Encoder is used to selecting what data is output when searching
-        m.submodules += self.encoder
+        # Encoder checks for multiple matches
+        m.submodules.AddressEncoder = self.encoder
         # Decoder is used to select which entry will be written to
-        m.submodules += self.decoder
+        m.submodules.Decoder = self.decoder
         # Don't forget to add all entries to the submodule list
         entry_array = self.entry_array
         m.submodules += entry_array
+        m.submodules.VectorAssembler = self.vector_assembler
 
         # Decoder logic
         m.d.comb += [
@@ -66,52 +70,50 @@ class Cam():
             self.decoder.n.eq(0)
         ]
 
-        # Set the key value for every CamEntry
-        for index in range(self.cam_size):
-            with m.If(self.enable == 1):
-                
-                # Read Operation
-                with m.If(self.write_enable == 0):
-                    m.d.comb += entry_array[index].command.eq(1)
-                    
+        with m.If(self.enable):
+            # Set the key value for every CamEntry
+            for index in range(self.cam_size):
+
                 # Write Operation
-                with m.Else():
+                with m.If(self.write_enable):
                     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)
-                        
+                        m.d.comb += entry_array[index].command.eq(0)                    
+
+                # Read Operation
+                with m.Else():
+                    m.d.comb += entry_array[index].command.eq(1)
+
                 # Send data input to all entries
                 m.d.comb += entry_array[index].data_in.eq(self.data_in)
-                # Send all entry matches to the priority encoder
-                m.d.comb += self.encoder.i[index].eq(entry_array[index].match)
-                
-                # Process out data based on encoder address
-                with m.If(self.encoder.n == 0):
-                    m.d.comb += [
-                        self.single_match.eq(1),
-                        self.match_address.eq(self.encoder.o)
-                    ]
-                with m.Else():
-                    m.d.comb += [
-                        self.read_warning.eq(0),
-                        self.single_match.eq(0),
-                        self.multiple_match.eq(0),
-                        self.match_address.eq(0)
-                    ]
-                    
-            with m.Else():
-                m.d.comb += [
-                        self.read_warning.eq(0),
-                        self.single_match.eq(0),
-                        self.multiple_match.eq(0),
-                        self.match_address.eq(0)
-                ]
+                # Send all entry matches to encoder
+                ematch = entry_array[index].match
+                m.d.comb += self.vector_assembler.i[index].eq(ematch)
+
+            # Give input to and accept output from encoder module
+            m.d.comb += [
+                self.encoder.i.eq(self.vector_assembler.o),
+                self.single_match.eq(self.encoder.single_match),
+                self.multiple_match.eq(self.encoder.multiple_match),
+                self.match_address.eq(self.encoder.o)
+            ]
+
+        # If the CAM is not enabled set all outputs to 0
+        with m.Else():
+            m.d.comb += [
+                    self.read_warning.eq(0),
+                    self.single_match.eq(0),
+                    self.multiple_match.eq(0),
+                    self.match_address.eq(0)
+            ]
+
         return m
 
 if __name__ == '__main__':
     cam = Cam(4, 4)
-    main(cam, ports=[cam.command, cam.address,
-                     cam.data_in, cam.data_hit,
-                     cam.data_out])
+    main(cam, ports=[cam.enable, cam.write_enable,
+                     cam.data_in, cam.data_mask,
+                     cam.read_warning, cam.single_match,
+                     cam.multiple_match, cam.match_address])