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
|
// See LICENSE for license details.
package chiselTests
import chisel3._
import chisel3.stage.ChiselStage
import chisel3.util.{Queue, EnqIO, DeqIO, QueueIO, log2Ceil}
import chisel3.experimental.{CloneModuleAsRecord, IO}
import chisel3.testers.BasicTester
class MultiIOQueue[T <: Data](gen: T, val entries: Int) extends MultiIOModule {
val clk = IO(Input(Clock()))
val rst = IO(Input(Reset()))
val enq = IO(Flipped(EnqIO(gen)))
val deq = IO(Flipped(DeqIO(gen)))
val count = IO(Output(UInt(log2Ceil(entries + 1).W)))
val impl = withClockAndReset(clk, rst) { Module(new Queue(gen, entries)) }
impl.io.enq <> enq
deq <> impl.io.deq
count := impl.io.count
}
class QueueClone(multiIO: Boolean = false) extends Module {
val io = IO(new QueueIO(UInt(32.W), 4))
if (multiIO) {
val q1 = Module(new MultiIOQueue(UInt(32.W), 2))
val q2_io = CloneModuleAsRecord(q1)
q1.clk := clock
q1.rst := reset
q1.enq <> io.enq
q2_io("clk").asInstanceOf[Clock] := clock
q2_io("rst").asInstanceOf[Reset] := reset
q2_io("enq").asInstanceOf[q1.enq.type] <> q1.deq
io.deq <> q2_io("deq").asInstanceOf[q1.deq.type]
io.count := q1.count + q2_io("count").asInstanceOf[q1.count.type]
} else {
val q1 = Module(new Queue(UInt(32.W), 2))
val q2_io = CloneModuleAsRecord(q1)
q1.io.enq <> io.enq
val q2_io_bundle = q2_io("io").asInstanceOf[q1.io.type]
q2_io_bundle.enq <> q1.io.deq
io.deq <> q2_io_bundle.deq
io.count := q1.io.count + q2_io_bundle.count
}
}
class QueueCloneTester(x: Int, multiIO: Boolean = false) extends BasicTester {
val dut = Module(new QueueClone(multiIO))
val start = RegNext(dut.io.enq.fire, true.B)
val accept = RegNext(dut.io.deq.valid, false.B)
dut.io.enq.bits := x.U
dut.io.enq.valid := start
dut.io.deq.ready := accept
when (dut.io.deq.fire) {
assert(dut.io.deq.bits === x.U)
stop()
}
}
class CloneModuleSpec extends ChiselPropSpec {
val xVals = Table(
("x"), // First tuple defines column names
(42), // Subsequent tuples define the data
(63),
(99))
property("QueueCloneTester should return the correct result") {
forAll (xVals) { (x: Int) =>
assertTesterPasses{ new QueueCloneTester(x) }
}
}
property("QueueClone's cloned queues should share the same module") {
val c = ChiselStage.convert(new QueueClone)
assert(c.modules.length == 2)
}
property("Clone of MultiIOModule should simulate correctly") {
forAll (xVals) { (x: Int) =>
assertTesterPasses{ new QueueCloneTester(x, multiIO=true) }
}
}
property("Clones of MultiIOModules should share the same module") {
val c = ChiselStage.convert(new QueueClone(multiIO=true))
assert(c.modules.length == 3)
}
}
|