From adaeb076bf7bab491d9b5c254dc78f25a189814e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E6=A0=BC=E8=87=B4?= Date: Wed, 8 Apr 2026 10:54:39 +0800 Subject: [PATCH] refactor(SBuffer, StoreDifftest): move diff store event calculate part from scala to cpp BREAKING CHANGE: struct DifftestStoreEvent is changed and broke backward compatibility! --- src/main/scala/Bundles.scala | 19 +++-- src/test/csrc/difftest/checkers/store.cpp | 94 ++++++++++++++++++++--- 2 files changed, 98 insertions(+), 15 deletions(-) diff --git a/src/main/scala/Bundles.scala b/src/main/scala/Bundles.scala index 9779e40a6..f9fc034ff 100644 --- a/src/main/scala/Bundles.scala +++ b/src/main/scala/Bundles.scala @@ -245,16 +245,23 @@ class UncacheMMStoreEvent extends DifftestBaseBundle with HasValid { } class StoreEvent extends DifftestBaseBundle with HasValid { - val addr = UInt(64.W) - val data = UInt(64.W) - val highData = UInt(64.W) - val mask = UInt(16.W) val wLine = Bool() - val vecNeedSplit = Bool() - val eew = UInt(8.W) val offset = UInt(16.W) val pc = UInt(64.W) val robidx = UInt(10.W) + + val isNonCacheable = Bool() + val isVStore = Bool() + val isUStride = Bool() + val isMasked = Bool() + val isWhole = Bool() + val veew = UInt(8.W) + val nf = UInt(8.W) + val rawDataLow = UInt(64.W) + val rawDataHigh = UInt(64.W) + val rawMask = UInt(16.W) + val rawAddr = UInt(64.W) + val isHighPart = Bool() } class LoadEvent extends DifftestBaseBundle with HasValid { diff --git a/src/test/csrc/difftest/checkers/store.cpp b/src/test/csrc/difftest/checkers/store.cpp index 202fcb72f..e002c87c3 100644 --- a/src/test/csrc/difftest/checkers/store.cpp +++ b/src/test/csrc/difftest/checkers/store.cpp @@ -27,6 +27,13 @@ void StoreRecorder::clear_valid(DifftestStoreEvent &probe) { probe.valid = 0; } +// Expand 8-bit mask to bit-and with 64-bit wide data +static uint64_t MaskExpand(uint8_t mask) { + uint64_t expander = 0x0101010101010101ULL; + uint64_t selector = 0x8040201008040201ULL; + return (((((mask * expander) & selector) * 0xFFULL) >> 7) & expander) * 0xFFULL; +} + int StoreRecorder::check(const DifftestStoreEvent &probe) { if (!probe.valid) return STATE_OK; @@ -35,18 +42,87 @@ int StoreRecorder::check(const DifftestStoreEvent &probe) { int WORDBYTES = 8; int COMMITBYTES = 16; - auto addr = probe.addr; - auto lowData = probe.data; - auto highData = probe.highData; - auto mask = probe.mask; + uint64_t calcAddr; + uint64_t calcDataLow; + uint64_t calcDataHigh; + uint16_t calcMask; + uint8_t calcEEW; + bool calcIsVSLine; + + auto isNonCacheable = probe.isNonCacheable; + auto isVStore = probe.isVStore; + auto isUStride = probe.isUStride; + auto isMasked = probe.isMasked; + auto isWhole = probe.isWhole; + auto veew = probe.veew; + auto nf = probe.nf; + auto rawDataLow = probe.rawDataLow; + auto rawDataHigh = probe.rawDataHigh; + auto rawMask = probe.rawMask; + auto rawAddr = probe.rawAddr; + auto wLine = probe.wLine; + auto isHighPart = probe.isHighPart; + + if (!isNonCacheable) { + bool isVse = isVStore && isUStride; + bool isVsm = isVStore && isMasked; + bool isVsr = isVStore && isWhole; + + uint8_t eew = veew; + uint32_t EEB = 1 << eew; + uint8_t nf2 = isVsr ? 0 : nf; + + bool isSegment = nf2 != 0 && !isVsm; + bool isVSLine = (isVse || isVsm || isVsr) && !isSegment; + bool isWline = wLine; + calcIsVSLine = isVSLine; + + if (isVSLine) { + calcAddr = rawAddr; + calcDataLow = rawDataLow; + calcDataHigh = rawDataHigh; + calcMask = rawMask; + } else if (isWline) { + calcAddr = rawAddr; + calcDataLow = rawDataLow; + calcDataHigh = rawDataHigh; + calcMask = rawMask; + Assert(rawDataLow == 0 && rawDataHigh == 0, "wLine only supports whole zero write now"); + } else if (isHighPart) { + calcAddr = (rawAddr & (~0xFULL)) | 0b1000; + calcMask = (rawMask >> 8) & 0xFF; + uint64_t tmpData = rawDataHigh; + calcDataLow = tmpData & MaskExpand(calcMask); + calcDataHigh = 0; + } else { + calcAddr = rawAddr & (~0xFULL); + calcMask = rawMask & 0xFF; + uint64_t tmpData = rawDataLow; + calcDataLow = tmpData & MaskExpand(calcMask); + calcDataHigh = 0; + } + calcEEW = EEB; + } else { + calcAddr = rawAddr & (~7ULL); + calcMask = rawMask; + calcDataLow = rawDataLow & MaskExpand(calcMask); + calcDataHigh = 0; + calcEEW = 0; + calcIsVSLine = false; + } + + auto addr = calcAddr; + auto lowData = calcDataLow; + auto highData = calcDataHigh; + auto mask = calcMask; auto offset = probe.offset; - auto eew = probe.eew; + auto eew = calcEEW; auto pc = probe.pc; auto robIdx = probe.robidx; uint64_t rawVecAddr = addr + offset; - if (probe.vecNeedSplit) { + if (calcIsVSLine) { uint16_t flow = COMMITBYTES / eew; uint64_t flowMask = (eew == 1) ? 0x1ULL : (eew == 2) ? 0x3ULL : (eew == 4) ? 0xfULL : (eew == 8) ? 0xffULL : 0x0ULL; uint64_t flowMaskBit = (eew == 1) ? 0xffULL @@ -103,7 +179,7 @@ int StoreRecorder::check(const DifftestStoreEvent &probe) { nextOffset = 8 - rawOffset; auto nextDataOffset = nextOffset * 8; - auto nextData = probe.highData << nextDataOffset; + auto nextData = calcDataHigh << nextDataOffset; refStoreCommitData = (nextData + presentData) & flowMaskBit; } else { @@ -145,9 +221,9 @@ int StoreRecorder::check(const DifftestStoreEvent &probe) { } } else { DiffState::StoreCommit storeCommit = {probe.valid, - probe.addr, + calcAddr, lowData, - static_cast(probe.mask & 0xFF), + static_cast(calcMask & 0xFF), pc, robIdx #ifdef CONFIG_DIFFTEST_SQUASH