Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenXiangShan
XiangShan
提交
f6b17531
X
XiangShan
项目概览
OpenXiangShan
/
XiangShan
10 个月 前同步成功
通知
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,体验更适合开发者的 AI 搜索 >>
提交
f6b17531
编写于
7月 09, 2021
作者:
J
JinYue
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
ICache: support 2-request access.
上级
bcd542b4
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
418 addition
and
0 deletion
+418
-0
src/main/scala/xiangshan/decoupled-frontend/ICache.scala
src/main/scala/xiangshan/decoupled-frontend/ICache.scala
+418
-0
未找到文件。
src/main/scala/xiangshan/decoupled-frontend/ICache.scala
浏览文件 @
f6b17531
package
xiangshan.frontend
import
chipsalliance.rocketchip.config.Parameters
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
utils._
case
class
ICacheParameters
(
nSets
:
Int
=
64
,
nWays
:
Int
=
4
,
rowBits
:
Int
=
64
,
nTLBEntries
:
Int
=
32
,
tagECC
:
Option
[
String
]
=
None
,
dataECC
:
Option
[
String
]
=
None
,
replacer
:
Option
[
String
]
=
Some
(
"random"
),
nMissEntries
:
Int
=
1
,
nMMIOs
:
Int
=
1
,
blockBytes
:
Int
=
64
)
extends
L1CacheParameters
{
def
tagCode
:
Code
=
Code
.
fromString
(
tagECC
)
def
dataCode
:
Code
=
Code
.
fromString
(
dataECC
)
def
replacement
=
ReplacementPolicy
.
fromString
(
replacer
,
nWays
,
nSets
)
}
trait
Temperary
{
val
idxBits
=
log2Ceil
(
nSets
)
val
wayBits
=
log2Ceil
(
nWays
)
val
offBits
=
log2Ceil
(
blockBytes
)
val
tagBits
=
VAddrBits
-
idxBits
-
offBitsi
val
bbBits
=
log2Ceil
(
BASICBLOCKSIZE
.
W
)
}
abstract
class
ICacheBundle
(
implicit
p
:
Parameters
)
extends
XSBundle
with
HasICacheParameters
with
Temperary
abstract
class
ICacheModule
(
implicit
p
:
Parameters
)
extends
XSModule
with
HasICacheParameters
with
Temperary
abstract
class
ICacheArray
(
implicit
p
:
Parameters
)
extends
XSModule
with
HasICacheParameters
with
Temperary
class
ICacheReadBundle
(
implicit
p
:
Parameters
)
extends
ICacheBundle
{
val
isDoubleLine
=
Bool
()
val
vSetIdx
=
Vec
(
2
,
UInt
(
log2Ceil
(
nSets
).
W
))
}
class
ICacheMetaRespBundle
(
implicit
p
:
Parameters
)
extends
ICacheBundle
{
val
tags
=
Vec
(
2
,
Vec
(
nWays
,
UInt
(
tagBits
.
W
)))
val
valid
=
Vec
(
2
,
Vec
(
nWays
,
Bool
()))
}
class
ICacheMetaWriteBundle
(
implicit
p
:
Parameters
)
extends
ICacheBundle
{
val
virIdx
=
UInt
(
idxBits
.
W
)
val
phyTag
=
UInt
(
tagBits
.
W
)
val
waymask
=
UInt
(
nWays
.
W
)
def
apply
(
tag
:
UInt
,
idx
:
UInt
,
waymask
:
UInt
){
this
.
virIdx
:=
idx
this
.
phyTag
:=
tag
this
.
waymask
:=
waymask
}
}
class
ICacheDataWriteBundle
(
implicit
p
:
Parameters
)
extends
ICacheBundle
{
val
virIdx
=
UInt
(
idxBits
.
W
)
val
data
=
Vec
(
blockRows
,
UInt
(
blockBits
.
W
))
val
waymask
=
UInt
(
nWays
.
W
)
def
apply
(
data
:
Vec
[
UInt
],
idx
:
UInt
,
waymask
:
UInt
){
this
.
virIdx
:=
idx
this
.
data
:=
data
this
.
waymask
:=
waymask
}
}
class
ICacheDataReadBundle
(
implicit
p
:
Parameters
)
extends
ICacheBundle
{
val
datas
=
Vec
(
2
,
Vec
(
nWays
,
Vec
(
blockRows
,
UInt
(
blockBits
.
W
))))
}
class
ICacheMetaArray
(
implicit
p
:
Parameters
)
extends
ICacheArray
{
val
io
=
IO
{
new
Bundle
{
val
write
=
Flipped
(
DecoupledIO
(
new
ICacheMetaWriteBundle
))
val
read
=
Flipped
(
DecoupledIO
(
new
ICacheReadBundle
))
val
readResp
=
Output
(
new
ICacheMetaRespBundle
)
}}
val
tagArrays
=
(
0
until
2
)
map
{
bank
=>
val
tagArray
=
Module
(
new
SRAMTemplate
(
UInt
(
tagBits
.
W
),
set
=
nSets
/
2
,
way
=
nWays
,
shouldReset
=
true
,
holdRead
=
true
,
singlePort
=
true
))
//meta connection
if
(
i
==
0
)
tagArray
.
io
.
r
.
req
.
valid
:=
io
.
read
.
valid
else
tagArray
.
io
.
r
.
req
.
valid
:=
io
.
read
.
valid
&&
io
.
read
.
bits
.
isDoubleLine
tagArray
.
io
.
r
.
req
.
bits
.
apply
(
setIdx
=
io
.
read
.
bits
.
vSetIdx
)
if
(
i
==
0
)
tagArray
.
io
.
w
.
req
.
valid
:=
io
.
write
.
valid
&&
!
io
.
write
.
bits
.
bankIdx
else
tagArray
.
io
.
w
.
req
.
valid
:=
io
.
write
.
valid
&&
io
.
write
bits
.
bankIdx
tagArray
.
io
.
w
.
req
.
bits
.
apply
(
data
=
io
.
write
.
bits
.
phyTag
,
setIdx
=
io
.
write
.
virIdx
,
waymask
=
io
.
write
.
waymask
)
tagArray
}
val
readIdxNext
=
RegNext
(
io
.
read
.
bits
.
vSetIdx
)
val
validArray
=
RegInit
(
0.
U
(
nSets
*
nWays
).
W
)
val
validMetas
=
VecInit
(
readIdx
.
map
{
bank
=>
val
validMeta
=
Cat
((
0
until
nWays
).
map
{
w
=>
validArray
(
Cat
(
readIdxNext
(
bank
),
w
.
U
(
log2Ceil
(
nWays
).
W
)))}.
reverse
).
asUInt
validMeta
})
val
wayNum
=
OHToUInt
(
io
.
write
.
bits
.
waymask
)
val
validPtr
=
Cat
(
io
.
write
.
bits
.
vitIdx
,
wayNum
)
when
(
io
.
write
.
valid
){
validArray
:=
validArray
.
bitSet
(
validPtr
,
true
.
B
)
}
(
io
.
resp
.
tags
zip
tagArray
).
map
{
case
(
io
,
sram
)
=>
io
:=
sram
.
io
.
r
.
resp
.
asTypeOf
(
Vec
(
nWays
,
UInt
(
tagBits
.
W
))}
(
io
.
resp
.
valid
zip
validMetas
).
map
{
case
(
io
,
reg
)
=>
io
:=
reg
.
asTypeOf
(
Vec
(
nWays
,
Bool
()))}
}
class
ICacheDataArray
(
implicit
p
:
Parameters
)
extends
ICacheArray
{
val
io
=
IO
{
new
Bundle
{
val
write
=
Flipped
(
DecoupledIO
(
new
ICacheDataWriteBundle
))
val
read
=
Flipped
(
DecoupledIO
(
new
ICacheReadBundle
)))
val
readResp
=
Output
(
new
ICacheDataReadBundle
)
}}
//dataEntryBits = 144
val
dataArrays
=
(
0
untils
2
)
map
{
i
=>
val
dataArray
=
List
.
fill
(
nWays
){
Module
(
new
SRAMTemplate
(
UInt
(
blockBits
.
W
),
set
=
nSets
/
2
,
way
=
nWays
,
shouldReset
=
true
,
holdRead
=
true
,
singlePort
=
true
))}
//port
dataArray
.
map
{
way
=>
//meta connection
if
(
i
==
0
)
way
.
io
.
r
.
req
.
valid
:=
io
.
read
.
valid
else
way
.
io
.
r
.
req
.
valid
:=
io
.
read
.
valid
&&
io
.
read
.
bits
.
isDoubleLine
way
.
io
.
r
.
req
.
bits
.
apply
(
setIdx
=
io
.
read
.
bits
.
vSetIdx
)
if
(
i
==
0
)
way
.
io
.
w
.
req
.
valid
:=
io
.
write
.
valid
&&
!
io
.
write
.
bits
.
bankIdx
else
way
.
io
.
w
.
req
.
valid
:=
io
.
write
.
valid
&&
io
.
write
bits
.
bankIdx
way
.
io
.
w
.
req
.
bits
.
apply
(
data
=
io
.
write
.
bits
.
phyTag
,
setIdx
=
io
.
write
.
virIdx
,
waymask
=
io
.
write
.
waymask
)
}
dataArray
}
(
io
.
resp
.
datas
zip
dataArrays
).
map
{
case
(
io
,
sram
)
=>
io
:=
Cat
(
sram
.
map
(
way
=>
way
.
io
.
r
.
resp
.
asTypeOf
(
Vec
(
blockRows
,
UInt
(
rowBits
.
W
))))).
asTypeOf
(
Vec
(
nWays
,
Vec
(
blockRows
,
UInt
(
rowBits
.
W
))))}
io
.
write
.
ready
:=
DontCare
}
abstract
class
ICacheMissQueueModule
(
implicit
p
:
Parameters
)
extends
XSModule
with
HasICacheParameters
with
Temperary
abstract
class
ICacheMissQueueBundle
(
implicit
p
:
Parameters
)
extends
XSBundle
with
HasICacheParameters
with
Temperary
class
ICacheRefill
(
implicit
p
:
Parameters
)
extends
ICacheMissQueueBundle
{
val
refill_idx
=
UInt
(
idxBits
.
W
)
val
refill_data
=
UInt
(
blockBits
.
W
)
val
refill_waymask
=
UInt
(
nWays
.
W
)
def
apply
(
data
:
UInt
,
vSetIdx
:
UInt
,
waymask
:
UInt
)
=
{
this
.
refill_idx
:=
vSetIdx
this
.
refill_data
:=
data
this
.
refill_waymask
:=
waymask
}
}
class
ICacheMetaWrite
(
implicit
p
:
Parameters
)
extends
ICacheMissQueueBundle
{
val
meta_write_idx
=
UInt
(
idxBits
.
W
)
val
meta_write_tag
=
UInt
(
tagBits
.
W
)
val
meta_write_waymask
=
UInt
(
nWays
.
W
)
def
apply
(
tag
:
UInt
,
vSetIdx
:
UInt
,
waymask
:
UInt
)
=
{
this
.
meta_write_idx
:=
vSetIdx
this
.
meta_write_tag
:=
tag
this
.
meta_write_waymask
:=
waymask
}
}
class
IcacheMissReq
(
implicit
p
:
Parameters
)
extends
ICacheBundle
{
val
addr
=
UInt
(
PAddrBits
.
W
)
val
vSetIdx
=
UInt
(
idxBits
.
W
)
val
waymask
=
UInt
(
PredictWidth
.
W
)
val
clientID
=
UInt
(
log2Ceil
(
cacheParams
.
nMissEntries
).
W
)
def
apply
(
missAddr
:
UInt
,
missIdx
:
UInt
,
missWaymask
:
UInt
,
source
:
UInt
)
=
{
this
.
addr
:=
missAddr
this
.
vSetIdx
:=
missIdx
this
.
waymask
:=
missWaymask
this
.
clientID
:=
source
}
override
def
toPrintable
:
Printable
=
{
p
"addr=0x${Hexadecimal(addr)} vSetIdx=0x${Hexadecimal(vSetIdx)} waymask=${Binary(waymask)} clientID=${Binary(clientID)}"
}
}
class
IcacheMissResp
(
implicit
p
:
Parameters
)
extends
ICacheBundle
{
val
data
=
UInt
(
blockBits
.
W
)
val
clientID
=
UInt
(
log2Ceil
(
cacheParams
.
nMissEntries
).
W
)
}
class
IcacheMissEntry
(
implicit
p
:
Parameters
)
extends
ICacheMissQueueModule
{
val
io
=
IO
(
new
Bundle
{
// MSHR ID
val
id
=
Input
(
UInt
(
log2Up
(
cacheParams
.
nMissEntries
).
W
))
val
req
=
Flipped
(
DecoupledIO
(
new
IcacheMissReq
))
val
resp
=
DecoupledIO
(
new
IcacheMissResp
)
val
mem_acquire
=
DecoupledIO
(
new
L1plusCacheReq
)
val
mem_grant
=
Flipped
(
DecoupledIO
(
new
L1plusCacheResp
))
val
meta_write
=
DecoupledIO
(
new
ICacheMetaWrite
)
val
refill
=
DecoupledIO
(
new
ICacheRefill
)
})
val
s_idle
::
s_memReadReq
::
s_memReadResp
::
s_write_back
::
s_wait_resp
::
Nil
=
Enum
(
5
)
val
state
=
RegInit
(
s_idle
)
//req register
val
req
=
Reg
(
new
IcacheMissReq
)
val
req_idx
=
req
.
vSetIdx
//virtual index
val
req_tag
=
get_tag
(
req
.
addr
)
//physical tag
val
req_waymask
=
req
.
waymask
//8 for 64 bits bus and 2 for 256 bits
val
readBeatCnt
=
Counter
(
refillCycles
)
//val respDataReg = Reg(Vec(refillCycles,UInt(beatBits.W)))
val
respDataReg
=
Reg
(
UInt
(
blockBits
.
W
))
//initial
io
.
resp
.
bits
:=
DontCare
io
.
mem_acquire
.
bits
:=
DontCare
io
.
mem_grant
.
ready
:=
true
.
B
io
.
meta_write
.
bits
:=
DontCare
io
.
refill
.
bits
:=
DontCare
io
.
req
.
ready
:=
state
===
s_idle
io
.
mem_acquire
.
valid
:=
state
===
s_memReadReq
//flush register
val
needFlush
=
RegInit
(
false
.
B
)
when
(
io
.
flush
&&
(
state
=/=
s_idle
)
&&
(
state
=/=
s_wait_resp
)){
needFlush
:=
true
.
B
}
.
elsewhen
((
state
===
s_wait_resp
)
&&
needFlush
){
needFlush
:=
false
.
B
}
//state change
switch
(
state
){
is
(
s_idle
){
when
(
io
.
req
.
fire
()){
state
:=
s_memReadReq
req
:=
io
.
req
.
bits
}
}
// memory request
is
(
s_memReadReq
){
when
(
io
.
mem_acquire
.
fire
()){
state
:=
s_memReadResp
}
}
is
(
s_memReadResp
){
when
(
io
.
mem_grant
.
bits
.
id
===
io
.
id
&&
io
.
mem_grant
.
fire
())
{
respDataReg
:=
io
.
mem_grant
.
bits
.
data
state
:=
Mux
(
needFlush
||
io
.
flush
,
s_wait_resp
,
s_write_back
)
}
}
//TODO: Maybe this sate is noe necessary so we don't need respDataReg
is
(
s_write_back
){
when
((
io
.
refill
.
fire
()
&&
io
.
meta_write
.
fire
())
||
needFlush
){
state
:=
s_wait_resp
}
}
is
(
s_wait_resp
){
io
.
resp
.
bits
.
data
:=
respDataReg
.
asUInt
io
.
resp
.
bits
.
clientID
:=
req
.
clientID
when
(
io
.
resp
.
fire
()
||
needFlush
){
state
:=
s_idle
}
}
}
//refill write and meta write
//WARNING: Maybe could not finish refill in 1 cycle
io
.
meta_write
.
valid
:=
(
state
===
s_write_back
)
&&
!
needFlush
io
.
meta_write
.
bits
.
apply
(
tag
=
req_tag
,
vSetIdx
=
req_idx
,
waymask
=
req_waymask
)
io
.
refill
.
valid
:=
(
state
===
s_write_back
)
&&
!
needFlush
io
.
refill
.
bits
.
apply
(
data
=
respDataReg
.
asUInt
,
vSetIdx
=
req_idx
,
waymask
=
req_waymask
)
//mem request
io
.
mem_acquire
.
bits
.
cmd
:=
MemoryOpConstants
.
M_XRD
io
.
mem_acquire
.
bits
.
addr
:=
req
.
addr
io
.
mem_acquire
.
bits
.
id
:=
io
.
id
//resp to icache
io
.
resp
.
valid
:=
(
state
===
s_wait_resp
)
&&
!
needFlush
XSDebug
(
"[ICache MSHR %d] (req)valid:%d ready:%d req.addr:%x waymask:%b || Register: req:%x \n"
,
io
.
id
.
asUInt
,
io
.
req
.
valid
,
io
.
req
.
ready
,
io
.
req
.
bits
.
addr
,
io
.
req
.
bits
.
waymask
,
req
.
asUInt
)
XSDebug
(
"[ICache MSHR %d] (Info)state:%d needFlush:%d\n"
,
io
.
id
.
asUInt
,
state
,
needFlush
)
XSDebug
(
"[ICache MSHR %d] (mem_acquire) valid%d ready:%d\n"
,
io
.
id
.
asUInt
,
io
.
mem_acquire
.
valid
,
io
.
mem_acquire
.
ready
)
XSDebug
(
"[ICache MSHR %d] (mem_grant) valid%d ready:%d data:%x \n"
,
io
.
id
.
asUInt
,
io
.
mem_grant
.
valid
,
io
.
mem_grant
.
ready
,
io
.
mem_grant
.
bits
.
data
)
XSDebug
(
"[ICache MSHR %d] (meta_write) valid%d ready:%d tag:%x \n"
,
io
.
id
.
asUInt
,
io
.
meta_write
.
valid
,
io
.
meta_write
.
ready
,
io
.
meta_write
.
bits
.
meta_write_tag
)
XSDebug
(
"[ICache MSHR %d] (refill) valid%d ready:%d data:%x \n"
,
io
.
id
.
asUInt
,
io
.
refill
.
valid
,
io
.
refill
.
ready
,
io
.
refill
.
bits
.
refill_data
)
XSDebug
(
"[ICache MSHR %d] (resp) valid%d ready:%d \n"
,
io
.
id
.
asUInt
,
io
.
resp
.
valid
,
io
.
resp
.
ready
)
}
class
IcacheMissQueue
(
implicit
p
:
Parameters
)
extends
ICacheMissQueueModule
{
val
io
=
IO
(
new
Bundle
{
val
req
=
Flipped
(
DecoupledIO
(
new
IcacheMissReq
))
val
resp
=
DecoupledIO
(
new
IcacheMissResp
)
val
mem_acquire
=
DecoupledIO
(
new
L1plusCacheReq
)
val
mem_grant
=
Flipped
(
DecoupledIO
(
new
L1plusCacheResp
))
val
meta_write
=
DecoupledIO
(
new
ICacheMetaWrite
)
val
data_refill
=
DecoupledIO
(
new
ICacheRefill
)
})
val
resp_arb
=
Module
(
new
Arbiter
(
new
IcacheMissResp
,
cacheParams
.
nMissEntries
))
val
meta_write_arb
=
Module
(
new
Arbiter
(
new
ICacheMetaWrite
,
cacheParams
.
nMissEntries
))
val
refill_arb
=
Module
(
new
Arbiter
(
new
ICacheRefill
,
cacheParams
.
nMissEntries
))
val
mem_acquire_arb
=
Module
(
new
Arbiter
(
new
L1plusCacheReq
,
cacheParams
.
nMissEntries
))
//initial
io
.
mem_grant
.
ready
:=
true
.
B
val
entry_alloc_idx
=
Wire
(
UInt
())
val
req_ready
=
WireInit
(
false
.
B
)
val
entries
=
(
0
until
cacheParams
.
nMissEntries
)
map
{
i
=>
val
entry
=
Module
(
new
IcacheMissEntry
)
entry
.
io
.
id
:=
i
.
U
(
log2Up
(
cacheParams
.
nMissEntries
).
W
)
// entry req
entry
.
io
.
req
.
valid
:=
(
i
.
U
===
entry_alloc_idx
)
&&
io
.
req
.
valid
entry
.
io
.
req
.
bits
:=
io
.
req
.
bits
when
(
i
.
U
===
entry_alloc_idx
)
{
req_ready
:=
entry
.
io
.
req
.
ready
}
// entry resp
resp_arb
.
io
.
in
(
i
)
<>
entry
.
io
.
resp
meta_write_arb
.
io
.
in
(
i
)
<>
entry
.
io
.
meta_write
refill_arb
.
io
.
in
(
i
)
<>
entry
.
io
.
refill
mem_acquire_arb
.
io
.
in
(
i
)
<>
entry
.
io
.
mem_acquire
entry
.
io
.
mem_grant
.
valid
:=
false
.
B
entry
.
io
.
mem_grant
.
bits
:=
DontCare
when
(
io
.
mem_grant
.
bits
.
id
===
i
.
U
)
{
entry
.
io
.
mem_grant
<>
io
.
mem_grant
}
XSPerfAccumulate
(
"entryPenalty"
+
Integer
.
toString
(
i
,
10
),
BoolStopWatch
(
start
=
entry
.
io
.
req
.
fire
(),
stop
=
entry
.
io
.
resp
.
fire
()
||
entry
.
io
.
flush
,
startHighPriority
=
true
)
)
XSPerfAccumulate
(
"entryReq"
+
Integer
.
toString
(
i
,
10
),
entry
.
io
.
req
.
fire
())
entry
}
entry_alloc_idx
:=
PriorityEncoder
(
entries
.
map
(
m
=>
m
.
io
.
req
.
ready
))
io
.
req
.
ready
:=
req_ready
io
.
resp
<>
resp_arb
.
io
.
out
io
.
meta_write
<>
meta_write_arb
.
io
.
out
io
.
refill
<>
refill_arb
.
io
.
out
io
.
mem_acquire
<>
mem_acquire_arb
.
io
.
out
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录