Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenXiangShan
XiangShan
提交
2c87aa6f
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,发现更多精彩内容 >>
未验证
提交
2c87aa6f
编写于
1月 29, 2021
作者:
L
ljw
提交者:
GitHub
1月 29, 2021
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #510 from RISCVERS/ftq
Ftq: save pc and branch infos by fetch packet
上级
d3851157
6e063394
变更
52
展开全部
隐藏空白更改
内联
并排
Showing
52 changed file
with
1982 addition
and
2037 deletion
+1982
-2037
src/main/scala/top/Parameters.scala
src/main/scala/top/Parameters.scala
+1
-1
src/main/scala/utils/LogUtils.scala
src/main/scala/utils/LogUtils.scala
+11
-25
src/main/scala/xiangshan/Bundle.scala
src/main/scala/xiangshan/Bundle.scala
+106
-85
src/main/scala/xiangshan/XSCore.scala
src/main/scala/xiangshan/XSCore.scala
+12
-5
src/main/scala/xiangshan/backend/CtrlBlock.scala
src/main/scala/xiangshan/backend/CtrlBlock.scala
+202
-47
src/main/scala/xiangshan/backend/FloatBlock.scala
src/main/scala/xiangshan/backend/FloatBlock.scala
+4
-0
src/main/scala/xiangshan/backend/IntegerBlock.scala
src/main/scala/xiangshan/backend/IntegerBlock.scala
+11
-3
src/main/scala/xiangshan/backend/MemBlock.scala
src/main/scala/xiangshan/backend/MemBlock.scala
+6
-0
src/main/scala/xiangshan/backend/brq/Brq.scala
src/main/scala/xiangshan/backend/brq/Brq.scala
+0
-420
src/main/scala/xiangshan/backend/decode/DecodeStage.scala
src/main/scala/xiangshan/backend/decode/DecodeStage.scala
+2
-33
src/main/scala/xiangshan/backend/decode/DecodeUnit.scala
src/main/scala/xiangshan/backend/decode/DecodeUnit.scala
+0
-1
src/main/scala/xiangshan/backend/dispatch/Dispatch.scala
src/main/scala/xiangshan/backend/dispatch/Dispatch.scala
+5
-1
src/main/scala/xiangshan/backend/dispatch/Dispatch1.scala
src/main/scala/xiangshan/backend/dispatch/Dispatch1.scala
+1
-1
src/main/scala/xiangshan/backend/dispatch/DispatchQueue.scala
...main/scala/xiangshan/backend/dispatch/DispatchQueue.scala
+10
-10
src/main/scala/xiangshan/backend/exu/AluExeUnit.scala
src/main/scala/xiangshan/backend/exu/AluExeUnit.scala
+0
-1
src/main/scala/xiangshan/backend/exu/Exu.scala
src/main/scala/xiangshan/backend/exu/Exu.scala
+3
-2
src/main/scala/xiangshan/backend/exu/FmacExeUnit.scala
src/main/scala/xiangshan/backend/exu/FmacExeUnit.scala
+1
-0
src/main/scala/xiangshan/backend/exu/JumpExeUnit.scala
src/main/scala/xiangshan/backend/exu/JumpExeUnit.scala
+7
-17
src/main/scala/xiangshan/backend/exu/MulDivExeUnit.scala
src/main/scala/xiangshan/backend/exu/MulDivExeUnit.scala
+2
-3
src/main/scala/xiangshan/backend/ftq/Ftq.scala
src/main/scala/xiangshan/backend/ftq/Ftq.scala
+291
-0
src/main/scala/xiangshan/backend/fu/Alu.scala
src/main/scala/xiangshan/backend/fu/Alu.scala
+6
-19
src/main/scala/xiangshan/backend/fu/CSR.scala
src/main/scala/xiangshan/backend/fu/CSR.scala
+31
-40
src/main/scala/xiangshan/backend/fu/FunctionUnit.scala
src/main/scala/xiangshan/backend/fu/FunctionUnit.scala
+2
-1
src/main/scala/xiangshan/backend/fu/Jump.scala
src/main/scala/xiangshan/backend/fu/Jump.scala
+15
-18
src/main/scala/xiangshan/backend/fu/Radix2Divider.scala
src/main/scala/xiangshan/backend/fu/Radix2Divider.scala
+3
-3
src/main/scala/xiangshan/backend/fu/SRT4Divider.scala
src/main/scala/xiangshan/backend/fu/SRT4Divider.scala
+2
-2
src/main/scala/xiangshan/backend/fu/fpu/FDivSqrt.scala
src/main/scala/xiangshan/backend/fu/fpu/FDivSqrt.scala
+3
-3
src/main/scala/xiangshan/backend/fu/fpu/IntToFP.scala
src/main/scala/xiangshan/backend/fu/fpu/IntToFP.scala
+2
-2
src/main/scala/xiangshan/backend/issue/ReservationStationNew.scala
...scala/xiangshan/backend/issue/ReservationStationNew.scala
+26
-9
src/main/scala/xiangshan/backend/rename/FreeList.scala
src/main/scala/xiangshan/backend/rename/FreeList.scala
+4
-5
src/main/scala/xiangshan/backend/rename/Rename.scala
src/main/scala/xiangshan/backend/rename/Rename.scala
+14
-7
src/main/scala/xiangshan/backend/rename/RenameTable.scala
src/main/scala/xiangshan/backend/rename/RenameTable.scala
+5
-5
src/main/scala/xiangshan/backend/roq/Roq.scala
src/main/scala/xiangshan/backend/roq/Roq.scala
+72
-38
src/main/scala/xiangshan/frontend/BPU.scala
src/main/scala/xiangshan/frontend/BPU.scala
+67
-81
src/main/scala/xiangshan/frontend/Bim.scala
src/main/scala/xiangshan/frontend/Bim.scala
+29
-30
src/main/scala/xiangshan/frontend/Btb.scala
src/main/scala/xiangshan/frontend/Btb.scala
+26
-35
src/main/scala/xiangshan/frontend/Frontend.scala
src/main/scala/xiangshan/frontend/Frontend.scala
+7
-3
src/main/scala/xiangshan/frontend/IFU.scala
src/main/scala/xiangshan/frontend/IFU.scala
+155
-133
src/main/scala/xiangshan/frontend/Ibuffer.scala
src/main/scala/xiangshan/frontend/Ibuffer.scala
+12
-10
src/main/scala/xiangshan/frontend/LoopPredictor.scala
src/main/scala/xiangshan/frontend/LoopPredictor.scala
+423
-433
src/main/scala/xiangshan/frontend/RAS.scala
src/main/scala/xiangshan/frontend/RAS.scala
+121
-200
src/main/scala/xiangshan/frontend/Tage.scala
src/main/scala/xiangshan/frontend/Tage.scala
+76
-82
src/main/scala/xiangshan/frontend/uBTB.scala
src/main/scala/xiangshan/frontend/uBTB.scala
+38
-57
src/main/scala/xiangshan/mem/lsqueue/LSQWrapper.scala
src/main/scala/xiangshan/mem/lsqueue/LSQWrapper.scala
+4
-1
src/main/scala/xiangshan/mem/lsqueue/LoadQueue.scala
src/main/scala/xiangshan/mem/lsqueue/LoadQueue.scala
+14
-13
src/main/scala/xiangshan/mem/lsqueue/StoreQueue.scala
src/main/scala/xiangshan/mem/lsqueue/StoreQueue.scala
+7
-7
src/main/scala/xiangshan/mem/pipeline/AtomicsUnit.scala
src/main/scala/xiangshan/mem/pipeline/AtomicsUnit.scala
+2
-2
src/main/scala/xiangshan/mem/pipeline/LoadUnit.scala
src/main/scala/xiangshan/mem/pipeline/LoadUnit.scala
+3
-3
src/main/scala/xiangshan/mem/pipeline/StoreUnit.scala
src/main/scala/xiangshan/mem/pipeline/StoreUnit.scala
+4
-4
src/main/scala/xiangshan/package.scala
src/main/scala/xiangshan/package.scala
+5
-7
src/test/scala/xiangshan/frontend/RASTest.scala
src/test/scala/xiangshan/frontend/RASTest.scala
+78
-78
src/test/scala/xiangshan/frontend/uBTBTest.scala
src/test/scala/xiangshan/frontend/uBTBTest.scala
+51
-51
未找到文件。
src/main/scala/top/Parameters.scala
浏览文件 @
2c87aa6f
...
...
@@ -22,7 +22,7 @@ case class Parameters
object
Parameters
{
val
dualCoreParameters
=
Parameters
(
socParameters
=
SoCParameters
(
NumCores
=
2
))
val
simParameters
=
Parameters
(
envParameters
=
EnviromentParameters
(
FPGAPlatform
=
false
))
// sim only, disable log
val
debugParameters
=
Parameters
(
envParameters
=
simParameters
.
envParameters
.
copy
(
EnableDebug
=
true
))
// open log
val
debugParameters
=
Parameters
(
envParameters
=
simParameters
.
envParameters
.
copy
(
EnableDebug
=
true
,
EnablePerfDebug
=
true
))
// open log
val
simDualCoreParameters
=
Parameters
(
socParameters
=
SoCParameters
(
NumCores
=
2
),
envParameters
=
EnviromentParameters
(
FPGAPlatform
=
true
,
DualCoreDifftest
=
true
))
val
debugDualCoreParameters
=
Parameters
(
socParameters
=
SoCParameters
(
NumCores
=
2
),
envParameters
=
simParameters
.
envParameters
.
copy
(
EnableDebug
=
true
))
...
...
src/main/scala/utils/LogUtils.scala
浏览文件 @
2c87aa6f
...
...
@@ -102,37 +102,23 @@ object XSWarn extends LogHelper(XSLogLevel.WARN)
object
XSError
extends
LogHelper
(
XSLogLevel
.
ERROR
)
object
XSPerf
{
def
apply
(
perfName
:
String
,
perfCnt
:
UInt
)(
implicit
name
:
String
)
=
{
val
reset
=
true
val
print_per_cycle
=
false
val
print_gap_bits
=
15
def
apply
(
perfName
:
String
,
perfCnt
:
UInt
,
acc
:
Boolean
=
false
,
intervalBits
:
Int
=
15
)(
implicit
name
:
String
)
=
{
val
counter
=
RegInit
(
0.
U
(
64.
W
))
val
next_counter
=
WireInit
(
0.
U
(
64.
W
))
val
logTimestamp
=
WireInit
(
0.
U
(
64.
W
))
val
enableDebug
=
Parameters
.
get
.
envParameters
.
EnableDebug
val
logEnable
=
WireInit
(
false
.
B
)
next_counter
:=
counter
+
perfCnt
counter
:=
next_counter
if
(
enableDebug
)
{
ExcitingUtils
.
addSink
(
logEnable
,
"DISPLAY_LOG_ENABLE"
)
if
(!
print_per_cycle
)
{
ExcitingUtils
.
addSink
(
logTimestamp
,
"logTimestamp"
)
next_counter
:=
counter
+
perfCnt
when
(
logEnable
&&
logTimestamp
(
print_gap_bits
-
1
,
0
)
===
0.
U
)
{
// TODO: Need print when program exit?
if
(
reset
)
{
next_counter
:=
perfCnt
XSLog
(
XSLogLevel
.
PERF
)(
true
,
true
.
B
,
p
"$perfName, $counter\n"
)
}
else
{
XSLog
(
XSLogLevel
.
PERF
)(
true
,
true
.
B
,
p
"$perfName, $next_counter\n"
)
}
}
counter
:=
next_counter
}
else
{
when
(
logEnable
)
{
ExcitingUtils
.
addSink
(
logTimestamp
,
"logTimestamp"
)
val
printCond
=
if
(
intervalBits
==
0
)
true
.
B
else
(
logTimestamp
(
intervalBits
-
1
,
0
)
===
0.
U
)
when
(
printCond
)
{
// TODO: Need print when program exit?
if
(
acc
)
{
XSLog
(
XSLogLevel
.
PERF
)(
true
,
true
.
B
,
p
"$perfName, $next_counter\n"
)
}
else
{
XSLog
(
XSLogLevel
.
PERF
)(
true
,
true
.
B
,
p
"$perfName, $perfCnt\n"
)
}
}
...
...
src/main/scala/xiangshan/Bundle.scala
浏览文件 @
2c87aa6f
...
...
@@ -3,8 +3,6 @@ package xiangshan
import
chisel3._
import
chisel3.util._
import
xiangshan.backend.SelImm
import
xiangshan.backend.brq.BrqPtr
import
xiangshan.backend.rename.FreeListPtr
import
xiangshan.backend.roq.RoqPtr
import
xiangshan.backend.decode.
{
ImmUnion
,
XDecode
}
import
xiangshan.mem.
{
LqPtr
,
SqPtr
}
...
...
@@ -13,10 +11,12 @@ import xiangshan.frontend.HasBPUParameter
import
xiangshan.frontend.HasTageParameter
import
xiangshan.frontend.HasIFUConst
import
xiangshan.frontend.GlobalHistory
import
xiangshan.frontend.RASEntry
import
utils._
import
scala.math.max
import
Chisel.experimental.chiselName
import
xiangshan.backend.ftq.FtqPtr
// Fetch FetchWidth x 32-bit insts from Icache
class
FetchPacket
extends
XSBundle
{
...
...
@@ -25,18 +25,18 @@ class FetchPacket extends XSBundle {
val
pdmask
=
UInt
(
PredictWidth
.
W
)
// val pc = UInt(VAddrBits.W)
val
pc
=
Vec
(
PredictWidth
,
UInt
(
VAddrBits
.
W
))
val
pnpc
=
Vec
(
PredictWidth
,
UInt
(
VAddrBits
.
W
))
val
bpuMeta
=
Vec
(
PredictWidth
,
new
BpuMeta
)
val
pd
=
Vec
(
PredictWidth
,
new
PreDecodeInfo
)
val
ipf
=
Bool
()
val
acf
=
Bool
()
val
crossPageIPFFix
=
Bool
()
val
predTaken
=
Bool
()
val
pred_taken
=
UInt
(
PredictWidth
.
W
)
val
ftqPtr
=
new
FtqPtr
}
class
ValidUndirectioned
[
T
<:
Data
](
gen
:
T
)
extends
Bundle
{
val
valid
=
Bool
()
val
bits
=
gen
.
cloneType
.
asInstanceOf
[
T
]
override
def
cloneType
=
new
ValidUndirectioned
(
gen
).
asInstanceOf
[
this.
type
]
}
...
...
@@ -47,15 +47,18 @@ 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
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
)
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
)
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
{
...
...
@@ -77,47 +80,32 @@ class BranchPrediction extends XSBundle with HasIFUConst {
val
jalMask
=
UInt
(
PredictWidth
.
W
)
val
targets
=
Vec
(
PredictWidth
,
UInt
(
VAddrBits
.
W
))
// marks the last 2 bytes of this fetch packet
// val endsAtTheEndOfFirstBank = Bool()
// val endsAtTheEndOfLastBank = Bool()
// half RVI could only start at the end of a packet
val
hasHalfRVI
=
Bool
()
def
brNotTakens
=
(~
takens
&
brMask
)
// assumes that only one of the two conditions could be true
def
lastHalfRVIMask
=
Cat
(
hasHalfRVI
.
asUInt
,
0.
U
((
PredictWidth
-
1
).
W
))
def
lastHalfRVIClearMask
=
~
lastHalfRVIMask
// is taken from half RVI
def
lastHalfRVITaken
=
takens
(
PredictWidth
-
1
)
&&
hasHalfRVI
def
lastHalfRVIIdx
=
(
PredictWidth
-
1
).
U
// should not be used if not lastHalfRVITaken
def
lastHalfRVITarget
=
targets
(
PredictWidth
-
1
)
def
realTakens
=
takens
&
lastHalfRVIClearMask
def
realBrMask
=
brMask
&
lastHalfRVIClearMask
def
realJalMask
=
jalMask
&
lastHalfRVIClearMask
def
brNotTakens
=
(~
takens
&
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
)
(
if
(
i
==
0
)
false
.
B
else
ParallelORR
(
brNotTakens
(
i
-
1
,
0
)))))
// if not taken before the half RVI inst
def
saveHalfRVI
=
hasHalfRVI
&&
!(
ParallelORR
(
takens
(
PredictWidth
-
2
,
0
)))
def
saveHalfRVI
=
hasHalfRVI
&&
!(
ParallelORR
(
takens
(
PredictWidth
-
2
,
0
)))
// could get PredictWidth-1 when only the first bank is valid
def
jmpIdx
=
ParallelPriorityEncoder
(
realTakens
)
def
jmpIdx
=
ParallelPriorityEncoder
(
takens
)
// only used when taken
def
target
=
{
val
generator
=
new
PriorityMuxGenerator
[
UInt
]
generator
.
register
(
realT
akens
.
asBools
,
targets
,
List
.
fill
(
PredictWidth
)(
None
))
generator
.
register
(
t
akens
.
asBools
,
targets
,
List
.
fill
(
PredictWidth
)(
None
))
generator
()
}
def
taken
=
ParallelORR
(
realTakens
)
def
takenOnBr
=
taken
&&
ParallelPriorityMux
(
realTakens
,
realBrMask
.
asBools
)
def
hasNotTakenBrs
=
Mux
(
taken
,
ParallelPriorityMux
(
realTakens
,
sawNotTakenBr
),
ParallelORR
(
brNotTakens
))
def
taken
=
ParallelORR
(
takens
)
def
takenOnBr
=
taken
&&
ParallelPriorityMux
(
takens
,
brMask
.
asBools
)
def
hasNotTakenBrs
=
Mux
(
taken
,
ParallelPriorityMux
(
takens
,
sawNotTakenBr
),
ParallelORR
(
brNotTakens
))
}
class
PredictorAnswer
extends
XSBundle
{
...
...
@@ -130,22 +118,12 @@ class BpuMeta extends XSBundle with HasBPUParameter {
val
ubtbWriteWay
=
UInt
(
log2Up
(
UBtbWays
).
W
)
val
ubtbHits
=
Bool
()
val
btbWriteWay
=
UInt
(
log2Up
(
BtbWays
).
W
)
val
btbHitJal
=
Bool
()
val
bimCtr
=
UInt
(
2.
W
)
val
tageMeta
=
new
TageMeta
val
rasSp
=
UInt
(
log2Up
(
RasSize
).
W
)
val
rasTopCtr
=
UInt
(
8.
W
)
val
rasToqAddr
=
UInt
(
VAddrBits
.
W
)
val
fetchIdx
=
UInt
(
log2Up
(
PredictWidth
).
W
)
val
specCnt
=
UInt
(
10.
W
)
// for global history
val
predTaken
=
Bool
()
val
hist
=
new
GlobalHistory
val
predHist
=
new
GlobalHistory
val
sawNotTakenBranch
=
Bool
()
val
debug_ubtb_cycle
=
if
(
EnableBPUTimeRecord
)
UInt
(
64.
W
)
else
UInt
(
0.
W
)
val
debug_btb_cycle
=
if
(
EnableBPUTimeRecord
)
UInt
(
64.
W
)
else
UInt
(
0.
W
)
val
debug_btb_cycle
=
if
(
EnableBPUTimeRecord
)
UInt
(
64.
W
)
else
UInt
(
0.
W
)
val
debug_tage_cycle
=
if
(
EnableBPUTimeRecord
)
UInt
(
64.
W
)
else
UInt
(
0.
W
)
val
predictor
=
if
(
BPUDebug
)
UInt
(
log2Up
(
4
).
W
)
else
UInt
(
0.
W
)
// Mark which component this prediction comes from {ubtb, btb, tage, loopPredictor}
...
...
@@ -164,6 +142,7 @@ class BpuMeta extends XSBundle with HasBPUParameter {
// this.asUInt
// }
def
size
=
0.
U
.
asTypeOf
(
this
).
getWidth
def
fromUInt
(
x
:
UInt
)
=
x
.
asTypeOf
(
this
)
}
...
...
@@ -177,19 +156,19 @@ class Predecode extends XSBundle with HasIFUConst {
class
CfiUpdateInfo
extends
XSBundle
with
HasBPUParameter
{
// from backend
val
pc
=
UInt
(
VAddrBits
.
W
)
val
pnpc
=
UInt
(
VAddrBits
.
W
)
val
fetchIdx
=
UInt
(
log2Up
(
PredictWidth
).
W
)
// frontend -> backend -> frontend
val
pd
=
new
PreDecodeInfo
val
bpuMeta
=
new
BpuMeta
val
rasSp
=
UInt
(
log2Up
(
RasSize
).
W
)
val
rasEntry
=
new
RASEntry
val
hist
=
new
GlobalHistory
val
predHist
=
new
GlobalHistory
val
specCnt
=
UInt
(
10.
W
)
// need pipeline update
val
sawNotTakenBranch
=
Bool
()
val
predTaken
=
Bool
()
val
target
=
UInt
(
VAddrBits
.
W
)
val
brTarget
=
UInt
(
VAddrBits
.
W
)
val
taken
=
Bool
()
val
isMisPred
=
Bool
()
val
brTag
=
new
BrqPtr
val
isReplay
=
Bool
()
}
// Dequeue DecodeWidth insts from Ibuffer
...
...
@@ -198,15 +177,53 @@ class CtrlFlow extends XSBundle {
val
pc
=
UInt
(
VAddrBits
.
W
)
val
exceptionVec
=
ExceptionVec
()
val
intrVec
=
Vec
(
12
,
Bool
())
val
brUpdate
=
new
CfiUpdateInfo
val
pd
=
new
PreDecodeInfo
val
pred_taken
=
Bool
()
val
crossPageIPFFix
=
Bool
()
val
ftqPtr
=
new
FtqPtr
val
ftqOffset
=
UInt
(
log2Up
(
PredictWidth
).
W
)
}
class
FtqEntry
extends
XSBundle
{
// fetch pc, pc of each inst could be generated by concatenation
val
ftqPC
=
UInt
((
VAddrBits
.
W
))
val
hasLastPrev
=
Bool
()
// prediction metas
val
hist
=
new
GlobalHistory
val
predHist
=
new
GlobalHistory
val
rasSp
=
UInt
(
log2Ceil
(
RasSize
).
W
)
val
rasTop
=
new
RASEntry
()
val
specCnt
=
Vec
(
PredictWidth
,
UInt
(
10.
W
))
val
metas
=
Vec
(
PredictWidth
,
new
BpuMeta
)
val
cfiIsCall
,
cfiIsRet
,
cfiIsRVC
=
Bool
()
val
rvc_mask
=
Vec
(
PredictWidth
,
Bool
())
val
br_mask
=
Vec
(
PredictWidth
,
Bool
())
val
cfiIndex
=
ValidUndirectioned
(
UInt
(
log2Up
(
PredictWidth
).
W
))
val
valids
=
Vec
(
PredictWidth
,
Bool
())
// backend update
val
mispred
=
Vec
(
PredictWidth
,
Bool
())
val
target
=
UInt
(
VAddrBits
.
W
)
def
takens
=
VecInit
((
0
until
PredictWidth
).
map
(
i
=>
cfiIndex
.
valid
&&
cfiIndex
.
bits
===
i
.
U
))
override
def
toPrintable
:
Printable
=
{
p
"ftqPC: ${Hexadecimal(ftqPC)} hasLastPrec:$hasLastPrev "
+
p
"rasSp:$rasSp specCnt:$specCnt brmask:${Binary(Cat(br_mask))} rvcmask:${Binary(Cat(rvc_mask))} "
+
p
"valids:${Binary(valids.asUInt())} cfi valid: ${cfiIndex.valid} "
+
p
"cfi index: ${cfiIndex.bits} isCall:$cfiIsCall isRet:$cfiIsRet isRvc:$cfiIsRVC "
+
p
"mispred:${Binary(Cat(mispred))} target:${Hexadecimal(target)}\n"
}
}
class
FPUCtrlSignals
extends
XSBundle
{
val
isAddSub
=
Bool
()
// swap23
val
typeTagIn
=
UInt
(
2.
W
)
val
typeTagOut
=
UInt
(
2.
W
)
val
typeTagIn
=
UInt
(
2.
W
)
val
typeTagOut
=
UInt
(
2.
W
)
val
fromInt
=
Bool
()
val
wflags
=
Bool
()
val
fpWen
=
Bool
()
...
...
@@ -229,9 +246,9 @@ class CtrlSignals extends XSBundle {
val
rfWen
=
Bool
()
val
fpWen
=
Bool
()
val
isXSTrap
=
Bool
()
val
noSpecExec
=
Bool
()
// wait forward
val
blockBackward
=
Bool
()
// block backward
val
flushPipe
=
Bool
()
// This inst will flush all the pipe when commit, like exception but can commit
val
noSpecExec
=
Bool
()
// wait forward
val
blockBackward
=
Bool
()
// block backward
val
flushPipe
=
Bool
()
// This inst will flush all the pipe when commit, like exception but can commit
val
isRVF
=
Bool
()
val
selImm
=
SelImm
()
val
imm
=
UInt
(
ImmUnion
.
maxLen
.
W
)
...
...
@@ -241,9 +258,9 @@ class CtrlSignals extends XSBundle {
def
decode
(
inst
:
UInt
,
table
:
Iterable
[(
BitPat
,
List
[
BitPat
])])
=
{
val
decoder
=
freechips
.
rocketchip
.
rocket
.
DecodeLogic
(
inst
,
XDecode
.
decodeDefault
,
table
)
val
signals
=
Seq
(
src1Type
,
src2Type
,
src3Type
,
fuType
,
fuOpType
,
rfWen
,
fpWen
,
isXSTrap
,
noSpecExec
,
blockBackward
,
flushPipe
,
isRVF
,
selImm
)
signals
zip
decoder
map
{
case
(
s
,
d
)
=>
s
:=
d
}
Seq
(
src1Type
,
src2Type
,
src3Type
,
fuType
,
fuOpType
,
rfWen
,
fpWen
,
isXSTrap
,
noSpecExec
,
blockBackward
,
flushPipe
,
isRVF
,
selImm
)
signals
zip
decoder
map
{
case
(
s
,
d
)
=>
s
:=
d
}
commitType
:=
DontCare
this
}
...
...
@@ -252,7 +269,6 @@ class CtrlSignals extends XSBundle {
class
CfCtrl
extends
XSBundle
{
val
cf
=
new
CtrlFlow
val
ctrl
=
new
CtrlSignals
val
brTag
=
new
BrqPtr
}
class
PerfDebugInfo
extends
XSBundle
{
...
...
@@ -283,15 +299,16 @@ class MicroOp extends CfCtrl {
class
Redirect
extends
XSBundle
{
val
roqIdx
=
new
RoqPtr
val
ftqIdx
=
new
FtqPtr
val
ftqOffset
=
UInt
(
log2Up
(
PredictWidth
).
W
)
val
level
=
RedirectLevel
()
val
interrupt
=
Bool
()
val
pc
=
UInt
(
VAddrBits
.
W
)
val
target
=
UInt
(
VAddrBits
.
W
)
val
brTag
=
new
BrqPtr
val
cfiUpdate
=
new
CfiUpdateInfo
def
isUnconditional
()
=
RedirectLevel
.
isUnconditional
(
level
)
// def isUnconditional() = RedirectLevel.isUnconditional(level)
def
flushItself
()
=
RedirectLevel
.
flushItself
(
level
)
def
isException
()
=
RedirectLevel
.
isException
(
level
)
//
def isException() = RedirectLevel.isException(level)
}
class
Dp1ToDp2IO
extends
XSBundle
{
...
...
@@ -307,23 +324,22 @@ class ReplayPregReq extends XSBundle {
val
preg
=
UInt
(
PhyRegIdxWidth
.
W
)
}
class
DebugBundle
extends
XSBundle
{
class
DebugBundle
extends
XSBundle
{
val
isMMIO
=
Bool
()
val
isPerfCnt
=
Bool
()
}
class
ExuInput
extends
XSBundle
{
val
uop
=
new
MicroOp
val
src1
,
src2
,
src3
=
UInt
((
XLEN
+
1
).
W
)
val
src1
,
src2
,
src3
=
UInt
((
XLEN
+
1
).
W
)
}
class
ExuOutput
extends
XSBundle
{
val
uop
=
new
MicroOp
val
data
=
UInt
((
XLEN
+
1
).
W
)
val
fflags
=
UInt
(
5.
W
)
val
data
=
UInt
((
XLEN
+
1
).
W
)
val
fflags
=
UInt
(
5.
W
)
val
redirectValid
=
Bool
()
val
redirect
=
new
Redirect
val
brUpdate
=
new
CfiUpdateInfo
val
debug
=
new
DebugBundle
}
...
...
@@ -350,6 +366,8 @@ class RoqCommitInfo extends XSBundle {
val
commitType
=
CommitType
()
val
pdest
=
UInt
(
PhyRegIdxWidth
.
W
)
val
old_pdest
=
UInt
(
PhyRegIdxWidth
.
W
)
val
ftqIdx
=
new
FtqPtr
val
ftqOffset
=
UInt
(
log2Up
(
PredictWidth
).
W
)
// these should be optimized for synthesis verilog
val
pc
=
UInt
(
VAddrBits
.
W
)
...
...
@@ -361,6 +379,7 @@ class RoqCommitIO extends XSBundle {
val
info
=
Vec
(
CommitWidth
,
Output
(
new
RoqCommitInfo
))
def
hasWalkInstr
=
isWalk
&&
valid
.
asUInt
.
orR
def
hasCommitInstr
=
!
isWalk
&&
valid
.
asUInt
.
orR
}
...
...
@@ -372,17 +391,19 @@ class TlbFeedback extends XSBundle {
class
FrontendToBackendIO
extends
XSBundle
{
// to backend end
val
cfVec
=
Vec
(
DecodeWidth
,
DecoupledIO
(
new
CtrlFlow
))
val
fetchInfo
=
DecoupledIO
(
new
FtqEntry
)
// from backend
val
redirect
=
Flipped
(
ValidIO
(
UInt
(
VAddrBits
.
W
)))
// val cfiUpdateInfo = Flipped(ValidIO(new CfiUpdateInfo))
val
cfiUpdateInfo
=
Flipped
(
ValidIO
(
new
CfiUpdateInfo
))
val
redirect_cfiUpdate
=
Flipped
(
ValidIO
(
new
Redirect
))
val
commit_cfiUpdate
=
Flipped
(
ValidIO
(
new
FtqEntry
))
val
ftqEnqPtr
=
Input
(
new
FtqPtr
)
val
ftqLeftOne
=
Input
(
Bool
())
}
class
TlbCsrBundle
extends
XSBundle
{
val
satp
=
new
Bundle
{
val
mode
=
UInt
(
4.
W
)
// TODO: may change number to parameter
val
asid
=
UInt
(
16.
W
)
val
ppn
=
UInt
(
44.
W
)
// just use PAddrBits - 3 - vpnnLen
val
ppn
=
UInt
(
44.
W
)
// just use PAddrBits - 3 - vpnnLen
}
val
priv
=
new
Bundle
{
val
mxr
=
Bool
()
...
...
@@ -392,8 +413,8 @@ class TlbCsrBundle extends XSBundle {
}
override
def
toPrintable
:
Printable
=
{
p
"Satp mode:0x${Hexadecimal(satp.mode)} asid:0x${Hexadecimal(satp.asid)} ppn:0x${Hexadecimal(satp.ppn)} "
+
p
"Priv mxr:${priv.mxr} sum:${priv.sum} imode:${priv.imode} dmode:${priv.dmode}"
p
"Satp mode:0x${Hexadecimal(satp.mode)} asid:0x${Hexadecimal(satp.asid)} ppn:0x${Hexadecimal(satp.ppn)} "
+
p
"Priv mxr:${priv.mxr} sum:${priv.sum} imode:${priv.imode} dmode:${priv.dmode}"
}
}
...
...
src/main/scala/xiangshan/XSCore.scala
浏览文件 @
2c87aa6f
...
...
@@ -48,8 +48,10 @@ case class XSCoreParameters
EnableBPD
:
Boolean
=
true
,
EnableRAS
:
Boolean
=
true
,
EnableLB
:
Boolean
=
false
,
EnableLoop
:
Boolean
=
tru
e
,
EnableLoop
:
Boolean
=
fals
e
,
EnableSC
:
Boolean
=
false
,
EnableJal
:
Boolean
=
false
,
EnableUBTB
:
Boolean
=
true
,
HistoryLength
:
Int
=
64
,
BtbSize
:
Int
=
2048
,
JbtacSize
:
Int
=
1024
,
...
...
@@ -65,6 +67,7 @@ case class XSCoreParameters
RenameWidth
:
Int
=
6
,
CommitWidth
:
Int
=
6
,
BrqSize
:
Int
=
32
,
FtqSize
:
Int
=
48
,
IssQueSize
:
Int
=
12
,
NRPhyRegs
:
Int
=
160
,
NRIntReadPorts
:
Int
=
14
,
...
...
@@ -156,6 +159,7 @@ trait HasXSParameter {
val
RenameWidth
=
core
.
RenameWidth
val
CommitWidth
=
core
.
CommitWidth
val
BrqSize
=
core
.
BrqSize
val
FtqSize
=
core
.
FtqSize
val
IssQueSize
=
core
.
IssQueSize
val
BrTagWidth
=
log2Up
(
BrqSize
)
val
NRPhyRegs
=
core
.
NRPhyRegs
...
...
@@ -184,6 +188,9 @@ trait HasXSParameter {
val
NumPerfCounters
=
core
.
NumPerfCounters
val
NrExtIntr
=
core
.
NrExtIntr
val
instBytes
=
if
(
HasCExtension
)
2
else
4
val
instOffsetBits
=
log2Ceil
(
instBytes
)
val
icacheParameters
=
ICacheParameters
(
tagECC
=
Some
(
"parity"
),
dataECC
=
Some
(
"parity"
),
...
...
@@ -456,8 +463,8 @@ class XSCoreImp(outer: XSCore) extends LazyModuleImp(outer)
integerBlock
.
io
.
csrio
.
fflags
<>
ctrlBlock
.
io
.
roqio
.
toCSR
.
fflags
integerBlock
.
io
.
csrio
.
dirty_fs
<>
ctrlBlock
.
io
.
roqio
.
toCSR
.
dirty_fs
integerBlock
.
io
.
csrio
.
exception
<>
ctrlBlock
.
io
.
roqio
.
exception
integerBlock
.
io
.
csrio
.
isInterrupt
<>
ctrlBlock
.
io
.
roqio
.
isInterrupt
integerBlock
.
io
.
csrio
.
trapTarget
<>
ctrlBlock
.
io
.
roqio
.
toCSR
.
trapTarget
integerBlock
.
io
.
csrio
.
isXRet
<>
ctrlBlock
.
io
.
roqio
.
toCSR
.
isXRet
integerBlock
.
io
.
csrio
.
interrupt
<>
ctrlBlock
.
io
.
roqio
.
toCSR
.
intrBitSet
integerBlock
.
io
.
csrio
.
memExceptionVAddr
<>
memBlock
.
io
.
lsqio
.
exceptionAddr
.
vaddr
integerBlock
.
io
.
csrio
.
externalInterrupt
<>
io
.
externalInterrupt
...
...
@@ -469,9 +476,9 @@ class XSCoreImp(outer: XSCore) extends LazyModuleImp(outer)
floatBlock
.
io
.
frm
<>
integerBlock
.
io
.
csrio
.
frm
memBlock
.
io
.
lsqio
.
roq
<>
ctrlBlock
.
io
.
roqio
.
lsq
memBlock
.
io
.
lsqio
.
exceptionAddr
.
lsIdx
.
lqIdx
:=
ctrlBlock
.
io
.
roqio
.
exception
.
bits
.
lqIdx
memBlock
.
io
.
lsqio
.
exceptionAddr
.
lsIdx
.
sqIdx
:=
ctrlBlock
.
io
.
roqio
.
exception
.
bits
.
sqIdx
memBlock
.
io
.
lsqio
.
exceptionAddr
.
isStore
:=
CommitType
.
lsInstIsStore
(
ctrlBlock
.
io
.
roqio
.
exception
.
bits
.
ctrl
.
commitType
)
memBlock
.
io
.
lsqio
.
exceptionAddr
.
lsIdx
.
lqIdx
:=
ctrlBlock
.
io
.
roqio
.
exception
.
bits
.
uop
.
lqIdx
memBlock
.
io
.
lsqio
.
exceptionAddr
.
lsIdx
.
sqIdx
:=
ctrlBlock
.
io
.
roqio
.
exception
.
bits
.
uop
.
sqIdx
memBlock
.
io
.
lsqio
.
exceptionAddr
.
isStore
:=
CommitType
.
lsInstIsStore
(
ctrlBlock
.
io
.
roqio
.
exception
.
bits
.
uop
.
ctrl
.
commitType
)
ptw
.
io
.
tlb
(
0
)
<>
memBlock
.
io
.
ptw
ptw
.
io
.
tlb
(
1
)
<>
frontend
.
io
.
ptw
...
...
src/main/scala/xiangshan/backend/CtrlBlock.scala
浏览文件 @
2c87aa6f
...
...
@@ -4,23 +4,25 @@ import chisel3._
import
chisel3.util._
import
utils._
import
xiangshan._
import
xiangshan.backend.decode.
DecodeStage
import
xiangshan.backend.decode.
{
DecodeStage
,
ImmUnion
}
import
xiangshan.backend.rename.
{
BusyTable
,
Rename
}
import
xiangshan.backend.brq.
{
Brq
,
BrqPcRead
}
import
xiangshan.backend.dispatch.Dispatch
import
xiangshan.backend.exu._
import
xiangshan.backend.exu.Exu.exuConfigs
import
xiangshan.backend.ftq.
{
Ftq
,
FtqRead
,
GetPcByFtq
}
import
xiangshan.backend.regfile.RfReadPort
import
xiangshan.backend.roq.
{
Roq
,
RoqCSRIO
,
RoqLsqIO
,
RoqPtr
}
import
xiangshan.backend.roq.
{
Roq
,
RoqCSRIO
,
RoqLsqIO
,
RoqPtr
,
RoqExceptionInfo
}
import
xiangshan.mem.LsqEnqIO
class
CtrlToIntBlockIO
extends
XSBundle
{
val
enqIqCtrl
=
Vec
(
exuParameters
.
IntExuCnt
,
DecoupledIO
(
new
MicroOp
))
val
readRf
=
Vec
(
NRIntReadPorts
,
Output
(
UInt
(
PhyRegIdxWidth
.
W
)))
val
jumpPc
=
Output
(
UInt
(
VAddrBits
.
W
))
val
jalr_target
=
Output
(
UInt
(
VAddrBits
.
W
))
// int block only uses port 0~7
val
readPortIndex
=
Vec
(
exuParameters
.
IntExuCnt
,
Output
(
UInt
(
log2Ceil
(
8
/
2
).
W
)))
// TODO parameterize 8 here
val
redirect
=
ValidIO
(
new
Redirect
)
val
flush
=
Output
(
Bool
())
}
class
CtrlToFpBlockIO
extends
XSBundle
{
...
...
@@ -29,12 +31,134 @@ class CtrlToFpBlockIO extends XSBundle {
// fp block uses port 0~11
val
readPortIndex
=
Vec
(
exuParameters
.
FpExuCnt
,
Output
(
UInt
(
log2Ceil
((
NRFpReadPorts
-
exuParameters
.
StuCnt
)
/
3
).
W
)))
val
redirect
=
ValidIO
(
new
Redirect
)
val
flush
=
Output
(
Bool
())
}
class
CtrlToLsBlockIO
extends
XSBundle
{
val
enqIqCtrl
=
Vec
(
exuParameters
.
LsExuCnt
,
DecoupledIO
(
new
MicroOp
))
val
enqLsq
=
Flipped
(
new
LsqEnqIO
)
val
redirect
=
ValidIO
(
new
Redirect
)
val
flush
=
Output
(
Bool
())
}
class
RedirectGenerator
extends
XSModule
with
HasCircularQueuePtrHelper
{
val
io
=
IO
(
new
Bundle
()
{
val
loadRelay
=
Flipped
(
ValidIO
(
new
Redirect
))
val
exuMispredict
=
Vec
(
exuParameters
.
JmpCnt
+
exuParameters
.
AluCnt
,
Flipped
(
ValidIO
(
new
ExuOutput
)))
val
flush
=
Input
(
Bool
())
val
stage2FtqRead
=
new
FtqRead
val
stage2Redirect
=
ValidIO
(
new
Redirect
)
val
stage3Redirect
=
ValidIO
(
new
Redirect
)
})
/*
LoadQueue Jump ALU0 ALU1 ALU2 ALU3 exception Stage1
| | | | | | |
|============= reg & compare =====| | ========
| |
| |
| | Stage2
| |
redirect (flush backend) |
| |
=== reg === | ========
| |
|----- mux (exception first) -----| Stage3
|
redirect (send to frontend)
*/
def
selectOlderRedirect
(
x
:
Valid
[
Redirect
],
y
:
Valid
[
Redirect
])
:
Valid
[
Redirect
]
=
{
Mux
(
x
.
valid
,
Mux
(
y
.
valid
,
Mux
(
isAfter
(
x
.
bits
.
roqIdx
,
y
.
bits
.
roqIdx
),
y
,
x
),
x
),
y
)
}
def
selectOlderExuOutWithFlag
(
x
:
Valid
[
ExuOutput
],
y
:
Valid
[
ExuOutput
])
:
(
Valid
[
ExuOutput
],
Bool
)
=
{
val
yIsOlder
=
Mux
(
x
.
valid
,
Mux
(
y
.
valid
,
Mux
(
isAfter
(
x
.
bits
.
redirect
.
roqIdx
,
y
.
bits
.
redirect
.
roqIdx
),
true
.
B
,
false
.
B
),
false
.
B
),
true
.
B
)
val
sel
=
Mux
(
yIsOlder
,
y
,
x
)
(
sel
,
yIsOlder
)
}
def
selectOlderExuOut
(
x
:
Valid
[
ExuOutput
],
y
:
Valid
[
ExuOutput
])
:
Valid
[
ExuOutput
]
=
{
selectOlderExuOutWithFlag
(
x
,
y
).
_1
}
val
jumpOut
=
io
.
exuMispredict
.
head
val
oldestAluOut
=
ParallelOperation
(
io
.
exuMispredict
.
tail
,
selectOlderExuOut
)
val
(
oldestExuOut
,
jumpIsOlder
)
=
selectOlderExuOutWithFlag
(
oldestAluOut
,
jumpOut
)
// select between jump and alu
val
oldestMispredict
=
selectOlderRedirect
(
io
.
loadRelay
,
{
val
redirect
=
Wire
(
Valid
(
new
Redirect
))
redirect
.
valid
:=
oldestExuOut
.
valid
redirect
.
bits
:=
oldestExuOut
.
bits
.
redirect
redirect
})
XSDebug
(
oldestExuOut
.
valid
,
p
"exuMispredict: ${Binary(Cat(io.exuMispredict.map(_.valid)))}\n"
)
val
s1_isJump
=
RegNext
(
jumpIsOlder
,
init
=
false
.
B
)
val
s1_jumpTarget
=
RegEnable
(
jumpOut
.
bits
.
redirect
.
cfiUpdate
.
target
,
jumpOut
.
valid
)
val
s1_imm12_reg
=
RegEnable
(
oldestExuOut
.
bits
.
uop
.
ctrl
.
imm
(
11
,
0
),
oldestExuOut
.
valid
)
val
s1_pd
=
RegEnable
(
oldestExuOut
.
bits
.
uop
.
cf
.
pd
,
oldestExuOut
.
valid
)
val
s1_redirect_bits_reg
=
Reg
(
new
Redirect
)
val
s1_redirect_valid_reg
=
RegInit
(
false
.
B
)
// stage1 -> stage2
when
(
oldestMispredict
.
valid
&&
!
oldestMispredict
.
bits
.
roqIdx
.
needFlush
(
io
.
stage2Redirect
,
io
.
flush
)){
s1_redirect_bits_reg
:=
oldestMispredict
.
bits
s1_redirect_valid_reg
:=
true
.
B
}.
otherwise
({
s1_redirect_valid_reg
:=
false
.
B
})
io
.
stage2Redirect
.
valid
:=
s1_redirect_valid_reg
io
.
stage2Redirect
.
bits
:=
s1_redirect_bits_reg
io
.
stage2Redirect
.
bits
.
cfiUpdate
:=
DontCare
// at stage2, we read ftq to get pc
io
.
stage2FtqRead
.
ptr
:=
s1_redirect_bits_reg
.
ftqIdx
// stage3, calculate redirect target
val
s2_isJump
=
RegNext
(
s1_isJump
)
val
s2_jumpTarget
=
RegEnable
(
s1_jumpTarget
,
s1_redirect_valid_reg
)
val
s2_imm12_reg
=
RegEnable
(
s1_imm12_reg
,
s1_redirect_valid_reg
)
val
s2_pd
=
RegEnable
(
s1_pd
,
s1_redirect_valid_reg
)
val
s2_redirect_bits_reg
=
RegEnable
(
s1_redirect_bits_reg
,
enable
=
s1_redirect_valid_reg
)
val
s2_redirect_valid_reg
=
RegNext
(
s1_redirect_valid_reg
&&
!
io
.
flush
,
init
=
false
.
B
)
val
ftqRead
=
io
.
stage2FtqRead
.
entry
val
pc
=
GetPcByFtq
(
ftqRead
.
ftqPC
,
s2_redirect_bits_reg
.
ftqOffset
,
ftqRead
.
hasLastPrev
)
val
brTarget
=
pc
+
SignExt
(
ImmUnion
.
B
.
toImm32
(
s2_imm12_reg
),
XLEN
)
val
snpc
=
pc
+
Mux
(
s2_pd
.
isRVC
,
2.
U
,
4.
U
)
val
isReplay
=
RedirectLevel
.
flushItself
(
s2_redirect_bits_reg
.
level
)
val
target
=
Mux
(
isReplay
,
pc
,
// repaly from itself
Mux
(
s2_redirect_bits_reg
.
cfiUpdate
.
taken
,
Mux
(
s2_isJump
,
s2_jumpTarget
,
brTarget
),
snpc
)
)
io
.
stage3Redirect
.
valid
:=
s2_redirect_valid_reg
io
.
stage3Redirect
.
bits
:=
s2_redirect_bits_reg
val
stage3CfiUpdate
=
io
.
stage3Redirect
.
bits
.
cfiUpdate
stage3CfiUpdate
.
pc
:=
pc
stage3CfiUpdate
.
pd
:=
s2_pd
stage3CfiUpdate
.
rasSp
:=
ftqRead
.
rasSp
stage3CfiUpdate
.
rasEntry
:=
ftqRead
.
rasTop
stage3CfiUpdate
.
hist
:=
ftqRead
.
hist
stage3CfiUpdate
.
predHist
:=
ftqRead
.
predHist
stage3CfiUpdate
.
specCnt
:=
ftqRead
.
specCnt
(
s2_redirect_bits_reg
.
ftqOffset
)
stage3CfiUpdate
.
predTaken
:=
s2_redirect_bits_reg
.
cfiUpdate
.
predTaken
stage3CfiUpdate
.
sawNotTakenBranch
:=
VecInit
((
0
until
PredictWidth
).
map
{
i
=>
if
(
i
==
0
)
false
.
B
else
Cat
(
ftqRead
.
br_mask
.
take
(
i
)).
orR
()
})(
s2_redirect_bits_reg
.
ftqOffset
)
stage3CfiUpdate
.
target
:=
target
stage3CfiUpdate
.
taken
:=
s2_redirect_bits_reg
.
cfiUpdate
.
taken
stage3CfiUpdate
.
isMisPred
:=
s2_redirect_bits_reg
.
cfiUpdate
.
isMisPred
}
class
CtrlBlock
extends
XSModule
with
HasCircularQueuePtrHelper
{
...
...
@@ -49,8 +173,7 @@ class CtrlBlock extends XSModule with HasCircularQueuePtrHelper {
val
roqio
=
new
Bundle
{
// to int block
val
toCSR
=
new
RoqCSRIO
val
exception
=
ValidIO
(
new
MicroOp
)
val
isInterrupt
=
Output
(
Bool
())
val
exception
=
ValidIO
(
new
RoqExceptionInfo
)
// to mem block
val
lsq
=
new
RoqLsqIO
}
...
...
@@ -72,57 +195,92 @@ class CtrlBlock extends XSModule with HasCircularQueuePtrHelper {
})
difftestIO
<>
DontCare
val
ftq
=
Module
(
new
Ftq
)
val
trapIO
=
IO
(
new
TrapIO
())
trapIO
<>
DontCare
val
decode
=
Module
(
new
DecodeStage
)
val
brq
=
Module
(
new
Brq
)
val
rename
=
Module
(
new
Rename
)
val
dispatch
=
Module
(
new
Dispatch
)
val
intBusyTable
=
Module
(
new
BusyTable
(
NRIntReadPorts
,
NRIntWritePorts
))
val
fpBusyTable
=
Module
(
new
BusyTable
(
NRFpReadPorts
,
NRFpWritePorts
))
val
redirectGen
=
Module
(
new
RedirectGenerator
)
val
roqWbSize
=
NRIntWritePorts
+
NRFpWritePorts
+
exuParameters
.
StuCnt
+
1
val
roqWbSize
=
NRIntWritePorts
+
NRFpWritePorts
+
exuParameters
.
StuCnt
val
roq
=
Module
(
new
Roq
(
roqWbSize
))
// When replay and mis-prediction have the same roqIdx,
// mis-prediction should have higher priority, since mis-prediction flushes the load instruction.
// Thus, only when mis-prediction roqIdx is after replay roqIdx, replay should be valid.
val
brqIsAfterLsq
=
isAfter
(
brq
.
io
.
redirectOut
.
bits
.
roqIdx
,
io
.
fromLsBlock
.
replay
.
bits
.
roqIdx
)
val
redirectArb
=
Mux
(
io
.
fromLsBlock
.
replay
.
valid
&&
(!
brq
.
io
.
redirectOut
.
valid
||
brqIsAfterLsq
),
io
.
fromLsBlock
.
replay
.
bits
,
brq
.
io
.
redirectOut
.
bits
)
val
redirectValid
=
roq
.
io
.
redirectOut
.
valid
||
brq
.
io
.
redirectOut
.
valid
||
io
.
fromLsBlock
.
replay
.
valid
val
redirect
=
Mux
(
roq
.
io
.
redirectOut
.
valid
,
roq
.
io
.
redirectOut
.
bits
,
redirectArb
)
val
backendRedirect
=
redirectGen
.
io
.
stage2Redirect
val
frontendRedirect
=
redirectGen
.
io
.
stage3Redirect
val
flush
=
roq
.
io
.
flushOut
.
valid
io
.
frontend
.
redirect
.
valid
:=
RegNext
(
redirectValid
)
io
.
frontend
.
redirect
.
bits
:=
RegNext
(
Mux
(
roq
.
io
.
redirectOut
.
valid
,
roq
.
io
.
redirectOut
.
bits
.
target
,
redirectArb
.
target
))
io
.
frontend
.
cfiUpdateInfo
<>
brq
.
io
.
cfiInfo
redirectGen
.
io
.
exuMispredict
.
zip
(
io
.
fromIntBlock
.
exuRedirect
).
map
({
case
(
x
,
y
)
=>
x
.
valid
:=
y
.
valid
&&
y
.
bits
.
redirect
.
cfiUpdate
.
isMisPred
x
.
bits
:=
y
.
bits
})
redirectGen
.
io
.
loadRelay
:=
io
.
fromLsBlock
.
replay
redirectGen
.
io
.
flush
:=
flush
ftq
.
io
.
enq
<>
io
.
frontend
.
fetchInfo
for
(
i
<-
0
until
CommitWidth
){
ftq
.
io
.
roq_commits
(
i
).
valid
:=
roq
.
io
.
commits
.
valid
(
i
)
&&
!
roq
.
io
.
commits
.
isWalk
ftq
.
io
.
roq_commits
(
i
).
bits
:=
roq
.
io
.
commits
.
info
(
i
)
}
ftq
.
io
.
redirect
<>
backendRedirect
ftq
.
io
.
flush
:=
flush
ftq
.
io
.
flushIdx
:=
roq
.
io
.
flushOut
.
bits
.
ftqIdx
ftq
.
io
.
flushOffset
:=
roq
.
io
.
flushOut
.
bits
.
ftqOffset
ftq
.
io
.
frontendRedirect
<>
frontendRedirect
ftq
.
io
.
exuWriteback
<>
io
.
fromIntBlock
.
exuRedirect
ftq
.
io
.
ftqRead
(
1
)
<>
redirectGen
.
io
.
stage2FtqRead
ftq
.
io
.
ftqRead
(
2
).
ptr
:=
roq
.
io
.
flushOut
.
bits
.
ftqIdx
val
flushPC
=
GetPcByFtq
(
ftq
.
io
.
ftqRead
(
2
).
entry
.
ftqPC
,
RegEnable
(
roq
.
io
.
flushOut
.
bits
.
ftqOffset
,
roq
.
io
.
flushOut
.
valid
),
ftq
.
io
.
ftqRead
(
2
).
entry
.
hasLastPrev
)
val
flushRedirect
=
Wire
(
Valid
(
new
Redirect
))
flushRedirect
.
valid
:=
RegNext
(
flush
)
flushRedirect
.
bits
:=
DontCare
flushRedirect
.
bits
.
ftqIdx
:=
RegEnable
(
roq
.
io
.
flushOut
.
bits
.
ftqIdx
,
flush
)
flushRedirect
.
bits
.
interrupt
:=
true
.
B
flushRedirect
.
bits
.
cfiUpdate
.
target
:=
Mux
(
io
.
roqio
.
toCSR
.
isXRet
||
roq
.
io
.
exception
.
valid
,
io
.
roqio
.
toCSR
.
trapTarget
,
flushPC
+
4.
U
// flush pipe
)
io
.
frontend
.
redirect_cfiUpdate
:=
Mux
(
flushRedirect
.
valid
,
flushRedirect
,
frontendRedirect
)
io
.
frontend
.
commit_cfiUpdate
:=
ftq
.
io
.
commit_ftqEntry
io
.
frontend
.
ftqEnqPtr
:=
ftq
.
io
.
enqPtr
io
.
frontend
.
ftqLeftOne
:=
ftq
.
io
.
leftOne
decode
.
io
.
in
<>
io
.
frontend
.
cfVec
decode
.
io
.
enqBrq
<>
brq
.
io
.
enq
brq
.
io
.
redirect
.
valid
<>
redirectValid
brq
.
io
.
redirect
.
bits
<>
redirect
brq
.
io
.
bcommit
<>
roq
.
io
.
bcommit
brq
.
io
.
exuRedirectWb
<>
io
.
fromIntBlock
.
exuRedirect
brq
.
io
.
pcReadReq
.
brqIdx
:=
dispatch
.
io
.
enqIQCtrl
(
0
).
bits
.
brTag
// jump
io
.
toIntBlock
.
jumpPc
:=
brq
.
io
.
pcReadReq
.
pc
val
jumpInst
=
dispatch
.
io
.
enqIQCtrl
(
0
).
bits
val
ftqOffsetReg
=
Reg
(
UInt
(
log2Up
(
PredictWidth
).
W
))
ftqOffsetReg
:=
jumpInst
.
cf
.
ftqOffset
ftq
.
io
.
ftqRead
(
0
).
ptr
:=
jumpInst
.
cf
.
ftqPtr
// jump
io
.
toIntBlock
.
jumpPc
:=
GetPcByFtq
(
ftq
.
io
.
ftqRead
(
0
).
entry
.
ftqPC
,
ftqOffsetReg
,
ftq
.
io
.
ftqRead
(
0
).
entry
.
hasLastPrev
)
io
.
toIntBlock
.
jalr_target
:=
ftq
.
io
.
ftqRead
(
0
).
entry
.
target
// pipeline between decode and dispatch
val
lastCycleRedirect
=
RegNext
(
redirectValid
)
for
(
i
<-
0
until
RenameWidth
)
{
PipelineConnect
(
decode
.
io
.
out
(
i
),
rename
.
io
.
in
(
i
),
rename
.
io
.
in
(
i
).
ready
,
redirectValid
||
lastCycleRedirect
)
PipelineConnect
(
decode
.
io
.
out
(
i
),
rename
.
io
.
in
(
i
),
rename
.
io
.
in
(
i
).
ready
,
backendRedirect
.
valid
||
flush
||
io
.
frontend
.
redirect_cfiUpdate
.
valid
)
}
rename
.
io
.
redirect
.
valid
<>
redirectValid
rename
.
io
.
redirect
.
bits
<>
redirect
rename
.
io
.
redirect
<>
backendRedirect
rename
.
io
.
flush
:=
flush
rename
.
io
.
roqCommits
<>
roq
.
io
.
commits
rename
.
io
.
out
<>
dispatch
.
io
.
fromRename
rename
.
io
.
renameBypass
<>
dispatch
.
io
.
renameBypass
dispatch
.
io
.
redirect
.
valid
<>
redirectValid
dispatch
.
io
.
redirect
.
bits
<>
redirect
dispatch
.
io
.
redirect
<>
backendRedirect
dispatch
.
io
.
flush
:=
flush
dispatch
.
io
.
enqRoq
<>
roq
.
io
.
enq
dispatch
.
io
.
enqLsq
<>
io
.
toLsBlock
.
enqLsq
dispatch
.
io
.
readIntRf
<>
io
.
toIntBlock
.
readRf
...
...
@@ -138,7 +296,6 @@ class CtrlBlock extends XSModule with HasCircularQueuePtrHelper {
// dispatch.io.enqIQData <> io.toIntBlock.enqIqData ++ io.toFpBlock.enqIqData ++ io.toLsBlock.enqIqData
val
flush
=
redirectValid
&&
RedirectLevel
.
isUnconditional
(
redirect
.
level
)
fpBusyTable
.
io
.
flush
:=
flush
intBusyTable
.
io
.
flush
:=
flush
for
((
wb
,
setPhyRegRdy
)
<-
io
.
fromIntBlock
.
wbRegs
.
zip
(
intBusyTable
.
io
.
wbPregs
)){
...
...
@@ -152,37 +309,35 @@ class CtrlBlock extends XSModule with HasCircularQueuePtrHelper {
intBusyTable
.
io
.
read
<>
dispatch
.
io
.
readIntState
fpBusyTable
.
io
.
read
<>
dispatch
.
io
.
readFpState
roq
.
io
.
redirect
.
valid
:=
brq
.
io
.
redirectOut
.
valid
||
io
.
fromLsBlock
.
replay
.
valid
roq
.
io
.
redirect
.
bits
<>
redirectArb
roq
.
io
.
exeWbResults
.
take
(
roqWbSize
-
1
).
zip
(
roq
.
io
.
redirect
<>
backendRedirect
roq
.
io
.
exeWbResults
.
zip
(
io
.
fromIntBlock
.
wbRegs
++
io
.
fromFpBlock
.
wbRegs
++
io
.
fromLsBlock
.
stOut
).
foreach
{
case
(
x
,
y
)
=>
x
.
bits
:=
y
.
bits
x
.
valid
:=
y
.
valid
&&
!
y
.
bits
.
redirectValid
x
.
valid
:=
y
.
valid
}
roq
.
io
.
exeWbResults
.
last
:=
brq
.
io
.
out
// TODO: is 'backendRedirect' necesscary?
io
.
toIntBlock
.
redirect
<>
backendRedirect
io
.
toIntBlock
.
flush
<>
flush
io
.
toFpBlock
.
redirect
<>
backendRedirect
io
.
toFpBlock
.
flush
<>
flush
io
.
toLsBlock
.
redirect
<>
backendRedirect
io
.
toLsBlock
.
flush
<>
flush
if
(
env
.
DualCoreDifftest
)
{
difftestIO
.
fromRoq
<>
roq
.
difftestIO
trapIO
<>
roq
.
trapIO
}
io
.
toIntBlock
.
redirect
.
valid
:=
redirectValid
io
.
toIntBlock
.
redirect
.
bits
:=
redirect
io
.
toFpBlock
.
redirect
.
valid
:=
redirectValid
io
.
toFpBlock
.
redirect
.
bits
:=
redirect
io
.
toLsBlock
.
redirect
.
valid
:=
redirectValid
io
.
toLsBlock
.
redirect
.
bits
:=
redirect
dispatch
.
io
.
readPortIndex
.
intIndex
<>
io
.
toIntBlock
.
readPortIndex
dispatch
.
io
.
readPortIndex
.
fpIndex
<>
io
.
toFpBlock
.
readPortIndex
// roq to int block
io
.
roqio
.
toCSR
<>
roq
.
io
.
csr
io
.
roqio
.
exception
.
valid
:=
roq
.
io
.
redirectOut
.
valid
&&
roq
.
io
.
redirectOut
.
bits
.
isException
()
io
.
roqio
.
exception
.
bits
:=
roq
.
io
.
exception
io
.
roqio
.
isInterrupt
:=
roq
.
io
.
redirectOut
.
bits
.
interrupt
io
.
roqio
.
exception
:=
roq
.
io
.
exception
io
.
roqio
.
exception
.
bits
.
uop
.
cf
.
pc
:=
flushPC
// roq to mem block
io
.
roqio
.
lsq
<>
roq
.
io
.
lsq
}
src/main/scala/xiangshan/backend/FloatBlock.scala
浏览文件 @
2c87aa6f
...
...
@@ -37,6 +37,7 @@ class FloatBlock
})
val
redirect
=
io
.
fromCtrlBlock
.
redirect
val
flush
=
io
.
fromCtrlBlock
.
flush
val
fpRf
=
Module
(
new
Regfile
(
numReadPorts
=
NRFpReadPorts
,
...
...
@@ -86,6 +87,7 @@ class FloatBlock
rsCtrl
.
io
.
data
<>
rsData
.
io
.
ctrl
rsCtrl
.
io
.
redirect
<>
redirect
// TODO: remove it
rsCtrl
.
io
.
flush
<>
flush
// TODO: remove it
rsCtrl
.
io
.
numExist
<>
io
.
toCtrlBlock
.
numExist
(
i
)
rsCtrl
.
io
.
enqCtrl
<>
io
.
fromCtrlBlock
.
enqIqCtrl
(
i
)
...
...
@@ -98,6 +100,7 @@ class FloatBlock
rsData
.
io
.
srcRegValue
(
1
)
:=
src2Value
(
readPortIndex
(
i
))
if
(
cfg
.
fpSrcCnt
>
2
)
rsData
.
io
.
srcRegValue
(
2
)
:=
src3Value
(
readPortIndex
(
i
))
rsData
.
io
.
redirect
<>
redirect
rsData
.
io
.
flush
<>
flush
rsData
.
io
.
writeBackedData
<>
writeBackData
for
((
x
,
y
)
<-
rsData
.
io
.
extraListenPorts
.
zip
(
extraListenPorts
))
{
...
...
@@ -106,6 +109,7 @@ class FloatBlock
}
exeUnits
(
i
).
io
.
redirect
<>
redirect
exeUnits
(
i
).
io
.
flush
<>
flush
exeUnits
(
i
).
io
.
fromFp
<>
rsData
.
io
.
deq
rsData
.
io
.
feedback
:=
DontCare
...
...
src/main/scala/xiangshan/backend/IntegerBlock.scala
浏览文件 @
2c87aa6f
...
...
@@ -8,6 +8,7 @@ import xiangshan.backend.exu._
import
xiangshan.backend.fu.FenceToSbuffer
import
xiangshan.backend.issue.
{
ReservationStationCtrl
,
ReservationStationData
}
import
xiangshan.backend.regfile.Regfile
import
xiangshan.backend.roq.RoqExceptionInfo
class
WakeUpBundle
(
numFast
:
Int
,
numSlow
:
Int
)
extends
XSBundle
{
val
fastUops
=
Vec
(
numFast
,
Flipped
(
ValidIO
(
new
MicroOp
)))
...
...
@@ -75,9 +76,9 @@ class IntegerBlock
val
fflags
=
Flipped
(
Valid
(
UInt
(
5.
W
)))
// from roq
val
dirty_fs
=
Input
(
Bool
())
// from roq
val
frm
=
Output
(
UInt
(
3.
W
))
// to float
val
exception
=
Flipped
(
ValidIO
(
new
MicroOp
))
// from roq
val
isInterrupt
=
Input
(
Bool
())
// from roq
val
exception
=
Flipped
(
ValidIO
(
new
RoqExceptionInfo
))
val
trapTarget
=
Output
(
UInt
(
VAddrBits
.
W
))
// to roq
val
isXRet
=
Output
(
Bool
())
val
interrupt
=
Output
(
Bool
())
// to roq
val
memExceptionVAddr
=
Input
(
UInt
(
VAddrBits
.
W
))
// from lsq
val
externalInterrupt
=
new
ExternalInterruptIO
// from outside
...
...
@@ -119,6 +120,7 @@ class IntegerBlock
difftestIO
<>
DontCare
val
redirect
=
io
.
fromCtrlBlock
.
redirect
val
flush
=
io
.
fromCtrlBlock
.
flush
val
intRf
=
Module
(
new
Regfile
(
numReadPorts
=
NRIntReadPorts
,
...
...
@@ -168,6 +170,7 @@ class IntegerBlock
rsCtrl
.
io
.
data
<>
rsData
.
io
.
ctrl
rsCtrl
.
io
.
redirect
<>
redirect
// TODO: remove it
rsCtrl
.
io
.
flush
<>
flush
// TODO: remove it
rsCtrl
.
io
.
numExist
<>
io
.
toCtrlBlock
.
numExist
(
i
)
rsCtrl
.
io
.
enqCtrl
<>
io
.
fromCtrlBlock
.
enqIqCtrl
(
i
)
...
...
@@ -176,8 +179,12 @@ class IntegerBlock
val
src2Value
=
VecInit
((
0
until
4
).
map
(
i
=>
intRf
.
io
.
readPorts
(
i
*
2
+
1
).
data
))
rsData
.
io
.
srcRegValue
(
0
)
:=
src1Value
(
readPortIndex
(
i
))
if
(
cfg
.
intSrcCnt
>
1
)
rsData
.
io
.
srcRegValue
(
1
)
:=
src2Value
(
readPortIndex
(
i
))
if
(
cfg
==
Exu
.
jumpExeUnitCfg
)
rsData
.
io
.
jumpPc
:=
io
.
fromCtrlBlock
.
jumpPc
if
(
cfg
==
Exu
.
jumpExeUnitCfg
)
{
rsData
.
io
.
jumpPc
:=
io
.
fromCtrlBlock
.
jumpPc
rsData
.
io
.
jalr_target
:=
io
.
fromCtrlBlock
.
jalr_target
}
rsData
.
io
.
redirect
<>
redirect
rsData
.
io
.
flush
<>
flush
rsData
.
io
.
writeBackedData
<>
writeBackData
for
((
x
,
y
)
<-
rsData
.
io
.
extraListenPorts
.
zip
(
extraListenPorts
))
{
...
...
@@ -186,6 +193,7 @@ class IntegerBlock
}
exeUnits
(
i
).
io
.
redirect
<>
redirect
exeUnits
(
i
).
io
.
flush
<>
flush
exeUnits
(
i
).
io
.
fromInt
<>
rsData
.
io
.
deq
rsData
.
io
.
feedback
:=
DontCare
...
...
src/main/scala/xiangshan/backend/MemBlock.scala
浏览文件 @
2c87aa6f
...
...
@@ -155,6 +155,7 @@ class MemBlockImp
rsCtrl
.
io
.
data
<>
rsData
.
io
.
ctrl
rsCtrl
.
io
.
redirect
<>
redirect
// TODO: remove it
rsCtrl
.
io
.
flush
<>
io
.
fromCtrlBlock
.
flush
// TODO: remove it
rsCtrl
.
io
.
numExist
<>
io
.
toCtrlBlock
.
numExist
(
i
)
rsCtrl
.
io
.
enqCtrl
<>
io
.
fromCtrlBlock
.
enqIqCtrl
(
i
)
...
...
@@ -165,6 +166,7 @@ class MemBlockImp
rsData
.
io
.
srcRegValue
(
1
)
:=
Mux
(
src2IsFp
,
io
.
fromFpBlock
.
readFpRf
(
i
-
exuParameters
.
LduCnt
).
data
,
io
.
fromIntBlock
.
readIntRf
(
readPortIndex
(
i
)
+
1
).
data
)
}
rsData
.
io
.
redirect
<>
redirect
rsData
.
io
.
flush
<>
io
.
fromCtrlBlock
.
flush
rsData
.
io
.
writeBackedData
<>
writeBackData
for
((
x
,
y
)
<-
rsData
.
io
.
extraListenPorts
.
zip
(
extraListenPorts
))
{
...
...
@@ -217,6 +219,7 @@ class MemBlockImp
// LoadUnit
for
(
i
<-
0
until
exuParameters
.
LduCnt
)
{
loadUnits
(
i
).
io
.
redirect
<>
io
.
fromCtrlBlock
.
redirect
loadUnits
(
i
).
io
.
flush
<>
io
.
fromCtrlBlock
.
flush
loadUnits
(
i
).
io
.
tlbFeedback
<>
reservationStations
(
i
).
io
.
feedback
loadUnits
(
i
).
io
.
dtlb
<>
dtlb
.
io
.
requestor
(
i
)
// get input form dispatch
...
...
@@ -240,6 +243,7 @@ class MemBlockImp
val
dtlbReq
=
dtlb
.
io
.
requestor
(
exuParameters
.
LduCnt
+
i
)
stu
.
io
.
redirect
<>
io
.
fromCtrlBlock
.
redirect
stu
.
io
.
flush
<>
io
.
fromCtrlBlock
.
flush
stu
.
io
.
tlbFeedback
<>
rs
.
io
.
feedback
stu
.
io
.
dtlb
<>
dtlbReq
stu
.
io
.
stin
<>
rs
.
io
.
deq
...
...
@@ -262,6 +266,7 @@ class MemBlockImp
lsq
.
io
.
roq
<>
io
.
lsqio
.
roq
lsq
.
io
.
enq
<>
io
.
fromCtrlBlock
.
enqLsq
lsq
.
io
.
brqRedirect
<>
io
.
fromCtrlBlock
.
redirect
lsq
.
io
.
flush
<>
io
.
fromCtrlBlock
.
flush
io
.
toCtrlBlock
.
replay
<>
lsq
.
io
.
rollback
lsq
.
io
.
dcache
<>
dcache
.
io
.
lsu
.
lsq
lsq
.
io
.
uncache
<>
uncache
.
io
.
lsq
...
...
@@ -314,6 +319,7 @@ class MemBlockImp
atomicsUnit
.
io
.
in
.
valid
:=
st0_atomics
||
st1_atomics
atomicsUnit
.
io
.
in
.
bits
:=
Mux
(
st0_atomics
,
reservationStations
(
atomic_rs0
).
io
.
deq
.
bits
,
reservationStations
(
atomic_rs1
).
io
.
deq
.
bits
)
atomicsUnit
.
io
.
redirect
<>
io
.
fromCtrlBlock
.
redirect
atomicsUnit
.
io
.
flush
<>
io
.
fromCtrlBlock
.
flush
atomicsUnit
.
io
.
dtlb
.
resp
.
valid
:=
false
.
B
atomicsUnit
.
io
.
dtlb
.
resp
.
bits
:=
DontCare
...
...
src/main/scala/xiangshan/backend/brq/Brq.scala
已删除
100644 → 0
浏览文件 @
d3851157
package
xiangshan.backend.brq
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
utils._
import
chisel3.ExcitingUtils._
import
xiangshan.backend.JumpOpType
import
xiangshan.backend.decode.ImmUnion
class
BrqPtr
extends
CircularQueuePtr
(
BrqPtr
.
BrqSize
)
with
HasCircularQueuePtrHelper
{
// this.age < that.age
final
def
<
(
that
:
BrqPtr
)
:
Bool
=
{
Mux
(
this
.
flag
===
that
.
flag
,
this
.
value
>
that
.
value
,
this
.
value
<
that
.
value
)
}
def
needBrFlush
(
redirect
:
Valid
[
Redirect
])
:
Bool
=
{
isAfter
(
this
,
redirect
.
bits
.
brTag
)
||
(
redirect
.
bits
.
flushItself
()
&&
redirect
.
bits
.
brTag
===
this
)
}
def
needFlush
(
redirect
:
Valid
[
Redirect
])
:
Bool
=
{
redirect
.
bits
.
isUnconditional
()
||
needBrFlush
(
redirect
)
}
override
def
toPrintable
:
Printable
=
p
"f:$flag v:$value"
}
object
BrqPtr
extends
HasXSParameter
{
def
apply
(
f
:
Bool
,
v
:
UInt
)
:
BrqPtr
=
{
val
ptr
=
Wire
(
new
BrqPtr
)
ptr
.
flag
:=
f
ptr
.
value
:=
v
ptr
}
}
class
BrqEnqIO
extends
XSBundle
{
val
needAlloc
=
Vec
(
RenameWidth
,
Input
(
Bool
()))
val
req
=
Vec
(
RenameWidth
,
Flipped
(
DecoupledIO
(
new
CtrlFlow
)))
val
resp
=
Vec
(
RenameWidth
,
Output
(
new
BrqPtr
))
}
class
BrqPcRead
extends
XSBundle
{
val
brqIdx
=
Input
(
new
BrqPtr
)
val
pc
=
Output
(
UInt
(
VAddrBits
.
W
))
}
class
BrqIO
extends
XSBundle
{
val
redirect
=
Input
(
ValidIO
(
new
Redirect
))
// receive branch/jump calculated target
val
exuRedirectWb
=
Vec
(
exuParameters
.
AluCnt
+
exuParameters
.
JmpCnt
,
Flipped
(
ValidIO
(
new
ExuOutput
)))
// from decode, branch insts enq
val
enq
=
new
BrqEnqIO
// to roq
val
out
=
ValidIO
(
new
ExuOutput
)
// misprediction, flush pipeline
val
redirectOut
=
Output
(
Valid
(
new
Redirect
))
val
cfiInfo
=
ValidIO
(
new
CfiUpdateInfo
)
// commit cnt of branch instr
val
bcommit
=
Input
(
UInt
(
BrTagWidth
.
W
))
// read pc for jump unit
val
pcReadReq
=
new
BrqPcRead
}
class
Brq
extends
XSModule
with
HasCircularQueuePtrHelper
{
val
io
=
IO
(
new
BrqIO
)
class
BrqEntry
extends
Bundle
{
val
ptrFlag
=
Bool
()
val
exuOut
=
new
ExuOutput
}
val
s_idle
::
s_wb
::
s_auipc_wb
::
Nil
=
Enum
(
3
)
class
DecodeEnqBrqData
extends
Bundle
{
val
cfiUpdateInfo
=
new
CfiUpdateInfo
// we use this to calculate branch target
val
imm12
=
UInt
(
12.
W
)
}
// data and state
val
decodeData
=
Module
(
new
SyncDataModuleTemplate
(
new
DecodeEnqBrqData
,
BrqSize
,
3
,
DecodeWidth
))
val
writebackData
=
Module
(
new
SyncDataModuleTemplate
(
new
ExuOutput
,
BrqSize
,
2
,
exuParameters
.
AluCnt
+
exuParameters
.
JmpCnt
))
val
ptrFlagVec
=
Reg
(
Vec
(
BrqSize
,
Bool
()))
val
stateQueue
=
RegInit
(
VecInit
(
Seq
.
fill
(
BrqSize
)(
s_idle
)))
// queue pointers
val
headPtr
,
tailPtr
=
RegInit
(
BrqPtr
(
false
.
B
,
0.
U
))
val
writebackPtr
=
RegInit
(
BrqPtr
(
false
.
B
,
0.
U
))
val
writebackPtr_next
=
WireInit
(
writebackPtr
)
writebackPtr
:=
writebackPtr_next
val
headIdx
=
headPtr
.
value
val
writebackIdx
=
writebackPtr
.
value
/**
* commit (dequeue): after ROB commits branch instructions, move headPtr forward
*/
headPtr
:=
headPtr
+
io
.
bcommit
/**
* write back
*/
val
wbState
=
stateQueue
(
writebackIdx
)
val
wbValid
=
wbState
===
s_wb
val
wbIsAuipc
=
wbState
===
s_auipc_wb
val
wbEntry
=
Wire
(
new
ExuOutput
)
val
wbIsMisPred
=
wbEntry
.
redirect
.
target
=/=
wbEntry
.
brUpdate
.
pnpc
io
.
redirectOut
.
valid
:=
wbValid
&&
wbIsMisPred
io
.
redirectOut
.
bits
:=
wbEntry
.
redirect
io
.
redirectOut
.
bits
.
level
:=
RedirectLevel
.
flushAfter
io
.
redirectOut
.
bits
.
brTag
:=
BrqPtr
(
ptrFlagVec
(
writebackIdx
),
writebackIdx
)
io
.
out
.
valid
:=
wbValid
||
wbIsAuipc
io
.
out
.
bits
:=
wbEntry
when
(
io
.
out
.
valid
)
{
stateQueue
(
writebackIdx
)
:=
s_idle
writebackPtr_next
:=
writebackPtr
+
1.
U
}
val
brUpdateReadIdx
=
Mux
(
io
.
redirect
.
bits
.
flushItself
(),
io
.
redirect
.
bits
.
brTag
-
1.
U
,
io
.
redirect
.
bits
.
brTag
)
val
brUpdateReadEntry
=
Wire
(
new
CfiUpdateInfo
)
io
.
cfiInfo
.
valid
:=
RegNext
(
io
.
redirect
.
valid
||
wbValid
)
io
.
cfiInfo
.
bits
:=
brUpdateReadEntry
io
.
cfiInfo
.
bits
.
target
:=
RegNext
(
Mux
(
io
.
redirect
.
bits
.
flushItself
(),
io
.
redirect
.
bits
.
target
,
wbEntry
.
brUpdate
.
target
))
io
.
cfiInfo
.
bits
.
brTarget
:=
io
.
cfiInfo
.
bits
.
target
io
.
cfiInfo
.
bits
.
brTag
:=
RegNext
(
brUpdateReadIdx
)
io
.
cfiInfo
.
bits
.
isReplay
:=
RegNext
(
io
.
redirect
.
bits
.
flushItself
())
io
.
cfiInfo
.
bits
.
isMisPred
:=
RegNext
(
wbIsMisPred
)
XSInfo
(
io
.
out
.
valid
,
p
"commit branch to roq, mispred:${io.redirectOut.valid} pc=${Hexadecimal(io.out.bits.uop.cf.pc)}\n"
)
/**
* branch insts enq
*/
// note that redirect sent to IFU is delayed for one clock cycle
// thus, brq should not allow enqueue in the next cycle after redirect
val
lastCycleRedirect
=
RegNext
(
io
.
redirect
.
valid
)
val
validEntries
=
distanceBetween
(
tailPtr
,
headPtr
)
val
enqBrTag
=
VecInit
((
0
until
DecodeWidth
).
map
(
i
=>
tailPtr
+
PopCount
(
io
.
enq
.
needAlloc
.
take
(
i
))))
io
.
enq
.
resp
:=
enqBrTag
for
(
i
<-
0
until
DecodeWidth
)
{
val
idx
=
enqBrTag
(
i
).
value
io
.
enq
.
req
(
i
).
ready
:=
validEntries
<=
(
BrqSize
-
(
i
+
1
)).
U
&&
!
lastCycleRedirect
when
(
io
.
enq
.
req
(
i
).
fire
())
{
ptrFlagVec
(
idx
)
:=
enqBrTag
(
i
).
flag
stateQueue
(
idx
)
:=
s_idle
}
}
val
enqCnt
=
PopCount
(
io
.
enq
.
req
.
map
(
_
.
fire
()))
tailPtr
:=
tailPtr
+
enqCnt
/**
* exu write back
*/
for
((
exuWb
,
i
)
<-
io
.
exuRedirectWb
.
zipWithIndex
)
{
when
(
exuWb
.
valid
)
{
val
wbIdx
=
exuWb
.
bits
.
redirect
.
brTag
.
value
XSInfo
(
p
"exu write back: brTag:${exuWb.bits.redirect.brTag}"
+
p
" pc=${Hexadecimal(exuWb.bits.uop.cf.pc)} "
+
// p"pnpc=${Hexadecimal(brQueue(wbIdx).exuOut.brUpdate.pnpc)} " +
p
"target=${Hexadecimal(exuWb.bits.redirect.target)}\n"
)
assert
(
stateQueue
(
wbIdx
)
===
s_idle
)
if
(
i
==
0
){
// jump
stateQueue
(
wbIdx
)
:=
Mux
(
JumpOpType
.
jumpOpisAuipc
(
exuWb
.
bits
.
uop
.
ctrl
.
fuOpType
),
s_auipc_wb
,
s_wb
)
}
else
{
// alu
stateQueue
(
wbIdx
)
:=
s_wb
}
}
}
// when redirect is valid, we need to update the states and pointers
when
(
io
.
redirect
.
valid
)
{
// For unconditional redirect, flush all entries
when
(
io
.
redirect
.
bits
.
isUnconditional
())
{
stateQueue
.
foreach
(
_
:=
s_idle
)
headPtr
:=
BrqPtr
(
false
.
B
,
0.
U
)
tailPtr
:=
BrqPtr
(
false
.
B
,
0.
U
)
writebackPtr_next
:=
BrqPtr
(
false
.
B
,
0.
U
)
}.
otherwise
{
// conditional check: branch mis-prediction and memory dependence violation
stateQueue
.
zipWithIndex
.
foreach
({
case
(
s
,
i
)
=>
val
ptr
=
BrqPtr
(
ptrFlagVec
(
i
),
i
.
U
)
when
(
ptr
.
needBrFlush
(
io
.
redirect
))
{
s
:=
s_idle
}
})
tailPtr
:=
io
.
redirect
.
bits
.
brTag
+
Mux
(
io
.
redirect
.
bits
.
flushItself
(),
0.
U
,
1.
U
)
when
(
io
.
redirect
.
bits
.
flushItself
()
&&
writebackPtr
.
needBrFlush
(
io
.
redirect
))
{
writebackPtr_next
:=
io
.
redirect
.
bits
.
brTag
}
}
}
def
mergeWbEntry
(
dec
:
DecodeEnqBrqData
,
wb
:
ExuOutput
)
:
ExuOutput
=
{
val
mergeData
=
Wire
(
new
ExuOutput
)
// only writeback necessary information
mergeData
.
uop
:=
wb
.
uop
mergeData
.
data
:=
wb
.
data
mergeData
.
fflags
:=
wb
.
fflags
mergeData
.
redirectValid
:=
wb
.
redirectValid
// calculate target pc
val
pc
=
dec
.
cfiUpdateInfo
.
pc
val
offset
=
SignExt
(
ImmUnion
.
B
.
toImm32
(
dec
.
imm12
),
VAddrBits
)
val
snpc
=
pc
+
Mux
(
dec
.
cfiUpdateInfo
.
pd
.
isRVC
,
2.
U
,
4.
U
)
val
bnpc
=
pc
+
offset
val
branch_pc
=
Mux
(
wb
.
brUpdate
.
taken
,
bnpc
,
snpc
)
val
redirectTarget
=
Mux
(
dec
.
cfiUpdateInfo
.
pd
.
isBr
,
branch_pc
,
wb
.
redirect
.
target
)
mergeData
.
redirect
:=
wb
.
redirect
mergeData
.
redirect
.
target
:=
redirectTarget
mergeData
.
debug
:=
wb
.
debug
mergeData
.
brUpdate
:=
dec
.
cfiUpdateInfo
mergeData
.
brUpdate
.
target
:=
redirectTarget
mergeData
.
brUpdate
.
brTarget
:=
redirectTarget
mergeData
.
brUpdate
.
taken
:=
wb
.
brUpdate
.
taken
mergeData
.
brUpdate
.
bpuMeta
.
predictor
:=
wb
.
brUpdate
.
bpuMeta
.
predictor
mergeData
}
def
mergeBrUpdateEntry
(
dec
:
DecodeEnqBrqData
,
wb
:
ExuOutput
)
:
CfiUpdateInfo
=
{
val
mergeData
=
WireInit
(
dec
.
cfiUpdateInfo
)
mergeData
.
taken
:=
wb
.
brUpdate
.
taken
mergeData
}
decodeData
.
io
.
raddr
(
0
)
:=
writebackPtr_next
.
value
decodeData
.
io
.
raddr
(
1
)
:=
brUpdateReadIdx
.
value
decodeData
.
io
.
raddr
(
2
)
:=
io
.
pcReadReq
.
brqIdx
.
value
decodeData
.
io
.
wen
:=
VecInit
(
io
.
enq
.
req
.
map
(
_
.
fire
()))
decodeData
.
io
.
waddr
:=
VecInit
(
enqBrTag
.
map
(
_
.
value
))
decodeData
.
io
.
wdata
.
zip
(
io
.
enq
.
req
).
foreach
{
case
(
wdata
,
req
)
=>
wdata
.
cfiUpdateInfo
:=
req
.
bits
.
brUpdate
wdata
.
cfiUpdateInfo
.
pc
:=
req
.
bits
.
pc
wdata
.
imm12
:=
ImmUnion
.
B
.
minBitsFromInstr
(
req
.
bits
.
instr
)
}
writebackData
.
io
.
raddr
(
0
)
:=
writebackPtr_next
.
value
writebackData
.
io
.
raddr
(
1
)
:=
brUpdateReadIdx
.
value
writebackData
.
io
.
wen
:=
VecInit
(
io
.
exuRedirectWb
.
map
(
_
.
valid
))
writebackData
.
io
.
waddr
:=
VecInit
(
io
.
exuRedirectWb
.
map
(
_
.
bits
.
redirect
.
brTag
.
value
))
writebackData
.
io
.
wdata
:=
VecInit
(
io
.
exuRedirectWb
.
map
(
_
.
bits
))
wbEntry
:=
mergeWbEntry
(
decodeData
.
io
.
rdata
(
0
),
writebackData
.
io
.
rdata
(
0
))
brUpdateReadEntry
:=
mergeBrUpdateEntry
(
decodeData
.
io
.
rdata
(
1
),
writebackData
.
io
.
rdata
(
1
))
io
.
pcReadReq
.
pc
:=
decodeData
.
io
.
rdata
(
2
).
cfiUpdateInfo
.
pc
// Debug info
val
debug_roq_redirect
=
io
.
redirect
.
valid
&&
io
.
redirect
.
bits
.
isUnconditional
()
val
debug_brq_redirect
=
io
.
redirectOut
.
valid
val
debug_normal_mode
=
!(
debug_roq_redirect
||
debug_brq_redirect
)
for
(
i
<-
0
until
DecodeWidth
){
XSDebug
(
debug_normal_mode
,
p
"enq v:${io.enq.req(i).valid} rdy:${io.enq.req(i).ready} pc:${Hexadecimal(io.enq.req(i).bits.pc)}"
+
p
" brTag:${io.enq.resp(i)}\n"
)
}
XSInfo
(
debug_roq_redirect
,
"roq redirect, flush brq\n"
)
XSInfo
(
debug_brq_redirect
,
p
"brq redirect, target:${Hexadecimal(io.redirectOut.bits.target)}\n"
)
XSDebug
(
io
.
cfiInfo
.
valid
,
"inOrderValid: pc=%x\n"
,
io
.
cfiInfo
.
bits
.
pc
)
XSDebug
(
p
"headIdx:$headIdx writebackIdx:$writebackIdx\n"
)
XSDebug
(
p
"headPtr:$headPtr tailPtr:$tailPtr\n"
)
XSDebug
(
""
)
stateQueue
.
reverse
.
map
(
s
=>{
XSDebug
(
false
,
s
===
s_idle
,
"-"
)
XSDebug
(
false
,
s
===
s_wb
,
"w"
)
})
XSDebug
(
false
,
true
.
B
,
"\n"
)
val
fire
=
io
.
out
.
fire
()
val
predRight
=
fire
&&
!
wbIsMisPred
val
predWrong
=
fire
&&
wbIsMisPred
// val isBType = wbEntry.brUpdate.btbType===BTBtype.B
val
isBType
=
wbEntry
.
brUpdate
.
pd
.
isBr
// val isJType = wbEntry.brUpdate.btbType===BTBtype.J
val
isJType
=
wbEntry
.
brUpdate
.
pd
.
isJal
// val isIType = wbEntry.brUpdate.btbType===BTBtype.I
val
isIType
=
wbEntry
.
brUpdate
.
pd
.
isJalr
// val isRType = wbEntry.brUpdate.btbType===BTBtype.R
val
isRType
=
wbEntry
.
brUpdate
.
pd
.
isRet
val
mbpInstr
=
fire
val
mbpRight
=
predRight
val
mbpWrong
=
predWrong
val
mbpBRight
=
predRight
&&
isBType
val
mbpBWrong
=
predWrong
&&
isBType
val
mbpJRight
=
predRight
&&
isJType
val
mbpJWrong
=
predWrong
&&
isJType
val
mbpIRight
=
predRight
&&
isIType
val
mbpIWrong
=
predWrong
&&
isIType
val
mbpRRight
=
predRight
&&
isRType
val
mbpRWrong
=
predWrong
&&
isRType
if
(!
env
.
FPGAPlatform
&&
env
.
EnablePerfDebug
)
{
val
predictor
=
io
.
cfiInfo
.
bits
.
bpuMeta
.
predictor
val
cfiCountValid
=
io
.
cfiInfo
.
valid
&&
!
io
.
cfiInfo
.
bits
.
isReplay
val
ubtbAns
=
io
.
cfiInfo
.
bits
.
bpuMeta
.
ubtbAns
val
btbAns
=
io
.
cfiInfo
.
bits
.
bpuMeta
.
btbAns
val
tageAns
=
io
.
cfiInfo
.
bits
.
bpuMeta
.
tageAns
val
rasAns
=
io
.
cfiInfo
.
bits
.
bpuMeta
.
rasAns
val
loopAns
=
io
.
cfiInfo
.
bits
.
bpuMeta
.
loopAns
// Pipeline stage counter
val
s1Right
=
cfiCountValid
&&
!
io
.
cfiInfo
.
bits
.
isMisPred
&&
predictor
===
0.
U
val
s1Wrong
=
cfiCountValid
&&
io
.
cfiInfo
.
bits
.
isMisPred
&&
predictor
===
0.
U
val
s2Right
=
cfiCountValid
&&
!
io
.
cfiInfo
.
bits
.
isMisPred
&&
predictor
===
1.
U
val
s2Wrong
=
cfiCountValid
&&
io
.
cfiInfo
.
bits
.
isMisPred
&&
predictor
===
1.
U
val
s3Right
=
cfiCountValid
&&
!
io
.
cfiInfo
.
bits
.
isMisPred
&&
predictor
===
2.
U
val
s3Wrong
=
cfiCountValid
&&
io
.
cfiInfo
.
bits
.
isMisPred
&&
predictor
===
2.
U
// Predictor counter
// val ubtbRight = cfiCountValid && ubtbAns.hit && io.cfiInfo.bits.target === ubtbAns.target && io.cfiInfo.bits.taken === ubtbAns.taken
// val ubtbWrong = cfiCountValid && ubtbAns.hit && (io.cfiInfo.bits.target =/= ubtbAns.target || io.cfiInfo.bits.taken =/= ubtbAns.taken)
val
ubtbRight
=
cfiCountValid
&&
ubtbAns
.
hit
&&
Mux
(
ubtbAns
.
taken
,
io
.
cfiInfo
.
bits
.
target
===
ubtbAns
.
target
&&
io
.
cfiInfo
.
bits
.
taken
===
ubtbAns
.
taken
,
// taken
io
.
cfiInfo
.
bits
.
taken
===
ubtbAns
.
taken
)
// noTaken
val
ubtbWrong
=
cfiCountValid
&&
ubtbAns
.
hit
&&
Mux
(
ubtbAns
.
taken
,
io
.
cfiInfo
.
bits
.
target
=/=
ubtbAns
.
target
||
io
.
cfiInfo
.
bits
.
taken
=/=
ubtbAns
.
taken
,
// taken
io
.
cfiInfo
.
bits
.
taken
=/=
ubtbAns
.
taken
)
// noTaken
val
takenAndRight
=
ubtbAns
.
taken
&&
ubtbRight
val
takenButWrong
=
ubtbAns
.
taken
&&
ubtbWrong
// val btbRight = cfiCountValid && btbAns.hit && io.cfiInfo.bits.target === btbAns.target && io.cfiInfo.bits.taken === btbAns.taken
// val btbWrong = cfiCountValid && btbAns.hit && (io.cfiInfo.bits.target =/= btbAns.target || io.cfiInfo.bits.taken =/= btbAns.taken)
val
btbRight
=
cfiCountValid
&&
btbAns
.
hit
&&
Mux
(
btbAns
.
taken
,
io
.
cfiInfo
.
bits
.
target
===
btbAns
.
target
&&
io
.
cfiInfo
.
bits
.
taken
===
btbAns
.
taken
,
// taken
io
.
cfiInfo
.
bits
.
taken
===
btbAns
.
taken
)
// noTaken
val
btbWrong
=
cfiCountValid
&&
btbAns
.
hit
&&
Mux
(
btbAns
.
taken
,
io
.
cfiInfo
.
bits
.
target
=/=
btbAns
.
target
||
io
.
cfiInfo
.
bits
.
taken
=/=
btbAns
.
taken
,
// taken
io
.
cfiInfo
.
bits
.
taken
=/=
btbAns
.
taken
)
// noTaken
val
tageRight
=
cfiCountValid
&&
io
.
cfiInfo
.
bits
.
pd
.
brType
=/=
"b10"
.
U
&&
io
.
cfiInfo
.
bits
.
taken
===
tageAns
.
taken
// DontCare jal
val
tageWrong
=
cfiCountValid
&&
io
.
cfiInfo
.
bits
.
pd
.
brType
=/=
"b10"
.
U
&&
io
.
cfiInfo
.
bits
.
taken
=/=
tageAns
.
taken
// DontCare jal
val
rasRight
=
cfiCountValid
&&
io
.
cfiInfo
.
bits
.
pd
.
isRet
&&
rasAns
.
hit
&&
io
.
cfiInfo
.
bits
.
target
===
rasAns
.
target
val
rasWrong
=
cfiCountValid
&&
io
.
cfiInfo
.
bits
.
pd
.
isRet
&&
rasAns
.
hit
&&
io
.
cfiInfo
.
bits
.
target
=/=
rasAns
.
target
val
loopRight
=
cfiCountValid
&&
loopAns
.
hit
&&
io
.
cfiInfo
.
bits
.
taken
===
loopAns
.
taken
val
loopWrong
=
cfiCountValid
&&
loopAns
.
hit
&&
io
.
cfiInfo
.
bits
.
taken
=/=
loopAns
.
taken
ExcitingUtils
.
addSource
(
mbpInstr
,
"perfCntCondBpInstr"
,
Perf
)
ExcitingUtils
.
addSource
(
mbpRight
,
"perfCntCondBpRight"
,
Perf
)
ExcitingUtils
.
addSource
(
mbpWrong
,
"perfCntCondBpWrong"
,
Perf
)
ExcitingUtils
.
addSource
(
mbpBRight
,
"perfCntCondBpBRight"
,
Perf
)
ExcitingUtils
.
addSource
(
mbpBWrong
,
"perfCntCondBpBWrong"
,
Perf
)
ExcitingUtils
.
addSource
(
mbpJRight
,
"perfCntCondBpJRight"
,
Perf
)
ExcitingUtils
.
addSource
(
mbpJWrong
,
"perfCntCondBpJWrong"
,
Perf
)
ExcitingUtils
.
addSource
(
mbpIRight
,
"perfCntCondBpIRight"
,
Perf
)
ExcitingUtils
.
addSource
(
mbpIWrong
,
"perfCntCondBpIWrong"
,
Perf
)
ExcitingUtils
.
addSource
(
mbpRRight
,
"perfCntCondBpRRight"
,
Perf
)
ExcitingUtils
.
addSource
(
mbpRWrong
,
"perfCntCondBpRWrong"
,
Perf
)
ExcitingUtils
.
addSource
(
s1Right
,
"perfCntS1Right"
,
Perf
)
ExcitingUtils
.
addSource
(
s1Wrong
,
"perfCntS1Wrong"
,
Perf
)
ExcitingUtils
.
addSource
(
s2Right
,
"perfCntS2Right"
,
Perf
)
ExcitingUtils
.
addSource
(
s2Wrong
,
"perfCntS2Wrong"
,
Perf
)
ExcitingUtils
.
addSource
(
s3Right
,
"perfCntS3Right"
,
Perf
)
ExcitingUtils
.
addSource
(
s3Wrong
,
"perfCntS3Wrong"
,
Perf
)
ExcitingUtils
.
addSource
(
ubtbRight
,
"perfCntubtbRight"
,
Perf
)
ExcitingUtils
.
addSource
(
ubtbWrong
,
"perfCntubtbWrong"
,
Perf
)
ExcitingUtils
.
addSource
(
btbRight
,
"perfCntbtbRight"
,
Perf
)
ExcitingUtils
.
addSource
(
btbWrong
,
"perfCntbtbWrong"
,
Perf
)
ExcitingUtils
.
addSource
(
tageRight
,
"perfCnttageRight"
,
Perf
)
ExcitingUtils
.
addSource
(
tageWrong
,
"perfCnttageWrong"
,
Perf
)
ExcitingUtils
.
addSource
(
rasRight
,
"perfCntrasRight"
,
Perf
)
ExcitingUtils
.
addSource
(
rasWrong
,
"perfCntrasWrong"
,
Perf
)
ExcitingUtils
.
addSource
(
loopRight
,
"perfCntloopRight"
,
Perf
)
ExcitingUtils
.
addSource
(
loopWrong
,
"perfCntloopWrong"
,
Perf
)
ExcitingUtils
.
addSource
(
takenAndRight
,
"perfCntTakenAndRight"
,
Perf
)
ExcitingUtils
.
addSource
(
takenButWrong
,
"perfCntTakenButWrong"
,
Perf
)
}
val
utilization
=
Mux
(
headPtr
.
flag
===
tailPtr
.
flag
,
tailPtr
.
value
-
headPtr
.
value
,
BrqSize
.
U
+
tailPtr
.
value
-
headPtr
.
value
)
XSPerf
(
"utilization"
,
utilization
)
XSPerf
(
"mbpInstr"
,
PopCount
(
mbpInstr
))
XSPerf
(
"mbpRight"
,
PopCount
(
mbpRight
))
XSPerf
(
"mbpWrong"
,
PopCount
(
mbpWrong
))
XSPerf
(
"mbpBRight"
,
PopCount
(
mbpBRight
))
XSPerf
(
"mbpBWrong"
,
PopCount
(
mbpBWrong
))
XSPerf
(
"mbpJRight"
,
PopCount
(
mbpJRight
))
XSPerf
(
"mbpJWrong"
,
PopCount
(
mbpJWrong
))
XSPerf
(
"mbpIRight"
,
PopCount
(
mbpIRight
))
XSPerf
(
"mbpIWrong"
,
PopCount
(
mbpIWrong
))
XSPerf
(
"mbpRRight"
,
PopCount
(
mbpRRight
))
XSPerf
(
"mbpRWrong"
,
PopCount
(
mbpRWrong
))
}
src/main/scala/xiangshan/backend/decode/DecodeStage.scala
浏览文件 @
2c87aa6f
...
...
@@ -3,15 +3,10 @@ package xiangshan.backend.decode
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.backend.brq.BrqEnqIO
import
utils._
import
xiangshan.backend.decode.Instructions.
{
AUIPC
,
MRET
,
SRET
}
class
DecodeStage
extends
XSModule
{
val
io
=
IO
(
new
Bundle
()
{
// enq Brq
val
enqBrq
=
Flipped
(
new
BrqEnqIO
)
// from Ibuffer
val
in
=
Vec
(
DecodeWidth
,
Flipped
(
DecoupledIO
(
new
CtrlFlow
)))
...
...
@@ -20,36 +15,10 @@ class DecodeStage extends XSModule {
})
val
decoders
=
Seq
.
fill
(
DecodeWidth
)(
Module
(
new
DecodeUnit
))
// Handshake ---------------------
// 1. if current instruction is valid, then:
// First, assert toBrq(i).valid if (in.valid and out.ready and isBr) and present toBrq(i).bits
// Second, check toBrq(i).ready and connect it to io.out(i).valid
// 2. To Decode Buffer:
// First, assert in(i).ready if out(i).ready
// Second, assert out(i).valid iff in(i).valid and instruction is valid (not implemented) and toBrq(i).ready
for
(
i
<-
0
until
DecodeWidth
)
{
decoders
(
i
).
io
.
enq
.
ctrl_flow
<>
io
.
in
(
i
).
bits
val
isMret
=
io
.
in
(
i
).
bits
.
instr
===
MRET
val
isSret
=
io
.
in
(
i
).
bits
.
instr
===
SRET
val
isAuiPc
=
io
.
in
(
i
).
bits
.
instr
===
AUIPC
val
thisBrqValid
=
!
io
.
in
(
i
).
bits
.
brUpdate
.
pd
.
notCFI
||
isMret
||
isSret
||
isAuiPc
io
.
enqBrq
.
needAlloc
(
i
)
:=
thisBrqValid
io
.
enqBrq
.
req
(
i
).
valid
:=
io
.
in
(
i
).
valid
&&
thisBrqValid
&&
io
.
out
(
i
).
ready
io
.
enqBrq
.
req
(
i
).
bits
:=
io
.
in
(
i
).
bits
io
.
enqBrq
.
req
(
i
).
bits
.
instr
:=
decoders
(
i
).
io
.
deq
.
cf_ctrl
.
cf
.
instr
io
.
out
(
i
).
valid
:=
io
.
in
(
i
).
valid
&&
io
.
enqBrq
.
req
(
i
).
ready
io
.
out
(
i
).
valid
:=
io
.
in
(
i
).
valid
io
.
out
(
i
).
bits
:=
decoders
(
i
).
io
.
deq
.
cf_ctrl
io
.
out
(
i
).
bits
.
brTag
:=
io
.
enqBrq
.
resp
(
i
)
io
.
in
(
i
).
ready
:=
io
.
out
(
i
).
ready
&&
io
.
enqBrq
.
req
(
i
).
ready
XSDebug
(
io
.
in
(
i
).
valid
||
io
.
out
(
i
).
valid
||
io
.
enqBrq
.
req
(
i
).
valid
,
"i:%d In(%d %d) Out(%d %d) ToBrq(%d %d) pc:%x instr:%x\n"
,
i
.
U
,
io
.
in
(
i
).
valid
,
io
.
in
(
i
).
ready
,
io
.
out
(
i
).
valid
,
io
.
out
(
i
).
ready
,
io
.
enqBrq
.
req
(
i
).
valid
,
io
.
enqBrq
.
req
(
i
).
ready
,
io
.
in
(
i
).
bits
.
pc
,
io
.
in
(
i
).
bits
.
instr
)
io
.
in
(
i
).
ready
:=
io
.
out
(
i
).
ready
}
}
src/main/scala/xiangshan/backend/decode/DecodeUnit.scala
浏览文件 @
2c87aa6f
...
...
@@ -411,7 +411,6 @@ class DecodeUnit extends XSModule with DecodeUnitConstants {
// output
cf_ctrl
.
cf
:=
ctrl_flow
cf_ctrl
.
brTag
:=
DontCare
val
cs
=
Wire
(
new
CtrlSignals
()).
decode
(
ctrl_flow
.
instr
,
decode_table
)
val
fpDecoder
=
Module
(
new
FPDecoder
)
...
...
src/main/scala/xiangshan/backend/dispatch/Dispatch.scala
浏览文件 @
2c87aa6f
...
...
@@ -24,6 +24,7 @@ class Dispatch extends XSModule {
val
io
=
IO
(
new
Bundle
()
{
// flush or replay
val
redirect
=
Flipped
(
ValidIO
(
new
Redirect
))
val
flush
=
Input
(
Bool
())
// from rename
val
fromRename
=
Vec
(
RenameWidth
,
Flipped
(
DecoupledIO
(
new
MicroOp
)))
val
renameBypass
=
Input
(
new
RenameBypassInfo
)
...
...
@@ -57,7 +58,7 @@ class Dispatch extends XSModule {
// pipeline between rename and dispatch
// accepts all at once
val
redirectValid
=
io
.
redirect
.
valid
// && !io.redirect.bits.isReplay
val
redirectValid
=
io
.
redirect
.
valid
||
io
.
flush
for
(
i
<-
0
until
RenameWidth
)
{
PipelineConnect
(
io
.
fromRename
(
i
),
dispatch1
.
io
.
fromRename
(
i
),
dispatch1
.
io
.
recv
(
i
),
redirectValid
)
}
...
...
@@ -75,8 +76,11 @@ class Dispatch extends XSModule {
// dispatch queue: queue uops and dispatch them to different reservation stations or issue queues
// it may cancel the uops
intDq
.
io
.
redirect
<>
io
.
redirect
intDq
.
io
.
flush
<>
io
.
flush
fpDq
.
io
.
redirect
<>
io
.
redirect
fpDq
.
io
.
flush
<>
io
.
flush
lsDq
.
io
.
redirect
<>
io
.
redirect
lsDq
.
io
.
flush
<>
io
.
flush
// Int dispatch queue to Int reservation stations
val
intDispatch
=
Module
(
new
Dispatch2Int
)
...
...
src/main/scala/xiangshan/backend/dispatch/Dispatch1.scala
浏览文件 @
2c87aa6f
...
...
@@ -48,7 +48,7 @@ class Dispatch1 extends XSModule with HasExceptionNO {
val
isInt
=
VecInit
(
io
.
fromRename
.
map
(
req
=>
FuType
.
isIntExu
(
req
.
bits
.
ctrl
.
fuType
)))
val
isBranch
=
VecInit
(
io
.
fromRename
.
map
(
req
=>
// cover auipc (a fake branch)
!
req
.
bits
.
cf
.
brUpdate
.
pd
.
notCFI
||
FuType
.
isJumpExu
(
req
.
bits
.
ctrl
.
fuType
)
!
req
.
bits
.
cf
.
pd
.
notCFI
||
FuType
.
isJumpExu
(
req
.
bits
.
ctrl
.
fuType
)
))
val
isFp
=
VecInit
(
io
.
fromRename
.
map
(
req
=>
FuType
.
isFpExu
(
req
.
bits
.
ctrl
.
fuType
)))
val
isMem
=
VecInit
(
io
.
fromRename
.
map
(
req
=>
FuType
.
isMemExu
(
req
.
bits
.
ctrl
.
fuType
)))
...
...
src/main/scala/xiangshan/backend/dispatch/DispatchQueue.scala
浏览文件 @
2c87aa6f
...
...
@@ -17,6 +17,7 @@ class DispatchQueueIO(enqnum: Int, deqnum: Int) extends XSBundle {
}
val
deq
=
Vec
(
deqnum
,
DecoupledIO
(
new
MicroOp
))
val
redirect
=
Flipped
(
ValidIO
(
new
Redirect
))
val
flush
=
Input
(
Bool
())
override
def
cloneType
:
DispatchQueueIO.this.
type
=
new
DispatchQueueIO
(
enqnum
,
deqnum
).
asInstanceOf
[
this.
type
]
}
...
...
@@ -45,7 +46,7 @@ class DispatchQueue(size: Int, enqnum: Int, deqnum: Int) extends XSModule with H
val
isTrueEmpty
=
~
Cat
((
0
until
size
).
map
(
i
=>
stateEntries
(
i
)
===
s_valid
)).
orR
val
canEnqueue
=
allowEnqueue
val
canActualEnqueue
=
canEnqueue
&&
!
io
.
redirect
.
valid
val
canActualEnqueue
=
canEnqueue
&&
!
(
io
.
redirect
.
valid
||
io
.
flush
)
/**
* Part 1: update states and uops when enqueue, dequeue, commit, redirect/replay
...
...
@@ -77,7 +78,7 @@ class DispatchQueue(size: Int, enqnum: Int, deqnum: Int) extends XSModule with H
// dequeue: from s_valid to s_dispatched
for
(
i
<-
0
until
deqnum
)
{
when
(
io
.
deq
(
i
).
fire
()
&&
!
io
.
redirect
.
valid
)
{
when
(
io
.
deq
(
i
).
fire
()
&&
!
(
io
.
redirect
.
valid
||
io
.
flush
)
)
{
stateEntries
(
headPtr
(
i
).
value
)
:=
s_invalid
XSError
(
stateEntries
(
headPtr
(
i
).
value
)
=/=
s_valid
,
"state of the dispatch entry is not s_valid\n"
)
...
...
@@ -87,7 +88,7 @@ class DispatchQueue(size: Int, enqnum: Int, deqnum: Int) extends XSModule with H
// redirect: cancel uops currently in the queue
val
needCancel
=
Wire
(
Vec
(
size
,
Bool
()))
for
(
i
<-
0
until
size
)
{
needCancel
(
i
)
:=
stateEntries
(
i
)
=/=
s_invalid
&&
roqIdxEntries
(
i
).
needFlush
(
io
.
redirect
)
needCancel
(
i
)
:=
stateEntries
(
i
)
=/=
s_invalid
&&
(
roqIdxEntries
(
i
).
needFlush
(
io
.
redirect
,
io
.
flush
)
||
io
.
flush
)
when
(
needCancel
(
i
))
{
stateEntries
(
i
)
:=
s_invalid
...
...
@@ -118,7 +119,7 @@ class DispatchQueue(size: Int, enqnum: Int, deqnum: Int) extends XSModule with H
// agreement with reservation station: don't dequeue when redirect.valid
val
nextHeadPtr
=
Wire
(
Vec
(
deqnum
,
new
CircularQueuePtr
(
size
)))
for
(
i
<-
0
until
deqnum
)
{
nextHeadPtr
(
i
)
:=
Mux
(
io
.
redirect
.
valid
&&
io
.
redirect
.
bits
.
isUnconditional
()
,
nextHeadPtr
(
i
)
:=
Mux
(
io
.
flush
,
i
.
U
.
asTypeOf
(
new
CircularQueuePtr
(
size
)),
Mux
(
io
.
redirect
.
valid
,
headPtr
(
i
),
headPtr
(
i
)
+
numDeq
))
headPtr
(
i
)
:=
nextHeadPtr
(
i
)
...
...
@@ -127,7 +128,7 @@ class DispatchQueue(size: Int, enqnum: Int, deqnum: Int) extends XSModule with H
// For branch mis-prediction or memory violation replay,
// we delay updating the indices for one clock cycle.
// For now, we simply use PopCount to count #instr cancelled.
val
lastCycleMisprediction
=
RegNext
(
io
.
redirect
.
valid
&&
!
io
.
redirect
.
bits
.
isUnconditional
()
)
val
lastCycleMisprediction
=
RegNext
(
io
.
redirect
.
valid
)
// find the last one's position, starting from headPtr and searching backwards
val
validBitVec
=
VecInit
((
0
until
size
).
map
(
i
=>
stateEntries
(
i
)
===
s_valid
))
val
loValidBitVec
=
Cat
((
0
until
size
).
map
(
i
=>
validBitVec
(
i
)
&&
headPtrMask
(
i
)))
...
...
@@ -140,8 +141,7 @@ class DispatchQueue(size: Int, enqnum: Int, deqnum: Int) extends XSModule with H
// enqueue
val
numEnq
=
Mux
(
io
.
enq
.
canAccept
,
PopCount
(
io
.
enq
.
req
.
map
(
_
.
valid
)),
0.
U
)
val
exceptionValid
=
io
.
redirect
.
valid
&&
io
.
redirect
.
bits
.
isUnconditional
()
tailPtr
(
0
)
:=
Mux
(
exceptionValid
,
tailPtr
(
0
)
:=
Mux
(
io
.
flush
,
0.
U
.
asTypeOf
(
new
CircularQueuePtr
(
size
)),
Mux
(
io
.
redirect
.
valid
,
tailPtr
(
0
),
...
...
@@ -149,10 +149,10 @@ class DispatchQueue(size: Int, enqnum: Int, deqnum: Int) extends XSModule with H
Mux
(
isTrueEmpty
,
headPtr
(
0
),
walkedTailPtr
),
tailPtr
(
0
)
+
numEnq
))
)
val
lastCycleException
=
RegNext
(
exceptionValid
)
val
lastCycleException
=
RegNext
(
io
.
flush
)
val
lastLastCycleMisprediction
=
RegNext
(
lastCycleMisprediction
)
for
(
i
<-
1
until
enqnum
)
{
tailPtr
(
i
)
:=
Mux
(
exceptionValid
,
tailPtr
(
i
)
:=
Mux
(
io
.
flush
,
i
.
U
.
asTypeOf
(
new
CircularQueuePtr
(
size
)),
Mux
(
io
.
redirect
.
valid
,
tailPtr
(
i
),
...
...
@@ -163,7 +163,7 @@ class DispatchQueue(size: Int, enqnum: Int, deqnum: Int) extends XSModule with H
}
// update valid counter and allowEnqueue reg
validCounter
:=
Mux
(
exceptionValid
,
validCounter
:=
Mux
(
io
.
flush
,
0.
U
,
Mux
(
io
.
redirect
.
valid
,
validCounter
,
...
...
src/main/scala/xiangshan/backend/exu/AluExeUnit.scala
浏览文件 @
2c87aa6f
...
...
@@ -15,7 +15,6 @@ class AluExeUnit extends Exu(aluExeUnitCfg)
io
.
toInt
.
bits
.
redirectValid
:=
alu
.
redirectOutValid
io
.
toInt
.
bits
.
redirect
:=
alu
.
redirectOut
io
.
toInt
.
bits
.
brUpdate
:=
alu
.
brUpdate
XSDebug
(
io
.
fromInt
.
valid
||
io
.
redirect
.
valid
,
p
"fromInt(${io.fromInt.valid} ${io.fromInt.ready}) toInt(${io.toInt.valid} ${io.toInt.ready})"
+
...
...
src/main/scala/xiangshan/backend/exu/Exu.scala
浏览文件 @
2c87aa6f
...
...
@@ -82,6 +82,7 @@ abstract class Exu(val config: ExuConfig) extends XSModule {
val
fromInt
=
if
(
config
.
readIntRf
)
Flipped
(
DecoupledIO
(
new
ExuInput
))
else
null
val
fromFp
=
if
(
config
.
readFpRf
)
Flipped
(
DecoupledIO
(
new
ExuInput
))
else
null
val
redirect
=
Flipped
(
ValidIO
(
new
Redirect
))
val
flush
=
Input
(
Bool
())
val
toInt
=
if
(
config
.
writeIntRf
)
DecoupledIO
(
new
ExuOutput
)
else
null
val
toFp
=
if
(
config
.
writeFpRf
)
DecoupledIO
(
new
ExuOutput
)
else
null
})
...
...
@@ -106,13 +107,14 @@ abstract class Exu(val config: ExuConfig) extends XSModule {
if
(
fuCfg
.
srcCnt
>
0
)
{
fu
.
io
.
in
.
bits
.
src
(
0
)
:=
src1
}
if
(
fuCfg
.
srcCnt
>
1
)
{
if
(
fuCfg
.
srcCnt
>
1
||
fuCfg
==
jmpCfg
)
{
// jump is special for jalr target
fu
.
io
.
in
.
bits
.
src
(
1
)
:=
src2
}
if
(
fuCfg
.
srcCnt
>
2
)
{
fu
.
io
.
in
.
bits
.
src
(
2
)
:=
src3
}
fu
.
io
.
redirectIn
:=
io
.
redirect
fu
.
io
.
flushIn
:=
io
.
flush
}
...
...
@@ -187,7 +189,6 @@ abstract class Exu(val config: ExuConfig) extends XSModule {
}
def
assignDontCares
(
out
:
ExuOutput
)
=
{
out
.
brUpdate
:=
DontCare
out
.
fflags
:=
DontCare
out
.
debug
<>
DontCare
out
.
debug
.
isMMIO
:=
false
.
B
...
...
src/main/scala/xiangshan/backend/exu/FmacExeUnit.scala
浏览文件 @
2c87aa6f
...
...
@@ -19,6 +19,7 @@ class FmacExeUnit extends Exu(fmacExeUnitCfg)
fma
.
rm
:=
Mux
(
instr_rm
=/=
7.
U
,
instr_rm
,
frm
)
fma
.
io
.
redirectIn
:=
io
.
redirect
fma
.
io
.
flushIn
:=
io
.
flush
fma
.
io
.
out
.
ready
:=
io
.
toFp
.
ready
io
.
toFp
.
bits
.
data
:=
box
(
fma
.
io
.
out
.
bits
.
data
,
fma
.
io
.
out
.
bits
.
uop
.
ctrl
.
fpu
.
typeTagOut
)
...
...
src/main/scala/xiangshan/backend/exu/JumpExeUnit.scala
浏览文件 @
2c87aa6f
...
...
@@ -7,6 +7,7 @@ import xiangshan._
import
xiangshan.backend.exu.Exu.jumpExeUnitCfg
import
xiangshan.backend.fu.fpu.IntToFP
import
xiangshan.backend.fu.
{
CSR
,
Fence
,
FenceToSbuffer
,
FunctionUnit
,
Jump
}
import
xiangshan.backend.roq.RoqExceptionInfo
class
JumpExeUnit
extends
Exu
(
jumpExeUnitCfg
)
{
...
...
@@ -14,9 +15,9 @@ class JumpExeUnit extends Exu(jumpExeUnitCfg)
val
fflags
=
Flipped
(
ValidIO
(
UInt
(
5.
W
)))
val
dirty_fs
=
Input
(
Bool
())
val
frm
=
Output
(
UInt
(
3.
W
))
val
exception
=
Flipped
(
ValidIO
(
new
MicroOp
))
val
isInterrupt
=
Input
(
Bool
())
val
exception
=
Flipped
(
ValidIO
(
new
RoqExceptionInfo
))
val
trapTarget
=
Output
(
UInt
(
VAddrBits
.
W
))
val
isXRet
=
Output
(
Bool
())
val
interrupt
=
Output
(
Bool
())
val
memExceptionVAddr
=
Input
(
UInt
(
VAddrBits
.
W
))
val
externalInterrupt
=
new
ExternalInterruptIO
...
...
@@ -76,8 +77,8 @@ class JumpExeUnit extends Exu(jumpExeUnitCfg)
csr
.
csrio
.
fpu
.
dirty_fs
<>
csrio
.
dirty_fs
csr
.
csrio
.
fpu
.
frm
<>
csrio
.
frm
csr
.
csrio
.
exception
<>
csrio
.
exception
csr
.
csrio
.
isInterrupt
<>
csrio
.
isInterrupt
csr
.
csrio
.
trapTarget
<>
csrio
.
trapTarget
csr
.
csrio
.
isXRet
<>
csrio
.
isXRet
csr
.
csrio
.
interrupt
<>
csrio
.
interrupt
csr
.
csrio
.
memExceptionVAddr
<>
csrio
.
memExceptionVAddr
csr
.
csrio
.
externalInterrupt
<>
csrio
.
externalInterrupt
...
...
@@ -98,18 +99,7 @@ class JumpExeUnit extends Exu(jumpExeUnitCfg)
val
isDouble
=
!
uop
.
ctrl
.
isRVF
when
(
csr
.
io
.
out
.
valid
){
io
.
toInt
.
bits
.
redirectValid
:=
csr
.
csrio
.
redirectOut
.
valid
io
.
toInt
.
bits
.
redirect
.
brTag
:=
uop
.
brTag
io
.
toInt
.
bits
.
redirect
.
level
:=
RedirectLevel
.
flushAfter
io
.
toInt
.
bits
.
redirect
.
interrupt
:=
DontCare
io
.
toInt
.
bits
.
redirect
.
roqIdx
:=
uop
.
roqIdx
io
.
toInt
.
bits
.
redirect
.
target
:=
csr
.
csrio
.
redirectOut
.
bits
io
.
toInt
.
bits
.
redirect
.
pc
:=
uop
.
cf
.
pc
io
.
toInt
.
bits
.
debug
.
isPerfCnt
:=
csr
.
csrio
.
isPerfCnt
}.
elsewhen
(
jmp
.
io
.
out
.
valid
){
io
.
toInt
.
bits
.
redirectValid
:=
jmp
.
redirectOutValid
io
.
toInt
.
bits
.
redirect
:=
jmp
.
redirectOut
io
.
toInt
.
bits
.
brUpdate
:=
jmp
.
brUpdate
}
io
.
toInt
.
bits
.
redirectValid
:=
jmp
.
redirectOutValid
io
.
toInt
.
bits
.
redirect
:=
jmp
.
redirectOut
}
src/main/scala/xiangshan/backend/exu/MulDivExeUnit.scala
浏览文件 @
2c87aa6f
...
...
@@ -65,12 +65,11 @@ class MulDivExeUnit extends Exu(mulDivExeUnitCfg) {
div
.
ctrl
.
isW
:=
isW
div
.
ctrl
.
sign
:=
isDivSign
XSDebug
(
io
.
fromInt
.
valid
,
"In(%d %d) Out(%d %d) Redirect:(%d %d)
brTag:%x
\n"
,
XSDebug
(
io
.
fromInt
.
valid
,
"In(%d %d) Out(%d %d) Redirect:(%d %d)\n"
,
io
.
fromInt
.
valid
,
io
.
fromInt
.
ready
,
io
.
toInt
.
valid
,
io
.
toInt
.
ready
,
io
.
redirect
.
valid
,
io
.
redirect
.
bits
.
level
,
io
.
redirect
.
bits
.
brTag
.
value
io
.
redirect
.
bits
.
level
)
XSDebug
(
io
.
fromInt
.
valid
,
"src1:%x src2:%x pc:%x\n"
,
src1
,
src2
,
io
.
fromInt
.
bits
.
uop
.
cf
.
pc
)
XSDebug
(
io
.
toInt
.
valid
,
"Out(%d %d) res:%x pc:%x\n"
,
...
...
src/main/scala/xiangshan/backend/ftq/Ftq.scala
0 → 100644
浏览文件 @
2c87aa6f
package
xiangshan.backend.ftq
import
chisel3._
import
chisel3.util._
import
utils.
{
CircularQueuePtr
,
DataModuleTemplate
,
HasCircularQueuePtrHelper
,
SRAMTemplate
,
XSDebug
,
XSPerf
}
import
xiangshan._
import
xiangshan.frontend.
{
GlobalHistory
,
RASEntry
}
class
FtqPtr
extends
CircularQueuePtr
(
FtqPtr
.
FtqSize
)
with
HasCircularQueuePtrHelper
object
FtqPtr
extends
HasXSParameter
{
def
apply
(
f
:
Bool
,
v
:
UInt
)
:
FtqPtr
=
{
val
ptr
=
Wire
(
new
FtqPtr
)
ptr
.
flag
:=
f
ptr
.
value
:=
v
ptr
}
}
object
GetPcByFtq
extends
HasXSParameter
{
def
apply
(
ftqPC
:
UInt
,
ftqOffset
:
UInt
,
hasLastPrev
:
Bool
)
=
{
assert
(
ftqPC
.
getWidth
==
VAddrBits
)
assert
(
ftqOffset
.
getWidth
==
log2Up
(
PredictWidth
))
val
idxBits
=
ftqPC
.
head
(
VAddrBits
-
ftqOffset
.
getWidth
-
instOffsetBits
)
val
selLastPacket
=
hasLastPrev
&&
(
ftqOffset
===
0.
U
)
val
packetIdx
=
Mux
(
selLastPacket
,
idxBits
-
1.
U
,
idxBits
)
Cat
(
packetIdx
,
// packet pc
Mux
(
selLastPacket
,
Fill
(
ftqOffset
.
getWidth
,
1.
U
(
1.
W
)),
ftqOffset
),
0.
U
(
instOffsetBits
.
W
)
)
}
}
class
FtqNRSRAM
[
T
<:
Data
](
gen
:
T
,
numRead
:
Int
)
extends
XSModule
{
val
io
=
IO
(
new
Bundle
()
{
val
raddr
=
Input
(
Vec
(
numRead
,
UInt
(
log2Up
(
FtqSize
).
W
)))
val
ren
=
Input
(
Vec
(
numRead
,
Bool
()))
val
rdata
=
Output
(
Vec
(
numRead
,
gen
))
val
waddr
=
Input
(
UInt
(
log2Up
(
FtqSize
).
W
))
val
wen
=
Input
(
Bool
())
val
wdata
=
Input
(
gen
)
})
for
(
i
<-
0
until
numRead
){
val
sram
=
Module
(
new
SRAMTemplate
(
gen
,
FtqSize
))
sram
.
io
.
r
.
req
.
valid
:=
io
.
ren
(
i
)
sram
.
io
.
r
.
req
.
bits
.
setIdx
:=
io
.
raddr
(
i
)
io
.
rdata
(
i
)
:=
sram
.
io
.
r
.
resp
.
data
(
0
)
sram
.
io
.
w
.
req
.
valid
:=
io
.
wen
sram
.
io
.
w
.
req
.
bits
.
setIdx
:=
io
.
waddr
sram
.
io
.
w
.
req
.
bits
.
data
:=
io
.
wdata
}
}
class
Ftq_4R_SRAMEntry
extends
XSBundle
{
val
ftqPC
=
UInt
(
VAddrBits
.
W
)
val
hasLastPrev
=
Bool
()
}
// redirect and commit need read these infos
class
Ftq_2R_SRAMEntry
extends
XSBundle
{
val
rasSp
=
UInt
(
log2Ceil
(
RasSize
).
W
)
val
rasEntry
=
new
RASEntry
val
hist
=
new
GlobalHistory
val
predHist
=
new
GlobalHistory
val
specCnt
=
Vec
(
PredictWidth
,
UInt
(
10.
W
))
val
br_mask
=
Vec
(
PredictWidth
,
Bool
())
}
class
Ftq_1R_Commit_SRAMEntry
extends
XSBundle
{
val
metas
=
Vec
(
PredictWidth
,
new
BpuMeta
)
val
rvc_mask
=
Vec
(
PredictWidth
,
Bool
())
}
class
FtqRead
extends
Bundle
{
val
ptr
=
Output
(
new
FtqPtr
)
val
entry
=
Input
(
new
FtqEntry
)
}
class
Ftq
extends
XSModule
with
HasCircularQueuePtrHelper
{
val
io
=
IO
(
new
Bundle
()
{
val
enq
=
Flipped
(
DecoupledIO
(
new
FtqEntry
))
val
leftOne
=
Output
(
Bool
())
val
enqPtr
=
Output
(
new
FtqPtr
)
// roq commit, read out fectch packet and deq
val
roq_commits
=
Vec
(
CommitWidth
,
Flipped
(
ValidIO
(
new
RoqCommitInfo
)))
val
commit_ftqEntry
=
ValidIO
(
new
FtqEntry
)
// redirect, reset enq ptr
val
redirect
=
Flipped
(
ValidIO
(
new
Redirect
))
val
flush
=
Input
(
Bool
())
val
flushIdx
=
Input
(
new
FtqPtr
)
val
flushOffset
=
Input
(
UInt
(
log2Up
(
PredictWidth
).
W
))
// update mispredict target
val
frontendRedirect
=
Flipped
(
ValidIO
(
new
Redirect
))
// exu write back, update info
val
exuWriteback
=
Vec
(
exuParameters
.
JmpCnt
+
exuParameters
.
AluCnt
,
Flipped
(
ValidIO
(
new
ExuOutput
)))
// pc read reqs (0: jump/auipc 1: mispredict/load replay 2: exceptions)
val
ftqRead
=
Vec
(
3
,
Flipped
(
new
FtqRead
))
})
val
headPtr
,
tailPtr
=
RegInit
(
FtqPtr
(
false
.
B
,
0.
U
))
val
validEntries
=
distanceBetween
(
tailPtr
,
headPtr
)
// enq
io
.
leftOne
:=
validEntries
===
(
FtqSize
-
1
).
U
io
.
enq
.
ready
:=
validEntries
<
FtqSize
.
U
io
.
enqPtr
:=
tailPtr
val
stage2Flush
=
io
.
redirect
.
valid
||
io
.
flush
val
stage3Flush
=
RegNext
(
stage2Flush
)
val
real_fire
=
io
.
enq
.
fire
()
&&
!
stage2Flush
&&
!
stage3Flush
val
ftq_4r_sram
=
Module
(
new
FtqNRSRAM
(
new
Ftq_4R_SRAMEntry
,
4
))
ftq_4r_sram
.
io
.
wen
:=
real_fire
ftq_4r_sram
.
io
.
waddr
:=
tailPtr
.
value
ftq_4r_sram
.
io
.
wdata
.
ftqPC
:=
io
.
enq
.
bits
.
ftqPC
ftq_4r_sram
.
io
.
wdata
.
hasLastPrev
:=
io
.
enq
.
bits
.
hasLastPrev
val
ftq_2r_sram
=
Module
(
new
FtqNRSRAM
(
new
Ftq_2R_SRAMEntry
,
2
))
ftq_2r_sram
.
io
.
wen
:=
real_fire
ftq_2r_sram
.
io
.
waddr
:=
tailPtr
.
value
ftq_2r_sram
.
io
.
wdata
.
rasSp
:=
io
.
enq
.
bits
.
rasSp
ftq_2r_sram
.
io
.
wdata
.
rasEntry
:=
io
.
enq
.
bits
.
rasTop
ftq_2r_sram
.
io
.
wdata
.
hist
:=
io
.
enq
.
bits
.
hist
ftq_2r_sram
.
io
.
wdata
.
predHist
:=
io
.
enq
.
bits
.
predHist
ftq_2r_sram
.
io
.
wdata
.
specCnt
:=
io
.
enq
.
bits
.
specCnt
ftq_2r_sram
.
io
.
wdata
.
br_mask
:=
io
.
enq
.
bits
.
br_mask
val
pred_target_sram
=
Module
(
new
FtqNRSRAM
(
UInt
(
VAddrBits
.
W
),
1
))
pred_target_sram
.
io
.
wen
:=
real_fire
pred_target_sram
.
io
.
waddr
:=
tailPtr
.
value
pred_target_sram
.
io
.
wdata
:=
io
.
enq
.
bits
.
target
val
ftq_1r_sram
=
Module
(
new
FtqNRSRAM
(
new
Ftq_1R_Commit_SRAMEntry
,
1
))
ftq_1r_sram
.
io
.
wen
:=
real_fire
ftq_1r_sram
.
io
.
waddr
:=
tailPtr
.
value
ftq_1r_sram
.
io
.
wdata
.
metas
:=
io
.
enq
.
bits
.
metas
ftq_1r_sram
.
io
.
wdata
.
rvc_mask
:=
io
.
enq
.
bits
.
rvc_mask
// multi-write
val
update_target
=
Reg
(
Vec
(
FtqSize
,
UInt
(
VAddrBits
.
W
)))
val
cfiIndex_vec
=
Reg
(
Vec
(
FtqSize
,
ValidUndirectioned
(
UInt
(
log2Up
(
PredictWidth
).
W
))))
val
cfiIsCall
,
cfiIsRet
,
cfiIsRVC
=
Reg
(
Vec
(
FtqSize
,
Bool
()))
val
mispredict_vec
=
Reg
(
Vec
(
FtqSize
,
Vec
(
PredictWidth
,
Bool
())))
val
s_invalid
::
s_valid
::
s_commited
::
Nil
=
Enum
(
3
)
val
commitStateQueue
=
RegInit
(
VecInit
(
Seq
.
fill
(
FtqSize
)
{
VecInit
(
Seq
.
fill
(
PredictWidth
)(
s_invalid
))
}))
when
(
real_fire
)
{
val
enqIdx
=
tailPtr
.
value
commitStateQueue
(
enqIdx
)
:=
VecInit
(
io
.
enq
.
bits
.
valids
.
map
(
v
=>
Mux
(
v
,
s_valid
,
s_invalid
)))
cfiIndex_vec
(
enqIdx
)
:=
io
.
enq
.
bits
.
cfiIndex
cfiIsCall
(
enqIdx
)
:=
io
.
enq
.
bits
.
cfiIsCall
cfiIsRet
(
enqIdx
)
:=
io
.
enq
.
bits
.
cfiIsRet
cfiIsRVC
(
enqIdx
)
:=
io
.
enq
.
bits
.
cfiIsRVC
mispredict_vec
(
enqIdx
)
:=
WireInit
(
VecInit
(
Seq
.
fill
(
PredictWidth
)(
false
.
B
)))
update_target
(
enqIdx
)
:=
io
.
enq
.
bits
.
target
}
tailPtr
:=
tailPtr
+
real_fire
// exu write back, update some info
for
((
wb
,
i
)
<-
io
.
exuWriteback
.
zipWithIndex
)
{
val
wbIdx
=
wb
.
bits
.
redirect
.
ftqIdx
.
value
val
offset
=
wb
.
bits
.
redirect
.
ftqOffset
val
cfiUpdate
=
wb
.
bits
.
redirect
.
cfiUpdate
when
(
wb
.
bits
.
redirectValid
)
{
mispredict_vec
(
wbIdx
)(
offset
)
:=
cfiUpdate
.
isMisPred
when
(
cfiUpdate
.
taken
&&
offset
<
cfiIndex_vec
(
wbIdx
).
bits
)
{
cfiIndex_vec
(
wbIdx
).
bits
:=
offset
cfiIsCall
(
wbIdx
)
:=
wb
.
bits
.
uop
.
cf
.
pd
.
isCall
cfiIsRet
(
wbIdx
)
:=
wb
.
bits
.
uop
.
cf
.
pd
.
isRet
cfiIsRVC
(
wbIdx
)
:=
wb
.
bits
.
uop
.
cf
.
pd
.
isRVC
}
when
(
offset
===
cfiIndex_vec
(
wbIdx
).
bits
)
{
cfiIndex_vec
(
wbIdx
).
valid
:=
cfiUpdate
.
taken
}
}
}
// fix mispredict entry
val
lastIsMispredict
=
RegNext
(
io
.
redirect
.
valid
&&
io
.
redirect
.
bits
.
level
===
RedirectLevel
.
flushAfter
,
init
=
false
.
B
)
when
(
io
.
frontendRedirect
.
valid
&&
lastIsMispredict
)
{
update_target
(
io
.
frontendRedirect
.
bits
.
ftqIdx
.
value
)
:=
io
.
frontendRedirect
.
bits
.
cfiUpdate
.
target
}
// commit
for
(
c
<-
io
.
roq_commits
)
{
when
(
c
.
valid
)
{
commitStateQueue
(
c
.
bits
.
ftqIdx
.
value
)(
c
.
bits
.
ftqOffset
)
:=
s_commited
}
}
val
headClear
=
Cat
(
commitStateQueue
(
headPtr
.
value
).
map
(
s
=>
s
===
s_invalid
)).
andR
()
when
(
headClear
&&
headPtr
=/=
tailPtr
)
{
headPtr
:=
headPtr
+
1.
U
}
ftq_4r_sram
.
io
.
raddr
(
0
)
:=
headPtr
.
value
ftq_4r_sram
.
io
.
ren
(
0
)
:=
true
.
B
ftq_2r_sram
.
io
.
raddr
(
0
)
:=
headPtr
.
value
ftq_2r_sram
.
io
.
ren
(
0
)
:=
true
.
B
ftq_1r_sram
.
io
.
raddr
(
0
)
:=
headPtr
.
value
ftq_1r_sram
.
io
.
ren
(
0
)
:=
true
.
B
val
commitEntry
=
Wire
(
new
FtqEntry
)
val
commit_valids
=
VecInit
(
commitStateQueue
(
headPtr
.
value
).
map
(
s
=>
s
===
s_commited
))
// set state to invalid next cycle
commitStateQueue
(
headPtr
.
value
).
zip
(
commit_valids
).
foreach
({
case
(
s
,
v
)
=>
when
(
v
)
{
s
:=
s_invalid
}
})
// from 4r sram
commitEntry
.
ftqPC
:=
ftq_4r_sram
.
io
.
rdata
(
0
).
ftqPC
commitEntry
.
hasLastPrev
:=
ftq_4r_sram
.
io
.
rdata
(
0
).
hasLastPrev
// from 2r sram
commitEntry
.
rasSp
:=
ftq_2r_sram
.
io
.
rdata
(
0
).
rasSp
commitEntry
.
rasTop
:=
ftq_2r_sram
.
io
.
rdata
(
0
).
rasEntry
commitEntry
.
hist
:=
ftq_2r_sram
.
io
.
rdata
(
0
).
hist
commitEntry
.
predHist
:=
ftq_2r_sram
.
io
.
rdata
(
0
).
predHist
commitEntry
.
specCnt
:=
ftq_2r_sram
.
io
.
rdata
(
0
).
specCnt
commitEntry
.
br_mask
:=
ftq_2r_sram
.
io
.
rdata
(
0
).
br_mask
// from 1r sram
commitEntry
.
metas
:=
ftq_1r_sram
.
io
.
rdata
(
0
).
metas
commitEntry
.
rvc_mask
:=
ftq_1r_sram
.
io
.
rdata
(
0
).
rvc_mask
// from regs
commitEntry
.
valids
:=
RegNext
(
commit_valids
)
commitEntry
.
mispred
:=
RegNext
(
mispredict_vec
(
headPtr
.
value
))
commitEntry
.
cfiIndex
:=
RegNext
(
cfiIndex_vec
(
headPtr
.
value
))
commitEntry
.
cfiIsCall
:=
RegNext
(
cfiIsCall
(
headPtr
.
value
))
commitEntry
.
cfiIsRet
:=
RegNext
(
cfiIsRet
(
headPtr
.
value
))
commitEntry
.
cfiIsRVC
:=
RegNext
(
cfiIsRVC
(
headPtr
.
value
))
commitEntry
.
target
:=
RegNext
(
update_target
(
headPtr
.
value
))
io
.
commit_ftqEntry
.
valid
:=
RegNext
(
Cat
(
commit_valids
).
orR
())
//TODO: do we need this?
io
.
commit_ftqEntry
.
bits
:=
commitEntry
// read logic
for
((
req
,
i
)
<-
io
.
ftqRead
.
zipWithIndex
)
{
req
.
entry
:=
DontCare
ftq_4r_sram
.
io
.
raddr
(
1
+
i
)
:=
req
.
ptr
.
value
ftq_4r_sram
.
io
.
ren
(
1
+
i
)
:=
true
.
B
req
.
entry
.
ftqPC
:=
ftq_4r_sram
.
io
.
rdata
(
1
+
i
).
ftqPC
req
.
entry
.
hasLastPrev
:=
ftq_4r_sram
.
io
.
rdata
(
1
+
i
).
hasLastPrev
if
(
i
==
0
){
// jump, read npc
pred_target_sram
.
io
.
raddr
(
0
)
:=
req
.
ptr
.
value
pred_target_sram
.
io
.
ren
(
0
)
:=
true
.
B
req
.
entry
.
target
:=
pred_target_sram
.
io
.
rdata
(
0
)
}
if
(
i
==
1
){
// mispredict, read more info
ftq_2r_sram
.
io
.
raddr
(
1
)
:=
req
.
ptr
.
value
ftq_2r_sram
.
io
.
ren
(
1
)
:=
true
.
B
req
.
entry
.
rasTop
:=
ftq_2r_sram
.
io
.
rdata
(
1
).
rasEntry
req
.
entry
.
hist
:=
ftq_2r_sram
.
io
.
rdata
(
1
).
hist
req
.
entry
.
predHist
:=
ftq_2r_sram
.
io
.
rdata
(
1
).
predHist
req
.
entry
.
specCnt
:=
ftq_2r_sram
.
io
.
rdata
(
1
).
specCnt
req
.
entry
.
br_mask
:=
ftq_2r_sram
.
io
.
rdata
(
1
).
br_mask
}
}
// redirect, reset ptr
when
(
io
.
flush
||
io
.
redirect
.
valid
){
val
idx
=
Mux
(
io
.
flush
,
io
.
flushIdx
,
io
.
redirect
.
bits
.
ftqIdx
)
val
next
=
io
.
redirect
.
bits
.
ftqIdx
+
1.
U
tailPtr
:=
next
val
offset
=
Mux
(
io
.
flush
,
io
.
flushOffset
,
io
.
redirect
.
bits
.
ftqOffset
)
val
notMisPredict
=
io
.
flush
||
(
io
.
redirect
.
valid
&&
RedirectLevel
.
flushItself
(
io
.
redirect
.
bits
.
level
))
commitStateQueue
(
idx
.
value
).
zipWithIndex
.
foreach
({
case
(
s
,
i
)
=>
when
(
i
.
U
>
offset
||
(
notMisPredict
&&
i
.
U
===
offset
)){
s
:=
s_invalid
}
})
commitStateQueue
(
next
.
value
).
foreach
(
_
:=
s_invalid
)
}
XSPerf
(
"ftqEntries"
,
validEntries
)
XSPerf
(
"ftqStallAcc"
,
io
.
enq
.
valid
&&
!
io
.
enq
.
ready
,
acc
=
true
)
XSPerf
(
"mispredictRedirectAcc"
,
io
.
redirect
.
valid
&&
RedirectLevel
.
flushAfter
===
io
.
redirect
.
bits
.
level
,
acc
=
true
)
XSPerf
(
"replayRedirectAcc"
,
io
.
redirect
.
valid
&&
RedirectLevel
.
flushItself
(
io
.
redirect
.
bits
.
level
),
acc
=
true
)
XSDebug
(
io
.
commit_ftqEntry
.
valid
,
p
"ftq commit: ${io.commit_ftqEntry.bits}"
)
XSDebug
(
io
.
enq
.
fire
(),
p
"ftq enq: ${io.enq.bits}"
)
}
src/main/scala/xiangshan/backend/fu/Alu.scala
浏览文件 @
2c87aa6f
...
...
@@ -58,7 +58,7 @@ class Alu extends FunctionUnit with HasRedirectOut {
)
val
isBranch
=
ALUOpType
.
isBranch
(
func
)
val
isRVC
=
uop
.
cf
.
brUpdate
.
pd
.
isRVC
val
isRVC
=
uop
.
cf
.
pd
.
isRVC
val
taken
=
LookupTree
(
ALUOpType
.
getBranchType
(
func
),
branchOpTable
)
^
ALUOpType
.
isBranchInvert
(
func
)
val
target
=
(
pc
+
offset
)(
VAddrBits
-
1
,
0
)
val
snpc
=
Mux
(
isRVC
,
pc
+
2.
U
,
pc
+
4.
U
)
...
...
@@ -67,26 +67,13 @@ class Alu extends FunctionUnit with HasRedirectOut {
// Only brTag, level, roqIdx are needed
// other infos are stored in brq
redirectOut
:=
DontCare
redirectOut
.
brTag
:=
uop
.
brTag
redirectOut
.
level
:=
RedirectLevel
.
flushAfter
redirectOut
.
roqIdx
:=
uop
.
roqIdx
// redirectOut.pc := DontCare//uop.cf.pc
// redirectOut.target := DontCare//Mux(!taken && isBranch, snpc, target)
// redirectOut.interrupt := DontCare//DontCare
// Only taken really needed, do we need brTag ?
brUpdate
:=
DontCare
brUpdate
.
taken
:=
isBranch
&&
taken
brUpdate
.
brTag
:=
uop
.
brTag
// brUpdate := uop.cf.brUpdate
// // override brUpdate
// brUpdate.pc := uop.cf.pc
// brUpdate.target := Mux(!taken && isBranch, snpc, target)
// brUpdate.brTarget := target
// brUpdate.taken := isBranch && taken
// brUpdate.brTag := uop.brTag
redirectOut
.
ftqIdx
:=
uop
.
cf
.
ftqPtr
redirectOut
.
ftqOffset
:=
uop
.
cf
.
ftqOffset
redirectOut
.
cfiUpdate
.
isMisPred
:=
(
uop
.
cf
.
pred_taken
^
taken
)
&&
isBranch
redirectOut
.
cfiUpdate
.
taken
:=
taken
redirectOut
.
cfiUpdate
.
predTaken
:=
uop
.
cf
.
pred_taken
io
.
in
.
ready
:=
io
.
out
.
ready
io
.
out
.
valid
:=
valid
...
...
src/main/scala/xiangshan/backend/fu/CSR.scala
浏览文件 @
2c87aa6f
...
...
@@ -7,7 +7,7 @@ import utils._
import
xiangshan._
import
xiangshan.backend._
import
xiangshan.backend.fu.util._
import
utils.XSDebug
import
xiangshan.backend.roq.RoqExceptionInfo
object
hartId
extends
(()
=>
Int
)
{
var
x
=
0
...
...
@@ -127,15 +127,14 @@ class CSR extends FunctionUnit with HasCSRConst
{
val
csrio
=
IO
(
new
Bundle
{
// output (for func === CSROpType.jmp)
val
redirectOut
=
ValidIO
(
UInt
(
VAddrBits
.
W
))
val
perf
=
new
PerfCounterIO
val
isPerfCnt
=
Output
(
Bool
())
// to FPU
val
fpu
=
Flipped
(
new
FpuCsrIO
)
// from rob
val
exception
=
Flipped
(
ValidIO
(
new
MicroOp
))
val
isInterrupt
=
Input
(
Bool
())
val
exception
=
Flipped
(
ValidIO
(
new
RoqExceptionInfo
))
// to ROB
val
isXRet
=
Output
(
Bool
())
val
trapTarget
=
Output
(
UInt
(
VAddrBits
.
W
))
val
interrupt
=
Output
(
Bool
())
// from LSQ
...
...
@@ -614,10 +613,7 @@ class CSR extends FunctionUnit with HasCSRConst
// Branch control
val
retTarget
=
Wire
(
UInt
(
VAddrBits
.
W
))
val
resetSatp
=
addr
===
Satp
.
U
&&
wen
// write to satp will cause the pipeline be flushed
csrio
.
redirectOut
.
valid
:=
valid
&&
func
===
CSROpType
.
jmp
&&
!
isEcall
csrio
.
redirectOut
.
bits
:=
retTarget
flushPipe
:=
resetSatp
XSDebug
(
csrio
.
redirectOut
.
valid
,
"redirect to %x, pc=%x\n"
,
csrio
.
redirectOut
.
bits
,
cfIn
.
pc
)
flushPipe
:=
resetSatp
||
(
valid
&&
func
===
CSROpType
.
jmp
&&
!
isEcall
)
retTarget
:=
DontCare
// val illegalEret = TODO
...
...
@@ -659,11 +655,6 @@ class CSR extends FunctionUnit with HasCSRConst
retTarget
:=
uepc
(
VAddrBits
-
1
,
0
)
}
XSDebug
(
csrio
.
redirectOut
.
valid
,
"Rediret %x isSret:%d retTarget:%x sepc:%x cfInpc:%x valid:%d\n"
,
csrio
.
redirectOut
.
bits
,
isSret
,
retTarget
,
sepc
,
cfIn
.
pc
,
valid
)
io
.
in
.
ready
:=
true
.
B
io
.
out
.
valid
:=
valid
...
...
@@ -697,31 +688,31 @@ class CSR extends FunctionUnit with HasCSRConst
// interrupts
val
intrNO
=
IntPriority
.
foldRight
(
0.
U
)((
i
:
Int
,
sum
:
UInt
)
=>
Mux
(
intrVec
(
i
),
i
.
U
,
sum
))
val
raiseIntr
=
csrio
.
exception
.
valid
&&
csrio
.
isInterrupt
XSDebug
(
raiseIntr
,
"interrupt: pc=0x%x, %d\n"
,
csrio
.
exception
.
bits
.
cf
.
pc
,
intrNO
)
val
raiseIntr
=
csrio
.
exception
.
valid
&&
csrio
.
exception
.
bits
.
isInterrupt
XSDebug
(
raiseIntr
,
"interrupt: pc=0x%x, %d\n"
,
csrio
.
exception
.
bits
.
uop
.
cf
.
pc
,
intrNO
)
// exceptions
val
raiseException
=
csrio
.
exception
.
valid
&&
!
csrio
.
isInterrupt
val
hasInstrPageFault
=
csrio
.
exception
.
bits
.
cf
.
exceptionVec
(
instrPageFault
)
&&
raiseException
val
hasLoadPageFault
=
csrio
.
exception
.
bits
.
cf
.
exceptionVec
(
loadPageFault
)
&&
raiseException
val
hasStorePageFault
=
csrio
.
exception
.
bits
.
cf
.
exceptionVec
(
storePageFault
)
&&
raiseException
val
hasStoreAddrMisaligned
=
csrio
.
exception
.
bits
.
cf
.
exceptionVec
(
storeAddrMisaligned
)
&&
raiseException
val
hasLoadAddrMisaligned
=
csrio
.
exception
.
bits
.
cf
.
exceptionVec
(
loadAddrMisaligned
)
&&
raiseException
val
hasInstrAccessFault
=
csrio
.
exception
.
bits
.
cf
.
exceptionVec
(
instrAccessFault
)
&&
raiseException
val
hasLoadAccessFault
=
csrio
.
exception
.
bits
.
cf
.
exceptionVec
(
loadAccessFault
)
&&
raiseException
val
hasStoreAccessFault
=
csrio
.
exception
.
bits
.
cf
.
exceptionVec
(
storeAccessFault
)
&&
raiseException
val
raiseExceptionVec
=
csrio
.
exception
.
bits
.
cf
.
exceptionVec
val
raiseException
=
csrio
.
exception
.
valid
&&
!
csrio
.
exception
.
bits
.
isInterrupt
val
hasInstrPageFault
=
csrio
.
exception
.
bits
.
uop
.
cf
.
exceptionVec
(
instrPageFault
)
&&
raiseException
val
hasLoadPageFault
=
csrio
.
exception
.
bits
.
uop
.
cf
.
exceptionVec
(
loadPageFault
)
&&
raiseException
val
hasStorePageFault
=
csrio
.
exception
.
bits
.
uop
.
cf
.
exceptionVec
(
storePageFault
)
&&
raiseException
val
hasStoreAddrMisaligned
=
csrio
.
exception
.
bits
.
uop
.
cf
.
exceptionVec
(
storeAddrMisaligned
)
&&
raiseException
val
hasLoadAddrMisaligned
=
csrio
.
exception
.
bits
.
uop
.
cf
.
exceptionVec
(
loadAddrMisaligned
)
&&
raiseException
val
hasInstrAccessFault
=
csrio
.
exception
.
bits
.
uop
.
cf
.
exceptionVec
(
instrAccessFault
)
&&
raiseException
val
hasLoadAccessFault
=
csrio
.
exception
.
bits
.
uop
.
cf
.
exceptionVec
(
loadAccessFault
)
&&
raiseException
val
hasStoreAccessFault
=
csrio
.
exception
.
bits
.
uop
.
cf
.
exceptionVec
(
storeAccessFault
)
&&
raiseException
val
raiseExceptionVec
=
csrio
.
exception
.
bits
.
uop
.
cf
.
exceptionVec
val
exceptionNO
=
ExcPriority
.
foldRight
(
0.
U
)((
i
:
Int
,
sum
:
UInt
)
=>
Mux
(
raiseExceptionVec
(
i
),
i
.
U
,
sum
))
val
causeNO
=
(
raiseIntr
<<
(
XLEN
-
1
)).
asUInt
()
|
Mux
(
raiseIntr
,
intrNO
,
exceptionNO
)
val
raiseExceptionIntr
=
csrio
.
exception
.
valid
XSDebug
(
raiseExceptionIntr
,
"int/exc: pc %x int (%d):%x exc: (%d):%x\n"
,
csrio
.
exception
.
bits
.
cf
.
pc
,
intrNO
,
intrVec
,
exceptionNO
,
raiseExceptionVec
.
asUInt
csrio
.
exception
.
bits
.
uop
.
cf
.
pc
,
intrNO
,
intrVec
,
exceptionNO
,
raiseExceptionVec
.
asUInt
)
XSDebug
(
raiseExceptionIntr
,
"pc %x mstatus %x mideleg %x medeleg %x mode %x\n"
,
csrio
.
exception
.
bits
.
cf
.
pc
,
csrio
.
exception
.
bits
.
uop
.
cf
.
pc
,
mstatus
,
mideleg
,
medeleg
,
...
...
@@ -734,9 +725,9 @@ class CSR extends FunctionUnit with HasCSRConst
val
tval
=
Mux
(
hasInstrPageFault
,
Mux
(
csrio
.
exception
.
bits
.
cf
.
crossPageIPFFix
,
SignExt
(
csrio
.
exception
.
bits
.
cf
.
pc
+
2.
U
,
XLEN
),
SignExt
(
csrio
.
exception
.
bits
.
cf
.
pc
,
XLEN
)
csrio
.
exception
.
bits
.
uop
.
cf
.
crossPageIPFFix
,
SignExt
(
csrio
.
exception
.
bits
.
uop
.
cf
.
pc
+
2.
U
,
XLEN
),
SignExt
(
csrio
.
exception
.
bits
.
uop
.
cf
.
pc
,
XLEN
)
),
memExceptionAddr
)
...
...
@@ -753,9 +744,14 @@ class CSR extends FunctionUnit with HasCSRConst
val
deleg
=
Mux
(
raiseIntr
,
mideleg
,
medeleg
)
// val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM);
val
delegS
=
(
deleg
(
causeNO
(
3
,
0
)
))
&&
(
priviledgeMode
<
ModeM
)
val
delegS
=
deleg
(
causeNO
(
3
,
0
))
&&
(
priviledgeMode
<
ModeM
)
val
tvalWen
=
!(
hasInstrPageFault
||
hasLoadPageFault
||
hasStorePageFault
||
hasLoadAddrMisaligned
||
hasStoreAddrMisaligned
)
||
raiseIntr
// TODO: need check
csrio
.
trapTarget
:=
Mux
(
delegS
,
stvec
,
mtvec
)(
VAddrBits
-
1
,
0
)
val
isXRet
=
func
===
CSROpType
.
jmp
&&
!
isEcall
csrio
.
isXRet
:=
RegNext
(
isXRet
)
csrio
.
trapTarget
:=
RegNext
(
Mux
(
csrio
.
isXRet
,
retTarget
,
Mux
(
delegS
,
stvec
,
mtvec
)(
VAddrBits
-
1
,
0
)
))
when
(
raiseExceptionIntr
)
{
val
mstatusOld
=
WireInit
(
mstatus
.
asTypeOf
(
new
MstatusStruct
))
...
...
@@ -763,7 +759,7 @@ class CSR extends FunctionUnit with HasCSRConst
when
(
delegS
)
{
scause
:=
causeNO
sepc
:=
SignExt
(
csrio
.
exception
.
bits
.
cf
.
pc
,
XLEN
)
sepc
:=
SignExt
(
csrio
.
exception
.
bits
.
uop
.
cf
.
pc
,
XLEN
)
mstatusNew
.
spp
:=
priviledgeMode
mstatusNew
.
pie
.
s
:=
mstatusOld
.
ie
.
s
mstatusNew
.
ie
.
s
:=
false
.
B
...
...
@@ -771,7 +767,7 @@ class CSR extends FunctionUnit with HasCSRConst
when
(
tvalWen
)
{
stval
:=
0.
U
}
}.
otherwise
{
mcause
:=
causeNO
mepc
:=
SignExt
(
csrio
.
exception
.
bits
.
cf
.
pc
,
XLEN
)
mepc
:=
SignExt
(
csrio
.
exception
.
bits
.
uop
.
cf
.
pc
,
XLEN
)
mstatusNew
.
mpp
:=
priviledgeMode
mstatusNew
.
pie
.
m
:=
mstatusOld
.
ie
.
m
mstatusNew
.
ie
.
m
:=
false
.
B
...
...
@@ -782,11 +778,6 @@ class CSR extends FunctionUnit with HasCSRConst
mstatus
:=
mstatusNew
.
asUInt
}
XSDebug
(
raiseExceptionIntr
&&
delegS
,
"Red(%d, %x) raiseExcepIntr:%d isSret:%d sepc:%x delegs:%d deleg:%x\n"
,
csrio
.
redirectOut
.
valid
,
csrio
.
redirectOut
.
bits
,
raiseExceptionIntr
,
isSret
,
sepc
,
delegS
,
deleg
)
XSDebug
(
raiseExceptionIntr
&&
delegS
,
"sepc is writen!!! pc:%x\n"
,
cfIn
.
pc
)
...
...
src/main/scala/xiangshan/backend/fu/FunctionUnit.scala
浏览文件 @
2c87aa6f
...
...
@@ -50,6 +50,7 @@ class FunctionUnitIO(val len: Int) extends XSBundle {
val
out
=
DecoupledIO
(
new
FuOutput
(
len
))
val
redirectIn
=
Flipped
(
ValidIO
(
new
Redirect
))
val
flushIn
=
Input
(
Bool
())
}
abstract
class
FunctionUnit
(
len
:
Int
=
64
)
extends
XSModule
{
...
...
@@ -71,7 +72,7 @@ trait HasPipelineReg {
// if flush(0), valid 0 will not given, so set flushVec(0) to false.B
val
flushVec
=
validVec
.
zip
(
uopVec
).
map
(
x
=>
x
.
_1
&&
x
.
_2
.
roqIdx
.
needFlush
(
io
.
redirectIn
))
val
flushVec
=
validVec
.
zip
(
uopVec
).
map
(
x
=>
x
.
_1
&&
x
.
_2
.
roqIdx
.
needFlush
(
io
.
redirectIn
,
io
.
flushIn
))
for
(
i
<-
0
until
latency
)
{
rdyVec
(
i
)
:=
!
validVec
(
i
+
1
)
||
rdyVec
(
i
+
1
)
...
...
src/main/scala/xiangshan/backend/fu/Jump.scala
浏览文件 @
2c87aa6f
...
...
@@ -12,16 +12,16 @@ import xiangshan.backend.decode.isa._
trait
HasRedirectOut
{
this:
RawModule
=>
val
redirectOutValid
=
IO
(
Output
(
Bool
()))
val
redirectOut
=
IO
(
Output
(
new
Redirect
))
val
brUpdate
=
IO
(
Output
(
new
CfiUpdateInfo
))
}
class
Jump
extends
FunctionUnit
with
HasRedirectOut
{
val
(
src1
,
immMin
,
func
,
p
c
,
uop
)
=
(
val
(
src1
,
jalr_target
,
pc
,
immMin
,
fun
c
,
uop
)
=
(
io
.
in
.
bits
.
src
(
0
),
io
.
in
.
bits
.
src
(
1
)(
VAddrBits
-
1
,
0
),
io
.
in
.
bits
.
uop
.
cf
.
pc
,
io
.
in
.
bits
.
uop
.
ctrl
.
imm
,
io
.
in
.
bits
.
uop
.
ctrl
.
fuOpType
,
SignExt
(
io
.
in
.
bits
.
uop
.
cf
.
pc
,
AddrBits
),
io
.
in
.
bits
.
uop
)
...
...
@@ -33,27 +33,25 @@ class Jump extends FunctionUnit with HasRedirectOut {
!(
isJalr
||
isAuipc
)
->
ImmUnion
.
J
.
toImm32
(
immMin
)
)),
XLEN
)
val
redirectHit
=
uop
.
roqIdx
.
needFlush
(
io
.
redirectIn
)
val
redirectHit
=
uop
.
roqIdx
.
needFlush
(
io
.
redirectIn
,
io
.
flushIn
)
val
valid
=
io
.
in
.
valid
val
isRVC
=
uop
.
cf
.
brUpdate
.
pd
.
isRVC
val
isRVC
=
uop
.
cf
.
pd
.
isRVC
val
snpc
=
Mux
(
isRVC
,
pc
+
2.
U
,
pc
+
4.
U
)
val
target
=
src1
+
offset
// NOTE: src1 is (pc/rf(rs1)), src2 is (offset)
redirectOutValid
:=
valid
redirectOutValid
:=
valid
&&
!
isAuipc
redirectOut
:=
DontCare
// redirectOut.pc := uop.cf.pc
redirectOut
.
target
:=
target
redirectOut
.
brTag
:=
uop
.
brTag
redirectOut
.
cfiUpdate
.
target
:=
target
redirectOut
.
level
:=
RedirectLevel
.
flushAfter
// redirectOut.interrupt := DontCare
redirectOut
.
roqIdx
:=
uop
.
roqIdx
redirectOut
.
ftqIdx
:=
uop
.
cf
.
ftqPtr
redirectOut
.
ftqOffset
:=
uop
.
cf
.
ftqOffset
redirectOut
.
cfiUpdate
.
predTaken
:=
true
.
B
redirectOut
.
cfiUpdate
.
taken
:=
true
.
B
redirectOut
.
cfiUpdate
.
target
:=
target
redirectOut
.
cfiUpdate
.
isMisPred
:=
target
=/=
jalr_target
brUpdate
:=
DontCare
//uop.cf.brUpdate
// brUpdate.pc := uop.cf.pc
brUpdate
.
target
:=
target
brUpdate
.
brTarget
:=
target
brUpdate
.
taken
:=
true
.
B
// Output
val
res
=
Mux
(
JumpOpType
.
jumpOpisAuipc
(
func
),
target
,
snpc
)
...
...
@@ -64,15 +62,14 @@ class Jump extends FunctionUnit with HasRedirectOut {
io
.
out
.
bits
.
data
:=
res
// NOTE: the debug info is for one-cycle exec, if FMV needs multi-cycle, may needs change it
XSDebug
(
io
.
in
.
valid
,
"In(%d %d) Out(%d %d) Redirect:(%d %d %d)
brTag:%x
\n"
,
XSDebug
(
io
.
in
.
valid
,
"In(%d %d) Out(%d %d) Redirect:(%d %d %d)\n"
,
io
.
in
.
valid
,
io
.
in
.
ready
,
io
.
out
.
valid
,
io
.
out
.
ready
,
io
.
redirectIn
.
valid
,
io
.
redirectIn
.
bits
.
level
,
redirectHit
,
io
.
redirectIn
.
bits
.
brTag
.
value
redirectHit
)
XSDebug
(
io
.
in
.
valid
,
"src1:%x offset:%x func:%b type:JUMP pc:%x res:%x\n"
,
src1
,
offset
,
func
,
pc
,
res
)
}
src/main/scala/xiangshan/backend/fu/Radix2Divider.scala
浏览文件 @
2c87aa6f
...
...
@@ -41,7 +41,7 @@ class Radix2Divider(len: Int) extends AbstractDivider(len) {
val
uopReg
=
RegEnable
(
uop
,
newReq
)
val
cnt
=
Counter
(
len
)
when
(
newReq
&&
!
io
.
in
.
bits
.
uop
.
roqIdx
.
needFlush
(
io
.
redirectIn
))
{
when
(
newReq
&&
!
io
.
in
.
bits
.
uop
.
roqIdx
.
needFlush
(
io
.
redirectIn
,
io
.
flushIn
))
{
state
:=
s_log2
}
.
elsewhen
(
state
===
s_log2
)
{
// `canSkipShift` is calculated as following:
...
...
@@ -71,7 +71,7 @@ class Radix2Divider(len: Int) extends AbstractDivider(len) {
}
}
val
kill
=
state
=/=
s_idle
&&
uopReg
.
roqIdx
.
needFlush
(
io
.
redirectIn
)
val
kill
=
state
=/=
s_idle
&&
uopReg
.
roqIdx
.
needFlush
(
io
.
redirectIn
,
io
.
flushIn
)
when
(
kill
){
state
:=
s_idle
}
...
...
@@ -87,4 +87,4 @@ class Radix2Divider(len: Int) extends AbstractDivider(len) {
io
.
out
.
valid
:=
state
===
s_finish
io
.
in
.
ready
:=
state
===
s_idle
}
\ No newline at end of file
}
src/main/scala/xiangshan/backend/fu/SRT4Divider.scala
浏览文件 @
2c87aa6f
...
...
@@ -33,11 +33,11 @@ class SRT4Divider(len: Int) extends AbstractDivider(len) {
val
divZero
=
b
===
0.
U
val
divZeroReg
=
RegEnable
(
divZero
,
newReq
)
val
kill
=
state
=/=
s_idle
&&
uopReg
.
roqIdx
.
needFlush
(
io
.
redirectIn
)
val
kill
=
state
=/=
s_idle
&&
uopReg
.
roqIdx
.
needFlush
(
io
.
redirectIn
,
io
.
flushIn
)
switch
(
state
){
is
(
s_idle
){
when
(
io
.
in
.
fire
()
&&
!
io
.
in
.
bits
.
uop
.
roqIdx
.
needFlush
(
io
.
redirectIn
))
{
when
(
io
.
in
.
fire
()
&&
!
io
.
in
.
bits
.
uop
.
roqIdx
.
needFlush
(
io
.
redirectIn
,
io
.
flushIn
))
{
state
:=
Mux
(
divZero
,
s_finish
,
s_lzd
)
}
}
...
...
src/main/scala/xiangshan/backend/fu/fpu/FDivSqrt.scala
浏览文件 @
2c87aa6f
...
...
@@ -18,12 +18,12 @@ class FDivSqrt extends FPUSubModule {
val
uopReg
=
RegEnable
(
io
.
in
.
bits
.
uop
,
io
.
in
.
fire
())
val
single
=
RegEnable
(
tag
===
S
,
io
.
in
.
fire
())
val
rmReg
=
RegEnable
(
rm
,
io
.
in
.
fire
())
val
kill
=
uopReg
.
roqIdx
.
needFlush
(
io
.
redirectIn
)
val
kill
=
uopReg
.
roqIdx
.
needFlush
(
io
.
redirectIn
,
io
.
flushIn
)
val
killReg
=
RegInit
(
false
.
B
)
switch
(
state
){
is
(
s_idle
){
when
(
io
.
in
.
fire
()
&&
!
io
.
in
.
bits
.
uop
.
roqIdx
.
needFlush
(
io
.
redirectIn
)){
state
:=
s_div
}
when
(
io
.
in
.
fire
()
&&
!
io
.
in
.
bits
.
uop
.
roqIdx
.
needFlush
(
io
.
redirectIn
,
io
.
flushIn
)){
state
:=
s_div
}
}
is
(
s_div
){
when
(
divSqrtRawValid
){
...
...
@@ -47,7 +47,7 @@ class FDivSqrt extends FPUSubModule {
val
src1
=
unbox
(
io
.
in
.
bits
.
src
(
0
),
tag
,
None
)
val
src2
=
unbox
(
io
.
in
.
bits
.
src
(
1
),
tag
,
None
)
divSqrt
.
io
.
inValid
:=
io
.
in
.
fire
()
&&
!
io
.
in
.
bits
.
uop
.
roqIdx
.
needFlush
(
io
.
redirectIn
)
divSqrt
.
io
.
inValid
:=
io
.
in
.
fire
()
&&
!
io
.
in
.
bits
.
uop
.
roqIdx
.
needFlush
(
io
.
redirectIn
,
io
.
flushIn
)
divSqrt
.
io
.
sqrtOp
:=
fpCtrl
.
sqrt
divSqrt
.
io
.
a
:=
src1
divSqrt
.
io
.
b
:=
src2
...
...
src/main/scala/xiangshan/backend/fu/fpu/IntToFP.scala
浏览文件 @
2c87aa6f
...
...
@@ -21,7 +21,7 @@ class IntToFP extends FPUSubModule {
switch
(
state
){
is
(
s_idle
){
when
(
io
.
in
.
fire
()
&&
!
io
.
in
.
bits
.
uop
.
roqIdx
.
needFlush
(
io
.
redirectIn
)){
when
(
io
.
in
.
fire
()
&&
!
io
.
in
.
bits
.
uop
.
roqIdx
.
needFlush
(
io
.
redirectIn
,
io
.
flushIn
)){
state
:=
s_cvt
}
}
...
...
@@ -34,7 +34,7 @@ class IntToFP extends FPUSubModule {
}
}
}
when
(
state
=/=
s_idle
&&
uopReg
.
roqIdx
.
needFlush
(
io
.
redirectIn
)){
when
(
state
=/=
s_idle
&&
uopReg
.
roqIdx
.
needFlush
(
io
.
redirectIn
,
io
.
flushIn
)){
state
:=
s_idle
}
...
...
src/main/scala/xiangshan/backend/issue/ReservationStationNew.scala
浏览文件 @
2c87aa6f
...
...
@@ -16,6 +16,7 @@ class BypassQueue(number: Int) extends XSModule {
val
in
=
Flipped
(
ValidIO
(
new
MicroOp
))
val
out
=
ValidIO
(
new
MicroOp
)
val
redirect
=
Flipped
(
ValidIO
(
new
Redirect
))
val
flush
=
Input
(
Bool
())
})
if
(
number
<
0
)
{
io
.
out
.
valid
:=
false
.
B
...
...
@@ -29,11 +30,11 @@ class BypassQueue(number: Int) extends XSModule {
val
valid
=
Bool
()
val
bits
=
new
MicroOp
})))
queue
(
0
).
valid
:=
io
.
in
.
valid
&&
!
io
.
in
.
bits
.
roqIdx
.
needFlush
(
io
.
redirect
)
queue
(
0
).
valid
:=
io
.
in
.
valid
&&
!
io
.
in
.
bits
.
roqIdx
.
needFlush
(
io
.
redirect
,
io
.
flush
)
queue
(
0
).
bits
:=
io
.
in
.
bits
(
0
until
(
number
-
1
)).
map
{
i
=>
queue
(
i
+
1
)
:=
queue
(
i
)
queue
(
i
+
1
).
valid
:=
queue
(
i
).
valid
&&
!
queue
(
i
).
bits
.
roqIdx
.
needFlush
(
io
.
redirect
)
queue
(
i
+
1
).
valid
:=
queue
(
i
).
valid
&&
!
queue
(
i
).
bits
.
roqIdx
.
needFlush
(
io
.
redirect
,
io
.
flush
)
}
io
.
out
.
valid
:=
queue
(
number
-
1
).
valid
io
.
out
.
bits
:=
queue
(
number
-
1
).
bits
...
...
@@ -73,13 +74,14 @@ class ReservationStationCtrl
val
iqIdxWidth
=
log2Up
(
iqSize
)
val
fastWakeup
=
fixedDelay
>=
0
// NOTE: if do not enable fastWakeup(bypass), set fixedDelay to -1
val
nonBlocked
=
fastWakeup
val
srcNum
=
max
(
exuCfg
.
intSrcCnt
,
exuCfg
.
fpSrcCnt
)
val
srcNum
=
if
(
exuCfg
==
Exu
.
jumpExeUnitCfg
)
2
else
max
(
exuCfg
.
intSrcCnt
,
exuCfg
.
fpSrcCnt
)
require
(
srcNum
>=
1
&&
srcNum
<=
3
)
println
(
s
"[RsCtrl] ExuConfig: ${exuCfg.name} (srcNum = $srcNum)"
)
val
io
=
IO
(
new
XSBundle
{
// flush
val
redirect
=
Flipped
(
ValidIO
(
new
Redirect
))
val
flush
=
Input
(
Bool
())
// enq Ctrl sigs at dispatch-2, only use srcState
val
enqCtrl
=
Flipped
(
DecoupledIO
(
new
MicroOp
))
...
...
@@ -174,7 +176,7 @@ class ReservationStationCtrl
val
bubbleReg
=
RegNext
(
bubbleValid
)
val
bubblePtrReg
=
RegNext
(
Mux
(
moveMask
(
bubblePtr
),
bubblePtr
-
1.
U
,
bubblePtr
))
lastbubbleMask
:=
~
Mux
(
bubbleReg
,
UIntToOH
(
bubblePtrReg
),
0.
U
)
&
(
if
(
feedback
)
~(
0.
U
(
iqSize
.
W
))
else
Mux
(
RegNext
(
selectValid
&&
io
.
redirect
.
valid
),
0.
U
,
~(
0.
U
(
iqSize
.
W
))))
else
Mux
(
RegNext
(
selectValid
&&
(
io
.
redirect
.
valid
||
io
.
flush
)
),
0.
U
,
~(
0.
U
(
iqSize
.
W
))))
// deq
val
dequeue
=
if
(
feedback
)
bubbleReg
...
...
@@ -231,7 +233,7 @@ class ReservationStationCtrl
// enq
val
isFull
=
tailPtr
.
flag
// agreement with dispatch: don't fire when io.redirect.valid
val
enqueue
=
io
.
enqCtrl
.
fire
()
&&
!
io
.
redirect
.
valid
val
enqueue
=
io
.
enqCtrl
.
fire
()
&&
!
(
io
.
redirect
.
valid
||
io
.
flush
)
val
tailInc
=
tailPtr
+
1.
U
val
tailDec
=
tailPtr
-
1.
U
tailPtr
:=
Mux
(
dequeue
===
enqueue
,
tailPtr
,
Mux
(
dequeue
,
tailDec
,
tailInc
))
...
...
@@ -350,13 +352,14 @@ class ReservationStationData
val
iqIdxWidth
=
log2Up
(
iqSize
)
val
fastWakeup
=
fixedDelay
>=
0
// NOTE: if do not enable fastWakeup(bypass), set fixedDelay to -1
val
nonBlocked
=
fastWakeup
val
srcNum
=
max
(
exuCfg
.
intSrcCnt
,
exuCfg
.
fpSrcCnt
)
val
srcNum
=
if
(
exuCfg
==
Exu
.
jumpExeUnitCfg
)
2
else
max
(
exuCfg
.
intSrcCnt
,
exuCfg
.
fpSrcCnt
)
require
(
srcNum
>=
1
&&
srcNum
<=
3
)
println
(
s
"[RsData] ExuConfig: ${exuCfg.name} (srcNum = $srcNum)"
)
val
io
=
IO
(
new
XSBundle
{
// flush
val
redirect
=
Flipped
(
ValidIO
(
new
Redirect
))
val
flush
=
Input
(
Bool
())
// send to exu
val
deq
=
DecoupledIO
(
new
ExuInput
)
...
...
@@ -367,6 +370,7 @@ class ReservationStationData
// read src op value
val
srcRegValue
=
Vec
(
srcNum
,
Input
(
UInt
((
XLEN
+
1
).
W
)))
val
jumpPc
=
if
(
exuCfg
==
Exu
.
jumpExeUnitCfg
)
Input
(
UInt
(
VAddrBits
.
W
))
else
null
val
jalr_target
=
if
(
exuCfg
==
Exu
.
jumpExeUnitCfg
)
Input
(
UInt
(
VAddrBits
.
W
))
else
null
// broadcast selected uop to other issue queues
val
selectedUop
=
ValidIO
(
new
MicroOp
)
...
...
@@ -391,6 +395,9 @@ class ReservationStationData
// Data : single read, multi write
// ------------------------
val
pcMem
=
if
(
exuCfg
==
Exu
.
jumpExeUnitCfg
)
Some
(
Module
(
new
SyncDataModuleTemplate
(
UInt
(
VAddrBits
.
W
),
iqSize
,
numRead
=
1
,
numWrite
=
1
)))
else
None
val
data
=
(
0
until
srcNum
).
map
{
i
=>
val
d
=
Module
(
new
RSDataSingleSrc
(
XLEN
+
1
,
iqSize
,
wakeupCnt
+
extraListenPortsCnt
))
d
.
suggestName
(
s
"${this.name}_data${i}"
)
...
...
@@ -446,6 +453,12 @@ class ReservationStationData
p
"${enqUop.src3State}|${enqUop.ctrl.src3Type} pc:0x${Hexadecimal(enqUop.cf.pc)} roqIdx:${enqUop.roqIdx}\n"
)
}
if
(
pcMem
.
nonEmpty
){
pcMem
.
get
.
io
.
wen
(
0
)
:=
enqEnReg
pcMem
.
get
.
io
.
waddr
(
0
)
:=
enqPtrReg
pcMem
.
get
.
io
.
wdata
(
0
)
:=
io
.
jumpPc
}
data
.
map
(
_
.
w
.
addr
:=
enqPtrReg
)
data
.
zip
(
io
.
ctrl
.
enqSrcReady
).
map
{
case
(
src
,
ready
)
=>
src
.
w
.
wen
:=
RegNext
(
ready
&&
enqEn
)
}
...
...
@@ -455,9 +468,8 @@ class ReservationStationData
SignExt
(
io
.
jumpPc
,
XLEN
),
io
.
srcRegValue
(
0
)
)
// data.io.w.bits.data(0) := src1Mux
data
(
0
).
w
.
wdata
:=
src1Mux
data
(
1
).
w
.
wdata
:=
io
.
jalr_target
case
Exu
.
aluExeUnitCfg
=>
val
src1Mux
=
Mux
(
enqUopReg
.
ctrl
.
src1Type
===
SrcType
.
pc
,
SignExt
(
enqUopReg
.
cf
.
pc
,
XLEN
),
...
...
@@ -515,6 +527,10 @@ class ReservationStationData
exuInput
:=
DontCare
exuInput
.
uop
:=
uop
(
deq
)
exuInput
.
uop
.
cf
.
exceptionVec
:=
0.
U
.
asTypeOf
(
ExceptionVec
())
if
(
pcMem
.
nonEmpty
){
pcMem
.
get
.
io
.
raddr
(
0
)
:=
sel
.
bits
exuInput
.
uop
.
cf
.
pc
:=
pcMem
.
get
.
io
.
rdata
(
0
)
}
data
.
map
(
_
.
r
.
addr
:=
sel
.
bits
)
val
regValues
=
data
.
map
(
_
.
r
.
rdata
)
XSDebug
(
io
.
deq
.
fire
(),
p
"[regValues] "
+
List
.
tabulate
(
srcNum
)(
idx
=>
p
"reg$idx: ${Hexadecimal(regValues(idx))}"
).
reduce
((
p1
,
p2
)
=>
p1
+
" "
+
p2
)
+
"\n"
)
...
...
@@ -551,7 +567,7 @@ class ReservationStationData
if
(
nonBlocked
)
{
io
.
ctrl
.
fuReady
:=
true
.
B
}
else
{
io
.
ctrl
.
fuReady
:=
io
.
deq
.
ready
}
io
.
ctrl
.
redirectVec
:=
uop
.
map
(
_
.
roqIdx
.
needFlush
(
io
.
redirect
))
io
.
ctrl
.
redirectVec
:=
uop
.
map
(
_
.
roqIdx
.
needFlush
(
io
.
redirect
,
io
.
flush
))
redirectHit
:=
io
.
ctrl
.
redirectVec
(
sel
.
bits
)
io
.
ctrl
.
feedback
:=
DontCare
...
...
@@ -573,6 +589,7 @@ class ReservationStationData
bpQueue
.
io
.
in
.
valid
:=
sel
.
valid
// FIXME: error when function is blocked => fu should not be blocked
bpQueue
.
io
.
in
.
bits
:=
uop
(
sel
.
bits
)
bpQueue
.
io
.
redirect
:=
io
.
redirect
bpQueue
.
io
.
flush
:=
io
.
flush
io
.
selectedUop
.
valid
:=
bpQueue
.
io
.
out
.
valid
io
.
selectedUop
.
bits
:=
bpQueue
.
io
.
out
.
bits
io
.
selectedUop
.
bits
.
cf
.
exceptionVec
:=
0.
U
.
asTypeOf
(
ExceptionVec
())
...
...
src/main/scala/xiangshan/backend/rename/FreeList.scala
浏览文件 @
2c87aa6f
...
...
@@ -4,7 +4,6 @@ import chisel3._
import
chisel3.util._
import
xiangshan._
import
utils._
import
xiangshan.backend.brq.BrqPtr
trait
HasFreeListConsts
extends
HasXSParameter
{
def
FL_SIZE
:
Int
=
NRPhyRegs
-
32
...
...
@@ -34,7 +33,8 @@ object FreeListPtr extends HasFreeListConsts {
class
FreeList
extends
XSModule
with
HasFreeListConsts
with
HasCircularQueuePtrHelper
{
val
io
=
IO
(
new
Bundle
()
{
val
redirect
=
Flipped
(
ValidIO
(
new
Redirect
))
val
redirect
=
Input
(
Bool
())
val
flush
=
Input
(
Bool
())
val
req
=
new
Bundle
{
// need to alloc (not actually do the allocation)
...
...
@@ -100,16 +100,15 @@ class FreeList extends XSModule with HasFreeListConsts with HasCircularQueuePtrH
freeRegs
:=
distanceBetween
(
tailPtr
,
headPtrNext
)
// priority: (1) exception and flushPipe; (2) walking; (3) mis-prediction; (4) normal dequeue
headPtr
:=
Mux
(
io
.
redirect
.
valid
&&
io
.
redirect
.
bits
.
isUnconditional
()
,
headPtr
:=
Mux
(
io
.
flush
,
FreeListPtr
(!
tailPtrNext
.
flag
,
tailPtrNext
.
value
),
Mux
(
io
.
walk
.
valid
,
headPtr
-
io
.
walk
.
bits
,
Mux
(
io
.
redirect
.
valid
,
headPtr
,
headPtrNext
))
Mux
(
io
.
redirect
,
headPtr
,
headPtrNext
))
)
XSDebug
(
p
"head:$headPtr tail:$tailPtr\n"
)
XSDebug
(
io
.
redirect
.
valid
,
p
"redirect: brqIdx=${io.redirect.bits.brTag.value}\n"
)
val
enableFreelistCheck
=
false
if
(
enableFreelistCheck
)
{
...
...
src/main/scala/xiangshan/backend/rename/Rename.scala
浏览文件 @
2c87aa6f
...
...
@@ -16,6 +16,7 @@ class RenameBypassInfo extends XSBundle {
class
Rename
extends
XSModule
with
HasCircularQueuePtrHelper
{
val
io
=
IO
(
new
Bundle
()
{
val
redirect
=
Flipped
(
ValidIO
(
new
Redirect
))
val
flush
=
Input
(
Bool
())
val
roqCommits
=
Flipped
(
new
RoqCommitIO
)
// from decode buffer
val
in
=
Vec
(
RenameWidth
,
Flipped
(
DecoupledIO
(
new
CfCtrl
)))
...
...
@@ -47,9 +48,11 @@ class Rename extends XSModule with HasCircularQueuePtrHelper {
val
allPhyResource
=
Seq
((
intRat
,
intFreeList
,
false
),
(
fpRat
,
fpFreeList
,
true
))
allPhyResource
.
map
{
case
(
rat
,
freelist
,
_
)
=>
rat
.
redirect
:=
io
.
redirect
rat
.
redirect
:=
io
.
redirect
.
valid
rat
.
flush
:=
io
.
flush
rat
.
walkWen
:=
io
.
roqCommits
.
isWalk
freelist
.
redirect
:=
io
.
redirect
freelist
.
redirect
:=
io
.
redirect
.
valid
freelist
.
flush
:=
io
.
flush
freelist
.
walk
.
valid
:=
io
.
roqCommits
.
isWalk
}
val
canOut
=
io
.
out
(
0
).
ready
&&
fpFreeList
.
req
.
canAlloc
&&
intFreeList
.
req
.
canAlloc
&&
!
io
.
roqCommits
.
isWalk
...
...
@@ -69,10 +72,15 @@ class Rename extends XSModule with HasCircularQueuePtrHelper {
// speculatively assign the instruction with an roqIdx
val
validCount
=
PopCount
(
io
.
in
.
map
(
_
.
valid
))
val
roqIdxHead
=
RegInit
(
0.
U
.
asTypeOf
(
new
RoqPtr
))
val
lastCycleMisprediction
=
RegNext
(
io
.
redirect
.
valid
&&
!
io
.
redirect
.
bits
.
isUnconditional
()
&&
!
io
.
redirect
.
bits
.
flushItself
())
val
roqIdxHeadNext
=
Mux
(
io
.
redirect
.
valid
,
Mux
(
io
.
redirect
.
bits
.
isUnconditional
(),
0.
U
.
asTypeOf
(
new
RoqPtr
),
io
.
redirect
.
bits
.
roqIdx
),
Mux
(
lastCycleMisprediction
,
roqIdxHead
+
1.
U
,
Mux
(
canOut
,
roqIdxHead
+
validCount
,
roqIdxHead
))
val
lastCycleMisprediction
=
RegNext
(
io
.
redirect
.
valid
&&
!
io
.
redirect
.
bits
.
flushItself
())
val
roqIdxHeadNext
=
Mux
(
io
.
flush
,
0.
U
.
asTypeOf
(
new
RoqPtr
),
Mux
(
io
.
redirect
.
valid
,
io
.
redirect
.
bits
.
roqIdx
,
Mux
(
lastCycleMisprediction
,
roqIdxHead
+
1.
U
,
Mux
(
canOut
,
roqIdxHead
+
validCount
,
roqIdxHead
))
)
)
roqIdxHead
:=
roqIdxHeadNext
...
...
@@ -100,7 +108,6 @@ class Rename extends XSModule with HasCircularQueuePtrHelper {
for
(
i
<-
0
until
RenameWidth
)
{
uops
(
i
).
cf
:=
io
.
in
(
i
).
bits
.
cf
uops
(
i
).
ctrl
:=
io
.
in
(
i
).
bits
.
ctrl
uops
(
i
).
brTag
:=
io
.
in
(
i
).
bits
.
brTag
val
inValid
=
io
.
in
(
i
).
valid
...
...
src/main/scala/xiangshan/backend/rename/RenameTable.scala
浏览文件 @
2c87aa6f
...
...
@@ -33,7 +33,8 @@ object hartIdRTFp extends (() => Int) {
class
RenameTable
(
float
:
Boolean
)
extends
XSModule
{
val
io
=
IO
(
new
Bundle
()
{
val
redirect
=
Flipped
(
ValidIO
(
new
Redirect
))
val
redirect
=
Input
(
Bool
())
val
flush
=
Input
(
Bool
())
val
walkWen
=
Input
(
Bool
())
val
readPorts
=
Vec
({
if
(
float
)
4
else
3
}
*
RenameWidth
,
new
RatReadPort
)
val
specWritePorts
=
Vec
(
CommitWidth
,
new
RatWritePort
)
...
...
@@ -48,8 +49,8 @@ class RenameTable(float: Boolean) extends XSModule {
// When redirect happens (mis-prediction), don't update the rename table
// However, when mis-prediction and walk happens at the same time, rename table needs to be updated
for
(
w
<-
io
.
specWritePorts
){
when
(
w
.
wen
&&
(!
io
.
redirect
.
valid
||
io
.
walkWen
))
{
for
(
w
<-
io
.
specWritePorts
){
when
(
w
.
wen
&&
(!(
io
.
redirect
||
io
.
flush
)
||
io
.
walkWen
))
{
spec_table
(
w
.
addr
)
:=
w
.
wdata
}
}
...
...
@@ -65,8 +66,7 @@ class RenameTable(float: Boolean) extends XSModule {
when
(
w
.
wen
){
arch_table
(
w
.
addr
)
:=
w
.
wdata
}
}
val
flush
=
io
.
redirect
.
valid
&&
io
.
redirect
.
bits
.
isUnconditional
()
when
(
flush
)
{
when
(
io
.
flush
)
{
spec_table
:=
arch_table
// spec table needs to be updated when flushPipe
for
(
w
<-
io
.
archWritePorts
)
{
...
...
src/main/scala/xiangshan/backend/roq/Roq.scala
浏览文件 @
2c87aa6f
...
...
@@ -6,6 +6,7 @@ import chisel3.util._
import
xiangshan._
import
utils._
import
xiangshan.backend.LSUOpType
import
xiangshan.backend.ftq.FtqPtr
import
xiangshan.mem.
{
LqPtr
,
SqPtr
}
object
roqDebugId
extends
Function0
[
Integer
]
{
...
...
@@ -17,9 +18,9 @@ object roqDebugId extends Function0[Integer] {
}
class
RoqPtr
extends
CircularQueuePtr
(
RoqPtr
.
RoqSize
)
with
HasCircularQueuePtrHelper
{
def
needFlush
(
redirect
:
Valid
[
Redirect
])
:
Bool
=
{
def
needFlush
(
redirect
:
Valid
[
Redirect
]
,
flush
:
Bool
)
:
Bool
=
{
val
flushItself
=
redirect
.
bits
.
flushItself
()
&&
this
===
redirect
.
bits
.
roqIdx
redirect
.
valid
&&
(
redirect
.
bits
.
isUnconditional
()
||
flushItself
||
isAfter
(
this
,
redirect
.
bits
.
roqIdx
))
flush
||
(
redirect
.
valid
&&
(
flushItself
||
isAfter
(
this
,
redirect
.
bits
.
roqIdx
)
))
}
}
...
...
@@ -35,6 +36,7 @@ object RoqPtr extends HasXSParameter {
class
RoqCSRIO
extends
XSBundle
{
val
intrBitSet
=
Input
(
Bool
())
val
trapTarget
=
Input
(
UInt
(
VAddrBits
.
W
))
val
isXRet
=
Input
(
Bool
())
val
fflags
=
Output
(
Valid
(
UInt
(
5.
W
)))
val
dirty_fs
=
Output
(
Bool
())
...
...
@@ -80,6 +82,8 @@ class RoqDeqPtrWrapper extends XSModule with HasCircularQueuePtrHelper {
val
intrBitSetReg
=
Input
(
Bool
())
val
hasNoSpecExec
=
Input
(
Bool
())
val
commitType
=
Input
(
CommitType
())
val
misPredBlock
=
Input
(
Bool
())
val
isReplaying
=
Input
(
Bool
())
// output: the CommitWidth deqPtr
val
out
=
Vec
(
CommitWidth
,
Output
(
new
RoqPtr
))
val
next_out
=
Vec
(
CommitWidth
,
Output
(
new
RoqPtr
))
...
...
@@ -97,11 +101,11 @@ class RoqDeqPtrWrapper extends XSModule with HasCircularQueuePtrHelper {
// for normal commits: only to consider when there're no exceptions
// we don't need to consider whether the first instruction has exceptions since it wil trigger exceptions.
val
commitBlocked
=
VecInit
((
0
until
CommitWidth
).
map
(
i
=>
if
(
i
==
0
)
false
.
B
else
possibleException
(
i
).
asUInt
.
orR
||
io
.
deq_flushPipe
(
i
)))
val
canCommit
=
VecInit
((
0
until
CommitWidth
).
map
(
i
=>
io
.
deq_v
(
i
)
&&
io
.
deq_w
(
i
)
/*&& !commitBlocked(i)*/
))
val
canCommit
=
VecInit
((
0
until
CommitWidth
).
map
(
i
=>
io
.
deq_v
(
i
)
&&
io
.
deq_w
(
i
)
&&
!
io
.
misPredBlock
&&
!
io
.
isReplaying
))
val
normalCommitCnt
=
PriorityEncoder
(
canCommit
.
map
(
c
=>
!
c
)
:+
true
.
B
)
// when io.intrBitSetReg or there're possible exceptions in these instructions, only one instruction is allowed to commit
val
allowOnlyOne
=
VecInit
(
commitBlocked
.
drop
(
1
)).
asUInt
.
orR
||
io
.
intrBitSetReg
val
commitCnt
=
Mux
(
allowOnlyOne
,
io
.
deq_v
(
0
)
&&
io
.
deq_w
(
0
),
normalCommitCnt
)
val
commitCnt
=
Mux
(
allowOnlyOne
,
canCommit
(
0
),
normalCommitCnt
)
val
resetDeqPtrVec
=
VecInit
((
0
until
CommitWidth
).
map
(
_
.
U
.
asTypeOf
(
new
RoqPtr
)))
val
commitDeqPtrVec
=
VecInit
(
deqPtrVec
.
map
(
_
+
commitCnt
))
...
...
@@ -202,12 +206,22 @@ class RoqEnqPtrWrapper extends XSModule with HasCircularQueuePtrHelper {
// }
class
RoqExceptionInfo
extends
XSBundle
{
val
uop
=
new
MicroOp
val
isInterrupt
=
Bool
()
}
class
RoqFlushInfo
extends
XSBundle
{
val
ftqIdx
=
new
FtqPtr
val
ftqOffset
=
UInt
(
log2Up
(
PredictWidth
).
W
)
}
class
Roq
(
numWbPorts
:
Int
)
extends
XSModule
with
HasCircularQueuePtrHelper
{
val
io
=
IO
(
new
Bundle
()
{
val
redirect
=
Input
(
Valid
(
new
Redirect
))
val
enq
=
new
RoqEnqIO
val
redirectOut
=
Output
(
Valid
(
new
Redirect
)
)
val
exception
=
Output
(
new
MicroOp
)
val
flushOut
=
ValidIO
(
new
RoqFlushInfo
)
val
exception
=
ValidIO
(
new
RoqExceptionInfo
)
// exu + brq
val
exeWbResults
=
Vec
(
numWbPorts
,
Flipped
(
ValidIO
(
new
ExuOutput
)))
val
commits
=
new
RoqCommitIO
...
...
@@ -264,6 +278,7 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
val
walkPtr
=
walkPtrVec
(
0
)
val
isEmpty
=
enqPtr
===
deqPtr
val
isReplaying
=
io
.
redirect
.
valid
&&
RedirectLevel
.
flushItself
(
io
.
redirect
.
bits
.
level
)
/**
* states of Roq
...
...
@@ -369,23 +384,25 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
// Thus, we don't allow load/store instructions to trigger an interrupt.
val
intrBitSetReg
=
RegNext
(
io
.
csr
.
intrBitSet
)
val
intrEnable
=
intrBitSetReg
&&
!
hasNoSpecExec
&&
!
CommitType
.
isLoadStore
(
deqDispatchData
.
commitType
)
val
exceptionEnable
=
writebacked
(
deqPtr
.
value
)
&&
Cat
(
deqExceptionVec
)
.
orR
()
val
exceptionEnable
=
writebacked
(
deqPtr
.
value
)
&&
deqExceptionVec
.
asUInt
.
orR
()
val
isFlushPipe
=
writebacked
(
deqPtr
.
value
)
&&
deqWritebackData
.
flushPipe
io
.
redirectOut
:=
DontCare
io
.
redirectOut
.
valid
:=
(
state
===
s_idle
)
&&
valid
(
deqPtr
.
value
)
&&
(
intrEnable
||
exceptionEnable
||
isFlushPipe
)
io
.
redirectOut
.
bits
.
level
:=
Mux
(
intrEnable
||
exceptionEnable
,
RedirectLevel
.
exception
,
RedirectLevel
.
flushAll
)
io
.
redirectOut
.
bits
.
interrupt
:=
intrEnable
io
.
redirectOut
.
bits
.
target
:=
Mux
(
intrEnable
||
exceptionEnable
,
io
.
csr
.
trapTarget
,
deqDispatchData
.
pc
+
4.
U
)
io
.
exception
:=
debug_deqUop
io
.
exception
.
ctrl
.
commitType
:=
deqDispatchData
.
commitType
io
.
exception
.
cf
.
pc
:=
deqDispatchData
.
pc
io
.
exception
.
cf
.
exceptionVec
:=
deqExceptionVec
io
.
exception
.
cf
.
crossPageIPFFix
:=
deqDispatchData
.
crossPageIPFFix
XSDebug
(
io
.
redirectOut
.
valid
,
p
"generate redirect: pc 0x${Hexadecimal(io.exception.cf.pc)} intr $intrEnable "
+
p
"excp $exceptionEnable flushPipe $isFlushPipe target 0x${Hexadecimal(io.redirectOut.bits.target)} "
+
io
.
flushOut
.
valid
:=
(
state
===
s_idle
)
&&
valid
(
deqPtr
.
value
)
&&
(
intrEnable
||
exceptionEnable
||
isFlushPipe
)
io
.
flushOut
.
bits
.
ftqIdx
:=
deqDispatchData
.
ftqIdx
io
.
flushOut
.
bits
.
ftqOffset
:=
deqDispatchData
.
ftqOffset
val
exceptionHappen
=
(
state
===
s_idle
)
&&
valid
(
deqPtr
.
value
)
&&
(
intrEnable
||
exceptionEnable
)
io
.
exception
.
valid
:=
RegNext
(
exceptionHappen
)
io
.
exception
.
bits
.
uop
:=
RegEnable
(
debug_deqUop
,
exceptionHappen
)
io
.
exception
.
bits
.
uop
.
ctrl
.
commitType
:=
RegEnable
(
deqDispatchData
.
commitType
,
exceptionHappen
)
io
.
exception
.
bits
.
uop
.
cf
.
pc
:=
DontCare
// we get pc at ftq, so roq don't save pc
io
.
exception
.
bits
.
uop
.
cf
.
exceptionVec
:=
RegEnable
(
deqExceptionVec
,
exceptionHappen
)
io
.
exception
.
bits
.
uop
.
cf
.
crossPageIPFFix
:=
RegEnable
(
deqDispatchData
.
crossPageIPFFix
,
exceptionHappen
)
io
.
exception
.
bits
.
isInterrupt
:=
RegEnable
(
intrEnable
,
exceptionHappen
)
XSDebug
(
io
.
flushOut
.
valid
,
p
"generate redirect: pc 0x${Hexadecimal(io.exception.bits.uop.cf.pc)} intr $intrEnable "
+
p
"excp $exceptionEnable flushPipe $isFlushPipe "
+
p
"Trap_target 0x${Hexadecimal(io.csr.trapTarget)} exceptionVec ${Binary(deqExceptionVec.asUInt)}\n"
)
...
...
@@ -420,6 +437,18 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
}).
reduce
(
_
|
_
)
val
dirty_fs
=
Mux
(
io
.
commits
.
isWalk
,
false
.
B
,
Cat
(
fpWen
).
orR
())
// when mispredict branches writeback, stop commit in the next 2 cycles
// TODO: don't check all exu write back
val
misPredWb
=
Cat
(
VecInit
((
0
until
numWbPorts
).
map
(
i
=>
io
.
exeWbResults
(
i
).
bits
.
redirect
.
cfiUpdate
.
isMisPred
&&
io
.
exeWbResults
(
i
).
bits
.
redirectValid
))).
orR
()
val
misPredBlockCounter
=
Reg
(
UInt
(
2.
W
))
misPredBlockCounter
:=
Mux
(
misPredWb
,
"b11"
.
U
,
misPredBlockCounter
>>
1.
U
)
val
misPredBlock
=
misPredBlockCounter
(
0
)
io
.
commits
.
isWalk
:=
state
=/=
s_idle
val
commit_v
=
Mux
(
state
===
s_idle
,
VecInit
(
deqPtrVec
.
map
(
ptr
=>
valid
(
ptr
.
value
))),
VecInit
(
walkPtrVec
.
map
(
ptr
=>
valid
(
ptr
.
value
))))
val
commit_w
=
VecInit
(
deqPtrVec
.
map
(
ptr
=>
writebacked
(
ptr
.
value
)))
...
...
@@ -430,8 +459,8 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
for
(
i
<-
0
until
CommitWidth
)
{
// defaults: state === s_idle and instructions commit
// when intrBitSetReg, allow only one instruction to commit at each clock cycle
val
isBlocked
=
if
(
i
!=
0
)
Cat
(
commit_block
.
take
(
i
)).
orR
||
allowOnlyOneCommit
else
intrEnable
||
commit_exception
(
0
)
io
.
commits
.
valid
(
i
)
:=
commit_v
(
i
)
&&
commit_w
(
i
)
&&
!
isBlocked
val
isBlocked
=
if
(
i
!=
0
)
Cat
(
commit_block
.
take
(
i
)).
orR
||
allowOnlyOneCommit
else
intrEnable
||
deqExceptionVec
.
asUInt
.
orR
io
.
commits
.
valid
(
i
)
:=
commit_v
(
i
)
&&
commit_w
(
i
)
&&
!
isBlocked
&&
!
misPredBlock
&&
!
isReplaying
io
.
commits
.
info
(
i
)
:=
dispatchDataRead
(
i
)
when
(
state
===
s_walk
)
{
...
...
@@ -490,7 +519,7 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
* (3) walk: when walking comes to the end, switch to s_walk
* (4) s_extrawalk to s_walk
*/
val
state_next
=
Mux
(
io
.
redirect
Out
.
valid
,
val
state_next
=
Mux
(
io
.
flush
Out
.
valid
,
s_idle
,
Mux
(
io
.
redirect
.
valid
,
Mux
(
io
.
enq
.
needAlloc
.
asUInt
.
orR
,
s_extrawalk
,
s_walk
),
...
...
@@ -514,6 +543,9 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
deqPtrGenModule
.
io
.
intrBitSetReg
:=
intrBitSetReg
deqPtrGenModule
.
io
.
hasNoSpecExec
:=
hasNoSpecExec
deqPtrGenModule
.
io
.
commitType
:=
deqDispatchData
.
commitType
deqPtrGenModule
.
io
.
misPredBlock
:=
misPredBlock
deqPtrGenModule
.
io
.
isReplaying
:=
isReplaying
deqPtrVec
:=
deqPtrGenModule
.
io
.
out
val
deqPtrVec_next
=
deqPtrGenModule
.
io
.
next_out
...
...
@@ -548,7 +580,7 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
val
lastCycleRedirect
=
RegNext
(
io
.
redirect
.
valid
)
val
trueValidCounter
=
Mux
(
lastCycleRedirect
,
distanceBetween
(
enqPtr
,
deqPtr
),
validCounter
)
val
commitCnt
=
PopCount
(
io
.
commits
.
valid
)
validCounter
:=
Mux
(
io
.
redirect
Out
.
valid
,
validCounter
:=
Mux
(
io
.
flush
Out
.
valid
,
0.
U
,
Mux
(
state
===
s_idle
,
(
validCounter
-
commitCnt
)
+
dispatchNum
,
...
...
@@ -556,7 +588,7 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
)
)
allowEnqueue
:=
Mux
(
io
.
redirect
Out
.
valid
,
allowEnqueue
:=
Mux
(
io
.
flush
Out
.
valid
,
true
.
B
,
Mux
(
state
===
s_idle
,
validCounter
+
dispatchNum
<=
(
RoqSize
-
RenameWidth
).
U
,
...
...
@@ -599,7 +631,7 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
}
}
// reset: when exception, reset all valid to false
when
(
io
.
redirect
Out
.
valid
)
{
when
(
io
.
flush
Out
.
valid
)
{
for
(
i
<-
0
until
RoqSize
)
{
valid
(
i
)
:=
false
.
B
}
...
...
@@ -651,6 +683,8 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
wdata
.
commitType
:=
req
.
ctrl
.
commitType
wdata
.
pdest
:=
req
.
pdest
wdata
.
old_pdest
:=
req
.
old_pdest
wdata
.
ftqIdx
:=
req
.
cf
.
ftqPtr
wdata
.
ftqOffset
:=
req
.
cf
.
ftqOffset
wdata
.
pc
:=
req
.
cf
.
pc
wdata
.
crossPageIPFFix
:=
req
.
cf
.
crossPageIPFFix
// wdata.exceptionVec := req.cf.exceptionVec
...
...
@@ -759,14 +793,14 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
XSPerf
(
"writeback"
,
PopCount
((
0
until
RoqSize
).
map
(
i
=>
valid
(
i
)
&&
writebacked
(
i
))))
// XSPerf("enqInstr", PopCount(io.dp1Req.map(_.fire())))
// XSPerf("d2rVnR", PopCount(io.dp1Req.map(p => p.valid && !p.ready)))
XSPerf
(
"walkInstr
"
,
Mux
(
io
.
commits
.
isWalk
,
PopCount
(
io
.
commits
.
valid
),
0.
U
)
)
XSPerf
(
"walkCycle
"
,
state
===
s_walk
||
state
===
s_extrawalk
)
XSPerf
(
"walkInstr
Acc"
,
Mux
(
io
.
commits
.
isWalk
,
PopCount
(
io
.
commits
.
valid
),
0.
U
),
acc
=
true
)
XSPerf
(
"walkCycle
Acc"
,
state
===
s_walk
||
state
===
s_extrawalk
,
acc
=
true
)
val
deqNotWritebacked
=
valid
(
deqPtr
.
value
)
&&
!
writebacked
(
deqPtr
.
value
)
val
deqUopCommitType
=
io
.
commits
.
info
(
0
).
commitType
XSPerf
(
"waitNormalCycle
"
,
deqNotWritebacked
&&
deqUopCommitType
===
CommitType
.
NORMAL
)
XSPerf
(
"waitBranchCycle
"
,
deqNotWritebacked
&&
deqUopCommitType
===
CommitType
.
BRANCH
)
XSPerf
(
"waitLoadCycle
"
,
deqNotWritebacked
&&
deqUopCommitType
===
CommitType
.
LOAD
)
XSPerf
(
"waitStoreCycle
"
,
deqNotWritebacked
&&
deqUopCommitType
===
CommitType
.
STORE
)
XSPerf
(
"waitNormalCycle
Acc"
,
deqNotWritebacked
&&
deqUopCommitType
===
CommitType
.
NORMAL
,
acc
=
true
)
XSPerf
(
"waitBranchCycle
Acc"
,
deqNotWritebacked
&&
deqUopCommitType
===
CommitType
.
BRANCH
,
acc
=
true
)
XSPerf
(
"waitLoadCycle
Acc"
,
deqNotWritebacked
&&
deqUopCommitType
===
CommitType
.
LOAD
,
acc
=
true
)
XSPerf
(
"waitStoreCycle
Acc"
,
deqNotWritebacked
&&
deqUopCommitType
===
CommitType
.
STORE
,
acc
=
true
)
XSPerf
(
"roqHeadPC"
,
io
.
commits
.
info
(
0
).
pc
)
val
instrCnt
=
RegInit
(
0.
U
(
64.
W
))
...
...
@@ -806,11 +840,11 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
diffTestDebugLrScValid
(
i
)
:=
uop
.
diffTestDebugLrScValid
wpc
(
i
)
:=
SignExt
(
uop
.
cf
.
pc
,
XLEN
)
trapVec
(
i
)
:=
io
.
commits
.
valid
(
i
)
&&
(
state
===
s_idle
)
&&
uop
.
ctrl
.
isXSTrap
isRVC
(
i
)
:=
uop
.
cf
.
brUpdate
.
pd
.
isRVC
isRVC
(
i
)
:=
uop
.
cf
.
pd
.
isRVC
}
val
retireCounterFix
=
Mux
(
io
.
redirectOut
.
valid
,
1.
U
,
retireCounter
)
val
retirePCFix
=
SignExt
(
Mux
(
io
.
redirectOut
.
valid
,
debug_deqUop
.
cf
.
pc
,
debug_microOp
(
firstValidCommit
).
cf
.
pc
),
XLEN
)
val
retireInstFix
=
Mux
(
io
.
redirectOut
.
valid
,
debug_deqUop
.
cf
.
instr
,
debug_microOp
(
firstValidCommit
).
cf
.
instr
)
val
retireCounterFix
=
Mux
(
io
.
exception
.
valid
,
1.
U
,
retireCounter
)
val
retirePCFix
=
SignExt
(
Mux
(
io
.
exception
.
valid
,
debug_deqUop
.
cf
.
pc
,
debug_microOp
(
firstValidCommit
).
cf
.
pc
),
XLEN
)
val
retireInstFix
=
Mux
(
io
.
exception
.
valid
,
debug_deqUop
.
cf
.
instr
,
debug_microOp
(
firstValidCommit
).
cf
.
instr
)
val
scFailed
=
!
diffTestDebugLrScValid
(
0
)
&&
debug_deqUop
.
ctrl
.
fuType
===
FuType
.
mou
&&
...
...
src/main/scala/xiangshan/frontend/BPU.scala
浏览文件 @
2c87aa6f
...
...
@@ -13,6 +13,7 @@ trait HasBPUParameter extends HasXSParameter {
val
EnableCFICommitLog
=
true
val
EnbaleCFIPredLog
=
true
val
EnableBPUTimeRecord
=
EnableCFICommitLog
||
EnbaleCFIPredLog
val
EnableCommit
=
false
}
class
TableAddr
(
val
idxBits
:
Int
,
val
banks
:
Int
)
extends
XSBundle
with
HasIFUConst
{
...
...
@@ -42,7 +43,7 @@ class PredictorResponse extends XSBundle {
// the valid bits indicates whether a target is hit
val
targets
=
Vec
(
PredictWidth
,
UInt
(
VAddrBits
.
W
))
val
hits
=
Vec
(
PredictWidth
,
Bool
())
val
types
=
Vec
(
PredictWidth
,
UInt
(
2.
W
))
val
isBrs
=
Vec
(
PredictWidth
,
Bool
(
))
val
isRVC
=
Vec
(
PredictWidth
,
Bool
())
}
class
BimResp
extends
XSBundle
{
...
...
@@ -123,18 +124,24 @@ abstract class BasePredictor extends XSModule
val
pc
=
Flipped
(
ValidIO
(
UInt
(
VAddrBits
.
W
)))
val
hist
=
Input
(
UInt
(
HistoryLength
.
W
))
val
inMask
=
Input
(
UInt
(
PredictWidth
.
W
))
val
update
=
Flipped
(
ValidIO
(
new
CfiUpdateInfo
))
val
update
=
Flipped
(
ValidIO
(
new
FtqEntry
))
}
val
io
=
new
DefaultBasePredictorIO
val
debug
=
true
}
class
BrInfo
extends
XSBundle
{
val
metas
=
Vec
(
PredictWidth
,
new
BpuMeta
)
val
rasSp
=
UInt
(
log2Ceil
(
RasSize
).
W
)
val
rasTop
=
new
RASEntry
val
specCnt
=
Vec
(
PredictWidth
,
UInt
(
10.
W
))
}
class
BPUStageIO
extends
XSBundle
{
val
pc
=
UInt
(
VAddrBits
.
W
)
val
mask
=
UInt
(
PredictWidth
.
W
)
val
resp
=
new
PredictorResponse
val
brInfo
=
Vec
(
PredictWidth
,
new
BpuMeta
)
val
brInfo
=
new
BrInfo
}
...
...
@@ -173,7 +180,6 @@ abstract class BPUStage extends XSModule with HasBPUParameter
io
.
out
.
mask
:=
inLatch
.
mask
io
.
out
.
resp
<>
inLatch
.
resp
io
.
out
.
brInfo
:=
inLatch
.
brInfo
(
0
until
PredictWidth
).
map
(
i
=>
io
.
out
.
brInfo
(
i
).
sawNotTakenBranch
:=
io
.
pred
.
sawNotTakenBr
(
i
))
if
(
BPUDebug
)
{
val
jmpIdx
=
io
.
pred
.
jmpIdx
...
...
@@ -212,7 +218,7 @@ class BPUStage1 extends BPUStage {
ubtbResp
.
hits
.
asUInt
,
ubtbResp
.
takens
.
asUInt
,
~
ubtbResp
.
takens
.
asUInt
&
brMask
.
asUInt
,
ubtbResp
.
is_RVC
.
asUInt
)
}
if
(
EnableBPUTimeRecord
)
{
io
.
out
.
brInfo
.
map
(
_
.
debug_ubtb_cycle
:=
GTimer
())
io
.
out
.
brInfo
.
m
etas
.
m
ap
(
_
.
debug_ubtb_cycle
:=
GTimer
())
}
}
@chiselName
...
...
@@ -220,9 +226,9 @@ class BPUStage2 extends BPUStage {
// Use latched response from s1
val
btbResp
=
inLatch
.
resp
.
btb
val
bimResp
=
inLatch
.
resp
.
bim
takens
:=
VecInit
((
0
until
PredictWidth
).
map
(
i
=>
btbResp
.
hits
(
i
)
&&
(
btbResp
.
types
(
i
)
===
BTBtype
.
B
&&
bimResp
.
ctrs
(
i
)(
1
)
||
btbResp
.
types
(
i
)
=/=
BTBtype
.
B
)))
takens
:=
VecInit
((
0
until
PredictWidth
).
map
(
i
=>
btbResp
.
hits
(
i
)
&&
(
btbResp
.
isBrs
(
i
)
&&
bimResp
.
ctrs
(
i
)(
1
)
||
!
btbResp
.
isBrs
(
i
)
)))
targets
:=
btbResp
.
targets
brMask
:=
VecInit
((
0
until
PredictWidth
).
map
(
i
=>
btbResp
.
types
(
i
)
===
BTBtype
.
B
&&
btbResp
.
hits
(
i
)))
brMask
:=
VecInit
((
0
until
PredictWidth
).
map
(
i
=>
btbResp
.
isBrs
(
i
)
&&
btbResp
.
hits
(
i
)))
jalMask
:=
DontCare
hasHalfRVI
:=
btbResp
.
hits
(
PredictWidth
-
1
)
&&
!
btbResp
.
isRVC
(
PredictWidth
-
1
)
&&
HasCExtension
.
B
...
...
@@ -232,7 +238,7 @@ class BPUStage2 extends BPUStage {
btbResp
.
hits
.
asUInt
,
VecInit
(
bimResp
.
ctrs
.
map
(
_
(
1
))).
asUInt
)
}
if
(
EnableBPUTimeRecord
)
{
io
.
out
.
brInfo
.
map
(
_
.
debug_btb_cycle
:=
GTimer
())
io
.
out
.
brInfo
.
m
etas
.
m
ap
(
_
.
debug_btb_cycle
:=
GTimer
())
}
}
@chiselName
...
...
@@ -240,9 +246,7 @@ class BPUStage3 extends BPUStage {
class
S3IO
extends
XSBundle
{
val
predecode
=
Input
(
new
Predecode
)
val
realMask
=
Input
(
UInt
(
PredictWidth
.
W
))
val
prevHalf
=
Flipped
(
ValidIO
(
new
PrevHalfInstr
))
val
recover
=
Flipped
(
ValidIO
(
new
CfiUpdateInfo
))
val
redirect
=
Flipped
(
ValidIO
(
new
Redirect
))
}
val
s3IO
=
IO
(
new
S3IO
)
// TAGE has its own pipelines and the
...
...
@@ -253,7 +257,6 @@ class BPUStage3 extends BPUStage {
val
loopResp
=
io
.
in
.
resp
.
loop
.
exit
// realMask is in it
val
pdMask
=
s3IO
.
predecode
.
mask
val
pdLastHalf
=
s3IO
.
predecode
.
lastHalf
val
pds
=
s3IO
.
predecode
.
pd
...
...
@@ -274,14 +277,12 @@ 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
.
bits
.
taken
&&
HasCExtension
.
B
val
prevHalfTakenMask
=
prevHalfTaken
.
asUInt
val
brTakens
=
((
brs
&
brPred
|
prevHalfTakenMask
)
&
~
loopRes
)
val
brTakens
=
((
brs
&
brPred
)
&
~
loopRes
)
// we should provide btb resp as well
btbHits
:=
btbResp
.
hits
.
asUInt
|
prevHalfTakenMask
btbHits
:=
btbResp
.
hits
.
asUInt
// predict taken only if btb has a target, jal targets will be provided by IFU
takens
:=
VecInit
((
0
until
PredictWidth
).
map
(
i
=>
(
brTakens
(
i
)
||
jalrs
(
i
))
&&
btbHits
(
i
)
||
jals
(
i
)))
// predict taken only if btb has a target, jal
and br
targets will be provided by IFU
takens
:=
VecInit
((
0
until
PredictWidth
).
map
(
i
=>
jalrs
(
i
)
&&
btbHits
(
i
)
||
(
jals
(
i
)
||
brTakens
(
i
)
)))
targets
:=
inLatch
.
resp
.
btb
.
targets
...
...
@@ -302,17 +303,16 @@ class BPUStage3 extends BPUStage {
ras
.
io
.
callIdx
.
bits
:=
callIdx
ras
.
io
.
isRVC
:=
(
calls
&
RVCs
).
orR
//TODO: this is ugly
ras
.
io
.
isLastHalfRVI
:=
s3IO
.
predecode
.
hasLastHalfRVI
ras
.
io
.
re
cover
:=
s3IO
.
recover
ras
.
io
.
re
direct
:=
s3IO
.
redirect
ras
.
fires
<>
fires
for
(
i
<-
0
until
PredictWidth
){
io
.
out
.
brInfo
(
i
).
rasSp
:=
ras
.
io
.
meta
.
rasSp
io
.
out
.
brInfo
(
i
).
rasTopCtr
:=
ras
.
io
.
meta
.
rasTopCtr
io
.
out
.
brInfo
(
i
).
rasToqAddr
:=
ras
.
io
.
meta
.
rasToqAddr
io
.
out
.
brInfo
.
rasSp
:=
ras
.
io
.
meta
.
rasSp
io
.
out
.
brInfo
.
rasTop
:=
ras
.
io
.
meta
.
rasTop
}
takens
:=
VecInit
((
0
until
PredictWidth
).
map
(
i
=>
{
(
(
brTakens
(
i
)
||
jalrs
(
i
)
)
&&
btbHits
(
i
))
||
jals
(
i
)
||
(
jalrs
(
i
)
&&
btbHits
(
i
))
||
jals
(
i
)
||
brTakens
(
i
)
||
(
ras
.
io
.
out
.
valid
&&
rets
(
i
))
||
(!
ras
.
io
.
out
.
valid
&&
rets
(
i
)
&&
btbHits
(
i
))
}
...
...
@@ -326,26 +326,13 @@ class BPUStage3 extends BPUStage {
}
// we should provide the prediction for the first half RVI of the end of a fetch packet
// branch taken information would be lost in the prediction of the next packet,
// so we preserve this information here
when
(
hasHalfRVI
&&
btbResp
.
types
(
PredictWidth
-
1
)
===
BTBtype
.
B
&&
btbHits
(
PredictWidth
-
1
)
&&
HasCExtension
.
B
)
{
takens
(
PredictWidth
-
1
)
:=
brPred
(
PredictWidth
-
1
)
&&
!
loopRes
(
PredictWidth
-
1
)
}
// 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
)
&&
HasCExtension
.
B
)
{
targets
(
0
)
:=
s3IO
.
prevHalf
.
bits
.
target
}
// Wrap tage resp and tage meta in
// This is ugly
io
.
out
.
resp
.
tage
<>
io
.
in
.
resp
.
tage
io
.
out
.
resp
.
loop
<>
io
.
in
.
resp
.
loop
for
(
i
<-
0
until
PredictWidth
)
{
io
.
out
.
brInfo
(
i
).
tageMeta
:=
io
.
in
.
brInfo
(
i
).
tageMeta
io
.
out
.
brInfo
(
i
).
specCnt
:=
io
.
in
.
brInfo
(
i
).
specCnt
io
.
out
.
brInfo
.
metas
(
i
).
tageMeta
:=
io
.
in
.
brInfo
.
metas
(
i
).
tageMeta
io
.
out
.
brInfo
.
specCnt
(
i
)
:=
io
.
in
.
brInfo
.
specCnt
(
i
)
}
if
(
BPUDebug
)
{
...
...
@@ -357,7 +344,7 @@ class BPUStage3 extends BPUStage {
}
XSDebug
(
p
"brs:${Binary(brs)} jals:${Binary(jals)} jalrs:${Binary(jalrs)} calls:${Binary(calls)} rets:${Binary(rets)} rvcs:${Binary(RVCs)}\n"
)
XSDebug
(
p
"callIdx:${callIdx} retIdx:${retIdx}\n"
)
XSDebug
(
p
"brPred:${Binary(brPred)} loopRes:${Binary(loopRes)}
prevHalfTaken:${prevHalfTaken}
brTakens:${Binary(brTakens)}\n"
)
XSDebug
(
p
"brPred:${Binary(brPred)} loopRes:${Binary(loopRes)} brTakens:${Binary(brTakens)}\n"
)
}
if
(
EnbaleCFIPredLog
)
{
...
...
@@ -366,7 +353,7 @@ class BPUStage3 extends BPUStage {
}
if
(
EnableBPUTimeRecord
)
{
io
.
out
.
brInfo
.
map
(
_
.
debug_tage_cycle
:=
GTimer
())
io
.
out
.
brInfo
.
m
etas
.
m
ap
(
_
.
debug_tage_cycle
:=
GTimer
())
}
}
...
...
@@ -376,8 +363,8 @@ trait BranchPredictorComponents extends HasXSParameter {
val
bim
=
Module
(
new
BIM
)
val
tage
=
(
if
(
EnableBPD
)
{
Module
(
new
Tage
)
}
else
{
Module
(
new
FakeTage
)
})
val
loop
=
Module
(
new
LoopPredictor
)
val
preds
=
Seq
(
ubtb
,
btb
,
bim
,
tage
,
loop
)
//
val loop = Module(new LoopPredictor)
val
preds
=
Seq
(
ubtb
,
btb
,
bim
,
tage
/* , loop */
)
preds
.
map
(
_
.
io
:=
DontCare
)
}
...
...
@@ -387,10 +374,12 @@ class BPUReq extends XSBundle {
val
inMask
=
UInt
(
PredictWidth
.
W
)
}
abstract
class
BaseBPU
extends
XSModule
with
BranchPredictorComponents
with
HasBPUParameter
{
abstract
class
BaseBPU
extends
XSModule
with
BranchPredictorComponents
with
HasBPUParameter
with
HasIFUConst
{
val
io
=
IO
(
new
Bundle
()
{
// from backend
val
cfiUpdateInfo
=
Flipped
(
ValidIO
(
new
CfiUpdateInfo
))
val
redirect
=
Flipped
(
ValidIO
(
new
Redirect
))
val
commit
=
Flipped
(
ValidIO
(
new
FtqEntry
))
// from if1
val
in
=
Input
(
new
BPUReq
)
val
inFire
=
Input
(
Vec
(
4
,
Bool
()))
...
...
@@ -398,14 +387,12 @@ abstract class BaseBPU extends XSModule with BranchPredictorComponents with HasB
val
out
=
Vec
(
3
,
Output
(
new
BranchPrediction
))
// from if4
val
predecode
=
Input
(
new
Predecode
)
val
realMask
=
Input
(
UInt
(
PredictWidth
.
W
))
val
prevHalf
=
Flipped
(
ValidIO
(
new
PrevHalfInstr
))
// to if4, some bpu info used for updating
val
b
puMeta
=
Output
(
Vec
(
PredictWidth
,
new
BpuMeta
)
)
val
b
rInfo
=
Output
(
new
BrInfo
)
})
preds
.
map
(
p
=>
{
p
.
io
.
update
<>
io
.
c
fiUpdateInfo
p
.
io
.
update
<>
io
.
c
ommit
p
.
fires
<>
io
.
inFire
})
...
...
@@ -436,14 +423,14 @@ abstract class BaseBPU extends XSModule with BranchPredictorComponents with HasB
io
.
out
(
1
)
<>
s2
.
io
.
pred
io
.
out
(
2
)
<>
s3
.
io
.
pred
io
.
b
puMeta
:=
s3
.
io
.
out
.
brInfo
io
.
b
rInfo
:=
s3
.
io
.
out
.
brInfo
if
(
BPUDebug
)
{
XSDebug
(
io
.
inFire
(
3
),
"bpuMeta sent!\n"
)
for
(
i
<-
0
until
PredictWidth
)
{
val
b
=
io
.
b
puMeta
(
i
)
XSDebug
(
io
.
inFire
(
3
),
"brInfo(%d): ubtbWrWay:%d, ubtbHit:%d, btbWrWay:%d, b
tbHitJal:%d, bimCtr:%d, fetchIdx
:%d\n"
,
i
.
U
,
b
.
ubtbWriteWay
,
b
.
ubtbHits
,
b
.
btbWriteWay
,
b
.
b
tbHitJal
,
b
.
bimCtr
,
b
.
fetchIdx
)
val
b
=
io
.
b
rInfo
.
metas
(
i
)
XSDebug
(
io
.
inFire
(
3
),
"brInfo(%d): ubtbWrWay:%d, ubtbHit:%d, btbWrWay:%d, b
imCtr
:%d\n"
,
i
.
U
,
b
.
ubtbWriteWay
,
b
.
ubtbHits
,
b
.
btbWriteWay
,
b
.
b
imCtr
)
val
t
=
b
.
tageMeta
XSDebug
(
io
.
inFire
(
3
),
" tageMeta: pvder(%d):%d, altDiffers:%d, pvderU:%d, pvderCtr:%d, allocate(%d):%d\n"
,
t
.
provider
.
valid
,
t
.
provider
.
bits
,
t
.
altDiffers
,
t
.
providerU
,
t
.
providerCtr
,
t
.
allocate
.
valid
,
t
.
allocate
.
bits
)
...
...
@@ -459,7 +446,7 @@ class FakeBPU extends BaseBPU {
i
<>
DontCare
i
.
takens
:=
0.
U
})
io
.
b
puMeta
<>
DontCare
io
.
b
rInfo
<>
DontCare
}
@chiselName
class
BPU
extends
BaseBPU
{
...
...
@@ -467,12 +454,11 @@ class BPU extends BaseBPU {
//**********************Stage 1****************************//
val
s1_resp_in
=
Wire
(
new
PredictorResponse
)
val
s1_brInfo_in
=
Wire
(
Vec
(
PredictWidth
,
new
BpuMeta
)
)
val
s1_brInfo_in
=
Wire
(
new
BrInfo
)
s1_resp_in
.
tage
:=
DontCare
s1_resp_in
.
loop
:=
DontCare
s1_brInfo_in
:=
DontCare
(
0
until
PredictWidth
).
foreach
(
i
=>
s1_brInfo_in
(
i
).
fetchIdx
:=
i
.
U
)
val
s1_inLatch
=
RegEnable
(
io
.
in
,
s1_fire
)
ubtb
.
io
.
pc
.
valid
:=
s2_fire
...
...
@@ -484,8 +470,8 @@ class BPU extends BaseBPU {
// Wrap ubtb response into resp_in and brInfo_in
s1_resp_in
.
ubtb
<>
ubtb
.
io
.
out
for
(
i
<-
0
until
PredictWidth
)
{
s1_brInfo_in
(
i
).
ubtbWriteWay
:=
ubtb
.
io
.
uBTBMeta
.
writeWay
(
i
)
s1_brInfo_in
(
i
).
ubtbHits
:=
ubtb
.
io
.
uBTBMeta
.
hits
(
i
)
s1_brInfo_in
.
metas
(
i
).
ubtbWriteWay
:=
ubtb
.
io
.
uBTBMeta
.
writeWay
(
i
)
s1_brInfo_in
.
metas
(
i
).
ubtbHits
:=
ubtb
.
io
.
uBTBMeta
.
hits
(
i
)
}
btb
.
io
.
pc
.
valid
:=
s1_fire
...
...
@@ -497,8 +483,7 @@ class BPU extends BaseBPU {
// Wrap btb response into resp_in and brInfo_in
s1_resp_in
.
btb
<>
btb
.
io
.
resp
for
(
i
<-
0
until
PredictWidth
)
{
s1_brInfo_in
(
i
).
btbWriteWay
:=
btb
.
io
.
meta
.
writeWay
(
i
)
s1_brInfo_in
(
i
).
btbHitJal
:=
btb
.
io
.
meta
.
hitJal
(
i
)
s1_brInfo_in
.
metas
(
i
).
btbWriteWay
:=
btb
.
io
.
meta
.
writeWay
(
i
)
}
bim
.
io
.
pc
.
valid
:=
s1_fire
...
...
@@ -509,7 +494,7 @@ class BPU extends BaseBPU {
// Wrap bim response into resp_in and brInfo_in
s1_resp_in
.
bim
<>
bim
.
io
.
resp
for
(
i
<-
0
until
PredictWidth
)
{
s1_brInfo_in
(
i
).
bimCtr
:=
bim
.
io
.
meta
.
ctrs
(
i
)
s1_brInfo_in
.
metas
(
i
).
bimCtr
:=
bim
.
io
.
meta
.
ctrs
(
i
)
}
...
...
@@ -538,29 +523,24 @@ class BPU extends BaseBPU {
// Wrap tage response and meta into s3.io.in.bits
// This is ugly
loop
.
io
.
pc
.
valid
:=
s2_fire
loop
.
io
.
if3_fire
:=
s3_fire
loop
.
io
.
pc
.
bits
:=
s2
.
io
.
in
.
pc
loop
.
io
.
inMask
:=
io
.
predecode
.
mask
loop
.
io
.
respIn
.
taken
:=
s3
.
io
.
pred
.
taken
loop
.
io
.
respIn
.
jmpIdx
:=
s3
.
io
.
pred
.
jmpIdx
//
loop.io.pc.valid := s2_fire
//
loop.io.if3_fire := s3_fire
//
loop.io.pc.bits := s2.io.in.pc
//
loop.io.inMask := io.predecode.mask
//
loop.io.respIn.taken := s3.io.pred.taken
//
loop.io.respIn.jmpIdx := s3.io.pred.jmpIdx
s3
.
io
.
in
.
resp
.
tage
<>
tage
.
io
.
resp
s3
.
io
.
in
.
resp
.
loop
<>
loop
.
io
.
resp
//
s3.io.in.resp.loop <> loop.io.resp
for
(
i
<-
0
until
PredictWidth
)
{
s3
.
io
.
in
.
brInfo
(
i
).
tageMeta
:=
tage
.
io
.
meta
(
i
)
s3
.
io
.
in
.
brInfo
(
i
).
specCnt
:=
loop
.
io
.
meta
.
specCnts
(
i
)
s3
.
io
.
in
.
brInfo
.
metas
(
i
).
tageMeta
:=
tage
.
io
.
meta
(
i
)
// s3.io.in.brInfo.specCnt(i)
:= loop.io.meta.specCnts(i)
}
s3
.
s3IO
.
predecode
<>
io
.
predecode
s3
.
s3IO
.
realMask
:=
io
.
realMask
s3
.
s3IO
.
prevHalf
:=
io
.
prevHalf
s3
.
s3IO
.
recover
.
valid
<>
io
.
cfiUpdateInfo
.
valid
s3
.
s3IO
.
recover
.
bits
<>
io
.
cfiUpdateInfo
.
bits
s3
.
s3IO
.
redirect
<>
io
.
redirect
if
(
BPUDebug
)
{
if
(
debug_verbose
)
{
...
...
@@ -576,11 +556,17 @@ class BPU extends BaseBPU {
if
(
EnableCFICommitLog
)
{
val
buValid
=
io
.
cfiUpdateInfo
.
valid
&&
!
io
.
cfiUpdateInfo
.
bits
.
isReplay
val
buinfo
=
io
.
cfiUpdateInfo
.
bits
val
pd
=
buinfo
.
pd
val
tage_cycle
=
buinfo
.
bpuMeta
.
debug_tage_cycle
XSDebug
(
buValid
,
p
"cfi_update: isBr(${pd.isBr}) pc(${Hexadecimal(buinfo.pc)}) taken(${buinfo.taken}) mispred(${buinfo.isMisPred}) cycle($tage_cycle) hist(${Hexadecimal(buinfo.bpuMeta.predHist.asUInt)})\n"
)
val
buValid
=
io
.
commit
.
valid
val
buinfo
=
io
.
commit
.
bits
for
(
i
<-
0
until
PredictWidth
)
{
val
cfi_idx
=
buinfo
.
cfiIndex
val
isTaken
=
cfi_idx
.
valid
&&
cfi_idx
.
bits
===
i
.
U
val
isCfi
=
buinfo
.
valids
(
i
)
&&
(
buinfo
.
br_mask
(
i
)
||
cfi_idx
.
valid
&&
cfi_idx
.
bits
===
i
.
U
)
val
isBr
=
buinfo
.
br_mask
(
i
)
val
pc
=
packetAligned
(
buinfo
.
ftqPC
)
+
(
i
*
instBytes
).
U
-
Mux
((
i
==
0
).
B
&&
buinfo
.
hasLastPrev
,
2.
U
,
0.
U
)
val
tage_cycle
=
buinfo
.
metas
(
i
).
debug_tage_cycle
XSDebug
(
buValid
&&
isCfi
,
p
"cfi_update: isBr(${isBr}) pc(${Hexadecimal(pc)}) taken(${isTaken}) mispred(${buinfo.mispred(i)}) cycle($tage_cycle) hist(${Hexadecimal(buinfo.predHist.asUInt)})\n"
)
}
}
}
...
...
src/main/scala/xiangshan/frontend/Bim.scala
浏览文件 @
2c87aa6f
...
...
@@ -62,8 +62,7 @@ class BIM extends BasePredictor with BimParams {
val
u
=
io
.
update
.
bits
val
updateBank
=
bimAddr
.
getBank
(
u
.
pc
)
val
updateRow
=
bimAddr
.
getBankIdx
(
u
.
pc
)
val
updateRow
=
bimAddr
.
getBankIdx
(
u
.
ftqPC
)
val
wrbypass_ctrs
=
Reg
(
Vec
(
bypassEntries
,
Vec
(
BimBanks
,
UInt
(
2.
W
))))
...
...
@@ -76,48 +75,48 @@ class BIM extends BasePredictor with BimParams {
val
wrbypass_hit
=
wrbypass_hits
.
reduce
(
_
||
_
)
val
wrbypass_hit_idx
=
PriorityEncoder
(
wrbypass_hits
)
val
oldCtr
=
Mux
(
wrbypass_hit
&&
wrbypass_ctr_valids
(
wrbypass_hit_idx
)(
updateBank
),
wrbypass_ctrs
(
wrbypass_hit_idx
)(
updateBank
),
u
.
bpuMeta
.
bimCtr
)
val
newTaken
=
u
.
taken
val
newCtr
=
satUpdate
(
oldCtr
,
2
,
newTaken
)
val
oldCtrs
=
VecInit
((
0
until
BimBanks
).
map
(
b
=>
Mux
(
wrbypass_hit
&&
wrbypass_ctr_valids
(
wrbypass_hit_idx
)(
b
),
wrbypass_ctrs
(
wrbypass_hit_idx
)(
b
),
u
.
metas
(
b
).
bimCtr
)))
val
newTakens
=
VecInit
((
0
until
BimBanks
).
map
(
b
=>
u
.
cfiIndex
.
valid
&&
u
.
cfiIndex
.
bits
===
b
.
U
))
val
newCtrs
=
VecInit
((
0
until
BimBanks
).
map
(
b
=>
satUpdate
(
oldCtrs
(
b
),
2
,
newTakens
(
b
))))
// val oldSaturated = newCtr === oldCtr
val
needToUpdate
=
io
.
update
.
valid
&&
u
.
pd
.
isBr
&&
!
u
.
isReplay
val
needToUpdate
=
VecInit
((
0
until
PredictWidth
).
map
(
i
=>
io
.
update
.
valid
&&
u
.
br_mask
(
i
)
&&
u
.
valids
(
i
)))
when
(
reset
.
asBool
)
{
wrbypass_ctr_valids
.
foreach
(
_
.
foreach
(
_
:=
false
.
B
))}
when
(
needToUpdate
)
{
when
(
wrbypass_hit
)
{
wrbypass_ctrs
(
wrbypass_hit_idx
)(
updateBank
)
:=
newCtr
wrbypass_ctr_valids
(
wrbypass_hit_idx
)(
updateBank
)
:=
true
.
B
}
.
otherwise
{
wrbypass_ctrs
(
wrbypass_enq_idx
)(
updateBank
)
:=
newCtr
(
0
until
BimBanks
).
foreach
(
b
=>
wrbypass_ctr_valids
(
wrbypass_enq_idx
)(
b
)
:=
false
.
B
)
// reset valid bits
wrbypass_ctr_valids
(
wrbypass_enq_idx
)(
updateBank
)
:=
true
.
B
wrbypass_rows
(
wrbypass_enq_idx
)
:=
updateRow
wrbypass_enq_idx
:=
(
wrbypass_enq_idx
+
1.
U
)(
log2Up
(
bypassEntries
)-
1
,
0
)
for
(
b
<-
0
until
BimBanks
)
{
when
(
needToUpdate
(
b
))
{
when
(
wrbypass_hit
)
{
wrbypass_ctrs
(
wrbypass_hit_idx
)(
b
)
:=
newCtrs
(
b
)
wrbypass_ctr_valids
(
wrbypass_hit_idx
)(
b
)
:=
true
.
B
}
.
otherwise
{
wrbypass_ctrs
(
wrbypass_enq_idx
)(
b
)
:=
newCtrs
(
b
)
(
0
until
BimBanks
).
foreach
(
b
=>
wrbypass_ctr_valids
(
wrbypass_enq_idx
)(
b
)
:=
false
.
B
)
// reset valid bits
wrbypass_ctr_valids
(
wrbypass_enq_idx
)(
b
)
:=
true
.
B
wrbypass_rows
(
wrbypass_enq_idx
)
:=
updateRow
wrbypass_enq_idx
:=
(
wrbypass_enq_idx
+
1.
U
)(
log2Up
(
bypassEntries
)-
1
,
0
)
}
}
}
for
(
b
<-
0
until
BimBanks
)
{
bim
(
b
).
io
.
w
.
req
.
valid
:=
needToUpdate
&&
b
.
U
===
updateBank
||
doing_reset
bim
(
b
).
io
.
w
.
req
.
valid
:=
needToUpdate
(
b
)
||
doing_reset
bim
(
b
).
io
.
w
.
req
.
bits
.
setIdx
:=
Mux
(
doing_reset
,
resetRow
,
updateRow
)
bim
(
b
).
io
.
w
.
req
.
bits
.
data
:=
Mux
(
doing_reset
,
2.
U
(
2.
W
),
newCtr
)
}
if
(!
env
.
FPGAPlatform
&&
env
.
EnablePerfDebug
)
{
val
bimResp
=
Wire
(
Vec
(
PredictWidth
,
Bool
()))
for
(
i
<-
0
until
PredictWidth
)
{
bimResp
(
i
)
:=
io
.
resp
.
ctrs
(
i
)(
1
)
}
ExcitingUtils
.
addSource
(
bimResp
,
"bimResp"
)
bim
(
b
).
io
.
w
.
req
.
bits
.
data
:=
Mux
(
doing_reset
,
2.
U
(
2.
W
),
newCtrs
(
b
))
}
if
(
BPUDebug
&&
debug
)
{
XSDebug
(
doing_reset
,
"Reseting...\n"
)
XSDebug
(
"[update] v=%d pc=%x pnpc=%x tgt=%x"
,
io
.
update
.
valid
,
u
.
pc
,
u
.
pnpc
,
u
.
target
)
XSDebug
(
"[update] taken=%d isMisPred=%d"
,
u
.
taken
,
u
.
isMisPred
)
XSDebug
(
false
,
true
.
B
,
p
"brTag=${u.brTag} pd.isBr=${u.pd.isBr} brInfo.bimCtr=${Binary(u.bpuMeta.bimCtr)}\n"
)
XSDebug
(
"needToUpdate=%d updateBank=%x updateRow=%x newCtr=%b oldCtr=%b\n"
,
needToUpdate
,
updateBank
,
updateRow
,
newCtr
,
oldCtr
)
XSDebug
(
"[update] v=%d pc=%x valids=%b, tgt=%x\n"
,
io
.
update
.
valid
,
u
.
ftqPC
,
u
.
valids
.
asUInt
,
u
.
target
)
XSDebug
(
"[update] brMask=%b, taken=%b isMisPred=%b\n"
,
u
.
br_mask
.
asUInt
,
newTakens
.
asUInt
,
u
.
mispred
.
asUInt
)
for
(
i
<-
0
until
BimBanks
)
{
XSDebug
(
true
.
B
,
p
"bimCtr(${i.U})=${Binary(u.metas(i).bimCtr)} oldCtr=${Binary(oldCtrs(i))} newCtr=${Binary(newCtrs(i))}\n"
)
}
XSDebug
(
"needToUpdate=%b updateRow=%x\n"
,
needToUpdate
.
asUInt
,
updateRow
)
XSDebug
(
"[wrbypass] hit=%d hits=%b\n"
,
wrbypass_hit
,
wrbypass_hits
.
asUInt
)
}
...
...
src/main/scala/xiangshan/frontend/Btb.scala
浏览文件 @
2c87aa6f
...
...
@@ -36,16 +36,16 @@ class BtbMetaEntry() extends XSBundle with BTBParams {
val
valid
=
Bool
()
// TODO: don't need full length of tag
val
tag
=
UInt
((
VAddrBits
-
log2Ceil
(
nRows
)
-
log2Ceil
(
PredictWidth
)
-
instOffsetBits
).
W
)
val
btbType
=
UInt
(
2.
W
)
val
isBr
=
Bool
(
)
val
isRVC
=
Bool
()
}
object
BtbMetaEntry
{
def
apply
(
tag
:
UInt
,
btbType
:
UInt
,
isRVC
:
Bool
)
=
{
def
apply
(
tag
:
UInt
,
isBr
:
UInt
,
isRVC
:
Bool
)
=
{
val
e
=
Wire
(
new
BtbMetaEntry
)
e
.
valid
:=
true
.
B
e
.
tag
:=
tag
e
.
btbType
:=
btbType
e
.
isBr
:=
isBr
e
.
isRVC
:=
isRVC
e
}
...
...
@@ -55,12 +55,11 @@ class BTB extends BasePredictor with BTBParams{
class
BTBResp
extends
Resp
{
val
targets
=
Vec
(
PredictWidth
,
UInt
(
VAddrBits
.
W
))
val
hits
=
Vec
(
PredictWidth
,
Bool
())
val
types
=
Vec
(
PredictWidth
,
UInt
(
2.
W
))
val
isBrs
=
Vec
(
PredictWidth
,
Bool
(
))
val
isRVC
=
Vec
(
PredictWidth
,
Bool
())
}
class
BTBMeta
extends
Meta
{
val
writeWay
=
Vec
(
PredictWidth
,
UInt
(
log2Up
(
BtbWays
).
W
))
val
hitJal
=
Vec
(
PredictWidth
,
Bool
())
}
class
BTBFromOthers
extends
FromOthers
{}
...
...
@@ -157,10 +156,10 @@ class BTB extends BasePredictor with BTBParams{
// Use real pc to calculate the target
io
.
resp
.
targets
(
b
)
:=
Mux
(
data_entry
.
extended
,
if2_edataRead
,
Cat
(
if2_pc
(
VAddrBits
-
1
,
lowerBitsSize
+
instOffsetBits
),
data_entry
.
lower
,
0.
U
(
instOffsetBits
.
W
)))
io
.
resp
.
hits
(
b
)
:=
if2_bankHits
(
b
)
io
.
resp
.
types
(
b
)
:=
meta_entry
.
btbType
io
.
resp
.
isBrs
(
b
)
:=
meta_entry
.
isBr
io
.
resp
.
isRVC
(
b
)
:=
meta_entry
.
isRVC
io
.
meta
.
writeWay
(
b
)
:=
writeWay
(
b
)
io
.
meta
.
hitJal
(
b
)
:=
if2_bankHits
(
b
)
&&
meta_entry
.
btbType
===
BTBtype
.
J
//
io.meta.hitJal(b) := if2_bankHits(b) && meta_entry.btbType === BTBtype.J
}
def
pdInfoToBTBtype
(
pd
:
PreDecodeInfo
)
=
{
...
...
@@ -173,30 +172,34 @@ class BTB extends BasePredictor with BTBParams{
}
val
u
=
io
.
update
.
bits
val
new_target
=
Mux
(
u
.
pd
.
isBr
,
u
.
brTarget
,
u
.
target
)
val
cfi_pc
=
packetAligned
(
u
.
ftqPC
)
+
(
u
.
cfiIndex
.
bits
<<
instOffsetBits
)
val
new_target
=
u
.
target
val
new_lower
=
new_target
(
lowerBitsSize
+
instOffsetBits
-
1
,
instOffsetBits
)
val
update_pc_higher
=
u
.
pc
(
VAddrBits
-
1
,
lowerBitsSize
+
instOffsetBits
)
val
update_pc_higher
=
cfi_
pc
(
VAddrBits
-
1
,
lowerBitsSize
+
instOffsetBits
)
val
update_target_higher
=
new_target
(
VAddrBits
-
1
,
lowerBitsSize
+
instOffsetBits
)
val
higher_identical
=
update_pc_higher
===
update_target_higher
val
new_extended
=
!
higher_identical
val
updateWay
=
u
.
bpuMeta
.
btbWriteWay
val
updateBankIdx
=
btbAddr
.
getBank
(
u
.
pc
)
val
updateRow
=
btbAddr
.
getBankIdx
(
u
.
pc
)
val
updateType
=
pdInfoToBTBtype
(
u
.
pd
)
val
metaWrite
=
BtbMetaEntry
(
btbAddr
.
getTag
(
u
.
pc
),
updateType
,
u
.
pd
.
isRVC
)
val
updateWay
=
u
.
metas
(
u
.
cfiIndex
.
bits
).
btbWriteWay
val
updateBank
=
u
.
cfiIndex
.
bits
val
updateRow
=
btbAddr
.
getBankIdx
(
cfi_pc
)
val
updateIsBr
=
u
.
br_mask
(
u
.
cfiIndex
.
bits
)
val
updateTaken
=
u
.
cfiIndex
.
valid
// TODO: remove isRVC
val
metaWrite
=
BtbMetaEntry
(
btbAddr
.
getTag
(
cfi_pc
),
updateIsBr
,
u
.
cfiIsRVC
)
val
dataWrite
=
BtbDataEntry
(
new_lower
,
new_extended
)
val
jalFirstEncountered
=
!
u
.
isMisPred
&&
!
u
.
bpuMeta
.
btbHitJal
&&
updateType
===
BTBtype
.
J
val
updateValid
=
io
.
update
.
valid
&&
(
u
.
isMisPred
||
jalFirstEncountered
)
&&
!
u
.
isReplay
//
val jalFirstEncountered = !u.isMisPred && !u.bpuMeta.btbHitJal && updateType === BTBtype.J
val
updateValid
=
io
.
update
.
valid
&&
updateTaken
// Update btb
for
(
w
<-
0
until
BtbWays
)
{
for
(
b
<-
0
until
BtbBanks
)
{
meta
(
w
)(
b
).
io
.
w
.
req
.
valid
:=
updateValid
&&
b
.
U
===
updateBank
Idx
&&
w
.
U
===
updateWay
meta
(
w
)(
b
).
io
.
w
.
req
.
valid
:=
updateValid
&&
b
.
U
===
updateBank
&&
w
.
U
===
updateWay
meta
(
w
)(
b
).
io
.
w
.
req
.
bits
.
setIdx
:=
updateRow
meta
(
w
)(
b
).
io
.
w
.
req
.
bits
.
data
:=
metaWrite
data
(
w
)(
b
).
io
.
w
.
req
.
valid
:=
updateValid
&&
b
.
U
===
updateBank
Idx
&&
w
.
U
===
updateWay
data
(
w
)(
b
).
io
.
w
.
req
.
valid
:=
updateValid
&&
b
.
U
===
updateBank
&&
w
.
U
===
updateWay
data
(
w
)(
b
).
io
.
w
.
req
.
bits
.
setIdx
:=
updateRow
data
(
w
)(
b
).
io
.
w
.
req
.
bits
.
data
:=
dataWrite
}
...
...
@@ -206,18 +209,6 @@ class BTB extends BasePredictor with BTBParams{
edata
.
io
.
w
.
req
.
bits
.
setIdx
:=
updateRow
edata
.
io
.
w
.
req
.
bits
.
data
:=
u
.
target
if
(!
env
.
FPGAPlatform
&&
env
.
EnablePerfDebug
)
{
val
btbAns
=
Wire
(
Vec
(
PredictWidth
,
new
PredictorAnswer
))
btbAns
.
zipWithIndex
.
foreach
{
case
(
x
,
i
)
=>
x
.
hit
:=
io
.
resp
.
hits
(
i
)
x
.
taken
:=
DontCare
x
.
target
:=
io
.
resp
.
targets
(
i
)
}
ExcitingUtils
.
addSource
(
btbAns
,
"btbAns"
)
}
if
(
BPUDebug
&&
debug
)
{
val
debug_verbose
=
true
...
...
@@ -228,18 +219,18 @@ class BTB extends BasePredictor with BTBParams{
if
(
debug_verbose
)
{
for
(
i
<-
0
until
BtbBanks
){
for
(
j
<-
0
until
BtbWays
)
{
XSDebug
(
validLatch
,
"read_resp[w=%d][b=%d][r=%d] is valid(%d) mask(%d), tag=0x%x, lower=0x%x,
type
=%d, isExtend=%d, isRVC=%d\n"
,
j
.
U
,
i
.
U
,
if2_row
,
if2_metaRead
(
j
)(
i
).
valid
,
if2_mask
(
i
),
if2_metaRead
(
j
)(
i
).
tag
,
if2_dataRead
(
j
)(
i
).
lower
,
if2_metaRead
(
j
)(
i
).
btbType
,
if2_dataRead
(
j
)(
i
).
extended
,
if2_metaRead
(
j
)(
i
).
isRVC
)
XSDebug
(
validLatch
,
"read_resp[w=%d][b=%d][r=%d] is valid(%d) mask(%d), tag=0x%x, lower=0x%x,
isBr
=%d, isExtend=%d, isRVC=%d\n"
,
j
.
U
,
i
.
U
,
if2_row
,
if2_metaRead
(
j
)(
i
).
valid
,
if2_mask
(
i
),
if2_metaRead
(
j
)(
i
).
tag
,
if2_dataRead
(
j
)(
i
).
lower
,
if2_metaRead
(
j
)(
i
).
isBr
,
if2_dataRead
(
j
)(
i
).
extended
,
if2_metaRead
(
j
)(
i
).
isRVC
)
}
}
}
for
(
i
<-
0
until
BtbBanks
)
{
XSDebug
(
validLatch
&&
if2_bankHits
(
i
),
"resp(%d): bank(%d) hits, tgt=%x, isRVC=%d,
type
=%d\n"
,
i
.
U
,
i
.
U
,
io
.
resp
.
targets
(
i
),
io
.
resp
.
isRVC
(
i
),
io
.
resp
.
type
s
(
i
))
XSDebug
(
validLatch
&&
if2_bankHits
(
i
),
"resp(%d): bank(%d) hits, tgt=%x, isRVC=%d,
isBr
=%d\n"
,
i
.
U
,
i
.
U
,
io
.
resp
.
targets
(
i
),
io
.
resp
.
isRVC
(
i
),
io
.
resp
.
isBr
s
(
i
))
}
XSDebug
(
updateValid
,
"update_req: cycle=%d, pc=0x%x, target=0x%x, misPred=%d, lower=%x, extended=%d, way=%d, bank=%d, row=0x%x\n"
,
u
.
bpuMeta
.
debug_btb_cycle
,
u
.
pc
,
new_target
,
u
.
isMisPred
,
new_lower
,
new_extended
,
updateWay
,
updateBankIdx
,
updateRow
)
u
.
metas
(
u
.
cfiIndex
.
bits
).
debug_btb_cycle
,
cfi_pc
,
new_target
,
u
.
mispred
(
u
.
cfiIndex
.
bits
),
new_lower
,
new_extended
,
updateWay
,
updateBank
,
updateRow
)
for
(
i
<-
0
until
BtbBanks
)
{
// Conflict when not hit and allocating a valid entry
val
conflict
=
if2_metaRead
(
allocWays
(
i
))(
i
).
valid
&&
!
if2_bankHits
(
i
)
...
...
src/main/scala/xiangshan/frontend/Frontend.scala
浏览文件 @
2c87aa6f
...
...
@@ -40,11 +40,13 @@ class FrontendImp (outer: Frontend) extends LazyModuleImp(outer)
val
l1plusPrefetcher
=
Module
(
new
L1plusPrefetcher
)
val
instrUncache
=
outer
.
instrUncache
.
module
val
needFlush
=
io
.
backend
.
redirect
.
valid
val
needFlush
=
io
.
backend
.
redirect
_cfiUpdate
.
valid
// from backend
ifu
.
io
.
redirect
<>
io
.
backend
.
redirect
ifu
.
io
.
cfiUpdateInfo
<>
io
.
backend
.
cfiUpdateInfo
ifu
.
io
.
redirect
<>
io
.
backend
.
redirect_cfiUpdate
ifu
.
io
.
commitUpdate
<>
io
.
backend
.
commit_cfiUpdate
ifu
.
io
.
ftqEnqPtr
<>
io
.
backend
.
ftqEnqPtr
ifu
.
io
.
ftqLeftOne
<>
io
.
backend
.
ftqLeftOne
// to icache
val
grantClientId
=
clientId
(
io
.
icacheMemGrant
.
bits
.
id
)
val
grantEntryId
=
entryId
(
io
.
icacheMemGrant
.
bits
.
id
)
...
...
@@ -86,6 +88,8 @@ class FrontendImp (outer: Frontend) extends LazyModuleImp(outer)
ibuffer
.
io
.
flush
:=
needFlush
// ibuffer to backend
io
.
backend
.
cfVec
<>
ibuffer
.
io
.
out
// ifu to backend
io
.
backend
.
fetchInfo
<>
ifu
.
io
.
toFtq
// for(out <- ibuffer.io.out){
// XSInfo(out.fire(),
...
...
src/main/scala/xiangshan/frontend/IFU.scala
浏览文件 @
2c87aa6f
此差异已折叠。
点击以展开。
src/main/scala/xiangshan/frontend/Ibuffer.scala
浏览文件 @
2c87aa6f
...
...
@@ -6,7 +6,7 @@ import chisel3.util._
import
xiangshan._
import
utils._
import
xiangshan.backend.fu.HasExceptionNO
import
xiangshan.backend.ftq.FtqPtr
class
IbufPtr
extends
CircularQueuePtr
(
IbufPtr
.
IBufSize
)
{
}
...
...
@@ -31,12 +31,13 @@ class Ibuffer extends XSModule with HasCircularQueuePtrHelper {
class
IBufEntry
extends
XSBundle
{
val
inst
=
UInt
(
32.
W
)
val
pc
=
UInt
(
VAddrBits
.
W
)
val
pnpc
=
UInt
(
VAddrBits
.
W
)
val
brInfo
=
new
BpuMeta
val
pd
=
new
PreDecodeInfo
val
ipf
=
Bool
()
val
acf
=
Bool
()
val
crossPageIPFFix
=
Bool
()
val
pred_taken
=
Bool
()
val
ftqPtr
=
new
FtqPtr
val
ftqOffset
=
UInt
(
log2Ceil
(
PredictWidth
).
W
)
}
// Ignore
...
...
@@ -92,12 +93,13 @@ class Ibuffer extends XSModule with HasCircularQueuePtrHelper {
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
inWire
.
pred_taken
:=
io
.
in
.
bits
.
pred_taken
(
i
)
inWire
.
ftqPtr
:=
io
.
in
.
bits
.
ftqPtr
inWire
.
ftqOffset
:=
i
.
U
// ibuf(tail_vec(offset(i)).value) := inWire
}
ibuf
.
io
.
waddr
(
i
)
:=
tail_vec
(
offset
(
i
)).
value
...
...
@@ -130,11 +132,11 @@ class Ibuffer extends XSModule with HasCircularQueuePtrHelper {
io
.
out
(
i
).
bits
.
exceptionVec
(
instrPageFault
)
:=
outWire
.
ipf
io
.
out
(
i
).
bits
.
exceptionVec
(
instrAccessFault
)
:=
outWire
.
acf
// io.out(i).bits.brUpdate := outWire.brInfo
io
.
out
(
i
).
bits
.
brUpdate
:=
DontCare
io
.
out
(
i
).
bits
.
brUpdate
.
pc
:=
outWire
.
pc
io
.
out
(
i
).
bits
.
brUpdate
.
pnpc
:=
outWire
.
pnpc
io
.
out
(
i
).
bits
.
brUpdate
.
pd
:=
outWire
.
pd
io
.
out
(
i
).
bits
.
brUpdate
.
bpuMeta
:=
outWire
.
brInfo
io
.
out
(
i
).
bits
.
pd
:=
outWire
.
pd
io
.
out
(
i
).
bits
.
pred_taken
:=
outWire
.
pred_taken
io
.
out
(
i
).
bits
.
ftqPtr
:=
outWire
.
ftqPtr
io
.
out
(
i
).
bits
.
ftqOffset
:=
outWire
.
ftqOffset
io
.
out
(
i
).
bits
.
crossPageIPFFix
:=
outWire
.
crossPageIPFFix
val
head_wire
=
next_head_ptr
.
value
+
i
.
U
...
...
src/main/scala/xiangshan/frontend/LoopPredictor.scala
浏览文件 @
2c87aa6f
此差异已折叠。
点击以展开。
src/main/scala/xiangshan/frontend/RAS.scala
浏览文件 @
2c87aa6f
此差异已折叠。
点击以展开。
src/main/scala/xiangshan/frontend/Tage.scala
浏览文件 @
2c87aa6f
...
...
@@ -62,7 +62,6 @@ class TageResp extends TageBundle {
class
TageUpdate
extends
TageBundle
{
val
pc
=
UInt
(
VAddrBits
.
W
)
val
fetchIdx
=
UInt
(
log2Up
(
TageBanks
).
W
)
val
hist
=
UInt
(
HistoryLength
.
W
)
// update tag and ctr
val
mask
=
Vec
(
TageBanks
,
Bool
())
...
...
@@ -318,12 +317,12 @@ class TageTable(val nRows: Int, val histLen: Int, val tagLen: Int, val uBitPerio
XSDebug
(
RegNext
(
io
.
req
.
valid
),
"TageTableResp: hits:%b, maskLatch is %b\n"
,
if3_req_rhits
.
asUInt
,
if3_mask
)
XSDebug
(
RegNext
(
io
.
req
.
valid
)
&&
!
if3_req_rhits
.
reduce
(
_
||
_
),
"TageTableResp: no hits!\n"
)
XSDebug
(
io
.
update
.
mask
.
reduce
(
_
||
_
),
"update Table: pc:%x,
fetchIdx:%d,
hist:%x, bank:%d, taken:%d, alloc:%d, oldCtr:%d\n"
,
u
.
pc
,
u
.
fetchIdx
,
u
.
hist
,
b
,
u
.
taken
(
b
),
u
.
alloc
(
b
),
u
.
oldCtr
(
b
))
XSDebug
(
io
.
update
.
mask
.
reduce
(
_
||
_
),
"update Table: pc:%x, hist:%x, bank:%d, taken:%d, alloc:%d, oldCtr:%d\n"
,
u
.
pc
,
u
.
hist
,
b
,
u
.
taken
(
b
),
u
.
alloc
(
b
),
u
.
oldCtr
(
b
))
XSDebug
(
io
.
update
.
mask
.
reduce
(
_
||
_
),
"update Table: writing tag:%b, ctr%d in idx:%d\n"
,
update_wdata
(
b
).
tag
,
update_wdata
(
b
).
ctr
,
update_idx
)
XSDebug
(
io
.
update
.
mask
.
reduce
(
_
||
_
),
"update u: pc:%x,
fetchIdx:%d,
hist:%x, bank:%d, writing in u:%b\n"
,
u
.
pc
,
u
.
fetchIdx
,
u
.
hist
,
ub
,
io
.
update
.
u
(
ub
))
XSDebug
(
io
.
update
.
mask
.
reduce
(
_
||
_
),
"update u: pc:%x, hist:%x, bank:%d, writing in u:%b\n"
,
u
.
pc
,
u
.
hist
,
ub
,
io
.
update
.
u
(
ub
))
val
updateBank
=
PriorityEncoder
(
io
.
update
.
mask
)
XSDebug
(
wrbypass_hit
&&
wrbypass_ctr_valids
(
wrbypass_hit_idx
)(
updateBank
),
...
...
@@ -394,6 +393,7 @@ class Tage extends BaseTage {
req
.
bits
.
pc
:=
io
.
pc
.
bits
req
.
bits
.
hist
:=
io
.
hist
req
.
bits
.
mask
:=
io
.
inMask
if
(!
EnableSC
)
{
t
.
io
.
update
:=
DontCare
}
t
}
}
...
...
@@ -421,12 +421,12 @@ class Tage extends BaseTage {
val
debug_hist_s3
=
RegEnable
(
debug_hist_s2
,
enable
=
s3_fire
)
val
u
=
io
.
update
.
bits
val
updateValid
=
io
.
update
.
valid
&&
!
io
.
update
.
bits
.
isReplay
val
updateHist
=
u
.
bpuMeta
.
predHist
.
asUInt
val
updateValid
s
=
u
.
valids
.
map
(
v
=>
v
&&
io
.
update
.
valid
)
val
updateHist
=
u
.
predHist
.
asUInt
val
update
IsBr
=
u
.
pd
.
isBr
val
updateMeta
=
u
.
bpuMeta
.
tageMeta
val
updateMisPred
=
u
.
isMisPred
&&
updateIsBr
val
update
BrMask
=
u
.
br_mask
val
updateMeta
s
=
VecInit
(
u
.
metas
.
map
(
_
.
tageMeta
))
val
updateMisPred
=
u
.
mispred
val
updateMask
=
WireInit
(
0.
U
.
asTypeOf
(
Vec
(
TageNTables
,
Vec
(
TageBanks
,
Bool
()))))
val
updateUMask
=
WireInit
(
0.
U
.
asTypeOf
(
Vec
(
TageNTables
,
Vec
(
TageBanks
,
Bool
()))))
...
...
@@ -447,10 +447,10 @@ class Tage extends BaseTage {
scUpdateTaken
:=
DontCare
scUpdateOldCtrs
:=
DontCare
val
updateSCMeta
=
u
.
bpuMeta
.
tageMeta
.
scMeta
val
updateTageMisPred
=
updateMeta
.
taken
=/=
u
.
taken
&&
updateIsBr
val
updateSCMeta
s
=
VecInit
(
u
.
metas
.
map
(
_
.
tageMeta
.
scMeta
))
val
updateTageMisPred
s
=
VecInit
((
0
until
PredictWidth
).
map
(
i
=>
updateMetas
(
i
).
taken
=/=
u
.
takens
(
i
)
&&
updateBrMask
(
i
)))
val
updateBank
=
u
.
pc
(
log2Ceil
(
TageBanks
)+
instOffsetBits
-
1
,
instOffsetBits
)
//
val updateBank = u.pc(log2Ceil(TageBanks)+instOffsetBits-1, instOffsetBits)
// access tag tables and output meta info
for
(
w
<-
0
until
TageBanks
)
{
...
...
@@ -544,9 +544,12 @@ class Tage extends BaseTage {
}
}
val
isUpdateTaken
=
updateValid
&&
updateBank
===
w
.
U
&&
u
.
taken
&&
updateIsBr
when
(
updateIsBr
&&
updateValid
&&
updateBank
===
w
.
U
)
{
val
updateValid
=
updateValids
(
w
)
val
updateMeta
=
updateMetas
(
w
)
val
updateIsBr
=
updateBrMask
(
w
)
val
isUpdateTaken
=
updateValid
&&
u
.
takens
(
w
)
&&
updateIsBr
val
updateMisPred
=
updateTageMisPreds
(
w
)
when
(
updateValid
&&
updateIsBr
)
{
when
(
updateMeta
.
provider
.
valid
)
{
val
provider
=
updateMeta
.
provider
.
bits
...
...
@@ -562,50 +565,49 @@ class Tage extends BaseTage {
updateAlloc
(
provider
)(
w
)
:=
false
.
B
}
}
}
when
(
updateValid
&&
updateTageMisPred
)
{
val
idx
=
updateBank
val
allocate
=
updateMeta
.
allocate
when
(
allocate
.
valid
)
{
updateMask
(
allocate
.
bits
)(
idx
)
:=
true
.
B
updateTaken
(
allocate
.
bits
)(
idx
)
:=
u
.
taken
updateAlloc
(
allocate
.
bits
)(
idx
)
:=
true
.
B
updateUMask
(
allocate
.
bits
)(
idx
)
:=
true
.
B
updateU
(
allocate
.
bits
)(
idx
)
:=
0.
U
}.
otherwise
{
val
provider
=
updateMeta
.
provider
val
decrMask
=
Mux
(
provider
.
valid
,
~
LowerMask
(
UIntToOH
(
provider
.
bits
),
TageNTables
),
0.
U
(
TageNTables
.
W
))
for
(
i
<-
0
until
TageNTables
)
{
when
(
decrMask
(
i
))
{
updateUMask
(
i
)(
idx
)
:=
true
.
B
updateU
(
i
)(
idx
)
:=
0.
U
when
(
updateValid
&&
updateMisPred
)
{
val
allocate
=
updateMeta
.
allocate
when
(
allocate
.
valid
)
{
updateMask
(
allocate
.
bits
)(
w
)
:=
true
.
B
updateTaken
(
allocate
.
bits
)(
w
)
:=
isUpdateTaken
updateAlloc
(
allocate
.
bits
)(
w
)
:=
true
.
B
updateUMask
(
allocate
.
bits
)(
w
)
:=
true
.
B
updateU
(
allocate
.
bits
)(
w
)
:=
0.
U
}.
otherwise
{
val
provider
=
updateMeta
.
provider
val
decrMask
=
Mux
(
provider
.
valid
,
~
LowerMask
(
UIntToOH
(
provider
.
bits
),
TageNTables
),
0.
U
(
TageNTables
.
W
))
for
(
i
<-
0
until
TageNTables
)
{
when
(
decrMask
(
i
))
{
updateUMask
(
i
)(
w
)
:=
true
.
B
updateU
(
i
)(
w
)
:=
0.
U
}
}
}
}
}
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"
)
}
}
}
// 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
)
{
...
...
@@ -616,38 +618,32 @@ class Tage extends BaseTage {
tables
(
i
).
io
.
update
.
uMask
(
w
)
:=
updateUMask
(
i
)(
w
)
tables
(
i
).
io
.
update
.
u
(
w
)
:=
updateU
(
i
)(
w
)
tables
(
i
).
io
.
update
.
pc
:=
packetAligned
(
u
.
ftqPC
)
+
(
w
<<
instOffsetBits
).
U
}
// use fetch pc instead of instruction pc
tables
(
i
).
io
.
update
.
pc
:=
u
.
pc
tables
(
i
).
io
.
update
.
hist
:=
updateHist
tables
(
i
).
io
.
update
.
fetchIdx
:=
u
.
bpuMeta
.
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
.
bpuMeta
.
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
// }
if
(!
env
.
FPGAPlatform
&&
env
.
EnablePerfDebug
)
{
val
tageAns
=
Wire
(
Vec
(
PredictWidth
,
new
PredictorAnswer
))
tageAns
.
zipWithIndex
.
foreach
{
case
(
x
,
i
)
=>
x
.
hit
:=
io
.
resp
.
hits
(
i
)
x
.
taken
:=
io
.
resp
.
takens
(
i
)
x
.
target
:=
DontCare
}
ExcitingUtils
.
addSource
(
tageAns
,
"tageAns"
)
}
if
(
BPUDebug
&&
debug
)
{
val
m
=
updateMeta
val
bri
=
u
.
bpuMeta
for
(
b
<-
0
until
TageBanks
)
{
val
m
=
updateMetas
(
b
)
val
bri
=
u
.
metas
(
b
)
XSDebug
(
updateValids
(
b
),
"update(%d): pc=%x, fetchpc=%x, cycle=%d, hist=%x, taken:%d, misPred:%d, bimctr:%d, pvdr(%d):%d, altDiff:%d, pvdrU:%d, pvdrCtr:%d, alloc(%d):%d\n"
,
b
.
U
,
u
.
ftqPC
,
packetAligned
(
u
.
ftqPC
)+(
b
<<
instOffsetBits
).
U
,
bri
.
debug_tage_cycle
,
updateHist
,
u
.
takens
(
b
),
u
.
mispred
(
b
),
bri
.
bimCtr
,
m
.
provider
.
valid
,
m
.
provider
.
bits
,
m
.
altDiffers
,
m
.
providerU
,
m
.
providerCtr
,
m
.
allocate
.
valid
,
m
.
allocate
.
bits
)
}
val
if4_resps
=
RegEnable
(
if3_resps
,
s3_fire
)
XSDebug
(
io
.
pc
.
valid
,
"req: pc=0x%x, hist=%x\n"
,
io
.
pc
.
bits
,
io
.
hist
)
XSDebug
(
s3_fire
,
"s3Fire:%d, resp: pc=%x, hist=%x\n"
,
s3_fire
,
debug_pc_s2
,
debug_hist_s2
)
...
...
@@ -656,10 +652,8 @@ class Tage extends BaseTage {
for
(
i
<-
0
until
TageNTables
)
{
XSDebug
(
RegNext
(
s3_fire
),
"TageTable(%d): valids:%b, resp_ctrs:%b, resp_us:%b\n"
,
i
.
U
,
VecInit
(
if4_resps
(
i
).
map
(
_
.
valid
)).
asUInt
,
Cat
(
if4_resps
(
i
).
map
(
_
.
bits
.
ctr
)),
Cat
(
if4_resps
(
i
).
map
(
_
.
bits
.
u
)))
}
XSDebug
(
io
.
update
.
valid
,
"update: pc=%x, fetchpc=%x, cycle=%d, hist=%x, taken:%d, misPred:%d, bimctr:%d, pvdr(%d):%d, altDiff:%d, pvdrU:%d, pvdrCtr:%d, alloc(%d):%d\n"
,
u
.
pc
,
u
.
pc
-
(
bri
.
fetchIdx
<<
instOffsetBits
.
U
),
bri
.
debug_tage_cycle
,
updateHist
,
u
.
taken
,
u
.
isMisPred
,
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"
)
// XSDebug(io.update.valid && updateIsBr, p"update: sc: ${updateSCMeta}\n")
// XSDebug(true.B, p"scThres: use(${useThreshold}), update(${updateThreshold})\n")
}
}
...
...
src/main/scala/xiangshan/frontend/uBTB.scala
浏览文件 @
2c87aa6f
此差异已折叠。
点击以展开。
src/main/scala/xiangshan/mem/lsqueue/LSQWrapper.scala
浏览文件 @
2c87aa6f
...
...
@@ -38,7 +38,8 @@ class LsqEnqIO extends XSBundle {
class
LsqWrappper
extends
XSModule
with
HasDCacheParameters
{
val
io
=
IO
(
new
Bundle
()
{
val
enq
=
new
LsqEnqIO
val
brqRedirect
=
Input
(
Valid
(
new
Redirect
))
val
brqRedirect
=
Flipped
(
ValidIO
(
new
Redirect
))
val
flush
=
Input
(
Bool
())
val
loadIn
=
Vec
(
LoadPipelineWidth
,
Flipped
(
Valid
(
new
LsPipelineBundle
)))
val
storeIn
=
Vec
(
StorePipelineWidth
,
Flipped
(
Valid
(
new
LsPipelineBundle
)))
val
loadDataForwarded
=
Vec
(
LoadPipelineWidth
,
Input
(
Bool
()))
...
...
@@ -89,6 +90,7 @@ class LsqWrappper extends XSModule with HasDCacheParameters {
// load queue wiring
loadQueue
.
io
.
brqRedirect
<>
io
.
brqRedirect
loadQueue
.
io
.
flush
<>
io
.
flush
loadQueue
.
io
.
loadIn
<>
io
.
loadIn
loadQueue
.
io
.
storeIn
<>
io
.
storeIn
loadQueue
.
io
.
loadDataForwarded
<>
io
.
loadDataForwarded
...
...
@@ -102,6 +104,7 @@ class LsqWrappper extends XSModule with HasDCacheParameters {
// store queue wiring
// storeQueue.io <> DontCare
storeQueue
.
io
.
brqRedirect
<>
io
.
brqRedirect
storeQueue
.
io
.
flush
<>
io
.
flush
storeQueue
.
io
.
storeIn
<>
io
.
storeIn
storeQueue
.
io
.
sbuffer
<>
io
.
sbuffer
storeQueue
.
io
.
mmioStout
<>
io
.
mmioStout
...
...
src/main/scala/xiangshan/mem/lsqueue/LoadQueue.scala
浏览文件 @
2c87aa6f
此差异已折叠。
点击以展开。
src/main/scala/xiangshan/mem/lsqueue/StoreQueue.scala
浏览文件 @
2c87aa6f
此差异已折叠。
点击以展开。
src/main/scala/xiangshan/mem/pipeline/AtomicsUnit.scala
浏览文件 @
2c87aa6f
此差异已折叠。
点击以展开。
src/main/scala/xiangshan/mem/pipeline/LoadUnit.scala
浏览文件 @
2c87aa6f
此差异已折叠。
点击以展开。
src/main/scala/xiangshan/mem/pipeline/StoreUnit.scala
浏览文件 @
2c87aa6f
此差异已折叠。
点击以展开。
src/main/scala/xiangshan/package.scala
浏览文件 @
2c87aa6f
此差异已折叠。
点击以展开。
src/test/scala/xiangshan/frontend/RASTest.scala
浏览文件 @
2c87aa6f
此差异已折叠。
点击以展开。
src/test/scala/xiangshan/frontend/uBTBTest.scala
浏览文件 @
2c87aa6f
此差异已折叠。
点击以展开。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录