Merge ktlim@zizzer:/bk/newmem
[gem5.git] / src / mem / cache / miss / blocking_buffer.cc
1 /*
2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Erik Hallnor
29 */
30
31 /**
32 * @file
33 * Definitions of a simple buffer for a blocking cache.
34 */
35
36 #include "cpu/smt.hh" //for maxThreadsPerCPU
37 #include "mem/cache/base_cache.hh"
38 #include "mem/cache/miss/blocking_buffer.hh"
39 #include "mem/cache/prefetch/base_prefetcher.hh"
40 #include "sim/eventq.hh" // for Event declaration.
41 #include "mem/request.hh"
42
43 /**
44 * @todo Move writebacks into shared BaseBuffer class.
45 */
46 void
47 BlockingBuffer::regStats(const std::string &name)
48 {
49 using namespace Stats;
50 writebacks
51 .init(maxThreadsPerCPU)
52 .name(name + ".writebacks")
53 .desc("number of writebacks")
54 .flags(total)
55 ;
56 }
57
58 void
59 BlockingBuffer::setCache(BaseCache *_cache)
60 {
61 cache = _cache;
62 blkSize = cache->getBlockSize();
63 }
64
65 void
66 BlockingBuffer::setPrefetcher(BasePrefetcher *_prefetcher)
67 {
68 prefetcher = _prefetcher;
69 }
70 void
71 BlockingBuffer::handleMiss(PacketPtr &pkt, int blk_size, Tick time)
72 {
73 Addr blk_addr = pkt->getAddr() & ~(Addr)(blk_size - 1);
74 if (pkt->isWrite() && (pkt->req->isUncacheable() || !writeAllocate ||
75 !pkt->needsResponse())) {
76 if (!pkt->needsResponse()) {
77 wb.allocateAsBuffer(pkt);
78 } else {
79 wb.allocate(pkt->cmd, blk_addr, blk_size, pkt);
80 }
81
82 memcpy(wb.pkt->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(), blk_size);
83
84 cache->setBlocked(Blocked_NoWBBuffers);
85 cache->setMasterRequest(Request_WB, time);
86 return;
87 }
88
89 if (!pkt->needsResponse()) {
90 miss.allocateAsBuffer(pkt);
91 } else {
92 miss.allocate(pkt->cmd, blk_addr, blk_size, pkt);
93 }
94 if (!pkt->req->isUncacheable()) {
95 miss.pkt->flags |= CACHE_LINE_FILL;
96 }
97 cache->setBlocked(Blocked_NoMSHRs);
98 cache->setMasterRequest(Request_MSHR, time);
99 }
100
101 PacketPtr
102 BlockingBuffer::getPacket()
103 {
104 if (miss.pkt && !miss.inService) {
105 return miss.pkt;
106 }
107 return wb.pkt;
108 }
109
110 void
111 BlockingBuffer::setBusCmd(PacketPtr &pkt, Packet::Command cmd)
112 {
113 MSHR *mshr = (MSHR*) pkt->senderState;
114 mshr->originalCmd = pkt->cmd;
115 if (pkt->isCacheFill())
116 pkt->cmdOverride(cmd);
117 }
118
119 void
120 BlockingBuffer::restoreOrigCmd(PacketPtr &pkt)
121 {
122 pkt->cmdOverride(((MSHR*)(pkt->senderState))->originalCmd);
123 }
124
125 void
126 BlockingBuffer::markInService(PacketPtr &pkt, MSHR* mshr)
127 {
128 if (!pkt->isCacheFill() && pkt->isWrite()) {
129 // Forwarding a write/ writeback, don't need to change
130 // the command
131 assert(mshr == &wb);
132 cache->clearMasterRequest(Request_WB);
133 if (!pkt->needsResponse()) {
134 assert(wb.getNumTargets() == 0);
135 wb.deallocate();
136 cache->clearBlocked(Blocked_NoWBBuffers);
137 } else {
138 wb.inService = true;
139 }
140 } else {
141 assert(mshr == &miss);
142 cache->clearMasterRequest(Request_MSHR);
143 if (!pkt->needsResponse()) {
144 assert(miss.getNumTargets() == 0);
145 miss.deallocate();
146 cache->clearBlocked(Blocked_NoMSHRs);
147 } else {
148 //mark in service
149 miss.inService = true;
150 }
151 }
152 }
153
154 void
155 BlockingBuffer::handleResponse(PacketPtr &pkt, Tick time)
156 {
157 if (pkt->isCacheFill()) {
158 // targets were handled in the cache tags
159 assert((MSHR*)pkt->senderState == &miss);
160 miss.deallocate();
161 cache->clearBlocked(Blocked_NoMSHRs);
162 } else {
163 if (((MSHR*)(pkt->senderState))->hasTargets()) {
164 // Should only have 1 target if we had any
165 assert(((MSHR*)(pkt->senderState))->getNumTargets() == 1);
166 PacketPtr target = ((MSHR*)(pkt->senderState))->getTarget();
167 ((MSHR*)(pkt->senderState))->popTarget();
168 if (pkt->isRead()) {
169 memcpy(target->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(), target->getSize());
170 }
171 cache->respond(target, time);
172 assert(!((MSHR*)(pkt->senderState))->hasTargets());
173 }
174
175 if (pkt->isWrite()) {
176 assert(((MSHR*)(pkt->senderState)) == &wb);
177 wb.deallocate();
178 cache->clearBlocked(Blocked_NoWBBuffers);
179 } else {
180 miss.deallocate();
181 cache->clearBlocked(Blocked_NoMSHRs);
182 }
183 }
184 }
185
186 void
187 BlockingBuffer::squash(int threadNum)
188 {
189 if (miss.threadNum == threadNum) {
190 PacketPtr target = miss.getTarget();
191 miss.popTarget();
192 assert(0/*target->req->getThreadNum()*/ == threadNum);
193 target = NULL;
194 assert(!miss.hasTargets());
195 miss.ntargets=0;
196 if (!miss.inService) {
197 miss.deallocate();
198 cache->clearBlocked(Blocked_NoMSHRs);
199 cache->clearMasterRequest(Request_MSHR);
200 }
201 }
202 }
203
204 void
205 BlockingBuffer::doWriteback(Addr addr,
206 int size, uint8_t *data, bool compressed)
207 {
208 // Generate request
209 Request * req = new Request(addr, size, 0);
210 PacketPtr pkt = new Packet(req, Packet::Writeback, -1);
211 pkt->allocate();
212 if (data) {
213 memcpy(pkt->getPtr<uint8_t>(), data, size);
214 }
215
216 if (compressed) {
217 pkt->flags |= COMPRESSED;
218 }
219
220 ///All writebacks charged to same thread @todo figure this out
221 writebacks[0/*pkt->req->getThreadNum()*/]++;
222
223 wb.allocateAsBuffer(pkt);
224 cache->setMasterRequest(Request_WB, curTick);
225 cache->setBlocked(Blocked_NoWBBuffers);
226 }
227
228
229
230 void
231 BlockingBuffer::doWriteback(PacketPtr &pkt)
232 {
233 writebacks[0/*pkt->req->getThreadNum()*/]++;
234
235 wb.allocateAsBuffer(pkt);
236
237 // Since allocate as buffer copies the request,
238 // need to copy data here.
239 memcpy(wb.pkt->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(), pkt->getSize());
240
241 cache->setBlocked(Blocked_NoWBBuffers);
242 cache->setMasterRequest(Request_WB, curTick);
243 }