Skip to content

Commit 10ddaa8

Browse files
klin02NewPaulWalker
andcommitted
fix(difftest): fix alignment for C++ type declarations
This update refines the alignment for difftest elems. Previously, element widths were simply rounded up to the nearest multiple of 8 bits, which could produce unsupported C++ types such as uint48_t (e.g., for a 41-bit signal). We now align each element to the nearest supported C++ type (uint8_t, uint16_t, uint32_t, uint64_t), ensuring correct code generation and type safety in the C++ logic. Co-authored-by: linzhida <linzhida19@mails.ucas.ac.cn>
1 parent 713a2c7 commit 10ddaa8

File tree

2 files changed

+25
-34
lines changed

2 files changed

+25
-34
lines changed

src/main/scala/Bundles.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ sealed trait DifftestBaseBundle extends Bundle {
4848
}
4949
}
5050

51-
class DeltaElem(elemBytes: Int) extends DifftestBaseBundle {
52-
val data = UInt((elemBytes * 8).W)
51+
class DeltaElem(elemWidth: Int) extends DifftestBaseBundle {
52+
val data = UInt(elemWidth.W)
5353
}
5454

5555
class ArchEvent extends DifftestBaseBundle with HasValid {

src/main/scala/Difftest.scala

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -96,17 +96,20 @@ sealed trait DifftestBundle extends Bundle with DifftestWithCoreid { this: Difft
9696

9797
def elementsInSeqUInt: Seq[(String, Seq[UInt])] = seqUIntHelper(elements.toSeq.reverse)
9898

99-
// return (name, data_width_in_byte, data_seq) for all elements except coreid and index
100-
def dataElements: Seq[(String, Int, Seq[UInt])] = {
101-
val nonDataElements = Seq("coreid", "index")
102-
elementsInSeqUInt.filterNot(e => nonDataElements.contains(e._1)).map { case (name, dataSeq) =>
99+
// return (name, data_width_aligned, data_seq) for all elements, where width can be 8,16,32,64
100+
def totalElements: Seq[(String, Int, Seq[UInt])] = {
101+
elementsInSeqUInt.map { case (name, dataSeq) =>
103102
val width = dataSeq.map(_.getWidth).distinct
104103
require(width.length == 1, "should not have different width")
105104
require(width.head <= 64, s"do not support DifftestBundle element with width (${width.head}) >= 64")
106-
(name, (width.head + 7) / 8, dataSeq)
105+
(name, math.pow(2, log2Ceil(width.head)).toInt, dataSeq)
107106
}
108107
}
109108

109+
// return (name, data_width_aligned, data_seq) for all elements except coreid and index
110+
def dataElements: Seq[(String, Int, Seq[UInt])] =
111+
totalElements.filterNot(e => Seq("coreid", "index").contains(e._1))
112+
110113
def toCppDeclMacro: String = {
111114
val macroName = s"CONFIG_DIFFTEST_${desiredModuleName.toUpperCase.replace("DIFFTEST", "")}"
112115
s"#define $macroName"
@@ -119,8 +122,8 @@ sealed trait DifftestBundle extends Bundle with DifftestWithCoreid { this: Difft
119122
val isRemoved = isFlatten && Seq("valid", "address").contains(name)
120123
if (!isRemoved) {
121124
// Align elem to 8 bytes for bundle enabled to split when Delta
122-
val elemSize = if (this.supportsDelta && aligned) deltaElemBytes else size
123-
val arrayType = s"uint${elemSize * 8}_t"
125+
val elemWidth = if (this.supportsDelta && aligned) deltaElemWidth else size
126+
val arrayType = s"uint${elemWidth}_t"
124127
val arrayWidth = if (elem.length == 1) "" else s"[${elem.length}]"
125128
cpp += f" $arrayType%-8s $name$arrayWidth;"
126129
}
@@ -130,13 +133,12 @@ sealed trait DifftestBundle extends Bundle with DifftestWithCoreid { this: Difft
130133
}
131134

132135
def toTraceDeclaration: String = {
133-
def byteWidth(data: Data) = (data.getWidth + 7) / 8 * 8
134136
val cpp = ListBuffer.empty[String]
135137
cpp += "typedef struct __attribute__((packed)) {"
136-
elements.toSeq.reverse.foreach { case (name, data) =>
138+
totalElements.foreach { case (name, width, data) =>
137139
val (typeWidth, arrSuffix) = data match {
138-
case v: Vec[_] => (byteWidth(v.head), s"[${v.length}]")
139-
case _ => (byteWidth(data), "")
140+
case v: Vec[_] => (width, s"[${v.length}]")
141+
case _ => (width, "")
140142
}
141143
cpp += f" ${s"uint${typeWidth}_t"}%-8s $name$arrSuffix;"
142144
}
@@ -174,34 +176,27 @@ sealed trait DifftestBundle extends Bundle with DifftestWithCoreid { this: Difft
174176

175177
val supportsDelta: Boolean = false
176178
def isDeltaElem: Boolean = this.isInstanceOf[DiffDeltaElem]
177-
def deltaElemBytes: Int = dataElements.map(_._2).max
179+
def deltaElemWidth: Int = dataElements.map(_._2).max
178180

179181
// Byte align all elements
180182
def getByteAlignElems(isTrace: Boolean): Seq[(String, Data)] = {
181-
def byteAlign(data: Data): UInt = {
182-
val width: Int = (data.getWidth + 7) / 8 * 8
183-
data.asTypeOf(UInt(width.W))
184-
}
185183
val gen = if (DataMirror.isWire(this) || DataMirror.isReg(this) || DataMirror.isIO(this)) {
186184
this
187185
} else {
188186
0.U.asTypeOf(this)
189187
}
190188
val elems = if (isTrace) {
191-
gen.elements.toSeq.reverse
189+
gen.totalElements
192190
} else {
193191
// Reorder to separate locating and transmitted data
194-
def locFilter: ((String, Data)) => Boolean = { case (name, _) =>
192+
def locFilter: ((String, Int, Seq[UInt])) => Boolean = { case (name, _, _) =>
195193
Seq("coreid", "index", "address").contains(name)
196194
}
197-
val raw = gen.elements.toSeq.reverse.filterNot(this.isFlatten && _._1 == "valid")
195+
val raw = gen.totalElements.filterNot(this.isFlatten && _._1 == "valid")
198196
raw.filterNot(locFilter) ++ raw.filter(locFilter)
199197
}
200-
elems.flatMap { case (name, data) =>
201-
data match {
202-
case vec: Vec[_] => vec.zipWithIndex.map { case (v, i) => (s"{${name}_$i}", byteAlign(v)) }
203-
case _ => Seq((s"$name", byteAlign(data)))
204-
}
198+
elems.flatMap { case (name, width, seq) =>
199+
seq.map(d => (name, d.asTypeOf(UInt(width.W))))
205200
}
206201
}
207202
def getByteAlignElems: Seq[(String, Data)] = getByteAlignElems(false)
@@ -213,15 +208,11 @@ sealed trait DifftestBundle extends Bundle with DifftestWithCoreid { this: Difft
213208
require(aligned.getWidth == this.getByteAlignWidth(isTrace))
214209
val bundle = WireInit(0.U.asTypeOf(this))
215210
val byteSeq = aligned.asTypeOf(Vec(aligned.getWidth / 8, UInt(8.W)))
216-
val elems = bundle.elements.toSeq.reverse
211+
val elems = bundle.totalElements
217212
.filterNot(this.isFlatten && _._1 == "valid" && !isTrace)
218-
.flatMap { case (_, data) =>
219-
data match {
220-
case vec: Vec[_] => vec.toSeq
221-
case _ => Seq(data)
222-
}
213+
.flatMap { case (_, width, seq) =>
214+
seq.map(d => (d, width / 8))
223215
}
224-
.map { d => (d, (d.getWidth + 7) / 8) }
225216
elems.zipWithIndex.foreach { case ((data, size), idx) =>
226217
val offset = elems.map(_._2).take(idx).sum
227218
data := MixedVecInit(byteSeq.slice(offset, offset + size).toSeq).asUInt
@@ -231,7 +222,7 @@ sealed trait DifftestBundle extends Bundle with DifftestWithCoreid { this: Difft
231222
}
232223

233224
class DiffDeltaElem(gen: DifftestBundle)
234-
extends DeltaElem(gen.deltaElemBytes)
225+
extends DeltaElem(gen.deltaElemWidth)
235226
with DifftestBundle
236227
with DifftestWithIndex {
237228
override val desiredCppName: String = gen.desiredCppName + "_elem"

0 commit comments

Comments
 (0)