Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenXiangShan
XiangShan
提交
51f54365
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,发现更多精彩内容 >>
提交
51f54365
编写于
1月 24, 2021
作者:
Z
zoujr
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' into perf-debug
上级
19d3028e
fe5d272d
变更
73
展开全部
显示空白变更内容
内联
并排
Showing
73 changed file
with
2324 addition
and
1205 deletion
+2324
-1205
.github/workflows/emu.yml
.github/workflows/emu.yml
+5
-5
Makefile
Makefile
+9
-10
block-inclusivecache-sifive
block-inclusivecache-sifive
+1
-1
debug/Makefile
debug/Makefile
+1
-1
debug/env.sh
debug/env.sh
+2
-0
scripts/utils/lock-emu.c
scripts/utils/lock-emu.c
+3
-1
src/main/scala/device/AXI4Flash.scala
src/main/scala/device/AXI4Flash.scala
+6
-4
src/main/scala/system/SoC.scala
src/main/scala/system/SoC.scala
+6
-4
src/main/scala/top/XiangShanStage.scala
src/main/scala/top/XiangShanStage.scala
+3
-1
src/main/scala/utils/DataDontCareNode.scala
src/main/scala/utils/DataDontCareNode.scala
+44
-0
src/main/scala/utils/ExcitingUtils.scala
src/main/scala/utils/ExcitingUtils.scala
+14
-5
src/main/scala/utils/SRAMTemplate.scala
src/main/scala/utils/SRAMTemplate.scala
+16
-8
src/main/scala/xiangshan/Bundle.scala
src/main/scala/xiangshan/Bundle.scala
+1
-1
src/main/scala/xiangshan/PMA.scala
src/main/scala/xiangshan/PMA.scala
+117
-0
src/main/scala/xiangshan/XSCore.scala
src/main/scala/xiangshan/XSCore.scala
+71
-43
src/main/scala/xiangshan/backend/CtrlBlock.scala
src/main/scala/xiangshan/backend/CtrlBlock.scala
+4
-6
src/main/scala/xiangshan/backend/FloatBlock.scala
src/main/scala/xiangshan/backend/FloatBlock.scala
+1
-1
src/main/scala/xiangshan/backend/IntegerBlock.scala
src/main/scala/xiangshan/backend/IntegerBlock.scala
+2
-2
src/main/scala/xiangshan/backend/MemBlock.scala
src/main/scala/xiangshan/backend/MemBlock.scala
+1
-0
src/main/scala/xiangshan/backend/brq/Brq.scala
src/main/scala/xiangshan/backend/brq/Brq.scala
+16
-7
src/main/scala/xiangshan/backend/decode/DecodeStage.scala
src/main/scala/xiangshan/backend/decode/DecodeStage.scala
+7
-4
src/main/scala/xiangshan/backend/decode/DecodeUnit.scala
src/main/scala/xiangshan/backend/decode/DecodeUnit.scala
+5
-35
src/main/scala/xiangshan/backend/decode/FPDecoder.scala
src/main/scala/xiangshan/backend/decode/FPDecoder.scala
+1
-1
src/main/scala/xiangshan/backend/dispatch/Dispatch.scala
src/main/scala/xiangshan/backend/dispatch/Dispatch.scala
+10
-10
src/main/scala/xiangshan/backend/dispatch/Dispatch1.scala
src/main/scala/xiangshan/backend/dispatch/Dispatch1.scala
+10
-5
src/main/scala/xiangshan/backend/dispatch/Dispatch2Fp.scala
src/main/scala/xiangshan/backend/dispatch/Dispatch2Fp.scala
+18
-11
src/main/scala/xiangshan/backend/dispatch/Dispatch2Int.scala
src/main/scala/xiangshan/backend/dispatch/Dispatch2Int.scala
+15
-8
src/main/scala/xiangshan/backend/dispatch/Dispatch2Ls.scala
src/main/scala/xiangshan/backend/dispatch/Dispatch2Ls.scala
+16
-10
src/main/scala/xiangshan/backend/exu/Exu.scala
src/main/scala/xiangshan/backend/exu/Exu.scala
+16
-8
src/main/scala/xiangshan/backend/exu/FmiscExeUnit.scala
src/main/scala/xiangshan/backend/exu/FmiscExeUnit.scala
+2
-2
src/main/scala/xiangshan/backend/exu/Wb.scala
src/main/scala/xiangshan/backend/exu/Wb.scala
+15
-9
src/main/scala/xiangshan/backend/fu/CSR.scala
src/main/scala/xiangshan/backend/fu/CSR.scala
+97
-30
src/main/scala/xiangshan/backend/fu/Fence.scala
src/main/scala/xiangshan/backend/fu/Fence.scala
+35
-25
src/main/scala/xiangshan/backend/fu/Jump.scala
src/main/scala/xiangshan/backend/fu/Jump.scala
+8
-5
src/main/scala/xiangshan/backend/fu/Radix2Divider.scala
src/main/scala/xiangshan/backend/fu/Radix2Divider.scala
+2
-2
src/main/scala/xiangshan/backend/fu/SRT4Divider.scala
src/main/scala/xiangshan/backend/fu/SRT4Divider.scala
+4
-2
src/main/scala/xiangshan/backend/fu/fpu/FDivSqrt.scala
src/main/scala/xiangshan/backend/fu/fpu/FDivSqrt.scala
+2
-2
src/main/scala/xiangshan/backend/fu/fpu/FPToFP.scala
src/main/scala/xiangshan/backend/fu/fpu/FPToFP.scala
+11
-14
src/main/scala/xiangshan/backend/fu/fpu/FPToInt.scala
src/main/scala/xiangshan/backend/fu/fpu/FPToInt.scala
+32
-33
src/main/scala/xiangshan/backend/fu/util/CSRConst.scala
src/main/scala/xiangshan/backend/fu/util/CSRConst.scala
+5
-0
src/main/scala/xiangshan/backend/issue/ReservationStationNew.scala
...scala/xiangshan/backend/issue/ReservationStationNew.scala
+142
-118
src/main/scala/xiangshan/backend/package.scala
src/main/scala/xiangshan/backend/package.scala
+5
-4
src/main/scala/xiangshan/backend/regfile/Regfile.scala
src/main/scala/xiangshan/backend/regfile/Regfile.scala
+2
-3
src/main/scala/xiangshan/backend/rename/BusyTable.scala
src/main/scala/xiangshan/backend/rename/BusyTable.scala
+7
-20
src/main/scala/xiangshan/backend/roq/Roq.scala
src/main/scala/xiangshan/backend/roq/Roq.scala
+68
-48
src/main/scala/xiangshan/cache/InstrUncache.scala
src/main/scala/xiangshan/cache/InstrUncache.scala
+206
-0
src/main/scala/xiangshan/cache/L1plusCache.scala
src/main/scala/xiangshan/cache/L1plusCache.scala
+26
-14
src/main/scala/xiangshan/cache/dcache.scala
src/main/scala/xiangshan/cache/dcache.scala
+10
-3
src/main/scala/xiangshan/cache/dtlb.scala
src/main/scala/xiangshan/cache/dtlb.scala
+206
-204
src/main/scala/xiangshan/cache/icache.scala
src/main/scala/xiangshan/cache/icache.scala
+208
-103
src/main/scala/xiangshan/cache/icacheMissQueue.scala
src/main/scala/xiangshan/cache/icacheMissQueue.scala
+3
-3
src/main/scala/xiangshan/cache/missQueue.scala
src/main/scala/xiangshan/cache/missQueue.scala
+2
-2
src/main/scala/xiangshan/cache/prefetch/BestOffsetPrefetch.scala
...n/scala/xiangshan/cache/prefetch/BestOffsetPrefetch.scala
+223
-49
src/main/scala/xiangshan/cache/prefetch/L2Prefetcher.scala
src/main/scala/xiangshan/cache/prefetch/L2Prefetcher.scala
+75
-40
src/main/scala/xiangshan/cache/prefetch/Prefetcher.scala
src/main/scala/xiangshan/cache/prefetch/Prefetcher.scala
+5
-5
src/main/scala/xiangshan/cache/prefetch/StreamPrefetch.scala
src/main/scala/xiangshan/cache/prefetch/StreamPrefetch.scala
+36
-19
src/main/scala/xiangshan/cache/ptw.scala
src/main/scala/xiangshan/cache/ptw.scala
+147
-21
src/main/scala/xiangshan/frontend/Frontend.scala
src/main/scala/xiangshan/frontend/Frontend.scala
+22
-2
src/main/scala/xiangshan/frontend/IFU.scala
src/main/scala/xiangshan/frontend/IFU.scala
+26
-3
src/main/scala/xiangshan/frontend/PreDecode.scala
src/main/scala/xiangshan/frontend/PreDecode.scala
+14
-0
src/main/scala/xiangshan/frontend/Tage.scala
src/main/scala/xiangshan/frontend/Tage.scala
+14
-2
src/main/scala/xiangshan/mem/Memend.scala
src/main/scala/xiangshan/mem/Memend.scala
+0
-1
src/main/scala/xiangshan/mem/lsqueue/LSQWrapper.scala
src/main/scala/xiangshan/mem/lsqueue/LSQWrapper.scala
+3
-0
src/main/scala/xiangshan/mem/lsqueue/LoadQueue.scala
src/main/scala/xiangshan/mem/lsqueue/LoadQueue.scala
+100
-148
src/main/scala/xiangshan/mem/lsqueue/LoadQueueData.scala
src/main/scala/xiangshan/mem/lsqueue/LoadQueueData.scala
+4
-14
src/main/scala/xiangshan/mem/lsqueue/StoreQueue.scala
src/main/scala/xiangshan/mem/lsqueue/StoreQueue.scala
+30
-31
src/main/scala/xiangshan/mem/lsqueue/StoreQueueData.scala
src/main/scala/xiangshan/mem/lsqueue/StoreQueueData.scala
+1
-1
src/main/scala/xiangshan/mem/pipeline/AtomicsUnit.scala
src/main/scala/xiangshan/mem/pipeline/AtomicsUnit.scala
+16
-7
src/main/scala/xiangshan/mem/pipeline/LoadUnit.scala
src/main/scala/xiangshan/mem/pipeline/LoadUnit.scala
+13
-8
src/main/scala/xiangshan/mem/pipeline/StoreUnit.scala
src/main/scala/xiangshan/mem/pipeline/StoreUnit.scala
+19
-3
src/main/scala/xiangshan/mem/sbuffer/NewSbuffer.scala
src/main/scala/xiangshan/mem/sbuffer/NewSbuffer.scala
+4
-3
src/main/scala/xiangshan/package.scala
src/main/scala/xiangshan/package.scala
+43
-2
src/test/csrc/ram.cpp
src/test/csrc/ram.cpp
+10
-8
未找到文件。
.github/workflows/emu.yml
浏览文件 @
51f54365
...
...
@@ -39,7 +39,7 @@ jobs:
echo "AM_HOME=/home/ci-runner/xsenv/nexus-am" >> $GITHUB_ENV
-
name
:
Build EMU
run
:
make ./build/emu SIM_ARGS=--disable-
all NEMU_HOME=$NEMU_HOME NOOP_HOME=$NOOP_HOME
-j220
make ./build/emu SIM_ARGS=--disable-
log NEMU_HOME=$NEMU_HOME NOOP_HOME=$NOOP_HOME B=0 E=0
-j220
-
name
:
Run cputest
run
:
|
CPU_TEST_DIR=$AM_HOME/tests/cputest
...
...
@@ -49,7 +49,7 @@ jobs:
do
t=${test%.c}
echo $t
make -C $CPU_TEST_DIR ALL=$t ARCH=riscv64-noop AM_HOME=$AM_HOME NEMU_HOME=$NEMU_HOME NOOP_HOME=$NOOP_HOME run
2>/dev/null
| grep "HIT GOOD TRAP"
make -C $CPU_TEST_DIR ALL=$t ARCH=riscv64-noop AM_HOME=$AM_HOME NEMU_HOME=$NEMU_HOME NOOP_HOME=$NOOP_HOME run
B=0 E=0
| grep "HIT GOOD TRAP"
if [[ $? != 0 ]];
then
echo $t fail
...
...
@@ -59,10 +59,10 @@ jobs:
exit $ret
-
name
:
Run riscv-tests
run
:
|
make -C $RVTEST_HOME/isa/ SUITES+=rv64ui SUITES+=rv64um SUITES+=rv64ua SUITES+=rv64uf SUITES+=rv64ud NEMU_HOME=$NEMU_HOME NOOP_HOME=$NOOP_HOME noop_run
2> /dev/null
make -C $RVTEST_HOME/isa/ SUITES+=rv64ui SUITES+=rv64um SUITES+=rv64ua SUITES+=rv64uf SUITES+=rv64ud NEMU_HOME=$NEMU_HOME NOOP_HOME=$NOOP_HOME noop_run
B=0 E=0
-
name
:
Run microbench
run
:
|
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
B=0 E=0
-
name
:
Run coremark
run
:
|
make -C $AM_HOME/apps/coremark ARCH=riscv64-noop AM_HOME=$AM_HOME NEMU_HOME=$NEMU_HOME NOOP_HOME=$NOOP_HOME run
2> /dev/null
make -C $AM_HOME/apps/coremark ARCH=riscv64-noop AM_HOME=$AM_HOME NEMU_HOME=$NEMU_HOME NOOP_HOME=$NOOP_HOME run
B=0 E=0
Makefile
浏览文件 @
51f54365
...
...
@@ -27,17 +27,16 @@ help:
$(TOP_V)
:
$(SCALA_FILE)
mkdir
-p
$
(
@D
)
mill XiangShan.test.runMain
$(SIMTOP)
-X
verilog
-td
$
(
@D
)
--full-stacktrace
--output-file
$
(
@F
)
--disable-all
--fpga-platform
--remove-assert
$(SIM_ARGS)
# mill XiangShan.runMain top.
$(TOP)
-X
verilog
-td
$
(
@D
)
--output-file
$
(
@F
)
--infer-rw
$(FPGATOP)
--repl-seq-mem
-c
:
$(FPGATOP)
:-o:
$
(
@D
)
/
$
(
@F
)
.conf
#
$(MEM_GEN)
$
(
@D
)
/
$
(
@F
)
.conf
>>
$@
mill XiangShan.test.runMain
$(SIMTOP)
-td
$
(
@D
)
--full-stacktrace
--output-file
$
(
@F
)
--disable-all
--fpga-platform
--remove-assert
--infer-rw
--repl-seq-mem
-c
:
$(SIMTOP)
:-o:
$
(
@D
)
/
$
(
@F
)
.conf
$(SIM_ARGS)
$(MEM_GEN)
$
(
@D
)
/
$
(
@F
)
.conf
>>
$@
# sed -i -e 's/_
\(
aw
\|
ar
\|
w
\|
r
\|
b
\)
_
\(\|
bits_
\)
/_
\1
/g
' $@
#
@git log -n 1 >> .__head__
#
@git diff >> .__diff__
#
@sed -i '
s/^/
\/\/
/
' .__head__
#
@sed -i '
s/^/
\/\/
/
' .__diff__
#
@cat .__head__ .__diff__ $@ > .__out__
#
@mv .__out__ $@
#
@rm .__head__ .__diff__
@
git log -n 1 >> .__head__
@
git diff >> .__diff__
@
sed -i '
s/^/
\/\/
/
' .__head__
@
sed -i '
s/^/
\/\/
/
' .__diff__
@
cat .__head__ .__diff__ $@ > .__out__
@
mv .__out__ $@
@
rm .__head__ .__diff__
deploy
:
build/top.zip
...
...
block-inclusivecache-sifive
@
cf429e42
比较
ab2a8e8a
...
cf429e42
Subproject commit
ab2a8e8afd162b601d9f749e6e6af452cccc03a7
Subproject commit
cf429e420be6702a2e24b9b91910366187c103b4
debug/Makefile
浏览文件 @
51f54365
...
...
@@ -3,7 +3,7 @@ NANOS_HOME ?= $(AM_HOME)/../nanos-lite
SINGLETEST
=
ALL
=
min3
B
?=
0
E
?=
0
E
?=
-1
V
?=
OFF
#V ?= OFF
EMU_ARGS
=
B
=
$(B)
E
=
$(E)
V
=
$(V)
...
...
debug/env.sh
0 → 100644
浏览文件 @
51f54365
export
NOOP_HOME
=
$(
pwd
)
/..
echo
$NOOP_HOME
scripts/utils/lock-emu.c
浏览文件 @
51f54365
...
...
@@ -23,7 +23,9 @@ int main(int argc, char* argv[]){
fd
=
tryLock
(
argv
[
1
]);
if
(
fd
>
0
){
getlogin_r
(
user
,
BUF_SIZE
);
write
(
fd
,
user
,
strlen
(
user
));
int
len
=
strlen
(
user
);
user
[
len
]
=
'\0'
;
write
(
fd
,
user
,
len
+
1
);
break
;
}
else
{
// someone is holding the lock...
...
...
src/main/scala/device/AXI4Flash.scala
浏览文件 @
51f54365
...
...
@@ -25,10 +25,12 @@ class AXI4Flash
)
def
getOffset
(
addr
:
UInt
)
=
addr
(
12
,
0
)
val
rdata
=
Wire
(
UInt
(
64.
W
))
RegMap
.
generate
(
mapping
,
getOffset
(
raddr
),
rdata
,
val
rdata
=
Wire
(
Vec
(
2
,
UInt
(
32.
W
)))
(
0
until
2
).
map
{
i
=>
RegMap
.
generate
(
mapping
,
getOffset
(
raddr
+
(
i
*
4
).
U
),
rdata
(
i
),
getOffset
(
waddr
),
in
.
w
.
fire
(),
in
.
w
.
bits
.
data
,
MaskExpand
(
in
.
w
.
bits
.
strb
))
}
in
.
r
.
bits
.
data
:=
Fill
(
2
,
rdata
(
31
,
0
))
in
.
r
.
bits
.
data
:=
rdata
.
asUInt
}
}
src/main/scala/system/SoC.scala
浏览文件 @
51f54365
...
...
@@ -6,7 +6,7 @@ import chisel3._
import
chisel3.util._
import
freechips.rocketchip.diplomacy.
{
AddressSet
,
LazyModule
,
LazyModuleImp
}
import
freechips.rocketchip.tilelink.
{
BankBinder
,
TLBuffer
,
TLBundleParameters
,
TLCacheCork
,
TLClientNode
,
TLFilter
,
TLFuzzer
,
TLIdentityNode
,
TLToAXI4
,
TLWidthWidget
,
TLXbar
}
import
utils.
DebugIdentityNode
import
utils.
{
DebugIdentityNode
,
DataDontCareNode
}
import
utils.XSInfo
import
xiangshan.
{
HasXSParameter
,
XSCore
,
HasXSLog
}
import
sifive.blocks.inclusivecache.
{
CacheParameters
,
InclusiveCache
,
InclusiveCacheMicroParameters
}
...
...
@@ -61,7 +61,7 @@ class XSSoc()(implicit p: Parameters) extends LazyModule with HasSoCParameter {
cacheName
=
s
"L2"
),
InclusiveCacheMicroParameters
(
writeBytes
=
8
writeBytes
=
32
)
)))
...
...
@@ -79,7 +79,7 @@ class XSSoc()(implicit p: Parameters) extends LazyModule with HasSoCParameter {
cacheName
=
"L3"
),
InclusiveCacheMicroParameters
(
writeBytes
=
8
writeBytes
=
32
)
)).
node
...
...
@@ -101,7 +101,8 @@ class XSSoc()(implicit p: Parameters) extends LazyModule with HasSoCParameter {
l2_xbar
(
i
)
:=
TLBuffer
()
:=
DebugIdentityNode
()
:=
xs_core
(
i
).
ptw
.
node
l2_xbar
(
i
)
:=
TLBuffer
()
:=
DebugIdentityNode
()
:=
xs_core
(
i
).
l2Prefetcher
.
clientNode
mmioXbar
:=
TLBuffer
()
:=
DebugIdentityNode
()
:=
xs_core
(
i
).
memBlock
.
uncache
.
clientNode
l2cache
(
i
).
node
:=
TLBuffer
()
:=
DebugIdentityNode
()
:=
l2_xbar
(
i
)
mmioXbar
:=
TLBuffer
()
:=
DebugIdentityNode
()
:=
xs_core
(
i
).
frontend
.
instrUncache
.
clientNode
l2cache
(
i
).
node
:=
DataDontCareNode
(
a
=
true
,
b
=
true
)
:=
TLBuffer
()
:=
DebugIdentityNode
()
:=
l2_xbar
(
i
)
l3_xbar
:=
TLBuffer
()
:=
DebugIdentityNode
()
:=
l2cache
(
i
).
node
}
...
...
@@ -169,6 +170,7 @@ class XSSoc()(implicit p: Parameters) extends LazyModule with HasSoCParameter {
xs_core
(
i
).
module
.
io
.
externalInterrupt
.
msip
:=
clint
.
module
.
io
.
msip
(
i
)
// xs_core(i).module.io.externalInterrupt.meip := RegNext(RegNext(io.meip(i)))
xs_core
(
i
).
module
.
io
.
externalInterrupt
.
meip
:=
plic
.
module
.
io
.
extra
.
get
.
meip
(
i
)
xs_core
(
i
).
module
.
io
.
l2ToPrefetcher
<>
l2cache
(
i
).
module
.
io
}
// do not let dma AXI signals optimized out
chisel3
.
dontTouch
(
dma
.
out
.
head
.
_1
)
...
...
src/main/scala/top/XiangShanStage.scala
浏览文件 @
51f54365
...
...
@@ -5,6 +5,7 @@ import firrtl.AnnotationSeq
import
firrtl.annotations.NoTargetAnnotation
import
firrtl.options.
{
HasShellOptions
,
Shell
,
ShellOption
}
import
firrtl.stage.
{
FirrtlCli
,
RunFirrtlTransformAnnotation
}
import
freechips.rocketchip.transforms.naming.
{
OverrideDesiredNameAnnotation
,
RenameDesiredNames
}
import
xstransforms.ShowPrintTransform
import
xstransforms.PrintModuleName
...
...
@@ -93,7 +94,8 @@ object XiangShanStage {
args
,
annotations
++
Seq
(
RunFirrtlTransformAnnotation
(
new
ShowPrintTransform
),
RunFirrtlTransformAnnotation
(
new
PrintModuleName
)
RunFirrtlTransformAnnotation
(
new
PrintModuleName
),
RunFirrtlTransformAnnotation
(
new
RenameDesiredNames
)
)
)
}
...
...
src/main/scala/utils/DataDontCareNode.scala
0 → 100644
浏览文件 @
51f54365
package
utils
import
chisel3._
import
chipsalliance.rocketchip.config.Parameters
import
chisel3.util.DecoupledIO
import
freechips.rocketchip.diplomacy.
{
LazyModule
,
LazyModuleImp
}
import
freechips.rocketchip.tilelink.
{
TLBundle
,
TLClientNode
,
TLIdentityNode
,
TLMasterParameters
,
TLMasterPortParameters
}
import
xiangshan.HasXSLog
class
DataDontCareNode
(
a
:
Boolean
=
false
,
b
:
Boolean
=
false
,
c
:
Boolean
=
false
,
d
:
Boolean
=
false
)(
implicit
p
:
Parameters
)
extends
LazyModule
{
val
node
=
TLIdentityNode
()
val
n
=
TLClientNode
(
Seq
(
TLMasterPortParameters
.
v1
(
Seq
(
TLMasterParameters
.
v1
(
"DataDontCareNode"
)
)
)))
lazy
val
module
=
new
LazyModuleImp
(
this
)
with
HasXSLog
with
HasTLDump
{
val
(
out
,
_
)
=
node
.
out
(
0
)
val
(
in
,
_
)
=
node
.
in
(
0
)
if
(
a
)
{
out
.
a
.
bits
.
data
:=
DontCare
}
if
(
b
)
{
in
.
b
.
bits
.
data
:=
DontCare
}
if
(
c
)
{
out
.
c
.
bits
.
data
:=
DontCare
}
if
(
d
)
{
in
.
d
.
bits
.
data
:=
DontCare
}
}
}
object
DataDontCareNode
{
def
apply
(
a
:
Boolean
=
false
,
b
:
Boolean
=
false
,
c
:
Boolean
=
false
,
d
:
Boolean
=
false
)(
implicit
p
:
Parameters
)
:
TLIdentityNode
=
{
val
dataDontCareNode
=
LazyModule
(
new
DataDontCareNode
(
a
,
b
,
c
,
d
))
dataDontCareNode
.
node
}
}
src/main/scala/utils/ExcitingUtils.scala
浏览文件 @
51f54365
...
...
@@ -23,14 +23,15 @@ object ExcitingUtils {
(
var
connType
:
ConnectionType
,
var
sourceModule
:
Option
[
String
]
=
None
,
var
sinkModule
:
Option
[
String
]
=
None
var
sinkModule
:
Option
[
String
]
=
None
,
var
warned
:
Boolean
=
false
){
override
def
toString
:
String
=
s
"type:[$connType] source location:[${sourceModule.getOrElse(strToErrorMsg("
Not
Found
"))}]"
+
s
" sink location:[${sinkModule.getOrElse(strToErrorMsg("
Not
Found
"))}]"
def
isLe
agle
Connection
:
Boolean
=
sourceModule
.
nonEmpty
&&
sinkModule
.
nonEmpty
def
isLe
gal
Connection
:
Boolean
=
sourceModule
.
nonEmpty
&&
sinkModule
.
nonEmpty
}
private
val
map
=
mutable
.
LinkedHashMap
[
String
,
Connection
]()
...
...
@@ -44,6 +45,10 @@ object ExcitingUtils {
uniqueName
:
Boolean
=
false
)
:
String
=
{
val
conn
=
map
.
getOrElseUpdate
(
name
,
new
Connection
(
connType
))
if
(!
conn
.
sourceModule
.
isEmpty
&&
!
conn
.
warned
)
{
println
(
s
"[WARN] Signal |$name| has multiple sources"
)
conn
.
warned
=
true
}
require
(
conn
.
connType
==
connType
)
conn
.
sourceModule
=
Some
(
component
.
parentModName
)
BoringUtils
.
addSource
(
component
,
name
,
disableDedup
,
uniqueName
)
...
...
@@ -58,6 +63,10 @@ object ExcitingUtils {
forceExists
:
Boolean
=
false
)
:
Unit
=
{
val
conn
=
map
.
getOrElseUpdate
(
name
,
new
Connection
(
connType
))
if
(!
conn
.
sinkModule
.
isEmpty
&&
!
conn
.
warned
)
{
println
(
s
"[WARN] Signal |$name| has multiple sinks"
)
conn
.
warned
=
true
}
require
(
conn
.
connType
==
connType
)
conn
.
sinkModule
=
Some
(
component
.
parentModName
)
BoringUtils
.
addSink
(
component
,
name
,
disableDedup
,
forceExists
)
...
...
@@ -77,14 +86,14 @@ object ExcitingUtils {
def
checkAndDisplay
()
:
Unit
=
{
var
le
agle
=
true
var
le
gal
=
true
val
buf
=
new
mutable
.
StringBuilder
()
for
((
id
,
conn
)
<-
map
){
buf
++=
s
"Connection:[$id] $conn\n"
if
(!
conn
.
isLe
agleConnection
)
leagle
=
false
if
(!
conn
.
isLe
galConnection
)
legal
=
false
}
print
(
buf
)
require
(
le
agle
,
strToErrorMsg
(
"Error: Illeagle
connection found!"
))
require
(
le
gal
,
strToErrorMsg
(
"Error: Illegal
connection found!"
))
}
}
src/main/scala/utils/SRAMTemplate.scala
浏览文件 @
51f54365
/**************************************************************************************
* Copyright (c) 2020 Institute of Computing Technology, CAS
* Copyright (c) 2020 University of Chinese Academy of Sciences
*
* NutShell is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR
* FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
***************************************************************************************/
package
utils
import
chisel3._
...
...
@@ -85,14 +101,6 @@ class SRAMTemplate[T <: Data](gen: T, set: Int, way: Int = 1,
io
.
r
.
req
.
ready
:=
!
resetState
&&
(
if
(
singlePort
)
!
wen
else
true
.
B
)
io
.
w
.
req
.
ready
:=
true
.
B
// Debug(false) {
// when (wen) {
// printf("%d: SRAMTemplate: write %x to idx = %d\n", GTimer(), wdata.asUInt, setIdx)
// }
// when (RegNext(realRen)) {
// printf("%d: SRAMTemplate: read %x at idx = %d\n", GTimer(), VecInit(rdata).asUInt, RegNext(io.r.req.bits.setIdx))
// }
// }
}
class
SRAMTemplateWithArbiter
[
T
<:
Data
](
nRead
:
Int
,
gen
:
T
,
set
:
Int
,
way
:
Int
=
1
,
...
...
src/main/scala/xiangshan/Bundle.scala
浏览文件 @
51f54365
...
...
@@ -196,7 +196,7 @@ class CfiUpdateInfo extends XSBundle with HasBPUParameter {
class
CtrlFlow
extends
XSBundle
{
val
instr
=
UInt
(
32.
W
)
val
pc
=
UInt
(
VAddrBits
.
W
)
val
exceptionVec
=
Vec
(
16
,
Bool
()
)
val
exceptionVec
=
ExceptionVec
(
)
val
intrVec
=
Vec
(
12
,
Bool
())
val
brUpdate
=
new
CfiUpdateInfo
val
crossPageIPFFix
=
Bool
()
...
...
src/main/scala/xiangshan/PMA.scala
0 → 100644
浏览文件 @
51f54365
package
xiangshan
import
chisel3._
import
chisel3.util._
import
utils._
import
Chisel.experimental.chiselName
import
xiangshan.cache.
{
DCache
,
HasDCacheParameters
,
DCacheParameters
,
ICache
,
ICacheParameters
,
L1plusCache
,
L1plusCacheParameters
,
PTW
,
Uncache
}
object
MemMap
{
def
apply
(
base
:
String
,
top
:
String
,
width
:
String
,
description
:
String
,
mode
:
String
)
:
((
String
,
String
),
Map
[
String
,
String
])
=
{
((
base
,
top
)
->
Map
(
"width"
->
width
,
// 0 means no limitation
"description"
->
description
,
"mode"
->
mode
,
))
}
}
object
AddressSpace
{
def
MemMapList
=
List
(
// Base address Top address Width Description Mode (RWXIDSAC)
MemMap
(
"h00_0000_0000"
,
"h00_0FFF_FFFF"
,
"h0"
,
"Reserved"
,
""
),
MemMap
(
"h00_1000_0000"
,
"h00_1FFF_FFFF"
,
"h0"
,
"QSPI_Flash"
,
"RX"
),
MemMap
(
"h00_2000_0000"
,
"h00_2FFF_FFFF"
,
"h0"
,
"Reserved"
,
""
),
MemMap
(
"h00_3000_0000"
,
"h00_3000_FFFF"
,
"h0"
,
"DMA"
,
"RW"
),
MemMap
(
"h00_3001_0000"
,
"h00_3004_FFFF"
,
"h0"
,
"GPU"
,
"RWC"
),
MemMap
(
"h00_3005_0000"
,
"h00_3005_FFFF"
,
"h0"
,
"USB"
,
"RW"
),
MemMap
(
"h00_3006_0000"
,
"h00_3006_FFFF"
,
"h0"
,
"SDMMC"
,
"RW"
),
MemMap
(
"h00_3007_0000"
,
"h00_30FF_FFFF"
,
"h0"
,
"Reserved"
,
""
),
MemMap
(
"h00_3100_0000"
,
"h00_3100_FFFF"
,
"h0"
,
"QSPI"
,
"RW"
),
MemMap
(
"h00_3101_0000"
,
"h00_3101_FFFF"
,
"h0"
,
"GMAC"
,
"RW"
),
MemMap
(
"h00_3102_0000"
,
"h00_3102_FFFF"
,
"h0"
,
"HDMI"
,
"RW"
),
MemMap
(
"h00_3103_0000"
,
"h00_3103_FFFF"
,
"h0"
,
"HDMI_PHY"
,
"RW"
),
MemMap
(
"h00_3104_0000"
,
"h00_3105_FFFF"
,
"h0"
,
"DP"
,
"RW"
),
MemMap
(
"h00_3106_0000"
,
"h00_3106_FFFF"
,
"h0"
,
"DDR0"
,
"RW"
),
MemMap
(
"h00_3107_0000"
,
"h00_3107_FFFF"
,
"h0"
,
"DDR0_PHY"
,
"RW"
),
MemMap
(
"h00_3108_0000"
,
"h00_3108_FFFF"
,
"h0"
,
"DDR1"
,
"RW"
),
MemMap
(
"h00_3109_0000"
,
"h00_3109_FFFF"
,
"h0"
,
"DDR1_PHY"
,
"RW"
),
MemMap
(
"h00_310A_0000"
,
"h00_310A_FFFF"
,
"h0"
,
"IIS"
,
"RW"
),
MemMap
(
"h00_310B_0000"
,
"h00_310B_FFFF"
,
"h0"
,
"UART0"
,
"RW"
),
MemMap
(
"h00_310C_0000"
,
"h00_310C_FFFF"
,
"h0"
,
"UART1"
,
"RW"
),
MemMap
(
"h00_310D_0000"
,
"h00_310D_FFFF"
,
"h0"
,
"IIC0"
,
"RW"
),
MemMap
(
"h00_310E_0000"
,
"h00_310E_FFFF"
,
"h0"
,
"IIC1"
,
"RW"
),
MemMap
(
"h00_310F_0000"
,
"h00_310F_FFFF"
,
"h0"
,
"IIC2"
,
"RW"
),
MemMap
(
"h00_3110_0000"
,
"h00_3110_FFFF"
,
"h0"
,
"GPIO"
,
"RW"
),
MemMap
(
"h00_3111_0000"
,
"h00_3111_FFFF"
,
"h0"
,
"CRU"
,
"RW"
),
MemMap
(
"h00_3112_0000"
,
"h00_37FF_FFFF"
,
"h0"
,
"Reserved"
,
""
),
MemMap
(
"h00_3800_0000"
,
"h00_3800_FFFF"
,
"h0"
,
"CLINT"
,
"RW"
),
MemMap
(
"h00_3801_0000"
,
"h00_3BFF_FFFF"
,
"h0"
,
"Reserved"
,
""
),
MemMap
(
"h00_3C00_0000"
,
"h00_3FFF_FFFF"
,
"h0"
,
"PLIC"
,
"RW"
),
MemMap
(
"h00_4000_0000"
,
"h00_4FFF_FFFF"
,
"h0"
,
"PCIe0"
,
"RW"
),
MemMap
(
"h00_5000_0000"
,
"h00_5FFF_FFFF"
,
"h0"
,
"PCIe1"
,
"RW"
),
MemMap
(
"h00_6000_0000"
,
"h00_6FFF_FFFF"
,
"h0"
,
"PCIe2"
,
"RW"
),
MemMap
(
"h00_7000_0000"
,
"h00_7FFF_FFFF"
,
"h0"
,
"PCIe3"
,
"RW"
),
MemMap
(
"h00_8000_0000"
,
"h1F_FFFF_FFFF"
,
"h0"
,
"DDR"
,
"RWXIDSA"
),
)
def
printMemmap
(){
println
(
"-------------------- memory map --------------------"
)
for
(
i
<-
MemMapList
){
println
(
i
.
_1
.
_1
+
"->"
+
i
.
_1
.
_2
+
" width "
+
(
if
(
i
.
_2
.
get
(
"width"
).
get
==
"0"
)
"unlimited"
else
i
.
_2
.
get
(
"width"
).
get
)
+
" "
+
i
.
_2
.
get
(
"description"
).
get
+
" ["
+
i
.
_2
.
get
(
"mode"
).
get
+
"]"
)
}
println
(
"----------------------------------------------------"
)
}
def
genMemmapMatchVec
(
addr
:
UInt
)
:
UInt
=
{
VecInit
(
MemMapList
.
map
(
i
=>
{
i
.
_1
.
_1
.
U
<=
addr
&&
addr
<
i
.
_1
.
_2
.
U
}).
toSeq
).
asUInt
}
def
queryMode
(
matchVec
:
UInt
)
:
UInt
=
{
Mux1H
(
matchVec
,
VecInit
(
MemMapList
.
map
(
i
=>
{
PMAMode
.
strToMode
(
i
.
_2
.
get
(
"mode"
).
get
)
}).
toSeq
))
}
def
queryWidth
(
matchVec
:
UInt
)
:
UInt
=
{
Mux1H
(
matchVec
,
VecInit
(
MemMapList
.
map
(
i
=>
{
i
.
_2
.
get
(
"width"
).
get
.
U
}).
toSeq
))
}
def
memmapAddrMatch
(
addr
:
UInt
)
:
(
UInt
,
UInt
)
=
{
val
matchVec
=
genMemmapMatchVec
(
addr
)
(
queryMode
(
matchVec
),
queryWidth
(
matchVec
))
}
def
isDMMIO
(
addr
:
UInt
)
:
Bool
=
!
PMAMode
.
dcache
(
memmapAddrMatch
(
addr
).
_1
)
def
isIMMIO
(
addr
:
UInt
)
:
Bool
=
!
PMAMode
.
icache
(
memmapAddrMatch
(
addr
).
_1
)
def
isConfigableAddr
(
addr
:
UInt
)
:
Bool
=
{
VecInit
(
MemMapList
.
map
(
i
=>
{
i
.
_1
.
_1
.
U
<=
addr
&&
addr
<
i
.
_1
.
_2
.
U
&&
(
i
.
_2
.
get
(
"mode"
).
get
.
toUpperCase
.
indexOf
(
"C"
)
>=
0
).
B
}).
toSeq
).
asUInt
.
orR
}
}
class
PMAChecker
extends
XSModule
with
HasDCacheParameters
{
val
io
=
IO
(
new
Bundle
()
{
val
paddr
=
Input
(
UInt
(
VAddrBits
.
W
))
val
mode
=
Output
(
PMAMode
())
val
widthLimit
=
Output
(
UInt
(
8.
W
))
// TODO: fixme
val
updateCConfig
=
Input
(
Valid
(
Bool
()))
})
val
enableConfigableCacheZone
=
RegInit
(
false
.
B
)
val
updateCConfig
=
RegNext
(
RegNext
(
RegNext
(
io
.
updateCConfig
)))
when
(
updateCConfig
.
valid
)
{
enableConfigableCacheZone
:=
updateCConfig
.
bits
}
val
(
mode
,
widthLimit
)
=
AddressSpace
.
memmapAddrMatch
(
io
.
paddr
)
io
.
mode
:=
Mux
(
AddressSpace
.
isConfigableAddr
(
io
.
paddr
)
&&
enableConfigableCacheZone
,
mode
|
PMAMode
.
D
,
mode
)
io
.
widthLimit
:=
widthLimit
}
\ No newline at end of file
src/main/scala/xiangshan/XSCore.scala
浏览文件 @
51f54365
...
...
@@ -10,7 +10,7 @@ import xiangshan.backend.exu.Exu._
import
xiangshan.frontend._
import
xiangshan.mem._
import
xiangshan.backend.fu.HasExceptionNO
import
xiangshan.cache.
{
DCache
,
DCacheParameters
,
ICache
,
ICacheParameters
,
L1plusCache
,
L1plusCacheParameters
,
PTW
,
Uncache
}
import
xiangshan.cache.
{
DCache
,
InstrUncache
,
DCacheParameters
,
ICache
,
ICacheParameters
,
L1plusCache
,
L1plusCacheParameters
,
PTW
,
Uncache
,
MemoryOpConstants
,
MissReq
}
import
xiangshan.cache.prefetch._
import
chipsalliance.rocketchip.config
import
freechips.rocketchip.diplomacy.
{
AddressSet
,
LazyModule
,
LazyModuleImp
}
...
...
@@ -19,6 +19,7 @@ import freechips.rocketchip.devices.tilelink.{DevNullParams, TLError}
import
sifive.blocks.inclusivecache.
{
CacheParameters
,
InclusiveCache
,
InclusiveCacheMicroParameters
}
import
freechips.rocketchip.amba.axi4.
{
AXI4Deinterleaver
,
AXI4Fragmenter
,
AXI4IdIndexer
,
AXI4IdentityNode
,
AXI4ToTL
,
AXI4UserYanker
}
import
freechips.rocketchip.tile.HasFPUParameters
import
sifive.blocks.inclusivecache.PrefetcherIO
import
utils._
case
class
XSCoreParameters
...
...
@@ -89,7 +90,9 @@ case class XSCoreParameters
StoreBufferSize
:
Int
=
16
,
RefillSize
:
Int
=
512
,
TlbEntrySize
:
Int
=
32
,
TlbSPEntrySize
:
Int
=
4
,
TlbL2EntrySize
:
Int
=
256
,
// or 512
TlbL2SPEntrySize
:
Int
=
16
,
PtwL1EntrySize
:
Int
=
16
,
PtwL2EntrySize
:
Int
=
256
,
NumPerfCounters
:
Int
=
16
,
...
...
@@ -165,7 +168,9 @@ trait HasXSParameter {
val
RefillSize
=
core
.
RefillSize
val
DTLBWidth
=
core
.
LoadPipelineWidth
+
core
.
StorePipelineWidth
val
TlbEntrySize
=
core
.
TlbEntrySize
val
TlbSPEntrySize
=
core
.
TlbSPEntrySize
val
TlbL2EntrySize
=
core
.
TlbL2EntrySize
val
TlbL2SPEntrySize
=
core
.
TlbL2SPEntrySize
val
PtwL1EntrySize
=
core
.
PtwL1EntrySize
val
PtwL2EntrySize
=
core
.
PtwL2EntrySize
val
NumPerfCounters
=
core
.
NumPerfCounters
...
...
@@ -183,32 +188,6 @@ trait HasXSParameter {
nMissEntries
=
8
)
// icache prefetcher
val
l1plusPrefetcherParameters
=
L1plusPrefetcherParameters
(
enable
=
false
,
_type
=
"stream"
,
streamParams
=
StreamPrefetchParameters
(
streamCnt
=
4
,
streamSize
=
4
,
ageWidth
=
4
,
blockBytes
=
l1plusCacheParameters
.
blockBytes
,
reallocStreamOnMissInstantly
=
true
)
)
// dcache prefetcher
val
l2PrefetcherParameters
=
L2PrefetcherParameters
(
enable
=
true
,
_type
=
"stream"
,
streamParams
=
StreamPrefetchParameters
(
streamCnt
=
4
,
streamSize
=
4
,
ageWidth
=
4
,
blockBytes
=
L2BlockSize
,
reallocStreamOnMissInstantly
=
true
)
)
val
dcacheParameters
=
DCacheParameters
(
tagECC
=
Some
(
"secded"
),
dataECC
=
Some
(
"secded"
),
...
...
@@ -240,6 +219,43 @@ trait HasXSParameter {
// on chip network configurations
val
L3BusWidth
=
256
// icache prefetcher
val
l1plusPrefetcherParameters
=
L1plusPrefetcherParameters
(
enable
=
true
,
_type
=
"stream"
,
streamParams
=
StreamPrefetchParameters
(
streamCnt
=
2
,
streamSize
=
4
,
ageWidth
=
4
,
blockBytes
=
l1plusCacheParameters
.
blockBytes
,
reallocStreamOnMissInstantly
=
true
,
cacheName
=
"icache"
)
)
// dcache prefetcher
val
l2PrefetcherParameters
=
L2PrefetcherParameters
(
enable
=
true
,
_type
=
"bop"
,
// "stream" or "bop"
streamParams
=
StreamPrefetchParameters
(
streamCnt
=
4
,
streamSize
=
4
,
ageWidth
=
4
,
blockBytes
=
L2BlockSize
,
reallocStreamOnMissInstantly
=
true
,
cacheName
=
"dcache"
),
bopParams
=
BOPParameters
(
rrTableEntries
=
256
,
rrTagBits
=
12
,
scoreBits
=
5
,
roundMax
=
50
,
badScore
=
1
,
blockBytes
=
L2BlockSize
,
nEntries
=
dcacheParameters
.
nMissEntries
*
2
// TODO: this is too large
),
)
}
trait
HasXSLog
{
this:
RawModule
=>
...
...
@@ -272,23 +288,23 @@ case class EnviromentParameters
(
FPGAPlatform
:
Boolean
=
true
,
EnableDebug
:
Boolean
=
false
,
EnablePerfDebug
:
Boolean
=
tru
e
EnablePerfDebug
:
Boolean
=
fals
e
)
object
AddressSpace
extends
HasXSParameter
{
// (start, size)
// address out of MMIO will be considered as DRAM
def
mmio
=
List
(
(
0x00000000
L
,
0x40000000
L
),
// internal devices, such as CLINT and PLIC
(
0x40000000
L
,
0x40000000
L
)
// external devices
)
//
object AddressSpace extends HasXSParameter {
//
// (start, size)
//
// address out of MMIO will be considered as DRAM
//
def mmio = List(
//
(0x00000000L, 0x40000000L), // internal devices, such as CLINT and PLIC
//
(0x40000000L, 0x40000000L) // external devices
//
)
def
isMMIO
(
addr
:
UInt
)
:
Bool
=
mmio
.
map
(
range
=>
{
require
(
isPow2
(
range
.
_2
))
val
bits
=
log2Up
(
range
.
_2
)
(
addr
^
range
.
_1
.
U
)(
PAddrBits
-
1
,
bits
)
===
0.
U
}).
reduce
(
_
||
_
)
}
//
def isMMIO(addr: UInt): Bool = mmio.map(range => {
//
require(isPow2(range._2))
//
val bits = log2Up(range._2)
//
(addr ^ range._1.U)(PAddrBits-1, bits) === 0.U
//
}).reduce(_ || _)
//
}
...
...
@@ -309,6 +325,7 @@ class XSCore()(implicit p: config.Parameters) extends LazyModule
val
fpBlockSlowWakeUpInt
=
fpExuConfigs
.
filter
(
intSlowFilter
)
// outer facing nodes
val
frontend
=
LazyModule
(
new
Frontend
())
val
l1pluscache
=
LazyModule
(
new
L1plusCache
())
val
ptw
=
LazyModule
(
new
PTW
())
val
l2Prefetcher
=
LazyModule
(
new
L2Prefetcher
())
...
...
@@ -330,9 +347,11 @@ class XSCoreImp(outer: XSCore) extends LazyModuleImp(outer)
{
val
io
=
IO
(
new
Bundle
{
val
externalInterrupt
=
new
ExternalInterruptIO
val
l2ToPrefetcher
=
Flipped
(
new
PrefetcherIO
(
PAddrBits
))
})
println
(
s
"FPGAPlatform:${env.FPGAPlatform} EnableDebug:${env.EnableDebug}"
)
AddressSpace
.
printMemmap
()
// to fast wake up fp, mem rs
val
intBlockFastWakeUpFp
=
intExuConfigs
.
filter
(
fpFastFilter
)
...
...
@@ -345,7 +364,6 @@ class XSCoreImp(outer: XSCore) extends LazyModuleImp(outer)
val
fpBlockFastWakeUpInt
=
fpExuConfigs
.
filter
(
intFastFilter
)
val
fpBlockSlowWakeUpInt
=
fpExuConfigs
.
filter
(
intSlowFilter
)
val
frontend
=
Module
(
new
Frontend
)
val
ctrlBlock
=
Module
(
new
CtrlBlock
)
val
integerBlock
=
Module
(
new
IntegerBlock
(
fastWakeUpIn
=
fpBlockFastWakeUpInt
,
...
...
@@ -364,6 +382,7 @@ class XSCoreImp(outer: XSCore) extends LazyModuleImp(outer)
slowIntOut
=
fpBlockSlowWakeUpInt
))
val
frontend
=
outer
.
frontend
.
module
val
memBlock
=
outer
.
memBlock
.
module
val
l1pluscache
=
outer
.
l1pluscache
.
module
val
ptw
=
outer
.
ptw
.
module
...
...
@@ -443,7 +462,16 @@ class XSCoreImp(outer: XSCore) extends LazyModuleImp(outer)
ptw
.
io
.
sfence
<>
integerBlock
.
io
.
fenceio
.
sfence
ptw
.
io
.
csr
<>
integerBlock
.
io
.
csrio
.
tlb
l2Prefetcher
.
io
.
in
<>
memBlock
.
io
.
toDCachePrefetch
val
l2PrefetcherIn
=
Wire
(
Decoupled
(
new
MissReq
))
if
(
l2PrefetcherParameters
.
enable
&&
l2PrefetcherParameters
.
_type
==
"bop"
)
{
l2PrefetcherIn
.
valid
:=
io
.
l2ToPrefetcher
.
acquire
.
valid
l2PrefetcherIn
.
bits
:=
DontCare
l2PrefetcherIn
.
bits
.
addr
:=
io
.
l2ToPrefetcher
.
acquire
.
bits
.
address
l2PrefetcherIn
.
bits
.
cmd
:=
Mux
(
io
.
l2ToPrefetcher
.
acquire
.
bits
.
write
,
MemoryOpConstants
.
M_XWR
,
MemoryOpConstants
.
M_XRD
)
}
else
{
l2PrefetcherIn
<>
memBlock
.
io
.
toDCachePrefetch
}
l2Prefetcher
.
io
.
in
<>
l2PrefetcherIn
if
(!
env
.
FPGAPlatform
)
{
val
debugIntReg
,
debugFpReg
=
WireInit
(
VecInit
(
Seq
.
fill
(
32
)(
0.
U
(
XLEN
.
W
))))
...
...
src/main/scala/xiangshan/backend/CtrlBlock.scala
浏览文件 @
51f54365
...
...
@@ -16,7 +16,7 @@ import xiangshan.mem.LsqEnqIO
class
CtrlToIntBlockIO
extends
XSBundle
{
val
enqIqCtrl
=
Vec
(
exuParameters
.
IntExuCnt
,
DecoupledIO
(
new
MicroOp
))
val
readRf
=
Vec
(
NRIntReadPorts
,
Flipped
(
new
RfReadPort
(
XLEN
)))
val
readRf
=
Vec
(
NRIntReadPorts
,
Output
(
UInt
(
PhyRegIdxWidth
.
W
)))
val
jumpPc
=
Output
(
UInt
(
VAddrBits
.
W
))
// int block only uses port 0~7
val
readPortIndex
=
Vec
(
exuParameters
.
IntExuCnt
,
Output
(
UInt
(
log2Ceil
(
8
/
2
).
W
)))
// TODO parameterize 8 here
...
...
@@ -25,7 +25,7 @@ class CtrlToIntBlockIO extends XSBundle {
class
CtrlToFpBlockIO
extends
XSBundle
{
val
enqIqCtrl
=
Vec
(
exuParameters
.
FpExuCnt
,
DecoupledIO
(
new
MicroOp
))
val
readRf
=
Vec
(
NRFpReadPorts
,
Flipped
(
new
RfReadPort
(
XLEN
+
1
)))
val
readRf
=
Vec
(
NRFpReadPorts
,
Output
(
UInt
(
PhyRegIdxWidth
.
W
)))
// fp block uses port 0~11
val
readPortIndex
=
Vec
(
exuParameters
.
FpExuCnt
,
Output
(
UInt
(
log2Ceil
((
NRFpReadPorts
-
exuParameters
.
StuCnt
)
/
3
).
W
)))
val
redirect
=
ValidIO
(
new
Redirect
)
...
...
@@ -131,10 +131,8 @@ class CtrlBlock extends XSModule with HasCircularQueuePtrHelper {
setPhyRegRdy
.
valid
:=
wb
.
valid
&&
wb
.
bits
.
uop
.
ctrl
.
fpWen
setPhyRegRdy
.
bits
:=
wb
.
bits
.
uop
.
pdest
}
intBusyTable
.
io
.
rfReadAddr
<>
dispatch
.
io
.
readIntRf
.
map
(
_
.
addr
)
intBusyTable
.
io
.
pregRdy
<>
dispatch
.
io
.
intPregRdy
fpBusyTable
.
io
.
rfReadAddr
<>
dispatch
.
io
.
readFpRf
.
map
(
_
.
addr
)
fpBusyTable
.
io
.
pregRdy
<>
dispatch
.
io
.
fpPregRdy
intBusyTable
.
io
.
read
<>
dispatch
.
io
.
readIntState
fpBusyTable
.
io
.
read
<>
dispatch
.
io
.
readFpState
roq
.
io
.
redirect
.
valid
:=
brq
.
io
.
redirectOut
.
valid
||
io
.
fromLsBlock
.
replay
.
valid
roq
.
io
.
redirect
.
bits
<>
redirectArb
...
...
src/main/scala/xiangshan/backend/FloatBlock.scala
浏览文件 @
51f54365
...
...
@@ -152,7 +152,7 @@ class FloatBlock
// read fp rf from ctrl block
fpRf
.
io
.
readPorts
<>
io
.
fromCtrlBlock
.
readRf
fpRf
.
io
.
readPorts
.
zipWithIndex
.
map
{
case
(
r
,
i
)
=>
r
.
addr
:=
io
.
fromCtrlBlock
.
readRf
(
i
)
}
(
0
until
exuParameters
.
StuCnt
).
foreach
(
i
=>
io
.
toMemBlock
.
readFpRf
(
i
).
data
:=
fpRf
.
io
.
readPorts
(
i
+
12
).
data
)
// write fp rf arbiter
val
fpWbArbiter
=
Module
(
new
Wb
(
...
...
src/main/scala/xiangshan/backend/IntegerBlock.scala
浏览文件 @
51f54365
...
...
@@ -218,7 +218,7 @@ class IntegerBlock
jmpExeUnit
.
fenceio
<>
io
.
fenceio
// read int rf from ctrl block
intRf
.
io
.
readPorts
<>
io
.
fromCtrlBlock
.
readRf
intRf
.
io
.
readPorts
.
zipWithIndex
.
map
{
case
(
r
,
i
)
=>
r
.
addr
:=
io
.
fromCtrlBlock
.
readRf
(
i
)
}
(
0
until
NRMemReadPorts
).
foreach
(
i
=>
io
.
toMemBlock
.
readIntRf
(
i
).
data
:=
intRf
.
io
.
readPorts
(
i
+
8
).
data
)
// write int rf arbiter
val
intWbArbiter
=
Module
(
new
Wb
(
...
...
src/main/scala/xiangshan/backend/MemBlock.scala
浏览文件 @
51f54365
...
...
@@ -250,6 +250,7 @@ class MemBlockImp
// LSQ to store buffer
lsq
.
io
.
sbuffer
<>
sbuffer
.
io
.
in
lsq
.
io
.
sqempty
<>
sbuffer
.
io
.
sqempty
// Sbuffer
sbuffer
.
io
.
dcache
<>
dcache
.
io
.
lsu
.
store
...
...
src/main/scala/xiangshan/backend/brq/Brq.scala
浏览文件 @
51f54365
...
...
@@ -5,6 +5,7 @@ import chisel3.util._
import
xiangshan._
import
utils._
import
chisel3.ExcitingUtils._
import
xiangshan.backend.JumpOpType
import
xiangshan.backend.decode.ImmUnion
...
...
@@ -75,7 +76,7 @@ class Brq extends XSModule with HasCircularQueuePtrHelper {
val
exuOut
=
new
ExuOutput
}
val
s_idle
::
s_wb
::
Nil
=
Enum
(
2
)
val
s_idle
::
s_wb
::
s_auipc_wb
::
Nil
=
Enum
(
3
)
class
DecodeEnqBrqData
extends
Bundle
{
val
cfiUpdateInfo
=
new
CfiUpdateInfo
...
...
@@ -107,7 +108,9 @@ class Brq extends XSModule with HasCircularQueuePtrHelper {
/**
* write back
*/
val
wbValid
=
stateQueue
(
writebackIdx
)
===
s_wb
val
wbState
=
stateQueue
(
writebackIdx
)
val
wbValid
=
wbState
===
s_wb
val
wbIsAuipc
=
wbState
===
s_auipc_wb
val
wbEntry
=
Wire
(
new
ExuOutput
)
val
wbIsMisPred
=
wbEntry
.
redirect
.
target
=/=
wbEntry
.
brUpdate
.
pnpc
...
...
@@ -115,9 +118,9 @@ class Brq extends XSModule with HasCircularQueuePtrHelper {
io
.
redirectOut
.
bits
:=
wbEntry
.
redirect
io
.
redirectOut
.
bits
.
brTag
:=
BrqPtr
(
ptrFlagVec
(
writebackIdx
),
writebackIdx
)
io
.
out
.
valid
:=
wbValid
io
.
out
.
valid
:=
wbValid
||
wbIsAuipc
io
.
out
.
bits
:=
wbEntry
when
(
wbV
alid
)
{
when
(
io
.
out
.
v
alid
)
{
stateQueue
(
writebackIdx
)
:=
s_idle
writebackPtr_next
:=
writebackPtr
+
1.
U
}
...
...
@@ -164,7 +167,7 @@ class Brq extends XSModule with HasCircularQueuePtrHelper {
/**
* exu write back
*/
for
(
exuWb
<-
io
.
exuRedirectWb
)
{
for
(
(
exuWb
,
i
)
<-
io
.
exuRedirectWb
.
zipWithIndex
)
{
when
(
exuWb
.
valid
)
{
val
wbIdx
=
exuWb
.
bits
.
redirect
.
brTag
.
value
XSInfo
(
...
...
@@ -174,10 +177,16 @@ class Brq extends XSModule with HasCircularQueuePtrHelper {
p
"target=${Hexadecimal(exuWb.bits.redirect.target)}\n"
)
assert
(
stateQueue
(
wbIdx
)
===
s_idle
)
if
(
i
==
0
){
// jump
stateQueue
(
wbIdx
)
:=
Mux
(
JumpOpType
.
jumpOpisAuipc
(
exuWb
.
bits
.
uop
.
ctrl
.
fuOpType
),
s_auipc_wb
,
s_wb
)
}
else
{
// alu
stateQueue
(
wbIdx
)
:=
s_wb
}
}
}
// when redirect is valid, we need to update the states and pointers
when
(
io
.
redirect
.
valid
)
{
...
...
src/main/scala/xiangshan/backend/decode/DecodeStage.scala
浏览文件 @
51f54365
...
...
@@ -5,6 +5,7 @@ import chisel3.util._
import
xiangshan._
import
xiangshan.backend.brq.BrqEnqIO
import
utils._
import
xiangshan.backend.decode.Instructions.
{
AUIPC
,
MRET
,
SRET
}
class
DecodeStage
extends
XSModule
{
val
io
=
IO
(
new
Bundle
()
{
...
...
@@ -31,12 +32,14 @@ class DecodeStage extends XSModule {
for
(
i
<-
0
until
DecodeWidth
)
{
decoders
(
i
).
io
.
enq
.
ctrl_flow
<>
io
.
in
(
i
).
bits
val
isMret
=
io
.
in
(
i
).
bits
.
instr
===
BitPat
(
"b001100000010_00000_000_00000_1110011"
)
val
isSret
=
io
.
in
(
i
).
bits
.
instr
===
BitPat
(
"b000100000010_00000_000_00000_1110011"
)
val
thisBrqValid
=
!
io
.
in
(
i
).
bits
.
brUpdate
.
pd
.
notCFI
||
isMret
||
isSret
val
isMret
=
io
.
in
(
i
).
bits
.
instr
===
MRET
val
isSret
=
io
.
in
(
i
).
bits
.
instr
===
SRET
val
isAuiPc
=
io
.
in
(
i
).
bits
.
instr
===
AUIPC
val
thisBrqValid
=
!
io
.
in
(
i
).
bits
.
brUpdate
.
pd
.
notCFI
||
isMret
||
isSret
||
isAuiPc
io
.
enqBrq
.
needAlloc
(
i
)
:=
thisBrqValid
io
.
enqBrq
.
req
(
i
).
valid
:=
io
.
in
(
i
).
valid
&&
thisBrqValid
&&
io
.
out
(
i
).
ready
io
.
enqBrq
.
req
(
i
).
bits
:=
decoders
(
i
).
io
.
deq
.
cf_ctrl
.
cf
io
.
enqBrq
.
req
(
i
).
bits
:=
io
.
in
(
i
).
bits
io
.
enqBrq
.
req
(
i
).
bits
.
instr
:=
decoders
(
i
).
io
.
deq
.
cf_ctrl
.
cf
.
instr
io
.
out
(
i
).
valid
:=
io
.
in
(
i
).
valid
&&
io
.
enqBrq
.
req
(
i
).
ready
io
.
out
(
i
).
bits
:=
decoders
(
i
).
io
.
deq
.
cf_ctrl
...
...
src/main/scala/xiangshan/backend/decode/DecodeUnit.scala
浏览文件 @
51f54365
...
...
@@ -135,7 +135,7 @@ object XDecode extends DecodeConstants {
REMW
->
List
(
SrcType
.
reg
,
SrcType
.
reg
,
SrcType
.
DC
,
FuType
.
div
,
MDUOpType
.
remw
,
Y
,
N
,
N
,
N
,
N
,
N
,
N
,
SelImm
.
IMM_X
),
REMUW
->
List
(
SrcType
.
reg
,
SrcType
.
reg
,
SrcType
.
DC
,
FuType
.
div
,
MDUOpType
.
remuw
,
Y
,
N
,
N
,
N
,
N
,
N
,
N
,
SelImm
.
IMM_X
),
AUIPC
->
List
(
SrcType
.
pc
,
SrcType
.
imm
,
SrcType
.
DC
,
FuType
.
alu
,
ALUOpType
.
add
,
Y
,
N
,
N
,
N
,
N
,
N
,
N
,
SelImm
.
IMM_U
),
AUIPC
->
List
(
SrcType
.
pc
,
SrcType
.
imm
,
SrcType
.
DC
,
FuType
.
jmp
,
JumpOpType
.
auipc
,
Y
,
N
,
N
,
N
,
N
,
N
,
N
,
SelImm
.
IMM_U
),
JAL
->
List
(
SrcType
.
pc
,
SrcType
.
imm
,
SrcType
.
DC
,
FuType
.
jmp
,
JumpOpType
.
jal
,
Y
,
N
,
N
,
N
,
N
,
N
,
N
,
SelImm
.
IMM_UJ
),
JALR
->
List
(
SrcType
.
reg
,
SrcType
.
imm
,
SrcType
.
DC
,
FuType
.
jmp
,
JumpOpType
.
jalr
,
Y
,
N
,
N
,
N
,
N
,
N
,
N
,
SelImm
.
IMM_I
),
BEQ
->
List
(
SrcType
.
reg
,
SrcType
.
reg
,
SrcType
.
DC
,
FuType
.
alu
,
ALUOpType
.
beq
,
N
,
N
,
N
,
N
,
N
,
N
,
N
,
SelImm
.
IMM_SB
),
...
...
@@ -155,9 +155,9 @@ object XDecode extends DecodeConstants {
CSRRCI
->
List
(
SrcType
.
reg
,
SrcType
.
imm
,
SrcType
.
DC
,
FuType
.
csr
,
CSROpType
.
clri
,
Y
,
N
,
N
,
Y
,
Y
,
N
,
N
,
SelImm
.
IMM_Z
),
SFENCE_VMA
->
List
(
SrcType
.
reg
,
SrcType
.
imm
,
SrcType
.
DC
,
FuType
.
fence
,
FenceOpType
.
sfence
,
N
,
N
,
N
,
Y
,
Y
,
Y
,
N
,
SelImm
.
IMM_X
),
ECALL
->
List
(
SrcType
.
reg
,
SrcType
.
imm
,
SrcType
.
DC
,
FuType
.
csr
,
CSROpType
.
jmp
,
Y
,
N
,
N
,
Y
,
Y
,
N
,
N
,
SelImm
.
IMM_
X
),
SRET
->
List
(
SrcType
.
reg
,
SrcType
.
imm
,
SrcType
.
DC
,
FuType
.
csr
,
CSROpType
.
jmp
,
Y
,
N
,
N
,
Y
,
Y
,
N
,
N
,
SelImm
.
IMM_
X
),
MRET
->
List
(
SrcType
.
reg
,
SrcType
.
imm
,
SrcType
.
DC
,
FuType
.
csr
,
CSROpType
.
jmp
,
Y
,
N
,
N
,
Y
,
Y
,
N
,
N
,
SelImm
.
IMM_
X
),
ECALL
->
List
(
SrcType
.
reg
,
SrcType
.
imm
,
SrcType
.
DC
,
FuType
.
csr
,
CSROpType
.
jmp
,
Y
,
N
,
N
,
Y
,
Y
,
N
,
N
,
SelImm
.
IMM_
I
),
SRET
->
List
(
SrcType
.
reg
,
SrcType
.
imm
,
SrcType
.
DC
,
FuType
.
csr
,
CSROpType
.
jmp
,
Y
,
N
,
N
,
Y
,
Y
,
N
,
N
,
SelImm
.
IMM_
I
),
MRET
->
List
(
SrcType
.
reg
,
SrcType
.
imm
,
SrcType
.
DC
,
FuType
.
csr
,
CSROpType
.
jmp
,
Y
,
N
,
N
,
Y
,
Y
,
N
,
N
,
SelImm
.
IMM_
I
),
WFI
->
List
(
SrcType
.
pc
,
SrcType
.
imm
,
SrcType
.
DC
,
FuType
.
alu
,
ALUOpType
.
sll
,
Y
,
N
,
N
,
N
,
N
,
N
,
N
,
SelImm
.
IMM_X
),
...
...
@@ -300,22 +300,6 @@ object XSTrapDecode extends DecodeConstants {
)
}
class
RVCExpander
extends
XSModule
{
val
io
=
IO
(
new
Bundle
{
val
in
=
Input
(
UInt
(
32.
W
))
val
out
=
Output
(
new
ExpandedInstruction
)
val
rvc
=
Output
(
Bool
())
})
if
(
HasCExtension
)
{
io
.
rvc
:=
io
.
in
(
1
,
0
)
=/=
3.
U
io
.
out
:=
new
RVCDecoder
(
io
.
in
,
XLEN
).
decode
}
else
{
io
.
rvc
:=
false
.
B
io
.
out
:=
new
RVCDecoder
(
io
.
in
,
XLEN
).
passthrough
}
}
//object Imm32Gen {
// def apply(sel: UInt, inst: UInt) = {
// val sign = Mux(sel === SelImm.IMM_Z, 0.S, inst(31).asSInt)
...
...
@@ -425,19 +409,7 @@ class DecodeUnit extends XSModule with DecodeUnitConstants {
val
ctrl_flow
=
Wire
(
new
CtrlFlow
)
// input with RVC Expanded
val
cf_ctrl
=
Wire
(
new
CfCtrl
)
val
exp
=
Module
(
new
RVCExpander
())
exp
.
io
.
in
:=
io
.
enq
.
ctrl_flow
.
instr
ctrl_flow
:=
io
.
enq
.
ctrl_flow
when
(
exp
.
io
.
rvc
)
{
ctrl_flow
.
instr
:=
exp
.
io
.
out
.
bits
}
// save rvc decode info
// TODO maybe rvc_info are useless?
val
rvc_info
=
Wire
(
new
ExpandedInstruction
())
val
is_rvc
=
Wire
(
Bool
())
rvc_info
:=
exp
.
io
.
out
is_rvc
:=
exp
.
io
.
rvc
var
decode_table
=
XDecode
.
table
++
FDecode
.
table
++
FDivSqrtDecode
.
table
++
X64Decode
.
table
++
XSTrapDecode
.
table
...
...
@@ -458,10 +430,8 @@ class DecodeUnit extends XSModule with DecodeUnitConstants {
cs
.
ldest
:=
Mux
(
cs
.
fpWen
||
cs
.
rfWen
,
ctrl_flow
.
instr
(
RD_MSB
,
RD_LSB
),
0.
U
)
// fill in exception vector
cf_ctrl
.
cf
.
exceptionVec
.
map
(
_
:=
false
.
B
)
cf_ctrl
.
cf
.
exceptionVec
:=
io
.
enq
.
ctrl_flow
.
exceptionVec
cf_ctrl
.
cf
.
exceptionVec
(
illegalInstr
)
:=
cs
.
selImm
===
SelImm
.
INVALID_INSTR
cf_ctrl
.
cf
.
exceptionVec
(
instrPageFault
)
:=
io
.
enq
.
ctrl_flow
.
exceptionVec
(
instrPageFault
)
cf_ctrl
.
cf
.
exceptionVec
(
instrAccessFault
)
:=
io
.
enq
.
ctrl_flow
.
exceptionVec
(
instrAccessFault
)
// fix frflags
// fflags zero csrrs rd csr
...
...
src/main/scala/xiangshan/backend/decode/FPDecoder.scala
浏览文件 @
51f54365
...
...
@@ -27,7 +27,7 @@ class FPDecoder extends XSModule{
FCVT_S_WU
->
List
(
N
,
s
,
s
,
Y
,
Y
,
Y
,
N
,
N
,
Y
),
FCVT_S_L
->
List
(
N
,
s
,
s
,
Y
,
Y
,
Y
,
N
,
N
,
Y
),
FCVT_S_LU
->
List
(
N
,
s
,
s
,
Y
,
Y
,
Y
,
N
,
N
,
Y
),
FMV_X_W
->
List
(
N
,
s
,
X
,
N
,
N
,
N
,
N
,
N
,
N
),
FMV_X_W
->
List
(
N
,
d
,
X
,
N
,
N
,
N
,
N
,
N
,
N
),
FCLASS_S
->
List
(
N
,
s
,
X
,
N
,
N
,
N
,
N
,
N
,
N
),
FCVT_W_S
->
List
(
N
,
s
,
X
,
N
,
Y
,
N
,
N
,
N
,
Y
),
FCVT_WU_S
->
List
(
N
,
s
,
X
,
N
,
Y
,
N
,
N
,
N
,
Y
),
...
...
src/main/scala/xiangshan/backend/dispatch/Dispatch.scala
浏览文件 @
51f54365
...
...
@@ -7,7 +7,7 @@ import utils._
import
xiangshan.backend.regfile.RfReadPort
import
chisel3.ExcitingUtils._
import
xiangshan.backend.roq.
{
RoqPtr
,
RoqEnqIO
}
import
xiangshan.backend.rename.
RenameBypassInfo
import
xiangshan.backend.rename.
{
RenameBypassInfo
,
BusyTableReadIO
}
import
xiangshan.mem.LsqEnqIO
case
class
DispatchParameters
...
...
@@ -34,11 +34,11 @@ class Dispatch extends XSModule {
// enq Lsq
val
enqLsq
=
Flipped
(
new
LsqEnqIO
)
// read regfile
val
readIntRf
=
Vec
(
NRIntReadPorts
,
Flipped
(
new
RfReadPort
(
XLEN
)))
val
readFpRf
=
Vec
(
NRFpReadPorts
,
Flipped
(
new
RfReadPort
(
XLEN
+
1
)))
//
read reg status
(busy/ready)
val
intPregRdy
=
Vec
(
NRIntReadPorts
,
Input
(
Bool
()
))
val
fpPregRdy
=
Vec
(
NRFpReadPorts
,
Input
(
Bool
()
))
val
readIntRf
=
Vec
(
NRIntReadPorts
,
Output
(
UInt
(
PhyRegIdxWidth
.
W
)))
val
readFpRf
=
Vec
(
NRFpReadPorts
,
Output
(
UInt
(
PhyRegIdxWidth
.
W
)))
//
to busytable: read physical registers' state
(busy/ready)
val
readIntState
=
Vec
(
NRIntReadPorts
,
Flipped
(
new
BusyTableReadIO
))
val
readFpState
=
Vec
(
NRFpReadPorts
,
Flipped
(
new
BusyTableReadIO
))
// to reservation stations
val
numExist
=
Input
(
Vec
(
exuParameters
.
ExuCnt
,
UInt
(
log2Ceil
(
IssQueSize
).
W
)))
val
enqIQCtrl
=
Vec
(
exuParameters
.
ExuCnt
,
DecoupledIO
(
new
MicroOp
))
...
...
@@ -82,7 +82,7 @@ class Dispatch extends XSModule {
val
intDispatch
=
Module
(
new
Dispatch2Int
)
intDispatch
.
io
.
fromDq
<>
intDq
.
io
.
deq
intDispatch
.
io
.
readRf
.
zipWithIndex
.
map
({
case
(
r
,
i
)
=>
r
<>
io
.
readIntRf
(
i
)})
intDispatch
.
io
.
re
gRdy
.
zipWithIndex
.
map
({
case
(
r
,
i
)
=>
r
<>
io
.
intPregRdy
(
i
)})
intDispatch
.
io
.
re
adState
.
zipWithIndex
.
map
({
case
(
r
,
i
)
=>
r
<>
io
.
readIntState
(
i
)})
intDispatch
.
io
.
numExist
.
zipWithIndex
.
map
({
case
(
num
,
i
)
=>
num
:=
io
.
numExist
(
i
)})
intDispatch
.
io
.
enqIQCtrl
.
zipWithIndex
.
map
({
case
(
enq
,
i
)
=>
enq
<>
io
.
enqIQCtrl
(
i
)})
// intDispatch.io.enqIQData.zipWithIndex.map({case (enq, i) => enq <> io.enqIQData(i)})
...
...
@@ -92,7 +92,7 @@ class Dispatch extends XSModule {
val
fpDispatch
=
Module
(
new
Dispatch2Fp
)
fpDispatch
.
io
.
fromDq
<>
fpDq
.
io
.
deq
fpDispatch
.
io
.
readRf
.
zipWithIndex
.
map
({
case
(
r
,
i
)
=>
r
<>
io
.
readFpRf
(
i
)})
fpDispatch
.
io
.
re
gRdy
.
zipWithIndex
.
map
({
case
(
r
,
i
)
=>
r
<>
io
.
fpPregRdy
(
i
)})
fpDispatch
.
io
.
re
adState
.
zipWithIndex
.
map
({
case
(
r
,
i
)
=>
r
<>
io
.
readFpState
(
i
)})
fpDispatch
.
io
.
numExist
.
zipWithIndex
.
map
({
case
(
num
,
i
)
=>
num
:=
io
.
numExist
(
i
+
exuParameters
.
IntExuCnt
)})
fpDispatch
.
io
.
enqIQCtrl
.
zipWithIndex
.
map
({
case
(
enq
,
i
)
=>
enq
<>
io
.
enqIQCtrl
(
i
+
exuParameters
.
IntExuCnt
)})
// fpDispatch.io.enqIQData.zipWithIndex.map({case (enq, i) => enq <> io.enqIQData(i + exuParameters.IntExuCnt)})
...
...
@@ -103,8 +103,8 @@ class Dispatch extends XSModule {
lsDispatch
.
io
.
fromDq
<>
lsDq
.
io
.
deq
lsDispatch
.
io
.
readIntRf
.
zipWithIndex
.
map
({
case
(
r
,
i
)
=>
r
<>
io
.
readIntRf
(
i
+
8
)})
lsDispatch
.
io
.
readFpRf
.
zipWithIndex
.
map
({
case
(
r
,
i
)
=>
r
<>
io
.
readFpRf
(
i
+
12
)})
lsDispatch
.
io
.
intRegRdy
.
zipWithIndex
.
map
({
case
(
r
,
i
)
=>
r
<>
io
.
intPregRdy
(
i
+
8
)})
lsDispatch
.
io
.
fpRegRdy
.
zipWithIndex
.
map
({
case
(
r
,
i
)
=>
r
<>
io
.
fpPregRdy
(
i
+
12
)})
lsDispatch
.
io
.
readIntState
.
zipWithIndex
.
map
({
case
(
r
,
i
)
=>
r
<>
io
.
readIntState
(
i
+
8
)})
lsDispatch
.
io
.
readFpState
.
zipWithIndex
.
map
({
case
(
r
,
i
)
=>
r
<>
io
.
readFpState
(
i
+
12
)})
lsDispatch
.
io
.
numExist
.
zipWithIndex
.
map
({
case
(
num
,
i
)
=>
num
:=
io
.
numExist
(
exuParameters
.
IntExuCnt
+
exuParameters
.
FpExuCnt
+
i
)})
lsDispatch
.
io
.
enqIQCtrl
.
zipWithIndex
.
map
({
case
(
enq
,
i
)
=>
enq
<>
io
.
enqIQCtrl
(
exuParameters
.
IntExuCnt
+
exuParameters
.
FpExuCnt
+
i
)})
// lsDispatch.io.enqIQData.zipWithIndex.map({case (enq, i) => enq <> io.enqIQData(exuParameters.IntExuCnt + exuParameters.FpExuCnt + i)})
...
...
src/main/scala/xiangshan/backend/dispatch/Dispatch1.scala
浏览文件 @
51f54365
...
...
@@ -8,9 +8,10 @@ import utils._
import
xiangshan.backend.roq.
{
RoqPtr
,
RoqEnqIO
}
import
xiangshan.backend.rename.RenameBypassInfo
import
xiangshan.mem.LsqEnqIO
import
xiangshan.backend.fu.HasExceptionNO
// read rob and enqueue
class
Dispatch1
extends
XSModule
{
class
Dispatch1
extends
XSModule
with
HasExceptionNO
{
val
io
=
IO
(
new
Bundle
()
{
// from rename
val
fromRename
=
Vec
(
RenameWidth
,
Flipped
(
DecoupledIO
(
new
MicroOp
)))
...
...
@@ -45,7 +46,10 @@ class Dispatch1 extends XSModule {
*/
// valid bits for different dispatch queues
val
isInt
=
VecInit
(
io
.
fromRename
.
map
(
req
=>
FuType
.
isIntExu
(
req
.
bits
.
ctrl
.
fuType
)))
val
isBranch
=
VecInit
(
io
.
fromRename
.
map
(
req
=>
!
req
.
bits
.
cf
.
brUpdate
.
pd
.
notCFI
))
val
isBranch
=
VecInit
(
io
.
fromRename
.
map
(
req
=>
// cover auipc (a fake branch)
!
req
.
bits
.
cf
.
brUpdate
.
pd
.
notCFI
||
FuType
.
isJumpExu
(
req
.
bits
.
ctrl
.
fuType
)
))
val
isFp
=
VecInit
(
io
.
fromRename
.
map
(
req
=>
FuType
.
isFpExu
(
req
.
bits
.
ctrl
.
fuType
)))
val
isLs
=
VecInit
(
io
.
fromRename
.
map
(
req
=>
FuType
.
isMemExu
(
req
.
bits
.
ctrl
.
fuType
)))
val
isStore
=
VecInit
(
io
.
fromRename
.
map
(
req
=>
FuType
.
isStoreExu
(
req
.
bits
.
ctrl
.
fuType
)))
...
...
@@ -113,6 +117,7 @@ class Dispatch1 extends XSModule {
// thisIsBlocked: this instruction is blocked by itself (based on noSpecExec)
// nextCanOut: next instructions can out (based on blockBackward)
// notBlockedByPrevious: previous instructions can enqueue
val
hasException
=
VecInit
(
io
.
fromRename
.
map
(
r
=>
selectFrontend
(
r
.
bits
.
cf
.
exceptionVec
).
asUInt
.
orR
))
val
thisIsBlocked
=
VecInit
((
0
until
RenameWidth
).
map
(
i
=>
{
// for i > 0, when Roq is empty but dispatch1 have valid instructions to enqueue, it's blocked
if
(
i
>
0
)
isNoSpecExec
(
i
)
&&
(!
io
.
enqRoq
.
isEmpty
||
Cat
(
io
.
fromRename
.
take
(
i
).
map
(
_
.
valid
)).
orR
)
...
...
@@ -153,17 +158,17 @@ class Dispatch1 extends XSModule {
// We use notBlockedByPrevious here.
io
.
toIntDq
.
needAlloc
(
i
)
:=
io
.
fromRename
(
i
).
valid
&&
isInt
(
i
)
io
.
toIntDq
.
req
(
i
).
bits
:=
updatedUop
(
i
)
io
.
toIntDq
.
req
(
i
).
valid
:=
io
.
fromRename
(
i
).
valid
&&
isInt
(
i
)
&&
thisCanActualOut
(
i
)
&&
io
.
toIntDq
.
req
(
i
).
valid
:=
io
.
fromRename
(
i
).
valid
&&
!
hasException
(
i
)
&&
isInt
(
i
)
&&
thisCanActualOut
(
i
)
&&
io
.
enqLsq
.
canAccept
&&
io
.
enqRoq
.
canAccept
&&
io
.
toFpDq
.
canAccept
&&
io
.
toLsDq
.
canAccept
io
.
toFpDq
.
needAlloc
(
i
)
:=
io
.
fromRename
(
i
).
valid
&&
isFp
(
i
)
io
.
toFpDq
.
req
(
i
).
bits
:=
updatedUop
(
i
)
io
.
toFpDq
.
req
(
i
).
valid
:=
io
.
fromRename
(
i
).
valid
&&
isFp
(
i
)
&&
thisCanActualOut
(
i
)
&&
io
.
toFpDq
.
req
(
i
).
valid
:=
io
.
fromRename
(
i
).
valid
&&
!
hasException
(
i
)
&&
isFp
(
i
)
&&
thisCanActualOut
(
i
)
&&
io
.
enqLsq
.
canAccept
&&
io
.
enqRoq
.
canAccept
&&
io
.
toIntDq
.
canAccept
&&
io
.
toLsDq
.
canAccept
io
.
toLsDq
.
needAlloc
(
i
)
:=
io
.
fromRename
(
i
).
valid
&&
isLs
(
i
)
io
.
toLsDq
.
req
(
i
).
bits
:=
updatedUop
(
i
)
io
.
toLsDq
.
req
(
i
).
valid
:=
io
.
fromRename
(
i
).
valid
&&
isLs
(
i
)
&&
thisCanActualOut
(
i
)
&&
io
.
toLsDq
.
req
(
i
).
valid
:=
io
.
fromRename
(
i
).
valid
&&
!
hasException
(
i
)
&&
isLs
(
i
)
&&
thisCanActualOut
(
i
)
&&
io
.
enqLsq
.
canAccept
&&
io
.
enqRoq
.
canAccept
&&
io
.
toIntDq
.
canAccept
&&
io
.
toFpDq
.
canAccept
XSDebug
(
io
.
toIntDq
.
req
(
i
).
valid
,
p
"pc 0x${Hexadecimal(io.toIntDq.req(i).bits.cf.pc)} int index $i\n"
)
...
...
src/main/scala/xiangshan/backend/dispatch/Dispatch2Fp.scala
浏览文件 @
51f54365
...
...
@@ -5,13 +5,14 @@ import chisel3.util._
import
xiangshan._
import
utils._
import
xiangshan.backend.regfile.RfReadPort
import
xiangshan.backend.rename.BusyTableReadIO
import
xiangshan.backend.exu.Exu._
class
Dispatch2Fp
extends
XSModule
{
val
io
=
IO
(
new
Bundle
()
{
val
fromDq
=
Flipped
(
Vec
(
dpParams
.
FpDqDeqWidth
,
DecoupledIO
(
new
MicroOp
)))
val
readRf
=
Vec
(
NRFpReadPorts
-
exuParameters
.
StuCnt
,
Flipped
(
new
RfReadPort
(
XLEN
+
1
)))
val
re
gRdy
=
Vec
(
NRFpReadPorts
-
exuParameters
.
StuCnt
,
Input
(
Bool
()
))
val
readRf
=
Vec
(
NRFpReadPorts
-
exuParameters
.
StuCnt
,
Output
(
UInt
(
PhyRegIdxWidth
.
W
)))
val
re
adState
=
Vec
(
NRFpReadPorts
-
exuParameters
.
StuCnt
,
Flipped
(
new
BusyTableReadIO
))
val
numExist
=
Input
(
Vec
(
exuParameters
.
FpExuCnt
,
UInt
(
log2Ceil
(
IssQueSize
).
W
)))
val
enqIQCtrl
=
Vec
(
exuParameters
.
FpExuCnt
,
DecoupledIO
(
new
MicroOp
))
val
readPortIndex
=
Vec
(
exuParameters
.
FpExuCnt
,
Output
(
UInt
(
log2Ceil
((
NRFpReadPorts
-
exuParameters
.
StuCnt
)
/
3
).
W
)))
...
...
@@ -51,14 +52,20 @@ class Dispatch2Fp extends XSModule {
val
fpDynamicMapped
=
fpDynamicIndex
.
map
(
i
=>
indexVec
(
i
))
for
(
i
<-
fpStaticIndex
.
indices
)
{
val
index
=
WireInit
(
VecInit
(
fpStaticMapped
(
i
)
+:
fpDynamicMapped
))
io
.
readRf
(
3
*
i
)
.
addr
:=
io
.
fromDq
(
index
(
fpReadPortSrc
(
i
))).
bits
.
psrc1
io
.
readRf
(
3
*
i
+
1
)
.
addr
:=
io
.
fromDq
(
index
(
fpReadPortSrc
(
i
))).
bits
.
psrc2
io
.
readRf
(
3
*
i
+
2
)
.
addr
:=
io
.
fromDq
(
index
(
fpReadPortSrc
(
i
))).
bits
.
psrc3
io
.
readRf
(
3
*
i
)
:=
io
.
fromDq
(
index
(
fpReadPortSrc
(
i
))).
bits
.
psrc1
io
.
readRf
(
3
*
i
+
1
)
:=
io
.
fromDq
(
index
(
fpReadPortSrc
(
i
))).
bits
.
psrc2
io
.
readRf
(
3
*
i
+
2
)
:=
io
.
fromDq
(
index
(
fpReadPortSrc
(
i
))).
bits
.
psrc3
}
val
readPortIndex
=
Wire
(
Vec
(
exuParameters
.
FpExuCnt
,
UInt
(
2.
W
)))
fpStaticIndex
.
zipWithIndex
.
map
({
case
(
index
,
i
)
=>
readPortIndex
(
index
)
:=
i
.
U
})
fpDynamicIndex
.
zipWithIndex
.
map
({
case
(
index
,
i
)
=>
readPortIndex
(
index
)
:=
fpDynamicExuSrc
(
i
)})
for
(
i
<-
0
until
dpParams
.
IntDqDeqWidth
)
{
io
.
readState
(
3
*
i
).
req
:=
io
.
fromDq
(
i
).
bits
.
psrc1
io
.
readState
(
3
*
i
+
1
).
req
:=
io
.
fromDq
(
i
).
bits
.
psrc2
io
.
readState
(
3
*
i
+
2
).
req
:=
io
.
fromDq
(
i
).
bits
.
psrc3
}
/**
* Part 3: dispatch to reservation stations
*/
...
...
@@ -74,12 +81,12 @@ class Dispatch2Fp extends XSModule {
}
enq
.
bits
:=
io
.
fromDq
(
indexVec
(
i
)).
bits
val
src1Ready
=
VecInit
((
0
until
4
).
map
(
i
=>
io
.
re
gRdy
(
i
*
3
)
))
val
src2Ready
=
VecInit
((
0
until
4
).
map
(
i
=>
io
.
re
gRdy
(
i
*
3
+
1
)
))
val
src3Ready
=
VecInit
((
0
until
4
).
map
(
i
=>
io
.
re
gRdy
(
i
*
3
+
2
)
))
enq
.
bits
.
src1State
:=
src1Ready
(
readPortIndex
(
i
))
enq
.
bits
.
src2State
:=
src2Ready
(
readPortIndex
(
i
))
enq
.
bits
.
src3State
:=
src3Ready
(
readPortIndex
(
i
))
val
src1Ready
=
VecInit
((
0
until
4
).
map
(
i
=>
io
.
re
adState
(
i
*
3
).
resp
))
val
src2Ready
=
VecInit
((
0
until
4
).
map
(
i
=>
io
.
re
adState
(
i
*
3
+
1
).
resp
))
val
src3Ready
=
VecInit
((
0
until
4
).
map
(
i
=>
io
.
re
adState
(
i
*
3
+
2
).
resp
))
enq
.
bits
.
src1State
:=
src1Ready
(
indexVec
(
i
))
enq
.
bits
.
src2State
:=
src2Ready
(
indexVec
(
i
))
enq
.
bits
.
src3State
:=
src3Ready
(
indexVec
(
i
))
XSInfo
(
enq
.
fire
(),
p
"pc 0x${Hexadecimal(enq.bits.cf.pc)} with type ${enq.bits.ctrl.fuType} "
+
p
"srcState(${enq.bits.src1State} ${enq.bits.src2State} ${enq.bits.src3State}) "
+
...
...
src/main/scala/xiangshan/backend/dispatch/Dispatch2Int.scala
浏览文件 @
51f54365
...
...
@@ -6,12 +6,13 @@ import xiangshan._
import
utils._
import
xiangshan.backend.exu.Exu._
import
xiangshan.backend.regfile.RfReadPort
import
xiangshan.backend.rename.BusyTableReadIO
class
Dispatch2Int
extends
XSModule
{
val
io
=
IO
(
new
Bundle
()
{
val
fromDq
=
Flipped
(
Vec
(
dpParams
.
IntDqDeqWidth
,
DecoupledIO
(
new
MicroOp
)))
val
readRf
=
Vec
(
NRIntReadPorts
-
NRMemReadPorts
,
Flipped
(
new
RfReadPort
(
XLEN
)))
val
re
gRdy
=
Vec
(
NRIntReadPorts
-
NRMemReadPorts
,
Input
(
Bool
()
))
val
readRf
=
Vec
(
NRIntReadPorts
-
NRMemReadPorts
,
Output
(
UInt
(
PhyRegIdxWidth
.
W
)))
val
re
adState
=
Vec
(
NRIntReadPorts
-
NRMemReadPorts
,
Flipped
(
new
BusyTableReadIO
))
val
numExist
=
Input
(
Vec
(
exuParameters
.
IntExuCnt
,
UInt
(
log2Ceil
(
IssQueSize
).
W
)))
val
enqIQCtrl
=
Vec
(
exuParameters
.
IntExuCnt
,
DecoupledIO
(
new
MicroOp
))
val
readPortIndex
=
Vec
(
exuParameters
.
IntExuCnt
,
Output
(
UInt
(
log2Ceil
(
8
/
2
).
W
)))
...
...
@@ -58,13 +59,18 @@ class Dispatch2Int extends XSModule {
val
intDynamicMapped
=
intDynamicIndex
.
map
(
i
=>
indexVec
(
i
))
for
(
i
<-
intStaticIndex
.
indices
)
{
val
index
=
WireInit
(
VecInit
(
intStaticMapped
(
i
)
+:
intDynamicMapped
))
io
.
readRf
(
2
*
i
)
.
addr
:=
io
.
fromDq
(
index
(
intReadPortSrc
(
i
))).
bits
.
psrc1
io
.
readRf
(
2
*
i
+
1
)
.
addr
:=
io
.
fromDq
(
index
(
intReadPortSrc
(
i
))).
bits
.
psrc2
io
.
readRf
(
2
*
i
)
:=
io
.
fromDq
(
index
(
intReadPortSrc
(
i
))).
bits
.
psrc1
io
.
readRf
(
2
*
i
+
1
)
:=
io
.
fromDq
(
index
(
intReadPortSrc
(
i
))).
bits
.
psrc2
}
val
readPortIndex
=
Wire
(
Vec
(
exuParameters
.
IntExuCnt
,
UInt
(
2.
W
)))
intStaticIndex
.
zipWithIndex
.
map
({
case
(
index
,
i
)
=>
readPortIndex
(
index
)
:=
i
.
U
})
intDynamicIndex
.
zipWithIndex
.
map
({
case
(
index
,
i
)
=>
readPortIndex
(
index
)
:=
intDynamicExuSrc
(
i
)})
for
(
i
<-
0
until
dpParams
.
IntDqDeqWidth
)
{
io
.
readState
(
2
*
i
).
req
:=
io
.
fromDq
(
i
).
bits
.
psrc1
io
.
readState
(
2
*
i
+
1
).
req
:=
io
.
fromDq
(
i
).
bits
.
psrc2
}
/**
* Part 3: dispatch to reservation stations
*/
...
...
@@ -84,10 +90,11 @@ class Dispatch2Int extends XSModule {
}
enq
.
bits
:=
io
.
fromDq
(
indexVec
(
i
)).
bits
val
src1Ready
=
VecInit
((
0
until
4
).
map
(
i
=>
io
.
regRdy
(
i
*
2
)))
val
src2Ready
=
VecInit
((
0
until
4
).
map
(
i
=>
io
.
regRdy
(
i
*
2
+
1
)))
enq
.
bits
.
src1State
:=
src1Ready
(
readPortIndex
(
i
))
enq
.
bits
.
src2State
:=
src2Ready
(
readPortIndex
(
i
))
val
src1Ready
=
VecInit
((
0
until
4
).
map
(
i
=>
io
.
readState
(
i
*
2
).
resp
))
val
src2Ready
=
VecInit
((
0
until
4
).
map
(
i
=>
io
.
readState
(
i
*
2
+
1
).
resp
))
enq
.
bits
.
src1State
:=
src1Ready
(
indexVec
(
i
))
enq
.
bits
.
src2State
:=
src2Ready
(
indexVec
(
i
))
enq
.
bits
.
src3State
:=
DontCare
XSInfo
(
enq
.
fire
(),
p
"pc 0x${Hexadecimal(enq.bits.cf.pc)} with type ${enq.bits.ctrl.fuType} "
+
p
"srcState(${enq.bits.src1State} ${enq.bits.src2State}) "
+
...
...
src/main/scala/xiangshan/backend/dispatch/Dispatch2Ls.scala
浏览文件 @
51f54365
...
...
@@ -5,17 +5,18 @@ import chisel3.util._
import
xiangshan._
import
utils._
import
xiangshan.backend.regfile.RfReadPort
import
xiangshan.backend.rename.BusyTableReadIO
import
xiangshan.backend.exu.Exu._
class
Dispatch2Ls
extends
XSModule
{
val
io
=
IO
(
new
Bundle
()
{
val
fromDq
=
Flipped
(
Vec
(
dpParams
.
LsDqDeqWidth
,
DecoupledIO
(
new
MicroOp
)))
val
readIntRf
=
Vec
(
NRMemReadPorts
,
Flipped
(
new
RfReadPort
(
XLEN
)))
val
readFpRf
=
Vec
(
exuParameters
.
StuCnt
,
Flipped
(
new
RfReadPort
(
XLEN
+
1
)))
val
readIntRf
=
Vec
(
NRMemReadPorts
,
Output
(
UInt
(
PhyRegIdxWidth
.
W
)))
val
readFpRf
=
Vec
(
exuParameters
.
StuCnt
,
Output
(
UInt
(
PhyRegIdxWidth
.
W
)))
// val intRegAddr = Vec(NRMemReadPorts, Output(UInt(PhyRegIdxWidth.W)))
// val fpRegAddr = Vec(exuParameters.StuCnt, Output(UInt(PhyRegIdxWidth.W)))
val
intRegRdy
=
Vec
(
NRMemReadPorts
,
Input
(
Bool
()
))
val
fpRegRdy
=
Vec
(
exuParameters
.
StuCnt
,
Input
(
Bool
()
))
val
readIntState
=
Vec
(
NRMemReadPorts
,
Flipped
(
new
BusyTableReadIO
))
val
readFpState
=
Vec
(
exuParameters
.
StuCnt
,
Flipped
(
new
BusyTableReadIO
))
val
numExist
=
Input
(
Vec
(
exuParameters
.
LsExuCnt
,
UInt
(
log2Ceil
(
IssQueSize
).
W
)))
val
enqIQCtrl
=
Vec
(
exuParameters
.
LsExuCnt
,
DecoupledIO
(
new
MicroOp
))
})
...
...
@@ -52,12 +53,16 @@ class Dispatch2Ls extends XSModule {
val
readPort
=
Seq
(
0
,
1
,
2
,
4
)
for
(
i
<-
0
until
exuParameters
.
LsExuCnt
)
{
if
(
i
<
exuParameters
.
LduCnt
)
{
io
.
readIntRf
(
readPort
(
i
)).
addr
:=
io
.
fromDq
(
indexVec
(
i
)).
bits
.
psrc1
io
.
readIntRf
(
readPort
(
i
))
:=
io
.
fromDq
(
indexVec
(
i
)).
bits
.
psrc1
io
.
readIntState
(
readPort
(
i
)).
req
:=
io
.
fromDq
(
indexVec
(
i
)).
bits
.
psrc1
}
else
{
io
.
readFpRf
(
i
-
exuParameters
.
LduCnt
).
addr
:=
io
.
fromDq
(
indexVec
(
i
)).
bits
.
psrc2
io
.
readIntRf
(
readPort
(
i
)
).
addr
:=
io
.
fromDq
(
indexVec
(
i
)).
bits
.
psrc1
io
.
readIntRf
(
readPort
(
i
)+
1
).
addr
:=
io
.
fromDq
(
indexVec
(
i
)).
bits
.
psrc2
io
.
readFpRf
(
i
-
exuParameters
.
LduCnt
)
:=
io
.
fromDq
(
indexVec
(
i
)).
bits
.
psrc2
io
.
readIntRf
(
readPort
(
i
)
)
:=
io
.
fromDq
(
indexVec
(
i
)).
bits
.
psrc1
io
.
readIntRf
(
readPort
(
i
)+
1
)
:=
io
.
fromDq
(
indexVec
(
i
)).
bits
.
psrc2
io
.
readFpState
(
i
-
exuParameters
.
LduCnt
).
req
:=
io
.
fromDq
(
indexVec
(
i
)).
bits
.
psrc2
io
.
readIntState
(
readPort
(
i
)
).
req
:=
io
.
fromDq
(
indexVec
(
i
)).
bits
.
psrc1
io
.
readIntState
(
readPort
(
i
)+
1
).
req
:=
io
.
fromDq
(
indexVec
(
i
)).
bits
.
psrc2
}
}
...
...
@@ -75,14 +80,15 @@ class Dispatch2Ls extends XSModule {
enq
.
valid
:=
storeIndexGen
.
io
.
mapping
(
i
-
exuParameters
.
LduCnt
).
valid
&&
storeReady
}
enq
.
bits
:=
io
.
fromDq
(
indexVec
(
i
)).
bits
enq
.
bits
.
src1State
:=
io
.
intRegRdy
(
readPort
(
i
))
enq
.
bits
.
src1State
:=
io
.
readIntState
(
readPort
(
i
)).
resp
if
(
i
<
exuParameters
.
LduCnt
)
{
enq
.
bits
.
src2State
:=
DontCare
}
else
{
enq
.
bits
.
src2State
:=
Mux
(
io
.
fromDq
(
indexVec
(
i
)).
bits
.
ctrl
.
src2Type
===
SrcType
.
fp
,
io
.
fpRegRdy
(
i
-
exuParameters
.
LduCnt
),
io
.
intRegRdy
(
readPort
(
i
)
+
1
)
)
io
.
readFpState
(
i
-
exuParameters
.
LduCnt
).
resp
,
io
.
readIntState
(
readPort
(
i
)
+
1
).
resp
)
}
enq
.
bits
.
src3State
:=
DontCare
XSInfo
(
enq
.
fire
(),
p
"pc 0x${Hexadecimal(enq.bits.cf.pc)} with type ${enq.bits.ctrl.fuType} "
+
p
"srcState(${enq.bits.src1State} ${enq.bits.src2State}) "
+
...
...
src/main/scala/xiangshan/backend/exu/Exu.scala
浏览文件 @
51f54365
...
...
@@ -100,7 +100,7 @@ abstract class Exu(val config: ExuConfig) extends XSModule {
val
src2
=
in
.
bits
.
src2
val
src3
=
in
.
bits
.
src3
fu
.
io
.
in
.
valid
:=
in
.
valid
&&
sel
&&
!
in
.
bits
.
uop
.
roqIdx
.
needFlush
(
io
.
redirect
)
fu
.
io
.
in
.
valid
:=
in
.
valid
&&
sel
fu
.
io
.
in
.
bits
.
uop
:=
in
.
bits
.
uop
fu
.
io
.
in
.
bits
.
src
.
foreach
(
_
<>
DontCare
)
if
(
fuCfg
.
srcCnt
>
0
)
{
...
...
@@ -120,6 +120,13 @@ abstract class Exu(val config: ExuConfig) extends XSModule {
def
writebackArb
(
in
:
Seq
[
DecoupledIO
[
FuOutput
]],
out
:
DecoupledIO
[
ExuOutput
])
:
Arbiter
[
FuOutput
]
=
{
if
(
needArbiter
)
{
if
(
in
.
size
==
1
){
in
.
head
.
ready
:=
out
.
ready
out
.
bits
.
data
:=
in
.
head
.
bits
.
data
out
.
bits
.
uop
:=
in
.
head
.
bits
.
uop
out
.
valid
:=
in
.
head
.
valid
null
}
else
{
val
arb
=
Module
(
new
Arbiter
(
new
FuOutput
(
in
.
head
.
bits
.
len
),
in
.
size
))
arb
.
io
.
in
<>
in
arb
.
io
.
out
.
ready
:=
out
.
ready
...
...
@@ -127,6 +134,7 @@ abstract class Exu(val config: ExuConfig) extends XSModule {
out
.
bits
.
uop
:=
arb
.
io
.
out
.
bits
.
uop
out
.
valid
:=
arb
.
io
.
out
.
valid
arb
}
}
else
{
in
.
foreach
(
_
.
ready
:=
out
.
ready
)
val
sel
=
Mux1H
(
in
.
map
(
x
=>
x
.
valid
->
x
))
...
...
src/main/scala/xiangshan/backend/exu/FmiscExeUnit.scala
浏览文件 @
51f54365
...
...
@@ -14,8 +14,8 @@ class FmiscExeUnit extends Exu(fmiscExeUnitCfg) {
val
toFpUnits
=
Seq
(
f2f
,
fdivSqrt
)
val
toIntUnits
=
Seq
(
f2i
)
assert
(
fpArb
.
io
.
in
.
length
==
toFpUnits
.
size
)
assert
(
intArb
.
io
.
in
.
length
==
toIntUnits
.
size
)
assert
(
toFpUnits
.
size
==
1
||
fpArb
.
io
.
in
.
length
==
toFpUnits
.
size
)
assert
(
toIntUnits
.
size
==
1
||
intArb
.
io
.
in
.
length
==
toIntUnits
.
size
)
val
input
=
io
.
fromFp
val
isRVF
=
input
.
bits
.
uop
.
ctrl
.
isRVF
...
...
src/main/scala/xiangshan/backend/exu/Wb.scala
浏览文件 @
51f54365
...
...
@@ -56,15 +56,20 @@ class Wb(cfgs: Seq[ExuConfig], numOut: Int, isFp: Boolean) extends XSModule {
mulReq
.
size
)
val
arbiters
=
for
(
i
<-
mulReq
.
indices
)
yield
{
for
(
i
<-
mulReq
.
indices
)
{
val
out
=
io
.
out
(
directConnect
.
size
+
i
)
val
other
=
arbReq
(
i
).
getOrElse
(
Seq
())
if
(
other
.
isEmpty
){
out
.
valid
:=
mulReq
(
i
).
valid
out
.
bits
:=
mulReq
(
i
).
bits
mulReq
(
i
).
ready
:=
true
.
B
}
else
{
val
arb
=
Module
(
new
Arbiter
(
new
ExuOutput
,
1
+
other
.
size
))
arb
.
io
.
in
<>
mulReq
(
i
)
+:
other
val
out
=
io
.
out
(
directConnect
.
size
+
i
)
out
.
valid
:=
arb
.
io
.
out
.
valid
out
.
bits
:=
arb
.
io
.
out
.
bits
arb
.
io
.
out
.
ready
:=
true
.
B
arb
}
}
if
(
portUsed
<
numOut
){
...
...
@@ -78,10 +83,11 @@ class Wb(cfgs: Seq[ExuConfig], numOut: Int, isFp: Boolean) extends XSModule {
}
for
(
i
<-
mulReq
.
indices
){
sb
.
append
(
s
"[ ${cfgs(io.in.indexOf(mulReq(i))).name} "
)
val
useArb
=
arbReq
(
i
).
nonEmpty
for
(
req
<-
arbReq
(
i
).
getOrElse
(
Nil
)){
sb
.
append
(
s
"${cfgs(io.in.indexOf(req)).name} "
)
}
sb
.
append
(
s
"] ->
arb ->
out #${directConnect.size + i}\n"
)
sb
.
append
(
s
"] ->
${if(useArb) "
arb
->
" else ""}
out #${directConnect.size + i}\n"
)
}
println
(
sb
)
...
...
src/main/scala/xiangshan/backend/fu/CSR.scala
浏览文件 @
51f54365
...
...
@@ -47,6 +47,67 @@ trait HasExceptionNO {
storeAddrMisaligned
,
loadAddrMisaligned
)
val
frontendSet
=
List
(
// instrAddrMisaligned,
instrAccessFault
,
illegalInstr
,
instrPageFault
)
val
csrSet
=
List
(
illegalInstr
,
breakPoint
,
ecallU
,
ecallS
,
ecallM
)
val
loadUnitSet
=
List
(
loadAddrMisaligned
,
loadAccessFault
,
loadPageFault
)
val
storeUnitSet
=
List
(
storeAddrMisaligned
,
storeAccessFault
,
storePageFault
)
val
atomicsUnitSet
=
(
loadUnitSet
++
storeUnitSet
).
distinct
val
allPossibleSet
=
(
frontendSet
++
csrSet
++
loadUnitSet
++
storeUnitSet
).
distinct
val
csrWbCount
=
(
0
until
16
).
map
(
i
=>
if
(
csrSet
.
contains
(
i
))
1
else
0
)
val
loadWbCount
=
(
0
until
16
).
map
(
i
=>
if
(
loadUnitSet
.
contains
(
i
))
1
else
0
)
val
storeWbCount
=
(
0
until
16
).
map
(
i
=>
if
(
storeUnitSet
.
contains
(
i
))
1
else
0
)
val
atomicsWbCount
=
(
0
until
16
).
map
(
i
=>
if
(
atomicsUnitSet
.
contains
(
i
))
1
else
0
)
val
writebackCount
=
(
0
until
16
).
map
(
i
=>
csrWbCount
(
i
)
+
atomicsWbCount
(
i
)
+
loadWbCount
(
i
)
+
2
*
storeWbCount
(
i
))
def
partialSelect
(
vec
:
Vec
[
Bool
],
select
:
Seq
[
Int
],
dontCareBits
:
Boolean
=
true
,
falseBits
:
Boolean
=
false
)
:
Vec
[
Bool
]
=
{
if
(
dontCareBits
)
{
val
new_vec
=
Wire
(
ExceptionVec
())
new_vec
:=
DontCare
select
.
map
(
i
=>
new_vec
(
i
)
:=
vec
(
i
))
return
new_vec
}
else
if
(
falseBits
)
{
val
new_vec
=
Wire
(
ExceptionVec
())
new_vec
.
map
(
_
:=
false
.
B
)
select
.
map
(
i
=>
new_vec
(
i
)
:=
vec
(
i
))
return
new_vec
}
else
{
val
new_vec
=
Wire
(
Vec
(
select
.
length
,
Bool
()))
select
.
zipWithIndex
.
map
{
case
(
s
,
i
)
=>
new_vec
(
i
)
:=
vec
(
s
)
}
return
new_vec
}
}
def
selectFrontend
(
vec
:
Vec
[
Bool
],
dontCareBits
:
Boolean
=
true
,
falseBits
:
Boolean
=
false
)
:
Vec
[
Bool
]
=
partialSelect
(
vec
,
frontendSet
,
dontCareBits
,
falseBits
)
def
selectCSR
(
vec
:
Vec
[
Bool
],
dontCareBits
:
Boolean
=
true
,
falseBits
:
Boolean
=
false
)
:
Vec
[
Bool
]
=
partialSelect
(
vec
,
csrSet
,
dontCareBits
,
falseBits
)
def
selectLoad
(
vec
:
Vec
[
Bool
],
dontCareBits
:
Boolean
=
true
,
falseBits
:
Boolean
=
false
)
:
Vec
[
Bool
]
=
partialSelect
(
vec
,
loadUnitSet
,
dontCareBits
,
falseBits
)
def
selectStore
(
vec
:
Vec
[
Bool
],
dontCareBits
:
Boolean
=
true
,
falseBits
:
Boolean
=
false
)
:
Vec
[
Bool
]
=
partialSelect
(
vec
,
storeUnitSet
,
dontCareBits
,
falseBits
)
def
selectAtomics
(
vec
:
Vec
[
Bool
],
dontCareBits
:
Boolean
=
true
,
falseBits
:
Boolean
=
false
)
:
Vec
[
Bool
]
=
partialSelect
(
vec
,
atomicsUnitSet
,
dontCareBits
,
falseBits
)
def
selectAll
(
vec
:
Vec
[
Bool
],
dontCareBits
:
Boolean
=
true
,
falseBits
:
Boolean
=
false
)
:
Vec
[
Bool
]
=
partialSelect
(
vec
,
allPossibleSet
,
dontCareBits
,
falseBits
)
}
class
FpuCsrIO
extends
XSBundle
{
...
...
@@ -175,7 +236,7 @@ class CSR extends FunctionUnit with HasCSRConst
val
mimpid
=
RegInit
(
UInt
(
XLEN
.
W
),
0.
U
)
// provides a unique encoding of the version of the processor implementation
val
mhartNo
=
hartId
()
val
mhartid
=
RegInit
(
UInt
(
XLEN
.
W
),
mhartNo
.
asUInt
)
// the hardware thread running the code
val
mstatus
=
RegInit
(
UInt
(
XLEN
.
W
),
"h00001800"
.
U
)
// another option: "h8000c0100".U
val
mstatus
=
RegInit
(
UInt
(
XLEN
.
W
),
0.
U
)
// mstatus Value Table
// | sd |
...
...
@@ -430,7 +491,7 @@ class CSR extends FunctionUnit with HasCSRConst
(
if
(
HasFPU
)
fcsrMapping
else
Nil
)
val
addr
=
src2
(
11
,
0
)
val
csri
=
src2
(
16
,
12
)
val
csri
=
ZeroExt
(
src2
(
16
,
12
),
XLEN
)
val
rdata
=
Wire
(
UInt
(
XLEN
.
W
))
val
wdata
=
LookupTree
(
func
,
List
(
CSROpType
.
wrt
->
src1
,
...
...
@@ -441,14 +502,17 @@ class CSR extends FunctionUnit with HasCSRConst
CSROpType
.
clri
->
(
rdata
&
(~
csri
).
asUInt
())
))
csrio
.
isPerfCnt
:=
(
addr
>=
Mcycle
.
U
)
&&
(
addr
<=
Mhpmcounter31
.
U
)
val
addrInPerfCnt
=
(
addr
>=
Mcycle
.
U
)
&&
(
addr
<=
Mhpmcounter31
.
U
)
csrio
.
isPerfCnt
:=
addrInPerfCnt
// satp wen check
val
satpLegalMode
=
(
wdata
.
asTypeOf
(
new
SatpStruct
).
mode
===
0.
U
)
||
(
wdata
.
asTypeOf
(
new
SatpStruct
).
mode
===
8.
U
)
// general CSR wen check
val
wen
=
valid
&&
func
=/=
CSROpType
.
jmp
&&
(
addr
=/=
Satp
.
U
||
satpLegalMode
)
val
permitted
=
csrAccessPermissionCheck
(
addr
,
false
.
B
,
priviledgeMode
)
val
modePermitted
=
csrAccessPermissionCheck
(
addr
,
false
.
B
,
priviledgeMode
)
val
perfcntPermitted
=
perfcntPermissionCheck
(
addr
,
priviledgeMode
,
mcounteren
,
scounteren
)
val
permitted
=
Mux
(
addrInPerfCnt
,
perfcntPermitted
,
modePermitted
)
// Writeable check is ingored.
// Currently, write to illegal csr addr will be ignored
MaskedRegMap
.
generate
(
mapping
,
addr
,
rdata
,
wen
&&
permitted
,
wdata
)
...
...
@@ -580,6 +644,17 @@ class CSR extends FunctionUnit with HasCSRConst
io
.
in
.
ready
:=
true
.
B
io
.
out
.
valid
:=
valid
val
csrExceptionVec
=
WireInit
(
cfIn
.
exceptionVec
)
csrExceptionVec
(
breakPoint
)
:=
io
.
in
.
valid
&&
isEbreak
csrExceptionVec
(
ecallM
)
:=
priviledgeMode
===
ModeM
&&
io
.
in
.
valid
&&
isEcall
csrExceptionVec
(
ecallS
)
:=
priviledgeMode
===
ModeS
&&
io
.
in
.
valid
&&
isEcall
csrExceptionVec
(
ecallU
)
:=
priviledgeMode
===
ModeU
&&
io
.
in
.
valid
&&
isEcall
// Trigger an illegal instr exception when:
// * unimplemented csr is being read/written
// * csr access is illegal
csrExceptionVec
(
illegalInstr
)
:=
(
isIllegalAddr
||
isIllegalAccess
)
&&
wen
cfOut
.
exceptionVec
:=
csrExceptionVec
/**
* Exception and Intr
*/
...
...
@@ -609,24 +684,11 @@ class CSR extends FunctionUnit with HasCSRConst
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
hasInstrAccessFault
=
csrio
.
exception
.
bits
.
cf
.
exceptionVec
(
instrAccessFault
)
&&
raiseException
val
hasLoadAccessFault
=
csrio
.
exception
.
bits
.
cf
.
exceptionVec
(
loadAccessFault
)
&&
raiseException
val
hasStoreAccessFault
=
csrio
.
exception
.
bits
.
cf
.
exceptionVec
(
storeAccessFault
)
&&
raiseException
val
csrExceptionVec
=
Wire
(
Vec
(
16
,
Bool
()))
csrExceptionVec
.
map
(
_
:=
false
.
B
)
csrExceptionVec
(
breakPoint
)
:=
io
.
in
.
valid
&&
isEbreak
csrExceptionVec
(
ecallM
)
:=
priviledgeMode
===
ModeM
&&
io
.
in
.
valid
&&
isEcall
csrExceptionVec
(
ecallS
)
:=
priviledgeMode
===
ModeS
&&
io
.
in
.
valid
&&
isEcall
csrExceptionVec
(
ecallU
)
:=
priviledgeMode
===
ModeU
&&
io
.
in
.
valid
&&
isEcall
// Trigger an illegal instr exception when:
// * unimplemented csr is being read/written
// * csr access is illegal
csrExceptionVec
(
illegalInstr
)
:=
(
isIllegalAddr
||
isIllegalAccess
)
&&
wen
csrExceptionVec
(
loadPageFault
)
:=
hasLoadPageFault
csrExceptionVec
(
storePageFault
)
:=
hasStorePageFault
val
iduExceptionVec
=
cfIn
.
exceptionVec
val
exceptionVec
=
csrExceptionVec
.
asUInt
()
|
iduExceptionVec
.
asUInt
()
cfOut
.
exceptionVec
.
zipWithIndex
.
map
{
case
(
e
,
i
)
=>
e
:=
exceptionVec
(
i
)
}
val
raiseExceptionVec
=
csrio
.
exception
.
bits
.
cf
.
exceptionVec
.
asUInt
()
val
raiseExceptionVec
=
csrio
.
exception
.
bits
.
cf
.
exceptionVec
val
exceptionNO
=
ExcPriority
.
foldRight
(
0.
U
)((
i
:
Int
,
sum
:
UInt
)
=>
Mux
(
raiseExceptionVec
(
i
),
i
.
U
,
sum
))
val
causeNO
=
(
raiseIntr
<<
(
XLEN
-
1
)).
asUInt
()
|
Mux
(
raiseIntr
,
intrNO
,
exceptionNO
)
...
...
@@ -738,6 +800,11 @@ class CSR extends FunctionUnit with HasCSRConst
"PtwL2TlbHit"
->
(
0x1027
,
"perfCntPtwL2TlbHit"
),
"ICacheReq"
->
(
0x1028
,
"perfCntIcacheReqCnt"
),
"ICacheMiss"
->
(
0x1029
,
"perfCntIcacheMissCnt"
),
"ICacheMMIO"
->
(
0x102a
,
"perfCntIcacheMMIOCnt"
),
// "FetchFromLoopBuffer" -> (0x102b, "CntFetchFromLoopBuffer"),
// "ExitLoop1" -> (0x102c, "CntExitLoop1"),
// "ExitLoop2" -> (0x102d, "CntExitLoop2"),
// "ExitLoop3" -> (0x102e, "CntExitLoop3")
"ubtbRight"
->
(
0x1030
,
"perfCntubtbRight"
),
"ubtbWrong"
->
(
0x1031
,
"perfCntubtbWrong"
),
...
...
src/main/scala/xiangshan/backend/fu/Fence.scala
浏览文件 @
51f54365
...
...
@@ -20,41 +20,51 @@ class Fence extends FunctionUnit{ // TODO: check it
val
fencei
=
IO
(
Output
(
Bool
()))
val
toSbuffer
=
IO
(
new
FenceToSbuffer
)
val
(
valid
,
src1
,
uop
,
func
,
lsrc1
,
lsrc2
)
=
(
val
(
valid
,
src1
)
=
(
io
.
in
.
valid
,
io
.
in
.
bits
.
src
(
0
),
io
.
in
.
bits
.
uop
,
io
.
in
.
bits
.
uop
.
ctrl
.
fuOpType
,
io
.
in
.
bits
.
uop
.
ctrl
.
lsrc1
,
io
.
in
.
bits
.
uop
.
ctrl
.
lsrc2
io
.
in
.
bits
.
src
(
0
)
)
val
s_sb
::
s_tlb
::
s_icache
::
s_none
::
Nil
=
Enum
(
4
)
val
state
=
RegInit
(
s_sb
)
val
s_idle
::
s_wait
::
s_tlb
::
s_icache
::
s_fence
::
Nil
=
Enum
(
5
)
val
state
=
RegInit
(
s_idle
)
/* fsm
* s_idle : init state, send sbflush
* s_wait : send sbflush, wait for sbEmpty
* s_tlb : flush tlb, just hold one cycle
* s_icache: flush icache, just hold one cycle
* s_fence : do nothing, for timing optimiaztion
*/
val
sbuffer
=
toSbuffer
.
flushSb
val
sbEmpty
=
toSbuffer
.
sbIsEmpty
val
uop
=
RegEnable
(
io
.
in
.
bits
.
uop
,
io
.
in
.
fire
())
val
func
=
uop
.
ctrl
.
fuOpType
val
lsrc1
=
uop
.
ctrl
.
lsrc1
val
lsrc2
=
uop
.
ctrl
.
lsrc2
// NOTE: icache & tlb & sbuffer must receive flush signal at any time
sbuffer
:=
valid
&&
state
===
s_sb
&&
!
sbEmpty
fencei
:=
(
state
===
s_icache
&&
sbEmpty
)
||
(
state
===
s_sb
&&
valid
&&
sbEmpty
&&
func
===
FenceOpType
.
fencei
)
sfence
.
valid
:=
(
state
===
s_tlb
&&
sbEmpty
)
||
(
state
===
s_sb
&&
valid
&&
sbEmpty
&&
func
===
FenceOpType
.
sfence
)
sfence
.
bits
.
rs1
:=
Mux
(
state
===
s_sb
,
lsrc1
===
0.
U
,
RegEnable
(
lsrc1
===
0.
U
,
io
.
in
.
fire
()))
sfence
.
bits
.
rs2
:=
Mux
(
state
===
s_sb
,
lsrc2
===
0.
U
,
RegEnable
(
lsrc2
===
0.
U
,
io
.
in
.
fire
()))
sfence
.
bits
.
addr
:=
Mux
(
state
===
s_sb
,
src1
,
RegEnable
(
src1
,
io
.
in
.
fire
()))
when
(
state
===
s_sb
&&
valid
&&
func
===
FenceOpType
.
fencei
&&
!
sbEmpty
)
{
state
:=
s_icache
}
when
(
state
===
s_sb
&&
valid
&&
func
===
FenceOpType
.
sfence
&&
!
sbEmpty
)
{
state
:=
s_tlb
}
when
(
state
===
s_sb
&&
valid
&&
func
===
FenceOpType
.
fence
&&
!
sbEmpty
)
{
state
:=
s_none
}
when
(
state
=/=
s_sb
&&
sbEmpty
)
{
state
:=
s_sb
}
sbuffer
:=
state
===
s_wait
fencei
:=
state
===
s_icache
sfence
.
valid
:=
state
===
s_tlb
sfence
.
bits
.
rs1
:=
lsrc1
===
0.
U
sfence
.
bits
.
rs2
:=
lsrc2
===
0.
U
sfence
.
bits
.
addr
:=
RegEnable
(
src1
,
io
.
in
.
fire
())
assert
(!(
io
.
out
.
valid
&&
io
.
out
.
bits
.
uop
.
ctrl
.
rfWen
))
io
.
in
.
ready
:=
state
===
s_sb
io
.
out
.
valid
:=
(
state
=/=
s_sb
&&
sbEmpty
)
||
(
state
===
s_sb
&&
sbEmpty
&&
valid
)
when
(
state
===
s_idle
&&
valid
)
{
state
:=
s_wait
}
when
(
state
===
s_wait
&&
func
===
FenceOpType
.
fencei
&&
sbEmpty
)
{
state
:=
s_icache
}
when
(
state
===
s_wait
&&
func
===
FenceOpType
.
sfence
&&
sbEmpty
)
{
state
:=
s_tlb
}
when
(
state
===
s_wait
&&
func
===
FenceOpType
.
fence
&&
sbEmpty
)
{
state
:=
s_fence
}
when
(
state
=/=
s_idle
&&
state
=/=
s_wait
)
{
state
:=
s_idle
}
io
.
in
.
ready
:=
state
===
s_idle
io
.
out
.
valid
:=
state
=/=
s_idle
&&
state
=/=
s_wait
io
.
out
.
bits
.
data
:=
DontCare
io
.
out
.
bits
.
uop
:=
Mux
(
state
===
s_sb
,
uop
,
RegEnable
(
uop
,
io
.
in
.
fire
()))
io
.
out
.
bits
.
uop
:=
uop
assert
(!(
valid
||
state
=/=
s_sb
)
||
io
.
out
.
ready
)
// NOTE: fence instr must be the first(only one) instr, so io.out.ready must be true
XSDebug
(
valid
,
p
"In(${io.in.valid} ${io.in.ready}) state:${state} Inpc:0x${Hexadecimal(io.in.bits.uop.cf.pc)} InroqIdx:${io.in.bits.uop.roqIdx}\n"
)
XSDebug
(
state
=/=
s_idle
,
p
"state:${state} sbuffer(flush:${sbuffer} empty:${sbEmpty}) fencei:${fencei} sfence:${sfence}\n"
)
XSDebug
(
io
.
out
.
valid
,
p
" Out(${io.out.valid} ${io.out.ready}) state:${state} Outpc:0x${Hexadecimal(io.out.bits.uop.cf.pc)} OutroqIdx:${io.out.bits.uop.roqIdx}\n"
)
XSDebug
(
valid
||
state
=/=
s_sb
||
io
.
out
.
valid
,
p
"In(${io.in.valid} ${io.in.ready}) Out(${io.out.valid} ${io.out.ready}) state:${state} sbuffer(flush:${sbuffer} empty:${sbEmpty}) fencei:${fencei} sfence:${sfence} Inpc:0x${Hexadecimal(io.in.bits.uop.cf.pc)} InroqIdx:${io.in.bits.uop.roqIdx} Outpc:0x${Hexadecimal(io.out.bits.uop.cf.pc)} OutroqIdx:${io.out.bits.uop.roqIdx}\n"
)
assert
(!(
io
.
out
.
valid
&&
io
.
out
.
bits
.
uop
.
ctrl
.
rfWen
))
assert
(!
io
.
out
.
valid
||
io
.
out
.
ready
,
"when fence is out valid, out ready should always be true"
)
}
\ No newline at end of file
src/main/scala/xiangshan/backend/fu/Jump.scala
浏览文件 @
51f54365
...
...
@@ -25,10 +25,13 @@ class Jump extends FunctionUnit with HasRedirectOut {
io
.
in
.
bits
.
uop
)
val
offset
=
SignExt
(
Mux
(
JumpOpType
.
jumpOpIsJal
(
func
),
ImmUnion
.
J
.
toImm32
(
immMin
),
ImmUnion
.
I
.
toImm32
(
immMin
)
),
XLEN
)
val
isJalr
=
JumpOpType
.
jumpOpisJalr
(
func
)
val
isAuipc
=
JumpOpType
.
jumpOpisAuipc
(
func
)
val
offset
=
SignExt
(
Mux1H
(
Seq
(
isJalr
->
ImmUnion
.
I
.
toImm32
(
immMin
),
isAuipc
->
ImmUnion
.
U
.
toImm32
(
immMin
),
!(
isJalr
||
isAuipc
)
->
ImmUnion
.
J
.
toImm32
(
immMin
)
)),
XLEN
)
val
redirectHit
=
uop
.
roqIdx
.
needFlush
(
io
.
redirectIn
)
val
valid
=
io
.
in
.
valid
...
...
@@ -53,7 +56,7 @@ class Jump extends FunctionUnit with HasRedirectOut {
brUpdate
.
taken
:=
true
.
B
// Output
val
res
=
snpc
val
res
=
Mux
(
JumpOpType
.
jumpOpisAuipc
(
func
),
target
,
snpc
)
io
.
in
.
ready
:=
io
.
out
.
ready
io
.
out
.
valid
:=
valid
...
...
src/main/scala/xiangshan/backend/fu/Radix2Divider.scala
浏览文件 @
51f54365
...
...
@@ -41,7 +41,7 @@ class Radix2Divider(len: Int) extends AbstractDivider(len) {
val
uopReg
=
RegEnable
(
uop
,
newReq
)
val
cnt
=
Counter
(
len
)
when
(
newReq
)
{
when
(
newReq
&&
!
io
.
in
.
bits
.
uop
.
roqIdx
.
needFlush
(
io
.
redirectIn
)
)
{
state
:=
s_log2
}
.
elsewhen
(
state
===
s_log2
)
{
// `canSkipShift` is calculated as following:
...
...
@@ -85,6 +85,6 @@ class Radix2Divider(len: Int) extends AbstractDivider(len) {
io
.
out
.
bits
.
data
:=
Mux
(
ctrlReg
.
isW
,
SignExt
(
res
(
31
,
0
),
xlen
),
res
)
io
.
out
.
bits
.
uop
:=
uopReg
io
.
out
.
valid
:=
state
===
s_finish
&&
!
kill
io
.
out
.
valid
:=
state
===
s_finish
io
.
in
.
ready
:=
state
===
s_idle
}
\ No newline at end of file
src/main/scala/xiangshan/backend/fu/SRT4Divider.scala
浏览文件 @
51f54365
...
...
@@ -37,7 +37,9 @@ class SRT4Divider(len: Int) extends AbstractDivider(len) {
switch
(
state
){
is
(
s_idle
){
when
(
io
.
in
.
fire
()){
state
:=
Mux
(
divZero
,
s_finish
,
s_lzd
)
}
when
(
io
.
in
.
fire
()
&&
!
io
.
in
.
bits
.
uop
.
roqIdx
.
needFlush
(
io
.
redirectIn
))
{
state
:=
Mux
(
divZero
,
s_finish
,
s_lzd
)
}
}
is
(
s_lzd
){
// leading zero detection
state
:=
s_normlize
...
...
@@ -220,7 +222,7 @@ class SRT4Divider(len: Int) extends AbstractDivider(len) {
)
io
.
in
.
ready
:=
state
===
s_idle
io
.
out
.
valid
:=
state
===
s_finish
&&
!
kill
io
.
out
.
valid
:=
state
===
s_finish
io
.
out
.
bits
.
data
:=
Mux
(
ctrlReg
.
isW
,
SignExt
(
res
(
31
,
0
),
len
),
res
...
...
src/main/scala/xiangshan/backend/fu/fpu/FDivSqrt.scala
浏览文件 @
51f54365
...
...
@@ -47,7 +47,7 @@ class FDivSqrt extends FPUSubModule {
val
src1
=
unbox
(
io
.
in
.
bits
.
src
(
0
),
tag
,
None
)
val
src2
=
unbox
(
io
.
in
.
bits
.
src
(
1
),
tag
,
None
)
divSqrt
.
io
.
inValid
:=
io
.
in
.
fire
()
divSqrt
.
io
.
inValid
:=
io
.
in
.
fire
()
&&
!
io
.
in
.
bits
.
uop
.
roqIdx
.
needFlush
(
io
.
redirectIn
)
divSqrt
.
io
.
sqrtOp
:=
fpCtrl
.
sqrt
divSqrt
.
io
.
a
:=
src1
divSqrt
.
io
.
b
:=
src2
...
...
@@ -74,7 +74,7 @@ class FDivSqrt extends FPUSubModule {
val
flags
=
Mux
(
single
,
round32
.
io
.
exceptionFlags
,
round64
.
io
.
exceptionFlags
)
io
.
in
.
ready
:=
state
===
s_idle
io
.
out
.
valid
:=
state
===
s_finish
&&
!
(
killReg
||
kill
)
io
.
out
.
valid
:=
state
===
s_finish
&&
!
killReg
io
.
out
.
bits
.
uop
:=
uopReg
io
.
out
.
bits
.
data
:=
RegNext
(
data
,
divSqrtRawValid
)
fflags
:=
RegNext
(
flags
,
divSqrtRawValid
)
...
...
src/main/scala/xiangshan/backend/fu/fpu/FPToFP.scala
浏览文件 @
51f54365
...
...
@@ -12,14 +12,16 @@ class FPToFP extends FPUPipelineModule{
override
def
latency
:
Int
=
FunctionUnit
.
f2iCfg
.
latency
.
latencyVal
.
get
val
ctrl
=
io
.
in
.
bits
.
uop
.
ctrl
.
fpu
val
ctrlIn
=
io
.
in
.
bits
.
uop
.
ctrl
.
fpu
val
ctrl
=
S1Reg
(
ctrlIn
)
val
inTag
=
ctrl
.
typeTagIn
val
outTag
=
ctrl
.
typeTagOut
val
src1
=
unbox
(
io
.
in
.
bits
.
src
(
0
),
inTag
,
None
)
val
src2
=
unbox
(
io
.
in
.
bits
.
src
(
1
),
inTag
,
None
)
val
wflags
=
ctrl
.
wflags
val
src1
=
S1Reg
(
unbox
(
io
.
in
.
bits
.
src
(
0
),
ctrlIn
.
typeTagIn
,
None
))
val
src2
=
S1Reg
(
unbox
(
io
.
in
.
bits
.
src
(
1
),
ctrlIn
.
typeTagIn
,
None
))
val
rmReg
=
S1Reg
(
rm
)
val
signNum
=
Mux
(
rm
(
1
),
src1
^
src2
,
Mux
(
rm
(
0
),
~
src2
,
src2
))
val
signNum
=
Mux
(
rm
Reg
(
1
),
src1
^
src2
,
Mux
(
rmReg
(
0
),
~
src2
,
src2
))
val
fsgnj
=
Cat
(
signNum
(
fLen
),
src1
(
fLen
-
1
,
0
))
val
fsgnjMux
=
Wire
(
new
Bundle
()
{
...
...
@@ -32,7 +34,7 @@ class FPToFP extends FPUPipelineModule{
val
dcmp
=
Module
(
new
CompareRecFN
(
maxExpWidth
,
maxSigWidth
))
dcmp
.
io
.
a
:=
src1
dcmp
.
io
.
b
:=
src2
dcmp
.
io
.
signaling
:=
!
rm
(
1
)
dcmp
.
io
.
signaling
:=
!
rm
Reg
(
1
)
val
lt
=
dcmp
.
io
.
lt
||
(
dcmp
.
io
.
a
.
asSInt
()
<
0.
S
&&
dcmp
.
io
.
b
.
asSInt
()
>=
0.
S
)
...
...
@@ -41,7 +43,7 @@ class FPToFP extends FPUPipelineModule{
val
isnan2
=
maxType
.
isNaN
(
src2
)
val
isInvalid
=
maxType
.
isSNaN
(
src1
)
||
maxType
.
isSNaN
(
src2
)
val
isNaNOut
=
isnan1
&&
isnan2
val
isLHS
=
isnan2
||
rm
(
0
)
=/=
lt
&&
!
isnan1
val
isLHS
=
isnan2
||
rm
Reg
(
0
)
=/=
lt
&&
!
isnan1
fsgnjMux
.
exc
:=
isInvalid
<<
4
fsgnjMux
.
data
:=
Mux
(
isNaNOut
,
maxType
.
qNaN
,
Mux
(
isLHS
,
src1
,
src2
))
}
...
...
@@ -67,7 +69,7 @@ class FPToFP extends FPUPipelineModule{
when
(
outTag
===
typeTag
(
outType
).
U
&&
(
typeTag
(
outType
)
==
0
).
B
||
(
outTag
<
inTag
)){
val
narrower
=
Module
(
new
hardfloat
.
RecFNToRecFN
(
maxType
.
exp
,
maxType
.
sig
,
outType
.
exp
,
outType
.
sig
))
narrower
.
io
.
in
:=
src1
narrower
.
io
.
roundingMode
:=
rm
narrower
.
io
.
roundingMode
:=
rm
Reg
narrower
.
io
.
detectTininess
:=
hardfloat
.
consts
.
tininess_afterRounding
val
narrowed
=
sanitizeNaN
(
narrower
.
io
.
out
,
outType
)
mux
.
data
:=
Cat
(
fsgnjMux
.
data
>>
narrowed
.
getWidth
,
narrowed
)
...
...
@@ -77,11 +79,6 @@ class FPToFP extends FPUPipelineModule{
}
}
var
resVec
=
Seq
(
mux
)
for
(
i
<-
1
to
latency
){
resVec
=
resVec
:+
PipelineReg
(
i
)(
resVec
(
i
-
1
))
}
io
.
out
.
bits
.
data
:=
resVec
.
last
.
data
fflags
:=
resVec
.
last
.
exc
io
.
out
.
bits
.
data
:=
S2Reg
(
mux
.
data
)
fflags
:=
S2Reg
(
mux
.
exc
)
}
src/main/scala/xiangshan/backend/fu/fpu/FPToInt.scala
浏览文件 @
51f54365
...
...
@@ -18,30 +18,37 @@ class FPToInt extends FPUPipelineModule {
val
ctrl
=
io
.
in
.
bits
.
uop
.
ctrl
.
fpu
val
src1_s
=
unbox
(
src1
,
S
,
Some
(
FType
.
S
))
val
src1_d
=
unbox
(
src1
,
ctrl
.
typeTagIn
,
None
)
val
src2_d
=
unbox
(
src2
,
ctrl
.
typeTagIn
,
None
)
val
src1_ieee
=
ieee
(
src1
)
val
move_out
=
Mux
(
ctrl
.
typeTagIn
===
S
,
src1_ieee
(
31
,
0
),
src1_ieee
)
// stage 1: unbox inputs
val
src1_d
=
S1Reg
(
unbox
(
src1
,
ctrl
.
typeTagIn
,
None
))
val
src2_d
=
S1Reg
(
unbox
(
src2
,
ctrl
.
typeTagIn
,
None
))
val
ctrl_reg
=
S1Reg
(
ctrl
)
val
rm_reg
=
S1Reg
(
rm
)
// stage2
val
src1_ieee
=
ieee
(
src1_d
)
val
move_out
=
Mux
(
ctrl_reg
.
typeTagIn
===
S
,
src1_ieee
(
FType
.
S
.
ieeeWidth
-
1
,
0
),
src1_ieee
)
val
classify_out
=
Mux
(
ctrl
.
typeTagIn
===
S
,
FType
.
S
.
classify
(
src1_s
),
FType
.
D
.
classify
(
src1
)
val
classify_out
=
Mux
(
ctrl
_reg
.
typeTagIn
===
S
,
FType
.
S
.
classify
(
maxType
.
unsafeConvert
(
src1_d
,
FType
.
S
)
),
FType
.
D
.
classify
(
src1
_d
)
)
val
dcmp
=
Module
(
new
hardfloat
.
CompareRecFN
(
maxExpWidth
,
maxSigWidth
))
dcmp
.
io
.
a
:=
src1_d
dcmp
.
io
.
b
:=
src2_d
dcmp
.
io
.
signaling
:=
!
rm
(
1
)
dcmp
.
io
.
signaling
:=
!
rm
_reg
(
1
)
val
dcmp_out
=
((~
rm
).
asUInt
()
&
Cat
(
dcmp
.
io
.
lt
,
dcmp
.
io
.
eq
)).
orR
()
val
dcmp_out
=
((~
rm
_reg
).
asUInt
()
&
Cat
(
dcmp
.
io
.
lt
,
dcmp
.
io
.
eq
)).
orR
()
val
dcmp_exc
=
dcmp
.
io
.
exceptionFlags
val
conv
=
Module
(
new
RecFNToIN
(
maxExpWidth
,
maxSigWidth
,
XLEN
))
conv
.
io
.
in
:=
src1_d
conv
.
io
.
roundingMode
:=
rm
conv
.
io
.
signedOut
:=
~
ctrl
.
typ
(
0
)
conv
.
io
.
roundingMode
:=
rm
_reg
conv
.
io
.
signedOut
:=
~
ctrl
_reg
.
typ
(
0
)
val
conv_out
=
WireInit
(
conv
.
io
.
out
)
val
conv_exc
=
WireInit
(
Cat
(
...
...
@@ -52,10 +59,10 @@ class FPToInt extends FPUPipelineModule {
val
narrow
=
Module
(
new
RecFNToIN
(
maxExpWidth
,
maxSigWidth
,
32
))
narrow
.
io
.
in
:=
src1_d
narrow
.
io
.
roundingMode
:=
rm
narrow
.
io
.
signedOut
:=
~
ctrl
.
typ
(
0
)
narrow
.
io
.
roundingMode
:=
rm
_reg
narrow
.
io
.
signedOut
:=
~
ctrl
_reg
.
typ
(
0
)
when
(!
ctrl
.
typ
(
1
))
{
// fcvt.w/wu.fp
when
(!
ctrl
_reg
.
typ
(
1
))
{
// fcvt.w/wu.fp
val
excSign
=
src1_d
(
maxExpWidth
+
maxSigWidth
)
&&
!
maxType
.
isNaN
(
src1_d
)
val
excOut
=
Cat
(
conv
.
io
.
signedOut
===
excSign
,
Fill
(
32
-
1
,
!
excSign
))
val
invalid
=
conv
.
io
.
intExceptionFlags
(
2
)
||
narrow
.
io
.
intExceptionFlags
(
1
)
...
...
@@ -67,26 +74,18 @@ class FPToInt extends FPUPipelineModule {
val
intData
=
Wire
(
UInt
(
XLEN
.
W
))
intData
:=
Mux
(
ctrl
.
wflags
,
Mux
(
ctrl
.
fcvt
,
conv_out
,
dcmp_out
),
Mux
(
rm
(
0
),
classify_out
,
move_out
)
intData
:=
Mux
(
ctrl
_reg
.
wflags
,
Mux
(
ctrl
_reg
.
fcvt
,
conv_out
,
dcmp_out
),
Mux
(
rm
_reg
(
0
),
classify_out
,
move_out
)
)
val
doubleOut
=
Mux
(
ctrl
.
fcvt
,
ctrl
.
typ
(
1
),
ctrl
.
fmt
(
0
))
val
intValue
=
Mux
(
doubleOut
,
val
doubleOut
=
Mux
(
ctrl
_reg
.
fcvt
,
ctrl_reg
.
typ
(
1
),
ctrl_reg
.
fmt
(
0
))
val
intValue
=
S2Reg
(
Mux
(
doubleOut
,
SignExt
(
intData
,
XLEN
),
SignExt
(
intData
(
31
,
0
),
XLEN
)
)
val
exc
=
Mux
(
ctrl
.
fcvt
,
conv_exc
,
dcmp_exc
)
var
dataVec
=
Seq
(
intValue
)
var
excVec
=
Seq
(
exc
)
))
for
(
i
<-
1
to
latency
)
{
dataVec
=
dataVec
:+
PipelineReg
(
i
)(
dataVec
(
i
-
1
))
excVec
=
excVec
:+
PipelineReg
(
i
)(
excVec
(
i
-
1
))
}
val
exc
=
S2Reg
(
Mux
(
ctrl_reg
.
fcvt
,
conv_exc
,
dcmp_exc
))
io
.
out
.
bits
.
data
:=
dataVec
.
last
fflags
:=
exc
Vec
.
last
io
.
out
.
bits
.
data
:=
intValue
fflags
:=
exc
}
src/main/scala/xiangshan/backend/fu/util/CSRConst.scala
浏览文件 @
51f54365
...
...
@@ -185,4 +185,9 @@ trait HasCSRConst {
val
lowestAccessPrivilegeLevel
=
addr
(
9
,
8
)
mode
>=
lowestAccessPrivilegeLevel
&&
!(
wen
&&
readOnly
)
}
def
perfcntPermissionCheck
(
addr
:
UInt
,
mode
:
UInt
,
mmask
:
UInt
,
smask
:
UInt
)
:
Bool
=
{
val
index
=
UIntToOH
(
addr
&
31.
U
)
Mux
(
mode
===
ModeM
,
true
.
B
,
Mux
(
mode
===
ModeS
,
(
index
&
mmask
)
=/=
0.
U
,
(
index
&
mmask
&
smask
)
=/=
0.
U
))
}
}
\ No newline at end of file
src/main/scala/xiangshan/backend/issue/ReservationStationNew.scala
浏览文件 @
51f54365
此差异已折叠。
点击以展开。
src/main/scala/xiangshan/backend/package.scala
浏览文件 @
51f54365
...
...
@@ -17,12 +17,13 @@ package object backend {
// jump
object
JumpOpType
{
def
jal
=
"b11_000"
.
U
def
jalr
=
"b11_010"
.
U
def
jal
=
"b00"
.
U
def
jalr
=
"b01"
.
U
def
auipc
=
"b10"
.
U
// def call = "b11_011".U
// def ret = "b11_100".U
def
jumpOp
IsJal
(
op
:
UInt
)
=
!
op
(
1
)
def
jumpOpis
Jalr
(
op
:
UInt
)
=
op
(
1
)
def
jumpOp
isJalr
(
op
:
UInt
)
=
op
(
0
)
def
jumpOpis
Auipc
(
op
:
UInt
)
=
op
(
1
)
}
object
FenceOpType
{
...
...
src/main/scala/xiangshan/backend/regfile/Regfile.scala
浏览文件 @
51f54365
...
...
@@ -35,9 +35,8 @@ class Regfile
if
(!
useBlackBox
)
{
val
mem
=
Mem
(
NRPhyRegs
,
UInt
(
len
.
W
))
for
(
r
<-
io
.
readPorts
)
{
val
raddr_reg
=
RegNext
(
r
.
addr
)
val
rdata
=
if
(
hasZero
)
Mux
(
raddr_reg
===
0.
U
,
0.
U
,
mem
(
raddr_reg
))
else
mem
(
raddr_reg
)
r
.
data
:=
rdata
val
rdata
=
if
(
hasZero
)
Mux
(
r
.
addr
===
0.
U
,
0.
U
,
mem
(
r
.
addr
))
else
mem
(
r
.
addr
)
r
.
data
:=
RegNext
(
rdata
)
}
for
(
w
<-
io
.
writePorts
)
{
when
(
w
.
wen
)
{
...
...
src/main/scala/xiangshan/backend/rename/BusyTable.scala
浏览文件 @
51f54365
...
...
@@ -5,6 +5,11 @@ import chisel3.util._
import
xiangshan._
import
utils.
{
ParallelOR
,
XSDebug
}
class
BusyTableReadIO
extends
XSBundle
{
val
req
=
Input
(
UInt
(
PhyRegIdxWidth
.
W
))
val
resp
=
Output
(
Bool
())
}
class
BusyTable
(
numReadPorts
:
Int
,
numWritePorts
:
Int
)
extends
XSModule
{
val
io
=
IO
(
new
Bundle
()
{
val
flush
=
Input
(
Bool
())
...
...
@@ -13,8 +18,7 @@ class BusyTable(numReadPorts: Int, numWritePorts: Int) extends XSModule {
// set preg state to ready (write back regfile + roq walk)
val
wbPregs
=
Vec
(
numWritePorts
,
Flipped
(
ValidIO
(
UInt
(
PhyRegIdxWidth
.
W
))))
// read preg state
val
rfReadAddr
=
Vec
(
numReadPorts
,
Input
(
UInt
(
PhyRegIdxWidth
.
W
)))
val
pregRdy
=
Vec
(
numReadPorts
,
Output
(
Bool
()))
val
read
=
Vec
(
numReadPorts
,
new
BusyTableReadIO
)
})
val
table
=
RegInit
(
0.
U
(
NRPhyRegs
.
W
))
...
...
@@ -29,27 +33,10 @@ class BusyTable(numReadPorts: Int, numWritePorts: Int) extends XSModule {
val
tableAfterWb
=
table
&
(~
wbMask
).
asUInt
val
tableAfterAlloc
=
tableAfterWb
|
allocMask
for
((
raddr
,
rdy
)
<-
io
.
rfReadAddr
.
zip
(
io
.
pregRdy
)){
rdy
:=
!
tableAfterWb
(
raddr
)
}
io
.
read
.
map
(
r
=>
r
.
resp
:=
!
table
(
r
.
req
))
table
:=
tableAfterAlloc
// for((alloc, i) <- io.allocPregs.zipWithIndex){
// when(alloc.valid){
// table(alloc.bits) := true.B
// }
// XSDebug(alloc.valid, "Allocate %d\n", alloc.bits)
// }
// for((wb, i) <- io.wbPregs.zipWithIndex){
// when(wb.valid){
// table(wb.bits) := false.B
// }
// XSDebug(wb.valid, "writeback %d\n", wb.bits)
// }
when
(
io
.
flush
){
table
:=
0.
U
(
NRPhyRegs
.
W
)
}
...
...
src/main/scala/xiangshan/backend/roq/Roq.scala
浏览文件 @
51f54365
...
...
@@ -54,12 +54,9 @@ class RoqEnqIO extends XSBundle {
class
RoqDispatchData
extends
RoqCommitInfo
{
val
crossPageIPFFix
=
Bool
()
val
exceptionVec
=
Vec
(
16
,
Bool
())
}
class
RoqWbData
extends
XSBundle
{
// mostly for exceptions
val
exceptionVec
=
Vec
(
16
,
Bool
())
val
fflags
=
UInt
(
5.
W
)
val
flushPipe
=
Bool
()
}
...
...
@@ -70,7 +67,7 @@ class RoqDeqPtrWrapper extends XSModule with HasCircularQueuePtrHelper {
val
state
=
Input
(
UInt
(
2.
W
))
val
deq_v
=
Vec
(
CommitWidth
,
Input
(
Bool
()))
val
deq_w
=
Vec
(
CommitWidth
,
Input
(
Bool
()))
val
deq_exceptionVec
=
Vec
(
CommitWidth
,
Input
(
UInt
(
16.
W
)))
val
deq_exceptionVec
=
Vec
(
CommitWidth
,
Input
(
ExceptionVec
(
)))
val
deq_flushPipe
=
Vec
(
CommitWidth
,
Input
(
Bool
()))
// for flush: when exception occurs, reset deqPtrs to range(0, CommitWidth)
val
intrBitSetReg
=
Input
(
Bool
())
...
...
@@ -83,19 +80,21 @@ class RoqDeqPtrWrapper extends XSModule with HasCircularQueuePtrHelper {
val
deqPtrVec
=
RegInit
(
VecInit
((
0
until
CommitWidth
).
map
(
_
.
U
.
asTypeOf
(
new
RoqPtr
))))
val
possibleException
=
VecInit
(
io
.
deq_exceptionVec
.
map
(
selectAll
(
_
,
false
)))
// for exceptions (flushPipe included) and interrupts:
// only consider the first instruction
val
intrEnable
=
io
.
intrBitSetReg
&&
!
io
.
hasNoSpecExec
&&
!
CommitType
.
isLoadStore
(
io
.
commitType
)
val
exceptionEnable
=
io
.
deq_w
(
0
)
&&
(
io
.
deq_exceptionVec
(
0
)
.
orR
||
io
.
deq_flushPipe
(
0
))
val
exceptionEnable
=
io
.
deq_w
(
0
)
&&
(
possibleException
(
0
).
asUInt
.
orR
||
io
.
deq_flushPipe
(
0
))
val
redirectOutValid
=
io
.
state
===
0.
U
&&
io
.
deq_v
(
0
)
&&
(
intrEnable
||
exceptionEnable
)
// for normal commits: only to consider when there're no exceptions
// we don't need to consider whether the first instruction has exceptions since it wil trigger exceptions.
val
commitBlocked
=
VecInit
((
0
until
CommitWidth
).
map
(
i
=>
if
(
i
==
0
)
false
.
B
else
io
.
deq_exceptionVec
(
i
)
.
orR
||
io
.
deq_flushPipe
(
i
)))
val
canCommit
=
VecInit
((
0
until
CommitWidth
).
map
(
i
=>
io
.
deq_v
(
i
)
&&
io
.
deq_w
(
i
)
&&
!
commitBlocked
(
i
)
))
val
commitBlocked
=
VecInit
((
0
until
CommitWidth
).
map
(
i
=>
if
(
i
==
0
)
false
.
B
else
possibleException
(
i
).
asUInt
.
orR
||
io
.
deq_flushPipe
(
i
)))
val
canCommit
=
VecInit
((
0
until
CommitWidth
).
map
(
i
=>
io
.
deq_v
(
i
)
&&
io
.
deq_w
(
i
)
/*&& !commitBlocked(i)*/
))
val
normalCommitCnt
=
PriorityEncoder
(
canCommit
.
map
(
c
=>
!
c
)
:+
true
.
B
)
// when io.intrBitSetReg, only one instruction is allowed to commit
val
commitCnt
=
Mux
(
io
.
intrBitSetReg
,
io
.
deq_v
(
0
)
&&
io
.
deq_w
(
0
),
normalCommitCnt
)
// when io.intrBitSetReg or there're possible exceptions in these instructions, only one instruction is allowed to commit
val
allowOnlyOne
=
VecInit
(
commitBlocked
.
drop
(
1
)).
asUInt
.
orR
||
io
.
intrBitSetReg
val
commitCnt
=
Mux
(
allowOnlyOne
,
io
.
deq_v
(
0
)
&&
io
.
deq_w
(
0
),
normalCommitCnt
)
val
resetDeqPtrVec
=
VecInit
((
0
until
CommitWidth
).
map
(
_
.
U
.
asTypeOf
(
new
RoqPtr
)))
val
commitDeqPtrVec
=
VecInit
(
deqPtrVec
.
map
(
_
+
commitCnt
))
...
...
@@ -118,7 +117,7 @@ class RoqEnqPtrWrapper extends XSModule with HasCircularQueuePtrHelper {
val
state
=
Input
(
UInt
(
2.
W
))
val
deq_v
=
Input
(
Bool
())
val
deq_w
=
Input
(
Bool
())
val
deq_exceptionVec
=
Input
(
UInt
(
16.
W
))
val
deq_exceptionVec
=
Input
(
ExceptionVec
(
))
val
deq_flushPipe
=
Input
(
Bool
())
val
intrBitSetReg
=
Input
(
Bool
())
val
hasNoSpecExec
=
Input
(
Bool
())
...
...
@@ -137,7 +136,7 @@ class RoqEnqPtrWrapper extends XSModule with HasCircularQueuePtrHelper {
// for exceptions (flushPipe included) and interrupts:
// only consider the first instruction
val
intrEnable
=
io
.
intrBitSetReg
&&
!
io
.
hasNoSpecExec
&&
!
CommitType
.
isLoadStore
(
io
.
commitType
)
val
exceptionEnable
=
io
.
deq_w
&&
(
io
.
deq_exceptionVec
.
orR
||
io
.
deq_flushPipe
)
val
exceptionEnable
=
io
.
deq_w
&&
(
selectAll
(
io
.
deq_exceptionVec
,
false
).
asUInt
.
orR
||
io
.
deq_flushPipe
)
val
redirectOutValid
=
io
.
state
===
0.
U
&&
io
.
deq_v
&&
(
intrEnable
||
exceptionEnable
)
// enqueue
...
...
@@ -264,28 +263,7 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
val
writebackData
=
Module
(
new
SyncDataModuleTemplate
(
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(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
)
mergeVec
(
storeAddrMisaligned
)
:=
wbData
.
exceptionVec
(
storeAddrMisaligned
)
mergeVec
(
storeAccessFault
)
:=
wbData
.
exceptionVec
(
storeAccessFault
)
mergeVec
(
ecallU
)
:=
wbData
.
exceptionVec
(
ecallU
)
mergeVec
(
ecallS
)
:=
wbData
.
exceptionVec
(
ecallS
)
mergeVec
(
ecallM
)
:=
wbData
.
exceptionVec
(
ecallM
)
mergeVec
(
loadPageFault
)
:=
wbData
.
exceptionVec
(
loadPageFault
)
mergeVec
(
storePageFault
)
:=
wbData
.
exceptionVec
(
storePageFault
)
// returns the merged exception vector
mergeVec
}
val
exceptionDataRead
=
Wire
(
Vec
(
CommitWidth
,
ExceptionVec
()))
io
.
roqDeqPtr
:=
deqPtr
...
...
@@ -303,7 +281,6 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
when
(
io
.
commits
.
valid
.
asUInt
.
orR
&&
state
=/=
s_extrawalk
)
{
hasNoSpecExec
:=
false
.
B
}
io
.
enq
.
canAccept
:=
allowEnqueue
&&
!
hasBlockBackward
io
.
enq
.
isEmpty
:=
isEmpty
io
.
enq
.
resp
:=
enqPtrVec
val
canEnqueue
=
VecInit
(
io
.
enq
.
req
.
map
(
_
.
valid
&&
io
.
enq
.
canAccept
))
for
(
i
<-
0
until
RenameWidth
)
{
...
...
@@ -319,9 +296,10 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
}
}
}
val
dispatchNum
=
Mux
(
io
.
enq
.
canAccept
,
PopCount
(
Cat
(
io
.
enq
.
req
.
map
(
_
.
valid
))),
0.
U
)
io
.
enq
.
isEmpty
:=
RegNext
(
isEmpty
&&
dispatchNum
===
0.
U
)
// debug info for enqueue (dispatch)
val
dispatchNum
=
Mux
(
io
.
enq
.
canAccept
,
PopCount
(
Cat
(
io
.
enq
.
req
.
map
(
_
.
valid
))),
0.
U
)
XSDebug
(
p
"(ready, valid): ${io.enq.canAccept}, ${Binary(Cat(io.enq.req.map(_.valid)))}\n"
)
XSInfo
(
dispatchNum
=/=
0.
U
,
p
"dispatched $dispatchNum insts\n"
)
...
...
@@ -359,7 +337,7 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
val
deqWritebackData
=
writebackDataRead
(
0
)
val
debug_deqUop
=
debug_microOp
(
deqPtr
.
value
)
val
deqExceptionVec
=
mergeExceptionVec
(
deqDispatchData
,
deqWritebackData
)
val
deqExceptionVec
=
exceptionDataRead
(
0
)
// 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.
...
...
@@ -369,9 +347,9 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
val
isFlushPipe
=
writebacked
(
deqPtr
.
value
)
&&
deqWritebackData
.
flushPipe
io
.
redirectOut
:=
DontCare
io
.
redirectOut
.
valid
:=
(
state
===
s_idle
)
&&
valid
(
deqPtr
.
value
)
&&
(
intrEnable
||
exceptionEnable
||
isFlushPipe
)
io
.
redirectOut
.
bits
.
level
:=
Mux
(
i
sFlushPipe
,
RedirectLevel
.
flushAll
,
RedirectLevel
.
exception
)
io
.
redirectOut
.
bits
.
level
:=
Mux
(
i
ntrEnable
||
exceptionEnable
,
RedirectLevel
.
exception
,
RedirectLevel
.
flushAll
)
io
.
redirectOut
.
bits
.
interrupt
:=
intrEnable
io
.
redirectOut
.
bits
.
target
:=
Mux
(
i
sFlushPipe
,
deqDispatchData
.
pc
+
4.
U
,
io
.
csr
.
trapTarget
)
io
.
redirectOut
.
bits
.
target
:=
Mux
(
i
ntrEnable
||
exceptionEnable
,
io
.
csr
.
trapTarget
,
deqDispatchData
.
pc
+
4.
U
)
io
.
exception
:=
debug_deqUop
io
.
exception
.
ctrl
.
commitType
:=
deqDispatchData
.
commitType
...
...
@@ -421,13 +399,15 @@ 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
=
dispatchDataRead
.
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
)
||
writebackDataRead
(
i
).
flushPipe
))
val
commit_exception
=
exceptionDataRead
.
zip
(
writebackDataRead
.
map
(
_
.
flushPipe
)).
map
{
case
(
e
,
f
)
=>
e
.
asUInt
.
orR
||
f
}
val
commit_block
=
VecInit
((
0
until
CommitWidth
).
map
(
i
=>
!
commit_w
(
i
)))
val
allowOnlyOneCommit
=
VecInit
(
commit_exception
.
drop
(
1
)).
asUInt
.
orR
||
intrBitSetReg
// for instructions that may block others, we don't allow them to commit
for
(
i
<-
0
until
CommitWidth
)
{
// defaults: state === s_idle and instructions commit
// 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
)
val
isBlocked
=
if
(
i
!=
0
)
Cat
(
commit_block
.
take
(
i
)).
orR
||
allowOnlyOneCommit
else
intrEnable
||
commit_exception
(
0
)
io
.
commits
.
valid
(
i
)
:=
commit_v
(
i
)
&&
commit_w
(
i
)
&&
!
isBlocked
io
.
commits
.
info
(
i
)
:=
dispatchDataRead
(
i
)
when
(
state
===
s_walk
)
{
...
...
@@ -495,7 +475,7 @@ 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
(
dispatchDataRead
.
zip
(
writebackDataRead
).
map
{
case
(
d
,
w
)
=>
mergeExceptionVec
(
d
,
w
).
asUInt
})
deqPtrGenModule
.
io
.
deq_exceptionVec
:=
exceptionDataRead
deqPtrGenModule
.
io
.
deq_flushPipe
:=
writebackDataRead
.
map
(
_
.
flushPipe
)
deqPtrGenModule
.
io
.
intrBitSetReg
:=
intrBitSetReg
deqPtrGenModule
.
io
.
hasNoSpecExec
:=
hasNoSpecExec
...
...
@@ -507,7 +487,7 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
enqPtrGenModule
.
io
.
state
:=
state
enqPtrGenModule
.
io
.
deq_v
:=
commit_v
(
0
)
enqPtrGenModule
.
io
.
deq_w
:=
commit_w
(
0
)
enqPtrGenModule
.
io
.
deq_exceptionVec
:=
deqExceptionVec
.
asUInt
enqPtrGenModule
.
io
.
deq_exceptionVec
:=
deqExceptionVec
enqPtrGenModule
.
io
.
deq_flushPipe
:=
writebackDataRead
(
0
).
flushPipe
enqPtrGenModule
.
io
.
intrBitSetReg
:=
intrBitSetReg
enqPtrGenModule
.
io
.
hasNoSpecExec
:=
hasNoSpecExec
...
...
@@ -600,7 +580,7 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
// enqueue logic set 6 writebacked to false
for
(
i
<-
0
until
RenameWidth
)
{
when
(
canEnqueue
(
i
))
{
writebacked
(
enqPtrVec
(
i
).
value
)
:=
false
.
B
writebacked
(
enqPtrVec
(
i
).
value
)
:=
selectFrontend
(
io
.
enq
.
req
(
i
).
bits
.
cf
.
exceptionVec
,
false
).
asUInt
.
orR
}
}
// writeback logic set numWbPorts writebacked to true
...
...
@@ -641,19 +621,59 @@ class Roq(numWbPorts: Int) extends XSModule with HasCircularQueuePtrHelper {
wdata
.
sqIdx
:=
req
.
sqIdx
wdata
.
pc
:=
req
.
cf
.
pc
wdata
.
crossPageIPFFix
:=
req
.
cf
.
crossPageIPFFix
wdata
.
exceptionVec
:=
req
.
cf
.
exceptionVec
//
wdata.exceptionVec := req.cf.exceptionVec
}
dispatchData
.
io
.
raddr
:=
commitReadAddr_next
writebackData
.
io
.
wen
:=
io
.
exeWbResults
.
map
(
_
.
valid
)
writebackData
.
io
.
waddr
:=
io
.
exeWbResults
.
map
(
_
.
bits
.
uop
.
roqIdx
.
value
)
writebackData
.
io
.
wdata
.
zip
(
io
.
exeWbResults
.
map
(
_
.
bits
)).
map
{
case
(
wdata
,
wb
)
=>
wdata
.
exceptionVec
:=
wb
.
uop
.
cf
.
exceptionVec
wdata
.
fflags
:=
wb
.
fflags
wdata
.
flushPipe
:=
wb
.
uop
.
ctrl
.
flushPipe
}
writebackData
.
io
.
raddr
:=
commitReadAddr_next
for
(
i
<-
0
until
16
)
{
val
exceptionData
=
Module
(
new
SyncDataModuleTemplate
(
Bool
(),
RoqSize
,
CommitWidth
,
RenameWidth
+
writebackCount
(
i
)))
var
wPortIdx
=
0
for
(
j
<-
0
until
RenameWidth
)
{
exceptionData
.
io
.
wen
(
wPortIdx
)
:=
canEnqueue
(
j
)
exceptionData
.
io
.
waddr
(
wPortIdx
)
:=
enqPtrVec
(
j
).
value
exceptionData
.
io
.
wdata
(
wPortIdx
)
:=
(
if
(
allPossibleSet
.
contains
(
i
))
io
.
enq
.
req
(
j
).
bits
.
cf
.
exceptionVec
(
i
)
else
false
.
B
)
wPortIdx
=
wPortIdx
+
1
}
if
(
csrWbCount
(
i
)
>
0
)
{
exceptionData
.
io
.
wen
(
wPortIdx
)
:=
io
.
exeWbResults
(
6
).
valid
exceptionData
.
io
.
waddr
(
wPortIdx
)
:=
io
.
exeWbResults
(
6
).
bits
.
uop
.
roqIdx
.
value
exceptionData
.
io
.
wdata
(
wPortIdx
)
:=
io
.
exeWbResults
(
6
).
bits
.
uop
.
cf
.
exceptionVec
(
i
)
wPortIdx
=
wPortIdx
+
1
}
if
(
atomicsWbCount
(
i
)
>
0
)
{
exceptionData
.
io
.
wen
(
wPortIdx
)
:=
io
.
exeWbResults
(
4
).
valid
exceptionData
.
io
.
waddr
(
wPortIdx
)
:=
io
.
exeWbResults
(
4
).
bits
.
uop
.
roqIdx
.
value
exceptionData
.
io
.
wdata
(
wPortIdx
)
:=
io
.
exeWbResults
(
4
).
bits
.
uop
.
cf
.
exceptionVec
(
i
)
wPortIdx
=
wPortIdx
+
1
}
if
(
loadWbCount
(
i
)
>
0
)
{
exceptionData
.
io
.
wen
(
wPortIdx
)
:=
io
.
exeWbResults
(
5
).
valid
exceptionData
.
io
.
waddr
(
wPortIdx
)
:=
io
.
exeWbResults
(
5
).
bits
.
uop
.
roqIdx
.
value
exceptionData
.
io
.
wdata
(
wPortIdx
)
:=
io
.
exeWbResults
(
5
).
bits
.
uop
.
cf
.
exceptionVec
(
i
)
wPortIdx
=
wPortIdx
+
1
}
if
(
storeWbCount
(
i
)
>
0
)
{
exceptionData
.
io
.
wen
(
wPortIdx
)
:=
io
.
exeWbResults
(
16
).
valid
exceptionData
.
io
.
waddr
(
wPortIdx
)
:=
io
.
exeWbResults
(
16
).
bits
.
uop
.
roqIdx
.
value
exceptionData
.
io
.
wdata
(
wPortIdx
)
:=
io
.
exeWbResults
(
16
).
bits
.
uop
.
cf
.
exceptionVec
(
i
)
wPortIdx
=
wPortIdx
+
1
exceptionData
.
io
.
wen
(
wPortIdx
)
:=
io
.
exeWbResults
(
17
).
valid
exceptionData
.
io
.
waddr
(
wPortIdx
)
:=
io
.
exeWbResults
(
17
).
bits
.
uop
.
roqIdx
.
value
exceptionData
.
io
.
wdata
(
wPortIdx
)
:=
io
.
exeWbResults
(
17
).
bits
.
uop
.
cf
.
exceptionVec
(
i
)
wPortIdx
=
wPortIdx
+
1
}
exceptionData
.
io
.
raddr
:=
VecInit
(
deqPtrVec_next
.
map
(
_
.
value
))
exceptionDataRead
.
zip
(
exceptionData
.
io
.
rdata
).
map
{
case
(
d
,
r
)
=>
d
(
i
)
:=
r
}
}
/**
* debug info
...
...
src/main/scala/xiangshan/cache/InstrUncache.scala
0 → 100644
浏览文件 @
51f54365
package
xiangshan.cache
import
chisel3._
import
chisel3.util._
import
utils._
import
chipsalliance.rocketchip.config.Parameters
import
freechips.rocketchip.diplomacy.
{
IdRange
,
LazyModule
,
LazyModuleImp
,
TransferSizes
}
import
freechips.rocketchip.tilelink.
{
TLArbiter
,
TLBundleA
,
TLBundleD
,
TLClientNode
,
TLEdgeOut
,
TLMasterParameters
,
TLMasterPortParameters
}
import
xiangshan._
import
xiangshan.frontend._
class
InsUncacheReq
extends
ICacheBundle
{
val
addr
=
UInt
(
PAddrBits
.
W
)
val
id
=
UInt
(
3.
W
)
}
class
InsUncacheResp
extends
ICacheBundle
{
val
data
=
UInt
((
mmioBeats
*
mmioBusWidth
).
W
)
val
id
=
UInt
(
3.
W
)
}
// One miss entry deals with one mmio request
class
InstrMMIOEntry
(
edge
:
TLEdgeOut
)
extends
XSModule
with
HasICacheParameters
{
val
io
=
IO
(
new
Bundle
{
val
id
=
Input
(
UInt
(
log2Up
(
cacheParams
.
nMMIOs
).
W
))
// client requests
val
req
=
Flipped
(
DecoupledIO
(
new
InsUncacheReq
))
val
resp
=
DecoupledIO
(
new
InsUncacheResp
)
val
mmio_acquire
=
DecoupledIO
(
new
TLBundleA
(
edge
.
bundle
))
val
mmio_grant
=
Flipped
(
DecoupledIO
(
new
TLBundleD
(
edge
.
bundle
)))
val
flush
=
Input
(
Bool
())
})
val
s_invalid
::
s_refill_req
::
s_refill_resp
::
s_send_resp
::
Nil
=
Enum
(
4
)
val
state
=
RegInit
(
s_invalid
)
val
req
=
Reg
(
new
InsUncacheReq
)
val
respDataReg
=
Reg
(
Vec
(
mmioBeats
,
UInt
(
mmioBusWidth
.
W
)))
val
beatCounter
=
Counter
(
mmioBeats
)
// assign default values to output signals
io
.
req
.
ready
:=
false
.
B
io
.
resp
.
valid
:=
false
.
B
io
.
resp
.
bits
:=
DontCare
io
.
mmio_acquire
.
valid
:=
false
.
B
io
.
mmio_acquire
.
bits
:=
DontCare
io
.
mmio_grant
.
ready
:=
false
.
B
val
needFlush
=
RegInit
(
false
.
B
)
XSDebug
(
"[ICache MMIO]entry: %d state: %d needFlush%d flush:%d\n"
,
io
.
id
,
state
,
needFlush
,
io
.
flush
)
XSDebug
(
"[ICache MMIO]req.addr: %x req.id \n"
,
req
.
addr
)
XSDebug
(
"[ICache MMIO]mmio_acquire:(v:%d r:%d) mmio_grant:(v:%d r:%d)\n"
,
io
.
mmio_acquire
.
valid
,
io
.
mmio_acquire
.
ready
,
io
.
mmio_grant
.
valid
,
io
.
mmio_grant
.
ready
)
XSDebug
(
"[ICache MMIO]mmio_acquire:(v:%d r:%d) mmio_grant:(v:%d r:%d)\n"
,
io
.
mmio_acquire
.
valid
,
io
.
mmio_acquire
.
ready
,
io
.
mmio_grant
.
valid
,
io
.
mmio_grant
.
ready
)
XSDebug
(
"[ICache MMIO]respReg: %x\n"
,
respDataReg
.
asUInt
)
when
(
io
.
flush
&&
(
state
=/=
s_invalid
)
&&
(
state
=/=
s_send_resp
)){
needFlush
:=
true
.
B
}
.
elsewhen
((
state
===
s_send_resp
)
&&
needFlush
){
needFlush
:=
false
.
B
}
// --------------------------------------------
// s_invalid: receive requests
when
(
state
===
s_invalid
)
{
io
.
req
.
ready
:=
true
.
B
beatCounter
.
value
:=
0.
U
when
(
io
.
req
.
fire
())
{
req
:=
io
.
req
.
bits
state
:=
s_refill_req
}
}
when
(
state
===
s_refill_req
)
{
io
.
mmio_acquire
.
valid
:=
true
.
B
io
.
mmio_acquire
.
bits
:=
edge
.
Get
(
fromSource
=
io
.
id
,
toAddress
=
req
.
addr
+
(
beatCounter
.
value
<<
log2Ceil
(
mmioBusBytes
).
U
),
lgSize
=
log2Ceil
(
mmioBusBytes
).
U
).
_2
when
(
io
.
mmio_acquire
.
fire
())
{
state
:=
s_refill_resp
}
}
val
(
_
,
_
,
refill_done
,
_
)
=
edge
.
addr_inc
(
io
.
mmio_grant
)
when
(
state
===
s_refill_resp
)
{
io
.
mmio_grant
.
ready
:=
true
.
B
when
(
io
.
mmio_grant
.
fire
())
{
respDataReg
(
beatCounter
.
value
)
:=
io
.
mmio_grant
.
bits
.
data
state
:=
Mux
(
needFlush
||
io
.
flush
,
s_invalid
,
Mux
(
beatCounter
.
value
===
(
mmioBeats
-
1
).
U
,
s_send_resp
,
s_refill_req
))
beatCounter
.
inc
()
}
}
// --------------------------------------------
when
(
state
===
s_send_resp
)
{
io
.
resp
.
valid
:=
true
.
B
io
.
resp
.
bits
.
data
:=
respDataReg
.
asUInt
io
.
resp
.
bits
.
id
:=
req
.
id
// meta data should go with the response
when
(
io
.
resp
.
fire
()
||
needFlush
)
{
state
:=
s_invalid
beatCounter
.
value
:=
0.
U
}
}
}
class
icacheUncacheIO
extends
DCacheBundle
{
val
req
=
Flipped
(
DecoupledIO
(
new
InsUncacheReq
))
val
resp
=
DecoupledIO
(
new
InsUncacheResp
)
val
flush
=
Input
(
Bool
())
}
// convert DCacheIO to TileLink
// for Now, we only deal with TL-UL
class
InstrUncache
()(
implicit
p
:
Parameters
)
extends
LazyModule
with
HasICacheParameters
{
val
clientParameters
=
TLMasterPortParameters
.
v1
(
clients
=
Seq
(
TLMasterParameters
.
v1
(
"InstrUncache"
,
sourceId
=
IdRange
(
0
,
cacheParams
.
nMMIOs
)
))
)
val
clientNode
=
TLClientNode
(
Seq
(
clientParameters
))
lazy
val
module
=
new
icacheUncacheImp
(
this
)
}
class
icacheUncacheImp
(
outer
:
InstrUncache
)
extends
LazyModuleImp
(
outer
)
with
HasICacheParameters
with
HasXSLog
with
HasTLDump
{
val
io
=
IO
(
new
icacheUncacheIO
)
val
(
bus
,
edge
)
=
outer
.
clientNode
.
out
.
head
require
(
bus
.
d
.
bits
.
data
.
getWidth
==
wordBits
,
"Uncache: tilelink width does not match"
)
val
resp_arb
=
Module
(
new
Arbiter
(
new
InsUncacheResp
,
cacheParams
.
nMMIOs
))
val
req
=
io
.
req
val
resp
=
io
.
resp
val
mmio_acquire
=
bus
.
a
val
mmio_grant
=
bus
.
d
val
entry_alloc_idx
=
Wire
(
UInt
())
val
req_ready
=
WireInit
(
false
.
B
)
// assign default values to output signals
bus
.
b
.
ready
:=
false
.
B
bus
.
c
.
valid
:=
false
.
B
bus
.
c
.
bits
:=
DontCare
bus
.
d
.
ready
:=
false
.
B
bus
.
e
.
valid
:=
false
.
B
bus
.
e
.
bits
:=
DontCare
val
entries
=
(
0
until
cacheParams
.
nMMIOs
)
map
{
i
=>
val
entry
=
Module
(
new
InstrMMIOEntry
(
edge
))
entry
.
io
.
id
:=
i
.
U
(
log2Up
(
cacheParams
.
nMMIOs
).
W
)
entry
.
io
.
flush
:=
io
.
flush
// entry req
entry
.
io
.
req
.
valid
:=
(
i
.
U
===
entry_alloc_idx
)
&&
req
.
valid
entry
.
io
.
req
.
bits
:=
req
.
bits
when
(
i
.
U
===
entry_alloc_idx
)
{
req_ready
:=
entry
.
io
.
req
.
ready
}
// entry resp
resp_arb
.
io
.
in
(
i
)
<>
entry
.
io
.
resp
entry
.
io
.
mmio_grant
.
valid
:=
false
.
B
entry
.
io
.
mmio_grant
.
bits
:=
DontCare
when
(
mmio_grant
.
bits
.
source
===
i
.
U
)
{
entry
.
io
.
mmio_grant
<>
mmio_grant
}
entry
}
entry_alloc_idx
:=
PriorityEncoder
(
entries
.
map
(
m
=>
m
.
io
.
req
.
ready
))
req
.
ready
:=
req_ready
resp
<>
resp_arb
.
io
.
out
TLArbiter
.
lowestFromSeq
(
edge
,
mmio_acquire
,
entries
.
map
(
_
.
io
.
mmio_acquire
))
}
src/main/scala/xiangshan/cache/L1plusCache.scala
浏览文件 @
51f54365
...
...
@@ -130,21 +130,33 @@ class L1plusCacheDataArray extends L1plusCacheModule {
io
.
read
.
ready
:=
!
rwhazard
for
(
w
<-
0
until
nWays
)
{
for
(
r
<-
0
until
blockRows
)
{
val
array
=
Module
(
new
SRAMTemplate
(
Bits
(
encRowBits
.
W
),
set
=
nSets
,
way
=
1
,
val
array
=
Module
(
new
SRAMTemplate
(
Bits
((
blockRows
*
encRowBits
).
W
),
set
=
nSets
,
way
=
1
,
shouldReset
=
false
,
holdRead
=
false
,
singlePort
=
singlePort
))
// data write
array
.
io
.
w
.
req
.
valid
:=
io
.
write
.
bits
.
way_en
(
w
)
&&
io
.
write
.
bits
.
wmask
(
r
).
asBool
&&
io
.
write
.
valid
array
.
io
.
w
.
req
.
valid
:=
io
.
write
.
bits
.
way_en
(
w
)
&&
io
.
write
.
valid
array
.
io
.
w
.
req
.
bits
.
apply
(
setIdx
=
waddr
,
data
=
io
.
write
.
bits
.
data
(
r
)
,
data
=
io
.
write
.
bits
.
data
.
asUInt
,
waymask
=
1.
U
)
// data read
array
.
io
.
r
.
req
.
valid
:=
io
.
read
.
bits
.
way_en
(
w
)
&&
io
.
read
.
bits
.
rmask
(
r
)
&&
io
.
read
.
valid
array
.
io
.
r
.
req
.
valid
:=
io
.
read
.
bits
.
way_en
(
w
)
&&
io
.
read
.
valid
array
.
io
.
r
.
req
.
bits
.
apply
(
setIdx
=
raddr
)
io
.
resp
(
w
)(
r
)
:=
RegNext
(
array
.
io
.
r
.
resp
.
data
(
0
))
for
(
r
<-
0
until
blockRows
)
{
io
.
resp
(
w
)(
r
)
:=
RegNext
(
array
.
io
.
r
.
resp
.
data
(
0
)((
r
+
1
)
*
encRowBits
-
1
,
r
*
encRowBits
))
}
}
// since we use a RAM of block width
// we must do full read and write
when
(
io
.
write
.
valid
)
{
assert
(
io
.
write
.
bits
.
wmask
.
andR
)
}
// since we use a RAM of block width
// we must do full read and write
when
(
io
.
read
.
valid
)
{
assert
(
io
.
read
.
bits
.
rmask
.
andR
)
}
// debug output
...
...
@@ -230,7 +242,7 @@ class L1plusCacheMetadataArray extends L1plusCacheModule {
cacheParams
.
tagCode
.
decode
(
rdata
).
corrected
)
for
(
i
<-
0
until
nWays
)
{
io
.
resp
(
i
).
valid
:=
RegNext
(
valid_array
(
io
.
read
.
bits
.
idx
)(
i
)
)
io
.
resp
(
i
).
valid
:=
valid_array
(
RegNext
(
io
.
read
.
bits
.
idx
))(
i
)
io
.
resp
(
i
).
tag
:=
rtags
(
i
)
}
...
...
src/main/scala/xiangshan/cache/dcache.scala
浏览文件 @
51f54365
...
...
@@ -197,15 +197,22 @@ class DuplicatedDataArray extends AbstractDataArray
io
.
resp
(
j
)(
w
)(
r
)
:=
Cat
((
0
until
rowWords
).
reverse
map
(
k
=>
resp
(
k
)))
for
(
k
<-
0
until
rowWords
)
{
val
array
=
Module
(
new
SRAMTemplate
(
Bits
(
encWordBits
.
W
),
set
=
nSets
,
way
=
1
,
shouldReset
=
false
,
holdRead
=
false
,
singlePort
=
singlePort
))
val
array
=
Module
(
new
SRAMTemplate
(
Bits
(
encWordBits
.
W
),
set
=
nSets
,
way
=
1
,
shouldReset
=
false
,
holdRead
=
false
,
singlePort
=
singlePort
))
// data write
val
wen
=
io
.
write
.
valid
&&
io
.
write
.
bits
.
way_en
(
w
)
&&
io
.
write
.
bits
.
wmask
(
r
)(
k
)
array
.
io
.
w
.
req
.
valid
:=
wen
array
.
io
.
w
.
req
.
bits
.
apply
(
setIdx
=
waddr
,
data
=
io
.
write
.
bits
.
data
(
r
)(
encWordBits
*(
k
+
1
)-
1
,
encWordBits
*
k
),
waymask
=
1.
U
)
waymask
=
1.
U
)
// data read
val
ren
=
io
.
read
(
j
).
valid
&&
io
.
read
(
j
).
bits
.
way_en
(
w
)
&&
io
.
read
(
j
).
bits
.
rmask
(
r
)
...
...
src/main/scala/xiangshan/cache/dtlb.scala
浏览文件 @
51f54365
此差异已折叠。
点击以展开。
src/main/scala/xiangshan/cache/icache.scala
浏览文件 @
51f54365
此差异已折叠。
点击以展开。
src/main/scala/xiangshan/cache/icacheMissQueue.scala
浏览文件 @
51f54365
...
...
@@ -135,7 +135,7 @@ class IcacheMissEntry extends ICacheMissQueueModule
//TODO: Maybe this sate is noe necessary so we don't need respDataReg
is
(
s_write_back
){
when
(
io
.
refill
.
fire
()
&&
io
.
meta_write
.
fire
()
){
when
(
(
io
.
refill
.
fire
()
&&
io
.
meta_write
.
fire
())
||
needFlush
||
io
.
flush
){
state
:=
s_wait_resp
}
}
...
...
@@ -150,10 +150,10 @@ class IcacheMissEntry extends ICacheMissQueueModule
//refill write and meta write
//WARNING: Maybe could not finish refill in 1 cycle
io
.
meta_write
.
valid
:=
(
state
===
s_write_back
)
&&
!
needFlush
io
.
meta_write
.
valid
:=
(
state
===
s_write_back
)
&&
!
needFlush
&&
!
io
.
flush
io
.
meta_write
.
bits
.
apply
(
tag
=
req_tag
,
setIdx
=
req_idx
,
waymask
=
req_waymask
)
io
.
refill
.
valid
:=
(
state
===
s_write_back
)
&&
!
needFlush
io
.
refill
.
valid
:=
(
state
===
s_write_back
)
&&
!
needFlush
&&
!
io
.
flush
io
.
refill
.
bits
.
apply
(
data
=
respDataReg
.
asUInt
,
setIdx
=
req_idx
,
waymask
=
req_waymask
)
...
...
src/main/scala/xiangshan/cache/missQueue.scala
浏览文件 @
51f54365
...
...
@@ -495,8 +495,8 @@ class MissQueue(edge: TLEdgeOut) extends DCacheModule with HasTLDump
if
(!
env
.
FPGAPlatform
)
{
ExcitingUtils
.
addSource
(
BoolStopWatch
(
start
=
entry
.
io
.
req
.
fire
()
,
stop
=
entry
.
io
.
resp
.
fire
()
,
start
=
entry
.
io
.
block_idx
.
valid
,
stop
=
!
entry
.
io
.
block_idx
.
valid
,
startHighPriority
=
true
),
"perfCntDCacheMissQueuePenaltyEntry"
+
Integer
.
toString
(
i
,
10
),
Perf
...
...
src/main/scala/xiangshan/cache/prefetch/BestOffsetPrefetch.scala
浏览文件 @
51f54365
...
...
@@ -12,21 +12,24 @@ case class BOPParameters(
scoreBits
:
Int
,
roundMax
:
Int
,
badScore
:
Int
,
scores
:
Int
=
52
,
// TODO: Is 256-offset necessary, which will cross pages?
offsetList
:
Seq
[
Int
]
=
Seq
(
1
,
2
,
3
,
4
,
5
,
6
,
8
,
9
,
10
,
12
,
15
,
16
,
18
,
20
,
24
,
25
,
27
,
30
,
32
,
36
,
15
,
16
/*
, 18, 20, 24, 25, 27, 30, 32, 36,
40, 45, 48, 50, 54, 60, 64, 72, 75, 80,
81, 90, 96, 100, 108, 120, 125, 128, 135, 144,
150, 160, 162, 180, 192, 200, 216, 225, 240, 243,
250
,
256
250, 256
*/
),
blockBytes
:
Int
blockBytes
:
Int
,
nEntries
:
Int
)
{
def
scores
=
offsetList
.
length
def
offsetWidth
=
log2Up
(
offsetList
(
scores
-
1
))
+
1
def
rrIdxBits
=
log2Up
(
rrTableEntries
)
def
roundBits
=
log2Up
(
roundMax
)
def
scoreMax
=
(
1
<<
scoreBits
)
-
1
def
totalWidth
=
log2Up
(
nEntries
)
// id's width
}
class
ScoreTableEntry
(
p
:
BOPParameters
)
extends
PrefetchBundle
{
...
...
@@ -34,7 +37,7 @@ class ScoreTableEntry(p: BOPParameters) extends PrefetchBundle {
val
score
=
UInt
(
p
.
scoreBits
.
W
)
def
apply
(
offset
:
UInt
,
score
:
UInt
)
=
{
val
entry
=
new
ScoreTableEntry
(
p
)
val
entry
=
Wire
(
new
ScoreTableEntry
(
p
)
)
entry
.
offset
:=
offset
entry
.
score
:=
score
entry
...
...
@@ -78,9 +81,51 @@ class TestOffsetBundle(p: BOPParameters) extends PrefetchBundle {
override
def
cloneType
:
this.
type
=
(
new
TestOffsetBundle
(
p
)).
asInstanceOf
[
this.
type
]
}
class
BestOffsetPrefetchReq
(
p
:
BOPParameters
)
extends
PrefetchReq
{
val
id
=
UInt
(
p
.
totalWidth
.
W
)
override
def
toPrintable
:
Printable
=
{
p
"addr=0x${Hexadecimal(addr)} w=${write} id=0x${Hexadecimal(id)}"
}
override
def
cloneType
:
this.
type
=
(
new
BestOffsetPrefetchReq
(
p
)).
asInstanceOf
[
this.
type
]
}
class
BestOffsetPrefetchResp
(
p
:
BOPParameters
)
extends
PrefetchResp
{
val
id
=
UInt
(
p
.
totalWidth
.
W
)
override
def
toPrintable
:
Printable
=
{
p
"id=0x${Hexadecimal(id)}"
}
override
def
cloneType
:
this.
type
=
(
new
BestOffsetPrefetchResp
(
p
)).
asInstanceOf
[
this.
type
]
}
class
BestOffsetPrefetchFinish
(
p
:
BOPParameters
)
extends
PrefetchFinish
{
val
id
=
UInt
(
p
.
totalWidth
.
W
)
override
def
toPrintable
:
Printable
=
{
p
"id=0x${Hexadecimal(id)}"
}
override
def
cloneType
:
this.
type
=
(
new
BestOffsetPrefetchFinish
(
p
)).
asInstanceOf
[
this.
type
]
}
class
BestOffsetPrefetchIO
(
p
:
BOPParameters
)
extends
PrefetchBundle
{
val
train
=
Flipped
(
ValidIO
(
new
PrefetchTrain
))
val
req
=
DecoupledIO
(
new
BestOffsetPrefetchReq
(
p
))
val
resp
=
Flipped
(
DecoupledIO
(
new
BestOffsetPrefetchResp
(
p
)))
val
finish
=
DecoupledIO
(
new
BestOffsetPrefetchFinish
(
p
))
override
def
toPrintable
:
Printable
=
{
p
"train: v=${train.valid} ${train.bits} "
+
p
"req: v=${req.valid} r=${req.ready} ${req.bits} "
+
p
"resp: v=${resp.valid} r=${resp.ready} ${resp.bits} "
+
p
"finish: v=${finish.valid} r=${finish.ready} ${finish.bits}"
}
override
def
cloneType
:
this.
type
=
(
new
BestOffsetPrefetchIO
(
p
)).
asInstanceOf
[
this.
type
]
}
class
RecentRequestTable
(
p
:
BOPParameters
)
extends
PrefetchModule
{
val
io
=
IO
(
new
Bundle
{
val
w
=
Flipped
(
Vali
dIO
(
UInt
(
PAddrBits
.
W
)))
val
w
=
Flipped
(
Decouple
dIO
(
UInt
(
PAddrBits
.
W
)))
val
r
=
Flipped
(
new
TestOffsetBundle
(
p
))
})
def
rrIdxBits
=
p
.
rrIdxBits
...
...
@@ -108,10 +153,10 @@ class RecentRequestTable(p: BOPParameters) extends PrefetchModule {
}
}
val
rrTable
=
Module
(
new
SRAMTemplate
(
rrTableEntry
(),
set
=
rrTableEntries
,
way
=
1
,
shouldReset
=
true
))
val
rrTable
=
Module
(
new
SRAMTemplate
(
rrTableEntry
(),
set
=
rrTableEntries
,
way
=
1
,
shouldReset
=
true
,
singlePort
=
true
))
val
wAddr
=
io
.
w
.
bits
rrTable
.
io
.
w
.
req
.
valid
:=
io
.
w
.
valid
rrTable
.
io
.
w
.
req
.
valid
:=
io
.
w
.
valid
&&
!
io
.
r
.
req
.
valid
rrTable
.
io
.
w
.
req
.
bits
.
setIdx
:=
idx
(
wAddr
)
rrTable
.
io
.
w
.
req
.
bits
.
data
.
valid
:=
true
.
B
rrTable
.
io
.
w
.
req
.
bits
.
data
.
tag
:=
tag
(
wAddr
)
...
...
@@ -122,32 +167,35 @@ class RecentRequestTable(p: BOPParameters) extends PrefetchModule {
rrTable
.
io
.
r
.
req
.
bits
.
setIdx
:=
idx
(
rAddr
)
rData
:=
rrTable
.
io
.
r
.
resp
.
data
(
0
)
val
rwConflict
=
io
.
w
.
valid
&&
io
.
r
.
req
.
fire
()
&&
idx
(
wAddr
)
===
idx
(
rAddr
)
when
(
rwConflict
)
{
rrTable
.
io
.
r
.
req
.
valid
:=
false
.
B
}
when
(
RegNext
(
rwConflict
))
{
rData
.
valid
:=
true
.
B
rData
.
tag
:=
RegNext
(
tag
(
wAddr
))
}
val
rwConflict
=
io
.
w
.
fire
()
&&
io
.
r
.
req
.
fire
()
&&
idx
(
wAddr
)
===
idx
(
rAddr
)
//
when (rwConflict) {
//
rrTable.io.r.req.valid := false.B
//
}
//
when (RegNext(rwConflict)) {
//
rData.valid := true.B
//
rData.tag := RegNext(tag(wAddr))
//
}
io
.
w
.
ready
:=
rrTable
.
io
.
w
.
req
.
ready
&&
!
io
.
r
.
req
.
valid
io
.
r
.
req
.
ready
:=
true
.
B
io
.
r
.
resp
.
valid
:=
RegNext
(
io
.
r
.
req
.
fire
())
io
.
r
.
resp
.
valid
:=
RegNext
(
rrTable
.
io
.
r
.
req
.
fire
())
io
.
r
.
resp
.
bits
.
testOffset
:=
RegNext
(
io
.
r
.
req
.
bits
.
testOffset
)
io
.
r
.
resp
.
bits
.
ptr
:=
RegNext
(
io
.
r
.
req
.
bits
.
ptr
)
io
.
r
.
resp
.
bits
.
hit
:=
rData
.
valid
&&
rData
.
tag
===
RegNext
(
tag
(
rAddr
))
assert
(!
RegNext
(
rwConflict
),
"single port SRAM should not read and write at the same time"
)
// debug info
XSDebug
(
io
.
w
.
valid
,
p
"io.write: v=${io.w.valid} addr=0x${Hexadecimal(io.w.bits)}\n"
)
XSDebug
(
io
.
w
.
fire
()
,
p
"io.write: v=${io.w.valid} addr=0x${Hexadecimal(io.w.bits)}\n"
)
XSDebug
(
p
"io.read: ${io.r}\n"
)
XSDebug
(
io
.
w
.
valid
,
p
"wAddr=0x${Hexadecimal(wAddr)} idx=${Hexadecimal(idx(wAddr))} tag=${Hexadecimal(tag(wAddr))}\n"
)
XSDebug
(
io
.
w
.
fire
()
,
p
"wAddr=0x${Hexadecimal(wAddr)} idx=${Hexadecimal(idx(wAddr))} tag=${Hexadecimal(tag(wAddr))}\n"
)
XSDebug
(
io
.
r
.
req
.
fire
(),
p
"rAddr=0x${Hexadecimal(rAddr)} idx=${Hexadecimal(idx(rAddr))} rData=${rData}\n"
)
XSDebug
(
rwConflict
,
p
"write and read conflict!\n"
)
}
class
OffsetScoreTable
(
p
:
BOPParameters
)
extends
PrefetchModule
{
val
io
=
IO
(
new
Bundle
{
val
req
=
Flipped
(
DecoupledIO
(
UInt
(
PAddrBits
.
W
)))
// req addr from L1
val
prefetchOffset
=
Output
(
UInt
(
p
.
offsetWidth
.
W
))
val
test
=
new
TestOffsetBundle
(
p
)
})
...
...
@@ -158,34 +206,35 @@ class OffsetScoreTable(p: BOPParameters) extends PrefetchModule {
def
roundBits
=
p
.
roundBits
def
roundMax
=
p
.
roundMax
def
scoreMax
=
p
.
scoreMax
def
badScore
=
p
.
badScore
val
prefetchOffset
=
RegInit
(
1.
U
(
offsetWidth
))
// best offset is 1, this
is, a next-line prefetcher as initialization
val
prefetchOffset
=
RegInit
(
2.
U
(
offsetWidth
.
W
))
// best offset is 1, that
is, a next-line prefetcher as initialization
val
st
=
RegInit
(
VecInit
(
offsetList
.
map
(
off
=>
new
ScoreTableEntry
(
p
).
apply
(
off
.
U
,
0.
U
))))
val
ptr
=
RegInit
(
0.
U
(
log2Up
(
scores
).
W
))
val
round
=
RegInit
(
0.
U
(
roundBits
.
W
))
val
bestOffset
=
RegInit
(
new
ScoreTableEntry
(
p
).
apply
(
1
.
U
,
0.
U
))
// the entry with the highest score while traversing
val
testOffset
=
WireInit
(
0.
U
(
offsetWidth
.
W
)
)
val
bestOffset
=
RegInit
(
new
ScoreTableEntry
(
p
).
apply
(
2
.
U
,
0.
U
))
// the entry with the highest score while traversing
val
testOffset
=
WireInit
(
st
(
ptr
).
offset
)
def
winner
(
e1
:
ScoreTableEntry
,
e2
:
ScoreTableEntry
)
:
ScoreTableEntry
=
{
val
w
=
new
ScoreTableEntry
(
p
)
val
w
=
Wire
(
new
ScoreTableEntry
(
p
)
)
w
:=
Mux
(
e1
.
score
>
e2
.
score
,
e1
,
e2
)
w
}
val
s_idle
::
s_learn
::
s_finish
::
Nil
=
Enum
(
3
)
val
s_idle
::
s_learn
::
Nil
=
Enum
(
2
)
val
state
=
RegInit
(
s_idle
)
// 1. At the start of a learning phase
// All the scores are reset to 0.
// At the end of every learning phase, the prefetch offset is updated as the one with the highest score.
when
(
state
===
s_idle
)
{
when
(
ptr
=/=
scores
.
U
)
{
st
(
ptr
).
score
:=
0.
U
ptr
:=
ptr
+
1.
U
}.
otherwise
{
st
.
foreach
(
_
.
score
:=
0.
U
)
ptr
:=
0.
U
round
:=
0.
U
bestOffset
.
score
:=
badScore
.
U
prefetchOffset
:=
bestOffset
.
offset
state
:=
s_learn
}
}
// 2. During a learning phase
// On every eligible L2 read access (miss or prefetched hit), we test an offset d_i from the list.
...
...
@@ -196,16 +245,18 @@ class OffsetScoreTable(p: BOPParameters) extends PrefetchModule {
// (1) one of the score equals SCOREMAX, or
// (2) the number of rounds equals ROUNDMAX.
when
(
state
===
s_learn
)
{
testOffset
:=
st
(
ptr
).
offset
when
(
io
.
test
.
req
.
fire
())
{
val
roundFinish
=
ptr
===
(
scores
-
1
).
U
ptr
:=
Mux
(
roundFinish
,
0.
U
,
ptr
+
1.
U
)
round
:=
Mux
(
roundFinish
,
round
+
1.
U
,
round
)
XSDebug
(
p
"test offset ${testOffset} req fire\n"
)
}
// (2) the number of rounds equals ROUNDMAX.
when
(
round
===
roundMax
.
U
)
{
state
:=
s_finish
when
(
round
>=
roundMax
.
U
)
{
state
:=
s_idle
XSDebug
(
p
"round reaches roundMax(${roundMax.U})\n"
)
}
when
(
io
.
test
.
resp
.
fire
()
&&
io
.
test
.
resp
.
bits
.
hit
)
{
...
...
@@ -216,25 +267,148 @@ class OffsetScoreTable(p: BOPParameters) extends PrefetchModule {
st
(
io
.
test
.
resp
.
bits
.
ptr
).
score
:=
newScore
bestOffset
:=
winner
(
new
ScoreTableEntry
(
p
).
apply
(
offset
,
newScore
),
bestOffset
)
// (1) one of the score equals SCOREMAX
when
(
newScore
===
scoreMax
.
U
)
{
state
:=
s_finish
when
(
newScore
>=
scoreMax
.
U
)
{
state
:=
s_idle
XSDebug
(
p
"newScore reaches scoreMax(${scoreMax.U})\n"
)
}
XSDebug
(
p
"test offset ${offset} resp fire and hit. score ${oldScore} -> ${newScore}\n"
)
}
}
io
.
req
.
ready
:=
true
.
B
io
.
prefetchOffset
:=
prefetchOffset
io
.
test
.
req
.
valid
:=
state
===
s_learn
&&
io
.
req
.
fire
()
io
.
test
.
req
.
bits
.
addr
:=
io
.
req
.
bits
io
.
test
.
req
.
bits
.
testOffset
:=
testOffset
io
.
test
.
req
.
bits
.
ptr
:=
ptr
io
.
test
.
resp
.
ready
:=
true
.
B
XSDebug
(
p
"state=${state} prefetchOffset=${prefetchOffset} ptr=${ptr} round=${round} bestOffset=${bestOffset} testOffset=${testOffset}\n"
)
// score table
XSDebug
(
p
"OffsetScoreTable(idx:offset:score) as follows:\n"
)
for
(
i
<-
0
until
scores
)
{
if
(
i
%
8
==
0
)
{
XSDebug
(
p
"${i.U}:${st(i)}\t"
)
}
else
if
(
i
%
8
==
7
||
i
==
scores
-
1
)
{
XSDebug
(
false
,
true
.
B
,
p
"${i.U}:${st(i)}\n"
)
}
else
{
XSDebug
(
false
,
true
.
B
,
p
"${i.U}:${st(i)}\t"
)
}
}
XSDebug
(
io
.
req
.
fire
(),
p
"receive req from L1. io.req.bits=0x${Hexadecimal(io.req.bits)}\n"
)
}
class
BestOffsetPrefetchEntry
(
p
:
BOPParameters
)
extends
PrefetchModule
{
val
io
=
IO
(
new
Bundle
{
val
id
=
Input
(
UInt
(
p
.
totalWidth
.
W
))
val
prefetchOffset
=
Input
(
UInt
(
p
.
offsetWidth
.
W
))
val
pft
=
new
BestOffsetPrefetchIO
(
p
)
val
inflight
=
ValidIO
(
UInt
(
PAddrBits
.
W
))
val
writeRRTable
=
DecoupledIO
(
UInt
(
PAddrBits
.
W
))
})
def
blockBytes
=
p
.
blockBytes
def
getBlockAddr
(
addr
:
UInt
)
=
Cat
(
addr
(
PAddrBits
-
1
,
log2Up
(
blockBytes
)),
0.
U
(
log2Up
(
blockBytes
).
W
))
val
s_idle
::
s_req
::
s_resp
::
s_write_recent_req
::
s_finish
::
Nil
=
Enum
(
5
)
val
state
=
RegInit
(
s_idle
)
val
req
=
RegInit
(
0.
U
.
asTypeOf
(
new
PrefetchReq
))
val
baseAddr
=
RegInit
(
0.
U
(
PAddrBits
.
W
))
when
(
state
===
s_idle
)
{
when
(
io
.
pft
.
train
.
valid
)
{
state
:=
s_req
req
.
addr
:=
getBlockAddr
(
io
.
pft
.
train
.
bits
.
addr
)
+
(
io
.
prefetchOffset
<<
log2Up
(
blockBytes
))
req
.
write
:=
io
.
pft
.
train
.
bits
.
write
baseAddr
:=
getBlockAddr
(
io
.
pft
.
train
.
bits
.
addr
)
}
}
when
(
state
===
s_req
)
{
when
(
io
.
pft
.
req
.
fire
())
{
state
:=
s_resp
}
}
when
(
state
===
s_resp
)
{
when
(
io
.
pft
.
resp
.
fire
())
{
state
:=
s_write_recent_req
}
}
when
(
state
===
s_write_recent_req
)
{
when
(
io
.
writeRRTable
.
fire
())
{
state
:=
s_finish
}
}
// 3. At the end of every learning phase, the prefetch offset is updated as the one with the highest score.
when
(
state
===
s_finish
)
{
prefetchOffset
:=
bestOffset
.
offset
ptr
:=
0.
U
round
:=
0.
U
bestOffset
.
offset
:=
1.
U
bestOffset
.
score
:=
0.
U
when
(
io
.
pft
.
finish
.
fire
())
{
state
:=
s_idle
}
}
io
.
pft
.
req
.
valid
:=
state
===
s_req
io
.
pft
.
req
.
bits
.
addr
:=
req
.
addr
io
.
pft
.
req
.
bits
.
write
:=
req
.
write
io
.
pft
.
req
.
bits
.
id
:=
io
.
id
io
.
pft
.
resp
.
ready
:=
state
===
s_resp
io
.
pft
.
finish
.
valid
:=
state
===
s_finish
io
.
pft
.
finish
.
bits
.
id
:=
io
.
id
io
.
inflight
.
valid
:=
state
=/=
s_idle
io
.
inflight
.
bits
:=
req
.
addr
io
.
writeRRTable
.
valid
:=
state
===
s_write_recent_req
io
.
writeRRTable
.
bits
:=
baseAddr
// write this into recent request table
XSDebug
(
p
"bopEntry ${io.id}: state=${state} prefetchOffset=${io.prefetchOffset} inflight=${io.inflight.valid} 0x${Hexadecimal(io.inflight.bits)} writeRRTable: ${io.writeRRTable.valid} 0x${Hexadecimal(io.writeRRTable.bits)} baseAddr=0x${Hexadecimal(baseAddr)} req: ${req}\n"
)
XSDebug
(
p
"bopEntry ${io.id}: io.pft: ${io.pft}\n"
)
}
class
BestOffsetPrefetch
(
p
:
BOPParameters
)
extends
PrefetchModule
{
val
io
=
IO
(
new
BestOffsetPrefetchIO
(
p
))
def
nEntries
=
p
.
nEntries
def
blockBytes
=
p
.
blockBytes
def
getBlockAddr
(
addr
:
UInt
)
=
Cat
(
addr
(
PAddrBits
-
1
,
log2Up
(
blockBytes
)),
0.
U
(
log2Up
(
blockBytes
).
W
))
val
scoreTable
=
Module
(
new
OffsetScoreTable
(
p
))
val
rrTable
=
Module
(
new
RecentRequestTable
(
p
))
val
reqArb
=
Module
(
new
Arbiter
(
new
BestOffsetPrefetchReq
(
p
),
nEntries
))
val
finishArb
=
Module
(
new
Arbiter
(
new
BestOffsetPrefetchFinish
(
p
),
nEntries
))
val
writeRRTableArb
=
Module
(
new
Arbiter
(
UInt
(
PAddrBits
.
W
),
nEntries
))
val
entryReadyIdx
=
Wire
(
UInt
(
log2Up
(
nEntries
).
W
))
val
inflightMatchVec
=
Wire
(
Vec
(
nEntries
,
Bool
()))
val
bopEntries
=
(
0
until
nEntries
).
map
{
i
=>
val
bopEntry
=
Module
(
new
BestOffsetPrefetchEntry
(
p
))
bopEntry
.
io
.
id
:=
i
.
U
bopEntry
.
io
.
prefetchOffset
:=
scoreTable
.
io
.
prefetchOffset
bopEntry
.
io
.
pft
.
train
.
valid
:=
io
.
train
.
valid
&&
i
.
U
===
entryReadyIdx
&&
!
inflightMatchVec
.
asUInt
.
orR
bopEntry
.
io
.
pft
.
train
.
bits
:=
io
.
train
.
bits
reqArb
.
io
.
in
(
i
)
<>
bopEntry
.
io
.
pft
.
req
bopEntry
.
io
.
pft
.
resp
.
valid
:=
io
.
resp
.
valid
&&
i
.
U
===
io
.
resp
.
bits
.
id
bopEntry
.
io
.
pft
.
resp
.
bits
:=
io
.
resp
.
bits
finishArb
.
io
.
in
(
i
)
<>
bopEntry
.
io
.
pft
.
finish
writeRRTableArb
.
io
.
in
(
i
)
<>
bopEntry
.
io
.
writeRRTable
bopEntry
}
entryReadyIdx
:=
PriorityEncoder
(
bopEntries
.
map
{
e
=>
!
e
.
io
.
inflight
.
valid
})
(
0
until
nEntries
).
foreach
(
i
=>
inflightMatchVec
(
i
)
:=
bopEntries
(
i
).
io
.
inflight
.
valid
&&
bopEntries
(
i
).
io
.
inflight
.
bits
===
getBlockAddr
(
io
.
train
.
bits
.
addr
)
)
io
.
req
<>
reqArb
.
io
.
out
io
.
resp
.
ready
:=
VecInit
(
bopEntries
.
zipWithIndex
.
map
{
case
(
e
,
i
)
=>
i
.
U
===
io
.
resp
.
bits
.
id
&&
e
.
io
.
pft
.
resp
.
ready
}).
asUInt
.
orR
io
.
finish
<>
finishArb
.
io
.
out
rrTable
.
io
.
w
<>
writeRRTableArb
.
io
.
out
rrTable
.
io
.
r
<>
scoreTable
.
io
.
test
scoreTable
.
io
.
req
.
valid
:=
io
.
train
.
valid
scoreTable
.
io
.
req
.
bits
:=
getBlockAddr
(
io
.
train
.
bits
.
addr
)
XSDebug
(
p
"io: ${io}\n"
)
XSDebug
(
p
"entryReadyIdx=${entryReadyIdx} inflightMatchVec=${Binary(inflightMatchVec.asUInt)}\n"
)
io
.
prefetchOffset
:=
prefetchOffset
io
.
test
.
req
.
valid
:=
state
===
s_learn
&&
round
=/=
roundMax
.
U
io
.
test
.
req
.
bits
.
addr
:=
DontCare
// assign this outside the score table
io
.
test
.
req
.
bits
.
testOffset
:=
testOffset
io
.
test
.
req
.
bits
.
ptr
:=
ptr
}
src/main/scala/xiangshan/cache/prefetch/L2Prefetcher.scala
浏览文件 @
51f54365
...
...
@@ -15,13 +15,30 @@ import freechips.rocketchip.tilelink.{TLClientNode, TLClientParameters,
TLEdgeOut
,
TLBundleA
,
TLBundleD
,
ClientStates
,
ClientMetadata
,
TLHints
}
import
sifive.blocks.inclusivecache.PrefetcherIO
case
class
L2PrefetcherParameters
(
enable
:
Boolean
,
_type
:
String
,
streamParams
:
StreamPrefetchParameters
streamParams
:
StreamPrefetchParameters
,
bopParams
:
BOPParameters
)
{
def
nEntries
:
Int
=
streamParams
.
streamCnt
*
streamParams
.
streamSize
// def nEntries: Int = streamParams.streamCnt * streamParams.streamSize
def
nEntries
:
Int
=
{
if
(
enable
&&
_type
==
"stream"
)
{
streamParams
.
streamCnt
*
streamParams
.
streamSize
}
else
if
(
enable
&&
_type
==
"bop"
)
{
bopParams
.
nEntries
}
else
1
}
def
totalWidth
:
Int
=
{
if
(
enable
&&
_type
==
"stream"
)
streamParams
.
totalWidth
else
if
(
enable
&&
_type
==
"bop"
)
bopParams
.
totalWidth
else
1
}
def
blockBytes
:
Int
=
{
if
(
enable
&&
_type
==
"stream"
)
streamParams
.
blockBytes
else
if
(
enable
&&
_type
==
"bop"
)
bopParams
.
blockBytes
else
64
}
}
class
L2Prefetcher
()(
implicit
p
:
Parameters
)
extends
LazyModule
with
HasPrefetchParameters
{
...
...
@@ -37,18 +54,41 @@ class L2Prefetcher()(implicit p: Parameters) extends LazyModule with HasPrefetch
lazy
val
module
=
new
L2PrefetcherImp
(
this
)
}
class
L2PrefetcherIO
extends
XSBundle
with
HasPrefetchParameters
{
val
in
=
Flipped
(
DecoupledIO
(
new
MissReq
))
}
// prefetch DCache lines in L2 using StreamPrefetch
class
L2PrefetcherImp
(
outer
:
L2Prefetcher
)
extends
LazyModuleImp
(
outer
)
with
HasPrefetchParameters
with
HasXSLog
{
val
io
=
IO
(
new
Bundle
{
val
in
=
Flipped
(
DecoupledIO
(
new
MissReq
))
// prefetch
// val mem_acquire = Decoupled(new TLBundleA(edge.bundle))
// val mem_grant = Flipped(Decoupled(new TLBundleD(edge.bundle)))
// val mem_finish = Decoupled(new TLBundleE(edge.bundle))
})
val
io
=
IO
(
new
L2PrefetcherIO
)
val
(
bus
,
edge
)
=
outer
.
clientNode
.
out
.
head
if
(
l2PrefetcherParameters
.
enable
&&
l2PrefetcherParameters
.
_type
==
"stream"
)
{
if
(
l2PrefetcherParameters
.
enable
&&
l2PrefetcherParameters
.
_type
==
"bop"
)
{
val
bopParams
=
l2PrefetcherParameters
.
bopParams
val
dPrefetch
=
Module
(
new
BestOffsetPrefetch
(
bopParams
))
dPrefetch
.
io
.
train
.
valid
:=
io
.
in
.
fire
()
dPrefetch
.
io
.
train
.
bits
.
addr
:=
io
.
in
.
bits
.
addr
dPrefetch
.
io
.
train
.
bits
.
write
:=
MemoryOpConstants
.
isWrite
(
io
.
in
.
bits
.
cmd
)
dPrefetch
.
io
.
train
.
bits
.
miss
:=
true
.
B
io
.
in
.
ready
:=
true
.
B
bus
.
a
.
valid
:=
dPrefetch
.
io
.
req
.
valid
bus
.
a
.
bits
:=
DontCare
bus
.
a
.
bits
:=
edge
.
Hint
(
fromSource
=
dPrefetch
.
io
.
req
.
bits
.
id
,
toAddress
=
dPrefetch
.
io
.
req
.
bits
.
addr
,
lgSize
=
log2Up
(
bopParams
.
blockBytes
).
U
,
param
=
Mux
(
dPrefetch
.
io
.
req
.
bits
.
write
,
TLHints
.
PREFETCH_WRITE
,
TLHints
.
PREFETCH_READ
)
).
_2
dPrefetch
.
io
.
req
.
ready
:=
bus
.
a
.
ready
dPrefetch
.
io
.
resp
.
valid
:=
bus
.
d
.
valid
dPrefetch
.
io
.
resp
.
bits
.
id
:=
bus
.
d
.
bits
.
source
(
bopParams
.
totalWidth
-
1
,
0
)
bus
.
d
.
ready
:=
dPrefetch
.
io
.
resp
.
ready
dPrefetch
.
io
.
finish
.
ready
:=
true
.
B
}
else
if
(
l2PrefetcherParameters
.
enable
&&
l2PrefetcherParameters
.
_type
==
"stream"
)
{
val
streamParams
=
l2PrefetcherParameters
.
streamParams
val
dPrefetch
=
Module
(
new
StreamPrefetch
(
streamParams
))
dPrefetch
.
io
.
train
.
valid
:=
io
.
in
.
fire
()
...
...
@@ -62,32 +102,38 @@ class L2PrefetcherImp(outer: L2Prefetcher) extends LazyModuleImp(outer) with Has
bus
.
a
.
bits
:=
edge
.
Hint
(
fromSource
=
dPrefetch
.
io
.
req
.
bits
.
id
,
toAddress
=
dPrefetch
.
io
.
req
.
bits
.
addr
,
lgSize
=
log2Up
(
streamParam
s
.
blockBytes
).
U
,
lgSize
=
log2Up
(
l2PrefetcherParameter
s
.
blockBytes
).
U
,
param
=
Mux
(
dPrefetch
.
io
.
req
.
bits
.
write
,
TLHints
.
PREFETCH_WRITE
,
TLHints
.
PREFETCH_READ
)
// TODO
).
_2
dPrefetch
.
io
.
req
.
ready
:=
bus
.
a
.
ready
dPrefetch
.
io
.
resp
.
valid
:=
bus
.
d
.
valid
dPrefetch
.
io
.
resp
.
bits
.
id
:=
bus
.
d
.
bits
.
source
(
l2PrefetcherParameters
.
totalWidth
-
1
,
0
)
bus
.
d
.
ready
:=
dPrefetch
.
io
.
resp
.
ready
dPrefetch
.
io
.
finish
.
ready
:=
true
.
B
}
else
{
bus
.
a
.
valid
:=
false
.
B
bus
.
a
.
bits
:=
DontCare
bus
.
d
.
ready
:=
true
.
B
}
bus
.
b
.
ready
:=
true
.
B
bus
.
c
.
valid
:=
false
.
B
bus
.
c
.
bits
:=
DontCare
dPrefetch
.
io
.
resp
.
valid
:=
bus
.
d
.
valid
dPrefetch
.
io
.
resp
.
bits
.
id
:=
bus
.
d
.
bits
.
source
(
streamParams
.
totalWidth
-
1
,
0
)
bus
.
d
.
ready
:=
dPrefetch
.
io
.
resp
.
ready
bus
.
e
.
valid
:=
false
.
B
bus
.
e
.
bits
:=
DontCare
dPrefetch
.
io
.
finish
.
ready
:=
true
.
B
if
(!
env
.
FPGAPlatform
)
{
ExcitingUtils
.
addSource
(
bus
.
a
.
fire
(),
"perfCntL2PrefetchReqCnt"
,
Perf
)
def
idWidth
=
log2Up
(
l2PrefetcherParameters
.
nEntries
)
(
0
until
l2PrefetcherParameters
.
nEntries
).
foreach
(
i
=>
ExcitingUtils
.
addSource
(
BoolStopWatch
(
start
=
bus
.
a
.
fire
()
&&
dPrefetch
.
io
.
req
.
bits
.
id
(
streamParam
s
.
totalWidth
-
1
,
0
)
===
i
.
U
,
stop
=
bus
.
d
.
fire
()
&&
bus
.
d
.
bits
.
source
(
streamParam
s
.
totalWidth
-
1
,
0
)
===
i
.
U
,
start
=
bus
.
a
.
fire
()
&&
bus
.
a
.
bits
.
source
(
l2PrefetcherParameter
s
.
totalWidth
-
1
,
0
)
===
i
.
U
,
stop
=
bus
.
d
.
fire
()
&&
bus
.
d
.
bits
.
source
(
l2PrefetcherParameter
s
.
totalWidth
-
1
,
0
)
===
i
.
U
,
startHighPriority
=
true
),
"perfCntL2PrefetchPenaltyEntry"
+
Integer
.
toString
(
i
,
10
),
...
...
@@ -95,16 +141,5 @@ class L2PrefetcherImp(outer: L2Prefetcher) extends LazyModuleImp(outer) with Has
)
)
}
}
else
{
bus
.
a
.
valid
:=
false
.
B
bus
.
a
.
bits
:=
DontCare
bus
.
b
.
ready
:=
true
.
B
bus
.
c
.
valid
:=
false
.
B
bus
.
c
.
bits
:=
DontCare
bus
.
d
.
ready
:=
true
.
B
bus
.
e
.
valid
:=
false
.
B
bus
.
e
.
bits
:=
DontCare
}
}
src/main/scala/xiangshan/cache/prefetch/Prefetcher.scala
浏览文件 @
51f54365
...
...
@@ -40,11 +40,11 @@ class PrefetchTrain extends PrefetchBundle {
}
}
class
PrefetchIO
extends
PrefetchBundle
{
val
train
=
Flipped
(
ValidIO
(
new
PrefetchTrain
))
val
req
=
DecoupledIO
(
new
PrefetchReq
)
val
resp
=
Flipped
(
DecoupledIO
(
new
PrefetchResp
))
}
//
class PrefetchIO extends PrefetchBundle {
//
val train = Flipped(ValidIO(new PrefetchTrain))
//
val req = DecoupledIO(new PrefetchReq)
//
val resp = Flipped(DecoupledIO(new PrefetchResp))
//
}
// class FakePrefetcher extends PrefetchModule {
// val io = IO(new PrefetchIO)
...
...
src/main/scala/xiangshan/cache/prefetch/StreamPrefetch.scala
浏览文件 @
51f54365
...
...
@@ -11,7 +11,8 @@ case class StreamPrefetchParameters(
streamSize
:
Int
,
ageWidth
:
Int
,
blockBytes
:
Int
,
reallocStreamOnMissInstantly
:
Boolean
reallocStreamOnMissInstantly
:
Boolean
,
cacheName
:
String
// distinguish between different prefetchers
)
{
def
streamWidth
=
log2Up
(
streamCnt
)
def
idxWidth
=
log2Up
(
streamSize
)
...
...
@@ -107,7 +108,7 @@ class StreamBuffer(p: StreamPrefetchParameters) extends PrefetchModule {
val
buf
=
RegInit
(
VecInit
(
Seq
.
fill
(
streamSize
)(
0.
U
.
asTypeOf
(
new
PrefetchReq
))))
val
valid
=
RegInit
(
VecInit
(
Seq
.
fill
(
streamSize
)(
false
.
B
)))
val
head
=
RegInit
(
0.
U
(
log2Up
(
streamSize
).
W
))
val
tail
=
RegInit
(
0.
U
(
log2Up
(
stream
Cnt
).
W
))
val
tail
=
RegInit
(
0.
U
(
log2Up
(
stream
Size
).
W
))
val
s_idle
::
s_req
::
s_resp
::
s_finish
::
Nil
=
Enum
(
4
)
val
state
=
RegInit
(
VecInit
(
Seq
.
fill
(
streamSize
)(
s_idle
)))
...
...
@@ -122,7 +123,7 @@ class StreamBuffer(p: StreamPrefetchParameters) extends PrefetchModule {
// dequeue
val
hitIdx
=
io
.
update
.
bits
.
hitIdx
when
(
io
.
update
.
valid
&&
!
empty
&&
valid
(
hitIdx
))
{
when
(
io
.
update
.
valid
&&
!
empty
&&
(
isPrefetching
(
hitIdx
)
||
valid
(
hitIdx
)
))
{
val
headBeforehitIdx
=
head
<=
hitIdx
&&
(
hitIdx
<
tail
||
tail
<=
head
)
val
hitIdxBeforeHead
=
hitIdx
<
tail
&&
tail
<=
head
when
(
headBeforehitIdx
)
{
...
...
@@ -132,6 +133,8 @@ class StreamBuffer(p: StreamPrefetchParameters) extends PrefetchModule {
when
(
hitIdxBeforeHead
)
{
(
0
until
streamSize
).
foreach
(
i
=>
deqLater
(
i
)
:=
Mux
(
i
.
U
>=
head
||
i
.
U
<=
hitIdx
,
true
.
B
,
deqLater
(
i
)))
}
XSDebug
(
io
.
update
.
valid
&&
!
empty
&&
(
isPrefetching
(
hitIdx
)
||
valid
(
hitIdx
)),
p
"hitIdx=${hitIdx} headBeforehitIdx=${headBeforehitIdx} hitIdxBeforeHead=${hitIdxBeforeHead}\n"
)
}
val
deqValid
=
WireInit
(
VecInit
(
Seq
.
fill
(
streamSize
)(
false
.
B
)))
...
...
@@ -143,8 +146,15 @@ class StreamBuffer(p: StreamPrefetchParameters) extends PrefetchModule {
deqValid
(
idx
)
:=
deq
}
(
0
until
streamSize
).
foreach
(
i
=>
valid
(
i
)
:=
valid
(
i
)
&&
!
deqValid
(
i
))
(
0
until
streamSize
).
foreach
(
i
=>
deqLater
(
i
)
:=
deqLater
(
i
)
&&
!
deqValid
(
i
))
// (0 until streamSize).foreach(i => valid(i) := valid(i) && !deqValid(i))
// (0 until streamSize).foreach(i => deqLater(i) := deqLater(i) && !deqValid(i))
for
(
i
<-
0
until
streamSize
)
{
when
(
deqValid
(
i
))
{
valid
(
i
)
:=
false
.
B
deqLater
(
i
)
:=
false
.
B
}
}
val
nextHead
=
head
+
PopCount
(
deqValid
)
when
(
deqValid
.
asUInt
.
orR
)
{
head
:=
nextHead
...
...
@@ -198,13 +208,17 @@ class StreamBuffer(p: StreamPrefetchParameters) extends PrefetchModule {
val
finishArb
=
Module
(
new
Arbiter
(
new
StreamPrefetchFinish
(
p
),
streamSize
))
for
(
i
<-
0
until
streamSize
)
{
prefetchPrior
(
i
)
:=
head
+
i
.
U
reqs
(
i
).
ready
:=
false
.
B
reqArb
.
io
.
in
(
i
)
<>
reqs
(
prefetchPrior
(
i
))
finishs
(
i
).
ready
:=
false
.
B
reqs
(
i
).
ready
:=
DontCare
finishArb
.
io
.
in
(
i
)
<>
finishs
(
prefetchPrior
(
i
))
finishs
(
i
).
ready
:=
DontCare
resps
(
i
).
bits
:=
io
.
resp
.
bits
resps
(
i
).
valid
:=
io
.
resp
.
valid
&&
io
.
resp
.
bits
.
idx
===
i
.
U
}
for
(
i
<-
0
until
streamSize
)
{
reqs
(
prefetchPrior
(
i
)).
ready
:=
reqArb
.
io
.
in
(
i
).
ready
finishs
(
prefetchPrior
(
i
)).
ready
:=
finishArb
.
io
.
in
(
i
).
ready
}
io
.
req
<>
reqArb
.
io
.
out
io
.
finish
<>
finishArb
.
io
.
out
io
.
resp
.
ready
:=
VecInit
(
resps
.
zipWithIndex
.
map
{
case
(
r
,
i
)
=>
...
...
@@ -225,6 +239,7 @@ class StreamBuffer(p: StreamPrefetchParameters) extends PrefetchModule {
needRealloc
:=
false
.
B
state
.
foreach
(
_
:=
s_idle
)
valid
.
foreach
(
_
:=
false
.
B
)
deqLater
.
foreach
(
_
:=
false
.
B
)
}
for
(
i
<-
0
until
streamSize
)
{
...
...
@@ -233,20 +248,20 @@ class StreamBuffer(p: StreamPrefetchParameters) extends PrefetchModule {
}
// debug info
XSDebug
(
p
"StreamBuf ${io.streamBufId} io.req: v=${io.req.valid} r=${io.req.ready} ${io.req.bits}\n"
)
XSDebug
(
p
"StreamBuf ${io.streamBufId} io.resp: v=${io.resp.valid} r=${io.resp.ready} ${io.resp.bits}\n"
)
XSDebug
(
p
"StreamBuf ${io.streamBufId} io.finish: v=${io.finish.valid} r=${io.finish.ready} ${io.finish.bits}
"
)
XSDebug
(
p
"StreamBuf ${io.streamBufId} io.update: v=${io.update.valid} ${io.update.bits}\n"
)
XSDebug
(
p
"StreamBuf ${io.streamBufId} io.alloc: v=${io.alloc.valid} ${io.alloc.bits}\n"
)
XSDebug
(
s
"${p.cacheName} "
+
p
"StreamBuf ${io.streamBufId} io.req: v=${io.req.valid} r=${io.req.ready} ${io.req.bits}\n"
)
XSDebug
(
s
"${p.cacheName} "
+
p
"StreamBuf ${io.streamBufId} io.resp: v=${io.resp.valid} r=${io.resp.ready} ${io.resp.bits}\n"
)
XSDebug
(
s
"${p.cacheName} "
+
p
"StreamBuf ${io.streamBufId} io.finish: v=${io.finish.valid} r=${io.finish.ready} ${io.finish.bits}\n
"
)
XSDebug
(
s
"${p.cacheName} "
+
p
"StreamBuf ${io.streamBufId} io.update: v=${io.update.valid} ${io.update.bits}\n"
)
XSDebug
(
s
"${p.cacheName} "
+
p
"StreamBuf ${io.streamBufId} io.alloc: v=${io.alloc.valid} ${io.alloc.bits}\n"
)
for
(
i
<-
0
until
streamSize
)
{
XSDebug
(
p
"StreamBuf ${io.streamBufId} [${i.U}] io.addrs: ${io.addrs(i).valid} 0x${Hexadecimal(io.addrs(i).bits)} "
+
XSDebug
(
s
"${p.cacheName} "
+
p
"StreamBuf ${io.streamBufId} [${i.U}] io.addrs: ${io.addrs(i).valid} 0x${Hexadecimal(io.addrs(i).bits)} "
+
p
"buf: ${buf(i)} valid: ${valid(i)} state: ${state(i)} isPfting: ${isPrefetching(i)} "
+
p
"deqLater: ${deqLater(i)} deqValid: ${deqValid(i)}\n"
)
}
XSDebug
(
p
"StreamBuf ${io.streamBufId} head: ${head} tail: ${tail} full: ${full} empty: ${empty} nextHead: ${nextHead
}\n"
)
XSDebug
(
p
"StreamBuf ${io.streamBufId} baseReq: v=${baseReq.valid} ${baseReq.bits} nextReq: ${nextReq}\n"
)
XSDebug
(
needRealloc
,
p
"StreamBuf ${io.streamBufId} needRealloc: ${needRealloc} reallocReq: ${reallocReq}\n"
)
XSDebug
(
p
"StreamBuf ${io.streamBufId} prefetchPrior: "
)
XSDebug
(
s
"${p.cacheName} "
+
p
"StreamBuf ${io.streamBufId} head: ${head} tail: ${tail} full: ${full} empty: ${empty} nextHead: ${nextHead} blockBytes: ${blockBytes.U
}\n"
)
XSDebug
(
s
"${p.cacheName} "
+
p
"StreamBuf ${io.streamBufId} baseReq: v=${baseReq.valid} ${baseReq.bits} nextReq: ${nextReq}\n"
)
XSDebug
(
needRealloc
,
s
"${p.cacheName} "
+
p
"StreamBuf ${io.streamBufId} needRealloc: ${needRealloc} reallocReq: ${reallocReq}\n"
)
XSDebug
(
s
"${p.cacheName} "
+
p
"StreamBuf ${io.streamBufId} prefetchPrior: "
)
(
0
until
streamSize
).
foreach
(
i
=>
XSDebug
(
false
,
true
.
B
,
p
"${prefetchPrior(i)} "
))
XSDebug
(
false
,
true
.
B
,
"\n"
)
}
...
...
@@ -267,6 +282,8 @@ object ParallelMin {
class
StreamPrefetch
(
p
:
StreamPrefetchParameters
)
extends
PrefetchModule
{
val
io
=
IO
(
new
StreamPrefetchIO
(
p
))
require
(
p
.
blockBytes
>
0
)
// TODO: implement this
def
streamCnt
=
p
.
streamCnt
def
streamSize
=
p
.
streamSize
...
...
@@ -352,8 +369,8 @@ class StreamPrefetch(p: StreamPrefetchParameters) extends PrefetchModule {
i
.
U
===
io
.
resp
.
bits
.
stream
&&
buf
.
io
.
resp
.
ready
}).
asUInt
.
orR
// debug info
XSDebug
(
p
"io: ${io}\n"
)
XSDebug
(
p
"bufValids: ${Binary(bufValids.asUInt)} hit: ${hit} ages: "
)
XSDebug
(
s
"${p.cacheName} "
+
p
"io: ${io}\n"
)
XSDebug
(
s
"${p.cacheName} "
+
p
"bufValids: ${Binary(bufValids.asUInt)} hit: ${hit} ages: "
)
(
0
until
streamCnt
).
foreach
(
i
=>
XSDebug
(
false
,
true
.
B
,
p
"${Hexadecimal(ages(i))} "
))
XSDebug
(
false
,
true
.
B
,
"\n"
)
}
src/main/scala/xiangshan/cache/ptw.scala
浏览文件 @
51f54365
...
...
@@ -156,6 +156,94 @@ class PtwEntries(num: Int, tagLen: Int) extends PtwBundle {
}
}
class
L2TlbEntry
extends
TlbBundle
{
val
tag
=
UInt
(
vpnLen
.
W
)
// tag is vpn
val
level
=
UInt
(
log2Up
(
Level
).
W
)
// 2 for 4KB, 1 for 2MB, 0 for 1GB
val
ppn
=
UInt
(
ppnLen
.
W
)
val
perm
=
new
PtePermBundle
def
hit
(
vpn
:
UInt
)
:
Bool
=
{
val
fullMask
=
VecInit
((
Seq
.
fill
(
vpnLen
)(
true
.
B
))).
asUInt
val
maskLevel
=
VecInit
((
Level
-
1
to
0
by
-
1
).
map
{
i
=>
// NOTE: level 2 for 4KB, 1 for 2MB, 0 for 1GB
Reverse
(
VecInit
(
Seq
.
fill
(
vpnLen
-
i
*
vpnnLen
)(
true
.
B
)
++
Seq
.
fill
(
i
*
vpnnLen
)(
false
.
B
)).
asUInt
)})
val
mask
=
maskLevel
(
level
)
(
mask
&
this
.
tag
)
===
(
mask
&
vpn
)
}
def
apply
(
pte
:
UInt
,
level
:
UInt
,
vpn
:
UInt
)
=
{
this
.
tag
:=
vpn
this
.
level
:=
level
this
.
ppn
:=
pte
.
asTypeOf
(
pteBundle
).
ppn
this
.
perm
:=
pte
.
asTypeOf
(
pteBundle
).
perm
this
}
override
def
toPrintable
:
Printable
=
{
p
"vpn:0x${Hexadecimal(tag)} level:${level} ppn:${Hexadecimal(ppn)} perm:${perm}"
}
}
class
L2TlbEntires
(
num
:
Int
,
tagLen
:
Int
)
extends
TlbBundle
{
require
(
log2Up
(
num
)==
log2Down
(
num
))
/* vpn can be divide into three part */
// vpn: tagPart(17bit) + addrPart(8bit) + cutLenPart(2bit)
val
cutLen
=
log2Up
(
num
)
val
tag
=
UInt
(
tagLen
.
W
)
// NOTE: high part of vpn
val
ppns
=
Vec
(
num
,
UInt
(
ppnLen
.
W
))
val
perms
=
Vec
(
num
,
new
PtePermBundle
)
val
vs
=
Vec
(
num
,
Bool
())
def
tagClip
(
vpn
:
UInt
)
=
{
// full vpn => tagLen
vpn
(
vpn
.
getWidth
-
1
,
vpn
.
getWidth
-
tagLen
)
}
// NOTE: get insize idx
def
idxClip
(
vpn
:
UInt
)
=
{
vpn
(
cutLen
-
1
,
0
)
}
def
hit
(
vpn
:
UInt
)
=
{
(
tag
===
tagClip
(
vpn
))
&&
vs
(
idxClip
(
vpn
))
}
def
genEntries
(
data
:
UInt
,
level
:
UInt
,
vpn
:
UInt
)
:
L2TlbEntires
=
{
require
((
data
.
getWidth
/
XLEN
)
==
num
,
"input data length must be multiple of pte length"
)
assert
(
level
===
2.
U
,
"tlb entries only support 4K pages"
)
val
ts
=
Wire
(
new
L2TlbEntires
(
num
,
tagLen
))
ts
.
tag
:=
tagClip
(
vpn
)
for
(
i
<-
0
until
num
)
{
val
pte
=
data
((
i
+
1
)*
XLEN
-
1
,
i
*
XLEN
).
asTypeOf
(
new
PteBundle
)
ts
.
ppns
(
i
)
:=
pte
.
ppn
ts
.
perms
(
i
):=
pte
.
perm
// this.perms has no v
ts
.
vs
(
i
)
:=
!
pte
.
isPf
(
level
)
&&
pte
.
isLeaf
()
// legal and leaf, store to l2Tlb
}
ts
}
def
get
(
vpn
:
UInt
)
:
L2TlbEntry
=
{
val
t
=
Wire
(
new
L2TlbEntry
)
val
idx
=
idxClip
(
vpn
)
t
.
tag
:=
vpn
// Note: Use input vpn, not vpn in TlbL2
t
.
level
:=
2.
U
// L2TlbEntries only support 4k page
t
.
ppn
:=
ppns
(
idx
)
t
.
perm
:=
perms
(
idx
)
t
}
override
def
cloneType
:
this.
type
=
(
new
L2TlbEntires
(
num
,
tagLen
)).
asInstanceOf
[
this.
type
]
override
def
toPrintable
:
Printable
=
{
require
(
num
==
4
,
"if num is not 4, please comment this toPrintable"
)
// NOTE: if num is not 4, please comment this toPrintable
p
"tag:${Hexadecimal(tag)} ppn(0):${Hexadecimal(ppns(0))} ppn(1):${Hexadecimal(ppns(1))}"
+
p
"ppn(2):${Hexadecimal(ppns(2))} ppn(3):${Hexadecimal(ppns(3))} "
+
p
"perms(0):${perms(0)} perms(1):${perms(1)} perms(2):${perms(2)} perms(3):${perms(3)} vs:${Binary(vs.asUInt)}"
}
}
class
PtwReq
extends
PtwBundle
{
val
vpn
=
UInt
(
vpnLen
.
W
)
...
...
@@ -165,8 +253,8 @@ class PtwReq extends PtwBundle {
}
class
PtwResp
extends
PtwBundle
{
val
entry
=
new
TlbEntry
val
pf
=
Bool
()
// simple pf no matter cmd
val
entry
=
new
L2
TlbEntry
val
pf
=
Bool
()
override
def
toPrintable
:
Printable
=
{
p
"entry:${entry} pf:${pf}"
...
...
@@ -235,13 +323,26 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
// two level: l2-tlb-cache && pde/pte-cache
// l2-tlb-cache is ram-larger-edition tlb
// pde/pte-cache is cache of page-table, speeding up ptw
val
tlbl2
=
Module
(
new
SRAMTemplate
(
new
TlbEntires
(
num
=
TlbL2LineSize
,
tagLen
=
TlbL2TagLen
),
set
=
TlbL2LineNum
))
// (total 256, one line is 4 => 64 lines)
val
tlbl2
=
Module
(
new
SRAMTemplate
(
new
L2TlbEntires
(
num
=
TlbL2LineSize
,
tagLen
=
TlbL2TagLen
),
set
=
TlbL2LineNum
,
singlePort
=
true
))
// (total 256, one line is 4 => 64 lines)
val
tlbv
=
RegInit
(
0.
U
(
TlbL2LineNum
.
W
))
// valid
val
tlbg
=
Reg
(
UInt
(
TlbL2LineNum
.
W
))
// global
val
sp
=
Reg
(
Vec
(
TlbL2SPEntrySize
,
new
L2TlbEntry
))
// (total 16, one is 4M or 1G)
val
spv
=
RegInit
(
0.
U
(
TlbL2SPEntrySize
.
W
))
val
spg
=
Reg
(
UInt
(
TlbL2SPEntrySize
.
W
))
val
ptwl1
=
Reg
(
Vec
(
PtwL1EntrySize
,
new
PtwEntry
(
tagLen
=
PtwL1TagLen
)))
val
l1v
=
RegInit
(
0.
U
(
PtwL1EntrySize
.
W
))
// valid
val
l1g
=
Reg
(
UInt
(
PtwL1EntrySize
.
W
))
val
ptwl2
=
Module
(
new
SRAMTemplate
(
new
PtwEntries
(
num
=
PtwL2LineSize
,
tagLen
=
PtwL2TagLen
),
set
=
PtwL2LineNum
))
// (total 256, one line is 4 => 64 lines)
val
ptwl2
=
Module
(
new
SRAMTemplate
(
new
PtwEntries
(
num
=
PtwL2LineSize
,
tagLen
=
PtwL2TagLen
),
set
=
PtwL2LineNum
,
singlePort
=
true
))
// (total 256, one line is 4 => 64 lines)
val
l2v
=
RegInit
(
0.
U
(
PtwL2LineNum
.
W
))
// valid
val
l2g
=
Reg
(
UInt
(
PtwL2LineNum
.
W
))
// global
...
...
@@ -268,7 +369,6 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
* tlbl2
*/
val
(
tlbHit
,
tlbHitData
)
=
{
assert
(
tlbl2
.
io
.
r
.
req
.
ready
)
val
ridx
=
genTlbL2Idx
(
req
.
vpn
)
val
vidx
=
RegEnable
(
tlbv
(
ridx
),
validOneCycle
)
...
...
@@ -276,10 +376,22 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
tlbl2
.
io
.
r
.
req
.
bits
.
apply
(
setIdx
=
ridx
)
val
ramData
=
tlbl2
.
io
.
r
.
resp
.
data
(
0
)
assert
(
tlbl2
.
io
.
r
.
req
.
ready
||
!
tlbl2
.
io
.
r
.
req
.
valid
)
XSDebug
(
tlbl2
.
io
.
r
.
req
.
valid
,
p
"tlbl2 Read rIdx:${Hexadecimal(ridx)}\n"
)
XSDebug
(
RegNext
(
tlbl2
.
io
.
r
.
req
.
valid
),
p
"tlbl2 RamData:${ramData}\n"
)
XSDebug
(
RegNext
(
tlbl2
.
io
.
r
.
req
.
valid
),
p
"tlbl2 v:${vidx} hit:${ramData.hit(req.vpn)} tlbPte:${ramData.get(req.vpn)}\n"
)
(
ramData
.
hit
(
req
.
vpn
)
&&
vidx
,
ramData
.
get
(
req
.
vpn
))
val
spHitVec
=
sp
.
zipWithIndex
.
map
{
case
(
a
,
i
)
=>
RegEnable
(
a
.
hit
(
req
.
vpn
)
&&
spv
(
i
),
validOneCycle
)
}
val
spHitData
=
ParallelMux
(
spHitVec
zip
sp
)
val
spHit
=
Cat
(
spHitVec
).
orR
XSDebug
(
RegNext
(
validOneCycle
),
p
"tlbl2 sp: spHit:${spHit} spPte:${spHitData}\n"
)
assert
(
RegNext
(!(
ramData
.
hit
(
req
.
vpn
)
&&
vidx
&&
spHit
&&
RegNext
(
validOneCycle
))),
"pages should not be normal page and super page as well"
)
(
ramData
.
hit
(
req
.
vpn
)
&&
vidx
||
spHit
,
Mux
(
spHit
,
spHitData
,
ramData
.
get
(
req
.
vpn
)))
}
/*
...
...
@@ -306,7 +418,7 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
val
idx
=
RegEnable
(
l2addr
(
log2Up
(
PtwL2LineSize
)+
log2Up
(
XLEN
/
8
)-
1
,
log2Up
(
XLEN
/
8
)),
readRam
)
val
vidx
=
RegEnable
(
l2v
(
ridx
),
readRam
)
assert
(
ptwl2
.
io
.
r
.
req
.
ready
)
assert
(
ptwl2
.
io
.
r
.
req
.
ready
||
!
readRam
)
ptwl2
.
io
.
r
.
req
.
valid
:=
readRam
ptwl2
.
io
.
r
.
req
.
bits
.
apply
(
setIdx
=
ridx
)
val
ramData
=
ptwl2
.
io
.
r
.
resp
.
data
(
0
)
...
...
@@ -361,7 +473,7 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
state
:=
state_idle
}.
otherwise
{
state
:=
state_wait_ready
latch
.
entry
:=
new
TlbEntry
().
genTlbEntr
y
(
memRdata
,
level
,
req
.
vpn
)
latch
.
entry
:=
Wire
(
new
L2TlbEntry
()).
appl
y
(
memRdata
,
level
,
req
.
vpn
)
latch
.
pf
:=
memPte
.
isPf
(
level
)
}
}.
otherwise
{
...
...
@@ -418,7 +530,7 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
for
(
i
<-
0
until
PtwWidth
)
{
resp
(
i
).
valid
:=
valid
&&
arbChosen
===
i
.
U
&&
ptwFinish
// TODO: add resp valid logic
resp
(
i
).
bits
.
entry
:=
Mux
(
tlbHit
,
tlbHitData
,
Mux
(
state
===
state_wait_ready
,
latch
.
entry
,
new
TlbEntry
().
genTlbEntr
y
(
memSelData
,
Mux
(
level
===
3.
U
,
2.
U
,
level
),
req
.
vpn
)))
Mux
(
state
===
state_wait_ready
,
latch
.
entry
,
Wire
(
new
L2TlbEntry
()).
appl
y
(
memSelData
,
Mux
(
level
===
3.
U
,
2.
U
,
level
),
req
.
vpn
)))
resp
(
i
).
bits
.
pf
:=
Mux
(
level
===
3.
U
||
notFound
,
true
.
B
,
Mux
(
tlbHit
,
false
.
B
,
Mux
(
state
===
state_wait_ready
,
latch
.
pf
,
memPte
.
isPf
(
level
))))
// TODO: the pf must not be correct, check it
}
...
...
@@ -434,13 +546,15 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
when
(
memRespFire
&&
!
memPte
.
isPf
(
level
)
&&
!
sfenceLatch
)
{
when
(
level
===
0.
U
&&
!
memPte
.
isLeaf
)
{
val
refillIdx
=
LFSR64
()(
log2Up
(
PtwL1EntrySize
)-
1
,
0
)
// TODO: may be LRU
val
rfOH
=
UIntToOH
(
refillIdx
)
ptwl1
(
refillIdx
).
refill
(
l1addr
,
memSelData
)
l1v
:=
l1v
|
UIntToOH
(
refillIdx
)
l1g
:=
(
l1g
&
~
UIntToOH
(
refillIdx
))
|
Mux
(
memPte
.
perm
.
g
,
UIntToOH
(
refillIdx
)
,
0.
U
)
l1v
:=
l1v
|
rfOH
l1g
:=
(
l1g
&
~
rfOH
)
|
Mux
(
memPte
.
perm
.
g
,
rfOH
,
0.
U
)
}
when
(
level
===
1.
U
&&
!
memPte
.
isLeaf
)
{
val
l2addrStore
=
RegEnable
(
l2addr
,
memReqFire
&&
state
===
state_req
&&
level
===
1.
U
)
val
refillIdx
=
genPtwL2Idx
(
l2addrStore
)
//getVpnn(req.vpn, 1)(log2Up(PtwL2EntrySize)-1, 0)
val
rfOH
=
UIntToOH
(
refillIdx
)
//TODO: check why the old refillIdx is right
assert
(
ptwl2
.
io
.
w
.
req
.
ready
)
...
...
@@ -451,26 +565,34 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
data
=
ps
,
waymask
=
-
1.
S
.
asUInt
)
l2v
:=
l2v
|
UIntToOH
(
refillIdx
)
l2g
:=
(
l2g
&
~
UIntToOH
(
refillIdx
))
|
Mux
(
Cat
(
memPtes
.
map
(
_
.
perm
.
g
)).
andR
,
UIntToOH
(
refillIdx
)
,
0.
U
)
l2v
:=
l2v
|
rfOH
l2g
:=
(
l2g
&
~
rfOH
)
|
Mux
(
Cat
(
memPtes
.
map
(
_
.
perm
.
g
)).
andR
,
rfOH
,
0.
U
)
XSDebug
(
p
"ptwl2 RefillIdx:${Hexadecimal(refillIdx)} ps:${ps}\n"
)
}
when
(
memPte
.
isLeaf
()
&&
(
level
===
2.
U
))
{
val
refillIdx
=
genTlbL2Idx
(
req
.
vpn
)
//getVpnn(req.vpn, 0)(log2Up(TlbL2EntrySize)-1, 0)
val
rfOH
=
UIntToOH
(
refillIdx
)
//TODO: check why the old refillIdx is right
assert
(
tlbl2
.
io
.
w
.
req
.
ready
)
val
ts
=
new
TlbEntires
(
num
=
TlbL2LineSize
,
tagLen
=
TlbL2TagLen
).
genEntries
(
memRdata
,
level
,
req
.
vpn
)
val
ts
=
new
L2
TlbEntires
(
num
=
TlbL2LineSize
,
tagLen
=
TlbL2TagLen
).
genEntries
(
memRdata
,
level
,
req
.
vpn
)
tlbl2
.
io
.
w
.
apply
(
valid
=
true
.
B
,
setIdx
=
refillIdx
,
data
=
ts
,
waymask
=
-
1.
S
.
asUInt
)
tlbv
:=
tlbv
|
UIntToOH
(
refillIdx
)
tlbg
:=
(
tlbg
&
~
UIntToOH
(
refillIdx
))
|
Mux
(
Cat
(
memPtes
.
map
(
_
.
perm
.
g
)).
andR
,
UIntToOH
(
refillIdx
)
,
0.
U
)
tlbv
:=
tlbv
|
rfOH
tlbg
:=
(
tlbg
&
~
rfOH
)
|
Mux
(
Cat
(
memPtes
.
map
(
_
.
perm
.
g
)).
andR
,
rfOH
,
0.
U
)
XSDebug
(
p
"tlbl2 refillIdx:${Hexadecimal(refillIdx)} ts:${ts}\n"
)
}
when
(
memPte
.
isLeaf
()
&&
(
level
===
1.
U
||
level
===
0.
U
))
{
val
refillIdx
=
LFSR64
()(
log2Up
(
TlbL2SPEntrySize
)-
1
,
0
)
// TODO: may be LRU
val
rfOH
=
UIntToOH
(
refillIdx
)
sp
(
refillIdx
)
:=
Wire
(
new
L2TlbEntry
()).
apply
(
memSelData
,
Mux
(
level
===
3.
U
,
2.
U
,
level
),
req
.
vpn
)
spv
:=
spv
|
rfOH
spg
:=
(
spg
&
~
rfOH
)
|
Mux
(
memPte
.
perm
.
g
,
rfOH
,
0.
U
)
}
}
/* sfence
...
...
@@ -488,25 +610,29 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
when
(
sfence
.
bits
.
rs2
)
{
// all va && all asid
tlbv
:=
0.
U
tlbg
:=
0.
U
spv
:=
0.
U
// tlbg := 0.U
l1v
:=
0.
U
l2v
:=
0.
U
l2g
:=
0.
U
//
l2g := 0.U
}
.
otherwise
{
// all va && specific asid except global
tlbv
:=
tlbv
&
tlbg
spv
:=
spv
&
spg
l1v
:=
l1v
&
l1g
l2v
:=
l2v
&
l2g
}
}
.
otherwise
{
val
sfenceTlbL2IdxOH
=
UIntToOH
(
genTlbL2Idx
(
sfence
.
bits
.
addr
(
sfence
.
bits
.
addr
.
getWidth
-
1
,
offLen
)))
when
(
sfence
.
bits
.
rs2
)
{
// specific leaf of addr && all asid
tlbv
:=
tlbv
&
~
UIntToOH
(
genTlbL2Idx
(
sfence
.
bits
.
addr
(
sfence
.
bits
.
addr
.
getWidth
-
1
,
offLen
)))
tlbg
:=
tlbg
&
~
UIntToOH
(
genTlbL2Idx
(
sfence
.
bits
.
addr
(
sfence
.
bits
.
addr
.
getWidth
-
1
,
offLen
)))
tlbv
:=
tlbv
&
~
sfenceTlbL2IdxOH
tlbg
:=
tlbg
&
~
sfenceTlbL2IdxOH
}
.
otherwise
{
// specific leaf of addr && specific asid
tlbv
:=
tlbv
&
(~
UIntToOH
(
genTlbL2Idx
(
sfence
.
bits
.
addr
(
sfence
.
bits
.
addr
.
getWidth
-
1
,
offLen
)))
|
tlbg
)
tlbv
:=
tlbv
&
(~
sfenceTlbL2IdxOH
|
tlbg
)
}
spv
:=
0.
U
}
}
...
...
src/main/scala/xiangshan/frontend/Frontend.scala
浏览文件 @
51f54365
...
...
@@ -2,13 +2,28 @@ package xiangshan.frontend
import
utils.XSInfo
import
chisel3._
import
chisel3.util._
import
chipsalliance.rocketchip.config.Parameters
import
freechips.rocketchip.diplomacy.
{
LazyModule
,
LazyModuleImp
}
import
utils.PipelineConnect
import
xiangshan._
import
xiangshan.cache._
import
xiangshan.cache.prefetch.L1plusPrefetcher
import
xiangshan.backend.fu.HasExceptionNO
class
Frontend
()(
implicit
p
:
Parameters
)
extends
LazyModule
with
HasXSParameter
{
class
Frontend
extends
XSModule
with
HasL1plusCacheParameters
{
val
instrUncache
=
LazyModule
(
new
InstrUncache
())
lazy
val
module
=
new
FrontendImp
(
this
)
}
class
FrontendImp
(
outer
:
Frontend
)
extends
LazyModuleImp
(
outer
)
with
HasL1plusCacheParameters
with
HasXSParameter
with
HasExceptionNO
with
HasXSLog
{
val
io
=
IO
(
new
Bundle
()
{
val
icacheMemAcq
=
DecoupledIO
(
new
L1plusCacheReq
)
val
icacheMemGrant
=
Flipped
(
DecoupledIO
(
new
L1plusCacheResp
))
...
...
@@ -23,7 +38,7 @@ class Frontend extends XSModule with HasL1plusCacheParameters {
val
ifu
=
Module
(
new
IFU
)
val
ibuffer
=
Module
(
new
Ibuffer
)
val
l1plusPrefetcher
=
Module
(
new
L1plusPrefetcher
)
val
instrUncache
=
outer
.
instrUncache
.
module
val
needFlush
=
io
.
backend
.
redirect
.
valid
...
...
@@ -43,6 +58,11 @@ class Frontend extends XSModule with HasL1plusCacheParameters {
ifu
.
io
.
icacheMemGrant
.
ready
,
l1plusPrefetcher
.
io
.
mem_grant
.
ready
)
ifu
.
io
.
fencei
:=
io
.
fencei
instrUncache
.
io
.
req
<>
ifu
.
io
.
mmio_acquire
instrUncache
.
io
.
resp
<>
ifu
.
io
.
mmio_grant
instrUncache
.
io
.
flush
<>
ifu
.
io
.
mmio_flush
// to tlb
ifu
.
io
.
sfence
:=
io
.
sfence
ifu
.
io
.
tlbCsr
:=
io
.
tlbCsr
...
...
src/main/scala/xiangshan/frontend/IFU.scala
浏览文件 @
51f54365
...
...
@@ -10,8 +10,16 @@ import chisel3.experimental.chiselName
import
freechips.rocketchip.tile.HasLazyRoCC
import
chisel3.ExcitingUtils._
trait
HasInstrMMIOConst
extends
HasXSParameter
with
HasIFUConst
{
def
mmioBusWidth
=
64
def
mmioBusBytes
=
mmioBusWidth
/
8
def
mmioBeats
=
FetchWidth
*
4
*
8
/
mmioBusWidth
def
mmioMask
=
VecInit
(
List
.
fill
(
PredictWidth
)(
true
.
B
)).
asUInt
def
mmioBusAligned
(
pc
:
UInt
)
:
UInt
=
align
(
pc
,
mmioBusBytes
)
}
trait
HasIFUConst
extends
HasXSParameter
{
val
resetVector
=
0x
8
0000000
L
//TODO: set reset vec
val
resetVector
=
0x
1
0000000
L
//TODO: set reset vec
def
align
(
pc
:
UInt
,
bytes
:
Int
)
:
UInt
=
Cat
(
pc
(
VAddrBits
-
1
,
log2Ceil
(
bytes
)),
0.
U
(
log2Ceil
(
bytes
).
W
))
val
instBytes
=
if
(
HasCExtension
)
2
else
4
val
instOffsetBits
=
log2Ceil
(
instBytes
)
...
...
@@ -71,6 +79,10 @@ class IFUIO extends XSBundle
val
tlbCsr
=
Input
(
new
TlbCsrBundle
)
// from tlb
val
ptw
=
new
TlbPtwIO
// icache uncache
val
mmio_acquire
=
DecoupledIO
(
new
InsUncacheReq
)
val
mmio_grant
=
Flipped
(
DecoupledIO
(
new
InsUncacheResp
))
val
mmio_flush
=
Output
(
Bool
())
}
class
PrevHalfInstr
extends
XSBundle
{
...
...
@@ -119,7 +131,7 @@ class IFU extends XSModule with HasIFUConst
val
if2_valid
=
RegInit
(
init
=
false
.
B
)
val
if2_allReady
=
WireInit
(
if2_ready
&&
icache
.
io
.
req
.
ready
)
val
if1_fire
=
(
if1_valid
&&
if2_allReady
)
&&
(
icache
.
io
.
tlb
.
resp
.
valid
||
!
if2_valid
)
val
if1_can_go
=
if1_fire
||
if
2
_flush
val
if1_can_go
=
if1_fire
||
if
3
_flush
val
if1_gh
,
if2_gh
,
if3_gh
,
if4_gh
=
Wire
(
new
GlobalHistory
)
val
if2_predicted_gh
,
if3_predicted_gh
,
if4_predicted_gh
=
Wire
(
new
GlobalHistory
)
...
...
@@ -418,6 +430,9 @@ class IFU extends XSModule with HasIFUConst
icache
.
io
.
prev
.
bits
:=
if3_prevHalfInstr
.
bits
.
instr
icache
.
io
.
prev_ipf
:=
if3_prevHalfInstr
.
bits
.
ipf
icache
.
io
.
prev_pc
:=
if3_prevHalfInstr
.
bits
.
pc
icache
.
io
.
mmio_acquire
<>
io
.
mmio_acquire
icache
.
io
.
mmio_grant
<>
io
.
mmio_grant
icache
.
io
.
mmio_flush
<>
io
.
mmio_flush
io
.
icacheMemAcq
<>
icache
.
io
.
mem_acquire
io
.
l1plusFlush
:=
icache
.
io
.
l1plusflush
io
.
prefetchTrainReq
:=
icache
.
io
.
prefetchTrainReq
...
...
@@ -443,10 +458,18 @@ class IFU extends XSModule with HasIFUConst
crossPageIPF
:=
true
.
B
// higher 16 bits page fault
}
//RVC expand
val
expandedInstrs
=
Wire
(
Vec
(
PredictWidth
,
UInt
(
32.
W
)))
for
(
i
<-
0
until
PredictWidth
){
val
expander
=
Module
(
new
RVCExpander
)
expander
.
io
.
in
:=
if4_pd
.
instrs
(
i
)
expandedInstrs
(
i
)
:=
expander
.
io
.
out
.
bits
}
val
fetchPacketValid
=
if4_valid
&&
!
io
.
redirect
.
valid
val
fetchPacketWire
=
Wire
(
new
FetchPacket
)
fetchPacketWire
.
instrs
:=
if4_pd
.
i
nstrs
fetchPacketWire
.
instrs
:=
expandedI
nstrs
fetchPacketWire
.
mask
:=
if4_pd
.
mask
&
(
Fill
(
PredictWidth
,
!
if4_bp
.
taken
)
|
(
Fill
(
PredictWidth
,
1.
U
(
1.
W
))
>>
(~
if4_bp
.
jmpIdx
)))
fetchPacketWire
.
pdmask
:=
if4_pd
.
mask
...
...
src/main/scala/xiangshan/frontend/PreDecode.scala
浏览文件 @
51f54365
...
...
@@ -3,6 +3,7 @@ package xiangshan.frontend
import
chisel3._
import
chisel3.util._
import
utils._
import
freechips.rocketchip.rocket.
{
RVCDecoder
,
ExpandedInstruction
}
import
xiangshan._
import
xiangshan.backend.decode.isa.predecode.PreDecodeInst
import
xiangshan.cache._
...
...
@@ -134,3 +135,16 @@ class PreDecode extends XSModule with HasPdconst with HasIFUConst {
)
}
}
class
RVCExpander
extends
XSModule
{
val
io
=
IO
(
new
Bundle
{
val
in
=
Input
(
UInt
(
32.
W
))
val
out
=
Output
(
new
ExpandedInstruction
)
})
if
(
HasCExtension
)
{
io
.
out
:=
new
RVCDecoder
(
io
.
in
,
XLEN
).
decode
}
else
{
io
.
out
:=
new
RVCDecoder
(
io
.
in
,
XLEN
).
passthrough
}
}
src/main/scala/xiangshan/frontend/Tage.scala
浏览文件 @
51f54365
...
...
@@ -5,6 +5,10 @@ import chisel3.util._
import
xiangshan._
import
utils._
import
chisel3.experimental.chiselName
import
chisel3.stage.
{
ChiselGeneratorAnnotation
,
ChiselStage
}
import
firrtl.stage.RunFirrtlTransformAnnotation
import
firrtl.transforms.RenameModules
import
freechips.rocketchip.transforms.naming.RenameDesiredNames
import
scala.math.min
import
scala.util.matching.Regex
...
...
@@ -373,7 +377,7 @@ class FakeTage extends BaseTage {
class
Tage
extends
BaseTage
{
val
tables
=
TableInfo
.
map
{
case
(
nRows
,
histLen
,
tagLen
)
=>
{
case
(
nRows
,
histLen
,
tagLen
)
=>
val
t
=
if
(
EnableBPD
)
Module
(
new
TageTable
(
nRows
,
histLen
,
tagLen
,
UBitPeriod
))
else
Module
(
new
FakeTageTable
)
t
.
io
.
req
.
valid
:=
io
.
pc
.
valid
t
.
io
.
req
.
bits
.
pc
:=
io
.
pc
.
bits
...
...
@@ -381,7 +385,6 @@ class Tage extends BaseTage {
t
.
io
.
req
.
bits
.
mask
:=
io
.
inMask
t
}
}
val
scTables
=
SCTableInfo
.
map
{
case
(
nRows
,
ctrBits
,
histLen
)
=>
{
...
...
@@ -659,3 +662,12 @@ class Tage extends BaseTage {
XSDebug
(
true
.
B
,
p
"scThres: use(${useThreshold}), update(${updateThreshold})\n"
)
}
}
object
TageTest
extends
App
{
override
def
main
(
args
:
Array
[
String
])
:
Unit
=
{
(
new
ChiselStage
).
execute
(
args
,
Seq
(
ChiselGeneratorAnnotation
(()
=>
new
Tage
),
RunFirrtlTransformAnnotation
(
new
RenameDesiredNames
)
))
}
}
\ No newline at end of file
src/main/scala/xiangshan/mem/Memend.scala
浏览文件 @
51f54365
...
...
@@ -41,7 +41,6 @@ class LsPipelineBundle extends XSBundle {
val
miss
=
Bool
()
val
tlbMiss
=
Bool
()
val
mmio
=
Bool
()
val
rollback
=
Bool
()
val
forwardMask
=
Vec
(
8
,
Bool
())
val
forwardData
=
Vec
(
8
,
UInt
(
8.
W
))
...
...
src/main/scala/xiangshan/mem/lsqueue/LSQWrapper.scala
浏览文件 @
51f54365
...
...
@@ -51,6 +51,7 @@ class LsqWrappper extends XSModule with HasDCacheParameters {
val
uncache
=
new
DCacheWordIO
val
roqDeqPtr
=
Input
(
new
RoqPtr
)
val
exceptionAddr
=
new
ExceptionAddrIO
val
sqempty
=
Output
(
Bool
())
})
val
loadQueue
=
Module
(
new
LoadQueue
)
...
...
@@ -103,6 +104,8 @@ class LsqWrappper extends XSModule with HasDCacheParameters {
loadQueue
.
io
.
load_s1
<>
io
.
forward
storeQueue
.
io
.
forward
<>
io
.
forward
// overlap forwardMask & forwardData, DO NOT CHANGE SEQUENCE
storeQueue
.
io
.
sqempty
<>
io
.
sqempty
io
.
exceptionAddr
.
vaddr
:=
Mux
(
io
.
exceptionAddr
.
isStore
,
storeQueue
.
io
.
exceptionAddr
.
vaddr
,
loadQueue
.
io
.
exceptionAddr
.
vaddr
)
// naive uncache arbiter
...
...
src/main/scala/xiangshan/mem/lsqueue/LoadQueue.scala
浏览文件 @
51f54365
此差异已折叠。
点击以展开。
src/main/scala/xiangshan/mem/lsqueue/LoadQueueData.scala
浏览文件 @
51f54365
...
...
@@ -15,7 +15,6 @@ class LQDataEntry extends XSBundle {
val
paddr
=
UInt
(
PAddrBits
.
W
)
val
mask
=
UInt
(
8.
W
)
val
data
=
UInt
(
XLEN
.
W
)
val
exception
=
UInt
(
16.
W
)
// TODO: opt size
val
fwdMask
=
Vec
(
8
,
Bool
())
}
...
...
@@ -38,7 +37,7 @@ class PaddrModule(numEntries: Int, numRead: Int, numWrite: Int) extends XSModule
// read ports
for
(
i
<-
0
until
numRead
)
{
io
.
rdata
(
i
)
:=
data
(
io
.
raddr
(
i
))
io
.
rdata
(
i
)
:=
data
(
RegNext
(
io
.
raddr
(
i
)
))
}
// below is the write ports (with priorities)
...
...
@@ -82,7 +81,7 @@ class MaskModule(numEntries: Int, numRead: Int, numWrite: Int) extends XSModule
// read ports
for
(
i
<-
0
until
numRead
)
{
io
.
rdata
(
i
)
:=
data
(
io
.
raddr
(
i
))
io
.
rdata
(
i
)
:=
data
(
RegNext
(
io
.
raddr
(
i
)
))
}
// below is the write ports (with priorities)
...
...
@@ -138,7 +137,7 @@ class CoredataModule(numEntries: Int, numRead: Int, numWrite: Int) extends XSMod
// read ports
for
(
i
<-
0
until
numRead
)
{
io
.
rdata
(
i
)
:=
data
(
io
.
raddr
(
i
))
io
.
rdata
(
i
)
:=
data
(
RegNext
(
io
.
raddr
(
i
)
))
}
// below is the write ports (with priorities)
...
...
@@ -236,7 +235,6 @@ class LoadQueueData(size: Int, wbNumRead: Int, wbNumWrite: Int) extends XSModule
// data module
val
paddrModule
=
Module
(
new
PaddrModule
(
size
,
numRead
=
3
,
numWrite
=
2
))
val
maskModule
=
Module
(
new
MaskModule
(
size
,
numRead
=
3
,
numWrite
=
2
))
val
exceptionModule
=
Module
(
new
AsyncDataModuleTemplate
(
UInt
(
16.
W
),
size
,
numRead
=
3
,
numWrite
=
2
))
val
coredataModule
=
Module
(
new
CoredataModule
(
size
,
numRead
=
3
,
numWrite
=
3
))
// read data
...
...
@@ -244,26 +242,22 @@ class LoadQueueData(size: Int, wbNumRead: Int, wbNumWrite: Int) extends XSModule
(
0
until
wbNumRead
).
map
(
i
=>
{
paddrModule
.
io
.
raddr
(
i
)
:=
io
.
wb
.
raddr
(
i
)
maskModule
.
io
.
raddr
(
i
)
:=
io
.
wb
.
raddr
(
i
)
exceptionModule
.
io
.
raddr
(
i
)
:=
io
.
wb
.
raddr
(
i
)
coredataModule
.
io
.
raddr
(
i
)
:=
io
.
wb
.
raddr
(
i
)
io
.
wb
.
rdata
(
i
).
paddr
:=
paddrModule
.
io
.
rdata
(
i
)
io
.
wb
.
rdata
(
i
).
mask
:=
maskModule
.
io
.
rdata
(
i
)
io
.
wb
.
rdata
(
i
).
data
:=
coredataModule
.
io
.
rdata
(
i
)
io
.
wb
.
rdata
(
i
).
exception
:=
exceptionModule
.
io
.
rdata
(
i
)
io
.
wb
.
rdata
(
i
).
fwdMask
:=
DontCare
})
// read port wbNumRead
paddrModule
.
io
.
raddr
(
wbNumRead
)
:=
io
.
uncache
.
raddr
maskModule
.
io
.
raddr
(
wbNumRead
)
:=
io
.
uncache
.
raddr
exceptionModule
.
io
.
raddr
(
wbNumRead
)
:=
io
.
uncache
.
raddr
coredataModule
.
io
.
raddr
(
wbNumRead
)
:=
io
.
uncache
.
raddr
io
.
uncache
.
rdata
.
paddr
:=
paddrModule
.
io
.
rdata
(
wbNumRead
)
io
.
uncache
.
rdata
.
mask
:=
maskModule
.
io
.
rdata
(
wbNumRead
)
io
.
uncache
.
rdata
.
data
:=
exceptionModule
.
io
.
rdata
(
wbNumRead
)
io
.
uncache
.
rdata
.
exception
:=
coredataModule
.
io
.
rdata
(
wbNumRead
)
io
.
uncache
.
rdata
.
data
:=
coredataModule
.
io
.
rdata
(
wbNumRead
)
io
.
uncache
.
rdata
.
fwdMask
:=
DontCare
// write data
...
...
@@ -271,19 +265,16 @@ class LoadQueueData(size: Int, wbNumRead: Int, wbNumWrite: Int) extends XSModule
(
0
until
wbNumWrite
).
map
(
i
=>
{
paddrModule
.
io
.
wen
(
i
)
:=
false
.
B
maskModule
.
io
.
wen
(
i
)
:=
false
.
B
exceptionModule
.
io
.
wen
(
i
)
:=
false
.
B
coredataModule
.
io
.
wen
(
i
)
:=
false
.
B
coredataModule
.
io
.
fwdMaskWen
(
i
)
:=
false
.
B
coredataModule
.
io
.
paddrWen
(
i
)
:=
false
.
B
paddrModule
.
io
.
waddr
(
i
)
:=
io
.
wb
.
waddr
(
i
)
maskModule
.
io
.
waddr
(
i
)
:=
io
.
wb
.
waddr
(
i
)
exceptionModule
.
io
.
waddr
(
i
)
:=
io
.
wb
.
waddr
(
i
)
coredataModule
.
io
.
waddr
(
i
)
:=
io
.
wb
.
waddr
(
i
)
paddrModule
.
io
.
wdata
(
i
)
:=
io
.
wb
.
wdata
(
i
).
paddr
maskModule
.
io
.
wdata
(
i
)
:=
io
.
wb
.
wdata
(
i
).
mask
exceptionModule
.
io
.
wdata
(
i
)
:=
io
.
wb
.
wdata
(
i
).
exception
coredataModule
.
io
.
wdata
(
i
)
:=
io
.
wb
.
wdata
(
i
).
data
coredataModule
.
io
.
fwdMaskWdata
(
i
)
:=
io
.
wb
.
wdata
(
i
).
fwdMask
.
asUInt
coredataModule
.
io
.
paddrWdata
(
i
)
:=
io
.
wb
.
wdata
(
i
).
paddr
...
...
@@ -291,7 +282,6 @@ class LoadQueueData(size: Int, wbNumRead: Int, wbNumWrite: Int) extends XSModule
when
(
io
.
wb
.
wen
(
i
)){
paddrModule
.
io
.
wen
(
i
)
:=
true
.
B
maskModule
.
io
.
wen
(
i
)
:=
true
.
B
exceptionModule
.
io
.
wen
(
i
)
:=
true
.
B
coredataModule
.
io
.
wen
(
i
)
:=
true
.
B
coredataModule
.
io
.
fwdMaskWen
(
i
)
:=
true
.
B
coredataModule
.
io
.
paddrWen
(
i
)
:=
true
.
B
...
...
src/main/scala/xiangshan/mem/lsqueue/StoreQueue.scala
浏览文件 @
51f54365
此差异已折叠。
点击以展开。
src/main/scala/xiangshan/mem/lsqueue/StoreQueueData.scala
浏览文件 @
51f54365
...
...
@@ -51,7 +51,7 @@ class StoreQueueData(size: Int, numRead: Int, numWrite: Int, numForward: Int) ex
// destorequeue read data
(
0
until
numRead
).
map
(
i
=>
{
io
.
rdata
(
i
)
:=
data
(
io
.
raddr
(
i
))
io
.
rdata
(
i
)
:=
data
(
RegNext
(
io
.
raddr
(
i
)
))
})
// DataModuleTemplate should not be used when there're any write conflicts
...
...
src/main/scala/xiangshan/mem/pipeline/AtomicsUnit.scala
浏览文件 @
51f54365
此差异已折叠。
点击以展开。
src/main/scala/xiangshan/mem/pipeline/LoadUnit.scala
浏览文件 @
51f54365
此差异已折叠。
点击以展开。
src/main/scala/xiangshan/mem/pipeline/StoreUnit.scala
浏览文件 @
51f54365
此差异已折叠。
点击以展开。
src/main/scala/xiangshan/mem/sbuffer/NewSbuffer.scala
浏览文件 @
51f54365
...
...
@@ -13,9 +13,9 @@ trait HasSbufferCst extends HasXSParameter {
def
s_prepare
=
2.
U
(
2.
W
)
def
s_inflight
=
3.
U
(
2.
W
)
val
evictCycle
=
8192
val
evictCycle
=
1
<<
20
require
(
isPow2
(
evictCycle
))
val
countBits
=
1
+
log2Up
(
evictCycle
)
val
countBits
=
log2Up
(
evictCycle
+
1
)
val
SbufferIndexWidth
:
Int
=
log2Up
(
StoreBufferSize
)
// paddr = tag + offset
...
...
@@ -108,6 +108,7 @@ class NewSbuffer extends XSModule with HasSbufferCst {
val
in
=
Vec
(
StorePipelineWidth
,
Flipped
(
Decoupled
(
new
DCacheWordReq
)))
//Todo: store logic only support Width == 2 now
val
dcache
=
new
DCacheLineIO
val
forward
=
Vec
(
LoadPipelineWidth
,
Flipped
(
new
LoadForwardQueryIO
))
val
sqempty
=
Input
(
Bool
())
val
flush
=
new
Bundle
{
val
valid
=
Input
(
Bool
())
val
empty
=
Output
(
Bool
())
...
...
@@ -291,7 +292,7 @@ class NewSbuffer extends XSModule with HasSbufferCst {
do_eviction
:=
validCount
>=
12.
U
io
.
flush
.
empty
:=
empty
io
.
flush
.
empty
:=
empty
&&
io
.
sqempty
lru
.
io
.
flush
:=
sbuffer_state
===
x_drain_sbuffer
&&
empty
switch
(
sbuffer_state
){
is
(
x_idle
){
...
...
src/main/scala/xiangshan/package.scala
浏览文件 @
51f54365
此差异已折叠。
点击以展开。
src/test/csrc/ram.cpp
浏览文件 @
51f54365
此差异已折叠。
点击以展开。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录