Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenXiangShan
XiangShan
提交
706f729c
X
XiangShan
项目概览
OpenXiangShan
/
XiangShan
大约 1 年 前同步成功
通知
1183
Star
3914
Fork
526
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
X
XiangShan
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
706f729c
编写于
7月 11, 2020
作者:
W
William Wang
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'origin/master' into dev-lsu
上级
8d7419d4
72e03dff
变更
44
隐藏空白更改
内联
并排
Showing
44 changed file
with
1447 addition
and
936 deletion
+1447
-936
.github/workflows/emu.yml
.github/workflows/emu.yml
+3
-3
Makefile
Makefile
+17
-0
src/main/scala/bus/simplebus/DistributedMem.scala
src/main/scala/bus/simplebus/DistributedMem.scala
+1
-1
src/main/scala/xiangshan/XSCore.scala
src/main/scala/xiangshan/XSCore.scala
+8
-7
src/main/scala/xiangshan/backend/Backend.scala
src/main/scala/xiangshan/backend/Backend.scala
+38
-24
src/main/scala/xiangshan/backend/brq/Brq.scala
src/main/scala/xiangshan/backend/brq/Brq.scala
+2
-2
src/main/scala/xiangshan/backend/decode/Decoder.scala
src/main/scala/xiangshan/backend/decode/Decoder.scala
+2
-2
src/main/scala/xiangshan/backend/decode/isa/RVI.scala
src/main/scala/xiangshan/backend/decode/isa/RVI.scala
+15
-15
src/main/scala/xiangshan/backend/decode/isa/RVM.scala
src/main/scala/xiangshan/backend/decode/isa/RVM.scala
+14
-14
src/main/scala/xiangshan/backend/dispatch/Dispatch.scala
src/main/scala/xiangshan/backend/dispatch/Dispatch.scala
+8
-6
src/main/scala/xiangshan/backend/dispatch/Dispatch1.scala
src/main/scala/xiangshan/backend/dispatch/Dispatch1.scala
+1
-1
src/main/scala/xiangshan/backend/dispatch/Dispatch2.scala
src/main/scala/xiangshan/backend/dispatch/Dispatch2.scala
+83
-143
src/main/scala/xiangshan/backend/dispatch/DispatchGen.scala
src/main/scala/xiangshan/backend/dispatch/DispatchGen.scala
+98
-0
src/main/scala/xiangshan/backend/dispatch/RegfileReadPortGen.scala
...scala/xiangshan/backend/dispatch/RegfileReadPortGen.scala
+107
-0
src/main/scala/xiangshan/backend/exu/AluExeUnit.scala
src/main/scala/xiangshan/backend/exu/AluExeUnit.scala
+3
-2
src/main/scala/xiangshan/backend/exu/DivExeUnit.scala
src/main/scala/xiangshan/backend/exu/DivExeUnit.scala
+61
-0
src/main/scala/xiangshan/backend/exu/Exu.scala
src/main/scala/xiangshan/backend/exu/Exu.scala
+45
-97
src/main/scala/xiangshan/backend/exu/JmpExeUnit.scala
src/main/scala/xiangshan/backend/exu/JmpExeUnit.scala
+3
-2
src/main/scala/xiangshan/backend/exu/LsExeUnit.scala
src/main/scala/xiangshan/backend/exu/LsExeUnit.scala
+3
-38
src/main/scala/xiangshan/backend/exu/Mul.scala
src/main/scala/xiangshan/backend/exu/Mul.scala
+0
-330
src/main/scala/xiangshan/backend/exu/MulDivExeUnit.scala
src/main/scala/xiangshan/backend/exu/MulDivExeUnit.scala
+50
-0
src/main/scala/xiangshan/backend/exu/MulExeUnit.scala
src/main/scala/xiangshan/backend/exu/MulExeUnit.scala
+64
-0
src/main/scala/xiangshan/backend/exu/Wbu.scala
src/main/scala/xiangshan/backend/exu/Wbu.scala
+37
-3
src/main/scala/xiangshan/backend/fu/Alu.scala
src/main/scala/xiangshan/backend/fu/Alu.scala
+89
-0
src/main/scala/xiangshan/backend/fu/Divider.scala
src/main/scala/xiangshan/backend/fu/Divider.scala
+84
-0
src/main/scala/xiangshan/backend/fu/FDivSqrt.scala
src/main/scala/xiangshan/backend/fu/FDivSqrt.scala
+14
-0
src/main/scala/xiangshan/backend/fu/Fmac.scala
src/main/scala/xiangshan/backend/fu/Fmac.scala
+14
-0
src/main/scala/xiangshan/backend/fu/Fmisc.scala
src/main/scala/xiangshan/backend/fu/Fmisc.scala
+14
-0
src/main/scala/xiangshan/backend/fu/FunctionUnit.scala
src/main/scala/xiangshan/backend/fu/FunctionUnit.scala
+55
-0
src/main/scala/xiangshan/backend/fu/I2f.scala
src/main/scala/xiangshan/backend/fu/I2f.scala
+12
-0
src/main/scala/xiangshan/backend/fu/Jump.scala
src/main/scala/xiangshan/backend/fu/Jump.scala
+60
-0
src/main/scala/xiangshan/backend/fu/Multiplier.scala
src/main/scala/xiangshan/backend/fu/Multiplier.scala
+98
-0
src/main/scala/xiangshan/backend/issue/IssueQueue.scala
src/main/scala/xiangshan/backend/issue/IssueQueue.scala
+78
-33
src/main/scala/xiangshan/backend/package.scala
src/main/scala/xiangshan/backend/package.scala
+18
-36
src/main/scala/xiangshan/backend/roq/Roq.scala
src/main/scala/xiangshan/backend/roq/Roq.scala
+1
-1
src/main/scala/xiangshan/frontend/Ibuffer.scala
src/main/scala/xiangshan/frontend/Ibuffer.scala
+142
-142
src/main/scala/xiangshan/package.scala
src/main/scala/xiangshan/package.scala
+34
-14
src/test/csrc/emu.h
src/test/csrc/emu.h
+1
-1
src/test/scala/top/XSSim.scala
src/test/scala/top/XSSim.scala
+4
-0
src/test/scala/xiangshan/backend/exu/AluTest.scala
src/test/scala/xiangshan/backend/exu/AluTest.scala
+2
-2
src/test/scala/xiangshan/backend/exu/LsuTest.scala
src/test/scala/xiangshan/backend/exu/LsuTest.scala
+3
-10
src/test/scala/xiangshan/backend/exu/MduTest.scala
src/test/scala/xiangshan/backend/exu/MduTest.scala
+3
-3
src/test/scala/xiangshan/backend/issue/IssueQueueTest.scala
src/test/scala/xiangshan/backend/issue/IssueQueueTest.scala
+54
-0
src/test/scala/xiangshan/testutils/TestCaseGenerator.scala
src/test/scala/xiangshan/testutils/TestCaseGenerator.scala
+4
-4
未找到文件。
.github/workflows/
core_ci
.yml
→
.github/workflows/
emu
.yml
浏览文件 @
706f729c
# This file describes the GitHub Actions workflow for continuous integration of XS Core.
name
:
XS Core CI
name
:
EMU Test
on
:
push
:
branches
:
[
master
,
ci-v2
]
branches
:
[
master
]
pull_request
:
branches
:
[
master
]
...
...
@@ -18,7 +18,7 @@ jobs:
echo ::set-env name=NEMU_HOME::/home/ci-runner/xsenv/NEMU
echo ::set-env name=NOOP_HOME::$GITHUB_WORKSPACE
-
name
:
Build EMU
run
:
make ./build/emu NEMU_HOME=$NEMU_HOME NOOP_HOME=$NOOP_HOME -j
4
0
run
:
make ./build/emu NEMU_HOME=$NEMU_HOME NOOP_HOME=$NOOP_HOME -j
2
0
cputest
:
runs-on
:
self-hosted
...
...
Makefile
浏览文件 @
706f729c
...
...
@@ -9,6 +9,10 @@ MEM_GEN = ./scripts/vlsi_mem_gen
SIMTOP
=
top.TestMain
IMAGE
?=
temp
# remote machine with high frequency to speedup verilog generation
REMOTE
?=
localhost
REMOTE_PREFIX
?=
/nfs/24/
$(
abspath
.
)
/
.DEFAULT_GOAL
=
verilog
help
:
...
...
@@ -41,7 +45,11 @@ SIM_TOP = XSSimTop
SIM_TOP_V
=
$(BUILD_DIR)
/
$(SIM_TOP)
.v
$(SIM_TOP_V)
:
$(SCALA_FILE) $(TEST_FILE)
mkdir
-p
$
(
@D
)
ifeq
($(REMOTE),localhost)
mill chiselModule.test.runMain
$(SIMTOP)
-X
verilog
-td
$
(
@D
)
--output-file
$
(
@F
)
else
ssh
$(REMOTE)
"cd
$(REMOTE_PREFIX)
&& mill chiselModule.test.runMain
$(SIMTOP)
-X verilog -td
$
(@D) --output-file
$
(@F)"
endif
EMU_CSRC_DIR
=
$(
abspath
./src/test/csrc
)
...
...
@@ -76,7 +84,12 @@ $(EMU_MK): $(SIM_TOP_V) | $(EMU_DEPS)
verilator
--cc
--exe
$(VERILATOR_FLAGS)
\
-o
$(
abspath
$(EMU)
)
-Mdir
$
(
@D
)
$^
$(EMU_DEPS)
ifeq
($(REMOTE),localhost)
REF_SO
:=
$(NEMU_HOME)
/build/riscv64-nemu-so
else
REF_SO
:=
/home/pcl/NEMU/build/riscv64-nemu-so
endif
$(REF_SO)
:
$(MAKE)
-C
$(NEMU_HOME)
ISA
=
riscv64
SHARE
=
1
...
...
@@ -93,7 +106,11 @@ E ?= -1
V
?=
ALL
emu
:
$(EMU)
ifeq
($(REMOTE),localhost)
@
$(EMU)
-i
$(IMAGE)
$(SEED)
-b
$(B)
-e
$(E)
-v
$(V)
else
ssh
$(REMOTE)
"cd
$(REMOTE_PREFIX)
&&
$(EMU)
-i
$(IMAGE)
$(SEED)
-b
$(B)
-e
$(E)
-v
$(V)
"
endif
cache
:
$(MAKE)
emu
IMAGE
=
Makefile
...
...
src/main/scala/bus/simplebus/DistributedMem.scala
浏览文件 @
706f729c
...
...
@@ -22,7 +22,7 @@ class DistributedMem(memByte: Int, dualPort: Boolean, delayCycles: Int = 0, data
val
roIdx
=
Index
(
io
.
ro
.
req
.
bits
.
addr
)
val
wen
=
io
.
rw
.
isWrite
()
val
wdataVec
=
VecInit
.
tabulate
(
nBank
)
{
i
=>
io
.
rw
.
req
.
bits
.
wdata
(
8
*
(
i
+
1
)
-
1
,
8
*
i
)
}
val
wmask
=
VecInit
.
tabulate
(
nBank
)
{
i
=>
io
.
rw
.
req
.
bits
.
wmask
(
i
).
toBool
}
val
wmask
=
VecInit
.
tabulate
(
nBank
)
{
i
=>
io
.
rw
.
req
.
bits
.
wmask
(
i
).
asBool
()
}
val
rwData
=
Wire
(
UInt
(
XLEN
.
W
))
val
roData
=
Wire
(
UInt
(
XLEN
.
W
))
...
...
src/main/scala/xiangshan/XSCore.scala
浏览文件 @
706f729c
...
...
@@ -5,8 +5,8 @@ import chisel3.util._
import
bus.simplebus._
import
noop.
{
Cache
,
CacheConfig
,
HasExceptionNO
,
TLB
,
TLBConfig
}
import
xiangshan.backend._
import
xiangshan.backend.dispatch.DP1
Config
import
xiangshan.backend.exu.Exu
Config
import
xiangshan.backend.dispatch.DP1
Parameters
import
xiangshan.backend.exu.Exu
Parameters
import
xiangshan.frontend.Frontend
import
xiangshan.mem._
import
xiangshan.utils._
...
...
@@ -32,6 +32,7 @@ trait HasXSParameter {
val
RenameWidth
=
6
val
CommitWidth
=
6
val
BrqSize
=
16
val
IssQueSize
=
8
val
BrTagWidth
=
log2Up
(
BrqSize
)
val
NRPhyRegs
=
128
val
PhyRegIdxWidth
=
log2Up
(
NRPhyRegs
)
...
...
@@ -43,21 +44,21 @@ trait HasXSParameter {
val
IntDqDeqWidth
=
4
val
FpDqDeqWidth
=
4
val
LsDqDeqWidth
=
4
val
dp1
Config
=
DP1Config
(
val
dp1
Paremeters
=
DP1Parameters
(
IntDqSize
=
16
,
FpDqSize
=
16
,
LsDqSize
=
16
)
val
exuConfig
=
ExuConfig
(
val
exuParameters
=
ExuParameters
(
JmpCnt
=
1
,
AluCnt
=
4
,
BruCnt
=
1
,
MulCnt
=
1
,
MduCnt
=
1
,
FmacCnt
=
0
,
FmiscCnt
=
0
,
FmiscDivSqrtCnt
=
0
,
LduCnt
=
1
,
StuCnt
=
0
LduCnt
=
0
,
StuCnt
=
1
)
}
...
...
src/main/scala/xiangshan/backend/Backend.scala
浏览文件 @
706f729c
...
...
@@ -11,6 +11,7 @@ import xiangshan.backend.rename.Rename
import
xiangshan.backend.brq.Brq
import
xiangshan.backend.dispatch.Dispatch
import
xiangshan.backend.exu._
import
xiangshan.backend.fu.FunctionUnit
import
xiangshan.backend.issue.IssueQueue
import
xiangshan.backend.regfile.
{
Regfile
,
RfWritePort
}
import
xiangshan.backend.roq.Roq
...
...
@@ -21,8 +22,7 @@ import xiangshan.backend.roq.Roq
*/
class
Backend
(
implicit
val
p
:
XSConfig
)
extends
XSModule
with
HasExeUnits
with
NeedImpl
{
with
NeedImpl
{
val
io
=
IO
(
new
Bundle
{
val
dmem
=
new
SimpleBusUC
(
addrBits
=
VAddrBits
)
val
memMMU
=
Flipped
(
new
MemMMUIO
)
...
...
@@ -56,41 +56,53 @@ class Backend(implicit val p: XSConfig) extends XSModule
redirectInfo
.
misPred
:=
!
roq
.
io
.
redirect
.
valid
&&
brq
.
io
.
redirect
.
valid
redirectInfo
.
redirect
:=
redirect
.
bits
val
issueQueues
=
exeUnits
.
zipWithIndex
.
map
({
case
(
eu
,
i
)
=>
def
needBypass
(
x
:
Exu
)
:
Boolean
=
eu
.
enableBypass
val
bypassCnt
=
exeUnits
.
count
(
needBypass
)
//if(eu.fuTypeInt == FuType.alu.litValue()) exuConfig.AluCnt else 0
def
needWakeup
(
x
:
Exu
)
:
Boolean
=
(
eu
.
readIntRf
&&
x
.
writeIntRf
)
||
(
eu
.
readFpRf
&&
x
.
writeFpRf
)
val
wakeupCnt
=
exeUnits
.
count
(
needWakeup
)
assert
(!(
needBypass
(
eu
)
&&
!
needWakeup
(
eu
)))
// needBypass but dont needWakeup is not allowed
val
iq
=
Module
(
new
IssueQueue
(
eu
.
fuTypeInt
,
wakeupCnt
,
bypassCnt
,
eu
.
fixedDelay
,
fifo
=
eu
.
fuTypeInt
==
FuType
.
ldu
.
litValue
()))
val
issueQueues
=
exeUnits
.
zipWithIndex
.
map
({
case
(
eu
,
i
)
=>
def
needBypass
(
cfg
:
ExuConfig
)
:
Boolean
=
cfg
.
enableBypass
val
bypassCnt
=
if
(
eu
.
config
.
enableBypass
)
exeUnits
.
map
(
_
.
config
).
count
(
needBypass
)
else
0
def
needWakeup
(
cfg
:
ExuConfig
)
:
Boolean
=
(
cfg
.
readIntRf
&&
cfg
.
writeIntRf
)
||
(
cfg
.
readFpRf
&&
cfg
.
writeFpRf
)
val
wakeupCnt
=
exeUnits
.
map
(
_
.
config
).
count
(
needWakeup
)
assert
(!(
needBypass
(
eu
.
config
)
&&
!
needWakeup
(
eu
.
config
)))
// needBypass but dont needWakeup is not allowed
val
iq
=
Module
(
new
IssueQueue
(
eu
.
config
,
wakeupCnt
,
bypassCnt
,
fifo
=
eu
.
config
.
supportedFuncUnits
.
contains
(
FunctionUnit
.
lsuCfg
)
))
iq
.
io
.
redirect
<>
redirect
iq
.
io
.
numExist
<>
dispatch
.
io
.
numExist
(
i
)
iq
.
io
.
enqCtrl
<>
dispatch
.
io
.
enqIQCtrl
(
i
)
iq
.
io
.
enqData
<>
dispatch
.
io
.
enqIQData
(
i
)
val
wuUnitsOut
=
exeUnits
.
filter
(
e
=>
needWakeup
(
e
)).
map
(
_
.
io
.
out
)
for
(
i
<-
iq
.
io
.
wakeUpPorts
.
indices
)
{
val
wuUnitsOut
=
exeUnits
.
filter
(
e
=>
needWakeup
(
e
.
config
)).
map
(
_
.
io
.
out
)
for
(
i
<-
iq
.
io
.
wakeUpPorts
.
indices
)
{
iq
.
io
.
wakeUpPorts
(
i
).
bits
<>
wuUnitsOut
(
i
).
bits
iq
.
io
.
wakeUpPorts
(
i
).
valid
:=
wuUnitsOut
(
i
).
valid
}
println
(
s
"[$i] $eu Queue wakeupCnt:$wakeupCnt bypassCnt:$bypassCnt"
)
println
(
s
"[$i] ${eu.name} Queue wakeupCnt:$wakeupCnt bypassCnt:$bypassCnt"
+
s
" Supported Function:["
+
s
"${
eu.config.supportedFuncUnits.map(
fu => FuType.functionNameMap(fu.fuType.litValue())).mkString("
,
"
)
}]"
)
eu
.
io
.
in
<>
iq
.
io
.
deq
eu
.
io
.
redirect
<>
redirect
iq
})
val
bypassQueues
=
issueQueues
.
filter
(
_
.
bypassCnt
>
0
)
val
bypassUnits
=
exeUnits
.
filter
(
_
.
enableBypass
)
val
bypassUnits
=
exeUnits
.
filter
(
_
.
config
.
enableBypass
)
bypassQueues
.
foreach
(
iq
=>
{
for
(
i
<-
iq
.
io
.
bypassUops
.
indices
)
{
for
(
i
<-
iq
.
io
.
bypassUops
.
indices
)
{
iq
.
io
.
bypassData
(
i
).
bits
:=
bypassUnits
(
i
).
io
.
out
.
bits
iq
.
io
.
bypassData
(
i
).
valid
:=
bypassUnits
(
i
).
io
.
out
.
valid
}
iq
.
io
.
bypassUops
<>
bypassQueues
.
map
(
_
.
io
.
selectedUop
)
})
// val aluQueues = issueQueues.filter(_.fuTypeInt == FuType.alu.litValue())
// aluQueues.foreach(aluQ => {
// aluQ.io.bypassUops <> aluQueues.map(_.io.selectedUop)
// aluQ.io.bypassData <> aluExeUnits.map(_.io.out)
// })
lsuExeUnits
.
foreach
(
_
.
io
.
dmem
<>
io
.
dmem
)
lsuExeUnits
.
foreach
(
_
.
io
.
scommit
<>
roq
.
io
.
scommit
)
...
...
@@ -101,7 +113,7 @@ class Backend(implicit val p: XSConfig) extends XSModule
decode
.
io
.
in
<>
io
.
frontend
.
cfVec
brq
.
io
.
roqRedirect
<>
roq
.
io
.
redirect
brq
.
io
.
enqReqs
<>
decode
.
io
.
toBrq
for
((
x
,
y
)
<-
brq
.
io
.
exuRedirect
.
zip
(
exeUnits
.
filter
(
_
.
hasRedirect
)))
{
for
((
x
,
y
)
<-
brq
.
io
.
exuRedirect
.
zip
(
exeUnits
.
filter
(
_
.
config
.
hasRedirect
)))
{
x
.
bits
:=
y
.
io
.
out
.
bits
x
.
valid
:=
y
.
io
.
out
.
fire
()
&&
y
.
io
.
out
.
bits
.
redirectValid
}
...
...
@@ -129,8 +141,8 @@ class Backend(implicit val p: XSConfig) extends XSModule
val
exeWbReqs
=
exeUnits
.
map
(
_
.
io
.
out
)
val
wbIntIdx
=
exeUnits
.
zipWithIndex
.
filter
(
_
.
_1
.
writeIntRf
).
map
(
_
.
_2
)
val
wbFpIdx
=
exeUnits
.
zipWithIndex
.
filter
(
_
.
_1
.
writeFpRf
).
map
(
_
.
_2
)
val
wbIntIdx
=
exeUnits
.
zipWithIndex
.
filter
(
_
.
_1
.
config
.
writeIntRf
).
map
(
_
.
_2
)
val
wbFpIdx
=
exeUnits
.
zipWithIndex
.
filter
(
_
.
_1
.
config
.
writeFpRf
).
map
(
_
.
_2
)
val
wbu
=
Module
(
new
Wbu
(
wbIntIdx
,
wbFpIdx
))
wbu
.
io
.
in
<>
exeWbReqs
...
...
@@ -172,13 +184,15 @@ class Backend(implicit val p: XSConfig) extends XSModule
"perfCntCondMdcacheReq"
,
"meip"
)
for
(
s
<-
sinks
){
BoringUtils
.
addSink
(
tmp
,
s
)
}
for
(
s
<-
sinks
)
{
BoringUtils
.
addSink
(
tmp
,
s
)
}
val
debugIntReg
,
debugFpReg
=
WireInit
(
VecInit
(
Seq
.
fill
(
32
)(
0.
U
(
XLEN
.
W
))))
BoringUtils
.
addSink
(
debugIntReg
,
"DEBUG_INT_ARCH_REG"
)
BoringUtils
.
addSink
(
debugFpReg
,
"DEBUG_FP_ARCH_REG"
)
val
debugArchReg
=
WireInit
(
VecInit
(
debugIntReg
++
debugFpReg
))
if
(!
p
.
FPGAPlatform
)
{
if
(!
p
.
FPGAPlatform
)
{
BoringUtils
.
addSource
(
debugArchReg
,
"difftestRegs"
)
}
...
...
src/main/scala/xiangshan/backend/brq/Brq.scala
浏览文件 @
706f729c
...
...
@@ -53,7 +53,7 @@ class BrqIO extends XSBundle{
// interrupt/exception happen, flush Brq
val
roqRedirect
=
Input
(
Valid
(
new
Redirect
))
// receive branch/jump calculated target
val
exuRedirect
=
Vec
(
exu
Config
.
AluCnt
+
exuConfig
.
Bru
Cnt
,
Flipped
(
ValidIO
(
new
ExuOutput
)))
val
exuRedirect
=
Vec
(
exu
Parameters
.
AluCnt
+
exuParameters
.
Jmp
Cnt
,
Flipped
(
ValidIO
(
new
ExuOutput
)))
// from decode, branch insts enq
val
enqReqs
=
Vec
(
DecodeWidth
,
Flipped
(
DecoupledIO
(
new
CfCtrl
)))
// to decode
...
...
@@ -171,7 +171,7 @@ class Brq extends XSModule {
val
wbIdx
=
exuWb
.
bits
.
redirect
.
brTag
.
value
XSInfo
(
p
"exu write back: brTag:${exuWb.bits.redirect.brTag}"
+
p
" pc=${Hexadecimal(exuWb.bits.uop.cf.pc)}\n"
p
" pc=${Hexadecimal(exuWb.bits.uop.cf.pc)}
pnpc=${Hexadecimal(brQueue(wbIdx).npc)} target=${Hexadecimal(exuWb.bits.redirect.target)}
\n"
)
stateQueue
(
wbIdx
)
:=
s_wb
brQueue
(
wbIdx
).
exuOut
:=
exuWb
.
bits
...
...
src/main/scala/xiangshan/backend/decode/Decoder.scala
浏览文件 @
706f729c
...
...
@@ -27,8 +27,8 @@ class Decoder extends XSModule with HasInstrType {
// todo: remove this when fetch stage can decide if an instr is br/jmp
io
.
out
.
cf
.
isBr
:=
(
instrType
===
InstrB
||
(
fuOpType
===
BRUOpType
.
jal
&&
instrType
===
InstrJ
&&
fuType
===
FuType
.
bru
)
||
(
fuOpType
===
BRUOpType
.
jalr
&&
instrType
===
InstrI
&&
fuType
===
FuType
.
bru
))
(
fuOpType
===
BRUOpType
.
jal
&&
instrType
===
InstrJ
&&
fuType
===
FuType
.
jmp
)
||
(
fuOpType
===
BRUOpType
.
jalr
&&
instrType
===
InstrI
&&
fuType
===
FuType
.
jmp
))
// val isRVC = instr(1, 0) =/= "b11".U
// val rvcImmType :: rvcSrc1Type :: rvcSrc2Type :: rvcDestType :: Nil =
...
...
src/main/scala/xiangshan/backend/decode/isa/RVI.scala
浏览文件 @
706f729c
...
...
@@ -4,7 +4,7 @@ import chisel3._
import
chisel3.util._
import
xiangshan.
{
FuType
,
HasXSParameter
}
import
xiangshan.backend.decode._
import
xiangshan.backend.
{
ALUOpType
,
BTBtype
,
BRUOpType
,
LDUOpType
,
STUOpType
}
import
xiangshan.backend.
_
object
RV32I_ALUInstr
extends
HasInstrType
with
HasXSParameter
{
def
ADDI
=
BitPat
(
"b????????????_?????_000_?????_0010011"
)
...
...
@@ -73,8 +73,8 @@ object RV32I_BRUInstr extends HasInstrType {
def
BGEU
=
BitPat
(
"b???????_?????_?????_111_?????_1100011"
)
val
table
=
Array
(
JAL
->
List
(
InstrJ
,
FuType
.
bru
,
BRUOpType
.
jal
),
JALR
->
List
(
InstrI
,
FuType
.
bru
,
BRUOpType
.
jalr
),
JAL
->
List
(
InstrJ
,
FuType
.
jmp
,
BRUOpType
.
jal
),
JALR
->
List
(
InstrI
,
FuType
.
jmp
,
BRUOpType
.
jalr
),
BEQ
->
List
(
InstrB
,
FuType
.
alu
,
ALUOpType
.
beq
),
BNE
->
List
(
InstrB
,
FuType
.
alu
,
ALUOpType
.
bne
),
...
...
@@ -109,15 +109,15 @@ object RV32I_LSUInstr extends HasInstrType {
def
SW
=
BitPat
(
"b???????_?????_?????_010_?????_0100011"
)
val
table
=
Array
(
LB
->
List
(
InstrI
,
FuType
.
ldu
,
L
D
UOpType
.
lb
),
LH
->
List
(
InstrI
,
FuType
.
ldu
,
L
D
UOpType
.
lh
),
LW
->
List
(
InstrI
,
FuType
.
ldu
,
L
D
UOpType
.
lw
),
LBU
->
List
(
InstrI
,
FuType
.
ldu
,
L
D
UOpType
.
lbu
),
LHU
->
List
(
InstrI
,
FuType
.
ldu
,
L
D
UOpType
.
lhu
),
SB
->
List
(
InstrS
,
FuType
.
stu
,
ST
UOpType
.
sb
),
SH
->
List
(
InstrS
,
FuType
.
stu
,
ST
UOpType
.
sh
),
SW
->
List
(
InstrS
,
FuType
.
stu
,
ST
UOpType
.
sw
)
LB
->
List
(
InstrI
,
FuType
.
ldu
,
L
S
UOpType
.
lb
),
LH
->
List
(
InstrI
,
FuType
.
ldu
,
L
S
UOpType
.
lh
),
LW
->
List
(
InstrI
,
FuType
.
ldu
,
L
S
UOpType
.
lw
),
LBU
->
List
(
InstrI
,
FuType
.
ldu
,
L
S
UOpType
.
lbu
),
LHU
->
List
(
InstrI
,
FuType
.
ldu
,
L
S
UOpType
.
lhu
),
SB
->
List
(
InstrS
,
FuType
.
stu
,
LS
UOpType
.
sb
),
SH
->
List
(
InstrS
,
FuType
.
stu
,
LS
UOpType
.
sh
),
SW
->
List
(
InstrS
,
FuType
.
stu
,
LS
UOpType
.
sw
)
)
}
...
...
@@ -147,9 +147,9 @@ object RV64IInstr extends HasInstrType {
ADDW
->
List
(
InstrR
,
FuType
.
alu
,
ALUOpType
.
addw
),
SUBW
->
List
(
InstrR
,
FuType
.
alu
,
ALUOpType
.
subw
),
LWU
->
List
(
InstrI
,
FuType
.
ldu
,
L
D
UOpType
.
lwu
),
LD
->
List
(
InstrI
,
FuType
.
ldu
,
L
D
UOpType
.
ld
),
SD
->
List
(
InstrS
,
FuType
.
stu
,
ST
UOpType
.
sd
)
LWU
->
List
(
InstrI
,
FuType
.
ldu
,
L
S
UOpType
.
lwu
),
LD
->
List
(
InstrI
,
FuType
.
ldu
,
L
S
UOpType
.
ld
),
SD
->
List
(
InstrS
,
FuType
.
stu
,
LS
UOpType
.
sd
)
)
}
...
...
src/main/scala/xiangshan/backend/decode/isa/RVM.scala
浏览文件 @
706f729c
...
...
@@ -4,7 +4,7 @@ import chisel3._
import
chisel3.util._
import
xiangshan.
{
FuType
,
HasXSParameter
}
import
xiangshan.backend.decode._
import
xiangshan.backend.
{
MDUOpType
,
MULOpType
}
import
xiangshan.backend.
MDUOpType
object
RV32MInstr
extends
HasInstrType
with
HasXSParameter
{
def
MUL
=
BitPat
(
"b0000001_?????_?????_000_?????_0110011"
)
...
...
@@ -22,16 +22,16 @@ object RV32MInstr extends HasInstrType with HasXSParameter {
def
REMUW
=
BitPat
(
"b0000001_?????_?????_111_?????_0111011"
)
val
mulTable
=
Array
(
MUL
->
List
(
InstrR
,
FuType
.
mul
,
M
UL
OpType
.
mul
),
MULH
->
List
(
InstrR
,
FuType
.
mul
,
M
UL
OpType
.
mulh
),
MULHSU
->
List
(
InstrR
,
FuType
.
mul
,
M
UL
OpType
.
mulhsu
),
MULHU
->
List
(
InstrR
,
FuType
.
mul
,
M
UL
OpType
.
mulhu
)
MUL
->
List
(
InstrR
,
FuType
.
mul
,
M
DU
OpType
.
mul
),
MULH
->
List
(
InstrR
,
FuType
.
mul
,
M
DU
OpType
.
mulh
),
MULHSU
->
List
(
InstrR
,
FuType
.
mul
,
M
DU
OpType
.
mulhsu
),
MULHU
->
List
(
InstrR
,
FuType
.
mul
,
M
DU
OpType
.
mulhu
)
)
val
divTable
=
Array
(
DIV
->
List
(
InstrR
,
FuType
.
mdu
,
MDUOpType
.
div
),
DIVU
->
List
(
InstrR
,
FuType
.
mdu
,
MDUOpType
.
divu
),
REM
->
List
(
InstrR
,
FuType
.
mdu
,
MDUOpType
.
rem
),
REMU
->
List
(
InstrR
,
FuType
.
mdu
,
MDUOpType
.
remu
)
DIV
->
List
(
InstrR
,
FuType
.
div
,
MDUOpType
.
div
),
DIVU
->
List
(
InstrR
,
FuType
.
div
,
MDUOpType
.
divu
),
REM
->
List
(
InstrR
,
FuType
.
div
,
MDUOpType
.
rem
),
REMU
->
List
(
InstrR
,
FuType
.
div
,
MDUOpType
.
remu
)
)
val
table
=
mulTable
++
(
if
(
HasDiv
)
divTable
else
Nil
)
}
...
...
@@ -44,13 +44,13 @@ object RV64MInstr extends HasInstrType with HasXSParameter {
def
REMUW
=
BitPat
(
"b0000001_?????_?????_111_?????_0111011"
)
val
mulTable
=
Array
(
MULW
->
List
(
InstrR
,
FuType
.
mul
,
M
UL
OpType
.
mulw
)
MULW
->
List
(
InstrR
,
FuType
.
mul
,
M
DU
OpType
.
mulw
)
)
val
divTable
=
Array
(
DIVW
->
List
(
InstrR
,
FuType
.
mdu
,
MDUOpType
.
divw
),
DIVUW
->
List
(
InstrR
,
FuType
.
mdu
,
MDUOpType
.
divuw
),
REMW
->
List
(
InstrR
,
FuType
.
mdu
,
MDUOpType
.
remw
),
REMUW
->
List
(
InstrR
,
FuType
.
mdu
,
MDUOpType
.
remuw
)
DIVW
->
List
(
InstrR
,
FuType
.
div
,
MDUOpType
.
divw
),
DIVUW
->
List
(
InstrR
,
FuType
.
div
,
MDUOpType
.
divuw
),
REMW
->
List
(
InstrR
,
FuType
.
div
,
MDUOpType
.
remw
),
REMUW
->
List
(
InstrR
,
FuType
.
div
,
MDUOpType
.
remuw
)
)
val
table
=
mulTable
++
(
if
(
HasDiv
)
divTable
else
Nil
)
}
...
...
src/main/scala/xiangshan/backend/dispatch/Dispatch.scala
浏览文件 @
706f729c
...
...
@@ -21,18 +21,19 @@ class Dispatch extends XSModule {
// read reg status (busy/ready)
val
intPregRdy
=
Vec
(
NRReadPorts
,
Input
(
Bool
()))
val
fpPregRdy
=
Vec
(
NRReadPorts
,
Input
(
Bool
()))
// ro reservation stations
val
enqIQCtrl
=
Vec
(
exuConfig
.
ExuCnt
,
DecoupledIO
(
new
MicroOp
))
val
enqIQData
=
Vec
(
exuConfig
.
ExuCnt
,
ValidIO
(
new
ExuInput
))
// to reservation stations
val
numExist
=
Input
(
Vec
(
exuParameters
.
ExuCnt
,
UInt
(
log2Ceil
(
IssQueSize
).
W
)))
val
enqIQCtrl
=
Vec
(
exuParameters
.
ExuCnt
,
DecoupledIO
(
new
MicroOp
))
val
enqIQData
=
Vec
(
exuParameters
.
ExuCnt
,
ValidIO
(
new
ExuInput
))
})
// pipeline between rename and dispatch
val
dispatch1
=
Module
(
new
Dispatch1
())
for
(
i
<-
0
until
RenameWidth
)
{
PipelineConnect
(
io
.
fromRename
(
i
),
dispatch1
.
io
.
fromRename
(
i
),
dispatch1
.
io
.
recv
(
i
),
false
.
B
)
}
val
intDq
=
Module
(
new
DispatchQueue
(
dp1
Config
.
IntDqSize
,
RenameWidth
,
IntDqDeqWidth
,
"IntDpQ"
))
val
fpDq
=
Module
(
new
DispatchQueue
(
dp1
Config
.
FpDqSize
,
RenameWidth
,
FpDqDeqWidth
,
"FpDpQ"
))
val
lsDq
=
Module
(
new
DispatchQueue
(
dp1
Config
.
LsDqSize
,
RenameWidth
,
LsDqDeqWidth
,
"LsDpQ"
))
val
intDq
=
Module
(
new
DispatchQueue
(
dp1
Paremeters
.
IntDqSize
,
RenameWidth
,
IntDqDeqWidth
,
"IntDpQ"
))
val
fpDq
=
Module
(
new
DispatchQueue
(
dp1
Paremeters
.
FpDqSize
,
RenameWidth
,
FpDqDeqWidth
,
"FpDpQ"
))
val
lsDq
=
Module
(
new
DispatchQueue
(
dp1
Paremeters
.
LsDqSize
,
RenameWidth
,
LsDqDeqWidth
,
"LsDpQ"
))
val
dispatch2
=
Module
(
new
Dispatch2
())
dispatch1
.
io
.
redirect
<>
io
.
redirect
...
...
@@ -57,4 +58,5 @@ class Dispatch extends XSModule {
dispatch2
.
io
.
fpPregRdy
<>
io
.
fpPregRdy
dispatch2
.
io
.
enqIQCtrl
<>
io
.
enqIQCtrl
dispatch2
.
io
.
enqIQData
<>
io
.
enqIQData
dispatch2
.
io
.
numExist
<>
io
.
numExist
}
src/main/scala/xiangshan/backend/dispatch/Dispatch1.scala
浏览文件 @
706f729c
...
...
@@ -5,7 +5,7 @@ import chisel3.util._
import
xiangshan._
import
xiangshan.utils.
{
XSDebug
,
XSInfo
,
XSWarn
}
case
class
DP1
Config
case
class
DP1
Parameters
(
IntDqSize
:
Int
,
FpDqSize
:
Int
,
...
...
src/main/scala/xiangshan/backend/dispatch/Dispatch2.scala
浏览文件 @
706f729c
...
...
@@ -6,7 +6,7 @@ import xiangshan._
import
xiangshan.backend.regfile.RfReadPort
import
xiangshan.utils.
{
XSDebug
,
XSInfo
}
class
Dispatch2
extends
XSModule
{
class
Dispatch2
extends
XSModule
{
val
io
=
IO
(
new
Bundle
()
{
// from dispatch queues
val
fromIntDq
=
Flipped
(
Vec
(
IntDqDeqWidth
,
DecoupledIO
(
new
MicroOp
)))
...
...
@@ -21,145 +21,79 @@ class Dispatch2 extends XSModule {
val
fpPregRdy
=
Vec
(
NRReadPorts
,
Input
(
Bool
()))
// enq Issue Queue
val
enqIQCtrl
=
Vec
(
exuConfig
.
ExuCnt
,
DecoupledIO
(
new
MicroOp
))
val
enqIQData
=
Vec
(
exuConfig
.
ExuCnt
,
ValidIO
(
new
ExuInput
))
val
numExist
=
Input
(
Vec
(
exuParameters
.
ExuCnt
,
UInt
(
log2Ceil
(
IssQueSize
).
W
)))
val
enqIQCtrl
=
Vec
(
exuParameters
.
ExuCnt
,
DecoupledIO
(
new
MicroOp
))
val
enqIQData
=
Vec
(
exuParameters
.
ExuCnt
,
ValidIO
(
new
ExuInput
))
})
// inst indexes for reservation stations
// append a true.B to avoid PriorityEncode(0000) -> 3
// if find a target uop, index[2] == 0, else index[2] == 1
val
bruInstIdx
=
PriorityEncoder
(
io
.
fromIntDq
.
map
(
deq
=>
deq
.
bits
.
ctrl
.
fuType
===
FuType
.
bru
&&
deq
.
valid
)
:+
true
.
B
)
val
aluInstIdxsTry
=
RegInit
(
VecInit
(
Seq
.
tabulate
(
exuConfig
.
AluCnt
)(
i
=>
i
.
U
(
2.
W
))))
val
aluInstIdxs
=
Wire
(
Vec
(
exuConfig
.
AluCnt
,
UInt
(
3.
W
)))
for
(
i
<-
0
until
exuConfig
.
AluCnt
)
{
assert
(
exuConfig
.
AluCnt
==
IntDqDeqWidth
)
// 0 -> 1 -> 2 -> 3 -> 0
aluInstIdxsTry
(
i
)
:=
aluInstIdxsTry
(
i
)
+
1.
U
val
deqAluInvalid
=
io
.
fromIntDq
(
aluInstIdxsTry
(
i
)).
bits
.
ctrl
.
fuType
=/=
FuType
.
alu
||
!
io
.
fromIntDq
(
aluInstIdxsTry
(
i
)).
valid
aluInstIdxs
(
i
)
:=
Cat
(
deqAluInvalid
.
asUInt
(),
aluInstIdxsTry
(
i
))
}
val
mulInstIdx
=
PriorityEncoder
(
io
.
fromIntDq
.
map
(
deq
=>
deq
.
bits
.
ctrl
.
fuType
===
FuType
.
mul
&&
deq
.
valid
)
:+
true
.
B
)
val
muldivInstIdx
=
PriorityEncoder
((
io
.
fromIntDq
.
zipWithIndex
map
{
case
(
deq
,
i
)
=>
((
deq
.
bits
.
ctrl
.
fuType
===
FuType
.
mul
&&
i
.
U
>
mulInstIdx
)
||
deq
.
bits
.
ctrl
.
fuType
===
FuType
.
mdu
)
&&
deq
.
valid
})
:+
true
.
B
)
// TODO uncomment when FmacCnt > 0
val
fmacInstIdxsTry
=
Reg
(
Vec
(
exuConfig
.
FmacCnt
,
UInt
(
2.
W
)))
// val fmacInstIdxsTry = RegInit(VecInit(Seq.tabulate(exuConfig.FmacCnt)(i => i.U(2.W))))
val
fmacInstIdxs
=
Wire
(
Vec
(
exuConfig
.
FmacCnt
,
UInt
(
3.
W
)))
// val deqFmacInstIdxs = RegInit(VecInit(Seq.tabulate(exuConfig.FmacCnt)(i => i.U(2.W))))
for
(
i
<-
0
until
exuConfig
.
FmacCnt
)
{
assert
(
exuConfig
.
FmacCnt
==
FpDqDeqWidth
)
// 0 -> 1 -> 2 -> 3 -> 0
fmacInstIdxsTry
(
i
)
:=
fmacInstIdxsTry
(
i
)
+
1.
U
val
deqFmacInvalid
=
io
.
fromFpDq
(
fmacInstIdxsTry
(
i
)).
bits
.
ctrl
.
fuType
=/=
FuType
.
fmac
||
!
io
.
fromFpDq
(
fmacInstIdxsTry
(
i
)).
valid
fmacInstIdxs
(
i
)
:=
Cat
(
deqFmacInvalid
.
asUInt
(),
fmacInstIdxsTry
(
i
))
for
(
i
<-
0
until
IntDqDeqWidth
)
{
XSDebug
(
io
.
fromIntDq
(
i
).
valid
,
p
"int dp queue $i: ${Hexadecimal(io.fromIntDq(i).bits.cf.pc)} type ${Binary(io.fromIntDq(i).bits.ctrl.fuType)}\n"
)
}
val
fmisc0InstIdx
=
PriorityEncoder
(
io
.
fromFpDq
.
map
(
deq
=>
deq
.
bits
.
ctrl
.
fuType
===
FuType
.
fmisc
&&
deq
.
valid
)
:+
true
.
B
)
val
fmisc1InstIdx
=
PriorityEncoder
((
io
.
fromFpDq
.
zipWithIndex
map
{
case
(
deq
,
i
)
=>
((
deq
.
bits
.
ctrl
.
fuType
===
FuType
.
fmisc
&&
i
.
U
>
fmisc0InstIdx
)
||
deq
.
bits
.
ctrl
.
fuType
===
FuType
.
fmiscDivSqrt
)
&&
deq
.
valid
})
:+
true
.
B
)
for
(
i
<-
0
until
FpDqDeqWidth
)
{
XSDebug
(
io
.
fromFpDq
(
i
).
valid
,
p
"fp dp queue $i: ${Hexadecimal(io.fromFpDq(i).bits.cf.pc)} type ${Binary(io.fromFpDq(i).bits.ctrl.fuType)}\n"
)
}
for
(
i
<-
0
until
LsDqDeqWidth
)
{
XSDebug
(
io
.
fromLsDq
(
i
).
valid
,
p
"ls dp queue $i: ${Hexadecimal(io.fromLsDq(i).bits.cf.pc)} type ${Binary(io.fromLsDq(i).bits.ctrl.fuType)}\n"
)
}
// inst indexes for reservation stations
val
rsIndexGen
=
Module
(
new
DispatchGen
())
rsIndexGen
.
io
.
fromIntDq
:=
io
.
fromIntDq
rsIndexGen
.
io
.
fromFpDq
:=
io
.
fromFpDq
rsIndexGen
.
io
.
fromLsDq
:=
io
.
fromLsDq
rsIndexGen
.
io
.
numExist
:=
io
.
numExist
// TODO: currently there's only one load/store reservation station
val
load0InstIdx
=
PriorityEncoder
(
io
.
fromLsDq
.
map
(
_
.
bits
.
ctrl
.
fuType
===
FuType
.
ldu
)
:+
true
.
B
)
val
load1InstIdx
=
PriorityEncoder
((
io
.
fromLsDq
.
zipWithIndex
map
{
case
(
uop
,
i
)
=>
uop
.
bits
.
ctrl
.
fuType
===
FuType
.
ldu
&&
i
.
U
>
load0InstIdx
})
:+
true
.
B
)
// val store0InstIdx = PriorityEncoder(io.fromLsDq.map(_.bits.ctrl.fuType === FuType.stu) :+ true.B)
val
store0InstIdx
=
PriorityEncoder
(
io
.
fromLsDq
.
map
(
deq
=>
FuType
.
isMemExu
(
deq
.
bits
.
ctrl
.
fuType
))
:+
true
.
B
)
val
store1InstIdx
=
PriorityEncoder
((
io
.
fromLsDq
.
zipWithIndex
map
{
case
(
uop
,
i
)
=>
uop
.
bits
.
ctrl
.
fuType
===
FuType
.
stu
&&
i
.
U
>
store0InstIdx
})
:+
true
.
B
)
val
instValid
=
rsIndexGen
.
io
.
enqIQIndex
.
map
(
_
.
valid
)
val
allIndex
=
rsIndexGen
.
io
.
enqIQIndex
.
map
(
_
.
bits
)
XSDebug
(
"%d %d %d %d %d %d %d %d\n"
,
bruInstIdx
,
aluInstIdxs
(
0
),
aluInstIdxs
(
1
),
aluInstIdxs
(
2
),
aluInstIdxs
(
3
),
mulInstIdx
,
muldivInstIdx
,
store0InstIdx
)
allIndex
.
zipWithIndex
.
map
({
case
(
index
,
i
)
=>
XSDebug
(
instValid
(
i
),
p
"dispatch to iq index $i: $index\n"
)})
// regfile read ports
// regfile is sync-read, data can used at the next cycle
// BRU, MUL0, MUL1 can use the 8 read ports
// priority: ALU > BRU > MUL
val
intExuIndex
=
WireInit
(
VecInit
(
Seq
.
fill
(
3
)(
0.
U
(
2.
W
))))
val
intDeqChoice
=
Wire
(
Vec
(
4
,
UInt
(
2.
W
)))
for
(
i
<-
0
until
4
)
{
val
readPortSrc
=
Seq
(
aluInstIdxs
(
i
),
bruInstIdx
,
mulInstIdx
,
muldivInstIdx
)
val
wantReadPort
=
(
0
until
4
).
map
(
j
=>
(
if
(
i
==
0
)
!
readPortSrc
(
j
)(
2
)
else
{
val
prevMax
=
(
0
until
i
).
map
(
intDeqChoice
(
_
)).
reduce
((
a
,
b
)
=>
Mux
(
a
>
b
,
a
,
b
))
!
readPortSrc
(
j
)(
2
)
&&
(
j
.
U
>
prevMax
||
j
.
U
===
0.
U
)
}))
val
readIdxVec
=
Wire
(
Vec
(
4
,
UInt
(
2.
W
)))
for
(
j
<-
0
until
4
)
{
readIdxVec
(
j
)
:=
readPortSrc
(
j
)(
1
,
0
)
}
intDeqChoice
(
i
)
:=
PriorityEncoder
(
wantReadPort
)
XSDebug
(
"int %d: want %b, deqChoice: %d\n"
,
i
.
U
,
Cat
(
wantReadPort
),
intDeqChoice
(
i
))
val
target
=
readIdxVec
(
intDeqChoice
(
i
)(
1
,
0
))
io
.
readIntRf
(
2
*
i
).
addr
:=
io
.
fromIntDq
(
target
).
bits
.
psrc1
io
.
readIntRf
(
2
*
i
+
1
).
addr
:=
io
.
fromIntDq
(
target
).
bits
.
psrc2
io
.
readIntRf
<>
DontCare
val
regfileRPGen
=
Module
(
new
RegfileReadPortGen
())
(
0
until
exuParameters
.
IntExuCnt
).
map
(
i
=>
regfileRPGen
.
io
.
intIQEnqIndex
(
i
)
:=
rsIndexGen
.
io
.
enqIQIndex
(
i
))
(
0
until
exuParameters
.
FpExuCnt
).
map
(
i
=>
regfileRPGen
.
io
.
fpIQEnqIndex
(
i
)
:=
rsIndexGen
.
io
.
enqIQIndex
(
exuParameters
.
IntExuCnt
+
i
))
(
0
until
exuParameters
.
LsExuCnt
).
map
(
i
=>
regfileRPGen
.
io
.
lsIQEnqIndex
(
i
)
:=
rsIndexGen
.
io
.
enqIQIndex
(
exuParameters
.
IntExuCnt
+
exuParameters
.
FpExuCnt
+
i
))
for
(
i
<-
0
until
2
*
exuParameters
.
IntExuCnt
)
{
val
bits
=
io
.
fromIntDq
(
regfileRPGen
.
io
.
readIntRf
(
i
)).
bits
io
.
readIntRf
(
i
).
addr
:=
(
if
(
i
%
2
==
0
)
bits
.
psrc1
else
bits
.
psrc2
)
XSDebug
(
p
"regfile $i from ${regfileRPGen.io.readIntRf(i)}\n"
)
}
// intExuIndex: which regfile read ports are assigned to BRU, MUL, MULDIV
for
(
j
<-
0
until
3
)
{
i
ntExuIndex
(
j
)
:=
PriorityEncoder
((
0
until
4
).
map
(
i
=>
intDeqChoice
(
i
)
===
(
j
+
1
).
U
)
)
for
(
i
<-
0
until
3
*
exuParameters
.
FpExuCnt
)
{
val
bits
=
io
.
fromFpDq
(
regfileRPGen
.
io
.
readFpRf
(
i
)).
bits
i
o
.
readFpRf
(
i
).
addr
:=
(
if
(
i
%
3
==
0
)
bits
.
psrc1
else
if
(
i
%
3
==
1
)
bits
.
psrc2
else
bits
.
psrc3
)
}
XSDebug
(
"intExuIndex: %d %d %d\n"
,
intExuIndex
(
0
),
intExuIndex
(
1
),
intExuIndex
(
2
))
// FMAC, FMISC can use the 12 read ports
// priority: FMAC > FMISC
val
fpExuIndex
=
WireInit
(
VecInit
(
Seq
.
fill
(
2
)(
0.
U
(
2.
W
))))
val
fpDeqChoice
=
Wire
(
Vec
(
4
,
UInt
(
2.
W
)))
fpDeqChoice
:=
DontCare
for
(
i
<-
0
until
exuConfig
.
FmacCnt
)
{
val
readPortSrc
=
Seq
(
fmacInstIdxs
(
i
),
fmisc0InstIdx
,
fmisc1InstIdx
)
val
wantReadPort
=
(
0
until
3
).
map
(
j
=>
(
if
(
i
==
0
)
!
readPortSrc
(
j
)(
2
)
else
{
val
prevMax
=
(
0
until
i
).
map
(
fpDeqChoice
(
_
)).
reduce
((
a
,
b
)
=>
Mux
(
a
>
b
,
a
,
b
))
!
readPortSrc
(
j
)(
2
)
&&
(
j
.
U
>
prevMax
||
j
.
U
===
0.
U
)
}))
val
readIdxVec
=
Wire
(
Vec
(
3
,
UInt
(
2.
W
)))
for
(
j
<-
0
until
3
)
{
readIdxVec
(
j
)
:=
readPortSrc
(
j
)(
1
,
0
)
}
fpDeqChoice
(
i
)
:=
PriorityEncoder
(
wantReadPort
)
XSDebug
(
"fp %d: want %b, deqChoice: %d\n"
,
i
.
U
,
Cat
(
wantReadPort
),
fpDeqChoice
(
i
))
val
target
=
readIdxVec
(
fpDeqChoice
(
i
))
io
.
readFpRf
(
3
*
i
).
addr
:=
io
.
fromFpDq
(
target
).
bits
.
psrc1
io
.
readFpRf
(
3
*
i
+
1
).
addr
:=
io
.
fromFpDq
(
target
).
bits
.
psrc2
io
.
readFpRf
(
3
*
i
+
2
).
addr
:=
io
.
fromFpDq
(
target
).
bits
.
psrc3
for
(
i
<-
0
until
exuParameters
.
LduCnt
)
{
val
start
=
2
*
exuParameters
.
AluCnt
io
.
readIntRf
(
start
+
i
).
addr
:=
io
.
fromLsDq
(
regfileRPGen
.
io
.
readIntRf
(
start
+
i
))
}
// fpExuIndex: which regfile read ports are assigned to FMISC0 FMISC1
for
(
j
<-
0
until
(
exuConfig
.
FmiscCnt
+
exuConfig
.
FmiscDivSqrtCnt
))
{
fpExuIndex
(
j
)
:=
PriorityEncoder
((
0
until
4
).
map
(
i
=>
fpDeqChoice
(
i
)
===
(
j
+
1
).
U
))
for
(
i
<-
0
until
2
*
exuParameters
.
StuCnt
)
{
val
start
=
2
*
exuParameters
.
AluCnt
+
exuParameters
.
LduCnt
val
bits
=
io
.
fromLsDq
(
regfileRPGen
.
io
.
readIntRf
(
start
+
i
)).
bits
io
.
readIntRf
(
start
+
i
).
addr
:=
(
if
(
i
%
2
==
0
)
bits
.
psrc1
else
bits
.
psrc2
)
}
for
(
i
<-
0
until
NRReadPorts
)
{
XSDebug
(
p
"regfile $i: addr ${io.readIntRf(i).addr}, state ${io.intPregRdy(i)}\n"
)
}
XSDebug
(
"fpExuIndex: %d %d\n"
,
fpExuIndex
(
0
),
fpExuIndex
(
1
))
// TODO uncomment me when fmac > 0
io
.
readFpRf
<>
DontCare
io
.
readIntRf
(
2
*
IntDqDeqWidth
).
addr
:=
io
.
fromLsDq
(
load0InstIdx
).
bits
.
psrc1
io
.
readIntRf
(
2
*
IntDqDeqWidth
+
1
).
addr
:=
io
.
fromLsDq
(
load1InstIdx
).
bits
.
psrc1
io
.
readIntRf
(
2
*
IntDqDeqWidth
+
2
).
addr
:=
io
.
fromLsDq
(
store0InstIdx
).
bits
.
psrc1
io
.
readIntRf
(
2
*
IntDqDeqWidth
+
3
).
addr
:=
io
.
fromLsDq
(
store0InstIdx
).
bits
.
psrc2
io
.
readIntRf
(
2
*
IntDqDeqWidth
+
4
).
addr
:=
io
.
fromLsDq
(
store1InstIdx
).
bits
.
psrc1
io
.
readIntRf
(
2
*
IntDqDeqWidth
+
5
).
addr
:=
io
.
fromLsDq
(
store1InstIdx
).
bits
.
psrc2
io
.
readFpRf
(
3
*
FpDqDeqWidth
).
addr
:=
io
.
fromLsDq
(
store0InstIdx
).
bits
.
psrc1
io
.
readFpRf
(
3
*
FpDqDeqWidth
+
1
).
addr
:=
io
.
fromLsDq
(
store1InstIdx
).
bits
.
psrc1
// insert into reservation station
val
instIdxes
=
Seq
(
bruInstIdx
,
aluInstIdxs
(
0
),
aluInstIdxs
(
1
),
aluInstIdxs
(
2
),
aluInstIdxs
(
3
),
mulInstIdx
,
muldivInstIdx
,
/*load0InstIdx, */
store0InstIdx
)
val
instIdxes
=
(
0
until
exuParameters
.
ExuCnt
).
map
(
i
=>
Cat
(!
instValid
(
i
),
allIndex
(
i
)))
io
.
enqIQCtrl
.
zipWithIndex
map
{
case
(
enq
,
i
)
=>
if
(
i
<
exu
Config
.
IntExuCnt
)
{
if
(
i
<
exu
Parameters
.
IntExuCnt
)
{
enq
.
valid
:=
!
instIdxes
(
i
)(
2
)
&&
io
.
fromIntDq
(
instIdxes
(
i
)(
1
,
0
)).
valid
enq
.
bits
:=
io
.
fromIntDq
(
instIdxes
(
i
)(
1
,
0
)).
bits
val
startIndex
=
if
(
i
==
0
)
2.
U
*
intExuIndex
(
0
)
else
if
(
i
>
4
)
2.
U
*
intExuIndex
(
i
-
4
)
else
(
2
*
(
i
-
1
)).
U
val
startIndex
=
regfileRPGen
.
io
.
intIQRfSrc
(
i
)
enq
.
bits
.
src1State
:=
io
.
intPregRdy
(
startIndex
)
enq
.
bits
.
src2State
:=
io
.
intPregRdy
(
startIndex
+
1.
U
)
}
else
if
(
i
<
exuConfig
.
IntExuCnt
+
exuConfig
.
FpExuCnt
)
{
val
startIndex
=
if
(
i
<
exuConfig
.
IntExuCnt
+
4
)
(
3
*
(
i
-
exuConfig
.
IntExuCnt
)).
U
else
3.
U
*
fpExuIndex
(
i
-
exuConfig
.
IntExuCnt
-
4
)
else
if
(
i
<
exuParameters
.
IntExuCnt
+
exuParameters
.
FpExuCnt
)
{
val
startIndex
=
regfileRPGen
.
io
.
fpIQRfSrc
(
i
-
exuParameters
.
IntExuCnt
)
enq
.
valid
:=
!
instIdxes
(
i
)(
2
)
&&
io
.
fromFpDq
(
instIdxes
(
i
)(
1
,
0
)).
valid
enq
.
bits
:=
io
.
fromFpDq
(
instIdxes
(
i
)(
1
,
0
)).
bits
enq
.
bits
.
src1State
:=
io
.
fpPregRdy
(
startIndex
)
...
...
@@ -167,11 +101,17 @@ class Dispatch2 extends XSModule {
enq
.
bits
.
src3State
:=
io
.
fpPregRdy
(
startIndex
+
2.
U
)
}
else
{
// TODO: load store with fp
val
startIndex
=
regfileRPGen
.
io
.
lsIQRfSrc
(
i
-
exuParameters
.
IntExuCnt
-
exuParameters
.
FpExuCnt
)
enq
.
valid
:=
!
instIdxes
(
i
)(
2
)
&&
io
.
fromLsDq
(
instIdxes
(
i
)(
1
,
0
)).
valid
enq
.
bits
:=
io
.
fromLsDq
(
instIdxes
(
i
)(
1
,
0
)).
bits
// TODO load and store
enq
.
bits
.
src1State
:=
io
.
intPregRdy
(
10
)
enq
.
bits
.
src2State
:=
io
.
intPregRdy
(
11
)
if
(
i
<
exuParameters
.
IntExuCnt
+
exuParameters
.
FpExuCnt
+
exuParameters
.
LduCnt
)
{
enq
.
bits
.
src1State
:=
io
.
intPregRdy
(
startIndex
)
}
else
{
enq
.
bits
.
src1State
:=
io
.
intPregRdy
(
startIndex
)
enq
.
bits
.
src2State
:=
io
.
intPregRdy
(
startIndex
+
1.
U
)
}
}
XSInfo
(
enq
.
fire
(),
"pc 0x%x with type %b srcState(%d %d %d) enters reservation station %d from %d\n"
,
...
...
@@ -181,7 +121,7 @@ class Dispatch2 extends XSModule {
// responds to dispatch queue
for
(
i
<-
0
until
IntDqDeqWidth
)
{
io
.
fromIntDq
(
i
).
ready
:=
(
io
.
enqIQCtrl
.
zipWithIndex
map
{
case
(
rs
,
j
)
=>
(
rs
.
ready
&&
instIdxes
(
j
)
===
i
.
U
&&
(
j
<
exu
Config
.
IntExuCnt
).
asBool
())
(
rs
.
ready
&&
instIdxes
(
j
)
===
i
.
U
&&
(
j
<
exu
Parameters
.
IntExuCnt
).
asBool
())
}).
reduce
((
l
,
r
)
=>
l
||
r
)
XSInfo
(
io
.
fromIntDq
(
i
).
fire
(),
"pc 0x%x leaves Int dispatch queue with nroq %d\n"
,
io
.
fromIntDq
(
i
).
bits
.
cf
.
pc
,
io
.
fromIntDq
(
i
).
bits
.
roqIdx
)
...
...
@@ -192,7 +132,7 @@ class Dispatch2 extends XSModule {
for
(
i
<-
0
until
FpDqDeqWidth
)
{
io
.
fromFpDq
(
i
).
ready
:=
(
io
.
enqIQCtrl
.
zipWithIndex
map
{
case
(
rs
,
j
)
=>
(
rs
.
ready
&&
instIdxes
(
j
)
===
i
.
U
&&
(
j
>=
exu
Config
.
IntExuCnt
&&
j
<
exuConfig
.
IntExuCnt
+
exuConfig
.
FpExuCnt
).
asBool
())
&&
(
j
>=
exu
Parameters
.
IntExuCnt
&&
j
<
exuParameters
.
IntExuCnt
+
exuParameters
.
FpExuCnt
).
asBool
())
}).
reduce
((
l
,
r
)
=>
l
||
r
)
XSInfo
(
io
.
fromFpDq
(
i
).
fire
(),
"pc 0x%x leaves Fp dispatch queue with nroq %d\n"
,
io
.
fromFpDq
(
i
).
bits
.
cf
.
pc
,
io
.
fromFpDq
(
i
).
bits
.
roqIdx
)
...
...
@@ -202,8 +142,8 @@ class Dispatch2 extends XSModule {
}
for
(
i
<-
0
until
LsDqDeqWidth
)
{
io
.
fromLsDq
(
i
).
ready
:=
(
io
.
enqIQCtrl
.
zipWithIndex
map
{
case
(
rs
,
j
)
=>
(
rs
.
ready
&&
0.
U
===
i
.
U
&&
(
j
>=
exu
Config
.
IntExuCnt
+
exuConfig
.
FpExuCnt
).
asBool
())
(
rs
.
ready
&&
instIdxes
(
j
)
===
i
.
U
&&
(
j
>=
exu
Parameters
.
IntExuCnt
+
exuParameters
.
FpExuCnt
).
asBool
())
}).
reduce
((
l
,
r
)
=>
l
||
r
)
XSInfo
(
io
.
fromLsDq
(
i
).
fire
(),
"pc 0x%x leaves Ls dispatch queue with nroq %d\n"
,
io
.
fromLsDq
(
i
).
bits
.
cf
.
pc
,
io
.
fromLsDq
(
i
).
bits
.
roqIdx
)
...
...
@@ -213,24 +153,24 @@ class Dispatch2 extends XSModule {
}
// TODO: store needs data from FpRegfile
val
intExuIndexReg
=
Reg
(
Vec
(
3
,
UInt
(
2.
W
)))
val
fpExuIndexReg
=
Reg
(
Vec
(
2
,
UInt
(
2.
W
)))
(
0
until
3
).
map
(
i
=>
intExuIndexReg
(
i
)
:=
intExuIndex
(
i
))
(
0
until
2
).
map
(
i
=>
fpExuIndexReg
(
i
)
:=
fpExuIndex
(
i
))
val
intExuIndexReg
=
Reg
(
Vec
(
exuParameters
.
IntExuCnt
,
UInt
(
log2Ceil
(
NRReadPorts
).
W
)))
val
fpExuIndexReg
=
Reg
(
Vec
(
exuParameters
.
FpExuCnt
,
UInt
(
log2Ceil
(
NRReadPorts
).
W
)))
val
lsExuIndexReg
=
Reg
(
Vec
(
exuParameters
.
LduCnt
+
exuParameters
.
StuCnt
,
UInt
(
log2Ceil
(
NRReadPorts
).
W
)))
(
0
until
exuParameters
.
IntExuCnt
).
map
(
i
=>
intExuIndexReg
(
i
)
:=
regfileRPGen
.
io
.
intIQRfSrc
(
i
))
(
0
until
exuParameters
.
FpExuCnt
).
map
(
i
=>
fpExuIndexReg
(
i
)
:=
regfileRPGen
.
io
.
fpIQRfSrc
(
i
))
(
0
until
exuParameters
.
LsExuCnt
).
map
(
i
=>
lsExuIndexReg
(
i
)
:=
regfileRPGen
.
io
.
lsIQRfSrc
(
i
))
// TODO: remove uop when reservation stations deal with imme
val
uop_reg
=
Reg
(
Vec
(
exu
Config
.
ExuCnt
,
new
MicroOp
))
val
data_valid
=
Reg
(
Vec
(
exu
Config
.
ExuCnt
,
Bool
()))
for
(
i
<-
0
until
exu
Config
.
ExuCnt
)
{
val
uop_reg
=
Reg
(
Vec
(
exu
Parameters
.
ExuCnt
,
new
MicroOp
))
val
data_valid
=
Reg
(
Vec
(
exu
Parameters
.
ExuCnt
,
Bool
()))
for
(
i
<-
0
until
exu
Parameters
.
ExuCnt
)
{
data_valid
(
i
)
:=
io
.
enqIQCtrl
(
i
).
fire
()
uop_reg
(
i
)
:=
io
.
enqIQCtrl
(
i
).
bits
io
.
enqIQData
(
i
).
valid
:=
DontCare
io
.
enqIQData
(
i
).
bits
:=
DontCare
val
srcIndex
=
Wire
(
Vec
(
3
,
UInt
(
4.
W
)))
if
(
i
<
exuConfig
.
IntExuCnt
)
{
val
startIndex
=
if
(
i
==
0
)
2.
U
*
intExuIndexReg
(
0
)
else
if
(
i
>
4
)
2.
U
*
intExuIndexReg
(
i
-
4
)
else
(
2
*
(
i
-
1
)).
U
if
(
i
<
exuParameters
.
IntExuCnt
)
{
val
startIndex
=
intExuIndexReg
(
i
)
io
.
enqIQData
(
i
).
bits
.
src1
:=
Mux
(
uop_reg
(
i
).
ctrl
.
src1Type
===
SrcType
.
pc
,
uop_reg
(
i
).
cf
.
pc
,
io
.
readIntRf
(
startIndex
).
data
)
io
.
enqIQData
(
i
).
bits
.
src2
:=
Mux
(
uop_reg
(
i
).
ctrl
.
src2Type
===
SrcType
.
imm
,
...
...
@@ -239,9 +179,8 @@ class Dispatch2 extends XSModule {
srcIndex
(
1
)
:=
startIndex
+
1.
U
srcIndex
(
2
)
:=
0.
U
}
else
if
(
i
<
exuConfig
.
IntExuCnt
+
exuConfig
.
FpExuCnt
)
{
val
startIndex
=
if
(
i
<
exuConfig
.
IntExuCnt
+
4
)
(
3
*
(
i
-
exuConfig
.
IntExuCnt
)).
U
else
3.
U
*
fpExuIndexReg
(
i
-
exuConfig
.
IntExuCnt
-
4
)
else
if
(
i
<
exuParameters
.
IntExuCnt
+
exuParameters
.
FpExuCnt
)
{
val
startIndex
=
fpExuIndexReg
(
i
-
exuParameters
.
IntExuCnt
)
io
.
enqIQData
(
i
).
bits
.
src1
:=
io
.
readFpRf
(
startIndex
).
data
io
.
enqIQData
(
i
).
bits
.
src2
:=
io
.
readFpRf
(
startIndex
+
1.
U
).
data
io
.
enqIQData
(
i
).
bits
.
src3
:=
io
.
readFpRf
(
startIndex
+
2.
U
).
data
...
...
@@ -250,12 +189,13 @@ class Dispatch2 extends XSModule {
srcIndex
(
2
)
:=
startIndex
+
2.
U
}
else
{
val
startIndex
=
lsExuIndexReg
(
i
-
exuParameters
.
IntExuCnt
-
exuParameters
.
FpExuCnt
)
io
.
enqIQData
(
i
).
bits
.
src1
:=
Mux
(
uop_reg
(
i
).
ctrl
.
src1Type
===
SrcType
.
pc
,
uop_reg
(
i
).
cf
.
pc
,
io
.
readIntRf
(
10
).
data
)
uop_reg
(
i
).
cf
.
pc
,
io
.
readIntRf
(
startIndex
).
data
)
io
.
enqIQData
(
i
).
bits
.
src2
:=
Mux
(
uop_reg
(
i
).
ctrl
.
src2Type
===
SrcType
.
imm
,
uop_reg
(
i
).
ctrl
.
imm
,
io
.
readIntRf
(
11
).
data
)
srcIndex
(
0
)
:=
10.
U
srcIndex
(
1
)
:=
1
1.
U
uop_reg
(
i
).
ctrl
.
imm
,
io
.
readIntRf
(
startIndex
+
1.
U
).
data
)
srcIndex
(
0
)
:=
startIndex
srcIndex
(
1
)
:=
startIndex
+
1.
U
srcIndex
(
2
)
:=
0.
U
}
...
...
src/main/scala/xiangshan/backend/dispatch/DispatchGen.scala
0 → 100644
浏览文件 @
706f729c
package
xiangshan.backend.dispatch
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.utils.
{
XSDebug
}
class
DispatchGen
extends
XSModule
{
val
io
=
IO
(
new
Bundle
()
{
// from dispatch queues
val
fromIntDq
=
Flipped
(
Vec
(
IntDqDeqWidth
,
ValidIO
(
new
MicroOp
)))
val
fromFpDq
=
Flipped
(
Vec
(
FpDqDeqWidth
,
ValidIO
(
new
MicroOp
)))
val
fromLsDq
=
Flipped
(
Vec
(
LsDqDeqWidth
,
ValidIO
(
new
MicroOp
)))
// enq Issue Queue
val
numExist
=
Input
(
Vec
(
exuParameters
.
ExuCnt
,
UInt
(
log2Ceil
(
IssQueSize
).
W
)))
val
enqIQIndex
=
Vec
(
exuParameters
.
ExuCnt
,
ValidIO
(
UInt
(
log2Ceil
(
IntDqDeqWidth
).
W
)))
})
assert
(
IntDqDeqWidth
>=
FpDqDeqWidth
)
assert
(
IntDqDeqWidth
>=
LsDqDeqWidth
)
def
PriorityGen
(
numExist
:
Seq
[
UInt
])
=
{
assert
(
numExist
.
length
>
1
)
val
sortedIndex
=
Wire
(
Vec
(
numExist
.
length
,
UInt
(
log2Ceil
(
numExist
.
length
).
W
)))
val
priority
=
WireInit
(
VecInit
(
Seq
.
tabulate
(
numExist
.
length
)(
i
=>
0.
U
(
log2Ceil
(
numExist
.
length
).
W
))))
for
(
i
<-
0
until
numExist
.
length
)
{
sortedIndex
(
i
)
:=
PriorityEncoder
((
0
until
numExist
.
length
).
map
(
each
=>
{
// itself should not be found yet
val
equalPrevious
=
(
if
(
i
==
0
)
false
.
B
else
Cat
((
0
until
i
).
map
(
l
=>
each
.
U
===
sortedIndex
(
l
))).
orR
())
val
largerThanAnyOther
=
Cat
((
0
until
numExist
.
length
).
map
(
another
=>
{
// no need to be compared with the larger ones
val
anotherEqualPrevious
=
(
if
(
i
==
0
)
false
.
B
else
Cat
((
0
until
i
).
map
(
l
=>
another
.
U
===
sortedIndex
(
l
))).
orR
())
// need to be no smaller than any other numbers except the previoud found larger ones
(
numExist
(
each
)
<=
numExist
(
another
))
||
anotherEqualPrevious
})).
andR
()
largerThanAnyOther
&&
!
equalPrevious
}))
priority
(
sortedIndex
(
i
))
:=
i
.
U
}
for
(
i
<-
0
until
numExist
.
length
)
{
XSDebug
(
p
"priority: data($i) = ${numExist(i)}, priority = ${priority(i)}\n"
)
}
priority
}
def
genIQIndex
(
exunum
:
Int
,
deqnum
:
Int
,
deq
:
Seq
[
Bool
],
numExist
:
Seq
[
UInt
])
=
{
assert
(
isPow2
(
deqnum
))
assert
(
exunum
==
numExist
.
length
)
// index without priority
val
IQIndex
=
Wire
(
Vec
(
exunum
,
UInt
((
log2Ceil
(
deqnum
)
+
1
).
W
)))
var
last_deq
=
deq
for
(
i
<-
0
until
exunum
)
{
IQIndex
(
i
)
:=
PriorityEncoder
(
last_deq
:+
true
.
B
)
val
onehot
=
UIntToOH
(
IQIndex
(
i
))
last_deq
=
(
0
until
deqnum
).
map
(
i
=>
!
onehot
(
i
)
&&
last_deq
(
i
))
}
// now consider the IQ priority with numExist
val
priority
=
(
if
(
numExist
.
length
>
1
)
PriorityGen
(
numExist
)
else
Seq
(
0.
U
))
(
0
until
exunum
).
map
(
i
=>
IQIndex
(
priority
(
i
)))
}
val
bruIQIndex
=
genIQIndex
(
exuParameters
.
JmpCnt
,
IntDqDeqWidth
,
io
.
fromIntDq
.
map
(
_
.
bits
.
ctrl
.
fuType
===
FuType
.
jmp
),
(
0
until
exuParameters
.
JmpCnt
).
map
(
i
=>
io
.
numExist
(
i
)))
val
aluIQIndex
=
genIQIndex
(
exuParameters
.
AluCnt
,
IntDqDeqWidth
,
io
.
fromIntDq
.
map
(
_
.
bits
.
ctrl
.
fuType
===
FuType
.
alu
),
(
0
until
exuParameters
.
AluCnt
).
map
(
i
=>
io
.
numExist
(
exuParameters
.
JmpCnt
+
i
)))
val
mulIQIndex
=
genIQIndex
(
exuParameters
.
MulCnt
,
IntDqDeqWidth
,
io
.
fromIntDq
.
map
(
_
.
bits
.
ctrl
.
fuType
===
FuType
.
mul
),
(
0
until
exuParameters
.
MulCnt
).
map
(
i
=>
io
.
numExist
(
exuParameters
.
JmpCnt
+
exuParameters
.
AluCnt
+
i
)))
val
muldivIQIndex
=
genIQIndex
(
exuParameters
.
MduCnt
,
IntDqDeqWidth
,
io
.
fromIntDq
.
map
(
_
.
bits
.
ctrl
.
fuType
===
FuType
.
div
),
(
0
until
exuParameters
.
MduCnt
).
map
(
i
=>
io
.
numExist
(
exuParameters
.
JmpCnt
+
exuParameters
.
AluCnt
+
exuParameters
.
MulCnt
+
i
)))
val
fmacIQIndex
=
genIQIndex
(
exuParameters
.
FmacCnt
,
FpDqDeqWidth
,
io
.
fromFpDq
.
map
(
_
.
bits
.
ctrl
.
fuType
===
FuType
.
fmac
),
(
0
until
exuParameters
.
FmacCnt
).
map
(
i
=>
io
.
numExist
(
exuParameters
.
IntExuCnt
+
i
)))
val
fmiscIQIndex
=
genIQIndex
(
exuParameters
.
FmiscCnt
,
FpDqDeqWidth
,
io
.
fromFpDq
.
map
(
_
.
bits
.
ctrl
.
fuType
===
FuType
.
fmisc
),
(
0
until
exuParameters
.
FmiscCnt
).
map
(
i
=>
io
.
numExist
(
exuParameters
.
IntExuCnt
+
exuParameters
.
FmacCnt
+
i
)))
val
lduIQIndex
=
genIQIndex
(
exuParameters
.
LduCnt
,
LsDqDeqWidth
,
io
.
fromLsDq
.
map
(
_
.
bits
.
ctrl
.
fuType
===
FuType
.
ldu
),
(
0
until
exuParameters
.
LduCnt
).
map
(
i
=>
io
.
numExist
(
exuParameters
.
IntExuCnt
+
exuParameters
.
FpExuCnt
+
i
)))
// val stuIQIndex = genIQIndex(exuParameters.StuCnt, LsDqDeqWidth, io.fromLsDq.map(_.bits.ctrl.fuType === FuType.stu))
val
stuIQIndex
=
genIQIndex
(
exuParameters
.
StuCnt
,
LsDqDeqWidth
,
io
.
fromLsDq
.
map
(
deq
=>
FuType
.
isMemExu
(
deq
.
bits
.
ctrl
.
fuType
)),
(
0
until
exuParameters
.
StuCnt
).
map
(
i
=>
io
.
numExist
(
exuParameters
.
IntExuCnt
+
exuParameters
.
FpExuCnt
+
exuParameters
.
LduCnt
+
i
)))
val
allIndex
=
Seq
(
bruIQIndex
,
aluIQIndex
,
mulIQIndex
,
muldivIQIndex
,
fmacIQIndex
,
fmiscIQIndex
,
lduIQIndex
,
stuIQIndex
)
val
allCnt
=
Seq
(
exuParameters
.
JmpCnt
,
exuParameters
.
AluCnt
,
exuParameters
.
MulCnt
,
exuParameters
.
MduCnt
,
exuParameters
.
FmacCnt
,
exuParameters
.
FmiscCnt
,
exuParameters
.
LduCnt
,
exuParameters
.
StuCnt
)
assert
(
allIndex
.
length
==
allCnt
.
length
)
var
startIndex
=
0
for
(
i
<-
0
until
allIndex
.
length
)
{
for
(
j
<-
0
until
allCnt
(
i
))
{
io
.
enqIQIndex
(
startIndex
+
j
).
valid
:=
!
allIndex
(
i
)(
j
)(
2
)
io
.
enqIQIndex
(
startIndex
+
j
).
bits
:=
allIndex
(
i
)(
j
)(
1
,
0
)
}
startIndex
+=
allCnt
(
i
)
}
}
src/main/scala/xiangshan/backend/dispatch/RegfileReadPortGen.scala
0 → 100644
浏览文件 @
706f729c
package
xiangshan.backend.dispatch
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.utils.
{
XSDebug
}
class
RegfileReadPortGen
extends
XSModule
{
val
io
=
IO
(
new
Bundle
()
{
// from dispatch queues
val
intIQEnqIndex
=
Flipped
(
Vec
(
exuParameters
.
IntExuCnt
,
ValidIO
(
UInt
(
log2Ceil
(
IntDqDeqWidth
).
W
))))
val
fpIQEnqIndex
=
Flipped
(
Vec
(
exuParameters
.
FpExuCnt
,
ValidIO
(
UInt
(
log2Ceil
(
FpDqDeqWidth
).
W
))))
val
lsIQEnqIndex
=
Flipped
(
Vec
(
exuParameters
.
LduCnt
+
exuParameters
.
StuCnt
,
ValidIO
(
UInt
(
log2Ceil
(
LsDqDeqWidth
).
W
))))
// chooses dispatch queue dequeue indexs for regfile read ports
val
readIntRf
=
Output
(
Vec
(
NRReadPorts
,
UInt
(
log2Ceil
(
IntDqDeqWidth
).
W
)))
val
readFpRf
=
Output
(
Vec
(
NRReadPorts
,
UInt
(
log2Ceil
(
IntDqDeqWidth
).
W
)))
// chooses regfile read ports for reservation stations
val
intIQRfSrc
=
Output
(
Vec
(
exuParameters
.
IntExuCnt
,
UInt
(
log2Ceil
(
NRReadPorts
).
W
)))
val
fpIQRfSrc
=
Output
(
Vec
(
exuParameters
.
FpExuCnt
,
UInt
(
log2Ceil
(
NRReadPorts
).
W
)))
val
lsIQRfSrc
=
Output
(
Vec
(
exuParameters
.
LsExuCnt
,
UInt
(
log2Ceil
(
NRReadPorts
).
W
)))
})
def
RegfileReadPortArbiter
(
staticMappedValid
:
Seq
[
Bool
],
dynamicMappedValid
:
Seq
[
Bool
])
=
{
val
choiceCount
=
dynamicMappedValid
.
length
+
1
// read port is assigned to readPortSrc
val
readPortSrc
=
Wire
(
Vec
(
staticMappedValid
.
length
,
UInt
(
log2Ceil
(
choiceCount
).
W
)))
var
hasAssigned
=
(
0
until
choiceCount
).
map
(
_
=>
false
.
B
)
for
(
i
<-
0
until
staticMappedValid
.
length
)
{
val
valid
=
staticMappedValid
(
i
)
+:
dynamicMappedValid
val
wantReadPort
=
(
0
until
choiceCount
).
map
(
j
=>
valid
(
j
)
&&
((
j
==
0
).
asBool
()
||
!
hasAssigned
(
j
)))
readPortSrc
(
i
)
:=
PriorityEncoder
(
wantReadPort
)
val
onehot
=
UIntToOH
(
readPortSrc
(
i
))
hasAssigned
=
(
0
until
choiceCount
).
map
(
i
=>
hasAssigned
(
i
)
||
onehot
(
i
))
XSDebug
(
"int %d: want %b, deqChoice: %d\n"
,
i
.
U
,
Cat
(
wantReadPort
),
readPortSrc
(
i
))
}
val
dynamicExuSrc
=
Wire
(
Vec
(
dynamicMappedValid
.
length
,
UInt
(
log2Ceil
(
staticMappedValid
.
length
).
W
)))
for
(
i
<-
0
until
dynamicMappedValid
.
length
)
{
val
targetMatch
=
(
0
until
staticMappedValid
.
length
).
map
(
j
=>
readPortSrc
(
j
)
===
(
i
+
1
).
U
)
dynamicExuSrc
(
i
)
:=
PriorityEncoder
(
targetMatch
)
XSDebug
(
p
"dynamicExuSrc $i: ${dynamicExuSrc(i)} ${Binary(Cat(targetMatch))}\n"
)
}
(
readPortSrc
,
dynamicExuSrc
)
}
val
intStaticIndex
=
Seq
(
1
,
2
,
3
,
4
)
val
intDynamicIndex
=
Seq
(
0
,
5
,
6
)
val
intStaticMappedValid
=
intStaticIndex
.
map
(
i
=>
io
.
intIQEnqIndex
(
i
).
valid
)
val
intDynamicMappedValid
=
intDynamicIndex
.
map
(
i
=>
io
.
intIQEnqIndex
(
i
).
valid
)
val
(
intReadPortSrc
,
intDynamicExuSrc
)
=
RegfileReadPortArbiter
(
intStaticMappedValid
,
intDynamicMappedValid
)
val
intStaticMapped
=
intStaticIndex
.
map
(
i
=>
io
.
intIQEnqIndex
(
i
).
bits
)
val
intDynamicMapped
=
intDynamicIndex
.
map
(
i
=>
io
.
intIQEnqIndex
(
i
).
bits
)
for
(
i
<-
0
until
intStaticIndex
.
length
)
{
val
index
=
WireInit
(
VecInit
(
intStaticMapped
(
i
)
+:
intDynamicMapped
))
io
.
readIntRf
(
2
*
i
)
:=
index
(
intReadPortSrc
(
i
))
io
.
readIntRf
(
2
*
i
+
1
)
:=
index
(
intReadPortSrc
(
i
))
}
intStaticIndex
.
zipWithIndex
.
map
({
case
(
index
,
i
)
=>
io
.
intIQRfSrc
(
index
)
:=
(
2
*
i
).
U
})
intDynamicIndex
.
zipWithIndex
.
map
({
case
(
index
,
i
)
=>
io
.
intIQRfSrc
(
index
)
:=
2.
U
*
intDynamicExuSrc
(
i
)})
if
(
exuParameters
.
FpExuCnt
>
0
)
{
val
fpStaticIndex
=
0
until
exuParameters
.
FmacCnt
val
fpDynamicIndex
=
exuParameters
.
FmacCnt
until
exuParameters
.
FpExuCnt
val
fpStaticMappedValid
=
fpStaticIndex
.
map
(
i
=>
io
.
fpIQEnqIndex
(
i
).
valid
)
val
fpDynamicMappedValid
=
fpDynamicIndex
.
map
(
i
=>
io
.
fpIQEnqIndex
(
i
).
valid
)
val
(
fpReadPortSrc
,
fpDynamicExuSrc
)
=
RegfileReadPortArbiter
(
fpStaticMappedValid
,
fpDynamicMappedValid
)
val
fpStaticMapped
=
fpStaticIndex
.
map
(
i
=>
io
.
fpIQEnqIndex
(
i
).
bits
)
val
fpDynamicMapped
=
fpDynamicIndex
.
map
(
i
=>
io
.
fpIQEnqIndex
(
i
).
bits
)
for
(
i
<-
0
until
fpStaticIndex
.
length
)
{
val
index
=
WireInit
(
VecInit
(
fpStaticMapped
(
i
)
+:
fpDynamicMapped
))
io
.
readFpRf
(
i
)
:=
index
(
fpReadPortSrc
(
i
))
io
.
fpIQRfSrc
(
fpStaticIndex
(
i
))
:=
(
3
*
i
).
U
}
fpDynamicIndex
.
zipWithIndex
.
map
({
case
(
index
,
i
)
=>
io
.
fpIQRfSrc
(
index
)
:=
3.
U
*
fpDynamicExuSrc
(
i
)
})
}
else
{
io
.
fpIQRfSrc
<>
DontCare
io
.
readFpRf
<>
DontCare
}
val
lsStaticIndex
=
0
until
exuParameters
.
LsExuCnt
val
lsDynamicIndex
=
0
until
0
val
lsStaticMappedValid
=
lsStaticIndex
.
map
(
i
=>
io
.
lsIQEnqIndex
(
i
).
valid
)
val
lsDynamicMappedValid
=
lsDynamicIndex
.
map
(
i
=>
io
.
lsIQEnqIndex
(
i
).
valid
)
val
(
lsReadPortSrc
,
lsDynamicExuSrc
)
=
RegfileReadPortArbiter
(
lsStaticMappedValid
,
lsDynamicMappedValid
)
val
lsStaticMapped
=
lsStaticIndex
.
map
(
i
=>
io
.
lsIQEnqIndex
(
i
).
bits
)
val
lsDynamicMapped
=
lsDynamicIndex
.
map
(
i
=>
io
.
lsIQEnqIndex
(
i
).
bits
)
for
(
i
<-
0
until
lsStaticIndex
.
length
)
{
val
index
=
WireInit
(
VecInit
(
lsStaticMapped
(
i
)
+:
lsDynamicMapped
))
if
(
i
<
exuParameters
.
LduCnt
)
{
val
start
=
intStaticIndex
.
length
*
2
io
.
readIntRf
(
start
+
i
)
:=
index
(
lsReadPortSrc
(
i
))
io
.
lsIQRfSrc
(
lsStaticIndex
(
i
))
:=
(
start
+
i
).
U
}
else
{
val
start
=
intStaticIndex
.
length
*
2
+
exuParameters
.
LduCnt
io
.
readIntRf
(
start
+
2
*
i
)
:=
index
(
lsReadPortSrc
(
i
))
io
.
readIntRf
(
start
+
2
*
i
+
1
)
:=
index
(
lsReadPortSrc
(
i
))
io
.
lsIQRfSrc
(
lsStaticIndex
(
i
))
:=
(
start
+
2
*
i
).
U
}
}
assert
(
lsDynamicIndex
.
length
==
0
)
val
usedPorts
=
intStaticIndex
.
length
*
2
+
exuParameters
.
LduCnt
+
exuParameters
.
StuCnt
*
2
for
(
i
<-
usedPorts
until
NRReadPorts
)
{
io
.
readIntRf
(
i
)
:=
DontCare
}
}
src/main/scala/xiangshan/backend/exu/Alu.scala
→
src/main/scala/xiangshan/backend/exu/Alu
ExeUnit
.scala
浏览文件 @
706f729c
...
...
@@ -6,9 +6,10 @@ import xiangshan._
import
xiangshan.FuType._
import
xiangshan.utils._
import
xiangshan.backend._
import
xiangshan.backend.fu.FunctionUnit._
class
Alu
extends
Exu
(
alu
.
litValue
(),
hasRedirect
=
true
)
{
override
def
toString
:
String
=
"Alu"
class
AluExeUnit
extends
Exu
(
Exu
.
aluExeUnitCfg
)
{
val
(
iovalid
,
src1
,
src2
,
offset
,
func
,
pc
,
uop
)
=
(
io
.
in
.
valid
,
io
.
in
.
bits
.
src1
,
io
.
in
.
bits
.
src2
,
io
.
in
.
bits
.
uop
.
ctrl
.
imm
,
io
.
in
.
bits
.
uop
.
ctrl
.
fuOpType
,
SignExt
(
io
.
in
.
bits
.
uop
.
cf
.
pc
,
AddrBits
),
io
.
in
.
bits
.
uop
)
...
...
src/main/scala/xiangshan/backend/exu/DivExeUnit.scala
0 → 100644
浏览文件 @
706f729c
package
xiangshan.backend.exu
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
utils._
import
xiangshan.backend.fu.Divider
import
xiangshan.backend.MDUOpType
class
DivExeUnit
extends
Exu
(
Exu
.
divExeUnitCfg
)
{
val
(
src1
,
src2
,
uop
,
func
)
=
(
io
.
in
.
bits
.
src1
,
io
.
in
.
bits
.
src2
,
io
.
in
.
bits
.
uop
,
io
.
in
.
bits
.
uop
.
ctrl
.
fuOpType
)
val
divider
=
Module
(
new
Divider
(
XLEN
))
val
isDiv
=
MDUOpType
.
isDiv
(
func
)
val
isDivSign
=
MDUOpType
.
isDivSign
(
func
)
val
isW
=
MDUOpType
.
isW
(
func
)
val
divInputFunc
=
(
x
:
UInt
)
=>
Mux
(
isW
,
Mux
(
isDivSign
,
SignExt
(
x
(
31
,
0
),
XLEN
),
ZeroExt
(
x
(
31
,
0
),
XLEN
)
),
x
)
divider
.
io
.
redirect
:=
io
.
redirect
divider
.
io
.
in
.
valid
:=
io
.
in
.
valid
divider
.
io
.
in
.
bits
.
ctrl
.
uop
:=
io
.
in
.
bits
.
uop
divider
.
io
.
in
.
bits
.
ctrl
.
sign
:=
isDivSign
divider
.
io
.
in
.
bits
.
ctrl
.
isW
:=
isW
divider
.
io
.
in
.
bits
.
ctrl
.
isHi
:=
func
(
1
)
divider
.
io
.
in
.
bits
.
src1
:=
divInputFunc
(
src1
)
divider
.
io
.
in
.
bits
.
src2
:=
divInputFunc
(
src2
)
divider
.
io
.
out
.
ready
:=
io
.
out
.
ready
io
.
in
.
ready
:=
divider
.
io
.
in
.
ready
io
.
out
.
valid
:=
divider
.
io
.
out
.
valid
io
.
out
.
bits
.
uop
:=
divider
.
io
.
out
.
bits
.
uop
io
.
out
.
bits
.
data
:=
divider
.
io
.
out
.
bits
.
data
io
.
out
.
bits
.
redirectValid
:=
false
.
B
io
.
out
.
bits
.
redirect
<>
DontCare
io
.
dmem
<>
DontCare
io
.
out
.
bits
.
debug
<>
DontCare
XSDebug
(
io
.
in
.
valid
,
"In(%d %d) Out(%d %d) Redirect:(%d %d) brTag:%x\n"
,
io
.
in
.
valid
,
io
.
in
.
ready
,
io
.
out
.
valid
,
io
.
out
.
ready
,
io
.
redirect
.
valid
,
io
.
redirect
.
bits
.
isException
,
io
.
redirect
.
bits
.
brTag
.
value
)
XSDebug
(
io
.
in
.
valid
,
"src1:%x src2:%x pc:%x\n"
,
src1
,
src2
,
io
.
in
.
bits
.
uop
.
cf
.
pc
)
XSDebug
(
io
.
out
.
valid
,
"Out(%d %d) res:%x pc:%x\n"
,
io
.
out
.
valid
,
io
.
out
.
ready
,
io
.
out
.
bits
.
data
,
io
.
out
.
bits
.
uop
.
cf
.
pc
)
}
src/main/scala/xiangshan/backend/exu/Exu.scala
浏览文件 @
706f729c
...
...
@@ -4,11 +4,13 @@ import chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.FuType._
import
xiangshan.utils.XSInfo
import
xiangshan.backend.fu.FuConfig
import
xiangshan.utils.ParallelOR
import
xiangshan.backend.fu.FunctionUnit._
case
class
Exu
Config
case
class
Exu
Parameters
(
Bru
Cnt
:
Int
,
Jmp
Cnt
:
Int
,
AluCnt
:
Int
,
MulCnt
:
Int
,
MduCnt
:
Int
,
...
...
@@ -18,117 +20,63 @@ case class ExuConfig
LduCnt
:
Int
,
StuCnt
:
Int
){
assert
(
BruCnt
==
1
,
"Only support 1 Bru
now!"
)
def
IntExuCnt
=
AluCnt
+
MulCnt
+
MduCnt
+
Bru
Cnt
assert
(
JmpCnt
==
1
,
"Only support 1 JmpUnit
now!"
)
def
IntExuCnt
=
AluCnt
+
MulCnt
+
MduCnt
+
Jmp
Cnt
def
FpExuCnt
=
FmacCnt
+
FmiscCnt
+
FmiscDivSqrtCnt
def
ExuCnt
=
IntExuCnt
+
FpExuCnt
+
LduCnt
def
LsExuCnt
=
LduCnt
+
StuCnt
def
ExuCnt
=
IntExuCnt
+
FpExuCnt
+
LduCnt
+
StuCnt
def
NRFuType
=
9
def
FuOpWidth
=
7
}
abstract
class
Exu
case
class
ExuConfig
(
val
fuTypeInt
:
BigInt
,
val
readIntRf
:
Boolean
=
true
,
val
readFpRf
:
Boolean
=
false
,
val
writeIntRf
:
Boolean
=
true
,
val
writeFpRf
:
Boolean
=
false
,
val
enableBypass
:
Boolean
=
false
,
// join bypass group or not, require readIntRf & writeIntRf now
val
fixedDelay
:
Int
=
1
,
// IssueQueue's selectUop's delay
val
hasRedirect
:
Boolean
=
false
)
extends
XSModule
{
name
:
String
,
supportedFuncUnits
:
Array
[
FuConfig
],
enableBypass
:
Boolean
){
def
max
(
in
:
Seq
[
Int
])
:
Int
=
in
.
reduce
((
x
,
y
)
=>
if
(
x
>
y
)
x
else
y
)
val
intSrcCnt
=
max
(
supportedFuncUnits
.
map
(
_
.
numIntSrc
))
val
fpSrcCnt
=
max
(
supportedFuncUnits
.
map
(
_
.
numFpSrc
))
val
readIntRf
=
intSrcCnt
>
0
val
readFpRf
=
fpSrcCnt
>
0
val
writeIntRf
=
supportedFuncUnits
.
map
(
_
.
writeIntRf
).
reduce
(
_
||
_
)
val
writeFpRf
=
supportedFuncUnits
.
map
(
_
.
writeFpRf
).
reduce
(
_
||
_
)
val
hasRedirect
=
supportedFuncUnits
.
map
(
_
.
hasRedirect
).
reduce
(
_
||
_
)
def
canAccept
(
fuType
:
UInt
)
:
Bool
=
{
ParallelOR
(
supportedFuncUnits
.
map
(
_
.
fuType
===
fuType
)).
asBool
()
}
}
abstract
class
Exu
(
val
config
:
ExuConfig
)
extends
XSModule
{
val
io
=
IO
(
new
ExuIO
)
io
.
dmem
<>
DontCare
io
.
out
.
bits
.
debug
.
isMMIO
:=
false
.
B
}
class
Fmac
extends
Exu
(
FuType
.
fmac
.
litValue
(),
readIntRf
=
false
,
readFpRf
=
true
,
writeIntRf
=
false
,
writeFpRf
=
true
)
with
NeedImpl
{
override
def
toString
:
String
=
"Fmac"
object
Exu
{
val
jmpExeUnitCfg
=
ExuConfig
(
"JmpExu"
,
Array
(
jmpCfg
,
i2fCfg
),
enableBypass
=
false
)
val
aluExeUnitCfg
=
ExuConfig
(
"AluExu"
,
Array
(
aluCfg
),
enableBypass
=
false
)
val
mulExeUnitCfg
=
ExuConfig
(
"MulExu"
,
Array
(
mulCfg
),
enableBypass
=
false
)
val
divExeUnitCfg
=
ExuConfig
(
"DivExu"
,
Array
(
divCfg
),
enableBypass
=
false
)
val
mulDivExeUnitCfg
=
ExuConfig
(
"MulDivExu"
,
Array
(
mulCfg
,
divCfg
),
enableBypass
=
false
)
val
lsuExeUnitCfg
=
ExuConfig
(
"LsExu"
,
Array
(
lsuCfg
),
enableBypass
=
false
)
}
class
Fmisc
extends
Exu
(
FuType
.
fmisc
.
litValue
(),
readIntRf
=
false
,
readFpRf
=
true
,
writeIntRf
=
true
,
writeFpRf
=
true
)
with
NeedImpl
{
override
def
toString
:
String
=
"Fmisc"
}
class
FmiscDivSqrt
extends
Exu
(
FuType
.
fmiscDivSqrt
.
litValue
(),
readIntRf
=
false
,
readFpRf
=
true
,
writeIntRf
=
false
,
writeFpRf
=
true
)
with
NeedImpl
{
override
def
toString
:
String
=
"FmiscDivSqrt"
}
// class Lsu extends Exu(
// FuType.ldu.litValue(),
// readIntRf = true,
// readFpRf = true,
// writeIntRf = true,
// writeFpRf = true
// ) with NeedImpl {
// override def toString: String = "Lsu"
// }
trait
HasExeUnits
{
val
aluExeUnits
=
Array
.
tabulate
(
exu
Config
.
AluCnt
)(
_
=>
Module
(
new
Alu
))
val
bruExeUnit
=
Module
(
new
Bru
)
val
mulExeUnits
=
Array
.
tabulate
(
exu
Config
.
MulCnt
)(
_
=>
Module
(
new
Mul
))
val
mduExeUnits
=
Array
.
tabulate
(
exu
Config
.
MduCnt
)(
_
=>
Module
(
new
Mdu
))
val
fmacExeUnits
=
Array
.
tabulate
(
exuConfig
.
FmacCnt
)(
_
=>
Module
(
new
Fmac
))
val
fmiscExeUnits
=
Array
.
tabulate
(
exuConfig
.
FmiscCnt
)(
_
=>
Module
(
new
Fmisc
))
val
fmiscDivSqrtExeUnits
=
Array
.
tabulate
(
exuConfig
.
FmiscDivSqrtCnt
)(
_
=>
Module
(
new
FmiscDivSqrt
))
val
lsuExeUnits
=
Array
.
tabulate
(
exu
Config
.
LduCnt
)(
_
=>
Module
(
new
Lsu
))
val
aluExeUnits
=
Array
.
tabulate
(
exu
Parameters
.
AluCnt
)(
_
=>
Module
(
new
AluExeUnit
))
val
jmpExeUnit
=
Module
(
new
JmpExeUnit
)
val
mulExeUnits
=
Array
.
tabulate
(
exu
Parameters
.
MulCnt
)(
_
=>
Module
(
new
MulExeUnit
))
val
mduExeUnits
=
Array
.
tabulate
(
exu
Parameters
.
MduCnt
)(
_
=>
Module
(
new
MulDivExeUnit
))
// val fmacExeUnits = Array.tabulate(exuParameters
.FmacCnt)(_ => Module(new Fmac))
// val fmiscExeUnits = Array.tabulate(exuParameters
.FmiscCnt)(_ => Module(new Fmisc))
// val fmiscDivSqrtExeUnits = Array.tabulate(exuParameters
.FmiscDivSqrtCnt)(_ => Module(new FmiscDivSqrt))
val
lsuExeUnits
=
Array
.
tabulate
(
exu
Parameters
.
StuCnt
)(
_
=>
Module
(
new
LsExeUnit
))
val
exeUnits
=
bruExeUnit
+:
(
aluExeUnits
++
mulExeUnits
++
mduExeUnits
++
fmacExeUnits
++
fmiscExeUnits
++
fmiscDivSqrtExeUnits
++
lsuExeUnits
)
val
exeUnits
=
jmpExeUnit
+:
(
aluExeUnits
++
mulExeUnits
++
mduExeUnits
++
lsuExeUnits
)
exeUnits
.
foreach
(
_
.
io
.
dmem
:=
DontCare
)
exeUnits
.
foreach
(
_
.
io
.
scommit
:=
DontCare
)
}
class
WriteBackArbMtoN
(
m
:
Int
,
n
:
Int
)
extends
XSModule
{
val
io
=
IO
(
new
Bundle
()
{
val
in
=
Vec
(
m
,
Flipped
(
DecoupledIO
(
new
ExuOutput
)))
val
out
=
Vec
(
n
,
ValidIO
(
new
ExuOutput
))
})
require
(
m
>=
n
,
"m < n! Why use an arbiter???"
)
// first n-1 ports, direct connect
for
((
i
,
o
)
<-
io
.
in
.
take
(
n
-
1
).
zip
(
io
.
out
)){
o
.
valid
:=
i
.
valid
o
.
bits
:=
i
.
bits
i
.
ready
:=
true
.
B
}
// last m-(n-1) ports, rr arb
val
arb
=
Module
(
new
RRArbiter
[
ExuOutput
](
new
ExuOutput
,
m
-
n
+
1
))
for
((
arbIn
,
ioIn
)
<-
arb
.
io
.
in
.
zip
(
io
.
in
.
drop
(
n
-
1
))){
arbIn
<>
ioIn
}
io
.
out
.
last
.
bits
:=
arb
.
io
.
out
.
bits
io
.
out
.
last
.
valid
:=
arb
.
io
.
out
.
valid
arb
.
io
.
out
.
ready
:=
true
.
B
for
(
i
<-
0
until
n
)
{
XSInfo
(
io
.
out
(
i
).
valid
,
"out(%d) pc(0x%x) writebacks 0x%x to pdest(%d) ldest(%d)\n"
,
i
.
U
,
io
.
out
(
i
).
bits
.
uop
.
cf
.
pc
,
io
.
out
(
i
).
bits
.
data
,
io
.
out
(
i
).
bits
.
uop
.
pdest
,
io
.
out
(
i
).
bits
.
uop
.
ctrl
.
ldest
)
}
}
src/main/scala/xiangshan/backend/exu/
Bru
.scala
→
src/main/scala/xiangshan/backend/exu/
JmpExeUnit
.scala
浏览文件 @
706f729c
...
...
@@ -6,12 +6,13 @@ import xiangshan._
import
xiangshan.FuType._
import
xiangshan.utils._
import
xiangshan.backend.regfile.RfWritePort
import
xiangshan.backend.fu.FunctionUnit._
import
xiangshan.backend.BRUOpType
// NOTE: BRUOpType is at backend/package.scala
class
Bru
extends
Exu
(
FuType
.
bru
.
litValue
(),
writeFpRf
=
true
,
hasRedirect
=
true
)
{
override
def
toString
:
String
=
"Bru"
// TODO: add csr
class
JmpExeUnit
extends
Exu
(
Exu
.
jmpExeUnitCfg
)
{
val
(
iovalid
,
src1
,
offset
,
func
,
pc
,
uop
)
=
(
io
.
in
.
valid
,
io
.
in
.
bits
.
src1
,
io
.
in
.
bits
.
uop
.
ctrl
.
imm
,
io
.
in
.
bits
.
uop
.
ctrl
.
fuOpType
,
SignExt
(
io
.
in
.
bits
.
uop
.
cf
.
pc
,
AddrBits
),
io
.
in
.
bits
.
uop
)
...
...
src/main/scala/xiangshan/backend/exu/Ls
u
.scala
→
src/main/scala/xiangshan/backend/exu/Ls
ExeUnit
.scala
浏览文件 @
706f729c
...
...
@@ -10,39 +10,11 @@ import xiangshan.backend.regfile.RfWritePort
import
utils._
import
bus.simplebus._
import
noop.AddressSpace
import
xiangshan.backend._
import
xiangshan.backend.brq.BrqPtr
import
xiangshan.backend.fu.FunctionUnit._
object
LSUOpType
{
def
lb
=
"b000000"
.
U
def
lh
=
"b000001"
.
U
def
lw
=
"b000010"
.
U
def
ld
=
"b000011"
.
U
def
lbu
=
"b000100"
.
U
def
lhu
=
"b000101"
.
U
def
lwu
=
"b000110"
.
U
def
sb
=
"b001000"
.
U
def
sh
=
"b001001"
.
U
def
sw
=
"b001010"
.
U
def
sd
=
"b001011"
.
U
def
lr
=
"b100010"
.
U
def
sc
=
"b100011"
.
U
def
amoswap
=
"b100001"
.
U
def
amoadd
=
"b100000"
.
U
def
amoxor
=
"b100100"
.
U
def
amoand
=
"b101100"
.
U
def
amoor
=
"b101000"
.
U
def
amomin
=
"b110000"
.
U
def
amomax
=
"b110100"
.
U
def
amominu
=
"b111000"
.
U
def
amomaxu
=
"b111100"
.
U
def
isStore
(
func
:
UInt
)
:
Bool
=
func
(
3
)
def
isAtom
(
func
:
UInt
)
:
Bool
=
func
(
5
)
def
atomW
=
"010"
.
U
def
atomD
=
"011"
.
U
}
class
StoreQueueEntry
extends
XSBundle
{
val
src1
=
UInt
(
XLEN
.
W
)
...
...
@@ -56,14 +28,7 @@ class StoreQueueEntry extends XSBundle{
}
// Multi-cycle LSU ported from NOOP
class
Lsu
extends
Exu
(
FuType
.
ldu
.
litValue
(),
readIntRf
=
true
,
readFpRf
=
true
,
writeIntRf
=
true
,
writeFpRf
=
true
){
override
def
toString
:
String
=
"Lsu"
class
LsExeUnit
extends
Exu
(
Exu
.
lsuExeUnitCfg
){
// store buffer
val
stqData
=
Reg
(
Vec
(
8
,
new
StoreQueueEntry
))
...
...
src/main/scala/xiangshan/backend/exu/Mul.scala
已删除
100644 → 0
浏览文件 @
8d7419d4
package
xiangshan.backend.exu
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
utils.
{
LookupTree
,
SignExt
,
ZeroExt
,
_
}
import
xiangshan.backend.
{
MDUOpType
,
MULOpType
}
class
Mul
extends
Exu
(
FuType
.
mul
.
litValue
()){
override
def
toString
:
String
=
"Mul"
val
(
src1
,
src2
,
uop
,
func
)
=
(
io
.
in
.
bits
.
src1
,
io
.
in
.
bits
.
src2
,
io
.
in
.
bits
.
uop
,
io
.
in
.
bits
.
uop
.
ctrl
.
fuOpType
)
val
mul
=
Module
(
new
ArrayMultiplier
(
XLEN
+
1
))
val
signext
=
SignExt
(
_:
UInt
,
XLEN
+
1
)
val
zeroext
=
ZeroExt
(
_:
UInt
,
XLEN
+
1
)
val
mulInputFuncTable
=
List
(
MULOpType
.
mul
->
(
zeroext
,
zeroext
),
MULOpType
.
mulh
->
(
signext
,
signext
),
MULOpType
.
mulhsu
->
(
signext
,
zeroext
),
MULOpType
.
mulhu
->
(
zeroext
,
zeroext
)
)
val
isW
=
MDUOpType
.
isW
(
func
)
mul
.
io
.
redirect
:=
io
.
redirect
mul
.
io
.
in
.
bits
.
ctrl
.
uop
:=
io
.
in
.
bits
.
uop
mul
.
io
.
in
.
bits
.
ctrl
.
sign
:=
DontCare
//Mul don't use this
mul
.
io
.
in
.
bits
.
ctrl
.
isW
:=
isW
mul
.
io
.
in
.
bits
.
ctrl
.
isHi
:=
func
(
1
,
0
)
=/=
MDUOpType
.
mul
(
1
,
0
)
mul
.
io
.
in
.
bits
.
src1
:=
LookupTree
(
func
(
1
,
0
),
mulInputFuncTable
.
map
(
p
=>
(
p
.
_1
(
1
,
0
),
p
.
_2
.
_1
(
src1
)))
)
mul
.
io
.
in
.
bits
.
src2
:=
LookupTree
(
func
(
1
,
0
),
mulInputFuncTable
.
map
(
p
=>
(
p
.
_1
(
1
,
0
),
p
.
_2
.
_2
(
src2
)))
)
mul
.
io
.
in
.
valid
:=
io
.
in
.
valid
mul
.
io
.
out
.
ready
:=
io
.
out
.
ready
io
.
in
.
ready
:=
mul
.
io
.
in
.
ready
io
.
out
.
valid
:=
mul
.
io
.
out
.
valid
io
.
out
.
bits
.
uop
:=
mul
.
io
.
out
.
bits
.
uop
io
.
out
.
bits
.
data
:=
mul
.
io
.
out
.
bits
.
data
io
.
out
.
bits
.
redirectValid
:=
false
.
B
io
.
out
.
bits
.
redirect
<>
DontCare
XSDebug
(
io
.
in
.
valid
,
"In(%d %d) Out(%d %d) Redirect:(%d %d) brTag:%x\n"
,
io
.
in
.
valid
,
io
.
in
.
ready
,
io
.
out
.
valid
,
io
.
out
.
ready
,
io
.
redirect
.
valid
,
io
.
redirect
.
bits
.
isException
,
io
.
redirect
.
bits
.
brTag
.
value
)
XSDebug
(
io
.
in
.
valid
,
"src1:%x src2:%x pc:%x\n"
,
src1
,
src2
,
io
.
in
.
bits
.
uop
.
cf
.
pc
)
XSDebug
(
io
.
out
.
valid
,
"Out(%d %d) res:%x pc:%x\n"
,
io
.
out
.
valid
,
io
.
out
.
ready
,
io
.
out
.
bits
.
data
,
io
.
out
.
bits
.
uop
.
cf
.
pc
)
XSDebug
(
io
.
redirect
.
valid
,
p
"redirect: ${io.redirect.bits.brTag}\n"
)
}
// A wrapper of Divider
class
Div
extends
XSModule
{
val
io
=
IO
(
new
ExuIO
)
val
(
src1
,
src2
,
uop
,
func
)
=
(
io
.
in
.
bits
.
src1
,
io
.
in
.
bits
.
src2
,
io
.
in
.
bits
.
uop
,
io
.
in
.
bits
.
uop
.
ctrl
.
fuOpType
)
val
divider
=
Module
(
new
Divider
(
XLEN
))
val
isDiv
=
MDUOpType
.
isDiv
(
func
)
val
isDivSign
=
MDUOpType
.
isDivSign
(
func
)
val
isW
=
MDUOpType
.
isW
(
func
)
val
divInputFunc
=
(
x
:
UInt
)
=>
Mux
(
isW
,
Mux
(
isDivSign
,
SignExt
(
x
(
31
,
0
),
XLEN
),
ZeroExt
(
x
(
31
,
0
),
XLEN
)
),
x
)
divider
.
io
.
redirect
:=
io
.
redirect
divider
.
io
.
in
.
valid
:=
io
.
in
.
valid
divider
.
io
.
in
.
bits
.
ctrl
.
uop
:=
io
.
in
.
bits
.
uop
divider
.
io
.
in
.
bits
.
ctrl
.
sign
:=
isDivSign
divider
.
io
.
in
.
bits
.
ctrl
.
isW
:=
isW
divider
.
io
.
in
.
bits
.
ctrl
.
isHi
:=
func
(
1
)
divider
.
io
.
in
.
bits
.
src1
:=
divInputFunc
(
src1
)
divider
.
io
.
in
.
bits
.
src2
:=
divInputFunc
(
src2
)
divider
.
io
.
out
.
ready
:=
io
.
out
.
ready
io
.
in
.
ready
:=
divider
.
io
.
in
.
ready
io
.
out
.
valid
:=
divider
.
io
.
out
.
valid
io
.
out
.
bits
.
uop
:=
divider
.
io
.
out
.
bits
.
uop
io
.
out
.
bits
.
data
:=
divider
.
io
.
out
.
bits
.
data
io
.
out
.
bits
.
redirectValid
:=
false
.
B
io
.
out
.
bits
.
redirect
<>
DontCare
io
.
dmem
<>
DontCare
io
.
out
.
bits
.
debug
<>
DontCare
XSDebug
(
io
.
in
.
valid
,
"In(%d %d) Out(%d %d) Redirect:(%d %d) brTag:%x\n"
,
io
.
in
.
valid
,
io
.
in
.
ready
,
io
.
out
.
valid
,
io
.
out
.
ready
,
io
.
redirect
.
valid
,
io
.
redirect
.
bits
.
isException
,
io
.
redirect
.
bits
.
brTag
.
value
)
XSDebug
(
io
.
in
.
valid
,
"src1:%x src2:%x pc:%x\n"
,
src1
,
src2
,
io
.
in
.
bits
.
uop
.
cf
.
pc
)
XSDebug
(
io
.
out
.
valid
,
"Out(%d %d) res:%x pc:%x\n"
,
io
.
out
.
valid
,
io
.
out
.
ready
,
io
.
out
.
bits
.
data
,
io
.
out
.
bits
.
uop
.
cf
.
pc
)
}
class
Mdu
extends
Exu
(
FuType
.
mdu
.
litValue
())
{
override
def
toString
:
String
=
"MulDiv"
val
(
src1
,
src2
,
uop
,
func
)
=
(
io
.
in
.
bits
.
src1
,
io
.
in
.
bits
.
src2
,
io
.
in
.
bits
.
uop
,
io
.
in
.
bits
.
uop
.
ctrl
.
fuOpType
)
val
isDiv
=
MDUOpType
.
isDiv
(
func
)
val
mul
=
Module
(
new
Mul
)
val
div
=
Module
(
new
Div
)
for
(
x
<-
Seq
(
mul
.
io
,
div
.
io
)){
x
.
scommit
<>
DontCare
x
.
dmem
<>
DontCare
x
.
in
.
bits
:=
io
.
in
.
bits
x
.
redirect
:=
io
.
redirect
}
mul
.
io
.
in
.
valid
:=
io
.
in
.
valid
&&
!
isDiv
div
.
io
.
in
.
valid
:=
io
.
in
.
valid
&&
isDiv
io
.
in
.
ready
:=
Mux
(
isDiv
,
div
.
io
.
in
.
ready
,
mul
.
io
.
in
.
ready
)
val
arb
=
Module
(
new
Arbiter
(
new
ExuOutput
,
2
))
arb
.
io
.
in
(
0
)
<>
mul
.
io
.
out
arb
.
io
.
in
(
1
)
<>
div
.
io
.
out
io
.
out
<>
arb
.
io
.
out
XSDebug
(
io
.
in
.
valid
,
"In(%d %d) Out(%d %d) Redirect:(%d %d) brTag:%x\n"
,
io
.
in
.
valid
,
io
.
in
.
ready
,
io
.
out
.
valid
,
io
.
out
.
ready
,
io
.
redirect
.
valid
,
io
.
redirect
.
bits
.
isException
,
io
.
redirect
.
bits
.
brTag
.
value
)
XSDebug
(
io
.
in
.
valid
,
"src1:%x src2:%x pc:%x\n"
,
src1
,
src2
,
io
.
in
.
bits
.
uop
.
cf
.
pc
)
XSDebug
(
io
.
out
.
valid
,
"Out(%d %d) res:%x pc:%x\n"
,
io
.
out
.
valid
,
io
.
out
.
ready
,
io
.
out
.
bits
.
data
,
io
.
out
.
bits
.
uop
.
cf
.
pc
)
}
class
MulDivCtrl
extends
Bundle
{
val
uop
=
new
MicroOp
val
sign
=
Bool
()
val
isW
=
Bool
()
val
isHi
=
Bool
()
// return hi bits of result ?
}
class
MulDivOutput
extends
XSBundle
{
val
data
=
UInt
(
XLEN
.
W
)
val
uop
=
new
MicroOp
}
class
MulDivIO
(
val
len
:
Int
)
extends
XSBundle
{
val
in
=
Flipped
(
DecoupledIO
(
new
Bundle
()
{
val
src1
,
src2
=
UInt
(
len
.
W
)
val
ctrl
=
new
MulDivCtrl
}))
val
out
=
DecoupledIO
(
new
MulDivOutput
)
val
redirect
=
Flipped
(
ValidIO
(
new
Redirect
))
}
trait
HasPipelineReg
{
this:
ArrayMultiplier
=>
val
validVec
=
io
.
in
.
valid
+:
Array
.
fill
(
latency
)(
RegInit
(
false
.
B
))
val
rdyVec
=
Array
.
fill
(
latency
)(
Wire
(
Bool
()))
:+
io
.
out
.
ready
val
ctrlVec
=
io
.
in
.
bits
.
ctrl
+:
Array
.
fill
(
latency
)(
Reg
(
new
MulDivCtrl
))
val
flushVec
=
ctrlVec
.
zip
(
validVec
).
map
(
x
=>
x
.
_2
&&
x
.
_1
.
uop
.
brTag
.
needFlush
(
io
.
redirect
))
for
(
i
<-
0
until
latency
){
rdyVec
(
i
)
:=
!
validVec
(
i
+
1
)
||
rdyVec
(
i
+
1
)
}
for
(
i
<-
1
to
latency
){
when
(
flushVec
(
i
)
||
rdyVec
(
i
)
&&
!
validVec
(
i
-
1
)){
validVec
(
i
)
:=
false
.
B
}.
elsewhen
(
rdyVec
(
i
-
1
)
&&
validVec
(
i
-
1
)
&&
!
flushVec
(
i
-
1
)){
validVec
(
i
)
:=
validVec
(
i
-
1
)
ctrlVec
(
i
)
:=
ctrlVec
(
i
-
1
)
}
}
io
.
in
.
ready
:=
rdyVec
(
0
)
io
.
out
.
valid
:=
validVec
.
last
&&
!
flushVec
.
last
io
.
out
.
bits
.
uop
:=
ctrlVec
.
last
.
uop
def
PipelineReg
[
T
<:
Data
](
i
:
Int
)(
next
:
T
)
=
RegEnable
(
next
,
enable
=
validVec
(
i
-
1
)
&&
rdyVec
(
i
-
1
))
def
S1Reg
[
T
<:
Data
](
next
:
T
)
:
T
=
PipelineReg
[
T
](
1
)(
next
)
def
S2Reg
[
T
<:
Data
](
next
:
T
)
:
T
=
PipelineReg
[
T
](
2
)(
next
)
def
S3Reg
[
T
<:
Data
](
next
:
T
)
:
T
=
PipelineReg
[
T
](
3
)(
next
)
def
S4Reg
[
T
<:
Data
](
next
:
T
)
:
T
=
PipelineReg
[
T
](
4
)(
next
)
def
S5Reg
[
T
<:
Data
](
next
:
T
)
:
T
=
PipelineReg
[
T
](
5
)(
next
)
}
abstract
class
Multiplier
(
val
len
:
Int
,
val
latency
:
Int
=
3
)
extends
Module
{
val
io
=
IO
(
new
MulDivIO
(
len
))
}
class
ArrayMultiplier
(
len
:
Int
,
latency
:
Int
=
3
,
realArray
:
Boolean
=
false
)
extends
Multiplier
(
len
,
latency
)
with
HasPipelineReg
{
val
mulRes
=
io
.
in
.
bits
.
src1
.
asSInt
()
*
io
.
in
.
bits
.
src2
.
asSInt
()
var
dataVec
=
Seq
(
mulRes
.
asUInt
())
for
(
i
<-
1
to
latency
){
dataVec
=
dataVec
:+
PipelineReg
(
i
)(
dataVec
(
i
-
1
))
}
val
xlen
=
io
.
out
.
bits
.
data
.
getWidth
val
res
=
Mux
(
ctrlVec
.
last
.
isHi
,
dataVec
.
last
(
2
*
xlen
-
1
,
xlen
),
dataVec
.
last
(
xlen
-
1
,
0
))
io
.
out
.
bits
.
data
:=
Mux
(
ctrlVec
.
last
.
isW
,
SignExt
(
res
(
31
,
0
),
xlen
),
res
)
XSDebug
(
p
"validVec:${Binary(Cat(validVec))} flushVec:${Binary(Cat(flushVec))}\n"
)(
this
.
name
)
// printf(p"t=${GTimer()} in: v${io.in.valid} r:${io.in.ready}\n")
// printf(p"t=${GTimer()} out: v:${io.out.valid} r:${io.out.ready} vec:${Binary(Cat(validVec))}\n")
}
class
Divider
(
len
:
Int
)
extends
Module
{
val
io
=
IO
(
new
MulDivIO
(
len
))
def
abs
(
a
:
UInt
,
sign
:
Bool
)
:
(
Bool
,
UInt
)
=
{
val
s
=
a
(
len
-
1
)
&&
sign
(
s
,
Mux
(
s
,
-
a
,
a
))
}
val
s_idle
::
s_log2
::
s_shift
::
s_compute
::
s_finish
::
Nil
=
Enum
(
5
)
val
state
=
RegInit
(
s_idle
)
val
newReq
=
(
state
===
s_idle
)
&&
io
.
in
.
fire
()
val
(
a
,
b
)
=
(
io
.
in
.
bits
.
src1
,
io
.
in
.
bits
.
src2
)
val
divBy0
=
b
===
0.
U
(
len
.
W
)
val
shiftReg
=
Reg
(
UInt
((
1
+
len
*
2
).
W
))
val
hi
=
shiftReg
(
len
*
2
,
len
)
val
lo
=
shiftReg
(
len
-
1
,
0
)
val
(
aSign
,
aVal
)
=
abs
(
a
,
io
.
in
.
bits
.
ctrl
.
sign
)
val
(
bSign
,
bVal
)
=
abs
(
b
,
io
.
in
.
bits
.
ctrl
.
sign
)
val
aSignReg
=
RegEnable
(
aSign
,
newReq
)
val
qSignReg
=
RegEnable
((
aSign
^
bSign
)
&&
!
divBy0
,
newReq
)
val
bReg
=
RegEnable
(
bVal
,
newReq
)
val
aValx2Reg
=
RegEnable
(
Cat
(
aVal
,
"b0"
.
U
),
newReq
)
val
ctrlReg
=
RegEnable
(
io
.
in
.
bits
.
ctrl
,
newReq
)
val
cnt
=
Counter
(
len
)
when
(
newReq
)
{
state
:=
s_log2
}
.
elsewhen
(
state
===
s_log2
)
{
// `canSkipShift` is calculated as following:
// bEffectiveBit = Log2(bVal, XLEN) + 1.U
// aLeadingZero = 64.U - aEffectiveBit = 64.U - (Log2(aVal, XLEN) + 1.U)
// canSkipShift = aLeadingZero + bEffectiveBit
// = 64.U - (Log2(aVal, XLEN) + 1.U) + Log2(bVal, XLEN) + 1.U
// = 64.U + Log2(bVal, XLEN) - Log2(aVal, XLEN)
// = (64.U | Log2(bVal, XLEN)) - Log2(aVal, XLEN) // since Log2(bVal, XLEN) < 64.U
val
canSkipShift
=
(
64.
U
|
Log2
(
bReg
))
-
Log2
(
aValx2Reg
)
// When divide by 0, the quotient should be all 1's.
// Therefore we can not shift in 0s here.
// We do not skip any shift to avoid this.
cnt
.
value
:=
Mux
(
divBy0
,
0.
U
,
Mux
(
canSkipShift
>=
(
len
-
1
).
U
,
(
len
-
1
).
U
,
canSkipShift
))
state
:=
s_shift
}
.
elsewhen
(
state
===
s_shift
)
{
shiftReg
:=
aValx2Reg
<<
cnt
.
value
state
:=
s_compute
}
.
elsewhen
(
state
===
s_compute
)
{
val
enough
=
hi
.
asUInt
>=
bReg
.
asUInt
shiftReg
:=
Cat
(
Mux
(
enough
,
hi
-
bReg
,
hi
)(
len
-
1
,
0
),
lo
,
enough
)
cnt
.
inc
()
when
(
cnt
.
value
===
(
len
-
1
).
U
)
{
state
:=
s_finish
}
}
.
elsewhen
(
state
===
s_finish
)
{
when
(
io
.
out
.
ready
){
state
:=
s_idle
}
}
when
(
state
=/=
s_idle
&&
ctrlReg
.
uop
.
brTag
.
needFlush
(
io
.
redirect
)){
state
:=
s_idle
}
val
r
=
hi
(
len
,
1
)
val
resQ
=
Mux
(
qSignReg
,
-
lo
,
lo
)
val
resR
=
Mux
(
aSignReg
,
-
r
,
r
)
val
xlen
=
io
.
out
.
bits
.
data
.
getWidth
val
res
=
Mux
(
ctrlReg
.
isHi
,
resR
,
resQ
)
io
.
out
.
bits
.
data
:=
Mux
(
ctrlReg
.
isW
,
SignExt
(
res
(
31
,
0
),
xlen
),
res
)
io
.
out
.
bits
.
uop
:=
ctrlReg
.
uop
io
.
out
.
valid
:=
state
===
s_finish
io
.
in
.
ready
:=
state
===
s_idle
}
\ No newline at end of file
src/main/scala/xiangshan/backend/exu/MulDivExeUnit.scala
0 → 100644
浏览文件 @
706f729c
package
xiangshan.backend.exu
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.utils._
import
xiangshan.backend.MDUOpType
import
xiangshan.backend.fu.FunctionUnit._
class
MulDivExeUnit
extends
Exu
(
Exu
.
mulDivExeUnitCfg
){
val
(
src1
,
src2
,
uop
,
func
)
=
(
io
.
in
.
bits
.
src1
,
io
.
in
.
bits
.
src2
,
io
.
in
.
bits
.
uop
,
io
.
in
.
bits
.
uop
.
ctrl
.
fuOpType
)
val
isDiv
=
MDUOpType
.
isDiv
(
func
)
val
mul
=
Module
(
new
MulExeUnit
)
val
div
=
Module
(
new
DivExeUnit
)
for
(
x
<-
Seq
(
mul
.
io
,
div
.
io
)){
x
.
scommit
<>
DontCare
x
.
dmem
<>
DontCare
x
.
in
.
bits
:=
io
.
in
.
bits
x
.
redirect
:=
io
.
redirect
}
mul
.
io
.
in
.
valid
:=
io
.
in
.
valid
&&
!
isDiv
div
.
io
.
in
.
valid
:=
io
.
in
.
valid
&&
isDiv
io
.
in
.
ready
:=
Mux
(
isDiv
,
div
.
io
.
in
.
ready
,
mul
.
io
.
in
.
ready
)
val
arb
=
Module
(
new
Arbiter
(
new
ExuOutput
,
2
))
arb
.
io
.
in
(
0
)
<>
mul
.
io
.
out
arb
.
io
.
in
(
1
)
<>
div
.
io
.
out
io
.
out
<>
arb
.
io
.
out
XSDebug
(
io
.
in
.
valid
,
"In(%d %d) Out(%d %d) Redirect:(%d %d) brTag:%x\n"
,
io
.
in
.
valid
,
io
.
in
.
ready
,
io
.
out
.
valid
,
io
.
out
.
ready
,
io
.
redirect
.
valid
,
io
.
redirect
.
bits
.
isException
,
io
.
redirect
.
bits
.
brTag
.
value
)
XSDebug
(
io
.
in
.
valid
,
"src1:%x src2:%x pc:%x\n"
,
src1
,
src2
,
io
.
in
.
bits
.
uop
.
cf
.
pc
)
XSDebug
(
io
.
out
.
valid
,
"Out(%d %d) res:%x pc:%x\n"
,
io
.
out
.
valid
,
io
.
out
.
ready
,
io
.
out
.
bits
.
data
,
io
.
out
.
bits
.
uop
.
cf
.
pc
)
}
src/main/scala/xiangshan/backend/exu/MulExeUnit.scala
0 → 100644
浏览文件 @
706f729c
package
xiangshan.backend.exu
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
utils._
import
xiangshan.backend.MDUOpType
import
xiangshan.backend.fu.FunctionUnit._
import
xiangshan.backend.fu.ArrayMultiplier
class
MulExeUnit
extends
Exu
(
Exu
.
mulExeUnitCfg
){
val
(
src1
,
src2
,
uop
,
func
)
=
(
io
.
in
.
bits
.
src1
,
io
.
in
.
bits
.
src2
,
io
.
in
.
bits
.
uop
,
io
.
in
.
bits
.
uop
.
ctrl
.
fuOpType
)
val
mul
=
Module
(
new
ArrayMultiplier
(
XLEN
+
1
))
val
signext
=
SignExt
(
_:
UInt
,
XLEN
+
1
)
val
zeroext
=
ZeroExt
(
_:
UInt
,
XLEN
+
1
)
val
mulInputFuncTable
=
List
(
MDUOpType
.
mul
->
(
zeroext
,
zeroext
),
MDUOpType
.
mulh
->
(
signext
,
signext
),
MDUOpType
.
mulhsu
->
(
signext
,
zeroext
),
MDUOpType
.
mulhu
->
(
zeroext
,
zeroext
)
)
val
isW
=
MDUOpType
.
isW
(
func
)
mul
.
io
.
redirect
:=
io
.
redirect
mul
.
io
.
in
.
bits
.
ctrl
.
uop
:=
io
.
in
.
bits
.
uop
mul
.
io
.
in
.
bits
.
ctrl
.
sign
:=
DontCare
//Mul don't use this
mul
.
io
.
in
.
bits
.
ctrl
.
isW
:=
isW
mul
.
io
.
in
.
bits
.
ctrl
.
isHi
:=
func
(
1
,
0
)
=/=
MDUOpType
.
mul
(
1
,
0
)
mul
.
io
.
in
.
bits
.
src1
:=
LookupTree
(
func
(
1
,
0
),
mulInputFuncTable
.
map
(
p
=>
(
p
.
_1
(
1
,
0
),
p
.
_2
.
_1
(
src1
)))
)
mul
.
io
.
in
.
bits
.
src2
:=
LookupTree
(
func
(
1
,
0
),
mulInputFuncTable
.
map
(
p
=>
(
p
.
_1
(
1
,
0
),
p
.
_2
.
_2
(
src2
)))
)
mul
.
io
.
in
.
valid
:=
io
.
in
.
valid
mul
.
io
.
out
.
ready
:=
io
.
out
.
ready
io
.
in
.
ready
:=
mul
.
io
.
in
.
ready
io
.
out
.
valid
:=
mul
.
io
.
out
.
valid
io
.
out
.
bits
.
uop
:=
mul
.
io
.
out
.
bits
.
uop
io
.
out
.
bits
.
data
:=
mul
.
io
.
out
.
bits
.
data
io
.
out
.
bits
.
redirectValid
:=
false
.
B
io
.
out
.
bits
.
redirect
<>
DontCare
XSDebug
(
io
.
in
.
valid
,
"In(%d %d) Out(%d %d) Redirect:(%d %d) brTag:%x\n"
,
io
.
in
.
valid
,
io
.
in
.
ready
,
io
.
out
.
valid
,
io
.
out
.
ready
,
io
.
redirect
.
valid
,
io
.
redirect
.
bits
.
isException
,
io
.
redirect
.
bits
.
brTag
.
value
)
XSDebug
(
io
.
in
.
valid
,
"src1:%x src2:%x pc:%x\n"
,
src1
,
src2
,
io
.
in
.
bits
.
uop
.
cf
.
pc
)
XSDebug
(
io
.
out
.
valid
,
"Out(%d %d) res:%x pc:%x\n"
,
io
.
out
.
valid
,
io
.
out
.
ready
,
io
.
out
.
bits
.
data
,
io
.
out
.
bits
.
uop
.
cf
.
pc
)
XSDebug
(
io
.
redirect
.
valid
,
p
"redirect: ${io.redirect.bits.brTag}\n"
)
}
src/main/scala/xiangshan/backend/exu/Wbu.scala
浏览文件 @
706f729c
...
...
@@ -2,13 +2,47 @@ package xiangshan.backend.exu
import
chisel3._
import
chisel3.util._
import
xiangshan.
{
ExuOutput
,
XSModule
}
import
xiangshan._
import
xiangshan.utils._
class
WriteBackArbMtoN
(
m
:
Int
,
n
:
Int
)
extends
XSModule
{
val
io
=
IO
(
new
Bundle
()
{
val
in
=
Vec
(
m
,
Flipped
(
DecoupledIO
(
new
ExuOutput
)))
val
out
=
Vec
(
n
,
ValidIO
(
new
ExuOutput
))
})
require
(
m
>=
n
,
"m < n! Why use an arbiter???"
)
// first n-1 ports, direct connect
for
((
i
,
o
)
<-
io
.
in
.
take
(
n
-
1
).
zip
(
io
.
out
)){
o
.
valid
:=
i
.
valid
o
.
bits
:=
i
.
bits
i
.
ready
:=
true
.
B
}
// last m-(n-1) ports, rr arb
val
arb
=
Module
(
new
RRArbiter
[
ExuOutput
](
new
ExuOutput
,
m
-
n
+
1
))
for
((
arbIn
,
ioIn
)
<-
arb
.
io
.
in
.
zip
(
io
.
in
.
drop
(
n
-
1
))){
arbIn
<>
ioIn
}
io
.
out
.
last
.
bits
:=
arb
.
io
.
out
.
bits
io
.
out
.
last
.
valid
:=
arb
.
io
.
out
.
valid
arb
.
io
.
out
.
ready
:=
true
.
B
for
(
i
<-
0
until
n
)
{
XSInfo
(
io
.
out
(
i
).
valid
,
"out(%d) pc(0x%x) writebacks 0x%x to pdest(%d) ldest(%d)\n"
,
i
.
U
,
io
.
out
(
i
).
bits
.
uop
.
cf
.
pc
,
io
.
out
(
i
).
bits
.
data
,
io
.
out
(
i
).
bits
.
uop
.
pdest
,
io
.
out
(
i
).
bits
.
uop
.
ctrl
.
ldest
)
}
}
class
Wbu
(
wbIntIdx
:
Array
[
Int
],
wbFpIdx
:
Array
[
Int
])
extends
XSModule
{
val
io
=
IO
(
new
Bundle
()
{
val
in
=
Vec
(
exu
Config
.
ExuCnt
,
Flipped
(
DecoupledIO
(
new
ExuOutput
)))
val
toRoq
=
Vec
(
exu
Config
.
ExuCnt
,
ValidIO
(
new
ExuOutput
))
val
in
=
Vec
(
exu
Parameters
.
ExuCnt
,
Flipped
(
DecoupledIO
(
new
ExuOutput
)))
val
toRoq
=
Vec
(
exu
Parameters
.
ExuCnt
,
ValidIO
(
new
ExuOutput
))
val
toIntRf
,
toFpRf
=
Vec
(
NRWritePorts
,
ValidIO
(
new
ExuOutput
))
})
...
...
src/main/scala/xiangshan/backend/fu/Alu.scala
0 → 100644
浏览文件 @
706f729c
package
xiangshan.backend.fu
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.utils._
import
xiangshan.backend._
import
xiangshan.backend.fu.FunctionUnit._
class
Alu
extends
FunctionUnit
(
aluCfg
)
{
val
io
=
IO
(
new
ExuIO
)
override
def
toString
:
String
=
"Alu"
val
(
iovalid
,
src1
,
src2
,
offset
,
func
,
pc
,
uop
)
=
(
io
.
in
.
valid
,
io
.
in
.
bits
.
src1
,
io
.
in
.
bits
.
src2
,
io
.
in
.
bits
.
uop
.
ctrl
.
imm
,
io
.
in
.
bits
.
uop
.
ctrl
.
fuOpType
,
SignExt
(
io
.
in
.
bits
.
uop
.
cf
.
pc
,
AddrBits
),
io
.
in
.
bits
.
uop
)
val
redirectHit
=
uop
.
brTag
.
needFlush
(
io
.
redirect
)
val
valid
=
iovalid
&&
!
redirectHit
val
isAdderSub
=
(
func
=/=
ALUOpType
.
add
)
&&
(
func
=/=
ALUOpType
.
addw
)
&&
!
ALUOpType
.
isJump
(
func
)
val
adderRes
=
(
src1
+&
(
src2
^
Fill
(
XLEN
,
isAdderSub
)))
+
isAdderSub
val
xorRes
=
src1
^
src2
val
sltu
=
!
adderRes
(
XLEN
)
val
slt
=
xorRes
(
XLEN
-
1
)
^
sltu
val
shsrc1
=
LookupTreeDefault
(
func
,
src1
,
List
(
ALUOpType
.
srlw
->
ZeroExt
(
src1
(
31
,
0
),
64
),
ALUOpType
.
sraw
->
SignExt
(
src1
(
31
,
0
),
64
)
))
val
shamt
=
Mux
(
ALUOpType
.
isWordOp
(
func
),
src2
(
4
,
0
),
src2
(
5
,
0
))
val
res
=
LookupTreeDefault
(
func
(
3
,
0
),
adderRes
,
List
(
ALUOpType
.
sll
->
((
shsrc1
<<
shamt
)(
XLEN
-
1
,
0
)),
ALUOpType
.
slt
->
ZeroExt
(
slt
,
XLEN
),
ALUOpType
.
sltu
->
ZeroExt
(
sltu
,
XLEN
),
ALUOpType
.
xor
->
xorRes
,
ALUOpType
.
srl
->
(
shsrc1
>>
shamt
),
ALUOpType
.
or
->
(
src1
|
src2
),
ALUOpType
.
and
->
(
src1
&
src2
),
ALUOpType
.
sra
->
((
shsrc1
.
asSInt
>>
shamt
).
asUInt
)
))
val
aluRes
=
Mux
(
ALUOpType
.
isWordOp
(
func
),
SignExt
(
res
(
31
,
0
),
64
),
res
)
val
branchOpTable
=
List
(
ALUOpType
.
getBranchType
(
ALUOpType
.
beq
)
->
!
xorRes
.
orR
,
ALUOpType
.
getBranchType
(
ALUOpType
.
blt
)
->
slt
,
ALUOpType
.
getBranchType
(
ALUOpType
.
bltu
)
->
sltu
)
val
isBru
=
ALUOpType
.
isBru
(
func
)
// val isBranch = io.in.bits.uop.cf.isBr// ALUOpType.isBranch(func)
val
isBranch
=
ALUOpType
.
isBranch
(
func
)
val
isJump
=
ALUOpType
.
isJump
(
func
)
val
taken
=
LookupTree
(
ALUOpType
.
getBranchType
(
func
),
branchOpTable
)
^
ALUOpType
.
isBranchInvert
(
func
)
val
target
=
Mux
(
isBranch
,
pc
+
offset
,
adderRes
)(
VAddrBits
-
1
,
0
)
val
isRVC
=
uop
.
cf
.
isRVC
//(io.in.bits.cf.instr(1,0) =/= "b11".U)
io
.
in
.
ready
:=
io
.
out
.
ready
val
pcLatchSlot
=
Mux
(
isRVC
,
pc
+
2.
U
,
pc
+
4.
U
)
io
.
out
.
bits
.
redirectValid
:=
io
.
out
.
valid
&&
isBru
//isBranch
io
.
out
.
bits
.
redirect
.
target
:=
Mux
(!
taken
&&
isBranch
,
pcLatchSlot
,
target
)
io
.
out
.
bits
.
redirect
.
brTag
:=
uop
.
brTag
io
.
out
.
bits
.
redirect
.
isException
:=
DontCare
// false.B
io
.
out
.
bits
.
redirect
.
roqIdx
:=
uop
.
roqIdx
io
.
out
.
bits
.
redirect
.
freelistAllocPtr
:=
uop
.
freelistAllocPtr
io
.
out
.
valid
:=
valid
io
.
out
.
bits
.
uop
<>
io
.
in
.
bits
.
uop
io
.
out
.
bits
.
data
:=
Mux
(
isJump
,
pcLatchSlot
,
aluRes
)
XSDebug
(
io
.
in
.
valid
,
"In(%d %d) Out(%d %d) Redirect:(%d %d %d) brTag:f:%d v:%d\n"
,
io
.
in
.
valid
,
io
.
in
.
ready
,
io
.
out
.
valid
,
io
.
out
.
ready
,
io
.
redirect
.
valid
,
io
.
redirect
.
bits
.
isException
,
redirectHit
,
io
.
redirect
.
bits
.
brTag
.
flag
,
io
.
redirect
.
bits
.
brTag
.
value
)
XSDebug
(
io
.
in
.
valid
,
"src1:%x src2:%x offset:%x func:%b pc:%x\n"
,
src1
,
src2
,
offset
,
func
,
pc
)
XSDebug
(
io
.
out
.
valid
,
"res:%x aluRes:%x isRVC:%d isBru:%d isBranch:%d isJump:%d target:%x taken:%d flptr:%x\n"
,
io
.
out
.
bits
.
data
,
aluRes
,
isRVC
,
isBru
,
isBranch
,
isJump
,
target
,
taken
,
io
.
out
.
bits
.
uop
.
freelistAllocPtr
.
value
)
}
src/main/scala/xiangshan/backend/fu/Divider.scala
0 → 100644
浏览文件 @
706f729c
package
xiangshan.backend.fu
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.utils._
import
xiangshan.backend._
import
xiangshan.backend.fu.FunctionUnit._
class
Divider
(
len
:
Int
)
extends
FunctionUnit
(
divCfg
)
{
val
io
=
IO
(
new
MulDivIO
(
len
))
def
abs
(
a
:
UInt
,
sign
:
Bool
)
:
(
Bool
,
UInt
)
=
{
val
s
=
a
(
len
-
1
)
&&
sign
(
s
,
Mux
(
s
,
-
a
,
a
))
}
val
s_idle
::
s_log2
::
s_shift
::
s_compute
::
s_finish
::
Nil
=
Enum
(
5
)
val
state
=
RegInit
(
s_idle
)
val
newReq
=
(
state
===
s_idle
)
&&
io
.
in
.
fire
()
val
(
a
,
b
)
=
(
io
.
in
.
bits
.
src1
,
io
.
in
.
bits
.
src2
)
val
divBy0
=
b
===
0.
U
(
len
.
W
)
val
shiftReg
=
Reg
(
UInt
((
1
+
len
*
2
).
W
))
val
hi
=
shiftReg
(
len
*
2
,
len
)
val
lo
=
shiftReg
(
len
-
1
,
0
)
val
(
aSign
,
aVal
)
=
abs
(
a
,
io
.
in
.
bits
.
ctrl
.
sign
)
val
(
bSign
,
bVal
)
=
abs
(
b
,
io
.
in
.
bits
.
ctrl
.
sign
)
val
aSignReg
=
RegEnable
(
aSign
,
newReq
)
val
qSignReg
=
RegEnable
((
aSign
^
bSign
)
&&
!
divBy0
,
newReq
)
val
bReg
=
RegEnable
(
bVal
,
newReq
)
val
aValx2Reg
=
RegEnable
(
Cat
(
aVal
,
"b0"
.
U
),
newReq
)
val
ctrlReg
=
RegEnable
(
io
.
in
.
bits
.
ctrl
,
newReq
)
val
cnt
=
Counter
(
len
)
when
(
newReq
)
{
state
:=
s_log2
}
.
elsewhen
(
state
===
s_log2
)
{
// `canSkipShift` is calculated as following:
// bEffectiveBit = Log2(bVal, XLEN) + 1.U
// aLeadingZero = 64.U - aEffectiveBit = 64.U - (Log2(aVal, XLEN) + 1.U)
// canSkipShift = aLeadingZero + bEffectiveBit
// = 64.U - (Log2(aVal, XLEN) + 1.U) + Log2(bVal, XLEN) + 1.U
// = 64.U + Log2(bVal, XLEN) - Log2(aVal, XLEN)
// = (64.U | Log2(bVal, XLEN)) - Log2(aVal, XLEN) // since Log2(bVal, XLEN) < 64.U
val
canSkipShift
=
(
64.
U
|
Log2
(
bReg
))
-
Log2
(
aValx2Reg
)
// When divide by 0, the quotient should be all 1's.
// Therefore we can not shift in 0s here.
// We do not skip any shift to avoid this.
cnt
.
value
:=
Mux
(
divBy0
,
0.
U
,
Mux
(
canSkipShift
>=
(
len
-
1
).
U
,
(
len
-
1
).
U
,
canSkipShift
))
state
:=
s_shift
}
.
elsewhen
(
state
===
s_shift
)
{
shiftReg
:=
aValx2Reg
<<
cnt
.
value
state
:=
s_compute
}
.
elsewhen
(
state
===
s_compute
)
{
val
enough
=
hi
.
asUInt
>=
bReg
.
asUInt
shiftReg
:=
Cat
(
Mux
(
enough
,
hi
-
bReg
,
hi
)(
len
-
1
,
0
),
lo
,
enough
)
cnt
.
inc
()
when
(
cnt
.
value
===
(
len
-
1
).
U
)
{
state
:=
s_finish
}
}
.
elsewhen
(
state
===
s_finish
)
{
when
(
io
.
out
.
ready
){
state
:=
s_idle
}
}
when
(
state
=/=
s_idle
&&
ctrlReg
.
uop
.
brTag
.
needFlush
(
io
.
redirect
)){
state
:=
s_idle
}
val
r
=
hi
(
len
,
1
)
val
resQ
=
Mux
(
qSignReg
,
-
lo
,
lo
)
val
resR
=
Mux
(
aSignReg
,
-
r
,
r
)
val
xlen
=
io
.
out
.
bits
.
data
.
getWidth
val
res
=
Mux
(
ctrlReg
.
isHi
,
resR
,
resQ
)
io
.
out
.
bits
.
data
:=
Mux
(
ctrlReg
.
isW
,
SignExt
(
res
(
31
,
0
),
xlen
),
res
)
io
.
out
.
bits
.
uop
:=
ctrlReg
.
uop
io
.
out
.
valid
:=
state
===
s_finish
io
.
in
.
ready
:=
state
===
s_idle
}
\ No newline at end of file
src/main/scala/xiangshan/backend/fu/FDivSqrt.scala
0 → 100644
浏览文件 @
706f729c
package
xiangshan.backend.fu
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.utils._
import
xiangshan.backend._
import
xiangshan.backend.fu.FunctionUnit._
class
FDivSqrt
extends
FunctionUnit
(
fDivSqrtCfg
){
val
io
=
IO
(
new
Bundle
()
{})
override
def
toString
:
String
=
"FDivSqrt"
}
src/main/scala/xiangshan/backend/fu/Fmac.scala
0 → 100644
浏览文件 @
706f729c
package
xiangshan.backend.fu
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.utils._
import
xiangshan.backend._
import
xiangshan.backend.fu.FunctionUnit._
class
Fmac
extends
FunctionUnit
(
fmacCfg
){
val
io
=
IO
(
new
Bundle
()
{})
override
def
toString
:
String
=
"Fmac"
}
src/main/scala/xiangshan/backend/fu/Fmisc.scala
0 → 100644
浏览文件 @
706f729c
package
xiangshan.backend.fu
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.utils._
import
xiangshan.backend._
import
xiangshan.backend.fu.FunctionUnit._
class
Fmisc
extends
FunctionUnit
(
fmiscCfg
){
val
io
=
IO
(
new
Bundle
()
{})
override
def
toString
:
String
=
"Fmisc"
}
src/main/scala/xiangshan/backend/fu/FunctionUnit.scala
0 → 100644
浏览文件 @
706f729c
package
xiangshan.backend.fu
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.utils._
import
FunctionUnit._
/*
XiangShan Function Unit
A Exu can have one or more function units
*/
case
class
FuConfig
(
fuType
:
UInt
,
numIntSrc
:
Int
,
numFpSrc
:
Int
,
writeIntRf
:
Boolean
,
writeFpRf
:
Boolean
,
hasRedirect
:
Boolean
)
abstract
class
FunctionUnit
(
cfg
:
FuConfig
)
extends
XSModule
object
FunctionUnit
{
val
jmpCfg
=
FuConfig
(
FuType
.
jmp
,
1
,
0
,
writeIntRf
=
true
,
writeFpRf
=
false
,
hasRedirect
=
true
)
val
i2fCfg
=
FuConfig
(
FuType
.
i2f
,
1
,
0
,
writeIntRf
=
false
,
writeFpRf
=
true
,
hasRedirect
=
false
)
val
aluCfg
=
FuConfig
(
FuType
.
alu
,
2
,
0
,
writeIntRf
=
true
,
writeFpRf
=
false
,
hasRedirect
=
true
)
val
mulCfg
=
FuConfig
(
FuType
.
mul
,
2
,
0
,
writeIntRf
=
true
,
writeFpRf
=
false
,
hasRedirect
=
false
)
val
divCfg
=
FuConfig
(
FuType
.
div
,
2
,
0
,
writeIntRf
=
true
,
writeFpRf
=
false
,
hasRedirect
=
false
)
val
lsuCfg
=
FuConfig
(
FuType
.
ldu
,
2
,
1
,
writeIntRf
=
true
,
writeFpRf
=
true
,
hasRedirect
=
false
)
val
fmacCfg
=
FuConfig
(
FuType
.
fmac
,
0
,
3
,
writeIntRf
=
false
,
writeFpRf
=
true
,
hasRedirect
=
false
)
val
fmiscCfg
=
FuConfig
(
FuType
.
fmisc
,
0
,
2
,
writeIntRf
=
false
,
writeFpRf
=
true
,
hasRedirect
=
false
)
val
fDivSqrtCfg
=
FuConfig
(
FuType
.
fDivSqrt
,
0
,
2
,
writeIntRf
=
false
,
writeFpRf
=
true
,
hasRedirect
=
false
)
}
\ No newline at end of file
src/main/scala/xiangshan/backend/fu/I2f.scala
0 → 100644
浏览文件 @
706f729c
package
xiangshan.backend.fu
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.utils._
import
xiangshan.backend._
import
xiangshan.backend.fu.FunctionUnit._
class
I2f
extends
FunctionUnit
(
i2fCfg
){
val
io
=
IO
(
new
Bundle
()
{})
}
src/main/scala/xiangshan/backend/fu/Jump.scala
0 → 100644
浏览文件 @
706f729c
package
xiangshan.backend.fu
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.utils._
import
xiangshan.backend._
import
xiangshan.backend.fu.FunctionUnit._
class
Jump
extends
FunctionUnit
(
jmpCfg
){
val
io
=
IO
(
new
ExuIO
)
override
def
toString
:
String
=
"Bru"
val
(
iovalid
,
src1
,
offset
,
func
,
pc
,
uop
)
=
(
io
.
in
.
valid
,
io
.
in
.
bits
.
src1
,
io
.
in
.
bits
.
uop
.
ctrl
.
imm
,
io
.
in
.
bits
.
uop
.
ctrl
.
fuOpType
,
SignExt
(
io
.
in
.
bits
.
uop
.
cf
.
pc
,
AddrBits
),
io
.
in
.
bits
.
uop
)
val
redirectHit
=
uop
.
brTag
.
needFlush
(
io
.
redirect
)
val
valid
=
iovalid
&&
!
redirectHit
val
isCSR
=
BRUOpType
.
isCSR
(
func
)
val
isFMV
=
BRUOpType
.
isFMV
(
func
)
val
isMOU
=
BRUOpType
.
isMOU
(
func
)
val
isJUMP
=
BRUOpType
.
isJUMP
(
func
)
// JUMP
val
isRVC
=
uop
.
cf
.
isRVC
val
pcDelaySlot
=
Mux
(
isRVC
,
pc
+
2.
U
,
pc
+
4.
U
)
val
target
=
src1
+
offset
// NOTE: src1 is (pc/rf(rs1)), src2 is (offset)
io
.
out
.
bits
.
redirectValid
:=
valid
&&
isJUMP
io
.
out
.
bits
.
redirect
.
target
:=
target
io
.
out
.
bits
.
redirect
.
brTag
:=
uop
.
brTag
io
.
out
.
bits
.
redirect
.
isException
:=
false
.
B
io
.
out
.
bits
.
redirect
.
roqIdx
:=
uop
.
roqIdx
io
.
out
.
bits
.
redirect
.
freelistAllocPtr
:=
uop
.
freelistAllocPtr
// Output
val
resCSR
=
WireInit
(
0.
U
(
XLEN
.
W
))
// TODO: implement it
val
resFMV
=
WireInit
(
0.
U
(
XLEN
.
W
))
// TODO: implement it
val
resMOU
=
WireInit
(
0.
U
(
XLEN
.
W
))
// TODO: implement it
val
resJMP
=
pcDelaySlot
val
res
=
ParallelMux
(
VecInit
(
isCSR
,
isFMV
,
isMOU
,
isJUMP
)
zip
VecInit
(
resCSR
,
resFMV
,
resMOU
,
resJMP
)
)
io
.
in
.
ready
:=
io
.
out
.
ready
io
.
out
.
valid
:=
valid
// TODO: CSR/MOU/FMV may need change it
io
.
out
.
bits
.
uop
<>
io
.
in
.
bits
.
uop
io
.
out
.
bits
.
data
:=
res
// NOTE: the debug info is for one-cycle exec, if FMV needs multi-cycle, may needs change it
XSDebug
(
io
.
in
.
valid
,
"In(%d %d) Out(%d %d) Redirect:(%d %d %d) brTag:%x\n"
,
io
.
in
.
valid
,
io
.
in
.
ready
,
io
.
out
.
valid
,
io
.
out
.
ready
,
io
.
redirect
.
valid
,
io
.
redirect
.
bits
.
isException
,
redirectHit
,
io
.
redirect
.
bits
.
brTag
.
value
)
XSDebug
(
io
.
in
.
valid
&&
isCSR
,
"src1:%x offset:%x func:%b type:CSR pc:%x\n"
,
src1
,
offset
,
func
,
pc
)
XSDebug
(
io
.
in
.
valid
&&
isFMV
,
"src1:%x offset:%x func:%b type:FMV pc:%x\n"
,
src1
,
offset
,
func
,
pc
)
XSDebug
(
io
.
in
.
valid
&&
isMOU
,
"src1:%x offset:%x func:%b type:MOU pc:%x\n"
,
src1
,
offset
,
func
,
pc
)
XSDebug
(
io
.
in
.
valid
&&
isJUMP
,
"src1:%x offset:%x func:%b type:JUMP pc:%x\n"
,
src1
,
offset
,
func
,
pc
)
XSDebug
(
io
.
in
.
valid
,
"Res:%x` CsrRes:%x FMV:%x Mou:%x Jmp:%x\n"
,
res
,
resCSR
,
resFMV
,
resMOU
,
resJMP
)
}
src/main/scala/xiangshan/backend/fu/Multiplier.scala
0 → 100644
浏览文件 @
706f729c
package
xiangshan.backend.fu
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.utils._
import
xiangshan.backend._
import
xiangshan.backend.fu.FunctionUnit._
class
MulDivCtrl
extends
Bundle
{
val
uop
=
new
MicroOp
val
sign
=
Bool
()
val
isW
=
Bool
()
val
isHi
=
Bool
()
// return hi bits of result ?
}
class
MulDivOutput
extends
XSBundle
{
val
data
=
UInt
(
XLEN
.
W
)
val
uop
=
new
MicroOp
}
class
MulDivIO
(
val
len
:
Int
)
extends
XSBundle
{
val
in
=
Flipped
(
DecoupledIO
(
new
Bundle
()
{
val
src1
,
src2
=
UInt
(
len
.
W
)
val
ctrl
=
new
MulDivCtrl
}))
val
out
=
DecoupledIO
(
new
MulDivOutput
)
val
redirect
=
Flipped
(
ValidIO
(
new
Redirect
))
}
abstract
class
Multiplier
(
val
len
:
Int
,
val
latency
:
Int
=
3
)
extends
FunctionUnit
(
mulCfg
)
{
val
io
=
IO
(
new
MulDivIO
(
len
))
}
trait
HasPipelineReg
{
this:
ArrayMultiplier
=>
val
validVec
=
io
.
in
.
valid
+:
Array
.
fill
(
latency
)(
RegInit
(
false
.
B
))
val
rdyVec
=
Array
.
fill
(
latency
)(
Wire
(
Bool
()))
:+
io
.
out
.
ready
val
ctrlVec
=
io
.
in
.
bits
.
ctrl
+:
Array
.
fill
(
latency
)(
Reg
(
new
MulDivCtrl
))
val
flushVec
=
ctrlVec
.
zip
(
validVec
).
map
(
x
=>
x
.
_2
&&
x
.
_1
.
uop
.
brTag
.
needFlush
(
io
.
redirect
))
for
(
i
<-
0
until
latency
){
rdyVec
(
i
)
:=
!
validVec
(
i
+
1
)
||
rdyVec
(
i
+
1
)
}
for
(
i
<-
1
to
latency
){
when
(
flushVec
(
i
)
||
rdyVec
(
i
)
&&
!
validVec
(
i
-
1
)){
validVec
(
i
)
:=
false
.
B
}.
elsewhen
(
rdyVec
(
i
-
1
)
&&
validVec
(
i
-
1
)
&&
!
flushVec
(
i
-
1
)){
validVec
(
i
)
:=
validVec
(
i
-
1
)
ctrlVec
(
i
)
:=
ctrlVec
(
i
-
1
)
}
}
io
.
in
.
ready
:=
rdyVec
(
0
)
io
.
out
.
valid
:=
validVec
.
last
&&
!
flushVec
.
last
io
.
out
.
bits
.
uop
:=
ctrlVec
.
last
.
uop
def
PipelineReg
[
T
<:
Data
](
i
:
Int
)(
next
:
T
)
=
RegEnable
(
next
,
enable
=
validVec
(
i
-
1
)
&&
rdyVec
(
i
-
1
)
&&
!
flushVec
(
i
-
1
)
)
def
S1Reg
[
T
<:
Data
](
next
:
T
)
:
T
=
PipelineReg
[
T
](
1
)(
next
)
def
S2Reg
[
T
<:
Data
](
next
:
T
)
:
T
=
PipelineReg
[
T
](
2
)(
next
)
def
S3Reg
[
T
<:
Data
](
next
:
T
)
:
T
=
PipelineReg
[
T
](
3
)(
next
)
def
S4Reg
[
T
<:
Data
](
next
:
T
)
:
T
=
PipelineReg
[
T
](
4
)(
next
)
def
S5Reg
[
T
<:
Data
](
next
:
T
)
:
T
=
PipelineReg
[
T
](
5
)(
next
)
}
class
ArrayMultiplier
(
len
:
Int
,
latency
:
Int
=
3
,
realArray
:
Boolean
=
false
)
extends
Multiplier
(
len
,
latency
)
with
HasPipelineReg
{
val
mulRes
=
io
.
in
.
bits
.
src1
.
asSInt
()
*
io
.
in
.
bits
.
src2
.
asSInt
()
var
dataVec
=
Seq
(
mulRes
.
asUInt
())
for
(
i
<-
1
to
latency
){
dataVec
=
dataVec
:+
PipelineReg
(
i
)(
dataVec
(
i
-
1
))
}
val
xlen
=
io
.
out
.
bits
.
data
.
getWidth
val
res
=
Mux
(
ctrlVec
.
last
.
isHi
,
dataVec
.
last
(
2
*
xlen
-
1
,
xlen
),
dataVec
.
last
(
xlen
-
1
,
0
))
io
.
out
.
bits
.
data
:=
Mux
(
ctrlVec
.
last
.
isW
,
SignExt
(
res
(
31
,
0
),
xlen
),
res
)
XSDebug
(
p
"validVec:${Binary(Cat(validVec))} flushVec:${Binary(Cat(flushVec))}\n"
)(
this
.
name
)
// printf(p"t=${GTimer()} in: v${io.in.valid} r:${io.in.ready}\n")
// printf(p"t=${GTimer()} out: v:${io.out.valid} r:${io.out.ready} vec:${Binary(Cat(validVec))}\n")
}
\ No newline at end of file
src/main/scala/xiangshan/backend/issue/IssueQueue.scala
浏览文件 @
706f729c
...
...
@@ -3,24 +3,39 @@ package xiangshan.backend.issue
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.backend.exu.
{
Exu
,
ExuConfig
}
import
xiangshan.backend.rename.FreeListPtr
import
xiangshan.utils._
import
xiangshan.backend.fu.FunctionUnit._
trait
IQConst
{
val
iqSize
=
8
trait
IQConst
extends
HasXSParameter
{
val
iqSize
=
IssQueSize
val
iqIdxWidth
=
log2Up
(
iqSize
)
}
sealed
abstract
class
IQBundle
extends
XSBundle
with
IQConst
sealed
abstract
class
IQModule
extends
XSModule
with
IQConst
class
IssueQueue
(
val
fuTypeInt
:
BigInt
,
val
wakeupCnt
:
Int
,
val
bypassCnt
:
Int
=
0
,
val
fixedDelay
:
Int
=
1
,
val
fifo
:
Boolean
=
false
)
extends
IQModule
{
object
OneCycleFire
{
def
apply
(
fire
:
Bool
)
=
{
val
valid
=
RegInit
(
false
.
B
)
when
(
valid
)
{
valid
:=
false
.
B
}
when
(
fire
)
{
valid
:=
true
.
B
}
valid
}
}
class
IssueQueue
(
exuCfg
:
ExuConfig
,
val
wakeupCnt
:
Int
,
val
bypassCnt
:
Int
=
0
,
val
fifo
:
Boolean
=
false
)
extends
IQModule
{
val
useBypass
=
bypassCnt
>
0
val
src2Use
=
true
val
src3Use
=
fuTypeInt
==
FuType
.
fmac
.
litValue
(
)
val
src3Use
=
(
exuCfg
.
intSrcCnt
>
2
)
||
(
exuCfg
.
fpSrcCnt
>
2
)
val
src2Listen
=
true
val
src3Listen
=
fuTypeInt
==
FuType
.
fmac
.
litValue
(
)
val
src3Listen
=
(
exuCfg
.
intSrcCnt
>
2
)
||
(
exuCfg
.
fpSrcCnt
>
2
)
val
io
=
IO
(
new
Bundle
()
{
// flush Issue Queue
...
...
@@ -43,6 +58,9 @@ class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int =
// use bypass uops to speculative wake-up
val
bypassUops
=
if
(
useBypass
)
Vec
(
bypassCnt
,
Flipped
(
ValidIO
(
new
MicroOp
)))
else
null
val
bypassData
=
if
(
useBypass
)
Vec
(
bypassCnt
,
Flipped
(
ValidIO
(
new
ExuOutput
)))
else
null
// to Dispatch
val
numExist
=
Output
(
UInt
(
iqIdxWidth
.
W
))
})
val
srcAllNum
=
3
...
...
@@ -78,7 +96,7 @@ class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int =
srcDataWire
:=
srcData
srcData
:=
srcDataWire
// there
is three stage
// there
are three stages
// |-------------|--------------------|--------------|
// |Enq:get state|Deq: select/get data| fire stage |
// |-------------|--------------------|--------------|
...
...
@@ -92,7 +110,9 @@ class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int =
val
popOne
=
Wire
(
Bool
())
io
.
enqCtrl
.
ready
:=
!
full
||
popOne
val
enqSelIq
=
Wire
(
UInt
(
iqIdxWidth
.
W
))
val
enqSrcRdy
=
List
(
Mux
(
SrcType
.
isPcImm
(
io
.
enqCtrl
.
bits
.
src1State
),
true
.
B
,
io
.
enqCtrl
.
bits
.
src1State
===
SrcState
.
rdy
),
Mux
(
SrcType
.
isPcImm
(
io
.
enqCtrl
.
bits
.
src2State
),
true
.
B
,
io
.
enqCtrl
.
bits
.
src2State
===
SrcState
.
rdy
),
Mux
(
SrcType
.
isPcImm
(
io
.
enqCtrl
.
bits
.
src3State
),
true
.
B
,
io
.
enqCtrl
.
bits
.
src3State
===
SrcState
.
rdy
))
val
enqSrcRdy
=
List
(
Mux
(
SrcType
.
isPcImm
(
io
.
enqCtrl
.
bits
.
ctrl
.
src1Type
),
true
.
B
,
io
.
enqCtrl
.
bits
.
src1State
===
SrcState
.
rdy
),
Mux
(
SrcType
.
isPcImm
(
io
.
enqCtrl
.
bits
.
ctrl
.
src2Type
),
true
.
B
,
io
.
enqCtrl
.
bits
.
src2State
===
SrcState
.
rdy
),
Mux
(
SrcType
.
isPcImm
(
io
.
enqCtrl
.
bits
.
ctrl
.
src3Type
),
true
.
B
,
io
.
enqCtrl
.
bits
.
src3State
===
SrcState
.
rdy
))
// state enq
when
(
enqFire
)
{
...
...
@@ -184,7 +204,7 @@ class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int =
// redirect issQue
val
redHitVec
=
List
.
tabulate
(
iqSize
)(
i
=>
issQue
(
i
).
uop
.
brTag
.
needFlush
(
io
.
redirect
))
for
(
i
<-
0
until
iqSize
)
{
for
(
i
<-
validQue
.
indices
)
{
when
(
redHitVec
(
i
)
&&
validQue
(
i
))
{
validQue
(
i
)
:=
false
.
B
}
...
...
@@ -199,7 +219,7 @@ class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int =
val
issueToExu
=
Reg
(
new
ExuInput
)
val
issueToExuValid
=
RegInit
(
false
.
B
)
val
deqFlushHit
=
issueToExu
.
uop
.
brTag
.
needFlush
(
io
.
redirect
)
val
deqCanIn
=
!
issueToExuValid
||
deqFire
||
deqFlushHit
val
deqCanIn
=
!
issueToExuValid
||
io
.
deq
.
ready
||
deqFlushHit
val
toIssFire
=
deqCanIn
&&
has1Rdy
&&
!
isPop
&&
!
selIsRed
popOne
:=
deqCanIn
&&
(
has1Rdy
||
isPop
)
// send a empty or valid term to issueStage
...
...
@@ -220,7 +240,6 @@ class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int =
io
.
deq
.
valid
:=
issueToExuValid
&&
!
deqFlushHit
io
.
deq
.
bits
:=
issueToExu
enqSelIq
:=
Mux
(
full
,
Mux
(
isPop
,
idQue
(
popSel
),
...
...
@@ -229,19 +248,43 @@ class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int =
idQue
(
tail
)
)
// Note: direct by IQue's idx, different from deqSel
io
.
numExist
:=
Mux
(
tailAll
===
iqSize
.
U
,
(
iqSize
-
1
).
U
,
tailAll
)
assert
(
tailAll
<
9.
U
)
//-----------------------------------------
// Issue with No Delay
//-----------------------------------------
// when enq is ready && no other rdy && no pop && fireStage is ready && no flush
// send out directly without store the data
val
enqAlreadyRdy
=
if
(
src3Listen
)
{
if
(
src2Listen
)
enqSrcRdy
(
0
)&&
enqSrcRdy
(
1
)&&
enqSrcRdy
(
2
)
else
enqSrcRdy
(
0
)&&
enqSrcRdy
(
2
)
}
else
{
if
(
src2Listen
)
enqSrcRdy
(
0
)&&
enqSrcRdy
(
1
)
else
enqSrcRdy
(
0
)
}
val
enqALRdyNext
=
OneCycleFire
(
enqAlreadyRdy
&&
enqFire
)
val
enqSendFlushHit
=
issQue
(
enqSelIqNext
).
uop
.
brTag
.
needFlush
(
io
.
redirect
)
val
enqSendEnable
=
if
(
fifo
)
{
RegNext
(
tailAll
===
0.
U
)
&&
enqALRdyNext
&&
(!
issueToExuValid
||
deqFlushHit
)
&&
(
enqSelIqNext
===
deqSelIq
)
&&
!
isPop
&&
!
enqSendFlushHit
/* && has1Rdy*//* && io.deq.ready*/
}
else
{
enqALRdyNext
&&
(!
issueToExuValid
||
deqFlushHit
)
&&
(
enqSelIqNext
===
deqSelIq
)
&&
!
isPop
&&
!
enqSendFlushHit
/* && has1Rdy*//* && io.deq.ready*/
}
// FIXME: has1Rdy has combination loop
when
(
enqSendEnable
)
{
io
.
deq
.
valid
:=
true
.
B
io
.
deq
.
bits
:=
issQue
(
enqSelIqNext
)
io
.
deq
.
bits
.
src1
:=
enqDataVec
(
0
)
if
(
src2Use
)
{
io
.
deq
.
bits
.
src2
:=
enqDataVec
(
1
)
}
if
(
src3Use
)
{
io
.
deq
.
bits
.
src3
:=
enqDataVec
(
2
)
}
issueToExuValid
:=
false
.
B
when
(!
io
.
deq
.
ready
)
{
// if Func Unit is not ready, store it to FireStage
issueToExuValid
:=
true
.
B
}
}
//-----------------------------------------
// Wakeup and Bypass
//-----------------------------------------
if
(
wakeupCnt
>
0
)
{
val
cdbValid
=
List
.
tabulate
(
wakeupCnt
)(
i
=>
io
.
wakeUpPorts
(
i
)
.
valid
)
val
cdbData
=
List
.
tabulate
(
wakeupCnt
)(
i
=>
io
.
wakeUpPorts
(
i
)
.
bits
.
data
)
val
cdbPdest
=
List
.
tabulate
(
wakeupCnt
)(
i
=>
io
.
wakeUpPorts
(
i
)
.
bits
.
uop
.
pdest
)
val
cdbrfWen
=
List
.
tabulate
(
wakeupCnt
)(
i
=>
io
.
wakeUpPorts
(
i
)
.
bits
.
uop
.
ctrl
.
rfWen
)
val
cdbfpWen
=
List
.
tabulate
(
wakeupCnt
)(
i
=>
io
.
wakeUpPorts
(
i
)
.
bits
.
uop
.
ctrl
.
fpWen
)
val
cdbValid
=
io
.
wakeUpPorts
.
map
(
_
.
valid
)
val
cdbData
=
io
.
wakeUpPorts
.
map
(
_
.
bits
.
data
)
val
cdbPdest
=
io
.
wakeUpPorts
.
map
(
_
.
bits
.
uop
.
pdest
)
val
cdbrfWen
=
io
.
wakeUpPorts
.
map
(
_
.
bits
.
uop
.
ctrl
.
rfWen
)
val
cdbfpWen
=
io
.
wakeUpPorts
.
map
(
_
.
bits
.
uop
.
ctrl
.
fpWen
)
for
(
i
<-
0
until
iqSize
)
{
for
(
i
<-
idQue
.
indices
)
{
// Should be IssQue.indices but Mem() does not support
for
(
j
<-
0
until
srcListenNum
)
{
val
hitVec
=
List
.
tabulate
(
wakeupCnt
)
(
k
=>
psrc
(
i
)(
j
)
===
cdbPdest
(
k
)
&&
cdbValid
(
k
)
&&
(
srcType
(
i
)(
j
)===
SrcType
.
reg
&&
cdbrfWen
(
k
)
||
srcType
(
i
)(
j
)===
SrcType
.
fp
&&
cdbfpWen
(
k
)))
val
hitVec
=
cdbValid
.
indices
.
map
(
k
=>
psrc
(
i
)(
j
)
===
cdbPdest
(
k
)
&&
cdbValid
(
k
)
&&
(
srcType
(
i
)(
j
)===
SrcType
.
reg
&&
cdbrfWen
(
k
)
||
srcType
(
i
)(
j
)===
SrcType
.
fp
&&
cdbfpWen
(
k
)))
val
hit
=
ParallelOR
(
hitVec
).
asBool
val
data
=
ParallelMux
(
hitVec
zip
cdbData
)
when
(
validQue
(
i
)
&&
!
srcRdyVec
(
i
)(
j
)
&&
hit
)
{
...
...
@@ -249,36 +292,36 @@ class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int =
srcRdyVec
(
i
)(
j
)
:=
true
.
B
}
// XSDebug(validQue(i) && !srcRdyVec(i)(j) && hit, "WakeUp: Sel:%d Src:(%d|%d) Rdy:%d Hit:%d HitVec:%b Data:%x\n", i.U, j.U, psrc(i)(j), srcRdyVec(i)(j), hit, VecInit(hitVec).asUInt, data)
for
(
k
<-
0
until
wakeupCnt
)
{
for
(
k
<-
cdbValid
.
indices
)
{
XSDebug
(
validQue
(
i
)
&&
!
srcRdyVec
(
i
)(
j
)
&&
hit
&&
hitVec
(
k
),
"WakeUpHit: IQIdx:%d Src%d:%d Ports:%d Data:%x Pc:%x RoqIdx:%x\n"
,
i
.
U
,
j
.
U
,
psrc
(
i
)(
j
),
k
.
U
,
cdbData
(
k
),
io
.
wakeUpPorts
(
k
).
bits
.
uop
.
cf
.
pc
,
io
.
wakeUpPorts
(
k
).
bits
.
uop
.
roqIdx
)
}
}
}
}
if
(
useBypass
)
{
val
bpPdest
=
List
.
tabulate
(
bypassCnt
)(
i
=>
io
.
bypassUops
(
i
)
.
bits
.
pdest
)
val
bpValid
=
List
.
tabulate
(
bypassCnt
)(
i
=>
io
.
bypassUops
(
i
)
.
valid
)
val
bpData
=
List
.
tabulate
(
bypassCnt
)(
i
=>
io
.
bypassData
(
i
)
.
bits
.
data
)
val
bprfWen
=
List
.
tabulate
(
bypassCnt
)(
i
=>
io
.
bypassUops
(
i
)
.
bits
.
ctrl
.
rfWen
)
val
bpfpWen
=
List
.
tabulate
(
bypassCnt
)(
i
=>
io
.
bypassUops
(
i
)
.
bits
.
ctrl
.
fpWen
)
val
bpPdest
=
io
.
bypassUops
.
map
(
_
.
bits
.
pdest
)
val
bpValid
=
io
.
bypassUops
.
map
(
_
.
valid
)
val
bpData
=
io
.
bypassData
.
map
(
_
.
bits
.
data
)
val
bprfWen
=
io
.
bypassUops
.
map
(
_
.
bits
.
ctrl
.
rfWen
)
val
bpfpWen
=
io
.
bypassUops
.
map
(
_
.
bits
.
ctrl
.
fpWen
)
for
(
i
<-
0
until
iqSize
)
{
for
(
i
<-
idQue
.
indices
)
{
// Should be IssQue.indices but Mem() does not support
for
(
j
<-
0
until
srcListenNum
)
{
val
hitVec
=
List
.
tabulate
(
bypassCnt
)
(
k
=>
psrc
(
i
)(
j
)
===
bpPdest
(
k
)
&&
bpValid
(
k
)
&&
(
srcType
(
i
)(
j
)===
SrcType
.
reg
&&
bprfWen
(
k
)
||
srcType
(
i
)(
j
)===
SrcType
.
fp
&&
bpfpWen
(
k
)))
val
hitVec
=
bpValid
.
indices
.
map
(
k
=>
psrc
(
i
)(
j
)
===
bpPdest
(
k
)
&&
bpValid
(
k
)
&&
(
srcType
(
i
)(
j
)===
SrcType
.
reg
&&
bprfWen
(
k
)
||
srcType
(
i
)(
j
)===
SrcType
.
fp
&&
bpfpWen
(
k
)))
val
hitVecNext
=
hitVec
.
map
(
RegNext
(
_
))
val
hit
=
ParallelOR
(
hitVec
).
asBool
when
(
validQue
(
i
)
&&
!
srcRdyVec
(
i
)(
j
)
&&
hit
)
{
srcRdyVec
(
i
)(
j
)
:=
true
.
B
// FIXME: if uncomment the up comment, will cause combiantional loop, but it is Mem type??
srcRdyVec
(
i
)(
j
)
:=
true
.
B
}
when
(
RegNext
(
validQue
(
i
)
&&
!
srcRdyVec
(
i
)(
j
)
&&
hit
))
{
srcDataWire
(
i
)(
j
)
:=
PriorityMux
(
hitVecNext
zip
bpData
)
}
// XSDebug(validQue(i) && !srcRdyVec(i)(j) && hit, "BypassCtrl: Sel:%d Src:(%d|%d) Rdy:%d Hit:%d HitVec:%b\n", i.U, j.U, psrc(i)(j), srcRdyVec(i)(j), hit, VecInit(hitVec).asUInt)
for
(
k
<-
0
until
bypassCnt
)
{
for
(
k
<-
bpValid
.
indices
)
{
XSDebug
(
validQue
(
i
)
&&
!
srcRdyVec
(
i
)(
j
)
&&
hit
&&
hitVec
(
k
),
"BypassCtrlHit: IQIdx:%d Src%d:%d Ports:%d Pc:%x RoqIdx:%x\n"
,
i
.
U
,
j
.
U
,
psrc
(
i
)(
j
),
k
.
U
,
io
.
bypassUops
(
k
).
bits
.
cf
.
pc
,
io
.
bypassUops
(
k
).
bits
.
roqIdx
)
}
// XSDebug(RegNext(validQue(i) && !srcRdyVec(i)(j) && hit), "BypassData: Sel:%d Src:(%d|%d) HitVecNext:%b Data:%x (for last cycle's Ctrl)\n", i.U, j.U, psrc(i)(j), VecInit(hitVecNext).asUInt, ParallelMux(hitVecNext zip bpData))
for
(
k
<-
0
until
bypassCnt
)
{
for
(
k
<-
bpValid
.
indices
)
{
XSDebug
(
RegNext
(
validQue
(
i
)
&&
!
srcRdyVec
(
i
)(
j
)
&&
hit
&&
hitVec
(
k
)),
"BypassDataHit: IQIdx:%d Src%d:%d Ports:%d Data:%x Pc:%x RoqIdx:%x\n"
,
i
.
U
,
j
.
U
,
psrc
(
i
)(
j
),
k
.
U
,
bpData
(
k
),
io
.
bypassUops
(
k
).
bits
.
cf
.
pc
,
io
.
bypassUops
(
k
).
bits
.
roqIdx
)
}
}
...
...
@@ -289,7 +332,7 @@ class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int =
val
enqPsrc
=
List
(
enqCtrl
.
bits
.
psrc1
,
enqCtrl
.
bits
.
psrc2
,
enqCtrl
.
bits
.
psrc3
)
val
enqSrcType
=
List
(
enqCtrl
.
bits
.
ctrl
.
src1Type
,
enqCtrl
.
bits
.
ctrl
.
src2Type
,
enqCtrl
.
bits
.
ctrl
.
src3Type
)
for
(
i
<-
0
until
srcListenNum
)
{
val
hitVec
=
List
.
tabulate
(
bypassCnt
)
(
j
=>
enqPsrc
(
i
)===
bpPdest
(
j
)
&&
bpValid
(
j
)
&&
(
enqSrcType
(
i
)===
SrcType
.
reg
&&
bprfWen
(
j
)
||
enqSrcType
(
i
)===
SrcType
.
fp
&&
bpfpWen
(
j
)))
val
hitVec
=
bpValid
.
indices
.
map
(
j
=>
enqPsrc
(
i
)===
bpPdest
(
j
)
&&
bpValid
(
j
)
&&
(
enqSrcType
(
i
)===
SrcType
.
reg
&&
bprfWen
(
j
)
||
enqSrcType
(
i
)===
SrcType
.
fp
&&
bpfpWen
(
j
)))
val
hitVecNext
=
hitVec
.
map
(
RegNext
(
_
))
val
hit
=
ParallelOR
(
hitVec
).
asBool
when
(
enqFire
&&
hit
&&
!
enqSrcRdy
(
i
))
{
...
...
@@ -299,17 +342,16 @@ class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int =
srcDataWire
(
enqSelIqNext
)(
i
)
:=
ParallelMux
(
hitVecNext
zip
bpData
)
}
// XSDebug(enqFire && hit, "EnqBypassCtrl: enqSelIq:%d Src:(%d|%d) Hit:%d HitVec:%b \n", enqSelIq, i.U, enqPsrc(i), hit, VecInit(hitVec).asUInt)
for
(
k
<-
0
until
bypassCnt
)
{
for
(
k
<-
bpValid
.
indices
)
{
XSDebug
(
enqFire
&&
hit
&&
!
enqSrcRdy
(
i
)
&&
hitVec
(
k
),
"EnqBypassCtrlHit: enqSelIq:%d Src%d:%d Ports:%d Pc:%x RoqIdx:%x\n"
,
enqSelIq
,
i
.
U
,
enqPsrc
(
i
),
k
.
U
,
io
.
bypassUops
(
k
).
bits
.
cf
.
pc
,
io
.
bypassUops
(
k
).
bits
.
roqIdx
)
}
// XSDebug(RegNext(enqFire && hit), "EnqBypassData: enqSelIqNext:%d Src:(%d|%d) HitVecNext:%b Data:%x (for last cycle's Ctrl)\n", enqSelIqNext, i.U, enqPsrc(i), VecInit(hitVecNext).asUInt, ParallelMux(hitVecNext zip bpData))
for
(
k
<-
0
until
bypassCnt
)
{
for
(
k
<-
bpValid
.
indices
)
{
XSDebug
(
RegNext
(
enqFire
&&
hit
&&
!
enqSrcRdy
(
i
)
&&
hitVec
(
k
)),
"EnqBypassDataHit: enqSelIq:%d Src%d:%d Ports:%d Data:%x Pc:%x RoqIdx:%x\n"
,
enqSelIq
,
i
.
U
,
enqPsrc
(
i
),
k
.
U
,
bpData
(
k
),
io
.
bypassUops
(
k
).
bits
.
cf
.
pc
,
io
.
bypassUops
(
k
).
bits
.
roqIdx
)
}
}
// send out bypass
assert
(
fixedDelay
==
1
)
// only support fixedDelay is 1 now
val
sel
=
io
.
selectedUop
sel
.
valid
:=
toIssFire
sel
.
bits
:=
DontCare
...
...
@@ -331,7 +373,10 @@ class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int =
}
else
{
XSDebug
(
"popOne:%d isPop:%d popSel:%d deqSel:%d deqCanIn:%d toIssFire:%d has1Rdy:%d selIsRed:%d nonValid:%b\n"
,
popOne
,
isPop
,
popSel
,
deqSel
,
deqCanIn
,
toIssFire
,
has1Rdy
,
selIsRed
,
nonValid
)
}
XSDebug
(
"id|v|r|psrc|r| src1 |psrc|r| src2 |psrc|r| src3 |brTag| pc |roqIdx FuType:%x\n"
,
fuTypeInt
.
U
)
XSDebug
(
enqSendEnable
,
p
"NoDelayIss: enqALRdy:${enqAlreadyRdy} *Next:${enqALRdyNext} En:${enqSendEnable} flush:${enqSendFlushHit} enqSelIqNext:${enqSelIqNext} deqSelIq:${deqSelIq} deqReady:${io.deq.ready}\n"
)
XSDebug
(
s
"id|v|r|psrc|r| src1 |psrc|r| src2 |psrc|r| src3 |brTag| pc |roqIdx Exu:${exuCfg.name}\n"
)
for
(
i
<-
0
until
iqSize
)
{
when
(
i
.
U
===
tail
&&
tailAll
=/=
8.
U
)
{
XSDebug
(
"%d |%d|%d| %d|%b|%x| %d|%b|%x| %d|%b|%x| %x |%x|%x <-\n"
,
...
...
src/main/scala/xiangshan/backend/package.scala
浏览文件 @
706f729c
...
...
@@ -83,15 +83,6 @@ package object backend {
def
isBranchInvert
(
func
:
UInt
)
=
func
(
0
)
}
object
MULOpType
{
def
mul
=
"b0000"
.
U
def
mulh
=
"b0001"
.
U
def
mulhsu
=
"b0010"
.
U
def
mulhu
=
"b0011"
.
U
def
mulw
=
"b1000"
.
U
}
object
MDUOpType
{
def
mul
=
"b0000"
.
U
def
mulh
=
"b0001"
.
U
...
...
@@ -114,7 +105,7 @@ package object backend {
def
isW
(
op
:
UInt
)
=
op
(
3
)
}
object
L
D
UOpType
{
object
L
S
UOpType
{
def
lb
=
"b000000"
.
U
def
lh
=
"b000001"
.
U
def
lw
=
"b000010"
.
U
...
...
@@ -122,37 +113,28 @@ package object backend {
def
lbu
=
"b000100"
.
U
def
lhu
=
"b000101"
.
U
def
lwu
=
"b000110"
.
U
def
flw
=
"b010110"
.
U
// box 32-bit data to 64-bit with 1s
// def lr = "b100000".U
// def sc = "b100001".U
// def amoswap = "b100010".U
// def amoadd = "b100011".U
// def amoxor = "b100100".U
// def amoand = "b100101".U
// def amoor = "b100110".U
// def amomin = "b110111".U
// def amomax = "b110000".U
// def amominu = "b110001".U
// def amomaxu = "b110010".U
def
isStore
(
func
:
UInt
)
:
Bool
=
func
(
3
)
def
isAtom
(
func
:
UInt
)
:
Bool
=
func
(
5
)
def
isLoad
(
func
:
UInt
)
:
Bool
=
!
isStore
(
func
)
&
!
isAtom
(
func
)
// def isLR(func: UInt): Bool = func === lr
// def isSC(func: UInt): Bool = func === sc
// def isAMO(func: UInt): Bool = isAtom(func) && !isLR(func) && !isSC(func)
// def atomW = "010".U
// def atomD = "011".U
}
object
STUOpType
{
def
sb
=
"b001000"
.
U
def
sh
=
"b001001"
.
U
def
sw
=
"b001010"
.
U
def
sd
=
"b001011"
.
U
def
lr
=
"b100010"
.
U
def
sc
=
"b100011"
.
U
def
amoswap
=
"b100001"
.
U
def
amoadd
=
"b100000"
.
U
def
amoxor
=
"b100100"
.
U
def
amoand
=
"b101100"
.
U
def
amoor
=
"b101000"
.
U
def
amomin
=
"b110000"
.
U
def
amomax
=
"b110100"
.
U
def
amominu
=
"b111000"
.
U
def
amomaxu
=
"b111100"
.
U
def
isStore
(
func
:
UInt
)
:
Bool
=
func
(
3
)
def
isAtom
(
func
:
UInt
)
:
Bool
=
func
(
5
)
def
atomW
=
"010"
.
U
def
atomD
=
"011"
.
U
}
...
...
src/main/scala/xiangshan/backend/roq/Roq.scala
浏览文件 @
706f729c
...
...
@@ -15,7 +15,7 @@ class Roq(implicit val p: XSConfig) extends XSModule {
val
roqIdxs
=
Output
(
Vec
(
RenameWidth
,
UInt
(
RoqIdxWidth
.
W
)))
val
redirect
=
Output
(
Valid
(
new
Redirect
))
// exu + brq
val
exeWbResults
=
Vec
(
exu
Config
.
ExuCnt
+
1
,
Flipped
(
ValidIO
(
new
ExuOutput
)))
val
exeWbResults
=
Vec
(
exu
Parameters
.
ExuCnt
+
1
,
Flipped
(
ValidIO
(
new
ExuOutput
)))
val
commits
=
Vec
(
CommitWidth
,
Valid
(
new
RoqCommit
))
val
scommit
=
Output
(
UInt
(
3.
W
))
})
...
...
src/main/scala/xiangshan/frontend/Ibuffer.scala
浏览文件 @
706f729c
package
xiangshan.frontend
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.utils._
class
Ibuffer
extends
XSModule
{
val
io
=
IO
(
new
Bundle
()
{
val
flush
=
Input
(
Bool
())
val
in
=
Flipped
(
DecoupledIO
(
new
FetchPacket
))
val
out
=
Vec
(
DecodeWidth
,
DecoupledIO
(
new
CtrlFlow
))
})
// ignore
for
(
i
<-
0
until
DecodeWidth
)
{
io
.
out
(
i
).
bits
.
exceptionVec
:=
DontCare
io
.
out
(
i
).
bits
.
intrVec
:=
DontCare
io
.
out
(
i
).
bits
.
isBr
:=
DontCare
}
//mask initial
// val mask = Wire(Vec(FetchWidth*2, false.B))
// (0 until 16).map(i => mask(i.U) := (io.in.bits.pc(4,1) <= i.U))
// ibuf define
val
ibuf
=
Reg
(
Vec
(
IBufSize
*
2
,
UInt
(
16.
W
)))
val
ibuf_pc
=
Reg
(
Vec
(
IBufSize
*
2
,
UInt
(
VAddrBits
.
W
)))
val
ibuf_valid
=
RegInit
(
VecInit
(
Seq
.
fill
(
IBufSize
*
2
)(
false
.
B
)))
val
head_ptr
=
RegInit
(
0.
U
(
log2Up
(
IBufSize
*
2
).
W
))
val
tail_ptr
=
RegInit
(
0.
U
(
log2Up
(
IBufSize
*
2
).
W
))
// true: Last operation is enqueue
// false: Last operation is deq_ueue
val
last_enq
=
RegInit
(
false
.
B
)
val
full
=
head_ptr
===
tail_ptr
&&
last_enq
val
empty
=
head_ptr
===
tail_ptr
&&
!
last_enq
val
enqValid
=
!
io
.
flush
&&
io
.
in
.
valid
&&
!
full
&&
!
ibuf_valid
(
tail_ptr
+
(
FetchWidth
*
2
).
U
)
val
deqValid
=
!
io
.
flush
&&
!
empty
//&& io.out.map(_.ready).reduce(_||_)
io
.
in
.
ready
:=
enqValid
// enque
when
(
enqValid
)
{
var
enq_idx
=
0.
U
(
log2Up
(
FetchWidth
*
2
+
1
).
W
)
for
(
i
<-
0
until
FetchWidth
*
2
)
{
when
(
io
.
in
.
bits
.
mask
(
i
))
{
ibuf
(
tail_ptr
+
enq_idx
)
:=
Mux
(
i
.
U
(
0
),
io
.
in
.
bits
.
instrs
(
i
>>
1
)(
31
,
16
),
io
.
in
.
bits
.
instrs
(
i
>>
1
)(
15
,
0
))
ibuf_pc
(
tail_ptr
+
enq_idx
)
:=
io
.
in
.
bits
.
pc
+
(
enq_idx
<<
1
).
asUInt
ibuf_valid
(
tail_ptr
+
enq_idx
)
:=
true
.
B
}
enq_idx
=
enq_idx
+
io
.
in
.
bits
.
mask
(
i
)
}
tail_ptr
:=
tail_ptr
+
enq_idx
last_enq
:=
true
.
B
}
// deque
when
(
deqValid
)
{
var
deq_idx
=
0.
U
(
log2Up
(
DecodeWidth
*
2
+
1
).
W
)
for
(
i
<-
0
until
DecodeWidth
)
{
when
(
io
.
out
(
i
).
ready
&&
ibuf_valid
(
head_ptr
+
deq_idx
))
{
when
(
ibuf
(
head_ptr
+
deq_idx
)(
1
,
0
)
=/=
"b11"
.
U
)
{
// is RVC
io
.
out
(
i
).
bits
.
instr
:=
Cat
(
0.
U
(
16.
W
),
ibuf
(
head_ptr
+
deq_idx
))
io
.
out
(
i
).
bits
.
pc
:=
ibuf_pc
(
head_ptr
+
deq_idx
)
io
.
out
(
i
).
bits
.
isRVC
:=
true
.
B
io
.
out
(
i
).
valid
:=
true
.
B
ibuf_valid
(
head_ptr
+
deq_idx
)
:=
false
.
B
}.
elsewhen
(
ibuf_valid
(
head_ptr
+
deq_idx
+
1.
U
))
{
// isn't RVC
io
.
out
(
i
).
bits
.
instr
:=
Cat
(
ibuf
(
head_ptr
+
deq_idx
+
1.
U
),
ibuf
(
head_ptr
+
deq_idx
))
io
.
out
(
i
).
bits
.
pc
:=
ibuf_pc
(
head_ptr
+
deq_idx
)
io
.
out
(
i
).
bits
.
isRVC
:=
false
.
B
io
.
out
(
i
).
valid
:=
true
.
B
ibuf_valid
(
head_ptr
+
deq_idx
)
:=
false
.
B
ibuf_valid
(
head_ptr
+
deq_idx
+
1.
U
)
:=
false
.
B
}.
otherwise
{
// half inst keep in buffer
io
.
out
(
i
).
bits
.
instr
:=
0.
U
(
32.
W
)
io
.
out
(
i
).
bits
.
pc
:=
0.
U
(
VAddrBits
.
W
)
io
.
out
(
i
).
bits
.
isRVC
:=
false
.
B
io
.
out
(
i
).
valid
:=
false
.
B
}
}.
otherwise
{
io
.
out
(
i
).
bits
.
instr
:=
Cat
(
ibuf
(
head_ptr
+
(
i
<<
1
).
U
+
1.
U
),
ibuf
(
head_ptr
+
(
i
<<
1
).
U
))
io
.
out
(
i
).
bits
.
pc
:=
ibuf_pc
(
head_ptr
+
(
i
<<
1
).
U
)
io
.
out
(
i
).
bits
.
isRVC
:=
false
.
B
io
.
out
(
i
).
valid
:=
false
.
B
}
// When can't deque, deq_idx+0
// when RVC deque, deq_idx+1
// when not RVC deque, deq_idx+2
// when only have half inst, keep it in buffer
deq_idx
=
deq_idx
+
PriorityMux
(
Seq
(
!(
io
.
out
(
i
).
ready
&&
ibuf_valid
(
head_ptr
+
deq_idx
))
->
0.
U
,
(
ibuf
(
head_ptr
+
deq_idx
)(
1
,
0
)
=/=
"b11"
.
U
)
->
1.
U
,
ibuf_valid
(
head_ptr
+
deq_idx
+
1.
U
)
->
2.
U
))
}
head_ptr
:=
head_ptr
+
deq_idx
last_enq
:=
false
.
B
}.
otherwise
{
for
(
i
<-
0
until
DecodeWidth
)
{
io
.
out
(
i
).
bits
.
instr
:=
0.
U
io
.
out
(
i
).
bits
.
pc
:=
0.
U
io
.
out
(
i
).
bits
.
isRVC
:=
false
.
B
io
.
out
(
i
).
valid
:=
false
.
B
}
}
// flush
when
(
io
.
flush
)
{
for
(
i
<-
0
until
IBufSize
*
2
)
{
ibuf_valid
(
i
)
:=
false
.
B
}
head_ptr
:=
0.
U
tail_ptr
:=
0.
U
for
(
i
<-
0
until
DecodeWidth
)
{
io
.
out
(
i
).
valid
:=
false
.
B
}
}
//Debug Info
XSDebug
(
enqValid
,
"Enque:\n"
)
for
(
i
<-
0
until
FetchWidth
)
{
XSDebug
(
enqValid
,
p
"${Binary(io.in.bits.instrs(i))}\n"
)
}
XSInfo
(
io
.
flush
,
"Flush signal received, clear buffer\n"
)
XSDebug
(
deqValid
,
"Deque:\n"
)
for
(
i
<-
0
until
DecodeWidth
)
{
XSDebug
(
deqValid
,
p
"${Binary(io.out(i).bits.instr)} PC=${Hexadecimal(io.out(i).bits.pc)} v=${io.out(i).valid} r=${io.out(i).ready}\n"
)
}
XSDebug
(
enqValid
,
p
"last_head_ptr=$head_ptr last_tail_ptr=$tail_ptr\n"
)
// XSInfo(full, "Queue is full\n")
}
package
xiangshan.frontend
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.utils._
class
Ibuffer
extends
XSModule
{
val
io
=
IO
(
new
Bundle
()
{
val
flush
=
Input
(
Bool
())
val
in
=
Flipped
(
DecoupledIO
(
new
FetchPacket
))
val
out
=
Vec
(
DecodeWidth
,
DecoupledIO
(
new
CtrlFlow
))
})
// ignore
for
(
i
<-
0
until
DecodeWidth
)
{
io
.
out
(
i
).
bits
.
exceptionVec
:=
DontCare
io
.
out
(
i
).
bits
.
intrVec
:=
DontCare
io
.
out
(
i
).
bits
.
isBr
:=
DontCare
}
//mask initial
// val mask = Wire(Vec(FetchWidth*2, false.B))
// (0 until 16).map(i => mask(i.U) := (io.in.bits.pc(4,1) <= i.U))
// ibuf define
val
ibuf
=
Reg
(
Vec
(
IBufSize
*
2
,
UInt
(
16.
W
)))
val
ibuf_pc
=
Reg
(
Vec
(
IBufSize
*
2
,
UInt
(
VAddrBits
.
W
)))
val
ibuf_valid
=
RegInit
(
VecInit
(
Seq
.
fill
(
IBufSize
*
2
)(
false
.
B
)))
val
head_ptr
=
RegInit
(
0.
U
(
log2Up
(
IBufSize
*
2
).
W
))
val
tail_ptr
=
RegInit
(
0.
U
(
log2Up
(
IBufSize
*
2
).
W
))
// true: Last operation is enqueue
// false: Last operation is deq_ueue
val
last_enq
=
RegInit
(
false
.
B
)
val
full
=
head_ptr
===
tail_ptr
&&
last_enq
val
empty
=
head_ptr
===
tail_ptr
&&
!
last_enq
val
enqValid
=
!
io
.
flush
&&
io
.
in
.
valid
&&
!
full
&&
!
ibuf_valid
(
tail_ptr
+
(
FetchWidth
*
2
).
U
)
val
deqValid
=
!
io
.
flush
&&
!
empty
//&& io.out.map(_.ready).reduce(_||_)
io
.
in
.
ready
:=
enqValid
// enque
when
(
enqValid
)
{
var
enq_idx
=
0.
U
(
log2Up
(
FetchWidth
*
2
+
1
).
W
)
for
(
i
<-
0
until
FetchWidth
*
2
)
{
when
(
io
.
in
.
bits
.
mask
(
i
))
{
ibuf
(
tail_ptr
+
enq_idx
)
:=
Mux
(
i
.
U
(
0
),
io
.
in
.
bits
.
instrs
(
i
>>
1
)(
31
,
16
),
io
.
in
.
bits
.
instrs
(
i
>>
1
)(
15
,
0
))
ibuf_pc
(
tail_ptr
+
enq_idx
)
:=
io
.
in
.
bits
.
pc
+
(
enq_idx
<<
1
).
asUInt
ibuf_valid
(
tail_ptr
+
enq_idx
)
:=
true
.
B
}
enq_idx
=
enq_idx
+
io
.
in
.
bits
.
mask
(
i
)
}
tail_ptr
:=
tail_ptr
+
enq_idx
last_enq
:=
true
.
B
}
// deque
when
(
deqValid
)
{
var
deq_idx
=
0.
U
(
log2Up
(
DecodeWidth
*
2
+
1
).
W
)
for
(
i
<-
0
until
DecodeWidth
)
{
when
(
io
.
out
(
i
).
ready
&&
ibuf_valid
(
head_ptr
+
deq_idx
))
{
when
(
ibuf
(
head_ptr
+
deq_idx
)(
1
,
0
)
=/=
"b11"
.
U
)
{
// is RVC
io
.
out
(
i
).
bits
.
instr
:=
Cat
(
0.
U
(
16.
W
),
ibuf
(
head_ptr
+
deq_idx
))
io
.
out
(
i
).
bits
.
pc
:=
ibuf_pc
(
head_ptr
+
deq_idx
)
io
.
out
(
i
).
bits
.
isRVC
:=
true
.
B
io
.
out
(
i
).
valid
:=
true
.
B
ibuf_valid
(
head_ptr
+
deq_idx
)
:=
false
.
B
}.
elsewhen
(
ibuf_valid
(
head_ptr
+
deq_idx
+
1.
U
))
{
// isn't RVC
io
.
out
(
i
).
bits
.
instr
:=
Cat
(
ibuf
(
head_ptr
+
deq_idx
+
1.
U
),
ibuf
(
head_ptr
+
deq_idx
))
io
.
out
(
i
).
bits
.
pc
:=
ibuf_pc
(
head_ptr
+
deq_idx
)
io
.
out
(
i
).
bits
.
isRVC
:=
false
.
B
io
.
out
(
i
).
valid
:=
true
.
B
ibuf_valid
(
head_ptr
+
deq_idx
)
:=
false
.
B
ibuf_valid
(
head_ptr
+
deq_idx
+
1.
U
)
:=
false
.
B
}.
otherwise
{
// half inst keep in buffer
io
.
out
(
i
).
bits
.
instr
:=
0.
U
(
32.
W
)
io
.
out
(
i
).
bits
.
pc
:=
0.
U
(
VAddrBits
.
W
)
io
.
out
(
i
).
bits
.
isRVC
:=
false
.
B
io
.
out
(
i
).
valid
:=
false
.
B
}
}.
otherwise
{
io
.
out
(
i
).
bits
.
instr
:=
Cat
(
ibuf
(
head_ptr
+
(
i
<<
1
).
U
+
1.
U
),
ibuf
(
head_ptr
+
(
i
<<
1
).
U
))
io
.
out
(
i
).
bits
.
pc
:=
ibuf_pc
(
head_ptr
+
(
i
<<
1
).
U
)
io
.
out
(
i
).
bits
.
isRVC
:=
false
.
B
io
.
out
(
i
).
valid
:=
false
.
B
}
// When can't deque, deq_idx+0
// when RVC deque, deq_idx+1
// when not RVC deque, deq_idx+2
// when only have half inst, keep it in buffer
deq_idx
=
deq_idx
+
PriorityMux
(
Seq
(
!(
io
.
out
(
i
).
ready
&&
ibuf_valid
(
head_ptr
+
deq_idx
))
->
0.
U
,
(
ibuf
(
head_ptr
+
deq_idx
)(
1
,
0
)
=/=
"b11"
.
U
)
->
1.
U
,
ibuf_valid
(
head_ptr
+
deq_idx
+
1.
U
)
->
2.
U
))
}
head_ptr
:=
head_ptr
+
deq_idx
last_enq
:=
false
.
B
}.
otherwise
{
for
(
i
<-
0
until
DecodeWidth
)
{
io
.
out
(
i
).
bits
.
instr
:=
0.
U
io
.
out
(
i
).
bits
.
pc
:=
0.
U
io
.
out
(
i
).
bits
.
isRVC
:=
false
.
B
io
.
out
(
i
).
valid
:=
false
.
B
}
}
// flush
when
(
io
.
flush
)
{
for
(
i
<-
0
until
IBufSize
*
2
)
{
ibuf_valid
(
i
)
:=
false
.
B
}
head_ptr
:=
0.
U
tail_ptr
:=
0.
U
for
(
i
<-
0
until
DecodeWidth
)
{
io
.
out
(
i
).
valid
:=
false
.
B
}
}
//Debug Info
XSDebug
(
enqValid
,
"Enque:\n"
)
for
(
i
<-
0
until
FetchWidth
)
{
XSDebug
(
enqValid
,
p
"${Binary(io.in.bits.instrs(i))}\n"
)
}
XSInfo
(
io
.
flush
,
"Flush signal received, clear buffer\n"
)
XSDebug
(
deqValid
,
"Deque:\n"
)
for
(
i
<-
0
until
DecodeWidth
)
{
XSDebug
(
deqValid
,
p
"${Binary(io.out(i).bits.instr)} PC=${Hexadecimal(io.out(i).bits.pc)} v=${io.out(i).valid} r=${io.out(i).ready}\n"
)
}
XSDebug
(
enqValid
,
p
"last_head_ptr=$head_ptr last_tail_ptr=$tail_ptr\n"
)
// XSInfo(full, "Queue is full\n")
}
src/main/scala/xiangshan/package.scala
浏览文件 @
706f729c
...
...
@@ -26,25 +26,45 @@ package object xiangshan {
}
object
FuType
extends
HasXSParameter
{
def
num
=
exuConfig
.
NRFuType
def
bru
=
"b0000"
.
U
def
alu
=
"b0001"
.
U
def
mul
=
"b0010"
.
U
def
mdu
=
"b0011"
.
U
def
fmac
=
"b0100"
.
U
def
fmisc
=
"b0101"
.
U
def
fmiscDivSqrt
=
"b0110"
.
U
def
ldu
=
"b1001"
.
U
def
stu
=
"b1000"
.
U
def
num
=
exuParameters
.
NRFuType
def
jmp
=
"b0000"
.
U
def
i2f
=
"b0001"
.
U
def
csr
=
"b0010"
.
U
def
alu
=
"b0011"
.
U
def
mul
=
"b0100"
.
U
def
div
=
"b0101"
.
U
def
fmac
=
"b1000"
.
U
def
fmisc
=
"b1001"
.
U
def
fDivSqrt
=
"b1010"
.
U
def
ldu
=
"b1100"
.
U
def
stu
=
"b1101"
.
U
def
apply
()
=
UInt
(
log2Up
(
num
).
W
)
def
isIntExu
(
fuType
:
UInt
)
=
fuType
(
3
,
2
)
===
"b00"
.
U
def
isFpExu
(
fuType
:
UInt
)
=
fuType
(
2
)
def
isMemExu
(
fuType
:
UInt
)
=
fuType
(
3
)
def
isIntExu
(
fuType
:
UInt
)
=
!
fuType
(
3
)
def
isFpExu
(
fuType
:
UInt
)
=
fuType
(
3
,
2
)
===
"b10"
.
U
def
isMemExu
(
fuType
:
UInt
)
=
fuType
(
3
,
2
)
===
"b11"
.
U
val
functionNameMap
=
Map
(
jmp
.
litValue
()
->
"jmp"
,
i2f
.
litValue
()
->
"int to float"
,
csr
.
litValue
()
->
"csr"
,
alu
.
litValue
()
->
"alu"
,
mul
.
litValue
()
->
"mul"
,
div
.
litValue
()
->
"div"
,
fmac
.
litValue
()
->
"fmac"
,
fmisc
.
litValue
()
->
"fmisc"
,
fDivSqrt
.
litValue
()
->
"fdiv/fsqrt"
,
ldu
.
litValue
()
->
"load"
,
stu
.
litValue
()
->
"store"
)
}
object
FuOpType
extends
HasXSParameter
{
def
apply
()
=
UInt
(
exu
Config
.
FuOpWidth
.
W
)
def
apply
()
=
UInt
(
exu
Parameters
.
FuOpWidth
.
W
)
}
}
src/test/csrc/emu.h
浏览文件 @
706f729c
...
...
@@ -149,7 +149,7 @@ class Emulator {
tfp
->
open
(
"vlt_dump.vcd"
);
// Open the dump file
#endif
while
(
n
>
0
)
{
while
(
!
is_finish
()
&&
n
>
0
)
{
single_cycle
();
n
--
;
...
...
src/test/scala/top/XSSim.scala
浏览文件 @
706f729c
...
...
@@ -97,3 +97,7 @@ object TestMain extends App {
Seq
(
ChiselGeneratorAnnotation
(()
=>
new
XSSimTop
))
)
}
object
FirMain
extends
App
{
firrtl
.
stage
.
FirrtlMain
.
stage
.
execute
(
args
,
Seq
(
ChiselGeneratorAnnotation
(()
=>
new
XSSimTop
)))
}
src/test/scala/xiangshan/backend/exu/AluTest.scala
浏览文件 @
706f729c
...
...
@@ -19,7 +19,7 @@ class AluTest extends FlatSpec
with
HasPartialDecoupledDriver
{
it
should
"do simple test corrcetly"
in
{
test
(
new
Alu
){
c
=>
test
(
new
Alu
ExeUnit
){
c
=>
c
.
io
.
in
.
initSource
().
setSourceClock
(
c
.
clock
)
c
.
io
.
out
.
initSink
().
setSinkClock
(
c
.
clock
)
...
...
@@ -32,7 +32,7 @@ class AluTest extends FlatSpec
}
it
should
"do random add correctly"
in
{
test
(
new
Alu
){
c
=>
test
(
new
Alu
ExeUnit
){
c
=>
c
.
io
.
in
.
initSource
().
setSourceClock
(
c
.
clock
)
c
.
io
.
out
.
initSink
().
setSinkClock
(
c
.
clock
)
...
...
src/test/scala/xiangshan/backend/exu/LsuTest.scala
浏览文件 @
706f729c
...
...
@@ -6,30 +6,23 @@ import chisel3._
import
chisel3.experimental.BundleLiterals._
import
chiseltest.experimental.TestOptionBuilder._
import
chiseltest.internal.VerilatorBackendAnnotation
import
bus.axi4.AXI4Delayer
import
bus.simplebus.
{
SimpleBusCrossbarNto1
,
SimpleBusUC
}
import
device.AXI4RAM
import
noop.
{
Cache
,
CacheConfig
,
MemMMUIO
,
TLB
,
TLBConfig
}
import
system.CoherenceManager
import
xiangshan._
import
xiangshan.backend.fu.FunctionUnit.lsuCfg
import
xiangshan.testutils._
import
xiangshan.testutils.TestCaseGenerator._
import
scala.util.Random
class
LsuDut
(
dispBegin
:
Int
,
dispEnd
:
Int
)
extends
Exu
(
FuType
.
ldu
.
litValue
(),
readIntRf
=
true
,
readFpRf
=
true
,
writeIntRf
=
true
,
writeFpRf
=
true
)
{
class
LsuDut
(
dispBegin
:
Int
,
dispEnd
:
Int
)
extends
Exu
(
Exu
.
lsuExeUnitCfg
)
{
io
.
dmem
<>
DontCare
val
lsu
=
Module
(
new
Ls
u
)
val
lsu
=
Module
(
new
Ls
ExeUnit
)
lsu
.
io
.
in
<>
io
.
in
lsu
.
io
.
redirect
<>
io
.
redirect
...
...
src/test/scala/xiangshan/backend/exu/MduTest.scala
浏览文件 @
706f729c
...
...
@@ -24,7 +24,7 @@ class MduTest extends FlatSpec
with
HasPartialDecoupledDriver
{
"MUL"
should
"random enq and deq correctly"
in
{
test
(
new
Mul
{
test
(
new
Mul
ExeUnit
{
val
disp_begin
=
WireInit
(
0.
S
(
64.
W
).
asUInt
())
val
disp_end
=
WireInit
((-
1
).
S
(
64.
W
).
asUInt
())
BoringUtils
.
addSource
(
disp_begin
,
"DISPLAY_LOG_START"
)
...
...
@@ -52,7 +52,7 @@ class MduTest extends FlatSpec
"MUL"
should
"dont flush same br tag"
in
{
test
(
new
Mul
{
test
(
new
Mul
ExeUnit
{
val
disp_begin
=
WireInit
(
0.
S
(
64.
W
).
asUInt
())
val
disp_end
=
WireInit
((-
1
).
S
(
64.
W
).
asUInt
())
BoringUtils
.
addSource
(
disp_begin
,
"DISPLAY_LOG_START"
)
...
...
@@ -93,7 +93,7 @@ class MduTest extends FlatSpec
"MDU"
should
"random enq and deq correctly"
in
{
test
(
new
M
du
{
test
(
new
M
ulDivExeUnit
{
val
disp_begin
=
WireInit
(
0.
S
(
64.
W
).
asUInt
())
val
disp_end
=
WireInit
((-
1
).
S
(
64.
W
).
asUInt
())
BoringUtils
.
addSource
(
disp_begin
,
"DISPLAY_LOG_START"
)
...
...
src/test/scala/xiangshan/backend/issue/IssueQueueTest.scala
0 → 100644
浏览文件 @
706f729c
package
xiangshan.backend.issue
import
org.scalatest._
import
chiseltest._
import
chisel3._
import
chisel3.util._
import
chisel3.experimental.BundleLiterals._
import
chiseltest.experimental.TestOptionBuilder._
import
chiseltest.internal.VerilatorBackendAnnotation
import
xiangshan._
import
xiangshan.backend.exu.Exu
import
xiangshan.testutils._
import
xiangshan.testutils.TestCaseGenerator._
import
scala.util.Random
class
IssueQueueTest
extends
FlatSpec
with
ChiselScalatestTester
with
Matchers
with
ParallelTestExecution
with
HasPartialDecoupledDriver
{
it
should
"do enq issue with no delay correctly"
in
{
test
(
new
IssueQueue
(
Exu
.
aluExeUnitCfg
,
wakeupCnt
=
1
,
bypassCnt
=
1
,
fifo
=
false
)
{
AddSinks
()
})
{
c
=>
def
genEnqRdyReq
(
x
:
=>
DecoupledIO
[
MicroOp
],
roq
:
Long
)
=
{
chiselTypeOf
(
x
.
bits
).
Lit
(
_
.
src1State
->
SrcState
.
rdy
,
_
.
src2State
->
SrcState
.
rdy
,
_
.
src3State
->
SrcState
.
rdy
,
_
.
roqIdx
->
roq
.
U
)
}
c
.
io
.
enqCtrl
.
initSource
().
setSourceClock
(
c
.
clock
)
c
.
io
.
deq
.
initSink
().
setSinkClock
(
c
.
clock
)
def
TEST_SIZE
=
2
val
roqSeq
=
(
0
until
TEST_SIZE
)
val
enqPort
=
c
.
io
.
enqCtrl
fork
{
c
.
io
.
enqCtrl
.
enqueuePartialSeq
(
roqSeq
.
map
(
roq
=>
genEnqRdyReq
(
enqPort
,
roq
)))
}.
fork
{
c
.
io
.
deq
.
expectDequeuePartialSeq
(
roqSeq
.
map
(
roq
=>
chiselTypeOf
(
c
.
io
.
deq
.
bits
).
Lit
(
_
.
uop
.
roqIdx
->
roq
.
U
)
))
}.
join
()
}
}
}
\ No newline at end of file
src/test/scala/xiangshan/testutils/TestCaseGenerator.scala
浏览文件 @
706f729c
...
...
@@ -61,15 +61,15 @@ object TestCaseGenerator {
}
def
genLsuLd
(
x
:
=>
ExuInput
,
base
:
Long
,
offset
:
Long
)
=
genLsuInput
(
L
D
UOpType
.
ld
)(
x
,
base
,
offset
,
0
)
genLsuInput
(
L
S
UOpType
.
ld
)(
x
,
base
,
offset
,
0
)
def
genLsuLw
(
x
:
=>
ExuInput
,
base
:
Long
,
offset
:
Long
)
=
genLsuInput
(
L
D
UOpType
.
lw
)(
x
,
base
,
offset
,
0
)
genLsuInput
(
L
S
UOpType
.
lw
)(
x
,
base
,
offset
,
0
)
def
genLsuSd
(
x
:
=>
ExuInput
,
base
:
Long
,
offset
:
Long
,
stData
:
Long
)
=
genLsuInput
(
ST
UOpType
.
sd
)(
x
,
base
,
offset
,
stData
)
genLsuInput
(
LS
UOpType
.
sd
)(
x
,
base
,
offset
,
stData
)
def
genLsuSw
(
x
:
=>
ExuInput
,
base
:
Long
,
offset
:
Long
,
stData
:
Long
)
=
genLsuInput
(
ST
UOpType
.
sw
)(
x
,
base
,
offset
,
stData
)
genLsuInput
(
LS
UOpType
.
sw
)(
x
,
base
,
offset
,
stData
)
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录