refactor(am): improve checking and reporting

This commit is contained in:
Zimmerma
2025-09-26 09:41:26 +02:00
committed by Derek Christ
parent 6665d6b6a1
commit 3d7c3ca473

View File

@@ -198,34 +198,55 @@ void AddressDecoder::checkMemorySize(const MemSpec& memSpec) {
(memSpec.getSimMemSizeInBytes() < upperBoundAddress + 1 && !np2Flag);
if (isMemorySizeMismatch) {
SC_REPORT_FATAL("AddressDecoder", "The mapped bits do not match the memory size");
std::ostringstream o;
o << "The mapped bits do not match the memory size field (MemSpec size: "
<< memSpec.getSimMemSizeInBytes() << ", mapping=" << upperBoundAddress + 1 << ")";
SC_REPORT_FATAL("AddressDecoder", o.str().c_str());
}
}
void AddressDecoder::checkMemSpecCompatibility(const MemSpec& memSpec) {
unsigned channels = std::lround(std::pow(2, channelBits.length));
unsigned ranks = std::lround(std::pow(2, rankBits.length));
unsigned rows = std::lround(std::pow(2, rowBits.length));
unsigned columns = std::lround(std::pow(2, columnBits.length));
unsigned pseudochannels = std::lround(std::pow(2, pseudochannelBits.length));
const unsigned channels = std::lround(std::pow(2, channelBits.length));
const unsigned ranks = std::lround(std::pow(2, rankBits.length));
const unsigned rows = std::lround(std::pow(2, rowBits.length));
const unsigned columns = std::lround(std::pow(2, columnBits.length));
const unsigned pseudochannels = std::lround(std::pow(2, pseudochannelBits.length));
unsigned absoluteBankGroups = bankgroupsPerRank * (ranks * pseudochannels);
unsigned absoluteBanks = banksPerGroup * absoluteBankGroups;
const unsigned absoluteBankGroups = bankgroupsPerRank * (ranks * pseudochannels);
const unsigned absoluteBanks = banksPerGroup * absoluteBankGroups;
const unsigned effectiveRanksPerChannel = static_cast<uint64_t>(ranks) * static_cast<uint64_t>(pseudochannels);
// Depending on the NP2 flag we must adapt the strictness of this check
if (np2Flag) {
if (memSpec.numberOfChannels > channels || memSpec.ranksPerChannel > (ranks * pseudochannels) ||
memSpec.bankGroupsPerChannel > absoluteBankGroups ||
memSpec.banksPerChannel > absoluteBanks || memSpec.rowsPerBank > rows ||
memSpec.columnsPerRow > columns)
SC_REPORT_FATAL("AddressDecoder", "Memspec and address mapping do not match");
}
else {
if (memSpec.numberOfChannels != channels || memSpec.ranksPerChannel != (ranks * pseudochannels) ||
memSpec.bankGroupsPerChannel != absoluteBankGroups ||
memSpec.banksPerChannel != absoluteBanks || memSpec.rowsPerBank != rows ||
memSpec.columnsPerRow != columns)
SC_REPORT_FATAL("AddressDecoder", "Memspec and address mapping do not match");
// Depending on the NP2 flag we might need to adapt the strictness of the checks
auto cmp = np2Flag
? std::function<bool(uint64_t,uint64_t)>([](uint64_t a, uint64_t b){ return a <= b; })
: std::function<bool(uint64_t,uint64_t)>([](uint64_t a, uint64_t b){ return a == b; });
// Check all and collect the errors
std::vector<std::string> errors;
const char* rel = np2Flag ? "<=" : "==";
auto check = [&](const char* field, uint64_t mem, uint64_t map) {
if (!cmp(mem, map)) {
std::ostringstream o;
o << field << ": memSpec=" << mem << ", mapping=" << map
<< " (required: memSpec " << rel << " mapping)";
errors.push_back(o.str());
}
};
check("numberOfChannels", memSpec.numberOfChannels, channels);
check("ranksPerChannel", memSpec.ranksPerChannel, effectiveRanksPerChannel);
check("bankGroupsPerChannel", memSpec.bankGroupsPerChannel, absoluteBankGroups);
check("banksPerChannel", memSpec.banksPerChannel, absoluteBanks);
check("rowsPerBank", memSpec.rowsPerBank, rows);
check("columnsPerRow", memSpec.columnsPerRow, columns);
// Handle collected errors
if (!errors.empty()) {
std::ostringstream all;
all << "Unexpected deviations between MemSpec and Address Mapping:\n";
for (auto& e : errors) all << " - " << e << '\n';
std::string msg = all.str();
SC_REPORT_FATAL("AddressDecoder", msg.c_str());
}
}