Skip to content
GitLab
Menu
Why GitLab
Pricing
Contact Sales
Explore
Why GitLab
Pricing
Contact Sales
Explore
Sign in
Get free trial
Primary navigation
Search or go to…
Project
M
mem
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Privacy statement
Keyboard shortcuts
?
What's new
6
Snippets
Groups
Projects
Show more breadcrumbs
Akita
mem
Commits
f45cf016
Commit
f45cf016
authored
6 years ago
by
Yifan Sun
Browse files
Options
Downloads
Patches
Plain Diff
More on write-back cache
parent
795d5534
No related branches found
Branches containing commit
No related tags found
Tags containing commit
1 merge request
!7
Resolve "Write-back cache"
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
cache/events.go
+37
-0
37 additions, 0 deletions
cache/events.go
cache/mshr.go
+2
-1
2 additions, 1 deletion
cache/mshr.go
cache/writebackcache.go
+161
-39
161 additions, 39 deletions
cache/writebackcache.go
cache/writebackcache_test.go
+204
-55
204 additions, 55 deletions
cache/writebackcache_test.go
with
404 additions
and
95 deletions
cache/events.go
+
37
−
0
View file @
f45cf016
...
...
@@ -20,7 +20,28 @@ func NewReadCompleteEvent(
evtBase
:=
core
.
NewEventBase
(
time
,
handler
)
event
:=
new
(
ReadCompleteEvent
)
event
.
EventBase
=
evtBase
return
event
}
// A ReadForEvictEvent marks the completion of a cache read. The data read
// is going to be written to the low module
type
ReadForEvictEvent
struct
{
*
core
.
EventBase
DataReady
*
mem
.
DataReadyRsp
EvictBlock
*
Block
NewBlock
*
Block
ReadBottomReq
*
mem
.
ReadReq
}
// NewReadForEvictEvent creates a new ReadForEvictEvent
func
NewReadForEvictEvent
(
time
core
.
VTimeInSec
,
handler
core
.
Handler
,
)
*
ReadForEvictEvent
{
evtBase
:=
core
.
NewEventBase
(
time
,
handler
)
event
:=
new
(
ReadForEvictEvent
)
event
.
EventBase
=
evtBase
return
event
}
...
...
@@ -82,3 +103,19 @@ func NewProcessMSHRReturnEvent(
evt
.
EventBase
=
evtBase
return
evt
}
// SendEvent triggers a cache to check its buffer and send requests out.
type
SendEvent
struct
{
*
core
.
EventBase
}
// NewSendEvent creates a new SendEvent
func
NewSendEvent
(
time
core
.
VTimeInSec
,
handler
core
.
Handler
,
)
*
SendEvent
{
evtBase
:=
core
.
NewEventBase
(
time
,
handler
)
evt
:=
new
(
SendEvent
)
evt
.
EventBase
=
evtBase
return
evt
}
This diff is collapsed.
Click to expand it.
cache/mshr.go
+
2
−
1
View file @
f45cf016
...
...
@@ -9,7 +9,8 @@ import (
// MSHREntry is an entry in MSHR
type
MSHREntry
struct
{
Requests
[]
mem
.
AccessReq
Requests
[]
mem
.
AccessReq
DataReady
*
mem
.
DataReadyRsp
}
// NewMSHREntry returns a new MSHR entry object
...
...
This diff is collapsed.
Click to expand it.
cache/writebackcache.go
+
161
−
39
View file @
f45cf016
...
...
@@ -9,6 +9,13 @@ import (
"gitlab.com/yaotsu/mem"
)
type
dataReadyInfo
struct
{
dataReady
*
mem
.
DataReadyRsp
newBlock
*
Block
evictBlock
*
Block
writeToBottom
*
mem
.
WriteReq
}
// A WriteBackCache is a cache that performs the write-back policy
type
WriteBackCache
struct
{
*
core
.
ComponentBase
...
...
@@ -27,10 +34,64 @@ type WriteBackCache struct {
LowModule
core
.
Component
// No need for buffer limitation as it cannot exceed MSHR entries
readBuffer
map
[
string
]
*
mem
.
ReadReq
writeBuffer
map
[
string
]
*
mem
.
WriteReq
readBuffer
[]
*
mem
.
ReadReq
pendingReadReq
map
[
string
]
*
mem
.
ReadReq
writeBufferCapacity
int
writeBuffer
[]
*
mem
.
WriteReq
pendingWriteReqs
map
[
string
]
*
mem
.
WriteReq
processingWriteReqs
map
[
uint64
]
*
mem
.
WriteReq
processingDataReady
map
[
uint64
]
*
dataReadyInfo
nextSendEventTime
core
.
VTimeInSec
nextHandleMSHRTime
core
.
VTimeInSec
}
func
(
c
*
WriteBackCache
)
isBusy
()
bool
{
return
c
.
BusyPort
>=
c
.
NumPort
}
func
(
c
*
WriteBackCache
)
sendLater
(
time
core
.
VTimeInSec
)
{
if
c
.
nextSendEventTime
<
time
{
evt
:=
NewSendEvent
(
time
,
c
)
c
.
engine
.
Schedule
(
evt
)
c
.
nextSendEventTime
=
time
}
}
func
(
c
*
WriteBackCache
)
handleMSHRLater
(
time
core
.
VTimeInSec
)
{
if
c
.
nextHandleMSHRTime
<
time
{
evt
:=
NewProcessMSHRReturnEvent
(
time
,
c
)
c
.
engine
.
Schedule
(
evt
)
c
.
nextHandleMSHRTime
=
time
}
}
func
(
c
*
WriteBackCache
)
isWriteBufferFull
()
bool
{
if
len
(
c
.
writeBuffer
)
>=
c
.
writeBufferCapacity
{
return
true
}
return
false
}
// Insert a write request to the write buffer. Return true if success
func
(
c
*
WriteBackCache
)
addToWriteBuffer
(
req
*
mem
.
WriteReq
)
bool
{
if
c
.
isWriteBufferFull
()
{
return
false
}
c
.
writeBuffer
=
append
(
c
.
writeBuffer
,
req
)
c
.
pendingWriteReqs
[
req
.
ID
]
=
req
c
.
sendLater
(
req
.
SendTime
())
return
true
}
func
(
c
*
WriteBackCache
)
addToReadBuffer
(
req
*
mem
.
ReadReq
)
bool
{
c
.
readBuffer
=
append
(
c
.
readBuffer
,
req
)
c
.
pendingReadReq
[
req
.
ID
]
=
req
c
.
sendLater
(
req
.
SendTime
())
return
true
}
// Recv processes incoming requests
...
...
@@ -101,18 +162,11 @@ func (c *WriteBackCache) processReadReq(req *mem.ReadReq) *core.Error {
}
// Request to bottom
readReq
:=
mem
.
NewReadReq
(
now
,
c
,
c
.
LowModule
,
cacheLineID
,
64
)
err
:=
c
.
GetConnection
(
"ToBottom"
)
.
Send
(
readReq
)
if
err
!=
nil
{
return
core
.
NewError
(
"Cache Busy"
,
false
,
c
.
Freq
.
NoEarlierThan
(
err
.
EarliestRetry
),
)
}
//fmt.Printf("%s, %.12f, 0x%x, MISS\n", c.Name(), now, req.Address)
readReq
:=
mem
.
NewReadReq
(
now
,
c
,
c
.
LowModule
,
cacheLineID
,
64
)
mshrEntry
=
c
.
mshr
.
Add
(
cacheLineID
)
mshrEntry
.
Requests
=
append
(
mshrEntry
.
Requests
,
req
)
c
.
r
eadBuffer
[
readReq
.
ID
]
=
readReq
c
.
addToR
eadBuffer
(
readReq
)
return
nil
}
...
...
@@ -120,26 +174,59 @@ func (c *WriteBackCache) processReadReq(req *mem.ReadReq) *core.Error {
func
(
c
*
WriteBackCache
)
processDataReadyRsp
(
rsp
*
mem
.
DataReadyRsp
)
*
core
.
Error
{
now
:=
rsp
.
RecvTime
()
if
c
.
BusyPort
>=
c
.
NumPort
{
if
c
.
isBusy
()
{
// TODO: There is space for performance improvement
return
core
.
NewError
(
"Cache Busy"
,
true
,
c
.
Freq
.
NextTick
(
now
))
}
readBottomReq
:=
c
.
readBuffer
[
rsp
.
RespondTo
]
writeEvent
:=
NewWriteFromBottomCompleteEvent
(
readBottomReq
:=
c
.
pendingReadReq
[
rsp
.
RespondTo
]
delete
(
c
.
pendingReadReq
,
rsp
.
RespondTo
)
mshrEntry
:=
c
.
mshr
.
Query
(
readBottomReq
.
Address
)
mshrEntry
.
DataReady
=
rsp
block
,
evict
:=
c
.
dir
.
FindEmpty
(
readBottomReq
.
Address
)
if
c
.
needEvict
(
evict
)
{
c
.
doEvict
(
now
,
rsp
,
readBottomReq
,
block
,
evict
)
}
else
{
c
.
doWriteLocal
(
now
,
rsp
,
readBottomReq
)
}
return
nil
}
func
(
c
*
WriteBackCache
)
doWriteLocal
(
now
core
.
VTimeInSec
,
dataReady
*
mem
.
DataReadyRsp
,
readBottomReq
*
mem
.
ReadReq
,
)
{
writeFromBottom
:=
NewWriteFromBottomCompleteEvent
(
c
.
Freq
.
NCyclesLater
(
c
.
Latency
,
now
),
c
,
)
write
Event
.
DataReadyRsp
=
rsp
write
Event
.
ReadReq
=
readBottomReq
c
.
engine
.
Schedule
(
write
Event
)
write
FromBottom
.
DataReadyRsp
=
dataReady
write
FromBottom
.
ReadReq
=
readBottomReq
c
.
engine
.
Schedule
(
write
FromBottom
)
c
.
BusyPort
++
}
mshrEntry
:=
c
.
mshr
.
Query
(
readBottomReq
.
Address
)
processMSHREvent
:=
NewProcessMSHRReturnEvent
(
c
.
Freq
.
NextTick
(
now
),
c
)
processMSHREvent
.
DataReady
=
rsp
processMSHREvent
.
MSHREntry
=
mshrEntry
c
.
engine
.
Schedule
(
processMSHREvent
)
func
(
c
*
WriteBackCache
)
doEvict
(
now
core
.
VTimeInSec
,
dataReady
*
mem
.
DataReadyRsp
,
readBottomReq
*
mem
.
ReadReq
,
block
*
Block
,
evict
*
Block
,
)
{
readForEvict
:=
NewReadForEvictEvent
(
now
,
c
)
readForEvict
.
DataReady
=
dataReady
readForEvict
.
ReadBottomReq
=
readBottomReq
readForEvict
.
NewBlock
=
block
readForEvict
.
EvictBlock
=
evict
c
.
engine
.
Schedule
(
readForEvict
)
c
.
BusyPort
++
}
return
nil
func
(
c
*
WriteBackCache
)
needEvict
(
evictBlock
*
Block
)
bool
{
return
evictBlock
!=
nil
&&
evictBlock
.
IsDirty
}
func
(
c
*
WriteBackCache
)
processWriteReq
(
req
*
mem
.
WriteReq
)
*
core
.
Error
{
...
...
@@ -194,20 +281,20 @@ func (c *WriteBackCache) processWriteReq(req *mem.WriteReq) *core.Error {
}
func
(
c
*
WriteBackCache
)
processDoneRsp
(
rsp
*
mem
.
DoneRsp
)
*
core
.
Error
{
writeReqToBottom
:=
c
.
writeBuffer
[
rsp
.
RespondTo
]
address
:=
writeReqToBottom
.
Address
writeReqFromTop
:=
c
.
processingWriteReqs
[
address
]
doneRspToTop
:=
mem
.
NewDoneRsp
(
rsp
.
RecvTime
(),
c
,
writeReqFromTop
.
Src
(),
writeReqFromTop
.
ID
)
err
:=
c
.
GetConnection
(
"ToTop"
)
.
Send
(
doneRspToTop
)
if
err
!=
nil
{
return
core
.
NewError
(
"Busy"
,
true
,
c
.
Freq
.
NoEarlierThan
(
err
.
EarliestRetry
))
}
delete
(
c
.
processingWriteReqs
,
address
)
delete
(
c
.
writeBuffer
,
writeReqToBottom
.
ID
)
//
writeReqToBottom := c.
pendingWriteReqs
[rsp.RespondTo]
//
address := writeReqToBottom.Address
//
writeReqFromTop := c.processingWriteReqs[address]
//
//
doneRspToTop := mem.NewDoneRsp(rsp.RecvTime(), c,
//
writeReqFromTop.Src(), writeReqFromTop.ID)
//
err := c.GetConnection("ToTop").Send(doneRspToTop)
//
if err != nil {
//
return core.NewError("Busy", true,
//
c.Freq.NoEarlierThan(err.EarliestRetry))
//
}
//
//
delete(c.processingWriteReqs, address)
//
delete(c.writeBuffer, writeReqToBottom.ID)
return
nil
}
...
...
@@ -229,6 +316,8 @@ func (c *WriteBackCache) Handle(evt core.Event) error {
return
c
.
handleWriteFromBottomCompleteEvent
(
evt
)
case
*
ProcessMSHRReturnEvent
:
return
c
.
handleProcessMSHRReturnEvent
(
evt
)
case
*
SendEvent
:
return
c
.
handleSendEvent
(
evt
)
default
:
log
.
Panicf
(
"cannot handle event of type %s"
,
reflect
.
TypeOf
(
evt
))
}
...
...
@@ -330,6 +419,35 @@ func (c *WriteBackCache) handleProcessMSHRReturnEvent(
return
nil
}
func
(
c
*
WriteBackCache
)
handleSendEvent
(
evt
*
SendEvent
)
error
{
now
:=
evt
.
Time
()
if
len
(
c
.
writeBuffer
)
>
0
{
req
:=
c
.
writeBuffer
[
0
]
req
.
SetSendTime
(
now
)
err
:=
c
.
GetConnection
(
"ToBottom"
)
.
Send
(
req
)
if
err
!=
nil
{
c
.
sendLater
(
c
.
Freq
.
NoEarlierThan
(
err
.
EarliestRetry
))
return
nil
}
c
.
writeBuffer
=
c
.
writeBuffer
[
1
:
]
}
else
if
len
(
c
.
readBuffer
)
>
0
{
req
:=
c
.
readBuffer
[
0
]
req
.
SetSendTime
(
now
)
err
:=
c
.
GetConnection
(
"ToBottom"
)
.
Send
(
req
)
if
err
!=
nil
{
c
.
sendLater
(
c
.
Freq
.
NoEarlierThan
(
err
.
EarliestRetry
))
return
nil
}
c
.
readBuffer
=
c
.
readBuffer
[
1
:
]
}
if
len
(
c
.
readBuffer
)
>
0
||
len
(
c
.
writeBuffer
)
>
0
{
c
.
sendLater
(
c
.
Freq
.
NextTick
(
now
))
}
return
nil
}
// Reset marks all the blocks in the cache to be invalid.
//
// FIXME: This is magic, to be removed in the future.
...
...
@@ -358,10 +476,14 @@ func NewWriteBackCache(
cache
.
Freq
=
1
*
util
.
GHz
cache
.
NumPort
=
1
cache
.
BusyPort
=
0
cache
.
readBuffer
=
make
(
map
[
string
]
*
mem
.
ReadReq
)
cache
.
writeBuffer
=
make
(
map
[
string
]
*
mem
.
WriteReq
)
cache
.
readBuffer
=
make
([]
*
mem
.
ReadReq
,
0
)
cache
.
pendingReadReq
=
make
(
map
[
string
]
*
mem
.
ReadReq
)
cache
.
writeBuffer
=
make
([]
*
mem
.
WriteReq
,
0
)
cache
.
pendingWriteReqs
=
make
(
map
[
string
]
*
mem
.
WriteReq
)
cache
.
writeBufferCapacity
=
4
cache
.
processingDataReady
=
make
(
map
[
uint64
]
*
dataReadyInfo
)
cache
.
processingWriteReqs
=
make
(
map
[
uint64
]
*
mem
.
WriteReq
)
cache
.
nextSendEventTime
=
0
cache
.
AddPort
(
"ToTop"
)
cache
.
AddPort
(
"ToBottom"
)
...
...
This diff is collapsed.
Click to expand it.
cache/writebackcache_test.go
+
204
−
55
View file @
f45cf016
...
...
@@ -4,10 +4,13 @@ import (
.
"github.com/onsi/ginkgo"
.
"github.com/onsi/gomega"
"gitlab.com/yaotsu/core"
"gitlab.com/yaotsu/core/connections"
"gitlab.com/yaotsu/core/engines"
"gitlab.com/yaotsu/core/util"
"gitlab.com/yaotsu/mem"
)
var
_
=
Describe
(
"Write-
Around
Cache"
,
func
()
{
var
_
=
Describe
(
"Write-
Back
Cache"
,
func
()
{
var
(
engine
*
core
.
MockEngine
...
...
@@ -84,6 +87,7 @@ var _ = Describe("Write-Around Cache", func() {
directory
.
ExpectLookup
(
0x100
,
nil
)
req
:=
mem
.
NewReadReq
(
10
,
nil
,
cache
,
0x100
,
4
)
err
:=
cache
.
Recv
(
req
)
Expect
(
err
)
.
NotTo
(
BeNil
())
...
...
@@ -97,31 +101,17 @@ var _ = Describe("Write-Around Cache", func() {
req
:=
mem
.
NewReadReq
(
10
,
nil
,
cache
,
0x104
,
4
)
req
.
SetRecvTime
(
10
)
readReq
:=
mem
.
NewReadReq
(
10
,
cache
,
nil
,
0x100
,
64
)
bottomConn
.
ExpectSend
(
readReq
,
nil
)
cache
.
Recv
(
req
)
Expect
(
bottomConn
.
AllExpectedSent
())
.
To
(
BeTrue
())
Expect
(
len
(
cache
.
readBuffer
))
.
To
(
Equal
(
1
))
mshrEntry
:=
mshr
.
Query
(
0x100
)
Expect
(
mshrEntry
)
.
NotTo
(
BeNil
())
Expect
(
mshrEntry
.
Requests
[
0
])
.
To
(
BeIdenticalTo
(
req
))
Expect
(
cache
.
readBuffer
)
.
To
(
HaveLen
(
1
))
Expect
(
cache
.
pendingReadReq
)
.
To
(
HaveLen
(
1
))
Expect
(
engine
.
ScheduledEvent
)
.
To
(
HaveLen
(
1
))
})
It
(
"should reject ReadReq if the cache cannot send read to bottom"
,
func
()
{
req
:=
mem
.
NewReadReq
(
10
,
nil
,
cache
,
0x100
,
4
)
req
.
SetRecvTime
(
10
)
directory
.
ExpectLookup
(
0x100
,
nil
)
readReq
:=
mem
.
NewReadReq
(
10
,
cache
,
nil
,
0x100
,
64
)
bottomConn
.
ExpectSend
(
readReq
,
core
.
NewError
(
""
,
true
,
11
))
err
:=
cache
.
Recv
(
req
)
Expect
(
err
)
.
NotTo
(
BeNil
())
Expect
(
mshr
.
entries
)
.
To
(
HaveLen
(
0
))
})
})
Context
(
"when processing WriteRequest"
,
func
()
{
...
...
@@ -388,26 +378,72 @@ var _ = Describe("Write-Around Cache", func() {
})
Context
(
"when process DataReadyRsp"
,
func
()
{
It
(
"should re
turn error
if cache busy"
,
func
()
{
It
(
"should re
spond busy
if cache busy"
,
func
()
{
cache
.
BusyPort
=
4
dataReady
:=
mem
.
NewDataReadyRsp
(
10
,
nil
,
cache
,
""
)
readReq
:=
mem
.
NewReadReq
(
9
,
cache
,
nil
,
0x100
,
64
)
cache
.
pendingReadReq
[
readReq
.
ID
]
=
readReq
dataReady
:=
mem
.
NewDataReadyRsp
(
10
,
nil
,
cache
,
readReq
.
ID
)
dataReady
.
SetRecvTime
(
10
)
err
:=
cache
.
Recv
(
dataReady
)
Expect
(
err
)
.
NotTo
(
BeNil
())
})
It
(
"should schedule cache write"
,
func
()
{
cache
.
BusyPort
=
0
readReq
:=
mem
.
NewReadReq
(
5
,
cache
,
nil
,
0x100
,
64
)
It
(
"should schedule ReadForEvictEvent if need eviction"
,
func
()
{
cache
.
BusyPort
=
3
mshrEntry
:=
mshr
.
Add
(
0x100
)
readReq
:=
mem
.
NewReadReq
(
9
,
cache
,
nil
,
0x100
,
64
)
cache
.
pendingReadReq
[
readReq
.
ID
]
=
readReq
dataReady
:=
mem
.
NewDataReadyRsp
(
10
,
nil
,
cache
,
readReq
.
ID
)
cache
.
readBuffer
[
readReq
.
ID
]
=
readReq
dataReady
.
SetRecvTime
(
10
)
block
:=
new
(
Block
)
evict
:=
new
(
Block
)
evict
.
IsDirty
=
true
evict
.
Tag
=
0x200
directory
.
ExpectFindEmpty
(
0x100
,
block
,
evict
)
err
:=
cache
.
Recv
(
dataReady
)
Expect
(
err
)
.
To
(
BeNil
())
Expect
(
cache
.
BusyPort
)
.
To
(
Equal
(
1
))
Expect
(
len
(
engine
.
ScheduledEvent
))
.
To
(
Equal
(
2
))
Expect
(
directory
.
AllExpectedCalled
())
.
To
(
BeTrue
())
Expect
(
engine
.
ScheduledEvent
)
.
To
(
HaveLen
(
1
))
Expect
(
cache
.
pendingReadReq
)
.
NotTo
(
ContainElement
(
readReq
.
ID
))
Expect
(
cache
.
BusyPort
)
.
To
(
Equal
(
4
))
Expect
(
mshrEntry
.
DataReady
)
.
To
(
BeIdenticalTo
(
dataReady
))
})
It
(
"should schedule WriteFromBottomEvent if no need for eviction"
,
func
()
{
cache
.
BusyPort
=
3
mshrEntry
:=
mshr
.
Add
(
0x100
)
readReq
:=
mem
.
NewReadReq
(
9
,
cache
,
nil
,
0x100
,
64
)
cache
.
pendingReadReq
[
readReq
.
ID
]
=
readReq
dataReady
:=
mem
.
NewDataReadyRsp
(
10
,
nil
,
cache
,
readReq
.
ID
)
dataReady
.
SetRecvTime
(
10
)
block
:=
new
(
Block
)
evict
:=
new
(
Block
)
evict
.
IsDirty
=
false
evict
.
Tag
=
0x200
directory
.
ExpectFindEmpty
(
0x100
,
block
,
evict
)
err
:=
cache
.
Recv
(
dataReady
)
Expect
(
err
)
.
To
(
BeNil
())
Expect
(
directory
.
AllExpectedCalled
())
.
To
(
BeTrue
())
Expect
(
engine
.
ScheduledEvent
)
.
To
(
HaveLen
(
1
))
Expect
(
cache
.
pendingReadReq
)
.
NotTo
(
ContainElement
(
readReq
.
ID
))
Expect
(
cache
.
BusyPort
)
.
To
(
Equal
(
4
))
Expect
(
mshrEntry
.
DataReady
)
.
To
(
BeIdenticalTo
(
dataReady
))
})
})
...
...
@@ -492,48 +528,161 @@ var _ = Describe("Write-Around Cache", func() {
})
Context
(
"when processing DoneRsp"
,
func
()
{
It
(
"should return error if connection busy"
,
func
()
{
incomingWriteReq
:=
mem
.
NewWriteReq
(
10
,
nil
,
cache
,
0x104
)
cache
.
processingWriteReqs
[
0x104
]
=
incomingWriteReq
//It("should return error if connection busy", func() {
// incomingWriteReq := mem.NewWriteReq(10, nil, cache, 0x104)
// cache.processingWriteReqs[0x104] = incomingWriteReq
//
// writeReqToBottom := mem.NewWriteReq(12, cache, nil, 0x104)
// cache.writeBuffer[writeReqToBottom.ID] = writeReqToBottom
//
// returnDoneRspFromBottom := mem.NewDoneRsp(14, nil, cache, writeReqToBottom.ID)
// returnDoneRspFromBottom.SetRecvTime(15)
//
// returnDoneRspToTop := mem.NewDoneRsp(15, cache, nil, incomingWriteReq.ID)
// topConn.ExpectSend(returnDoneRspToTop,
// core.NewError("Busy", true, 16))
//
// err := cache.Recv(returnDoneRspFromBottom)
//
// Expect(err).NotTo(BeNil())
// Expect(topConn.AllExpectedSent()).To(BeTrue())
// Expect(cache.processingWriteReqs).To(HaveLen(1))
// Expect(cache.writeBuffer).To(HaveLen(1))
//})
//
//It("should send DoneRsp up", func() {
// incomingWriteReq := mem.NewWriteReq(10, nil, cache, 0x104)
// cache.processingWriteReqs[0x104] = incomingWriteReq
//
// writeReqToBottom := mem.NewWriteReq(12, cache, nil, 0x104)
// cache.writeBuffer[writeReqToBottom.ID] = writeReqToBottom
//
// returnDoneRspFromBottom := mem.NewDoneRsp(14, nil, cache, writeReqToBottom.ID)
// returnDoneRspFromBottom.SetRecvTime(15)
//
// returnDoneRspToTop := mem.NewDoneRsp(15, cache, nil, incomingWriteReq.ID)
// topConn.ExpectSend(returnDoneRspToTop, nil)
//
// err := cache.Recv(returnDoneRspFromBottom)
//
// Expect(err).To(BeNil())
// Expect(topConn.AllExpectedSent()).To(BeTrue())
// Expect(cache.processingWriteReqs).To(HaveLen(0))
// Expect(cache.writeBuffer).To(HaveLen(0))
//})
})
writeReqToBottom
:=
mem
.
NewWriteReq
(
12
,
cache
,
nil
,
0x104
)
cache
.
writeBuffer
[
writeReqToBottom
.
ID
]
=
writeReqToBottom
Context
(
"when handling SendEvent"
,
func
()
{
returnDoneRspFromBottom
:=
mem
.
NewDoneRsp
(
14
,
nil
,
cache
,
writeReqToBottom
.
ID
)
returnDoneRspFromBottom
.
SetRecvTime
(
15
)
It
(
"should first send write req"
,
func
()
{
writeToBottom
:=
mem
.
NewWriteReq
(
10
,
cache
,
nil
,
4096
)
cache
.
writeBuffer
=
append
(
cache
.
writeBuffer
,
writeToBottom
)
returnDoneRspToTop
:=
mem
.
NewDoneRsp
(
15
,
cache
,
nil
,
incomingWriteReq
.
ID
)
topConn
.
ExpectSend
(
returnDoneRspToTop
,
core
.
NewError
(
"Busy"
,
true
,
16
))
readToBottom
:=
mem
.
NewReadReq
(
10
,
cache
,
nil
,
4096
,
64
)
cache
.
readBuffer
=
append
(
cache
.
readBuffer
,
readToBottom
)
err
:=
cache
.
Recv
(
returnDoneRspFrom
Bottom
)
bottomConn
.
ExpectSend
(
writeTo
Bottom
,
nil
)
Expect
(
err
)
.
NotTo
(
BeNil
())
Expect
(
topConn
.
AllExpectedSent
())
.
To
(
BeTrue
())
Expect
(
cache
.
processingWriteReqs
)
.
To
(
HaveLen
(
1
))
Expect
(
cache
.
writeBuffer
)
.
To
(
HaveLen
(
1
))
sendEvent
:=
NewSendEvent
(
11
,
cache
)
cache
.
Handle
(
sendEvent
)
Expect
(
bottomConn
.
AllExpectedSent
())
.
To
(
BeTrue
())
Expect
(
cache
.
writeBuffer
)
.
To
(
HaveLen
(
0
))
Expect
(
writeToBottom
.
SendTime
())
.
To
(
Equal
(
core
.
VTimeInSec
(
11
)))
Expect
(
engine
.
ScheduledEvent
)
.
To
(
HaveLen
(
1
))
})
It
(
"should send
DoneRsp up
"
,
func
()
{
incomingWriteReq
:=
mem
.
New
Write
Req
(
10
,
nil
,
cache
,
0x10
4
)
cache
.
processingWriteReqs
[
0x104
]
=
incomingWriteReq
It
(
"should send
read req if no write req
"
,
func
()
{
readToBottom
:=
mem
.
New
Read
Req
(
10
,
cache
,
nil
,
4096
,
6
4
)
cache
.
readBuffer
=
append
(
cache
.
readBuffer
,
readToBottom
)
writeReqToBottom
:=
mem
.
NewWriteReq
(
12
,
cache
,
nil
,
0x104
)
cache
.
writeBuffer
[
writeReqToBottom
.
ID
]
=
writeReqToBottom
bottomConn
.
ExpectSend
(
readToBottom
,
nil
)
returnDoneRspFromBottom
:=
mem
.
NewDoneRsp
(
14
,
nil
,
cache
,
writeReqToBottom
.
ID
)
returnDoneRspFromBottom
.
SetRecvTime
(
15
)
sendEvent
:=
NewSendEvent
(
11
,
cache
)
cache
.
Handle
(
sendEvent
)
returnDoneRspToTop
:=
mem
.
NewDoneRsp
(
15
,
cache
,
nil
,
incomingWriteReq
.
ID
)
topConn
.
ExpectSend
(
returnDoneRspToTop
,
nil
)
Expect
(
bottomConn
.
AllExpectedSent
())
.
To
(
BeTrue
())
Expect
(
readToBottom
.
SendTime
())
.
To
(
Equal
(
core
.
VTimeInSec
(
11
)))
Expect
(
cache
.
readBuffer
)
.
To
(
HaveLen
(
0
))
})
err
:=
cache
.
Recv
(
returnDoneRspFromBottom
)
It
(
"should reschedule SendEvent if send write request failed"
,
func
()
{
writeToBottom
:=
mem
.
NewWriteReq
(
10
,
cache
,
nil
,
4096
)
cache
.
writeBuffer
=
append
(
cache
.
writeBuffer
,
writeToBottom
)
Expect
(
err
)
.
To
(
BeNil
())
Expect
(
topConn
.
AllExpectedSent
())
.
To
(
BeTrue
())
Expect
(
cache
.
processingWriteReqs
)
.
To
(
HaveLen
(
0
))
Expect
(
cache
.
writeBuffer
)
.
To
(
HaveLen
(
0
))
readToBottom
:=
mem
.
NewReadReq
(
10
,
cache
,
nil
,
4096
,
64
)
cache
.
readBuffer
=
append
(
cache
.
readBuffer
,
readToBottom
)
bottomConn
.
ExpectSend
(
writeToBottom
,
core
.
NewError
(
"Busy"
,
true
,
15
))
sendEvent
:=
NewSendEvent
(
11
,
cache
)
cache
.
Handle
(
sendEvent
)
Expect
(
bottomConn
.
AllExpectedSent
())
.
To
(
BeTrue
())
Expect
(
cache
.
writeBuffer
)
.
To
(
HaveLen
(
1
))
Expect
(
engine
.
ScheduledEvent
)
.
To
(
HaveLen
(
1
))
})
It
(
"should send read req if no write req"
,
func
()
{
readToBottom
:=
mem
.
NewReadReq
(
10
,
cache
,
nil
,
4096
,
64
)
cache
.
readBuffer
=
append
(
cache
.
readBuffer
,
readToBottom
)
bottomConn
.
ExpectSend
(
readToBottom
,
core
.
NewError
(
"Busy"
,
true
,
15
))
sendEvent
:=
NewSendEvent
(
11
,
cache
)
cache
.
Handle
(
sendEvent
)
Expect
(
bottomConn
.
AllExpectedSent
())
.
To
(
BeTrue
())
Expect
(
cache
.
readBuffer
)
.
To
(
HaveLen
(
1
))
Expect
(
engine
.
ScheduledEvent
)
.
To
(
HaveLen
(
1
))
})
})
})
var
_
=
Describe
(
"Write-Back Cache"
,
func
()
{
var
(
engine
core
.
Engine
evictor
*
LRUEvictor
directory
*
DirectoryImpl
mshr
*
MSHRImpl
storage
*
mem
.
Storage
cache
*
WriteBackCache
dram
*
mem
.
IdealMemController
conn
*
connections
.
DirectConnection
agent
*
core
.
MockComponent
)
BeforeEach
(
func
()
{
agent
=
core
.
NewMockComponent
(
"Agent"
)
engine
=
engines
.
NewSerialEngine
()
evictor
=
NewLRUEvictor
()
directory
=
NewDirectory
(
evictor
)
directory
.
NumSets
=
1024
directory
.
NumWays
=
4
directory
.
BlockSize
=
64
mshr
=
NewMSHR
(
4
)
storage
=
mem
.
NewStorage
(
4
*
mem
.
MB
)
cache
=
NewWriteBackCache
(
"Cache"
,
engine
,
directory
,
mshr
,
storage
)
cache
.
Freq
=
1
*
util
.
GHz
dram
=
mem
.
NewIdealMemController
(
"Dram"
,
engine
,
4
*
mem
.
GB
)
cache
.
LowModule
=
dram
conn
=
connections
.
NewDirectConnection
(
engine
)
core
.
PlugIn
(
cache
,
"ToTop"
,
conn
)
core
.
PlugIn
(
cache
,
"ToBottom"
,
conn
)
core
.
PlugIn
(
dram
,
"Top"
,
conn
)
})
It
(
"should handle read"
,
func
()
{
readReq
:=
mem
.
NewReadReq
(
10
,
agent
,
cache
,
5000
,
4
)
readReq
.
SetRecvTime
(
10
)
cache
.
Recv
(
readReq
)
})
})
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment