Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenXiangShan
XiangShan
提交
54453403
X
XiangShan
项目概览
OpenXiangShan
/
XiangShan
10 个月 前同步成功
通知
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,体验更适合开发者的 AI 搜索 >>
提交
54453403
编写于
10月 09, 2019
作者:
Z
Zihao Yu
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'icache-mmio' into 'master'
Icache mmio See merge request projectn/noop!31
上级
12ed0a0e
0997f329
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
175 addition
and
124 deletion
+175
-124
src/main/scala/bus/simplebus/Crossbar.scala
src/main/scala/bus/simplebus/Crossbar.scala
+75
-31
src/main/scala/noop/Cache.scala
src/main/scala/noop/Cache.scala
+78
-38
src/main/scala/noop/EXU.scala
src/main/scala/noop/EXU.scala
+0
-3
src/main/scala/noop/IFU.scala
src/main/scala/noop/IFU.scala
+7
-6
src/main/scala/noop/NOOP.scala
src/main/scala/noop/NOOP.scala
+5
-22
src/main/scala/noop/fu/LSU.scala
src/main/scala/noop/fu/LSU.scala
+8
-22
src/test/scala/top/SimMMIO.scala
src/test/scala/top/SimMMIO.scala
+2
-2
未找到文件。
src/main/scala/bus/simplebus/Crossbar.scala
浏览文件 @
54453403
...
...
@@ -5,57 +5,47 @@ import chisel3.util._
import
utils._
class
SimpleBusCrossbar
(
m
:
Int
,
addressSpace
:
List
[(
Long
,
Long
)])
extends
Module
{
class
SimpleBusCrossbar
1toN
(
addressSpace
:
List
[(
Long
,
Long
)])
extends
Module
{
val
io
=
IO
(
new
Bundle
{
val
in
=
Flipped
(
Vec
(
m
,
new
SimpleBusUC
)
)
val
in
=
Flipped
(
new
SimpleBusUC
)
val
out
=
Vec
(
addressSpace
.
length
,
new
SimpleBusUC
)
})
require
(
m
==
1
,
"now we only support 1 input channel"
)
val
inSel
=
io
.
in
(
0
)
val
s_idle
::
s_resp
::
Nil
=
Enum
(
2
)
val
state
=
RegInit
(
s_idle
)
// select the output channel according to the address
val
addr
=
i
nSel
.
req
.
bits
.
addr
val
addr
=
i
o
.
in
.
req
.
bits
.
addr
val
outSelVec
=
VecInit
(
addressSpace
.
map
(
range
=>
(
addr
>=
range
.
_1
.
U
&&
addr
<
(
range
.
_1
+
range
.
_2
).
U
)))
val
outSelIdx
=
PriorityEncoder
(
outSelVec
)
val
outSel
=
io
.
out
(
outSelIdx
)
val
outSelIdxResp
=
RegEnable
(
outSelIdx
,
outSel
.
req
.
fire
()
&&
(
state
===
s_idle
))
val
outSelResp
=
io
.
out
(
outSelIdxResp
)
assert
(!
inSel
.
req
.
valid
||
outSelVec
.
asUInt
.
orR
,
"address decode error, bad addr = 0x%x\n"
,
addr
)
assert
(!(
inSel
.
req
.
valid
&&
outSelVec
.
asUInt
.
andR
),
"address decode error, bad addr = 0x%x\n"
,
addr
)
val
s_idle
::
s_req
::
s_resp
::
Nil
=
Enum
(
3
)
val
state
=
RegInit
(
s_idle
)
assert
(!
io
.
in
.
req
.
valid
||
outSelVec
.
asUInt
.
orR
,
"address decode error, bad addr = 0x%x\n"
,
addr
)
assert
(!(
io
.
in
.
req
.
valid
&&
outSelVec
.
asUInt
.
andR
),
"address decode error, bad addr = 0x%x\n"
,
addr
)
// bind out.req channel
(
io
.
out
zip
outSelVec
).
map
{
case
(
o
,
v
)
=>
{
o
.
req
.
bits
:=
i
nSel
.
req
.
bits
o
.
req
.
valid
:=
v
&&
(
(
inSel
.
req
.
valid
&&
(
state
===
s_idle
))
||
(
state
===
s_req
))
o
.
req
.
bits
:=
i
o
.
in
.
req
.
bits
o
.
req
.
valid
:=
v
&&
(
io
.
in
.
req
.
valid
&&
(
state
===
s_idle
))
o
.
resp
.
ready
:=
v
}}
val
bypass_s_resp
=
Mux
(
outSel
.
resp
.
fire
(),
s_idle
,
s_resp
)
val
bypass_s_req
=
Mux
(
outSel
.
req
.
fire
(),
bypass_s_resp
,
s_req
)
switch
(
state
)
{
is
(
s_idle
)
{
when
(
inSel
.
req
.
valid
)
{
state
:=
bypass_s_req
}
}
is
(
s_req
)
{
when
(
outSel
.
req
.
fire
())
{
state
:=
bypass_s_resp
}
}
is
(
s_resp
)
{
when
(
outSel
.
resp
.
fire
())
{
state
:=
s_idle
}
}
is
(
s_idle
)
{
when
(
outSel
.
req
.
fire
())
{
state
:=
s_resp
}
}
is
(
s_resp
)
{
when
(
outSelResp
.
resp
.
fire
())
{
state
:=
s_idle
}
}
}
i
nSel
.
resp
.
valid
:=
outSel
.
resp
.
fire
()
i
nSel
.
resp
.
bits
<>
outSel
.
resp
.
bits
outSel
.
resp
.
ready
:=
inSel
.
resp
.
ready
i
nSel
.
req
.
ready
:=
outSel
.
req
.
ready
i
o
.
in
.
resp
.
valid
:=
outSelResp
.
resp
.
fire
()
i
o
.
in
.
resp
.
bits
<>
outSelResp
.
resp
.
bits
outSel
Resp
.
resp
.
ready
:=
io
.
in
.
resp
.
ready
i
o
.
in
.
req
.
ready
:=
outSel
.
req
.
ready
Debug
()
{
when
(
state
===
s_idle
&&
i
nSel
.
req
.
valid
)
{
printf
(
p
"${GTimer()}: xbar: in.req: ${i
nSel
.req.bits}\n"
)
when
(
state
===
s_idle
&&
i
o
.
in
.
req
.
valid
)
{
printf
(
p
"${GTimer()}: xbar: in.req: ${i
o.in
.req.bits}\n"
)
}
when
(
outSel
.
req
.
fire
())
{
...
...
@@ -65,8 +55,62 @@ class SimpleBusCrossbar(m: Int, addressSpace: List[(Long, Long)]) extends Module
printf
(
p
"${GTimer()}: xbar: outSelIdx= ${outSelIdx}, outSel.resp: ${outSel.resp.bits}\n"
)
}
when
(
inSel
.
resp
.
fire
())
{
printf
(
p
"${GTimer()}: xbar: in.resp: ${inSel.resp.bits}\n"
)
when
(
io
.
in
.
resp
.
fire
())
{
printf
(
p
"${GTimer()}: xbar: in.resp: ${io.in.resp.bits}\n"
)
}
}
}
class
SimpleBusCrossbarNto1
(
n
:
Int
)
extends
Module
{
val
io
=
IO
(
new
Bundle
{
val
in
=
Flipped
(
Vec
(
n
,
new
SimpleBusUC
))
val
out
=
new
SimpleBusUC
})
val
s_idle
::
s_readResp
::
s_writeResp
::
Nil
=
Enum
(
3
)
val
state
=
RegInit
(
s_idle
)
val
lockWriteFun
=
((
x
:
SimpleBusReqBundle
)
=>
x
.
isWrite
()
&&
x
.
isBurst
())
val
inputArb
=
Module
(
new
LockingArbiter
(
chiselTypeOf
(
io
.
in
(
0
).
req
.
bits
),
n
,
8
,
Some
(
lockWriteFun
)))
(
inputArb
.
io
.
in
zip
io
.
in
.
map
(
_
.
req
)).
map
{
case
(
arb
,
in
)
=>
arb
<>
in
}
val
thisReq
=
inputArb
.
io
.
out
assert
(!(
thisReq
.
valid
&&
!
thisReq
.
bits
.
isRead
()
&&
!
thisReq
.
bits
.
isWrite
()))
val
inflightSrc
=
Reg
(
UInt
(
log2Up
(
n
).
W
))
io
.
out
.
req
.
bits
:=
thisReq
.
bits
// bind correct valid and ready signals
io
.
out
.
req
.
valid
:=
thisReq
.
valid
&&
(
state
===
s_idle
)
thisReq
.
ready
:=
io
.
out
.
req
.
ready
&&
(
state
===
s_idle
)
io
.
in
.
map
(
_
.
resp
.
bits
:=
io
.
out
.
resp
.
bits
)
io
.
in
.
map
(
_
.
resp
.
valid
:=
false
.
B
)
(
io
.
in
(
inflightSrc
).
resp
,
io
.
out
.
resp
)
match
{
case
(
l
,
r
)
=>
{
l
.
valid
:=
r
.
valid
r
.
ready
:=
l
.
ready
}}
switch
(
state
)
{
is
(
s_idle
)
{
when
(
thisReq
.
fire
())
{
inflightSrc
:=
inputArb
.
io
.
chosen
when
(
thisReq
.
bits
.
isRead
())
{
state
:=
s_readResp
}
.
elsewhen
(
thisReq
.
bits
.
isWriteLast
()
||
thisReq
.
bits
.
isWriteSingle
())
{
state
:=
s_writeResp
}
}
}
is
(
s_readResp
)
{
when
(
io
.
out
.
resp
.
fire
()
&&
io
.
out
.
resp
.
bits
.
isReadLast
())
{
state
:=
s_idle
}
}
is
(
s_writeResp
)
{
when
(
io
.
out
.
resp
.
fire
())
{
state
:=
s_idle
}
}
}
}
class
SimpleBusCrossbar
(
n
:
Int
,
addressSpace
:
List
[(
Long
,
Long
)])
extends
Module
{
val
io
=
IO
(
new
Bundle
{
val
in
=
Flipped
(
Vec
(
n
,
new
SimpleBusUC
))
val
out
=
Vec
(
addressSpace
.
length
,
new
SimpleBusUC
)
})
val
inXbar
=
Module
(
new
SimpleBusCrossbarNto1
(
n
))
val
outXbar
=
Module
(
new
SimpleBusCrossbar1toN
(
addressSpace
))
inXbar
.
io
.
in
<>
io
.
in
outXbar
.
io
.
in
<>
inXbar
.
io
.
out
io
.
out
<>
outXbar
.
io
.
out
}
src/main/scala/noop/Cache.scala
浏览文件 @
54453403
...
...
@@ -8,14 +8,29 @@ import bus.simplebus._
import
bus.axi4._
import
utils._
case
class
CacheConfig
(
ro
:
Boolean
=
false
,
name
:
String
=
"cache"
,
userBits
:
Int
=
0
,
totalSize
:
Int
=
32
,
// Kbytes
ways
:
Int
=
4
)
sealed
trait
HasCacheConst
{
implicit
val
cacheConfig
:
CacheConfig
val
AddrBits
:
Int
val
XLEN
:
Int
val
TotalSize
=
32
// Kbytes
val
ro
=
cacheConfig
.
ro
val
cacheName
=
cacheConfig
.
name
val
userBits
=
cacheConfig
.
userBits
val
TotalSize
=
cacheConfig
.
totalSize
val
Ways
=
cacheConfig
.
ways
val
LineSize
=
XLEN
// byte
val
LineBeats
=
LineSize
/
8
//DATA WIDTH 64
val
Ways
=
4
val
Sets
=
TotalSize
*
1024
/
LineSize
/
Ways
val
OffsetBits
=
log2Up
(
LineSize
)
val
IndexBits
=
log2Up
(
Sets
)
...
...
@@ -40,10 +55,10 @@ sealed trait HasCacheConst {
def
isSetConflict
(
a1
:
UInt
,
a2
:
UInt
)
=
(
a1
.
asTypeOf
(
addrBundle
).
index
===
a2
.
asTypeOf
(
addrBundle
).
index
)
}
sealed
abstract
class
CacheBundle
extends
Bundle
with
HasNOOPParameter
with
HasCacheConst
sealed
abstract
class
CacheModule
extends
Module
with
HasNOOPParameter
with
HasCacheConst
sealed
abstract
class
CacheBundle
(
implicit
cacheConfig
:
CacheConfig
)
extends
Bundle
with
HasNOOPParameter
with
HasCacheConst
sealed
abstract
class
CacheModule
(
implicit
cacheConfig
:
CacheConfig
)
extends
Module
with
HasNOOPParameter
with
HasCacheConst
sealed
class
MetaBundle
extends
CacheBundle
{
sealed
class
MetaBundle
(
implicit
val
cacheConfig
:
CacheConfig
)
extends
CacheBundle
{
val
tag
=
Output
(
UInt
(
TagBits
.
W
))
val
valid
=
Output
(
Bool
())
val
dirty
=
Output
(
Bool
())
...
...
@@ -56,7 +71,7 @@ sealed class MetaBundle extends CacheBundle {
}
}
sealed
class
DataBundle
extends
CacheBundle
{
sealed
class
DataBundle
(
implicit
val
cacheConfig
:
CacheConfig
)
extends
CacheBundle
{
val
data
=
Output
(
UInt
(
DataBits
.
W
))
def
apply
(
data
:
UInt
)
=
{
...
...
@@ -65,15 +80,15 @@ sealed class DataBundle extends CacheBundle {
}
}
sealed
class
Stage1IO
(
val
userBits
:
Int
=
0
)
extends
CacheBundle
{
sealed
class
Stage1IO
(
implicit
val
cacheConfig
:
CacheConfig
)
extends
CacheBundle
{
val
req
=
new
SimpleBusReqBundle
(
userBits
=
userBits
)
}
// meta read
sealed
class
CacheStage1
(
ro
:
Boolean
,
name
:
String
,
userBits
:
Int
=
0
)
extends
CacheModule
{
sealed
class
CacheStage1
(
implicit
val
cacheConfig
:
CacheConfig
)
extends
CacheModule
{
val
io
=
IO
(
new
Bundle
{
val
in
=
Flipped
(
Decoupled
(
new
SimpleBusReqBundle
(
userBits
=
userBits
)))
val
out
=
Decoupled
(
new
Stage1IO
(
userBits
)
)
val
out
=
Decoupled
(
new
Stage1IO
)
val
metaReadBus
=
CacheMetaArrayReadBus
()
val
dataReadBus
=
CacheDataArrayReadBus
()
...
...
@@ -102,19 +117,20 @@ sealed class CacheStage1(ro: Boolean, name: String, userBits: Int = 0) extends C
io
.
in
.
ready
:=
(!
io
.
in
.
valid
||
io
.
out
.
fire
())
&&
io
.
metaReadBus
.
req
.
ready
&&
io
.
dataReadBus
.
req
.
ready
}
sealed
class
Stage2IO
(
val
userBits
:
Int
=
0
)
extends
CacheBundle
{
sealed
class
Stage2IO
(
implicit
val
cacheConfig
:
CacheConfig
)
extends
CacheBundle
{
val
req
=
new
SimpleBusReqBundle
(
userBits
=
userBits
)
val
metas
=
Vec
(
Ways
,
new
MetaBundle
)
val
datas
=
Vec
(
Ways
,
new
DataBundle
)
val
hit
=
Output
(
Bool
())
val
waymask
=
Output
(
UInt
(
Ways
.
W
))
val
mmio
=
Output
(
Bool
())
}
// check
sealed
class
CacheStage2
(
ro
:
Boolean
,
name
:
String
,
userBits
:
Int
=
0
)
extends
CacheModule
{
sealed
class
CacheStage2
(
implicit
val
cacheConfig
:
CacheConfig
)
extends
CacheModule
{
val
io
=
IO
(
new
Bundle
{
val
in
=
Flipped
(
Decoupled
(
new
Stage1IO
(
userBits
)
))
val
out
=
Decoupled
(
new
Stage2IO
(
userBits
)
)
val
in
=
Flipped
(
Decoupled
(
new
Stage1IO
))
val
out
=
Decoupled
(
new
Stage2IO
)
val
metaReadResp
=
Flipped
(
Vec
(
Ways
,
new
MetaBundle
))
val
dataReadResp
=
Flipped
(
Vec
(
Ways
,
new
DataBundle
))
})
...
...
@@ -131,31 +147,34 @@ sealed class CacheStage2(ro: Boolean, name: String, userBits: Int = 0) extends C
io
.
out
.
bits
.
hit
:=
io
.
in
.
valid
&&
hitVec
.
orR
io
.
out
.
bits
.
waymask
:=
waymask
io
.
out
.
bits
.
datas
:=
io
.
dataReadResp
io
.
out
.
bits
.
mmio
:=
AddressSpace
.
isMMIO
(
req
.
addr
)
io
.
out
.
bits
.
req
<>
io
.
in
.
bits
.
req
io
.
out
.
bits
.
req
<>
req
io
.
out
.
valid
:=
io
.
in
.
valid
io
.
in
.
ready
:=
!
io
.
in
.
valid
||
io
.
out
.
fire
()
}
// writeback
sealed
class
CacheStage3
(
ro
:
Boolean
,
name
:
String
,
userBits
:
Int
=
0
)
extends
CacheModule
{
sealed
class
CacheStage3
(
implicit
val
cacheConfig
:
CacheConfig
)
extends
CacheModule
{
val
io
=
IO
(
new
Bundle
{
val
in
=
Flipped
(
Decoupled
(
new
Stage2IO
(
userBits
)
))
val
in
=
Flipped
(
Decoupled
(
new
Stage2IO
))
val
out
=
Decoupled
(
new
SimpleBusRespBundle
(
userBits
=
userBits
))
val
isFinish
=
Output
(
Bool
())
val
addr
=
Output
(
UInt
(
AddrBits
.
W
))
val
flush
=
Input
(
Bool
())
val
dataWriteBus
=
CacheDataArrayWriteBus
()
val
dataReadBus
=
CacheDataArrayReadBus
()
val
metaWriteBus
=
CacheMetaArrayWriteBus
()
val
mem
=
new
SimpleBusUC
val
mmio
=
new
SimpleBusUC
})
val
req
=
io
.
in
.
bits
.
req
val
addr
=
req
.
addr
.
asTypeOf
(
addrBundle
)
val
mmio
=
io
.
in
.
valid
&&
io
.
in
.
bits
.
mmio
val
hit
=
io
.
in
.
valid
&&
io
.
in
.
bits
.
hit
val
miss
=
io
.
in
.
valid
&&
!
io
.
in
.
bits
.
hit
val
meta
=
Mux1H
(
io
.
in
.
bits
.
waymask
,
io
.
in
.
bits
.
metas
)
assert
(!(
mmio
&&
hit
),
"MMIO request should not hit in cache"
)
val
dataRead
=
Mux1H
(
io
.
in
.
bits
.
waymask
,
io
.
in
.
bits
.
datas
).
data
val
wordMask
=
Mux
(!
ro
.
B
&&
req
.
isWrite
(),
MaskExpand
(
req
.
wmask
),
0.
U
(
DataBits
.
W
))
...
...
@@ -170,7 +189,7 @@ sealed class CacheStage3(ro: Boolean, name: String, userBits: Int = 0) extends C
data
=
Wire
(
new
MetaBundle
).
apply
(
tag
=
meta
.
tag
,
valid
=
true
.
B
,
dirty
=
(!
ro
).
B
)
)
val
s_idle
::
s_memReadReq
::
s_memReadResp
::
s_memWriteReq
::
s_memWriteResp
::
s_
wait_resp
::
Nil
=
Enum
(
6
)
val
s_idle
::
s_memReadReq
::
s_memReadResp
::
s_memWriteReq
::
s_memWriteResp
::
s_
mmioReq
::
s_mmioResp
::
s_wait_resp
::
Nil
=
Enum
(
8
)
val
state
=
RegInit
(
s_idle
)
val
needFlush
=
RegInit
(
false
.
B
)
when
(
io
.
flush
&&
(
state
=/=
s_idle
))
{
needFlush
:=
true
.
B
}
...
...
@@ -208,10 +227,16 @@ sealed class CacheStage3(ro: Boolean, name: String, userBits: Int = 0) extends C
io
.
mem
.
resp
.
ready
:=
true
.
B
io
.
mem
.
req
.
valid
:=
(
state
===
s_memReadReq
)
||
((
state
===
s_memWriteReq
)
&&
(
state2
===
s2_memWriteReq
))
// mmio
io
.
mmio
.
req
.
bits
:=
io
.
in
.
bits
.
req
io
.
mmio
.
resp
.
ready
:=
true
.
B
io
.
mmio
.
req
.
valid
:=
(
state
===
s_mmioReq
)
val
afterFirstRead
=
RegInit
(
false
.
B
)
val
alreadyOutFire
=
RegEnable
(
true
.
B
,
init
=
false
.
B
,
io
.
out
.
fire
())
val
readingFirst
=
!
afterFirstRead
&&
io
.
mem
.
resp
.
fire
()
&&
(
state
===
s_memReadResp
)
val
inRdataRegDemand
=
RegEnable
(
io
.
mem
.
resp
.
bits
.
rdata
,
readingFirst
)
val
inRdataRegDemand
=
RegEnable
(
Mux
(
mmio
,
io
.
mmio
.
resp
.
bits
.
rdata
,
io
.
mem
.
resp
.
bits
.
rdata
),
Mux
(
mmio
,
state
===
s_mmioResp
,
readingFirst
))
switch
(
state
)
{
is
(
s_idle
)
{
...
...
@@ -219,8 +244,14 @@ sealed class CacheStage3(ro: Boolean, name: String, userBits: Int = 0) extends C
alreadyOutFire
:=
false
.
B
// actually this can use s2 to test
when
(
miss
&&
!
io
.
flush
)
{
state
:=
Mux
(!
ro
.
B
&&
meta
.
dirty
,
s_memWriteReq
,
s_memReadReq
)
}
when
((
miss
||
mmio
)
&&
!
io
.
flush
)
{
state
:=
Mux
(
mmio
,
s_mmioReq
,
Mux
(!
ro
.
B
&&
meta
.
dirty
,
s_memWriteReq
,
s_memReadReq
))
}
}
is
(
s_mmioReq
)
{
when
(
io
.
mmio
.
req
.
fire
())
{
state
:=
s_mmioResp
}
}
is
(
s_mmioResp
)
{
when
(
io
.
mmio
.
resp
.
fire
())
{
state
:=
s_wait_resp
}
}
is
(
s_memReadReq
)
{
when
(
io
.
mem
.
req
.
fire
())
{
state
:=
s_memReadResp
readBeatCnt
.
value
:=
addr
.
wordIndex
...
...
@@ -267,26 +298,25 @@ sealed class CacheStage3(ro: Boolean, name: String, userBits: Int = 0) extends C
io
.
out
.
bits
.
rdata
:=
Mux
(
hit
,
dataRead
,
inRdataRegDemand
)
io
.
out
.
bits
.
cmd
:=
DontCare
io
.
out
.
bits
.
user
.
zip
(
io
.
in
.
bits
.
req
.
user
).
map
{
case
(
o
,
i
)
=>
o
:=
i
}
io
.
out
.
valid
:=
io
.
in
.
valid
&&
Mux
(
hit
,
true
.
B
,
Mux
(
req
.
isWrite
(),
state
===
s_wait_resp
,
afterFirstRead
&&
!
alreadyOutFire
))
io
.
out
.
valid
:=
io
.
in
.
valid
&&
Mux
(
hit
,
true
.
B
,
Mux
(
req
.
isWrite
()
||
mmio
,
state
===
s_wait_resp
,
afterFirstRead
&&
!
alreadyOutFire
))
// With critical-word first, the pipeline registers between
// s2 and s3 can not be overwritten before a missing request
// is totally handled. We use io.isFinish to indicate when the
// request really ends.
io
.
isFinish
:=
Mux
(
hit
||
req
.
isWrite
(),
io
.
out
.
fire
(),
(
state
===
s_wait_resp
)
&&
(
io
.
out
.
fire
()
||
alreadyOutFire
))
io
.
addr
:=
req
.
addr
io
.
in
.
ready
:=
io
.
out
.
ready
&&
(
state
===
s_idle
)
&&
!
miss
assert
(!(
metaHitWriteBus
.
req
.
valid
&&
metaRefillWriteBus
.
req
.
valid
))
assert
(!(
dataHitWriteBus
.
req
.
valid
&&
dataRefillWriteBus
.
req
.
valid
))
Debug
(
debug
)
{
printf
(
"%d: ["
+
n
ame
+
" stage3]: in.ready = %d, in.valid = %d, state = %d, addr = %x\n"
,
printf
(
"%d: ["
+
cacheN
ame
+
" stage3]: in.ready = %d, in.valid = %d, state = %d, addr = %x\n"
,
GTimer
(),
io
.
in
.
ready
,
io
.
in
.
valid
,
state
,
req
.
addr
)
}
}
// probe
sealed
class
CacheProbeStage
(
ro
:
Boolean
,
name
:
Strin
g
)
extends
CacheModule
{
sealed
class
CacheProbeStage
(
implicit
val
cacheConfig
:
CacheConfi
g
)
extends
CacheModule
{
val
io
=
IO
(
new
Bundle
{
val
in
=
Flipped
(
Decoupled
(
new
SimpleBusReqBundle
))
val
out
=
Decoupled
(
new
SimpleBusRespBundle
)
...
...
@@ -340,22 +370,22 @@ sealed class CacheProbeStage(ro: Boolean, name: String) extends CacheModule {
Mux
(
hit
,
SimpleBusCmd
.
probeHit
,
SimpleBusCmd
.
probeMiss
))
}
class
Cache
(
ro
:
Boolean
,
name
:
String
,
userBits
:
Int
=
0
)
extends
CacheModule
{
class
Cache
(
implicit
val
cacheConfig
:
CacheConfig
)
extends
CacheModule
{
val
io
=
IO
(
new
Bundle
{
val
in
=
Flipped
(
new
SimpleBusUC
(
userBits
=
userBits
))
val
addr
=
Output
(
UInt
(
AddrBits
.
W
))
val
flush
=
Input
(
UInt
(
2.
W
))
val
out
=
new
SimpleBusC
val
mmio
=
new
SimpleBusUC
})
// cpu pipeline
val
s1
=
Module
(
new
CacheStage1
(
ro
,
name
,
userBits
)
)
val
s2
=
Module
(
new
CacheStage2
(
ro
,
name
,
userBits
)
)
val
s3
=
Module
(
new
CacheStage3
(
ro
,
name
,
userBits
)
)
val
s1
=
Module
(
new
CacheStage1
)
val
s2
=
Module
(
new
CacheStage2
)
val
s3
=
Module
(
new
CacheStage3
)
val
metaArray
=
Module
(
new
SRAMTemplate
(
new
MetaBundle
,
set
=
Sets
,
way
=
Ways
,
shouldReset
=
true
,
singlePort
=
true
))
val
dataArray
=
Module
(
new
SRAMTemplate
(
new
DataBundle
,
set
=
Sets
*
LineBeats
,
way
=
Ways
,
singlePort
=
true
))
if
(
n
ame
==
"icache"
)
{
if
(
cacheN
ame
==
"icache"
)
{
// flush icache when executing fence.i
val
flushICache
=
WireInit
(
false
.
B
)
BoringUtils
.
addSink
(
flushICache
,
"MOUFlushICache"
)
...
...
@@ -367,8 +397,8 @@ class Cache(ro: Boolean, name: String, userBits: Int = 0) extends CacheModule {
PipelineConnect
(
s2
.
io
.
out
,
s3
.
io
.
in
,
s3
.
io
.
isFinish
,
io
.
flush
(
1
))
io
.
in
.
resp
<>
s3
.
io
.
out
s3
.
io
.
flush
:=
io
.
flush
(
1
)
io
.
addr
:=
s3
.
io
.
addr
io
.
out
.
mem
<>
s3
.
io
.
mem
io
.
mmio
<>
s3
.
io
.
mmio
// stalling
s1
.
io
.
s2Req
.
valid
:=
s2
.
io
.
in
.
valid
...
...
@@ -378,7 +408,7 @@ class Cache(ro: Boolean, name: String, userBits: Int = 0) extends CacheModule {
s1
.
io
.
s2s3Miss
:=
s3
.
io
.
in
.
valid
&&
!
s3
.
io
.
in
.
bits
.
hit
// coherence state machine
val
coh
=
Module
(
new
CacheProbeStage
(
ro
,
name
)
)
val
coh
=
Module
(
new
CacheProbeStage
)
coh
.
io
.
in
<>
io
.
out
.
coh
.
req
io
.
out
.
coh
.
resp
<>
coh
.
io
.
out
...
...
@@ -406,15 +436,25 @@ class Cache(ro: Boolean, name: String, userBits: Int = 0) extends CacheModule {
s2
.
io
.
metaReadResp
:=
metaArray
.
io
.
r
.
resp
.
data
s2
.
io
.
dataReadResp
:=
dataArray
.
io
.
r
.
resp
.
data
BoringUtils
.
addSource
(
s3
.
io
.
in
.
valid
&&
s3
.
io
.
in
.
bits
.
hit
,
"perfCntCondM"
+
n
ame
+
"Hit"
)
BoringUtils
.
addSource
(
s3
.
io
.
in
.
valid
&&
s3
.
io
.
in
.
bits
.
hit
,
"perfCntCondM"
+
cacheN
ame
+
"Hit"
)
Debug
(
debug
)
{
io
.
in
.
dump
(
n
ame
+
".in"
)
io
.
in
.
dump
(
cacheN
ame
+
".in"
)
printf
(
"%d: s1:(%d,%d), s2:(%d,%d), s3:(%d,%d)\n"
,
GTimer
(),
s1
.
io
.
in
.
valid
,
s1
.
io
.
in
.
ready
,
s2
.
io
.
in
.
valid
,
s2
.
io
.
in
.
ready
,
s3
.
io
.
in
.
valid
,
s3
.
io
.
in
.
ready
)
when
(
s1
.
io
.
in
.
valid
)
{
printf
(
p
"[${name}.S1]: ${s1.io.in.bits}\n"
)
}
when
(
s2
.
io
.
in
.
valid
)
{
printf
(
p
"[${name}.S2]: ${s2.io.in.bits.req}\n"
)
}
when
(
s3
.
io
.
in
.
valid
)
{
printf
(
p
"[${name}.S3]: ${s3.io.in.bits.req}\n"
)
}
s3
.
io
.
mem
.
dump
(
name
+
".mem"
)
when
(
s1
.
io
.
in
.
valid
)
{
printf
(
p
"[${cacheName}.S1]: ${s1.io.in.bits}\n"
)
}
when
(
s2
.
io
.
in
.
valid
)
{
printf
(
p
"[${cacheName}.S2]: ${s2.io.in.bits.req}\n"
)
}
when
(
s3
.
io
.
in
.
valid
)
{
printf
(
p
"[${cacheName}.S3]: ${s3.io.in.bits.req}\n"
)
}
s3
.
io
.
mem
.
dump
(
cacheName
+
".mem"
)
}
}
object
Cache
{
def
apply
(
in
:
SimpleBusUC
,
mmio
:
SimpleBusUC
,
flush
:
UInt
)(
implicit
cacheConfig
:
CacheConfig
)
=
{
val
cache
=
Module
(
new
Cache
)
cache
.
io
.
flush
:=
flush
cache
.
io
.
in
<>
in
mmio
<>
cache
.
io
.
mmio
cache
.
io
.
out
}
}
src/main/scala/noop/EXU.scala
浏览文件 @
54453403
...
...
@@ -13,9 +13,7 @@ class EXU(implicit val p: NOOPConfig) extends NOOPModule {
val
out
=
Decoupled
(
new
CommitIO
)
val
flush
=
Input
(
Bool
())
val
dmem
=
new
SimpleBusUC
val
mmio
=
new
SimpleBusUC
val
forward
=
new
ForwardIO
//val wbData = Input(UInt(32.W))
})
val
src1
=
io
.
in
.
bits
.
data
.
src1
...
...
@@ -37,7 +35,6 @@ class EXU(implicit val p: NOOPConfig) extends NOOPModule {
lsu
.
io
.
wdata
:=
src2
io
.
out
.
bits
.
isMMIO
:=
lsu
.
io
.
isMMIO
io
.
dmem
<>
lsu
.
io
.
dmem
io
.
mmio
<>
lsu
.
io
.
mmio
lsu
.
io
.
out
.
ready
:=
true
.
B
val
mdu
=
Module
(
new
MDU
)
...
...
src/main/scala/noop/IFU.scala
浏览文件 @
54453403
...
...
@@ -13,8 +13,7 @@ trait HasResetVector {
class
IFU
extends
NOOPModule
with
HasResetVector
{
val
io
=
IO
(
new
Bundle
{
val
imem
=
new
SimpleBusUC
(
userBits
=
AddrBits
)
val
pc
=
Input
(
UInt
(
AddrBits
.
W
))
val
imem
=
new
SimpleBusUC
(
userBits
=
AddrBits
*
2
)
val
out
=
Decoupled
(
new
CtrlFlowIO
)
val
redirect
=
Flipped
(
new
RedirectIO
)
val
flushVec
=
Output
(
UInt
(
4.
W
))
...
...
@@ -41,16 +40,18 @@ class IFU extends NOOPModule with HasResetVector {
io
.
bpFlush
:=
false
.
B
io
.
imem
.
req
.
bits
.
apply
(
addr
=
Cat
(
pc
(
AddrBits
-
1
,
2
),
0.
U
(
2.
W
)),
//cache will treat it as Cat(pc(63,3),0.U(3.W))
size
=
"b11"
.
U
,
cmd
=
SimpleBusCmd
.
read
,
wdata
=
0.
U
,
wmask
=
0.
U
,
user
=
npc
)
size
=
"b11"
.
U
,
cmd
=
SimpleBusCmd
.
read
,
wdata
=
0.
U
,
wmask
=
0.
U
,
user
=
Cat
(
npc
,
pc
)
)
io
.
imem
.
req
.
valid
:=
io
.
out
.
ready
io
.
imem
.
resp
.
ready
:=
io
.
out
.
ready
||
io
.
flushVec
(
0
)
io
.
out
.
bits
:=
DontCare
io
.
out
.
bits
.
pc
:=
io
.
pc
//inst path only uses 32bit inst, get the right inst according to pc(2)
io
.
out
.
bits
.
instr
:=
(
if
(
XLEN
==
64
)
io
.
imem
.
resp
.
bits
.
rdata
.
asTypeOf
(
Vec
(
2
,
UInt
(
32.
W
)))(
io
.
pc
(
2
))
io
.
out
.
bits
.
instr
:=
(
if
(
XLEN
==
64
)
io
.
imem
.
resp
.
bits
.
rdata
.
asTypeOf
(
Vec
(
2
,
UInt
(
32.
W
)))(
io
.
out
.
bits
.
pc
(
2
))
else
io
.
imem
.
resp
.
bits
.
rdata
)
io
.
imem
.
resp
.
bits
.
user
.
map
(
io
.
out
.
bits
.
pnpc
:=
_
)
io
.
imem
.
resp
.
bits
.
user
.
map
{
case
x
=>
io
.
out
.
bits
.
pc
:=
x
(
AddrBits
-
1
,
0
)
io
.
out
.
bits
.
pnpc
:=
x
(
AddrBits
*
2
-
1
,
AddrBits
)
}
io
.
out
.
valid
:=
io
.
imem
.
resp
.
valid
&&
!
io
.
flushVec
(
0
)
BoringUtils
.
addSource
(
BoolStopWatch
(
io
.
imem
.
req
.
valid
,
io
.
imem
.
resp
.
fire
()),
"perfCntCondMimemStall"
)
...
...
src/main/scala/noop/NOOP.scala
浏览文件 @
54453403
...
...
@@ -80,26 +80,9 @@ class NOOP(implicit val p: NOOPConfig) extends NOOPModule {
// forward
isu
.
io
.
forward
<>
exu
.
io
.
forward
io
.
imem
<>
(
if
(
HasIcache
)
{
val
icache
=
Module
(
new
Cache
(
ro
=
true
,
name
=
"icache"
,
userBits
=
AddrBits
))
icache
.
io
.
in
<>
ifu
.
io
.
imem
icache
.
io
.
flush
:=
Fill
(
2
,
ifu
.
io
.
flushVec
(
0
)
|
ifu
.
io
.
bpFlush
)
ifu
.
io
.
pc
:=
icache
.
io
.
addr
icache
.
io
.
out
}
else
{
ifu
.
io
.
imem
})
io
.
dmem
<>
(
if
(
HasDcache
)
{
val
dcache
=
Module
(
new
Cache
(
ro
=
false
,
name
=
"dcache"
))
dcache
.
io
.
in
<>
exu
.
io
.
dmem
dcache
.
io
.
flush
:=
Fill
(
2
,
false
.
B
)
dcache
.
io
.
out
}
else
{
val
busC
=
Wire
(
new
SimpleBusC
)
busC
.
mem
<>
exu
.
io
.
dmem
busC
.
coh
:=
DontCare
busC
.
coh
.
req
.
valid
:=
false
.
B
busC
.
coh
.
resp
.
ready
:=
true
.
B
busC
})
io
.
mmio
<>
exu
.
io
.
mmio
val
mmioXbar
=
Module
(
new
SimpleBusCrossbarNto1
(
2
))
io
.
imem
<>
Cache
(
ifu
.
io
.
imem
,
mmioXbar
.
io
.
in
(
0
),
Fill
(
2
,
ifu
.
io
.
flushVec
(
0
)
|
ifu
.
io
.
bpFlush
))(
CacheConfig
(
ro
=
true
,
name
=
"icache"
,
userBits
=
AddrBits
*
2
))
io
.
dmem
<>
Cache
(
exu
.
io
.
dmem
,
mmioXbar
.
io
.
in
(
1
),
"b00"
.
U
)(
CacheConfig
(
ro
=
false
,
name
=
"dcache"
))
io
.
mmio
<>
mmioXbar
.
io
.
out
}
src/main/scala/noop/fu/LSU.scala
浏览文件 @
54453403
package
noop
//TODO(rv64)
import
chisel3._
import
chisel3.util._
import
chisel3.util.experimental.BoringUtils
...
...
@@ -26,7 +25,6 @@ object LSUOpType {
class
LSUIO
extends
FunctionUnitIO
{
val
wdata
=
Input
(
UInt
(
XLEN
.
W
))
val
dmem
=
new
SimpleBusUC
val
mmio
=
new
SimpleBusUC
val
isMMIO
=
Output
(
Bool
())
}
...
...
@@ -63,39 +61,27 @@ class LSU extends NOOPModule {
val
addr
=
src1
+
src2
val
addrLatch
=
RegNext
(
addr
)
val
isStore
=
valid
&&
LSUOpType
.
isStore
(
func
)
val
partialLoad
=
!
isStore
&&
(
func
=/=
LSUOpType
.
ld
)
val
s_idle
::
s_wait_resp
::
s_partialLoad
::
Nil
=
Enum
(
3
)
val
state
=
RegInit
(
s_idle
)
val
mmio
=
AddressSpace
.
isMMIO
(
addr
)
val
partialLoad
=
!
isStore
&&
(
func
=/=
LSUOpType
.
ld
)
switch
(
state
)
{
is
(
s_idle
)
{
when
(
valid
)
{
when
(
Mux
(
mmio
,
io
.
mmio
.
req
.
fire
(),
dmem
.
req
.
fire
()))
{
state
:=
Mux
(
isStore
&&
!
mmio
,
s_partialLoad
,
s_wait_resp
)
}
}}
is
(
s_wait_resp
)
{
when
(
Mux
(
mmio
,
io
.
mmio
.
resp
.
fire
(),
dmem
.
resp
.
fire
()))
{
state
:=
Mux
(
partialLoad
,
s_partialLoad
,
s_idle
)
}
}
is
(
s_idle
)
{
when
(
dmem
.
req
.
fire
())
{
state
:=
Mux
(
isStore
,
s_partialLoad
,
s_wait_resp
)
}
}
is
(
s_wait_resp
)
{
when
(
dmem
.
resp
.
fire
())
{
state
:=
Mux
(
partialLoad
,
s_partialLoad
,
s_idle
)
}
}
is
(
s_partialLoad
)
{
state
:=
s_idle
}
}
val
size
=
func
(
1
,
0
)
dmem
.
req
.
bits
.
apply
(
addr
=
addr
,
size
=
size
,
wdata
=
genWdata
(
io
.
wdata
,
size
),
wmask
=
genWmask
(
addr
,
size
),
cmd
=
Mux
(
isStore
,
SimpleBusCmd
.
write
,
SimpleBusCmd
.
read
))
dmem
.
req
.
valid
:=
valid
&&
(
state
===
s_idle
)
&&
!
mmio
dmem
.
req
.
valid
:=
valid
&&
(
state
===
s_idle
)
dmem
.
resp
.
ready
:=
true
.
B
io
.
mmio
.
req
.
bits
:=
dmem
.
req
.
bits
io
.
mmio
.
req
.
valid
:=
valid
&&
(
state
===
s_idle
)
&&
mmio
io
.
mmio
.
resp
.
ready
:=
true
.
B
io
.
out
.
valid
:=
Mux
(
isStore
&&
!
mmio
,
state
===
s_partialLoad
,
Mux
(
partialLoad
,
state
===
s_partialLoad
,
Mux
(
mmio
,
io
.
mmio
.
resp
.
fire
(),
dmem
.
resp
.
fire
()
&&
(
state
===
s_wait_resp
))))
io
.
out
.
valid
:=
Mux
(
isStore
||
partialLoad
,
state
===
s_partialLoad
,
dmem
.
resp
.
fire
()
&&
(
state
===
s_wait_resp
))
io
.
in
.
ready
:=
(
state
===
s_idle
)
val
mmioLatch
=
RegNext
(
mmio
)
val
rdata
=
Mux
(
mmioLatch
,
io
.
mmio
.
resp
.
bits
.
rdata
,
dmem
.
resp
.
bits
.
rdata
)
val
rdata
=
dmem
.
resp
.
bits
.
rdata
val
rdataLatch
=
RegNext
(
rdata
)
val
rdataSel
=
LookupTree
(
addrLatch
(
2
,
0
),
List
(
"b000"
.
U
->
rdataLatch
(
63
,
0
),
...
...
@@ -117,10 +103,10 @@ class LSU extends NOOPModule {
))
io
.
out
.
bits
:=
Mux
(
partialLoad
,
rdataPartialLoad
,
rdata
)
io
.
isMMIO
:=
mmio
&&
valid
io
.
isMMIO
:=
AddressSpace
.
isMMIO
(
addr
)
&&
io
.
out
.
valid
BoringUtils
.
addSource
(
dmem
.
isRead
()
&&
dmem
.
req
.
fire
(),
"perfCntCondMloadInstr"
)
BoringUtils
.
addSource
(
BoolStopWatch
(
dmem
.
isRead
(),
dmem
.
resp
.
fire
()),
"perfCntCondMloadStall"
)
BoringUtils
.
addSource
(
BoolStopWatch
(
dmem
.
isWrite
(),
dmem
.
resp
.
fire
()),
"perfCntCondMstoreStall"
)
BoringUtils
.
addSource
(
io
.
mmio
.
req
.
fire
()
,
"perfCntCondMmmioInstr"
)
BoringUtils
.
addSource
(
io
.
isMMIO
,
"perfCntCondMmmioInstr"
)
}
src/test/scala/top/SimMMIO.scala
浏览文件 @
54453403
...
...
@@ -19,8 +19,8 @@ class SimMMIO extends Module {
(
0x40800000
L
,
0x8
L
)
// vga ctrl
)
val
xbar
=
Module
(
new
SimpleBusCrossbar
(
1
,
devAddrSpace
))
xbar
.
io
.
in
(
0
)
<>
io
.
rw
val
xbar
=
Module
(
new
SimpleBusCrossbar
1toN
(
devAddrSpace
))
xbar
.
io
.
in
<>
io
.
rw
val
uart
=
Module
(
new
AXI4UART
)
val
timer
=
Module
(
new
AXI4Timer
(
sim
=
true
))
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录