Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenXiangShan
XiangShan
提交
a057a757
X
XiangShan
项目概览
OpenXiangShan
/
XiangShan
大约 1 年 前同步成功
通知
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,发现更多精彩内容 >>
未验证
提交
a057a757
编写于
1月 18, 2021
作者:
Y
Yinan Xu
提交者:
GitHub
1月 18, 2021
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #447 from RISCVERS/tlb-sp
Tlb: divide normal 4k page and super page in tlb and l2tlb
上级
48553637
cc714d38
变更
5
显示空白变更内容
内联
并排
Showing
5 changed file
with
345 addition
and
236 deletion
+345
-236
src/main/scala/xiangshan/XSCore.scala
src/main/scala/xiangshan/XSCore.scala
+4
-0
src/main/scala/xiangshan/backend/fu/CSR.scala
src/main/scala/xiangshan/backend/fu/CSR.scala
+10
-10
src/main/scala/xiangshan/cache/dtlb.scala
src/main/scala/xiangshan/cache/dtlb.scala
+185
-200
src/main/scala/xiangshan/cache/ptw.scala
src/main/scala/xiangshan/cache/ptw.scala
+136
-18
src/test/csrc/ram.cpp
src/test/csrc/ram.cpp
+10
-8
未找到文件。
src/main/scala/xiangshan/XSCore.scala
浏览文件 @
a057a757
...
...
@@ -89,7 +89,9 @@ case class XSCoreParameters
StoreBufferSize
:
Int
=
16
,
RefillSize
:
Int
=
512
,
TlbEntrySize
:
Int
=
32
,
TlbSPEntrySize
:
Int
=
4
,
TlbL2EntrySize
:
Int
=
256
,
// or 512
TlbL2SPEntrySize
:
Int
=
16
,
PtwL1EntrySize
:
Int
=
16
,
PtwL2EntrySize
:
Int
=
256
,
NumPerfCounters
:
Int
=
16
,
...
...
@@ -165,7 +167,9 @@ trait HasXSParameter {
val
RefillSize
=
core
.
RefillSize
val
DTLBWidth
=
core
.
LoadPipelineWidth
+
core
.
StorePipelineWidth
val
TlbEntrySize
=
core
.
TlbEntrySize
val
TlbSPEntrySize
=
core
.
TlbSPEntrySize
val
TlbL2EntrySize
=
core
.
TlbL2EntrySize
val
TlbL2SPEntrySize
=
core
.
TlbL2SPEntrySize
val
PtwL1EntrySize
=
core
.
PtwL1EntrySize
val
PtwL2EntrySize
=
core
.
PtwL2EntrySize
val
NumPerfCounters
=
core
.
NumPerfCounters
...
...
src/main/scala/xiangshan/backend/fu/CSR.scala
浏览文件 @
a057a757
src/main/scala/xiangshan/cache/dtlb.scala
浏览文件 @
a057a757
...
...
@@ -43,7 +43,7 @@ trait HasTlbConst extends HasXSParameter {
abstract
class
TlbBundle
extends
XSBundle
with
HasTlbConst
abstract
class
TlbModule
extends
XSModule
with
HasTlbConst
class
P
ermBundle
(
val
hasV
:
Boolean
=
true
)
extends
TlbBundle
{
class
P
tePermBundle
extends
TlbBundle
{
val
d
=
Bool
()
val
a
=
Bool
()
val
g
=
Bool
()
...
...
@@ -51,7 +51,6 @@ class PermBundle(val hasV: Boolean = true) extends TlbBundle {
val
x
=
Bool
()
val
w
=
Bool
()
val
r
=
Bool
()
if
(
hasV
)
{
val
v
=
Bool
()
}
override
def
toPrintable
:
Printable
=
{
p
"d:${d} a:${a} g:${g} u:${u} x:${x} w:${w} r:${r}"
// +
...
...
@@ -59,6 +58,27 @@ class PermBundle(val hasV: Boolean = true) extends TlbBundle {
}
}
class
TlbPermBundle
extends
TlbBundle
{
val
pf
=
Bool
()
// NOTE: if this is true, just raise pf
val
d
=
Bool
()
val
a
=
Bool
()
val
g
=
Bool
()
val
u
=
Bool
()
val
x
=
Bool
()
val
w
=
Bool
()
val
r
=
Bool
()
// pma perm check
// val at = Bool() // Access Type
// val as = Bool() // Atomic Swap
// val al = Bool() // Atomic Logical
// val aa = Bool() // Atomic Arithmetic
// TODO: add pma check
override
def
toPrintable
:
Printable
=
{
p
"pf:${pf} d:${d} a:${a} g:${g} u:${u} x:${x} w:${w} r:${r}"
}
}
class
comBundle
extends
TlbBundle
with
HasCircularQueuePtrHelper
{
val
roqIdx
=
new
RoqPtr
val
valid
=
Bool
()
...
...
@@ -73,111 +93,94 @@ object Compare {
}
}
class
TlbEntry
extends
TlbBundle
{
val
vpn
=
UInt
(
vpnLen
.
W
)
// tag is vpn
val
ppn
=
UInt
(
ppnLen
.
W
)
val
level
=
UInt
(
log2Up
(
Level
).
W
)
// 2 for 4KB, 1 for 2MB, 0 for 1GB
// val asid = UInt(asidLen.W), asid maybe expensive to support, but useless
// val v = Bool() // v&g is special, may need sperate storage?
val
perm
=
new
PermBundle
(
hasV
=
false
)
def
vpnHit
(
vpn
:
UInt
)
:
Bool
=
{
val
fullMask
=
VecInit
((
Seq
.
fill
(
vpnLen
)(
true
.
B
))).
asUInt
val
maskLevel
=
VecInit
((
Level
-
1
to
0
by
-
1
).
map
{
i
=>
// NOTE: level 2 for 4KB, 1 for 2MB, 0 for 1GB
Reverse
(
VecInit
(
Seq
.
fill
(
vpnLen
-
i
*
vpnnLen
)(
true
.
B
)
++
Seq
.
fill
(
i
*
vpnnLen
)(
false
.
B
)).
asUInt
)})
val
mask
=
maskLevel
(
level
)
(
mask
&
this
.
vpn
)
===
(
mask
&
vpn
)
// multi-read && single-write
// input is data, output is hot-code(not one-hot)
class
CAMTemplate
[
T
<:
Data
](
val
gen
:
T
,
val
set
:
Int
,
val
readWidth
:
Int
)
extends
TlbModule
{
val
io
=
IO
(
new
Bundle
{
val
r
=
new
Bundle
{
val
req
=
Input
(
Vec
(
readWidth
,
gen
))
val
resp
=
Output
(
Vec
(
readWidth
,
UInt
(
set
.
W
)))
}
val
w
=
Flipped
(
ValidIO
(
new
Bundle
{
val
index
=
UInt
(
log2Up
(
set
).
W
)
val
data
=
gen
}))
})
// def asidHit(asid: UInt) = {
// this.asid === asid
// }
val
wordType
=
UInt
(
gen
.
getWidth
.
W
)
val
array
=
Reg
(
Vec
(
set
,
wordType
))
def
hit
(
vpn
:
UInt/*
,
asid
:
UInt*/
)
:
Bool
=
{
vpnHit
(
vpn
)
// && asidHit(asid)
io
.
r
.
resp
.
zipWithIndex
.
map
{
case
(
a
,
i
)
=>
a
:=
VecInit
(
array
.
map
(
io
.
r
.
req
(
i
).
asUInt
===
_
)).
asUInt
}
def
genTlbEntry
(
pte
:
UInt
,
level
:
UInt
,
vpn
:
UInt/*
,
asid
:
UInt*/
)
=
{
val
e
=
Wire
(
new
TlbEntry
)
e
.
ppn
:=
pte
.
asTypeOf
(
pteBundle
).
ppn
e
.
level
:=
level
e
.
vpn
:=
vpn
e
.
perm
:=
pte
.
asTypeOf
(
pteBundle
).
perm
// e.asid := asid
e
when
(
io
.
w
.
valid
)
{
array
(
io
.
w
.
bits
.
index
)
:=
io
.
w
.
bits
.
data
}
}
class
TlbEntryData
extends
TlbBundle
{
val
ppn
=
UInt
(
ppnLen
.
W
)
val
perm
=
new
TlbPermBundle
// TODO: change perm to every kinds of pf check
override
def
toPrintable
:
Printable
=
{
p
"
vpn:0x${Hexadecimal(vpn)} ppn:0x${Hexadecimal(ppn)} level:${level
} perm:${perm}"
p
"
ppn:0x${Hexadecimal(ppn)
} perm:${perm}"
}
}
class
TlbEntires
(
num
:
Int
,
tagLen
:
Int
)
extends
TlbBundle
{
require
(
log2Up
(
num
)==
log2Down
(
num
))
/* vpn can be divide into three part */
// vpn: tagPart(17bit) + addrPart(8bit) + cutLenPart(2bit)
val
cutLen
=
log2Up
(
num
)
class
TlbEntry
(
superpage
:
Boolean
=
false
)
extends
TlbBundle
{
val
tag
=
UInt
(
vpnLen
.
W
)
// tag is vpn
val
level
=
if
(
superpage
)
Some
(
UInt
(
1.
W
))
else
None
// /*2 for 4KB,*/ 1 for 2MB, 0 for 1GB
val
data
=
new
TlbEntryData
val
tag
=
UInt
(
tagLen
.
W
)
// NOTE: high part of vpn
val
level
=
UInt
(
log2Up
(
Level
).
W
)
val
ppns
=
Vec
(
num
,
UInt
(
ppnLen
.
W
))
val
perms
=
Vec
(
num
,
new
PermBundle
(
hasV
=
false
))
val
vs
=
Vec
(
num
,
Bool
())
def
tagClip
(
vpn
:
UInt
,
level
:
UInt
)
=
{
// full vpn => tagLen
val
tmp
=
Mux
(
level
===
0.
U
,
Cat
(
vpn
(
vpnLen
-
1
,
vpnnLen
*
2
+
cutLen
),
0.
U
(
vpnnLen
*
2
)),
Mux
(
level
===
1.
U
,
Cat
(
vpn
(
vpnLen
-
1
,
vpnnLen
*
1
+
cutLen
),
0.
U
(
vpnnLen
*
1
)),
Cat
(
vpn
(
vpnLen
-
1
,
vpnnLen
*
0
+
cutLen
),
0.
U
(
vpnnLen
*
0
))))
tmp
(
tmp
.
getWidth
-
1
,
tmp
.
getWidth
-
tagLen
)
def
hit
(
vpn
:
UInt
)
:
Bool
=
{
if
(
superpage
)
{
val
insideLevel
=
level
.
getOrElse
(
0.
U
)
val
a
=
tag
(
vpnnLen
*
3
-
1
,
vpnnLen
*
2
)
===
vpn
(
vpnnLen
*
3
-
1
,
vpnnLen
*
2
)
val
b
=
tag
(
vpnnLen
*
2
-
1
,
vpnnLen
*
1
)
===
vpn
(
vpnnLen
*
2
-
1
,
vpnnLen
*
1
)
XSDebug
(
Mux
(
insideLevel
.
asBool
,
a
&
b
,
a
),
p
"Hit superpage: hit:${Mux(insideLevel.asBool, a&b, a)} tag:${Hexadecimal(tag)} level:${insideLevel} data:${data} a:${a} b:${b} vpn:${Hexadecimal(vpn)}\n"
)(
"TlbEntrySuperpage"
)
Mux
(
insideLevel
.
asBool
,
a
&
b
,
a
)
}
else
{
XSDebug
(
tag
===
vpn
,
p
"Hit normalpage: hit:${tag === vpn} tag:${Hexadecimal(tag)} data:${data} vpn:${Hexadecimal(vpn)}\n"
)(
"TlbEntryNormalpage"
)
tag
===
vpn
}
// NOTE: get insize idx
def
idxClip
(
vpn
:
UInt
,
level
:
UInt
)
=
{
Mux
(
level
===
0.
U
,
vpn
(
vpnnLen
*
2
+
cutLen
-
1
,
vpnnLen
*
2
),
Mux
(
level
===
1.
U
,
vpn
(
vpnnLen
*
1
+
cutLen
-
1
,
vpnnLen
*
1
),
vpn
(
vpnnLen
*
0
+
cutLen
-
1
,
vpnnLen
*
0
)))
}
def
hit
(
vpn
:
UInt
)
=
{
(
tag
===
tagClip
(
vpn
,
level
))
&&
vs
(
idxClip
(
vpn
,
level
))
&&
(
level
===
2.
U
)
def
ppn
(
vpn
:
UInt
)
:
UInt
=
{
if
(
superpage
)
{
val
insideLevel
=
level
.
getOrElse
(
0.
U
)
Mux
(
insideLevel
.
asBool
,
Cat
(
data
.
ppn
(
data
.
ppn
.
getWidth
-
1
,
vpnnLen
*
1
),
vpn
(
vpnnLen
*
1
-
1
,
0
)),
Cat
(
data
.
ppn
(
data
.
ppn
.
getWidth
-
1
,
vpnnLen
*
2
),
vpn
(
vpnnLen
*
2
-
1
,
0
)))
}
else
{
data
.
ppn
}
def
genEntries
(
data
:
UInt
,
level
:
UInt
,
vpn
:
UInt
)
:
TlbEntires
=
{
require
((
data
.
getWidth
/
XLEN
)
==
num
,
"input data length must be multiple of pte length"
)
assert
(
level
=/=
3.
U
,
"level should not be 3"
)
val
ts
=
Wire
(
new
TlbEntires
(
num
,
tagLen
))
ts
.
tag
:=
tagClip
(
vpn
,
level
)
ts
.
level
:=
level
for
(
i
<-
0
until
num
)
{
val
pte
=
data
((
i
+
1
)*
XLEN
-
1
,
i
*
XLEN
).
asTypeOf
(
new
PteBundle
)
ts
.
ppns
(
i
)
:=
pte
.
ppn
ts
.
perms
(
i
):=
pte
.
perm
// this.perms has no v
ts
.
vs
(
i
)
:=
!
pte
.
isPf
(
level
)
&&
pte
.
isLeaf
()
// legal and leaf, store to l2Tlb
}
ts
}
def
apply
(
vpn
:
UInt
,
ppn
:
UInt
,
level
:
UInt
,
perm
:
UInt
,
pf
:
Bool
)
=
{
this
.
tag
:=
vpn
this
.
level
.
map
(
_
:=
level
(
0
))
this
.
data
.
ppn
:=
ppn
val
ptePerm
=
perm
.
asTypeOf
(
new
PtePermBundle
)
this
.
data
.
perm
.
pf
:=
pf
this
.
data
.
perm
.
d
:=
ptePerm
.
d
this
.
data
.
perm
.
a
:=
ptePerm
.
a
this
.
data
.
perm
.
g
:=
ptePerm
.
g
this
.
data
.
perm
.
u
:=
ptePerm
.
u
this
.
data
.
perm
.
x
:=
ptePerm
.
x
this
.
data
.
perm
.
w
:=
ptePerm
.
w
this
.
data
.
perm
.
r
:=
ptePerm
.
r
def
get
(
vpn
:
UInt
)
:
TlbEntry
=
{
val
t
=
Wire
(
new
TlbEntry
())
val
idx
=
idxClip
(
vpn
,
level
)
t
.
vpn
:=
vpn
// Note: Use input vpn, not vpn in TlbL2
t
.
ppn
:=
ppns
(
idx
)
t
.
level
:=
level
t
.
perm
:=
perms
(
idx
)
t
this
}
override
def
cloneType
:
this.
type
=
(
new
TlbEntires
(
num
,
tagLen
)).
asInstanceOf
[
this.
type
]
override
def
toPrintable
:
Printable
=
{
require
(
num
==
4
,
"if num is not 4, please comment this toPrintable"
)
// NOTE: if num is not 4, please comment this toPrintable
p
"tag:${Hexadecimal(tag)} level:${level} ppn(0):${Hexadecimal(ppns(0))} ppn(1):${Hexadecimal(ppns(1))}"
+
p
"ppn(2):${Hexadecimal(ppns(2))} ppn(3):${Hexadecimal(ppns(3))} "
+
p
"perms(0):${perms(0)} perms(1):${perms(1)} perms(2):${perms(2)} perms(3):${perms(3)} vs:${Binary(vs.asUInt)}"
val
insideLevel
=
level
.
getOrElse
(
0.
U
)
p
"vpn:0x${Hexadecimal(tag)} level:${insideLevel} data:${data}"
}
override
def
cloneType
:
this.
type
=
(
new
TlbEntry
(
superpage
)).
asInstanceOf
[
this.
type
]
}
object
TlbCmd
{
...
...
@@ -278,34 +281,63 @@ class TLB(Width: Int, isDtlb: Boolean) extends TlbModule with HasCSRConst{
def
widthMapSeq
[
T
<:
Seq
[
Data
]](
f
:
Int
=>
T
)
=
(
0
until
Width
).
map
(
f
)
def
widthMap
[
T
<:
Data
](
f
:
Int
=>
T
)
=
(
0
until
Width
).
map
(
f
)
val
v
=
RegInit
(
0.
U
(
TlbEntrySize
.
W
))
val
pf
=
RegInit
(
0.
U
(
TlbEntrySize
.
W
))
// TODO: when ptw resp a pf(now only page not found), store here
val
entry
=
Reg
(
Vec
(
TlbEntrySize
,
new
TlbEntry
))
val
g
=
VecInit
(
entry
.
map
(
_
.
perm
.
g
)).
asUInt
// TODO: need check if reverse is needed
// Normal page && Super page
val
nv
=
RegInit
(
VecInit
(
Seq
.
fill
(
TlbEntrySize
)(
false
.
B
)))
val
nentry
=
Reg
(
Vec
(
TlbEntrySize
,
new
TlbEntry
(
false
)))
val
sv
=
RegInit
(
VecInit
(
Seq
.
fill
(
TlbSPEntrySize
)(
false
.
B
)))
val
sentry
=
Reg
(
Vec
(
TlbSPEntrySize
,
new
TlbEntry
(
true
)))
val
v
=
nv
++
sv
val
entry
=
nentry
++
sentry
val
g
=
VecInit
(
entry
.
map
(
_
.
data
.
perm
.
g
))
val
pf
=
VecInit
(
entry
.
zip
(
v
).
map
{
case
(
e
,
vi
)
=>
e
.
data
.
perm
.
pf
&
vi
})
/**
* PTW refill
*/
val
refill
=
ptw
.
resp
.
fire
()
val
randIdx
=
LFSR64
()(
log2Up
(
TlbEntrySize
)-
1
,
0
)
val
priorIdx
=
PriorityEncoder
(~(
v
|
pf
))
val
tlbfull
=
ParallelAND
((
v
|
pf
).
asBools
)
val
refillIdx
=
Mux
(
tlbfull
,
randIdx
,
priorIdx
)
val
refillIdxOH
=
UIntToOH
(
refillIdx
)
def
randReplace
(
v
:
UInt
)
=
{
val
width
=
v
.
getWidth
val
randIdx
=
LFSR64
()(
log2Up
(
width
)-
1
,
0
)
val
priorIdx
=
PriorityEncoder
(~(
v
))
val
full
=
Cat
(
v
).
andR
Mux
(
full
,
randIdx
,
priorIdx
)
}
when
(
refill
)
{
v
:=
Mux
(
ptw
.
resp
.
bits
.
pf
,
v
&
~
refillIdxOH
,
v
|
refillIdxOH
)
entry
(
refillIdx
)
:=
ptw
.
resp
.
bits
.
entry
XSDebug
(
p
"Refill: idx:${refillIdx} entry:${ptw.resp.bits.entry}\n"
)
val
resp
=
ptw
.
resp
.
bits
when
(
resp
.
entry
.
level
===
2.
U
)
{
val
refillIdx
=
randReplace
(
nv
.
asUInt
)
nv
(
refillIdx
)
:=
true
.
B
nentry
(
refillIdx
).
apply
(
vpn
=
resp
.
entry
.
tag
,
ppn
=
resp
.
entry
.
ppn
,
level
=
resp
.
entry
.
level
,
perm
=
VecInit
(
resp
.
entry
.
perm
).
asUInt
,
pf
=
resp
.
pf
)
XSDebug
(
p
"Refill normal: idx:${refillIdx} entry:${resp.entry} pf:${resp.pf}\n"
)
}.
otherwise
{
val
refillIdx
=
randReplace
(
sv
.
asUInt
)
sv
(
refillIdx
)
:=
true
.
B
sentry
(
refillIdx
).
apply
(
vpn
=
resp
.
entry
.
tag
,
ppn
=
resp
.
entry
.
ppn
,
level
=
resp
.
entry
.
level
,
perm
=
VecInit
(
resp
.
entry
.
perm
).
asUInt
,
pf
=
resp
.
pf
)
XSDebug
(
p
"Refill superpage: idx:${refillIdx} entry:${resp.entry} pf:${resp.pf}\n"
)
}
}
/**
* L1 TLB read
*/
val
tlb_read_mask
=
Mux
(
refill
,
refillIdxOH
,
0.
U
(
TlbEntrySize
.
W
))
def
TLBRead
(
i
:
Int
)
=
{
// val tlb_read_mask = Mux(refill, ((1<<(TlbEntrySize+TlbSPEntrySize))-1).U, 0.U((TlbEntrySize+TlbSPEntrySize)
.W))
def
TLB
Normal
Read
(
i
:
Int
)
=
{
val
entryHitVec
=
(
if
(
isDtlb
)
VecInit
(
(
tlb_read_mask
.
asBools
zip
entry
).
map
{
case
(
r
,
e
)
=>
!
r
&&
e
.
hit
(
reqAddr
(
i
).
vpn
/*, satp.asid*/
)})
VecInit
(
entry
.
map
{
e
=>
~
refill
&&
e
.
hit
(
reqAddr
(
i
).
vpn
/*, satp.asid*/
)})
else
VecInit
(
entry
.
map
(
_
.
hit
(
reqAddr
(
i
).
vpn
/*, satp.asid*/
)))
)
...
...
@@ -315,26 +347,24 @@ class TLB(Width: Int, isDtlb: Boolean) extends TlbModule with HasCSRConst{
val
validReg
=
if
(
isDtlb
)
RegNext
(
valid
(
i
))
else
valid
(
i
)
val
entryHitVecReg
=
if
(
isDtlb
)
RegNext
(
entryHitVec
)
else
entryHitVec
val
hitVec
=
(
v
.
asBools
zip
entryHitVecReg
).
map
{
case
(
a
,
b
)
=>
a
&
b
}
val
pfHitVec
=
(
pf
.
asBools
zip
entryHitVecReg
).
map
{
case
(
a
,
b
)
=>
a
&
b
}
val
hitVec
=
(
v
zip
entryHitVecReg
).
map
{
case
(
a
,
b
)
=>
a
&
b
}
val
pfHitVec
=
(
pf
zip
entryHitVecReg
).
map
{
case
(
a
,
b
)
=>
a
&
b
}
val
pfArray
=
ParallelOR
(
pfHitVec
).
asBool
&&
validReg
&&
vmEnable
val
hit
=
ParallelOR
(
hitVec
).
asBool
&&
validReg
&&
vmEnable
&&
~
pfArray
val
miss
=
!
hit
&&
validReg
&&
vmEnable
&&
~
pfArray
val
hitppn
=
ParallelMux
(
hitVec
zip
entry
.
map
(
_
.
ppn
))
val
hitPerm
=
ParallelMux
(
hitVec
zip
entry
.
map
(
_
.
perm
))
val
hitLevel
=
ParallelMux
(
hitVec
zip
entry
.
map
(
_
.
level
))
val
hitppn
=
ParallelMux
(
hitVec
zip
entry
.
map
(
_
.
ppn
(
reqAddrReg
.
vpn
)))
val
hitPerm
=
ParallelMux
(
hitVec
zip
entry
.
map
(
_
.
data
.
perm
))
XSDebug
(
valid
(
i
),
p
"(${i.U}) entryHit:${Hexadecimal(entryHitVec.asUInt)}\n"
)
XSDebug
(
validReg
,
p
"(${i.U}) entryHitReg:${Hexadecimal(entryHitVecReg.asUInt)} hitVec:${Hexadecimal(VecInit(hitVec).asUInt)} pfHitVec:${Hexadecimal(VecInit(pfHitVec).asUInt)} pfArray:${Hexadecimal(pfArray.asUInt)} hit:${hit} miss:${miss} hitppn:${Hexadecimal(hitppn)} hitPerm:${hitPerm}\n"
)
val
multiHit
=
{
val
hitSum
=
PopCount
(
hitVec
)
val
pfHitSum
=
PopCount
(
pfHitVec
)
!(
hitSum
===
0.
U
||
hitSum
===
1.
U
)
||
!(
pfHitSum
===
0.
U
||
pfHitSum
===
1.
U
)
!(
hitSum
===
0.
U
||
hitSum
===
1.
U
)
}
// resp // TODO: A/D has not being concerned
val
paddr
=
LookupTreeDefault
(
hitLevel
,
Cat
(
hitppn
,
reqAddrReg
.
off
),
List
(
0.
U
->
Cat
(
hitppn
(
ppnLen
-
1
,
2
*
vpnnLen
),
reqAddrReg
.
vpn
(
2
*
vpnnLen
-
1
,
0
),
reqAddrReg
.
off
),
1.
U
->
Cat
(
hitppn
(
ppnLen
-
1
,
vpnnLen
),
reqAddrReg
.
vpn
(
vpnnLen
-
1
,
0
),
reqAddrReg
.
off
),
2.
U
->
Cat
(
hitppn
,
reqAddrReg
.
off
)
))
val
paddr
=
Cat
(
hitppn
,
reqAddrReg
.
off
)
val
vaddr
=
SignExt
(
req
(
i
).
bits
.
vaddr
,
PAddrBits
)
req
(
i
).
ready
:=
resp
(
i
).
ready
...
...
@@ -361,7 +391,7 @@ class TLB(Width: Int, isDtlb: Boolean) extends TlbModule with HasCSRConst{
(
hit
,
miss
,
pfHitVec
,
multiHit
)
}
val
readResult
=
(
0
until
Width
).
map
(
TLBRead
(
_
))
val
readResult
=
(
0
until
Width
).
map
(
TLB
Normal
Read
(
_
))
val
hitVec
=
readResult
.
map
(
res
=>
res
.
_1
)
val
missVec
=
readResult
.
map
(
res
=>
res
.
_2
)
val
pfHitVecVec
=
readResult
.
map
(
res
=>
res
.
_3
)
...
...
@@ -369,12 +399,15 @@ class TLB(Width: Int, isDtlb: Boolean) extends TlbModule with HasCSRConst{
val
hasMissReq
=
Cat
(
missVec
).
orR
// ptw
val
state_idle
::
state_wait
::
Nil
=
Enum
(
2
)
val
state
=
RegInit
(
state_idle
)
ptw
<>
DontCare
// TODO: need check it
ptw
.
req
.
valid
:=
hasMissReq
&&
state
===
state_idle
&&
!
sfence
.
valid
ptw
.
resp
.
ready
:=
state
===
state_wait
val
waiting
=
RegInit
(
false
.
B
)
when
(
ptw
.
req
.
fire
())
{
waiting
:=
true
.
B
}.
elsewhen
(
sfence
.
valid
||
ptw
.
resp
.
valid
)
{
waiting
:=
false
.
B
}
// ptw <> DontCare // TODO: need check it
ptw
.
req
.
valid
:=
hasMissReq
&&
!
sfence
.
valid
&&
!
waiting
ptw
.
resp
.
ready
:=
waiting
// val ptwReqSeq = Wire(Seq.fill(Width)(new comBundle()))
val
ptwReqSeq
=
Seq
.
fill
(
Width
)(
Wire
(
new
comBundle
()))
...
...
@@ -385,82 +418,49 @@ class TLB(Width: Int, isDtlb: Boolean) extends TlbModule with HasCSRConst{
}
ptw
.
req
.
bits
:=
Compare
(
ptwReqSeq
).
bits
switch
(
state
)
{
is
(
state_idle
)
{
when
(
hasMissReq
&&
ptw
.
req
.
fire
())
{
state
:=
state_wait
}
assert
(!
ptw
.
resp
.
valid
)
}
is
(
state_wait
)
{
when
(
ptw
.
resp
.
fire
())
{
state
:=
state_idle
}
}
}
// reset pf when pf hit
val
pfHitReset
=
ParallelOR
(
widthMap
{
i
=>
Mux
(
resp
(
i
).
fire
(),
VecInit
(
pfHitVecVec
(
i
)).
asUInt
,
0.
U
)
})
val
pfHitRefill
=
false
.
B
//ParallelOR(pfHitReset.asBools)
// pf update
when
(
refill
)
{
when
(
pfHitRefill
)
{
pf
:=
Mux
(
ptw
.
resp
.
bits
.
pf
,
pf
|
refillIdxOH
,
pf
&
~
refillIdxOH
)
&
~
pfHitReset
}
.
otherwise
{
pf
:=
Mux
(
ptw
.
resp
.
bits
.
pf
,
pf
|
refillIdxOH
,
pf
&
~
refillIdxOH
)
}
}
.
otherwise
{
when
(
pfHitRefill
)
{
pf
:=
pf
&
~
pfHitReset
}
}
when
(
PopCount
(
pf
)
>
10.
U
)
{
// when too much pf, just clear
pf
:=
Mux
(
refill
&&
ptw
.
resp
.
bits
.
pf
,
refillIdxOH
,
0.
U
)
val
tooManyPf
=
PopCount
(
pf
)
>
5.
U
when
(
tooManyPf
)
{
// when too much pf, just clear
XSDebug
(
p
"Too many pf just flush all the pf v:${Hexadecimal(VecInit(v).asUInt)} pf:${Hexadecimal(pf.asUInt)}\n"
)
v
.
zipWithIndex
.
map
{
case
(
a
,
i
)
=>
a
:=
a
&
!
pf
(
i
)
}
}
// sfence (flush)
when
(
sfence
.
valid
)
{
state
:=
state_idle
ptw
.
req
.
valid
:=
false
.
B
when
(
sfence
.
bits
.
rs1
)
{
// virtual address *.rs1 <- (rs1===0.U)
when
(
sfence
.
bits
.
rs2
)
{
// asid, but i do not want to support asid, *.rs2 <- (rs2===0.U)
// all addr and all asid
v
:=
0.
U
pf
:=
0.
U
v
.
map
(
_
:=
false
.
B
)
}.
otherwise
{
// all addr but specific asid
v
:=
v
&
g
// TODO: need check if reverse is needed
pf
:=
pf
&
g
v
.
zipWithIndex
.
map
{
case
(
a
,
i
)
=>
a
:=
a
&
g
(
i
)
}
}
}.
otherwise
{
val
sfenceVpn
=
sfence
.
bits
.
addr
.
asTypeOf
(
vaBundle
).
vpn
when
(
sfence
.
bits
.
rs2
)
{
// specific addr but all asid
v
:=
v
&
~
VecInit
(
entry
.
map
(
_
.
hit
(
sfence
.
bits
.
addr
.
asTypeOf
(
vaBundle
).
vpn
))).
asUInt
pf
:=
pf
&
~
VecInit
(
entry
.
map
(
_
.
hit
(
sfence
.
bits
.
addr
.
asTypeOf
(
vaBundle
).
vpn
))).
asUInt
v
.
zipWithIndex
.
map
{
case
(
a
,
i
)
=>
a
:=
a
&
!
entry
(
i
).
hit
(
sfenceVpn
)
}
}.
otherwise
{
// specific addr and specific asid
v
:=
v
&
~
VecInit
(
entry
.
map
(
e
=>
e
.
hit
(
sfence
.
bits
.
addr
.
asTypeOf
(
vaBundle
).
vpn
)
&&
(
/*e.asid === sfence.bits.asid && */
!
e
.
perm
.
g
))).
asUInt
pf
:=
pf
&
~
VecInit
(
entry
.
map
(
e
=>
e
.
hit
(
sfence
.
bits
.
addr
.
asTypeOf
(
vaBundle
).
vpn
)
&&
(
/*e.asid === sfence.bits.asid && */
!
e
.
perm
.
g
))).
asUInt
v
.
zipWithIndex
.
map
{
case
(
a
,
i
)
=>
a
:=
a
&
!(
entry
(
i
).
hit
(
sfenceVpn
)
&&
!
g
(
i
))}
}
}
}
if
(!
env
.
FPGAPlatform
&&
isDtlb
)
{
ExcitingUtils
.
addSource
(
valid
(
0
)
/* && vmEnable*/
,
"perfCntDtlbReqCnt0"
,
Perf
)
ExcitingUtils
.
addSource
(
valid
(
1
)
/* && vmEnable*/
,
"perfCntDtlbReqCnt1"
,
Perf
)
ExcitingUtils
.
addSource
(
valid
(
2
)
/* && vmEnable*/
,
"perfCntDtlbReqCnt2"
,
Perf
)
ExcitingUtils
.
addSource
(
valid
(
3
)
/* && vmEnable*/
,
"perfCntDtlbReqCnt3"
,
Perf
)
ExcitingUtils
.
addSource
(
valid
(
0
)
/* && vmEnable*/
&&
missVec
(
0
),
"perfCntDtlbMissCnt0"
,
Perf
)
ExcitingUtils
.
addSource
(
valid
(
1
)
/* && vmEnable*/
&&
missVec
(
1
),
"perfCntDtlbMissCnt1"
,
Perf
)
ExcitingUtils
.
addSource
(
valid
(
2
)
/* && vmEnable*/
&&
missVec
(
2
),
"perfCntDtlbMissCnt2"
,
Perf
)
ExcitingUtils
.
addSource
(
valid
(
3
)
/* && vmEnable*/
&&
missVec
(
3
),
"perfCntDtlbMissCnt3"
,
Perf
)
ExcitingUtils
.
addSource
(
valid
(
0
)
&&
vmEnable
,
"perfCntDtlbReqCnt0"
,
Perf
)
ExcitingUtils
.
addSource
(
valid
(
1
)
&&
vmEnable
,
"perfCntDtlbReqCnt1"
,
Perf
)
ExcitingUtils
.
addSource
(
valid
(
2
)
&&
vmEnable
,
"perfCntDtlbReqCnt2"
,
Perf
)
ExcitingUtils
.
addSource
(
valid
(
3
)
&&
vmEnable
,
"perfCntDtlbReqCnt3"
,
Perf
)
ExcitingUtils
.
addSource
(
valid
(
0
)
&&
vmEnable
&&
missVec
(
0
),
"perfCntDtlbMissCnt0"
,
Perf
)
ExcitingUtils
.
addSource
(
valid
(
1
)
&&
vmEnable
&&
missVec
(
1
),
"perfCntDtlbMissCnt1"
,
Perf
)
ExcitingUtils
.
addSource
(
valid
(
2
)
&&
vmEnable
&&
missVec
(
2
),
"perfCntDtlbMissCnt2"
,
Perf
)
ExcitingUtils
.
addSource
(
valid
(
3
)
&&
vmEnable
&&
missVec
(
3
),
"perfCntDtlbMissCnt3"
,
Perf
)
}
if
(!
env
.
FPGAPlatform
&&
!
isDtlb
)
{
ExcitingUtils
.
addSource
(
valid
(
0
)
/* && vmEnable*/
,
"perfCntItlbReqCnt0"
,
Perf
)
ExcitingUtils
.
addSource
(
valid
(
0
)
/* && vmEnable*/
&&
missVec
(
0
),
"perfCntItlbMissCnt0"
,
Perf
)
ExcitingUtils
.
addSource
(
valid
(
0
)
&&
vmEnable
,
"perfCntItlbReqCnt0"
,
Perf
)
ExcitingUtils
.
addSource
(
valid
(
0
)
&&
vmEnable
&&
missVec
(
0
),
"perfCntItlbMissCnt0"
,
Perf
)
}
// Log
...
...
@@ -471,35 +471,20 @@ class TLB(Width: Int, isDtlb: Boolean) extends TlbModule with HasCSRConst{
XSDebug
(
sfence
.
valid
,
p
"Sfence: ${sfence}\n"
)
XSDebug
(
ParallelOR
(
valid
)||
ptw
.
resp
.
valid
,
p
"CSR: ${csr}\n"
)
XSDebug
(
ParallelOR
(
valid
)
||
ptw
.
resp
.
valid
,
p
"vmEnable:${vmEnable} hit:${Binary(VecInit(hitVec).asUInt)} miss:${Binary(VecInit(missVec).asUInt)} v:${Hexadecimal(
v)} pf:${Hexadecimal(pf)} state:${state
}\n"
)
XSDebug
(
ParallelOR
(
valid
)
||
ptw
.
resp
.
valid
,
p
"vmEnable:${vmEnable} hit:${Binary(VecInit(hitVec).asUInt)} miss:${Binary(VecInit(missVec).asUInt)} v:${Hexadecimal(
VecInit(v).asUInt)} pf:${Hexadecimal(pf.asUInt)
}\n"
)
XSDebug
(
ptw
.
req
.
fire
(),
p
"PTW req:${ptw.req.bits}\n"
)
XSDebug
(
ptw
.
resp
.
valid
,
p
"PTW resp:${ptw.resp.bits} (v:${ptw.resp.valid}r:${ptw.resp.ready}) \n"
)
// // assert check, can be remove when tlb can work
// for(i <- 0 until Width) {
// assert((hit(i)&pfArray(i))===false.B, "hit(%d):%d pfArray(%d):%d v:0x%x pf:0x%x", i.U, hit(i), i.U, pfArray(i), v, pf)
// }
// for(i <- 0 until Width) {
// XSDebug(multiHit, p"vpn:0x${Hexadecimal(reqAddr(i).vpn)} hitVec:0x${Hexadecimal(VecInit(hitVec(i)).asUInt)} pfHitVecVec:0x${Hexadecimal(VecInit(pfHitVecVec(i)).asUInt)}\n")
// }
// for(i <- 0 until TlbEntrySize) {
// XSDebug(multiHit, p"entry(${i.U}): v:${v(i)} ${entry(i)}\n")
// }
// assert(!multiHit) // add multiHit here, later it should be removed (maybe), turn to miss and flush
// for (i <- 0 until Width) {
// XSDebug(resp(i).valid && hit(i) && !(req(i).bits.vaddr===resp(i).bits.paddr), p"vaddr:0x${Hexadecimal(req(i).bits.vaddr)} paddr:0x${Hexadecimal(resp(i).bits.paddr)} hitVec:0x${Hexadecimal(VecInit(hitVec(i)).asUInt)}}\n")
// when (resp(i).valid && hit(i) && !(req(i).bits.vaddr===resp(i).bits.paddr)) {
// for (j <- 0 until TlbEntrySize) {
// XSDebug(true.B, p"TLBEntry(${j.U}): v:${v(j)} ${entry(j)}\n")
// }
// } // FIXME: remove me when tlb may be ok
// when(resp(i).valid && hit(i)) {
// assert(req(i).bits.vaddr===resp(i).bits.paddr, "vaddr:0x%x paddr:0x%x hitVec:%x ", req(i).bits.vaddr, resp(i).bits.paddr, VecInit(hitVec(i)).asUInt)
// } // FIXME: remove me when tlb may be ok
// }
// assert((v&pf)===0.U, "v and pf can't be true at same time: v:0x%x pf:0x%x", v, pf)
// // NOTE: just for simple tlb debug, comment it after tlb's debug
// for (i <- 0 until Width) {
// if(isDtlb) {
// XSDebug(!(!vmEnable || RegNext(req(i).bits.vaddr)===resp(i).bits.paddr || !resp(i).valid || resp(i).bits.miss || Cat(VecInit(resp(i).bits.excp.pf).asUInt).orR), p"Dtlb: vaddr:${Hexadecimal(RegNext(req(i).bits.vaddr))} paddr:${Hexadecimal(resp(i).bits.paddr)} should be equal\n")
// assert(!vmEnable || RegNext(req(i).bits.vaddr)===resp(i).bits.paddr || !resp(i).valid || resp(i).bits.miss || Cat(VecInit(resp(i).bits.excp.pf).asUInt).orR)
// } else {
// XSDebug(!(!vmEnable || req(i).bits.vaddr===resp(i).bits.paddr || !resp(i).valid || resp(i).bits.miss || Cat(VecInit(resp(i).bits.excp.pf).asUInt).orR), p"Itlb: vaddr:${Hexadecimal(RegNext(req(i).bits.vaddr))} paddr:${Hexadecimal(resp(i).bits.paddr)} should be equal\n")
// assert(!vmEnable || req(i).bits.vaddr===resp(i).bits.paddr || !resp(i).valid || resp(i).bits.miss || Cat(VecInit(resp(i).bits.excp.pf).asUInt).orR)
// }
// }
}
object
TLB
{
...
...
src/main/scala/xiangshan/cache/ptw.scala
浏览文件 @
a057a757
...
...
@@ -156,6 +156,94 @@ class PtwEntries(num: Int, tagLen: Int) extends PtwBundle {
}
}
class
L2TlbEntry
extends
TlbBundle
{
val
tag
=
UInt
(
vpnLen
.
W
)
// tag is vpn
val
level
=
UInt
(
log2Up
(
Level
).
W
)
// 2 for 4KB, 1 for 2MB, 0 for 1GB
val
ppn
=
UInt
(
ppnLen
.
W
)
val
perm
=
new
PtePermBundle
def
hit
(
vpn
:
UInt
)
:
Bool
=
{
val
fullMask
=
VecInit
((
Seq
.
fill
(
vpnLen
)(
true
.
B
))).
asUInt
val
maskLevel
=
VecInit
((
Level
-
1
to
0
by
-
1
).
map
{
i
=>
// NOTE: level 2 for 4KB, 1 for 2MB, 0 for 1GB
Reverse
(
VecInit
(
Seq
.
fill
(
vpnLen
-
i
*
vpnnLen
)(
true
.
B
)
++
Seq
.
fill
(
i
*
vpnnLen
)(
false
.
B
)).
asUInt
)})
val
mask
=
maskLevel
(
level
)
(
mask
&
this
.
tag
)
===
(
mask
&
vpn
)
}
def
apply
(
pte
:
UInt
,
level
:
UInt
,
vpn
:
UInt
)
=
{
this
.
tag
:=
vpn
this
.
level
:=
level
this
.
ppn
:=
pte
.
asTypeOf
(
pteBundle
).
ppn
this
.
perm
:=
pte
.
asTypeOf
(
pteBundle
).
perm
this
}
override
def
toPrintable
:
Printable
=
{
p
"vpn:0x${Hexadecimal(tag)} level:${level} ppn:${Hexadecimal(ppn)} perm:${perm}"
}
}
class
L2TlbEntires
(
num
:
Int
,
tagLen
:
Int
)
extends
TlbBundle
{
require
(
log2Up
(
num
)==
log2Down
(
num
))
/* vpn can be divide into three part */
// vpn: tagPart(17bit) + addrPart(8bit) + cutLenPart(2bit)
val
cutLen
=
log2Up
(
num
)
val
tag
=
UInt
(
tagLen
.
W
)
// NOTE: high part of vpn
val
ppns
=
Vec
(
num
,
UInt
(
ppnLen
.
W
))
val
perms
=
Vec
(
num
,
new
PtePermBundle
)
val
vs
=
Vec
(
num
,
Bool
())
def
tagClip
(
vpn
:
UInt
)
=
{
// full vpn => tagLen
vpn
(
vpn
.
getWidth
-
1
,
vpn
.
getWidth
-
tagLen
)
}
// NOTE: get insize idx
def
idxClip
(
vpn
:
UInt
)
=
{
vpn
(
cutLen
-
1
,
0
)
}
def
hit
(
vpn
:
UInt
)
=
{
(
tag
===
tagClip
(
vpn
))
&&
vs
(
idxClip
(
vpn
))
}
def
genEntries
(
data
:
UInt
,
level
:
UInt
,
vpn
:
UInt
)
:
L2TlbEntires
=
{
require
((
data
.
getWidth
/
XLEN
)
==
num
,
"input data length must be multiple of pte length"
)
assert
(
level
===
2.
U
,
"tlb entries only support 4K pages"
)
val
ts
=
Wire
(
new
L2TlbEntires
(
num
,
tagLen
))
ts
.
tag
:=
tagClip
(
vpn
)
for
(
i
<-
0
until
num
)
{
val
pte
=
data
((
i
+
1
)*
XLEN
-
1
,
i
*
XLEN
).
asTypeOf
(
new
PteBundle
)
ts
.
ppns
(
i
)
:=
pte
.
ppn
ts
.
perms
(
i
):=
pte
.
perm
// this.perms has no v
ts
.
vs
(
i
)
:=
!
pte
.
isPf
(
level
)
&&
pte
.
isLeaf
()
// legal and leaf, store to l2Tlb
}
ts
}
def
get
(
vpn
:
UInt
)
:
L2TlbEntry
=
{
val
t
=
Wire
(
new
L2TlbEntry
)
val
idx
=
idxClip
(
vpn
)
t
.
tag
:=
vpn
// Note: Use input vpn, not vpn in TlbL2
t
.
level
:=
2.
U
// L2TlbEntries only support 4k page
t
.
ppn
:=
ppns
(
idx
)
t
.
perm
:=
perms
(
idx
)
t
}
override
def
cloneType
:
this.
type
=
(
new
L2TlbEntires
(
num
,
tagLen
)).
asInstanceOf
[
this.
type
]
override
def
toPrintable
:
Printable
=
{
require
(
num
==
4
,
"if num is not 4, please comment this toPrintable"
)
// NOTE: if num is not 4, please comment this toPrintable
p
"tag:${Hexadecimal(tag)} ppn(0):${Hexadecimal(ppns(0))} ppn(1):${Hexadecimal(ppns(1))}"
+
p
"ppn(2):${Hexadecimal(ppns(2))} ppn(3):${Hexadecimal(ppns(3))} "
+
p
"perms(0):${perms(0)} perms(1):${perms(1)} perms(2):${perms(2)} perms(3):${perms(3)} vs:${Binary(vs.asUInt)}"
}
}
class
PtwReq
extends
PtwBundle
{
val
vpn
=
UInt
(
vpnLen
.
W
)
...
...
@@ -165,8 +253,8 @@ class PtwReq extends PtwBundle {
}
class
PtwResp
extends
PtwBundle
{
val
entry
=
new
TlbEntry
val
pf
=
Bool
()
// simple pf no matter cmd
val
entry
=
new
L2
TlbEntry
val
pf
=
Bool
()
override
def
toPrintable
:
Printable
=
{
p
"entry:${entry} pf:${pf}"
...
...
@@ -237,11 +325,16 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
// pde/pte-cache is cache of page-table, speeding up ptw
val
tlbl2
=
Module
(
new
SRAMWrapper
(
"L2TLB"
,
new
TlbEntires
(
num
=
TlbL2LineSize
,
tagLen
=
TlbL2TagLen
),
new
L2
TlbEntires
(
num
=
TlbL2LineSize
,
tagLen
=
TlbL2TagLen
),
set
=
TlbL2LineNum
))
// (total 256, one line is 4 => 64 lines)
val
tlbv
=
RegInit
(
0.
U
(
TlbL2LineNum
.
W
))
// valid
val
tlbg
=
Reg
(
UInt
(
TlbL2LineNum
.
W
))
// global
val
sp
=
Reg
(
Vec
(
TlbL2SPEntrySize
,
new
L2TlbEntry
))
// (total 16, one is 4M or 1G)
val
spv
=
RegInit
(
0.
U
(
TlbL2SPEntrySize
.
W
))
val
spg
=
Reg
(
UInt
(
TlbL2SPEntrySize
.
W
))
val
ptwl1
=
Reg
(
Vec
(
PtwL1EntrySize
,
new
PtwEntry
(
tagLen
=
PtwL1TagLen
)))
val
l1v
=
RegInit
(
0.
U
(
PtwL1EntrySize
.
W
))
// valid
val
l1g
=
Reg
(
UInt
(
PtwL1EntrySize
.
W
))
...
...
@@ -287,7 +380,18 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
XSDebug
(
tlbl2
.
io
.
r
.
req
.
valid
,
p
"tlbl2 Read rIdx:${Hexadecimal(ridx)}\n"
)
XSDebug
(
RegNext
(
tlbl2
.
io
.
r
.
req
.
valid
),
p
"tlbl2 RamData:${ramData}\n"
)
XSDebug
(
RegNext
(
tlbl2
.
io
.
r
.
req
.
valid
),
p
"tlbl2 v:${vidx} hit:${ramData.hit(req.vpn)} tlbPte:${ramData.get(req.vpn)}\n"
)
(
ramData
.
hit
(
req
.
vpn
)
&&
vidx
,
ramData
.
get
(
req
.
vpn
))
val
spHitVec
=
sp
.
zipWithIndex
.
map
{
case
(
a
,
i
)
=>
RegNext
(
a
.
hit
(
req
.
vpn
)
&&
spv
(
i
),
validOneCycle
)
}
val
spHitData
=
ParallelMux
(
spHitVec
zip
sp
)
val
spHit
=
Cat
(
spHitVec
).
orR
XSDebug
(
RegNext
(
validOneCycle
),
p
"tlbl2 sp: spHit:${spHit} spPte:${spHitData}\n"
)
assert
(
RegNext
(!(
ramData
.
hit
(
req
.
vpn
)
&&
spHit
)),
"pages should not be normal page and super page as well"
)
(
ramData
.
hit
(
req
.
vpn
)
&&
vidx
||
spHit
,
Mux
(
spHit
,
spHitData
,
ramData
.
get
(
req
.
vpn
)))
}
/*
...
...
@@ -369,7 +473,7 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
state
:=
state_idle
}.
otherwise
{
state
:=
state_wait_ready
latch
.
entry
:=
new
TlbEntry
().
genTlbEntr
y
(
memRdata
,
level
,
req
.
vpn
)
latch
.
entry
:=
Wire
(
new
L2TlbEntry
()).
appl
y
(
memRdata
,
level
,
req
.
vpn
)
latch
.
pf
:=
memPte
.
isPf
(
level
)
}
}.
otherwise
{
...
...
@@ -426,7 +530,7 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
for
(
i
<-
0
until
PtwWidth
)
{
resp
(
i
).
valid
:=
valid
&&
arbChosen
===
i
.
U
&&
ptwFinish
// TODO: add resp valid logic
resp
(
i
).
bits
.
entry
:=
Mux
(
tlbHit
,
tlbHitData
,
Mux
(
state
===
state_wait_ready
,
latch
.
entry
,
new
TlbEntry
().
genTlbEntr
y
(
memSelData
,
Mux
(
level
===
3.
U
,
2.
U
,
level
),
req
.
vpn
)))
Mux
(
state
===
state_wait_ready
,
latch
.
entry
,
Wire
(
new
L2TlbEntry
()).
appl
y
(
memSelData
,
Mux
(
level
===
3.
U
,
2.
U
,
level
),
req
.
vpn
)))
resp
(
i
).
bits
.
pf
:=
Mux
(
level
===
3.
U
||
notFound
,
true
.
B
,
Mux
(
tlbHit
,
false
.
B
,
Mux
(
state
===
state_wait_ready
,
latch
.
pf
,
memPte
.
isPf
(
level
))))
// TODO: the pf must not be correct, check it
}
...
...
@@ -442,13 +546,15 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
when
(
memRespFire
&&
!
memPte
.
isPf
(
level
)
&&
!
sfenceLatch
)
{
when
(
level
===
0.
U
&&
!
memPte
.
isLeaf
)
{
val
refillIdx
=
LFSR64
()(
log2Up
(
PtwL1EntrySize
)-
1
,
0
)
// TODO: may be LRU
val
rfOH
=
UIntToOH
(
refillIdx
)
ptwl1
(
refillIdx
).
refill
(
l1addr
,
memSelData
)
l1v
:=
l1v
|
UIntToOH
(
refillIdx
)
l1g
:=
(
l1g
&
~
UIntToOH
(
refillIdx
))
|
Mux
(
memPte
.
perm
.
g
,
UIntToOH
(
refillIdx
)
,
0.
U
)
l1v
:=
l1v
|
rfOH
l1g
:=
(
l1g
&
~
rfOH
)
|
Mux
(
memPte
.
perm
.
g
,
rfOH
,
0.
U
)
}
when
(
level
===
1.
U
&&
!
memPte
.
isLeaf
)
{
val
l2addrStore
=
RegEnable
(
l2addr
,
memReqFire
&&
state
===
state_req
&&
level
===
1.
U
)
val
refillIdx
=
genPtwL2Idx
(
l2addrStore
)
//getVpnn(req.vpn, 1)(log2Up(PtwL2EntrySize)-1, 0)
val
rfOH
=
UIntToOH
(
refillIdx
)
//TODO: check why the old refillIdx is right
assert
(
ptwl2
.
io
.
w
.
req
.
ready
)
...
...
@@ -459,26 +565,34 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
data
=
ps
,
waymask
=
-
1.
S
.
asUInt
)
l2v
:=
l2v
|
UIntToOH
(
refillIdx
)
l2g
:=
(
l2g
&
~
UIntToOH
(
refillIdx
))
|
Mux
(
Cat
(
memPtes
.
map
(
_
.
perm
.
g
)).
andR
,
UIntToOH
(
refillIdx
)
,
0.
U
)
l2v
:=
l2v
|
rfOH
l2g
:=
(
l2g
&
~
rfOH
)
|
Mux
(
Cat
(
memPtes
.
map
(
_
.
perm
.
g
)).
andR
,
rfOH
,
0.
U
)
XSDebug
(
p
"ptwl2 RefillIdx:${Hexadecimal(refillIdx)} ps:${ps}\n"
)
}
when
(
memPte
.
isLeaf
()
&&
(
level
===
2.
U
))
{
val
refillIdx
=
genTlbL2Idx
(
req
.
vpn
)
//getVpnn(req.vpn, 0)(log2Up(TlbL2EntrySize)-1, 0)
val
rfOH
=
UIntToOH
(
refillIdx
)
//TODO: check why the old refillIdx is right
assert
(
tlbl2
.
io
.
w
.
req
.
ready
)
val
ts
=
new
TlbEntires
(
num
=
TlbL2LineSize
,
tagLen
=
TlbL2TagLen
).
genEntries
(
memRdata
,
level
,
req
.
vpn
)
val
ts
=
new
L2
TlbEntires
(
num
=
TlbL2LineSize
,
tagLen
=
TlbL2TagLen
).
genEntries
(
memRdata
,
level
,
req
.
vpn
)
tlbl2
.
io
.
w
.
apply
(
valid
=
true
.
B
,
setIdx
=
refillIdx
,
data
=
ts
,
waymask
=
-
1.
S
.
asUInt
)
tlbv
:=
tlbv
|
UIntToOH
(
refillIdx
)
tlbg
:=
(
tlbg
&
~
UIntToOH
(
refillIdx
))
|
Mux
(
Cat
(
memPtes
.
map
(
_
.
perm
.
g
)).
andR
,
UIntToOH
(
refillIdx
)
,
0.
U
)
tlbv
:=
tlbv
|
rfOH
tlbg
:=
(
tlbg
&
~
rfOH
)
|
Mux
(
Cat
(
memPtes
.
map
(
_
.
perm
.
g
)).
andR
,
rfOH
,
0.
U
)
XSDebug
(
p
"tlbl2 refillIdx:${Hexadecimal(refillIdx)} ts:${ts}\n"
)
}
when
(
memPte
.
isLeaf
()
&&
(
level
===
1.
U
||
level
===
0.
U
))
{
val
refillIdx
=
LFSR64
()(
log2Up
(
TlbL2SPEntrySize
)-
1
,
0
)
// TODO: may be LRU
val
rfOH
=
UIntToOH
(
refillIdx
)
sp
(
refillIdx
)
:=
Wire
(
new
L2TlbEntry
()).
apply
(
memSelData
,
Mux
(
level
===
3.
U
,
2.
U
,
level
),
req
.
vpn
)
spv
:=
spv
|
rfOH
spg
:=
(
spg
&
~
rfOH
)
|
Mux
(
memPte
.
perm
.
g
,
rfOH
,
0.
U
)
}
}
/* sfence
...
...
@@ -496,25 +610,29 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
when
(
sfence
.
bits
.
rs2
)
{
// all va && all asid
tlbv
:=
0.
U
tlbg
:=
0.
U
spv
:=
0.
U
// tlbg := 0.U
l1v
:=
0.
U
l2v
:=
0.
U
l2g
:=
0.
U
//
l2g := 0.U
}
.
otherwise
{
// all va && specific asid except global
tlbv
:=
tlbv
&
tlbg
spv
:=
spv
&
spg
l1v
:=
l1v
&
l1g
l2v
:=
l2v
&
l2g
}
}
.
otherwise
{
val
sfenceTlbL2IdxOH
=
UIntToOH
(
genTlbL2Idx
(
sfence
.
bits
.
addr
(
sfence
.
bits
.
addr
.
getWidth
-
1
,
offLen
)))
when
(
sfence
.
bits
.
rs2
)
{
// specific leaf of addr && all asid
tlbv
:=
tlbv
&
~
UIntToOH
(
genTlbL2Idx
(
sfence
.
bits
.
addr
(
sfence
.
bits
.
addr
.
getWidth
-
1
,
offLen
)))
tlbg
:=
tlbg
&
~
UIntToOH
(
genTlbL2Idx
(
sfence
.
bits
.
addr
(
sfence
.
bits
.
addr
.
getWidth
-
1
,
offLen
)))
tlbv
:=
tlbv
&
~
sfenceTlbL2IdxOH
tlbg
:=
tlbg
&
~
sfenceTlbL2IdxOH
}
.
otherwise
{
// specific leaf of addr && specific asid
tlbv
:=
tlbv
&
(~
UIntToOH
(
genTlbL2Idx
(
sfence
.
bits
.
addr
(
sfence
.
bits
.
addr
.
getWidth
-
1
,
offLen
)))
|
tlbg
)
tlbv
:=
tlbv
&
(~
sfenceTlbL2IdxOH
|
tlbg
)
}
spv
:=
0.
U
}
}
...
...
src/test/csrc/ram.cpp
浏览文件 @
a057a757
...
...
@@ -4,6 +4,7 @@
#include "ram.h"
#include "compress.h"
// #define TLB_UNITTEST
#ifdef WITH_DRAMSIM3
#include "cosimulation.h"
...
...
@@ -84,8 +85,8 @@ void addpageSv39() {
//pdde[2] = ((0x80000000&0xc0000000) >> 2) | 0xf;
for
(
int
i
=
0
;
i
<
PTENUM
;
i
++
)
{
pde
[
i
]
=
((
PTEADDR
(
i
)
&
0xfffff000
)
>>
2
)
|
0x1
;
//pde[i] = (((0x8
000000+i*2*1024*1024)&0xffe00000)>>2) | 0xf;
//
pde[i] = ((PTEADDR(i)&0xfffff000)>>2) | 0x1;
pde
[
i
]
=
(((
0x80
000000
+
i
*
2
*
1024
*
1024
)
&
0xffe00000
)
>>
2
)
|
0xf
;
}
for
(
int
outidx
=
0
;
outidx
<
PTENUM
;
outidx
++
)
{
...
...
@@ -94,6 +95,7 @@ void addpageSv39() {
}
}
printf
(
"try to add identical tlb page to ram
\n
"
);
memcpy
((
char
*
)
ram
+
(
TOPSIZE
-
PAGESIZE
*
(
PTENUM
+
PDDENUM
+
PDENUM
+
PDEMMIONUM
+
PTEMMIONUM
+
PDEDEVNUM
+
PTEDEVNUM
)),
ptedev
,
PAGESIZE
*
PTEDEVNUM
);
memcpy
((
char
*
)
ram
+
(
TOPSIZE
-
PAGESIZE
*
(
PTENUM
+
PDDENUM
+
PDENUM
+
PDEMMIONUM
+
PTEMMIONUM
+
PDEDEVNUM
)),
pdedev
,
PAGESIZE
*
PDEDEVNUM
);
memcpy
((
char
*
)
ram
+
(
TOPSIZE
-
PAGESIZE
*
(
PTENUM
+
PDDENUM
+
PDENUM
+
PDEMMIONUM
+
PTEMMIONUM
)),
ptemmio
,
PAGESIZE
*
PTEMMIONUM
);
...
...
@@ -117,6 +119,12 @@ void init_ram(const char *img) {
assert
(
0
);
}
#ifdef TLB_UNITTEST
//new add
addpageSv39
();
//new end
#endif
int
ret
;
if
(
isGzFile
(
img
))
{
printf
(
"Gzip file detected and loading image from extracted gz file
\n
"
);
...
...
@@ -143,12 +151,6 @@ void init_ram(const char *img) {
fclose
(
fp
);
}
#ifdef TLB_UNITTEST
//new add
addpageSv39
();
//new end
#endif
#ifdef WITH_DRAMSIM3
#if !defined(DRAMSIM3_CONFIG) || !defined(DRAMSIM3_OUTDIR)
#error DRAMSIM3_CONFIG or DRAMSIM3_OUTDIR is not defined
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录