@@ -48,16 +48,16 @@ trait Peekable[T <: Data] {
48
48
def expect (expected : T )(implicit sourceInfo : SourceInfo ): Unit =
49
49
expect(expected, (observed, expected) => s " Expectation failed: observed value $observed != $expected" )
50
50
51
- private [simulator] final def dataToString (data : Data ): String = {
52
- data match {
51
+ private [simulator] def dataToString (value : Data ): String = {
52
+ value match {
53
53
case x : Bundle =>
54
54
x.elements.map { case (name, elt) =>
55
55
s " $name: ${dataToString(elt)}"
56
56
}.mkString(" {" , " , " , " }" )
57
57
case x : Vec [_] => x.getElements.map(dataToString).mkString(" [" , " , " , " ]" )
58
58
case x : EnumType => x.toString
59
59
case x if x.isLit => x.litValue.toString
60
- case _ => data .toString
60
+ case _ => value .toString
61
61
}
62
62
}
63
63
}
@@ -75,9 +75,9 @@ trait Pokable[T <: Data] {
75
75
sealed trait AnyTestableData [T <: Data ] {
76
76
protected def data : T
77
77
78
- protected def simulatedModule = AnySimulatedModule .current
78
+ protected def simulatedModule : AnySimulatedModule = AnySimulatedModule .current
79
79
80
- protected def simulationPort = simulatedModule.port(data)
80
+ protected def simulationPort : Simulation . Port = simulatedModule.port(data)
81
81
}
82
82
83
83
trait PeekPokable [T <: Data ] extends Peekable [T ] with Pokable [T ] with AnyTestableData [T ]
@@ -305,8 +305,6 @@ object PeekPokeAPI {
305
305
}
306
306
}
307
307
308
- def poke (value : Boolean ): Unit = poke(value.B )
309
-
310
308
def peekBoolean (): Boolean = peek().litToBoolean
311
309
312
310
override def expect (expected : Bool )(implicit sourceInfo : SourceInfo ): Unit = expect[Bool ](
@@ -318,12 +316,14 @@ object PeekPokeAPI {
318
316
)
319
317
320
318
def expect (value : Boolean )(implicit sourceInfo : SourceInfo ): Unit = expect(value.B )
321
- }
322
319
323
- implicit final class TestableReset (val data : Reset ) extends TestableElement [Reset ] {
324
320
def poke (value : Boolean ): Unit = poke(value.B )
321
+ }
325
322
323
+ implicit final class TestableReset (val data : Reset ) extends TestableElement [Reset ] {
326
324
def encode (width : Int , value : BigInt ): Reset = TestableBool (data.asBool).encode(width, value)
325
+
326
+ def poke (value : Boolean ): Unit = poke(value.B )
327
327
}
328
328
329
329
implicit class TestableEnum [T <: EnumType ](val data : T ) extends TestableElement [T ] {
@@ -333,7 +333,6 @@ object PeekPokeAPI {
333
333
}
334
334
335
335
implicit class TestableRecord [T <: Record ](val data : T ) extends PeekPokable [T ] {
336
-
337
336
override def peek (): T = {
338
337
chiselTypeOf(data).Lit (
339
338
data.elements.toSeq.map { case (name : String , elt : Data ) =>
@@ -342,22 +341,15 @@ object PeekPokeAPI {
342
341
)
343
342
}
344
343
345
- override def poke (value : T ): Unit = data.elements.foreach { case (name, d) =>
346
- val valueEl = value.elements(name)
347
- require(
348
- d.getClass == valueEl.getClass,
349
- s " Type mismatch for Record element ' $name': expected ${d.getClass}, got ${valueEl.getClass}"
350
- )
351
- d.poke(valueEl)
352
- }
353
-
354
344
def expect (expected : T , buildMessage : (T , T , String ) => String , allowPartial : Boolean )(
355
345
implicit sourceInfo : SourceInfo
356
346
): Unit = {
357
347
require(DataMirror .checkTypeEquivalence(data, expected), " Type mismatch" )
358
348
359
- // FIXME: I can't understand why but _not_ getting the peeked value as a `val` beforehand results in infinite recursion
360
- val peekedValue = peek()
349
+ // Not peeking the value beforehand or using `def` or `lazy val` results in a mysterious infinite recursion and StackOverflowError
350
+ // The value is not used if the expected value matches and incurs an overhead
351
+ // TODO: dig deeper amd see if we can avoid this
352
+ val peekedValue = data.peek()
361
353
362
354
data.elements.foreach { case (elName, elData) =>
363
355
expected.elements(elName) match {
@@ -398,6 +390,15 @@ object PeekPokeAPI {
398
390
399
391
override def expect (expected : T )(implicit sourceInfo : SourceInfo ): Unit =
400
392
expect(expected, (obs : T , exp : T ) => " " , allowPartial = false )
393
+
394
+ override def poke (literal : T ): Unit = data.elements.foreach { case (name, dataEl) =>
395
+ val valueEl = literal.elements(name)
396
+ require(
397
+ dataEl.getClass == valueEl.getClass,
398
+ s " Type mismatch for Record element ' $name': expected ${dataEl.getClass}, got ${valueEl.getClass}"
399
+ )
400
+ dataEl.poke(valueEl)
401
+ }
401
402
}
402
403
403
404
implicit class TestableVec [T <: Data ](val data : Vec [T ]) extends PeekPokable [Vec [T ]] {
@@ -406,21 +407,6 @@ object PeekPokeAPI {
406
407
chiselTypeOf(data).Lit (elementValues.zipWithIndex.map { _.swap }: _* )
407
408
}
408
409
409
- // internal
410
- private [simulator] final def _poke [U <: Data ](literal : Seq [U ]): Unit = {
411
- require(data.length == literal.length, s " Vec length mismatch: expected ${data.length}, got ${literal.length}" )
412
- data.getElements.zip(literal).foreach {
413
- case (portEl, valueEl) if portEl.getClass == valueEl.getClass =>
414
- portEl.poke(valueEl)
415
- case (portEl, valueEl) =>
416
- throw new Exception (
417
- s " Port element type: ${portEl.getClass} != literal element ${valueEl.getClass}"
418
- )
419
- }
420
- }
421
-
422
- override def poke (literal : Vec [T ]): Unit = _poke[T ](literal)
423
-
424
410
// internal
425
411
private [simulator] final def _expect [U <: Data ](expected : Vec [U ], buildMessage : (Vec [T ], Vec [U ], Int ) => String )(
426
412
implicit sourceInfo : SourceInfo
@@ -429,7 +415,12 @@ object PeekPokeAPI {
429
415
expected.length == data.length,
430
416
s " Vec length mismatch: Data port has ${data.length} elements while the expected value is of length ${expected.length}"
431
417
)
418
+
419
+ // Not peeking the value beforehand or using `def` or `lazy val` results in a mysterious infinite recursion and StackOverflowError
420
+ // The value is not used if the expected value matches and incurs an overhead
421
+ // TODO: dig deeper amd see if we can avoid this
432
422
val peekedValue = data.peek()
423
+
433
424
data.zip(expected).zipWithIndex.foreach { case ((datEl, expEl), index) =>
434
425
expEl match {
435
426
case DontCare =>
@@ -447,14 +438,42 @@ object PeekPokeAPI {
447
438
}
448
439
}
449
440
441
+ private [simulator] def _expect [U <: Data ](
442
+ expected : Vec [U ],
443
+ buildMessage : (Vec [T ], Vec [U ]) => String ,
444
+ appendFailedIndexToMsg : Boolean
445
+ )(
446
+ implicit sourceInfo : SourceInfo
447
+ ): Unit =
448
+ _expect[U ](
449
+ expected,
450
+ (observed : Vec [T ], expected : Vec [U ], idx : Int ) =>
451
+ buildMessage(observed, expected) + (if (appendFailedIndexToMsg) s " ; First mismatch at index $idx" else " " )
452
+ )
453
+
450
454
override def expect (expected : Vec [T ], buildMessage : (Vec [T ], Vec [T ]) => String )(
451
455
implicit sourceInfo : SourceInfo
452
456
): Unit =
453
457
_expect[T ](
454
458
expected,
455
- ( observed : Vec [ T ], expected : Vec [ T ], idx : Int ) =>
456
- buildMessage(observed, expected) + s " . First mismatch at index $idx . "
459
+ buildMessage,
460
+ appendFailedIndexToMsg = true
457
461
)
462
+
463
+ // for internal use
464
+ private [simulator] final def _poke [U <: Data ](literal : Vec [U ]): Unit = {
465
+ require(data.length == literal.length, s " Vec length mismatch: expected ${data.length}, got ${literal.length}" )
466
+ data.getElements.zip(literal).foreach {
467
+ case (portEl, valueEl) if portEl.getClass == valueEl.getClass =>
468
+ portEl.poke(valueEl)
469
+ case (portEl, valueEl) =>
470
+ throw new Exception (
471
+ s " Port element type: ${portEl.getClass} != literal element ${valueEl.getClass}"
472
+ )
473
+ }
474
+ }
475
+
476
+ override def poke (literal : Vec [T ]): Unit = _poke[T ](literal)
458
477
}
459
478
460
479
implicit class TestableData [T <: Data ](val data : T ) extends PeekPokable [T ] {
@@ -493,14 +512,8 @@ object PeekPokeAPI {
493
512
case (dat : Record , exp : Record ) =>
494
513
new TestableRecord (dat).expect(exp, buildMsgFn _)
495
514
case (dat : Vec [_], exp : Vec [_]) =>
496
- new TestableVec (dat)._expect(
497
- exp,
498
- (obs : Vec [_], _ : Vec [_], idx : Int ) => {
499
- require(obs.getClass == exp.getClass, s " Type mismatch: ${obs.getClass} != ${exp.getClass}" )
500
- buildMessage(obs.asInstanceOf [T ], expected.asInstanceOf [T ]) + s " . First mismatch at index $idx. "
501
- }
502
- )
503
- case x => throw new Exception (s " don't know how to expect $x" )
515
+ new TestableVec (dat)._expect(exp, buildMsgFn _, appendFailedIndexToMsg = true )
516
+ case x => throw new Exception (s " Don't know how to expect $x" )
504
517
}
505
518
}
506
519
0 commit comments