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
03be2246
Commit
03be2246
authored
Aug 25, 2017
by
Jens Korinth
Browse files
!WIP! still working on fixing Axi
parent
8f2faf2e
Changes
12
Hide whitespace changes
Inline
Side-by-side
build.sbt
View file @
03be2246
...
...
@@ -19,9 +19,9 @@ libraryDependencies ++= (Seq("chisel3","chisel-iotesters").map {
dep
:
String
=>
"edu.berkeley.cs"
%%
dep
%
sys
.
props
.
getOrElse
(
dep
+
"Version"
,
defaultVersions
(
dep
))
})
libraryDependencies
++=
Seq
(
"
com.novocode
"
%
"
junit-interface"
%
"0.11
"
%
"test"
,
"org.scala
test
"
%%
"scala
test"
%
"2.2.6
"
%
"test"
,
"com.typesafe.play"
%%
"play-json"
%
"2.
4.8
"
"
org.scalatest
"
%
%
"
scalatest"
%
"3.0.4
"
%
"test"
,
"org.scala
check
"
%%
"scala
check"
%
"1.13.5
"
%
"test"
,
"com.typesafe.play"
%%
"play-json"
%
"2.
6.3
"
)
scalacOptions
++=
Seq
(
"-language:implicitConversions"
,
"-language:reflectiveCalls"
,
"-deprecation"
,
"-feature"
)
...
...
@@ -32,5 +32,5 @@ lazy val packaging = project.in(file("packaging"))
lazy
val
miscutils
=
project
.
in
(
file
(
"miscutils"
))
lazy
val
root
=
(
project
in
file
(
"."
)).
dependsOn
(
packaging
,
miscutils
)
lazy
val
root
=
(
project
in
file
(
"."
)).
dependsOn
(
packaging
,
miscutils
,
miscutils
%
"test->test"
)
src/main/scala/AxiModuleBuilder.scala
View file @
03be2246
package
chisel.axiutils
import
chisel.axiutils.registers._
import
chisel.packaging.
{
CoreDefinition
,
ModuleBuilder
}
import
chisel.packaging.CoreDefinition.root
import
chisel.packaging._
,
chisel
.
packaging
.
CoreDefinition
.
root
import
chisel.miscutils.DecoupledDataSource
import
scala.sys.process._
import
java.nio.file.Paths
...
...
@@ -35,10 +34,22 @@ object AxiModuleBuilder extends ModuleBuilder {
DataWidth
(
64
),
IdWidth
(
1
))
implicit
val
axilite
=
Axi4Lite
.
Configuration
(
AddrWidth
(
32
),
Axi4Lite
.
Width64
)
Axi4Lite
.
Width32
)
val
exampleRegisterFile
=
new
Axi4LiteRegisterFileConfiguration
(
addrGranularity
=
8
,
regs
=
Map
(
0
->
new
ConstantRegister
(
value
=
BigInt
(
"10101010"
,
16
)),
4
->
new
ConstantRegister
(
value
=
BigInt
(
"20202020"
,
16
)),
8
->
new
ConstantRegister
(
value
=
BigInt
(
"30303030"
,
16
)),
16
->
new
ConstantRegister
(
value
=
BigInt
(
"40404040"
,
16
),
bitfield
=
Map
(
"Byte #3"
->
BitRange
(
31
,
24
),
"Byte #2"
->
BitRange
(
23
,
16
),
"Byte #1"
->
BitRange
(
15
,
8
),
"Byte #0"
->
BitRange
(
7
,
0
)
))
))(
Axi4Lite
.
Configuration
(
AddrWidth
(
32
),
Axi4Lite
.
Width32
))
val
modules
:
List
[(()
=>
Module
,
CoreDefinition
)]
=
List
(
(
// test module with fixed data
val
modules
:
Seq
[
ModuleDef
]
=
Seq
(
ModuleDef
(
// test module with fixed data
None
,
()
=>
new
FifoAxiAdapterTest1
(
dataWidth
=
32
,
256
),
CoreDefinition
(
name
=
"FifoAxiAdapterTest1"
,
...
...
@@ -48,7 +59,8 @@ object AxiModuleBuilder extends ModuleBuilder {
root
=
Paths
.
get
(
"."
).
toAbsolutePath
.
resolve
(
"ip"
).
resolve
(
"FifoAxiAdapterTest1"
).
toString
)
),
(
// generic adapter module FIFO -> AXI
ModuleDef
(
// generic adapter module FIFO -> AXI
None
,
()
=>
new
FifoAxiAdapter
(
fifoDepth
=
8
),
CoreDefinition
(
name
=
"FifoAxiAdapter"
,
...
...
@@ -58,7 +70,8 @@ object AxiModuleBuilder extends ModuleBuilder {
root
=
Paths
.
get
(
"."
).
toAbsolutePath
.
resolve
(
"ip"
).
resolve
(
"FifoAxiAdapter"
).
toString
)
),
(
// generic adapter module AXI -> FIFO
ModuleDef
(
// generic adapter module AXI -> FIFO
None
,
()
=>
AxiFifoAdapter
(
fifoDepth
=
4
)
(
Axi4
.
Configuration
(
addrWidth
=
AddrWidth
(
32
),
dataWidth
=
DataWidth
(
32
),
...
...
@@ -71,7 +84,8 @@ object AxiModuleBuilder extends ModuleBuilder {
root
=
Paths
.
get
(
"."
).
toAbsolutePath
.
resolve
(
"ip"
).
resolve
(
"AxiFifoAdapter"
).
toString
)
),
(
// AXI-based sliding window
ModuleDef
(
// AXI-based sliding window
None
,
()
=>
{
implicit
val
axi
=
Axi4
.
Configuration
(
AddrWidth
(
32
),
DataWidth
(
64
),
IdWidth
(
1
))
new
AxiSlidingWindow
(
AxiSlidingWindowConfiguration
(
...
...
@@ -89,7 +103,8 @@ object AxiModuleBuilder extends ModuleBuilder {
root
=
root
(
"AxiSlidingWindow"
)
)
),
(
// AXI Crossbar
ModuleDef
(
// AXI Crossbar
None
,
()
=>
new
AxiMux
(
8
),
CoreDefinition
(
name
=
"AxiMux"
,
...
...
@@ -99,50 +114,20 @@ object AxiModuleBuilder extends ModuleBuilder {
root
=
root
(
"AxiMux"
)
)
),
(
// AXI Register File
()
=>
{
new
Axi4LiteRegisterFile
(
new
Axi4LiteRegisterFileConfiguration
(
regs
=
Map
(
0
->
new
ConstantRegister
(
value
=
BigInt
(
"10101010"
,
16
)),
4
->
new
ConstantRegister
(
value
=
BigInt
(
"20202020"
,
16
)),
8
->
new
ConstantRegister
(
value
=
BigInt
(
"30303030"
,
16
)),
16
->
new
ConstantRegister
(
value
=
BigInt
(
"40404040"
,
16
),
bitfield
=
Map
(
"Byte #3"
->
BitRange
(
31
,
24
),
"Byte #2"
->
BitRange
(
23
,
16
),
"Byte #1"
->
BitRange
(
15
,
8
),
"Byte #0"
->
BitRange
(
7
,
0
)
)))
))
},
CoreDefinition
/*.withActions*/
(
ModuleDef
(
// AXI Register File
Some
(
exampleRegisterFile
),
()
=>
new
Axi4LiteRegisterFile
(
exampleRegisterFile
),
CoreDefinition
.
withActions
(
name
=
"Axi4LiteRegisterFile"
,
vendor
=
"esa.cs.tu-darmstadt.de"
,
library
=
"chisel"
,
version
=
"0.1"
,
root
=
root
(
"Axi4LiteRegisterFile"
)
/*
,
root
=
root
(
"Axi4LiteRegisterFile"
),
postBuildActions
=
Seq
(
_
match
{
case m: Axi4LiteRegisterFile => m.dumpAddressMap(root("Axi4LiteRegisterFile"))
})*/
)
)
/*,
( // AXI4 Dummy
() => new chisel.axi.Dummy,
CoreDefinition(
name = "Axi4Dummy",
vendor = "esa.cs.tu-darmstadt.de",
library = "chisel",
version = "0.1",
root = root("Dummy")
)
),
( // AXI4Lite Dummy
() => new chisel.axi.Axi4Lite.Dummy,
CoreDefinition(
name = "Axi4LiteDummy",
vendor = "esa.cs.tu-darmstadt.de",
library = "chisel",
version = "0.1",
root = root("Dummy")
case
Some
(
cfg
:
Axi4LiteRegisterFileConfiguration
)
=>
cfg
.
dumpAddressMap
(
root
(
"Axi4LiteRegisterFile"
))
case
_
=>
()
})
)
)
*/
)
)
}
src/main/scala/axi/Axi4.scala
View file @
03be2246
...
...
@@ -142,11 +142,11 @@ object Axi4 {
}
class
Master
private
(
implicit
cfg
:
Configuration
)
extends
Bundle
{
val
writeAddr
=
Decoup
le
d
(
new
Address
)
val
writeData
=
Decoup
le
d
(
new
Data
.
Write
)
val
writeResp
=
Flipped
(
Decoup
le
d
(
new
WriteResponse
))
val
readAddr
=
Decoup
le
d
(
new
Address
)
val
readData
=
Flipped
(
Decoup
le
d
(
new
Data
.
Read
))
val
writeAddr
=
Irrevocab
le
(
new
Address
)
val
writeData
=
Irrevocab
le
(
new
Data
.
Write
)
val
writeResp
=
Flipped
(
Irrevocab
le
(
new
WriteResponse
))
val
readAddr
=
Irrevocab
le
(
new
Address
)
val
readData
=
Flipped
(
Irrevocab
le
(
new
Data
.
Read
))
override
def
cloneType
=
{
new
Master
()(
cfg
).
asInstanceOf
[
this.
type
]
}
}
...
...
src/main/scala/axi/Axi4Lite.scala
View file @
03be2246
...
...
@@ -50,11 +50,11 @@ object Axi4Lite {
}
class
Master
private
(
implicit
cfg
:
Configuration
)
extends
Bundle
{
val
writeAddr
=
Decoup
le
d
(
new
Address
)
val
writeData
=
Decoup
le
d
(
new
Data
.
Write
)
val
writeResp
=
Flipped
(
Decoup
le
d
(
new
WriteResponse
))
val
readAddr
=
Decoup
le
d
(
new
Address
)
val
readData
=
Flipped
(
Decoup
le
d
(
new
Data
.
Read
))
val
writeAddr
=
Irrevocab
le
(
new
Address
)
val
writeData
=
Irrevocab
le
(
new
Data
.
Write
)
val
writeResp
=
Flipped
(
Irrevocab
le
(
new
WriteResponse
))
val
readAddr
=
Irrevocab
le
(
new
Address
)
val
readData
=
Flipped
(
Irrevocab
le
(
new
Data
.
Read
))
override
def
cloneType
=
{
new
Master
()(
cfg
).
asInstanceOf
[
this.
type
]
}
}
...
...
src/main/scala/registers/RegisterFile.scala
View file @
03be2246
...
...
@@ -25,6 +25,20 @@ case class Axi4LiteRegisterFileConfiguration(addrGranularity: Int = 32, regs: Ma
/** Minimum bit width of address lines. */
lazy
val
minAddrWidth
:
AddrWidth
=
AddrWidth
(
Seq
(
log2Ceil
(
regs
.
size
*
axi
.
dataWidth
.
toInt
/
addrGranularity
),
log2Ceil
(
regs
.
keys
.
max
)).
max
)
/** Dumps address map as markdown file. **/
def
dumpAddressMap
(
path
:
String
)
=
{
def
mksz
(
s
:
String
,
w
:
Int
)
=
if
(
s
.
length
>
w
)
s
.
take
(
w
)
else
if
(
s
.
length
<
w
)
s
+
(
" "
*
(
w
-
s
.
length
))
else
s
val
fw
=
new
java
.
io
.
FileWriter
(
java
.
nio
.
file
.
Paths
.
get
(
path
).
resolve
(
"AdressMap.md"
).
toString
)
fw
.
append
(
"| **Name** |**From**|**To** | **Description** |"
).
append
(
NL
)
.
append
(
"|:----------------|:------:|:------:|:-----------------------------------------|"
).
append
(
NL
)
for
(
off
<-
regs
.
keys
.
toList
.
sorted
;
reg
=
regs
(
off
))
fw
.
append
(
"| %s | 0x%04x | 0x%04x | %s |"
.
format
(
mksz
(
reg
.
name
.
getOrElse
(
"N/A"
),
15
),
off
,
off
+
axi
.
dataWidth
/
8
-
1
,
reg
.
description
)).
append
(
NL
)
fw
.
flush
()
fw
.
close
}
}
/**
...
...
@@ -45,20 +59,6 @@ class Axi4LiteRegisterFileIO(cfg: Axi4LiteRegisterFileConfiguration)(implicit ax
* @param axi Implicit AXI configuration.
**/
class
Axi4LiteRegisterFile
(
cfg
:
Axi4LiteRegisterFileConfiguration
)(
implicit
axi
:
Configuration
)
extends
Module
{
/** Dumps address map as markdown file. **/
def
dumpAddressMap
(
path
:
String
)
=
{
def
mksz
(
s
:
String
,
w
:
Int
)
=
if
(
s
.
length
>
w
)
s
.
take
(
w
)
else
if
(
s
.
length
<
w
)
s
+
(
" "
*
(
w
-
s
.
length
))
else
s
val
fw
=
new
java
.
io
.
FileWriter
(
java
.
nio
.
file
.
Paths
.
get
(
path
).
resolve
(
"AdressMap.md"
).
toString
)
fw
.
append
(
"| **Name** |**From**|**To** | **Description** |"
).
append
(
NL
)
.
append
(
"|:----------------|:------:|:------:|:-----------------------------------------|"
).
append
(
NL
)
for
(
off
<-
cfg
.
regs
.
keys
.
toList
.
sorted
;
reg
=
cfg
.
regs
(
off
))
fw
.
append
(
"| %s | 0x%04x | 0x%04x | %s |"
.
format
(
mksz
(
reg
.
name
.
getOrElse
(
"N/A"
),
15
),
off
,
off
+
axi
.
dataWidth
/
8
-
1
,
reg
.
description
)).
append
(
NL
)
fw
.
flush
()
fw
.
close
}
/** HARDWARE **/
val
io
=
IO
(
new
Axi4LiteRegisterFileIO
(
cfg
))
...
...
src/main/scala/registers/Registers.scala
View file @
03be2246
...
...
@@ -17,7 +17,7 @@ sealed abstract class ControlRegister(_name: Option[String], bitfield: BitfieldM
def
name
:
Option
[
String
]
=
_name
/** Description of the register. */
def
description
:
String
=
if
(
bitfield
.
size
>
0
)
bf
else
_name
.
getOrElse
(
"
N/A
"
)
def
description
:
String
=
if
(
bitfield
.
size
>
0
)
bf
else
_name
.
getOrElse
(
"
Reserved
"
)
/** Access to named bit range. */
def
apply
(
s
:
String
)
:
Option
[
UInt
]
=
read
()
map
{
v
=>
...
...
src/test/scala/Axi2AxiSuite.scala
View file @
03be2246
...
...
@@ -16,22 +16,25 @@ class Axi2AxiModule(val fifoDepth: Int = 16, val size: Option[Int])
(
implicit
axi
:
Axi4.Configuration
)
extends
Module
{
require
(
size
.
isEmpty
||
log2Ceil
(
size
.
get
)
<=
axi
.
addrWidth
,
"size (%d) elements cannot be addressed by %d address bits"
.
format
(
size
.
get
,
axi
.
addrWidth
))
"size (%d) elements cannot be addressed by %d address bits"
.
format
(
size
.
get
,
axi
.
addrWidth
:
Int
))
val
io
=
IO
(
new
Bundle
{
val
deq
=
Decoupled
(
UInt
(
axi
.
dataWidth
))
})
val
sz
=
size
.
getOrElse
(
pow
(
2
,
axi
.
addrWidth
.
toDouble
).
toInt
)
val
sz
=
size
.
getOrElse
(
pow
(
2
,
axi
.
addrWidth
.
toDouble
).
toInt
/
axi
.
dataWidth
)
val
aw
=
Seq
(
axi
.
addrWidth
:
Int
,
log2Ceil
(
sz
*
(
axi
.
dataWidth
/
8
))).
min
println
(
"Axi2AxiModule: address bits = %d, size = %d"
.
format
(
aw
,
sz
))
val
cfg
=
AxiSlaveModelConfiguration
()
val
data
=
0
to
sz
map
(
n
=>
n
%
pow
(
2
,
axi
.
dataWidth
:
Int
).
toInt
)
val
dsrc
=
Module
(
new
DecoupledDataSource
(
gen
=
UInt
(
axi
.
dataWidth
),
size
=
sz
,
//data = n => UInt((random * pow(2, axi.dataWidth)).toInt),
data
=
n
=>
(
n
%
pow
(
2
,
axi
.
dataWidth
:
Int
).
toInt
).
U
,
//data = n => (n % pow(2, axi.dataWidth:Int).toInt).U,
data
=
data
map
(
_
.
U
),
repeat
=
false
))
val
fad
=
Module
(
new
FifoAxiAdapter
(
fifoDepth
=
sz
,
burstSize
=
Some
(
fifoDepth
)))
...
...
@@ -45,7 +48,7 @@ class Axi2AxiModule(val fifoDepth: Int = 16, val size: Option[Int])
saxi
.
io
.
saxi
.
writeResp
<>
fad
.
io
.
maxi
.
writeResp
saxi
.
io
.
saxi
.
readAddr
<>
afa
.
io
.
maxi
.
readAddr
saxi
.
io
.
saxi
.
readData
<>
afa
.
io
.
maxi
.
readData
afa
.
reset
:=
dsrc
.
io
.
out
.
valid
||
fad
.
fifo
.
io
.
count
>
0.
U
//
afa.reset := dsrc.io.out.valid || fad.fifo.io.count > 0.U
fad
.
io
.
base
:=
base
afa
.
io
.
base
:=
base
io
.
deq
<>
afa
.
io
.
deq
...
...
@@ -60,7 +63,7 @@ class Axi2AxiModule(val fifoDepth: Int = 16, val size: Option[Int])
class
Axi2AxiTester
(
m
:
Axi2AxiModule
)
(
implicit
axi
:
Axi4.Configuration
)
extends
PeekPokeTester
(
m
)
{
def
toBinaryString
(
v
:
BigInt
)
:
String
=
"b%%%ds"
.
format
(
axi
.
dataWidth
).
format
(
v
.
toString
(
2
)).
replace
(
' '
,
'0'
)
"b%%%ds"
.
format
(
axi
.
dataWidth
:
Int
).
format
(
v
.
toString
(
2
)).
replace
(
' '
,
'0'
)
private
val
O
=
10000
private
var
cc
=
0
private
var
ccc
=
O
...
...
@@ -79,7 +82,7 @@ class Axi2AxiTester(m: Axi2AxiModule)
for
(
i
<-
0
until
m
.
sz
)
{
while
(
peek
(
m
.
io
.
deq
.
valid
)
==
0
)
step
(
1
)
val
v
=
peek
(
m
.
io
.
deq
.
bits
)
val
e
=
m
.
dsrc
.
data
(
i
)
val
e
=
m
.
data
(
i
)
expect
(
v
==
e
,
"mem[%08d] = %d (%s), expected: %d (%s)"
.
format
(
i
,
v
,
toBinaryString
(
v
),
e
,
toBinaryString
(
e
)))
step
(
1
)
// advance sim
...
...
@@ -94,7 +97,7 @@ class Axi2AxiSuite extends ChiselFlatSpec {
def
run
(
size
:
Int
,
fifoDepth
:
Int
,
addrWidth
:
Int
,
dataWidth
:
Int
)
{
implicit
val
axi
=
Axi4
.
Configuration
(
addrWidth
=
AddrWidth
(
addrWidth
),
dataWidth
=
DataWidth
(
dataWidth
))
val
dir
=
Paths
.
get
(
"test"
)
.
resolve
(
"s%d_aw%d_dw%d"
.
format
(
size
,
addrWidth
,
axi
.
dataWidth
))
.
resolve
(
"s%d_aw%d_dw%d"
.
format
(
size
,
addrWidth
,
axi
.
dataWidth
:
Int
))
.
toString
Driver
.
execute
(
Array
(
"--fint-write-vcd"
,
"--target-dir"
,
dir
),
()
=>
new
Axi2AxiModule
(
fifoDepth
=
fifoDepth
,
...
...
src/test/scala/AxiFifoAdapterSuite.scala
View file @
03be2246
package
chisel.axiutils
import
chisel
3
._
import
chisel3.util._
import
chisel
.miscutils.generators
._
import
chisel3._
,
chisel3
.
util
.
_
import
chisel3.iotesters.
{
ChiselFlatSpec
,
Driver
,
PeekPokeTester
}
import
java.nio.file.Paths
import
chisel.axi._
import
org.scalacheck._
,
org
.
scalacheck
.
Prop
.
_
import
org.scalatest.prop.Checkers
class
AxiFifoAdapterModule1
(
val
fifoDepth
:
Int
,
val
blockSize
:
Int
)
(
implicit
axi
:
Axi4.Configuration
)
extends
Module
{
val
addrWidth
=
log2Ceil
(
axi
.
dataWidth
*
fifoDepth
*
blockSize
/
8
)
val
addrWidth
=
Seq
(
log2Ceil
(
axi
.
dataWidth
*
fifoDepth
*
blockSize
/
8
)
,
1
).
max
val
cfg
=
AxiSlaveModelConfiguration
(
size
=
Some
(
Math
.
pow
(
2
,
addrWidth
:
Int
).
toInt
))
val
saxi
=
Module
(
new
AxiSlaveModel
(
cfg
))
val
io
=
IO
(
new
Bundle
{
val
dqr
=
Output
(
Bool
())
val
afa_en
=
Input
(
Bool
())
val
afa_deq_valid
=
Output
(
Bool
())
val
afa_deq_bits
=
Output
(
UInt
(
axi
.
dataWidth
))
val
saxi_debug
=
saxi
.
io
.
debug
.
cloneType
})
val
afa
=
Module
(
AxiFifoAdapter
(
fifoDepth
=
fifoDepth
))
val
saxi
=
Module
(
new
AxiSlaveModel
(
cfg
))
val
dqr
=
RegInit
(
true
.
B
)
afa
.
io
.
base
:=
0.
U
...
...
@@ -25,11 +29,11 @@ class AxiFifoAdapterModule1(val fifoDepth: Int, val blockSize: Int)
dqr
:=
io
.
dqr
io
.
afa_deq_valid
:=
afa
.
io
.
deq
.
valid
io
.
afa_deq_bits
:=
afa
.
io
.
deq
.
bits
io
.
saxi_debug
<>
saxi
.
io
.
debug
}
class
AxiFifoAdapterModule1Test
(
m
:
AxiFifoAdapterModule1
)
(
implicit
axi
:
Axi4.Configuration
)
extends
PeekPokeTester
(
m
)
{
import
scala.util.Properties.
{
lineSeparator
=>
NL
}
private
var
_cc
=
0
// re-define step to output progress info
...
...
@@ -39,15 +43,27 @@ class AxiFifoAdapterModule1Test(m: AxiFifoAdapterModule1)
if
(
cc
%
1000
==
0
)
println
(
"clock cycle: "
+
_cc
)
}
poke
(
m
.
io
.
afa_en
,
false
.
B
)
reset
(
10
)
// setup data
println
(
"prepping %d (%d x %d) mem elements ..."
.
format
(
m
.
fifoDepth
*
m
.
blockSize
,
m
.
fifoDepth
,
m
.
blockSize
))
for
(
i
<-
0
until
m
.
fifoDepth
*
m
.
blockSize
)
pokeAt
(
m
.
saxi
.
mem
,
i
%
scala
.
math
.
pow
(
2
,
axi
.
dataWidth
:
Int
).
toInt
,
i
)
poke
(
m
.
io
.
saxi_debug
.
r
,
false
.
B
)
poke
(
m
.
io
.
saxi_debug
.
ra
,
0
)
poke
(
m
.
io
.
saxi_debug
.
w
,
true
.
B
)
for
(
i
<-
0
until
m
.
fifoDepth
*
m
.
blockSize
)
{
poke
(
m
.
io
.
saxi_debug
.
wa
,
i
%
math
.
pow
(
2
,
axi
.
dataWidth
:
Int
).
toInt
)
poke
(
m
.
io
.
saxi_debug
.
din
,
i
)
step
(
1
)
//pokeAt(m.saxi.mem, i % scala.math.pow(2, axi.dataWidth:Int).toInt, i)
}
poke
(
m
.
io
.
saxi_debug
.
w
,
false
.
B
)
poke
(
m
.
io
.
saxi_debug
.
r
,
false
.
B
)
poke
(
m
.
io
.
afa_en
,
true
.
B
)
var
res
:
List
[
BigInt
]
=
List
()
var
cc
:
Int
=
m
.
fifoDepth
*
m
.
blockSize
*
10
// upper bound on cycles
reset
(
10
)
poke
(
m
.
io
.
dqr
,
true
)
while
(
cc
>
0
&&
res
.
length
<
m
.
fifoDepth
*
m
.
blockSize
)
{
if
(
peek
(
m
.
io
.
afa_deq_valid
)
!=
0
)
{
...
...
@@ -66,15 +82,20 @@ class AxiFifoAdapterModule1Test(m: AxiFifoAdapterModule1)
println
(
"#%d: 0x%x (0b%s)"
.
format
(
i
,
v
,
v
.
toString
(
2
)))
})
for
(
i
<-
0
until
res
.
length
if
res
(
i
)
!=
peekAt
(
m
.
saxi
.
mem
,
i
))
{
val
msg
=
"Mem[%03d] = %d (expected %d)"
.
format
(
i
,
res
(
i
),
peekAt
(
m
.
saxi
.
mem
,
i
))
poke
(
m
.
io
.
saxi_debug
.
r
,
true
.
B
)
step
(
1
)
for
(
i
<-
0
until
res
.
length
/*if res(i) != peekAt(m.saxi.mem, i)*/
)
{
poke
(
m
.
io
.
saxi_debug
.
ra
,
i
)
step
(
1
)
val
v
=
peek
(
m
.
io
.
saxi_debug
.
dout
)
val
msg
=
"Mem[%03d] = %d (expected %d)"
.
format
(
i
,
res
(
i
),
v
)
println
(
msg
)
expect
(
res
(
i
)
==
peekAt
(
m
.
saxi
.
mem
,
i
),
msg
)
expect
(
res
(
i
)
==
v
/*
peekAt(m.saxi.mem, i)
*/
,
msg
)
}
}
class
AxiFifoAdapterSuite
extends
ChiselFlatSpec
{
def
runTest
(
dataWidth
:
Int
,
fifoDepth
:
Int
,
blockSize
:
Int
)
{
class
AxiFifoAdapterSuite
extends
ChiselFlatSpec
with
Checkers
{
def
runTest
(
dataWidth
:
Int
,
fifoDepth
:
Int
,
blockSize
:
Int
)
:
Boolean
=
{
val
dir
=
Paths
.
get
(
"test"
).
resolve
(
"dw%d_fd%d_bs%d"
.
format
(
dataWidth
,
fifoDepth
,
blockSize
)).
toString
implicit
val
axi
=
Axi4
.
Configuration
(
dataWidth
=
DataWidth
(
dataWidth
),
addrWidth
=
AddrWidth
(
32
))
Driver
.
execute
(
Array
(
"--fint-write-vcd"
,
"--target-dir"
,
dir
),
...
...
@@ -82,13 +103,21 @@ class AxiFifoAdapterSuite extends ChiselFlatSpec {
{
m
=>
new
AxiFifoAdapterModule1Test
(
m
)
}
}
"checkDw32Fd1Bs256"
should
"be ok"
in
{
runTest
(
dataWidth
=
32
,
fifoDepth
=
1
,
blockSize
=
256
/
1
)
}
"checkDw32Fd8Bs32"
should
"be ok"
in
{
runTest
(
dataWidth
=
32
,
fifoDepth
=
8
,
blockSize
=
256
/
8
)
}
behavior
of
"AxiFifoAdapter"
/*it should "read data in correct order for arbitrary configurations" in
check(forAll(bitWidthGen(128), genLimited(1, 8) map (1 << _)) { case (bw, fd) =>
println("Testing with %d bit and %d FIFO depth".format(bw:Int, fd:Int))
runTest(bw, fd, 256)
})*/
it
should
"be ok"
in
{
runTest
(
dataWidth
=
32
,
fifoDepth
=
1
,
blockSize
=
256
/
1
)
}
/*"checkDw32Fd8Bs32" should "be ok" in { runTest(dataWidth = 32, fifoDepth = 8, blockSize = 256/8) }
"checkDw8Fd8Bs32" should "be ok" in { runTest(dataWidth = 8, fifoDepth = 8, blockSize = 256/8) }
"checkDw8Fd2Bs128" should "be ok" in { runTest(dataWidth = 8, fifoDepth = 2, blockSize = 256/2) }
"checkDw64Fd16Bs512" should "be ok" in { runTest(dataWidth = 64, fifoDepth = 16, blockSize = 512) }
"checkDw128Fd128Bs1024" should "be ok" in { runTest(dataWidth = 128, fifoDepth = 128, blockSize = 1024/128) }
// FIXME seems to work, but too slow
// "checkDw8Fd1080Bs480" should "be ok" in { runTest(dataWidth = 8, fifoDepth = 256, blockSize = 480*4) }
// "checkDw8Fd1080Bs480" should "be ok" in { runTest(dataWidth = 8, fifoDepth = 256, blockSize = 480*4) }
*/
}
src/test/scala/AxiSlaveModel.scala
View file @
03be2246
package
chisel.axiutils
import
chisel3._
import
chisel3.util._
import
chisel3._
,
chisel3
.
util
.
_
import
chisel3.iotesters.
{
PeekPokeTester
}
import
chisel.axi._
class
DebugIO
(
implicit
axi
:
Axi4.Configuration
)
extends
Bundle
{
val
ra
=
Input
(
UInt
(
axi
.
addrWidth
))
val
r
=
Input
(
Bool
())
val
dout
=
Output
(
UInt
(
axi
.
dataWidth
))
val
wa
=
Input
(
UInt
(
axi
.
addrWidth
))
val
w
=
Input
(
Bool
())
val
din
=
Input
(
UInt
(
axi
.
dataWidth
))
override
def
cloneType
=
{
new
DebugIO
()(
axi
).
asInstanceOf
[
this.
type
]
}
}
class
AxiSlaveModelIO
(
val
cfg
:
AxiSlaveModelConfiguration
)
(
implicit
axi
:
Axi4.Configuration
)
extends
Bundle
{
val
saxi
=
Axi4
.
Slave
(
axi
)
val
saxi
=
Axi4
.
Slave
(
axi
)
val
debug
=
new
DebugIO
override
def
cloneType
=
{
new
AxiSlaveModelIO
(
cfg
)(
axi
).
asInstanceOf
[
this.
type
]
}
}
class
AxiSlaveModel
(
val
cfg
:
AxiSlaveModelConfiguration
)
...
...
@@ -15,7 +28,21 @@ class AxiSlaveModel(val cfg: AxiSlaveModelConfiguration)
println
(
"AxiSlaveModel: %s"
.
format
(
cfg
.
toString
))
val
io
=
IO
(
new
AxiSlaveModelIO
(
cfg
))
val
mem
=
Mem
(
sz
,
UInt
(
axi
.
dataWidth
))
val
mem
=
SyncReadMem
(
sz
,
UInt
(
axi
.
dataWidth
))
/** DEBUG PROCESS **/
val
d_read
=
io
.
debug
.
r
val
d_write
=
RegNext
(
io
.
debug
.
w
)
val
d_waddr
=
RegNext
(
io
.
debug
.
wa
)
val
d_raddr
=
RegNext
(
io
.
debug
.
ra
)
val
d_din
=
RegNext
(
io
.
debug
.
din
)
d_din
:=
io
.
debug
.
din
when
(
d_read
)
{
io
.
debug
.
dout
:=
mem
.
read
(
d_raddr
)
}
when
(
d_write
)
{
mem
.
write
(
d_waddr
,
d_din
)
}
/** WRITE PROCESS **/
val
wa_valid
=
(
io
.
saxi
.
writeAddr
.
valid
)
...
...
@@ -49,7 +76,8 @@ class AxiSlaveModel(val cfg: AxiSlaveModelConfiguration)
require
(
idx
>=
0
&&
idx
<
cfg
.
size
,
"AxiSlaveModel: read at invalid index %d (max: %d) for address 0x%x"
.
format
(
idx
,
cfg
.
size
-
1
,
address
))
t
.
peekAt
(
mem
,
address
/
(
axi
.
dataWidth
/
8
))
//t.peekAt(mem, address / (axi.dataWidth / 8))
BigInt
(
0
)
}
/**
...
...
@@ -62,7 +90,8 @@ class AxiSlaveModel(val cfg: AxiSlaveModelConfiguration)
require
(
index
>=
0
&&
index
<
cfg
.
size
,
"AxiSlaveModel: read at invalid index %d (max: %d)"
.
format
(
index
,
cfg
.
size
-
1
))
t
.
peekAt
(
mem
,
index
)
//t.peekAt(mem, index)
BigInt
(
0
)
}
/**
...
...
@@ -74,7 +103,7 @@ class AxiSlaveModel(val cfg: AxiSlaveModelConfiguration)
def
set
(
address
:
Int
,
value
:
BigInt
)(
implicit
t
:
PeekPokeTester
[
_
])
=
{
val
idx
=
address
/
(
axi
.
dataWidth
/
8
)
printf
(
"AxiSlaveModel: set data at 0x%x (idx: %d) to 0x%x"
.
format
(
address
,
value
,
idx
))
t
.
pokeAt
(
mem
,
value
,
idx
)
//
t.pokeAt(mem, value, idx)
}
io
.
saxi
.
writeAddr
.
ready
:=
!
wa_hs
...
...
@@ -106,7 +135,8 @@ class AxiSlaveModel(val cfg: AxiSlaveModelConfiguration)
when
(
wa_hs
&&
wr_wait
===
0.
U
)
{
when
(
wa_hs
&&
wd_valid
&&
!
wr_valid
)
{
val
shifted_addr
=
if
(
axi
.
dataWidth
>
8
)
wa
>>
log2Ceil
(
axi
.
dataWidth
/
8
).
U
else
wa
mem
(
shifted_addr
)
:=
wd_data
//mem(shifted_addr) := wd_data
mem
.
write
(
shifted_addr
,
wd_data
)
printf
(
"writing data 0x%x to address 0x%x (0x%x)\n"
,
wd_data
,
wa
,
shifted_addr
)
when
(
io
.
saxi
.
writeData
.
bits
.
last
||
wl
===
0.
U
)
{
wr_valid
:=
true
.
B
}
.
otherwise
{
...
...
@@ -143,7 +173,7 @@ class AxiSlaveModel(val cfg: AxiSlaveModelConfiguration)
val
rd_valid
=
ra_hs
&&
rr_wait
===
0.
U
io
.
saxi
.
readData
.
valid
:=
rd_valid
io
.
saxi
.
readData
.
bits
.
data
:=
mem
(
if
(
axi
.
dataWidth
>
8
)
ra
>>
(
log2Ceil
(
axi
.
dataWidth
/
8
)).
U
else
ra
)
io
.
saxi
.
readData
.
bits
.
data
:=
mem
.
read
(
if
(
axi
.
dataWidth
>
8
)
ra
>>
(
Seq
(
log2Ceil
(
axi
.
dataWidth
/
8
)
,
1
).
max
).
U
else
ra
)
io
.
saxi
.
readData
.
bits
.
last
:=
ra_hs
&&
l
===
0.
U
io
.
saxi
.
readData
.
bits
.
resp
:=
rr_resp
...
...
src/test/scala/AxiSlaveModelConfiguration.scala
View file @
03be2246
...
...
@@ -36,7 +36,7 @@ object AxiSlaveModelConfiguration {
**/
def
apply
(
size
:
Option
[
Int
]
=
None
,
readDelay
:
Int
=
30
,
writeDelay
:
Int
=
120
)
(
implicit
axi
:
Axi4.Configuration
)
=
{
val
sz
:
Int
=
size
.
getOrElse
(
scala
.
math
.
pow
(
2
,
axi
.
addrWidth
.
ge
t
).
toInt
)
val
sz
:
Int
=
size
.
getOrElse
(
scala
.
math
.
pow
(
2
,
axi
.
addrWidth
:
In
t
).
toInt
/
axi
.
dataWidth
)
val
aw
:
Int
=
Seq
(
axi
.
addrWidth
:
Int
,
log2Ceil
(
sz
*
axi
.
dataWidth
/
8
).
toInt
).
min
new
AxiSlaveModelConfiguration
(
size
=
sz
,
readDelay
=
readDelay
,
writeDelay
=
writeDelay
)
}
...
...
src/test/scala/AxiSlaveModelDumper.scala
deleted
100644 → 0
View file @
8f2faf2e
package
chisel.axiutils
import
chisel3._
import
chisel3.iotesters.PeekPokeTester
import
chisel.axi._
/**
* Helper companion: Dump complete memory of slave into file.
**/
object
AxiSlaveModelDumper
{
/**
* Dumps the complete data of the AXI slave mode to a file.
* @param m The slave model to dump.
* @param filename Filename of dump file (paths will be created).
* @param lineWidth Number of bytes per line in file (default: 16).
* @param t Tester instance.
**/
def
writeHexDump
(
m
:
AxiSlaveModel
,
filename
:
String
,
lineWidth
:
Int
=
16
)
(
implicit
t
:
PeekPokeTester
[
_
])
{
require
(
lineWidth
>=
m
.
axi
.
dataWidth
/
8
,
"lineWidth (%d) must be >= dataWidth / 8 (%d)"
.
format
(
lineWidth
,
m
.
axi
.
dataWidth
/
8
))
require
((
lineWidth
*
8
)
%
m
.
axi
.
dataWidth
==
0
,
"lineWidth (%d) must be evenly divisible by word width (%d)"
.
format
(
lineWidth
*
8
,
m
.
axi
.
dataWidth
))
def
hexAddr
(
addr
:
Int
)
:
String
=
"%%0%dx"
.
format
(
m
.
axi
.
addrWidth
/
4
).
format
(
addr
)
def
hexByte
(
v
:
Int
)
:
String
=
"%02x "
.
format
(
v
)
def
asciiByte
(
v
:
Int
)
:
String
=
"%c"
.
format
(
v
)
take
1
def
toBytes
(
v
:
BigInt
)
:
Seq
[
Int
]
=
(
for
(
i
<-
0
until
m
.
axi
.
dataWidth
/
8
)
yield
((
v
>>
(
i
*
8
))
&
0xFF
).
toInt
).
reverse
def
hexStr
(
vs
:
Seq
[
BigInt
])
:
String
=
vs
map
toBytes
reduce
(
_
++
_
)
map
hexByte
reduce
(
_
++
_
)
def
asciiStr
(
vs
:
Seq
[
BigInt
])
:
String
=
vs
map
toBytes
reduce
(
_
++
_
)
map
asciiByte
reduce
(
_
++
_
)
def
addrToIdx
(
addr
:
Int
)
:
Int
=
addr
/
(
m
.
axi
.
dataWidth
/
8
)
def
idxToAddr
(
idx
:
Int
)
:
Int
=
idx
*
(
m
.
axi
.
dataWidth
/
8
)
java
.
nio
.
file
.
Paths
.
get
(
filename
).
toAbsolutePath
.
getParent
.
toFile
.
mkdirs
()
val
fw
=
new
java
.
io
.
FileWriter
(
filename
)
val
lwords
=
(
lineWidth
*
8
/
m
.
axi
.
dataWidth
)
println
(
"m.cfg.size = %d, lwords = %d"
.
format
(
m
.
cfg
.
size
,
lwords
))
for
(
idx
<-
0
until
m
.
cfg
.
size
if
idx
%
lwords
==
0
;
words
=
for
(
i
<-
0
until
lwords
)
yield
t
.
peekAt
(
m
.
mem
,
idx
+
i
))
{
fw
.
append
(
"%s\t%s\t%s\n"
.
format
(
hexAddr
(
idxToAddr
(
idx
)),
hexStr
(
words
),
asciiStr
(
words
)))
}