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
8f2faf2e
Commit
8f2faf2e
authored
Aug 25, 2017
by
Jens Korinth
Browse files
Merge of chisel-miscutils
Merge commit '61fdb4b48f81caf5ae3e68aead564fb34a2c4371'
parents
511f7779
20323ee9
Changes
16
Hide whitespace changes
Inline
Side-by-side
miscutils/build.sbt
View file @
8f2faf2e
...
...
@@ -2,11 +2,9 @@ name := "chisel-miscutils"
organization
:=
"esa.cs.tu-darmstadt.de"
version
:=
"0.
2
-SNAPSHOT"
version
:=
"0.
3
-SNAPSHOT"
scalaVersion
:=
"2.11.7"
crossScalaVersions
:=
Seq
(
"2.10.3"
,
"2.10.4"
,
"2.11.0"
)
scalaVersion
:=
"2.11.11"
resolvers
++=
Seq
(
Resolver
.
sonatypeRepo
(
"snapshots"
),
...
...
@@ -21,8 +19,9 @@ libraryDependencies ++= (Seq("chisel3","chisel-iotesters").map {
dep
:
String
=>
"edu.berkeley.cs"
%%
dep
%
sys
.
props
.
getOrElse
(
dep
+
"Version"
,
defaultVersions
(
dep
))
})
libraryDependencies
++=
Seq
(
"org.scalatest"
%%
"scalatest"
%
"2.2.6"
%
"test"
,
"com.typesafe.play"
%%
"play-json"
%
"2.4.8"
"org.scalatest"
%%
"scalatest"
%
"3.0.4"
%
"test"
,
"org.scalacheck"
%%
"scalacheck"
%
"1.13.5"
%
"test"
,
"com.typesafe.play"
%%
"play-json"
%
"2.6.3"
)
// no parallel tests
...
...
miscutils/src/main/scala/DataWidthConverter.scala
View file @
8f2faf2e
...
...
@@ -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)"
...
...
miscutils/src/main/scala/DecoupledDataSource.scala
View file @
8f2faf2e
...
...
@@ -22,9 +22,8 @@ class DecoupledDataSourceIO[T <: Data](gen: T) extends Bundle {
**/
class
DecoupledDataSource
[
T
<:
Data
](
gen
:
T
,
val
size
:
Int
,
val
data
:
(
Int
)
=>
T
,
val
repeat
:
Boolean
=
true
)
extends
Module
{
println
(
"DecoupledDataSource: size = %d, repeat = %s"
.
format
(
size
,
if
(
repeat
)
"true"
else
"false"
))
println
(
" width = %d"
.
format
(
log2Ceil
(
if
(
repeat
)
size
else
size
+
1
)))
println
(
"DecoupledDataSource: size = %d, repeat = %s, addrWidth = %d"
.
format
(
size
,
if
(
repeat
)
"true"
else
"false"
,
log2Ceil
(
if
(
repeat
)
size
else
size
+
1
)))
val
ds
=
for
(
i
<-
0
until
size
)
yield
data
(
i
)
// evaluate data to array
val
io
=
IO
(
new
DecoupledDataSourceIO
(
gen
))
// interface
...
...
miscutils/src/main/scala/SignalGenerator.scala
View file @
8f2faf2e
...
...
@@ -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
)
...
...
miscutils/src/test/scala/DataWidthConverterSuiteCorrectness.scala
deleted
100644 → 0
View file @
511f7779
package
chisel.miscutils
import
chisel3._
import
chisel3.util._
import
chisel3.iotesters.
{
ChiselFlatSpec
,
Driver
,
PeekPokeTester
}
import
org.scalatest.junit.JUnitSuite
import
scala.math._
import
java.nio.file.Paths
class
SlowQueue
(
width
:
Int
,
val
delay
:
Int
=
10
)
extends
Module
{
val
io
=
IO
(
new
Bundle
{
val
enq
=
Flipped
(
Decoupled
(
UInt
(
width
.
W
)))
val
deq
=
Decoupled
(
UInt
(
width
.
W
))
val
dly
=
Input
(
UInt
(
log2Ceil
(
delay
).
W
))
})
val
waiting
::
ready
::
Nil
=
Enum
(
2
)
val
state
=
RegInit
(
init
=
ready
)
val
wr
=
Reg
(
UInt
(
log2Ceil
(
delay
).
W
))
io
.
deq
.
bits
:=
io
.
enq
.
bits
io
.
enq
.
ready
:=
io
.
deq
.
ready
&&
state
===
ready
io
.
deq
.
valid
:=
io
.
enq
.
valid
&&
state
===
ready
when
(
reset
)
{
state
:=
ready
}
.
otherwise
{
when
(
state
===
ready
&&
io
.
enq
.
ready
&&
io
.
deq
.
valid
)
{
state
:=
waiting
wr
:=
io
.
dly
}
when
(
state
===
waiting
)
{
wr
:=
wr
-
1.
U
when
(
wr
===
0.
U
)
{
state
:=
ready
}
}
}
}
/**
* DataWidthConverterHarness: Correctness test harness.
* A DecoupledDataSource with random data is connected to a pair
* of data width converters with inverted params. This circuit
* must behave exactly like a delay on the input stream (where
* the length of the delay is 2 * in/out-width-ratio).
* There's a slow queue in-between to simulate receivers with
* varying speed of consumption.
**/
class
DataWidthConverterHarness
(
inWidth
:
Int
,
outWidth
:
Int
,
littleEndian
:
Boolean
,
delay
:
Int
=
10
)
extends
Module
{
val
io
=
IO
(
new
Bundle
{
val
dly
=
Input
(
UInt
(
log2Ceil
(
delay
).
W
))
val
dsrc_out_valid
=
Output
(
Bool
())
val
dsrc_out_bits
=
Output
(
UInt
())
val
dwc_inq_valid
=
Output
(
Bool
())
val
dwc_inq_ready
=
Output
(
Bool
())
val
dwc_deq_valid
=
Output
(
Bool
())
val
dwc_deq_ready
=
Output
(
Bool
())
val
dwc2_inq_valid
=
Output
(
Bool
())
val
dwc2_deq_valid
=
Output
(
Bool
())
val
dwc2_deq_ready
=
Output
(
Bool
())
val
dwc2_deq_bits
=
Output
(
UInt
())
})
val
dwc
=
Module
(
new
DataWidthConverter
(
inWidth
,
outWidth
,
littleEndian
))
val
dsrc
=
Module
(
new
DecoupledDataSource
(
UInt
(
inWidth
.
W
),
Seq
(
Seq
(
pow
(
2
,
inWidth
).
toLong
,
dwc
.
ratio
).
max
,
500.
toLong
).
min
.
toInt
,
n
=>
(
scala
.
math
.
random
*
pow
(
2
,
inWidth
)).
toLong
.
U
,
repeat
=
false
))
val
dwc2
=
Module
(
new
DataWidthConverter
(
outWidth
,
inWidth
,
littleEndian
))
val
slq
=
Module
(
new
SlowQueue
(
outWidth
,
delay
))
dwc
.
io
.
inq
<>
dsrc
.
io
.
out
slq
.
io
.
enq
<>
dwc
.
io
.
deq
slq
.
io
.
dly
:=
io
.
dly
dwc2
.
io
.
inq
<>
slq
.
io
.
deq
dwc2
.
io
.
deq
.
ready
:=
true
.
B
// internal peek-and-poke does not work, need to wire as outputs:
io
.
dsrc_out_valid
:=
dsrc
.
io
.
out
.
valid
io
.
dsrc_out_bits
:=
dsrc
.
io
.
out
.
bits
io
.
dwc_inq_valid
:=
dwc
.
io
.
inq
.
valid
io
.
dwc_inq_ready
:=
dwc
.
io
.
inq
.
ready
io
.
dwc_deq_valid
:=
dwc
.
io
.
deq
.
valid
io
.
dwc_deq_ready
:=
dwc
.
io
.
deq
.
ready
io
.
dwc2_inq_valid
:=
dwc2
.
io
.
inq
.
valid
io
.
dwc2_deq_valid
:=
dwc2
.
io
.
deq
.
valid
io
.
dwc2_deq_ready
:=
dwc2
.
io
.
deq
.
ready
io
.
dwc2_deq_bits
:=
dwc2
.
io
.
deq
.
bits
}
/**
* Generic tester for DataWidthConverterHarness:
* Uses DataWidthConverterHarness class to check output correctness.
* Tracks incoming data from the data source in expecteds list.
* Whenever output is valid, it is compared to the expecteds,
* mismatches are reported accordingly.
* Does NOT check timing, only correctness of the output values.
**/
class
DataWidthConverterCorrectnessTester
[
T
<:
UInt
](
m
:
DataWidthConverterHarness
)
extends
PeekPokeTester
(
m
)
{
import
scala.util.Properties.
{
lineSeparator
=>
NL
}
// returns binary string for Int, e.g., 0011 for 3, width 4
private
def
toBinaryString
(
n
:
BigInt
,
width
:
Int
)
=
"%%%ds"
.
format
(
width
).
format
(
n
.
toString
(
2
)).
replace
(
' '
,
'0'
)
/** Performs data correctness check. **/
def
check
()
=
{
var
i
=
0
var
delay
=
m
.
slq
.
delay
-
1
poke
(
m
.
io
.
dly
,
delay
)
var
expecteds
:
List
[
BigInt
]
=
List
()
def
running
=
peek
(
m
.
io
.
dsrc_out_valid
)
>
0
||
peek
(
m
.
io
.
dwc_inq_valid
)
>
0
||
peek
(
m
.
io
.
dwc_deq_valid
)
>
0
||
peek
(
m
.
io
.
dwc2_inq_valid
)
>
0
||
peek
(
m
.
io
.
dwc2_deq_valid
)
>
0
while
(
running
)
{
// scan output element and add to end of expected list
if
(
peek
(
m
.
io
.
dsrc_out_valid
)
>
0
&&
peek
(
m
.
io
.
dwc_inq_ready
)
>
0
)
{
val
e
=
peek
(
m
.
io
.
dsrc_out_bits
)
expecteds
=
expecteds
:+
e
println
(
"adding expected value: %d (%s)"
.
format
(
e
,
toBinaryString
(
e
,
m
.
dwc
.
inWidth
)))
}
// check output element: must match head of expecteds
if
(
peek
(
m
.
io
.
dwc2_deq_valid
)
>
0
&&
peek
(
m
.
io
.
dwc2_deq_ready
)
>
0
)
{
// update delay (decreasing with each output)
delay
=
if
(
delay
==
0
)
m
.
slq
.
delay
-
1
else
delay
-
1
poke
(
m
.
io
.
dly
,
delay
)
// check output
val
v
=
peek
(
m
.
io
.
dwc2_deq_bits
)
if
(
expecteds
.
isEmpty
)
{
val
errmsg
=
"received value output value %d (%s), but none expected yet"
.
format
(
v
,
toBinaryString
(
v
,
m
.
dwc
.
inWidth
))
println
(
errmsg
)
expect
(
false
,
errmsg
)
}
else
{
if
(
v
==
expecteds
.
head
)
{
println
(
"element #%d ok!"
.
format
(
i
))
}
else
{
val
errmsg
=
"element #%d wrong: expected %d (%s), found %d (%s)"
.
format
(
i
,
expecteds
.
head
,
toBinaryString
(
expecteds
.
head
,
m
.
dwc
.
inWidth
),
v
,
toBinaryString
(
v
,
m
.
dwc
.
inWidth
))
println
(
errmsg
)
expect
(
v
==
expecteds
.
head
,
errmsg
)
}
expecteds
=
expecteds
.
tail
}
i
+=
1
}
// advance sim
step
(
1
)
}
}
reset
(
10
)
// reset for 10 cycles
check
()
step
(
20
)
// settle output
}
/** Unit test for DataWidthConverter hardware. **/
class
DataWidthConverterSuite
extends
ChiselFlatSpec
{
def
resize
(
inWidth
:
Int
,
outWidth
:
Int
,
littleEndian
:
Boolean
=
true
)
=
{
println
(
"testing conversion of %d bit to %d bit, %s ..."
.
format
(
inWidth
,
outWidth
,
if
(
littleEndian
)
"little-endian"
else
"big-endian"
))
val
dir
=
Paths
.
get
(
"test"
)
.
resolve
(
"DataWidthConverterSuite"
)
.
resolve
(
"%dto%d%s"
.
format
(
inWidth
,
outWidth
,
if
(
littleEndian
)
"le"
else
"be"
))
.
toString
Driver
.
execute
(
Array
(
"--fint-write-vcd"
,
"--target-dir"
,
dir
),
()
=>
new
DataWidthConverterHarness
(
inWidth
,
outWidth
,
littleEndian
))
{
m
=>
new
DataWidthConverterCorrectnessTester
(
m
)
}
}
// simple test group, can be used for waveform analysis
/*"check16to4le" should "be ok" in { resize(16, 4, true) }
"check4to16le" should "be ok" in { resize(4, 16, true) }
"check16to4be" should "be ok" in { resize(16, 4, false) }
"check4to16be" should "be ok" in { resize(4, 16, false) }
"check64to32be" should "be ok" in { resize(64, 32, false) }*/
// downsizing tests
"check2to1le"
should
"be ok"
in
{
resize
(
2
,
1
,
true
)
}
"check2to1be"
should
"be ok"
in
{
resize
(
2
,
1
,
false
)
}
"check8to1le"
should
"be ok"
in
{
resize
(
8
,
1
,
true
)
}
"check8to1be"
should
"be ok"
in
{
resize
(
8
,
1
,
false
)
}
"check16to4le"
should
"be ok"
in
{
resize
(
16
,
4
,
true
)
}
"check16to4be"
should
"be ok"
in
{
resize
(
16
,
4
,
false
)
}
"check16to8le"
should
"be ok"
in
{
resize
(
16
,
8
,
true
)
}
"check16to8be"
should
"be ok"
in
{
resize
(
16
,
8
,
false
)
}
"check32to8le"
should
"be ok"
in
{
resize
(
32
,
8
,
true
)
}
"check32to8be"
should
"be ok"
in
{
resize
(
32
,
8
,
false
)
}
"check64ot8le"
should
"be ok"
in
{
resize
(
64
,
8
,
true
)
}
"check64to8be"
should
"be ok"
in
{
resize
(
64
,
8
,
false
)
}
"check64ot32le"
should
"be ok"
in
{
resize
(
64
,
32
,
true
)
}
"check64to32be"
should
"be ok"
in
{
resize
(
64
,
32
,
false
)
}
// upsizing tests
"check1to2le"
should
"be ok"
in
{
resize
(
1
,
2
,
true
)
}
"check1to2be"
should
"be ok"
in
{
resize
(
1
,
2
,
false
)
}
"check1to8le"
should
"be ok"
in
{
resize
(
1
,
8
,
true
)
}
"check1to8be"
should
"be ok"
in
{
resize
(
1
,
8
,
false
)
}
"check4to16le"
should
"be ok"
in
{
resize
(
4
,
16
,
true
)
}
"check4to16be"
should
"be ok"
in
{
resize
(
4
,
16
,
false
)
}
"check8to16le"
should
"be ok"
in
{
resize
(
8
,
16
,
true
)
}
"check8to16be"
should
"be ok"
in
{
resize
(
8
,
16
,
false
)
}
"check8to32le"
should
"be ok"
in
{
resize
(
8
,
32
,
true
)
}
"check8to32be"
should
"be ok"
in
{
resize
(
8
,
32
,
false
)
}
"check8ot64le"
should
"be ok"
in
{
resize
(
8
,
64
,
true
)
}
"check8to64be"
should
"be ok"
in
{
resize
(
8
,
64
,
false
)
}
"check32ot64le"
should
"be ok"
in
{
resize
(
32
,
64
,
true
)
}
"check32to64be"
should
"be ok"
in
{
resize
(
32
,
64
,
false
)
}
}
miscutils/src/test/scala/DecoupledDataSourceSuite.scala
deleted
100644 → 0
View file @
511f7779
package
chisel.miscutils
import
chisel3._
import
chisel3.util._
import
chisel3.iotesters.
{
ChiselFlatSpec
,
Driver
,
PeekPokeTester
}
/**
* Tester class for DecoupledDataSource.
* Automatically exhausts the internal data of the instance, checks that
* each dequeued output matches the expected value. Also checks whether
* or not the module wraps correctly (in case repeat is true).
**/
class
DecoupledDataSource_OutputCheck
[
T
<:
UInt
](
m
:
DecoupledDataSource
[
T
],
data
:
Int
=>
Int
)
extends
PeekPokeTester
(
m
)
{
import
scala.util.Properties.
{
lineSeparator
=>
NL
}
poke
(
m
.
io
.
out
.
ready
,
true
)
var
errors
:
List
[
String
]
=
List
()
var
i
=
0
while
(
peek
(
m
.
io
.
out
.
valid
)
>
0
&&
i
<=
m
.
size
)
{
if
(
i
>=
m
.
size
)
{
if
(!
m
.
repeat
)
errors
=
"repeat is false, but index (%d) exceeds size(%d)"
.
format
(
i
,
m
.
size
)
::
errors
}
else
{
if
(
peek
(
m
.
io
.
out
.
bits
)
!=
m
.
data
(
i
))
{
errors
=
"output #%d: expected %d, found %d"
.
format
(
i
,
data
(
i
),
peek
(
m
.
io
.
out
.
bits
))
::
errors
}
else
{
// wait for random time up to 10 cycles
val
wait
=
(
scala
.
math
.
random
*
10
).
toInt
poke
(
m
.
io
.
out
.
ready
,
false
)
step
(
wait
)
poke
(
m
.
io
.
out
.
ready
,
true
)
}
}
i
+=
1
step
(
1
)
}
expect
(
errors
.
length
==
0
,
(
"all elements should match, errors: "
::
errors
).
mkString
(
NL
))
}
class
DecoupledDataSourceSuite
extends
ChiselFlatSpec
{
/** Performs randomized tests with random data of random size. **/
"checkRandomOutputs"
should
"be ok"
in
{
for
(
i
<-
0
until
1
)
{
val
cnt
=
Seq
(
1
,
(
scala
.
math
.
random
*
1000
).
toInt
).
max
val
width
=
Seq
(
1
,
(
scala
.
math
.
random
*
64
).
toInt
).
max
val
repeat
=
scala
.
math
.
random
>
0.5
val
data
=
for
(
i
<-
0
until
cnt
)
yield
(
scala
.
math
.
random
*
scala
.
math
.
pow
(
2
,
width
)).
toInt
println
(
"testing cnt = %d, width = %d, repeat = %b ..."
.
format
(
cnt
,
width
,
repeat
))
Driver
.
execute
(
Array
(
"--fint-write-vcd"
,
"--target-dir"
,
"test/DecoupledDataSourceSuite/checkRandomOutputs"
),
()
=>
new
DecoupledDataSource
(
UInt
(
width
.
W
),
cnt
,
i
=>
data
(
i
).
U
,
repeat
))
{
m
=>
new
DecoupledDataSource_OutputCheck
(
m
,
data
)
}
}
}
/** Performs test for 8bit wide sequential data with repeat. **/
"checkSequentialOutputsWithRepeat"
should
"be ok"
in
{
val
data
=
0
until
256
Driver
.
execute
(
Array
(
"--fint-write-vcd"
,
"--target-dir"
,
"test/DecoupledDataSourceSuite/checkSequentialOutputsWithRepeat"
),
()
=>
new
DecoupledDataSource
(
UInt
(
8.
W
),
256
,
i
=>
data
(
i
).
U
,
true
))
{
m
=>
new
DecoupledDataSource_OutputCheck
(
m
,
data
)
}
}
/** Performs test for 8bit wide sequential data without repeat. **/
"checkSequentialOutputsWithoutRepeat"
should
"be ok"
in
{
val
data
=
0
until
256
Driver
.
execute
(
Array
(
"--fint-write-vcd"
,
"--target-dir"
,
"test/DecoupledDataSourceSuite/checkSequentialOutputWithoutRepeat"
),
()
=>
new
DecoupledDataSource
(
UInt
(
8.
W
),
256
,
i
=>
data
(
i
).
U
,
false
))
{
m
=>
new
DecoupledDataSource_OutputCheck
(
m
,
data
)
}
}
}
miscutils/src/test/scala/SignalGeneratorTest.scala
deleted
100644 → 0
View file @
511f7779
package
chisel.miscutils
import
chisel3._
import
chisel3.util._
import
chisel3.iotesters.
{
ChiselFlatSpec
,
Driver
,
PeekPokeTester
}
import
SignalGenerator._
class
SignalGeneratorComposition1
extends
Module
{
val
waveform
:
SignalGenerator.Waveform
=
(
for
(
i
<-
2
until
30
)
yield
List
((
false
,
5
),
(
true
,
i
)))
reduce
(
_
++
_
)
val
clock_sg
=
Module
(
new
SignalGenerator
(
List
((
true
,
2
),
(
false
,
2
))))
val
test_sg
=
Module
(
new
SignalGenerator
(
waveform
,
true
))
val
io
=
IO
(
new
Bundle
{
val
v
=
Output
(
Bool
())
})
test_sg
.
io
.
in
:=
clock_sg
.
io
.
v
io
.
v
:=
test_sg
.
io
.
v
}
class
SignalGeneratorSuite
extends
ChiselFlatSpec
{
"test1"
should
"be ok"
in
{
val
waveform
:
SignalGenerator.Waveform
=
(
for
(
i
<-
2
until
30
)
yield
List
((
false
,
5
),
(
true
,
i
)))
reduce
(
_
++
_
)
Driver
.
execute
(
Array
(
"--fint-write-vcd"
,
"--target-dir"
,
"test/signalgenerator"
),
()
=>
new
SignalGenerator
(
waveform
))
{
m
=>
new
SignalGeneratorTest
(
m
)
}
}
"test2"
should
"be ok"
in
{
// same as test1, but with user supplied clock
Driver
.
execute
(
Array
(
"--fint-write-vcd"
,
"--target-dir"
,
"test/signalgenerator"
),
()
=>
new
SignalGeneratorComposition1
)
{
m
=>
new
SignalGeneratorComposition1Test
(
m
)
}
}
}
class
SignalGeneratorTest
(
sg
:
SignalGenerator
)
extends
PeekPokeTester
(
sg
)
{
import
scala.util.Properties.
{
lineSeparator
=>
NL
}
private
var
cc
=
0
// re-define step to output progress info
override
def
step
(
n
:
Int
)
{
super
.
step
(
n
)
cc
+=
n
if
(
cc
%
1000
==
0
)
println
(
"clock cycle: "
+
cc
)
}
// waits for next positive edge on signal
def
waitForPosEdge
[
T
<:
Chisel.Bits
](
s
:
T
)
{
while
(
peek
(
s
)
>
0
)
step
(
1
)
while
(
peek
(
s
)
==
0
)
step
(
1
)
}
// waits for next positive edge on signal
def
waitForNegEdge
[
T
<:
Chisel.Bits
](
s
:
T
)
{
while
(
peek
(
s
)
==
0
)
step
(
1
)
while
(
peek
(
s
)
>
0
)
step
(
1
)
}
reset
(
10
)
for
(
j
<-
0
to
1
)
{
for
(
i
<-
2
until
30
)
{
waitForPosEdge
(
sg
.
io
.
v
)
val
cc_start
=
cc
waitForNegEdge
(
sg
.
io
.
v
)
expect
(
cc
-
cc_start
==
i
,
"wrong number of clock cycles"
)
}
}
}
class
SignalGeneratorComposition1Test
(
sg
:
SignalGeneratorComposition1
)
extends
PeekPokeTester
(
sg
)
{
private
var
cc
=
0
// re-define step to output progress info
override
def
step
(
n
:
Int
)
{
super
.
step
(
n
)
cc
+=
n
if
(
cc
%
1000
==
0
)
println
(
"clock cycle: "
+
cc
)
}
// waits for next positive edge on signal
def
waitForPosEdge
[
T
<:
Chisel.Bits
](
s
:
T
)
{
while
(
peek
(
s
)
>
0
)
step
(
1
)
while
(
peek
(
s
)
==
0
)
step
(
1
)
}
// waits for next positive edge on signal
def
waitForNegEdge
[
T
<:
Chisel.Bits
](
s
:
T
)
{
while
(
peek
(
s
)
==
0
)
step
(
1
)
while
(
peek
(
s
)
>
0
)
step
(
1
)
}
reset
(
10
)
for
(
j
<-
0
to
1
)
{
for
(
i
<-
2
until
30
)
{
waitForPosEdge
(
sg
.
io
.
v
)
val
cc_start
=
cc
waitForNegEdge
(
sg
.
io
.
v
)
expect
(
cc
-
cc_start
==
i
*
4
,
"wrong number of clock cycles"
)
}
}
}
miscutils/src/test/scala/SlowQueue.scala
0 → 100644
View file @
8f2faf2e
package
chisel.miscutils
import
chisel3._
import
chisel3.util._
/** A slow queue which delays each element by a configurable delay. */
class
SlowQueue
(
width
:
Int
,
val
delay
:
Int
=
10
)
extends
Module
{
val
io
=
IO
(
new
Bundle
{
val
enq
=
Flipped
(
Decoupled
(
UInt
(
width
.
W
)))
val
deq
=
Decoupled
(
UInt
(
width
.
W
))
val
dly
=
Input
(
UInt
(
log2Ceil
(
delay
).
W
))
})
val
waiting
::
ready
::
Nil
=
Enum
(
2
)
val
state
=
RegInit
(
ready
)
val
wr
=
Reg
(
UInt
(
log2Ceil
(
delay
).
W
))
io
.
deq
.
bits
:=
io
.
enq
.
bits
io
.
enq
.
ready
:=
io
.
deq
.
ready
&&
state
===
ready
io
.
deq
.
valid
:=
io
.
enq
.
valid
&&
state
===
ready
when
(
reset
)
{
state
:=
ready
}
.
otherwise
{
when
(
state
===
ready
&&
io
.
enq
.
ready
&&
io
.
deq
.
valid
)
{
state
:=
waiting
wr
:=
io
.
dly
}
when
(
state
===
waiting
)
{
wr
:=
wr
-
1.
U
when
(
wr
===
0.
U
)
{
state
:=
ready
}
}
}
}
miscutils/src/test/scala/datawidthconverter/CorrectnessHarness.scala
0 → 100644
View file @
8f2faf2e
package
chisel.miscutils.datawidthconverter
import
chisel.miscutils._
import
chisel3._
import
chisel3.util._
import
math.pow
/** Correctness test harness for DataWidthConverter:
* A DecoupledDataSource with random data is connected to a pair
* of data width converters with inverted params. This circuit
* must behave exactly like a delay on the input stream (where
* the length of the delay is 2 * in/out-width-ratio).
* There's a slow queue in-between to simulate receivers with
* varying speed of consumption.
* @param inWidth Bit width of input data.
* @param outWidth Bit width of output data (in and out must be
* integer multiples/fractions of each other)
* @param littleEndian Byte-endianess.
* @param delay Clock cycle delay in [[SlowQueue]].
*/
class
CorrectnessHarness
(
inWidth
:
Int
,
outWidth
:
Int
,
littleEndian
:
Boolean
,
delay
:
Int
=
10
)
extends
Module
{
require
(
delay
>
0
,
"delay bitwidth must be > 0"
)
val
io
=
IO
(
new
Bundle
{
val
dly
=
Input
(
UInt
(
Seq
(
log2Ceil
(
delay
),
1
).
max
.
W
))
val
dsrc_out_valid
=
Output
(
Bool
())
val
dsrc_out_bits
=
Output
(
UInt
())
val
dwc_inq_valid
=
Output
(
Bool
())
val
dwc_inq_ready
=
Output
(
Bool
())
val
dwc_deq_valid
=
Output
(
Bool
())
val
dwc_deq_ready
=
Output
(
Bool
())
val
dwc2_inq_valid
=
Output
(
Bool
())
val
dwc2_deq_valid
=
Output
(
Bool
())
val
dwc2_deq_ready
=
Output
(
Bool
())
val
dwc2_deq_bits
=
Output
(
UInt
())
})
val
dwc
=
Module
(
new
DataWidthConverter
(
inWidth
,
outWidth
,
littleEndian
))
val
dsrc
=
Module
(
new
DecoupledDataSource
(
UInt
(
inWidth
.
W
),
Seq
(
Seq
(
pow
(
2
,
inWidth
).
toLong
,
dwc
.
ratio
).
max
,
500.
toLong
).
min
.
toInt
,
n
=>
(
scala
.
math
.
random
*
pow
(
2
,
inWidth
)).
toLong
.
U
,
repeat
=
false
))
val
dwc2
=
Module
(
new
DataWidthConverter
(
outWidth
,
inWidth
,
littleEndian
))
val
slq
=
Module
(
new
SlowQueue
(
outWidth
,
delay
))
dwc
.
io
.
inq
<>
dsrc
.
io
.
out