1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
// SPDX-License-Identifier: Apache-2.0
package chiselTests
import chisel3._
import chisel3.util.Counter
import chisel3.testers._
import chisel3.experimental.{BaseModule, ChiselAnnotation, RunFirrtlTransform}
import chisel3.util.experimental.BoringUtils
import firrtl.{ChirrtlForm, CircuitForm, CircuitState, DependencyAPIMigration, Transform}
import firrtl.annotations.{Annotation, NoTargetAnnotation}
import firrtl.options.Dependency
import firrtl.transforms.{DontTouchAnnotation, NoDedupAnnotation}
import firrtl.passes.wiring.{WiringException, WiringTransform}
import firrtl.stage.Forms
abstract class ShouldntAssertTester(cyclesToWait: BigInt = 4) extends BasicTester {
val dut: BaseModule
val (_, done) = Counter(true.B, 2)
when(done) { stop() }
}
class StripNoDedupAnnotation extends Transform with DependencyAPIMigration {
override def prerequisites = Forms.ChirrtlForm
override def optionalPrerequisites = Seq.empty
override def optionalPrerequisiteOf = Dependency[WiringTransform] +: Forms.ChirrtlEmitters
override def invalidates(a: Transform) = false
def execute(state: CircuitState): CircuitState = {
state.copy(annotations = state.annotations.filter { case _: NoDedupAnnotation => false; case _ => true })
}
}
class BoringUtilsSpec extends ChiselFlatSpec with ChiselRunners {
class BoringInverter extends Module {
val io = IO(new Bundle {})
val a = Wire(UInt(1.W))
val notA = Wire(UInt(1.W))
val b = Wire(UInt(1.W))
a := 0.U
notA := ~a
b := a
chisel3.assert(b === 1.U)
BoringUtils.addSource(notA, "x")
BoringUtils.addSink(b, "x")
}
behavior.of("BoringUtils.{addSink, addSource}")
it should "connect two wires within a module" in {
runTester(
new ShouldntAssertTester { val dut = Module(new BoringInverter) },
annotations = TesterDriver.verilatorOnly
) should be(true)
}
trait WireX { this: BaseModule =>
val x = Wire(UInt(4.W))
chisel3.experimental.annotate(new ChiselAnnotation {
def toFirrtl: Annotation = DontTouchAnnotation(x.toNamed)
})
}
class Source extends RawModule with WireX {
val in = IO(Input(UInt()))
x := in
}
class Sink extends RawModule with WireX {
val out = IO(Output(UInt()))
x := 0.U // Default value. Output is zero unless we bore...
out := x
}
class Top(val width: Int) extends Module {
/* From the perspective of deduplication, all sources are identical and all sinks are identical. */
val sources = Seq.fill(3)(Module(new Source))
val sinks = Seq.fill(6)(Module(new Sink))
/* Sources are differentiated by their input connections only. */
sources.zip(Seq(0, 1, 2)).map { case (a, b) => a.in := b.U }
/* Sinks are differentiated by their post-boring outputs. */
sinks.zip(Seq(0, 1, 1, 2, 2, 2)).map { case (a, b) => chisel3.assert(a.out === b.U) }
}
/** This is testing a complicated wiring pattern and exercising
* the necessity of disabling deduplication for sources and sinks.
* Without disabling deduplication, this test will fail.
*/
class TopTester extends ShouldntAssertTester {
val dut = Module(new Top(4))
BoringUtils.bore(dut.sources(1).x, Seq(dut.sinks(1).x, dut.sinks(2).x))
BoringUtils.bore(dut.sources(2).x, Seq(dut.sinks(3).x, dut.sinks(4).x, dut.sinks(5).x))
}
trait FailViaDedup { this: TopTester =>
case object FooAnnotation extends NoTargetAnnotation
chisel3.experimental.annotate(new ChiselAnnotation with RunFirrtlTransform {
def toFirrtl: Annotation = FooAnnotation
def transformClass: Class[_ <: Transform] = classOf[StripNoDedupAnnotation]
})
}
behavior.of("BoringUtils.bore")
it should "connect across modules using BoringUtils.bore" in {
runTester(new TopTester, annotations = TesterDriver.verilatorOnly) should be(true)
}
it should "throw an exception if NoDedupAnnotations are removed" in {
intercept[WiringException] {
runTester(new TopTester with FailViaDedup, annotations = Seq(TesterDriver.VerilatorBackend))
}.getMessage should startWith("Unable to determine source mapping for sink")
}
class InternalBore extends RawModule {
val in = IO(Input(Bool()))
val out = IO(Output(Bool()))
out := false.B
BoringUtils.bore(in, Seq(out))
}
class InternalBoreTester extends ShouldntAssertTester {
val dut = Module(new InternalBore)
dut.in := true.B
chisel3.assert(dut.out === true.B)
}
it should "work for an internal (same module) BoringUtils.bore" in {
runTester(new InternalBoreTester, annotations = TesterDriver.verilatorOnly) should be(true)
}
}
|