getWriteData method

Logic getWriteData(
  1. Logic wd
)

Given some arbitrary data wd to write to this CSR, return the data that should actually be written based on the access control of the CSR and its fields.

Implementation

Logic getWriteData(Logic wd) {
  // if the whole register is ready only, return the current value
  if (access == CsrAccess.readOnly) {
    return this;
  }
  // register can be written, but still need to look at the fields...
  else {
    // special case of no explicit fields defined
    // in this case, we have an implicit read/write field
    // so there is nothing special to do
    if (fields.isEmpty) {
      return wd;
    }

    // otherwise, we need to look at the fields
    var finalWd = wd;
    var currIdx = 0;
    var currField = 0;
    for (var i = 0; i < elements.length; i++) {
      // if the given field is reserved or read only
      // take the current value instead of the new value
      final chk1 = rsvdIndices.contains(i);
      if (chk1) {
        finalWd = finalWd.withSet(currIdx, elements[i]);
        currIdx += elements[i].width;
        continue;
      }

      // if the given field is read only
      // take the current value instead of the new value
      final chk2 = fields[currField].access == CsrFieldAccess.readOnly ||
          fields[currField].access == CsrFieldAccess.writeOnesClear;
      if (chk2) {
        finalWd = finalWd.withSet(currIdx, elements[i]);
        currField++;
        currIdx += elements[i].width;
        continue;
      }

      if (fields[currField].access == CsrFieldAccess.readWriteLegal) {
        // if the given field is write legal
        // make sure the value is in fact legal
        // and transform it if not
        final origVal =
            wd.getRange(currIdx, currIdx + fields[currField].width);
        final legalCases = <Logic, Logic>{};
        for (var i = 0; i < fields[currField].legalValues.length; i++) {
          legalCases[Const(fields[currField].legalValues[i],
              width: fields[currField].width)] = origVal;
        }
        final newVal = cases(
            origVal,
            conditionalType: ConditionalType.unique,
            legalCases,
            defaultValue: Const(fields[currField].transformIllegalValue(),
                width: fields[currField].width));

        finalWd = finalWd.withSet(currIdx, newVal);
        currField++;
        currIdx += elements[i].width;
      } else {
        // normal read/write field
        currField++;
        currIdx += elements[i].width;
      }
    }
    return finalWd;
  }
}