Cam constructor
Constructs a new Cam with write ports and lookup ports using TagInterface.
For write ports, en enables the write, idx specifies the address,
and tag provides the data to write. The hit signal is ignored for
writes.
For lookup ports, tag is the query, idx returns the matching index,
and hit indicates whether a match was found.
If enableValidTracking is true, the CAM will maintain a count of
valid entries and provide full, empty, and validCount signals.
Example with valid tracking enabled:
final cam = Cam(
clk, reset,
[writePort], [lookupPort],
numEntries: 16,
enableValidTracking: true,
);
// Use cam.full, cam.empty, and cam.validCount signals
Implementation
Cam(Logic clk, Logic reset, List<TagInterface> writePorts,
List<TagInterface> lookupPorts,
{this.numEntries = 8,
this.enableValidTracking = false,
super.name = 'cam',
super.reserveName,
super.reserveDefinitionName,
String? definitionName})
: numWrites = writePorts.length,
numLookups = lookupPorts.length,
super(
definitionName: definitionName ??
'CAM_WP${writePorts.length}'
'_LP${lookupPorts.length}_E$numEntries') {
if (writePorts.isEmpty && lookupPorts.isEmpty) {
throw ArgumentError('Must provide at least one write or lookup port.');
}
if (lookupPorts.isEmpty) {
throw ArgumentError('Must provide at least one lookup port.');
}
addInput('clk', clk);
addInput('reset', reset);
// Connect write ports - all signals are inputs for writes
for (var i = 0; i < numWrites; i++) {
wrPorts.add(writePorts[i].clone()
..connectIO(this, writePorts[i],
inputTags: {DataPortGroup.control, DataPortGroup.data},
outputTags: {},
uniquify: (original) => 'wr_${original}_$i'));
}
// Connect lookup ports - control signals are inputs, data signals are
// outputs
for (var i = 0; i < numLookups; i++) {
this.lookupPorts.add(lookupPorts[i].clone()
..connectIO(this, lookupPorts[i],
inputTags: {DataPortGroup.control},
outputTags: {DataPortGroup.data},
uniquify: (original) => 'lookup_${original}_$i'));
}
_buildLogic();
}