FifoChecker constructor
Builds a checker for a fifo.
Attaches to the top level Test.instance if no parent is provided.
Implementation
FifoChecker(
this.fifo, {
String name = 'fifoChecker',
Component? parent,
this.enableEndOfTestEmptyCheck = true,
this.enableUnderflowCheck = true,
this.enableOverflowCheck = true,
}) : super(name, parent ?? Test.instance) {
var hasReset = false;
// ignore: invalid_use_of_protected_member
final fifoPortSignals = [...fifo.inputs.values, ...fifo.outputs.values]
// data can be invalid since it's not control
.where((e) => !e.name.contains('Data'));
fifo._clk.posedge.listen((event) {
if (!fifo._reset.previousValue!.isValid) {
// reset is invalid, bad state
hasReset = false;
return;
} else if (fifo._reset.previousValue!.toBool()) {
// reset is high, track that and move on
hasReset = true;
return;
} else if (hasReset) {
// reset is low, and we've previously reset, should be good to check
if (!fifoPortSignals
.map((e) => e.previousValue!.isValid)
.reduce((a, b) => a && b)) {
final portValuesMap = Map.fromEntries(
fifoPortSignals.map((e) => MapEntry(e.name, e.previousValue!)));
logger.severe('Fifo control port has an invalid value after reset.'
' Port values: $portValuesMap');
return;
}
if (fifo.full.previousValue!.toBool() &&
fifo._writeEnable.previousValue!.toBool() &&
!fifo._readEnable.previousValue!.toBool()) {
if (enableOverflowCheck) {
logger
.severe('Fifo $fifo received a write that caused an overflow.');
}
} else if (fifo.empty.previousValue!.toBool() &&
fifo._readEnable.previousValue!.toBool()) {
if (!(fifo.generateBypass &&
fifo._writeEnable.previousValue!.toBool())) {
if (enableUnderflowCheck) {
logger.severe(
'Fifo $fifo received a read that caused an underflow.');
}
}
}
}
});
}