Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenXiangShan
XiangShan
提交
9412fdbd
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,发现更多精彩内容 >>
未验证
提交
9412fdbd
编写于
11月 06, 2020
作者:
L
ljw
提交者:
GitHub
11月 06, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #218 from RISCVERS/sbuffer-test
Update LRU algorithm
上级
d087d2dd
966b421d
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
206 addition
and
4 deletion
+206
-4
.github/workflows/emu.yml
.github/workflows/emu.yml
+2
-2
src/main/scala/utils/ParallelMux.scala
src/main/scala/utils/ParallelMux.scala
+12
-0
src/main/scala/utils/Replacement.scala
src/main/scala/utils/Replacement.scala
+64
-0
src/main/scala/xiangshan/mem/sbuffer/NewSbuffer.scala
src/main/scala/xiangshan/mem/sbuffer/NewSbuffer.scala
+5
-2
src/test/scala/xiangshan/memend/SbufferTest.scala
src/test/scala/xiangshan/memend/SbufferTest.scala
+123
-0
未找到文件。
.github/workflows/emu.yml
浏览文件 @
9412fdbd
...
...
@@ -70,7 +70,7 @@ jobs:
echo $AM_HOME
echo $NEMU_HOME
echo $NOOP_HOME
make -C $AM_HOME/apps/microbench ARCH=riscv64-noop AM_HOME=$AM_HOME NEMU_HOME=$NEMU_HOME NOOP_HOME=$NOOP_HOME mainargs=test run
2> /dev/null
make -C $AM_HOME/apps/microbench ARCH=riscv64-noop AM_HOME=$AM_HOME NEMU_HOME=$NEMU_HOME NOOP_HOME=$NOOP_HOME mainargs=test run
riscv-tests
:
runs-on
:
self-hosted
...
...
@@ -87,5 +87,5 @@ jobs:
echo $NEMU_HOME
echo $NOOP_HOME
echo $RVTEST_HOME
make -C $RVTEST_HOME/isa/ SUITES+=rv64ui SUITES+=rv64um SUITES+=rv64ua NEMU_HOME=$NEMU_HOME NOOP_HOME=$NOOP_HOME noop_run
2> /dev/null
make -C $RVTEST_HOME/isa/ SUITES+=rv64ui SUITES+=rv64um SUITES+=rv64ua NEMU_HOME=$NEMU_HOME NOOP_HOME=$NOOP_HOME noop_run
src/main/scala/utils/ParallelMux.scala
浏览文件 @
9412fdbd
...
...
@@ -37,4 +37,16 @@ object ParallelLookUp {
def
apply
[
T
<:
Data
](
key
:
UInt
,
mapping
:
Seq
[(
UInt
,
T
)])
:
T
=
{
ParallelMux
(
mapping
.
map
(
m
=>
(
m
.
_1
===
key
)
->
m
.
_2
))
}
}
object
ParallelMax
{
def
apply
[
T
<:
Data
](
xs
:
Seq
[
T
])
:
T
=
{
ParallelOperation
(
xs
,
(
a
:
T
,
b
:
T
)
=>
Mux
(
a
.
asUInt
()
>
b
.
asUInt
(),
a
,
b
).
asTypeOf
(
xs
.
head
))
}
}
object
ParallelMin
{
def
apply
[
T
<:
Data
](
xs
:
Seq
[
T
])
:
T
=
{
ParallelOperation
(
xs
,
(
a
:
T
,
b
:
T
)
=>
Mux
(
a
.
asUInt
()
<
b
.
asUInt
(),
a
,
b
).
asTypeOf
(
xs
.
head
))
}
}
\ No newline at end of file
src/main/scala/utils/Replacement.scala
浏览文件 @
9412fdbd
...
...
@@ -76,6 +76,7 @@ class TrueLRU(n_ways: Int) {
nextState
.
zipWithIndex
.
tail
.
foldLeft
((
nextState
.
head
.
apply
(
n_ways
-
1
,
1
),
0
))
{
case
((
pe
,
pi
),(
ce
,
ci
))
=>
(
Cat
(
ce
.
apply
(
n_ways
-
1
,
ci
+
1
),
pe
),
ci
)
}.
_1
}
def
get_next_state
(
state
:
UInt
,
touch_ways
:
Seq
[
Valid
[
UInt
]])
:
UInt
=
{
touch_ways
.
foldLeft
(
state
)((
prev
,
touch_way
)
=>
Mux
(
touch_way
.
valid
,
get_next_state
(
prev
,
touch_way
.
bits
),
prev
))
}
...
...
@@ -162,3 +163,66 @@ class SeqPLRU(n_sets: Int, n_ways: Int) extends SeqReplacementPolicy {
def
way
=
plru_way
}
class
SbufferLRU
(
n_ways
:
Int
)
{
def
nBits
=
n_ways
*
n_ways
private
val
state_reg
=
RegInit
(
0.
U
(
nBits
.
W
))
def
state_read
=
WireDefault
(
state_reg
)
def
get_next_state
(
state
:
UInt
,
touch_way
:
UInt
)
:
UInt
=
{
val
nextState
=
Wire
(
Vec
(
n_ways
,
UInt
(
n_ways
.
W
)))
val
moreRecentVec
=
state
.
asTypeOf
(
Vec
(
n_ways
,
UInt
(
n_ways
.
W
)))
val
wayDec
=
UIntToOH
(
touch_way
,
n_ways
)
val
wayUpd
=
(~
wayDec
).
asUInt
()
nextState
.
zipWithIndex
.
foreach
{
case
(
e
,
i
)
=>
e
:=
Mux
(
i
.
U
===
touch_way
,
wayUpd
,
moreRecentVec
(
i
)
&
wayUpd
)
}
nextState
.
asUInt
()
}
def
get_next_state
(
state
:
UInt
,
touch_ways
:
Seq
[
Valid
[
UInt
]])
:
UInt
=
{
touch_ways
.
foldLeft
(
state
)((
prev
,
touch_way
)
=>
Mux
(
touch_way
.
valid
,
get_next_state
(
prev
,
touch_way
.
bits
),
prev
))
}
def
access
(
touch_way
:
UInt
)
{
state_reg
:=
get_next_state
(
state_reg
,
touch_way
)
}
def
access
(
touch_ways
:
Seq
[
Valid
[
UInt
]])
{
when
(
ParallelOR
(
touch_ways
.
map
(
_
.
valid
)))
{
state_reg
:=
get_next_state
(
state_reg
,
touch_ways
)
}
}
def
get_min_value
(
xs
:
Seq
[(
UInt
,
UInt
)])
:
(
UInt
,
UInt
)
=
{
xs
match
{
case
Seq
(
a
)
=>
a
case
Seq
(
a
,
b
)
=>
(
Mux
(
a
.
_1
<
b
.
_1
,
a
.
_1
,
b
.
_1
),
Mux
(
a
.
_1
<
b
.
_1
,
a
.
_2
,
b
.
_2
))
case
_
=>
get_min_value
(
Seq
(
get_min_value
(
xs
take
xs
.
size
/
2
),
get_min_value
(
xs
drop
xs
.
size
/
2
)))
}
}
def
get_replace_way
(
state
:
UInt
,
sbufferState
:
Seq
[
Bool
])
:
UInt
=
{
val
moreRecentVec
=
state
.
asTypeOf
(
Vec
(
n_ways
,
UInt
(
n_ways
.
W
)))
val
count
=
Wire
(
Vec
(
n_ways
,
UInt
(
log2Up
(
n_ways
).
W
)))
for
(
i
<-
0
until
n_ways
){
count
(
i
)
:=
Mux
(
sbufferState
(
i
),
PopCount
(
moreRecentVec
(
i
)),
((
1
<<
n_ways
)-
1
).
U
)
}
count
.
zip
((
0
until
n_ways
).
map
(
_
.
U
))
get_min_value
(
count
.
zip
((
0
until
n_ways
).
map
(
_
.
U
))).
_2
}
def
way
(
sbufferState
:
Seq
[
Bool
])
=
get_replace_way
(
state_reg
,
sbufferState
)
//def miss = access(way)
def
hit
=
{}
def
flush
()
=
{
state_reg
:=
0.
U
(
nBits
.
W
)
}
//@deprecated("replace 'replace' with 'way' from abstract class ReplacementPolicy","Rocket Chip 2020.05")
//def replace: UInt = way
}
\ No newline at end of file
src/main/scala/xiangshan/mem/sbuffer/NewSbuffer.scala
浏览文件 @
9412fdbd
...
...
@@ -70,7 +70,8 @@ class NewSbuffer extends XSModule with HasSbufferCst {
val
buffer
=
Mem
(
StoreBufferSize
,
new
SbufferLine
)
val
stateVec
=
RegInit
(
VecInit
(
Seq
.
fill
(
StoreBufferSize
)(
s_invalid
)))
val
lru
=
new
TrueLRU
(
StoreBufferSize
)
//val lru = new SbufferLRU(StoreBufferSize)
val
lru
=
new
SbufferLRU
(
StoreBufferSize
)
// 2 * enq + 1 * deq
val
lruAccessWays
=
Wire
(
Vec
(
io
.
in
.
getWidth
+
1
,
new
Valid
(
UInt
(
SbufferIndexWidth
.
W
))))
for
(
w
<-
lruAccessWays
){
...
...
@@ -217,7 +218,7 @@ class NewSbuffer extends XSModule with HasSbufferCst {
val
do_eviction
=
Wire
(
Bool
())
val
empty
=
Cat
(
stateVec
.
map
(
s
=>
s
===
s_invalid
)).
andR
()
&&
!
Cat
(
io
.
in
.
map
(
_
.
valid
)).
orR
()
val
replaceIdx
=
lru
.
way
val
replaceIdx
=
lru
.
way
(
stateVec
.
map
(
s
=>
s
===
s_valid
))
val
firstValidEntry
=
PriorityEncoder
(
stateVec
.
map
(
s
=>
s
===
s_valid
))
val
evictor
=
Module
(
new
NaiveEvictor
(
StoreBufferSize
-
4
))
...
...
@@ -248,6 +249,8 @@ class NewSbuffer extends XSModule with HasSbufferCst {
}
XSDebug
(
p
"sbuffer state:${sbuffer_state} do eviction:${do_eviction} empty:${empty}\n"
)
//XSDebug(p"replaceIdx:${replaceIdx}\n")
//val evictionIdxWire = replaceIdx
val
evictionIdxWire
=
Mux
(
stateVec
(
replaceIdx
)===
s_valid
,
replaceIdx
,
firstValidEntry
)
val
evictionIdxEnqReq
=
Wire
(
DecoupledIO
(
UInt
(
SbufferIndexWidth
.
W
)))
val
evictionIdxQueue
=
Module
(
new
Queue
(
UInt
(
SbufferIndexWidth
.
W
),
StoreBufferSize
,
pipe
=
true
,
flow
=
false
))
...
...
src/test/scala/xiangshan/memend/SbufferTest.scala
0 → 100644
浏览文件 @
9412fdbd
package
xiangshan.memend
import
org.scalatest._
import
chiseltest._
import
chisel3._
import
chisel3.experimental.BundleLiterals._
import
chisel3.util._
import
xiangshan._
import
xiangshan.cache.
{
DCacheLineIO
,
DCacheWordReq
}
import
xiangshan.mem.
{
LoadForwardQueryIO
,
NewSbuffer
}
import
xiangshan.testutils._
import
scala.util.Random
class
SbufferWapper
extends
XSModule
{
val
io
=
IO
(
new
Bundle
()
{
val
in
=
Vec
(
StorePipelineWidth
,
Flipped
(
Decoupled
(
new
DCacheWordReq
)))
val
dcache
=
new
DCacheLineIO
val
forward
=
Vec
(
LoadPipelineWidth
,
Flipped
(
new
LoadForwardQueryIO
))
val
flush
=
new
Bundle
{
val
valid
=
Input
(
Bool
())
val
empty
=
Output
(
Bool
())
}
// sbuffer flush
})
val
sbuffer
=
Module
(
new
NewSbuffer
)
io
<>
sbuffer
.
io
// fake dcache
sbuffer
.
io
.
dcache
.
req
.
ready
:=
true
.
B
sbuffer
.
io
.
dcache
.
resp
.
valid
:=
RegNext
(
RegNext
(
RegNext
(
RegNext
(
sbuffer
.
io
.
dcache
.
req
.
valid
))))
sbuffer
.
io
.
dcache
.
resp
.
bits
.
meta
.
id
:=
RegNext
(
RegNext
(
RegNext
(
RegNext
(
sbuffer
.
io
.
dcache
.
req
.
bits
.
meta
.
id
))))
}
class
SbufferTest
extends
FlatSpec
with
ChiselScalatestTester
with
Matchers
with
HasXSParameter
with
ParallelTestExecution
with
HasPartialDecoupledDriver
{
top
.
Parameters
.
set
(
top
.
Parameters
.
debugParameters
)
it
should
"random req"
in
{
test
(
new
SbufferWapper
{
AddSinks
()}){
c
=>
def
store_enq
(
addr
:
Seq
[
UInt
],
data
:
Seq
[
UInt
],
mask
:
Seq
[
UInt
])
={
(
0
until
StorePipelineWidth
).
map
{
i
=>
c
.
io
.
in
(
i
).
valid
.
poke
(
true
.
B
)
c
.
io
.
in
(
i
).
bits
.
pokePartial
(
chiselTypeOf
(
c
.
io
.
in
(
i
).
bits
).
Lit
(
_
.
mask
->
mask
(
i
),
_
.
addr
->
addr
(
i
),
_
.
data
->
data
(
i
)
))
}
c
.
clock
.
step
(
1
)
for
(
in
<-
c
.
io
.
in
){
in
.
valid
.
poke
(
false
.
B
)}
}
def
forward_req_and_resp
(
addr
:
Seq
[
UInt
],
data
:
Seq
[
UInt
],
mask
:
Seq
[
UInt
])
=
{
(
0
until
LoadPipelineWidth
).
map
{
i
=>
c
.
io
.
forward
(
i
).
paddr
.
poke
(
addr
(
i
))
c
.
io
.
forward
(
i
).
mask
.
poke
(
mask
(
i
))
if
(
c
.
io
.
in
(
i
).
ready
.
peek
()
==
true
.
B
)
{
(
0
until
8
).
map
{
j
=>
c
.
io
.
forward
(
i
).
forwardData
(
j
).
expect
(
data
(
i
)(
j
*
8
+
7
,
j
*
8
))
}
}
}
}
val
TEST_SIZE
=
100
for
(
i
<-
0
until
TEST_SIZE
)
{
val
addr
=
Seq
.
fill
(
StorePipelineWidth
)((
Random
.
nextLong
()
&
0x7ffffffff8
L
).
U
)
// align to block size
val
data
=
Seq
.
fill
(
StorePipelineWidth
)((
Random
.
nextLong
()
&
0x7fffffffffffffff
L
).
U
)
val
mask
=
Seq
.
fill
(
StorePipelineWidth
)(
0xff
.
U
)
store_enq
(
addr
,
data
,
mask
)
forward_req_and_resp
(
addr
,
data
,
mask
)
}
}
}
it
should
"sequence req"
in
{
test
(
new
SbufferWapper
{
AddSinks
()}){
c
=>
def
store_enq
(
addr
:
Seq
[
UInt
],
data
:
Seq
[
UInt
],
mask
:
Seq
[
UInt
])
=
{
(
0
until
StorePipelineWidth
).
map
{
i
=>
c
.
io
.
in
(
i
).
valid
.
poke
(
true
.
B
)
c
.
io
.
in
(
i
).
bits
.
pokePartial
(
chiselTypeOf
(
c
.
io
.
in
(
i
).
bits
).
Lit
(
_
.
mask
->
mask
(
i
),
_
.
addr
->
addr
(
i
),
_
.
data
->
data
(
i
)
))
}
c
.
clock
.
step
(
1
)
for
(
in
<-
c
.
io
.
in
){
in
.
valid
.
poke
(
false
.
B
)}
}
def
forward_req_and_resp
(
addr
:
Seq
[
UInt
],
data
:
Seq
[
UInt
],
mask
:
Seq
[
UInt
])
=
{
(
0
until
LoadPipelineWidth
).
map
{
i
=>
c
.
io
.
forward
(
i
).
paddr
.
poke
(
addr
(
i
))
c
.
io
.
forward
(
i
).
mask
.
poke
(
mask
(
i
))
if
(
c
.
io
.
in
(
i
).
ready
.
peek
()
==
true
.
B
)
{
(
0
until
8
).
map
{
j
=>
c
.
io
.
forward
(
i
).
forwardData
(
j
).
expect
(
data
(
i
)(
j
*
8
+
7
,
j
*
8
))
}
}
}
}
val
TEST_SIZE
=
100
val
start_addr
=
Random
.
nextLong
()
&
0x7ffffffff8
L
for
(
i
<-
0
until
TEST_SIZE
)
{
val
addr
=
Seq
(((
i
<<
4
)
+
start_addr
).
U
,((
i
<<
4
)+
8
+
start_addr
).
U
)
val
data
=
Seq
.
fill
(
StorePipelineWidth
)((
Random
.
nextLong
()
&
0x7fffffffffffffff
L
).
U
)
val
mask
=
Seq
.
fill
(
StorePipelineWidth
)(
0xff
.
U
)
store_enq
(
addr
,
data
,
mask
)
forward_req_and_resp
(
addr
,
data
,
mask
)
}
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录