Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
tapasco
tapasco
Commits
187a74fb
Commit
187a74fb
authored
Aug 24, 2017
by
Jens Korinth
Browse files
Started with property-based testing
parent
63498417
Changes
5
Hide whitespace changes
Inline
Side-by-side
src/main/scala/DataWidthConverter.scala
View file @
187a74fb
...
...
@@ -15,12 +15,9 @@ import chisel3.util._
* @param littleEndian if inWidth > outWidth, determines
* the order of the nibbles (low to high)
**/
class
DataWidthConverter
(
val
inWidth
:
Int
,
val
outWidth
:
Int
,
val
littleEndian
:
Boolean
=
true
)
extends
Module
{
class
DataWidthConverter
(
val
inWidth
:
Int
,
val
outWidth
:
Int
,
val
littleEndian
:
Boolean
=
true
)
extends
Module
{
require
(
inWidth
>
0
,
"inWidth must be > 0"
)
require
(
outWidth
>
0
,
"inWidth must be > 0"
)
require
(
inWidth
!=
outWidth
,
"inWidth (%d) must be different from outWidth (%d)"
...
...
src/main/scala/SignalGenerator.scala
View file @
187a74fb
...
...
@@ -2,18 +2,24 @@ package chisel.miscutils
import
chisel3._
import
chisel3.util._
sealed
case
class
Signal
(
value
:
Boolean
,
periods
:
Int
=
1
)
extends
Ordered
[
Signal
]
{
import
scala.math.Ordered.orderingToOrdered
def
compare
(
that
:
Signal
)
:
Int
=
periods
compare
that
.
periods
}
object
SignalGenerator
{
type
Waveform
=
List
[
Signal
]
sealed
case
class
Signal
(
value
:
Boolean
,
periods
:
Int
=
1
)
extends
Ordered
[
Signal
]
{
import
scala.math.Ordered.orderingToOrdered
def
compare
(
that
:
Signal
)
:
Int
=
periods
compare
that
.
periods
def
unary_!
=
this
.
copy
(
value
=
!
value
)
}
final
case
class
Waveform
(
signals
:
Seq
[
Signal
])
{
require
(
signals
.
length
>
0
,
"waveform must not be empty"
)
}
implicit
def
waveformToSeq
(
w
:
Waveform
)
:
Seq
[
Signal
]
=
w
.
signals
implicit
def
seqToWaveform
(
s
:
Seq
[
Signal
])
:
Waveform
=
Waveform
.
apply
(
s
)
implicit
def
makeSignal
(
sd
:
(
Boolean
,
Int
))
:
Signal
=
Signal
(
sd
.
_1
,
sd
.
_2
)
implicit
def
makeWaveform
(
ls
:
List
[(
Boolean
,
Int
)])
:
Waveform
=
ls
map
makeSignal
}
class
SignalGenerator
(
signals
:
SignalGenerator.Waveform
,
useInputAsClock
:
Boolean
=
false
)
extends
Module
{
class
SignalGenerator
(
val
signals
:
SignalGenerator.Waveform
,
val
useInputAsClock
:
Boolean
=
false
)
extends
Module
{
require
(
signals
.
length
>
0
,
"Waveform must not be empty."
)
require
(
signals
map
(
_
.
periods
>
1
)
reduce
(
_
&&
_
),
"All signals must have at least two clock cycles length."
)
...
...
@@ -29,7 +35,7 @@ class SignalGenerator(signals: SignalGenerator.Waveform, useInputAsClock: Boolea
when
(
reset
)
{
curr_idx
:=
0.
U
cnt
:=
cnts_rom
(
0
)
vreg
:=
0.
U
vreg
:=
vals_rom
(
0
)
}
.
otherwise
{
vreg
:=
vals_rom
(
curr_idx
)
...
...
src/test/scala/SignalGeneratorSpec.scala
0 → 100644
View file @
187a74fb
package
chisel.miscutils
import
generators._
import
org.scalacheck._
,
org
.
scalacheck
.
Prop
.
_
import
org.scalatest.prop.Checkers
import
chisel3._
import
chisel3.iotesters.
{
ChiselFlatSpec
,
Driver
,
PeekPokeTester
}
class
SignalGeneratorWaveformTest
(
sg
:
SignalGenerator
)
extends
PeekPokeTester
(
sg
)
{
private
var
cc
=
0
// re-define step to output progress info
override
def
step
(
n
:
Int
)
{
if
(
sg
.
useInputAsClock
)
{
super
.
step
(
1
)
poke
(
sg
.
io
.
in
,
(
peek
(
sg
.
io
.
in
)
+
1
)
%
2
)
super
.
step
(
1
)
cc
+=
1
}
else
{
super
.
step
(
n
)
cc
+=
n
}
}
poke
(
sg
.
io
.
in
,
0
)
reset
(
10
)
step
(
10
)
cc
=
0
for
(
i
<-
0
until
sg
.
signals
.
length
)
{
println
(
s
"signal ${i+1}/${sg.signals.length} started at $cc"
)
for
(
s
<-
0
until
sg
.
signals
(
i
).
periods
)
{
val
e
=
sg
.
signals
(
i
).
value
val
p
=
peek
(
sg
.
io
.
v
)
expect
(
sg
.
io
.
v
,
sg
.
signals
(
i
).
value
.
B
,
s
"expected $e at clock cycle $cc"
)
step
(
1
)
}
println
(
s
"signal ${i+1}/${sg.signals.length} finished at $cc"
)
step
(
1
)
}
}
class
SignalGeneratorSpec
extends
ChiselFlatSpec
with
Checkers
{
behavior
of
"SignalGenerator"
it
should
"generate arbitrary waveforms"
in
check
(
forAll
(
signalGeneratorGen
)
{
case
(
wave
,
useInputAsClock
)
=>
println
(
s
"useInputAsClock: $useInputAsClock, wave: $wave"
)
Driver
.
execute
(
Array
(
"--fint-write-vcd"
,
"--target-dir"
,
"test/signalgenerator/spec"
),
()
=>
new
SignalGenerator
(
wave
,
useInputAsClock
))
{
m
=>
new
SignalGeneratorWaveformTest
(
m
)
}
})
}
src/test/scala/SignalGeneratorTest.scala
View file @
187a74fb
...
...
@@ -57,7 +57,7 @@ class SignalGeneratorTest(sg: SignalGenerator) extends PeekPokeTester(sg) {
for
(
j
<-
0
to
1
)
{
for
(
i
<-
2
until
30
)
{
waitForPosEdge
(
sg
.
io
.
v
)
//
waitForPosEdge(sg.io.v)
val
cc_start
=
cc
waitForNegEdge
(
sg
.
io
.
v
)
expect
(
cc
-
cc_start
==
i
,
"wrong number of clock cycles"
)
...
...
src/test/scala/generators.scala
0 → 100644
View file @
187a74fb
package
chisel.miscutils
import
org.scalacheck._
import
SignalGenerator._
import
scala.language.implicitConversions
package
object
generators
{
final
case
class
Limited
[
A
](
a
:
A
,
min
:
A
,
max
:
A
)(
implicit
num
:
Numeric
[
A
])
{
import
num._
require
(
a
>=
min
,
s
"$a must be >= $min"
)
require
(
a
<=
max
,
s
"$a must be <= $max"
)
}
implicit
def
limitedToA
[
A
](
l
:
Limited
[
A
])
:
A
=
l
.
a
def
genLimited
[
A
](
min
:
A
,
max
:
A
)(
implicit
num
:
Numeric
[
A
],
c
:
Gen.Choose
[
A
])
:
Gen
[
Limited
[
A
]]
=
Gen
.
choose
(
min
,
max
)
map
(
v
=>
Limited
.
apply
(
v
,
min
,
max
))
implicit
def
shrinkLimited
[
A
](
l
:
Limited
[
A
])(
implicit
num
:
Numeric
[
A
])
:
Shrink
[
Limited
[
A
]]
=
Shrink
{
l
=>
import
num._
if
(
l
.
a
<=
l
.
min
)
Stream
.
empty
[
Limited
[
A
]]
else
Stream
(
Limited
(
l
.
a
-
num
.
one
,
l
.
min
,
l
.
max
))
}
type
BitWidth
=
Limited
[
Int
]
type
DataSize
=
Limited
[
Int
]
def
bitWidthGen
(
max
:
Int
=
64
)
:
Gen
[
BitWidth
]
=
genLimited
(
1
,
max
)
def
dataSizeGen
(
max
:
Int
=
1024
)
:
Gen
[
DataSize
]
=
genLimited
(
1
,
max
)
def
widthConversionGen
(
max
:
Int
=
64
)
:
Gen
[(
BitWidth
,
BitWidth
,
Boolean
)]
=
for
{
inWidth
<-
bitWidthGen
(
max
)
outWidth
<-
bitWidthGen
(
max
)
littleEndian
<-
Arbitrary
.
arbitrary
[
Boolean
]
}
yield
(
inWidth
,
outWidth
,
littleEndian
)
def
dataSourceGen
(
maxWidth
:
Int
=
64
,
maxSize
:
Int
=
1024
)
:
Gen
[(
BitWidth
,
DataSize
,
Boolean
)]
=
for
{
bw
<-
bitWidthGen
(
maxWidth
)
ds
<-
dataSizeGen
(
maxSize
)
r
<-
Arbitrary
.
arbitrary
[
Boolean
]
}
yield
(
bw
,
ds
,
r
)
def
signalGen
(
maxLength
:
Int
=
15
)
:
Gen
[
Signal
]
=
for
{
v
<-
Arbitrary
.
arbitrary
[
Boolean
]
p
<-
genLimited
(
2
,
maxLength
)
}
yield
Signal
(
v
,
p
)
def
alternate
(
ss
:
Seq
[
Signal
])
:
Seq
[
Signal
]
=
ss
match
{
case
s0
+:
s1
+:
sr
=>
s0
+:
alternate
(
s1
.
copy
(
value
=
!
s0
.
value
)
+:
sr
)
case
s
+:
sr
=>
s
+:
sr
case
Seq
()
=>
Seq
()
}
def
waveformGen
(
maxLength
:
Int
=
20
)
:
Gen
[
Waveform
]
=
Gen
.
sized
{
n
=>
Gen
.
nonEmptyBuildableOf
[
Seq
[
Signal
]
,
Signal
](
signalGen
())
map
(
ss
=>
Waveform
(
alternate
(
ss
)))
}
implicit
def
waveformShrink
(
waveform
:
Waveform
)
:
Shrink
[
Waveform
]
=
Shrink
{
w
=>
if
(
w
.
length
<=
1
)
Stream
.
empty
[
Waveform
]
else
Stream
(
w
.
drop
(
1
))
}
def
signalGeneratorGen
:
Gen
[(
Waveform
,
Boolean
)]
=
for
{
w
<-
waveformGen
()
i
<-
Arbitrary
.
arbitrary
[
Boolean
]
}
yield
(
w
,
true
)
}
Jens Korinth
@jk
mentioned in commit
17f0d672
·
Mar 05, 2018
mentioned in commit
17f0d672
mentioned in commit 17f0d67240ebf5d7e1d0be9162d272b04256c47d
Toggle commit list
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment