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
|
// See LICENSE for license details.
package chiselTests
import chisel3._
import chisel3.util._
import chisel3.testers.BasicTester
import chisel3.experimental._
/* This test is different from AnalogSpec in that it uses more complicated black boxes that can each
* drive the bidirectional bus. It was created to evaluate Analog with synthesis tools since the
* simple tests in AnalogSpec don't anything interesting in them to synthesize.
*/
class AnalogBlackBoxPort extends Bundle {
val in = Input(Valid(UInt(32.W)))
val out = Output(UInt(32.W))
}
// This IO can be used for a single BlackBox or to group multiple
// Has multiple ports for driving and checking but only one shared bus
class AnalogBlackBoxIO(n: Int) extends Bundle {
require(n > 0)
val bus = Analog(32.W)
val port = Vec(n, new AnalogBlackBoxPort)
}
// Assigns bus to out
// Assigns in.bits + index to bus when in.valid
class AnalogBlackBox(index: Int) extends BlackBox(Map("index" -> index)) {
val io = IO(new AnalogBlackBoxIO(1))
}
// Wraps up n blackboxes, connecing their buses and simply forwarding their ports up
class AnalogBlackBoxWrapper(n: Int, idxs: Seq[Int]) extends Module {
require(n > 0)
val io = IO(new AnalogBlackBoxIO(n))
val bbs = idxs.map(i => Module(new AnalogBlackBox(i)))
io.bus <> bbs.head.io.bus // Always bulk connect io.bus to first bus
io.port <> bbs.flatMap(_.io.port) // Connect ports
attach(bbs.map(_.io.bus):_*) // Attach all the buses
}
// Common superclass for AnalogDUT and AnalogSmallDUT
abstract class AnalogDUTModule(numBlackBoxes: Int) extends Module {
require(numBlackBoxes > 0)
val io = IO(new Bundle {
val ports = Vec(numBlackBoxes, new AnalogBlackBoxPort)
})
}
/** Single test case for lots of things
*
* $ - Wire at top connecting child inouts (Done in AnalogDUT)
* $ - Port inout connected to 1 or more children inouts (AnalogBackBoxWrapper)
* $ - Multiple port inouts connected (AnalogConnector)
*/
class AnalogDUT extends AnalogDUTModule(5) { // 5 BlackBoxes
val mods = Seq(
Module(new AnalogBlackBoxWrapper(1, Seq(0))),
Module(new AnalogBlackBox(1)),
Module(new AnalogBlackBoxWrapper(2, Seq(2, 3))), // 2 blackboxes
Module(new AnalogBlackBox(4))
)
// Connect all ports to top
io.ports <> mods.flatMap(_.io.port)
// Attach first 3 Modules
attach(mods.take(3).map(_.io.bus):_*)
// Attach last module to 1st through AnalogConnector
val con = Module(new AnalogConnector)
attach(con.io.bus1, mods.head.io.bus)
attach(con.io.bus2, mods.last.io.bus)
}
/** Same as [[AnalogDUT]] except it omits [[AnalogConnector]] because that is currently not
* supported by Verilator
* @todo Delete once Verilator can handle [[AnalogDUT]]
*/
class AnalogSmallDUT extends AnalogDUTModule(4) { // 4 BlackBoxes
val mods = Seq(
Module(new AnalogBlackBoxWrapper(1, Seq(0))),
Module(new AnalogBlackBox(1)),
Module(new AnalogBlackBoxWrapper(2, Seq(2, 3))) // 2 BlackBoxes
)
// Connect all ports to top
io.ports <> mods.flatMap(_.io.port)
// Attach first 3 Modules
attach(mods.take(3).map(_.io.bus):_*)
}
// This tester is primarily intended to be able to pass the dut to synthesis
class AnalogIntegrationTester(mod: => AnalogDUTModule) extends BasicTester {
val BusValue = 2.U(32.W) // arbitrary
val dut = Module(mod)
val expectedValue = Wire(UInt(32.W))
expectedValue := BusValue // Overridden each cycle
val (cycle, done) = Counter(true.B, dut.io.ports.size)
for ((dut, idx) <- dut.io.ports.zipWithIndex) {
printf(p"@$cycle: BlackBox #$idx: $dut\n")
// Defaults
dut.in.valid := false.B
dut.in.bits := BusValue
// Error checking
assert(dut.out === expectedValue)
when (cycle === idx.U) {
expectedValue := BusValue + idx.U
dut.in.valid := true.B
}
}
when (done) { stop() }
}
class AnalogIntegrationSpec extends ChiselFlatSpec {
behavior of "Verilator"
it should "support simple bidirectional wires" in {
assertTesterPasses(new AnalogIntegrationTester(new AnalogSmallDUT), Seq("/AnalogBlackBox.v"))
}
// Use this test once Verilator supports alias
ignore should "support arbitrary bidirectional wires" in {
assertTesterPasses(new AnalogIntegrationTester(new AnalogDUT), Seq("/AnalogBlackBox.v"))
}
}
|