Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenXiangShan
XiangShan
提交
0e8472d1
X
XiangShan
项目概览
OpenXiangShan
/
XiangShan
11 个月 前同步成功
通知
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,发现更多精彩内容 >>
未验证
提交
0e8472d1
编写于
11月 12, 2020
作者:
Y
Yinan Xu
提交者:
GitHub
11月 12, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' into new-lbuf
上级
5e3fc932
21aac058
变更
15
隐藏空白更改
内联
并排
Showing
15 changed file
with
797 addition
and
139 deletion
+797
-139
.github/workflows/emu.yml
.github/workflows/emu.yml
+5
-47
block-inclusivecache-sifive
block-inclusivecache-sifive
+1
-1
src/main/scala/top/XiangShanStage.scala
src/main/scala/top/XiangShanStage.scala
+2
-2
src/main/scala/xiangshan/backend/exu/MulDivExeUnit.scala
src/main/scala/xiangshan/backend/exu/MulDivExeUnit.scala
+2
-2
src/main/scala/xiangshan/backend/fu/FunctionUnit.scala
src/main/scala/xiangshan/backend/fu/FunctionUnit.scala
+3
-2
src/main/scala/xiangshan/backend/fu/Multiplier.scala
src/main/scala/xiangshan/backend/fu/Multiplier.scala
+139
-8
src/main/scala/xiangshan/backend/fu/Radix2Divider.scala
src/main/scala/xiangshan/backend/fu/Radix2Divider.scala
+8
-5
src/main/scala/xiangshan/backend/fu/SRT4Divider.scala
src/main/scala/xiangshan/backend/fu/SRT4Divider.scala
+230
-0
src/main/scala/xiangshan/backend/fu/fpu/divsqrt/DivSqrt.scala
...main/scala/xiangshan/backend/fu/fpu/divsqrt/DivSqrt.scala
+1
-1
src/main/scala/xiangshan/backend/issue/ReservationStationNew.scala
...scala/xiangshan/backend/issue/ReservationStationNew.scala
+1
-1
src/main/scala/xiangshan/backend/roq/Roq.scala
src/main/scala/xiangshan/backend/roq/Roq.scala
+1
-1
src/main/scala/xiangshan/cache/storeMissQueue.scala
src/main/scala/xiangshan/cache/storeMissQueue.scala
+4
-3
src/test/csrc/difftest.cpp
src/test/csrc/difftest.cpp
+1
-1
src/test/scala/cache/L1plusCacheTest.scala
src/test/scala/cache/L1plusCacheTest.scala
+74
-65
src/test/scala/cache/L2CacheNonInclusiveGetTest.scala
src/test/scala/cache/L2CacheNonInclusiveGetTest.scala
+325
-0
未找到文件。
.github/workflows/emu.yml
浏览文件 @
0e8472d1
...
...
@@ -21,26 +21,13 @@ jobs:
run
:
|
echo ::set-env name=NEMU_HOME::/home/ci-runner/xsenv/NEMU
echo ::set-env name=NOOP_HOME::$GITHUB_WORKSPACE
echo ::set-env name=RVTEST_HOME::/home/ci-runner/xsenv/riscv-tests
echo ::set-env name=AM_HOME::/home/ci-runner/xsenv/nexus-am
-
name
:
Build EMU
run
:
make ./build/emu SIM_ARGS=--disable-log EMU_THREADS=16 NEMU_HOME=$NEMU_HOME NOOP_HOME=$NOOP_HOME -j20
cputest
:
runs-on
:
self-hosted
name
:
Run cputest
needs
:
[
build-emu
]
steps
:
-
name
:
Set env
run
:
|
echo ::set-env name=AM_HOME::/home/ci-runner/xsenv/nexus-am
echo ::set-env name=NEMU_HOME::/home/ci-runner/xsenv/NEMU
echo ::set-env name=NOOP_HOME::$GITHUB_WORKSPACE
-
name
:
Run cputest
run
:
|
echo $AM_HOME
echo $NEMU_HOME
echo $NOOP_HOME
CPU_TEST_DIR=$AM_HOME/tests/cputest
echo $CPU_TEST_DIR
ret=0
...
...
@@ -56,38 +43,9 @@ jobs:
fi
done
exit $ret
microbench
:
runs-on
:
self-hosted
name
:
Run microbench
needs
:
[
build-emu
]
steps
:
-
name
:
Set env
-
name
:
Run riscv-tests
run
:
|
echo ::set-env name=AM_HOME::/home/ci-runner/xsenv/nexus-am
echo ::set-env name=NEMU_HOME::/home/ci-runner/xsenv/NEMU
echo ::set-env name=NOOP_HOME::$GITHUB_WORKSPACE
make -C $RVTEST_HOME/isa/ SUITES+=rv64ui SUITES+=rv64um SUITES+=rv64ua NEMU_HOME=$NEMU_HOME NOOP_HOME=$NOOP_HOME noop_run 2> /dev/null
-
name
:
Run microbench
run
:
|
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
riscv-tests
:
runs-on
:
self-hosted
name
:
Run riscv-tests
needs
:
[
build-emu
]
steps
:
-
name
:
Set env
run
:
|
echo ::set-env name=NEMU_HOME::/home/ci-runner/xsenv/NEMU
echo ::set-env name=NOOP_HOME::$GITHUB_WORKSPACE
echo ::set-env name=RVTEST_HOME::/home/ci-runner/xsenv/riscv-tests
-
name
:
Run riscv-test
run
:
|
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 $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
\ No newline at end of file
block-inclusivecache-sifive
@
37d27a8f
比较
5ca43398
...
37d27a8f
Subproject commit
5ca43398ac8b1b293291bd4e6e8c233be6c66968
Subproject commit
37d27a8f3b7d288c4663eebd8571018357fd827a
src/main/scala/top/XiangShanStage.scala
浏览文件 @
0e8472d1
...
...
@@ -5,7 +5,7 @@ import firrtl.AnnotationSeq
import
firrtl.annotations.NoTargetAnnotation
import
firrtl.options.
{
HasShellOptions
,
Shell
,
ShellOption
}
import
firrtl.stage.
{
FirrtlCli
,
RunFirrtlTransformAnnotation
}
//
import xstransforms.ShowPrintTransform
import
xstransforms.ShowPrintTransform
import
xstransforms.PrintModuleName
case
class
DisablePrintfAnnotation
(
m
:
String
)
extends
NoTargetAnnotation
...
...
@@ -78,7 +78,7 @@ object XiangShanStage {
(
new
XiangShanStage
).
execute
(
args
,
annotations
++
Seq
(
//
RunFirrtlTransformAnnotation(new ShowPrintTransform),
RunFirrtlTransformAnnotation
(
new
ShowPrintTransform
),
RunFirrtlTransformAnnotation
(
new
PrintModuleName
)
)
)
...
...
src/main/scala/xiangshan/backend/exu/MulDivExeUnit.scala
浏览文件 @
0e8472d1
...
...
@@ -5,7 +5,7 @@ import chisel3.util._
import
xiangshan._
import
utils._
import
xiangshan.backend.MDUOpType
import
xiangshan.backend.fu.
{
A
rrayMultiplier
,
Divider
,
FunctionUnit
}
import
xiangshan.backend.fu.
{
A
bstractDivider
,
ArrayMultiplier
,
FunctionUnit
,
Radix2Divider
}
class
MulDivExeUnit
(
hasDiv
:
Boolean
=
true
)
extends
Exu
(
exuName
=
if
(
hasDiv
)
"MulDivExeUnit"
else
"MulExeUnit"
,
...
...
@@ -31,7 +31,7 @@ class MulDivExeUnit(hasDiv: Boolean = true) extends Exu(
}.
get
val
div
=
supportedFunctionUnits
.
collectFirst
{
case
d
:
Divider
=>
d
case
d
:
Abstract
Divider
=>
d
}.
orNull
// override inputs
...
...
src/main/scala/xiangshan/backend/fu/FunctionUnit.scala
浏览文件 @
0e8472d1
...
...
@@ -129,8 +129,9 @@ trait HasPipelineReg { this: FunctionUnit =>
object
FunctionUnit
extends
HasXSParameter
{
def
multiplier
=
new
ArrayMultiplier
(
XLEN
+
1
)
def
divider
=
new
Divider
(
XLEN
)
def
divider
=
new
SRT4Divider
(
XLEN
)
def
multiplier
=
new
ArrayMultiplier
(
XLEN
+
1
,
Seq
(
0
,
2
))
def
alu
=
new
Alu
def
jmp
=
new
Jump
...
...
src/main/scala/xiangshan/backend/fu/Multiplier.scala
浏览文件 @
0e8472d1
...
...
@@ -4,8 +4,7 @@ import chisel3._
import
chisel3.util._
import
xiangshan._
import
utils._
import
xiangshan.backend._
import
xiangshan.backend.fu.FunctionUnit._
import
xiangshan.backend.fu.fpu.util.
{
C22
,
C32
,
C53
}
class
MulDivCtrl
extends
Bundle
{
val
sign
=
Bool
()
...
...
@@ -13,14 +12,17 @@ class MulDivCtrl extends Bundle{
val
isHi
=
Bool
()
// return hi bits of result ?
}
class
ArrayMultiplier
(
len
:
Int
,
latency
:
Int
=
3
)
extends
FunctionUnit
(
FuConfig
(
FuType
.
mul
,
2
,
0
,
writeIntRf
=
true
,
writeFpRf
=
false
,
hasRedirect
=
false
,
CertainLatency
(
latency
)),
len
)
class
AbstractMultiplier
(
len
:
Int
,
latency
:
Int
=
2
)
extends
FunctionUnit
(
FuConfig
(
FuType
.
mul
,
2
,
0
,
writeIntRf
=
true
,
writeFpRf
=
false
,
hasRedirect
=
false
,
CertainLatency
(
latency
)),
len
){
val
ctrl
=
IO
(
Input
(
new
MulDivCtrl
))
}
class
NaiveMultiplier
(
len
:
Int
,
latency
:
Int
=
3
)
extends
AbstractMultiplier
(
len
,
latency
)
with
HasPipelineReg
{
val
ctrl
=
IO
(
Input
(
new
MulDivCtrl
))
val
(
src1
,
src2
)
=
(
io
.
in
.
bits
.
src
(
0
),
io
.
in
.
bits
.
src
(
1
))
...
...
@@ -38,5 +40,134 @@ class ArrayMultiplier(len: Int, latency: Int = 3)
val
res
=
Mux
(
ctrlVec
.
last
.
isHi
,
dataVec
.
last
(
2
*
xlen
-
1
,
xlen
),
dataVec
.
last
(
xlen
-
1
,
0
))
io
.
out
.
bits
.
data
:=
Mux
(
ctrlVec
.
last
.
isW
,
SignExt
(
res
(
31
,
0
),
xlen
),
res
)
XSDebug
(
p
"validVec:${Binary(Cat(validVec))} flushVec:${Binary(Cat(flushVec))}\n"
)
}
class
ArrayMultiplier
(
len
:
Int
,
doReg
:
Seq
[
Int
])
extends
AbstractMultiplier
(
len
,
doReg
.
size
)
with
HasPipelineReg
{
val
doRegSorted
=
doReg
.
sortWith
(
_
<
_
)
println
(
doRegSorted
)
val
(
a
,
b
)
=
(
io
.
in
.
bits
.
src
(
0
),
io
.
in
.
bits
.
src
(
1
))
val
b_sext
,
bx2
,
neg_b
,
neg_bx2
=
Wire
(
UInt
((
len
+
1
).
W
))
b_sext
:=
SignExt
(
b
,
len
+
1
)
bx2
:=
b_sext
<<
1
neg_b
:=
(~
b_sext
).
asUInt
()
neg_bx2
:=
neg_b
<<
1
val
columns
:
Array
[
Seq
[
Bool
]]
=
Array
.
fill
(
2
*
len
)(
Seq
())
var
last_x
=
WireInit
(
0.
U
(
3.
W
))
for
(
i
<-
Range
(
0
,
len
,
2
)){
val
x
=
if
(
i
==
0
)
Cat
(
a
(
1
,
0
),
0.
U
(
1.
W
))
else
if
(
i
+
1
==
len
)
SignExt
(
a
(
i
,
i
-
1
),
3
)
else
a
(
i
+
1
,
i
-
1
)
val
pp_temp
=
MuxLookup
(
x
,
0.
U
,
Seq
(
1.
U
->
b_sext
,
2.
U
->
b_sext
,
3.
U
->
bx2
,
4.
U
->
neg_bx2
,
5.
U
->
neg_b
,
6.
U
->
neg_b
))
val
s
=
pp_temp
(
len
)
val
t
=
MuxLookup
(
last_x
,
0.
U
(
2.
W
),
Seq
(
4.
U
->
2.
U
(
2.
W
),
5.
U
->
1.
U
(
2.
W
),
6.
U
->
1.
U
(
2.
W
)
))
last_x
=
x
val
(
pp
,
weight
)
=
i
match
{
case
0
=>
(
Cat
(~
s
,
s
,
s
,
pp_temp
),
0
)
case
n
if
(
n
==
len
-
1
)
||
(
n
==
len
-
2
)
=>
(
Cat
(~
s
,
pp_temp
,
t
),
i
-
2
)
case
_
=>
(
Cat
(
1.
U
(
1.
W
),
~
s
,
pp_temp
,
t
),
i
-
2
)
}
for
(
j
<-
columns
.
indices
){
if
(
j
>=
weight
&&
j
<
(
weight
+
pp
.
getWidth
)){
columns
(
j
)
=
columns
(
j
)
:+
pp
(
j
-
weight
)
}
}
}
def
addOneColumn
(
col
:
Seq
[
Bool
],
cin
:
Seq
[
Bool
])
:
(
Seq
[
Bool
],
Seq
[
Bool
],
Seq
[
Bool
])
=
{
var
sum
=
Seq
[
Bool
]()
var
cout1
=
Seq
[
Bool
]()
var
cout2
=
Seq
[
Bool
]()
col
.
size
match
{
case
1
=>
// do nothing
sum
=
col
++
cin
case
2
=>
val
c22
=
Module
(
new
C22
)
c22
.
io
.
in
:=
col
sum
=
c22
.
io
.
out
(
0
).
asBool
()
+:
cin
cout2
=
Seq
(
c22
.
io
.
out
(
1
).
asBool
())
case
3
=>
val
c32
=
Module
(
new
C32
)
c32
.
io
.
in
:=
col
sum
=
c32
.
io
.
out
(
0
).
asBool
()
+:
cin
cout2
=
Seq
(
c32
.
io
.
out
(
1
).
asBool
())
case
4
=>
val
c53
=
Module
(
new
C53
)
for
((
x
,
y
)
<-
c53
.
io
.
in
.
take
(
4
)
zip
col
){
x
:=
y
}
c53
.
io
.
in
.
last
:=
(
if
(
cin
.
nonEmpty
)
cin
.
head
else
0.
U
)
sum
=
Seq
(
c53
.
io
.
out
(
0
).
asBool
())
++
(
if
(
cin
.
nonEmpty
)
cin
.
drop
(
1
)
else
Nil
)
cout1
=
Seq
(
c53
.
io
.
out
(
1
).
asBool
())
cout2
=
Seq
(
c53
.
io
.
out
(
2
).
asBool
())
case
n
=>
val
cin_1
=
if
(
cin
.
nonEmpty
)
Seq
(
cin
.
head
)
else
Nil
val
cin_2
=
if
(
cin
.
nonEmpty
)
cin
.
drop
(
1
)
else
Nil
val
(
s_1
,
c_1_1
,
c_1_2
)
=
addOneColumn
(
col
take
4
,
cin_1
)
val
(
s_2
,
c_2_1
,
c_2_2
)
=
addOneColumn
(
col
drop
4
,
cin_2
)
sum
=
s_1
++
s_2
cout1
=
c_1_1
++
c_2_1
cout2
=
c_1_2
++
c_2_2
}
(
sum
,
cout1
,
cout2
)
}
def
max
(
in
:
Iterable
[
Int
])
:
Int
=
in
.
reduce
((
a
,
b
)
=>
if
(
a
>
b
)
a
else
b
)
def
addAll
(
cols
:
Array
[
Seq
[
Bool
]],
depth
:
Int
)
:
(
UInt
,
UInt
)
=
{
if
(
max
(
cols
.
map
(
_
.
size
))
<=
2
){
val
sum
=
Cat
(
cols
.
map
(
_
(
0
)).
reverse
)
var
k
=
0
while
(
cols
(
k
).
size
==
1
)
k
=
k
+
1
val
carry
=
Cat
(
cols
.
drop
(
k
).
map
(
_
(
1
)).
reverse
)
(
sum
,
Cat
(
carry
,
0.
U
(
k
.
W
)))
}
else
{
val
columns_next
=
Array
.
fill
(
2
*
len
)(
Seq
[
Bool
]())
var
cout1
,
cout2
=
Seq
[
Bool
]()
for
(
i
<-
cols
.
indices
){
val
(
s
,
c1
,
c2
)
=
addOneColumn
(
cols
(
i
),
cout1
)
columns_next
(
i
)
=
s
++
cout2
cout1
=
c1
cout2
=
c2
}
val
needReg
=
doRegSorted
.
contains
(
depth
)
val
toNextLayer
=
if
(
needReg
)
columns_next
.
map
(
_
.
map
(
PipelineReg
(
doRegSorted
.
indexOf
(
depth
)
+
1
)(
_
)))
else
columns_next
addAll
(
toNextLayer
,
depth
+
1
)
}
}
val
(
sum
,
carry
)
=
addAll
(
cols
=
columns
,
depth
=
0
)
val
result
=
sum
+
carry
var
ctrlVec
=
Seq
(
ctrl
)
for
(
i
<-
1
to
latency
){
ctrlVec
=
ctrlVec
:+
PipelineReg
(
i
)(
ctrlVec
(
i
-
1
))
}
val
xlen
=
io
.
out
.
bits
.
data
.
getWidth
val
res
=
Mux
(
ctrlVec
.
last
.
isHi
,
result
(
2
*
xlen
-
1
,
xlen
),
result
(
xlen
-
1
,
0
))
io
.
out
.
bits
.
data
:=
Mux
(
ctrlVec
.
last
.
isW
,
SignExt
(
res
(
31
,
0
),
xlen
),
res
)
XSDebug
(
p
"validVec:${Binary(Cat(validVec))} flushVec:${Binary(Cat(flushVec))}\n"
)
}
\ No newline at end of file
src/main/scala/xiangshan/backend/fu/Divider.scala
→
src/main/scala/xiangshan/backend/fu/
Radix2
Divider.scala
浏览文件 @
0e8472d1
...
...
@@ -5,13 +5,15 @@ import chisel3.util._
import
xiangshan._
import
utils._
class
Divider
(
len
:
Int
)
extends
FunctionUnit
(
abstract
class
Abstract
Divider
(
len
:
Int
)
extends
FunctionUnit
(
FuConfig
(
FuType
.
div
,
2
,
0
,
writeIntRf
=
true
,
writeFpRf
=
false
,
hasRedirect
=
false
,
UncertainLatency
()),
len
)
{
){
val
ctrl
=
IO
(
Input
(
new
MulDivCtrl
))
val
sign
=
ctrl
.
sign
}
class
Radix2Divider
(
len
:
Int
)
extends
AbstractDivider
(
len
)
{
def
abs
(
a
:
UInt
,
sign
:
Bool
)
:
(
Bool
,
UInt
)
=
{
val
s
=
a
(
len
-
1
)
&&
sign
...
...
@@ -72,7 +74,8 @@ class Divider(len: Int) extends FunctionUnit(
}
}
when
(
state
=/=
s_idle
&&
uopReg
.
roqIdx
.
needFlush
(
io
.
redirectIn
)){
val
kill
=
state
=/=
s_idle
&&
uopReg
.
roqIdx
.
needFlush
(
io
.
redirectIn
)
when
(
kill
){
state
:=
s_idle
}
...
...
@@ -85,6 +88,6 @@ class Divider(len: Int) extends FunctionUnit(
io
.
out
.
bits
.
data
:=
Mux
(
ctrlReg
.
isW
,
SignExt
(
res
(
31
,
0
),
xlen
),
res
)
io
.
out
.
bits
.
uop
:=
uopReg
io
.
out
.
valid
:=
state
===
s_finish
io
.
out
.
valid
:=
state
===
s_finish
&&
!
kill
io
.
in
.
ready
:=
state
===
s_idle
}
\ No newline at end of file
src/main/scala/xiangshan/backend/fu/SRT4Divider.scala
0 → 100644
浏览文件 @
0e8472d1
package
xiangshan.backend.fu
import
chisel3._
import
chisel3.util._
import
utils.SignExt
import
xiangshan.backend.fu.fpu.util.CSA3_2
/** A Radix-4 SRT Integer Divider
*
* 2 ~ (5 + (len+3)/2) cycles are needed for each division.
*/
class
SRT4Divider
(
len
:
Int
)
extends
AbstractDivider
(
len
)
{
val
s_idle
::
s_lzd
::
s_normlize
::
s_recurrence
::
s_recovery
::
s_finish
::
Nil
=
Enum
(
6
)
val
state
=
RegInit
(
s_idle
)
val
newReq
=
(
state
===
s_idle
)
&&
io
.
in
.
fire
()
val
cnt_next
=
Wire
(
UInt
(
log2Up
((
len
+
3
)/
2
).
W
))
val
cnt
=
RegEnable
(
cnt_next
,
state
===
s_normlize
||
state
===
s_recurrence
)
val
rec_enough
=
cnt_next
===
0.
U
def
abs
(
a
:
UInt
,
sign
:
Bool
)
:
(
Bool
,
UInt
)
=
{
val
s
=
a
(
len
-
1
)
&&
sign
(
s
,
Mux
(
s
,
-
a
,
a
))
}
val
(
a
,
b
)
=
(
io
.
in
.
bits
.
src
(
0
),
io
.
in
.
bits
.
src
(
1
))
val
uop
=
io
.
in
.
bits
.
uop
val
(
aSign
,
aVal
)
=
abs
(
a
,
sign
)
val
(
bSign
,
bVal
)
=
abs
(
b
,
sign
)
val
aSignReg
=
RegEnable
(
aSign
,
newReq
)
val
qSignReg
=
RegEnable
(
aSign
^
bSign
,
newReq
)
val
uopReg
=
RegEnable
(
uop
,
newReq
)
val
ctrlReg
=
RegEnable
(
ctrl
,
newReq
)
val
divZero
=
b
===
0.
U
val
divZeroReg
=
RegEnable
(
divZero
,
newReq
)
val
kill
=
state
=/=
s_idle
&&
uopReg
.
roqIdx
.
needFlush
(
io
.
redirectIn
)
switch
(
state
){
is
(
s_idle
){
when
(
io
.
in
.
fire
()){
state
:=
Mux
(
divZero
,
s_finish
,
s_lzd
)
}
}
is
(
s_lzd
){
// leading zero detection
state
:=
s_normlize
}
is
(
s_normlize
){
// shift a/b
state
:=
s_recurrence
}
is
(
s_recurrence
){
// (ws[j+1], wc[j+1]) = 4(ws[j],wc[j]) - q(j+1)*d
when
(
rec_enough
){
state
:=
s_recovery
}
}
is
(
s_recovery
){
// if rem < 0, rem = rem + d
state
:=
s_finish
}
is
(
s_finish
){
when
(
io
.
out
.
fire
()){
state
:=
s_idle
}
}
}
when
(
kill
){
state
:=
s_idle
}
/** Calculate abs(a)/abs(b) by recurrence
*
* ws, wc: partial remainder in carry-save form,
* in recurrence steps, ws/wc = 4ws[j]/4wc[j];
* in recovery step, ws/wc = ws[j]/wc[j];
* in final step, ws = abs(a)/abs(b).
*
* d: normlized divisor(1/2<=d<1)
*
* wLen = 3 integer bits + (len+1) frac bits
*/
def
wLen
=
3
+
len
+
1
val
ws
,
wc
=
Reg
(
UInt
(
wLen
.
W
))
val
ws_next
,
wc_next
=
Wire
(
UInt
(
wLen
.
W
))
val
d
=
Reg
(
UInt
(
wLen
.
W
))
val
aLeadingZeros
=
RegEnable
(
next
=
PriorityEncoder
(
ws
(
len
-
1
,
0
).
asBools
().
reverse
),
enable
=
state
===
s_lzd
)
val
bLeadingZeros
=
RegEnable
(
next
=
PriorityEncoder
(
d
(
len
-
1
,
0
).
asBools
().
reverse
),
enable
=
state
===
s_lzd
)
val
diff
=
Cat
(
0.
U
(
1.
W
),
bLeadingZeros
).
asSInt
()
-
Cat
(
0.
U
(
1.
W
),
aLeadingZeros
).
asSInt
()
val
isNegDiff
=
diff
(
diff
.
getWidth
-
1
)
val
quotientBits
=
Mux
(
isNegDiff
,
0.
U
,
diff
.
asUInt
())
val
qBitsIsOdd
=
quotientBits
(
0
)
val
recoveryShift
=
RegEnable
(
len
.
U
-
bLeadingZeros
,
state
===
s_normlize
)
val
a_shifted
,
b_shifted
=
Wire
(
UInt
(
len
.
W
))
a_shifted
:=
Mux
(
isNegDiff
,
ws
(
len
-
1
,
0
)
<<
bLeadingZeros
,
ws
(
len
-
1
,
0
)
<<
aLeadingZeros
)
b_shifted
:=
d
(
len
-
1
,
0
)
<<
bLeadingZeros
val
rem_temp
=
ws
+
wc
val
rem_fixed
=
Mux
(
rem_temp
(
wLen
-
1
),
rem_temp
+
d
,
rem_temp
)
val
rem_abs
=
(
rem_fixed
<<
recoveryShift
)(
2
*
len
,
len
+
1
)
when
(
newReq
){
ws
:=
Cat
(
0.
U
(
4.
W
),
Mux
(
divZero
,
a
,
aVal
))
wc
:=
0.
U
d
:=
Cat
(
0.
U
(
4.
W
),
bVal
)
}.
elsewhen
(
state
===
s_normlize
){
d
:=
Cat
(
0.
U
(
3.
W
),
b_shifted
,
0.
U
(
1.
W
))
ws
:=
Mux
(
qBitsIsOdd
,
a_shifted
,
a_shifted
<<
1
)
}.
elsewhen
(
state
===
s_recurrence
){
ws
:=
Mux
(
rec_enough
,
ws_next
,
ws_next
<<
2
)
wc
:=
Mux
(
rec_enough
,
wc_next
,
wc_next
<<
2
)
}.
elsewhen
(
state
===
s_recovery
){
ws
:=
rem_abs
}
cnt_next
:=
Mux
(
state
===
s_normlize
,
(
quotientBits
+
3.
U
)
>>
1
,
cnt
-
1.
U
)
/** Quotient selection
*
* the quotient selection table use truncated 7-bit remainder
* and 3-bit divisor
*/
val
sel_0
::
sel_d
::
sel_dx2
::
sel_neg_d
::
sel_neg_dx2
::
Nil
=
Enum
(
5
)
val
dx2
,
neg_d
,
neg_dx2
=
Wire
(
UInt
(
wLen
.
W
))
dx2
:=
d
<<
1
neg_d
:=
(~
d
).
asUInt
()
// add '1' in carry-save adder later
neg_dx2
:=
neg_d
<<
1
val
q_sel
=
Wire
(
UInt
(
3.
W
))
val
wc_adj
=
MuxLookup
(
q_sel
,
0.
U
(
2.
W
),
Seq
(
sel_d
->
1.
U
(
2.
W
),
sel_dx2
->
2.
U
(
2.
W
)
))
val
w_truncated
=
(
ws
(
wLen
-
1
,
wLen
-
1
-
6
)
+
wc
(
wLen
-
1
,
wLen
-
1
-
6
)).
asSInt
()
val
d_truncated
=
d
(
len
-
1
,
len
-
3
)
val
qSelTable
=
Array
(
Array
(
12
,
4
,
-
4
,
-
13
),
Array
(
14
,
4
,
-
6
,
-
15
),
Array
(
15
,
4
,
-
6
,
-
16
),
Array
(
16
,
4
,
-
6
,
-
18
),
Array
(
18
,
6
,
-
8
,
-
20
),
Array
(
20
,
6
,
-
8
,
-
20
),
Array
(
20
,
8
,
-
8
,
-
22
),
Array
(
24
,
8
,
-
8
,
-
24
)
)
// ge(x): w_truncated >= x
var
ge
=
Map
[
Int
,
Bool
]()
for
(
row
<-
qSelTable
){
for
(
k
<-
row
){
if
(!
ge
.
contains
(
k
))
ge
=
ge
+
(
k
->
(
w_truncated
>=
k
.
S
(
7.
W
)))
}
}
q_sel
:=
MuxLookup
(
d_truncated
,
sel_0
,
qSelTable
.
map
(
x
=>
MuxCase
(
sel_neg_dx2
,
Seq
(
ge
(
x
(
0
))
->
sel_dx2
,
ge
(
x
(
1
))
->
sel_d
,
ge
(
x
(
2
))
->
sel_0
,
ge
(
x
(
3
))
->
sel_neg_d
))
).
zipWithIndex
.
map
({
case
(
v
,
i
)
=>
i
.
U
->
v
})
)
/** Calculate (ws[j+1],wc[j+1]) by a [3-2]carry-save adder
*
* (ws[j+1], wc[j+1]) = 4(ws[j],wc[j]) - q(j+1)*d
*/
val
csa
=
Module
(
new
CSA3_2
(
wLen
))
csa
.
io
.
in
(
0
)
:=
ws
csa
.
io
.
in
(
1
)
:=
Cat
(
wc
(
wLen
-
1
,
2
),
wc_adj
)
csa
.
io
.
in
(
2
)
:=
MuxLookup
(
q_sel
,
0.
U
,
Seq
(
sel_d
->
neg_d
,
sel_dx2
->
neg_dx2
,
sel_neg_d
->
d
,
sel_neg_dx2
->
dx2
))
ws_next
:=
csa
.
io
.
out
(
0
)
wc_next
:=
csa
.
io
.
out
(
1
)
<<
1
// On the fly quotient conversion
val
q
,
qm
=
Reg
(
UInt
(
len
.
W
))
when
(
newReq
){
q
:=
0.
U
qm
:=
0.
U
}.
elsewhen
(
state
===
s_recurrence
){
val
qMap
=
Seq
(
sel_0
->
(
q
,
0
),
sel_d
->
(
q
,
1
),
sel_dx2
->
(
q
,
2
),
sel_neg_d
->
(
qm
,
3
),
sel_neg_dx2
->
(
qm
,
2
)
)
q
:=
MuxLookup
(
q_sel
,
0.
U
,
qMap
.
map
(
m
=>
m
.
_1
->
Cat
(
m
.
_2
.
_1
(
len
-
3
,
0
),
m
.
_2
.
_2
.
U
(
2.
W
)))
)
val
qmMap
=
Seq
(
sel_0
->
(
qm
,
3
),
sel_d
->
(
q
,
0
),
sel_dx2
->
(
q
,
1
),
sel_neg_d
->
(
qm
,
2
),
sel_neg_dx2
->
(
qm
,
1
)
)
qm
:=
MuxLookup
(
q_sel
,
0.
U
,
qmMap
.
map
(
m
=>
m
.
_1
->
Cat
(
m
.
_2
.
_1
(
len
-
3
,
0
),
m
.
_2
.
_2
.
U
(
2.
W
)))
)
}.
elsewhen
(
state
===
s_recovery
){
q
:=
Mux
(
rem_temp
(
wLen
-
1
),
qm
,
q
)
}
val
remainder
=
Mux
(
aSignReg
,
-
ws
(
len
-
1
,
0
),
ws
(
len
-
1
,
0
))
val
quotient
=
Mux
(
qSignReg
,
-
q
,
q
)
val
res
=
Mux
(
ctrlReg
.
isHi
,
Mux
(
divZeroReg
,
ws
(
len
-
1
,
0
),
remainder
),
Mux
(
divZeroReg
,
Fill
(
len
,
1.
U
(
1.
W
)),
quotient
)
)
io
.
in
.
ready
:=
state
===
s_idle
io
.
out
.
valid
:=
state
===
s_finish
&&
!
kill
io
.
out
.
bits
.
data
:=
Mux
(
ctrlReg
.
isW
,
SignExt
(
res
(
31
,
0
),
len
),
res
)
io
.
out
.
bits
.
uop
:=
uopReg
}
src/main/scala/xiangshan/backend/fu/fpu/divsqrt/DivSqrt.scala
浏览文件 @
0e8472d1
...
...
@@ -21,7 +21,7 @@ class DivSqrt extends FPUSubModule(
val
uopReg
=
RegEnable
(
io
.
in
.
bits
.
uop
,
io
.
in
.
fire
())
val
kill
=
uopReg
.
roqIdx
.
needFlush
(
io
.
redirectIn
)
val
kill
=
state
=/=
s_idle
&&
uopReg
.
roqIdx
.
needFlush
(
io
.
redirectIn
)
val
rmReg
=
RegEnable
(
rm
,
io
.
in
.
fire
())
val
isDiv
=
!
op
(
0
)
val
isDivReg
=
RegEnable
(
isDiv
,
io
.
in
.
fire
())
...
...
src/main/scala/xiangshan/backend/issue/ReservationStationNew.scala
浏览文件 @
0e8472d1
...
...
@@ -295,7 +295,7 @@ class ReservationStationNew
val
srcStateSeq
=
Seq
(
enqUop
.
src1State
,
enqUop
.
src2State
,
enqUop
.
src3State
)
val
srcDataSeq
=
Seq
(
io
.
enqData
.
src1
,
io
.
enqData
.
src2
,
io
.
enqData
.
src3
)
val
enqPtr
=
Mux
(
tailPtr
.
head
(
1
).
asBool
,
selectedIdxReg
,
tailPtr
.
tail
(
1
))
val
enqPtr
=
Mux
(
tailPtr
.
head
(
1
).
asBool
,
deqIdx
,
tailPtr
.
tail
(
1
))
val
enqIdx_data
=
idxQueue
(
enqPtr
)
val
enqIdx_ctrl
=
tailAfterRealDeq
.
tail
(
1
)
val
enqIdxNext
=
RegNext
(
enqIdx_data
)
...
...
src/main/scala/xiangshan/backend/roq/Roq.scala
浏览文件 @
0e8472d1
...
...
@@ -281,7 +281,7 @@ class Roq extends XSModule with HasCircularQueuePtrHelper {
val
retireCounter
=
Mux
(
state
===
s_idle
,
commitCnt
,
0.
U
)
XSInfo
(
retireCounter
>
0.
U
,
"retired %d insts\n"
,
retireCounter
)
val
commitOffset
=
PriorityEncoder
((
validCommit
:+
false
.
B
).
map
(!
_
))
io
.
commitRoqIndex
.
valid
:=
io
.
commits
(
0
).
valid
&&
!
io
.
commits
(
0
).
bits
.
isWalk
io
.
commitRoqIndex
.
valid
:=
state
===
s_idle
io
.
commitRoqIndex
.
bits
:=
deqPtrExt
+
commitOffset
// commit branch to brq
...
...
src/main/scala/xiangshan/cache/storeMissQueue.scala
浏览文件 @
0e8472d1
...
...
@@ -54,7 +54,7 @@ class StoreMissEntry extends DCacheModule
when
(
state
=/=
s_invalid
)
{
XSDebug
(
"entry: %d state: %d
\n"
,
io
.
id
,
state
)
XSDebug
(
"entry: %d state: %d
idx: %x tag: %x\n"
,
io
.
id
,
state
,
io
.
idx
.
bits
,
io
.
tag
.
bits
)
}
// --------------------------------------------
...
...
@@ -158,12 +158,13 @@ class StoreMissQueue extends DCacheModule
val
replay_arb
=
Module
(
new
Arbiter
(
new
DCacheLineReq
,
cfg
.
nStoreMissEntries
))
val
resp_arb
=
Module
(
new
Arbiter
(
new
DCacheLineResp
,
cfg
.
nStoreMissEntries
))
val
idx_matches
=
Wire
(
Vec
(
cfg
.
n
Load
MissEntries
,
Bool
()))
val
tag_matches
=
Wire
(
Vec
(
cfg
.
n
Load
MissEntries
,
Bool
()))
val
idx_matches
=
Wire
(
Vec
(
cfg
.
n
Store
MissEntries
,
Bool
()))
val
tag_matches
=
Wire
(
Vec
(
cfg
.
n
Store
MissEntries
,
Bool
()))
val
tag_match
=
Mux1H
(
idx_matches
,
tag_matches
)
val
idx_match
=
idx_matches
.
reduce
(
_
||
_
)
XSDebug
(
"idx_match: %b tag_match: %b\n"
,
idx_match
,
tag_match
)
val
req
=
io
.
lsu
.
req
val
entry_alloc_idx
=
Wire
(
UInt
())
...
...
src/test/csrc/difftest.cpp
浏览文件 @
0e8472d1
...
...
@@ -204,7 +204,7 @@ int difftest_step(DiffState *s) {
ds
.
exceptionNo
=
s
->
cause
;
ds
.
mtval
=
s
->
reg_scala
[
DIFFTEST_MTVAL
];
ds
.
stval
=
s
->
reg_scala
[
DIFFTEST_STVAL
];
ref_disambiguate_exec
(
&
s
->
cause
);
ref_disambiguate_exec
(
&
ds
);
}
else
{
ref_difftest_exec
(
1
);
}
...
...
src/test/scala/cache/L1plusCacheTest.scala
浏览文件 @
0e8472d1
...
...
@@ -201,21 +201,24 @@ class L1plusCacheTest extends FlatSpec with ChiselScalatestTester with Matchers
}
// emulated queue
class
IdPool
(
val
nReqIds
:
Int
)
{
class
IdPool
(
val
nReqIds
:
Int
,
name
:
String
)
{
val
freeIds
=
new
Array
[
Boolean
](
nReqIds
)
def
allocate
()
:
Int
=
{
for
(
i
<-
0
until
freeIds
.
size
)
{
if
(
freeIds
(
i
))
{
println
(
f
"$name allocate: $i"
)
freeIds
(
i
)
=
false
return
i
}
}
// no free id to allocate
println
(
f
"$name allocate failed"
)
return
-
1
}
def
free
(
id
:
Int
)
:
Unit
=
{
println
(
f
"$name free: $id"
)
assert
(!
freeIds
(
id
))
freeIds
(
id
)
=
true
}
...
...
@@ -248,7 +251,7 @@ case class QueueEntry(
class
Queue
(
nEntries
:
Int
,
name
:
String
)
{
// Queue
// ---------------------------------------
val
idPool
=
new
IdPool
(
nEntries
)
val
idPool
=
new
IdPool
(
nEntries
,
name
+
"IdPool"
)
val
queue
=
new
ArrayBuffer
[
QueueEntry
]()
def
enq
(
req
:
Req
)
=
{
// for unissued reqs, they have id = -1
...
...
@@ -313,48 +316,51 @@ class StoreQueue(nEntries: Int) extends Queue(nEntries, "StoreQueue") {
def
sendReq
(
port
:
DCacheLineIO
)
:
Unit
=
{
val
req
=
port
.
req
// has last cycle's req been fired?
if
(
reqWaiting
&&
req
.
ready
.
peek
().
litToBoolean
)
{
reqWaiting
=
false
// no requests waiting on line
// reset valid signal
req
.
valid
.
poke
(
false
.
B
)
}
// can we send a new request in this cycle
val
reqIdx
=
select
()
if
(
reqWaiting
||
reqIdx
==
-
1
)
{
return
}
if
(!
reqWaiting
)
{
val
reqIdx
=
select
()
if
(
reqIdx
==
-
1
)
{
// no more request to send
req
.
valid
.
poke
(
false
.
B
)
return
}
val
tId
=
idPool
.
allocate
()
if
(
tId
==
-
1
)
{
return
val
tId
=
idPool
.
allocate
()
if
(
tId
==
-
1
)
{
// no more request to send
req
.
valid
.
poke
(
false
.
B
)
return
}
// try sending a new request in this cycle
// select a req to issue
reqWaiting
=
true
issue
(
reqIdx
,
tId
)
val
CMD_WRITE
=
MemoryOpConstants
.
M_XWR
val
FULL_MASK
=
BigInt
(
"ffffffffffffffff"
,
16
).
U
val
r
=
queue
(
reqIdx
).
req
req
.
valid
.
poke
(
true
.
B
)
req
.
bits
.
cmd
.
poke
(
CMD_WRITE
)
req
.
bits
.
addr
.
poke
(
r
.
addr
.
U
)
req
.
bits
.
data
.
poke
(
r
.
data
.
U
)
req
.
bits
.
mask
.
poke
(
FULL_MASK
)
req
.
bits
.
meta
.
id
.
poke
(
tId
.
U
)
req
.
bits
.
meta
.
vaddr
.
poke
(
r
.
addr
.
U
)
req
.
bits
.
meta
.
paddr
.
poke
(
r
.
addr
.
U
)
// req.bits.meta.uop.poke(0.U.asTypeOf(new MicroOp))
req
.
bits
.
meta
.
mmio
.
poke
(
false
.
B
)
req
.
bits
.
meta
.
tlb_miss
.
poke
(
false
.
B
)
req
.
bits
.
meta
.
mask
.
poke
(
FULL_MASK
)
req
.
bits
.
meta
.
replay
.
poke
(
false
.
B
)
}
// try sending a new request in this cycle
// select a req to issue
reqWaiting
=
true
issue
(
reqIdx
,
tId
)
val
CMD_WRITE
=
MemoryOpConstants
.
M_XWR
val
FULL_MASK
=
BigInt
(
"ffffffffffffffff"
,
16
).
U
val
r
=
queue
(
reqIdx
).
req
req
.
valid
.
poke
(
true
.
B
)
req
.
bits
.
cmd
.
poke
(
CMD_WRITE
)
req
.
bits
.
addr
.
poke
(
r
.
addr
.
U
)
req
.
bits
.
data
.
poke
(
r
.
data
.
U
)
req
.
bits
.
mask
.
poke
(
FULL_MASK
)
req
.
bits
.
meta
.
id
.
poke
(
tId
.
U
)
req
.
bits
.
meta
.
vaddr
.
poke
(
r
.
addr
.
U
)
req
.
bits
.
meta
.
paddr
.
poke
(
r
.
addr
.
U
)
// req.bits.meta.uop.poke(0.U.asTypeOf(new MicroOp))
req
.
bits
.
meta
.
mmio
.
poke
(
false
.
B
)
req
.
bits
.
meta
.
tlb_miss
.
poke
(
false
.
B
)
req
.
bits
.
meta
.
mask
.
poke
(
FULL_MASK
)
req
.
bits
.
meta
.
replay
.
poke
(
false
.
B
)
if
(
req
.
valid
.
peek
().
litToBoolean
&&
req
.
ready
.
peek
().
litToBoolean
)
{
reqWaiting
=
false
}
}
def
handleResp
(
port
:
DCacheLineIO
)
=
{
...
...
@@ -380,37 +386,40 @@ class LoadQueue(nEntries: Int) extends Queue(nEntries, "LoadQueue") {
def
sendReq
(
port
:
L1plusCacheIO
)
:
Unit
=
{
val
req
=
port
.
req
// has last cycle's req been fired?
if
(
reqWaiting
&&
req
.
ready
.
peek
().
litToBoolean
)
{
reqWaiting
=
false
// no requests waiting on line
// reset valid signal
req
.
valid
.
poke
(
false
.
B
)
}
// can we send a new request in this cycle
val
reqIdx
=
select
()
if
(
reqWaiting
||
reqIdx
==
-
1
)
{
return
}
if
(!
reqWaiting
)
{
val
reqIdx
=
select
()
if
(
reqIdx
==
-
1
)
{
// no more request to send
req
.
valid
.
poke
(
false
.
B
)
return
}
val
tId
=
idPool
.
allocate
()
if
(
tId
==
-
1
)
{
return
}
val
tId
=
idPool
.
allocate
()
if
(
tId
==
-
1
)
{
// no more request to send
req
.
valid
.
poke
(
false
.
B
)
return
}
// try sending a new request in this cycle
// select a req to issue
// try sending a new request in this cycl
e
// select a req to issue
reqWaiting
=
tru
e
issue
(
reqIdx
,
tId
)
reqWaiting
=
true
issue
(
reqIdx
,
tId
)
val
CMD_READ
=
MemoryOpConstants
.
M_XRD
val
CMD_READ
=
MemoryOpConstants
.
M_XRD
val
r
=
queue
(
reqIdx
).
req
req
.
valid
.
poke
(
true
.
B
)
req
.
bits
.
cmd
.
poke
(
CMD_READ
)
req
.
bits
.
addr
.
poke
(
r
.
addr
.
U
)
req
.
bits
.
id
.
poke
(
tId
.
U
)
}
val
r
=
queue
(
reqIdx
).
req
req
.
valid
.
poke
(
true
.
B
)
req
.
bits
.
cmd
.
poke
(
CMD_READ
)
req
.
bits
.
addr
.
poke
(
r
.
addr
.
U
)
req
.
bits
.
id
.
poke
(
tId
.
U
)
if
(
req
.
valid
.
peek
().
litToBoolean
&&
req
.
ready
.
peek
().
litToBoolean
)
{
reqWaiting
=
false
}
}
def
handleResp
(
port
:
L1plusCacheIO
)
=
{
...
...
src/test/scala/cache/L2CacheNonInclusiveGetTest.scala
0 → 100644
浏览文件 @
0e8472d1
package
cache
import
scala.collection.mutable.ArrayBuffer
import
chipsalliance.rocketchip.config.
{
Field
,
Parameters
}
import
chisel3._
import
chisel3.util._
import
chiseltest.experimental.TestOptionBuilder._
import
chiseltest.internal.VerilatorBackendAnnotation
import
chiseltest._
import
chisel3.experimental.BundleLiterals._
import
firrtl.stage.RunFirrtlTransformAnnotation
import
chiseltest.ChiselScalatestTester
import
device.AXI4RAM
import
freechips.rocketchip.amba.axi4.AXI4UserYanker
import
freechips.rocketchip.diplomacy.
{
AddressSet
,
LazyModule
,
LazyModuleImp
}
import
freechips.rocketchip.tilelink.
{
TLBuffer
,
TLCacheCork
,
TLToAXI4
,
TLXbar
}
import
org.scalatest.
{
FlatSpec
,
Matchers
}
import
sifive.blocks.inclusivecache.
{
CacheParameters
,
InclusiveCache
,
InclusiveCacheMicroParameters
,
InclusiveCacheControlParameters
}
import
utils.
{
DebugIdentityNode
,
HoldUnless
,
XSDebug
}
import
xiangshan.
{
HasXSLog
,
MicroOp
}
import
xiangshan.cache.
{
DCache
,
L1plusCache
,
Uncache
,
DCacheWordIO
,
DCacheLineIO
,
L1plusCacheIO
,
MemoryOpConstants
}
import
xiangshan.testutils.AddSinks
import
xstransforms.PrintModuleName
import
scala.util.Random
class
L2NonInclusiveGetTestTopIO
extends
Bundle
{
val
l1plus
=
new
L1plusCacheIO
()
val
dcacheStore
=
new
DCacheLineIO
()
val
l2Flush
=
new
DCacheWordIO
}
class
L2NonInclusiveGetTestTop
()(
implicit
p
:
Parameters
)
extends
LazyModule
{
val
uncache
=
LazyModule
(
new
Uncache
())
val
dcache
=
LazyModule
(
new
DCache
())
val
l1plusCache
=
LazyModule
(
new
L1plusCache
())
val
l2
=
LazyModule
(
new
InclusiveCache
(
CacheParameters
(
level
=
2
,
ways
=
4
,
sets
=
4
*
1024
/
(
64
*
4
*
4
),
blockBytes
=
64
,
beatBytes
=
32
,
cacheName
=
s
"L2"
),
InclusiveCacheMicroParameters
(
writeBytes
=
8
),
Some
(
InclusiveCacheControlParameters
(
address
=
0x8000000
L
,
beatBytes
=
8
))))
val
ram
=
LazyModule
(
new
AXI4RAM
(
AddressSet
(
0x0
L
,
0x7ffffff
L
),
memByte
=
128
*
1024
*
1024
,
useBlackBox
=
false
))
val
xbar
=
TLXbar
()
xbar
:=
TLBuffer
()
:=
DebugIdentityNode
()
:=
dcache
.
clientNode
xbar
:=
TLBuffer
()
:=
DebugIdentityNode
()
:=
l1plusCache
.
clientNode
l2
.
node
:=
DebugIdentityNode
()
:=
xbar
ram
.
node
:=
AXI4UserYanker
()
:=
TLToAXI4
()
:=
TLBuffer
()
:=
TLCacheCork
()
:=
DebugIdentityNode
()
:=
l2
.
node
// connect uncache access to l2 control node
l2
.
ctlnode
.
get
:=
DebugIdentityNode
()
:=
uncache
.
clientNode
lazy
val
module
=
new
LazyModuleImp
(
this
)
with
HasXSLog
{
val
io
=
IO
(
Flipped
(
new
L2NonInclusiveGetTestTopIO
))
AddSinks
()
dcache
.
module
.
io
<>
DontCare
dcache
.
module
.
io
.
lsu
.
store
<>
io
.
dcacheStore
l1plusCache
.
module
.
io
<>
io
.
l1plus
uncache
.
module
.
io
.
lsroq
<>
io
.
l2Flush
}
}
class
L2NonInclusiveGetTest
extends
FlatSpec
with
ChiselScalatestTester
with
Matchers
{
behavior
of
"L2Cache"
val
mem_size
=
128
*
1024
*
1024
val
block_size
=
64
val
block_bits
=
log2Up
(
block_size
)
// val nblocks = mem_size / block_size
val
nblocks
=
100
// data structures
// our golden version cache
val
cache_blocks
=
new
Array
[
BigInt
](
nblocks
)
for
(
i
<-
0
until
nblocks
)
{
cache_blocks
(
i
)
=
BigInt
(
0
)
}
// ----------------------------------------
// useful request parameter values
val
CMD_READ
=
MemoryOpConstants
.
M_XRD
val
CMD_WRITE
=
MemoryOpConstants
.
M_XWR
// 64bit full mask
val
FULL_MASK_64
=
BigInt
(
"ffffffffffffffff"
,
16
).
U
val
L2_FLUSH_BASE_ADDR
=
0x8000000
L
val
CONFIG_ADDR
=
L2_FLUSH_BASE_ADDR
+
0x0
val
FLUSH64_ADDR
=
L2_FLUSH_BASE_ADDR
+
0x200
val
FLUSH32_ADDR
=
L2_FLUSH_BASE_ADDR
+
0x240
val
r
=
scala
.
util
.
Random
top
.
Parameters
.
set
(
top
.
Parameters
.
debugParameters
)
val
annos
=
Seq
(
VerilatorBackendAnnotation
,
RunFirrtlTransformAnnotation
(
new
PrintModuleName
)
)
it
should
"run"
in
{
implicit
val
p
=
Parameters
((
site
,
up
,
here
)
=>
{
case
L1plusCacheTestKey
=>
0
})
test
(
LazyModule
(
new
L2NonInclusiveGetTestTop
()).
module
)
.
withAnnotations
(
annos
){
c
=>
c
.
clock
.
step
(
100
)
val
sq
=
new
StoreQueue
(
8
)
val
lq
=
new
LoadQueue
(
8
)
def
init
()
=
{
sq
.
init
()
lq
.
init
()
// initialize DUT inputs
c
.
io
.
dcacheStore
.
req
.
valid
.
poke
(
false
.
B
)
c
.
io
.
dcacheStore
.
resp
.
ready
.
poke
(
false
.
B
)
c
.
io
.
l1plus
.
req
.
valid
.
poke
(
false
.
B
)
c
.
io
.
l1plus
.
resp
.
ready
.
poke
(
false
.
B
)
c
.
io
.
l1plus
.
flush
.
poke
(
false
.
B
)
c
.
io
.
l2Flush
.
req
.
valid
.
poke
(
false
.
B
)
c
.
io
.
l2Flush
.
resp
.
ready
.
poke
(
false
.
B
)
}
def
mmio_read
(
addr
:
BigInt
)
:
BigInt
=
{
// send req
val
req
=
c
.
io
.
l2Flush
.
req
req
.
valid
.
poke
(
true
.
B
)
req
.
bits
.
cmd
.
poke
(
CMD_READ
)
req
.
bits
.
addr
.
poke
(
addr
.
U
)
req
.
bits
.
data
.
poke
(
0.
U
)
req
.
bits
.
mask
.
poke
(
FULL_MASK_64
)
req
.
bits
.
meta
.
id
.
poke
(
0.
U
)
req
.
bits
.
meta
.
vaddr
.
poke
(
addr
.
U
)
req
.
bits
.
meta
.
paddr
.
poke
(
addr
.
U
)
// req.bits.meta.uop.poke(0.U.asTypeOf(new MicroOp))
req
.
bits
.
meta
.
mmio
.
poke
(
true
.
B
)
req
.
bits
.
meta
.
tlb_miss
.
poke
(
false
.
B
)
req
.
bits
.
meta
.
mask
.
poke
(
FULL_MASK_64
)
req
.
bits
.
meta
.
replay
.
poke
(
false
.
B
)
while
(!
req
.
ready
.
peek
().
litToBoolean
)
{
c
.
clock
.
step
()
}
// actually send the req
c
.
clock
.
step
()
// lower valid
req
.
valid
.
poke
(
false
.
B
)
// recv resp
val
resp
=
c
.
io
.
l2Flush
.
resp
resp
.
ready
.
poke
(
true
.
B
)
while
(!
resp
.
valid
.
peek
().
litToBoolean
)
{
c
.
clock
.
step
()
}
val
data
=
resp
.
bits
.
data
.
peek
().
litValue
// actually recv the response
c
.
clock
.
step
()
// lower ready
resp
.
ready
.
poke
(
false
.
B
)
return
data
}
def
mmio_write
(
addr
:
BigInt
,
data
:
BigInt
)
=
{
// send req
val
req
=
c
.
io
.
l2Flush
.
req
req
.
valid
.
poke
(
true
.
B
)
req
.
bits
.
cmd
.
poke
(
CMD_WRITE
)
req
.
bits
.
addr
.
poke
(
addr
.
U
)
req
.
bits
.
data
.
poke
(
data
.
U
)
req
.
bits
.
mask
.
poke
(
FULL_MASK_64
)
req
.
bits
.
meta
.
id
.
poke
(
0.
U
)
req
.
bits
.
meta
.
vaddr
.
poke
(
addr
.
U
)
req
.
bits
.
meta
.
paddr
.
poke
(
addr
.
U
)
// req.bits.meta.uop.poke(0.U.asTypeOf(new MicroOp))
req
.
bits
.
meta
.
mmio
.
poke
(
true
.
B
)
req
.
bits
.
meta
.
tlb_miss
.
poke
(
false
.
B
)
req
.
bits
.
meta
.
mask
.
poke
(
FULL_MASK_64
)
req
.
bits
.
meta
.
replay
.
poke
(
false
.
B
)
while
(!
req
.
ready
.
peek
().
litToBoolean
)
{
c
.
clock
.
step
()
}
// actually send the req
c
.
clock
.
step
()
// lower valid
req
.
valid
.
poke
(
false
.
B
)
// recv resp
val
resp
=
c
.
io
.
l2Flush
.
resp
resp
.
ready
.
poke
(
true
.
B
)
while
(!
resp
.
valid
.
peek
().
litToBoolean
)
{
c
.
clock
.
step
()
}
// actually recv the response
c
.
clock
.
step
()
// lower ready
resp
.
ready
.
poke
(
false
.
B
)
}
def
get_l2_configurations
()
=
{
val
config
=
mmio_read
(
CONFIG_ADDR
)
val
nBank
=
config
&
0xf
val
nWay
=
config
>>
8
&
0xf
val
nSet
=
1
<<
(
config
.
toInt
>>
16
&
0xf
)
val
nBlock
=
1
<<
(
config
.
toInt
>>
24
&
0xf
)
println
(
f
"L2 configuration: nBank: $nBank nWay: $nWay nSet: $nSet nBlock: $nBlock"
)
}
def
flush_l2_block
(
addr
:
BigInt
)
=
{
mmio_write
(
FLUSH64_ADDR
,
addr
)
println
(
f
"L2 flush block: $addr%x"
)
}
def
flush_l1plus
()
=
{
c
.
io
.
l1plus
.
flush
.
poke
(
true
.
B
)
while
(!
c
.
io
.
l1plus
.
empty
.
peek
().
litToBoolean
)
{
c
.
clock
.
step
()
}
c
.
io
.
l1plus
.
flush
.
poke
(
false
.
B
)
}
def
flush_l2_range
(
begin
:
BigInt
,
end
:
BigInt
)
=
{
var
addr
=
begin
>>
block_bits
<<
block_bits
while
(
addr
<
end
)
{
flush_l2_block
(
addr
)
addr
+=
block_size
}
}
def
evaluate
()
=
{
while
(!
sq
.
isFinished
()
||
!
lq
.
isFinished
())
{
sq
.
tick
(
c
.
io
.
dcacheStore
)
lq
.
tick
(
c
.
io
.
l1plus
)
c
.
clock
.
step
()
}
}
get_l2_configurations
()
// ----------------------------------------
// scan test
def
populate_memory
()
=
{
println
(
s
"scan test"
)
init
()
// first, initialize every memory block with random numbers
for
(
i
<-
0
until
nblocks
)
{
val
addr
=
i
*
64
val
words
=
(
0
until
8
)
map
{
_
=>
(
BigInt
(
r
.
nextLong
()
&
0x7fffffffffffffff
L
))
}
val
data
=
words
.
foldLeft
(
BigInt
(
0
))((
sum
,
i
)
=>
sum
<<
64
|
i
)
cache_blocks
(
i
)
=
data
println
(
f
"enq store addr: $addr%x data: $data%x"
)
sq
.
enq
(
Req
(
addr
,
data
))
}
// execute reqs
evaluate
()
}
def
flush_memory
()
=
{
flush_l2_range
(
0
,
(
nblocks
-
1
)*
block_size
)
}
def
read_memory
()
=
{
// read them out
for
(
i
<-
0
until
nblocks
)
{
val
addr
=
i
*
64
val
data
=
cache_blocks
(
i
)
println
(
f
"enq load addr: $addr%x data: $data%x"
)
lq
.
enq
(
Req
(
addr
,
data
))
}
// execute reqs
evaluate
()
}
for
(
i
<-
0
until
10
)
{
populate_memory
()
flush_memory
()
// these loads should cause get miss
flush_l1plus
()
read_memory
()
populate_memory
()
// these loads should not miss
flush_l1plus
()
read_memory
()
}
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录