Port ContentAddressableMemory from #395#573
Conversation
| m.submodules.encoder_addr = encoder_addr = MultiPriorityEncoder(self.entries_number, 1) | ||
| m.submodules.encoder_valids = encoder_valids = MultiPriorityEncoder(self.entries_number, 1) |
There was a problem hiding this comment.
These have a single output, so they are just standard priority encoders, right?
There was a problem hiding this comment.
Yes. But PriorityEncoders are going to be removed from amaranth.lib and MultiPriorityEncoder is a more generic solution which will be useful in future.
| class ContentAddressableMemory(Elaboratable): | ||
| """Content addresable memory | ||
|
|
||
| This module implements a transactorn interface for the content addressable memory. |
There was a problem hiding this comment.
| This module implements a transactorn interface for the content addressable memory. | |
| This module implements a Transactron interface for a content-addressable memory. |
There was a problem hiding this comment.
Does it make sense to call it an interface, when there is no internal module which has a traditional interface?
Shouldn't you write a few words to explain what a content addressable memory is? Also, this is a very specialized kind of content-addressable memory - no non-destructive reads, no writes.
There was a problem hiding this comment.
And also, no possibility of adding an eviction mechanism, for CAMs used as a cache.
| m = TModule() | ||
|
|
||
| address_array = Array([Record(self.address_layout) for _ in range(self.entries_number)]) | ||
| data_array = Array([Record(self.data_layout) for _ in range(self.entries_number)]) |
There was a problem hiding this comment.
The data could be stored in a memory.
There was a problem hiding this comment.
After change of interface I decided to not use the Memory because it would need 3 ports.
|
This could be nice to have in Transactron (I see some use cases for it), but the work has stopped. :( |
Co-authored-by: Marek Materzok <tilk@tilk.eu>
|
I was able to run first test using |
|
I have prepared different solution which should be less prone to the order of processes because all data are generated before test execution (so only result has to be deterministic). Normal test execution is fast (no observable difference to the solution with randoms), but the case reduction can take a lot of time (45s). Below are two example messages with found failing examples. They are saved locally in |
| return m | ||
|
|
||
|
|
||
| class MultiPriorityEncoder(Elaboratable): |
There was a problem hiding this comment.
I was thinking that since the priority encoder is just a combinational logic, it would be nice if we could use it like:
idx, valid = prio_encoder(m, one_hot_signal)instead of the boilerplate code
m.submodules.prio_encoder = prio_encoder = PriorityEncoder(cnt)
m.d.av_comb += prio_encoder.i.eq(one_hot_singal)
idx = prio_encoder.o
valid = ~prio.encoder.nThere was a problem hiding this comment.
And another thing. It would be great if we could specify the bit order of the priority encoder. In theory by having one type of the priority encoder, we could get the other type by reversing the input and subtracting the outputs, but that requires a few adders.
I know that this is pretty much a feature request, so feel free to ignore it - it can be done later
There was a problem hiding this comment.
I have added create_priority_encoder to add the automatic connections. Please see what you think about it.
Regarding to the different bit ordering I don't see a reason why we should add it, because it can be handled without subtraction. You pass the reversed array and you use indexes returned by encoder in this reversed array.
There was a problem hiding this comment.
I have added create_priority_encoder to add the automatic connections.
First, that's a mouthful. Second, a shorthand for creating outputs_count=1 encoders would be nice, as the return type of the function complicates deconstruction.
There was a problem hiding this comment.
I have updated the name to the create additionally I have added create_simple as a special case for outputs_count=1.
Co-authored-by: Marek Materzok <tilk@tilk.eu>
| def fixture_initialize_testing_env(self, request): | ||
| self._transactron_hypothesis_iter_counter = 0 | ||
| self._transactron_base_output_file_name = ".".join(request.node.nodeid.split("/")) | ||
| self._transactron_current_output_file_name = self._transactron_base_output_file_name |
There was a problem hiding this comment.
The logic behind _transactron_current_output_file_name deserves a comment.
Co-authored-by: Marek Materzok <tilk@tilk.eu>
…ks into lekcyjna/port-cam
| """Content addresable memory | ||
|
|
||
| This module implements a content-addressable memory (in short CAM) with Transactron interface. | ||
| CAM is a type of memory where instead of predefined indexes there are used values feed in runtime |
|
|
||
| This module implements a content-addressable memory (in short CAM) with Transactron interface. | ||
| CAM is a type of memory where instead of predefined indexes there are used values feed in runtime | ||
| as keys (smimlar as in python dictionary). To insert new entry a pair `(key, value)` has to be |


Yet another PR to port something from #395. This time I ported CAM, which was requested by @makz00 for the LSU implementation. To port CAM few other things were needed:
Resolves: #560
Resolves: #559
EDIT 03.05.2024:
I have uploaded a new set of commits with the refactored functionalities, changes: