Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenXiangShan
XiangShan
提交
22e06089
X
XiangShan
项目概览
OpenXiangShan
/
XiangShan
10 个月 前同步成功
通知
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,体验更适合开发者的 AI 搜索 >>
提交
22e06089
编写于
2月 23, 2021
作者:
L
Lingrui98
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
ubtb: wrap meta bank and data bank
上级
e7d4886b
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
114 addition
and
151 deletion
+114
-151
src/main/scala/xiangshan/frontend/uBTB.scala
src/main/scala/xiangshan/frontend/uBTB.scala
+114
-151
未找到文件。
src/main/scala/xiangshan/frontend/uBTB.scala
浏览文件 @
22e06089
...
...
@@ -73,206 +73,169 @@ class MicroBTB extends BasePredictor
val
pred
=
UInt
(
2.
W
)
}
@chiselName
class
UBTBMetaBank
(
nWays
:
Int
)
extends
XSModule
{
val
io
=
IO
(
new
Bundle
{
val
wen
=
Input
(
Bool
())
val
wWay
=
Input
(
UInt
(
log2Up
(
nWays
).
W
))
val
wdata
=
Input
(
new
MicroBTBMeta
)
val
rtag
=
Input
(
UInt
(
tagSize
.
W
))
val
rdata
=
Output
(
new
MetaOutput
)
val
hit_and_taken
=
Output
(
Bool
())
val
hit_ohs
=
Output
(
Vec
(
nWays
,
Bool
()))
val
hit_way
=
Output
(
UInt
(
log2Up
(
nWays
).
W
))
val
allocatable_way
=
Valid
(
UInt
(
log2Up
(
nWays
).
W
))
val
rWay
=
Input
(
UInt
(
log2Up
(
nWays
).
W
))
val
rpred
=
Output
(
UInt
(
2.
W
))
})
val
mem
=
Mem
(
nWays
,
new
MicroBTBMeta
)
val
rentries
=
VecInit
((
0
until
nWays
)
map
(
i
=>
mem
(
i
)))
val
hit_ohs
=
VecInit
(
rentries
map
(
e
=>
e
.
valid
&&
e
.
tag
===
io
.
rtag
))
io
.
hit_and_taken
:=
VecInit
(
rentries
map
(
e
=>
e
.
valid
&&
e
.
tag
===
io
.
rtag
&&
e
.
pred
(
1
))).
asUInt
.
orR
val
hit_way
=
OHToUInt
(
hit_ohs
)
//val hit_entry = rentries(hit_way)
val
hit_entry
=
ParallelMux
(
hit_ohs
zip
rentries
)
io
.
hit_ohs
:=
hit_ohs
io
.
hit_way
:=
hit_way
io
.
rdata
.
is_Br
:=
hit_entry
.
is_Br
io
.
rdata
.
is_RVC
:=
hit_entry
.
is_RVC
io
.
rdata
.
pred
:=
hit_entry
.
pred
val
entry_emptys
=
VecInit
(
rentries
.
map
(
e
=>
!
e
.
valid
))
val
allocatable
=
ParallelOR
(
entry_emptys
)
io
.
allocatable_way
.
bits
:=
PriorityEncoder
(
entry_emptys
)
io
.
allocatable_way
.
valid
:=
allocatable
io
.
rpred
:=
rentries
(
io
.
rWay
).
pred
when
(
io
.
wen
)
{
mem
.
write
(
io
.
wWay
,
io
.
wdata
)
}
}
@chiselName
class
UBTBDataBank
(
nWays
:
Int
)
extends
XSModule
{
val
io
=
IO
(
new
Bundle
{
val
wen
=
Input
(
Bool
())
val
wWay
=
Input
(
UInt
(
log2Up
(
nWays
).
W
))
val
wdata
=
Input
(
new
MicroBTBEntry
)
val
rOHs
=
Input
(
Vec
(
nWays
,
Bool
()))
val
rdata
=
Output
(
new
MicroBTBEntry
)
})
val
mem
=
Mem
(
nWays
,
new
MicroBTBEntry
)
val
rentries
=
VecInit
((
0
until
nWays
)
map
(
i
=>
mem
(
i
)))
// io.rdata := rentries(io.rWay)
io
.
rdata
:=
ParallelMux
(
io
.
rOHs
zip
rentries
)
when
(
io
.
wen
)
{
mem
.
write
(
io
.
wWay
,
io
.
wdata
)
}
}
val
metaBanks
=
Seq
.
fill
(
PredictWidth
)(
Module
(
new
UBTBMetaBank
(
nWays
)))
val
dataBanks
=
Seq
.
fill
(
PredictWidth
)(
Module
(
new
UBTBDataBank
(
nWays
)))
val
metas
=
VecInit
(
metaBanks
.
map
(
_
.
io
))
val
datas
=
VecInit
(
dataBanks
.
map
(
_
.
io
))
val
uBTBMeta
=
VecInit
(
metas
.
map
(
m
=>
m
.
rdata
))
val
uBTB
=
VecInit
(
datas
.
map
(
d
=>
d
.
rdata
))
val
do_reset
=
RegInit
(
true
.
B
)
val
reset_way
=
RegInit
(
0.
U
(
log2Ceil
(
nWays
).
W
))
when
(
do_reset
)
{
reset_way
:=
reset_way
+
1.
U
}
when
(
reset_way
===
(
nWays
-
1
).
U
)
{
do_reset
:=
false
.
B
}
//uBTB read
//tag is packet aligned
val
packetAlignedPC
=
packetAligned
(
io
.
pc
.
bits
)
val
read_valid
=
io
.
pc
.
valid
val
read_req_tag
=
getTag
(
packetAlignedPC
)
class
ReadRespEntry
extends
XSBundle
class
ReadResp
extends
XSBundle
{
val
is_RVC
=
Bool
()
val
target
=
UInt
(
VAddrBits
.
W
)
val
valid
=
Bool
()
val
taken
=
Bool
()
val
target
=
UInt
(
VAddrBits
.
W
)
val
is_RVC
=
Bool
()
val
is_Br
=
Bool
()
}
val
read_resp
=
Wire
(
Vec
(
PredictWidth
,
new
ReadRespEntry
))
(
0
until
PredictWidth
).
map
{
b
=>
metas
(
b
).
rtag
:=
read_req_tag
}
val
read_hit_ohs
=
(
0
until
PredictWidth
).
map
{
b
=>
metas
(
b
).
hit_ohs
}
val
read_hit_vec
=
VecInit
(
read_hit_ohs
.
map
{
oh
=>
ParallelOR
(
oh
).
asBool
})
val
read_hit_ways
=
(
0
until
PredictWidth
).
map
{
b
=>
metas
(
b
).
hit_way
}
(
0
until
PredictWidth
).
map
(
b
=>
datas
(
b
).
rOHs
:=
read_hit_ohs
(
b
))
val
uBTBMeta_resp
=
VecInit
((
0
until
PredictWidth
).
map
(
b
=>
metas
(
b
).
rdata
))
val
btb_resp
=
VecInit
((
0
until
PredictWidth
).
map
(
b
=>
datas
(
b
).
rdata
))
class
UBTBBank
(
val
nWays
:
Int
)
extends
XSModule
with
HasIFUConst
{
val
io
=
IO
(
new
Bundle
{
val
read_pc
=
Flipped
(
Valid
(
UInt
(
VAddrBits
.
W
)))
val
read_resp
=
Output
(
new
ReadResp
)
val
read_hit
=
Output
(
Bool
())
val
to_write_way
=
Output
(
UInt
(
log2Ceil
(
nWays
).
W
))
for
(
i
<-
0
until
PredictWidth
){
// do not need to decide whether to produce results\
read_resp
(
i
).
valid
:=
io
.
inMask
(
i
)
read_resp
(
i
).
taken
:=
read_resp
(
i
).
valid
&&
metas
(
i
).
hit_and_taken
read_resp
(
i
).
is_Br
:=
read_resp
(
i
).
valid
&&
uBTBMeta_resp
(
i
).
is_Br
read_resp
(
i
).
target
:=
Cat
(
io
.
pc
.
bits
(
VAddrBits
-
1
,
lowerBitsSize
+
instOffsetBits
),
btb_resp
(
i
).
asUInt
,
0.
U
(
instOffsetBits
.
W
))
read_resp
(
i
).
is_RVC
:=
read_resp
(
i
).
valid
&&
uBTBMeta_resp
(
i
).
is_RVC
val
update_way
=
Input
(
UInt
(
log2Ceil
(
nWays
).
W
))
val
update_read_pred
=
Output
(
UInt
(
2.
W
))
out_ubtb_br_info
.
hits
(
i
)
:=
read_hit_vec
(
i
)
}
val
update_write_meta
=
Flipped
(
Valid
(
new
MicroBTBMeta
))
val
update_write_data
=
Flipped
(
Valid
(
new
MicroBTBEntry
))
})
val
meta
=
Module
(
new
AsyncDataModuleTemplate
(
new
MicroBTBMeta
,
nWays
,
nWays
,
1
))
val
data
=
Module
(
new
AsyncDataModuleTemplate
(
new
MicroBTBEntry
,
nWays
,
nWays
,
1
))
//TODO: way alloc algorithm
def
alloc_way
(
valids
:
UInt
,
meta_tags
:
UInt
,
req_tag
:
UInt
)
=
{
val
way
=
Wire
(
UInt
(
log2Up
(
BtbWays
).
W
))
val
all_valid
=
valids
.
andR
.
asBool
val
tags
=
Cat
(
meta_tags
,
req_tag
)
val
l
=
log2Ceil
(
nWays
)
val
nChunks
=
(
tags
.
getWidth
+
l
-
1
)
/
l
val
chunks
=
(
0
until
nChunks
)
map
{
i
=>
tags
(
min
((
i
+
1
)*
l
,
tags
.
getWidth
)-
1
,
i
*
l
)
for
(
w
<-
0
until
nWays
)
{
meta
.
io
.
raddr
(
w
)
:=
w
.
U
data
.
io
.
raddr
(
w
)
:=
w
.
U
}
way
:=
Mux
(
all_valid
,
chunks
.
reduce
(
_
^
_
),
PriorityEncoder
(~
valids
))
way
}
meta
.
io
.
waddr
(
0
)
:=
io
.
update_way
meta
.
io
.
wen
(
0
)
:=
io
.
update_write_meta
.
valid
meta
.
io
.
wdata
(
0
)
:=
io
.
update_write_meta
.
bits
data
.
io
.
waddr
(
0
)
:=
io
.
update_way
data
.
io
.
wen
(
0
)
:=
io
.
update_write_data
.
valid
data
.
io
.
wdata
(
0
)
:=
io
.
update_write_data
.
bits
val
rmetas
=
meta
.
io
.
rdata
val
rdatas
=
data
.
io
.
rdata
val
packetAlignedPC
=
packetAligned
(
io
.
read_pc
.
bits
)
val
read_tag
=
getTag
(
io
.
read_pc
.
bits
)
val
hits
=
VecInit
(
rmetas
.
map
(
m
=>
m
.
valid
&&
m
.
tag
===
read_tag
))
val
takens
=
VecInit
(
rmetas
.
map
(
m
=>
m
.
pred
(
1
)))
val
hit_oh
=
hits
.
asUInt
val
hit_and_taken
=
VecInit
((
hits
zip
takens
)
map
{
case
(
h
,
t
)
=>
h
&&
t
}).
asUInt
.
orR
val
hit_meta
=
ParallelMux
(
hits
zip
rmetas
)
val
hit_data
=
ParallelMux
(
hits
zip
rdatas
)
val
target
=
Cat
(
io
.
read_pc
.
bits
(
VAddrBits
-
1
,
lowerBitsSize
+
instOffsetBits
),
hit_data
.
lower
,
0.
U
(
instOffsetBits
.
W
))
val
emptys
=
rmetas
.
map
(
m
=>
!
m
.
valid
)
val
allocatable
=
VecInit
(
emptys
).
asUInt
.
orR
val
empty_way
=
ParallelPriorityEncoder
(
emptys
)
val
hit_way
=
OHToUInt
(
hit_oh
)
val
random_way
=
LFSR64
()(
log2Ceil
(
nWays
)-
1
,
0
)
io
.
to_write_way
:=
Mux
(
hit_oh
.
orR
,
hit_way
,
Mux
(
allocatable
,
empty_way
,
random_way
))
val
ren
=
io
.
read_pc
.
valid
io
.
read_resp
.
valid
:=
ren
io
.
read_resp
.
is_RVC
:=
ren
&&
hit_meta
.
is_RVC
io
.
read_resp
.
is_Br
:=
ren
&&
hit_meta
.
is_Br
io
.
read_resp
.
taken
:=
ren
&&
hit_and_taken
io
.
read_resp
.
target
:=
target
io
.
read_hit
:=
ren
&&
hit_oh
.
orR
io
.
update_read_pred
:=
rmetas
(
io
.
update_way
).
pred
}
val
ubtbBanks
=
Seq
.
fill
(
PredictWidth
)(
Module
(
new
UBTBBank
(
nWays
)))
val
banks
=
VecInit
(
ubtbBanks
.
map
(
_
.
io
))
val
read_resps
=
VecInit
(
banks
.
map
(
b
=>
b
.
read_resp
))
val
alloc_ways
=
(
0
until
PredictWidth
).
map
{
b
=>
Mux
(
metas
(
b
).
allocatable_way
.
valid
,
metas
(
b
).
allocatable_way
.
bits
,
LFSR64
()(
log2Ceil
(
nWays
)-
1
,
0
))}
(
0
until
PredictWidth
).
map
(
i
=>
out_ubtb_br_info
.
writeWay
(
i
)
:=
Mux
(
read_hit_vec
(
i
).
asBool
,
read_hit_ways
(
i
),
alloc_ways
(
i
)))
for
(
b
<-
0
until
PredictWidth
)
{
banks
(
b
).
read_pc
.
valid
:=
io
.
pc
.
valid
&&
io
.
inMask
(
b
)
banks
(
b
).
read_pc
.
bits
:=
io
.
pc
.
bits
out_ubtb_br_info
.
writeWay
(
b
)
:=
banks
(
b
).
to_write_way
out_ubtb_br_info
.
hits
(
b
)
:=
banks
(
b
).
read_hit
//response
//only when hit and instruction valid and entry valid can output data
for
(
i
<-
0
until
PredictWidth
)
{
io
.
out
.
targets
(
i
)
:=
read_resp
(
i
).
target
io
.
out
.
hits
(
i
)
:=
read_resp
(
i
).
valid
&&
read_hit_vec
(
i
)
io
.
out
.
takens
(
i
)
:=
read_resp
(
i
).
taken
io
.
out
.
is_RVC
(
i
)
:=
read_resp
(
i
).
is_RVC
io
.
out
.
brMask
(
i
)
:=
read_resp
(
i
).
is_Br
//only when hit and instruction valid and entry valid can output data
io
.
out
.
targets
(
b
)
:=
read_resps
(
b
).
target
io
.
out
.
hits
(
b
)
:=
banks
(
b
).
read_hit
io
.
out
.
takens
(
b
)
:=
read_resps
(
b
).
taken
io
.
out
.
is_RVC
(
b
)
:=
read_resps
(
b
).
is_RVC
io
.
out
.
brMask
(
b
)
:=
read_resps
(
b
).
is_Br
}
val
do_reset
=
RegInit
(
true
.
B
)
val
reset_way
=
RegInit
(
0.
U
(
log2Ceil
(
nWays
).
W
))
when
(
do_reset
)
{
reset_way
:=
reset_way
+
1.
U
}
when
(
reset_way
===
(
nWays
-
1
).
U
)
{
do_reset
:=
false
.
B
}
//uBTB update
//backend should send fetch pc to update
val
u
=
io
.
update
.
bits
val
update_packet_pc
=
packetAligned
(
u
.
ftqPC
)
val
update_pcs
=
VecInit
((
0
until
PredictWidth
).
map
(
i
=>
update_packet_pc
+
(
i
<<
instOffsetBits
).
U
))
val
update_write_ways
=
VecInit
(
u
.
metas
.
map
(
_
.
ubtbWriteWay
))
val
update_hits
=
u
.
metas
.
map
(
_
.
ubtbHits
)
val
update_takens
=
u
.
takens
val
update_bank
=
u
.
cfiIndex
.
bits
val
update_tag
=
getTag
(
update_packet_pc
)
val
update_target
=
u
.
target
val
update_target_lower
=
update_target
(
lowerBitsSize
-
1
+
instOffsetBits
,
instOffsetBits
)
val
update_target_lower
=
u
.
target
(
lowerBitsSize
-
1
+
instOffsetBits
,
instOffsetBits
)
// only when taken should we update target
val
entry_write_valid
=
io
.
update
.
valid
&&
u
.
valids
(
u
.
cfiIndex
.
bits
)
&&
u
.
takens
(
u
.
cfiIndex
.
bits
)
val
data_write_valids
=
VecInit
((
0
until
PredictWidth
).
map
(
i
=>
io
.
update
.
valid
&&
u
.
valids
(
i
)
&&
u
.
takens
(
i
)))
val
meta_write_valids
=
VecInit
((
0
until
PredictWidth
).
map
(
i
=>
io
.
update
.
valid
&&
u
.
valids
(
i
)
&&
(
u
.
br_mask
(
i
)
||
u
.
takens
(
i
))))
for
(
b
<-
0
until
PredictWidth
)
{
datas
(
b
).
wen
:=
do_reset
||
(
entry_write_valid
&&
b
.
U
===
update_bank
)
datas
(
b
).
wWay
:=
Mux
(
do_reset
,
reset_way
,
update_write_ways
(
u
.
cfiIndex
.
bits
))
datas
(
b
).
wdata
:=
Mux
(
do_reset
,
0.
U
.
asTypeOf
(
new
MicroBTBEntry
),
update_target_lower
.
asTypeOf
(
new
MicroBTBEntry
))
}
VecInit
((
0
until
PredictWidth
).
map
(
i
=>
io
.
update
.
valid
&&
u
.
valids
(
i
)
&&
(
u
.
br_mask
(
i
)
||
u
.
takens
(
i
))))
val
new_preds
=
VecInit
((
0
until
PredictWidth
).
map
(
i
=>
Mux
(!
update_hits
(
i
),
Mux
(
update_takens
(
i
),
3.
U
,
0.
U
),
satUpdate
(
banks
(
i
).
update_read_pred
,
2
,
update_takens
(
i
)))))
val
new_preds
=
VecInit
((
0
until
PredictWidth
).
map
(
i
=>
Mux
(!
update_hits
(
i
),
Mux
(
update_takens
(
i
),
3.
U
,
0.
U
),
satUpdate
(
metas
(
i
).
rpred
,
2
,
update_takens
(
i
)))))
//write the uBTBMeta
(
0
until
PredictWidth
).
map
(
i
=>
metas
(
i
).
rWay
:=
update_write_ways
(
i
))
val
update_write_metas
=
Wire
(
Vec
(
PredictWidth
,
new
MicroBTBMeta
))
val
update_write_datas
=
Wire
(
Vec
(
PredictWidth
,
new
MicroBTBEntry
))
for
(
i
<-
0
until
PredictWidth
)
{
update_write_metas
(
i
).
is_Br
:=
u
.
br_mask
(
i
)
update_write_metas
(
i
).
is_RVC
:=
u
.
rvc_mask
(
i
)
update_write_metas
(
i
).
valid
:=
true
.
B
update_write_metas
(
i
).
tag
:=
update_tag
update_write_metas
(
i
).
pred
:=
new_preds
(
i
)
}
update_write_datas
(
i
).
lower
:=
update_target_lower
}
for
(
b
<-
0
until
PredictWidth
)
{
metas
(
b
).
wen
:=
do_reset
||
meta_write_valids
(
b
)
metas
(
b
).
wWay
:=
Mux
(
do_reset
,
reset_way
,
update_write_ways
(
b
))
metas
(
b
).
wdata
:=
Mux
(
do_reset
,
0.
U
.
asTypeOf
(
new
MicroBTBMeta
),
update_write_metas
(
b
))
banks
(
b
).
update_way
:=
update_write_ways
(
b
)
banks
(
b
).
update_write_meta
.
valid
:=
do_reset
||
meta_write_valids
(
b
)
banks
(
b
).
update_write_meta
.
bits
:=
Mux
(
do_reset
,
0.
U
.
asTypeOf
(
new
MicroBTBMeta
),
update_write_metas
(
b
))
banks
(
b
).
update_write_data
.
valid
:=
do_reset
||
data_write_valids
(
b
)
banks
(
b
).
update_write_data
.
bits
:=
Mux
(
do_reset
,
0.
U
.
asTypeOf
(
new
MicroBTBEntry
),
update_write_datas
(
b
))
}
if
(
BPUDebug
&&
debug
)
{
val
update_pcs
=
VecInit
((
0
until
PredictWidth
).
map
(
i
=>
update_packet_pc
+
(
i
<<
instOffsetBits
).
U
))
val
update_bank
=
u
.
cfiIndex
.
bits
val
read_valid
=
io
.
pc
.
valid
val
read_req_tag
=
getTag
(
io
.
pc
.
bits
)
val
read_hit_vec
=
VecInit
(
banks
.
map
(
b
=>
b
.
read_hit
))
val
read_hit_ways
=
VecInit
(
banks
.
map
(
b
=>
b
.
to_write_way
))
XSDebug
(
read_valid
,
"uBTB read req: pc:0x%x, tag:%x \n"
,
io
.
pc
.
bits
,
read_req_tag
)
XSDebug
(
read_valid
,
"uBTB read resp: read_hit_vec:%b, \n"
,
read_hit_vec
.
asUInt
)
for
(
i
<-
0
until
PredictWidth
)
{
XSDebug
(
read_valid
,
"bank(%d) hit:%d way:%d valid:%d is_RVC:%d taken:%d isBr:%d target:0x%x alloc_way:%d\n"
,
i
.
U
,
read_hit_vec
(
i
),
read_hit_ways
(
i
),
read_resp
(
i
).
valid
,
read_resp
(
i
).
is_RVC
,
read_resp
(
i
).
taken
,
read_resp
(
i
).
is_Br
,
read_resp
(
i
).
target
,
out_ubtb_br_info
.
writeWay
(
i
))
XSDebug
(
entry_write_valid
&&
(
i
.
U
===
update_bank
),
i
.
U
,
read_hit_vec
(
i
),
read_hit_ways
(
i
),
read_resp
s
(
i
).
valid
,
read_resps
(
i
).
is_RVC
,
read_resp
s
(
i
).
taken
,
read_resps
(
i
).
is_Br
,
read_resps
(
i
).
target
,
out_ubtb_br_info
.
writeWay
(
i
))
XSDebug
(
data_write_valids
(
i
),
"uBTB update data(%d): update | pc:0x%x | update hits:%b | update_write_way:%d | update_lower 0x%x\n "
,
i
.
U
,
update_pcs
(
i
),
update_hits
(
i
),
update_write_ways
(
i
),
update_target_lower
(
lowerBitsSize
-
1
,
0
))
XSDebug
(
meta_write_valids
(
i
),
"uBTB update meta(%d): update_taken:%d | old_pred:%b | new_pred:%b | br:%d | rvc:%d | update_tag:%x\n"
,
i
.
U
,
update_takens
(
i
),
metas
(
i
).
r
pred
,
new_preds
(
i
),
u
.
br_mask
(
i
),
u
.
rvc_mask
(
i
),
update_tag
)
i
.
U
,
update_takens
(
i
),
banks
(
i
).
update_read_
pred
,
new_preds
(
i
),
u
.
br_mask
(
i
),
u
.
rvc_mask
(
i
),
update_tag
)
}
}
if
(
extended_stat
)
{
val
update_target
=
u
.
target
val
high_identical
=
update_target
(
VAddrBits
-
1
,
lowerBitsSize
)
=/=
update_packet_pc
(
VAddrBits
-
1
,
lowerBitsSize
)
XSDebug
(
io
.
update
.
valid
,
"extended_stat: identical %d\n"
,
high_identical
)
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录