getWriteData method
- 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;
}
}