Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenXiangShan
XiangShan
提交
daaf393a
X
XiangShan
项目概览
OpenXiangShan
/
XiangShan
大约 1 年 前同步成功
通知
1183
Star
3914
Fork
526
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
X
XiangShan
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
daaf393a
编写于
10月 09, 2019
作者:
W
William Wang
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat(BPU, datapath): add branch predict support for RVC
上级
a207cd54
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
60 addition
and
17 deletion
+60
-17
devlog.md
devlog.md
+8
-1
src/main/scala/noop/BPU.scala
src/main/scala/noop/BPU.scala
+11
-3
src/main/scala/noop/Bundle.scala
src/main/scala/noop/Bundle.scala
+3
-0
src/main/scala/noop/IDU.scala
src/main/scala/noop/IDU.scala
+18
-4
src/main/scala/noop/IFU.scala
src/main/scala/noop/IFU.scala
+10
-3
src/main/scala/noop/NOOP.scala
src/main/scala/noop/NOOP.scala
+1
-1
src/main/scala/noop/fu/ALU.scala
src/main/scala/noop/fu/ALU.scala
+8
-5
src/main/scala/noop/fu/CSR.scala
src/main/scala/noop/fu/CSR.scala
+1
-0
未找到文件。
devlog.md
浏览文件 @
daaf393a
...
...
@@ -57,4 +57,11 @@ REMUW |BitPat("b0100000_?????_?????_101_?????_0111011")|1
其他要调整的指令
*
LX/SX
*
ALUI
\ No newline at end of file
*
ALUI
# RVC指令集及流水线变动
检查下列指令的nemu实现
```
8010074a: 80fd srli s1,s1,0x1f
```
\ No newline at end of file
src/main/scala/noop/BPU.scala
浏览文件 @
daaf393a
...
...
@@ -11,7 +11,7 @@ class TableAddr(idxBits: Int) extends NOOPBundle {
val
tag
=
UInt
(
tagBits
.
W
)
val
idx
=
UInt
(
idxBits
.
W
)
val
pad
=
UInt
(
2
.
W
)
val
pad
=
UInt
(
1
.
W
)
def
fromUInt
(
x
:
UInt
)
=
x
.
asTypeOf
(
UInt
(
AddrBits
.
W
)).
asTypeOf
(
this
)
def
getTag
(
x
:
UInt
)
=
fromUInt
(
x
).
tag
...
...
@@ -37,6 +37,7 @@ class BPUUpdateReq extends NOOPBundle {
val
actualTaken
=
Output
(
Bool
())
// for branch
val
fuOpType
=
Output
(
FuOpType
())
val
btbType
=
Output
(
BTBtype
())
val
isRVC
=
Output
(
Bool
())
// for ras, save PC+2 to stack if is RVC
}
class
BPU1
extends
NOOPModule
{
...
...
@@ -55,6 +56,7 @@ class BPU1 extends NOOPModule {
val
tag
=
UInt
(
btbAddr
.
tagBits
.
W
)
val
_type
=
UInt
(
2.
W
)
val
target
=
UInt
(
AddrBits
.
W
)
val
brIdx
=
UInt
(
2.
W
)
}
val
btb
=
Module
(
new
SRAMTemplate
(
btbEntry
(),
set
=
NRbtb
,
shouldReset
=
true
,
holdRead
=
true
,
singlePort
=
true
))
...
...
@@ -67,6 +69,7 @@ class BPU1 extends NOOPModule {
// we should latch the input pc for one cycle
val
pcLatch
=
RegEnable
(
io
.
in
.
pc
.
bits
,
io
.
in
.
pc
.
valid
)
val
btbHit
=
btbRead
.
tag
===
btbAddr
.
getTag
(
pcLatch
)
&&
!
flush
&&
RegNext
(
btb
.
io
.
r
.
req
.
ready
,
init
=
false
.
B
)
// btbHit will ignore pc(1,0). pc(1,0) is used to build brIdx
// PHT
val
pht
=
Mem
(
NRbtb
,
UInt
(
2.
W
))
...
...
@@ -76,8 +79,10 @@ class BPU1 extends NOOPModule {
val
NRras
=
16
val
ras
=
Mem
(
NRras
,
UInt
(
AddrBits
.
W
))
val
raBrIdxs
=
Mem
(
NRras
,
UInt
(
2.
W
))
val
sp
=
Counter
(
NRras
)
val
rasTarget
=
RegEnable
(
ras
.
read
(
sp
.
value
),
io
.
in
.
pc
.
valid
)
val
rasBrIdx
=
RegEnable
(
raBrIdxs
.
read
(
sp
.
value
),
io
.
in
.
pc
.
valid
)
// update
val
req
=
WireInit
(
0.
U
.
asTypeOf
(
new
BPUUpdateReq
))
...
...
@@ -87,6 +92,7 @@ class BPU1 extends NOOPModule {
btbWrite
.
tag
:=
btbAddr
.
getTag
(
req
.
pc
)
btbWrite
.
target
:=
req
.
actualTarget
btbWrite
.
_type
:=
req
.
btbType
btbWrite
.
brIdx
:=
Cat
(
req
.
pc
(
1
),
~
req
.
pc
(
1
))
// NOTE: We only update BTB at a miss prediction.
// If a miss prediction is found, the pipeline will be flushed
// in the next cycle. Therefore it is safe to use single-port
...
...
@@ -109,8 +115,9 @@ class BPU1 extends NOOPModule {
}
}
when
(
req
.
valid
)
{
when
(
req
.
fuOpType
===
ALUOpType
.
call
)
{
ras
.
write
(
sp
.
value
+
1.
U
,
req
.
pc
+
4.
U
)
when
(
req
.
fuOpType
===
ALUOpType
.
call
)
{
ras
.
write
(
sp
.
value
+
1.
U
,
Mux
(
req
.
isRVC
,
req
.
pc
+
2.
U
,
req
.
pc
+
4.
U
))
raBrIdxs
.
write
(
sp
.
value
+
1.
U
,
Mux
(
req
.
pc
(
1
),
2.
U
,
1.
U
))
sp
.
value
:=
sp
.
value
+
1.
U
}
.
elsewhen
(
req
.
fuOpType
===
ALUOpType
.
ret
)
{
...
...
@@ -119,6 +126,7 @@ class BPU1 extends NOOPModule {
}
io
.
out
.
target
:=
Mux
(
btbRead
.
_type
===
BTBtype
.
R
,
rasTarget
,
btbRead
.
target
)
io
.
out
.
brIdx
:=
Mux
(
btbRead
.
_type
===
BTBtype
.
R
,
rasBrIdx
,
btbRead
.
brIdx
)
io
.
out
.
valid
:=
btbHit
&&
Mux
(
btbRead
.
_type
===
BTBtype
.
B
,
phtTaken
,
true
.
B
)
}
...
...
src/main/scala/noop/Bundle.scala
浏览文件 @
daaf393a
...
...
@@ -26,6 +26,7 @@ class DataSrcIO extends NOOPBundle {
class
RedirectIO
extends
NOOPBundle
{
val
target
=
Output
(
UInt
(
AddrBits
.
W
))
val
brIdx
=
Output
(
UInt
(
2.
W
))
// for RVC
val
valid
=
Output
(
Bool
())
}
...
...
@@ -33,6 +34,7 @@ class IRIDCtrlFlowIO extends NOOPBundle {
val
instr
=
Output
(
UInt
(
64.
W
))
val
pc
=
Output
(
UInt
(
AddrBits
.
W
))
val
pnpc
=
Output
(
UInt
(
AddrBits
.
W
))
val
brIdx
=
Output
(
UInt
(
2.
W
))
val
redirect
=
new
RedirectIO
}
...
...
@@ -40,6 +42,7 @@ class CtrlFlowIO extends NOOPBundle {
val
instr
=
Output
(
UInt
(
32.
W
))
val
pc
=
Output
(
UInt
(
AddrBits
.
W
))
val
pnpc
=
Output
(
UInt
(
AddrBits
.
W
))
val
brIdx
=
Output
(
UInt
(
2.
W
))
val
redirect
=
new
RedirectIO
}
...
...
src/main/scala/noop/IDU.scala
浏览文件 @
daaf393a
...
...
@@ -127,15 +127,19 @@ class IDU extends NOOPModule with HasInstrType {
// val nextState = WireInit(0.U(2.W))
val
canGo
=
WireInit
(
false
.
B
)
val
canIn
=
WireInit
(
false
.
B
)
val
rvcFinish
=
pcOffset
===
0.
U
&&
!
isRVC
||
pcOffset
===
4.
U
&&
!
isRVC
||
pcOffset
===
2.
U
&&
isRVC
||
pcOffset
===
6.
U
&&
isRVC
// val brIdx = io.in.bits.brIdx
val
brIdx
=
0.
U
val
rvcFinish
=
pcOffset
===
0.
U
&&
(!
isRVC
||
brIdx
(
0
))
||
pcOffset
===
4.
U
&&
(!
isRVC
||
brIdx
(
0
))
||
pcOffset
===
2.
U
&&
isRVC
||
pcOffset
===
6.
U
&&
isRVC
// if brIdx(0) (branch taken at inst with offest 0), ignore the rest part of this instline
// just get next pc and instline from IFU
val
rvcNext
=
pcOffset
===
0.
U
&&
isRVC
||
pcOffset
===
4.
U
&&
isRVC
||
pcOffset
===
2.
U
&&
!
isRVC
val
rvcSpecial
=
pcOffset
===
6.
U
&&
!
isRVC
val
flushIFU
=
(
state
===
s_idle
||
state
===
s_extra
)
&&
rvcSpecial
&&
io
.
in
.
valid
val
pcOut
=
WireInit
(
0.
U
(
AddrBits
.
W
))
val
pnpcOut
=
WireInit
(
0.
U
(
AddrBits
.
W
))
val
specialPCR
=
Reg
(
UInt
(
AddrBits
.
W
))
val
specialPCR
=
Reg
(
UInt
(
AddrBits
.
W
))
// reg for full inst taht cross 2 inst line
val
specialInstR
=
Reg
(
UInt
(
16.
W
))
val
redirectPC
=
Cat
(
io
.
in
.
bits
.
pc
(
31
,
3
),
0.
U
(
3.
W
))+
"b1010"
.
U
val
redirectPC
=
Cat
(
io
.
in
.
bits
.
pc
(
31
,
3
),
0.
U
(
3.
W
))+
"b1010"
.
U
// IDU can got get full inst from a single inst line
val
rvcForceLoadNext
=
pcOffset
===
2.
U
&&
!
isRVC
&&
io
.
in
.
bits
.
pnpc
(
2
,
0
)
===
4.
U
//------------------------------------------------------
// rvcForceLoadNext is used to deal with:
...
...
@@ -145,6 +149,10 @@ class IDU extends NOOPModule with HasInstrType {
// For icache req inst in seq, if there is no rvcForceLoadNext,
// after 8010004e there will be 8010004c instead of 80100050
//------------------------------------------------------
// if there is a j inst in current inst line, a redirect req will be sent by ALU before invalid inst exception being committed
// only for test, add this to pipeline when do real implementation
// val predictBranch = io.in.valid && Mux(io.in.bits.pc(1), io.in.bits.pc + 2.U === io.in.bits.pnpc, io.in.bits.pc + 4.U === io.in.bits.pnpc)
// val flush = rvcSpecial
instr
:=
Mux
(
state
===
s_waitnext
,
Cat
(
instIn
(
15
,
0
),
specialInstR
),
LookupTree
(
pcOffset
,
List
(
"b000"
.
U
->
instIn
(
31
,
0
),
...
...
@@ -155,6 +163,7 @@ class IDU extends NOOPModule with HasInstrType {
io
.
redirect
.
target
:=
redirectPC
io
.
redirect
.
valid
:=
flushIFU
io
.
redirect
.
brIdx
:=
DontCare
when
(!
io
.
flush
){
switch
(
state
){
...
...
@@ -197,7 +206,7 @@ class IDU extends NOOPModule with HasInstrType {
is
(
s_waitnext
){
//require next 64bits, for this inst has size 32 and offset 6
//ignore bp result, use pc+4 instead
pcOut
:=
specialPCR
pnpcOut
:=
specialPCR
+
4.
U
pnpcOut
:=
specialPCR
+
4.
U
// pnpcOut := Mux(rvcFinish, io.in.bits.pnpc, Mux(isRVC, pcOut+2.U, pcOut+4.U))
canGo
:=
io
.
in
.
valid
canIn
:=
false
.
B
...
...
@@ -226,6 +235,11 @@ class IDU extends NOOPModule with HasInstrType {
io
.
out
.
valid
:=
io
.
in
.
valid
&&
canGo
io
.
in
.
ready
:=
!
io
.
in
.
valid
||
(
io
.
out
.
fire
()
&&
canIn
)
// NOTE:
// we did not do special opt for cross-line jump inst, hopefully there will not be too much such inst
// for perf counter:
// val crossLineJump = state === s_waitnext && fuType === FuType.alu && fuOpType.isBru()
Debug
(){
when
(
io
.
out
.
fire
()){
printf
(
"[IDU] pc %x pcin: %x instr %x instrin %x state %x instrType: %x fuType: %x fuOpType: %x\n"
,
pcOut
,
io
.
in
.
bits
.
pc
,
instr
,
io
.
in
.
bits
.
instr
,
state
,
instrType
,
fuType
,
fuOpType
)
...
...
src/main/scala/noop/IFU.scala
浏览文件 @
daaf393a
...
...
@@ -13,7 +13,7 @@ trait HasResetVector {
class
IFU
extends
NOOPModule
with
HasResetVector
{
val
io
=
IO
(
new
Bundle
{
val
imem
=
new
SimpleBusUC
(
userBits
=
AddrBits
)
val
imem
=
new
SimpleBusUC
(
userBits
=
AddrBits
+
2
)
val
pc
=
Input
(
UInt
(
AddrBits
.
W
))
val
out
=
Decoupled
(
new
IRIDCtrlFlowIO
)
val
redirect
=
Flipped
(
new
RedirectIO
)
...
...
@@ -30,8 +30,14 @@ class IFU extends NOOPModule with HasResetVector {
val
bp1
=
Module
(
new
BPU1
)
// predicted next pc
val
pnpc
=
bp1
.
io
.
out
.
target
val
pbrIdx
=
bp1
.
io
.
out
.
brIdx
// val npc = Mux(io.redirect.valid, io.redirect.target, Mux(io.redirectRVC.valid, io.redirectRVC.target, Mux(bp1.io.out.valid, pnpc, snpc)))
val
npc
=
Mux
(
io
.
redirect
.
valid
,
io
.
redirect
.
target
,
Mux
(
io
.
redirectRVC
.
valid
,
io
.
redirectRVC
.
target
,
snpc
))
val
brIdx
=
Wire
(
UInt
(
2.
W
))
// brIdx(0) -> branch at pc offset 0 (mod 4)
// brIdx(1) -> branch at pc offset 2 (mod 4)
brIdx
:=
Mux
(
io
.
redirect
.
valid
,
0.
U
,
Mux
(
io
.
redirectRVC
.
valid
,
0.
U
,
pbrIdx
))
//TODO: BP will be disabled shortly after a redirect request
bp1
.
io
.
in
.
pc
.
valid
:=
io
.
imem
.
req
.
fire
()
// only predict when Icache accepts a request
bp1
.
io
.
in
.
pc
.
bits
:=
npc
// predict one cycle early
...
...
@@ -55,14 +61,15 @@ class IFU extends NOOPModule with HasResetVector {
io
.
imem
.
req
.
bits
.
addr
:=
Cat
(
pc
(
AddrBits
-
1
,
1
),
0.
U
(
1.
W
))
//cache will treat it as Cat(pc(63,3),0.U(3.W))
io
.
imem
.
req
.
bits
.
size
:=
"b11"
.
U
io
.
imem
.
req
.
bits
.
cmd
:=
SimpleBusCmd
.
read
io
.
imem
.
req
.
bits
.
user
:=
npc
io
.
imem
.
req
.
bits
.
user
:=
Cat
(
brIdx
,
npc
)
io
.
imem
.
resp
.
ready
:=
io
.
out
.
ready
||
io
.
flushVec
(
0
)
io
.
out
.
bits
:=
DontCare
io
.
out
.
bits
.
pc
:=
io
.
pc
//inst path only uses 32bit inst, get the right inst according to pc(2)
io
.
out
.
bits
.
instr
:=
io
.
imem
.
resp
.
bits
.
rdata
io
.
out
.
bits
.
pnpc
:=
io
.
imem
.
resp
.
bits
.
user
io
.
out
.
bits
.
pnpc
:=
io
.
imem
.
resp
.
bits
.
user
(
AddrBits
-
1
,
0
)
io
.
out
.
bits
.
brIdx
:=
io
.
imem
.
resp
.
bits
.
user
(
AddrBits
+
1
,
AddrBits
)
io
.
out
.
valid
:=
io
.
imem
.
resp
.
valid
&&
!
io
.
flushVec
(
0
)
Debug
(){
...
...
src/main/scala/noop/NOOP.scala
浏览文件 @
daaf393a
...
...
@@ -84,7 +84,7 @@ class NOOP(implicit val p: NOOPConfig) extends NOOPModule {
isu
.
io
.
forward
<>
exu
.
io
.
forward
io
.
imem
<>
(
if
(
HasIcache
)
{
val
icache
=
Module
(
new
Cache
(
ro
=
true
,
name
=
"icache"
,
userBits
=
AddrBits
))
val
icache
=
Module
(
new
Cache
(
ro
=
true
,
name
=
"icache"
,
userBits
=
AddrBits
+
2
))
// userBits = AddrBits + BrIdxBits
icache
.
io
.
in
<>
ifu
.
io
.
imem
icache
.
io
.
flush
:=
Fill
(
2
,
ifu
.
io
.
flushVec
(
0
)
|
ifu
.
io
.
bpFlush
)
ifu
.
io
.
pc
:=
icache
.
io
.
addr
...
...
src/main/scala/noop/fu/ALU.scala
浏览文件 @
daaf393a
...
...
@@ -100,13 +100,15 @@ class ALU extends NOOPModule {
// val pcPlus2 = ALUOpType.pcPlus2(func)
val
taken
=
LookupTree
(
ALUOpType
.
getBranchType
(
func
),
branchOpTable
)
^
ALUOpType
.
isBranchInvert
(
func
)
val
target
=
Mux
(
isBranch
,
io
.
cfIn
.
pc
+
io
.
offset
,
adderRes
)(
AddrBits
-
1
,
0
)
val
predictWrong
=
true
.
B
//(io.redirect.target =/= io.cfIn.pnpc)
io
.
redirect
.
target
:=
Mux
(!
taken
&&
isBranch
,
Mux
(
io
.
cfIn
.
instr
(
1
,
0
)=/=
"b11"
.
U
,
io
.
cfIn
.
pc
+
2.
U
,
io
.
cfIn
.
pc
+
4.
U
),
target
)
val
predictWrong
=
(
io
.
redirect
.
target
=/=
io
.
cfIn
.
pnpc
)
val
isRVC
=
(
io
.
cfIn
.
instr
(
1
,
0
)
=/=
"b11"
.
U
)
io
.
redirect
.
target
:=
Mux
(!
taken
&&
isBranch
,
Mux
(
isRVC
,
io
.
cfIn
.
pc
+
2.
U
,
io
.
cfIn
.
pc
+
4.
U
),
target
)
// with branch predictor, this is actually to fix the wrong prediction
io
.
redirect
.
valid
:=
valid
&&
isBru
&&
predictWrong
// may be can move to ISU to calculate pc + 4
// this is actually for jal and jalr to write pc + 4 to rd
io
.
out
.
bits
:=
Mux
(
isBru
,
Mux
(
io
.
cfIn
.
instr
(
1
,
0
)===
"b11"
.
U
,
io
.
cfIn
.
pc
+
4.
U
,
io
.
cfIn
.
pc
+
2.
U
),
aluRes
)
// may be can be moved to ISU to calculate pc + 4
// this is actually for jal and jalr to write pc + 4/2 to rd
io
.
redirect
.
brIdx
:=
DontCare
io
.
out
.
bits
:=
Mux
(
isBru
,
Mux
(!
isRVC
,
io
.
cfIn
.
pc
+
4.
U
,
io
.
cfIn
.
pc
+
2.
U
),
aluRes
)
// when(pcPlus2 && isBru){
// printf("CJALR %x %x \n ", io.cfIn.instr, io.cfIn.pc)
// }
...
...
@@ -134,6 +136,7 @@ class ALU extends NOOPModule {
bpuUpdateReq
.
actualTaken
:=
taken
bpuUpdateReq
.
fuOpType
:=
func
bpuUpdateReq
.
btbType
:=
LookupTree
(
func
,
RV32I_BRUInstr
.
bruFuncTobtbTypeTable
)
bpuUpdateReq
.
isRVC
:=
isRVC
BoringUtils
.
addSource
(
RegNext
(
bpuUpdateReq
),
"bpuUpdateReq"
)
...
...
src/main/scala/noop/fu/CSR.scala
浏览文件 @
daaf393a
...
...
@@ -104,6 +104,7 @@ class CSR(implicit val p: NOOPConfig) extends NOOPModule with HasCSRConst {
io
.
redirect
.
valid
:=
(
valid
&&
func
===
CSROpType
.
jmp
)
||
isException
io
.
redirect
.
target
:=
Mux
(
isMret
,
mepc
,
mtvec
)
io
.
redirect
.
brIdx
:=
DontCare
when
(
io
.
redirect
.
valid
&&
!
isMret
)
{
mepc
:=
io
.
cfIn
.
pc
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录