Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenXiangShan
XiangShan
提交
4a28083f
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,发现更多精彩内容 >>
提交
4a28083f
编写于
12月 18, 2020
作者:
Y
Yinan Xu
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'origin/master' into debian-gogogo
上级
81f6dca4
77701a78
变更
8
显示空白变更内容
内联
并排
Showing
8 changed file
with
324 addition
and
54 deletion
+324
-54
Makefile
Makefile
+11
-0
scripts/coverage/statistics.py
scripts/coverage/statistics.py
+213
-16
src/main/scala/utils/ParallelMux.scala
src/main/scala/utils/ParallelMux.scala
+25
-2
src/main/scala/utils/PriorityMuxGen.scala
src/main/scala/utils/PriorityMuxGen.scala
+19
-0
src/main/scala/xiangshan/Bundle.scala
src/main/scala/xiangshan/Bundle.scala
+9
-9
src/main/scala/xiangshan/frontend/IFU.scala
src/main/scala/xiangshan/frontend/IFU.scala
+15
-27
src/test/csrc/emu.cpp
src/test/csrc/emu.cpp
+28
-0
src/test/csrc/emu.h
src/test/csrc/emu.h
+4
-0
未找到文件。
Makefile
浏览文件 @
4a28083f
...
@@ -90,6 +90,12 @@ VEXTRA_FLAGS += --savable
...
@@ -90,6 +90,12 @@ VEXTRA_FLAGS += --savable
EMU_CXXFLAGS
+=
-DVM_SAVABLE
EMU_CXXFLAGS
+=
-DVM_SAVABLE
endif
endif
# Verilator coverage
EMU_COVERAGE
?=
ifeq
($(EMU_COVERAGE),1)
VEXTRA_FLAGS
+=
--coverage-line
--coverage-toggle
endif
# co-simulation with DRAMsim3
# co-simulation with DRAMsim3
ifeq
($(WITH_DRAMSIM3),1)
ifeq
($(WITH_DRAMSIM3),1)
EMU_CXXFLAGS
+=
-I
$(DRAMSIM3_HOME)
/src
EMU_CXXFLAGS
+=
-I
$(DRAMSIM3_HOME)
/src
...
@@ -167,6 +173,11 @@ emu: $(EMU)
...
@@ -167,6 +173,11 @@ emu: $(EMU)
ls
build
ls
build
$(EMU)
-i
$(IMAGE)
$(EMU_FLAGS)
$(EMU)
-i
$(IMAGE)
$(EMU_FLAGS)
coverage
:
verilator_coverage
--annotate
build/logs/annotated
--annotate-min
1 build/logs/coverage.dat
python3 scripts/coverage/coverage.py build/logs/annotated/XSSimTop.v build/XSSimTop_annotated.v
python3 scripts/coverage/statistics.py build/XSSimTop_annotated.v
>
build/coverage.log
# extract verilog module from sim_top.v
# extract verilog module from sim_top.v
# usage: make vme VME_MODULE=Roq
# usage: make vme VME_MODULE=Roq
vme
:
$(SIM_TOP_V)
vme
:
$(SIM_TOP_V)
...
...
scripts/coverage/statistics.py
浏览文件 @
4a28083f
...
@@ -3,26 +3,223 @@
...
@@ -3,26 +3,223 @@
import
sys
import
sys
import
re
import
re
import
copy
import
copy
import
pprint
if
__name__
==
"__main__"
:
COVERRED
=
"COVERRED"
assert
len
(
sys
.
argv
)
==
2
,
"Expect input_file"
NOT_COVERRED
=
"NOT_COVERRED"
input_file
=
sys
.
argv
[
1
]
DONTCARE
=
"DONTCARE"
coverred
=
0
BEGIN
=
"BEGIN"
not_coverred
=
0
END
=
"END"
CHILDREN
=
"CHILDREN"
MODULE
=
"MODULE"
INSTANCE
=
"INSTANCE"
TYPE
=
"TYPE"
ROOT
=
"ROOT"
NODE
=
"NODE"
SELFCOVERAGE
=
"SELFCOVERAGE"
TREECOVERAGE
=
"TREECOVERAGE"
def
get_lines
(
input_file
):
lines
=
[]
with
open
(
input_file
)
as
f
:
with
open
(
input_file
)
as
f
:
for
line
in
f
:
for
line
in
f
:
coverred_pattern
=
re
.
compile
(
'^\s*(\d+)\s+if'
)
lines
.
append
(
line
)
not_coverred_pattern
=
re
.
compile
(
'^\s*(%0+)\s+if'
)
return
lines
coverred_match
=
coverred_pattern
.
search
(
line
)
def
get_line_annotation
(
lines
):
not_coverred_match
=
not_coverred_pattern
.
search
(
line
)
line_annotations
=
[]
# pattern_1: 040192 if(array_0_MPORT_en & array_0_MPORT_mask) begin
# pattern_2: 2218110 end else if (_T_30) begin // @[Conditional.scala 40:58]
# pattern_2: 000417 end else begin
coverred_pattern_1
=
re
.
compile
(
'^\s*(\d+)\s+if'
)
coverred_pattern_2
=
re
.
compile
(
'^\s*(\d+)\s+end else'
)
not_coverred_pattern_1
=
re
.
compile
(
'^\s*(%0+)\s+if'
)
not_coverred_pattern_2
=
re
.
compile
(
'^\s*(%0+)\s+end else'
)
for
line
in
lines
:
coverred_match
=
coverred_pattern_1
.
search
(
line
)
or
coverred_pattern_2
.
search
(
line
)
not_coverred_match
=
not_coverred_pattern_1
.
search
(
line
)
or
not_coverred_pattern_2
.
search
(
line
)
assert
not
(
coverred_match
and
not_coverred_match
)
assert
not
(
coverred_match
and
not_coverred_match
)
if
coverred_match
:
if
coverred_match
:
line_annotations
.
append
(
COVERRED
)
elif
not_coverred_match
:
line_annotations
.
append
(
NOT_COVERRED
)
else
:
line_annotations
.
append
(
DONTCARE
)
return
line_annotations
# get the line coverage statistics in line range [start, end)
def
get_coverage_statistics
(
line_annotations
,
start
,
end
):
coverred
=
0
not_coverred
=
0
for
i
in
range
(
start
,
end
):
if
line_annotations
[
i
]
==
COVERRED
:
coverred
+=
1
coverred
+=
1
if
not_coverred_match
:
if
line_annotations
[
i
]
==
NOT_COVERRED
:
not_coverred
+=
1
not_coverred
+=
1
print
(
"cover: %d not_cover: %d coverage: %f"
%
(
coverred
,
not_coverred
,
float
(
coverred
)
/
(
coverred
+
not_coverred
)))
# deal with divide by zero
coverage
=
1.0
if
coverred
+
not_coverred
!=
0
:
coverage
=
float
(
coverred
)
/
(
coverred
+
not_coverred
)
return
(
coverred
,
not_coverred
,
coverage
)
# get modules and all it's submodules
def
get_modules
(
lines
):
modules
=
{}
module_pattern
=
re
.
compile
(
"module (\w+)\("
)
endmodule_pattern
=
re
.
compile
(
"endmodule"
)
submodule_pattern
=
re
.
compile
(
"(\w+) (\w+) \( // @\[\w+.scala \d+:\d+\]"
)
line_count
=
0
name
=
"ModuleName"
for
line
in
lines
:
module_match
=
module_pattern
.
search
(
line
)
endmodule_match
=
endmodule_pattern
.
search
(
line
)
submodule_match
=
submodule_pattern
.
search
(
line
)
assert
not
(
module_match
and
endmodule_match
)
if
module_match
:
name
=
module_match
.
group
(
1
)
# print("module_match: module: %s" % name)
assert
name
not
in
modules
# [begin
modules
[
name
]
=
{}
modules
[
name
][
BEGIN
]
=
line_count
# the first time we see a module, we treat as a root node
modules
[
name
][
TYPE
]
=
ROOT
if
endmodule_match
:
# print("endmodule_match: module: %s" % name)
assert
name
in
modules
assert
END
not
in
modules
[
name
]
# end)
modules
[
name
][
END
]
=
line_count
+
1
# reset module name to invalid
name
=
"ModuleName"
if
submodule_match
:
# submodule must be inside hierarchy
assert
name
!=
"ModuleName"
submodule_type
=
submodule_match
.
group
(
1
)
submodule_instance
=
submodule_match
.
group
(
2
)
# print("submodule_match: type: %s instance: %s" % (submodule_type, submodule_instance))
# submodules should be defined first
# if we can not find it's definition
# we consider it a black block module
if
submodule_type
not
in
modules
:
print
(
"Module %s is a Blackbox"
%
submodule_type
)
else
:
# mark submodule as a tree node
# it's no longer root any more
modules
[
submodule_type
][
TYPE
]
=
NODE
if
CHILDREN
not
in
modules
[
name
]:
modules
[
name
][
CHILDREN
]
=
[]
submodule
=
{
MODULE
:
submodule_type
,
INSTANCE
:
submodule_instance
}
modules
[
name
][
CHILDREN
].
append
(
submodule
)
line_count
+=
1
return
modules
# we define two coverage metrics:
# self coverage: coverage results of this module(excluding submodules)
# tree coverage: coverage results of this module(including submodules)
def
get_tree_coverage
(
modules
,
coverage
):
def
dfs
(
module
):
if
TREECOVERAGE
not
in
modules
[
module
]:
self_coverage
=
modules
[
module
][
SELFCOVERAGE
]
if
CHILDREN
not
in
modules
[
module
]:
modules
[
module
][
TREECOVERAGE
]
=
self_coverage
else
:
coverred
=
self_coverage
[
0
]
not_coverred
=
self_coverage
[
1
]
# the dfs part
for
child
in
modules
[
module
][
CHILDREN
]:
child_coverage
=
dfs
(
child
[
MODULE
])
coverred
+=
child_coverage
[
0
]
not_coverred
+=
child_coverage
[
1
]
# deal with divide by zero
coverage
=
1.0
if
coverred
+
not_coverred
!=
0
:
coverage
=
float
(
coverred
)
/
(
coverred
+
not_coverred
)
modules
[
module
][
TREECOVERAGE
]
=
(
coverred
,
not_coverred
,
coverage
)
return
modules
[
module
][
TREECOVERAGE
]
for
module
in
modules
:
modules
[
module
][
SELFCOVERAGE
]
=
coverage
[
module
]
for
module
in
modules
:
modules
[
module
][
TREECOVERAGE
]
=
dfs
(
module
)
return
modules
# arg1: tree coverage results
# arg2: coverage type
def
sort_coverage
(
coverage
,
coverage_type
):
l
=
[(
module
,
coverage
[
module
][
coverage_type
])
for
module
in
coverage
]
l
.
sort
(
key
=
lambda
x
:
x
[
1
][
2
])
return
l
def
print_tree_coverage
(
tree_coverage
):
def
dfs
(
module
,
level
):
# print current node
tree
=
tree_coverage
[
module
][
TREECOVERAGE
]
self
=
tree_coverage
[
module
][
SELFCOVERAGE
]
print
(
" "
*
level
+
"- "
+
module
)
print
(
" "
*
level
+
" tree"
,
end
=
""
)
print
(
"(%d, %d, %.2f)"
%
(
tree
[
0
],
tree
[
1
],
tree
[
2
]
*
100.0
))
print
(
" "
*
level
+
" self"
,
end
=
""
)
print
(
"(%d, %d, %.2f)"
%
(
self
[
0
],
self
[
1
],
self
[
2
]
*
100.0
))
# print children nodes
if
CHILDREN
in
modules
[
module
]:
# the dfs part
for
child
in
modules
[
module
][
CHILDREN
]:
dfs
(
child
[
MODULE
],
level
+
1
)
for
module
in
tree_coverage
:
if
tree_coverage
[
module
][
TYPE
]
==
ROOT
:
dfs
(
module
,
0
)
if
__name__
==
"__main__"
:
assert
len
(
sys
.
argv
)
==
2
,
"Expect input_file"
input_file
=
sys
.
argv
[
1
]
pp
=
pprint
.
PrettyPrinter
(
indent
=
4
)
lines
=
get_lines
(
input_file
)
# print("lines:")
# pp.pprint(lines)
annotations
=
get_line_annotation
(
lines
)
# print("annotations:")
# pp.pprint(annotations)
modules
=
get_modules
(
lines
)
# print("modules:")
# pp.pprint(modules)
self_coverage
=
{
module
:
get_coverage_statistics
(
annotations
,
modules
[
module
][
BEGIN
],
modules
[
module
][
END
])
for
module
in
modules
}
# print("self_coverage:")
# pp.pprint(self_coverage)
tree_coverage
=
get_tree_coverage
(
modules
,
self_coverage
)
# print("tree_coverage:")
# pp.pprint(tree_coverage)
print
(
"SelfCoverage:"
)
pp
.
pprint
(
sort_coverage
(
tree_coverage
,
SELFCOVERAGE
))
print
(
"TreeCoverage:"
)
pp
.
pprint
(
sort_coverage
(
tree_coverage
,
TREECOVERAGE
))
print
(
"AllCoverage:"
)
print_tree_coverage
(
tree_coverage
)
src/main/scala/utils/ParallelMux.scala
浏览文件 @
4a28083f
...
@@ -4,7 +4,7 @@ import chisel3._
...
@@ -4,7 +4,7 @@ import chisel3._
import
chisel3.util._
import
chisel3.util._
object
ParallelOperation
{
object
ParallelOperation
{
def
apply
[
T
<:
Data
](
xs
:
Seq
[
T
],
func
:
(
T
,
T
)
=>
T
)
:
T
=
{
def
apply
[
T
](
xs
:
Seq
[
T
],
func
:
(
T
,
T
)
=>
T
)
:
T
=
{
require
(
xs
.
nonEmpty
)
require
(
xs
.
nonEmpty
)
xs
match
{
xs
match
{
case
Seq
(
a
)
=>
a
case
Seq
(
a
)
=>
a
...
@@ -21,12 +21,22 @@ object ParallelOR {
...
@@ -21,12 +21,22 @@ object ParallelOR {
}
}
}
}
object
ParallelORR
{
def
apply
(
in
:
Seq
[
Bool
])
:
Bool
=
ParallelOR
(
in
)
def
apply
(
in
:
Bits
)
:
Bool
=
apply
(
in
.
asBools
)
}
object
ParallelAND
{
object
ParallelAND
{
def
apply
[
T
<:
Data
](
xs
:
Seq
[
T
])
:
T
=
{
def
apply
[
T
<:
Data
](
xs
:
Seq
[
T
])
:
T
=
{
ParallelOperation
(
xs
,
(
a
:
T
,
b
:
T
)
=>
(
a
.
asUInt
()
&
b
.
asUInt
()).
asTypeOf
(
xs
.
head
))
ParallelOperation
(
xs
,
(
a
:
T
,
b
:
T
)
=>
(
a
.
asUInt
()
&
b
.
asUInt
()).
asTypeOf
(
xs
.
head
))
}
}
}
}
object
ParallelANDR
{
def
apply
(
in
:
Seq
[
Bool
])
:
Bool
=
ParallelAND
(
in
)
def
apply
(
in
:
Bits
)
:
Bool
=
apply
(
in
.
asBools
)
}
object
ParallelMux
{
object
ParallelMux
{
def
apply
[
T
<:
Data
](
in
:
Seq
[(
Bool
,
T
)])
:
T
=
{
def
apply
[
T
<:
Data
](
in
:
Seq
[(
Bool
,
T
)])
:
T
=
{
val
xs
=
in
map
{
case
(
cond
,
x
)
=>
(
Fill
(
x
.
getWidth
,
cond
)
&
x
.
asUInt
()).
asTypeOf
(
in
.
head
.
_2
)
}
val
xs
=
in
map
{
case
(
cond
,
x
)
=>
(
Fill
(
x
.
getWidth
,
cond
)
&
x
.
asUInt
()).
asTypeOf
(
in
.
head
.
_2
)
}
...
@@ -51,3 +61,16 @@ object ParallelMin {
...
@@ -51,3 +61,16 @@ object ParallelMin {
ParallelOperation
(
xs
,
(
a
:
T
,
b
:
T
)
=>
Mux
(
a
.
asUInt
()
<
b
.
asUInt
(),
a
,
b
).
asTypeOf
(
xs
.
head
))
ParallelOperation
(
xs
,
(
a
:
T
,
b
:
T
)
=>
Mux
(
a
.
asUInt
()
<
b
.
asUInt
(),
a
,
b
).
asTypeOf
(
xs
.
head
))
}
}
}
}
object
ParallelPriorityMux
{
def
apply
[
T
<:
Data
](
in
:
Seq
[(
Bool
,
T
)])
:
T
=
{
ParallelOperation
(
in
,
(
a
:
(
Bool
,
T
),
b
:
(
Bool
,
T
))
=>
(
a
.
_1
||
b
.
_1
,
Mux
(
a
.
_1
,
a
.
_2
,
b
.
_2
))).
_2
}
def
apply
[
T
<:
Data
](
sel
:
Bits
,
in
:
Seq
[
T
])
:
T
=
apply
((
0
until
in
.
size
).
map
(
sel
(
_
)),
in
)
def
apply
[
T
<:
Data
](
sel
:
Seq
[
Bool
],
in
:
Seq
[
T
])
:
T
=
apply
(
sel
zip
in
)
}
object
ParallelPriorityEncoder
{
def
apply
(
in
:
Seq
[
Bool
])
:
UInt
=
ParallelPriorityMux
(
in
,
(
0
until
in
.
size
).
map
(
_
.
asUInt
))
def
apply
(
in
:
Bits
)
:
UInt
=
apply
(
in
.
asBools
)
}
src/main/scala/utils/PriorityMuxGen.scala
0 → 100644
浏览文件 @
4a28083f
package
utils
import
chisel3._
import
chisel3.util._
// this could be used to handle the situation
// in which we have mux sources at multiple
// locations, and this is same to multiple
// when clauses as below, but collect them
// and put them into a ParallelPrioriyMux
// when (sel1) { x := in1 }
// when (sel2) { x := in2 }
class
PriorityMuxGenerator
[
T
<:
Data
]
{
var
src
:
List
[(
Bool
,
T
)]
=
List
()
def
register
(
sel
:
Bool
,
in
:
T
)
=
src
=
(
sel
,
in
)
::
src
def
register
(
in
:
Seq
[(
Bool
,
T
)])
=
src
=
in
.
toList
:::
src
def
register
(
sel
:
Seq
[
Bool
],
in
:
Seq
[
T
])
=
src
=
(
sel
zip
in
).
toList
:::
src
def
apply
()
:
T
=
ParallelPriorityMux
(
src
)
}
\ No newline at end of file
src/main/scala/xiangshan/Bundle.scala
浏览文件 @
4a28083f
...
@@ -90,7 +90,7 @@ class BranchPrediction extends XSBundle with HasIFUConst {
...
@@ -90,7 +90,7 @@ class BranchPrediction extends XSBundle with HasIFUConst {
def
lastHalfRVIClearMask
=
~
lastHalfRVIMask
def
lastHalfRVIClearMask
=
~
lastHalfRVIMask
// is taken from half RVI
// is taken from half RVI
def
lastHalfRVITaken
=
(
takens
&
lastHalfRVIMask
).
orR
def
lastHalfRVITaken
=
ParallelORR
(
takens
&
lastHalfRVIMask
)
def
lastHalfRVIIdx
=
Mux
(
firstBankHasHalfRVI
,
(
bankWidth
-
1
).
U
,
(
PredictWidth
-
1
).
U
)
def
lastHalfRVIIdx
=
Mux
(
firstBankHasHalfRVI
,
(
bankWidth
-
1
).
U
,
(
PredictWidth
-
1
).
U
)
// should not be used if not lastHalfRVITaken
// should not be used if not lastHalfRVITaken
...
@@ -102,18 +102,18 @@ class BranchPrediction extends XSBundle with HasIFUConst {
...
@@ -102,18 +102,18 @@ class BranchPrediction extends XSBundle with HasIFUConst {
def
brNotTakens
=
~
realTakens
&
realBrMask
def
brNotTakens
=
~
realTakens
&
realBrMask
def
sawNotTakenBr
=
VecInit
((
0
until
PredictWidth
).
map
(
i
=>
def
sawNotTakenBr
=
VecInit
((
0
until
PredictWidth
).
map
(
i
=>
(
if
(
i
==
0
)
false
.
B
else
brNotTakens
(
i
-
1
,
0
).
orR
)))
(
if
(
i
==
0
)
false
.
B
else
ParallelORR
(
brNotTakens
(
i
-
1
,
0
))
)))
// def hasNotTakenBrs = (brNotTakens & LowerMaskFromLowest(realTakens)).orR
// def hasNotTakenBrs = (brNotTakens & LowerMaskFromLowest(realTakens)).orR
def
unmaskedJmpIdx
=
PriorityEncoder
(
takens
)
def
unmaskedJmpIdx
=
P
arallelP
riorityEncoder
(
takens
)
def
saveHalfRVI
=
(
firstBankHasHalfRVI
&&
(
unmaskedJmpIdx
===
(
bankWidth
-
1
).
U
||
!(
takens
.
orR
)))
||
def
saveHalfRVI
=
(
firstBankHasHalfRVI
&&
(
unmaskedJmpIdx
===
(
bankWidth
-
1
).
U
||
!(
ParallelORR
(
takens
)
)))
||
(
lastBankHasHalfRVI
&&
unmaskedJmpIdx
===
(
PredictWidth
-
1
).
U
)
(
lastBankHasHalfRVI
&&
unmaskedJmpIdx
===
(
PredictWidth
-
1
).
U
)
// could get PredictWidth-1 when only the first bank is valid
// could get PredictWidth-1 when only the first bank is valid
def
jmpIdx
=
PriorityEncoder
(
realTakens
)
def
jmpIdx
=
P
arallelP
riorityEncoder
(
realTakens
)
// only used when taken
// only used when taken
def
target
=
targets
(
jmpIdx
)
def
target
=
ParallelPriorityMux
(
realTakens
,
targets
)
def
taken
=
realTakens
.
orR
def
taken
=
ParallelORR
(
realTakens
)
def
takenOnBr
=
taken
&&
realBrMask
(
jmpIdx
)
def
takenOnBr
=
taken
&&
ParallelPriorityMux
(
realTakens
,
realBrMask
.
asBools
)
def
hasNotTakenBrs
=
Mux
(
taken
,
sawNotTakenBr
(
jmpIdx
),
brNotTakens
.
orR
)
def
hasNotTakenBrs
=
Mux
(
taken
,
ParallelPriorityMux
(
realTakens
,
sawNotTakenBr
),
ParallelORR
(
brNotTakens
)
)
}
}
class
BranchInfo
extends
XSBundle
with
HasBPUParameter
{
class
BranchInfo
extends
XSBundle
with
HasBPUParameter
{
...
...
src/main/scala/xiangshan/frontend/IFU.scala
浏览文件 @
4a28083f
...
@@ -140,23 +140,15 @@ class IFU extends XSModule with HasIFUConst
...
@@ -140,23 +140,15 @@ class IFU extends XSModule with HasIFUConst
.
elsewhen
(
if2_flush
)
{
if2_valid
:=
false
.
B
}
.
elsewhen
(
if2_flush
)
{
if2_valid
:=
false
.
B
}
.
elsewhen
(
if2_fire
)
{
if2_valid
:=
false
.
B
}
.
elsewhen
(
if2_fire
)
{
if2_valid
:=
false
.
B
}
when
(
RegNext
(
reset
.
asBool
)
&&
!
reset
.
asBool
)
{
val
npcGen
=
new
PriorityMuxGenerator
[
UInt
]
if1_npc
:=
resetVector
.
U
(
VAddrBits
.
W
)
npcGen
.
register
(
true
.
B
,
RegNext
(
if1_npc
))
}.
elsewhen
(
if2_fire
)
{
npcGen
.
register
(
if2_fire
,
if2_snpc
)
if1_npc
:=
if2_snpc
}.
otherwise
{
if1_npc
:=
RegNext
(
if1_npc
)
}
val
if2_bp
=
bpu
.
io
.
out
(
0
)
val
if2_bp
=
bpu
.
io
.
out
(
0
)
// val if2_GHInfo = wrapGHInfo(if2_bp, if2_predHist)
// if taken, bp_redirect should be true
// if taken, bp_redirect should be true
// when taken on half RVI, we suppress this redirect signal
// when taken on half RVI, we suppress this redirect signal
if2_redirect
:=
if2_fire
&&
if2_bp
.
taken
if2_redirect
:=
if2_fire
&&
if2_bp
.
taken
when
(
if2_redirect
)
{
npcGen
.
register
(
if2_redirect
,
if2_bp
.
target
)
if1_npc
:=
if2_bp
.
target
}
if2_predicted_gh
:=
if2_gh
.
update
(
if2_bp
.
hasNotTakenBrs
,
if2_bp
.
takenOnBr
)
if2_predicted_gh
:=
if2_gh
.
update
(
if2_bp
.
hasNotTakenBrs
,
if2_bp
.
takenOnBr
)
...
@@ -166,7 +158,6 @@ class IFU extends XSModule with HasIFUConst
...
@@ -166,7 +158,6 @@ class IFU extends XSModule with HasIFUConst
val
if3_fire
=
if3_valid
&&
if4_ready
&&
(
inLoop
||
io
.
icacheResp
.
valid
)
&&
!
if3_flush
val
if3_fire
=
if3_valid
&&
if4_ready
&&
(
inLoop
||
io
.
icacheResp
.
valid
)
&&
!
if3_flush
val
if3_pc
=
RegEnable
(
if2_pc
,
if2_fire
)
val
if3_pc
=
RegEnable
(
if2_pc
,
if2_fire
)
val
if3_predHist
=
RegEnable
(
if2_predHist
,
enable
=
if2_fire
)
val
if3_predHist
=
RegEnable
(
if2_predHist
,
enable
=
if2_fire
)
// val if3_nextValidPC = Mux(if2_valid)
if3_ready
:=
if3_fire
||
!
if3_valid
||
if3_flush
if3_ready
:=
if3_fire
||
!
if3_valid
||
if3_flush
when
(
if3_flush
)
{
if3_valid
:=
false
.
B
}
when
(
if3_flush
)
{
if3_valid
:=
false
.
B
}
.
elsewhen
(
if2_fire
)
{
if3_valid
:=
true
.
B
}
.
elsewhen
(
if2_fire
)
{
if3_valid
:=
true
.
B
}
...
@@ -181,7 +172,7 @@ class IFU extends XSModule with HasIFUConst
...
@@ -181,7 +172,7 @@ class IFU extends XSModule with HasIFUConst
val
hasPrevHalfInstrReq
=
prevHalfInstrReq
.
valid
val
hasPrevHalfInstrReq
=
prevHalfInstrReq
.
valid
val
if3_prevHalfInstr
=
RegInit
(
0.
U
.
asTypeOf
(
new
PrevHalfInstr
))
val
if3_prevHalfInstr
=
RegInit
(
0.
U
.
asTypeOf
(
new
PrevHalfInstr
))
// val if4_prevHalfInstr = Wire(new PrevHalfInstr)
// 32-bit instr crosses 2 pages, and the higher 16-bit triggers page fault
// 32-bit instr crosses 2 pages, and the higher 16-bit triggers page fault
val
crossPageIPF
=
WireInit
(
false
.
B
)
val
crossPageIPF
=
WireInit
(
false
.
B
)
...
@@ -238,10 +229,11 @@ class IFU extends XSModule with HasIFUConst
...
@@ -238,10 +229,11 @@ class IFU extends XSModule with HasIFUConst
// }.elsewhen (if3_ghInfoNotIdenticalRedirect) {
// }.elsewhen (if3_ghInfoNotIdenticalRedirect) {
// if3_target := Mux(if3_bp.taken, if3_bp.target, snpc(if3_pc))
// if3_target := Mux(if3_bp.taken, if3_bp.target, snpc(if3_pc))
// }
// }
npcGen
.
register
(
if3_redirect
,
if3_target
)
when
(
if3_redirect
)
{
//
when (if3_redirect) {
if1_npc
:=
if3_target
//
if1_npc := if3_target
}
//
}
//********************** IF4 ****************************//
//********************** IF4 ****************************//
val
if4_pd
=
RegEnable
(
pd
.
io
.
out
,
if3_fire
)
val
if4_pd
=
RegEnable
(
pd
.
io
.
out
,
if3_fire
)
...
@@ -350,9 +342,7 @@ class IFU extends XSModule with HasIFUConst
...
@@ -350,9 +342,7 @@ class IFU extends XSModule with HasIFUConst
// }.elsewhen (if4_ghInfoNotIdenticalRedirect) {
// }.elsewhen (if4_ghInfoNotIdenticalRedirect) {
// if4_target := Mux(if4_bp.taken, if4_bp.target, if4_snpc)
// if4_target := Mux(if4_bp.taken, if4_bp.target, if4_snpc)
// }
// }
when
(
if4_redirect
)
{
npcGen
.
register
(
if4_redirect
,
if4_target
)
if1_npc
:=
if4_target
}
when
(
if4_fire
)
{
when
(
if4_fire
)
{
final_gh
:=
if4_predicted_gh
final_gh
:=
if4_predicted_gh
...
@@ -378,13 +368,11 @@ class IFU extends XSModule with HasIFUConst
...
@@ -378,13 +368,11 @@ class IFU extends XSModule with HasIFUConst
flush_final_gh
:=
true
.
B
flush_final_gh
:=
true
.
B
}
}
when
(
loopBufPar
.
LBredirect
.
valid
)
{
npcGen
.
register
(
loopBufPar
.
LBredirect
.
valid
,
loopBufPar
.
LBredirect
.
bits
)
if1_npc
:=
loopBufPar
.
LBredirect
.
bits
npcGen
.
register
(
io
.
redirect
.
valid
,
io
.
redirect
.
bits
)
}
npcGen
.
register
(
RegNext
(
reset
.
asBool
)
&&
!
reset
.
asBool
,
resetVector
.
U
(
VAddrBits
.
W
))
when
(
io
.
redirect
.
valid
)
{
if1_npc
:=
npcGen
()
if1_npc
:=
io
.
redirect
.
bits
}
when
(
inLoop
)
{
when
(
inLoop
)
{
io
.
icacheReq
.
valid
:=
if4_flush
io
.
icacheReq
.
valid
:=
if4_flush
...
...
src/test/csrc/emu.cpp
浏览文件 @
4a28083f
...
@@ -247,6 +247,13 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) {
...
@@ -247,6 +247,13 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) {
diff
.
wdata
=
wdata
;
diff
.
wdata
=
wdata
;
diff
.
wdst
=
wdst
;
diff
.
wdst
=
wdst
;
#if VM_COVERAGE == 1
// we dump coverage into files at the end
// since we are not sure when an emu will stop
// we distinguish multiple dat files by emu start time
time_t
start_time
=
time
(
NULL
);
#endif
while
(
!
Verilated
::
gotFinish
()
&&
trapCode
==
STATE_RUNNING
)
{
while
(
!
Verilated
::
gotFinish
()
&&
trapCode
==
STATE_RUNNING
)
{
if
(
!
(
max_cycle
>
0
&&
max_instr
>
0
&&
instr_left_last_cycle
>=
max_instr
/* handle overflow */
))
{
if
(
!
(
max_cycle
>
0
&&
max_instr
>
0
&&
instr_left_last_cycle
>=
max_instr
/* handle overflow */
))
{
trapCode
=
STATE_LIMIT_EXCEEDED
;
trapCode
=
STATE_LIMIT_EXCEEDED
;
...
@@ -334,6 +341,11 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) {
...
@@ -334,6 +341,11 @@ uint64_t Emulator::execute(uint64_t max_cycle, uint64_t max_instr) {
#if VM_TRACE == 1
#if VM_TRACE == 1
if
(
enable_waveform
)
tfp
->
close
();
if
(
enable_waveform
)
tfp
->
close
();
#endif
#endif
#if VM_COVERAGE == 1
save_coverage
(
start_time
);
#endif
display_trapinfo
();
display_trapinfo
();
return
cycles
;
return
cycles
;
}
}
...
@@ -363,6 +375,22 @@ inline char* Emulator::waveform_filename(time_t t) {
...
@@ -363,6 +375,22 @@ inline char* Emulator::waveform_filename(time_t t) {
return
buf
;
return
buf
;
}
}
#if VM_COVERAGE == 1
inline
char
*
Emulator
::
coverage_filename
(
time_t
t
)
{
static
char
buf
[
1024
];
char
*
p
=
timestamp_filename
(
t
,
buf
);
strcpy
(
p
,
".coverage.dat"
);
return
buf
;
}
inline
void
Emulator
::
save_coverage
(
time_t
t
)
{
char
*
p
=
coverage_filename
(
t
);
VerilatedCov
::
write
(
p
);
}
#endif
void
Emulator
::
display_trapinfo
()
{
void
Emulator
::
display_trapinfo
()
{
uint64_t
pc
=
dut_ptr
->
io_trap_pc
;
uint64_t
pc
=
dut_ptr
->
io_trap_pc
;
uint64_t
instrCnt
=
dut_ptr
->
io_trap_instrCnt
;
uint64_t
instrCnt
=
dut_ptr
->
io_trap_instrCnt
;
...
...
src/test/csrc/emu.h
浏览文件 @
4a28083f
...
@@ -56,9 +56,13 @@ class Emulator {
...
@@ -56,9 +56,13 @@ class Emulator {
void
display_trapinfo
();
void
display_trapinfo
();
inline
char
*
timestamp_filename
(
time_t
t
,
char
*
buf
);
inline
char
*
timestamp_filename
(
time_t
t
,
char
*
buf
);
inline
char
*
snapshot_filename
(
time_t
t
);
inline
char
*
snapshot_filename
(
time_t
t
);
inline
char
*
coverage_filename
(
time_t
t
);
void
snapshot_save
(
const
char
*
filename
);
void
snapshot_save
(
const
char
*
filename
);
void
snapshot_load
(
const
char
*
filename
);
void
snapshot_load
(
const
char
*
filename
);
inline
char
*
waveform_filename
(
time_t
t
);
inline
char
*
waveform_filename
(
time_t
t
);
#if VM_COVERAGE == 1
inline
void
save_coverage
(
time_t
t
);
#endif
public:
public:
Emulator
(
int
argc
,
const
char
*
argv
[]);
Emulator
(
int
argc
,
const
char
*
argv
[]);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录