Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenXiangShan
XiangShan
提交
67559d9e
X
XiangShan
项目概览
OpenXiangShan
/
XiangShan
11 个月 前同步成功
通知
1183
Star
3914
Fork
526
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
X
XiangShan
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
67559d9e
编写于
11月 06, 2020
作者:
L
LinJiawei
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'origin/master' into xs-fpu
上级
89722029
9412fdbd
变更
15
展开全部
隐藏空白更改
内联
并排
Showing
15 changed file
with
1448 addition
and
37 deletion
+1448
-37
.github/workflows/emu.yml
.github/workflows/emu.yml
+1
-1
src/main/scala/utils/ParallelMux.scala
src/main/scala/utils/ParallelMux.scala
+12
-0
src/main/scala/utils/Replacement.scala
src/main/scala/utils/Replacement.scala
+64
-0
src/main/scala/xiangshan/XSCore.scala
src/main/scala/xiangshan/XSCore.scala
+9
-2
src/main/scala/xiangshan/backend/fu/CSR.scala
src/main/scala/xiangshan/backend/fu/CSR.scala
+0
-15
src/main/scala/xiangshan/backend/fu/FunctionUnit.scala
src/main/scala/xiangshan/backend/fu/FunctionUnit.scala
+1
-1
src/main/scala/xiangshan/backend/roq/Roq.scala
src/main/scala/xiangshan/backend/roq/Roq.scala
+0
-2
src/main/scala/xiangshan/cache/L1plusCache.scala
src/main/scala/xiangshan/cache/L1plusCache.scala
+779
-0
src/main/scala/xiangshan/frontend/PreDecode.scala
src/main/scala/xiangshan/frontend/PreDecode.scala
+1
-1
src/main/scala/xiangshan/frontend/RAS.scala
src/main/scala/xiangshan/frontend/RAS.scala
+2
-2
src/main/scala/xiangshan/mem/sbuffer/NewSbuffer.scala
src/main/scala/xiangshan/mem/sbuffer/NewSbuffer.scala
+5
-2
src/test/csrc/ram.cpp
src/test/csrc/ram.cpp
+6
-7
src/test/scala/cache/L1plusCacheTest.scala
src/test/scala/cache/L1plusCacheTest.scala
+436
-0
src/test/scala/xiangshan/memend/SbufferTest.scala
src/test/scala/xiangshan/memend/SbufferTest.scala
+123
-0
src/test/vsrc/ram.v
src/test/vsrc/ram.v
+9
-4
未找到文件。
.github/workflows/emu.yml
浏览文件 @
67559d9e
...
...
@@ -3,7 +3,7 @@ name: EMU Test
on
:
push
:
branches
:
[
master
,
update-ci
,
xs-fpu
]
branches
:
[
master
,
update-ci
]
pull_request
:
branches
:
[
master
]
...
...
src/main/scala/utils/ParallelMux.scala
浏览文件 @
67559d9e
...
...
@@ -39,3 +39,15 @@ object ParallelLookUp {
ParallelMux
(
mapping
.
map
(
m
=>
(
m
.
_1
===
key
)
->
m
.
_2
))
}
}
object
ParallelMax
{
def
apply
[
T
<:
Data
](
xs
:
Seq
[
T
])
:
T
=
{
ParallelOperation
(
xs
,
(
a
:
T
,
b
:
T
)
=>
Mux
(
a
.
asUInt
()
>
b
.
asUInt
(),
a
,
b
).
asTypeOf
(
xs
.
head
))
}
}
object
ParallelMin
{
def
apply
[
T
<:
Data
](
xs
:
Seq
[
T
])
:
T
=
{
ParallelOperation
(
xs
,
(
a
:
T
,
b
:
T
)
=>
Mux
(
a
.
asUInt
()
<
b
.
asUInt
(),
a
,
b
).
asTypeOf
(
xs
.
head
))
}
}
\ No newline at end of file
src/main/scala/utils/Replacement.scala
浏览文件 @
67559d9e
...
...
@@ -76,6 +76,7 @@ class TrueLRU(n_ways: Int) {
nextState
.
zipWithIndex
.
tail
.
foldLeft
((
nextState
.
head
.
apply
(
n_ways
-
1
,
1
),
0
))
{
case
((
pe
,
pi
),(
ce
,
ci
))
=>
(
Cat
(
ce
.
apply
(
n_ways
-
1
,
ci
+
1
),
pe
),
ci
)
}.
_1
}
def
get_next_state
(
state
:
UInt
,
touch_ways
:
Seq
[
Valid
[
UInt
]])
:
UInt
=
{
touch_ways
.
foldLeft
(
state
)((
prev
,
touch_way
)
=>
Mux
(
touch_way
.
valid
,
get_next_state
(
prev
,
touch_way
.
bits
),
prev
))
}
...
...
@@ -162,3 +163,66 @@ class SeqPLRU(n_sets: Int, n_ways: Int) extends SeqReplacementPolicy {
def
way
=
plru_way
}
class
SbufferLRU
(
n_ways
:
Int
)
{
def
nBits
=
n_ways
*
n_ways
private
val
state_reg
=
RegInit
(
0.
U
(
nBits
.
W
))
def
state_read
=
WireDefault
(
state_reg
)
def
get_next_state
(
state
:
UInt
,
touch_way
:
UInt
)
:
UInt
=
{
val
nextState
=
Wire
(
Vec
(
n_ways
,
UInt
(
n_ways
.
W
)))
val
moreRecentVec
=
state
.
asTypeOf
(
Vec
(
n_ways
,
UInt
(
n_ways
.
W
)))
val
wayDec
=
UIntToOH
(
touch_way
,
n_ways
)
val
wayUpd
=
(~
wayDec
).
asUInt
()
nextState
.
zipWithIndex
.
foreach
{
case
(
e
,
i
)
=>
e
:=
Mux
(
i
.
U
===
touch_way
,
wayUpd
,
moreRecentVec
(
i
)
&
wayUpd
)
}
nextState
.
asUInt
()
}
def
get_next_state
(
state
:
UInt
,
touch_ways
:
Seq
[
Valid
[
UInt
]])
:
UInt
=
{
touch_ways
.
foldLeft
(
state
)((
prev
,
touch_way
)
=>
Mux
(
touch_way
.
valid
,
get_next_state
(
prev
,
touch_way
.
bits
),
prev
))
}
def
access
(
touch_way
:
UInt
)
{
state_reg
:=
get_next_state
(
state_reg
,
touch_way
)
}
def
access
(
touch_ways
:
Seq
[
Valid
[
UInt
]])
{
when
(
ParallelOR
(
touch_ways
.
map
(
_
.
valid
)))
{
state_reg
:=
get_next_state
(
state_reg
,
touch_ways
)
}
}
def
get_min_value
(
xs
:
Seq
[(
UInt
,
UInt
)])
:
(
UInt
,
UInt
)
=
{
xs
match
{
case
Seq
(
a
)
=>
a
case
Seq
(
a
,
b
)
=>
(
Mux
(
a
.
_1
<
b
.
_1
,
a
.
_1
,
b
.
_1
),
Mux
(
a
.
_1
<
b
.
_1
,
a
.
_2
,
b
.
_2
))
case
_
=>
get_min_value
(
Seq
(
get_min_value
(
xs
take
xs
.
size
/
2
),
get_min_value
(
xs
drop
xs
.
size
/
2
)))
}
}
def
get_replace_way
(
state
:
UInt
,
sbufferState
:
Seq
[
Bool
])
:
UInt
=
{
val
moreRecentVec
=
state
.
asTypeOf
(
Vec
(
n_ways
,
UInt
(
n_ways
.
W
)))
val
count
=
Wire
(
Vec
(
n_ways
,
UInt
(
log2Up
(
n_ways
).
W
)))
for
(
i
<-
0
until
n_ways
){
count
(
i
)
:=
Mux
(
sbufferState
(
i
),
PopCount
(
moreRecentVec
(
i
)),
((
1
<<
n_ways
)-
1
).
U
)
}
count
.
zip
((
0
until
n_ways
).
map
(
_
.
U
))
get_min_value
(
count
.
zip
((
0
until
n_ways
).
map
(
_
.
U
))).
_2
}
def
way
(
sbufferState
:
Seq
[
Bool
])
=
get_replace_way
(
state_reg
,
sbufferState
)
//def miss = access(way)
def
hit
=
{}
def
flush
()
=
{
state_reg
:=
0.
U
(
nBits
.
W
)
}
//@deprecated("replace 'replace' with 'way' from abstract class ReplacementPolicy","Rocket Chip 2020.05")
//def replace: UInt = way
}
\ No newline at end of file
src/main/scala/xiangshan/XSCore.scala
浏览文件 @
67559d9e
...
...
@@ -9,7 +9,7 @@ import xiangshan.backend.exu.ExuParameters
import
xiangshan.frontend._
import
xiangshan.mem._
import
xiangshan.backend.fu.HasExceptionNO
import
xiangshan.cache.
{
ICache
,
DCache
,
DCacheParameters
,
ICacheParameters
,
PTW
,
Uncache
}
import
xiangshan.cache.
{
ICache
,
DCache
,
DCacheParameters
,
ICacheParameters
,
L1plusCacheParameters
,
PTW
,
Uncache
}
import
chipsalliance.rocketchip.config
import
freechips.rocketchip.diplomacy.
{
LazyModule
,
LazyModuleImp
}
import
freechips.rocketchip.tilelink.
{
TLBundleParameters
,
TLCacheCork
,
TLBuffer
,
TLClientNode
,
TLIdentityNode
,
TLXbar
}
...
...
@@ -172,7 +172,12 @@ trait HasXSParameter {
val
icacheParameters
=
ICacheParameters
(
)
val
LRSCCycles
=
100
val
l1plusCacheParameters
=
L1plusCacheParameters
(
tagECC
=
Some
(
"secded"
),
dataECC
=
Some
(
"secded"
),
nMissEntries
=
8
)
val
dcacheParameters
=
DCacheParameters
(
tagECC
=
Some
(
"secded"
),
dataECC
=
Some
(
"secded"
),
...
...
@@ -180,6 +185,8 @@ trait HasXSParameter {
nLoadMissEntries
=
8
,
nStoreMissEntries
=
8
)
val
LRSCCycles
=
100
}
trait
HasXSLog
{
this:
RawModule
=>
...
...
src/main/scala/xiangshan/backend/fu/CSR.scala
浏览文件 @
67559d9e
...
...
@@ -3,7 +3,6 @@ package xiangshan.backend.fu
import
chisel3._
import
chisel3.ExcitingUtils.
{
ConnectionType
,
Debug
}
import
chisel3.util._
import
chisel3.util.experimental.BoringUtils
import
fpu.Fflags
import
utils._
import
xiangshan._
...
...
@@ -411,11 +410,6 @@ class CSR extends XSModule
// val setLrAddr = WireInit(UInt(AddrBits.W), DontCare) //TODO : need check
// val lr = RegInit(Bool(), false.B)
// val lrAddr = RegInit(UInt(AddrBits.W), 0.U)
// BoringUtils.addSink(setLr, "set_lr")
// BoringUtils.addSink(setLrVal, "set_lr_val")
// BoringUtils.addSink(setLrAddr, "set_lr_addr")
// BoringUtils.addSource(lr, "lr")
// BoringUtils.addSource(lrAddr, "lr_addr")
//
// when(setLr){
// lr := setLrVal
...
...
@@ -855,14 +849,6 @@ class CSR extends XSModule
}
}
// for differential testing
// BoringUtils.addSource(RegNext(priviledgeMode), "difftestMode")
// BoringUtils.addSource(RegNext(mstatus), "difftestMstatus")
// BoringUtils.addSource(RegNext(mstatus & sstatusRmask), "difftestSstatus")
// BoringUtils.addSource(RegNext(mepc), "difftestMepc")
// BoringUtils.addSource(RegNext(sepc), "difftestSepc")
// BoringUtils.addSource(RegNext(mcause), "difftestMcause")
// BoringUtils.addSource(RegNext(scause), "difftestScause")
ExcitingUtils
.
addSource
(
priviledgeMode
,
"difftestMode"
,
Debug
)
ExcitingUtils
.
addSource
(
mstatus
,
"difftestMstatus"
,
Debug
)
ExcitingUtils
.
addSource
(
mstatus
&
sstatusRmask
,
"difftestSstatus"
,
Debug
)
...
...
@@ -882,6 +868,5 @@ class CSR extends XSModule
ExcitingUtils
.
addSource
(
mideleg
,
"difftestMideleg"
,
Debug
)
ExcitingUtils
.
addSource
(
medeleg
,
"difftestMedeleg"
,
Debug
)
}
else
{
// BoringUtils.addSource(readWithScala(perfCntList("Minstret")._1), "ilaInstrCnt")
}
}
src/main/scala/xiangshan/backend/fu/FunctionUnit.scala
浏览文件 @
67559d9e
...
...
@@ -177,7 +177,7 @@ object FunctionUnit {
val
fmiscCfg
=
FuConfig
(
FuType
.
fmisc
,
0
,
2
,
writeIntRf
=
false
,
writeFpRf
=
true
,
hasRedirect
=
false
,
CertainLatency
(
2
)
UncertainLatency
(
)
)
val
fDivSqrtCfg
=
...
...
src/main/scala/xiangshan/backend/roq/Roq.scala
浏览文件 @
67559d9e
...
...
@@ -7,7 +7,6 @@ import xiangshan._
import
utils._
import
xiangshan.backend.LSUOpType
import
xiangshan.backend.fu.fpu.Fflags
import
xiangshan.backend.decode.isa.Privileged.WFI
class
RoqPtr
extends
CircularQueuePtr
(
RoqPtr
.
RoqSize
)
with
HasCircularQueuePtrHelper
{
...
...
@@ -396,7 +395,6 @@ class Roq extends XSModule with HasCircularQueuePtrHelper {
ExcitingUtils
.
addSource
(
RegNext
(
retirePCFix
),
"difftestThisPC"
,
ExcitingUtils
.
Debug
)
//first valid PC
ExcitingUtils
.
addSource
(
RegNext
(
retireInstFix
),
"difftestThisINST"
,
ExcitingUtils
.
Debug
)
//first valid inst
ExcitingUtils
.
addSource
(
RegNext
(
skip
.
asUInt
),
"difftestSkip"
,
ExcitingUtils
.
Debug
)
// BoringUtils.addSource(RegNext(false.B), "difftestIsRVC")//FIXIT
ExcitingUtils
.
addSource
(
RegNext
(
isRVC
.
asUInt
),
"difftestIsRVC"
,
ExcitingUtils
.
Debug
)
ExcitingUtils
.
addSource
(
RegNext
(
wen
.
asUInt
),
"difftestWen"
,
ExcitingUtils
.
Debug
)
ExcitingUtils
.
addSource
(
RegNext
(
wpc
),
"difftestWpc"
,
ExcitingUtils
.
Debug
)
...
...
src/main/scala/xiangshan/cache/L1plusCache.scala
0 → 100644
浏览文件 @
67559d9e
此差异已折叠。
点击以展开。
src/main/scala/xiangshan/frontend/PreDecode.scala
浏览文件 @
67559d9e
...
...
@@ -14,7 +14,7 @@ trait HasPdconst{ this: XSModule =>
val
brType
::
Nil
=
ListLookup
(
instr
,
List
(
BrType
.
notBr
),
PreDecodeInst
.
brTable
)
val
rd
=
Mux
(
isRVC
(
instr
),
instr
(
12
),
instr
(
11
,
7
))
val
rs
=
Mux
(
isRVC
(
instr
),
Mux
(
brType
===
BrType
.
jal
,
0.
U
,
instr
(
11
,
7
)),
instr
(
19
,
15
))
val
isCall
=
(
brType
===
BrType
.
jal
||
brType
===
BrType
.
jalr
)
&&
isLink
(
rd
)
val
isCall
=
(
brType
===
BrType
.
jal
&&
!
isRVC
(
instr
)
||
brType
===
BrType
.
jalr
)
&&
isLink
(
rd
)
// Only for RV64
val
isRet
=
brType
===
BrType
.
jalr
&&
isLink
(
rs
)
&&
!
isCall
List
(
brType
,
isCall
,
isRet
)
}
...
...
src/main/scala/xiangshan/frontend/RAS.scala
浏览文件 @
67559d9e
...
...
@@ -106,7 +106,7 @@ class RAS extends BasePredictor
//update commit ras
val
commit_push
=
!
commit_is_full
&&
io
.
recover
.
valid
&&
io
.
recover
.
bits
.
pd
.
isCall
val
commit_pop
=
!
commit_is_empty
&&
io
.
recover
.
valid
&&
io
.
recover
.
bits
.
pd
.
isRet
val
commit_new_addr
=
io
.
recover
.
bits
.
pc
+
4.
U
//TODO: consider RVC
val
commit_new_addr
=
Mux
(
io
.
recover
.
bits
.
pd
.
isRVC
,
io
.
recover
.
bits
.
pc
+
2.
U
,
io
.
recover
.
bits
.
pc
+
4.
U
)
val
commit_ras_write
=
WireInit
(
0.
U
.
asTypeOf
(
rasEntry
()))
val
commit_alloc_new
=
commit_new_addr
=/=
commit_ras_top_addr
when
(
commit_push
)
{
...
...
@@ -202,4 +202,4 @@ class RAS extends BasePredictor
// }
// }
}
\ No newline at end of file
}
src/main/scala/xiangshan/mem/sbuffer/NewSbuffer.scala
浏览文件 @
67559d9e
...
...
@@ -70,7 +70,8 @@ class NewSbuffer extends XSModule with HasSbufferCst {
val
buffer
=
Mem
(
StoreBufferSize
,
new
SbufferLine
)
val
stateVec
=
RegInit
(
VecInit
(
Seq
.
fill
(
StoreBufferSize
)(
s_invalid
)))
val
lru
=
new
TrueLRU
(
StoreBufferSize
)
//val lru = new SbufferLRU(StoreBufferSize)
val
lru
=
new
SbufferLRU
(
StoreBufferSize
)
// 2 * enq + 1 * deq
val
lruAccessWays
=
Wire
(
Vec
(
io
.
in
.
getWidth
+
1
,
new
Valid
(
UInt
(
SbufferIndexWidth
.
W
))))
for
(
w
<-
lruAccessWays
){
...
...
@@ -217,7 +218,7 @@ class NewSbuffer extends XSModule with HasSbufferCst {
val
do_eviction
=
Wire
(
Bool
())
val
empty
=
Cat
(
stateVec
.
map
(
s
=>
s
===
s_invalid
)).
andR
()
&&
!
Cat
(
io
.
in
.
map
(
_
.
valid
)).
orR
()
val
replaceIdx
=
lru
.
way
val
replaceIdx
=
lru
.
way
(
stateVec
.
map
(
s
=>
s
===
s_valid
))
val
firstValidEntry
=
PriorityEncoder
(
stateVec
.
map
(
s
=>
s
===
s_valid
))
val
evictor
=
Module
(
new
NaiveEvictor
(
StoreBufferSize
-
4
))
...
...
@@ -248,6 +249,8 @@ class NewSbuffer extends XSModule with HasSbufferCst {
}
XSDebug
(
p
"sbuffer state:${sbuffer_state} do eviction:${do_eviction} empty:${empty}\n"
)
//XSDebug(p"replaceIdx:${replaceIdx}\n")
//val evictionIdxWire = replaceIdx
val
evictionIdxWire
=
Mux
(
stateVec
(
replaceIdx
)===
s_valid
,
replaceIdx
,
firstValidEntry
)
val
evictionIdxEnqReq
=
Wire
(
DecoupledIO
(
UInt
(
SbufferIndexWidth
.
W
)))
val
evictionIdxQueue
=
Module
(
new
Queue
(
UInt
(
SbufferIndexWidth
.
W
),
StoreBufferSize
,
pipe
=
true
,
flow
=
false
))
...
...
src/test/csrc/ram.cpp
浏览文件 @
67559d9e
...
...
@@ -115,16 +115,15 @@ void init_ram(const char *img) {
//new end
}
extern
"C"
void
ram_helper
(
uint64_t
rIdx
,
uint64_t
*
rdata
,
uint64_t
wIdx
,
uint64_t
wdata
,
uint64_t
wmask
,
uint8_t
wen
)
{
extern
"C"
uint64_t
ram_read_helper
(
uint64_t
rIdx
)
{
if
(
rIdx
>=
RAMSIZE
/
sizeof
(
uint64_t
))
{
printf
(
"ERROR: ram idx = 0x%x out of bound!
\n
"
,
rIdx
);
// TODO: don't allow out of bound when crossbar is ready
//assert(rIdx < RAMSIZE / sizeof(uint64_t));
*
rdata
=
0xabcd12345678dcbaUL
;
return
;
assert
(
rIdx
<
RAMSIZE
/
sizeof
(
uint64_t
));
}
*
rdata
=
ram
[
rIdx
];
return
ram
[
rIdx
];
}
extern
"C"
void
ram_write_helper
(
uint64_t
wIdx
,
uint64_t
wdata
,
uint64_t
wmask
,
uint8_t
wen
)
{
if
(
wen
)
{
assert
(
wIdx
<
RAMSIZE
/
sizeof
(
uint64_t
));
ram
[
wIdx
]
=
(
ram
[
wIdx
]
&
~
wmask
)
|
(
wdata
&
wmask
);
...
...
src/test/scala/cache/L1plusCacheTest.scala
0 → 100644
浏览文件 @
67559d9e
package
cache
import
scala.collection.mutable.ArrayBuffer
import
chipsalliance.rocketchip.config.
{
Field
,
Parameters
}
import
chisel3._
import
chisel3.util._
import
chiseltest.experimental.TestOptionBuilder._
import
chiseltest.internal.VerilatorBackendAnnotation
import
chiseltest._
import
chisel3.experimental.BundleLiterals._
import
firrtl.stage.RunFirrtlTransformAnnotation
import
chiseltest.ChiselScalatestTester
import
device.AXI4RAM
import
freechips.rocketchip.amba.axi4.AXI4UserYanker
import
freechips.rocketchip.diplomacy.
{
AddressSet
,
LazyModule
,
LazyModuleImp
}
import
freechips.rocketchip.tilelink.
{
TLBuffer
,
TLCacheCork
,
TLToAXI4
,
TLXbar
}
import
org.scalatest.
{
FlatSpec
,
Matchers
}
import
sifive.blocks.inclusivecache.
{
CacheParameters
,
InclusiveCache
,
InclusiveCacheMicroParameters
}
import
utils.
{
DebugIdentityNode
,
HoldUnless
,
XSDebug
}
import
xiangshan.
{
HasXSLog
,
MicroOp
}
import
xiangshan.cache.
{
DCache
,
L1plusCache
,
DCacheLineIO
,
L1plusCacheIO
,
MemoryOpConstants
}
import
xiangshan.testutils.AddSinks
import
xstransforms.PrintModuleName
import
scala.util.Random
case
object
L1plusCacheTestKey
extends
Field
[
Long
]
class
L1plusTestTopIO
extends
Bundle
{
val
l1plus
=
new
L1plusCacheIO
()
val
dcacheStore
=
new
DCacheLineIO
()
}
class
L1plusTestTop
()(
implicit
p
:
Parameters
)
extends
LazyModule
{
val
dcache
=
LazyModule
(
new
DCache
())
val
l1plusCache
=
LazyModule
(
new
L1plusCache
())
val
l2
=
LazyModule
(
new
InclusiveCache
(
CacheParameters
(
level
=
2
,
ways
=
4
,
sets
=
4
*
1024
/
(
64
*
4
*
4
),
blockBytes
=
64
,
beatBytes
=
32
,
cacheName
=
s
"L2"
),
InclusiveCacheMicroParameters
(
writeBytes
=
8
)
))
val
ram
=
LazyModule
(
new
AXI4RAM
(
AddressSet
(
0x0
L
,
0xffffffffff
L
),
memByte
=
128
*
1024
*
1024
,
useBlackBox
=
false
))
val
xbar
=
TLXbar
()
xbar
:=
TLBuffer
()
:=
dcache
.
clientNode
xbar
:=
TLBuffer
()
:=
l1plusCache
.
clientNode
l2
.
node
:=
xbar
ram
.
node
:=
AXI4UserYanker
()
:=
TLToAXI4
()
:=
TLBuffer
()
:=
TLCacheCork
()
:=
l2
.
node
lazy
val
module
=
new
LazyModuleImp
(
this
)
with
HasXSLog
{
val
io
=
IO
(
Flipped
(
new
L1plusTestTopIO
))
AddSinks
()
dcache
.
module
.
io
<>
DontCare
dcache
.
module
.
io
.
lsu
.
store
<>
io
.
dcacheStore
l1plusCache
.
module
.
io
<>
io
.
l1plus
}
}
class
L1plusCacheTest
extends
FlatSpec
with
ChiselScalatestTester
with
Matchers
{
behavior
of
"L1plusCache"
val
mem_size
=
128
*
1024
*
1024
val
block_size
=
64
// val nblocks = mem_size / block_size
val
nblocks
=
100
// data structures
// our golden version cache
val
cache_blocks
=
new
Array
[
BigInt
](
nblocks
)
for
(
i
<-
0
until
nblocks
)
{
cache_blocks
(
i
)
=
BigInt
(
0
)
}
// ----------------------------------------
// useful request parameter values
val
CMD_READ
=
MemoryOpConstants
.
M_XRD
val
r
=
scala
.
util
.
Random
top
.
Parameters
.
set
(
top
.
Parameters
.
debugParameters
)
val
annos
=
Seq
(
VerilatorBackendAnnotation
,
RunFirrtlTransformAnnotation
(
new
PrintModuleName
)
)
it
should
"run"
in
{
implicit
val
p
=
Parameters
((
site
,
up
,
here
)
=>
{
case
L1plusCacheTestKey
=>
0
})
test
(
LazyModule
(
new
L1plusTestTop
()).
module
)
.
withAnnotations
(
annos
){
c
=>
c
.
clock
.
step
(
100
)
val
sq
=
new
StoreQueue
(
8
)
val
lq
=
new
LoadQueue
(
8
)
def
init
()
=
{
sq
.
init
()
lq
.
init
()
// initialize DUT inputs
c
.
io
.
dcacheStore
.
req
.
valid
.
poke
(
false
.
B
)
c
.
io
.
dcacheStore
.
resp
.
ready
.
poke
(
false
.
B
)
c
.
io
.
l1plus
.
req
.
valid
.
poke
(
false
.
B
)
c
.
io
.
l1plus
.
resp
.
ready
.
poke
(
false
.
B
)
c
.
io
.
l1plus
.
flush
.
poke
(
false
.
B
)
}
def
flush_l1plus
()
=
{
c
.
io
.
l1plus
.
flush
.
poke
(
true
.
B
)
while
(!
c
.
io
.
l1plus
.
empty
.
peek
().
litToBoolean
)
{
c
.
clock
.
step
()
}
c
.
io
.
l1plus
.
flush
.
poke
(
false
.
B
)
}
def
evaluate
()
=
{
while
(!
sq
.
isFinished
()
||
!
lq
.
isFinished
())
{
sq
.
tick
(
c
.
io
.
dcacheStore
)
lq
.
tick
(
c
.
io
.
l1plus
)
c
.
clock
.
step
()
}
}
// ----------------------------------------
// scan test
// write every memory block and then read out every memory cell
def
scan_test
()
=
{
println
(
s
"scan test"
)
init
()
// first, initialize every memory block with random numbers
for
(
i
<-
0
until
nblocks
)
{
val
addr
=
i
*
64
val
words
=
(
0
until
8
)
map
{
_
=>
(
BigInt
(
r
.
nextLong
()
&
0x7fffffffffffffff
L
))
}
val
data
=
words
.
foldLeft
(
BigInt
(
0
))((
sum
,
i
)
=>
sum
<<
64
|
i
)
cache_blocks
(
i
)
=
data
println
(
f
"enq store addr: $addr%x data: $data%x"
)
sq
.
enq
(
Req
(
addr
,
data
))
}
// execute reqs
evaluate
()
// read them out
for
(
i
<-
0
until
nblocks
)
{
val
addr
=
i
*
64
val
data
=
cache_blocks
(
i
)
println
(
f
"enq load addr: $addr%x data: $data%x"
)
lq
.
enq
(
Req
(
addr
,
data
))
}
// execute reqs
evaluate
()
}
scan_test
()
// self_modify_test
def
self_modify_test
()
=
{
println
(
s
"self_modify_test"
)
for
(
i
<-
0
until
10
)
{
flush_l1plus
()
scan_test
()
}
}
self_modify_test
()
}
}
}
// emulated queue
class
IdPool
(
val
nReqIds
:
Int
)
{
val
freeIds
=
new
Array
[
Boolean
](
nReqIds
)
def
allocate
()
:
Int
=
{
for
(
i
<-
0
until
freeIds
.
size
)
{
if
(
freeIds
(
i
))
{
freeIds
(
i
)
=
false
return
i
}
}
// no free id to allocate
return
-
1
}
def
free
(
id
:
Int
)
:
Unit
=
{
assert
(!
freeIds
(
id
))
freeIds
(
id
)
=
true
}
def
init
()
:
Unit
=
{
for
(
i
<-
0
until
freeIds
.
size
)
{
freeIds
(
i
)
=
true
}
}
}
case
class
Req
(
addr
:
Long
,
data
:
BigInt
)
{
override
def
toString
()
:
String
=
{
return
f
"addr: $addr%x data: $data%x"
}
}
case
class
QueueEntry
(
var
id
:
Int
,
// it's transaction id
req
:
Req
)
{
override
def
toString
()
:
String
=
{
return
f
"id: $id%d req: $req"
}
}
class
Queue
(
nEntries
:
Int
,
name
:
String
)
{
// Queue
// ---------------------------------------
val
idPool
=
new
IdPool
(
nEntries
)
val
queue
=
new
ArrayBuffer
[
QueueEntry
]()
def
enq
(
req
:
Req
)
=
{
// for unissued reqs, they have id = -1
queue
+=
new
QueueEntry
(-
1
,
req
)
}
// select a req to issue
// req with id == -1 are not issued
def
select
()
:
Int
=
{
for
(
i
<-
0
until
queue
.
size
)
{
if
(
queue
(
i
).
id
==
-
1
)
return
i
}
return
-
1
}
// retire the req with transaction id tId
def
retire
(
tId
:
Int
)
:
Unit
=
{
println
(
f
"$name retire transaction: $tId%d"
)
for
(
i
<-
0
until
queue
.
size
)
{
if
(
queue
(
i
).
id
==
tId
)
{
// remove this request
queue
.
remove
(
i
)
println
(
f
"$name retire req: $i%d transaction: $tId%d"
)
return
}
}
assert
(
false
)
}
def
issue
(
idx
:
Int
,
tId
:
Int
)
=
{
println
(
f
"$name issue req: $idx%d transaction: $tId%d"
)
assert
(
queue
(
idx
).
id
==
-
1
)
queue
(
idx
).
id
=
tId
}
// look up req by transaction id tId
def
lookUp
(
tId
:
Int
)
:
Req
=
{
for
(
i
<-
0
until
queue
.
size
)
{
if
(
queue
(
i
).
id
==
tId
)
{
// remove this request
return
queue
(
i
).
req
}
}
// we must return a value
// just to make scala happy
return
Req
(
0
,
0
)
}
var
reqWaiting
=
false
def
init
()
:
Unit
=
{
idPool
.
init
()
queue
.
clear
()
reqWaiting
=
false
}
def
isFinished
()
=
queue
.
isEmpty
}
class
StoreQueue
(
nEntries
:
Int
)
extends
Queue
(
nEntries
,
"StoreQueue"
)
{
def
sendReq
(
port
:
DCacheLineIO
)
:
Unit
=
{
val
req
=
port
.
req
// has last cycle's req been fired?
if
(
reqWaiting
&&
req
.
ready
.
peek
().
litToBoolean
)
{
reqWaiting
=
false
// no requests waiting on line
// reset valid signal
req
.
valid
.
poke
(
false
.
B
)
}
// can we send a new request in this cycle
val
reqIdx
=
select
()
if
(
reqWaiting
||
reqIdx
==
-
1
)
{
return
}
val
tId
=
idPool
.
allocate
()
if
(
tId
==
-
1
)
{
return
}
// try sending a new request in this cycle
// select a req to issue
reqWaiting
=
true
issue
(
reqIdx
,
tId
)
val
CMD_WRITE
=
MemoryOpConstants
.
M_XWR
val
FULL_MASK
=
BigInt
(
"ffffffffffffffff"
,
16
).
U
val
r
=
queue
(
reqIdx
).
req
req
.
valid
.
poke
(
true
.
B
)
req
.
bits
.
cmd
.
poke
(
CMD_WRITE
)
req
.
bits
.
addr
.
poke
(
r
.
addr
.
U
)
req
.
bits
.
data
.
poke
(
r
.
data
.
U
)
req
.
bits
.
mask
.
poke
(
FULL_MASK
)
req
.
bits
.
meta
.
id
.
poke
(
tId
.
U
)
req
.
bits
.
meta
.
vaddr
.
poke
(
r
.
addr
.
U
)
req
.
bits
.
meta
.
paddr
.
poke
(
r
.
addr
.
U
)
// req.bits.meta.uop.poke(0.U.asTypeOf(new MicroOp))
req
.
bits
.
meta
.
mmio
.
poke
(
false
.
B
)
req
.
bits
.
meta
.
tlb_miss
.
poke
(
false
.
B
)
req
.
bits
.
meta
.
mask
.
poke
(
FULL_MASK
)
req
.
bits
.
meta
.
replay
.
poke
(
false
.
B
)
}
def
handleResp
(
port
:
DCacheLineIO
)
=
{
val
resp
=
port
.
resp
// always ready
resp
.
ready
.
poke
(
true
.
B
)
if
(
resp
.
valid
.
peek
().
litToBoolean
)
{
val
id
=
resp
.
bits
.
meta
.
id
.
peek
().
litValue
.
longValue
.
toInt
idPool
.
free
(
id
)
retire
(
id
)
}
}
def
tick
(
port
:
DCacheLineIO
)
=
{
// first, try to send reqs
sendReq
(
port
)
// then, receive responses
handleResp
(
port
)
}
}
class
LoadQueue
(
nEntries
:
Int
)
extends
Queue
(
nEntries
,
"LoadQueue"
)
{
def
sendReq
(
port
:
L1plusCacheIO
)
:
Unit
=
{
val
req
=
port
.
req
// has last cycle's req been fired?
if
(
reqWaiting
&&
req
.
ready
.
peek
().
litToBoolean
)
{
reqWaiting
=
false
// no requests waiting on line
// reset valid signal
req
.
valid
.
poke
(
false
.
B
)
}
// can we send a new request in this cycle
val
reqIdx
=
select
()
if
(
reqWaiting
||
reqIdx
==
-
1
)
{
return
}
val
tId
=
idPool
.
allocate
()
if
(
tId
==
-
1
)
{
return
}
// try sending a new request in this cycle
// select a req to issue
reqWaiting
=
true
issue
(
reqIdx
,
tId
)
val
CMD_READ
=
MemoryOpConstants
.
M_XRD
val
r
=
queue
(
reqIdx
).
req
req
.
valid
.
poke
(
true
.
B
)
req
.
bits
.
cmd
.
poke
(
CMD_READ
)
req
.
bits
.
addr
.
poke
(
r
.
addr
.
U
)
req
.
bits
.
id
.
poke
(
tId
.
U
)
}
def
handleResp
(
port
:
L1plusCacheIO
)
=
{
val
resp
=
port
.
resp
// always ready
resp
.
ready
.
poke
(
true
.
B
)
if
(
resp
.
valid
.
peek
().
litToBoolean
)
{
val
id
=
resp
.
bits
.
id
.
peek
().
litValue
.
longValue
.
toInt
val
rdata
=
resp
.
bits
.
data
.
peek
().
litValue
val
r
=
lookUp
(
id
)
assert
(
r
.
data
==
rdata
)
idPool
.
free
(
id
)
retire
(
id
)
}
}
def
tick
(
port
:
L1plusCacheIO
)
=
{
// first, try to send reqs
sendReq
(
port
)
// then, receive responses
handleResp
(
port
)
}
}
src/test/scala/xiangshan/memend/SbufferTest.scala
0 → 100644
浏览文件 @
67559d9e
package
xiangshan.memend
import
org.scalatest._
import
chiseltest._
import
chisel3._
import
chisel3.experimental.BundleLiterals._
import
chisel3.util._
import
xiangshan._
import
xiangshan.cache.
{
DCacheLineIO
,
DCacheWordReq
}
import
xiangshan.mem.
{
LoadForwardQueryIO
,
NewSbuffer
}
import
xiangshan.testutils._
import
scala.util.Random
class
SbufferWapper
extends
XSModule
{
val
io
=
IO
(
new
Bundle
()
{
val
in
=
Vec
(
StorePipelineWidth
,
Flipped
(
Decoupled
(
new
DCacheWordReq
)))
val
dcache
=
new
DCacheLineIO
val
forward
=
Vec
(
LoadPipelineWidth
,
Flipped
(
new
LoadForwardQueryIO
))
val
flush
=
new
Bundle
{
val
valid
=
Input
(
Bool
())
val
empty
=
Output
(
Bool
())
}
// sbuffer flush
})
val
sbuffer
=
Module
(
new
NewSbuffer
)
io
<>
sbuffer
.
io
// fake dcache
sbuffer
.
io
.
dcache
.
req
.
ready
:=
true
.
B
sbuffer
.
io
.
dcache
.
resp
.
valid
:=
RegNext
(
RegNext
(
RegNext
(
RegNext
(
sbuffer
.
io
.
dcache
.
req
.
valid
))))
sbuffer
.
io
.
dcache
.
resp
.
bits
.
meta
.
id
:=
RegNext
(
RegNext
(
RegNext
(
RegNext
(
sbuffer
.
io
.
dcache
.
req
.
bits
.
meta
.
id
))))
}
class
SbufferTest
extends
FlatSpec
with
ChiselScalatestTester
with
Matchers
with
HasXSParameter
with
ParallelTestExecution
with
HasPartialDecoupledDriver
{
top
.
Parameters
.
set
(
top
.
Parameters
.
debugParameters
)
it
should
"random req"
in
{
test
(
new
SbufferWapper
{
AddSinks
()}){
c
=>
def
store_enq
(
addr
:
Seq
[
UInt
],
data
:
Seq
[
UInt
],
mask
:
Seq
[
UInt
])
={
(
0
until
StorePipelineWidth
).
map
{
i
=>
c
.
io
.
in
(
i
).
valid
.
poke
(
true
.
B
)
c
.
io
.
in
(
i
).
bits
.
pokePartial
(
chiselTypeOf
(
c
.
io
.
in
(
i
).
bits
).
Lit
(
_
.
mask
->
mask
(
i
),
_
.
addr
->
addr
(
i
),
_
.
data
->
data
(
i
)
))
}
c
.
clock
.
step
(
1
)
for
(
in
<-
c
.
io
.
in
){
in
.
valid
.
poke
(
false
.
B
)}
}
def
forward_req_and_resp
(
addr
:
Seq
[
UInt
],
data
:
Seq
[
UInt
],
mask
:
Seq
[
UInt
])
=
{
(
0
until
LoadPipelineWidth
).
map
{
i
=>
c
.
io
.
forward
(
i
).
paddr
.
poke
(
addr
(
i
))
c
.
io
.
forward
(
i
).
mask
.
poke
(
mask
(
i
))
if
(
c
.
io
.
in
(
i
).
ready
.
peek
()
==
true
.
B
)
{
(
0
until
8
).
map
{
j
=>
c
.
io
.
forward
(
i
).
forwardData
(
j
).
expect
(
data
(
i
)(
j
*
8
+
7
,
j
*
8
))
}
}
}
}
val
TEST_SIZE
=
100
for
(
i
<-
0
until
TEST_SIZE
)
{
val
addr
=
Seq
.
fill
(
StorePipelineWidth
)((
Random
.
nextLong
()
&
0x7ffffffff8
L
).
U
)
// align to block size
val
data
=
Seq
.
fill
(
StorePipelineWidth
)((
Random
.
nextLong
()
&
0x7fffffffffffffff
L
).
U
)
val
mask
=
Seq
.
fill
(
StorePipelineWidth
)(
0xff
.
U
)
store_enq
(
addr
,
data
,
mask
)
forward_req_and_resp
(
addr
,
data
,
mask
)
}
}
}
it
should
"sequence req"
in
{
test
(
new
SbufferWapper
{
AddSinks
()}){
c
=>
def
store_enq
(
addr
:
Seq
[
UInt
],
data
:
Seq
[
UInt
],
mask
:
Seq
[
UInt
])
=
{
(
0
until
StorePipelineWidth
).
map
{
i
=>
c
.
io
.
in
(
i
).
valid
.
poke
(
true
.
B
)
c
.
io
.
in
(
i
).
bits
.
pokePartial
(
chiselTypeOf
(
c
.
io
.
in
(
i
).
bits
).
Lit
(
_
.
mask
->
mask
(
i
),
_
.
addr
->
addr
(
i
),
_
.
data
->
data
(
i
)
))
}
c
.
clock
.
step
(
1
)
for
(
in
<-
c
.
io
.
in
){
in
.
valid
.
poke
(
false
.
B
)}
}
def
forward_req_and_resp
(
addr
:
Seq
[
UInt
],
data
:
Seq
[
UInt
],
mask
:
Seq
[
UInt
])
=
{
(
0
until
LoadPipelineWidth
).
map
{
i
=>
c
.
io
.
forward
(
i
).
paddr
.
poke
(
addr
(
i
))
c
.
io
.
forward
(
i
).
mask
.
poke
(
mask
(
i
))
if
(
c
.
io
.
in
(
i
).
ready
.
peek
()
==
true
.
B
)
{
(
0
until
8
).
map
{
j
=>
c
.
io
.
forward
(
i
).
forwardData
(
j
).
expect
(
data
(
i
)(
j
*
8
+
7
,
j
*
8
))
}
}
}
}
val
TEST_SIZE
=
100
val
start_addr
=
Random
.
nextLong
()
&
0x7ffffffff8
L
for
(
i
<-
0
until
TEST_SIZE
)
{
val
addr
=
Seq
(((
i
<<
4
)
+
start_addr
).
U
,((
i
<<
4
)+
8
+
start_addr
).
U
)
val
data
=
Seq
.
fill
(
StorePipelineWidth
)((
Random
.
nextLong
()
&
0x7fffffffffffffff
L
).
U
)
val
mask
=
Seq
.
fill
(
StorePipelineWidth
)(
0xff
.
U
)
store_enq
(
addr
,
data
,
mask
)
forward_req_and_resp
(
addr
,
data
,
mask
)
}
}
}
}
src/test/vsrc/ram.v
浏览文件 @
67559d9e
import
"DPI-C"
function
void
ram_helper
import
"DPI-C"
function
void
ram_
write_
helper
(
input
longint
rIdx
,
output
longint
rdata
,
input
longint
wIdx
,
input
longint
wdata
,
input
longint
wmask
,
input
bit
wen
);
import
"DPI-C"
function
longint
ram_read_helper
(
input
longint
rIdx
);
module
RAMHelper
(
input
clk
,
input
[
63
:
0
]
rIdx
,
...
...
@@ -18,8 +21,10 @@ module RAMHelper(
input
wen
);
assign
rdata
=
ram_read_helper
(
rIdx
);
always
@
(
posedge
clk
)
begin
ram_
helper
(
rIdx
,
rdata
,
wIdx
,
wdata
,
wmask
,
wen
);
ram_
write_helper
(
wIdx
,
wdata
,
wmask
,
wen
);
end
endmodule
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录