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
|
// SPDX-License-Identifier: Apache-2.0
package firrtlTests.fixed
import firrtl.{ChirrtlForm, CircuitState, LowFirrtlCompiler}
import firrtl.testutils.FirrtlFlatSpec
class FixedPointMathSpec extends FirrtlFlatSpec {
val SumPattern = """.*output sum.*<(\d+)>.*.*""".r
val ProductPattern = """.*output product.*<(\d+)>.*""".r
val DifferencePattern = """.*output difference.*<(\d+)>.*""".r
val AssignPattern = """\s*(\w+) <= (\w+)\((.*)\)\s*""".r
for {
bits1 <- 1 to 4
binaryPoint1 <- 1 to 4
bits2 <- 1 to 4
binaryPoint2 <- 1 to 4
} {
def config = s"($bits1,$binaryPoint1)($bits2,$binaryPoint2)"
s"Configuration $config" should "pass" in {
val input =
s"""circuit Unit :
| module Unit :
| input a : Fixed<$bits1><<$binaryPoint1>>
| input b : Fixed<$bits2><<$binaryPoint2>>
| output sum : Fixed
| output product : Fixed
| output difference : Fixed
| sum <= add(a, b)
| product <= mul(a, b)
| difference <= sub(a, b)
| """.stripMargin
val lowerer = new LowFirrtlCompiler
val res = lowerer.compileAndEmit(CircuitState(parse(input), ChirrtlForm))
val output = res.getEmittedCircuit.value.split("\n")
def inferredAddWidth: Int = {
val binaryDifference = binaryPoint1 - binaryPoint2
val (newW1, newW2) = if (binaryDifference > 0) {
(bits1, bits2 + binaryDifference)
} else {
(bits1 + binaryDifference.abs, bits2)
}
newW1.max(newW2) + 1
}
for (line <- output) {
line match {
case SumPattern(varWidth) =>
assert(varWidth.toInt === inferredAddWidth, s"$config sum sint bits wrong for $line")
case ProductPattern(varWidth) =>
assert(varWidth.toInt === bits1 + bits2, s"$config product bits wrong for $line")
case DifferencePattern(varWidth) =>
assert(varWidth.toInt === inferredAddWidth, s"$config difference bits wrong for $line")
case AssignPattern(varName, operation, args) =>
varName match {
case "sum" =>
assert(operation === "add", s"var sum should be result of an add in $line")
if (binaryPoint1 > binaryPoint2) {
assert(!args.contains("shl(a"), s"$config first arg should be just a in $line")
assert(
args.contains(s"shl(b, ${binaryPoint1 - binaryPoint2})"),
s"$config second arg incorrect in $line"
)
} else if (binaryPoint1 < binaryPoint2) {
assert(
args.contains(s"shl(a, ${(binaryPoint1 - binaryPoint2).abs})"),
s"$config second arg incorrect in $line"
)
assert(!args.contains("shl(b"), s"$config second arg should be just b in $line")
} else {
assert(!args.contains("shl(a"), s"$config first arg should be just a in $line")
assert(!args.contains("shl(b"), s"$config second arg should be just b in $line")
}
case "product" =>
assert(operation === "mul", s"var sum should be result of an add in $line")
assert(!args.contains("shl(a"), s"$config first arg should be just a in $line")
assert(!args.contains("shl(b"), s"$config second arg should be just b in $line")
case "difference" =>
assert(operation === "sub", s"var difference should be result of an sub in $line")
if (binaryPoint1 > binaryPoint2) {
assert(!args.contains("shl(a"), s"$config first arg should be just a in $line")
assert(
args.contains(s"shl(b, ${binaryPoint1 - binaryPoint2})"),
s"$config second arg incorrect in $line"
)
} else if (binaryPoint1 < binaryPoint2) {
assert(
args.contains(s"shl(a, ${(binaryPoint1 - binaryPoint2).abs})"),
s"$config second arg incorrect in $line"
)
assert(!args.contains("shl(b"), s"$config second arg should be just b in $line")
} else {
assert(!args.contains("shl(a"), s"$config first arg should be just a in $line")
assert(!args.contains("shl(b"), s"$config second arg should be just b in $line")
}
case _ =>
}
case _ =>
}
}
}
}
}
|