FifoChecker constructor

FifoChecker(
  1. Fifo fifo, {
  2. String name = 'fifoChecker',
  3. Component? parent,
  4. bool enableEndOfTestEmptyCheck = true,
  5. bool enableUnderflowCheck = true,
  6. bool enableOverflowCheck = true,
})

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.');
          }
        }
      }
    }
  });
}