Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenXiangShan
XiangShan
提交
8c0bf90f
X
XiangShan
项目概览
OpenXiangShan
/
XiangShan
11 个月 前同步成功
通知
1183
Star
3914
Fork
526
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
X
XiangShan
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
8c0bf90f
编写于
6月 25, 2020
作者:
Y
Your Name
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' into ibuf
上级
b78afa66
98d86110
变更
18
隐藏空白更改
内联
并排
Showing
18 changed file
with
665 addition
and
149 deletion
+665
-149
src/main/scala/xiangshan/Bundle.scala
src/main/scala/xiangshan/Bundle.scala
+1
-1
src/main/scala/xiangshan/XSCore.scala
src/main/scala/xiangshan/XSCore.scala
+7
-0
src/main/scala/xiangshan/backend/Backend.scala
src/main/scala/xiangshan/backend/Backend.scala
+23
-31
src/main/scala/xiangshan/backend/brq/Brq.scala
src/main/scala/xiangshan/backend/brq/Brq.scala
+20
-0
src/main/scala/xiangshan/backend/decode/DecodeStage.scala
src/main/scala/xiangshan/backend/decode/DecodeStage.scala
+8
-2
src/main/scala/xiangshan/backend/decode/Decoder.scala
src/main/scala/xiangshan/backend/decode/Decoder.scala
+5
-0
src/main/scala/xiangshan/backend/dispatch/Dispatch1.scala
src/main/scala/xiangshan/backend/dispatch/Dispatch1.scala
+11
-19
src/main/scala/xiangshan/backend/dispatch/Dispatch2.scala
src/main/scala/xiangshan/backend/dispatch/Dispatch2.scala
+38
-42
src/main/scala/xiangshan/backend/dispatch/DispatchQueue.scala
...main/scala/xiangshan/backend/dispatch/DispatchQueue.scala
+10
-15
src/main/scala/xiangshan/backend/exu/Exu.scala
src/main/scala/xiangshan/backend/exu/Exu.scala
+3
-1
src/main/scala/xiangshan/backend/issue/IssueQueue.scala
src/main/scala/xiangshan/backend/issue/IssueQueue.scala
+357
-5
src/main/scala/xiangshan/backend/rename/Rename.scala
src/main/scala/xiangshan/backend/rename/Rename.scala
+31
-0
src/main/scala/xiangshan/backend/roq/Roq.scala
src/main/scala/xiangshan/backend/roq/Roq.scala
+66
-10
src/main/scala/xiangshan/frontend/Frontend.scala
src/main/scala/xiangshan/frontend/Frontend.scala
+8
-0
src/main/scala/xiangshan/utils/LogUtils.scala
src/main/scala/xiangshan/utils/LogUtils.scala
+51
-0
src/test/csrc/difftest.cpp
src/test/csrc/difftest.cpp
+19
-16
src/test/csrc/emu.h
src/test/csrc/emu.h
+4
-4
src/test/scala/top/XSSim.scala
src/test/scala/top/XSSim.scala
+3
-3
未找到文件。
src/main/scala/xiangshan/Bundle.scala
浏览文件 @
8c0bf90f
...
...
@@ -68,7 +68,7 @@ class Dp1ToDp2IO extends XSBundle {
}
class
DebugBundle
extends
XSBundle
{
val
isMMIO
=
Output
(
Bool
()
)
val
isMMIO
=
Bool
(
)
}
class
ExuInput
extends
XSBundle
{
...
...
src/main/scala/xiangshan/XSCore.scala
浏览文件 @
8c0bf90f
...
...
@@ -8,8 +8,10 @@ import xiangshan.backend._
import
xiangshan.backend.dispatch.DP1Config
import
xiangshan.backend.exu.ExuConfig
import
xiangshan.frontend.Frontend
import
xiangshan.utils._
trait
HasXSParameter
{
val
LogLevel
=
XSLogLevel
.
ALL
val
XLEN
=
64
val
HasMExtension
=
true
val
HasCExtension
=
true
...
...
@@ -60,9 +62,14 @@ trait HasXSParameter {
)
}
trait
HasXSLog
{
this:
Module
=>
implicit
val
_implict_module
=
this
}
abstract
class
XSModule
extends
Module
with
HasXSParameter
with
HasExceptionNO
with
HasXSLog
//remove this trait after impl module logic
trait
NeedImpl
{
this:
Module
=>
...
...
src/main/scala/xiangshan/backend/Backend.scala
浏览文件 @
8c0bf90f
...
...
@@ -48,25 +48,40 @@ class Backend(implicit val p: XSConfig) extends XSModule
))
val
redirect
=
Mux
(
roq
.
io
.
redirect
.
valid
,
roq
.
io
.
redirect
,
brq
.
io
.
redirect
)
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
)
val
bypassCnt
=
if
(
eu
.
fuTypeInt
==
FuType
.
alu
.
litValue
())
exuConfig
.
AluCnt
else
0
val
iq
=
Module
(
new
IssueQueue
(
eu
.
fuTypeInt
,
wakeupCnt
,
bypassCnt
))
assert
(!(
needBypass
(
eu
)
&&
!
needWakeup
(
eu
)))
// needBypass but dont needWakeup is not allowed
val
iq
=
Module
(
new
IssueQueue
(
eu
.
fuTypeInt
,
wakeupCnt
,
bypassCnt
,
eu
.
fixedDelay
))
iq
.
io
.
redirect
<>
redirect
iq
.
io
.
enqCtrl
<>
dispatch
.
io
.
enqIQCtrl
(
i
)
iq
.
io
.
enqData
<>
dispatch
.
io
.
enqIQData
(
i
)
iq
.
io
.
wakeUpPorts
<>
exeUnits
.
filter
(
needWakeup
).
map
(
_
.
io
.
out
)
val
wuUnitsOut
=
exeUnits
.
filter
(
e
=>
needWakeup
(
e
)).
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"
)
eu
.
io
.
in
<>
iq
.
io
.
deq
eu
.
io
.
redirect
<>
redirect
iq
})
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
)
val
bypassQueues
=
issueQueues
.
filter
(
_
.
bypassCnt
>
0
)
val
bypassUnits
=
exeUnits
.
filter
(
_
.
enableBypass
)
bypassQueues
.
foreach
(
iq
=>
{
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
)
...
...
@@ -104,7 +119,7 @@ class Backend(implicit val p: XSConfig) extends XSModule
fpRf
.
io
.
readPorts
<>
dispatch
.
io
.
readFpRf
val
exeWbReqs
=
exeUnits
.
map
(
_
.
io
.
out
)
val
wbIntReqs
=
(
bruExeUnit
+:
(
aluExeUnits
++
mulExeUnits
++
mduExeUnits
)).
map
(
_
.
io
.
out
)
val
wbIntReqs
=
(
bruExeUnit
+:
(
aluExeUnits
++
mulExeUnits
++
mduExeUnits
++
lsuExeUnits
)).
map
(
_
.
io
.
out
)
val
wbFpReqs
=
(
fmacExeUnits
++
fmiscExeUnits
++
fmiscDivSqrtExeUnits
).
map
(
_
.
io
.
out
)
val
intWbArb
=
Module
(
new
WriteBackArbMtoN
(
wbIntReqs
.
length
,
NRWritePorts
))
val
fpWbArb
=
Module
(
new
WriteBackArbMtoN
(
wbFpReqs
.
length
,
NRWritePorts
))
...
...
@@ -152,27 +167,4 @@ class Backend(implicit val p: XSConfig) extends XSModule
)
for
(
s
<-
sinks
){
BoringUtils
.
addSink
(
tmp
,
s
)
}
// A fake commit
// TODO: difftest 6 insts per cycle
val
commit
=
RegNext
(
RegNext
(
RegNext
(
true
.
B
)))
val
pc
=
WireInit
(
"h80000000"
.
U
)
val
inst
=
WireInit
(
"h66666666"
.
U
)
if
(!
p
.
FPGAPlatform
){
BoringUtils
.
addSource
(
commit
,
"difftestCommit"
)
BoringUtils
.
addSource
(
pc
,
"difftestThisPC"
)
BoringUtils
.
addSource
(
inst
,
"difftestThisINST"
)
BoringUtils
.
addSource
(
tmp
,
"difftestIsMMIO"
)
BoringUtils
.
addSource
(
tmp
,
"difftestIsRVC"
)
BoringUtils
.
addSource
(
tmp
,
"difftestIntrNO"
)
BoringUtils
.
addSource
(
VecInit
(
Seq
.
fill
(
64
)(
tmp
)),
"difftestRegs"
)
BoringUtils
.
addSource
(
tmp
,
"difftestMode"
)
BoringUtils
.
addSource
(
tmp
,
"difftestMstatus"
)
BoringUtils
.
addSource
(
tmp
,
"difftestSstatus"
)
BoringUtils
.
addSource
(
tmp
,
"difftestMepc"
)
BoringUtils
.
addSource
(
tmp
,
"difftestSepc"
)
BoringUtils
.
addSource
(
tmp
,
"difftestMcause"
)
BoringUtils
.
addSource
(
tmp
,
"difftestScause"
)
}
}
src/main/scala/xiangshan/backend/brq/Brq.scala
浏览文件 @
8c0bf90f
...
...
@@ -3,6 +3,7 @@ package xiangshan.backend.brq
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.utils.XSInfo
...
...
@@ -78,4 +79,23 @@ class Brq extends XSModule {
headPtr
:=
0.
U
tailPtr
:=
0.
U
}
// Debug info
val
debug_roq_redirect
=
io
.
roqRedirect
.
valid
val
debug_brq_redirect
=
io
.
redirect
.
valid
&&
!
debug_roq_redirect
val
debug_normal_mode
=
!(
debug_roq_redirect
||
debug_brq_redirect
)
for
(
i
<-
0
until
DecodeWidth
){
XSInfo
(
debug_normal_mode
,
p
"enq v:${io.enqReqs(i).valid} rdy:${io.enqReqs(i).ready} pc:${Hexadecimal(io.enqReqs(i).bits.cf.pc)}"
+
p
" brMask:${Binary(io.brMasks(i))} brTag:${io.brTags(i)}\n"
)
}
XSInfo
(
debug_roq_redirect
,
"roq redirect, flush brq\n"
)
XSInfo
(
debug_brq_redirect
,
p
"brq redirect, target:${Hexadecimal(io.redirect.bits.target)}\n"
)
}
src/main/scala/xiangshan/backend/decode/DecodeStage.scala
浏览文件 @
8c0bf90f
...
...
@@ -3,6 +3,7 @@ package xiangshan.backend.decode
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.utils._
class
DecodeStage
extends
XSModule
{
val
io
=
IO
(
new
Bundle
()
{
...
...
@@ -24,7 +25,7 @@ class DecodeStage extends XSModule {
// Handshake ---------------------
// 1. if current instruction is valid, then:
// First, assert toBrq(i).valid and present toBrq(i).bits
// First, assert toBrq(i).valid
if (in.valid and out.ready and isBr)
and present toBrq(i).bits
// Second, check toBrq(i).ready and connect it to io.out(i).valid
// 2. To Decode Buffer:
// First, assert in(i).ready if out(i).ready
...
...
@@ -34,12 +35,17 @@ class DecodeStage extends XSModule {
decoders
(
i
).
io
.
in
<>
io
.
in
(
i
).
bits
decoderToBrq
(
i
)
:=
decoders
(
i
).
io
.
out
// CfCtrl without bfTag and brMask
// send CfCtrl without brTags and brMasks to brq
io
.
toBrq
(
i
).
valid
:=
io
.
in
(
i
).
valid
io
.
toBrq
(
i
).
valid
:=
io
.
in
(
i
).
valid
&&
io
.
out
(
i
).
ready
&&
decoders
(
i
).
io
.
out
.
cf
.
isBr
XSDebug
(
io
.
toBrq
(
i
).
valid
&&
io
.
toBrq
(
i
).
ready
,
p
"Branch instr detected. Sending it to BRQ."
)
XSDebug
(
io
.
toBrq
(
i
).
valid
&&
!
io
.
toBrq
(
i
).
ready
,
p
"Branch instr detected. BRQ full...waiting"
)
XSDebug
(
io
.
in
(
i
).
valid
&&
!
io
.
out
(
i
).
ready
,
p
"DecBuf full...waiting"
)
decoderToBrq
(
i
).
brMask
:=
DontCare
decoderToBrq
(
i
).
brTag
:=
DontCare
io
.
toBrq
(
i
).
bits
:=
decoderToBrq
(
i
)
// if brq returns ready, then assert valid and send CfCtrl with bfTag and brMask to DecBuffer
io
.
out
(
i
).
valid
:=
io
.
toBrq
(
i
).
ready
&&
io
.
in
(
i
).
valid
XSDebug
(
io
.
out
(
i
).
valid
&&
decoders
(
i
).
io
.
out
.
cf
.
isBr
&&
io
.
out
(
i
).
ready
,
p
"Sending branch instr to DecBuf"
)
XSDebug
(
io
.
out
(
i
).
valid
&&
!
decoders
(
i
).
io
.
out
.
cf
.
isBr
&&
io
.
out
(
i
).
ready
,
p
"Sending non-branch instr to DecBuf"
)
decoderToDecBuffer
(
i
)
:=
decoders
(
i
).
io
.
out
decoderToDecBuffer
(
i
).
brTag
:=
io
.
brTags
(
i
)
decoderToDecBuffer
(
i
).
brMask
:=
io
.
brMasks
(
i
)
...
...
src/main/scala/xiangshan/backend/decode/Decoder.scala
浏览文件 @
8c0bf90f
...
...
@@ -21,6 +21,11 @@ class Decoder extends XSModule with HasInstrType {
val
decodeList
=
ListLookup
(
instr
,
Instructions
.
DecodeDefault
,
Instructions
.
DecodeTable
)
val
instrType
::
fuType
::
fuOpType
::
Nil
=
decodeList
// 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
))
// val isRVC = instr(1, 0) =/= "b11".U
// val rvcImmType :: rvcSrc1Type :: rvcSrc2Type :: rvcDestType :: Nil =
// ListLookup(instr, CInstructions.DecodeDefault, CInstructions.CExtraDecodeTable)
...
...
src/main/scala/xiangshan/backend/dispatch/Dispatch1.scala
浏览文件 @
8c0bf90f
...
...
@@ -3,7 +3,7 @@ package xiangshan.backend.dispatch
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
utils.
{
GTimer
}
import
xiangshan.utils.
{
XSDebug
,
XSInfo
}
case
class
DP1Config
(
...
...
@@ -43,14 +43,10 @@ class Dispatch1 extends XSModule{
(
io
.
toLsDq
(
i
).
ready
&&
FuType
.
isMemExu
(
io
.
fromRename
(
i
).
bits
.
ctrl
.
fuType
))
enq_valid
(
i
)
:=
io
.
toIntDq
(
i
).
valid
||
io
.
toFpDq
(
i
).
valid
||
io
.
toLsDq
(
i
).
valid
io
.
recv
(
i
)
:=
(
enq_ready
(
i
)
&&
enq_valid
(
i
))
||
cancelled
(
i
)
when
(
io
.
recv
(
i
)
&&
!
cancelled
(
i
))
{
printf
(
"[Cycle:%d][Dispatch1] instruction 0x%x accepted by queue %x %x %x\n"
,
GTimer
(),
io
.
fromRename
(
i
).
bits
.
cf
.
pc
,
io
.
toIntDq
(
i
).
valid
,
io
.
toFpDq
(
i
).
valid
,
io
.
toLsDq
(
i
).
valid
)
}
when
(
io
.
recv
(
i
)
&&
cancelled
(
i
))
{
printf
(
"[Cycle:%d][Dispatch1] instruction 0x%x with brMask %x brTag %x cancelled\n"
,
GTimer
(),
io
.
fromRename
(
i
).
bits
.
cf
.
pc
,
io
.
fromRename
(
i
).
bits
.
brMask
,
io
.
redirect
.
bits
.
brTag
)
}
XSInfo
(
io
.
recv
(
i
)
&&
!
cancelled
(
i
),
"instruction 0x%x accepted by queue %x %x %x\n"
,
io
.
fromRename
(
i
).
bits
.
cf
.
pc
,
io
.
toIntDq
(
i
).
valid
,
io
.
toFpDq
(
i
).
valid
,
io
.
toLsDq
(
i
).
valid
)
XSInfo
(
io
.
recv
(
i
)
&&
cancelled
(
i
),
"instruction 0x%x with brMask %x brTag %x cancelled\n"
,
io
.
fromRename
(
i
).
bits
.
cf
.
pc
,
io
.
fromRename
(
i
).
bits
.
brMask
,
io
.
redirect
.
bits
.
brTag
)
}
// latch indexes from roq in case of DQ not fire
...
...
@@ -62,13 +58,13 @@ class Dispatch1 extends XSModule{
when
(
io
.
toRoq
(
i
).
fire
()
&&
!
io
.
recv
(
i
))
{
roqIndexReg
(
i
)
:=
io
.
roqIdxs
(
i
)
roqIndexRegValid
(
i
)
:=
true
.
B
printf
(
"[Cycle:%d][Dispatch1] instruction 0x%x receives nboq %x but not accepted by queue (and it waits)\n"
,
GTimer
(),
io
.
fromRename
(
i
).
bits
.
cf
.
pc
,
io
.
roqIdxs
(
i
))
}
.
elsewhen
(
io
.
recv
(
i
))
{
roqIndexRegValid
(
i
)
:=
false
.
B
printf
(
"[Cycle:%d][Dispatch1] waiting instruction 0x%x is accepted by queue\n"
,
GTimer
(),
io
.
fromRename
(
i
).
bits
.
cf
.
pc
)
}
XSDebug
(
io
.
toRoq
(
i
).
fire
()
&&
!
io
.
recv
(
i
),
"instruction 0x%x receives nboq %x but not accepted by queue (and it waits)\n"
,
io
.
fromRename
(
i
).
bits
.
cf
.
pc
,
io
.
roqIdxs
(
i
))
}
// append nroq to uop
...
...
@@ -76,9 +72,7 @@ class Dispatch1 extends XSModule{
for
(
i
<-
0
until
RenameWidth
)
{
uop_nroq
(
i
)
:=
io
.
fromRename
(
i
).
bits
uop_nroq
(
i
).
roqIdx
:=
Mux
(
io
.
toRoq
(
i
).
ready
,
io
.
roqIdxs
(
i
),
roqIndexReg
(
i
))
when
(
io
.
toRoq
(
i
).
fire
())
{
printf
(
"[Cycle:%d][Dispatch1] instruction 0x%x receives nroq %d\n"
,
GTimer
(),
io
.
fromRename
(
i
).
bits
.
cf
.
pc
,
io
.
roqIdxs
(
i
))
}
XSDebug
(
io
.
toRoq
(
i
).
fire
(),
"instruction 0x%x receives nroq %d\n"
,
io
.
fromRename
(
i
).
bits
.
cf
.
pc
,
io
.
roqIdxs
(
i
))
}
// uop can enqueue when rename.valid and roq.valid
...
...
@@ -100,9 +94,7 @@ class Dispatch1 extends XSModule{
io
.
toRoq
(
i
).
bits
<>
io
.
fromRename
(
i
).
bits
io
.
toRoq
(
i
).
valid
:=
io
.
fromRename
(
i
).
valid
&&
!
roqIndexRegValid
(
i
)
io
.
fromRename
(
i
).
ready
:=
all_recv
when
(
io
.
fromRename
(
i
).
valid
)
{
printf
(
"[Cycle:%d][Dispatch1] instruction 0x%x of type %b is in %d-th slot\n"
,
GTimer
(),
io
.
fromRename
(
i
).
bits
.
cf
.
pc
,
io
.
fromRename
(
i
).
bits
.
ctrl
.
fuType
,
i
.
U
)
}
XSDebug
(
io
.
fromRename
(
i
).
valid
,
"instruction 0x%x of type %b is in %d-th slot\n"
,
io
.
fromRename
(
i
).
bits
.
cf
.
pc
,
io
.
fromRename
(
i
).
bits
.
ctrl
.
fuType
,
i
.
U
)
}
}
src/main/scala/xiangshan/backend/dispatch/Dispatch2.scala
浏览文件 @
8c0bf90f
...
...
@@ -4,7 +4,7 @@ import chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.backend.regfile.RfReadPort
import
xiangshan.utils.
GTimer
import
xiangshan.utils.
{
XSDebug
,
XSInfo
}
class
Dispatch2
extends
XSModule
with
NeedImpl
{
val
io
=
IO
(
new
Bundle
()
{
...
...
@@ -59,7 +59,7 @@ class Dispatch2 extends XSModule with NeedImpl {
(
uop
.
bits
.
ctrl
.
fuType
===
FuType
.
fmisc
&&
i
.
U
>
fmisc0InstIdx
)
||
uop
.
bits
.
ctrl
.
fuType
===
FuType
.
fmiscDivSqrt
})
:+
true
.
B
)
// TODO: currently there's only one
LSU
// TODO: currently there's only one
load/store reservation station
// val load0InstIdx = PriorityEncoder(io.fromLsDq.map(deq => (deq.bits.ctrl.fuType === FuType.ldu)) :+ true.B)
val
load0InstIdx
=
PriorityEncoder
(
io
.
fromLsDq
.
map
(
deq
=>
FuType
.
isMemExu
(
deq
.
bits
.
ctrl
.
fuType
))
:+
true
.
B
)
val
load1InstIdx
=
PriorityEncoder
((
io
.
fromLsDq
.
zipWithIndex
map
{
case
(
uop
,
i
)
=>
...
...
@@ -93,25 +93,31 @@ class Dispatch2 extends XSModule with NeedImpl {
// insert into reservation station
val
instIdxes
=
Seq
(
bruInstIdx
,
alu0InstIdx
,
alu1InstIdx
,
alu2InstIdx
,
alu3InstIdx
,
mulInstIdx
,
muldivInstIdx
,
fmac0InstIdx
,
fmac1InstIdx
,
fmac2InstIdx
,
fmac3InstIdx
,
fmisc0InstIdx
,
fmisc1InstIdx
,
load0InstIdx
,
store0InstIdx
)
load0InstIdx
)
//
, store0InstIdx)
io
.
enqIQCtrl
.
zipWithIndex
map
{
case
(
enq
,
i
)
=>
if
(
i
<
exuConfig
.
IntExuCnt
)
{
enq
.
valid
:=
!
instIdxes
(
i
)(
2
)
&&
io
.
fromIntDq
(
instIdxes
(
i
)(
1
,
0
)).
valid
enq
.
bits
:=
io
.
fromIntDq
(
instIdxes
(
i
)(
1
,
0
)).
bits
enq
.
bits
.
src1State
:=
io
.
intPregRdy
((
instIdxes
(
i
)
<<
1
).
asUInt
())
enq
.
bits
.
src2State
:=
io
.
intPregRdy
((
instIdxes
(
i
)
<<
1
).
asUInt
()
+
1.
U
)
}
else
if
(
i
<
exuConfig
.
IntExuCnt
+
exuConfig
.
FpExuCnt
)
{
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
(
instIdxes
(
i
)
*
3.
U
)
enq
.
bits
.
src2State
:=
io
.
fpPregRdy
(
instIdxes
(
i
)
*
3.
U
+
1.
U
)
enq
.
bits
.
src3State
:=
io
.
fpPregRdy
(
instIdxes
(
i
)
*
3.
U
+
2.
U
)
}
else
{
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
:=
Mux
(
enq
.
bits
.
ctrl
.
fuType
===
FuType
.
ldu
,
io
.
intPregRdy
(
8
),
io
.
intPregRdy
(
10
))
enq
.
bits
.
src2State
:=
io
.
intPregRdy
(
11
)
}
when
(
enq
.
fire
())
{
printf
(
"[Cycle:%d][Dispatch2] instruction 0x%x with type %b enters reservation station %d from %d\n"
,
GTimer
(),
enq
.
bits
.
cf
.
pc
,
enq
.
bits
.
ctrl
.
fuType
,
i
.
U
,
instIdxes
(
i
))
}
XSInfo
(
enq
.
fire
(),
"instruction 0x%x with type %b enters reservation station %d from %d\n"
,
enq
.
bits
.
cf
.
pc
,
enq
.
bits
.
ctrl
.
fuType
,
i
.
U
,
instIdxes
(
i
))
}
// responds to dispatch queue
...
...
@@ -119,42 +125,33 @@ class Dispatch2 extends XSModule with NeedImpl {
io
.
fromIntDq
(
i
).
ready
:=
(
io
.
enqIQCtrl
.
zipWithIndex
map
{
case
(
rs
,
j
)
=>
(
rs
.
ready
&&
instIdxes
(
j
)
===
i
.
U
&&
(
j
<
exuConfig
.
IntExuCnt
).
asBool
())
}).
reduce
((
l
,
r
)
=>
l
||
r
)
when
(
io
.
fromIntDq
(
i
).
fire
())
{
printf
(
"[Cycle:%d][Dispatch2] instruction 0x%x leaves Int dispatch queue with nroq %d\n"
,
GTimer
(),
io
.
fromIntDq
(
i
).
bits
.
cf
.
pc
,
io
.
fromIntDq
(
i
).
bits
.
roqIdx
)
}
when
(
io
.
fromIntDq
(
i
).
valid
&&
!
io
.
fromIntDq
(
i
).
ready
)
{
printf
(
"[Cycle:%d][Dispatch2] instruction 0x%x waits at Int dispatch queue with index %d\n"
,
GTimer
(),
io
.
fromIntDq
(
i
).
bits
.
cf
.
pc
,
i
.
U
)
}
XSInfo
(
io
.
fromIntDq
(
i
).
fire
(),
"instruction 0x%x leaves Int dispatch queue with nroq %d\n"
,
io
.
fromIntDq
(
i
).
bits
.
cf
.
pc
,
io
.
fromIntDq
(
i
).
bits
.
roqIdx
)
XSDebug
(
io
.
fromIntDq
(
i
).
valid
&&
!
io
.
fromIntDq
(
i
).
ready
,
"instruction 0x%x waits at Int dispatch queue with index %d\n"
,
io
.
fromIntDq
(
i
).
bits
.
cf
.
pc
,
i
.
U
)
}
for
(
i
<-
0
until
FpDqDeqWidth
)
{
io
.
fromFpDq
(
i
).
ready
:=
(
io
.
enqIQCtrl
.
zipWithIndex
map
{
case
(
rs
,
j
)
=>
(
rs
.
ready
&&
instIdxes
(
j
)
===
i
.
U
&&
(
j
>=
exuConfig
.
IntExuCnt
&&
j
<
exuConfig
.
IntExuCnt
+
exuConfig
.
FpExuCnt
).
asBool
())
}).
reduce
((
l
,
r
)
=>
l
||
r
)
when
(
io
.
fromFpDq
(
i
).
fire
())
{
printf
(
"[Cycle:%d][Dispatch2] instruction 0x%x leaves Fp dispatch queue with nroq %d\n"
,
GTimer
(),
io
.
fromFpDq
(
i
).
bits
.
cf
.
pc
,
io
.
fromFpDq
(
i
).
bits
.
roqIdx
)
}
when
(
io
.
fromFpDq
(
i
).
valid
&&
!
io
.
fromFpDq
(
i
).
ready
)
{
printf
(
"[Cycle:%d][Dispatch2] instruction 0x%x waits at Fp dispatch queue with index %d\n"
,
GTimer
(),
io
.
fromFpDq
(
i
).
bits
.
cf
.
pc
,
i
.
U
)
}
XSInfo
(
io
.
fromFpDq
(
i
).
fire
(),
"instruction 0x%x leaves Fp dispatch queue with nroq %d\n"
,
io
.
fromFpDq
(
i
).
bits
.
cf
.
pc
,
io
.
fromFpDq
(
i
).
bits
.
roqIdx
)
XSDebug
(
io
.
fromFpDq
(
i
).
valid
&&
!
io
.
fromFpDq
(
i
).
ready
,
"instruction 0x%x waits at Fp dispatch queue with index %d\n"
,
io
.
fromFpDq
(
i
).
bits
.
cf
.
pc
,
i
.
U
)
}
for
(
i
<-
0
until
LsDqDeqWidth
)
{
io
.
fromLsDq
(
i
).
ready
:=
(
io
.
enqIQCtrl
.
zipWithIndex
map
{
case
(
rs
,
j
)
=>
(
rs
.
ready
&&
instIdxes
(
j
)
===
i
.
U
&&
(
j
>=
exuConfig
.
IntExuCnt
+
exuConfig
.
FpExuCnt
).
asBool
())
}).
reduce
((
l
,
r
)
=>
l
||
r
)
when
(
io
.
fromLsDq
(
i
).
fire
())
{
printf
(
"[Cycle:%d][Dispatch2] instruction 0x%x leaves Ls dispatch queue with nroq %d\n"
,
GTimer
(),
io
.
fromLsDq
(
i
).
bits
.
cf
.
pc
,
io
.
fromLsDq
(
i
).
bits
.
roqIdx
)
}
when
(
io
.
fromLsDq
(
i
).
valid
&&
!
io
.
fromLsDq
(
i
).
ready
)
{
printf
(
"[Cycle:%d][Dispatch2] instruction 0x%x waits at Ls dispatch queue with index %d\n"
,
GTimer
(),
io
.
fromLsDq
(
i
).
bits
.
cf
.
pc
,
i
.
U
)
}
XSInfo
(
io
.
fromLsDq
(
i
).
fire
(),
"instruction 0x%x leaves Ls dispatch queue with nroq %d\n"
,
io
.
fromLsDq
(
i
).
bits
.
cf
.
pc
,
io
.
fromLsDq
(
i
).
bits
.
roqIdx
)
XSDebug
(
io
.
fromLsDq
(
i
).
valid
&&
!
io
.
fromLsDq
(
i
).
ready
,
"instruction 0x%x waits at Ls dispatch queue with index %d\n"
,
io
.
fromLsDq
(
i
).
bits
.
cf
.
pc
,
i
.
U
)
}
// next stage: insert data
...
...
@@ -207,12 +204,12 @@ class Dispatch2 extends XSModule with NeedImpl {
io
.
enqIQData
(
i
).
valid
:=
data_valid
(
i
)
io
.
enqIQData
(
i
).
bits
.
uop
:=
uop_reg
(
i
)
io
.
enqIQData
(
i
).
bits
.
uop
.
src1State
:=
Mux
(
src1Type
(
i
)(
1
),
SrcState
.
rdy
,
Mux
(
src1Type
(
i
)(
0
),
io
.
intPregRdy
(
src1Index
(
i
)),
io
.
fpPregRdy
(
src1Index
(
i
))))
io
.
enqIQData
(
i
).
bits
.
uop
.
src2State
:=
Mux
(
src2Type
(
i
)(
1
),
SrcState
.
rdy
,
Mux
(
src2Type
(
i
)(
0
),
io
.
intPregRdy
(
src2Index
(
i
)),
io
.
fpPregRdy
(
src2Index
(
i
))))
io
.
enqIQData
(
i
).
bits
.
uop
.
src3State
:=
Mux
(
src3Type
(
i
)(
1
),
SrcState
.
rdy
,
Mux
(
src3Type
(
i
)(
0
),
io
.
intPregRdy
(
src3Index
(
i
)),
io
.
fpPregRdy
(
src3Index
(
i
))))
//
io.enqIQData(i).bits.uop.src1State := Mux(src1Type(i)(1), SrcState.rdy,
//
Mux(src1Type(i)(0), io.intPregRdy(src1Index(i)), io.fpPregRdy(src1Index(i))))
//
io.enqIQData(i).bits.uop.src2State := Mux(src2Type(i)(1), SrcState.rdy,
//
Mux(src2Type(i)(0), io.intPregRdy(src2Index(i)), io.fpPregRdy(src2Index(i))))
//
io.enqIQData(i).bits.uop.src3State := Mux(src3Type(i)(1), SrcState.rdy,
//
Mux(src3Type(i)(0), io.intPregRdy(src3Index(i)), io.fpPregRdy(src3Index(i))))
val
src1
=
Mux
(
src1Type
(
i
)(
1
),
0.
U
,
Mux
(
src1Type
(
i
)(
0
),
io
.
readFpRf
(
src1Index
(
i
)).
data
,
io
.
readIntRf
(
src1Index
(
i
)).
data
))
io
.
enqIQData
(
i
).
bits
.
src1
:=
Mux
(
index_reg
(
i
)(
2
),
0.
U
,
src1
)
...
...
@@ -223,11 +220,10 @@ class Dispatch2 extends XSModule with NeedImpl {
Mux
(
src3Type
(
i
)(
0
),
io
.
readFpRf
(
src3Index
(
i
)).
data
,
io
.
readIntRf
(
src3Index
(
i
)).
data
))
io
.
enqIQData
(
i
).
bits
.
src3
:=
Mux
(
index_reg
(
i
)(
2
),
0.
U
,
src3
)
when
(
io
.
enqIQData
(
i
).
valid
)
{
printf
(
"[Cycle:%d][Dispatch2] instruction 0x%x reads operands from (%d, %d, %x), (%d, %d, %x), (%d, %d, %x)\n"
,
GTimer
(),
io
.
enqIQData
(
i
).
bits
.
uop
.
cf
.
pc
,
src1Type
(
i
),
src1Index
(
i
),
src1
,
src2Type
(
i
),
src2Index
(
i
),
src2
,
src3Type
(
i
),
src3Index
(
i
),
src3
)
}
XSDebug
(
io
.
enqIQData
(
i
).
valid
,
"instruction 0x%x reads operands from (%d, %d, %x), (%d, %d, %x), (%d, %d, %x)\n"
,
io
.
enqIQData
(
i
).
bits
.
uop
.
cf
.
pc
,
src1Type
(
i
),
src1Index
(
i
),
src1
,
src2Type
(
i
),
src2Index
(
i
),
src2
,
src3Type
(
i
),
src3Index
(
i
),
src3
)
}
}
src/main/scala/xiangshan/backend/dispatch/DispatchQueue.scala
浏览文件 @
8c0bf90f
...
...
@@ -2,7 +2,7 @@ package xiangshan.backend.dispatch
import
chisel3._
import
chisel3.util._
import
xiangshan.utils.
GTimer
import
xiangshan.utils.
{
XSDebug
,
XSInfo
}
import
xiangshan.
{
MicroOp
,
Redirect
,
XSBundle
,
XSModule
}
...
...
@@ -61,9 +61,10 @@ class DispatchQueue(size: Int, enqnum: Int, deqnum: Int, name: String) extends X
for
(
i
<-
0
until
size
)
{
when
(
cancelled
(
i
)
&&
entriesValid
(
i
))
{
entriesValid
(
i
)
:=
false
.
B
printf
(
"[Cycle:%d]["
+
name
+
"] valid entry(%d)(pc = %x) cancelled with brMask %x brTag %x\n"
,
GTimer
(),
i
.
U
,
entries
(
i
).
cf
.
pc
,
entries
(
i
).
brMask
,
io
.
redirect
.
bits
.
brTag
)
}
XSInfo
(
cancelled
(
i
)
&&
entriesValid
(
i
),
name
+
": valid entry(%d)(pc = %x) cancelled with brMask %x brTag %x\n"
,
i
.
U
,
entries
(
i
).
cf
.
pc
,
entries
(
i
).
brMask
,
io
.
redirect
.
bits
.
brTag
)
}
// enqueue
...
...
@@ -87,16 +88,10 @@ class DispatchQueue(size: Int, enqnum: Int, deqnum: Int, name: String) extends X
head
:=
(
head
+
num_deq
)
%
size
.
U
head_direction
:=
((
Cat
(
0.
U
(
1.
W
),
head
)
+
num_deq
)
>=
size
.
U
).
asUInt
()
^
head_direction
when
(
num_deq
>
0.
U
)
{
printf
(
"[Cycle:%d]["
+
name
+
"] num_deq = %d, head = (%d -> %d)\n"
,
GTimer
(),
num_deq
,
head
,
(
head
+
num_deq
)
%
size
.
U
)
}
when
(
num_enq
>
0.
U
)
{
printf
(
"[Cycle:%d]["
+
name
+
"] num_enq = %d, tail = (%d -> %d)\n"
,
GTimer
(),
num_enq
,
tail
,
(
tail
+
num_enq
)
%
size
.
U
)
}
when
(
valid_entries
>
0.
U
)
{
printf
(
"[Cycle:%d]["
+
name
+
"] valid_entries = %d, head = (%d, %d), tail = (%d, %d), \n"
,
GTimer
(),
valid_entries
,
head_direction
,
head
,
tail_direction
,
tail
)
}
XSDebug
(
num_deq
>
0.
U
,
name
+
": num_deq = %d, head = (%d -> %d)\n"
,
num_deq
,
head
,
(
head
+
num_deq
)
%
size
.
U
)
XSDebug
(
num_enq
>
0.
U
,
name
+
"] num_enq = %d, tail = (%d -> %d)\n"
,
num_enq
,
tail
,
(
tail
+
num_enq
)
%
size
.
U
)
XSDebug
(
valid_entries
>
0.
U
,
name
+
"] valid_entries = %d, head = (%d, %d), tail = (%d, %d), \n"
,
valid_entries
,
head_direction
,
head
,
tail_direction
,
tail
)
}
\ No newline at end of file
src/main/scala/xiangshan/backend/exu/Exu.scala
浏览文件 @
8c0bf90f
...
...
@@ -31,7 +31,9 @@ abstract class Exu
val
readIntRf
:
Boolean
=
true
,
val
readFpRf
:
Boolean
=
false
,
val
writeIntRf
:
Boolean
=
true
,
val
writeFpRf
:
Boolean
=
false
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
)
extends
Module
{
val
io
=
IO
(
new
ExuIO
)
}
...
...
src/main/scala/xiangshan/backend/issue/IssueQueue.scala
浏览文件 @
8c0bf90f
...
...
@@ -3,8 +3,80 @@ package xiangshan.backend.issue
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.utils._
class
IssueQueue
(
val
fuTypeInt
:
BigInt
,
wakeupCnt
:
Int
,
val
bypassCnt
:
Int
)
extends
XSModule
with
NeedImpl
{
trait
IQConst
{
val
iqSize
=
8
val
iqIdxWidth
=
log2Up
(
iqSize
)
val
layer1Size
=
iqSize
val
layer2Size
=
iqSize
/
2
val
debug
=
false
}
sealed
abstract
class
IQBundle
extends
XSBundle
with
IQConst
sealed
abstract
class
IQModule
extends
XSModule
with
IQConst
//with NeedImpl
sealed
class
CmpInputBundle
extends
IQBundle
{
val
instRdy
=
Input
(
Bool
())
val
roqIdx
=
Input
(
UInt
(
RoqIdxWidth
.
W
))
val
iqIdx
=
Input
(
UInt
(
iqIdxWidth
.
W
))
def
apply
(
instRdy
:
Bool
,
roqIdx
:
UInt
,
iqIdx
:
UInt
)
=
{
this
.
instRdy
:=
instRdy
this
.
roqIdx
:=
roqIdx
this
.
iqIdx
:=
iqIdx
this
}
}
sealed
class
CompareCircuitUnit
extends
IQModule
{
val
io
=
IO
(
new
Bundle
(){
val
in1
=
new
CmpInputBundle
val
in2
=
new
CmpInputBundle
val
out
=
Flipped
(
new
CmpInputBundle
)
})
val
roqIdx1
=
io
.
in1
.
roqIdx
val
roqIdx2
=
io
.
in2
.
roqIdx
val
iqIdx1
=
io
.
in1
.
iqIdx
val
iqIdx2
=
io
.
in2
.
iqIdx
val
inst1Rdy
=
io
.
in1
.
instRdy
val
inst2Rdy
=
io
.
in2
.
instRdy
io
.
out
.
instRdy
:=
inst1Rdy
|
inst2Rdy
io
.
out
.
roqIdx
:=
roqIdx2
io
.
out
.
iqIdx
:=
iqIdx2
when
((
inst1Rdy
&&
!
inst2Rdy
)
||
(
inst1Rdy
&&
inst2Rdy
&&
(
roqIdx1
<
roqIdx2
))){
io
.
out
.
roqIdx
:=
roqIdx1
io
.
out
.
iqIdx
:=
iqIdx1
}
}
object
CCU
{
def
apply
(
in1
:
CmpInputBundle
,
in2
:
CmpInputBundle
)
=
{
val
CCU
=
Module
(
new
CompareCircuitUnit
)
CCU
.
io
.
in1
<>
in1
CCU
.
io
.
in2
<>
in2
CCU
.
io
.
out
}
}
object
ParallelSel
{
def
apply
(
iq
:
Seq
[
CmpInputBundle
])
:
CmpInputBundle
=
{
iq
match
{
case
Seq
(
a
)
=>
a
case
Seq
(
a
,
b
)
=>
CCU
(
a
,
b
)
case
_
=>
apply
(
Seq
(
apply
(
iq
take
iq
.
size
/
2
),
apply
(
iq
drop
iq
.
size
/
2
)))
}
}
}
class
IssueQueue
(
val
fuTypeInt
:
BigInt
,
val
wakeupCnt
:
Int
,
val
bypassCnt
:
Int
=
0
,
val
fixedDelay
:
Int
=
1
)
extends
IQModule
{
val
useBypass
=
bypassCnt
>
0
...
...
@@ -18,16 +90,296 @@ class IssueQueue(val fuTypeInt: BigInt, wakeupCnt: Int, val bypassCnt: Int) exte
val
enqData
=
Flipped
(
ValidIO
(
new
ExuInput
))
// broadcast selected uop to other issue queues which has bypasses
val
selectedUop
=
if
(
useBypass
)
Decouple
dIO
(
new
MicroOp
)
else
null
val
selectedUop
=
if
(
useBypass
)
Vali
dIO
(
new
MicroOp
)
else
null
// send to exu
val
deq
=
DecoupledIO
(
new
ExuInput
)
// listen to write back bus
val
wakeUpPorts
=
Vec
(
wakeupCnt
,
Flipped
(
Decouple
dIO
(
new
ExuOutput
)))
val
wakeUpPorts
=
Vec
(
wakeupCnt
,
Flipped
(
Vali
dIO
(
new
ExuOutput
)))
// use bypass uops to speculative wake-up
val
bypassUops
=
if
(
useBypass
)
Vec
(
bypassCnt
,
Flipped
(
Decouple
dIO
(
new
MicroOp
)))
else
null
val
bypassData
=
if
(
useBypass
)
Vec
(
bypassCnt
,
Flipped
(
Decouple
dIO
(
new
ExuOutput
)))
else
null
val
bypassUops
=
if
(
useBypass
)
Vec
(
bypassCnt
,
Flipped
(
Vali
dIO
(
new
MicroOp
)))
else
null
val
bypassData
=
if
(
useBypass
)
Vec
(
bypassCnt
,
Flipped
(
Vali
dIO
(
new
ExuOutput
)))
else
null
})
//---------------------------------------------------------
// Issue Queue
//---------------------------------------------------------
//Tag Queue
val
ctrlFlow
=
Mem
(
iqSize
,
new
CtrlFlow
)
val
ctrlSig
=
Mem
(
iqSize
,
new
CtrlSignals
)
val
brMask
=
RegInit
(
VecInit
(
Seq
.
fill
(
iqSize
)(
0.
U
(
BrqSize
.
W
))))
val
brTag
=
RegInit
(
VecInit
(
Seq
.
fill
(
iqSize
)(
0.
U
(
BrTagWidth
.
W
))))
val
validReg
=
RegInit
(
VecInit
(
Seq
.
fill
(
iqSize
)(
false
.
B
)))
val
validWillFalse
=
WireInit
(
VecInit
(
Seq
.
fill
(
iqSize
)(
false
.
B
)))
val
valid
=
validReg
.
asUInt
&
~
validWillFalse
.
asUInt
val
src1Rdy
=
RegInit
(
VecInit
(
Seq
.
fill
(
iqSize
)(
false
.
B
)))
val
src2Rdy
=
RegInit
(
VecInit
(
Seq
.
fill
(
iqSize
)(
false
.
B
)))
val
src3Rdy
=
RegInit
(
VecInit
(
Seq
.
fill
(
iqSize
)(
false
.
B
)))
val
prfSrc1
=
Reg
(
Vec
(
iqSize
,
UInt
(
PhyRegIdxWidth
.
W
)))
val
prfSrc2
=
Reg
(
Vec
(
iqSize
,
UInt
(
PhyRegIdxWidth
.
W
)))
val
prfSrc3
=
Reg
(
Vec
(
iqSize
,
UInt
(
PhyRegIdxWidth
.
W
)))
val
prfDest
=
Reg
(
Vec
(
iqSize
,
UInt
(
PhyRegIdxWidth
.
W
)))
val
oldPDest
=
Reg
(
Vec
(
iqSize
,
UInt
(
PhyRegIdxWidth
.
W
)))
val
freelistAllocPtr
=
Reg
(
Vec
(
iqSize
,
UInt
(
PhyRegIdxWidth
.
W
)))
val
roqIdx
=
Reg
(
Vec
(
iqSize
,
UInt
(
RoqIdxWidth
.
W
)))
val
instRdy
=
WireInit
(
VecInit
(
List
.
tabulate
(
iqSize
)(
i
=>
src1Rdy
(
i
)
&&
src2Rdy
(
i
)
&&
src3Rdy
(
i
)&&
valid
(
i
))))
//tag enqueue
val
iqEmty
=
!
valid
.
asUInt
.
orR
val
iqFull
=
valid
.
asUInt
.
andR
val
iqAllowIn
=
!
iqFull
io
.
enqCtrl
.
ready
:=
iqAllowIn
//enqueue pointer
val
emptySlot
=
~
valid
.
asUInt
val
enqueueSelect
=
PriorityEncoder
(
emptySlot
)
//assert(!(io.enqCtrl.valid && io.redirect.valid),"enqueue valid should be false when redirect valid")
XSError
(
io
.
enqCtrl
.
valid
&&
io
.
redirect
.
valid
,
"enqueue valid should be false when redirect valid"
)
val
srcEnqRdy
=
WireInit
(
VecInit
(
false
.
B
,
false
.
B
,
false
.
B
))
srcEnqRdy
(
0
)
:=
Mux
(
io
.
enqCtrl
.
bits
.
ctrl
.
src1Type
=/=
SrcType
.
reg
,
true
.
B
,
io
.
enqCtrl
.
bits
.
src1State
===
SrcState
.
rdy
)
srcEnqRdy
(
1
)
:=
Mux
(
io
.
enqCtrl
.
bits
.
ctrl
.
src2Type
=/=
SrcType
.
reg
,
true
.
B
,
io
.
enqCtrl
.
bits
.
src2State
===
SrcState
.
rdy
)
srcEnqRdy
(
2
)
:=
Mux
(
io
.
enqCtrl
.
bits
.
ctrl
.
src3Type
=/=
SrcType
.
reg
,
true
.
B
,
io
.
enqCtrl
.
bits
.
src3State
===
SrcState
.
rdy
)
when
(
io
.
enqCtrl
.
fire
())
{
ctrlFlow
(
enqueueSelect
)
:=
io
.
enqCtrl
.
bits
.
cf
ctrlSig
(
enqueueSelect
)
:=
io
.
enqCtrl
.
bits
.
ctrl
brMask
(
enqueueSelect
)
:=
io
.
enqCtrl
.
bits
.
brMask
brTag
(
enqueueSelect
)
:=
io
.
enqCtrl
.
bits
.
brTag
validReg
(
enqueueSelect
)
:=
true
.
B
src1Rdy
(
enqueueSelect
)
:=
srcEnqRdy
(
0
)
src2Rdy
(
enqueueSelect
)
:=
srcEnqRdy
(
1
)
src3Rdy
(
enqueueSelect
)
:=
srcEnqRdy
(
2
)
prfSrc1
(
enqueueSelect
)
:=
io
.
enqCtrl
.
bits
.
psrc1
prfSrc2
(
enqueueSelect
)
:=
io
.
enqCtrl
.
bits
.
psrc2
prfSrc3
(
enqueueSelect
)
:=
io
.
enqCtrl
.
bits
.
psrc3
prfDest
(
enqueueSelect
)
:=
io
.
enqCtrl
.
bits
.
pdest
oldPDest
(
enqueueSelect
)
:=
io
.
enqCtrl
.
bits
.
old_pdest
freelistAllocPtr
(
enqueueSelect
)
:=
io
.
enqCtrl
.
bits
.
freelistAllocPtr
roqIdx
(
enqueueSelect
)
:=
io
.
enqCtrl
.
bits
.
roqIdx
if
(
debug
)
{
XSDebug
(
"[IQ enq]: enqSelect:%d | s1Rd:%d s2Rd:%d s3Rd:%d\n"
,
enqueueSelect
.
asUInt
,
(
io
.
enqCtrl
.
bits
.
src1State
===
SrcState
.
rdy
),
(
io
.
enqCtrl
.
bits
.
src2State
===
SrcState
.
rdy
),
(
io
.
enqCtrl
.
bits
.
src3State
===
SrcState
.
rdy
))}
}
//Data Queue
val
src1Data
=
Reg
(
Vec
(
iqSize
,
UInt
(
XLEN
.
W
)))
val
src2Data
=
Reg
(
Vec
(
iqSize
,
UInt
(
XLEN
.
W
)))
val
src3Data
=
Reg
(
Vec
(
iqSize
,
UInt
(
XLEN
.
W
)))
val
enqSelNext
=
RegNext
(
enqueueSelect
)
val
enqFireNext
=
RegNext
(
io
.
enqCtrl
.
fire
())
// Read RegFile
//Ready data will written at next cycle
when
(
enqFireNext
)
{
when
(
src1Rdy
(
enqSelNext
)){
src1Data
(
enqSelNext
)
:=
io
.
enqData
.
bits
.
src1
}
when
(
src2Rdy
(
enqSelNext
)){
src2Data
(
enqSelNext
)
:=
io
.
enqData
.
bits
.
src2
}
when
(
src3Rdy
(
enqSelNext
)){
src3Data
(
enqSelNext
)
:=
io
.
enqData
.
bits
.
src3
}
}
if
(
debug
)
{
XSDebug
(
"[Reg info-ENQ] enqSelNext:%d | enqFireNext:%d \n"
,
enqSelNext
,
enqFireNext
)
XSDebug
(
"[IQ content] valid vr vf| pc insruction | src1rdy src1 | src2Rdy src2 pdest \n"
)
for
(
i
<-
0
to
(
iqSize
-
1
)){
val
ins
=
ctrlFlow
(
i
).
instr
val
pc
=
ctrlFlow
(
i
).
pc
when
(
valid
(
i
)){
XSDebug
(
"[IQ content][%d] %d%d%d |%x %x| %x %x | %x %x | %d valid|\n"
,
i
.
asUInt
,
valid
(
i
),
validReg
(
i
),
validWillFalse
(
i
),
pc
,
ins
,
src1Rdy
(
i
),
src1Data
(
i
),
src2Rdy
(
i
),
src2Data
(
i
),
prfDest
(
i
))}
.
elsewhen
(
validReg
(
i
)
&&
validWillFalse
(
i
)){
XSDebug
(
"[IQ content][%d] %d%d%d |%x %x| %x %x | %x %x | %d valid will be False|\n"
,
i
.
asUInt
,
valid
(
i
),
validReg
(
i
),
validWillFalse
(
i
),
pc
,
ins
,
src1Rdy
(
i
),
src1Data
(
i
),
src2Rdy
(
i
),
src2Data
(
i
),
prfDest
(
i
))}
.
otherwise
{
XSDebug
(
"[IQ content][%d] %d%d%d |%x %x| %x %x | %x %x | %d\n"
,
i
.
asUInt
,
valid
(
i
),
validReg
(
i
),
validWillFalse
(
i
),
pc
,
ins
,
src1Rdy
(
i
),
src1Data
(
i
),
src2Rdy
(
i
),
src2Data
(
i
),
prfDest
(
i
))}
}
}
// From Common Data Bus(wakeUpPort)
// chisel claims that firrtl will optimize Mux1H to and/or tree
// TODO: ignore ALU'cdb srcRdy, for byPass has done it
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
srcNum
=
3
val
prfSrc
=
List
(
prfSrc1
,
prfSrc2
,
prfSrc3
)
val
srcRdy
=
List
(
src1Rdy
,
src2Rdy
,
src3Rdy
)
val
srcData
=
List
(
src1Data
,
src2Data
,
src3Data
)
val
srcHitVec
=
List
.
tabulate
(
srcNum
)(
k
=>
List
.
tabulate
(
iqSize
)(
i
=>
List
.
tabulate
(
wakeupCnt
)(
j
=>
(
prfSrc
(
k
)(
i
)
===
cdbPdest
(
j
))
&&
cdbValid
(
j
))))
val
srcHit
=
List
.
tabulate
(
srcNum
)(
k
=>
List
.
tabulate
(
iqSize
)(
i
=>
ParallelOR
(
srcHitVec
(
k
)(
i
)).
asBool
()))
// VecInit(srcHitVec(k)(i)).asUInt.orR))
for
(
k
<-
0
until
srcNum
){
for
(
i
<-
0
until
iqSize
)(
when
(
valid
(
i
))
{
when
(!
srcRdy
(
k
)(
i
)
&&
srcHit
(
k
)(
i
))
{
srcRdy
(
k
)(
i
)
:=
true
.
B
// srcData(k)(i) := Mux1H(srcHitVec(k)(i), cdbData)
srcData
(
k
)(
i
)
:=
ParallelMux
(
srcHitVec
(
k
)(
i
)
zip
cdbData
)
}
})
}
// From byPass [speculative] (just for ALU to listen to other ALU's res, include itself)
// just need Tag(Ctrl). send out Tag when Tag is decided. other ALUIQ listen to them and decide Tag
// byPassUops is one cycle before byPassDatas
if
(
bypassCnt
>
0
)
{
val
bypassPdest
=
List
.
tabulate
(
bypassCnt
)(
i
=>
io
.
bypassUops
(
i
).
bits
.
pdest
)
val
bypassValid
=
List
.
tabulate
(
bypassCnt
)(
i
=>
io
.
bypassUops
(
i
).
valid
)
// may only need valid not fire()
val
bypassData
=
List
.
tabulate
(
bypassCnt
)(
i
=>
io
.
bypassData
(
i
).
bits
.
data
)
val
srcBpHitVec
=
List
.
tabulate
(
srcNum
)(
k
=>
List
.
tabulate
(
iqSize
)(
i
=>
List
.
tabulate
(
bypassCnt
)(
j
=>
(
prfSrc
(
k
)(
i
)
===
bypassPdest
(
j
))
&&
bypassValid
(
j
))))
val
srcBpHit
=
List
.
tabulate
(
srcNum
)(
k
=>
List
.
tabulate
(
iqSize
)(
i
=>
ParallelOR
(
srcBpHitVec
(
k
)(
i
)).
asBool
()))
// VecInit(srcBpHitVec(k)(i)).asUInt.orR))
val
srcBpHitVecNext
=
List
.
tabulate
(
srcNum
)(
k
=>
List
.
tabulate
(
iqSize
)(
i
=>
List
.
tabulate
(
bypassCnt
)(
j
=>
RegNext
(
srcBpHitVec
(
k
)(
i
)(
j
)))))
val
srcBpHitNext
=
List
.
tabulate
(
srcNum
)(
k
=>
List
.
tabulate
(
iqSize
)(
i
=>
RegNext
(
srcBpHit
(
k
)(
i
))))
val
srcBpData
=
List
.
tabulate
(
srcNum
)(
k
=>
List
.
tabulate
(
iqSize
)(
i
=>
ParallelMux
(
srcBpHitVecNext
(
k
)(
i
)
zip
bypassData
)))
// Mux1H(srcBpHitVecNext(k)(i), bypassData)))
for
(
k
<-
0
until
srcNum
){
for
(
i
<-
0
until
iqSize
){
when
(
valid
(
i
))
{
when
(
valid
(
i
)
&&
!
srcRdy
(
k
)(
i
)
&&
srcBpHit
(
k
)(
i
))
{
srcRdy
(
k
)(
i
)
:=
true
.
B
}
when
(
srcBpHitNext
(
k
)(
i
))
{
srcData
(
k
)(
i
)
:=
srcBpData
(
k
)(
i
)}
}}
}
// Enqueue Bypass
val
enqBypass
=
WireInit
(
VecInit
(
false
.
B
,
false
.
B
,
false
.
B
))
val
enqBypassHitVec
=
List
(
List
.
tabulate
(
bypassCnt
)(
j
=>
io
.
enqCtrl
.
bits
.
psrc1
===
bypassPdest
(
j
)
&&
bypassValid
(
j
)
&&
io
.
enqCtrl
.
fire
()),
List
.
tabulate
(
bypassCnt
)(
j
=>
io
.
enqCtrl
.
bits
.
psrc2
===
bypassPdest
(
j
)
&&
bypassValid
(
j
)
&&
io
.
enqCtrl
.
fire
()),
List
.
tabulate
(
bypassCnt
)(
j
=>
io
.
enqCtrl
.
bits
.
psrc3
===
bypassPdest
(
j
)
&&
bypassValid
(
j
)
&&
io
.
enqCtrl
.
fire
()))
val
enqBypassHitVecNext
=
enqBypassHitVec
.
map
(
i
=>
i
.
map
(
j
=>
RegNext
(
j
)))
enqBypass
(
0
)
:=
ParallelOR
(
enqBypassHitVec
(
0
))
enqBypass
(
1
)
:=
ParallelOR
(
enqBypassHitVec
(
1
))
enqBypass
(
2
)
:=
ParallelOR
(
enqBypassHitVec
(
2
))
when
(
enqBypass
(
0
))
{
src1Rdy
(
enqueueSelect
)
:=
true
.
B
}
when
(
enqBypass
(
1
))
{
src2Rdy
(
enqueueSelect
)
:=
true
.
B
}
when
(
enqBypass
(
2
))
{
src3Rdy
(
enqueueSelect
)
:=
true
.
B
}
when
(
RegNext
(
enqBypass
(
0
)))
{
src1Data
(
enqSelNext
)
:=
ParallelMux
(
enqBypassHitVecNext
(
0
)
zip
bypassData
)}
when
(
RegNext
(
enqBypass
(
1
)))
{
src2Data
(
enqSelNext
)
:=
ParallelMux
(
enqBypassHitVecNext
(
1
)
zip
bypassData
)}
when
(
RegNext
(
enqBypass
(
2
)))
{
src3Data
(
enqSelNext
)
:=
ParallelMux
(
enqBypassHitVecNext
(
2
)
zip
bypassData
)}
}
}
//---------------------------------------------------------
// Select Circuit
//---------------------------------------------------------
val
selVec
=
List
.
tabulate
(
iqSize
){
i
=>
Wire
(
new
CmpInputBundle
).
apply
(
instRdy
(
i
),
roqIdx
(
i
),
i
.
U
)
}
val
selResult
=
ParallelSel
(
selVec
)
if
(
debug
)
{
XSDebug
(
"[Sel Result] ResReady:%d || ResultId:%d\n"
,
selResult
.
instRdy
,
selResult
.
iqIdx
.
asUInt
)
}
//---------------------------------------------------------
// Redirect Logic
//---------------------------------------------------------
val
expRedirect
=
io
.
redirect
.
valid
&&
io
.
redirect
.
bits
.
isException
val
brRedirect
=
io
.
redirect
.
valid
&&
!
io
.
redirect
.
bits
.
isException
List
.
tabulate
(
iqSize
)(
i
=>
when
(
brRedirect
&&
(
UIntToOH
(
io
.
redirect
.
bits
.
brTag
)
&
brMask
(
i
)).
orR
&&
validReg
(
i
)
){
validReg
(
i
)
:=
false
.
B
validWillFalse
(
i
)
:=
true
.
B
}
.
elsewhen
(
expRedirect
)
{
validReg
(
i
)
:=
false
.
B
validWillFalse
(
i
)
:=
true
.
B
}
)
//---------------------------------------------------------
// Dequeue Logic
//---------------------------------------------------------
//hold the sel-index to wait for data
val
selInstIdx
=
RegInit
(
0.
U
(
iqIdxWidth
.
W
))
val
selInstRdy
=
RegInit
(
false
.
B
)
//issue the select instruction
val
dequeueSelect
=
Wire
(
UInt
(
iqIdxWidth
.
W
))
dequeueSelect
:=
selInstIdx
val
brRedirectMaskMatch
=
(
UIntToOH
(
io
.
redirect
.
bits
.
brTag
)
&
brMask
(
dequeueSelect
)).
orR
val
IQreadyGo
=
selInstRdy
&&
!
expRedirect
&&
(!
brRedirect
||
!
brRedirectMaskMatch
)
io
.
deq
.
valid
:=
IQreadyGo
io
.
deq
.
bits
.
uop
.
cf
:=
ctrlFlow
(
dequeueSelect
)
io
.
deq
.
bits
.
uop
.
ctrl
:=
ctrlSig
(
dequeueSelect
)
io
.
deq
.
bits
.
uop
.
brMask
:=
brMask
(
dequeueSelect
)
io
.
deq
.
bits
.
uop
.
brTag
:=
brTag
(
dequeueSelect
)
io
.
deq
.
bits
.
uop
.
psrc1
:=
prfSrc1
(
dequeueSelect
)
io
.
deq
.
bits
.
uop
.
psrc2
:=
prfSrc2
(
dequeueSelect
)
io
.
deq
.
bits
.
uop
.
psrc3
:=
prfSrc3
(
dequeueSelect
)
io
.
deq
.
bits
.
uop
.
pdest
:=
prfDest
(
dequeueSelect
)
io
.
deq
.
bits
.
uop
.
old_pdest
:=
oldPDest
(
dequeueSelect
)
io
.
deq
.
bits
.
uop
.
src1State
:=
SrcState
.
rdy
io
.
deq
.
bits
.
uop
.
src2State
:=
SrcState
.
rdy
io
.
deq
.
bits
.
uop
.
src3State
:=
SrcState
.
rdy
io
.
deq
.
bits
.
uop
.
freelistAllocPtr
:=
freelistAllocPtr
(
dequeueSelect
)
io
.
deq
.
bits
.
uop
.
roqIdx
:=
roqIdx
(
dequeueSelect
)
io
.
deq
.
bits
.
src1
:=
src1Data
(
dequeueSelect
)
io
.
deq
.
bits
.
src2
:=
src2Data
(
dequeueSelect
)
io
.
deq
.
bits
.
src3
:=
src3Data
(
dequeueSelect
)
if
(
debug
)
{
XSDebug
(
"[Reg Info-Sel] selInstRdy:%d || selIdx:%d\n"
,
selInstRdy
,
selInstIdx
.
asUInt
)
XSDebug
(
IQreadyGo
,
"[IQ dequeue] **dequeue fire:%d** roqIdx:%d dequeueSel:%d | src1Rd:%d src1:%d | src2Rd:%d src2:%d\n"
,
io
.
deq
.
fire
(),
io
.
deq
.
bits
.
uop
.
roqIdx
,
dequeueSelect
.
asUInt
,
(
io
.
deq
.
bits
.
uop
.
src1State
===
SrcState
.
rdy
),
io
.
deq
.
bits
.
uop
.
psrc1
,
(
io
.
deq
.
bits
.
uop
.
src2State
===
SrcState
.
rdy
),
io
.
deq
.
bits
.
uop
.
psrc2
)
}
//update the index register of instruction that can be issue, unless function unit not allow in
//then the issue will be stopped to wait the function unit
//clear the validBit of dequeued instruction in issuequeue
when
(
io
.
deq
.
fire
()){
validReg
(
dequeueSelect
)
:=
false
.
B
validWillFalse
(
dequeueSelect
)
:=
true
.
B
}
val
selRegflush
=
expRedirect
||
(
brRedirect
&&
brRedirectMaskMatch
)
selInstRdy
:=
Mux
(
selRegflush
,
false
.
B
,
selResult
.
instRdy
)
selInstIdx
:=
Mux
(
selRegflush
,
0.
U
,
selResult
.
iqIdx
)
// SelectedUop (bypass / speculative)
if
(
useBypass
)
{
assert
(
fixedDelay
==
1
)
// only support fixedDelay is 1 now
def
DelayPipe
[
T
<:
Data
](
a
:
T
,
delay
:
Int
=
0
)
=
{
// println(delay)
if
(
delay
==
0
)
a
else
{
val
storage
=
Wire
(
VecInit
(
Seq
.
fill
(
delay
+
1
)(
a
)))
// storage(0) := a
for
(
i
<-
1
until
delay
)
{
storage
(
i
)
:=
RegNext
(
storage
(
i
-
1
))
}
storage
(
delay
)
}
}
val
sel
=
io
.
selectedUop
val
selIQIdx
=
selResult
.
iqIdx
val
delayPipe
=
DelayPipe
(
VecInit
(
selResult
.
instRdy
,
prfDest
(
selIQIdx
)),
fixedDelay
-
1
)
sel
.
bits
:=
DontCare
sel
.
bits
.
pdest
:=
delayPipe
(
fixedDelay
-
1
)(
1
)
}
}
src/main/scala/xiangshan/backend/rename/Rename.scala
浏览文件 @
8c0bf90f
...
...
@@ -3,6 +3,7 @@ package xiangshan.backend.rename
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.utils.XSInfo
class
Rename
extends
XSModule
{
val
io
=
IO
(
new
Bundle
()
{
...
...
@@ -20,6 +21,26 @@ class Rename extends XSModule {
val
out
=
Vec
(
RenameWidth
,
DecoupledIO
(
new
MicroOp
))
})
val
debug_exception
=
io
.
redirect
.
valid
&&
io
.
redirect
.
bits
.
isException
val
debug_walk
=
io
.
roqCommits
.
map
(
_
.
bits
.
isWalk
).
reduce
(
_
||
_
)
val
debug_norm
=
!(
debug_exception
||
debug_walk
)
def
printRenameInfo
(
in
:
DecoupledIO
[
CfCtrl
],
out
:
DecoupledIO
[
MicroOp
])
=
{
XSInfo
(
debug_norm
,
p
"pc:${Hexadecimal(in.bits.cf.pc)} v:${in.valid} rdy:${in.ready} "
+
p
"lsrc1:${in.bits.ctrl.lsrc1} -> psrc1:${out.bits.psrc1} "
+
p
"lsrc2:${in.bits.ctrl.lsrc2} -> psrc2:${out.bits.psrc2} "
+
p
"lsrc3:${in.bits.ctrl.lsrc3} -> psrc3:${out.bits.psrc3} "
+
p
"ldest:${in.bits.ctrl.ldest} -> pdest:${out.bits.pdest} "
+
p
"old_pdest:${out.bits.old_pdest}\n"
)
}
for
((
x
,
y
)
<-
io
.
in
.
zip
(
io
.
out
)){
printRenameInfo
(
x
,
y
)
}
val
fpFreeList
,
intFreeList
=
Module
(
new
FreeList
).
io
val
fpRat
=
Module
(
new
RenameTable
(
float
=
true
)).
io
val
intRat
=
Module
(
new
RenameTable
(
float
=
false
)).
io
...
...
@@ -85,10 +106,20 @@ class Rename extends XSModule {
rat
.
specWritePorts
(
i
).
addr
:=
Mux
(
specWen
,
uops
(
i
).
ctrl
.
ldest
,
io
.
roqCommits
(
i
).
bits
.
uop
.
ctrl
.
ldest
)
rat
.
specWritePorts
(
i
).
wdata
:=
Mux
(
specWen
,
freeList
.
pdests
(
i
),
io
.
roqCommits
(
i
).
bits
.
uop
.
old_pdest
)
XSInfo
(
walkWen
,
{
if
(
fp
)
"fp"
else
"int "
}
+
p
"walk: pc:${Hexadecimal(uops(i).cf.pc)}"
+
p
" ldst:${rat.specWritePorts(i).addr} old_pdest:${rat.specWritePorts(i).wdata}\n"
)
rat
.
archWritePorts
(
i
).
wen
:=
commitDestValid
&&
!
io
.
roqCommits
(
i
).
bits
.
isWalk
rat
.
archWritePorts
(
i
).
addr
:=
io
.
roqCommits
(
i
).
bits
.
uop
.
ctrl
.
ldest
rat
.
archWritePorts
(
i
).
wdata
:=
io
.
roqCommits
(
i
).
bits
.
uop
.
pdest
XSInfo
(
rat
.
archWritePorts
(
i
).
wen
,
{
if
(
fp
)
"fp"
else
"int "
}
+
p
" rat arch: ldest:${rat.archWritePorts(i).addr}"
+
p
" pdest:${rat.archWritePorts(i).wdata}\n"
)
freeList
.
deallocReqs
(
i
)
:=
rat
.
archWritePorts
(
i
).
wen
freeList
.
deallocPregs
(
i
)
:=
io
.
roqCommits
(
i
).
bits
.
uop
.
old_pdest
...
...
src/main/scala/xiangshan/backend/roq/Roq.scala
浏览文件 @
8c0bf90f
...
...
@@ -3,9 +3,11 @@ package xiangshan.backend.roq
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.utils._
import
chisel3.util.experimental.BoringUtils
// A "just-enough" Roq
class
Roq
extends
XSModule
{
class
Roq
(
implicit
val
p
:
XSConfig
)
extends
XSModule
{
val
io
=
IO
(
new
Bundle
()
{
val
brqRedirect
=
Input
(
Valid
(
new
Redirect
))
val
dp1Req
=
Vec
(
RenameWidth
,
Flipped
(
DecoupledIO
(
new
MicroOp
)))
...
...
@@ -20,8 +22,10 @@ class Roq extends XSModule {
val
valid
=
RegInit
(
VecInit
(
List
.
fill
(
RoqSize
)(
false
.
B
)))
val
writebacked
=
Reg
(
Vec
(
RoqSize
,
Bool
()))
val
redirect
=
Reg
(
Vec
(
RoqSize
,
new
Redirect
))
val
isMMIO
=
Reg
(
Vec
(
RoqSize
,
Bool
()))
//for debug
val
intrNO
=
Reg
(
Vec
(
RoqSize
,
UInt
(
XLEN
.
W
)))
//for debug
val
exuData
=
Reg
(
Vec
(
RoqSize
,
UInt
(
XLEN
.
W
)))
//for debug
val
exuDebug
=
Reg
(
Vec
(
RoqSize
,
new
DebugBundle
))
//for debug
val
archRF
=
RegInit
(
VecInit
(
List
.
fill
(
64
)(
0.
U
(
32.
W
))))
//for debug, fp regs included
val
ringBufferHeadExtended
=
RegInit
(
0.
U
(
ExtendedRoqIdxWidth
.
W
))
val
ringBufferTailExtended
=
RegInit
(
0.
U
(
ExtendedRoqIdxWidth
.
W
))
...
...
@@ -39,33 +43,47 @@ class Roq extends XSModule {
// Dispatch
val
validDispatch
=
VecInit
((
0
until
RenameWidth
).
map
(
io
.
dp1Req
(
_
).
valid
)).
asUInt
XSDebug
(
"(ready, valid): "
)
for
(
i
<-
0
until
RenameWidth
){
val
offset
=
if
(
i
==
0
)
0.
U
else
PopCount
(
validDispatch
(
i
-
1
,
0
))
when
(
io
.
dp1Req
(
i
).
fire
()){
microOp
(
ringBufferHead
+
offset
)
:=
io
.
dp1Req
(
i
).
bits
valid
(
ringBufferHead
+
offset
)
:=
true
.
B
writebacked
(
ringBufferHead
+
offset
)
:=
false
.
B
}
io
.
dp1Req
(
i
).
ready
:=
ringBufferAllowin
&&
!
valid
(
ringBufferHead
+
offset
)
&&
state
===
s_idle
io
.
roqIdxs
(
i
)
:=
ringBufferHeadExtended
+
offset
XSDebug
(){
printf
(
"(%d, %d) "
,
io
.
dp1Req
(
i
).
ready
,
io
.
dp1Req
(
i
).
valid
)}
}
XSDebug
(){
printf
(
"\n"
)}
val
firedDispatch
=
VecInit
((
0
until
CommitWidth
).
map
(
io
.
dp1Req
(
_
).
fire
())).
asUInt
when
(
validDispatch
.
orR
){
ringBufferHeadExtended
:=
ringBufferHeadExtended
+
PopCount
(
validDispatch
)
when
(
firedDispatch
.
orR
){
ringBufferHeadExtended
:=
ringBufferHeadExtended
+
PopCount
(
firedDispatch
)
XSInfo
(
"dispatched %d insts\n"
,
PopCount
(
firedDispatch
))
}
// Writeback
for
(
i
<-
0
until
exuConfig
.
ExuCnt
){
when
(
io
.
exeWbResults
(
i
).
fire
()){
writebacked
(
io
.
exeWbResults
(
i
).
bits
.
uop
.
roqIdx
)
:=
true
.
B
exuData
(
io
.
exeWbResults
(
i
).
bits
.
uop
.
roqIdx
)
:=
io
.
exeWbResults
(
i
).
bits
.
data
exuDebug
(
io
.
exeWbResults
(
i
).
bits
.
uop
.
roqIdx
)
:=
io
.
exeWbResults
(
i
).
bits
.
debug
}
}
val
firedWriteback
=
VecInit
((
0
until
exuConfig
.
ExuCnt
).
map
(
io
.
exeWbResults
(
_
).
fire
())).
asUInt
when
(
PopCount
(
firedWriteback
)
>
0.
U
){
XSInfo
(
"writebacked %d insts\n"
,
PopCount
(
firedWriteback
))
}
// Commit uop to Rename
for
(
i
<-
0
until
CommitWidth
){
when
(
state
===
s_idle
){
io
.
commits
(
i
).
valid
:=
valid
(
ringBufferTail
+
i
.
U
)
&&
writebacked
(
ringBufferTail
+
i
.
U
)
val
canCommit
=
if
(
i
!=
0
)
io
.
commits
(
i
-
1
).
valid
else
true
.
B
io
.
commits
(
i
).
valid
:=
valid
(
ringBufferTail
+
i
.
U
)
&&
writebacked
(
ringBufferTail
+
i
.
U
)
&&
canCommit
io
.
commits
(
i
).
bits
.
uop
:=
microOp
(
ringBufferTail
+
i
.
U
)
when
(
valid
(
ringBufferTail
+
i
.
U
)){
valid
(
ringBufferTail
+
i
.
U
)
:=
false
.
B
}
//FIXIT
when
(
microOp
(
i
).
ctrl
.
rfWen
){
archRF
(
microOp
(
i
).
ctrl
.
ldest
)
:=
exuData
(
i
)
}
when
(
io
.
commits
(
i
).
valid
){
valid
(
ringBufferTail
+
i
.
U
)
:=
false
.
B
}
}.
otherwise
{
//state === s_walk
io
.
commits
(
i
).
valid
:=
valid
(
ringBufferWalk
+
i
.
U
)
&&
writebacked
(
ringBufferWalk
+
i
.
U
)
io
.
commits
(
i
).
bits
.
uop
:=
microOp
(
ringBufferWalk
+
i
.
U
)
...
...
@@ -78,6 +96,9 @@ class Roq extends XSModule {
when
(
state
===
s_idle
){
ringBufferTailExtended
:=
ringBufferTailExtended
+
PopCount
(
validCommit
)
}
val
retireCounter
=
Mux
(
state
===
s_idle
,
PopCount
(
validCommit
),
0.
U
)
// TODO: commit store
XSInfo
(
retireCounter
>
0.
U
,
"retired %d insts\n"
,
retireCounter
)
val
walkFinished
=
(
0
until
CommitWidth
).
map
(
i
=>
(
ringBufferWalk
+
i
.
U
)
===
ringBufferWalkTarget
).
reduce
(
_
||
_
)
...
...
@@ -87,9 +108,7 @@ class Roq extends XSModule {
state
:=
s_idle
}
ringBufferWalkExtended
:=
ringBufferWalkExtended
+
CommitWidth
.
U
// Debug(){
printf
(
"[ROQ] rolling back: head %d tail %d walk %d\n"
,
ringBufferHead
,
ringBufferTail
,
ringBufferWalk
)
// }
XSInfo
(
"rolling back: head %d tail %d walk %d\n"
,
ringBufferHead
,
ringBufferTail
,
ringBufferWalk
)
}
when
(
io
.
brqRedirect
.
valid
){
...
...
@@ -102,4 +121,41 @@ class Roq extends XSModule {
// roq redirect only used for exception
io
.
redirect
:=
DontCare
//TODO
io
.
redirect
.
valid
:=
false
.
B
//TODO
// debug info
XSDebug
(
"head %d tail %d\n"
,
ringBufferHead
,
ringBufferTail
)
XSDebug
(
""
)
XSDebug
(){
for
(
i
<-
0
until
RoqSize
){
when
(!
valid
(
i
)){
printf
(
"-"
)}
when
(
valid
(
i
)
&&
writebacked
(
i
)){
printf
(
"w"
)}
when
(
valid
(
i
)
&&
!
writebacked
(
i
)){
printf
(
"v"
)}
}
printf
(
"\n"
)
}
//difftest signals
val
firstValidCommit
=
ringBufferTail
+
PriorityMux
(
validCommit
,
VecInit
(
List
.
tabulate
(
CommitWidth
)(
_
.
U
)))
val
emptyCsr
=
WireInit
(
0.
U
(
64.
W
))
if
(!
p
.
FPGAPlatform
){
BoringUtils
.
addSink
(
RegNext
(
retireCounter
),
"difftestCommit"
)
BoringUtils
.
addSink
(
RegNext
(
microOp
(
firstValidCommit
).
cf
.
pc
),
"difftestThisPC"
)
//first valid PC
BoringUtils
.
addSink
(
RegNext
(
microOp
(
firstValidCommit
).
cf
.
instr
),
"difftestThisINST"
)
//first valid inst
BoringUtils
.
addSink
(
archRF
,
"difftestRegs"
)
//arch RegFile
BoringUtils
.
addSink
(
RegNext
(
false
.
B
),
"difftestSkip"
)
//SKIP
BoringUtils
.
addSink
(
RegNext
(
false
.
B
),
"difftestIsRVC"
)
//FIXIT
BoringUtils
.
addSink
(
RegNext
(
0.
U
),
"difftestIntrNO"
)
//TODO: skip insts that commited in the same cycle ahead of exception
//csr debug signals
val
ModeM
=
WireInit
(
0x3
.
U
)
BoringUtils
.
addSource
(
ModeM
,
"difftestMode"
)
BoringUtils
.
addSource
(
emptyCsr
,
"difftestMstatus"
)
BoringUtils
.
addSource
(
emptyCsr
,
"difftestSstatus"
)
BoringUtils
.
addSource
(
emptyCsr
,
"difftestMepc"
)
BoringUtils
.
addSource
(
emptyCsr
,
"difftestSepc"
)
BoringUtils
.
addSource
(
emptyCsr
,
"difftestMcause"
)
BoringUtils
.
addSource
(
emptyCsr
,
"difftestScause"
)
}
}
src/main/scala/xiangshan/frontend/Frontend.scala
浏览文件 @
8c0bf90f
...
...
@@ -4,6 +4,7 @@ import chisel3._
import
chisel3.util._
import
utils.PipelineConnect
import
xiangshan._
import
xiangshan.utils.XSInfo
class
Frontend
extends
XSModule
{
val
io
=
IO
(
new
Bundle
()
{
...
...
@@ -19,4 +20,11 @@ class Frontend extends XSModule {
ibuffer
.
io
.
flush
:=
io
.
backend
.
redirect
.
valid
io
.
backend
.
cfVec
<>
ibuffer
.
io
.
out
for
(
out
<-
ibuffer
.
io
.
out
){
XSInfo
(
out
.
fire
(),
p
"inst:${Hexadecimal(out.bits.instr)} pc:${Hexadecimal(out.bits.pc)}\n"
)
}
}
src/main/scala/xiangshan/utils/LogUtils.scala
0 → 100644
浏览文件 @
8c0bf90f
package
xiangshan.utils
import
chisel3._
import
xiangshan.HasXSParameter
import
xiangshan.utils.XSLogLevel.XSLogLevel
object
XSLogLevel
extends
Enumeration
{
type
XSLogLevel
=
Value
val
ALL
=
Value
(
"ALL"
)
val
DEBUG
=
Value
(
"DEBUG"
)
val
INFO
=
Value
(
"INFO"
)
val
WARN
=
Value
(
"WARN"
)
val
ERROR
=
Value
(
"ERROR"
)
val
OFF
=
Value
(
"OFF"
)
}
object
XSLog
extends
HasXSParameter
{
def
apply
(
debugLevel
:
XSLogLevel
)
(
cond
:
Bool
,
pable
:
Printable
)
(
implicit
m
:
Module
)
:
Any
=
{
if
(
debugLevel
>=
LogLevel
)
{
when
(
cond
)
{
val
commonInfo
=
p
"[$debugLevel][time=${GTimer()}] ${m.name}: "
printf
(
commonInfo
+
pable
)
}
}
}
}
sealed
abstract
class
LogHelper
(
val
logLevel
:
XSLogLevel
)
extends
HasXSParameter
{
def
apply
(
cond
:
Bool
,
fmt
:
String
,
data
:
Bits*
)(
implicit
m
:
Module
)
:
Any
=
apply
(
cond
,
Printable
.
pack
(
fmt
,
data
:_
*
))
def
apply
(
cond
:
Bool
,
pable
:
Printable
)(
implicit
m
:
Module
)
:
Any
=
XSLog
(
logLevel
)(
cond
,
pable
)
def
apply
(
fmt
:
String
,
data
:
Bits*
)(
implicit
m
:
Module
)
:
Any
=
apply
(
true
.
B
,
Printable
.
pack
(
fmt
,
data
:_
*
))
def
apply
(
pable
:
Printable
)(
implicit
m
:
Module
)
:
Any
=
XSLog
(
logLevel
)(
true
.
B
,
pable
)
// Do not use that unless you have valid reasons
def
apply
(
cond
:
Bool
=
true
.
B
)(
body
:
=>
Unit
)
:
Any
=
if
(
logLevel
>=
LogLevel
)
{
when
(
cond
)
{
body
}
}
}
object
XSDebug
extends
LogHelper
(
XSLogLevel
.
DEBUG
)
object
XSInfo
extends
LogHelper
(
XSLogLevel
.
INFO
)
object
XSWarn
extends
LogHelper
(
XSLogLevel
.
WARN
)
object
XSError
extends
LogHelper
(
XSLogLevel
.
ERROR
)
src/test/csrc/difftest.cpp
浏览文件 @
8c0bf90f
...
...
@@ -83,9 +83,10 @@ static const char *reg_name[DIFFTEST_NR_REG] = {
"sstatus"
,
"scause"
,
"sepc"
};
int
difftest_step
(
uint64_t
*
reg_scala
,
uint32_t
this_inst
,
int
isMMIO
,
int
isRVC
,
uint64_t
intrNO
,
int
priviledgeMode
)
{
int
difftest_step
(
int
commit
,
uint64_t
*
reg_scala
,
uint32_t
this_inst
,
int
skip
,
int
isRVC
,
uint64_t
intrNO
,
int
priviledgeMode
)
{
assert
(
!
skip
&&
!
isRVC
&&
intrNO
==
0
);
#define DEBUG_RETIRE_TRACE_SIZE 16
uint64_t
ref_r
[
DIFFTEST_NR_REG
];
...
...
@@ -97,7 +98,7 @@ int difftest_step(uint64_t *reg_scala, uint32_t this_inst,
static
uint32_t
inst_retire_queue
[
DEBUG_RETIRE_TRACE_SIZE
]
=
{
0
};
static
int
pc_retire_pointer
=
7
;
if
(
isMMIO
)
{
if
(
skip
)
{
// printf("diff pc: %x isRVC %x\n", this_pc, isRVC);
// MMIO accessing should not be a branch or jump, just +2/+4 to get the next pc
reg_scala
[
DIFFTEST_THIS_PC
]
+=
isRVC
?
2
:
4
;
...
...
@@ -112,10 +113,11 @@ int difftest_step(uint64_t *reg_scala, uint32_t this_inst,
if
(
intrNO
)
{
ref_difftest_raise_intr
(
intrNO
);
}
else
{
ref_difftest_exec
(
1
);
ref_difftest_exec
(
1
);
//TODO
}
assert
(
commit
>
0
&&
commit
<=
6
);
ref_difftest_exec
(
commit
);
ref_difftest_getregs
(
&
ref_r
);
uint64_t
next_pc
=
ref_r
[
DIFFTEST_THIS_PC
];
...
...
@@ -123,17 +125,18 @@ int difftest_step(uint64_t *reg_scala, uint32_t this_inst,
pc_retire_queue
[
pc_retire_pointer
]
=
this_pc
;
inst_retire_queue
[
pc_retire_pointer
]
=
this_inst
;
int
isCSR
=
((
this_inst
&
0x7f
)
==
0x73
);
int
isCSRMip
=
((
this_inst
>>
20
)
==
0x344
)
&&
isCSR
;
if
(
isCSRMip
)
{
// We can not handle NEMU.mip.mtip since it is driven by CLINT,
// which is not accessed in NEMU due to MMIO.
// Just sync the state of NEMU from NOOP.
reg_scala
[
DIFFTEST_THIS_PC
]
=
next_pc
;
nemu_this_pc
=
next_pc
;
ref_difftest_setregs
(
reg_scala
);
return
0
;
}
// TODO: fix mip.mtip
// int isCSR = ((this_inst & 0x7f) == 0x73);
// int isCSRMip = ((this_inst >> 20) == 0x344) && isCSR;
// if (isCSRMip) {
// // We can not handle NEMU.mip.mtip since it is driven by CLINT,
// // which is not accessed in NEMU due to MMIO.
// // Just sync the state of NEMU from NOOP.
// reg_scala[DIFFTEST_THIS_PC] = next_pc;
// nemu_this_pc = next_pc;
// ref_difftest_setregs(reg_scala);
// return 0;
// }
// replace with "this pc" for checking
ref_r
[
DIFFTEST_THIS_PC
]
=
nemu_this_pc
;
...
...
src/test/csrc/emu.h
浏览文件 @
8c0bf90f
...
...
@@ -148,10 +148,10 @@ class Emulator {
uint64_t
reg
[
DIFFTEST_NR_REG
];
read_emu_regs
(
reg
);
extern
int
difftest_step
(
uint64_t
*
reg_scala
,
uint32_t
this_inst
,
int
isMMIO
,
int
isRVC
,
uint64_t
intrNO
,
int
priviledgeMode
);
if
(
difftest_step
(
reg
,
dut_ptr
->
io_difftest_thisINST
,
dut_ptr
->
io_difftest_
isMMIO
,
dut_ptr
->
io_difftest_isRVC
,
extern
int
difftest_step
(
int
commit
,
uint64_t
*
reg_scala
,
uint32_t
this_inst
,
int
skip
,
int
isRVC
,
uint64_t
intrNO
,
int
priviledgeMode
);
if
(
difftest_step
(
dut_ptr
->
io_difftest_commit
,
reg
,
dut_ptr
->
io_difftest_thisINST
,
dut_ptr
->
io_difftest_
skip
,
dut_ptr
->
io_difftest_isRVC
,
dut_ptr
->
io_difftest_intrNO
,
dut_ptr
->
io_difftest_priviledgeMode
))
{
#if VM_TRACE
tfp
->
close
();
...
...
src/test/scala/top/XSSim.scala
浏览文件 @
8c0bf90f
...
...
@@ -11,10 +11,10 @@ import xiangshan._
class
DiffTestIO
extends
Bundle
{
val
r
=
Output
(
Vec
(
64
,
UInt
(
64.
W
)))
val
commit
=
Output
(
Bool
(
))
val
commit
=
Output
(
UInt
(
32.
W
))
val
thisPC
=
Output
(
UInt
(
64.
W
))
val
thisINST
=
Output
(
UInt
(
32.
W
))
val
isMMIO
=
Output
(
Bool
())
val
skip
=
Output
(
Bool
())
val
isRVC
=
Output
(
Bool
())
val
intrNO
=
Output
(
UInt
(
64.
W
))
...
...
@@ -54,7 +54,7 @@ class XSSimTop extends Module {
BoringUtils
.
addSink
(
difftest
.
commit
,
"difftestCommit"
)
BoringUtils
.
addSink
(
difftest
.
thisPC
,
"difftestThisPC"
)
BoringUtils
.
addSink
(
difftest
.
thisINST
,
"difftestThisINST"
)
BoringUtils
.
addSink
(
difftest
.
isMMIO
,
"difftestIsMMIO
"
)
BoringUtils
.
addSink
(
difftest
.
skip
,
"difftestSkip
"
)
BoringUtils
.
addSink
(
difftest
.
isRVC
,
"difftestIsRVC"
)
BoringUtils
.
addSink
(
difftest
.
intrNO
,
"difftestIntrNO"
)
BoringUtils
.
addSink
(
difftest
.
r
,
"difftestRegs"
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录