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
48cb64c9
Commit
48cb64c9
authored
Jul 15, 2017
by
Jens Korinth
Browse files
Merge commit '537797a1709f872129c78d22b07ad42ab469c1cf'
Pulled chisel-miscutils.
parents
641d8456
8a742587
Changes
9
Hide whitespace changes
Inline
Side-by-side
miscutils/README.md
0 → 100644
View file @
48cb64c9
# Miscellaneous Chisel IP
Some very basic IP for everyday use, written in Chisel 3.0. Currently contains:
*
[
DataWidthConverter
][
1
]
Converts
`UInt`
of arbitrary bit width to
`UInt`
of different bit width.
Zero delay, handshaked channels using Chisels
`Decoupled`
interface.
*
[
DecoupledDataSource
][
2
]
Generic data provider with fixed (compile-time) data; uses handshakes via
Chisels
`Decoupled`
interface.
*
[
SignalGenerator
][
3
]
Primitive 1-bit signal generator: Specify via change list, can cycle.
These were basically warm-up exercises with Chisel, but can be useful now and
then. For usage examples see the
[
unit test suites
][
4
]
.
[
1
]:
src/main/scala/DataWidthConverter.scala
[
2
]:
src/main/scala/DecoupledDataSource.scala
[
3
]:
src/main/scala/SignalGenerator.scala
[
4
]:
src/test/scala/
miscutils/build.sbt
View file @
48cb64c9
...
...
@@ -8,9 +8,19 @@ scalaVersion := "2.11.7"
crossScalaVersions
:=
Seq
(
"2.10.3"
,
"2.10.4"
,
"2.11.0"
)
resolvers
++=
Seq
(
Resolver
.
sonatypeRepo
(
"snapshots"
),
Resolver
.
sonatypeRepo
(
"releases"
)
)
// Provide a managed dependency on X if -DXVersion="" is supplied on the command line.
val
defaultVersions
=
Map
(
"chisel3"
->
"3.0-SNAPSHOT"
,
"chisel-iotesters"
->
"1.1-SNAPSHOT"
)
libraryDependencies
++=
(
Seq
(
"chisel3"
,
"chisel-iotesters"
).
map
{
dep
:
String
=>
"edu.berkeley.cs"
%%
dep
%
sys
.
props
.
getOrElse
(
dep
+
"Version"
,
defaultVersions
(
dep
))
})
libraryDependencies
++=
Seq
(
"edu.berkeley.cs"
%%
"chisel"
%
"latest.release"
,
"com.novocode"
%
"junit-interface"
%
"0.11"
%
"test"
,
"org.scalatest"
%%
"scalatest"
%
"2.2.6"
%
"test"
,
"com.typesafe.play"
%%
"play-json"
%
"2.4.8"
)
...
...
@@ -21,3 +31,5 @@ parallelExecution in Test := false
testForkedParallel
in
Test
:=
false
scalacOptions
++=
Seq
(
"-language:implicitConversions"
,
"-language:reflectiveCalls"
,
"-deprecation"
,
"-feature"
)
miscutils/src/main/scala/DataWidthConverter.scala
View file @
48cb64c9
package
chisel.miscutils
import
Chisel._
import
chisel3._
import
chisel3.util._
/**
* DataWidthConverter converts the data width of a Queue.
...
...
@@ -8,8 +9,8 @@ import Chisel._
* Note: This would be much more useful, if the two Queues
* could use different clocks, but multi-clock support
* in Chisel is currently unstable.
* @param inWidth Data width of input Decoupled (bits).
* @param outWidth Data width of output Decoupled (bits); must
* @param inWidth Data width of input Decoupled
IO
(bits).
* @param outWidth Data width of output Decoupled
IO
(bits); must
* be integer multiples of each other.
* @param littleEndian if inWidth > outWidth, determines
* the order of the nibbles (low to high)
...
...
@@ -28,10 +29,10 @@ class DataWidthConverter(
"inWidth (%d) and outWidth (%d) must be integer multiples of each other"
.
format
(
inWidth
,
outWidth
))
val
io
=
new
Bundle
{
val
inq
=
Decoupled
(
UInt
(
width
=
inWidth
)).
flip
(
)
val
deq
=
Decoupled
(
UInt
(
width
=
outWidth
))
}
val
io
=
IO
(
new
Bundle
{
val
inq
=
Flipped
(
Decoupled
(
UInt
(
inWidth
.
W
))
)
val
deq
=
Decoupled
(
UInt
(
outWidth
.
W
))
}
)
val
ratio
:
Int
=
if
(
inWidth
>
outWidth
)
inWidth
/
outWidth
else
outWidth
/
inWidth
val
d_w
=
if
(
inWidth
>
outWidth
)
inWidth
else
outWidth
// data register width
...
...
@@ -42,57 +43,57 @@ class DataWidthConverter(
upsize
()
private
def
upsize
()
=
{
val
i
=
Reg
(
UInt
(
width
=
log2Up
(
ratio
+
1
)))
val
d
=
Reg
(
UInt
(
width
=
outWidth
))
val
i
=
Reg
(
UInt
(
log2Ceil
(
ratio
+
1
)
.
W
))
val
d
=
Reg
(
UInt
(
outWidth
.
W
))
io
.
inq
.
ready
:=
!
reset
&&
(
i
=/=
UInt
(
0
)
||
(
io
.
inq
.
valid
&&
io
.
deq
.
ready
))
io
.
inq
.
ready
:=
!
reset
&&
(
i
=/=
0.
U
||
(
io
.
inq
.
valid
&&
io
.
deq
.
ready
))
io
.
deq
.
bits
:=
d
io
.
deq
.
valid
:=
!
reset
&&
i
===
UInt
(
0
)
io
.
deq
.
valid
:=
!
reset
&&
i
===
0.
U
when
(
reset
)
{
i
:=
UInt
(
ratio
)
d
:=
UInt
(
0
)
i
:=
ratio
.
U
d
:=
0.
U
}
.
otherwise
{
when
(
io
.
inq
.
ready
&&
io
.
inq
.
valid
)
{
if
(
littleEndian
)
d
:=
Cat
(
io
.
inq
.
bits
,
d
)
>>
UInt
(
inWidth
)
d
:=
Cat
(
io
.
inq
.
bits
,
d
)
>>
inWidth
.
U
else
d
:=
(
d
<<
UInt
(
inWidth
)
)
|
io
.
inq
.
bits
i
:=
i
-
UInt
(
1
)
d
:=
(
d
<<
inWidth
.
U
)
|
io
.
inq
.
bits
i
:=
i
-
1.
U
}
when
(
io
.
deq
.
valid
&&
io
.
deq
.
ready
)
{
i
:=
Mux
(
io
.
inq
.
valid
,
UInt
(
ratio
-
1
),
UInt
(
ratio
)
)
i
:=
Mux
(
io
.
inq
.
valid
,
(
ratio
-
1
)
.
U
,
ratio
.
U
)
}
}
}
private
def
downsize
()
=
{
val
i
=
Reg
(
UInt
(
width
=
log2Up
(
ratio
+
1
)))
val
d
=
Reg
(
UInt
(
width
=
inWidth
))
val
i
=
Reg
(
UInt
(
log2Ceil
(
ratio
+
1
)
.
W
))
val
d
=
Reg
(
UInt
(
inWidth
.
W
))
io
.
inq
.
ready
:=
!
reset
&&
(
i
===
UInt
(
0
)
||
(
i
===
UInt
(
1
)
&&
io
.
deq
.
ready
))
io
.
inq
.
ready
:=
!
reset
&&
(
i
===
0.
U
||
(
i
===
1.
U
&&
io
.
deq
.
ready
))
if
(
littleEndian
)
io
.
deq
.
bits
:=
d
(
outWidth
-
1
,
0
)
else
io
.
deq
.
bits
:=
d
(
inWidth
-
1
,
inWidth
-
outWidth
)
io
.
deq
.
valid
:=
!
reset
&&
i
>
UInt
(
0
)
io
.
deq
.
valid
:=
!
reset
&&
i
>
0.
U
when
(
reset
)
{
i
:=
UInt
(
0
)
d
:=
UInt
(
0
)
i
:=
0.
U
d
:=
0.
U
}
.
otherwise
{
when
(
i
>
UInt
(
0
)
&&
io
.
deq
.
ready
)
{
when
(
i
>
0.
U
&&
io
.
deq
.
ready
)
{
if
(
littleEndian
)
d
:=
d
>>
UInt
(
outWidth
)
d
:=
d
>>
outWidth
.
U
else
d
:=
d
<<
UInt
(
outWidth
)
i
:=
i
-
UInt
(
1
)
d
:=
d
<<
outWidth
.
U
i
:=
i
-
1.
U
}
when
(
io
.
inq
.
ready
&&
io
.
inq
.
valid
)
{
d
:=
io
.
inq
.
bits
i
:=
UInt
(
ratio
)
i
:=
ratio
.
U
}
}
}
...
...
miscutils/src/main/scala/DecoupledDataSource.scala
View file @
48cb64c9
package
chisel.miscutils
import
Chisel._
import
chisel3._
import
chisel3.util._
/**
* Interface for DecoupledDataSource.
...
...
@@ -19,25 +20,25 @@ class DecoupledDataSourceIO[T <: Data](gen: T) extends Bundle {
otherwise valid will go low after data was
consumed.
**/
class
DecoupledDataSource
[
T
<:
Data
](
gen
:
T
,
val
size
:
Int
,
data
:
(
Int
)
=>
T
,
val
repeat
:
Boolean
=
true
)
extends
Module
{
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
(
log2
Up
(
if
(
repeat
)
size
else
size
+
1
)))
println
(
" width = %d"
.
format
(
log2
Ceil
(
if
(
repeat
)
size
else
size
+
1
)))
val
ds
=
for
(
i
<-
0
until
size
)
yield
data
(
i
)
// evaluate data to array
val
io
=
new
DecoupledDataSourceIO
(
gen
)
// interface
val
i
=
Reg
(
UInt
(
width
=
log2Up
(
if
(
repeat
)
size
else
size
+
1
)))
// index
val
io
=
IO
(
new
DecoupledDataSourceIO
(
gen
)
)
// interface
val
i
=
Reg
(
UInt
(
log2Ceil
(
if
(
repeat
)
size
else
size
+
1
)
.
W
))
// index
val
rom
=
Vec
.
tabulate
(
size
)(
n
=>
ds
(
n
))
// ROM with data
io
.
out
.
bits
:=
rom
(
i
)
// current index data
io
.
out
.
valid
:=
!
reset
&&
i
<
UInt
(
size
)
// valid until exceeded
io
.
out
.
valid
:=
!
reset
&&
i
<
size
.
U
// valid until exceeded
when
(
reset
)
{
i
:=
UInt
(
0
)
i
:=
0.
U
}
.
otherwise
{
if
(
repeat
)
when
(
io
.
out
.
ready
&&
io
.
out
.
valid
)
{
i
:=
i
+
UInt
(
1
)
}
when
(
io
.
out
.
ready
&&
io
.
out
.
valid
)
{
i
:=
i
+
1.
U
}
else
when
(
io
.
out
.
ready
&&
io
.
out
.
valid
&&
i
<
UInt
(
size
)
)
{
i
:=
i
+
UInt
(
1
)
}
when
(
io
.
out
.
ready
&&
io
.
out
.
valid
&&
i
<
size
.
U
)
{
i
:=
i
+
1.
U
}
}
}
miscutils/src/main/scala/SignalGenerator.scala
View file @
48cb64c9
package
chisel.miscutils
import
Chisel._
import
chisel3._
import
chisel3.util._
sealed
case
class
Signal
(
value
:
Boolean
,
periods
:
Int
=
1
)
extends
Ordered
[
Signal
]
{
import
scala.math.Ordered.orderingToOrdered
...
...
@@ -16,31 +17,31 @@ class SignalGenerator(signals: SignalGenerator.Waveform, useInputAsClock: Boolea
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."
)
val
io
=
new
Bundle
{
val
v
=
Bool
(
OUTPUT
);
val
in
=
Bool
(
INPUT
)
}
val
cnts_rom
=
Vec
(
signals
map
(
n
=>
UInt
(
n
.
periods
-
1
)))
val
vals_rom
=
Vec
(
signals
map
(
n
=>
Bool
(
n
.
value
)))
val
cnt
=
Reg
(
UInt
(
width
=
log2Up
(
signals
.
max
.
periods
)))
val
curr_idx
=
Reg
(
UInt
(
width
=
log2Up
(
signals
.
length
)))
val
io
=
IO
(
new
Bundle
{
val
v
=
Output
(
Bool
());
val
in
=
Input
(
Bool
()
)
}
)
val
cnts_rom
=
Vec
(
signals
map
(
n
=>
(
n
.
periods
-
1
)
.
U
))
val
vals_rom
=
Vec
(
signals
map
(
n
=>
(
n
.
value
)
.
B
))
val
cnt
=
Reg
(
UInt
(
log2Ceil
(
signals
.
max
.
periods
)
.
W
))
val
curr_idx
=
Reg
(
UInt
(
log2Ceil
(
signals
.
length
)
.
W
))
val
vreg
=
Reg
(
Bool
())
io
.
v
:=
vreg
when
(
reset
)
{
curr_idx
:=
UInt
(
0
)
curr_idx
:=
0.
U
cnt
:=
cnts_rom
(
0
)
vreg
:=
UInt
(
0
)
vreg
:=
0.
U
}
.
otherwise
{
vreg
:=
vals_rom
(
curr_idx
)
// trigger on either clock or pos input edge
when
(
if
(
useInputAsClock
)
io
.
in
&&
!
RegNext
(
io
.
in
)
else
Bool
(
true
)
)
{
when
(
cnt
===
UInt
(
0
)
)
{
val
next_idx
=
Mux
(
curr_idx
<
UInt
(
signals
.
length
-
1
),
curr_idx
+
UInt
(
1
),
UInt
(
0
)
)
when
(
if
(
useInputAsClock
)
io
.
in
&&
!
RegNext
(
io
.
in
)
else
true
.
B
)
{
when
(
cnt
===
0.
U
)
{
val
next_idx
=
Mux
(
curr_idx
<
(
signals
.
length
-
1
)
.
U
,
curr_idx
+
1.
U
,
0.
U
)
curr_idx
:=
next_idx
cnt
:=
cnts_rom
(
next_idx
)
}
.
otherwise
{
cnt
:=
cnt
-
UInt
(
1
)
cnt
:=
cnt
-
1.
U
}
}
}
...
...
miscutils/src/test/scala/DataWidthConverterSuiteCorrectness.scala
View file @
48cb64c9
package
chisel.miscutils
import
C
hisel._
import
org.scalatest.junit.JUnitSuite
import
org.junit.
Test
import
org.
junit.Assert._
import
scala.math._
import
java.nio.file.Paths
import
c
hisel
3
._
import
chisel3.util._
import
chisel3.iotesters.
{
ChiselFlatSpec
,
Driver
,
PeekPoke
Test
er
}
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
=
new
Bundle
{
val
enq
=
Decoupled
(
UInt
(
width
=
width
)).
flip
val
deq
=
Decoupled
(
UInt
(
width
=
width
))
val
dly
=
U
In
t
(
INPUT
,
width
=
log2Up
(
delay
))
}
val
io
=
IO
(
new
Bundle
{
val
enq
=
Flipped
(
Decoupled
(
UInt
(
width
.
W
)))
val
deq
=
Decoupled
(
UInt
(
width
.
W
))
val
dly
=
In
put
(
UInt
(
log2Ceil
(
delay
)
.
W
)
)
}
)
val
waiting
::
ready
::
Nil
=
Enum
(
UInt
(),
2
)
val
state
=
Reg
(
init
=
ready
)
val
waiting
::
ready
::
Nil
=
Enum
(
2
)
val
state
=
Reg
Init
(
init
=
ready
)
val
wr
=
Reg
(
UInt
(
width
=
log2Up
(
delay
)))
val
wr
=
Reg
(
UInt
(
log2Ceil
(
delay
)
.
W
))
io
.
deq
.
bits
:=
io
.
enq
.
bits
io
.
enq
.
ready
:=
io
.
deq
.
ready
&&
state
===
ready
...
...
@@ -31,8 +31,8 @@ class SlowQueue(width: Int, val delay: Int = 10) extends Module {
wr
:=
io
.
dly
}
when
(
state
===
waiting
)
{
wr
:=
wr
-
UInt
(
1
)
when
(
wr
===
UInt
(
0
)
)
{
state
:=
ready
}
wr
:=
wr
-
1.
U
when
(
wr
===
0.
U
)
{
state
:=
ready
}
}
}
}
...
...
@@ -47,12 +47,23 @@ class SlowQueue(width: Int, val delay: Int = 10) extends Module {
* varying speed of consumption.
**/
class
DataWidthConverterHarness
(
inWidth
:
Int
,
outWidth
:
Int
,
littleEndian
:
Boolean
,
delay
:
Int
=
10
)
extends
Module
{
val
io
=
new
Bundle
{
val
dly
=
UInt
(
INPUT
,
width
=
log2Up
(
delay
))
}
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
(
width
=
inWidth
),
Seq
(
Seq
(
pow
(
2
,
inWidth
).
toLong
,
dwc
.
ratio
).
max
,
10000.
toLong
).
min
.
toInt
,
//n => UInt(n % pow(2, inWidth).toInt + 1, width = inWidth),
n
=>
UInt
((
scala
.
math
.
random
*
pow
(
2
,
inWidth
)).
toLong
,
width
=
inWidth
),
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
))
...
...
@@ -61,7 +72,19 @@ class DataWidthConverterHarness(inWidth: Int, outWidth: Int, littleEndian: Boole
slq
.
io
.
enq
<>
dwc
.
io
.
deq
slq
.
io
.
dly
:=
io
.
dly
dwc2
.
io
.
inq
<>
slq
.
io
.
deq
dwc2
.
io
.
deq
.
ready
:=
Bool
(
true
)
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
}
/**
...
...
@@ -72,7 +95,7 @@ class DataWidthConverterHarness(inWidth: Int, outWidth: Int, littleEndian: Boole
* mismatches are reported accordingly.
* Does NOT check timing, only correctness of the output values.
**/
class
DataWidthConverterCorrectnessTester
[
T
<:
UInt
](
m
:
DataWidthConverterHarness
)
extends
Tester
(
m
,
false
)
{
class
DataWidthConverterCorrectnessTester
[
T
<:
UInt
](
m
:
DataWidthConverterHarness
)
extends
PeekPoke
Tester
(
m
)
{
import
scala.util.Properties.
{
lineSeparator
=>
NL
}
// returns binary string for Int, e.g., 0011 for 3, width 4
...
...
@@ -83,28 +106,28 @@ class DataWidthConverterCorrectnessTester[T <: UInt](m: DataWidthConverterHarnes
def
check
()
=
{
var
i
=
0
var
delay
=
m
.
slq
.
delay
-
1
poke
(
m
.
slq
.
io
.
dly
,
delay
)
poke
(
m
.
io
.
dly
,
delay
)
var
expecteds
:
List
[
BigInt
]
=
List
()
def
running
=
peek
(
m
.
dsrc
.
io
.
out
.
valid
)
>
0
||
peek
(
m
.
dwc
.
io
.
inq
.
valid
)
>
0
||
peek
(
m
.
dwc
.
io
.
deq
.
valid
)
>
0
||
peek
(
m
.
dwc2
.
io
.
inq
.
valid
)
>
0
||
peek
(
m
.
dwc2
.
io
.
deq
.
valid
)
>
0
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
.
dsrc
.
io
.
out
.
valid
)
>
0
&&
peek
(
m
.
dwc
.
io
.
inq
.
ready
)
>
0
)
{
val
e
=
peek
(
m
.
dsrc
.
io
.
out
.
bits
)
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
.
dwc2
.
io
.
deq
.
valid
)
>
0
&&
peek
(
m
.
dwc2
.
io
.
deq
.
ready
)
>
0
)
{
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
.
dwc2
.
io
.
deq
.
bits
)
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
))
...
...
@@ -136,7 +159,7 @@ class DataWidthConverterCorrectnessTester[T <: UInt](m: DataWidthConverterHarnes
}
/** Unit test for DataWidthConverter hardware. **/
class
DataWidthConverterSuite
extends
JUnitSuite
{
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"
))
...
...
@@ -144,47 +167,47 @@ class DataWidthConverterSuite extends JUnitSuite {
.
resolve
(
"DataWidthConverterSuite"
)
.
resolve
(
"%dto%d%s"
.
format
(
inWidth
,
outWidth
,
if
(
littleEndian
)
"le"
else
"be"
))
.
toString
chiselMainTest
(
Array
(
"--genHarness"
,
"--backend"
,
"c"
,
"-
-vcd"
,
"--target
D
ir"
,
dir
,
"--compile"
,
"--test"
),
()
=>
Module
(
new
DataWidthConverterHarness
(
inWidth
,
outWidth
,
littleEndian
))
)
Driver
.
execute
(
Array
(
"--fint-write
-vcd"
,
"--target
-d
ir"
,
dir
),
()
=>
new
DataWidthConverterHarness
(
inWidth
,
outWidth
,
littleEndian
))
{
m
=>
new
DataWidthConverterCorrectnessTester
(
m
)
}
}
// simple test group, can be used for waveform analysis
/*
@Test def
check16to4le { resize(16, 4, true) }
@Test def
check4to16le { resize(4, 16, true) }
@Test def
check16to4be { resize(16, 4, false) }
@Test def
check4to16be { resize(4, 16, false) }
@Test def
check64to32be { resize(64, 32, false) }*/
/*
"
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
@Test
def
check2to1le
{
resize
(
2
,
1
,
true
)
}
@Test
def
check2to1be
{
resize
(
2
,
1
,
false
)
}
@Test
def
check8to1le
{
resize
(
8
,
1
,
true
)
}
@Test
def
check8to1be
{
resize
(
8
,
1
,
false
)
}
@Test
def
check16to4le
{
resize
(
16
,
4
,
true
)
}
@Test
def
check16to4be
{
resize
(
16
,
4
,
false
)
}
@Test
def
check16to8le
{
resize
(
16
,
8
,
true
)
}
@Test
def
check16to8be
{
resize
(
16
,
8
,
false
)
}
@Test
def
check32to8le
{
resize
(
32
,
8
,
true
)
}
@Test
def
check32to8be
{
resize
(
32
,
8
,
false
)
}
@Test
def
check64ot8le
{
resize
(
64
,
8
,
true
)
}
@Test
def
check64to8be
{
resize
(
64
,
8
,
false
)
}
@Test
def
check64ot32le
{
resize
(
64
,
32
,
true
)
}
@Test
def
check64to32be
{
resize
(
64
,
32
,
false
)
}
"
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
@Test
def
check1to2le
{
resize
(
1
,
2
,
true
)
}
@Test
def
check1to2be
{
resize
(
1
,
2
,
false
)
}
@Test
def
check1to8le
{
resize
(
1
,
8
,
true
)
}
@Test
def
check1to8be
{
resize
(
1
,
8
,
false
)
}
@Test
def
check4to16le
{
resize
(
4
,
16
,
true
)
}
@Test
def
check4to16be
{
resize
(
4
,
16
,
false
)
}
@Test
def
check8to16le
{
resize
(
8
,
16
,
true
)
}
@Test
def
check8to16be
{
resize
(
8
,
16
,
false
)
}
@Test
def
check8to32le
{
resize
(
8
,
32
,
true
)
}
@Test
def
check8to32be
{
resize
(
8
,
32
,
false
)
}
@Test
def
check8ot64le
{
resize
(
8
,
64
,
true
)
}
@Test
def
check8to64be
{
resize
(
8
,
64
,
false
)
}
@Test
def
check32ot64le
{
resize
(
32
,
64
,
true
)
}
@Test
def
check32to64be
{
resize
(
32
,
64
,
false
)
}
"
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/DataWidthConverterSuiteFullSpeed.scala
View file @
48cb64c9
package
chisel.miscutils
import
Chisel._
import
org.scalatest.junit.JUnitSuite
import
org.junit.Test
import
org.junit.Assert._
import
scala.math._
import
java.nio.file.Paths
import
chisel3._
import
chisel3.util._
import
chisel3.iotesters.
{
ChiselFlatSpec
,
Driver
,
PeekPokeTester
}
import
scala.math._
import
java.nio.file.Paths
/**
* DataWidthConverterHarness: Correctness test harness.
...
...
@@ -14,17 +13,40 @@ import java.nio.file.Paths
* the length of the delay is 2 * in/out-width-ratio).
**/
class
DataWidthConverterHarnessFullSpeed
(
val
inWidth
:
Int
,
val
outWidth
:
Int
,
val
littleEndian
:
Boolean
)
extends
Module
{
val
io
=
new
Bundle
val
io
=
IO
(
new
Bundle
{
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
(
width
=
inWidth
),
Seq
(
Seq
(
pow
(
2
,
inWidth
).
toLong
,
dwc
.
ratio
).
max
,
100
00.
toLong
).
min
.
toInt
,
val
dsrc
=
Module
(
new
DecoupledDataSource
(
UInt
(
inWidth
.
W
),
Seq
(
Seq
(
pow
(
2
,
inWidth
).
toLong
,
dwc
.
ratio
).
max
,
5
00.
toLong
).
min
.
toInt
,
//n => UInt(n % pow(2, inWidth).toInt + 1, width = inWidth),
n
=>
UInt
(
(
scala
.
math
.
random
*
pow
(
2
,
inWidth
)).
toLong
,
width
=
inWidth
)
,
n
=>
(
scala
.
math
.
random
*
pow
(
2
,
inWidth
)).
toLong
.
U
,
repeat
=
false
))
val
dwc2
=
Module
(
new
DataWidthConverter
(
outWidth
,
inWidth
,
littleEndian
))
dwc
.
io
.
inq
<>
dsrc
.
io
.
out
dwc2
.
io
.
inq
<>
dwc
.
io
.
deq
dwc2
.
io
.
deq
.
ready
:=
!
reset
// 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