Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenXiangShan
XiangShan
提交
570ceca1
X
XiangShan
项目概览
OpenXiangShan
/
XiangShan
12 个月 前同步成功
通知
1183
Star
3914
Fork
526
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
X
XiangShan
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
570ceca1
编写于
12月 22, 2020
作者:
Y
Yinan Xu
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'origin/master' into opt-redirect
上级
782517ae
65c997d6
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
168 addition
and
121 deletion
+168
-121
src/main/scala/xiangshan/Bundle.scala
src/main/scala/xiangshan/Bundle.scala
+8
-9
src/main/scala/xiangshan/frontend/BPU.scala
src/main/scala/xiangshan/frontend/BPU.scala
+4
-4
src/main/scala/xiangshan/frontend/IFU.scala
src/main/scala/xiangshan/frontend/IFU.scala
+79
-61
src/main/scala/xiangshan/frontend/Ibuffer.scala
src/main/scala/xiangshan/frontend/Ibuffer.scala
+74
-44
src/main/scala/xiangshan/frontend/Tage.scala
src/main/scala/xiangshan/frontend/Tage.scala
+2
-2
src/main/scala/xiangshan/frontend/uBTB.scala
src/main/scala/xiangshan/frontend/uBTB.scala
+1
-1
未找到文件。
src/main/scala/xiangshan/Bundle.scala
浏览文件 @
570ceca1
...
...
@@ -21,6 +21,7 @@ import scala.math.max
class
FetchPacket
extends
XSBundle
{
val
instrs
=
Vec
(
PredictWidth
,
UInt
(
32.
W
))
val
mask
=
UInt
(
PredictWidth
.
W
)
val
pdmask
=
UInt
(
PredictWidth
.
W
)
// val pc = UInt(VAddrBits.W)
val
pc
=
Vec
(
PredictWidth
,
UInt
(
VAddrBits
.
W
))
val
pnpc
=
Vec
(
PredictWidth
,
UInt
(
VAddrBits
.
W
))
...
...
@@ -82,15 +83,12 @@ class BranchPrediction extends XSBundle with HasIFUConst {
val
firstBankHasHalfRVI
=
Bool
()
val
lastBankHasHalfRVI
=
Bool
()
def
lastHalfRVIMask
=
Mux
(
firstBankHasHalfRVI
,
UIntToOH
((
bankWidth
-
1
).
U
),
Mux
(
lastBankHasHalfRVI
,
UIntToOH
((
PredictWidth
-
1
).
U
),
0.
U
(
PredictWidth
.
W
)
)
)
// assumes that only one of the two conditions could be true
def
lastHalfRVIMask
=
Cat
(
lastBankHasHalfRVI
.
asUInt
,
0.
U
(
7.
W
),
firstBankHasHalfRVI
.
asUInt
,
0.
U
(
7.
W
))
def
lastHalfRVIClearMask
=
~
lastHalfRVIMask
// is taken from half RVI
def
lastHalfRVITaken
=
ParallelORR
(
takens
&
lastHalfRVIMask
)
def
lastHalfRVITaken
=
(
takens
(
bankWidth
-
1
)
&&
firstBankHasHalfRVI
)
||
(
takens
(
PredictWidth
-
1
)
&&
lastBankHasHalfRVI
)
def
lastHalfRVIIdx
=
Mux
(
firstBankHasHalfRVI
,
(
bankWidth
-
1
).
U
,
(
PredictWidth
-
1
).
U
)
// should not be used if not lastHalfRVITaken
...
...
@@ -100,13 +98,14 @@ class BranchPrediction extends XSBundle with HasIFUConst {
def
realBrMask
=
brMask
&
lastHalfRVIClearMask
def
realJalMask
=
jalMask
&
lastHalfRVIClearMask
def
brNotTakens
=
~
realT
akens
&
realBrMask
def
brNotTakens
=
~
t
akens
&
realBrMask
def
sawNotTakenBr
=
VecInit
((
0
until
PredictWidth
).
map
(
i
=>
(
if
(
i
==
0
)
false
.
B
else
ParallelORR
(
brNotTakens
(
i
-
1
,
0
)))))
// def hasNotTakenBrs = (brNotTakens & LowerMaskFromLowest(realTakens)).orR
def
unmaskedJmpIdx
=
ParallelPriorityEncoder
(
takens
)
def
saveHalfRVI
=
(
firstBankHasHalfRVI
&&
(
unmaskedJmpIdx
===
(
bankWidth
-
1
).
U
||
!(
ParallelORR
(
takens
))))
||
(
lastBankHasHalfRVI
&&
unmaskedJmpIdx
===
(
PredictWidth
-
1
).
U
)
// if not taken before the half RVI inst
def
saveHalfRVI
=
(
firstBankHasHalfRVI
&&
!(
ParallelORR
(
takens
(
bankWidth
-
2
,
0
))))
||
(
lastBankHasHalfRVI
&&
!(
ParallelORR
(
takens
(
PredictWidth
-
2
,
0
))))
// could get PredictWidth-1 when only the first bank is valid
def
jmpIdx
=
ParallelPriorityEncoder
(
realTakens
)
// only used when taken
...
...
src/main/scala/xiangshan/frontend/BPU.scala
浏览文件 @
570ceca1
...
...
@@ -250,7 +250,7 @@ class BPUStage3 extends BPUStage {
val
predecode
=
Input
(
new
Predecode
)
val
realMask
=
Input
(
UInt
(
PredictWidth
.
W
))
val
prevHalf
=
Input
(
new
PrevHalfInstr
)
val
prevHalf
=
Flipped
(
ValidIO
(
new
PrevHalfInstr
)
)
val
recover
=
Flipped
(
ValidIO
(
new
CfiUpdateInfo
))
}
val
s3IO
=
IO
(
new
S3IO
)
...
...
@@ -283,7 +283,7 @@ class BPUStage3 extends BPUStage {
val
brPred
=
(
if
(
EnableBPD
)
tageTakens
else
bimTakens
).
asUInt
val
loopRes
=
(
if
(
EnableLoop
)
loopResp
else
VecInit
(
Fill
(
PredictWidth
,
0.
U
(
1.
W
)))).
asUInt
val
prevHalfTaken
=
s3IO
.
prevHalf
.
valid
&&
s3IO
.
prevHalf
.
taken
val
prevHalfTaken
=
s3IO
.
prevHalf
.
valid
&&
s3IO
.
prevHalf
.
bits
.
taken
val
prevHalfTakenMask
=
prevHalfTaken
.
asUInt
val
brTakens
=
((
brs
&
brPred
|
prevHalfTakenMask
)
&
~
loopRes
)
// VecInit((0 until PredictWidth).map(i => brs(i) && (brPred(i) || (if (i == 0) prevHalfTaken else false.B)) && !loopRes(i)))
...
...
@@ -349,7 +349,7 @@ class BPUStage3 extends BPUStage {
// targets would be lost as well, since it is from btb
// unless it is a ret, which target is from ras
when
(
prevHalfTaken
&&
!
rets
(
0
))
{
targets
(
0
)
:=
s3IO
.
prevHalf
.
target
targets
(
0
)
:=
s3IO
.
prevHalf
.
bits
.
target
}
// Wrap tage resp and tage meta in
...
...
@@ -430,7 +430,7 @@ abstract class BaseBPU extends XSModule with BranchPredictorComponents with HasB
// from if4
val
predecode
=
Input
(
new
Predecode
)
val
realMask
=
Input
(
UInt
(
PredictWidth
.
W
))
val
prevHalf
=
Input
(
new
PrevHalfInstr
)
val
prevHalf
=
Flipped
(
ValidIO
(
new
PrevHalfInstr
)
)
// to if4, some bpu info used for updating
val
bpuMeta
=
Output
(
Vec
(
PredictWidth
,
new
BpuMeta
))
})
...
...
src/main/scala/xiangshan/frontend/IFU.scala
浏览文件 @
570ceca1
...
...
@@ -79,12 +79,12 @@ class IFUIO extends XSBundle
}
class
PrevHalfInstr
extends
XSBundle
{
val
valid
=
Bool
()
val
taken
=
Bool
()
val
ghInfo
=
new
GlobalHistory
()
val
fetchpc
=
UInt
(
VAddrBits
.
W
)
// only for debug
val
idx
=
UInt
(
VAddrBits
.
W
)
// only for debug
val
pc
=
UInt
(
VAddrBits
.
W
)
val
npc
=
UInt
(
VAddrBits
.
W
)
val
target
=
UInt
(
VAddrBits
.
W
)
val
instr
=
UInt
(
16.
W
)
val
ipf
=
Bool
()
...
...
@@ -117,7 +117,8 @@ class IFU extends XSModule with HasIFUConst
val
if1_valid
=
!
reset
.
asBool
&&
GTimer
()
>
500.
U
val
if1_npc
=
WireInit
(
0.
U
(
VAddrBits
.
W
))
val
if2_ready
=
WireInit
(
false
.
B
)
val
if1_fire
=
if1_valid
&&
(
if2_ready
||
if1_flush
)
&&
(
inLoop
||
io
.
icacheReq
.
ready
)
val
if2_allReady
=
WireInit
(
if2_ready
&&
(
inLoop
||
io
.
icacheReq
.
ready
))
val
if1_fire
=
if1_valid
&&
(
if2_allReady
||
if1_flush
)
// val if2_newPtr, if3_newPtr, if4_newPtr = Wire(UInt(log2Up(ExtHistoryLength).W))
...
...
@@ -131,12 +132,12 @@ class IFU extends XSModule with HasIFUConst
//********************** IF2 ****************************//
val
if2_valid
=
RegInit
(
init
=
false
.
B
)
val
if3_ready
=
WireInit
(
false
.
B
)
val
if2_fire
=
if2_valid
&&
if3_ready
&&
!
if2_flush
val
if2_fire
=
if2_valid
&&
if3_ready
val
if2_pc
=
RegEnable
(
next
=
if1_npc
,
init
=
resetVector
.
U
,
enable
=
if1_fire
)
val
if2_snpc
=
snpc
(
if2_pc
,
inLoop
)
val
if2_predHist
=
RegEnable
(
if1_gh
.
predHist
,
enable
=
if1_fire
)
if2_ready
:=
if
2_fire
||
!
if2_valid
||
if2_flush
when
(
if1_fire
)
{
if2_valid
:=
if1_valid
}
if2_ready
:=
if
3_ready
||
!
if2_valid
when
(
if1_fire
)
{
if2_valid
:=
true
.
B
}
.
elsewhen
(
if2_flush
)
{
if2_valid
:=
false
.
B
}
.
elsewhen
(
if2_fire
)
{
if2_valid
:=
false
.
B
}
...
...
@@ -147,31 +148,37 @@ class IFU extends XSModule with HasIFUConst
// if taken, bp_redirect should be true
// when taken on half RVI, we suppress this redirect signal
if2_redirect
:=
if2_
fire
&&
if2_bp
.
taken
if2_redirect
:=
if2_
valid
&&
if2_bp
.
taken
npcGen
.
register
(
if2_redirect
,
if2_bp
.
target
)
if2_predicted_gh
:=
if2_gh
.
update
(
if2_bp
.
hasNotTakenBrs
,
if2_bp
.
takenOnBr
)
//********************** IF3 ****************************//
// if3 should wait for instructions resp to arrive
val
if3_valid
=
RegInit
(
init
=
false
.
B
)
val
if4_ready
=
WireInit
(
false
.
B
)
val
if3_fire
=
if3_valid
&&
if4_ready
&&
(
inLoop
||
io
.
icacheResp
.
valid
)
&&
!
if3_flush
val
if3_allValid
=
if3_valid
&&
(
inLoop
||
io
.
icacheResp
.
valid
)
val
if3_fire
=
if3_allValid
&&
if4_ready
val
if3_pc
=
RegEnable
(
if2_pc
,
if2_fire
)
val
if3_predHist
=
RegEnable
(
if2_predHist
,
enable
=
if2_fire
)
if3_ready
:=
if3_fire
||
!
if3_valid
||
if3_flush
when
(
if3_flush
)
{
if3_valid
:=
false
.
B
}
.
elsewhen
(
if2_fire
)
{
if3_valid
:=
true
.
B
}
.
elsewhen
(
if3_fire
)
{
if3_valid
:=
false
.
B
}
if3_ready
:=
if4_ready
&&
(
inLoop
||
io
.
icacheResp
.
valid
)
||
!
if3_valid
when
(
if3_flush
)
{
if3_valid
:=
false
.
B
}.
elsewhen
(
if2_fire
&&
!
if2_flush
)
{
if3_valid
:=
true
.
B
}.
elsewhen
(
if3_fire
)
{
if3_valid
:=
false
.
B
}
val
if3_bp
=
bpu
.
io
.
out
(
1
)
if3_predicted_gh
:=
if3_gh
.
update
(
if3_bp
.
hasNotTakenBrs
,
if3_bp
.
takenOnBr
)
val
prevHalfInstrReq
=
Wire
(
new
PrevHalfInstr
)
val
prevHalfInstrReq
=
Wire
Init
(
0.
U
.
asTypeOf
(
ValidUndirectioned
(
new
PrevHalfInstr
))
)
// only valid when if4_fire
val
hasPrevHalfInstrReq
=
prevHalfInstrReq
.
valid
val
if3_prevHalfInstr
=
RegInit
(
0.
U
.
asTypeOf
(
new
PrevHalfInstr
))
val
if3_prevHalfInstr
=
RegInit
(
0.
U
.
asTypeOf
(
ValidUndirectioned
(
new
PrevHalfInstr
)
))
// 32-bit instr crosses 2 pages, and the higher 16-bit triggers page fault
val
crossPageIPF
=
WireInit
(
false
.
B
)
...
...
@@ -179,28 +186,30 @@ class IFU extends XSModule with HasIFUConst
val
if3_pendingPrevHalfInstr
=
if3_prevHalfInstr
.
valid
// the previous half of RVI instruction waits until it meets its last half
val
if3_prevHalfInstrMet
=
if3_pendingPrevHalfInstr
&&
(
if3_prevHalfInstr
.
pc
+
2.
U
)
===
if3_pc
&&
if3_valid
&&
(
inLoop
||
io
.
icacheResp
.
valid
)
val
if3_prevHalfInstrMet
=
if3_pendingPrevHalfInstr
&&
if3_prevHalfInstr
.
bits
.
npc
===
if3_pc
&&
if3_valid
// set to invalid once consumed or redirect from backend
val
if3_prevHalfConsumed
=
if3_prevHalfInstrMet
&&
if3_fire
val
if3_prevHalfFlush
=
if4_flush
when
(
hasPrevHalfInstrReq
)
{
if3_prevHalfInstr
:=
prevHalfInstrReq
when
(
hasPrevHalfInstrReq
&&
!
if3_prevHalfFlush
)
{
if3_prevHalfInstr
.
valid
:=
true
.
B
}.
elsewhen
(
if3_prevHalfConsumed
||
if3_prevHalfFlush
)
{
if3_prevHalfInstr
.
valid
:=
false
.
B
}
when
(
hasPrevHalfInstrReq
)
{
if3_prevHalfInstr
.
bits
:=
prevHalfInstrReq
.
bits
}
// when bp signal a redirect, we distinguish between taken and not taken
// if taken and saveHalfRVI is true, we do not redirect to the target
def
if3_nextValidPCNotEquals
(
pc
:
UInt
)
=
!
if2_valid
||
if2_valid
&&
if2_pc
=/=
pc
val
if3_prevHalfMetRedirect
=
if3_pendingPrevHalfInstr
&&
if3_prevHalfInstrMet
&&
if3_prevHalfInstr
.
taken
&&
if3_nextValidPCNotEquals
(
if3_prevHalfInstr
.
target
)
val
if3_prevHalfNotMetRedirect
=
if3_pendingPrevHalfInstr
&&
!
if3_prevHalfInstrMet
&&
if3_nextValidPCNotEquals
(
if3_prevHalfInstr
.
pc
+
2.
U
)
val
if3_prevHalfMetRedirect
=
if3_pendingPrevHalfInstr
&&
if3_prevHalfInstrMet
&&
if3_prevHalfInstr
.
bits
.
taken
&&
if3_nextValidPCNotEquals
(
if3_prevHalfInstr
.
bits
.
target
)
val
if3_prevHalfNotMetRedirect
=
if3_pendingPrevHalfInstr
&&
!
if3_prevHalfInstrMet
&&
if3_nextValidPCNotEquals
(
if3_prevHalfInstr
.
bits
.
npc
)
val
if3_predTakenRedirect
=
!
if3_pendingPrevHalfInstr
&&
if3_bp
.
taken
&&
if3_nextValidPCNotEquals
(
if3_bp
.
target
)
val
if3_predNotTakenRedirect
=
!
if3_pendingPrevHalfInstr
&&
!
if3_bp
.
taken
&&
if3_nextValidPCNotEquals
(
snpc
(
if3_pc
,
inLoop
))
// when pendingPrevHalfInstr, if3_GHInfo is set to the info of last prev half instr
// val if3_ghInfoNotIdenticalRedirect = !if3_pendingPrevHalfInstr && if3_GHInfo =/= if3_lastGHInfo && enableGhistRepair.B
if3_redirect
:=
if3_
fire
&&
(
if3_redirect
:=
if3_
valid
&&
(
// prevHalf is consumed but the next packet is not where it meant to be
// we do not handle this condition because of the burden of building a correct GHInfo
// prevHalfMetRedirect ||
...
...
@@ -220,7 +229,7 @@ class IFU extends XSModule with HasIFUConst
if1_npc := if3_prevHalfInstr.target
}.else */
when
(
if3_prevHalfNotMetRedirect
)
{
if3_target
:=
if3_prevHalfInstr
.
pc
+
2.
U
if3_target
:=
if3_prevHalfInstr
.
bits
.
npc
}.
elsewhen
(
if3_predTakenRedirect
)
{
if3_target
:=
if3_bp
.
target
}.
elsewhen
(
if3_predNotTakenRedirect
)
{
...
...
@@ -237,7 +246,7 @@ class IFU extends XSModule with HasIFUConst
//********************** IF4 ****************************//
val
if4_pd
=
RegEnable
(
pd
.
io
.
out
,
if3_fire
)
val
if4_ipf
=
RegEnable
(
icacheResp
.
ipf
||
if3_prevHalfInstrMet
&&
if3_prevHalfInstr
.
ipf
,
if3_fire
)
val
if4_ipf
=
RegEnable
(
icacheResp
.
ipf
||
if3_prevHalfInstrMet
&&
if3_prevHalfInstr
.
bits
.
ipf
,
if3_fire
)
val
if4_acf
=
RegEnable
(
icacheResp
.
acf
,
if3_fire
)
val
if4_crossPageIPF
=
RegEnable
(
crossPageIPF
,
if3_fire
)
val
if4_valid
=
RegInit
(
false
.
B
)
...
...
@@ -250,10 +259,14 @@ class IFU extends XSModule with HasIFUConst
val
if4_predHist
=
RegEnable
(
if3_predHist
,
enable
=
if3_fire
)
// wait until prevHalfInstr written into reg
if4_ready
:=
(
if4_fire
&&
!
hasPrevHalfInstrReq
||
!
if4_valid
||
if4_flush
)
&&
GTimer
()
>
500.
U
when
(
if4_flush
)
{
if4_valid
:=
false
.
B
}
.
elsewhen
(
if3_fire
)
{
if4_valid
:=
true
.
B
}
.
elsewhen
(
if4_fire
)
{
if4_valid
:=
false
.
B
}
if4_ready
:=
(
io
.
fetchPacket
.
ready
&&
!
hasPrevHalfInstrReq
||
!
if4_valid
)
&&
GTimer
()
>
500.
U
when
(
if4_flush
)
{
if4_valid
:=
false
.
B
}.
elsewhen
(
if3_fire
&&
!
if3_flush
)
{
if4_valid
:=
Mux
(
if3_pendingPrevHalfInstr
,
if3_prevHalfInstrMet
,
true
.
B
)
}.
elsewhen
(
if4_fire
)
{
if4_valid
:=
false
.
B
}
val
if4_bp
=
Wire
(
new
BranchPrediction
)
if4_bp
:=
bpu
.
io
.
out
(
2
)
...
...
@@ -281,47 +294,50 @@ class IFU extends XSModule with HasIFUConst
// we need this to tell BPU the prediction of prev half
// because the prediction is with the start of each inst
val
if4_prevHalfInstr
=
RegInit
(
0.
U
.
asTypeOf
(
new
PrevHalfInstr
))
val
if4_prevHalfInstr
=
RegInit
(
0.
U
.
asTypeOf
(
ValidUndirectioned
(
new
PrevHalfInstr
)
))
val
if4_pendingPrevHalfInstr
=
if4_prevHalfInstr
.
valid
val
if4_prevHalfInstrMet
=
if4_pendingPrevHalfInstr
&&
(
if4_prevHalfInstr
.
pc
+
2.
U
)
===
if4_pc
&&
if4_valid
val
if4_prevHalfInstrMet
=
if4_pendingPrevHalfInstr
&&
if4_prevHalfInstr
.
bits
.
npc
===
if4_pc
&&
if4_valid
val
if4_prevHalfConsumed
=
if4_prevHalfInstrMet
&&
if4_fire
val
if4_prevHalfFlush
=
if4_flush
val
if4_takenPrevHalf
=
WireInit
(
if4_prevHalfInstrMet
&&
if4_prevHalfInstr
.
taken
)
val
if4_takenPrevHalf
=
WireInit
(
if4_prevHalfInstrMet
&&
if4_prevHalfInstr
.
bits
.
taken
)
when
(
if3_prevHalfConsumed
)
{
if4_prevHalfInstr
:=
if3_prevHalfInstr
if4_prevHalfInstr
.
valid
:=
if3_prevHalfInstr
.
valid
}.
elsewhen
(
if4_prevHalfConsumed
||
if4_prevHalfFlush
)
{
if4_prevHalfInstr
.
valid
:=
false
.
B
}
prevHalfInstrReq
:=
0.
U
.
asTypeOf
(
new
PrevHalfInstr
)
when
(
if4_fire
&&
if4_bp
.
saveHalfRVI
)
{
val
idx
=
if4_bp
.
lastHalfRVIIdx
prevHalfInstrReq
.
valid
:=
true
.
B
// this is result of the last half RVI
prevHalfInstrReq
.
taken
:=
if4_bp
.
lastHalfRVITaken
prevHalfInstrReq
.
ghInfo
:=
if4_gh
prevHalfInstrReq
.
newPtr
:=
DontCare
prevHalfInstrReq
.
fetchpc
:=
if4_pc
prevHalfInstrReq
.
idx
:=
idx
prevHalfInstrReq
.
pc
:=
if4_pd
.
pc
(
idx
)
prevHalfInstrReq
.
target
:=
if4_bp
.
lastHalfRVITarget
prevHalfInstrReq
.
instr
:=
if4_pd
.
instrs
(
idx
)(
15
,
0
)
prevHalfInstrReq
.
ipf
:=
if4_ipf
when
(
if3_prevHalfConsumed
)
{
if4_prevHalfInstr
.
bits
:=
if3_prevHalfInstr
.
bits
}
prevHalfInstrReq
.
valid
:=
if4_fire
&&
if4_bp
.
saveHalfRVI
val
idx
=
if4_bp
.
lastHalfRVIIdx
// this is result of the last half RVI
prevHalfInstrReq
.
bits
.
taken
:=
if4_bp
.
lastHalfRVITaken
prevHalfInstrReq
.
bits
.
ghInfo
:=
if4_gh
prevHalfInstrReq
.
bits
.
newPtr
:=
DontCare
prevHalfInstrReq
.
bits
.
fetchpc
:=
if4_pc
prevHalfInstrReq
.
bits
.
idx
:=
idx
prevHalfInstrReq
.
bits
.
pc
:=
if4_pd
.
pc
(
idx
)
prevHalfInstrReq
.
bits
.
npc
:=
if4_pd
.
pc
(
idx
)
+
2.
U
prevHalfInstrReq
.
bits
.
target
:=
if4_bp
.
lastHalfRVITarget
prevHalfInstrReq
.
bits
.
instr
:=
if4_pd
.
instrs
(
idx
)(
15
,
0
)
prevHalfInstrReq
.
bits
.
ipf
:=
if4_ipf
def
if4_nextValidPCNotEquals
(
pc
:
UInt
)
=
if3_valid
&&
if3_pc
=/=
pc
||
!
if3_valid
&&
(
if2_valid
&&
if2_pc
=/=
pc
)
||
!
if3_valid
&&
!
if2_valid
val
if4_prevHalfNextNotMet
=
hasPrevHalfInstrReq
&&
if4_nextValidPCNotEquals
(
prevHalfInstrReq
.
pc
+
2.
U
)
val
if4_prevHalfNextNotMet
=
hasPrevHalfInstrReq
&&
if4_nextValidPCNotEquals
(
prevHalfInstrReq
.
bits
.
pc
+
2.
U
)
val
if4_predTakenRedirect
=
!
hasPrevHalfInstrReq
&&
if4_bp
.
taken
&&
if4_nextValidPCNotEquals
(
if4_bp
.
target
)
val
if4_predNotTakenRedirect
=
!
hasPrevHalfInstrReq
&&
!
if4_bp
.
taken
&&
if4_nextValidPCNotEquals
(
if4_snpc
)
// val if4_ghInfoNotIdenticalRedirect = if4_GHInfo =/= if4_lastGHInfo && enableGhistRepair.B
if4_redirect
:=
if4_
fire
&&
(
if4_redirect
:=
if4_
valid
&&
(
// when if4 has a lastHalfRVI, but the next fetch packet is not snpc
if4_prevHalfNextNotMet
||
//
if4_prevHalfNextNotMet ||
// when if4 preds taken, but the pc of next fetch packet is not the target
if4_predTakenRedirect
||
// when if4 preds not taken, but the pc of next fetch packet is not snpc
...
...
@@ -332,9 +348,10 @@ class IFU extends XSModule with HasIFUConst
val
if4_target
=
WireInit
(
if4_snpc
)
when
(
if4_prevHalfNextNotMet
)
{
if4_target
:=
prevHalfInstrReq
.
pc
+
2.
U
}.
elsewhen
(
if4_predTakenRedirect
)
{
// when (if4_prevHalfNextNotMet) {
// if4_target := prevHalfInstrReq.pc+2.U
// }.else
when
(
if4_predTakenRedirect
)
{
if4_target
:=
if4_bp
.
target
}.
elsewhen
(
if4_predNotTakenRedirect
)
{
if4_target
:=
if4_snpc
...
...
@@ -377,7 +394,7 @@ class IFU extends XSModule with HasIFUConst
when
(
inLoop
)
{
io
.
icacheReq
.
valid
:=
if4_flush
}.
otherwise
{
io
.
icacheReq
.
valid
:=
if1_valid
&&
if2_ready
io
.
icacheReq
.
valid
:=
if1_valid
&&
(
if2_ready
||
if1_flush
)
}
io
.
icacheResp
.
ready
:=
if4_ready
io
.
icacheReq
.
bits
.
addr
:=
if1_npc
...
...
@@ -427,19 +444,19 @@ class IFU extends XSModule with HasIFUConst
}
pd
.
io
.
prev
.
valid
:=
if3_prevHalfInstrMet
pd
.
io
.
prev
.
bits
:=
if3_prevHalfInstr
.
instr
pd
.
io
.
prev
.
bits
:=
if3_prevHalfInstr
.
bits
.
instr
// if a fetch packet triggers page fault, set the pf instruction to nop
when
(!
if3_prevHalfInstrMet
&&
icacheResp
.
ipf
)
{
val
instrs
=
Wire
(
Vec
(
FetchWidth
,
UInt
(
32.
W
)))
(
0
until
FetchWidth
).
foreach
(
i
=>
instrs
(
i
)
:=
ZeroExt
(
"b0010011"
.
U
,
32
))
// nop
pd
.
io
.
in
.
data
:=
instrs
.
asUInt
}.
elsewhen
(
if3_prevHalfInstrMet
&&
(
if3_prevHalfInstr
.
ipf
||
icacheResp
.
ipf
))
{
}.
elsewhen
(
if3_prevHalfInstrMet
&&
(
if3_prevHalfInstr
.
bits
.
ipf
||
icacheResp
.
ipf
))
{
pd
.
io
.
prev
.
bits
:=
ZeroExt
(
"b0010011"
.
U
,
16
)
val
instrs
=
Wire
(
Vec
(
FetchWidth
,
UInt
(
32.
W
)))
(
0
until
FetchWidth
).
foreach
(
i
=>
instrs
(
i
)
:=
Cat
(
ZeroExt
(
"b0010011"
.
U
,
16
),
Fill
(
16
,
0.
U
(
1.
W
))))
pd
.
io
.
in
.
data
:=
instrs
.
asUInt
when
(
icacheResp
.
ipf
&&
!
if3_prevHalfInstr
.
ipf
)
{
crossPageIPF
:=
true
.
B
}
// higher 16 bits page fault
when
(
icacheResp
.
ipf
&&
!
if3_prevHalfInstr
.
bits
.
ipf
)
{
crossPageIPF
:=
true
.
B
}
// higher 16 bits page fault
}
//Performance Counter
...
...
@@ -454,6 +471,7 @@ class IFU extends XSModule with HasIFUConst
// io.fetchPacket.valid := if4_valid && !io.redirect.valid
fetchPacketWire
.
instrs
:=
if4_pd
.
instrs
fetchPacketWire
.
mask
:=
if4_pd
.
mask
&
(
Fill
(
PredictWidth
,
!
if4_bp
.
taken
)
|
(
Fill
(
PredictWidth
,
1.
U
(
1.
W
))
>>
(~
if4_bp
.
jmpIdx
)))
fetchPacketWire
.
pdmask
:=
if4_pd
.
mask
loopBufPar
.
noTakenMask
:=
if4_pd
.
mask
fetchPacketWire
.
pc
:=
if4_pd
.
pc
...
...
@@ -504,19 +522,19 @@ class IFU extends XSModule with HasIFUConst
XSDebug
(
"[IF3][redirect]: v=%d, prevMet=%d, prevNMet=%d, predT=%d, predNT=%d\n"
,
if3_redirect
,
if3_prevHalfMetRedirect
,
if3_prevHalfNotMetRedirect
,
if3_predTakenRedirect
,
if3_predNotTakenRedirect
)
// XSDebug("[IF3][prevHalfInstr] v=%d redirect=%d fetchpc=%x idx=%d tgt=%x taken=%d instr=%x\n\n",
// prev_half_valid, prev_half_redirect, prev_half_fetchpc, prev_half_idx, prev_half_tgt, prev_half_taken, prev_half_instr)
XSDebug
(
"[IF3][ prevHalfInstr] v=%d taken=%d fetchpc=%x idx=%d pc=%x tgt=%x instr=%x ipf=%d\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][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][if3_prevHalfInstr] v=%d taken=%d fetchpc=%x idx=%d pc=%x npc=%x tgt=%x instr=%x ipf=%d\n\n"
,
if3_prevHalfInstr
.
valid
,
if3_prevHalfInstr
.
bits
.
taken
,
if3_prevHalfInstr
.
bits
.
fetchpc
,
if3_prevHalfInstr
.
bits
.
idx
,
if3_prevHalfInstr
.
bits
.
pc
,
if3_prevHalfInstr
.
bits
.
npc
,
if3_prevHalfInstr
.
bits
.
target
,
if3_prevHalfInstr
.
bits
.
instr
,
if3_prevHalfInstr
.
bits
.
ipf
)
if3_gh
.
debug
(
"if3"
)
XSDebug
(
"[IF4][predecode] mask=%b\n"
,
if4_pd
.
mask
)
XSDebug
(
"[IF4][snpc]: %x, realMask=%b\n"
,
if4_snpc
,
if4_mask
)
XSDebug
(
"[IF4][bp] taken=%d jmpIdx=%d hasNTBrs=%d target=%x saveHalfRVI=%d\n"
,
if4_bp
.
taken
,
if4_bp
.
jmpIdx
,
if4_bp
.
hasNotTakenBrs
,
if4_bp
.
target
,
if4_bp
.
saveHalfRVI
)
XSDebug
(
"[IF4][redirect]: v=%d, prevNotMet=%d, predT=%d, predNT=%d\n"
,
if4_redirect
,
if4_prevHalfNextNotMet
,
if4_predTakenRedirect
,
if4_predNotTakenRedirect
)
XSDebug
(
if4_pd
.
pd
(
if4_bp
.
jmpIdx
).
isJal
&&
if4_bp
.
taken
,
"[IF4] cfi is jal! instr=%x target=%x\n"
,
if4_instrs
(
if4_bp
.
jmpIdx
),
if4_jal_tgts
(
if4_bp
.
jmpIdx
))
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][ prevHalfInstrReq] v=%d taken=%d fetchpc=%x idx=%d pc=%x npc=%x tgt=%x instr=%x ipf=%d\n"
,
prevHalfInstrReq
.
valid
,
prevHalfInstrReq
.
bits
.
taken
,
prevHalfInstrReq
.
bits
.
fetchpc
,
prevHalfInstrReq
.
bits
.
idx
,
prevHalfInstrReq
.
bits
.
pc
,
prevHalfInstrReq
.
bits
.
npc
,
prevHalfInstrReq
.
bits
.
target
,
prevHalfInstrReq
.
bits
.
instr
,
prevHalfInstrReq
.
bits
.
ipf
)
XSDebug
(
"[IF4][if4_prevHalfInstr] v=%d taken=%d fetchpc=%x idx=%d pc=%x npc=%x tgt=%x instr=%x ipf=%d\n"
,
if4_prevHalfInstr
.
valid
,
if4_prevHalfInstr
.
bits
.
taken
,
if4_prevHalfInstr
.
bits
.
fetchpc
,
if4_prevHalfInstr
.
bits
.
idx
,
if4_prevHalfInstr
.
bits
.
pc
,
if4_prevHalfInstr
.
bits
.
npc
,
if4_prevHalfInstr
.
bits
.
target
,
if4_prevHalfInstr
.
bits
.
instr
,
if4_prevHalfInstr
.
bits
.
ipf
)
if4_gh
.
debug
(
"if4"
)
XSDebug
(
io
.
fetchPacket
.
fire
(),
"[IF4][fetchPacket] v=%d r=%d mask=%b ipf=%d acf=%d crossPageIPF=%d\n"
,
io
.
fetchPacket
.
valid
,
io
.
fetchPacket
.
ready
,
io
.
fetchPacket
.
bits
.
mask
,
io
.
fetchPacket
.
bits
.
ipf
,
io
.
fetchPacket
.
bits
.
acf
,
io
.
fetchPacket
.
bits
.
crossPageIPFFix
)
...
...
src/main/scala/xiangshan/frontend/Ibuffer.scala
浏览文件 @
570ceca1
...
...
@@ -7,13 +7,25 @@ import xiangshan._
import
utils._
import
xiangshan.backend.fu.HasExceptionNO
class
IbufPtr
extends
CircularQueuePtr
(
IbufPtr
.
IBufSize
)
{
}
object
IbufPtr
extends
HasXSParameter
{
def
apply
(
f
:
Bool
,
v
:
UInt
)
:
IbufPtr
=
{
val
ptr
=
Wire
(
new
IbufPtr
)
ptr
.
flag
:=
f
ptr
.
value
:=
v
ptr
}
}
class
IBufferIO
extends
XSBundle
{
val
flush
=
Input
(
Bool
())
val
in
=
Flipped
(
DecoupledIO
(
new
FetchPacket
))
val
out
=
Vec
(
DecodeWidth
,
DecoupledIO
(
new
CtrlFlow
))
}
class
Ibuffer
extends
XSModule
{
class
Ibuffer
extends
XSModule
with
HasCircularQueuePtrHelper
{
val
io
=
IO
(
new
IBufferIO
)
class
IBufEntry
extends
XSBundle
{
...
...
@@ -41,52 +53,56 @@ class Ibuffer extends XSModule {
// Ibuffer define
val
ibuf
=
Mem
(
IBufSize
,
new
IBufEntry
)
val
ibuf_valid
=
RegInit
(
VecInit
(
Seq
.
fill
(
IBufSize
)(
false
.
B
)))
val
head_ptr
=
RegInit
(
0.
U
(
log2Up
(
IBufSize
).
W
))
val
tail_ptr
=
RegInit
(
0.
U
(
log2Up
(
IBufSize
).
W
))
val
head_ptr
=
RegInit
(
IbufPtr
(
false
.
B
,
0.
U
))
val
tail_ptr
=
RegInit
(
IbufPtr
(
false
.
B
,
0.
U
))
val
enqValid
=
!
io
.
flush
&&
!
ibuf_valid
(
tail_ptr
+
PredictWidth
.
U
-
1.
U
)
val
deqValid
=
!
io
.
flush
&&
ibuf_valid
(
head_ptr
)
val
validEntries
=
distanceBetween
(
tail_ptr
,
head_ptr
)
// valid entries
val
enqValid
=
IBufSize
.
U
-
PredictWidth
.
U
>=
validEntries
val
deqValid
=
validEntries
>
0.
U
// Enque
io
.
in
.
ready
:=
enqValid
when
(
io
.
in
.
fire
)
{
var
enq_idx
=
WireInit
(
tail_ptr
)
val
enq_vec
=
Wire
(
Vec
(
PredictWidth
,
UInt
(
log2Up
(
IBufSize
).
W
)))
for
(
i
<-
0
until
PredictWidth
)
{
if
(
i
==
0
)
{
enq_vec
(
i
)
:=
tail_ptr
.
value
}
else
{
enq_vec
(
i
)
:=
tail_ptr
.
value
+
PopCount
(
io
.
in
.
bits
.
pdmask
(
i
-
1
,
0
))
}
}
when
(
io
.
in
.
fire
&&
!
io
.
flush
)
{
for
(
i
<-
0
until
PredictWidth
)
{
va
r
inWire
=
Wire
(
new
IBufEntry
)
va
l
inWire
=
Wire
(
new
IBufEntry
)
inWire
:=
DontCare
ibuf_valid
(
enq_idx
)
:=
io
.
in
.
bits
.
mask
(
i
)
inWire
.
inst
:=
io
.
in
.
bits
.
instrs
(
i
)
inWire
.
pc
:=
io
.
in
.
bits
.
pc
(
i
)
inWire
.
pnpc
:=
io
.
in
.
bits
.
pnpc
(
i
)
inWire
.
brInfo
:=
io
.
in
.
bits
.
bpuMeta
(
i
)
inWire
.
pd
:=
io
.
in
.
bits
.
pd
(
i
)
inWire
.
ipf
:=
io
.
in
.
bits
.
ipf
inWire
.
acf
:=
io
.
in
.
bits
.
acf
inWire
.
crossPageIPFFix
:=
io
.
in
.
bits
.
crossPageIPFFix
ibuf
(
enq_idx
)
:=
inWire
enq_idx
=
enq_idx
+
io
.
in
.
bits
.
mask
(
i
)
when
(
io
.
in
.
bits
.
mask
(
i
))
{
inWire
.
inst
:=
io
.
in
.
bits
.
instrs
(
i
)
inWire
.
pc
:=
io
.
in
.
bits
.
pc
(
i
)
inWire
.
pnpc
:=
io
.
in
.
bits
.
pnpc
(
i
)
inWire
.
brInfo
:=
io
.
in
.
bits
.
bpuMeta
(
i
)
inWire
.
pd
:=
io
.
in
.
bits
.
pd
(
i
)
inWire
.
ipf
:=
io
.
in
.
bits
.
ipf
inWire
.
acf
:=
io
.
in
.
bits
.
acf
inWire
.
crossPageIPFFix
:=
io
.
in
.
bits
.
crossPageIPFFix
ibuf
(
enq_vec
(
i
))
:=
inWire
}
}
tail_ptr
:=
enq_idx
tail_ptr
:=
tail_ptr
+
PopCount
(
io
.
in
.
bits
.
mask
)
}
// Deque
when
(
deqValid
)
{
val
validVec
=
UIntToMask
(
validEntries
,
DecodeWidth
)
io
.
out
.
zipWithIndex
.
foreach
{
case
(
e
,
i
)
=>
e
.
valid
:=
validVec
(
i
)}
for
(
i
<-
0
until
DecodeWidth
)
{
val
head_wire
=
head_ptr
+
i
.
U
val
head_wire
=
head_ptr
.
value
+
i
.
U
val
outWire
=
WireInit
(
ibuf
(
head_wire
))
io
.
out
(
i
).
valid
:=
ibuf_valid
(
head_wire
)
when
(
ibuf_valid
(
head_wire
)
&&
io
.
out
(
i
).
ready
)
{
ibuf_valid
(
head_wire
)
:=
false
.
B
}
io
.
out
(
i
).
bits
.
instr
:=
outWire
.
inst
io
.
out
(
i
).
bits
.
pc
:=
outWire
.
pc
// io.out(i).bits.exceptionVec := Mux(outWire.ipf, UIntToOH(instrPageFault.U), 0.U)
...
...
@@ -101,7 +117,7 @@ class Ibuffer extends XSModule {
io
.
out
(
i
).
bits
.
brUpdate
.
bpuMeta
:=
outWire
.
brInfo
io
.
out
(
i
).
bits
.
crossPageIPFFix
:=
outWire
.
crossPageIPFFix
}
head_ptr
:=
head_ptr
+
io
.
out
.
map
(
_
.
fire
).
fold
(
0.
U
(
log2Up
(
DecodeWidth
).
W
))(
_
+
_
)
head_ptr
:=
head_ptr
+
PopCount
(
io
.
out
.
map
(
_
.
fire
)
)
}.
otherwise
{
io
.
out
.
foreach
(
_
.
valid
:=
false
.
B
)
io
.
out
.
foreach
(
_
.
bits
<>
DontCare
)
...
...
@@ -109,10 +125,10 @@ class Ibuffer extends XSModule {
// Flush
when
(
io
.
flush
)
{
ibuf_valid
.
foreach
(
_
:=
false
.
B
)
head_ptr
:=
0.
U
tail_ptr
:=
0.
U
io
.
out
.
foreach
(
_
.
valid
:=
false
.
B
)
head_ptr
.
value
:=
0.
U
head_ptr
.
flag
:=
false
.
B
tail_ptr
.
value
:=
0.
U
tail_ptr
.
flag
:=
false
.
B
}
// Debug info
...
...
@@ -134,17 +150,31 @@ class Ibuffer extends XSModule {
}
}
// XSDebug(p"last_head_ptr=$head_ptr last_tail_ptr=$tail_ptr\n")
// for(i <- 0 until IBufSize/8) {
// XSDebug("%x v:%b | %x v:%b | %x v:%b | %x v:%b | %x v:%b | %x v:%b | %x v:%b | %x v:%b\n",
// ibuf(i*8+0).inst, ibuf_valid(i*8+0),
// ibuf(i*8+1).inst, ibuf_valid(i*8+1),
// ibuf(i*8+2).inst, ibuf_valid(i*8+2),
// ibuf(i*8+3).inst, ibuf_valid(i*8+3),
// ibuf(i*8+4).inst, ibuf_valid(i*8+4),
// ibuf(i*8+5).inst, ibuf_valid(i*8+5),
// ibuf(i*8+6).inst, ibuf_valid(i*8+6),
// ibuf(i*8+7).inst, ibuf_valid(i*8+7)
// )
// }
XSDebug
(
p
"last_head_ptr=$head_ptr last_tail_ptr=$tail_ptr\n"
)
for
(
i
<-
0
until
IBufSize
/
8
)
{
XSDebug
(
"%x
v:%b | %x v:%b | %x v:%b | %x v:%b | %x v:%b | %x v:%b | %x v:%b | %x v:%b
\n"
,
ibuf
(
i
*
8
+
0
).
inst
,
ibuf_valid
(
i
*
8
+
0
),
ibuf
(
i
*
8
+
1
).
inst
,
ibuf_valid
(
i
*
8
+
1
),
ibuf
(
i
*
8
+
2
).
inst
,
ibuf_valid
(
i
*
8
+
2
),
ibuf
(
i
*
8
+
3
).
inst
,
ibuf_valid
(
i
*
8
+
3
),
ibuf
(
i
*
8
+
4
).
inst
,
ibuf_valid
(
i
*
8
+
4
),
ibuf
(
i
*
8
+
5
).
inst
,
ibuf_valid
(
i
*
8
+
5
),
ibuf
(
i
*
8
+
6
).
inst
,
ibuf_valid
(
i
*
8
+
6
),
ibuf
(
i
*
8
+
7
).
inst
,
ibuf_valid
(
i
*
8
+
7
)
XSDebug
(
"%x
| %x | %x | %x | %x | %x | %x | %x
\n"
,
ibuf
(
i
*
8
+
0
).
inst
,
ibuf
(
i
*
8
+
1
).
inst
,
ibuf
(
i
*
8
+
2
).
inst
,
ibuf
(
i
*
8
+
3
).
inst
,
ibuf
(
i
*
8
+
4
).
inst
,
ibuf
(
i
*
8
+
5
).
inst
,
ibuf
(
i
*
8
+
6
).
inst
,
ibuf
(
i
*
8
+
7
).
inst
)
}
}
\ No newline at end of file
}
src/main/scala/xiangshan/frontend/Tage.scala
浏览文件 @
570ceca1
...
...
@@ -408,7 +408,7 @@ class Tage extends BaseTage {
val
tables
=
TableInfo
.
map
{
case
(
nRows
,
histLen
,
tagLen
)
=>
{
val
t
=
if
(
EnableBPD
)
Module
(
new
TageTable
(
nRows
,
histLen
,
tagLen
,
UBitPeriod
))
else
Module
(
new
FakeTageTable
)
t
.
io
.
req
.
valid
:=
io
.
pc
.
valid
&&
!
io
.
flush
t
.
io
.
req
.
valid
:=
io
.
pc
.
valid
t
.
io
.
req
.
bits
.
pc
:=
io
.
pc
.
bits
t
.
io
.
req
.
bits
.
hist
:=
io
.
hist
t
.
io
.
req
.
bits
.
mask
:=
io
.
inMask
...
...
@@ -420,7 +420,7 @@ class Tage extends BaseTage {
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
.
valid
:=
io
.
pc
.
valid
req
.
bits
.
pc
:=
io
.
pc
.
bits
req
.
bits
.
hist
:=
io
.
hist
req
.
bits
.
mask
:=
io
.
inMask
...
...
src/main/scala/xiangshan/frontend/uBTB.scala
浏览文件 @
570ceca1
...
...
@@ -162,7 +162,7 @@ class MicroBTB extends BasePredictor
val
do_reset
=
RegInit
(
true
.
B
)
val
reset_way
=
RegInit
(
0.
U
(
log2Ceil
(
nWays
).
W
))
when
(
do_reset
)
{
reset_way
:=
reset_way
+
1.
U
}
when
(
reset_way
===
nWays
.
U
)
{
do_reset
:=
false
.
B
}
when
(
reset_way
===
(
nWays
-
1
)
.
U
)
{
do_reset
:=
false
.
B
}
//uBTB read
//tag is bank align
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录