Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenXiangShan
XiangShan
提交
f6235c24
X
XiangShan
项目概览
OpenXiangShan
/
XiangShan
12 个月 前同步成功
通知
1183
Star
3914
Fork
526
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
X
XiangShan
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
f6235c24
编写于
6月 25, 2020
作者:
Y
YikeZhou
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' into decoder-dev
上级
973d04d8
4abd92c2
变更
15
隐藏空白更改
内联
并排
Showing
15 changed file
with
719 addition
and
155 deletion
+719
-155
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/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
+335
-5
src/main/scala/xiangshan/backend/rename/BusyTable.scala
src/main/scala/xiangshan/backend/rename/BusyTable.scala
+2
-1
src/main/scala/xiangshan/backend/roq/Roq.scala
src/main/scala/xiangshan/backend/roq/Roq.scala
+35
-3
src/main/scala/xiangshan/frontend/Ibuffer.scala
src/main/scala/xiangshan/frontend/Ibuffer.scala
+177
-14
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
浏览文件 @
f6235c24
...
...
@@ -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
浏览文件 @
f6235c24
...
...
@@ -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
浏览文件 @
f6235c24
...
...
@@ -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/dispatch/Dispatch1.scala
浏览文件 @
f6235c24
...
...
@@ -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
浏览文件 @
f6235c24
...
...
@@ -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
浏览文件 @
f6235c24
...
...
@@ -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
浏览文件 @
f6235c24
...
...
@@ -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
浏览文件 @
f6235c24
...
...
@@ -3,8 +3,57 @@ package xiangshan.backend.issue
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.utils._
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
))
}
sealed
class
CompareCircuitUnit
(
layer
:
Int
=
0
,
id
:
Int
=
0
)
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
}
if
(
debug
&&
(
layer
==
3
))
{
printf
(
"(%d)[CCU(L%did%d)] in1.ready:%d in1.index:%d || in1.ready:%d in1.index:%d || out.ready:%d out.index:%d\n"
,
GTimer
(),
layer
.
asUInt
,
id
.
asUInt
,
inst1Rdy
,
iqIdx1
,
inst2Rdy
,
iqIdx2
,
io
.
out
.
instRdy
,
io
.
out
.
iqIdx
)
}
class
IssueQueue
(
val
fuTypeInt
:
BigInt
,
wakeupCnt
:
Int
,
val
bypassCnt
:
Int
)
extends
XSModule
with
NeedImpl
{
}
class
IssueQueue
(
val
fuTypeInt
:
BigInt
,
val
wakeupCnt
:
Int
,
val
bypassCnt
:
Int
=
0
,
val
fixedDelay
:
Int
=
1
)
extends
IQModule
{
val
useBypass
=
bypassCnt
>
0
...
...
@@ -18,16 +67,297 @@ 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
validFire
=
WireInit
(
VecInit
(
Seq
.
fill
(
iqSize
)(
false
.
B
)))
val
valid
=
validReg
.
asUInt
&
~
validFire
.
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"
)
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
)
:=
Mux
(
io
.
enqCtrl
.
bits
.
ctrl
.
src1Type
=/=
SrcType
.
reg
,
true
.
B
,
io
.
enqCtrl
.
bits
.
src1State
===
SrcState
.
rdy
)
src2Rdy
(
enqueueSelect
)
:=
Mux
(
io
.
enqCtrl
.
bits
.
ctrl
.
src2Type
=/=
SrcType
.
reg
,
true
.
B
,
io
.
enqCtrl
.
bits
.
src2State
===
SrcState
.
rdy
)
src3Rdy
(
enqueueSelect
)
:=
Mux
(
io
.
enqCtrl
.
bits
.
ctrl
.
src3Type
=/=
SrcType
.
reg
,
true
.
B
,
io
.
enqCtrl
.
bits
.
src3State
===
SrcState
.
rdy
)
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
)
{
printf
(
"(%d)[IQ enq]: enqSelect:%d | s1Rd:%d s2Rd:%d s3Rd:%d\n"
,
GTimer
(),
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
)
{
printf
(
"(%d)[Reg info] enqSelNext:%d | enqFireNext:%d \n"
,
GTimer
(),
enqSelNext
,
enqFireNext
)
printf
(
"(%d)[IQ content] valid | src1rdy src1 | src2Rdy src2 pdest \n"
,
GTimer
())
for
(
i
<-
0
to
(
iqSize
-
1
)){
printf
(
"(%d)[IQ content][%d] %d%d%d | %x %x | %x %x | %d"
,
GTimer
(),
i
.
asUInt
,
valid
(
i
),
validReg
(
i
),
validFire
(
i
),
src1Rdy
(
i
),
src1Data
(
i
),
src2Rdy
(
i
),
src2Data
(
i
),
prfDest
(
i
))
when
(
valid
(
i
)){
printf
(
" valid"
)}
printf
(
" |\n"
)
}
}
// 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
)}
}}
}
}
}
//---------------------------------------------------------
// Select Circuit
//---------------------------------------------------------
//layer 1
val
layer1CCUs
=
(
0
until
layer1Size
by
2
)
map
{
i
=>
val
CCU_1
=
Module
(
new
CompareCircuitUnit
(
layer
=
1
,
id
=
i
/
2
))
CCU_1
.
io
.
in1
.
instRdy
:=
instRdy
(
i
)
CCU_1
.
io
.
in1
.
roqIdx
:=
roqIdx
(
i
)
CCU_1
.
io
.
in1
.
iqIdx
:=
i
.
U
CCU_1
.
io
.
in2
.
instRdy
:=
instRdy
(
i
+
1
)
CCU_1
.
io
.
in2
.
roqIdx
:=
roqIdx
(
i
+
1
)
CCU_1
.
io
.
in2
.
iqIdx
:=
(
i
+
1
).
U
CCU_1
}
//layer 2
val
layer2CCUs
=
(
0
until
layer2Size
by
2
)
map
{
i
=>
val
CCU_2
=
Module
(
new
CompareCircuitUnit
(
layer
=
2
,
id
=
i
/
2
))
CCU_2
.
io
.
in1
.
instRdy
:=
layer1CCUs
(
i
).
io
.
out
.
instRdy
CCU_2
.
io
.
in1
.
roqIdx
:=
layer1CCUs
(
i
).
io
.
out
.
roqIdx
CCU_2
.
io
.
in1
.
iqIdx
:=
layer1CCUs
(
i
).
io
.
out
.
iqIdx
CCU_2
.
io
.
in2
.
instRdy
:=
layer1CCUs
(
i
+
1
).
io
.
out
.
instRdy
CCU_2
.
io
.
in2
.
roqIdx
:=
layer1CCUs
(
i
+
1
).
io
.
out
.
roqIdx
CCU_2
.
io
.
in2
.
iqIdx
:=
layer1CCUs
(
i
+
1
).
io
.
out
.
iqIdx
CCU_2
}
//layer 3
val
CCU_3
=
Module
(
new
CompareCircuitUnit
(
layer
=
3
,
id
=
0
))
CCU_3
.
io
.
in1
.
instRdy
:=
layer2CCUs
(
0
).
io
.
out
.
instRdy
CCU_3
.
io
.
in1
.
roqIdx
:=
layer2CCUs
(
0
).
io
.
out
.
roqIdx
CCU_3
.
io
.
in1
.
iqIdx
:=
layer2CCUs
(
0
).
io
.
out
.
iqIdx
CCU_3
.
io
.
in2
.
instRdy
:=
layer2CCUs
(
1
).
io
.
out
.
instRdy
CCU_3
.
io
.
in2
.
roqIdx
:=
layer2CCUs
(
1
).
io
.
out
.
roqIdx
CCU_3
.
io
.
in2
.
iqIdx
:=
layer2CCUs
(
1
).
io
.
out
.
iqIdx
//---------------------------------------------------------
// 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
&&
valid
(
i
)
){
validReg
(
i
)
:=
false
.
B
}
.
elsewhen
(
expRedirect
)
{
validReg
(
i
)
:=
false
.
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
)
{
printf
(
"(%d)[Sel Reg] selInstRdy:%d || selIdx:%d\n"
,
GTimer
(),
selInstRdy
,
selInstIdx
.
asUInt
)
when
(
IQreadyGo
){
printf
(
"(%d)[IQ dequeue] **fire:%d** roqIdx:%d dequeueSel:%d | src1Rd:%d src1:%d | src2Rd:%d src2:%d\n"
,
GTimer
(),
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
validFire
(
dequeueSelect
)
:=
true
.
B
}
val
selRegflush
=
expRedirect
||
(
brRedirect
&&
brRedirectMaskMatch
)
selInstRdy
:=
Mux
(
selRegflush
,
false
.
B
,
CCU_3
.
io
.
out
.
instRdy
)
selInstIdx
:=
Mux
(
selRegflush
,
0.
U
,
CCU_3
.
io
.
out
.
iqIdx
)
// SelectedUop (bypass / speculative)
if
(
useBypass
)
{
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
=
CCU_3
.
io
.
out
.
iqIdx
val
delayPipe
=
DelayPipe
(
VecInit
(
CCU_3
.
io
.
out
.
instRdy
,
prfDest
(
selIQIdx
)),
fixedDelay
-
1
)
sel
.
valid
:=
delayPipe
(
fixedDelay
-
1
)(
0
)
sel
.
bits
:=
DontCare
sel
.
bits
.
pdest
:=
delayPipe
(
fixedDelay
-
1
)(
1
)
}
}
src/main/scala/xiangshan/backend/rename/BusyTable.scala
浏览文件 @
f6235c24
...
...
@@ -3,6 +3,7 @@ package xiangshan.backend.rename
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.utils.ParallelOR
class
BusyTable
extends
XSModule
{
val
io
=
IO
(
new
Bundle
()
{
...
...
@@ -19,7 +20,7 @@ class BusyTable extends XSModule {
val
table
=
RegInit
(
VecInit
(
Seq
.
fill
(
NRPhyRegs
)(
false
.
B
)))
for
((
raddr
,
rdy
)
<-
io
.
rfReadAddr
.
zip
(
io
.
pregRdy
)){
rdy
:=
!
table
(
raddr
)
rdy
:=
!
table
(
raddr
)
||
ParallelOR
(
io
.
wbPregs
.
map
(
wb
=>
wb
.
valid
&&
(
wb
.
bits
===
raddr
))).
asBool
()
}
for
((
alloc
,
i
)
<-
io
.
allocPregs
.
zipWithIndex
){
...
...
src/main/scala/xiangshan/backend/roq/Roq.scala
浏览文件 @
f6235c24
...
...
@@ -3,9 +3,10 @@ package xiangshan.backend.roq
import
chisel3._
import
chisel3.util._
import
xiangshan._
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 +21,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
))
...
...
@@ -57,6 +60,8 @@ class Roq extends XSModule {
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
}
}
...
...
@@ -65,6 +70,7 @@ class Roq extends XSModule {
when
(
state
===
s_idle
){
io
.
commits
(
i
).
valid
:=
valid
(
ringBufferTail
+
i
.
U
)
&&
writebacked
(
ringBufferTail
+
i
.
U
)
io
.
commits
(
i
).
bits
.
uop
:=
microOp
(
ringBufferTail
+
i
.
U
)
when
(
microOp
(
i
).
ctrl
.
rfWen
){
archRF
(
microOp
(
i
).
ctrl
.
ldest
)
:=
exuData
(
i
)
}
when
(
valid
(
ringBufferTail
+
i
.
U
)){
valid
(
ringBufferTail
+
i
.
U
)
:=
false
.
B
}
//FIXIT
}.
otherwise
{
//state === s_walk
io
.
commits
(
i
).
valid
:=
valid
(
ringBufferWalk
+
i
.
U
)
&&
writebacked
(
ringBufferWalk
+
i
.
U
)
...
...
@@ -78,6 +84,7 @@ class Roq extends XSModule {
when
(
state
===
s_idle
){
ringBufferTailExtended
:=
ringBufferTailExtended
+
PopCount
(
validCommit
)
}
val
retireCounter
=
Mux
(
state
===
s_idle
,
PopCount
(
validCommit
),
0.
U
)
val
walkFinished
=
(
0
until
CommitWidth
).
map
(
i
=>
(
ringBufferWalk
+
i
.
U
)
===
ringBufferWalkTarget
).
reduce
(
_
||
_
)
...
...
@@ -102,4 +109,29 @@ class Roq extends XSModule {
// roq redirect only used for exception
io
.
redirect
:=
DontCare
//TODO
io
.
redirect
.
valid
:=
false
.
B
//TODO
//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/Ibuffer.scala
浏览文件 @
f6235c24
package
xiangshan.frontend
import
chisel3._
import
chisel3.util._
import
xiangshan._
import
xiangshan.utils._
class
Ibuffer
extends
XSModule
with
NeedImpl
{
val
io
=
IO
(
new
Bundle
()
{
val
flush
=
Input
(
Bool
())
val
in
=
Flipped
(
DecoupledIO
(
new
FetchPacket
))
val
out
=
Vec
(
DecodeWidth
,
DecoupledIO
(
new
CtrlFlow
))
})
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
))
})
val
debug
=
false
if
(
debug
){
// printf("\n------New Cycle------\n")
when
(
io
.
in
.
valid
)
{
printf
(
"cache data:\n"
)
for
(
i
<-
0
until
FetchWidth
)
{
printf
(
"%b\n"
,
io
.
in
.
bits
.
instrs
(
i
))
}
printf
(
"\n"
)
}
}
// ignore
for
(
i
<-
0
until
DecodeWidth
)
{
io
.
out
(
i
).
bits
.
exceptionVec
:=
DontCare
io
.
out
(
i
).
bits
.
intrVec
:=
DontCare
io
.
out
(
i
).
bits
.
isBr
:=
DontCare
}
// ibuf define
val
ibuf
=
RegInit
(
VecInit
(
Seq
.
fill
(
IBufSize
*
2
)(
0.
U
(
16.
W
))))
val
ibuf_pc
=
RegInit
(
VecInit
(
Seq
.
fill
(
IBufSize
*
2
)(
0.
U
(
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
)
{
if
(
debug
)
{
printf
(
"\n*****Enque start*****\n"
)
}
var
enq_idx
=
0.
U
(
log2Up
(
FetchWidth
*
2
+
1
).
W
)
for
(
i
<-
0
until
FetchWidth
)
{
when
(
io
.
in
.
bits
.
mask
(
i
))
{
ibuf
(
tail_ptr
+
enq_idx
)
:=
io
.
in
.
bits
.
instrs
(
i
)(
15
,
0
)
ibuf_pc
(
tail_ptr
+
enq_idx
)
:=
io
.
in
.
bits
.
pc
+
enq_idx
+
enq_idx
ibuf_valid
(
tail_ptr
+
enq_idx
)
:=
true
.
B
ibuf
(
tail_ptr
+
enq_idx
+
1.
U
)
:=
io
.
in
.
bits
.
instrs
(
i
)(
31
,
16
)
ibuf_pc
(
tail_ptr
+
enq_idx
+
1.
U
)
:=
io
.
in
.
bits
.
pc
+
enq_idx
+
enq_idx
+
2.
U
ibuf_valid
(
tail_ptr
+
enq_idx
+
1.
U
)
:=
true
.
B
if
(
debug
)
{
printf
(
"%b\n"
,
io
.
in
.
bits
.
instrs
(
i
)(
15
,
0
))
printf
(
"%b\n"
,
io
.
in
.
bits
.
instrs
(
i
)(
31
,
16
))
}
}
enq_idx
=
enq_idx
+
io
.
in
.
bits
.
mask
(
i
)
+
io
.
in
.
bits
.
mask
(
i
)
}
tail_ptr
:=
tail_ptr
+
enq_idx
last_enq
:=
true
.
B
if
(
debug
)
{
printf
(
"tail_ptr: %d\n"
,
tail_ptr
+
enq_idx
)
}
}
// deque
when
(
deqValid
)
{
if
(
debug
)
{
printf
(
"\n*****Deque start*****\n"
)
printf
(
"Last head_ptr: %d, tail_ptr: %d\n"
,
head_ptr
,
tail_ptr
)
}
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
)
if
(
debug
)
{
printf
(
"RCV: %b "
,
Cat
(
0.
U
(
16.
W
),
ibuf
(
head_ptr
+
deq_idx
)))
printf
(
"PC: %d\n"
,
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
)
if
(
debug
)
{
printf
(
"NOT RVC: %b "
,
Cat
(
ibuf
(
head_ptr
+
deq_idx
+
1.
U
),
ibuf
(
head_ptr
+
deq_idx
)))
printf
(
"PC: %d\n"
,
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
)
if
(
debug
)
{
printf
(
"This is half inst\n"
)
}
io
.
out
(
i
).
bits
.
pc
:=
0.
U
(
VAddrBits
.
W
)
io
.
out
(
i
).
bits
.
isRVC
:=
false
.
B
io
.
out
(
i
).
valid
:=
false
.
B
}
}.
otherwise
{
if
(
debug
)
{
printf
(
"This output is not ready, or buffer is empty\n"
)
}
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
}
if
(
debug
)
{
printf
(
"deq_idx: %d\n"
,
deq_idx
)
}
// 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
+
(
io
.
out
(
i
).
ready
&&
ibuf_valid
(
head_ptr
+
deq_idx
)
&&
ibuf
(
head_ptr
+
deq_idx
)(
1
,
0
)
=/=
"b11"
.
U
)
+
(
io
.
out
(
i
).
ready
&&
ibuf_valid
(
head_ptr
+
deq_idx
)
&&
!(
ibuf
(
head_ptr
+
deq_idx
)(
1
,
0
)
=/=
"b11"
.
U
)
&&
ibuf_valid
(
head_ptr
+
deq_idx
+
1.
U
))
+
(
io
.
out
(
i
).
ready
&&
ibuf_valid
(
head_ptr
+
deq_idx
)
&&
!(
ibuf
(
head_ptr
+
deq_idx
)(
1
,
0
)
=/=
"b11"
.
U
)
&&
ibuf_valid
(
head_ptr
+
deq_idx
+
1.
U
))
}
head_ptr
:=
head_ptr
+
deq_idx
if
(
debug
)
{
printf
(
"head_ptr: %d\n"
,
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
)
{
ibuf_valid
(
i
)
:=
false
.
B
head_ptr
:=
0.
U
tail_ptr
:=
0.
U
}
for
(
i
<-
0
until
DecodeWidth
)
{
io
.
out
(
i
).
valid
:=
false
.
B
}
}
}
\ No newline at end of file
src/main/scala/xiangshan/utils/LogUtils.scala
0 → 100644
浏览文件 @
f6235c24
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
浏览文件 @
f6235c24
...
...
@@ -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
浏览文件 @
f6235c24
...
...
@@ -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
浏览文件 @
f6235c24
...
...
@@ -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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录