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
136
137
138
139
|
// SPDX-License-Identifier: Apache-2.0
package chiselTests
import java.io.File
import chisel3._
import chisel3.util.{HasBlackBoxInline, HasBlackBoxPath, HasBlackBoxResource}
import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage}
import firrtl.transforms.BlackBoxNotFoundException
import org.scalacheck.Test.Failed
import org.scalatest.Succeeded
import org.scalatest.freespec.AnyFreeSpec
import org.scalatest.matchers.should.Matchers
class BlackBoxAdd(n: Int) extends HasBlackBoxInline {
val io = IO(new Bundle {
val in = Input(UInt(16.W))
val out = Output(UInt(16.W))
})
setInline(
"BlackBoxAdd.v",
s"""
|module BlackBoxAdd(
| input [15:0] in,
| output [15:0] out
|);
| assign out = in + $n;
|endmodule
""".stripMargin
)
}
class UsesBlackBoxAddViaInline extends Module {
val io = IO(new Bundle {
val in = Input(UInt(16.W))
val out = Output(UInt(16.W))
})
val blackBoxAdd = Module(new BlackBoxAdd(5))
blackBoxAdd.io.in := io.in
io.out := blackBoxAdd.io.out
}
class BlackBoxMinus extends HasBlackBoxResource {
val io = IO(new Bundle {
val in1 = Input(UInt(16.W))
val in2 = Input(UInt(16.W))
val out = Output(UInt(16.W))
})
addResource("/chisel3/BlackBoxTest.v")
}
class BlackBoxMinusPath extends HasBlackBoxPath {
val io = IO(new Bundle {
val in1 = Input(UInt(16.W))
val in2 = Input(UInt(16.W))
val out = Output(UInt(16.W))
})
addPath(new File("src/test/resources/chisel3/BlackBoxTest.v").getCanonicalPath)
}
class UsesBlackBoxMinusViaResource extends Module {
val io = IO(new Bundle {
val in1 = Input(UInt(16.W))
val in2 = Input(UInt(16.W))
val out = Output(UInt(16.W))
})
val mod0 = Module(new BlackBoxMinus)
mod0.io.in1 := io.in1
mod0.io.in2 := io.in2
io.out := mod0.io.out
}
class UsesBlackBoxMinusViaPath extends Module {
val io = IO(new Bundle {
val in1 = Input(UInt(16.W))
val in2 = Input(UInt(16.W))
val out = Output(UInt(16.W))
})
val mod0 = Module(new BlackBoxMinusPath)
mod0.io.in1 := io.in1
mod0.io.in2 := io.in2
io.out := mod0.io.out
}
class BlackBoxResourceNotFound extends HasBlackBoxResource {
val io = IO(new Bundle {})
addResource("/missing.resource")
}
class UsesMissingBlackBoxResource extends RawModule {
val foo = Module(new BlackBoxResourceNotFound)
}
class BlackBoxImplSpec extends AnyFreeSpec with Matchers {
val targetDir = "test_run_dir"
val stage = new ChiselStage
"BlackBox can have verilator source implementation" - {
"Implementations can be contained in-line" in {
stage.execute(
Array("-X", "verilog", "--target-dir", targetDir),
Seq(ChiselGeneratorAnnotation(() => new UsesBlackBoxAddViaInline))
)
val verilogOutput = new File(targetDir, "BlackBoxAdd.v")
verilogOutput.exists() should be(true)
verilogOutput.delete()
}
"Implementations can be contained in resource files" in {
stage.execute(
Array("-X", "low", "--target-dir", targetDir),
Seq(ChiselGeneratorAnnotation(() => new UsesBlackBoxMinusViaResource))
)
val verilogOutput = new File(targetDir, "BlackBoxTest.v")
verilogOutput.exists() should be(true)
verilogOutput.delete()
}
"Implementations can be contained in arbitrary files" in {
stage.execute(
Array("-X", "low", "--target-dir", targetDir),
Seq(ChiselGeneratorAnnotation(() => new UsesBlackBoxMinusViaPath))
)
val verilogOutput = new File(targetDir, "BlackBoxTest.v")
verilogOutput.exists() should be(true)
verilogOutput.delete()
Succeeded
}
"Resource files that do not exist produce Chisel errors" in {
assertThrows[BlackBoxNotFoundException] {
ChiselStage.emitChirrtl(new UsesMissingBlackBoxResource)
}
}
}
}
|