Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenXiangShan
XiangShan
提交
6b0d407e
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,发现更多精彩内容 >>
提交
6b0d407e
编写于
11月 19, 2020
作者:
A
Allen
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of github.com:RISCVERS/XiangShan into fixBankedL3
上级
9a5912cd
8b2161a4
变更
16
隐藏空白更改
内联
并排
Showing
16 changed file
with
794 addition
and
322 deletion
+794
-322
Makefile
Makefile
+16
-15
debug/sc_stat.sh
debug/sc_stat.sh
+12
-0
src/main/scala/xiangshan/Bundle.scala
src/main/scala/xiangshan/Bundle.scala
+15
-0
src/main/scala/xiangshan/XSCore.scala
src/main/scala/xiangshan/XSCore.scala
+2
-0
src/main/scala/xiangshan/frontend/BPU.scala
src/main/scala/xiangshan/frontend/BPU.scala
+41
-20
src/main/scala/xiangshan/frontend/Bim.scala
src/main/scala/xiangshan/frontend/Bim.scala
+0
-9
src/main/scala/xiangshan/frontend/IFU.scala
src/main/scala/xiangshan/frontend/IFU.scala
+30
-61
src/main/scala/xiangshan/frontend/LoopPredictor.scala
src/main/scala/xiangshan/frontend/LoopPredictor.scala
+70
-18
src/main/scala/xiangshan/frontend/RAS.scala
src/main/scala/xiangshan/frontend/RAS.scala
+148
-103
src/main/scala/xiangshan/frontend/SC.scala
src/main/scala/xiangshan/frontend/SC.scala
+146
-0
src/main/scala/xiangshan/frontend/Tage.scala
src/main/scala/xiangshan/frontend/Tage.scala
+138
-36
src/main/scala/xiangshan/frontend/uBTB.scala
src/main/scala/xiangshan/frontend/uBTB.scala
+159
-54
src/test/csrc/emu.cpp
src/test/csrc/emu.cpp
+6
-6
src/test/csrc/emu.h
src/test/csrc/emu.h
+2
-0
src/test/csrc/snapshot.cpp
src/test/csrc/snapshot.cpp
+2
-0
src/test/csrc/snapshot.h
src/test/csrc/snapshot.h
+7
-0
未找到文件。
Makefile
浏览文件 @
6b0d407e
...
...
@@ -52,14 +52,22 @@ EMU_VSRC_DIR = $(abspath ./src/test/vsrc)
EMU_CXXFILES
=
$(
shell
find
$(EMU_CSRC_DIR)
-name
"*.cpp"
)
EMU_VFILES
=
$(
shell
find
$(EMU_VSRC_DIR)
-name
"*.v"
-or
-name
"*.sv"
)
EMU_CXXFLAGS
=
-std
=
c++11
-static
-Wall
-I
$(EMU_CSRC_DIR)
EMU_CXXFLAGS
+
=
-std
=
c++11
-static
-Wall
-I
$(EMU_CSRC_DIR)
EMU_CXXFLAGS
+=
-DVERILATOR
-Wno-maybe-uninitialized
EMU_LDFLAGS
=
-lpthread
-lSDL2
-ldl
EMU_THREADS
=
1
ifeq
($(EMU_THREADS), 1)
VTHREAD_FLAGS
=
--threads
1
else
VTHREAD_FLAGS
=
--threads
$(EMU_THREADS)
--threads-dpi
none
# Verilator trace support
VEXTRA_FLAGS
=
--trace
# Verilator multi-thread support
EMU_THREADS
?=
1
VEXTRA_FLAGS
+=
--threads
$(EMU_THREADS)
--threads-dpi
none
# Verilator savable
EMU_SNAPSHOT
?=
0
ifeq
($(EMU_SNAPSHOT),1)
VEXTRA_FLAGS
+=
--savable
EMU_CXXFLAGS
+=
-DVM_SAVABLE
endif
# --trace
...
...
@@ -68,10 +76,8 @@ VERILATOR_FLAGS = --top-module $(SIM_TOP) \
+define+PRINTF_COND
=
1
\
+define+RANDOMIZE_REG_INIT
\
+define+RANDOMIZE_MEM_INIT
\
$(VTHREAD_FLAGS)
\
--trace
\
$(VEXTRA_FLAGS)
\
--assert
\
--savable
\
--stats-vars
\
--output-split
5000
\
--output-split-cfuncs
5000
\
...
...
@@ -97,7 +103,7 @@ $(EMU): $(EMU_MK) $(EMU_DEPS) $(EMU_HEADERS) $(REF_SO)
ifeq
($(REMOTE),localhost)
CPPFLAGS
=
-DREF_SO
=
\\\"
$(REF_SO)
\\\"
$(MAKE)
VM_PARALLEL_BUILDS
=
1
OPT_FAST
=
"-O3"
-C
$(
abspath
$(
dir
$(EMU_MK)
))
-f
$(
abspath
$(EMU_MK)
)
else
ssh
-tt
$(REMOTE)
'CPPFLAGS=-DREF_SO=\\\"
$(REF_SO)
\\\"
$(MAKE)
-j
8
0 VM_PARALLEL_BUILDS=1 OPT_FAST="-O3" -C
$(
abspath
$(
dir
$(EMU_MK)
))
-f
$(
abspath
$(EMU_MK)
)
'
ssh
-tt
$(REMOTE)
'CPPFLAGS=-DREF_SO=\\\"
$(REF_SO)
\\\"
$(MAKE)
-j
20
0 VM_PARALLEL_BUILDS=1 OPT_FAST="-O3" -C
$(
abspath
$(
dir
$(EMU_MK)
))
-f
$(
abspath
$(EMU_MK)
)
'
endif
SEED
?=
$(
shell
shuf
-i
1-10000
-n
1
)
...
...
@@ -108,7 +114,6 @@ SEED ?= $(shell shuf -i 1-10000 -n 1)
B
?=
0
E
?=
-1
SNAPSHOT
?=
ENABLESNAPSHOT
?=
0
# enable this runtime option if you want to generate a vcd file
# use 'emu -h' to see more details
...
...
@@ -121,10 +126,6 @@ SNAPSHOT_OPTION = --load-snapshot=$(SNAPSHOT)
endif
ifeq
($(ENABLESNAPSHOT),1)
EMU_CXXFLAGS
+=
-D__ENABLESNAPSHOT__
endif
EMU_FLAGS
=
-s
$(SEED)
-b
$(B)
-e
$(E)
$(SNAPSHOT_OPTION)
$(WAVEFORM)
emu
:
$(EMU)
...
...
debug/sc_stat.sh
0 → 100755
浏览文件 @
6b0d407e
#!/bin/bash
log_dir
=
$1
tage_w_sc_w
=
$(
grep
"scUpdate"
$log_dir
|
grep
"sc(1), tage(1)"
-c
)
tage_w_sc_r
=
$(
grep
"scUpdate"
$log_dir
|
grep
"sc(0), tage(1)"
-c
)
tage_r_sc_w
=
$(
grep
"scUpdate"
$log_dir
|
grep
"sc(1), tage(0)"
-c
)
tage_r_sc_r
=
$(
grep
"scUpdate"
$log_dir
|
grep
"sc(0), tage(0)"
-c
)
echo
$tage_r_sc_w
tage right but mispredicted by sc
echo
$tage_w_sc_r
tage wrong and rectified by sc
echo
`
expr
$tage_w_sc_w
+
$tage_r_sc_r
`
branches remain unchanged,
in
which
$tage_w_sc_w
are wrong
src/main/scala/xiangshan/Bundle.scala
浏览文件 @
6b0d407e
...
...
@@ -10,6 +10,7 @@ import xiangshan.mem.{LqPtr, SqPtr}
import
xiangshan.frontend.PreDecodeInfo
import
xiangshan.frontend.HasBPUParameter
import
xiangshan.frontend.HasTageParameter
import
scala.math.max
// Fetch FetchWidth x 32-bit insts from Icache
class
FetchPacket
extends
XSBundle
{
...
...
@@ -37,12 +38,26 @@ object ValidUndirectioned {
}
}
class
SCMeta
(
val
useSC
:
Boolean
)
extends
XSBundle
with
HasTageParameter
{
def
maxVal
=
8
*
((
1
<<
TageCtrBits
)
-
1
)
+
SCTableInfo
.
map
{
case
(
_
,
cb
,
_
)
=>
(
1
<<
cb
)
-
1
}.
reduce
(
_
+
_
)
def
minVal
=
-(
8
*
(
1
<<
TageCtrBits
)
+
SCTableInfo
.
map
{
case
(
_
,
cb
,
_
)
=>
1
<<
cb
}.
reduce
(
_
+
_
))
def
sumCtrBits
=
max
(
log2Ceil
(-
minVal
),
log2Ceil
(
maxVal
+
1
))
+
1
val
tageTaken
=
if
(
useSC
)
Bool
()
else
UInt
(
0.
W
)
val
scUsed
=
if
(
useSC
)
Bool
()
else
UInt
(
0.
W
)
val
scPred
=
if
(
useSC
)
Bool
()
else
UInt
(
0.
W
)
// Suppose ctrbits of all tables are identical
val
ctrs
=
if
(
useSC
)
Vec
(
SCNTables
,
SInt
(
SCCtrBits
.
W
))
else
Vec
(
SCNTables
,
SInt
(
0.
W
))
val
sumAbs
=
if
(
useSC
)
UInt
(
sumCtrBits
.
W
)
else
UInt
(
0.
W
)
}
class
TageMeta
extends
XSBundle
with
HasTageParameter
{
val
provider
=
ValidUndirectioned
(
UInt
(
log2Ceil
(
TageNTables
).
W
))
val
altDiffers
=
Bool
()
val
providerU
=
UInt
(
2.
W
)
val
providerCtr
=
UInt
(
3.
W
)
val
allocate
=
ValidUndirectioned
(
UInt
(
log2Ceil
(
TageNTables
).
W
))
val
taken
=
Bool
()
val
scMeta
=
new
SCMeta
(
EnableSC
)
}
class
BranchPrediction
extends
XSBundle
{
...
...
src/main/scala/xiangshan/XSCore.scala
浏览文件 @
6b0d407e
...
...
@@ -37,6 +37,7 @@ case class XSCoreParameters
EnableRAS
:
Boolean
=
true
,
EnableLB
:
Boolean
=
true
,
EnableLoop
:
Boolean
=
true
,
EnableSC
:
Boolean
=
false
,
HistoryLength
:
Int
=
64
,
BtbSize
:
Int
=
2048
,
JbtacSize
:
Int
=
1024
,
...
...
@@ -121,6 +122,7 @@ trait HasXSParameter {
val
EnableRAS
=
core
.
EnableRAS
val
EnableLB
=
core
.
EnableLB
val
EnableLoop
=
core
.
EnableLoop
val
EnableSC
=
core
.
EnableSC
val
HistoryLength
=
core
.
HistoryLength
val
BtbSize
=
core
.
BtbSize
// val BtbWays = 4
...
...
src/main/scala/xiangshan/frontend/BPU.scala
浏览文件 @
6b0d407e
...
...
@@ -11,7 +11,7 @@ trait HasBPUParameter extends HasXSParameter {
val
BPUDebug
=
false
val
EnableCFICommitLog
=
true
val
EnbaleCFIPredLog
=
true
val
EnableBPUTimeRecord
=
true
val
EnableBPUTimeRecord
=
EnableCFICommitLog
||
EnbaleCFIPredLog
}
class
TableAddr
(
val
idxBits
:
Int
,
val
banks
:
Int
)
extends
XSBundle
{
...
...
@@ -63,7 +63,42 @@ class PredictorResponse extends XSBundle {
val
loop
=
new
LoopResp
}
abstract
class
BasePredictor
extends
XSModule
with
HasBPUParameter
{
trait
PredictorUtils
{
// circular shifting
def
circularShiftLeft
(
source
:
UInt
,
len
:
Int
,
shamt
:
UInt
)
:
UInt
=
{
val
res
=
Wire
(
UInt
(
len
.
W
))
val
higher
=
source
<<
shamt
val
lower
=
source
>>
(
len
.
U
-
shamt
)
res
:=
higher
|
lower
res
}
def
circularShiftRight
(
source
:
UInt
,
len
:
Int
,
shamt
:
UInt
)
:
UInt
=
{
val
res
=
Wire
(
UInt
(
len
.
W
))
val
higher
=
source
<<
(
len
.
U
-
shamt
)
val
lower
=
source
>>
shamt
res
:=
higher
|
lower
res
}
// To be verified
def
satUpdate
(
old
:
UInt
,
len
:
Int
,
taken
:
Bool
)
:
UInt
=
{
val
oldSatTaken
=
old
===
((
1
<<
len
)-
1
).
U
val
oldSatNotTaken
=
old
===
0.
U
Mux
(
oldSatTaken
&&
taken
,
((
1
<<
len
)-
1
).
U
,
Mux
(
oldSatNotTaken
&&
!
taken
,
0.
U
,
Mux
(
taken
,
old
+
1.
U
,
old
-
1.
U
)))
}
def
signedSatUpdate
(
old
:
SInt
,
len
:
Int
,
taken
:
Bool
)
:
SInt
=
{
val
oldSatTaken
=
old
===
((
1
<<
(
len
-
1
))-
1
).
S
val
oldSatNotTaken
=
old
===
(-(
1
<<
(
len
-
1
))).
S
Mux
(
oldSatTaken
&&
taken
,
((
1
<<
(
len
-
1
))-
1
).
S
,
Mux
(
oldSatNotTaken
&&
!
taken
,
(-(
1
<<
(
len
-
1
))).
S
,
Mux
(
taken
,
old
+
1.
S
,
old
-
1.
S
)))
}
}
abstract
class
BasePredictor
extends
XSModule
with
HasBPUParameter
with
PredictorUtils
{
val
metaLen
=
0
// An implementation MUST extend the IO bundle with a response
...
...
@@ -85,23 +120,6 @@ abstract class BasePredictor extends XSModule with HasBPUParameter{
val
io
=
new
DefaultBasePredictorIO
val
debug
=
false
// circular shifting
def
circularShiftLeft
(
source
:
UInt
,
len
:
Int
,
shamt
:
UInt
)
:
UInt
=
{
val
res
=
Wire
(
UInt
(
len
.
W
))
val
higher
=
source
<<
shamt
val
lower
=
source
>>
(
len
.
U
-
shamt
)
res
:=
higher
|
lower
res
}
def
circularShiftRight
(
source
:
UInt
,
len
:
Int
,
shamt
:
UInt
)
:
UInt
=
{
val
res
=
Wire
(
UInt
(
len
.
W
))
val
higher
=
source
<<
(
len
.
U
-
shamt
)
val
lower
=
source
>>
shamt
res
:=
higher
|
lower
res
}
}
class
BPUStageIO
extends
XSBundle
{
...
...
@@ -237,6 +255,9 @@ class BPUStage1 extends BPUStage {
io
.
out
.
bits
.
resp
<>
io
.
in
.
bits
.
resp
io
.
out
.
bits
.
brInfo
:=
io
.
in
.
bits
.
brInfo
// we do not need to compare target in stage1
io
.
pred
.
bits
.
redirect
:=
taken
if
(
BPUDebug
)
{
XSDebug
(
io
.
pred
.
fire
(),
"outPred using ubtb resp: hits:%b, takens:%b, notTakens:%b, isRVC:%b\n"
,
ubtbResp
.
hits
.
asUInt
,
ubtbResp
.
takens
.
asUInt
,
~
ubtbResp
.
takens
.
asUInt
&
brMask
.
asUInt
,
ubtbResp
.
is_RVC
.
asUInt
)
...
...
@@ -571,7 +592,7 @@ class BPU extends BaseBPU {
s1
.
io
.
in
.
valid
:=
io
.
in
.
valid
s1
.
io
.
in
.
bits
.
pc
:=
io
.
in
.
bits
.
pc
s1
.
io
.
in
.
bits
.
mask
:=
io
.
in
.
bits
.
inMask
s1
.
io
.
in
.
bits
.
target
:=
npc
(
io
.
in
.
bits
.
pc
,
PopCount
(
io
.
in
.
bits
.
inMask
))
// Deault target npc
s1
.
io
.
in
.
bits
.
target
:=
DontCare
s1
.
io
.
in
.
bits
.
resp
<>
s1_resp_in
s1
.
io
.
in
.
bits
.
brInfo
<>
s1_brInfo_in
s1
.
io
.
in
.
bits
.
saveHalfRVI
:=
false
.
B
...
...
src/main/scala/xiangshan/frontend/Bim.scala
浏览文件 @
6b0d407e
...
...
@@ -29,15 +29,6 @@ class BIM extends BasePredictor with BimParams{
}
override
val
io
=
IO
(
new
BIMIO
)
// Update logic
// 1 calculate new 2-bit saturated counter value
def
satUpdate
(
old
:
UInt
,
len
:
Int
,
taken
:
Bool
)
:
UInt
=
{
val
oldSatTaken
=
old
===
((
1
<<
len
)-
1
).
U
val
oldSatNotTaken
=
old
===
0.
U
Mux
(
oldSatTaken
&&
taken
,
((
1
<<
len
)-
1
).
U
,
Mux
(
oldSatNotTaken
&&
!
taken
,
0.
U
,
Mux
(
taken
,
old
+
1.
U
,
old
-
1.
U
)))
}
val
bimAddr
=
new
TableAddr
(
log2Up
(
BimSize
),
BimBanks
)
...
...
src/main/scala/xiangshan/frontend/IFU.scala
浏览文件 @
6b0d407e
...
...
@@ -84,10 +84,13 @@ class IFU extends XSModule with HasIFUConst
shiftPtr
:=
false
.
B
newPtr
:=
if1_histPtr
val
if1_GHInfo
=
Wire
(
new
GlobalHistoryInfo
())
if1_GHInfo
:=
0.
U
.
asTypeOf
(
new
GlobalHistoryInfo
)
def
wrapGHInfo
(
bp
:
BranchPrediction
)
=
{
val
ghi
=
Wire
(
new
GlobalHistoryInfo
())
ghi
.
sawNTBr
:=
bp
.
hasNotTakenBrs
ghi
.
takenOnBr
:=
bp
.
takenOnBr
ghi
.
saveHalfRVI
:=
bp
.
saveHalfRVI
ghi
}
//********************** IF2 ****************************//
val
if2_valid
=
RegEnable
(
next
=
if1_valid
,
init
=
false
.
B
,
enable
=
if1_fire
)
...
...
@@ -95,7 +98,6 @@ class IFU extends XSModule with HasIFUConst
val
if2_fire
=
if2_valid
&&
if3_ready
&&
!
if2_flush
val
if2_pc
=
RegEnable
(
next
=
if1_npc
,
init
=
resetVector
.
U
,
enable
=
if1_fire
)
val
if2_snpc
=
snpc
(
if2_pc
)
val
if2_GHInfo
=
RegEnable
(
if1_GHInfo
,
if1_fire
)
val
if2_predHistPtr
=
RegEnable
(
ptr
,
enable
=
if1_fire
)
if2_ready
:=
if2_fire
||
!
if2_valid
||
if2_flush
when
(
if2_flush
)
{
if2_valid
:=
if1_fire
}
...
...
@@ -118,17 +120,14 @@ class IFU extends XSModule with HasIFUConst
if1_npc
:=
if2_bp
.
target
}
val
if2_realGHInfo
=
Wire
(
new
GlobalHistoryInfo
())
if2_realGHInfo
.
sawNTBr
:=
if2_bp
.
hasNotTakenBrs
if2_realGHInfo
.
takenOnBr
:=
if2_bp
.
takenOnBr
if2_realGHInfo
.
saveHalfRVI
:=
if2_bp
.
saveHalfRVI
val
if2_GHInfo
=
wrapGHInfo
(
if2_bp
)
when
(
if2_fire
&&
if2_
real
GHInfo
.
shifted
)
{
when
(
if2_fire
&&
if2_GHInfo
.
shifted
)
{
shiftPtr
:=
true
.
B
newPtr
:=
if2_newPtr
}
when
(
if2_
real
GHInfo
.
shifted
&&
if2_newPtr
>=
ptr
)
{
hist
(
if2_newPtr
-
ptr
)
:=
if2_
real
GHInfo
.
takenOnBr
.
asUInt
when
(
if2_GHInfo
.
shifted
&&
if2_newPtr
>=
ptr
)
{
hist
(
if2_newPtr
-
ptr
)
:=
if2_GHInfo
.
takenOnBr
.
asUInt
}
...
...
@@ -138,7 +137,6 @@ class IFU extends XSModule with HasIFUConst
val
if4_ready
=
WireInit
(
false
.
B
)
val
if3_fire
=
if3_valid
&&
if4_ready
&&
(
inLoop
||
io
.
icacheResp
.
valid
)
&&
!
if3_flush
val
if3_pc
=
RegEnable
(
if2_pc
,
if2_fire
)
val
if3_GHInfo
=
RegEnable
(
if2_realGHInfo
,
if2_fire
)
val
if3_predHistPtr
=
RegEnable
(
if2_predHistPtr
,
enable
=
if2_fire
)
if3_ready
:=
if3_fire
||
!
if3_valid
||
if3_flush
when
(
if3_flush
)
{
if3_valid
:=
false
.
B
}
...
...
@@ -147,10 +145,7 @@ class IFU extends XSModule with HasIFUConst
val
if3_bp
=
bpu
.
io
.
out
(
1
).
bits
val
if3_realGHInfo
=
Wire
(
new
GlobalHistoryInfo
())
if3_realGHInfo
.
sawNTBr
:=
if3_bp
.
hasNotTakenBrs
if3_realGHInfo
.
takenOnBr
:=
if3_bp
.
takenOnBr
if3_realGHInfo
.
saveHalfRVI
:=
if3_bp
.
saveHalfRVI
val
if3_GHInfo
=
wrapGHInfo
(
if3_bp
)
class
PrevHalfInstr
extends
Bundle
{
val
valid
=
Bool
()
...
...
@@ -189,7 +184,7 @@ class IFU extends XSModule with HasIFUConst
when
(
if3_redirect
)
{
when
(!(
if3_hasPrevHalfInstr
&&
prevHalfInstr
.
taken
))
{
if1_npc
:=
if3_bp
.
target
when
(
if3_
real
GHInfo
.
shifted
){
when
(
if3_GHInfo
.
shifted
){
shiftPtr
:=
true
.
B
newPtr
:=
if3_newPtr
}
...
...
@@ -197,8 +192,8 @@ class IFU extends XSModule with HasIFUConst
}
// when it does not redirect, we still need to modify hist(wire)
when
(
if3_
real
GHInfo
.
shifted
&&
if3_newPtr
>=
ptr
)
{
hist
(
if3_newPtr
-
ptr
)
:=
if3_
real
GHInfo
.
takenOnBr
when
(
if3_GHInfo
.
shifted
&&
if3_newPtr
>=
ptr
)
{
hist
(
if3_newPtr
-
ptr
)
:=
if3_GHInfo
.
takenOnBr
}
when
(
if3_hasPrevHalfInstr
&&
prevHalfInstr
.
ghInfo
.
shifted
&&
prevHalfInstr
.
newPtr
>=
ptr
)
{
hist
(
prevHalfInstr
.
newPtr
-
ptr
)
:=
prevHalfInstr
.
ghInfo
.
takenOnBr
...
...
@@ -212,7 +207,6 @@ class IFU extends XSModule with HasIFUConst
val
if4_fire
=
if4_valid
&&
io
.
fetchPacket
.
ready
val
if4_pc
=
RegEnable
(
if3_pc
,
if3_fire
)
val
if4_GHInfo
=
RegEnable
(
if3_realGHInfo
,
if3_fire
)
val
if4_predHistPtr
=
RegEnable
(
if3_predHistPtr
,
enable
=
if3_fire
)
if4_ready
:=
(
if4_fire
||
!
if4_valid
||
if4_flush
)
&&
GTimer
()
>
500.
U
when
(
if4_flush
)
{
if4_valid
:=
false
.
B
}
...
...
@@ -222,11 +216,7 @@ class IFU extends XSModule with HasIFUConst
val
if4_bp
=
Wire
(
new
BranchPrediction
)
if4_bp
:=
bpu
.
io
.
out
(
2
).
bits
val
if4_realGHInfo
=
Wire
(
new
GlobalHistoryInfo
())
if4_realGHInfo
.
sawNTBr
:=
if4_bp
.
hasNotTakenBrs
if4_realGHInfo
.
takenOnBr
:=
if4_bp
.
takenOnBr
if4_realGHInfo
.
saveHalfRVI
:=
if4_bp
.
saveHalfRVI
val
if4_GHInfo
=
wrapGHInfo
(
if4_bp
)
val
if4_cfi_jal
=
if4_pd
.
instrs
(
if4_bp
.
jmpIdx
)
val
if4_cfi_jal_tgt
=
if4_pd
.
pc
(
if4_bp
.
jmpIdx
)
+
Mux
(
if4_pd
.
pd
(
if4_bp
.
jmpIdx
).
isRVC
,
...
...
@@ -239,7 +229,7 @@ class IFU extends XSModule with HasIFUConst
when
(
bpu
.
io
.
out
(
2
).
valid
&&
if4_fire
&&
if4_bp
.
saveHalfRVI
)
{
if4_prevHalfInstr
.
valid
:=
true
.
B
if4_prevHalfInstr
.
taken
:=
if4_bp
.
taken
if4_prevHalfInstr
.
ghInfo
:=
if4_
real
GHInfo
if4_prevHalfInstr
.
ghInfo
:=
if4_GHInfo
// Make sure shifted can work
if4_prevHalfInstr
.
ghInfo
.
saveHalfRVI
:=
false
.
B
if4_prevHalfInstr
.
newPtr
:=
if4_newPtr
...
...
@@ -260,14 +250,6 @@ class IFU extends XSModule with HasIFUConst
if1_npc
:=
if4_bp
.
target
}
}
// }.elsewhen (bpu.io.out(2).valid && if4_fire/* && !if4_bp.redirect*/) {
// // We redirect the pipeline to the next fetch packet,
// // which contains the last half of the RVI instruction
// when (if4_bp.saveHalfRVI && if4_bp.taken) {
// if4_redirect := true.B
// if1_npc := snpc(if4_pc)
// }
// }
// This should cover the if4 redirect to snpc when saveHalfRVI
when
(
if3_redirect
)
{
...
...
@@ -280,20 +262,10 @@ class IFU extends XSModule with HasIFUConst
when
(
bpu
.
io
.
out
(
2
).
valid
&&
if4_fire
&&
if4_bp
.
redirect
)
{
shiftPtr
:=
true
.
B
newPtr
:=
if4_newPtr
// }.elsewhen (bpu.io.out(2).valid && if4_fire/* && !if4_bp.redirect*/) {
// // only if we hasn't seen not taken branches and
// // see a not taken branch in if4 should we tell
// // if3 and if4 to update histptr
// // We do not shift global history pointer unless we have the full
// // RVI instruction
// when (if4_newSawNTBrs && !if4_bp.takenOnBr) {
// shiftPtr := true.B
// // newPtr := if4_realGHInfo.newPtr
// }
}
when
(
if4_
real
GHInfo
.
shifted
&&
if4_newPtr
>=
ptr
)
{
hist
(
if4_newPtr
-
ptr
)
:=
if4_
real
GHInfo
.
takenOnBr
when
(
if4_GHInfo
.
shifted
&&
if4_newPtr
>=
ptr
)
{
hist
(
if4_newPtr
-
ptr
)
:=
if4_GHInfo
.
takenOnBr
}
when
(
if3_redirect
)
{
...
...
@@ -306,8 +278,8 @@ class IFU extends XSModule with HasIFUConst
}
// modify GHR at the end of a prediction lifetime
when
(
if4_fire
&&
if4_
real
GHInfo
.
shifted
)
{
extHist
(
if4_newPtr
)
:=
if4_
real
GHInfo
.
takenOnBr
when
(
if4_fire
&&
if4_GHInfo
.
shifted
)
{
extHist
(
if4_newPtr
)
:=
if4_GHInfo
.
takenOnBr
}
// This is a histPtr which is only modified when a prediction
...
...
@@ -315,17 +287,17 @@ class IFU extends XSModule with HasIFUConst
val
finalPredHistPtr
=
RegInit
(
0.
U
(
log2Up
(
ExtHistoryLength
).
W
))
if4_histPtr
:=
finalPredHistPtr
if4_newPtr
:=
if3_histPtr
when
(
if4_fire
&&
if4_
real
GHInfo
.
shifted
)
{
when
(
if4_fire
&&
if4_GHInfo
.
shifted
)
{
finalPredHistPtr
:=
if4_newPtr
}
if3_histPtr
:=
Mux
(
if4_
real
GHInfo
.
shifted
&&
if4_valid
&&
!
if4_flush
,
if4_histPtr
-
1.
U
,
if4_histPtr
)
if3_histPtr
:=
Mux
(
if4_GHInfo
.
shifted
&&
if4_valid
&&
!
if4_flush
,
if4_histPtr
-
1.
U
,
if4_histPtr
)
if3_newPtr
:=
if2_histPtr
if2_histPtr
:=
Mux
(
if3_
real
GHInfo
.
shifted
&&
if3_valid
&&
!
if3_flush
,
if3_histPtr
-
1.
U
,
if3_histPtr
)
if2_histPtr
:=
Mux
(
if3_GHInfo
.
shifted
&&
if3_valid
&&
!
if3_flush
,
if3_histPtr
-
1.
U
,
if3_histPtr
)
if2_newPtr
:=
if1_histPtr
if1_histPtr
:=
Mux
(
if2_
real
GHInfo
.
shifted
&&
if2_valid
&&
!
if2_flush
,
if2_histPtr
-
1.
U
,
if2_histPtr
)
if1_histPtr
:=
Mux
(
if2_GHInfo
.
shifted
&&
if2_valid
&&
!
if2_flush
,
if2_histPtr
-
1.
U
,
if2_histPtr
)
...
...
@@ -473,16 +445,15 @@ class IFU extends XSModule with HasIFUConst
XSDebug
(
"[IF1] v=%d fire=%d flush=%d pc=%x ptr=%d mask=%b\n"
,
if1_valid
,
if1_fire
,
if1_flush
,
if1_npc
,
ptr
,
mask
(
if1_npc
))
XSDebug
(
"[IF2] v=%d r=%d fire=%d redirect=%d flush=%d pc=%x ptr=%d snpc=%x\n"
,
if2_valid
,
if2_ready
,
if2_fire
,
if2_redirect
,
if2_flush
,
if2_pc
,
if2_histPtr
,
if2_snpc
)
XSDebug
(
"[IF3] v=%d r=%d fire=%d redirect=%d flush=%d pc=%x ptr=%d crossPageIPF=%d sawNTBrs=%d\n"
,
if3_valid
,
if3_ready
,
if3_fire
,
if3_redirect
,
if3_flush
,
if3_pc
,
if3_histPtr
,
crossPageIPF
,
if3_
real
GHInfo
.
sawNTBr
)
XSDebug
(
"[IF4] v=%d r=%d fire=%d redirect=%d flush=%d pc=%x ptr=%d crossPageIPF=%d sawNTBrs=%d\n"
,
if4_valid
,
if4_ready
,
if4_fire
,
if4_redirect
,
if4_flush
,
if4_pc
,
if4_histPtr
,
if4_crossPageIPF
,
if4_
real
GHInfo
.
sawNTBr
)
XSDebug
(
"[IF3] v=%d r=%d fire=%d redirect=%d flush=%d pc=%x ptr=%d crossPageIPF=%d sawNTBrs=%d\n"
,
if3_valid
,
if3_ready
,
if3_fire
,
if3_redirect
,
if3_flush
,
if3_pc
,
if3_histPtr
,
crossPageIPF
,
if3_GHInfo
.
sawNTBr
)
XSDebug
(
"[IF4] v=%d r=%d fire=%d redirect=%d flush=%d pc=%x ptr=%d crossPageIPF=%d sawNTBrs=%d\n"
,
if4_valid
,
if4_ready
,
if4_fire
,
if4_redirect
,
if4_flush
,
if4_pc
,
if4_histPtr
,
if4_crossPageIPF
,
if4_GHInfo
.
sawNTBr
)
XSDebug
(
"[IF1][icacheReq] v=%d r=%d addr=%x\n"
,
io
.
icacheReq
.
valid
,
io
.
icacheReq
.
ready
,
io
.
icacheReq
.
bits
.
addr
)
XSDebug
(
"[IF1][ghr] headPtr=%d shiftPtr=%d newPtr=%d ptr=%d\n"
,
if1_histPtr
,
shiftPtr
,
newPtr
,
ptr
)
XSDebug
(
"[IF1][ghr] hist=%b\n"
,
hist
.
asUInt
)
XSDebug
(
"[IF1][ghr] extHist=%b\n\n"
,
extHist
.
asUInt
)
XSDebug
(
"[IF2][bp] redirect=%d taken=%d jmpIdx=%d hasNTBrs=%d target=%x saveHalfRVI=%d\n\n"
,
if2_bp
.
redirect
,
if2_bp
.
taken
,
if2_bp
.
jmpIdx
,
if2_bp
.
hasNotTakenBrs
,
if2_bp
.
target
,
if2_bp
.
saveHalfRVI
)
// XSDebug("[IF2][GHInfo]: %s\n", if2_realGHInfo)
if2_realGHInfo
.
debug
if2_GHInfo
.
debug
XSDebug
(
"[IF3][icacheResp] v=%d r=%d pc=%x mask=%b\n"
,
io
.
icacheResp
.
valid
,
io
.
icacheResp
.
ready
,
io
.
icacheResp
.
bits
.
pc
,
io
.
icacheResp
.
bits
.
mask
)
XSDebug
(
"[IF3][bp] redirect=%d taken=%d jmpIdx=%d hasNTBrs=%d target=%x saveHalfRVI=%d\n"
,
if3_bp
.
redirect
,
if3_bp
.
taken
,
if3_bp
.
jmpIdx
,
if3_bp
.
hasNotTakenBrs
,
if3_bp
.
target
,
if3_bp
.
saveHalfRVI
)
...
...
@@ -492,16 +463,14 @@ class IFU extends XSModule with HasIFUConst
prevHalfInstr
.
valid
,
prevHalfInstr
.
taken
,
prevHalfInstr
.
fetchpc
,
prevHalfInstr
.
idx
,
prevHalfInstr
.
pc
,
prevHalfInstr
.
target
,
prevHalfInstr
.
instr
,
prevHalfInstr
.
ipf
)
XSDebug
(
"[IF3][if3_prevHalfInstr] v=%d taken=%d fetchpc=%x idx=%d pc=%x tgt=%x instr=%x ipf=%d\n\n"
,
if3_prevHalfInstr
.
valid
,
if3_prevHalfInstr
.
taken
,
if3_prevHalfInstr
.
fetchpc
,
if3_prevHalfInstr
.
idx
,
if3_prevHalfInstr
.
pc
,
if3_prevHalfInstr
.
target
,
if3_prevHalfInstr
.
instr
,
if3_prevHalfInstr
.
ipf
)
// XSDebug("[IF3][GHInfo]: %s\n", if3_realGHInfo)
if3_realGHInfo
.
debug
if3_GHInfo
.
debug
XSDebug
(
"[IF4][predecode] mask=%b\n"
,
if4_pd
.
mask
)
XSDebug
(
"[IF4][bp] redirect=%d taken=%d jmpIdx=%d hasNTBrs=%d target=%x saveHalfRVI=%d\n"
,
if4_bp
.
redirect
,
if4_bp
.
taken
,
if4_bp
.
jmpIdx
,
if4_bp
.
hasNotTakenBrs
,
if4_bp
.
target
,
if4_bp
.
saveHalfRVI
)
XSDebug
(
if4_pd
.
pd
(
if4_bp
.
jmpIdx
).
isJal
&&
if4_bp
.
taken
,
"[IF4] cfi is jal! instr=%x target=%x\n"
,
if4_cfi_jal
,
if4_cfi_jal_tgt
)
XSDebug
(
"[IF4][if4_prevHalfInstr] v=%d taken=%d fetchpc=%x idx=%d pc=%x tgt=%x instr=%x ipf=%d\n"
,
if4_prevHalfInstr
.
valid
,
if4_prevHalfInstr
.
taken
,
if4_prevHalfInstr
.
fetchpc
,
if4_prevHalfInstr
.
idx
,
if4_prevHalfInstr
.
pc
,
if4_prevHalfInstr
.
target
,
if4_prevHalfInstr
.
instr
,
if4_prevHalfInstr
.
ipf
)
// XSDebug("[IF4][GHInfo]: %s\n", if4_realGHInfo)
if4_realGHInfo
.
debug
if4_GHInfo
.
debug
XSDebug
(
io
.
fetchPacket
.
fire
(),
"[IF4][fetchPacket] v=%d r=%d mask=%b ipf=%d crossPageIPF=%d\n"
,
io
.
fetchPacket
.
valid
,
io
.
fetchPacket
.
ready
,
io
.
fetchPacket
.
bits
.
mask
,
io
.
fetchPacket
.
bits
.
ipf
,
io
.
fetchPacket
.
bits
.
crossPageIPFFix
)
for
(
i
<-
0
until
PredictWidth
)
{
...
...
src/main/scala/xiangshan/frontend/LoopPredictor.scala
浏览文件 @
6b0d407e
...
...
@@ -77,7 +77,48 @@ class LTBColumn extends LTBModule {
val
repair
=
Input
(
Bool
())
// roll back specCnts in the other 15 LTBs
})
val
ltb
=
Reg
(
Vec
(
nRows
,
new
LoopEntry
))
class
LTBMem
extends
LTBModule
{
val
io
=
IO
(
new
Bundle
{
val
rIdx
=
Input
(
UInt
(
idxLen
.
W
))
val
rdata
=
Output
(
new
LoopEntry
)
val
urIdx
=
Input
(
UInt
(
idxLen
.
W
))
val
urdata
=
Output
(
new
LoopEntry
)
val
wen
=
Input
(
Bool
())
val
wIdx
=
Input
(
UInt
(
idxLen
.
W
))
val
wdata
=
Input
(
new
LoopEntry
)
val
swen
=
Input
(
Bool
())
val
swIdx
=
Input
(
UInt
(
idxLen
.
W
))
val
swdata
=
Input
(
new
LoopEntry
)
val
copyCnt
=
Input
(
Vec
(
nRows
,
Bool
()))
})
// val mem = RegInit(0.U.asTypeOf(Vec(nRows, new LoopEntry)))
val
mem
=
Mem
(
nRows
,
new
LoopEntry
)
io
.
rdata
:=
mem
(
io
.
rIdx
)
io
.
urdata
:=
mem
(
io
.
urIdx
)
val
wdata
=
WireInit
(
io
.
wdata
)
val
swdata
=
WireInit
(
io
.
swdata
)
for
(
i
<-
0
until
nRows
)
{
val
copyValid
=
io
.
copyCnt
(
i
)
when
(
copyValid
&&
io
.
swIdx
===
i
.
U
&&
io
.
swen
)
{
swdata
.
specCnt
:=
mem
(
i
).
nSpecCnt
}
val
wd
=
WireInit
(
mem
(
i
))
// default for copycnt
val
wen
=
WireInit
(
io
.
copyCnt
(
i
)
||
io
.
wen
&&
io
.
wIdx
===
i
.
U
||
io
.
swen
&&
io
.
swIdx
===
i
.
U
)
when
(!
copyValid
)
{
when
(
io
.
swen
)
{
wd
:=
swdata
}.
elsewhen
(
io
.
wen
)
{
wd
:=
wdata
}
}
when
(
wen
)
{
mem
.
write
(
i
.
U
,
wd
)
}
}
}
// val ltb = Reg(Vec(nRows, new LoopEntry))
val
ltb
=
Module
(
new
LTBMem
).
io
val
ltbAddr
=
new
TableAddr
(
idxLen
+
4
,
PredictWidth
)
val
updateIdx
=
ltbAddr
.
getBankIdx
(
io
.
update
.
bits
.
pc
)
val
updateTag
=
ltbAddr
.
getTag
(
io
.
update
.
bits
.
pc
)(
tagLen
-
1
,
0
)
...
...
@@ -92,7 +133,8 @@ class LTBColumn extends LTBModule {
val
if4_idx
=
io
.
req
.
idx
val
if4_tag
=
io
.
req
.
tag
val
if4_pc
=
io
.
req
.
pc
// only for debug
val
if4_entry
=
WireInit
(
ltb
(
if4_idx
))
ltb
.
rIdx
:=
if4_idx
val
if4_entry
=
WireInit
(
ltb
.
rdata
)
val
valid
=
RegInit
(
false
.
B
)
when
(
io
.
if4_fire
)
{
valid
:=
false
.
B
}
...
...
@@ -104,11 +146,16 @@ class LTBColumn extends LTBModule {
io
.
resp
.
exit
:=
if4_tag
===
if4_entry
.
tag
&&
(
if4_entry
.
specCnt
+
1.
U
)
===
if4_entry
.
tripCnt
&&
valid
&&
if4_entry
.
isConf
// when resolving a branch
val
entry
=
ltb
(
updateIdx
)
ltb
.
urIdx
:=
updateIdx
val
entry
=
ltb
.
urdata
val
tagMatch
=
entry
.
tag
===
updateTag
val
cntMatch
=
entry
.
tripCnt
===
io
.
update
.
bits
.
meta
val
wEntry
=
WireInit
(
entry
)
ltb
.
wIdx
:=
updateIdx
ltb
.
wdata
:=
wEntry
ltb
.
wen
:=
false
.
B
when
(
io
.
update
.
valid
&&
!
doingReset
)
{
// When a branch resolves and is found to not be in the LTB,
// it is inserted into the LTB if determined to be a loop-branch and if it is mispredicted by the default predictor.
...
...
@@ -121,7 +168,8 @@ class LTBColumn extends LTBModule {
wEntry
.
nSpecCnt
:=
Mux
(
io
.
update
.
bits
.
taken
,
1.
U
,
0.
U
)
wEntry
.
brTag
:=
updateBrTag
wEntry
.
unusable
:=
false
.
B
ltb
(
updateIdx
)
:=
wEntry
// ltb(updateIdx) := wEntry
ltb
.
wen
:=
true
.
B
}.
elsewhen
(
tagMatch
)
{
// During resolution, a taken branch found in the LTB has its nSpecCnt incremented by one.
when
(
io
.
update
.
bits
.
taken
)
{
...
...
@@ -142,40 +190,44 @@ class LTBColumn extends LTBModule {
wEntry
.
brTag
:=
updateBrTag
wEntry
.
unusable
:=
io
.
update
.
bits
.
misPred
&&
(
io
.
update
.
bits
.
meta
>
entry
.
tripCnt
)
}
ltb
(
updateIdx
)
:=
wEntry
// ltb(updateIdx) := wEntry
ltb
.
wen
:=
true
.
B
}
}
// speculatively update specCnt
ltb
.
swen
:=
valid
&&
if4_entry
.
tag
===
if4_tag
||
doingReset
ltb
.
swIdx
:=
Mux
(
doingReset
,
resetIdx
,
if4_idx
)
val
swEntry
=
WireInit
(
if4_entry
)
ltb
.
swdata
:=
Mux
(
doingReset
,
0.
U
.
asTypeOf
(
new
LoopEntry
),
swEntry
)
when
(
io
.
if4_fire
&&
if4_entry
.
tag
===
if4_tag
&&
io
.
outMask
)
{
when
((
if4_entry
.
specCnt
+
1.
U
)
===
if4_entry
.
tripCnt
)
{
ltb
(
if4_idx
)
.
age
:=
7.
U
ltb
(
if4_idx
)
.
specCnt
:=
0.
U
when
((
if4_entry
.
specCnt
+
1.
U
)
===
if4_entry
.
tripCnt
/* && if4_entry.isConf*/
)
{
swEntry
.
age
:=
7.
U
swEntry
.
specCnt
:=
0.
U
}.
otherwise
{
ltb
(
if4_idx
)
.
age
:=
Mux
(
if4_entry
.
age
===
7.
U
,
7.
U
,
if4_entry
.
age
+
1.
U
)
ltb
(
if4_idx
)
.
specCnt
:=
if4_entry
.
specCnt
+
1.
U
swEntry
.
age
:=
Mux
(
if4_entry
.
age
===
7.
U
,
7.
U
,
if4_entry
.
age
+
1.
U
)
swEntry
.
specCnt
:=
if4_entry
.
specCnt
+
1.
U
}
}
// Reseting
when
(
doingReset
)
{
ltb
(
resetIdx
)
:=
0.
U
.
asTypeOf
(
new
LoopEntry
)
}
//
when (doingReset) {
//
ltb(resetIdx) := 0.U.asTypeOf(new LoopEntry)
//
}
// when a branch misprediction occurs, all of the nSpecCnts copy their values into the specCnts
for
(
i
<-
0
until
nRows
)
{
when
(
io
.
update
.
valid
&&
io
.
update
.
bits
.
misPred
&&
i
.
U
=/=
updateIdx
||
io
.
repair
)
{
ltb
(
i
).
specCnt
:=
ltb
(
i
).
nSpecCnt
}
ltb
.
copyCnt
(
i
)
:=
io
.
update
.
valid
&&
io
.
update
.
bits
.
misPred
&&
i
.
U
=/=
updateIdx
||
io
.
repair
}
// bypass for if4_entry.specCnt
when
(
io
.
update
.
valid
&&
!
doingReset
&&
valid
&&
updateIdx
===
if4_idx
)
{
when
(!
tagMatch
&&
io
.
update
.
bits
.
misPred
||
tagMatch
)
{
if4_e
ntry
.
specCnt
:=
wEntry
.
specCnt
swE
ntry
.
specCnt
:=
wEntry
.
specCnt
}
}
when
(
io
.
repair
&&
!
doingReset
&&
valid
)
{
if4_e
ntry
.
specCnt
:=
if4_entry
.
nSpecCnt
swE
ntry
.
specCnt
:=
if4_entry
.
nSpecCnt
}
if
(
BPUDebug
&&
debug
)
{
...
...
src/main/scala/xiangshan/frontend/RAS.scala
浏览文件 @
6b0d407e
...
...
@@ -32,12 +32,95 @@ class RAS extends BasePredictor
val
branchInfo
=
Output
(
new
RASBranchInfo
)
}
def
rasEntry
()
=
new
Bundle
{
class
RASEntry
()
extends
XS
Bundle
{
val
retAddr
=
UInt
(
VAddrBits
.
W
)
val
ctr
=
UInt
(
8.
W
)
// layer of nested call functions
}
def
rasEntry
()
=
new
RASEntry
object
RASEntry
{
def
apply
(
retAddr
:
UInt
,
ctr
:
UInt
)
:
RASEntry
=
{
val
e
=
Wire
(
rasEntry
())
e
.
retAddr
:=
retAddr
e
.
ctr
:=
ctr
e
}
}
override
val
io
=
IO
(
new
RASIO
)
class
RASStack
(
val
rasSize
:
Int
)
extends
XSModule
{
val
io
=
IO
(
new
Bundle
{
val
push_valid
=
Input
(
Bool
())
val
pop_valid
=
Input
(
Bool
())
val
new_addr
=
Input
(
UInt
(
VAddrBits
.
W
))
val
top_addr
=
Output
(
UInt
(
VAddrBits
.
W
))
val
is_empty
=
Output
(
Bool
())
val
is_full
=
Output
(
Bool
())
val
copy_valid
=
Input
(
Bool
())
val
copy_in_mem
=
Input
(
Vec
(
rasSize
,
rasEntry
()))
val
copy_in_sp
=
Input
(
UInt
(
log2Up
(
rasSize
).
W
))
val
copy_out_mem
=
Output
(
Vec
(
rasSize
,
rasEntry
()))
val
copy_out_sp
=
Output
(
UInt
(
log2Up
(
rasSize
).
W
))
})
class
Stack
(
val
size
:
Int
)
extends
XSModule
{
val
io
=
IO
(
new
Bundle
{
val
rIdx
=
Input
(
UInt
(
log2Up
(
size
).
W
))
val
rdata
=
Output
(
rasEntry
())
val
wen
=
Input
(
Bool
())
val
wIdx
=
Input
(
UInt
(
log2Up
(
size
).
W
))
val
wdata
=
Input
(
rasEntry
())
val
copyen
=
Input
(
Bool
())
val
copy_in
=
Input
(
Vec
(
size
,
rasEntry
()))
val
copy_out
=
Output
(
Vec
(
size
,
rasEntry
()))
})
val
mem
=
Reg
(
Vec
(
size
,
rasEntry
()))
when
(
io
.
wen
)
{
mem
(
io
.
wIdx
)
:=
io
.
wdata
}
io
.
rdata
:=
mem
(
io
.
rIdx
)
(
0
until
size
).
foreach
{
i
=>
io
.
copy_out
(
i
)
:=
mem
(
i
)
}
when
(
io
.
copyen
)
{
(
0
until
size
).
foreach
{
i
=>
mem
(
i
)
:=
io
.
copy_in
(
i
)
}
}
}
val
sp
=
RegInit
(
0.
U
(
log2Up
(
rasSize
).
W
))
val
stack
=
Module
(
new
Stack
(
rasSize
)).
io
stack
.
rIdx
:=
sp
-
1.
U
val
top_entry
=
stack
.
rdata
val
top_addr
=
top_entry
.
retAddr
val
top_ctr
=
top_entry
.
ctr
val
alloc_new
=
io
.
new_addr
=/=
top_addr
stack
.
wen
:=
io
.
push_valid
||
io
.
pop_valid
&&
top_ctr
=/=
1.
U
stack
.
wIdx
:=
Mux
(
io
.
pop_valid
&&
top_ctr
=/=
1.
U
,
sp
-
1.
U
,
Mux
(
alloc_new
,
sp
,
sp
-
1.
U
))
stack
.
wdata
:=
Mux
(
io
.
pop_valid
&&
top_ctr
=/=
1.
U
,
RASEntry
(
top_addr
,
top_ctr
-
1.
U
),
Mux
(
alloc_new
,
RASEntry
(
io
.
new_addr
,
1.
U
),
RASEntry
(
top_addr
,
top_ctr
+
1.
U
)))
when
(
io
.
push_valid
&&
alloc_new
)
{
sp
:=
sp
+
1.
U
}
when
(
io
.
pop_valid
&&
top_ctr
===
1.
U
)
{
sp
:=
Mux
(
sp
===
0.
U
,
0.
U
,
sp
-
1.
U
)
}
io
.
copy_out_mem
:=
stack
.
copy_out
io
.
copy_out_sp
:=
sp
stack
.
copyen
:=
io
.
copy_valid
stack
.
copy_in
:=
io
.
copy_in_mem
when
(
io
.
copy_valid
)
{
sp
:=
io
.
copy_in_sp
}
io
.
top_addr
:=
top_addr
io
.
is_empty
:=
sp
===
0.
U
io
.
is_full
:=
sp
===
(
RasSize
-
1
).
U
}
// val ras_0 = Reg(Vec(RasSize, rasEntry())) //RegInit(0.U)asTypeOf(Vec(RasSize,rasEntry)) cause comb loop
// val ras_1 = Reg(Vec(RasSize, rasEntry()))
// val sp_0 = RegInit(0.U(log2Up(RasSize).W))
...
...
@@ -48,121 +131,83 @@ class RAS extends BasePredictor
// val commit_ras = Mux(choose_bit, ras_0, ras_1)
// val commit_sp = Mux(choose_bit,sp_0,sp_1)
val
spec_ras
=
Reg
(
Vec
(
RasSize
,
rasEntry
()))
val
spec_sp
=
RegInit
(
0.
U
(
log2Up
(
RasSize
).
W
))
val
commit_ras
=
Reg
(
Vec
(
RasSize
,
rasEntry
()))
val
commit_sp
=
RegInit
(
0.
U
(
log2Up
(
RasSize
).
W
))
//
val spec_ras = Reg(Vec(RasSize, rasEntry()))
//
val spec_sp = RegInit(0.U(log2Up(RasSize).W))
//
val commit_ras = Reg(Vec(RasSize, rasEntry()))
//
val commit_sp = RegInit(0.U(log2Up(RasSize).W))
val
spec_ras
=
Module
(
new
RASStack
(
RasSize
)).
io
val
spec_is_empty
=
spec_sp
===
0.
U
val
spec_is_full
=
spec_sp
===
(
RasSize
-
1
).
U
val
spec_push
=
WireInit
(
false
.
B
)
val
spec_pop
=
WireInit
(
false
.
B
)
val
spec_new_addr
=
WireInit
(
io
.
pc
.
bits
+
(
io
.
callIdx
.
bits
<<
1.
U
)
+
Mux
(
io
.
isRVC
,
2.
U
,
Mux
(
io
.
isLastHalfRVI
,
2.
U
,
4.
U
)))
spec_ras
.
push_valid
:=
spec_push
spec_ras
.
pop_valid
:=
spec_pop
spec_ras
.
new_addr
:=
spec_new_addr
val
spec_is_empty
=
spec_ras
.
is_empty
val
spec_is_full
=
spec_ras
.
is_full
val
spec_top_addr
=
spec_ras
.
top_addr
spec_push
:=
!
spec_is_full
&&
io
.
callIdx
.
valid
&&
io
.
pc
.
valid
spec_pop
:=
!
spec_is_empty
&&
io
.
is_ret
&&
io
.
pc
.
valid
val
commit_ras
=
Module
(
new
RASStack
(
RasSize
)).
io
val
commit_push
=
WireInit
(
false
.
B
)
val
commit_pop
=
WireInit
(
false
.
B
)
val
commit_new_addr
=
Mux
(
io
.
recover
.
bits
.
pd
.
isRVC
,
io
.
recover
.
bits
.
pc
+
2.
U
,
io
.
recover
.
bits
.
pc
+
4.
U
)
commit_ras
.
push_valid
:=
commit_push
commit_ras
.
pop_valid
:=
commit_pop
commit_ras
.
new_addr
:=
commit_new_addr
val
commit_is_empty
=
commit_ras
.
is_empty
val
commit_is_full
=
commit_ras
.
is_full
val
commit_top_addr
=
commit_ras
.
top_addr
commit_push
:=
!
commit_is_full
&&
io
.
recover
.
valid
&&
io
.
recover
.
bits
.
pd
.
isCall
commit_pop
:=
!
commit_is_empty
&&
io
.
recover
.
valid
&&
io
.
recover
.
bits
.
pd
.
isRet
val
spec_ras_top_entry
=
spec_ras
(
spec_sp
-
1.
U
)
val
spec_ras_top_addr
=
spec_ras_top_entry
.
retAddr
val
spec_ras_top_ctr
=
spec_ras_top_entry
.
ctr
//no need to pass the ras branchInfo
io
.
branchInfo
.
rasSp
:=
DontCare
io
.
branchInfo
.
rasTopCtr
:=
DontCare
io
.
branchInfo
.
rasToqAddr
:=
DontCare
io
.
out
.
valid
:=
!
spec_is_empty
&&
io
.
is_ret
io
.
out
.
bits
.
target
:=
spec_top_addr
io
.
out
.
bits
.
specEmpty
:=
spec_is_empty
// update spec RAS
// speculative update RAS
val
spec_push
=
!
spec_is_full
&&
io
.
callIdx
.
valid
&&
io
.
pc
.
valid
val
spec_pop
=
!
spec_is_empty
&&
io
.
is_ret
&&
io
.
pc
.
valid
val
spec_new_addr
=
io
.
pc
.
bits
+
(
io
.
callIdx
.
bits
<<
1.
U
)
+
Mux
(
io
.
isRVC
,
2.
U
,
Mux
(
io
.
isLastHalfRVI
,
2.
U
,
4.
U
))
val
spec_ras_write
=
WireInit
(
0.
U
.
asTypeOf
(
rasEntry
()))
val
sepc_alloc_new
=
spec_new_addr
=/=
spec_ras_top_addr
when
(
spec_push
)
{
//push
spec_ras_write
.
ctr
:=
1.
U
spec_ras_write
.
retAddr
:=
spec_new_addr
when
(
sepc_alloc_new
){
spec_sp
:=
spec_sp
+
1.
U
spec_ras
(
spec_sp
)
:=
spec_ras_write
}.
otherwise
{
spec_ras_top_ctr
:=
spec_ras_top_ctr
+
1.
U
}
}
when
(
spec_pop
)
{
//pop
when
(
spec_ras_top_ctr
===
1.
U
)
{
spec_sp
:=
Mux
(
spec_sp
===
0.
U
,
0.
U
,
spec_sp
-
1.
U
)
}.
otherwise
{
spec_ras_top_ctr
:=
spec_ras_top_ctr
-
1.
U
}
}
io
.
out
.
bits
.
target
:=
spec_ras_top_addr
// TODO: back-up stack for ras
// use checkpoint to recover RAS
val
commit_is_empty
=
commit_sp
===
0.
U
val
commit_is_full
=
commit_sp
===
(
RasSize
-
1
).
U
val
commit_ras_top_entry
=
commit_ras
(
commit_sp
-
1.
U
)
val
commit_ras_top_addr
=
commit_ras_top_entry
.
retAddr
val
commit_ras_top_ctr
=
commit_ras_top_entry
.
ctr
//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
=
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
)
{
//push
commit_ras_write
.
ctr
:=
1.
U
commit_ras_write
.
retAddr
:=
commit_new_addr
when
(
commit_alloc_new
){
commit_sp
:=
commit_sp
+
1.
U
commit_ras
(
commit_sp
)
:=
commit_ras_write
}.
otherwise
{
commit_ras_top_ctr
:=
commit_ras_top_ctr
+
1.
U
}
}
when
(
commit_pop
)
{
//pop
when
(
commit_ras_top_ctr
===
1.
U
)
{
commit_sp
:=
Mux
(
commit_sp
===
0.
U
,
0.
U
,
commit_sp
-
1.
U
)
}.
otherwise
{
commit_ras_top_ctr
:=
commit_ras_top_ctr
-
1.
U
}
}
val
copy_valid
=
io
.
recover
.
valid
&&
io
.
recover
.
bits
.
isMisPred
val
copy_next
=
RegNext
(
copy_valid
)
when
(
copy_next
)
{
for
(
i
<-
0
until
RasSize
)
{
spec_ras
(
i
)
:=
commit_ras
(
i
)
spec_sp
:=
commit_sp
}
}
spec_ras
.
copy_valid
:=
copy_next
spec_ras
.
copy_in_mem
:=
commit_ras
.
copy_out_mem
spec_ras
.
copy_in_sp
:=
commit_ras
.
copy_out_sp
commit_ras
.
copy_valid
:=
DontCare
commit_ras
.
copy_in_mem
:=
DontCare
commit_ras
.
copy_in_sp
:=
DontCare
if
(
BPUDebug
&&
debug
)
{
XSDebug
(
"----------------RAS(spec)----------------\n"
)
XSDebug
(
" index addr ctr \n"
)
for
(
i
<-
0
until
RasSize
){
XSDebug
(
" (%d) 0x%x %d"
,
i
.
U
,
spec_ras
(
i
).
retAddr
,
spec_ras
(
i
).
ctr
)
when
(
i
.
U
===
spec_sp
){
XSDebug
(
false
,
true
.
B
,
" <----sp"
)}
XSDebug
(
false
,
true
.
B
,
"\n"
)
}
XSDebug
(
"----------------RAS(commit)----------------\n"
)
XSDebug
(
" index addr ctr \n"
)
for
(
i
<-
0
until
RasSize
){
XSDebug
(
" (%d) 0x%x %d"
,
i
.
U
,
commit_ras
(
i
).
retAddr
,
commit_ras
(
i
).
ctr
)
when
(
i
.
U
===
commit_sp
){
XSDebug
(
false
,
true
.
B
,
" <----sp"
)}
XSDebug
(
false
,
true
.
B
,
"\n"
)
}
//no need to pass the ras branchInfo
io
.
branchInfo
.
rasSp
:=
DontCare
io
.
branchInfo
.
rasTopCtr
:=
DontCare
io
.
branchInfo
.
rasToqAddr
:=
DontCare
XSDebug
(
spec_push
,
"(spec_ras)push inAddr: 0x%x inCtr: %d | allocNewEntry:%d | sp:%d \n"
,
spec_ras_write
.
retAddr
,
spec_ras_write
.
ctr
,
sepc_alloc_new
,
spec_sp
.
asUInt
)
XSDebug
(
spec_pop
,
"(spec_ras)pop outValid:%d outAddr: 0x%x \n"
,
io
.
out
.
valid
,
io
.
out
.
bits
.
target
)
XSDebug
(
commit_push
,
"(commit_ras)push inAddr: 0x%x inCtr: %d | allocNewEntry:%d | sp:%d \n"
,
commit_ras_write
.
retAddr
,
commit_ras_write
.
ctr
,
sepc_alloc_new
,
commit_sp
.
asUInt
)
XSDebug
(
commit_pop
,
"(commit_ras)pop outValid:%d outAddr: 0x%x \n"
,
io
.
out
.
valid
,
io
.
out
.
bits
.
target
)
XSDebug
(
"copyValid:%d copyNext:%d \n"
,
copy_valid
,
copy_next
)
if
(
BPUDebug
&&
debug
)
{
// XSDebug("----------------RAS(spec)----------------\n")
// XSDebug(" index addr ctr \n")
// for(i <- 0 until RasSize){
// XSDebug(" (%d) 0x%x %d",i.U,spec_ras(i).retAddr,spec_ras(i).ctr)
// when(i.U === spec_sp){XSDebug(false,true.B," <----sp")}
// XSDebug(false,true.B,"\n")
// }
// XSDebug("----------------RAS(commit)----------------\n")
// XSDebug(" index addr ctr \n")
// for(i <- 0 until RasSize){
// XSDebug(" (%d) 0x%x %d",i.U,commit_ras(i).retAddr,commit_ras(i).ctr)
// when(i.U === commit_sp){XSDebug(false,true.B," <----sp")}
// XSDebug(false,true.B,"\n")
// }
// XSDebug(spec_push, "(spec_ras)push inAddr: 0x%x inCtr: %d | allocNewEntry:%d | sp:%d \n",spec_ras_write.retAddr,spec_ras_write.ctr,sepc_alloc_new,spec_sp.asUInt)
// XSDebug(spec_pop, "(spec_ras)pop outValid:%d outAddr: 0x%x \n",io.out.valid,io.out.bits.target)
// XSDebug(commit_push, "(commit_ras)push inAddr: 0x%x inCtr: %d | allocNewEntry:%d | sp:%d \n",commit_ras_write.retAddr,commit_ras_write.ctr,sepc_alloc_new,commit_sp.asUInt)
// XSDebug(commit_pop, "(commit_ras)pop outValid:%d outAddr: 0x%x \n",io.out.valid,io.out.bits.target)
// XSDebug("copyValid:%d copyNext:%d \n",copy_valid,copy_next)
}
...
...
src/main/scala/xiangshan/frontend/SC.scala
0 → 100644
浏览文件 @
6b0d407e
package
xiangshan.frontend
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
utils._
import
scala.math.min
class
SCReq
extends
TageReq
class
SCResp
(
val
ctrBits
:
Int
=
6
)
extends
TageBundle
{
val
ctr
=
Vec
(
2
,
SInt
(
ctrBits
.
W
))
}
class
SCUpdate
(
val
ctrBits
:
Int
=
6
)
extends
TageBundle
{
val
pc
=
UInt
(
VAddrBits
.
W
)
val
fetchIdx
=
UInt
(
log2Up
(
TageBanks
).
W
)
val
hist
=
UInt
(
HistoryLength
.
W
)
val
mask
=
Vec
(
TageBanks
,
Bool
())
val
oldCtr
=
SInt
(
ctrBits
.
W
)
val
tagePred
=
Bool
()
val
taken
=
Bool
()
}
class
SCTableIO
extends
TageBundle
{
val
req
=
Input
(
Valid
(
new
SCReq
))
val
resp
=
Output
(
Vec
(
TageBanks
,
new
SCResp
))
val
update
=
Input
(
new
SCUpdate
)
}
abstract
class
BaseSCTable
(
val
r
:
Int
=
1024
,
val
cb
:
Int
=
6
,
val
h
:
Int
=
0
)
extends
TageModule
{
val
io
=
IO
(
new
SCTableIO
)
def
getCenteredValue
(
ctr
:
SInt
)
:
SInt
=
(
ctr
<<
1
).
asSInt
+
1.
S
}
class
FakeSCTable
extends
BaseSCTable
{
io
.
resp
:=
0.
U
.
asTypeOf
(
Vec
(
TageBanks
,
new
SCResp
))
}
class
SCTable
(
val
nRows
:
Int
,
val
ctrBits
:
Int
,
val
histLen
:
Int
)
extends
BaseSCTable
(
nRows
,
ctrBits
,
histLen
)
{
val
table
=
List
.
fill
(
TageBanks
)
{
List
.
fill
(
2
)
{
Module
(
new
SRAMTemplate
(
SInt
(
ctrBits
.
W
),
set
=
nRows
,
shouldReset
=
false
,
holdRead
=
true
,
singlePort
=
false
))
}
}
def
compute_folded_hist
(
hist
:
UInt
,
l
:
Int
)
=
{
if
(
histLen
>
0
)
{
val
nChunks
=
(
histLen
+
l
-
1
)
/
l
val
hist_chunks
=
(
0
until
nChunks
)
map
{
i
=>
hist
(
min
((
i
+
1
)*
l
,
histLen
)-
1
,
i
*
l
)
}
hist_chunks
.
reduce
(
_
^
_
)
}
else
0.
U
}
def
getIdx
(
hist
:
UInt
,
pc
:
UInt
)
=
{
(
compute_folded_hist
(
hist
,
log2Ceil
(
nRows
))
^
(
pc
>>
1.
U
))(
log2Ceil
(
nRows
)-
1
,
0
)
}
def
ctrUpdate
(
ctr
:
SInt
,
cond
:
Bool
)
:
SInt
=
signedSatUpdate
(
ctr
,
ctrBits
,
cond
)
val
doing_reset
=
RegInit
(
true
.
B
)
val
reset_idx
=
RegInit
(
0.
U
(
log2Ceil
(
nRows
).
W
))
reset_idx
:=
reset_idx
+
doing_reset
when
(
reset_idx
===
(
nRows
-
1
).
U
)
{
doing_reset
:=
false
.
B
}
val
idx
=
getIdx
(
io
.
req
.
bits
.
hist
,
io
.
req
.
bits
.
pc
)
val
idxLatch
=
RegEnable
(
idx
,
enable
=
io
.
req
.
valid
)
val
table_r
=
WireInit
(
0.
U
.
asTypeOf
(
Vec
(
TageBanks
,
Vec
(
2
,
SInt
(
ctrBits
.
W
)))))
val
baseBank
=
io
.
req
.
bits
.
pc
(
log2Up
(
TageBanks
),
1
)
val
baseBankLatch
=
RegEnable
(
baseBank
,
enable
=
io
.
req
.
valid
)
val
bankIdxInOrder
=
VecInit
((
0
until
TageBanks
).
map
(
b
=>
(
baseBankLatch
+&
b
.
U
)(
log2Up
(
TageBanks
)-
1
,
0
)))
val
realMask
=
circularShiftLeft
(
io
.
req
.
bits
.
mask
,
TageBanks
,
baseBank
)
val
maskLatch
=
RegEnable
(
io
.
req
.
bits
.
mask
,
enable
=
io
.
req
.
valid
)
val
update_idx
=
getIdx
(
io
.
update
.
hist
,
io
.
update
.
pc
-
(
io
.
update
.
fetchIdx
<<
1
))
val
update_wdata
=
ctrUpdate
(
io
.
update
.
oldCtr
,
io
.
update
.
taken
)
for
(
b
<-
0
until
TageBanks
)
{
for
(
i
<-
0
to
1
)
{
table
(
b
)(
i
).
reset
:=
reset
.
asBool
table
(
b
)(
i
).
io
.
r
.
req
.
valid
:=
io
.
req
.
valid
&&
realMask
(
b
)
table
(
b
)(
i
).
io
.
r
.
req
.
bits
.
setIdx
:=
idx
table_r
(
b
)(
i
)
:=
table
(
b
)(
i
).
io
.
r
.
resp
.
data
(
0
)
table
(
b
)(
i
).
io
.
w
.
req
.
valid
:=
(
io
.
update
.
mask
(
b
)
&&
i
.
U
===
io
.
update
.
tagePred
.
asUInt
)
||
doing_reset
table
(
b
)(
i
).
io
.
w
.
req
.
bits
.
setIdx
:=
Mux
(
doing_reset
,
reset_idx
,
update_idx
)
table
(
b
)(
i
).
io
.
w
.
req
.
bits
.
data
:=
Mux
(
doing_reset
,
0.
S
,
update_wdata
)
}
}
(
0
until
TageBanks
).
map
(
b
=>
{
io
.
resp
(
b
).
ctr
:=
table_r
(
bankIdxInOrder
(
b
))
})
if
(
BPUDebug
&&
debug
)
{
val
u
=
io
.
update
val
b
=
PriorityEncoder
(
u
.
mask
)
XSDebug
(
io
.
req
.
valid
,
p
"scTableReq: pc=0x${io.req.bits.pc}%x, idx=${idx}%d, hist=${io.req.bits.hist}%x, baseBank=${baseBank}%d, mask=${io.req.bits.mask}%b, realMask=${realMask}%b\n"
)
for
(
i
<-
0
until
TageBanks
)
{
XSDebug
(
RegNext
(
io
.
req
.
valid
),
p
"scTableResp[${i.U}]: idx=${idxLatch}%d, ctr:${io.resp(i).ctr}\n"
)
}
XSDebug
(
io
.
update
.
mask
.
reduce
(
_
||
_
),
p
"update Table: pc:${u.pc}%x, fetchIdx:${u.fetchIdx}%d, hist:${u.hist}%x, bank:${b}%d, tageTaken:${u.tagePred}%d, taken:${u.taken}%d, oldCtr:${u.oldCtr}%d\n"
)
}
}
class
SCThreshold
(
val
ctrBits
:
Int
=
5
)
extends
TageBundle
{
val
ctr
=
UInt
(
ctrBits
.
W
)
def
satPos
(
ctr
:
UInt
=
this
.
ctr
)
=
ctr
===
((
1.
U
<<
ctrBits
)
-
1.
U
)
def
satNeg
(
ctr
:
UInt
=
this
.
ctr
)
=
ctr
===
0.
U
def
neutralVal
=
(
1.
U
<<
(
ctrBits
-
1
))
val
thres
=
UInt
(
5.
W
)
def
minThres
=
5.
U
def
maxThres
=
31.
U
def
update
(
cause
:
Bool
)
:
SCThreshold
=
{
val
res
=
Wire
(
new
SCThreshold
(
this
.
ctrBits
))
val
newCtr
=
satUpdate
(
this
.
ctr
,
this
.
ctrBits
,
cause
)
val
newThres
=
Mux
(
res
.
satPos
(
newCtr
),
this
.
thres
+
1.
U
,
Mux
(
res
.
satNeg
(
newCtr
),
this
.
thres
-
1.
U
,
this
.
thres
))
res
.
thres
:=
newThres
res
.
ctr
:=
Mux
(
res
.
satPos
(
newCtr
)
||
res
.
satNeg
(
newCtr
),
res
.
neutralVal
,
newCtr
)
// XSDebug(true.B, p"scThres Update: cause${cause} newCtr ${newCtr} newThres ${newThres}\n")
res
}
}
object
SCThreshold
{
def
apply
(
bits
:
Int
)
=
{
val
t
=
Wire
(
new
SCThreshold
(
ctrBits
=
bits
))
t
.
ctr
:=
t
.
neutralVal
t
.
thres
:=
t
.
minThres
t
}
}
\ No newline at end of file
src/main/scala/xiangshan/frontend/Tage.scala
浏览文件 @
6b0d407e
...
...
@@ -24,16 +24,21 @@ trait HasTageParameter extends HasXSParameter with HasBPUParameter{
val
TageNTables
=
TableInfo
.
size
val
UBitPeriod
=
2048
val
TageBanks
=
PredictWidth
// FetchWidth
val
TageCtrBits
=
3
val
SCHistLens
=
0
::
TableInfo
.
map
{
case
(
_
,
h
,
_
)
=>
h
}.
toList
val
SCNTables
=
6
val
SCCtrBits
=
6
val
SCNRows
=
1024
val
SCTableInfo
=
Seq
.
fill
(
SCNTables
)((
SCNRows
,
SCCtrBits
))
zip
SCHistLens
map
{
case
((
n
,
cb
),
h
)
=>
(
n
,
cb
,
h
)}
val
TotalBits
=
TableInfo
.
map
{
case
(
s
,
h
,
t
)
=>
{
s
*
(
1
+
t
+
3
)
*
PredictWidth
s
*
(
1
+
t
+
TageCtrBits
)
*
PredictWidth
}
}.
reduce
(
_
+
_
)
}
abstract
class
TageBundle
extends
XSBundle
with
HasTageParameter
abstract
class
TageModule
extends
XSModule
with
HasTageParameter
{
val
debug
=
false
}
abstract
class
TageBundle
extends
XSBundle
with
HasTageParameter
with
PredictorUtils
abstract
class
TageModule
extends
XSModule
with
HasTageParameter
with
PredictorUtils
{
val
debug
=
false
}
...
...
@@ -45,7 +50,7 @@ class TageReq extends TageBundle {
}
class
TageResp
extends
TageBundle
{
val
ctr
=
UInt
(
3
.
W
)
val
ctr
=
UInt
(
TageCtrBits
.
W
)
val
u
=
UInt
(
2.
W
)
}
...
...
@@ -57,7 +62,7 @@ class TageUpdate extends TageBundle {
val
mask
=
Vec
(
TageBanks
,
Bool
())
val
taken
=
Vec
(
TageBanks
,
Bool
())
val
alloc
=
Vec
(
TageBanks
,
Bool
())
val
oldCtr
=
Vec
(
TageBanks
,
UInt
(
3
.
W
))
val
oldCtr
=
Vec
(
TageBanks
,
UInt
(
TageCtrBits
.
W
))
// update u
val
uMask
=
Vec
(
TageBanks
,
Bool
())
val
u
=
Vec
(
TageBanks
,
UInt
(
2.
W
))
...
...
@@ -100,18 +105,7 @@ class TageTable(val nRows: Int, val histLen: Int, val tagLen: Int, val uBitPerio
(
idx
,
tag
)
}
def
inc_ctr
(
ctr
:
UInt
,
taken
:
Bool
)
:
UInt
=
{
Mux
(!
taken
,
Mux
(
ctr
===
0.
U
,
0.
U
,
ctr
-
1.
U
),
Mux
(
ctr
===
7.
U
,
7.
U
,
ctr
+
1.
U
))
}
// circular shifting
def
circularShiftLeft
(
source
:
UInt
,
len
:
Int
,
shamt
:
UInt
)
:
UInt
=
{
val
res
=
Wire
(
UInt
(
len
.
W
))
val
higher
=
source
<<
shamt
val
lower
=
source
>>
(
len
.
U
-
shamt
)
res
:=
higher
|
lower
res
}
def
inc_ctr
(
ctr
:
UInt
,
taken
:
Bool
)
:
UInt
=
satUpdate
(
ctr
,
TageCtrBits
,
taken
)
val
doing_reset
=
RegInit
(
true
.
B
)
val
reset_idx
=
RegInit
(
0.
U
(
log2Ceil
(
nRows
).
W
))
...
...
@@ -121,10 +115,10 @@ class TageTable(val nRows: Int, val histLen: Int, val tagLen: Int, val uBitPerio
class
TageEntry
()
extends
TageBundle
{
val
valid
=
Bool
()
val
tag
=
UInt
(
tagLen
.
W
)
val
ctr
=
UInt
(
3
.
W
)
val
ctr
=
UInt
(
TageCtrBits
.
W
)
}
val
tageEntrySz
=
1
+
tagLen
+
3
val
tageEntrySz
=
1
+
tagLen
+
TageCtrBits
// use real address to index
// val unhashed_idxes = VecInit((0 until TageBanks).map(b => ((io.req.bits.pc >> 1.U) + b.U) >> log2Up(TageBanks).U))
...
...
@@ -156,15 +150,13 @@ class TageTable(val nRows: Int, val histLen: Int, val tagLen: Int, val uBitPerio
(
0
until
TageBanks
).
map
(
b
=>
{
hi_us
(
b
).
reset
:=
reset
.
asBool
lo_us
(
b
).
reset
:=
reset
.
asBool
table
(
b
).
reset
:=
reset
.
asBool
hi_us
(
b
).
io
.
r
.
req
.
valid
:=
io
.
req
.
valid
&&
realMask
(
b
)
lo_us
(
b
).
io
.
r
.
req
.
valid
:=
io
.
req
.
valid
&&
realMask
(
b
)
table
(
b
).
io
.
r
.
req
.
valid
:=
io
.
req
.
valid
&&
realMask
(
b
)
lo_us
(
b
).
io
.
r
.
req
.
bits
.
setIdx
:=
idx
hi_us
(
b
).
io
.
r
.
req
.
bits
.
setIdx
:=
idx
table
(
b
).
io
.
r
.
req
.
bits
.
setIdx
:=
idx
Seq
(
hi_us
,
lo_us
,
table
).
map
(
t
=>
{
t
(
b
).
reset
:=
reset
.
asBool
t
(
b
).
io
.
r
.
req
.
valid
:=
io
.
req
.
valid
&&
realMask
(
b
)
t
(
b
).
io
.
r
.
req
.
bits
.
setIdx
:=
idx
}
)
hi_us_r
(
b
)
:=
hi_us
(
b
).
io
.
r
.
resp
.
data
(
0
)
lo_us_r
(
b
)
:=
lo_us
(
b
).
io
.
r
.
resp
.
data
(
0
)
...
...
@@ -217,7 +209,7 @@ class TageTable(val nRows: Int, val histLen: Int, val tagLen: Int, val uBitPerio
val
wrbypass_tags
=
Reg
(
Vec
(
wrBypassEntries
,
UInt
(
tagLen
.
W
)))
val
wrbypass_idxs
=
Reg
(
Vec
(
wrBypassEntries
,
UInt
(
log2Ceil
(
nRows
).
W
)))
val
wrbypass_ctrs
=
Reg
(
Vec
(
wrBypassEntries
,
Vec
(
TageBanks
,
UInt
(
3
.
W
))))
val
wrbypass_ctrs
=
Reg
(
Vec
(
wrBypassEntries
,
Vec
(
TageBanks
,
UInt
(
TageCtrBits
.
W
))))
val
wrbypass_ctr_valids
=
Reg
(
Vec
(
wrBypassEntries
,
Vec
(
TageBanks
,
Bool
())))
val
wrbypass_enq_idx
=
RegInit
(
0.
U
(
log2Ceil
(
wrBypassEntries
).
W
))
...
...
@@ -368,10 +360,27 @@ class Tage extends BaseTage {
}
}
val
scTables
=
SCTableInfo
.
map
{
case
(
nRows
,
ctrBits
,
histLen
)
=>
{
val
t
=
if
(
EnableSC
)
Module
(
new
SCTable
(
nRows
/
TageBanks
,
ctrBits
,
histLen
))
else
Module
(
new
FakeSCTable
)
val
req
=
t
.
io
.
req
req
.
valid
:=
io
.
pc
.
valid
&&
!
io
.
flush
req
.
bits
.
pc
:=
io
.
pc
.
bits
req
.
bits
.
hist
:=
io
.
hist
req
.
bits
.
mask
:=
io
.
inMask
t
}
}
val
scThreshold
=
RegInit
(
SCThreshold
(
5
))
val
useThreshold
=
WireInit
(
scThreshold
.
thres
)
val
updateThreshold
=
WireInit
((
useThreshold
<<
3
)
+
21.
U
)
// override val debug = true
// Keep the table responses to process in s3
val
resps
=
VecInit
(
tables
.
map
(
t
=>
RegEnable
(
t
.
io
.
resp
,
enable
=
io
.
s3Fire
)))
val
scResps
=
VecInit
(
scTables
.
map
(
t
=>
RegEnable
(
t
.
io
.
resp
,
enable
=
io
.
s3Fire
)))
// val flushLatch = RegNext(io.flush)
val
s2_bim
=
RegEnable
(
io
.
bim
,
enable
=
io
.
pc
.
valid
)
// actually it is s2Fire
...
...
@@ -387,24 +396,37 @@ class Tage extends BaseTage {
val
updateValid
=
io
.
update
.
valid
val
updateHist
=
io
.
update
.
bits
.
hist
val
updateIsBr
=
u
.
pd
.
isBr
val
updateMeta
=
u
.
brInfo
.
tageMeta
val
updateMisPred
=
u
.
isMisPred
&&
u
.
pd
.
i
sBr
val
updateMisPred
=
u
.
isMisPred
&&
u
pdateI
sBr
val
updateMask
=
WireInit
(
0.
U
.
asTypeOf
(
Vec
(
TageNTables
,
Vec
(
TageBanks
,
Bool
()))))
val
updateUMask
=
WireInit
(
0.
U
.
asTypeOf
(
Vec
(
TageNTables
,
Vec
(
TageBanks
,
Bool
()))))
val
updateTaken
=
Wire
(
Vec
(
TageNTables
,
Vec
(
TageBanks
,
Bool
())))
val
updateAlloc
=
Wire
(
Vec
(
TageNTables
,
Vec
(
TageBanks
,
Bool
())))
val
updateOldCtr
=
Wire
(
Vec
(
TageNTables
,
Vec
(
TageBanks
,
UInt
(
3
.
W
))))
val
updateOldCtr
=
Wire
(
Vec
(
TageNTables
,
Vec
(
TageBanks
,
UInt
(
TageCtrBits
.
W
))))
val
updateU
=
Wire
(
Vec
(
TageNTables
,
Vec
(
TageBanks
,
UInt
(
2.
W
))))
updateTaken
:=
DontCare
updateAlloc
:=
DontCare
updateOldCtr
:=
DontCare
updateU
:=
DontCare
val
scUpdateMask
=
WireInit
(
0.
U
.
asTypeOf
(
Vec
(
SCNTables
,
Vec
(
TageBanks
,
Bool
()))))
val
scUpdateTagePred
=
Wire
(
Bool
())
val
scUpdateTaken
=
Wire
(
Bool
())
val
scUpdateOldCtrs
=
Wire
(
Vec
(
SCNTables
,
SInt
(
SCCtrBits
.
W
)))
scUpdateTagePred
:=
DontCare
scUpdateTaken
:=
DontCare
scUpdateOldCtrs
:=
DontCare
val
updateSCMeta
=
u
.
brInfo
.
tageMeta
.
scMeta
val
updateTageMisPred
=
updateMeta
.
taken
=/=
u
.
taken
&&
updateIsBr
val
updateBank
=
u
.
pc
(
log2Ceil
(
TageBanks
),
1
)
// access tag tables and output meta info
for
(
w
<-
0
until
TageBanks
)
{
val
tageTaken
=
WireInit
(
false
.
B
)
var
altPred
=
s3_bim
.
ctrs
(
w
)(
1
)
val
finalAltPred
=
WireInit
(
s3_bim
.
ctrs
(
w
)(
1
))
var
provided
=
false
.
B
...
...
@@ -416,6 +438,7 @@ class Tage extends BaseTage {
val
ctr
=
resps
(
i
)(
w
).
bits
.
ctr
when
(
hit
)
{
io
.
resp
.
takens
(
w
)
:=
Mux
(
ctr
===
3.
U
||
ctr
===
4.
U
,
altPred
,
ctr
(
2
))
// Use altpred on weak taken
tageTaken
:=
Mux
(
ctr
===
3.
U
||
ctr
===
4.
U
,
altPred
,
ctr
(
2
))
finalAltPred
:=
altPred
}
provided
=
provided
||
hit
// Once hit then provide
...
...
@@ -428,6 +451,7 @@ class Tage extends BaseTage {
io
.
meta
(
w
).
altDiffers
:=
finalAltPred
=/=
io
.
resp
.
takens
(
w
)
io
.
meta
(
w
).
providerU
:=
resps
(
provider
)(
w
).
bits
.
u
io
.
meta
(
w
).
providerCtr
:=
resps
(
provider
)(
w
).
bits
.
ctr
io
.
meta
(
w
).
taken
:=
tageTaken
// Create a mask fo tables which did not hit our query, and also contain useless entries
// and also uses a longer history than the provider
...
...
@@ -441,10 +465,53 @@ class Tage extends BaseTage {
io
.
meta
(
w
).
allocate
.
valid
:=
allocatableSlots
=/=
0.
U
io
.
meta
(
w
).
allocate
.
bits
:=
allocEntry
val
scMeta
=
io
.
meta
(
w
).
scMeta
scMeta
:=
DontCare
val
scTableSums
=
VecInit
(
(
0
to
1
)
map
{
i
=>
{
// val providerCtr = resps(provider)(w).bits.ctr.zext()
// val pvdrCtrCentered = (((providerCtr - 4.S) << 1) + 1.S) << 3
// sum += pvdrCtrCentered
if
(
EnableSC
)
{
(
0
until
SCNTables
)
map
{
j
=>
scTables
(
j
).
getCenteredValue
(
scResps
(
j
)(
w
).
ctr
(
i
))
}
reduce
(
_
+
_
)
// TODO: rewrite with adder tree
}
else
0.
S
}
}
)
if
(
EnableSC
)
{
scMeta
.
tageTaken
:=
tageTaken
scMeta
.
scUsed
:=
provided
scMeta
.
scPred
:=
tageTaken
scMeta
.
sumAbs
:=
0.
U
when
(
provided
)
{
val
providerCtr
=
resps
(
provider
)(
w
).
bits
.
ctr
.
zext
()
val
pvdrCtrCentered
=
((((
providerCtr
-
4.
S
)
<<
1
).
asSInt
+
1.
S
)
<<
3
).
asSInt
val
totalSum
=
scTableSums
(
tageTaken
.
asUInt
)
+
pvdrCtrCentered
val
sumAbs
=
totalSum
.
abs
().
asUInt
val
sumBelowThreshold
=
totalSum
.
abs
.
asUInt
<
useThreshold
val
scPred
=
totalSum
>=
0.
S
scMeta
.
sumAbs
:=
sumAbs
scMeta
.
ctrs
:=
VecInit
(
scResps
.
map
(
r
=>
r
(
w
).
ctr
(
tageTaken
.
asUInt
)))
for
(
i
<-
0
until
SCNTables
)
{
XSDebug
(
RegNext
(
io
.
s3Fire
),
p
"SCTable(${i.U})(${w.U}): ctr:(${scResps(i)(w).ctr(0)},${scResps(i)(w).ctr(1)})\n"
)
}
XSDebug
(
RegNext
(
io
.
s3Fire
),
p
"SC(${w.U}): pvdCtr(${providerCtr}), pvdCentred(${pvdrCtrCentered}), totalSum(${totalSum}), abs(${sumAbs}) useThres(${useThreshold}), scPred(${scPred})\n"
)
// Use prediction from Statistical Corrector
when
(!
sumBelowThreshold
)
{
XSDebug
(
RegNext
(
io
.
s3Fire
),
p
"SC(${w.U}) overriden pred to ${scPred}\n"
)
scMeta
.
scPred
:=
scPred
io
.
resp
.
takens
(
w
)
:=
scPred
}
}
}
val
isUpdateTaken
=
updateValid
&&
updateBank
===
w
.
U
&&
u
.
taken
&&
u
.
pd
.
i
sBr
when
(
u
.
pd
.
i
sBr
&&
updateValid
&&
updateBank
===
w
.
U
)
{
u
.
taken
&&
u
pdateI
sBr
when
(
u
pdateI
sBr
&&
updateValid
&&
updateBank
===
w
.
U
)
{
when
(
updateMeta
.
provider
.
valid
)
{
val
provider
=
updateMeta
.
provider
.
bits
...
...
@@ -462,7 +529,7 @@ class Tage extends BaseTage {
}
}
when
(
updateValid
&&
updateMisPred
)
{
when
(
updateValid
&&
update
Tage
MisPred
)
{
val
idx
=
updateBank
val
allocate
=
updateMeta
.
allocate
when
(
allocate
.
valid
)
{
...
...
@@ -483,6 +550,28 @@ class Tage extends BaseTage {
}
}
if
(
EnableSC
)
{
when
(
updateValid
&&
updateSCMeta
.
scUsed
.
asBool
&&
updateIsBr
)
{
val
scPred
=
updateSCMeta
.
scPred
val
tageTaken
=
updateSCMeta
.
tageTaken
val
sumAbs
=
updateSCMeta
.
sumAbs
.
asUInt
val
scOldCtrs
=
updateSCMeta
.
ctrs
when
(
scPred
=/=
tageTaken
&&
sumAbs
<
useThreshold
-
2.
U
)
{
val
newThres
=
scThreshold
.
update
(
scPred
=/=
u
.
taken
)
scThreshold
:=
newThres
XSDebug
(
p
"scThres update: old d${useThreshold} --> new ${newThres.thres}\n"
)
}
when
(
scPred
=/=
u
.
taken
||
sumAbs
<
updateThreshold
)
{
scUpdateMask
.
foreach
(
t
=>
t
(
updateBank
)
:=
true
.
B
)
scUpdateTagePred
:=
tageTaken
scUpdateTaken
:=
u
.
taken
(
scUpdateOldCtrs
zip
scOldCtrs
).
foreach
{
case
(
t
,
c
)
=>
t
:=
c
}
XSDebug
(
p
"scUpdate: bank(${updateBank}), scPred(${scPred}), tageTaken(${tageTaken}), scSumAbs(${sumAbs}), mispred: sc(${updateMisPred}), tage(${updateTageMisPred})\n"
)
XSDebug
(
p
"update: sc: ${updateSCMeta}\n"
)
}
}
}
for
(
i
<-
0
until
TageNTables
)
{
for
(
w
<-
0
until
TageBanks
)
{
tables
(
i
).
io
.
update
.
mask
(
w
)
:=
updateMask
(
i
)(
w
)
...
...
@@ -499,6 +588,17 @@ class Tage extends BaseTage {
tables
(
i
).
io
.
update
.
fetchIdx
:=
u
.
brInfo
.
fetchIdx
}
for
(
i
<-
0
until
SCNTables
)
{
scTables
(
i
).
io
.
update
.
mask
:=
scUpdateMask
(
i
)
scTables
(
i
).
io
.
update
.
tagePred
:=
scUpdateTagePred
scTables
(
i
).
io
.
update
.
taken
:=
scUpdateTaken
scTables
(
i
).
io
.
update
.
oldCtr
:=
scUpdateOldCtrs
(
i
)
scTables
(
i
).
io
.
update
.
pc
:=
u
.
pc
scTables
(
i
).
io
.
update
.
hist
:=
updateHist
scTables
(
i
).
io
.
update
.
fetchIdx
:=
u
.
brInfo
.
fetchIdx
}
if
(
BPUDebug
&&
debug
)
{
val
m
=
updateMeta
...
...
@@ -508,9 +608,11 @@ class Tage extends BaseTage {
XSDebug
(
RegNext
(
io
.
s3Fire
),
"s3FireOnLastCycle: resp: pc=%x, hist=%x, hits=%b, takens=%b\n"
,
debug_pc_s3
,
debug_hist_s3
,
io
.
resp
.
hits
.
asUInt
,
io
.
resp
.
takens
.
asUInt
)
for
(
i
<-
0
until
TageNTables
)
{
XSDebug
(
RegNext
(
io
.
s3Fire
),
"Table(%d): valids:%b, resp_ctrs:%b, resp_us:%b\n"
,
i
.
U
,
VecInit
(
resps
(
i
).
map
(
_
.
valid
)).
asUInt
,
Cat
(
resps
(
i
).
map
(
_
.
bits
.
ctr
)),
Cat
(
resps
(
i
).
map
(
_
.
bits
.
u
)))
XSDebug
(
RegNext
(
io
.
s3Fire
),
"Ta
geTa
ble(%d): valids:%b, resp_ctrs:%b, resp_us:%b\n"
,
i
.
U
,
VecInit
(
resps
(
i
).
map
(
_
.
valid
)).
asUInt
,
Cat
(
resps
(
i
).
map
(
_
.
bits
.
ctr
)),
Cat
(
resps
(
i
).
map
(
_
.
bits
.
u
)))
}
XSDebug
(
io
.
update
.
valid
,
"update: pc=%x, fetchpc=%x, cycle=%d, hist=%x, taken:%d, misPred:%d, histPtr:%d, bimctr:%d, pvdr(%d):%d, altDiff:%d, pvdrU:%d, pvdrCtr:%d, alloc(%d):%d\n"
,
u
.
pc
,
u
.
pc
-
(
bri
.
fetchIdx
<<
1.
U
),
bri
.
debug_tage_cycle
,
updateHist
,
u
.
taken
,
u
.
isMisPred
,
bri
.
histPtr
,
bri
.
bimCtr
,
m
.
provider
.
valid
,
m
.
provider
.
bits
,
m
.
altDiffers
,
m
.
providerU
,
m
.
providerCtr
,
m
.
allocate
.
valid
,
m
.
allocate
.
bits
)
XSDebug
(
io
.
update
.
valid
&&
updateIsBr
,
p
"update: sc: ${updateSCMeta}\n"
)
XSDebug
(
true
.
B
,
p
"scThres: use(${useThreshold}), update(${updateThreshold})\n"
)
}
}
\ No newline at end of file
src/main/scala/xiangshan/frontend/uBTB.scala
浏览文件 @
6b0d407e
...
...
@@ -46,14 +46,6 @@ class MicroBTB extends BasePredictor
def
getTag
(
pc
:
UInt
)
=
(
pc
>>
(
log2Ceil
(
PredictWidth
)
+
1
)).
asUInt
()
def
getBank
(
pc
:
UInt
)
=
pc
(
log2Ceil
(
PredictWidth
)
,
1
)
def
satUpdate
(
old
:
UInt
,
len
:
Int
,
taken
:
Bool
)
:
UInt
=
{
val
oldSatTaken
=
old
===
((
1
<<
len
)-
1
).
U
val
oldSatNotTaken
=
old
===
0.
U
Mux
(
oldSatTaken
&&
taken
,
((
1
<<
len
)-
1
).
U
,
Mux
(
oldSatNotTaken
&&
!
taken
,
0.
U
,
Mux
(
taken
,
old
+
1.
U
,
old
-
1.
U
)))
}
class
MicroBTBMeta
extends
XSBundle
{
...
...
@@ -69,8 +61,93 @@ class MicroBTB extends BasePredictor
val
offset
=
SInt
(
offsetSize
.
W
)
}
val
uBTBMeta
=
RegInit
((
0.
U
).
asTypeOf
(
Vec
(
nWays
,
Vec
(
PredictWidth
,
new
MicroBTBMeta
))))
val
uBTB
=
Reg
(
Vec
(
nWays
,
Vec
(
PredictWidth
,
new
MicroBTBEntry
)))
// val uBTBMeta = RegInit((0.U).asTypeOf(Vec(nWays, Vec(PredictWidth, new MicroBTBMeta))))
// val uBTB = Reg(Vec(nWays, Vec(PredictWidth, new MicroBTBEntry)))
// class UBTBMem[T <: Data](gen: T, nWays: Int) extends XSModule {
// class UBTBBundleR[T <: Data](private val gen: T, val way: Int) extends Bundle {
// val data = Output(Vec(way, gen))
// }
// class UBTBReadBus[T <: Data](private val gen: T, val way: Int) {
// val resp = Output(new UBTBBundleR(gen, way))
// }
// class UBTBWriteBus[T <: Data](private val gen: T, val set: Int, val way: Int) extends Bundle {
// val req =
// }
// val io = IO(new Bundle {
// val wen = Input(Bool())
// val wWay = Input(UInt(log2Up(nWays).W))
// val wRow = Input(UInt(log2Up(PredictWidth).W))
// val wdata = Input(new T)
// val entries = Output(Vec(nWays, Vec(PredictWidth, gen)))
// })
// val mem = RegInit((0.U).asTypeOf(Vec(nWays, Vec(PredictWidth, new T))))
// io.entries := mem
// when (io.wen) {
// mem(wWay)(wRow) := wdata
// }
// }
class
MetaOutput
extends
XSBundle
{
val
is_Br
=
Bool
()
val
is_RVC
=
Bool
()
val
pred
=
UInt
(
2.
W
)
}
class
UBTBMetaBank
(
nWays
:
Int
)
extends
XSModule
{
val
io
=
IO
(
new
Bundle
{
val
wen
=
Input
(
Bool
())
val
wWay
=
Input
(
UInt
(
log2Up
(
nWays
).
W
))
val
wdata
=
Input
(
new
MicroBTBMeta
)
val
rtag
=
Input
(
UInt
(
tagSize
.
W
))
val
rdata
=
Output
(
new
MetaOutput
)
val
hit_ohs
=
Output
(
Vec
(
nWays
,
Bool
()))
val
allocatable_way
=
Valid
(
UInt
(
log2Up
(
nWays
).
W
))
val
rWay
=
Input
(
UInt
(
log2Up
(
nWays
).
W
))
val
rpred
=
Output
(
UInt
(
2.
W
))
})
val
mem
=
Mem
(
nWays
,
new
MicroBTBMeta
)
val
rentries
=
VecInit
((
0
until
nWays
)
map
(
i
=>
mem
(
i
)))
val
hit_ohs
=
VecInit
(
rentries
map
(
e
=>
e
.
valid
&&
e
.
tag
===
io
.
rtag
))
val
hit_way
=
PriorityEncoder
(
hit_ohs
)
val
hit_entry
=
rentries
(
hit_way
)
io
.
hit_ohs
:=
hit_ohs
io
.
rdata
.
is_Br
:=
hit_entry
.
is_Br
io
.
rdata
.
is_RVC
:=
hit_entry
.
is_RVC
io
.
rdata
.
pred
:=
hit_entry
.
pred
val
entry_emptys
=
VecInit
(
rentries
.
map
(
e
=>
!
e
.
valid
))
val
allocatable
=
ParallelOR
(
entry_emptys
)
io
.
allocatable_way
.
bits
:=
PriorityEncoder
(
entry_emptys
)
io
.
allocatable_way
.
valid
:=
allocatable
io
.
rpred
:=
rentries
(
io
.
rWay
).
pred
when
(
io
.
wen
)
{
mem
.
write
(
io
.
wWay
,
io
.
wdata
)
}
}
class
UBTBDataBank
(
nWays
:
Int
)
extends
XSModule
{
val
io
=
IO
(
new
Bundle
{
val
wen
=
Input
(
Bool
())
val
wWay
=
Input
(
UInt
(
log2Up
(
nWays
).
W
))
val
wdata
=
Input
(
new
MicroBTBEntry
)
val
rWay
=
Input
(
UInt
(
log2Up
(
nWays
).
W
))
val
rdata
=
Output
(
new
MicroBTBEntry
)
})
val
mem
=
Mem
(
nWays
,
new
MicroBTBEntry
)
val
rentries
=
VecInit
((
0
until
nWays
)
map
(
i
=>
mem
(
i
)))
io
.
rdata
:=
rentries
(
io
.
rWay
)
when
(
io
.
wen
)
{
mem
.
write
(
io
.
wWay
,
io
.
wdata
)
}
}
val
metaBanks
=
Seq
.
fill
(
PredictWidth
)(
Module
(
new
UBTBMetaBank
(
nWays
)))
val
dataBanks
=
Seq
.
fill
(
PredictWidth
)(
Module
(
new
UBTBDataBank
(
nWays
)))
val
metas
=
VecInit
(
metaBanks
.
map
(
_
.
io
))
val
datas
=
VecInit
(
dataBanks
.
map
(
_
.
io
))
val
uBTBMeta
=
VecInit
(
metas
.
map
(
m
=>
m
.
rdata
))
val
uBTB
=
VecInit
(
datas
.
map
(
d
=>
d
.
rdata
))
//uBTB read
//tag is bank align
...
...
@@ -92,23 +169,23 @@ class MicroBTB extends BasePredictor
val
read_bank_inOrder
=
VecInit
((
0
until
PredictWidth
).
map
(
b
=>
(
read_req_basebank
+
b
.
U
)(
log2Up
(
PredictWidth
)-
1
,
0
)
))
val
isInNextRow
=
VecInit
((
0
until
PredictWidth
).
map
(
_
.
U
<
read_req_basebank
))
val
read_hit_ohs
=
read_bank_inOrder
.
map
{
b
=>
VecInit
((
0
until
nWays
)
map
{
w
=>
Mux
(
isInNextRow
(
b
),
read_req_tag
+
1.
U
,
read_req_tag
)
===
uBTBMeta
(
w
)(
b
).
tag
})
}
(
0
until
PredictWidth
).
map
{
b
=>
metas
(
b
).
rtag
:=
Mux
(
isInNextRow
(
b
),
read_req_tag
+
1.
U
,
read_req_tag
)
}
val
read_hit_ohs
=
read_bank_inOrder
.
map
{
b
=>
metas
(
b
).
hit_ohs
}
val
read_hit_vec
=
VecInit
(
read_hit_ohs
.
map
{
oh
=>
ParallelOR
(
oh
).
asBool
})
val
read_hit_ways
=
VecInit
(
read_hit_ohs
.
map
{
oh
=>
PriorityEncoder
(
oh
)})
val
read_hit
=
ParallelOR
(
read_hit_vec
).
asBool
val
read_hit_way
=
PriorityEncoder
(
ParallelOR
(
read_hit_ohs
.
map
(
_
.
asUInt
)))
//
val read_hit = ParallelOR(read_hit_vec).asBool
//
val read_hit_way = PriorityEncoder(ParallelOR(read_hit_ohs.map(_.asUInt)))
val
uBTBMeta_resp
=
VecInit
((
0
until
PredictWidth
).
map
(
b
=>
uBTBMeta
(
read_hit_ways
(
b
))(
read_bank_inOrder
(
b
))))
val
btb_resp
=
VecInit
((
0
until
PredictWidth
).
map
(
b
=>
uBTB
(
read_hit_ways
(
b
))(
read_bank_inOrder
(
b
))))
(
0
until
PredictWidth
).
map
(
b
=>
datas
(
b
).
rWay
:=
read_hit_ways
(
PredictWidth
.
U
-
read_bank_inOrder
(
b
)))
val
uBTBMeta_resp
=
VecInit
((
0
until
PredictWidth
).
map
(
b
=>
metas
(
read_bank_inOrder
(
b
)).
rdata
))
val
btb_resp
=
VecInit
((
0
until
PredictWidth
).
map
(
b
=>
datas
(
read_bank_inOrder
(
b
)).
rdata
))
for
(
i
<-
0
until
PredictWidth
){
// do not need to decide whether to produce results\
read_resp
(
i
).
valid
:=
uBTBMeta_resp
(
i
).
valid
&&
read_hit_vec
(
i
)
&&
io
.
inMask
(
i
)
read_resp
(
i
).
valid
:=
read_hit_vec
(
i
)
&&
io
.
inMask
(
i
)
read_resp
(
i
).
taken
:=
read_resp
(
i
).
valid
&&
uBTBMeta_resp
(
i
).
pred
(
1
)
read_resp
(
i
).
is_Br
:=
read_resp
(
i
).
valid
&&
uBTBMeta_resp
(
i
).
is_Br
read_resp
(
i
).
target
:=
((
io
.
pc
.
bits
).
asSInt
+
(
i
<<
1
).
S
+
btb_resp
(
i
).
offset
).
asUInt
...
...
@@ -130,12 +207,16 @@ class MicroBTB extends BasePredictor
way
:=
Mux
(
all_valid
,
chunks
.
reduce
(
_
^
_
),
PriorityEncoder
(~
valids
))
way
}
val
alloc_ways
=
read_bank_inOrder
.
map
{
b
=>
alloc_way
(
VecInit
(
uBTBMeta
.
map
(
w
=>
w
(
b
).
valid
)).
asUInt
,
VecInit
(
uBTBMeta
.
map
(
w
=>
w
(
b
).
tag
)).
asUInt
,
Mux
(
isInNextRow
(
b
).
asBool
,
read_req_tag
+
1.
U
,
read_req_tag
))
// val alloc_ways = read_bank_inOrder.map{ b =>
// alloc_way(VecInit(uBTBMeta.map(w => w(b).valid)).asUInt,
// VecInit(uBTBMeta.map(w => w(b).tag)).asUInt,
// Mux(isInNextRow(b).asBool,read_req_tag + 1.U,read_req_tag))
}
// }
val
alloc_ways
=
read_bank_inOrder
.
map
{
b
=>
Mux
(
metas
(
b
).
allocatable_way
.
valid
,
metas
(
b
).
allocatable_way
.
bits
,
LFSR64
()(
log2Ceil
(
nWays
)-
1
,
0
))}
(
0
until
PredictWidth
).
map
(
i
=>
out_ubtb_br_info
.
writeWay
(
i
)
:=
Mux
(
read_hit_vec
(
i
).
asBool
,
read_hit_ways
(
i
),
alloc_ways
(
i
)))
//response
...
...
@@ -172,41 +253,65 @@ class MicroBTB extends BasePredictor
val
entry_write_valid
=
io
.
update
.
valid
&&
(
u
.
isMisPred
||
!
u
.
isMisPred
&&
u
.
pd
.
isBr
||
jalFirstEncountered
)
//io.update.valid //&& update_is_BR_or_JAL
val
meta_write_valid
=
io
.
update
.
valid
&&
(
u
.
isMisPred
||
!
u
.
isMisPred
&&
u
.
pd
.
isBr
||
jalFirstEncountered
)
//io.update.valid //&& update_is_BR_or_JAL
//write btb target when miss prediction
when
(
entry_write_valid
)
{
uBTB
(
update_write_way
)(
update_bank
).
offset
:=
update_taget_offset
// when(entry_write_valid)
// {
// uBTB(update_write_way)(update_bank).offset := update_taget_offset
// }
for
(
b
<-
0
until
PredictWidth
)
{
datas
(
b
).
wen
:=
entry_write_valid
&&
b
.
U
===
update_bank
datas
(
b
).
wWay
:=
update_write_way
datas
(
b
).
wdata
:=
update_taget_offset
.
asTypeOf
(
new
MicroBTBEntry
)
}
//write the uBTBMeta
when
(
meta_write_valid
)
{
//commit update
uBTBMeta
(
update_write_way
)(
update_bank
).
is_Br
:=
u
.
pd
.
brType
===
BrType
.
branch
uBTBMeta
(
update_write_way
)(
update_bank
).
is_RVC
:=
u
.
pd
.
isRVC
//(0 until PredictWidth).foreach{b => uBTBMeta(update_write_way)(b).valid := false.B}
uBTBMeta
(
update_write_way
)(
update_bank
).
valid
:=
true
.
B
uBTBMeta
(
update_write_way
)(
update_bank
).
tag
:=
update_tag
uBTBMeta
(
update_write_way
)(
update_bank
).
pred
:=
Mux
(!
update_hits
,
Mux
(
update_taken
,
3.
U
,
0.
U
),
satUpdate
(
uBTBMeta
(
update_write_way
)(
update_bank
).
pred
,
2
,
update_taken
)
)
(
0
until
PredictWidth
).
map
(
i
=>
metas
(
i
).
rWay
:=
update_write_way
)
val
update_write_meta
=
Wire
(
new
MicroBTBMeta
)
update_write_meta
.
is_Br
:=
u
.
pd
.
brType
===
BrType
.
branch
update_write_meta
.
is_RVC
:=
u
.
pd
.
isRVC
update_write_meta
.
valid
:=
true
.
B
update_write_meta
.
tag
:=
update_tag
update_write_meta
.
pred
:=
Mux
(!
update_hits
,
Mux
(
update_taken
,
3.
U
,
0.
U
),
satUpdate
(
metas
(
update_bank
).
rpred
,
2
,
update_taken
)
)
for
(
b
<-
0
until
PredictWidth
)
{
metas
(
b
).
wen
:=
meta_write_valid
&&
b
.
U
===
update_bank
metas
(
b
).
wWay
:=
update_write_way
metas
(
b
).
wdata
:=
update_write_meta
}
// when(meta_write_valid)
// {
// //commit update
// uBTBMeta(update_write_way)(update_bank).is_Br := u.pd.brType === BrType.branch
// uBTBMeta(update_write_way)(update_bank).is_RVC := u.pd.isRVC
// //(0 until PredictWidth).foreach{b => uBTBMeta(update_write_way)(b).valid := false.B}
// uBTBMeta(update_write_way)(update_bank).valid := true.B
// uBTBMeta(update_write_way)(update_bank).tag := update_tag
// uBTBMeta(update_write_way)(update_bank).pred :=
// Mux(!update_hits,
// Mux(update_taken,3.U,0.U),
// satUpdate( uBTBMeta(update_write_way)(update_bank).pred,2,update_taken)
// )
// }
if
(
BPUDebug
&&
debug
)
{
XSDebug
(
read_valid
,
"uBTB read req: pc:0x%x, tag:%x basebank:%d\n"
,
io
.
pc
.
bits
,
read_req_tag
,
read_req_basebank
)
XSDebug
(
read_valid
,
"uBTB read resp: read_hit_vec:%b, \n"
,
read_hit_vec
.
asUInt
)
for
(
i
<-
0
until
PredictWidth
)
{
XSDebug
(
read_valid
,
"bank(%d) hit:%d way:%d valid:%d is_RVC:%d taken:%d isBr:%d target:0x%x alloc_way:%d\n"
,
i
.
U
,
read_hit_vec
(
i
),
read_hit_ways
(
i
),
read_resp
(
i
).
valid
,
read_resp
(
i
).
is_RVC
,
read_resp
(
i
).
taken
,
read_resp
(
i
).
is_Br
,
read_resp
(
i
).
target
,
out_ubtb_br_info
.
writeWay
(
i
))
}
//
XSDebug(read_valid,"uBTB read req: pc:0x%x, tag:%x basebank:%d\n",io.pc.bits,read_req_tag,read_req_basebank)
//
XSDebug(read_valid,"uBTB read resp: read_hit_vec:%b, \n",read_hit_vec.asUInt)
//
for(i <- 0 until PredictWidth) {
//
XSDebug(read_valid,"bank(%d) hit:%d way:%d valid:%d is_RVC:%d taken:%d isBr:%d target:0x%x alloc_way:%d\n",
//
i.U,read_hit_vec(i),read_hit_ways(i),read_resp(i).valid,read_resp(i).is_RVC,read_resp(i).taken,read_resp(i).is_Br,read_resp(i).target,out_ubtb_br_info.writeWay(i))
//
}
XSDebug
(
meta_write_valid
,
"uBTB update: update | pc:0x%x | update hits:%b | | update_write_way:%d | update_bank: %d| update_br_index:%d | update_tag:%x | upadate_offset 0x%x\n "
,
update_br_pc
,
update_hits
,
update_write_way
,
update_bank
,
update_br_idx
,
update_tag
,
update_taget_offset
(
offsetSize
-
1
,
0
))
XSDebug
(
meta_write_valid
,
"uBTB update: update_taken:%d | old_pred:%b | new_pred:%b\n"
,
update_taken
,
uBTBMeta
(
update_write_way
)(
update_bank
).
pred
,
Mux
(!
update_hits
,
Mux
(
update_taken
,
3.
U
,
0.
U
),
satUpdate
(
uBTBMeta
(
update_write_way
)(
update_bank
).
pred
,
2
,
update_taken
)))
//
XSDebug(meta_write_valid,"uBTB update: update | pc:0x%x | update hits:%b | | update_write_way:%d | update_bank: %d| update_br_index:%d | update_tag:%x | upadate_offset 0x%x\n "
//
,update_br_pc,update_hits,update_write_way,update_bank,update_br_idx,update_tag,update_taget_offset(offsetSize-1,0))
//
XSDebug(meta_write_valid, "uBTB update: update_taken:%d | old_pred:%b | new_pred:%b\n",
//
update_taken, uBTBMeta(update_write_way)(update_bank).pred,
//
Mux(!update_hits,
//
Mux(update_taken,3.U,0.U),
//
satUpdate( uBTBMeta(update_write_way)(update_bank).pred,2,update_taken)))
}
...
...
src/test/csrc/emu.cpp
浏览文件 @
6b0d407e
...
...
@@ -107,7 +107,7 @@ Emulator::Emulator(int argc, const char *argv[]):
enable_waveform
=
false
;
#endif
#ifdef
__ENABLESNAPSHOT__
#ifdef
VM_SAVABLE
if
(
args
.
snapshot_path
!=
NULL
)
{
printf
(
"loading from snapshot `%s`...
\n
"
,
args
.
snapshot_path
);
snapshot_load
(
args
.
snapshot_path
);
...
...
@@ -122,7 +122,7 @@ Emulator::Emulator(int argc, const char *argv[]):
}
Emulator
::~
Emulator
()
{
#ifdef
__ENABLESNAPSHOT__
#ifdef
VM_SAVABLE
snapshot_slot
[
0
].
save
();
snapshot_slot
[
1
].
save
();
printf
(
"Please remove unused snapshots manually
\n
"
);
...
...
@@ -281,7 +281,7 @@ uint64_t Emulator::execute(uint64_t n) {
poll_event
();
lasttime_poll
=
t
;
}
#ifdef
__ENABLESNAPSHOT__
#ifdef
VM_SAVABLE
static
int
snapshot_count
=
0
;
if
(
trapCode
!=
STATE_GOODTRAP
&&
t
-
lasttime_snapshot
>
1000
*
SNAPSHOT_INTERVAL
)
{
// save snapshot every 10s
...
...
@@ -314,7 +314,7 @@ inline char* Emulator::timestamp_filename(time_t t, char *buf) {
return
buf
+
len
;
}
#ifdef
__ENABLESNAPSHOT__
#ifdef
VM_SAVABLE
inline
char
*
Emulator
::
snapshot_filename
(
time_t
t
)
{
static
char
buf
[
1024
];
char
*
p
=
timestamp_filename
(
t
,
buf
);
...
...
@@ -355,7 +355,7 @@ void Emulator::display_trapinfo() {
instrCnt
,
cycleCnt
,
ipc
);
}
#ifdef
__ENABLESNAPSHOT__
#ifdef
VM_SAVABLE
void
Emulator
::
snapshot_save
(
const
char
*
filename
)
{
static
int
last_slot
=
0
;
VerilatedSaveMem
&
stream
=
snapshot_slot
[
last_slot
];
...
...
@@ -435,4 +435,4 @@ void Emulator::snapshot_load(const char *filename) {
if
(
fp
)
fseek
(
fp
,
sdcard_offset
,
SEEK_SET
);
}
#endif
\ No newline at end of file
#endif
src/test/csrc/emu.h
浏览文件 @
6b0d407e
...
...
@@ -29,7 +29,9 @@ class Emulator {
VXSSimTop
*
dut_ptr
;
VerilatedVcdC
*
tfp
;
bool
enable_waveform
;
#ifdef VM_SAVABLE
VerilatedSaveMem
snapshot_slot
[
2
];
#endif
EmuArgs
args
;
enum
{
...
...
src/test/csrc/snapshot.cpp
浏览文件 @
6b0d407e
#include "snapshot.h"
#ifdef VM_SAVABLE
void
VerilatedSaveMem
::
flush
()
{
long
flush_size
=
m_cp
-
m_bufp
;
assert
(
buf_size
-
size
>
flush_size
);
...
...
@@ -19,3 +20,4 @@ void VerilatedSaveMem::save() {
size
=
0
;
printf
(
"save snapshot to %s...
\n
"
,
m_filename
.
c_str
());
}
#endif
src/test/csrc/snapshot.h
浏览文件 @
6b0d407e
#ifndef SNAPSHOT_H
#define SNAPSHOT_H
#ifdef VM_SAVABLE
#include "VXSSimTop.h"
#include <verilated_save.h>
...
...
@@ -28,3 +32,6 @@ public:
void
flush
();
void
save
();
};
#endif
#endif
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录