Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenXiangShan
XiangShan
提交
35377176
X
XiangShan
项目概览
OpenXiangShan
/
XiangShan
12 个月 前同步成功
通知
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,发现更多精彩内容 >>
提交
35377176
编写于
11月 15, 2019
作者:
Z
zhanglinjuan
浏览文件
操作
浏览文件
下载
差异文件
fix bugs in l2cache(turn off prefetcher)
上级
d2d827d9
eb8bdfa7
变更
16
展开全部
隐藏空白更改
内联
并排
Showing
16 changed file
with
534 addition
and
465 deletion
+534
-465
Makefile
Makefile
+8
-4
src/main/scala/bus/simplebus/SimpleBus.scala
src/main/scala/bus/simplebus/SimpleBus.scala
+1
-0
src/main/scala/noop/Cache.scala
src/main/scala/noop/Cache.scala
+181
-320
src/main/scala/noop/EXU.scala
src/main/scala/noop/EXU.scala
+5
-1
src/main/scala/noop/NOOP.scala
src/main/scala/noop/NOOP.scala
+6
-4
src/main/scala/noop/fu/CSR.scala
src/main/scala/noop/fu/CSR.scala
+14
-14
src/main/scala/noop/fu/LSU.scala
src/main/scala/noop/fu/LSU.scala
+2
-2
src/main/scala/system/Coherence.scala
src/main/scala/system/Coherence.scala
+33
-67
src/main/scala/system/Prefetcher.scala
src/main/scala/system/Prefetcher.scala
+1
-1
src/main/scala/system/SoC.scala
src/main/scala/system/SoC.scala
+36
-43
src/main/scala/utils/Debug.scala
src/main/scala/utils/Debug.scala
+1
-1
src/main/scala/utils/Lock.scala
src/main/scala/utils/Lock.scala
+43
-0
src/main/scala/utils/SRAMTemplate.scala
src/main/scala/utils/SRAMTemplate.scala
+29
-0
src/test/csrc/emu.h
src/test/csrc/emu.h
+20
-2
src/test/scala/cache/CacheTest.scala
src/test/scala/cache/CacheTest.scala
+151
-0
src/test/scala/top/SimMMIO.scala
src/test/scala/top/SimMMIO.scala
+3
-6
未找到文件。
Makefile
浏览文件 @
35377176
...
...
@@ -41,12 +41,13 @@ EMU_LDFLAGS = -lpthread -lSDL2 -ldl
VERILATOR_FLAGS
=
--top-module
$(SIM_TOP)
\
+define+VERILATOR
=
1
\
+define+PRINTF_COND
=
1
\
+define+RANDOMIZE_REG_INIT
\
--assert
--output-split
20000
\
--trace
\
+define+RANDOMIZE_REG_INIT
\
--assert
\
--output-split
5000
\
--output-split-cfuncs
5000
\
-I
$(
abspath
$(BUILD_DIR)
)
\
--x-assign
unique
-O3
-CFLAGS
"
$(EMU_CXXFLAGS)
"
\
-LDFLAGS
"
$(EMU_LDFLAGS)
"
-LDFLAGS
"
$(EMU_LDFLAGS)
"
EMU_MK
:=
$(BUILD_DIR)
/emu-compile/V
$(SIM_TOP)
.mk
EMU_DEPS
:=
$(EMU_VFILES)
$(EMU_CXXFILES)
...
...
@@ -72,6 +73,9 @@ endif
emu
:
$(EMU)
@
$(EMU)
-i
$(IMAGE)
$(MAINARGS)
cache
:
$(MAKE)
emu
IMAGE
=
Makefile
clean
:
rm
-rf
$(BUILD_DIR)
...
...
src/main/scala/bus/simplebus/SimpleBus.scala
浏览文件 @
35377176
...
...
@@ -53,6 +53,7 @@ class SimpleBusReqBundle(val userBits: Int = 0) extends SimpleBusBundle {
def
isRead
()
=
!
cmd
(
0
)
&&
!
cmd
(
3
)
def
isWrite
()
=
cmd
(
0
)
def
isBurst
()
=
cmd
(
1
)
def
isReadBurst
()
=
cmd
===
SimpleBusCmd
.
readBurst
def
isWriteSingle
()
=
cmd
===
SimpleBusCmd
.
write
def
isWriteLast
()
=
cmd
===
SimpleBusCmd
.
writeLast
def
isProbe
()
=
cmd
===
SimpleBusCmd
.
probe
...
...
src/main/scala/noop/Cache.scala
浏览文件 @
35377176
此差异已折叠。
点击以展开。
src/main/scala/noop/EXU.scala
浏览文件 @
35377176
...
...
@@ -84,7 +84,11 @@ class EXU(implicit val p: NOOPConfig) extends NOOPModule {
io
.
forward
.
wb
.
rfDest
:=
io
.
in
.
bits
.
ctrl
.
rfDest
io
.
forward
.
wb
.
rfData
:=
Mux
(
alu
.
io
.
out
.
fire
(),
aluOut
,
lsuOut
)
io
.
forward
.
fuType
:=
io
.
in
.
bits
.
ctrl
.
fuType
/*
Debug(true) {
printf("[EXU] dmem.req.valid = %d, dmem.req.bits.addr = %x\n", io.dmem.req.valid, io.dmem.req.bits.addr)
}
*/
val
isBru
=
ALUOpType
.
isBru
(
fuOpType
)
BoringUtils
.
addSource
(
alu
.
io
.
out
.
fire
()
&&
!
isBru
,
"perfCntCondMaluInstr"
)
BoringUtils
.
addSource
(
alu
.
io
.
out
.
fire
()
&&
isBru
,
"perfCntCondMbruInstr"
)
...
...
src/main/scala/noop/NOOP.scala
浏览文件 @
35377176
...
...
@@ -14,6 +14,8 @@ trait HasNOOPParameter {
val
HasDiv
=
true
val
HasIcache
=
true
val
HasDcache
=
true
val
HasL2cache
=
true
val
HasPrefetch
=
false
val
AddrBits
=
32
val
AddrBytes
=
AddrBits
/
8
val
DataBits
=
XLEN
...
...
@@ -42,7 +44,7 @@ class NOOP(implicit val p: NOOPConfig) extends NOOPModule {
val
imem
=
new
SimpleBusC
val
dmem
=
new
SimpleBusC
val
mmio
=
new
SimpleBusUC
//
val prefetchReq = Decoupled(new SimpleBusReqBundle)
val
prefetchReq
=
Decoupled
(
new
SimpleBusReqBundle
)
})
val
ifu
=
Module
(
new
IFU
)
...
...
@@ -73,7 +75,7 @@ class NOOP(implicit val p: NOOPConfig) extends NOOPModule {
when
(
idu
.
io
.
in
.
valid
)
{
printf
(
"IDU: pc = 0x%x, instr = 0x%x, pnpc = 0x%x\n"
,
idu
.
io
.
in
.
bits
.
pc
,
idu
.
io
.
in
.
bits
.
instr
,
idu
.
io
.
in
.
bits
.
pnpc
)
}
when
(
isu
.
io
.
in
.
valid
)
{
printf
(
"ISU: pc = 0x%x, pnpc = 0x%x\n"
,
isu
.
io
.
in
.
bits
.
cf
.
pc
,
isu
.
io
.
in
.
bits
.
cf
.
pnpc
)
}
when
(
exu
.
io
.
in
.
valid
)
{
printf
(
"EXU: pc = 0x%x, pnpc = 0x%x\n"
,
exu
.
io
.
in
.
bits
.
cf
.
pc
,
exu
.
io
.
in
.
bits
.
cf
.
pnpc
)
}
when
(
wbu
.
io
.
in
.
valid
)
{
printf
(
"WBU: pc = 0x%x\n"
,
wbu
.
io
.
in
.
bits
.
decode
.
cf
.
pc
)
}
when
(
wbu
.
io
.
in
.
valid
)
{
printf
(
"WBU: pc = 0x%x\n"
,
wbu
.
io
.
in
.
bits
.
decode
.
cf
.
pc
)
}
}
isu
.
io
.
wb
<>
wbu
.
io
.
wb
...
...
@@ -85,7 +87,7 @@ class NOOP(implicit val p: NOOPConfig) extends NOOPModule {
io
.
imem
<>
Cache
(
ifu
.
io
.
imem
,
mmioXbar
.
io
.
in
(
0
),
Fill
(
2
,
ifu
.
io
.
flushVec
(
0
)
|
ifu
.
io
.
bpFlush
))(
CacheConfig
(
ro
=
true
,
name
=
"icache"
,
userBits
=
AddrBits
*
2
))
io
.
dmem
<>
Cache
(
exu
.
io
.
dmem
,
mmioXbar
.
io
.
in
(
1
),
"b00"
.
U
,
enable
=
HasDcache
)(
CacheConfig
(
ro
=
false
,
name
=
"dcache"
))
//
io.prefetchReq.bits := exu.io.dmem.req.bits
//
io.prefetchReq.valid := exu.io.dmem.req.valid
io
.
prefetchReq
.
bits
:=
exu
.
io
.
dmem
.
req
.
bits
io
.
prefetchReq
.
valid
:=
exu
.
io
.
dmem
.
req
.
valid
io
.
mmio
<>
mmioXbar
.
io
.
out
}
src/main/scala/noop/fu/CSR.scala
浏览文件 @
35377176
...
...
@@ -194,21 +194,21 @@ class CSR(implicit val p: NOOPConfig) extends NOOPModule with HasCSRConst {
"MmmioInstr"
->
(
0xb0c
,
"perfCntCondMmmioInstr"
),
"MicacheHit"
->
(
0xb0d
,
"perfCntCondMicacheHit"
),
"MdcacheHit"
->
(
0xb0e
,
"perfCntCondMdcacheHit"
),
"MmulInstr"
->
(
0xb0f
,
"perfCntCondMmulInstr"
),
"MifuFlush"
->
(
0xb10
,
"perfCntCondMifuFlush"
),
"MrawStall"
->
(
0xb11
,
"perfCntCondMrawStall"
),
"MexuBusy"
->
(
0xb12
,
"perfCntCondMexuBusy"
),
"MbpBRight"
->
(
0xb13
,
"MbpBRight"
),
"MbpBWrong"
->
(
0xb14
,
"MbpBWrong"
),
"MbpJRight"
->
(
0xb15
,
"MbpJRight"
),
"MbpJWrong"
->
(
0xb16
,
"MbpJWrong"
),
"MbpIRight"
->
(
0xb17
,
"MbpIRight"
),
"MbpIWrong"
->
(
0xb18
,
"MbpIWrong"
),
"MbpRRight"
->
(
0xb19
,
"MbpRRight"
),
"MbpRWrong"
->
(
0xb1a
,
"MbpRWrong"
)
"Ml2cacheHit"
->
(
0xb0f
,
"perfCntCondMl2cacheHit"
),
"MmulInstr"
->
(
0xb10
,
"perfCntCondMmulInstr"
),
"MifuFlush"
->
(
0xb11
,
"perfCntCondMifuFlush"
),
"MrawStall"
->
(
0xb12
,
"perfCntCondMrawStall"
),
"MexuBusy"
->
(
0xb13
,
"perfCntCondMexuBusy"
),
"MbpBRight"
->
(
0xb14
,
"MbpBRight"
),
"MbpBWrong"
->
(
0xb15
,
"MbpBWrong"
),
"MbpJRight"
->
(
0xb16
,
"MbpJRight"
),
"MbpJWrong"
->
(
0xb17
,
"MbpJWrong"
),
"MbpIRight"
->
(
0xb18
,
"MbpIRight"
),
"MbpIWrong"
->
(
0xb19
,
"MbpIWrong"
),
"MbpRRight"
->
(
0xb1a
,
"MbpRRight"
),
"MbpRWrong"
->
(
0xb1b
,
"MbpRWrong"
)
)
val
perfCntCond
=
List
.
fill
(
0x80
)(
WireInit
(
false
.
B
))
val
perfCntCond
=
List
.
fill
(
0x80
)(
WireInit
(
false
.
B
))
(
perfCnts
zip
perfCntCond
).
map
{
case
(
c
,
e
)
=>
{
when
(
e
)
{
c
:=
c
+
1.
U
}
}
}
BoringUtils
.
addSource
(
WireInit
(
true
.
B
),
"perfCntCondMcycle"
)
...
...
src/main/scala/noop/fu/LSU.scala
浏览文件 @
35377176
...
...
@@ -67,7 +67,7 @@ class LSU extends NOOPModule {
val
state
=
RegInit
(
s_idle
)
switch
(
state
)
{
is
(
s_idle
)
{
when
(
dmem
.
req
.
fire
())
{
state
:=
Mux
(
isStore
,
s_partialLoad
,
s_wait_resp
)
}
}
is
(
s_idle
)
{
when
(
dmem
.
req
.
fire
())
{
state
:=
s_wait_resp
}
}
is
(
s_wait_resp
)
{
when
(
dmem
.
resp
.
fire
())
{
state
:=
Mux
(
partialLoad
,
s_partialLoad
,
s_idle
)
}
}
is
(
s_partialLoad
)
{
state
:=
s_idle
}
}
...
...
@@ -78,7 +78,7 @@ class LSU extends NOOPModule {
dmem
.
req
.
valid
:=
valid
&&
(
state
===
s_idle
)
dmem
.
resp
.
ready
:=
true
.
B
io
.
out
.
valid
:=
Mux
(
isStore
||
partialLoad
,
state
===
s_partialLoad
,
dmem
.
resp
.
fire
()
&&
(
state
===
s_wait_resp
))
io
.
out
.
valid
:=
Mux
(
partialLoad
,
state
===
s_partialLoad
,
dmem
.
resp
.
fire
()
&&
(
state
===
s_wait_resp
))
io
.
in
.
ready
:=
(
state
===
s_idle
)
val
rdata
=
dmem
.
resp
.
bits
.
rdata
...
...
src/main/scala/system/Coherence.scala
浏览文件 @
35377176
...
...
@@ -11,107 +11,73 @@ trait HasCoherenceParameter extends HasNOOPParameter {
val
supportCoh
=
HasDcache
}
class
Coherence
Interconnect
extends
Module
with
HasCoherenceParameter
{
class
Coherence
Manager
extends
Module
with
HasCoherenceParameter
{
val
io
=
IO
(
new
Bundle
{
val
in
=
Flipped
(
Vec
(
2
,
new
SimpleBusC
))
val
out
=
new
SimpleBusUC
val
in
=
Flipped
(
new
SimpleBusUC
)
val
out
=
new
Bundle
{
val
mem
=
new
SimpleBusUC
val
coh
=
new
SimpleBusUC
}
})
def
anotherMaster
(
thisMaster
:
UInt
)
=
Mux
(
thisMaster
===
1.
U
,
0.
U
,
1.
U
)
def
isDcache
()
=
inputArb
.
io
.
chosen
===
1.
U
// state transition:
// write: s_idle -> s_memWriteResp -> s_idle
// read from Dcache: s_idle -> s_memResp -> s_idle
// read from Icache: s_idle -> s_probeResp -> (hit) s_probeForward -> s_idle
// +> (miss) s_memReadReq -> s_memReadResp -> s_idle
// read: s_idle -> s_probeResp -> (hit) s_probeForward -> s_idle
// +> (miss) s_memReadReq -> s_memReadResp -> s_idle
val
s_idle
::
s_probeResp
::
s_probeForward
::
s_memReadReq
::
s_memReadResp
::
s_memWriteResp
::
Nil
=
Enum
(
6
)
val
state
=
RegInit
(
s_idle
)
val
inflight
=
state
=/=
s_idle
val
inflight
=
RegInit
(
false
.
B
)
val
inflightSrc
=
Reg
(
UInt
(
1.
W
))
// 0 - icache, 1 - dcache
val
lockWriteFun
=
((
x
:
SimpleBusReqBundle
)
=>
x
.
isWrite
()
&&
x
.
isBurst
())
val
inputArb
=
Module
(
new
LockingArbiter
(
chiselTypeOf
(
io
.
in
(
0
).
mem
.
req
.
bits
),
2
,
8
,
Some
(
lockWriteFun
)))
(
inputArb
.
io
.
in
zip
io
.
in
.
map
(
_
.
mem
.
req
)).
map
{
case
(
arb
,
in
)
=>
arb
<>
in
}
val
thisReq
=
inputArb
.
io
.
out
val
thisReq
=
io
.
in
.
req
assert
(!(
thisReq
.
valid
&&
!
thisReq
.
bits
.
isRead
()
&&
!
thisReq
.
bits
.
isWrite
()))
// when read, we should first probe
another master
// when read, we should first probe
dcache
val
reqLatch
=
RegEnable
(
thisReq
.
bits
,
!
inflight
&&
thisReq
.
bits
.
isRead
())
io
.
in
.
map
(
_
.
coh
).
map
{
case
c
=>
{
io
.
out
.
coh
match
{
case
c
=>
{
c
.
req
.
bits
:=
thisReq
.
bits
c
.
req
.
bits
.
cmd
:=
SimpleBusCmd
.
probe
c
.
resp
.
ready
:=
true
.
B
}}
io
.
out
.
req
.
bits
:=
thisReq
.
bits
io
.
out
.
mem
.
req
.
bits
:=
thisReq
.
bits
// bind correct valid and ready signals
io
.
out
.
req
.
valid
:=
false
.
B
io
.
out
.
mem
.
req
.
valid
:=
false
.
B
thisReq
.
ready
:=
false
.
B
io
.
in
.
map
(
_
.
coh
.
req
.
valid
).
map
{
_
:=
false
.
B
}
when
(
if
(
supportCoh
)
(
thisReq
.
bits
.
isWrite
()
||
isDcache
()
)
else
true
.
B
)
{
io
.
out
.
req
.
valid
:=
thisReq
.
valid
&&
!
inflight
thisReq
.
ready
:=
io
.
out
.
req
.
ready
&&
!
inflight
io
.
out
.
coh
.
req
.
valid
:=
false
.
B
when
(
if
(
supportCoh
)
thisReq
.
bits
.
isWrite
(
)
else
true
.
B
)
{
io
.
out
.
mem
.
req
.
valid
:=
thisReq
.
valid
&&
!
inflight
thisReq
.
ready
:=
io
.
out
.
mem
.
req
.
ready
&&
!
inflight
}
.
elsewhen
(
thisReq
.
bits
.
isRead
())
{
io
.
in
(
anotherMaster
(
inputArb
.
io
.
chosen
))
.
coh
.
req
.
valid
:=
thisReq
.
valid
&&
!
inflight
thisReq
.
ready
:=
io
.
in
(
anotherMaster
(
inputArb
.
io
.
chosen
))
.
coh
.
req
.
ready
&&
!
inflight
io
.
out
.
coh
.
req
.
valid
:=
thisReq
.
valid
&&
!
inflight
thisReq
.
ready
:=
io
.
out
.
coh
.
req
.
ready
&&
!
inflight
}
io
.
in
.
map
(
_
.
mem
.
resp
.
bits
:=
io
.
out
.
resp
.
bits
)
io
.
in
.
map
(
_
.
mem
.
resp
.
valid
:=
false
.
B
)
(
io
.
in
(
inflightSrc
).
mem
.
resp
,
io
.
out
.
resp
)
match
{
case
(
l
,
r
)
=>
{
l
.
valid
:=
r
.
valid
r
.
ready
:=
l
.
ready
}}
io
.
in
.
resp
<>
io
.
out
.
mem
.
resp
switch
(
state
)
{
is
(
s_idle
)
{
when
(
thisReq
.
fire
())
{
inflightSrc
:=
inputArb
.
io
.
chosen
when
(
thisReq
.
bits
.
isRead
())
{
inflight
:=
true
.
B
state
:=
Mux
(
if
(
supportCoh
)
isDcache
()
else
true
.
B
,
s_memReadResp
,
s_probeResp
)
}
.
elsewhen
(
thisReq
.
bits
.
isWriteLast
())
{
inflight
:=
true
.
B
state
:=
s_memWriteResp
}
when
(
thisReq
.
bits
.
isRead
())
{
state
:=
Mux
(
supportCoh
.
B
,
s_probeResp
,
s_memReadResp
)
}
.
elsewhen
(
thisReq
.
bits
.
isWriteLast
())
{
state
:=
s_memWriteResp
}
}
}
is
(
s_probeResp
)
{
when
(
io
.
in
(
anotherMaster
(
inflightSrc
))
.
coh
.
resp
.
fire
())
{
state
:=
Mux
(
io
.
in
(
anotherMaster
(
inflightSrc
))
.
coh
.
resp
.
bits
.
isProbeHit
(),
s_probeForward
,
s_memReadReq
)
when
(
io
.
out
.
coh
.
resp
.
fire
())
{
state
:=
Mux
(
io
.
out
.
coh
.
resp
.
bits
.
isProbeHit
(),
s_probeForward
,
s_memReadReq
)
}
}
is
(
s_probeForward
)
{
val
thisResp
=
io
.
in
(
inflightSrc
).
mem
.
resp
val
anotherCohResp
=
io
.
in
(
anotherMaster
(
inflightSrc
)).
coh
.
resp
thisResp
.
bits
:=
anotherCohResp
.
bits
thisResp
.
valid
:=
anotherCohResp
.
valid
anotherCohResp
.
ready
:=
thisResp
.
ready
when
(
thisResp
.
fire
()
&&
thisResp
.
bits
.
isReadLast
())
{
inflight
:=
false
.
B
state
:=
s_idle
}
val
thisResp
=
io
.
in
.
resp
thisResp
<>
io
.
out
.
coh
.
resp
when
(
thisResp
.
fire
()
&&
thisResp
.
bits
.
isReadLast
())
{
state
:=
s_idle
}
}
is
(
s_memReadReq
)
{
io
.
out
.
req
.
bits
:=
reqLatch
io
.
out
.
req
.
valid
:=
true
.
B
when
(
io
.
out
.
req
.
fire
())
{
state
:=
s_memReadResp
}
}
is
(
s_memReadResp
)
{
when
(
io
.
out
.
resp
.
fire
()
&&
io
.
out
.
resp
.
bits
.
isReadLast
())
{
inflight
:=
false
.
B
state
:=
s_idle
}
}
is
(
s_memWriteResp
)
{
when
(
io
.
out
.
resp
.
fire
())
{
inflight
:=
false
.
B
state
:=
s_idle
}
io
.
out
.
mem
.
req
.
bits
:=
reqLatch
io
.
out
.
mem
.
req
.
valid
:=
true
.
B
when
(
io
.
out
.
mem
.
req
.
fire
())
{
state
:=
s_memReadResp
}
}
is
(
s_memReadResp
)
{
when
(
io
.
out
.
mem
.
resp
.
fire
()
&&
io
.
out
.
mem
.
resp
.
bits
.
isReadLast
())
{
state
:=
s_idle
}
}
is
(
s_memWriteResp
)
{
when
(
io
.
out
.
mem
.
resp
.
fire
())
{
state
:=
s_idle
}
}
}
}
src/main/scala/system/Prefetcher.scala
浏览文件 @
35377176
package
system
import
noop.
{
NOOP
,
NOOPConfig
,
HasNOOPParameter
,
Cache
,
L2Cache
,
CacheConfig
}
import
noop.
{
NOOP
,
NOOPConfig
,
HasNOOPParameter
,
Cache
,
CacheConfig
}
import
bus.axi4.
{
AXI4
,
AXI4Lite
}
import
bus.simplebus._
...
...
src/main/scala/system/SoC.scala
浏览文件 @
35377176
package
system
import
noop.
{
NOOP
,
NOOPConfig
,
Cache
,
L2Cache
,
CacheConfig
}
import
noop.
_
import
bus.axi4.
{
AXI4
,
AXI4Lite
}
import
bus.simplebus._
...
...
@@ -8,7 +8,7 @@ import chisel3._
import
chisel3.util._
import
chisel3.util.experimental.BoringUtils
class
NOOPSoC
(
implicit
val
p
:
NOOPConfig
)
extends
Module
{
class
NOOPSoC
(
implicit
val
p
:
NOOPConfig
)
extends
NOOP
Module
{
val
io
=
IO
(
new
Bundle
{
val
mem
=
new
AXI4
val
mmio
=
(
if
(
p
.
FPGAPlatform
)
{
new
AXI4Lite
}
else
{
new
SimpleBusUC
})
...
...
@@ -17,54 +17,47 @@ class NOOPSoC(implicit val p: NOOPConfig) extends Module {
})
val
noop
=
Module
(
new
NOOP
)
val
cohMg
=
Module
(
new
CoherenceInterconnect
)
cohMg
.
io
.
in
(
0
)
<>
noop
.
io
.
imem
cohMg
.
io
.
in
(
1
)
<>
noop
.
io
.
dmem
// add L2 Cache and Dcache Prefetcher
/*
val prefetcher = Module(new Prefetcher)
prefetcher.io.in <> noop.io.prefetchReq
val
l2cacheIn = Wire(new SimpleBusUC
)
val l2cacheInReqArb = Module(new Arbiter(chiselTypeOf(noop.io.prefetchReq.bits),
2))
l2cacheInReqArb.io.in(0) <> cohMg.io.out.req
l2cacheInReqArb.io.in(1) <> prefetcher.io.out
l2cacheIn.req <> l2cacheInReqArb.io.out
cohMg.io.out.resp <> l2cacheIn.resp
val
cohMg
=
Module
(
new
CoherenceManager
)
val
xbar
=
Module
(
new
SimpleBusCrossbarNto1
(
2
))
cohMg
.
io
.
in
<>
noop
.
io
.
imem
.
mem
noop
.
io
.
dmem
.
coh
<>
cohMg
.
io
.
out
.
coh
xbar
.
io
.
in
(
0
)
<>
cohMg
.
io
.
out
.
mem
xbar
.
io
.
in
(
1
)
<>
noop
.
io
.
dmem
.
mem
val mmioXbar = Module(new SimpleBusCrossbarNto1(2))
val l2cacheOut = Wire(new SimpleBusUC)
l2cacheOut <> Cache(in = l2cacheIn, mmio = mmioXbar.io.in(0), flush = "b00".U, enable = true)(CacheConfig(ro = false, name = "l2cache", cacheLevel = 2))
io.mem <> l2cacheOut.toAXI4()
if
(
HasL2cache
)
{
val
l2cacheOut
=
Wire
(
new
SimpleBusC
)
if
(
HasPrefetch
)
{
val
prefetcher
=
Module
(
new
Prefetcher
)
prefetcher
.
io
.
in
<>
noop
.
io
.
prefetchReq
val
l2cacheIn
=
Wire
(
new
SimpleBusUC
)
val
l2cacheInReqArb
=
Module
(
new
Arbiter
(
chiselTypeOf
(
noop
.
io
.
prefetchReq
.
bits
),
2
))
l2cacheInReqArb
.
io
.
in
(
0
)
<>
xbar
.
io
.
out
.
req
l2cacheInReqArb
.
io
.
in
(
1
)
<>
prefetcher
.
io
.
out
l2cacheIn
.
req
<>
l2cacheInReqArb
.
io
.
out
xbar
.
io
.
out
.
resp
<>
l2cacheIn
.
resp
l2cacheOut
<>
Cache
(
in
=
l2cacheIn
,
mmio
=
0.
U
.
asTypeOf
(
new
SimpleBusUC
),
flush
=
"b00"
.
U
,
enable
=
true
)(
CacheConfig
(
ro
=
false
,
name
=
"l2cache"
,
cacheLevel
=
2
))
}
else
{
l2cacheOut
<>
Cache
(
in
=
xbar
.
io
.
out
,
mmio
=
0.
U
.
asTypeOf
(
new
SimpleBusUC
),
flush
=
"b00"
.
U
,
enable
=
true
)(
CacheConfig
(
ro
=
false
,
name
=
"l2cache"
,
cacheLevel
=
2
))
}
io
.
mem
<>
l2cacheOut
.
mem
.
toAXI4
()
l2cacheOut
.
coh
.
resp
.
ready
:=
true
.
B
l2cacheOut
.
coh
.
req
.
valid
:=
false
.
B
l2cacheOut
.
coh
.
req
.
bits
:=
DontCare
}
else
{
io
.
mem
<>
xbar
.
io
.
out
.
toAXI4
()
}
mmioXbar.io.in(1) <> noop.io.mmio
if (p.FPGAPlatform) io.mmio <> mmioXbar.io.out.toAXI4Lite()
else io.mmio <> mmioXbar.io.out
*/
// add L2 Cache
/*
val mmioXbar = Module(new SimpleBusCrossbarNto1(2))
val l2cacheOut = Wire(new SimpleBusUC)
l2cacheOut <> Cache(in = cohMg.io.out, mmio = mmioXbar.io.in(0), flush = "b00".U, enable = true)(CacheConfig(ro = false, name = "l2cache", cacheLevel = 2))
io.mem <> l2cacheOut.toAXI4()
if
(!
HasPrefetch
)
{
noop
.
io
.
prefetchReq
.
ready
:=
true
.
B
}
mmioXbar.io.in(1) <> noop.io.mmio
if (p.FPGAPlatform) io.mmio <> mmioXbar.io.out.toAXI4Lite()
else io.mmio <> mmioXbar.io.out
*/
// no L2 Cache
io
.
mem
<>
cohMg
.
io
.
out
.
toAXI4
()
noop
.
io
.
imem
.
coh
.
resp
.
ready
:=
true
.
B
noop
.
io
.
imem
.
coh
.
req
.
valid
:=
false
.
B
noop
.
io
.
imem
.
coh
.
req
.
bits
:=
DontCare
if
(
p
.
FPGAPlatform
)
io
.
mmio
<>
noop
.
io
.
mmio
.
toAXI4Lite
()
else
io
.
mmio
<>
noop
.
io
.
mmio
val
mtipSync
=
RegNext
(
RegNext
(
io
.
mtip
))
val
meipSync
=
RegNext
(
RegNext
(
io
.
meip
))
...
...
src/main/scala/utils/Debug.scala
浏览文件 @
35377176
...
...
@@ -12,4 +12,4 @@ object Debug {
object
ShowType
{
def
apply
[
T:
Manifest
](
t
:
T
)
=
println
(
manifest
[
T
])
}
}
src/main/scala/utils/Lock.scala
0 → 100644
浏览文件 @
35377176
package
utils
import
chisel3._
import
chisel3.util._
class
LockBundle
extends
Bundle
{
val
lock
=
Input
(
Bool
())
val
unlock
=
Input
(
Bool
())
val
holding
=
Output
(
Bool
())
}
class
Lock
(
n
:
Int
)
extends
Module
{
val
io
=
IO
(
new
Bundle
{
val
bundle
=
Vec
(
n
,
new
LockBundle
)
})
val
lock
=
RegInit
(
0.
U
(
n
.
W
))
val
lockReq
=
VecInit
(
io
.
bundle
.
map
(
_
.
lock
)).
asUInt
val
unlockReq
=
VecInit
(
io
.
bundle
.
map
(
_
.
unlock
)).
asUInt
val
lockEmpty
=
lock
===
0.
U
val
hasLockReq
=
lockReq
=/=
0.
U
val
lockNext
=
1.
U
<<
PriorityEncoder
(
lockReq
)
when
(
lockEmpty
&&
hasLockReq
)
{
lock
:=
lockNext
}
val
hasUnlockReq
=
unlockReq
=/=
0.
U
assert
(
PopCount
(
unlockReq
)
<=
1.
U
,
"only the lock holder can issue unlock request"
)
assert
(!(
lockEmpty
&&
hasUnlockReq
),
"only the lock holder can issue unlock request"
)
assert
((
lock
&
lockReq
)
===
0.
U
,
"can not issue lock request when holding the lock"
)
when
(!
lockEmpty
&&
hasUnlockReq
)
{
assert
(
unlockReq
===
lock
,
"only the lock holder can issue unlock request"
)
lock
:=
0.
U
}
val
holding
=
Mux
(
lockEmpty
&&
hasLockReq
,
lockNext
,
lock
)
io
.
bundle
.
map
(
_
.
holding
).
zip
(
holding
.
asBools
).
map
{
case
(
l
,
r
)
=>
l
:=
r
}
assert
(
PopCount
(
io
.
bundle
.
map
(
_
.
holding
))
<=
1.
U
,
"there should be only one lock holder"
)
Debug
()
{
when
(
lockEmpty
&&
hasLockReq
)
{
printf
(
"%d: %d acquire lock\n"
,
GTimer
(),
PriorityEncoder
(
lockNext
))
}
when
(!
lockEmpty
&&
hasUnlockReq
)
{
printf
(
"%d: %d release lock\n"
,
GTimer
(),
PriorityEncoder
(
lock
))
}
}
}
src/main/scala/utils/SRAMTemplate.scala
浏览文件 @
35377176
...
...
@@ -84,4 +84,33 @@ class SRAMTemplate[T <: Data](gen: T, set: Int, way: Int = 1,
io
.
r
.
req
.
ready
:=
!
resetState
&&
(
if
(
singlePort
)
!
wen
else
true
.
B
)
io
.
w
.
req
.
ready
:=
true
.
B
Debug
(
false
)
{
when
(
wen
)
{
printf
(
"%d: SRAMTemplate: write %x to idx = %d\n"
,
GTimer
(),
wdata
.
asUInt
,
setIdx
)
}
when
(
RegNext
(
realRen
))
{
printf
(
"%d: SRAMTemplate: read %x at idx = %d\n"
,
GTimer
(),
VecInit
(
rdata
).
asUInt
,
RegNext
(
io
.
r
.
req
.
bits
.
setIdx
))
}
}
}
class
SRAMTemplateWithArbiter
[
T
<:
Data
](
nRead
:
Int
,
gen
:
T
,
set
:
Int
,
way
:
Int
=
1
,
shouldReset
:
Boolean
=
false
)
extends
Module
{
val
io
=
IO
(
new
Bundle
{
val
r
=
Flipped
(
Vec
(
nRead
,
new
SRAMReadBus
(
gen
,
set
,
way
)))
val
w
=
Flipped
(
new
SRAMWriteBus
(
gen
,
set
,
way
))
})
val
ram
=
Module
(
new
SRAMTemplate
(
gen
,
set
,
way
,
shouldReset
,
holdRead
=
false
,
singlePort
=
true
))
ram
.
io
.
w
<>
io
.
w
val
readArb
=
Module
(
new
Arbiter
(
chiselTypeOf
(
io
.
r
(
0
).
req
.
bits
),
nRead
))
readArb
.
io
.
in
<>
io
.
r
.
map
(
_
.
req
)
ram
.
io
.
r
.
req
<>
readArb
.
io
.
out
// latch read results
io
.
r
.
map
{
case
r
=>
{
r
.
resp
.
data
:=
HoldUnless
(
ram
.
io
.
r
.
resp
.
data
,
RegNext
(
r
.
req
.
fire
()))
}}
}
src/test/csrc/emu.h
浏览文件 @
35377176
...
...
@@ -102,7 +102,9 @@ class Emulator {
n
--
;
if
(
lastcommit
-
n
>
stuck_limit
&&
hascommit
)
{
eprintf
(
"No instruction commits for %d cycles, maybe get stuck
\n
"
,
stuck_limit
);
eprintf
(
"No instruction commits for %d cycles, maybe get stuck
\n
"
"(please also check whether a fence.i instruction requires more than %d cycles to flush the icache)
\n
"
,
stuck_limit
,
stuck_limit
);
set_abort
();
}
...
...
@@ -128,7 +130,23 @@ class Emulator {
}
}
void
execute
()
{
execute_cycles
(
max_cycles
);
}
void
cache_test
(
uint64_t
n
)
{
while
(
n
>
0
)
{
single_cycle
();
n
--
;
}
}
void
execute
()
{
//#define CACHE_TEST
#ifdef CACHE_TEST
eprintf
(
ANSI_COLOR_MAGENTA
"This is random test for cache.
\n
"
ANSI_COLOR_RESET
);
cache_test
(
max_cycles
);
#else
execute_cycles
(
max_cycles
);
#endif
}
uint64_t
get_cycles
()
const
{
return
cycles
;
}
uint64_t
get_max_cycles
()
const
{
return
max_cycles
;
}
};
src/test/scala/cache/CacheTest.scala
0 → 100644
浏览文件 @
35377176
package
top
import
noop._
import
bus.simplebus._
import
device._
import
utils._
import
chisel3._
import
chisel3.util._
import
chisel3.util.experimental.BoringUtils
// To run the following cache random test, do the following:
// * uncomment the following class
// * comment the NOOPSimTop class in noop/src/test/scala/top/NOOPSim.scala
// * define the macro CACHE_TEST in noop/src/test/csrc/emu.h:141
// * run 'make cache' under noop/
/*
class NOOPSimTop extends Module {
val io = IO(new Bundle{
val difftest = new DiffTestIO
})
val memBase = 0x80000000L
val cacheSizeKB = 1 // Bytes
val memSizeB = 4096 // Bytes
val NRmemBlock = memSizeB / 8
val printCnt = 100000
val Name = "dcache"
val in = WireInit(0.U.asTypeOf(new SimpleBusUC(userBits = 33)))
val cohIn = WireInit(0.U.asTypeOf(new SimpleBusUC))
val mmioOut = WireInit(0.U.asTypeOf(new SimpleBusUC))
val cacheOut = Cache(in, mmioOut, "b00".U)(CacheConfig(name = Name, totalSize = cacheSizeKB, userBits = 33, ways = 4))
val mem = Module(new AXI4RAM(memByte = memSizeB, useBlackBox = false))
mem.io.in <> cacheOut.mem.toAXI4()
cacheOut.coh <> cohIn
def addrInRange(x: UInt) = (x >= memBase.U) && x < (memBase + memSizeB).U
val perfCntHit = WireInit(false.B)
BoringUtils.addSink(perfCntHit, "perfCntCondM" + Name + "Hit")
val s_init_req :: s_init_resp :: s_test :: Nil = Enum(3)
val state = RegInit(s_init_req)
val initCnt = Counter(NRmemBlock)
switch (state) {
is (s_init_req) {
when (in.req.fire()) { state := s_init_resp }
}
is (s_init_resp) {
when (in.resp.fire()) {
val wrap = initCnt.inc()
state := Mux(wrap, s_test, s_init_req)
when (wrap) {
printf("One '.' for handling %d requests from CPU, and one '@' for handling %d coherence requests\n",
printCnt.U, printCnt.U)
}
}
}
}
val initAddr = memBase.U + initCnt.value * 8.U
val initWmask = 0xff.U
val initCmd = SimpleBusCmd.write
val randBundle = new Bundle {
val isWrite = Bool()
val readyChoose = UInt(2.W)
val wmask = UInt(8.W)
val addr = UInt(log2Up(NRmemBlock).W)
val cohChoose = UInt(1.W)
val cohAddr = UInt(log2Up(NRmemBlock).W)
val cohReadyChoose = UInt(2.W)
}
val rand = LFSR64(true.B).asTypeOf(randBundle)
val randAddr = memBase.U + rand.addr * 8.U
val randWmask = rand.wmask
val randCmd = Mux(rand.isWrite, SimpleBusCmd.write, SimpleBusCmd.read)
val addr = Mux(state === s_test, randAddr, initAddr)
val wmask = Mux(state === s_test, randWmask, initWmask)
val cmd = Mux(state === s_test, randCmd, initCmd)
val wdata = Fill(2, addr)
val user = Cat(addr, Mux(state === s_test, rand.isWrite, true.B))
in.req.bits.apply(addr = addr, size = "b11".U, user = user,
wdata = wdata, wmask = wmask, cmd = cmd)
in.req.valid := (state === s_init_req) || (state === s_test)
in.resp.ready := rand.readyChoose =/= 0.U
val cohInflight = RegInit(false.B)
when (cohIn.resp.fire()) {
val resp = cohIn.resp.bits
val isProbeEnd = resp.isProbeMiss() || (resp.cmd === SimpleBusCmd.readLast)
when (isProbeEnd) { cohInflight := false.B }
}
when (cohIn.req.fire()) { cohInflight := true.B }
cohIn.req.bits.apply(addr = rand.cohAddr * 8.U + memBase.U, size = "b11".U,
wdata = 0.U, wmask = 0.U, cmd = SimpleBusCmd.probe)
cohIn.req.valid := (state === s_test) && rand.cohChoose === 0.U && !cohInflight
cohIn.resp.ready := rand.cohReadyChoose =/= 0.U
when (Counter((state === s_test) && in.resp.fire(), printCnt)._2) { printf(".") }
when (Counter((state === s_test) && cohIn.req.fire(), printCnt)._2) { printf("@") }
Debug(false) {
when (in.req.fire()) { printf(p"${GTimer()},[in.req] ${in.req.bits}\n") }
}
def checkData(addr: UInt, data: UInt): Bool = data === Fill(2, addr)
def checkDataMask(addr: UInt, data: UInt): Bool = {
val mask = "hffffffc0".U
(data & Fill(2, mask)) === Fill(2, addr & mask)
}
assert(!(cacheOut.mem.req.valid && !addrInRange(cacheOut.mem.req.bits.addr)),
"bad addr = %x", cacheOut.mem.req.bits.addr)
// check rdata from cache
when (in.resp.valid && !in.resp.bits.user.get(0)) {
val addr = in.resp.bits.user.get(32,1)
assert(checkData(addr, in.resp.bits.rdata), "%d: bad rdata = %x at addr = %x",
GTimer(), in.resp.bits.rdata, addr)
}
// check wdata to mem
when (cacheOut.mem.req.valid && cacheOut.mem.req.bits.isWrite()) {
val addr = cacheOut.mem.req.bits.addr(31,0)
assert(checkDataMask(addr, cacheOut.mem.req.bits.wdata), "%d: bad wdata = %x at addr = %x",
GTimer(), cacheOut.mem.req.bits.wdata, addr)
}
// check rdata from cohIn
val cohAddr = RegEnable(cohIn.req.bits.addr(31,0), cohIn.req.fire())
when (cohIn.resp.valid) {
val resp = cohIn.resp.bits
val isRead = resp.cmd === SimpleBusCmd.readLast || resp.cmd === SimpleBusCmd.read
val isProbeResp = resp.isProbeHit() || resp.isProbeMiss()
assert(isRead || isProbeResp)
assert(!(isRead && !checkDataMask(cohAddr, cohIn.resp.bits.rdata)), "%d: bad rdata = %x at addr = %x",
GTimer(), cohIn.resp.bits.rdata, cohAddr)
}
// only use to keep consistent with NOOPSimTop
io.difftest := DontCare
dontTouch(io.difftest)
}
*/
src/test/scala/top/SimMMIO.scala
浏览文件 @
35377176
...
...
@@ -13,13 +13,10 @@ class SimMMIO extends Module {
})
val
devAddrSpace
=
List
(
// (0x40600000L, 0x10L), // uart
(
0x40600000
L
,
0x100
L
),
// (0x40700000L, 0x10L), // timer
(
0x40700000
L
,
0x100
L
),
(
0x40600000
L
,
0x10
L
),
// uart
(
0x40700000
L
,
0x10
L
),
// timer
(
0x40000000
L
,
0x400000
L
),
// vmem
// (0x40800000L, 0x8L) // vga ctrl
(
0x40800000
L
,
0x80
L
)
(
0x40800000
L
,
0x8
L
)
// vga ctrl
)
val
xbar
=
Module
(
new
SimpleBusCrossbar1toN
(
devAddrSpace
))
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录