Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenXiangShan
XiangShan
提交
d0e78cc9
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,发现更多精彩内容 >>
提交
d0e78cc9
编写于
1月 02, 2021
作者:
Fa_wang
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'origin/master' into opt-sbuffer-timing
上级
dc94afa6
c9caf8e0
变更
23
隐藏空白更改
内联
并排
Showing
23 changed file
with
415 addition
and
257 deletion
+415
-257
Makefile
Makefile
+2
-2
rocket-chip
rocket-chip
+1
-1
src/main/scala/xiangshan/backend/fu/CSR.scala
src/main/scala/xiangshan/backend/fu/CSR.scala
+94
-109
src/main/scala/xiangshan/backend/issue/ReservationStationNew.scala
...scala/xiangshan/backend/issue/ReservationStationNew.scala
+25
-12
src/main/scala/xiangshan/backend/rename/FreeList.scala
src/main/scala/xiangshan/backend/rename/FreeList.scala
+1
-1
src/main/scala/xiangshan/backend/rename/Rename.scala
src/main/scala/xiangshan/backend/rename/Rename.scala
+60
-46
src/main/scala/xiangshan/backend/rename/RenameTable.scala
src/main/scala/xiangshan/backend/rename/RenameTable.scala
+1
-1
src/main/scala/xiangshan/backend/roq/Roq.scala
src/main/scala/xiangshan/backend/roq/Roq.scala
+81
-25
src/main/scala/xiangshan/cache/dtlb.scala
src/main/scala/xiangshan/cache/dtlb.scala
+1
-1
src/main/scala/xiangshan/frontend/BPU.scala
src/main/scala/xiangshan/frontend/BPU.scala
+4
-2
src/main/scala/xiangshan/frontend/Bim.scala
src/main/scala/xiangshan/frontend/Bim.scala
+2
-2
src/main/scala/xiangshan/frontend/IFU.scala
src/main/scala/xiangshan/frontend/IFU.scala
+18
-9
src/main/scala/xiangshan/frontend/Ibuffer.scala
src/main/scala/xiangshan/frontend/Ibuffer.scala
+23
-13
src/test/csrc/assert.cpp
src/test/csrc/assert.cpp
+20
-0
src/test/csrc/common.h
src/test/csrc/common.h
+5
-0
src/test/csrc/difftest.cpp
src/test/csrc/difftest.cpp
+1
-1
src/test/csrc/difftest.h
src/test/csrc/difftest.h
+5
-0
src/test/csrc/emu.cpp
src/test/csrc/emu.cpp
+46
-27
src/test/csrc/emu.h
src/test/csrc/emu.h
+1
-2
src/test/csrc/main.cpp
src/test/csrc/main.cpp
+6
-2
src/test/csrc/ram.cpp
src/test/csrc/ram.cpp
+12
-1
src/test/csrc/ram.h
src/test/csrc/ram.h
+2
-0
src/test/vsrc/assert.v
src/test/vsrc/assert.v
+4
-0
未找到文件。
Makefile
浏览文件 @
d0e78cc9
...
...
@@ -56,7 +56,7 @@ $(SIM_TOP_V): $(SCALA_FILE) $(TEST_FILE)
date
-R
mill XiangShan.test.runMain
$(SIMTOP)
-X
verilog
-td
$
(
@D
)
--full-stacktrace
--output-file
$
(
@F
)
$(SIM_ARGS)
sed
-i
'/module XSSimTop/,/endmodule/d'
$(SIM_TOP_V)
sed
-i
-e
's/$$fatal/
$$finish
/g'
$(SIM_TOP_V)
sed
-i
-e
's/$$fatal/
xs_assert(`__LINE__)
/g'
$(SIM_TOP_V)
date
-R
EMU_TOP
=
XSSimSoC
...
...
@@ -80,7 +80,7 @@ endif
# Verilator multi-thread support
EMU_THREADS
?=
1
ifneq
($(EMU_THREADS),1)
VEXTRA_FLAGS
+=
--threads
$(EMU_THREADS)
--threads-dpi
none
VEXTRA_FLAGS
+=
--threads
$(EMU_THREADS)
--threads-dpi
all
endif
# Verilator savable
...
...
rocket-chip
@
9cf18f11
比较
147bdcc4
...
9cf18f11
Subproject commit
147bdcc4a26c74e5d7a47e3d667d456699d6d11f
Subproject commit
9cf18f1173443e2542990c090a69bdd62d26228d
src/main/scala/xiangshan/backend/fu/CSR.scala
浏览文件 @
d0e78cc9
...
...
@@ -597,58 +597,92 @@ class CSR extends FunctionUnit with HasCSRConst
tlbBundle
.
priv
.
imode
:=
priviledgeMode
tlbBundle
.
priv
.
dmode
:=
Mux
(
mstatusStruct
.
mprv
.
asBool
,
mstatusStruct
.
mpp
,
priviledgeMode
)
val
hasInstrPageFault
=
csrio
.
exception
.
bits
.
cf
.
exceptionVec
(
instrPageFault
)
&&
csrio
.
exception
.
valid
val
hasLoadPageFault
=
csrio
.
exception
.
bits
.
cf
.
exceptionVec
(
loadPageFault
)
&&
csrio
.
exception
.
valid
val
hasStorePageFault
=
csrio
.
exception
.
bits
.
cf
.
exceptionVec
(
storePageFault
)
&&
csrio
.
exception
.
valid
val
hasStoreAddrMisaligned
=
csrio
.
exception
.
bits
.
cf
.
exceptionVec
(
storeAddrMisaligned
)
&&
csrio
.
exception
.
valid
val
hasLoadAddrMisaligned
=
csrio
.
exception
.
bits
.
cf
.
exceptionVec
(
loadAddrMisaligned
)
&&
csrio
.
exception
.
valid
// 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
)
// mtval write logic
val
memExceptionAddr
=
SignExt
(
csrio
.
memExceptionVAddr
,
XLEN
)
when
(
hasInstrPageFault
||
hasLoadPageFault
||
hasStorePageFault
){
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
)
),
memExceptionAddr
)
when
(
priviledgeMode
===
ModeM
){
mtval
:=
tval
}.
otherwise
{
stval
:=
tval
}
retTarget
:=
DontCare
// val illegalEret = TODO
when
(
valid
&&
isMret
)
{
val
mstatusOld
=
WireInit
(
mstatus
.
asTypeOf
(
new
MstatusStruct
))
val
mstatusNew
=
WireInit
(
mstatus
.
asTypeOf
(
new
MstatusStruct
))
mstatusNew
.
ie
.
m
:=
mstatusOld
.
pie
.
m
priviledgeMode
:=
mstatusOld
.
mpp
mstatusNew
.
pie
.
m
:=
true
.
B
mstatusNew
.
mpp
:=
ModeU
mstatusNew
.
mprv
:=
0.
U
mstatus
:=
mstatusNew
.
asUInt
// lr := false.B
retTarget
:=
mepc
(
VAddrBits
-
1
,
0
)
}
when
(
hasLoadAddrMisaligned
||
hasStoreAddrMisaligned
)
{
mtval
:=
memExceptionAddr
when
(
valid
&&
isSret
&&
!
illegalSModeSret
)
{
val
mstatusOld
=
WireInit
(
mstatus
.
asTypeOf
(
new
MstatusStruct
))
val
mstatusNew
=
WireInit
(
mstatus
.
asTypeOf
(
new
MstatusStruct
))
mstatusNew
.
ie
.
s
:=
mstatusOld
.
pie
.
s
priviledgeMode
:=
Cat
(
0.
U
(
1.
W
),
mstatusOld
.
spp
)
mstatusNew
.
pie
.
s
:=
true
.
B
mstatusNew
.
spp
:=
ModeU
mstatus
:=
mstatusNew
.
asUInt
mstatusNew
.
mprv
:=
0.
U
// lr := false.B
retTarget
:=
sepc
(
VAddrBits
-
1
,
0
)
}
// Exception and Intr
when
(
valid
&&
isUret
)
{
val
mstatusOld
=
WireInit
(
mstatus
.
asTypeOf
(
new
MstatusStruct
))
val
mstatusNew
=
WireInit
(
mstatus
.
asTypeOf
(
new
MstatusStruct
))
// mstatusNew.mpp.m := ModeU //TODO: add mode U
mstatusNew
.
ie
.
u
:=
mstatusOld
.
pie
.
u
priviledgeMode
:=
ModeU
mstatusNew
.
pie
.
u
:=
true
.
B
mstatus
:=
mstatusNew
.
asUInt
retTarget
:=
uepc
(
VAddrBits
-
1
,
0
)
}
// interrupts
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
/**
* Exception and Intr
*/
val
ideleg
=
(
mideleg
&
mip
.
asUInt
)
def
priviledgedEnableDetect
(
x
:
Bool
)
:
Bool
=
Mux
(
x
,
((
priviledgeMode
===
ModeS
)
&&
mstatusStruct
.
ie
.
s
)
||
(
priviledgeMode
<
ModeS
),
((
priviledgeMode
===
ModeM
)
&&
mstatusStruct
.
ie
.
m
)
||
(
priviledgeMode
<
ModeM
))
// send interrupt information to ROQ
val
intrVecEnable
=
Wire
(
Vec
(
12
,
Bool
()))
intrVecEnable
.
zip
(
ideleg
.
asBools
).
map
{
case
(
x
,
y
)
=>
x
:=
priviledgedEnableDetect
(
y
)}
val
intrVec
=
mie
(
11
,
0
)
&
mip
.
asUInt
&
intrVecEnable
.
asUInt
val
intrBitSet
=
intrVec
.
orR
()
csrio
.
interrupt
:=
intrBitSet
val
intrNO
=
IntPriority
.
foldRight
(
0.
U
)((
i
:
Int
,
sum
:
UInt
)
=>
Mux
(
intrVec
(
i
),
i
.
U
,
sum
))
val
raiseIntr
=
intrBitSet
&&
csrio
.
exception
.
valid
&&
csrio
.
isInterrupt
XSDebug
(
raiseIntr
,
"interrupt: pc=0x%x, %d\n"
,
csrio
.
exception
.
bits
.
cf
.
pc
,
intrNO
)
mipWire
.
t
.
m
:=
csrio
.
externalInterrupt
.
mtip
mipWire
.
s
.
m
:=
csrio
.
externalInterrupt
.
msip
mipWire
.
e
.
m
:=
csrio
.
externalInterrupt
.
meip
// 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
)
// 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
csrExceptionVec
=
Wire
(
Vec
(
16
,
Bool
()))
csrExceptionVec
.
map
(
_
:=
false
.
B
)
csrExceptionVec
(
breakPoint
)
:=
io
.
in
.
valid
&&
isEbreak
...
...
@@ -676,14 +710,6 @@ class CSR extends FunctionUnit with HasCSRConst
// }
val
raiseExceptionIntr
=
csrio
.
exception
.
valid
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
)
XSDebug
(
raiseExceptionIntr
,
"int/exc: pc %x int (%d):%x exc: (%d):%x\n"
,
csrio
.
exception
.
bits
.
cf
.
pc
,
intrNO
,
intrVec
,
exceptionNO
,
raiseExceptionVec
.
asUInt
)
...
...
@@ -696,53 +722,35 @@ class CSR extends FunctionUnit with HasCSRConst
priviledgeMode
)
// Branch control
// mtval write logic
val
memExceptionAddr
=
SignExt
(
csrio
.
memExceptionVAddr
,
XLEN
)
when
(
hasInstrPageFault
||
hasLoadPageFault
||
hasStorePageFault
){
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
)
),
memExceptionAddr
)
when
(
priviledgeMode
===
ModeM
){
mtval
:=
tval
}.
otherwise
{
stval
:=
tval
}
}
when
(
hasLoadAddrMisaligned
||
hasStoreAddrMisaligned
)
{
mtval
:=
memExceptionAddr
}
val
deleg
=
Mux
(
raiseIntr
,
mideleg
,
medeleg
)
// val delegS = ((deleg & (1 << (causeNO & 0xf))) != 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
)
retTarget
:=
DontCare
// val illegalEret = TODO
when
(
valid
&&
isMret
)
{
val
mstatusOld
=
WireInit
(
mstatus
.
asTypeOf
(
new
MstatusStruct
))
val
mstatusNew
=
WireInit
(
mstatus
.
asTypeOf
(
new
MstatusStruct
))
mstatusNew
.
ie
.
m
:=
mstatusOld
.
pie
.
m
priviledgeMode
:=
mstatusOld
.
mpp
mstatusNew
.
pie
.
m
:=
true
.
B
mstatusNew
.
mpp
:=
ModeU
mstatusNew
.
mprv
:=
0.
U
mstatus
:=
mstatusNew
.
asUInt
// lr := false.B
retTarget
:=
mepc
(
VAddrBits
-
1
,
0
)
}
when
(
valid
&&
isSret
&&
!
illegalSModeSret
)
{
val
mstatusOld
=
WireInit
(
mstatus
.
asTypeOf
(
new
MstatusStruct
))
val
mstatusNew
=
WireInit
(
mstatus
.
asTypeOf
(
new
MstatusStruct
))
mstatusNew
.
ie
.
s
:=
mstatusOld
.
pie
.
s
priviledgeMode
:=
Cat
(
0.
U
(
1.
W
),
mstatusOld
.
spp
)
mstatusNew
.
pie
.
s
:=
true
.
B
mstatusNew
.
spp
:=
ModeU
mstatus
:=
mstatusNew
.
asUInt
mstatusNew
.
mprv
:=
0.
U
// lr := false.B
retTarget
:=
sepc
(
VAddrBits
-
1
,
0
)
}
when
(
valid
&&
isUret
)
{
val
mstatusOld
=
WireInit
(
mstatus
.
asTypeOf
(
new
MstatusStruct
))
val
mstatusNew
=
WireInit
(
mstatus
.
asTypeOf
(
new
MstatusStruct
))
// mstatusNew.mpp.m := ModeU //TODO: add mode U
mstatusNew
.
ie
.
u
:=
mstatusOld
.
pie
.
u
priviledgeMode
:=
ModeU
mstatusNew
.
pie
.
u
:=
true
.
B
mstatus
:=
mstatusNew
.
asUInt
retTarget
:=
uepc
(
VAddrBits
-
1
,
0
)
}
when
(
raiseExceptionIntr
)
{
val
mstatusOld
=
WireInit
(
mstatus
.
asTypeOf
(
new
MstatusStruct
))
...
...
@@ -771,40 +779,17 @@ class CSR extends FunctionUnit with HasCSRConst
mstatus
:=
mstatusNew
.
asUInt
}
io
.
in
.
ready
:=
true
.
B
io
.
out
.
valid
:=
valid
XSDebug
(
csrio
.
redirectOut
.
valid
,
"Rediret %x raiseExcepIntr:%d isSret:%d retTarget:%x sepc:%x delegs:%d deleg:%x cfInpc:%x valid:%d\n"
,
csrio
.
redirectOut
.
bits
,
raiseExceptionIntr
,
isSret
,
retTarget
,
sepc
,
delegS
,
deleg
,
cfIn
.
pc
,
valid
)
XSDebug
(
raiseExceptionIntr
&&
delegS
,
"Red(%d, %x) raiseExcepIntr:%d isSret:%d retTarget:%x sepc:%x delegs:%d deleg:%x cfInpc:%x valid:%d\n"
,
csrio
.
redirectOut
.
valid
,
csrio
.
redirectOut
.
bits
,
raiseExceptionIntr
,
isSret
,
retTarget
,
sepc
,
delegS
,
deleg
,
cfIn
.
pc
,
valid
"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
)
// perfcnt
/**
* Performance counters
*/
val
perfCntList
=
Map
(
// "Mcycle" -> (0xb00, "perfCntCondMcycle" ),
// "Minstret" -> (0xb02, "perfCntCondMinstret" ),
...
...
src/main/scala/xiangshan/backend/issue/ReservationStationNew.scala
浏览文件 @
d0e78cc9
...
...
@@ -167,32 +167,56 @@ class ReservationStationCtrl
}
// redirect and feedback
// redirect and feedback && wakeup
//
for
(
i
<-
0
until
iqSize
)
{
val
cnt
=
cntQueue
(
idxQueue
(
i
))
when
(!(
deqIdx
===
i
.
U
&&
deqValid
))
{
if
(
i
!=
0
)
{
// TODO: combine the two case
val
nextIdx
=
i
.
U
-
moveMask
(
i
-
1
)
// cnt
when
(
stateQueue
(
i
)===
s_replay
)
{
when
(
cnt
===
0.
U
)
{
stateQueue
(
nextIdx
)
:=
s_valid
}
.
otherwise
{
cnt
:=
cnt
-
1.
U
}
}
// feedback
when
(
fbMatchVec
(
i
))
{
stateQueue
(
nextIdx
)
:=
Mux
(
fbHit
,
s_idle
,
s_replay
)
cnt
:=
Mux
(
fbHit
,
cnt
,
(
replayDelay
-
1
).
U
)
}
// redirect
when
(
redHitVec
(
i
))
{
stateQueue
(
nextIdx
)
:=
s_idle
}
// wakeup
val
hitVec
=
io
.
data
.
srcUpdate
(
idxQueue
(
i
))
for
(
j
<-
0
until
srcNum
)
{
when
(
hitVec
(
j
)
&&
validQueue
(
i
))
{
srcQueue
(
nextIdx
)(
j
)
:=
true
.
B
XSDebug
(
p
"srcHit: i:${i.U} j:${j.U} moveMask(${i.U}):${moveMask(i)} nextIdx:${nextIdx}"
)
}
}
}
else
{
when
(!
moveMask
(
i
))
{
val
nextIdx
=
i
// cnt
when
(
stateQueue
(
i
)===
s_replay
)
{
when
(
cnt
===
0.
U
)
{
stateQueue
(
nextIdx
)
:=
s_valid
}
.
otherwise
{
cnt
:=
cnt
-
1.
U
}
}
// feedback
when
(
fbMatchVec
(
i
))
{
stateQueue
(
nextIdx
)
:=
Mux
(
fbHit
,
s_idle
,
s_replay
)
cnt
:=
Mux
(
fbHit
,
cnt
,
(
replayDelay
-
1
).
U
)
}
// redirect
when
(
redHitVec
(
i
))
{
stateQueue
(
nextIdx
)
:=
s_idle
}
// wakeup
val
hitVec
=
io
.
data
.
srcUpdate
(
idxQueue
(
i
))
for
(
j
<-
0
until
srcNum
)
{
when
(
hitVec
(
j
)
&&
validQueue
(
i
))
{
srcQueue
(
nextIdx
)(
j
)
:=
true
.
B
XSDebug
(
p
"srcHit: i:${i.U} j:${j.U} moveMask(${i.U}):${moveMask(i)} nextIdx:${nextIdx}"
)
}
}
}}
}
}
...
...
@@ -235,17 +259,6 @@ class ReservationStationCtrl
p
"type:${srcTypeSeq(2)}\n"
)
}
// wakeup
for
(
i
<-
0
until
IssQueSize
)
{
val
hitVec
=
io
.
data
.
srcUpdate
(
idxQueue
(
i
))
for
(
j
<-
0
until
srcNum
)
{
when
(
hitVec
(
j
)
&&
validQueue
(
i
))
{
srcQueue
(
i
.
U
-
moveMask
(
i
))(
j
)
:=
true
.
B
XSDebug
(
p
"srcHit: i:${i.U} j:${j.U}\n"
)
}
}
}
// other to Data
io
.
data
.
enqPtr
:=
idxQueue
(
Mux
(
tailPtr
.
flag
,
deqIdx
,
tailPtr
.
value
))
io
.
data
.
deqPtr
.
valid
:=
selValid
...
...
src/main/scala/xiangshan/backend/rename/FreeList.scala
浏览文件 @
d0e78cc9
...
...
@@ -49,7 +49,7 @@ class FreeList extends XSModule with HasFreeListConsts with HasCircularQueuePtrH
// do checkpoints
// val cpReqs = Vec(RenameWidth, Flipped(ValidIO(new BrqPtr)))
val
walk
=
Flipped
(
ValidIO
(
UInt
(
log2Up
(
RenameWidth
).
W
)))
val
walk
=
Flipped
(
ValidIO
(
UInt
(
log2Up
(
CommitWidth
+
1
).
W
)))
// dealloc phy regs
val
deallocReqs
=
Input
(
Vec
(
CommitWidth
,
Bool
()))
...
...
src/main/scala/xiangshan/backend/rename/Rename.scala
浏览文件 @
d0e78cc9
...
...
@@ -40,17 +40,17 @@ class Rename extends XSModule {
printRenameInfo
(
x
,
y
)
}
val
fpFreeList
,
intFreeList
=
Module
(
new
FreeList
).
io
val
fpRat
=
Module
(
new
RenameTable
(
float
=
true
)).
io
val
intFreeList
,
fpFreeList
=
Module
(
new
FreeList
).
io
val
intRat
=
Module
(
new
RenameTable
(
float
=
false
)).
io
val
fpRat
=
Module
(
new
RenameTable
(
float
=
true
)).
io
val
allPhyResource
=
Seq
((
intRat
,
intFreeList
,
false
),
(
fpRat
,
fpFreeList
,
true
))
fpFreeList
.
redirect
:=
io
.
redirect
intFreeList
.
redirect
:=
io
.
redirect
fpRat
.
redirect
:=
io
.
redirect
intRat
.
redirect
:=
io
.
redirect
fpRat
.
walkWen
:=
io
.
roqCommits
.
isWalk
intRat
.
walkWen
:=
io
.
roqCommits
.
isWalk
allPhyResource
.
map
{
case
(
rat
,
freelist
,
_
)
=>
rat
.
redirect
:=
io
.
redirect
rat
.
walkWen
:=
io
.
roqCommits
.
isWalk
freelist
.
redirect
:=
io
.
redirect
freelist
.
walk
.
valid
:=
io
.
roqCommits
.
isWalk
}
def
needDestReg
[
T
<:
CfCtrl
](
fp
:
Boolean
,
x
:
T
)
:
Bool
=
{
{
if
(
fp
)
x
.
ctrl
.
fpWen
else
x
.
ctrl
.
rfWen
&&
(
x
.
ctrl
.
ldest
=/=
0.
U
)}
...
...
@@ -58,14 +58,15 @@ class Rename extends XSModule {
def
needDestRegCommit
[
T
<:
RoqCommitInfo
](
fp
:
Boolean
,
x
:
T
)
:
Bool
=
{
{
if
(
fp
)
x
.
fpWen
else
x
.
rfWen
&&
(
x
.
ldest
=/=
0.
U
)}
}
fpFreeList
.
walk
.
valid
:=
io
.
roqCommits
.
isWalk
intFreeList
.
walk
.
valid
:=
io
.
roqCommits
.
isWalk
fpFreeList
.
walk
.
bits
:=
PopCount
((
0
until
CommitWidth
).
map
(
i
=>
io
.
roqCommits
.
valid
(
i
)
&&
needDestRegCommit
(
true
,
io
.
roqCommits
.
info
(
i
))))
intFreeList
.
walk
.
bits
:=
PopCount
((
0
until
CommitWidth
).
map
(
i
=>
io
.
roqCommits
.
valid
(
i
)
&&
needDestRegCommit
(
false
,
io
.
roqCommits
.
info
(
i
))))
fpFreeList
.
walk
.
bits
:=
PopCount
(
io
.
roqCommits
.
valid
.
zip
(
io
.
roqCommits
.
info
).
map
{
case
(
v
,
i
)
=>
v
&&
needDestRegCommit
(
true
,
i
)})
intFreeList
.
walk
.
bits
:=
PopCount
(
io
.
roqCommits
.
valid
.
zip
(
io
.
roqCommits
.
info
).
map
{
case
(
v
,
i
)
=>
v
&&
needDestRegCommit
(
false
,
i
)})
// walk has higher priority than allocation and thus we don't use isWalk here
fpFreeList
.
req
.
doAlloc
:=
intFreeList
.
req
.
canAlloc
&&
io
.
out
(
0
).
ready
intFreeList
.
req
.
doAlloc
:=
fpFreeList
.
req
.
canAlloc
&&
io
.
out
(
0
).
ready
/**
* Rename: allocate free physical register and update rename table
*/
val
uops
=
Wire
(
Vec
(
RenameWidth
,
new
MicroOp
))
uops
.
foreach
(
uop
=>
{
...
...
@@ -84,7 +85,7 @@ class Rename extends XSModule {
val
needIntDest
=
Wire
(
Vec
(
RenameWidth
,
Bool
()))
val
hasValid
=
Cat
(
io
.
in
.
map
(
_
.
valid
)).
orR
val
canOut
=
io
.
out
(
0
).
ready
&&
fpFreeList
.
req
.
canAlloc
&&
intFreeList
.
req
.
canAlloc
&&
!
io
.
roqCommits
.
isWalk
for
(
i
<-
0
until
RenameWidth
)
{
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
...
...
@@ -116,42 +117,17 @@ class Rename extends XSModule {
io
.
out
(
i
).
valid
:=
io
.
in
(
i
).
valid
&&
intFreeList
.
req
.
canAlloc
&&
fpFreeList
.
req
.
canAlloc
&&
!
io
.
roqCommits
.
isWalk
io
.
out
(
i
).
bits
:=
uops
(
i
)
// write rename table
def
writeRat
(
fp
:
Boolean
)
=
{
val
rat
=
if
(
fp
)
fpRat
else
intRat
val
freeList
=
if
(
fp
)
fpFreeList
else
intFreeList
// speculative inst write
val
specWen
=
freeList
.
req
.
allocReqs
(
i
)
&&
freeList
.
req
.
canAlloc
&&
freeList
.
req
.
doAlloc
&&
!
io
.
roqCommits
.
isWalk
// walk back write
val
commitDestValid
=
io
.
roqCommits
.
valid
(
i
)
&&
needDestRegCommit
(
fp
,
io
.
roqCommits
.
info
(
i
))
val
walkWen
=
commitDestValid
&&
io
.
roqCommits
.
isWalk
rat
.
specWritePorts
(
i
).
wen
:=
specWen
||
walkWen
rat
.
specWritePorts
(
i
).
addr
:=
Mux
(
specWen
,
uops
(
i
).
ctrl
.
ldest
,
io
.
roqCommits
.
info
(
i
).
ldest
)
rat
.
specWritePorts
(
i
).
wdata
:=
Mux
(
specWen
,
freeList
.
req
.
pdests
(
i
),
io
.
roqCommits
.
info
(
i
).
old_pdest
)
XSInfo
(
walkWen
,
{
if
(
fp
)
p
"fp"
else
p
"int "
}
+
p
"walk: "
+
p
" ldest:${rat.specWritePorts(i).addr} old_pdest:${rat.specWritePorts(i).wdata}\n"
)
rat
.
archWritePorts
(
i
).
wen
:=
commitDestValid
&&
!
io
.
roqCommits
.
isWalk
rat
.
archWritePorts
(
i
).
addr
:=
io
.
roqCommits
.
info
(
i
).
ldest
rat
.
archWritePorts
(
i
).
wdata
:=
io
.
roqCommits
.
info
(
i
).
pdest
XSInfo
(
rat
.
archWritePorts
(
i
).
wen
,
{
if
(
fp
)
p
"fp"
else
p
"int "
}
+
p
" rat arch: ldest:${rat.archWritePorts(i).addr}"
+
p
" pdest:${rat.archWritePorts(i).wdata}\n"
)
// write speculative rename table
allPhyResource
.
map
{
case
(
rat
,
freelist
,
_
)
=>
val
specWen
=
freelist
.
req
.
allocReqs
(
i
)
&&
freelist
.
req
.
canAlloc
&&
freelist
.
req
.
doAlloc
&&
!
io
.
roqCommits
.
isWalk
freeList
.
deallocReqs
(
i
)
:=
rat
.
archWritePorts
(
i
).
wen
freeList
.
deallocPregs
(
i
)
:=
io
.
roqCommits
.
info
(
i
).
old_pdest
rat
.
specWritePorts
(
i
).
wen
:=
specWen
rat
.
specWritePorts
(
i
).
addr
:=
uops
(
i
).
ctrl
.
ldest
rat
.
specWritePorts
(
i
).
wdata
:=
freelist
.
req
.
pdests
(
i
)
freelist
.
deallocReqs
(
i
)
:=
specWen
}
writeRat
(
fp
=
false
)
writeRat
(
fp
=
true
)
// read rename table
def
readRat
(
lsrcList
:
List
[
UInt
],
ldest
:
UInt
,
fp
:
Boolean
)
=
{
val
rat
=
if
(
fp
)
fpRat
else
intRat
...
...
@@ -204,4 +180,42 @@ class Rename extends XSModule {
(
fpMatch
||
intMatch
)
&&
io
.
in
(
j
).
bits
.
ctrl
.
ldest
===
io
.
in
(
i
).
bits
.
ctrl
.
ldest
}).
reverse
)
}
/**
* Instructions commit: update freelist and rename table
*/
for
(
i
<-
0
until
CommitWidth
)
{
if
(
i
>=
RenameWidth
)
{
allPhyResource
.
map
{
case
(
rat
,
_
,
_
)
=>
rat
.
specWritePorts
(
i
).
wen
:=
false
.
B
rat
.
specWritePorts
(
i
).
addr
:=
DontCare
rat
.
specWritePorts
(
i
).
wdata
:=
DontCare
}
}
allPhyResource
.
map
{
case
(
rat
,
freelist
,
fp
)
=>
// walk back write
val
commitDestValid
=
io
.
roqCommits
.
valid
(
i
)
&&
needDestRegCommit
(
fp
,
io
.
roqCommits
.
info
(
i
))
when
(
commitDestValid
&&
io
.
roqCommits
.
isWalk
)
{
rat
.
specWritePorts
(
i
).
wen
:=
true
.
B
rat
.
specWritePorts
(
i
).
addr
:=
io
.
roqCommits
.
info
(
i
).
ldest
rat
.
specWritePorts
(
i
).
wdata
:=
io
.
roqCommits
.
info
(
i
).
old_pdest
XSInfo
({
if
(
fp
)
p
"fp"
else
p
"int "
}
+
p
"walk: "
+
p
" ldest:${rat.specWritePorts(i).addr} old_pdest:${rat.specWritePorts(i).wdata}\n"
)
}
rat
.
archWritePorts
(
i
).
wen
:=
commitDestValid
&&
!
io
.
roqCommits
.
isWalk
rat
.
archWritePorts
(
i
).
addr
:=
io
.
roqCommits
.
info
(
i
).
ldest
rat
.
archWritePorts
(
i
).
wdata
:=
io
.
roqCommits
.
info
(
i
).
pdest
XSInfo
(
rat
.
archWritePorts
(
i
).
wen
,
{
if
(
fp
)
p
"fp"
else
p
"int "
}
+
p
" rat arch: ldest:${rat.archWritePorts(i).addr}"
+
p
" pdest:${rat.archWritePorts(i).wdata}\n"
)
freelist
.
deallocReqs
(
i
)
:=
rat
.
archWritePorts
(
i
).
wen
freelist
.
deallocPregs
(
i
)
:=
io
.
roqCommits
.
info
(
i
).
old_pdest
}
}
}
src/main/scala/xiangshan/backend/rename/RenameTable.scala
浏览文件 @
d0e78cc9
...
...
@@ -20,7 +20,7 @@ class RenameTable(float: Boolean) extends XSModule {
val
redirect
=
Flipped
(
ValidIO
(
new
Redirect
))
val
walkWen
=
Input
(
Bool
())
val
readPorts
=
Vec
({
if
(
float
)
4
else
3
}
*
RenameWidth
,
new
RatReadPort
)
val
specWritePorts
=
Vec
(
Rename
Width
,
new
RatWritePort
)
val
specWritePorts
=
Vec
(
Commit
Width
,
new
RatWritePort
)
val
archWritePorts
=
Vec
(
CommitWidth
,
new
RatWritePort
)
})
...
...
src/main/scala/xiangshan/backend/roq/Roq.scala
浏览文件 @
d0e78cc9
...
...
@@ -161,6 +161,46 @@ class RoqEnqPtrWrapper extends XSModule with HasCircularQueuePtrHelper {
}
// class RoqStateWrapper extends XSModule with HasCircularQueuePtrHelper {
// val io = IO(new Bundle {
// val redirect = ValidIO(new Redirect)
// val raddr = Vec(CommitWidth, Input(UInt(log2Up(numEntries).W)))
// val wen = Vec(RenameWidth, Input(Bool()))
// val waddr = Vec(RenameWidth)
// })
// val valid = Mme(RoqSize, Bool())
// val flagBkup = RegInit(VecInit(List.fill(RoqSize)(false.B)))
// for (i <- 0 until RoqSize) {
// when (reset.asBool || io.redirectOut.valid) {
// valid(i) := false.B
// }.elsewhen (io.redirectOut.valid)
// }
// when (reset.asBool) {
// valid(i)
// }
// // enqueue logic writes 6 valid
// for (i <- 0 until RenameWidth) {
// when (canEnqueue(i) && !io.redirect.valid) {
// valid(enqPtrVec(i).value) := true.B
// }
// }
// // dequeue/walk logic writes 6 valid, dequeue and walk will not happen at the same time
// for (i <- 0 until CommitWidth) {
// when (io.commits.valid(i) && state =/= s_extrawalk) {
// valid(commitReadAddr(i)) := false.B
// }
// }
// // reset: when exception, reset all valid to false
// when (io.redirectOut.valid) {
// for (i <- 0 until RoqSize) {
// valid(i) := false.B
// }
// }
// }
class
Roq
(
numWbPorts
:
Int
)
extends
XSModule
with
HasCircularQueuePtrHelper
{
val
io
=
IO
(
new
Bundle
()
{
val
redirect
=
Input
(
Valid
(
new
Redirect
))
...
...
@@ -176,11 +216,14 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
})
// instvalid field
val
valid
=
RegInit
(
VecInit
(
List
.
fill
(
RoqSize
)(
false
.
B
)))
// val valid = RegInit(VecInit(List.fill(RoqSize)(false.B)))
val
valid
=
Mem
(
RoqSize
,
Bool
())
// writeback status
val
writebacked
=
Reg
(
Vec
(
RoqSize
,
Bool
()))
// val writebacked = Reg(Vec(RoqSize, Bool()))
val
writebacked
=
Mem
(
RoqSize
,
Bool
())
// data for redirect, exception, etc.
val
flagBkup
=
RegInit
(
VecInit
(
List
.
fill
(
RoqSize
)(
false
.
B
)))
// val flagBkup = RegInit(VecInit(List.fill(RoqSize)(false.B)))
val
flagBkup
=
Mem
(
RoqSize
,
Bool
())
// data for debug
// Warn: debug_* prefix should not exist in generated verilog.
...
...
@@ -221,16 +264,20 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
* (2) write: write back from exe units
*/
val
dispatchData
=
Module
(
new
DataModuleTemplate
(
new
RoqDispatchData
,
RoqSize
,
CommitWidth
,
RenameWidth
))
val
dispatchDataRead
=
dispatchData
.
io
.
rdata
val
writebackData
=
Module
(
new
DataModuleTemplate
(
new
RoqWbData
,
RoqSize
,
CommitWidth
,
numWbPorts
))
val
writebackDataRead
=
writebackData
.
io
.
rdata
def
mergeExceptionVec
(
dpData
:
RoqDispatchData
,
wbData
:
RoqWbData
)
=
{
// these exceptions can be determined before dispatch.
// by default, let all exceptions be determined by dispatch.
// mergeVec(instrAddrMisaligned) := dpData(instrAddrMisaligned)
// mergeVec(instrAccessFault) := dpData(instrAccessFault)
// mergeVec(illegalInstr) := dpData(illegalInstr)
// mergeVec(instrPageFault) := dpData(instrPageFault)
val
mergeVec
=
WireInit
(
dpData
.
exceptionVec
)
// these exceptions are determined in execution units
mergeVec
(
illegalInstr
)
:=
wbData
.
exceptionVec
(
illegalInstr
)
mergeVec
(
breakPoint
)
:=
wbData
.
exceptionVec
(
breakPoint
)
mergeVec
(
loadAddrMisaligned
)
:=
wbData
.
exceptionVec
(
loadAddrMisaligned
)
mergeVec
(
loadAccessFault
)
:=
wbData
.
exceptionVec
(
loadAccessFault
)
...
...
@@ -310,21 +357,20 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
/**
* RedirectOut: Interrupt and Exceptions
*/
val
deqDispatchData
=
dispatchData
.
io
.
rdata
(
0
)
val
deqWritebackData
=
writebackData
.
io
.
rdata
(
0
)
val
deqDispatchData
=
dispatchData
Read
(
0
)
val
deqWritebackData
=
writebackData
Read
(
0
)
val
debug_deqUop
=
debug_microOp
(
deqPtr
.
value
)
val
deqPtrWritebacked
=
writebacked
(
deqPtr
.
value
)
&&
valid
(
deqPtr
.
value
)
val
deqExceptionVec
=
mergeExceptionVec
(
deqDispatchData
,
deqWritebackData
)
// For MMIO instructions, they should not trigger interrupts since they may be sent to lower level before it writes back.
// However, we cannot determine whether a load/store instruction is MMIO.
// Thus, we don't allow load/store instructions to trigger an interrupt.
val
intrBitSetReg
=
RegNext
(
io
.
csr
.
intrBitSet
)
val
intrEnable
=
intrBitSetReg
&&
valid
(
deqPtr
.
value
)
&&
!
hasNoSpecExec
&&
!
CommitType
.
isLoadStore
(
deqDispatchData
.
commitType
)
val
exceptionEnable
=
deqPtrWritebacked
&&
Cat
(
deqExceptionVec
).
orR
()
val
isFlushPipe
=
deqPtrWritebacked
&&
deqWritebackData
.
flushPipe
val
intrEnable
=
intrBitSetReg
&&
!
hasNoSpecExec
&&
!
CommitType
.
isLoadStore
(
deqDispatchData
.
commitType
)
val
exceptionEnable
=
writebacked
(
deqPtr
.
value
)
&&
Cat
(
deqExceptionVec
).
orR
()
val
isFlushPipe
=
writebacked
(
deqPtr
.
value
)
&&
deqWritebackData
.
flushPipe
io
.
redirectOut
:=
DontCare
io
.
redirectOut
.
valid
:=
(
state
===
s_idle
)
&&
(
intrEnable
||
exceptionEnable
||
isFlushPipe
)
io
.
redirectOut
.
valid
:=
(
state
===
s_idle
)
&&
valid
(
deqPtr
.
value
)
&&
(
intrEnable
||
exceptionEnable
||
isFlushPipe
)
io
.
redirectOut
.
bits
.
level
:=
Mux
(
isFlushPipe
,
RedirectLevel
.
flushAll
,
RedirectLevel
.
exception
)
io
.
redirectOut
.
bits
.
interrupt
:=
intrEnable
io
.
redirectOut
.
bits
.
target
:=
Mux
(
isFlushPipe
,
deqDispatchData
.
pc
+
4.
U
,
io
.
csr
.
trapTarget
)
...
...
@@ -352,8 +398,9 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
val
walkFinished
=
walkCounter
<=
CommitWidth
.
U
// extra space is used when roq has no enough space, but mispredict recovery needs such info to walk regmap
val
needExtraSpaceForMPR
=
VecInit
((
0
until
CommitWidth
).
map
(
i
=>
io
.
redirect
.
valid
&&
io
.
enq
.
needAlloc
(
i
)))
val
extraSpaceForMPR
=
Reg
(
Vec
(
RenameWidth
,
new
RoqCommitInfo
))
require
(
RenameWidth
<=
CommitWidth
)
val
needExtraSpaceForMPR
=
VecInit
((
0
until
RenameWidth
).
map
(
i
=>
io
.
redirect
.
valid
&&
io
.
enq
.
needAlloc
(
i
)))
val
extraSpaceForMPR
=
Reg
(
Vec
(
RenameWidth
,
new
RoqDispatchData
))
val
usedSpaceForMPR
=
Reg
(
Vec
(
RenameWidth
,
Bool
()))
// wiring to csr
...
...
@@ -363,25 +410,26 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
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
)))
val
commit_exception
=
dispatchData
.
io
.
rdata
.
zip
(
writebackData
.
io
.
rdata
).
map
{
case
(
d
,
w
)
=>
mergeExceptionVec
(
d
,
w
).
asUInt
.
orR
}
val
commit_block
=
VecInit
((
0
until
CommitWidth
).
map
(
i
=>
!
commit_w
(
i
)
||
commit_exception
(
i
)
||
writebackData
.
io
.
rdata
(
i
).
flushPipe
))
val
commit_exception
=
dispatchData
Read
.
zip
(
writebackDataRead
).
map
{
case
(
d
,
w
)
=>
mergeExceptionVec
(
d
,
w
).
asUInt
.
orR
}
val
commit_block
=
VecInit
((
0
until
CommitWidth
).
map
(
i
=>
!
commit_w
(
i
)
||
commit_exception
(
i
)
||
writebackData
Read
(
i
).
flushPipe
))
for
(
i
<-
0
until
CommitWidth
)
{
// defaults: state === s_idle and instructions commit
val
isBlocked
=
if
(
i
!=
0
)
Cat
(
commit_block
.
take
(
i
)).
orR
||
intrEnable
else
false
.
B
// when intrBitSetReg, allow only one instruction to commit at each clock cycle
val
isBlocked
=
if
(
i
!=
0
)
Cat
(
commit_block
.
take
(
i
)).
orR
||
intrBitSetReg
else
intrEnable
io
.
commits
.
valid
(
i
)
:=
commit_v
(
i
)
&&
commit_w
(
i
)
&&
!
isBlocked
&&
!
commit_exception
(
i
)
io
.
commits
.
info
(
i
)
:=
dispatchData
.
io
.
rdata
(
i
)
io
.
commits
.
info
(
i
)
:=
dispatchData
Read
(
i
)
when
(
state
===
s_idle
)
{
when
(
io
.
commits
.
valid
(
i
)
&&
writebackData
.
io
.
rdata
(
i
).
fflags
.
asUInt
.
orR
())
{
fflags
:=
writebackData
.
io
.
rdata
(
i
).
fflags
when
(
io
.
commits
.
valid
(
i
)
&&
writebackData
Read
(
i
).
fflags
.
asUInt
.
orR
())
{
fflags
:=
writebackData
Read
(
i
).
fflags
}
}
when
(
state
===
s_walk
)
{
io
.
commits
.
valid
(
i
)
:=
commit_v
(
i
)
&&
shouldWalkVec
(
i
)
}.
elsewhen
(
state
===
s_extrawalk
)
{
io
.
commits
.
valid
(
i
)
:=
usedSpaceForMPR
(
RenameWidth
-
i
-
1
)
io
.
commits
.
info
(
i
)
:=
extraSpaceForMPR
(
RenameWidth
-
i
-
1
)
io
.
commits
.
valid
(
i
)
:=
(
if
(
i
<
RenameWidth
)
usedSpaceForMPR
(
RenameWidth
-
i
-
1
)
else
false
.
B
)
io
.
commits
.
info
(
i
)
:=
(
if
(
i
<
RenameWidth
)
extraSpaceForMPR
(
RenameWidth
-
i
-
1
)
else
DontCare
)
state
:=
s_walk
}
...
...
@@ -393,7 +441,7 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
io
.
commits
.
info
(
i
).
pdest
,
io
.
commits
.
info
(
i
).
old_pdest
,
debug_exuData
(
deqPtrVec
(
i
).
value
),
writebackData
.
io
.
rdata
(
i
).
fflags
.
asUInt
writebackData
Read
(
i
).
fflags
.
asUInt
)
XSInfo
(
state
===
s_walk
&&
io
.
commits
.
valid
(
i
),
"walked pc %x wen %d ldst %d data %x\n"
,
debug_microOp
(
walkPtrVec
(
i
).
value
).
cf
.
pc
,
...
...
@@ -406,6 +454,9 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
io
.
commits
.
info
(
i
).
ldest
)
}
if
(!
env
.
FPGAPlatform
)
{
io
.
commits
.
info
.
map
(
info
=>
dontTouch
(
info
.
pc
))
}
io
.
csr
.
fflags
:=
fflags
io
.
csr
.
dirty_fs
:=
dirty_fs
...
...
@@ -481,8 +532,8 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
deqPtrGenModule
.
io
.
state
:=
state
deqPtrGenModule
.
io
.
deq_v
:=
commit_v
deqPtrGenModule
.
io
.
deq_w
:=
commit_w
deqPtrGenModule
.
io
.
deq_exceptionVec
:=
VecInit
(
dispatchData
.
io
.
rdata
.
zip
(
writebackData
.
io
.
rdata
).
map
{
case
(
d
,
w
)
=>
mergeExceptionVec
(
d
,
w
).
asUInt
})
deqPtrGenModule
.
io
.
deq_flushPipe
:=
writebackData
.
io
.
rdata
.
map
(
_
.
flushPipe
)
deqPtrGenModule
.
io
.
deq_exceptionVec
:=
VecInit
(
dispatchData
Read
.
zip
(
writebackDataRead
).
map
{
case
(
d
,
w
)
=>
mergeExceptionVec
(
d
,
w
).
asUInt
})
deqPtrGenModule
.
io
.
deq_flushPipe
:=
writebackData
Read
.
map
(
_
.
flushPipe
)
deqPtrGenModule
.
io
.
intrBitSetReg
:=
intrBitSetReg
deqPtrGenModule
.
io
.
hasNoSpecExec
:=
hasNoSpecExec
deqPtrGenModule
.
io
.
commitType
:=
deqDispatchData
.
commitType
...
...
@@ -493,7 +544,7 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
enqPtrGenModule
.
io
.
deq_v
:=
commit_v
(
0
)
enqPtrGenModule
.
io
.
deq_w
:=
commit_w
(
0
)
enqPtrGenModule
.
io
.
deq_exceptionVec
:=
deqExceptionVec
.
asUInt
enqPtrGenModule
.
io
.
deq_flushPipe
:=
writebackData
.
io
.
rdata
(
0
).
flushPipe
enqPtrGenModule
.
io
.
deq_flushPipe
:=
writebackData
Read
(
0
).
flushPipe
enqPtrGenModule
.
io
.
intrBitSetReg
:=
intrBitSetReg
enqPtrGenModule
.
io
.
hasNoSpecExec
:=
hasNoSpecExec
enqPtrGenModule
.
io
.
commitType
:=
deqDispatchData
.
commitType
...
...
@@ -570,6 +621,11 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
valid
(
i
)
:=
false
.
B
}
}
when
(
reset
.
asBool
)
{
for
(
i
<-
0
until
RoqSize
)
{
valid
(
i
)
:=
false
.
B
}
}
// status field: writebacked
// enqueue logic set 6 writebacked to false
...
...
src/main/scala/xiangshan/cache/dtlb.scala
浏览文件 @
d0e78cc9
...
...
@@ -387,7 +387,7 @@ class TLB(Width: Int, isDtlb: Boolean) extends TlbModule with HasCSRConst{
// reset pf when pf hit
val
pfHitReset
=
ParallelOR
(
widthMap
{
i
=>
Mux
(
resp
(
i
).
fire
(),
VecInit
(
pfHitVecVec
(
i
)).
asUInt
,
0.
U
)
})
val
pfHitRefill
=
ParallelOR
(
pfHitReset
.
asBools
)
val
pfHitRefill
=
false
.
B
//
ParallelOR(pfHitReset.asBools)
// pf update
when
(
refill
)
{
...
...
src/main/scala/xiangshan/frontend/BPU.scala
浏览文件 @
d0e78cc9
...
...
@@ -267,8 +267,8 @@ class BPUStage3 extends BPUStage {
val
pdLastHalf
=
s3IO
.
predecode
.
lastHalf
val
pds
=
s3IO
.
predecode
.
pd
val
btbResp
=
inLatch
.
resp
.
btb
val
btbHits
=
btbResp
.
hits
.
asUInt
val
btbResp
=
WireInit
(
inLatch
.
resp
.
btb
)
val
btbHits
=
WireInit
(
btbResp
.
hits
.
asUInt
)
val
bimTakens
=
VecInit
(
inLatch
.
resp
.
bim
.
ctrs
.
map
(
_
(
1
)))
val
brs
=
pdMask
&
Reverse
(
Cat
(
pds
.
map
(
_
.
isBr
)))
...
...
@@ -287,6 +287,8 @@ class BPUStage3 extends BPUStage {
val
prevHalfTakenMask
=
prevHalfTaken
.
asUInt
val
brTakens
=
((
brs
&
brPred
|
prevHalfTakenMask
)
&
~
loopRes
)
// VecInit((0 until PredictWidth).map(i => brs(i) && (brPred(i) || (if (i == 0) prevHalfTaken else false.B)) && !loopRes(i)))
// we should provide btb resp as well
btbHits
:=
btbResp
.
hits
.
asUInt
|
prevHalfTakenMask
// 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
)))
...
...
src/main/scala/xiangshan/frontend/Bim.scala
浏览文件 @
d0e78cc9
...
...
@@ -108,9 +108,9 @@ class BIM extends BasePredictor with BimParams {
when
(
needToUpdate
)
{
when
(
wrbypass_hit
)
{
wrbypass_ctrs
(
wrbypass_hit_idx
)(
updateBank
)
:=
newCtr
wrbypass_ctr_valids
(
wrbypass_
enq
_idx
)(
updateBank
)
:=
true
.
B
wrbypass_ctr_valids
(
wrbypass_
hit
_idx
)(
updateBank
)
:=
true
.
B
}
.
otherwise
{
wrbypass_ctrs
(
wrbypass_
hit
_idx
)(
updateBank
)
:=
newCtr
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
...
...
src/main/scala/xiangshan/frontend/IFU.scala
浏览文件 @
d0e78cc9
...
...
@@ -92,7 +92,8 @@ class PrevHalfInstr extends XSBundle {
val
target
=
UInt
(
VAddrBits
.
W
)
val
instr
=
UInt
(
16.
W
)
val
ipf
=
Bool
()
val
newPtr
=
UInt
(
log2Up
(
ExtHistoryLength
).
W
)
val
meta
=
new
BpuMeta
// val newPtr = UInt(log2Up(ExtHistoryLength).W)
}
@chiselName
...
...
@@ -200,9 +201,11 @@ class IFU extends XSModule with HasIFUConst
// set to invalid once consumed or redirect from backend
val
if3_prevHalfConsumed
=
if3_prevHalfInstrMet
&&
if3_fire
val
if3_prevHalfFlush
=
if4_flush
when
(
hasPrevHalfInstrReq
&&
!
if3_prevHalfFlush
)
{
when
(
if3_prevHalfFlush
)
{
if3_prevHalfInstr
.
valid
:=
false
.
B
}.
elsewhen
(
hasPrevHalfInstrReq
)
{
if3_prevHalfInstr
.
valid
:=
true
.
B
}.
elsewhen
(
if3_prevHalfConsumed
||
if3_prevHalfFlush
)
{
}.
elsewhen
(
if3_prevHalfConsumed
)
{
if3_prevHalfInstr
.
valid
:=
false
.
B
}
when
(
hasPrevHalfInstrReq
)
{
...
...
@@ -280,9 +283,9 @@ class IFU extends XSModule with HasIFUConst
val
if4_bp
=
Wire
(
new
BranchPrediction
)
if4_bp
:=
bpu
.
io
.
out
(
2
)
if4_bp
.
takens
:=
bpu
.
io
.
out
(
2
).
takens
&
if4_mask
if4_bp
.
brMask
:=
bpu
.
io
.
out
(
2
).
brMask
&
if4_mask
if4_bp
.
jalMask
:=
bpu
.
io
.
out
(
2
).
jalMask
&
if4_mask
//
if4_bp.takens := bpu.io.out(2).takens & if4_mask
//
if4_bp.brMask := bpu.io.out(2).brMask & if4_mask
//
if4_bp.jalMask := bpu.io.out(2).jalMask & if4_mask
if4_predicted_gh
:=
if4_gh
.
update
(
if4_bp
.
hasNotTakenBrs
,
if4_bp
.
takenOnBr
)
...
...
@@ -311,9 +314,11 @@ class IFU extends XSModule with HasIFUConst
val
if4_prevHalfFlush
=
if4_flush
val
if4_takenPrevHalf
=
WireInit
(
if4_prevHalfInstrMet
&&
if4_prevHalfInstr
.
bits
.
taken
)
when
(
if3_prevHalfConsumed
)
{
when
(
if4_prevHalfFlush
)
{
if4_prevHalfInstr
.
valid
:=
false
.
B
}.
elsewhen
(
if3_prevHalfConsumed
)
{
if4_prevHalfInstr
.
valid
:=
if3_prevHalfInstr
.
valid
}.
elsewhen
(
if4_prevHalfConsumed
||
if4_prevHalfFlush
)
{
}.
elsewhen
(
if4_prevHalfConsumed
)
{
if4_prevHalfInstr
.
valid
:=
false
.
B
}
...
...
@@ -327,7 +332,6 @@ class IFU extends XSModule with HasIFUConst
// this is result of the last half RVI
prevHalfInstrReq
.
bits
.
taken
:=
if4_bp
.
lastHalfRVITaken
prevHalfInstrReq
.
bits
.
ghInfo
:=
if4_gh
prevHalfInstrReq
.
bits
.
newPtr
:=
DontCare
prevHalfInstrReq
.
bits
.
fetchpc
:=
if4_pc
prevHalfInstrReq
.
bits
.
idx
:=
idx
prevHalfInstrReq
.
bits
.
pc
:=
if4_pd
.
pc
(
idx
)
...
...
@@ -335,6 +339,7 @@ class IFU extends XSModule with HasIFUConst
prevHalfInstrReq
.
bits
.
target
:=
if4_bp
.
lastHalfRVITarget
prevHalfInstrReq
.
bits
.
instr
:=
if4_pd
.
instrs
(
idx
)(
15
,
0
)
prevHalfInstrReq
.
bits
.
ipf
:=
if4_ipf
prevHalfInstrReq
.
bits
.
meta
:=
bpu
.
io
.
bpuMeta
(
idx
)
def
if4_nextValidPCNotEquals
(
pc
:
UInt
)
=
if3_valid
&&
if3_pc
=/=
pc
||
!
if3_valid
&&
(
if2_valid
&&
if2_pc
=/=
pc
)
||
...
...
@@ -462,6 +467,10 @@ class IFU extends XSModule with HasIFUConst
fetchPacketWire
.
pnpc
(
if4_bp
.
jmpIdx
)
:=
if4_bp
.
target
}
fetchPacketWire
.
bpuMeta
:=
bpu
.
io
.
bpuMeta
// save it for update
when
(
if4_pendingPrevHalfInstr
)
{
fetchPacketWire
.
bpuMeta
(
0
)
:=
if4_prevHalfInstr
.
bits
.
meta
}
(
0
until
PredictWidth
).
foreach
(
i
=>
{
val
meta
=
fetchPacketWire
.
bpuMeta
(
i
)
meta
.
hist
:=
final_gh
...
...
src/main/scala/xiangshan/frontend/Ibuffer.scala
浏览文件 @
d0e78cc9
...
...
@@ -52,24 +52,33 @@ class Ibuffer extends XSModule with HasCircularQueuePtrHelper {
}
// Ibuffer define
val
ibuf
=
Mem
(
IBufSize
,
new
IBufEntry
)
val
ibuf
=
Reg
(
Vec
(
IBufSize
,
new
IBufEntry
)
)
val
head_ptr
=
RegInit
(
IbufPtr
(
false
.
B
,
0.
U
))
val
tail_ptr
=
RegInit
(
IbufPtr
(
false
.
B
,
0.
U
))
val
tail_vec
=
RegInit
(
VecInit
((
0
until
PredictWidth
).
map
(
_
.
U
.
asTypeOf
(
new
IbufPtr
))))
val
tail_ptr
=
tail_vec
(
0
)
val
validEntries
=
distanceBetween
(
tail_ptr
,
head_ptr
)
// valid entries
// val validEntries = distanceBetween(tail_ptr, head_ptr) // valid entries
val
validEntries
=
RegInit
(
0.
U
(
log2Up
(
IBufSize
+
1
).
W
))
// valid entries
val
allowEnq
=
RegInit
(
true
.
B
)
val
enqValid
=
IBufSize
.
U
-
PredictWidth
.
U
>=
validEntries
// val enqValid = (IBufSize.U - PredictWidth.U)
>= validEntries
val
deqValid
=
validEntries
>
0.
U
val
numEnq
=
Mux
(
io
.
in
.
fire
,
PopCount
(
io
.
in
.
bits
.
mask
),
0.
U
)
val
numDeq
=
Mux
(
deqValid
,
PopCount
(
io
.
out
.
map
(
_
.
fire
)),
0.
U
)
validEntries
:=
validEntries
+
numEnq
-
numDeq
allowEnq
:=
(
IBufSize
.
U
-
PredictWidth
.
U
)
>=
(
validEntries
+
numEnq
)
// Enque
io
.
in
.
ready
:=
enqValid
io
.
in
.
ready
:=
allowEnq
val
enq_vec
=
Wire
(
Vec
(
PredictWidth
,
UInt
(
log2Up
(
IBufSize
).
W
)))
val
offset
=
Wire
(
Vec
(
PredictWidth
,
UInt
(
log2Up
(
PredictWidth
).
W
)))
for
(
i
<-
0
until
PredictWidth
)
{
if
(
i
==
0
)
{
enq_vec
(
i
)
:=
tail_ptr
.
value
offset
(
i
)
:=
0.
U
}
else
{
enq_vec
(
i
)
:=
tail_ptr
.
value
+
PopCount
(
io
.
in
.
bits
.
pdmask
(
i
-
1
,
0
))
offset
(
i
)
:=
PopCount
(
io
.
in
.
bits
.
pdmask
(
i
-
1
,
0
))
}
}
...
...
@@ -87,11 +96,11 @@ class Ibuffer extends XSModule with HasCircularQueuePtrHelper {
inWire
.
ipf
:=
io
.
in
.
bits
.
ipf
inWire
.
acf
:=
io
.
in
.
bits
.
acf
inWire
.
crossPageIPFFix
:=
io
.
in
.
bits
.
crossPageIPFFix
ibuf
(
enq_vec
(
i
)
)
:=
inWire
ibuf
(
tail_vec
(
offset
(
i
)).
value
)
:=
inWire
}
}
tail_
ptr
:=
tail_ptr
+
PopCount
(
io
.
in
.
bits
.
mask
)
tail_
vec
:=
VecInit
(
tail_vec
.
map
(
_
+
PopCount
(
io
.
in
.
bits
.
mask
))
)
}
// Deque
...
...
@@ -125,10 +134,11 @@ class Ibuffer extends XSModule with HasCircularQueuePtrHelper {
// Flush
when
(
io
.
flush
)
{
validEntries
:=
0.
U
allowEnq
:=
true
.
B
head_ptr
.
value
:=
0.
U
head_ptr
.
flag
:=
false
.
B
tail_ptr
.
value
:=
0.
U
tail_ptr
.
flag
:=
false
.
B
tail_vec
:=
VecInit
((
0
until
PredictWidth
).
map
(
_
.
U
.
asTypeOf
(
new
IbufPtr
)))
}
// Debug info
...
...
@@ -164,7 +174,7 @@ class Ibuffer extends XSModule with HasCircularQueuePtrHelper {
// )
// }
XSDebug
(
p
"last_head_ptr=$head_ptr last_tail_ptr=$tail_ptr\n"
)
XSDebug
(
p
"
validEntries=$validEntries,
last_head_ptr=$head_ptr last_tail_ptr=$tail_ptr\n"
)
for
(
i
<-
0
until
IBufSize
/
8
)
{
XSDebug
(
"%x | %x | %x | %x | %x | %x | %x | %x\n"
,
ibuf
(
i
*
8
+
0
).
inst
,
...
...
src/test/csrc/assert.cpp
0 → 100644
浏览文件 @
d0e78cc9
#include "common.h"
#include "emu.h"
int
assert_count
=
0
;
static
pthread_mutex_t
assert_mutex
;
void
assert_init
()
{
pthread_mutex_init
(
&
assert_mutex
,
0
);
}
void
assert_finish
()
{
pthread_mutex_destroy
(
&
assert_mutex
);
}
extern
"C"
void
xs_assert
(
long
long
line
)
{
pthread_mutex_lock
(
&
assert_mutex
);
printf
(
"Assertion failed at line %lld
\n
."
,
line
);
assert_count
++
;
pthread_mutex_unlock
(
&
assert_mutex
);
}
src/test/csrc/common.h
浏览文件 @
d0e78cc9
...
...
@@ -6,6 +6,7 @@
#include <cstdlib>
#include <stdint.h>
#include <assert.h>
#include <pthread.h>
#define ANSI_COLOR_RED "\x1b[31m"
#define ANSI_COLOR_GREEN "\x1b[32m"
...
...
@@ -21,4 +22,8 @@
#include "cosimulation.h"
#endif
extern
int
assert_count
;
void
assert_init
();
void
assert_finish
();
#endif // __COMMON_H
src/test/csrc/difftest.cpp
浏览文件 @
d0e78cc9
...
...
@@ -180,7 +180,7 @@ int difftest_step(DiffState *s) {
// ref_difftest_exec(1);//TODO
}
else
{
assert
(
s
->
commit
>
0
&&
s
->
commit
<=
6
);
assert
(
s
->
commit
>
0
&&
s
->
commit
<=
DIFFTEST_WIDTH
);
for
(
int
i
=
0
;
i
<
s
->
commit
;
i
++
){
pc_wb_queue
[
wb_pointer
]
=
s
->
wpc
[
i
];
wen_wb_queue
[
wb_pointer
]
=
selectBit
(
s
->
wen
,
i
);
...
...
src/test/csrc/difftest.h
浏览文件 @
d0e78cc9
...
...
@@ -5,6 +5,8 @@
#include <assert.h>
#include <string.h>
#define DIFFTEST_WIDTH 6
typedef
uint64_t
rtlreg_t
;
typedef
uint64_t
paddr_t
;
...
...
@@ -96,4 +98,7 @@ int difftest_step(DiffState *s);
int
difftest_store_step
(
uint64_t
*
saddr
,
uint64_t
*
sdata
,
uint8_t
*
smask
);
void
difftest_display
(
uint8_t
mode
);
uint64_t
get_nemu_this_pc
();
void
set_nemu_this_pc
(
uint64_t
pc
);
#endif
src/test/csrc/emu.cpp
浏览文件 @
d0e78cc9
...
...
@@ -2,18 +2,12 @@
#include "sdcard.h"
#include "difftest.h"
#include <getopt.h>
#include<signal.h>
#include<unistd.h>
#include
<signal.h>
#include
<unistd.h>
#include "ram.h"
#include "zlib.h"
#include "compress.h"
void
*
get_ram_start
();
long
get_ram_size
();
uint64_t
get_nemu_this_pc
();
void
set_nemu_this_pc
(
uint64_t
pc
);
static
inline
void
print_help
(
const
char
*
file
)
{
printf
(
"Usage: %s [OPTION...]
\n
"
,
file
);
printf
(
"
\n
"
);
...
...
@@ -90,6 +84,7 @@ Emulator::Emulator(int argc, const char *argv[]):
srand
(
args
.
seed
);
srand48
(
args
.
seed
);
Verilated
::
randReset
(
2
);
assert_init
();
// init core
reset_ncycles
(
10
);
...
...
@@ -132,6 +127,7 @@ Emulator::Emulator(int argc, const char *argv[]):
Emulator
::~
Emulator
()
{
ram_finish
();
assert_finish
();
#ifdef VM_SAVABLE
if
(
args
.
enable_snapshot
&&
trapCode
!=
STATE_GOODTRAP
&&
trapCode
!=
STATE_LIMIT_EXCEEDED
)
{
...
...
@@ -178,21 +174,45 @@ inline void Emulator::read_wb_info(uint64_t *wpc, uint64_t *wdata, uint32_t *wds
#define dut_ptr_wpc(x) wpc[x] = dut_ptr->io_difftest_wpc_##x
#define dut_ptr_wdata(x) wdata[x] = dut_ptr->io_difftest_wdata_##x
#define dut_ptr_wdst(x) wdst[x] = dut_ptr->io_difftest_wdst_##x
dut_ptr_wpc
(
0
);
dut_ptr_wdata
(
0
);
dut_ptr_wdst
(
0
);
dut_ptr_wpc
(
1
);
dut_ptr_wdata
(
1
);
dut_ptr_wdst
(
1
);
dut_ptr_wpc
(
2
);
dut_ptr_wdata
(
2
);
dut_ptr_wdst
(
2
);
dut_ptr_wpc
(
3
);
dut_ptr_wdata
(
3
);
dut_ptr_wdst
(
3
);
dut_ptr_wpc
(
4
);
dut_ptr_wdata
(
4
);
dut_ptr_wdst
(
4
);
dut_ptr_wpc
(
5
);
dut_ptr_wdata
(
5
);
dut_ptr_wdst
(
5
);
#define dut_ptr_read_wb(x) dut_ptr_wpc(x); dut_ptr_wdata(x); dut_ptr_wdst(x);
#if DIFFTEST_WIDTH >= 13 || DIFFTEST_WIDTH < 6
#error "not supported difftest width"
#endif
dut_ptr_read_wb
(
0
);
dut_ptr_read_wb
(
1
);
dut_ptr_read_wb
(
2
);
dut_ptr_read_wb
(
3
);
dut_ptr_read_wb
(
4
);
dut_ptr_read_wb
(
5
);
#if DIFFTEST_WIDTH >= 7
dut_ptr_read_wb
(
6
);
#endif
#if DIFFTEST_WIDTH >= 8
dut_ptr_read_wb
(
7
);
#endif
#if DIFFTEST_WIDTH >= 9
dut_ptr_read_wb
(
8
);
#endif
#if DIFFTEST_WIDTH >= 10
dut_ptr_read_wb
(
9
);
#endif
#if DIFFTEST_WIDTH >= 11
dut_ptr_read_wb
(
10
);
#endif
#if DIFFTEST_WIDTH >= 12
dut_ptr_read_wb
(
11
);
#endif
}
inline
void
Emulator
::
read_store_info
(
uint64_t
*
saddr
,
uint64_t
*
sdata
,
uint8_t
*
smask
)
{
#define dut_ptr_saddr(x) saddr[x] = dut_ptr->io_difftest_storeAddr_##x
#define dut_ptr_sdata(x) sdata[x] = dut_ptr->io_difftest_storeData_##x
#define dut_ptr_smask(x) smask[x] = dut_ptr->io_difftest_storeMask_##x
dut_ptr_saddr
(
0
);
dut_ptr_saddr
(
1
);
dut_ptr_
sdata
(
0
);
dut_ptr_sdata
(
1
);
dut_ptr_
smask
(
0
);
dut_ptr_smask
(
1
);
#define dut_ptr_read_store(x) dut_ptr_saddr(x); dut_ptr_sdata(x); dut_ptr_smask(x
);
dut_ptr_
read_store
(
0
);
dut_ptr_
read_store
(
1
);
}
inline
void
Emulator
::
reset_ncycles
(
size_t
cycles
)
{
...
...
@@ -295,6 +315,11 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) {
max_cycle
--
;
if
(
dut_ptr
->
io_trap_valid
)
trapCode
=
dut_ptr
->
io_trap_code
;
if
(
assert_count
>
0
)
{
difftest_display
(
dut_ptr
->
io_difftest_priviledgeMode
);
eprintf
(
"The simulation stopped. There might be some assertion failed.
\n
"
);
trapCode
=
STATE_ABORT
;
}
if
(
trapCode
!=
STATE_RUNNING
)
break
;
if
(
lastcommit
-
max_cycle
>
stuck_limit
&&
hascommit
)
{
...
...
@@ -367,12 +392,12 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) {
}
#ifdef VM_SAVABLE
static
int
snapshot_count
=
0
;
if
(
args
.
enable_snapshot
&&
trapCode
!=
STATE_GOODTRAP
&&
t
-
lasttime_snapshot
>
6
000
*
SNAPSHOT_INTERVAL
)
{
if
(
args
.
enable_snapshot
&&
trapCode
!=
STATE_GOODTRAP
&&
t
-
lasttime_snapshot
>
1
000
*
SNAPSHOT_INTERVAL
)
{
// save snapshot every 60s
time_t
now
=
time
(
NULL
);
snapshot_save
(
snapshot_filename
(
now
));
lasttime_snapshot
=
t
;
// dump
snapshot to file every 10 minute
s
// dump
one snapshot to file every 60 snapshot
s
snapshot_count
++
;
if
(
snapshot_count
==
60
)
{
snapshot_slot
[
0
].
save
();
...
...
@@ -382,12 +407,6 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) {
#endif
}
if
(
Verilated
::
gotFinish
())
{
difftest_display
(
dut_ptr
->
io_difftest_priviledgeMode
);
eprintf
(
"The simulation stopped. There might be some assertion failed.
\n
"
);
trapCode
=
STATE_ABORT
;
}
#if VM_TRACE == 1
if
(
enable_waveform
)
tfp
->
close
();
#endif
...
...
@@ -465,8 +484,8 @@ void Emulator::display_trapinfo() {
}
double
ipc
=
(
double
)
instrCnt
/
(
cycleCnt
-
500
);
eprintf
(
ANSI_COLOR_MAGENTA
"total guest instructions = %"
PRIu64
"
\n
"
ANSI_COLOR_RESET
,
instrCnt
);
eprintf
(
ANSI_COLOR_MAGENTA
"instrCnt = %
"
PRIu64
", cycleCnt = %
"
PRIu64
", IPC = %lf
\n
"
ANSI_COLOR_RESET
,
eprintf
(
ANSI_COLOR_MAGENTA
"total guest instructions = %
'
"
PRIu64
"
\n
"
ANSI_COLOR_RESET
,
instrCnt
);
eprintf
(
ANSI_COLOR_MAGENTA
"instrCnt = %
'"
PRIu64
", cycleCnt = %'
"
PRIu64
", IPC = %lf
\n
"
ANSI_COLOR_RESET
,
instrCnt
,
cycleCnt
,
ipc
);
}
...
...
src/test/csrc/emu.h
浏览文件 @
d0e78cc9
...
...
@@ -3,8 +3,7 @@
#include "VXSSimSoC.h"
#include <verilated_vcd_c.h> // Trace file format header
#define DIFFTEST_WIDTH 6
#define SNAPSHOT_INTERVAL 10 // unit: second
#define SNAPSHOT_INTERVAL 60 // unit: second
struct
EmuArgs
{
uint32_t
seed
;
...
...
src/test/csrc/main.cpp
浏览文件 @
d0e78cc9
#include "emu.h"
#include <functional>
#include <locale.h>
static
char
mybuf
[
BUFSIZ
];
...
...
@@ -12,6 +13,9 @@ int main(int argc, const char** argv) {
setbuf
(
stderr
,
mybuf
);
// enable thousands separator for printf()
setlocale
(
LC_NUMERIC
,
""
);
auto
emu
=
new
Emulator
(
argc
,
argv
);
get_sc_time_stamp
=
[
&
emu
]()
->
double
{
...
...
@@ -27,9 +31,9 @@ int main(int argc, const char** argv) {
extern
uint32_t
uptime
(
void
);
uint32_t
ms
=
uptime
();
eprintf
(
ANSI_COLOR_BLUE
"Seed=%d Guest cycle spent: %"
PRIu64
eprintf
(
ANSI_COLOR_BLUE
"Seed=%d Guest cycle spent: %
'
"
PRIu64
" (this will be different from cycleCnt if emu loads a snapshot)
\n
"
ANSI_COLOR_RESET
,
args
.
seed
,
cycles
);
eprintf
(
ANSI_COLOR_BLUE
"Host time spent: %dms
\n
"
ANSI_COLOR_RESET
,
ms
);
eprintf
(
ANSI_COLOR_BLUE
"Host time spent: %
'
dms
\n
"
ANSI_COLOR_RESET
,
ms
);
// return !is_good_trap;
return
trapcode
;
...
...
src/test/csrc/ram.cpp
浏览文件 @
d0e78cc9
...
...
@@ -12,6 +12,8 @@ CoDRAMsim3 *dram = NULL;
static
uint64_t
*
ram
;
static
long
img_size
=
0
;
static
pthread_mutex_t
ram_mutex
;
void
*
get_img_start
()
{
return
&
ram
[
0
];
}
long
get_img_size
()
{
return
img_size
;
}
void
*
get_ram_start
()
{
return
&
ram
[
0
];
}
...
...
@@ -155,6 +157,8 @@ void init_ram(const char *img) {
dram
=
new
CoDRAMsim3
(
DRAMSIM3_CONFIG
,
DRAMSIM3_OUTDIR
);
#endif
pthread_mutex_init
(
&
ram_mutex
,
0
);
}
void
ram_finish
()
{
...
...
@@ -162,13 +166,18 @@ void ram_finish() {
#ifdef WITH_DRAMSIM3
dramsim3_finish
();
#endif
pthread_mutex_destroy
(
&
ram_mutex
);
}
extern
"C"
uint64_t
ram_read_helper
(
uint8_t
en
,
uint64_t
rIdx
)
{
if
(
en
&&
rIdx
>=
EMU_RAM_SIZE
/
sizeof
(
uint64_t
))
{
rIdx
%=
EMU_RAM_SIZE
/
sizeof
(
uint64_t
);
}
return
(
en
)
?
ram
[
rIdx
]
:
0
;
pthread_mutex_lock
(
&
ram_mutex
);
uint64_t
rdata
=
(
en
)
?
ram
[
rIdx
]
:
0
;
pthread_mutex_unlock
(
&
ram_mutex
);
return
rdata
;
}
extern
"C"
void
ram_write_helper
(
uint64_t
wIdx
,
uint64_t
wdata
,
uint64_t
wmask
,
uint8_t
wen
)
{
...
...
@@ -177,7 +186,9 @@ extern "C" void ram_write_helper(uint64_t wIdx, uint64_t wdata, uint64_t wmask,
printf
(
"ERROR: ram wIdx = 0x%lx out of bound!
\n
"
,
wIdx
);
assert
(
wIdx
<
EMU_RAM_SIZE
/
sizeof
(
uint64_t
));
}
pthread_mutex_lock
(
&
ram_mutex
);
ram
[
wIdx
]
=
(
ram
[
wIdx
]
&
~
wmask
)
|
(
wdata
&
wmask
);
pthread_mutex_unlock
(
&
ram_mutex
);
}
}
...
...
src/test/csrc/ram.h
浏览文件 @
d0e78cc9
...
...
@@ -8,6 +8,8 @@
void
init_ram
(
const
char
*
img
);
void
ram_finish
();
void
*
get_ram_start
();
long
get_ram_size
();
#ifdef WITH_DRAMSIM3
// 4*64 bits
...
...
src/test/vsrc/assert.v
0 → 100644
浏览文件 @
d0e78cc9
import
"DPI-C"
function
void
xs_assert
(
input
longint
line
);
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录