Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / api / memsync / src / LoadStoreBuffer.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: LoadStoreBuffer.cc
4// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
6//
7// The above named program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public
9// License version 2 as published by the Free Software Foundation.
10//
11// The above named program is distributed in the hope that it will be
12// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15//
16// You should have received a copy of the GNU General Public
17// License along with this work; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19//
20// ========== Copyright Header End ============================================
21/************************************************************************
22**
23** Copyright (C) 2002, Sun Microsystems, Inc.
24**
25** Sun considers its source code as an unpublished, proprietary
26** trade secret and it is available only under strict license provisions.
27** This copyright notice is placed here only to protect Sun in the event
28** the source is deemed a published work. Disassembly, decompilation,
29** or other means of reducing the object code to human readable form
30** is prohibited by the license agreement under which this code is
31** provided to the user or company in possession of this copy."
32**
33*************************************************************************/
34#include "LoadStoreBuffer.h"
35#include <sstream>
36
37using namespace std;
38////////////////////////////////////////////////
39
40LoadStoreBuffer::LoadStoreBuffer()
41{
42 // cerr << "LoadStoreBuffer Created, size= " << buf_.size() << endl;
43}
44
45////////////////////////////////////////////////
46
47LoadStoreBuffer::LoadStoreBuffer( const LoadStoreBuffer & orig )
48{
49
50}
51
52////////////////////////////////////////////////
53
54LoadStoreBuffer::~LoadStoreBuffer()
55{
56
57}
58
59////////////////////////////////////////////////
60
61const LoadStoreBuffer &
62LoadStoreBuffer::operator=( const LoadStoreBuffer & rhs )
63{
64 return *this;
65}
66
67////////////////////////////////////////////////
68
69bool
70LoadStoreBuffer::operator==( const LoadStoreBuffer & rhs ) const
71{
72 return false;
73}
74
75////////////////////////////////////////////////
76
77string
78LoadStoreBuffer::toString() const
79{
80 ostringstream os;
81 list<LoadStoreEntry>::const_iterator ii;
82
83 os << bufName_ << " (size=" << buf_.size() << ")" << endl;
84 for (ii = buf_.begin(); ii != buf_.end(); ii++) {
85 os << ii->toString();
86 }
87 os << endl;
88 return os.str();
89}
90
91list<LoadStoreEntry>::iterator
92LoadStoreBuffer::pushBack(LoadStoreEntry& entry)
93{
94 // cerr << "In LoadStoreBuffer::pushBack" << endl;
95
96 list<LoadStoreEntry>::iterator it;
97
98 buf_.push_back(entry);
99
100#ifdef MMDEBUG
101 //MSYNC_DEBUG(1, "%s", toString().c_str());
102 MSYNC_DEBUG(1, "%s Pushback\n%s", bufName_, entry.toString().c_str());
103 MSYNC_DEBUG(1, "%s", toString().c_str());
104#endif
105
106 it = buf_.end();
107 return (--it);
108}
109
110void
111LoadStoreBuffer::erase(list<LoadStoreEntry>::iterator ii)
112{
113 //assert(buf_.size() > 0);
114 if (buf_.size() == 0) return;
115
116#ifdef MMDEBUG
117 MSYNC_DEBUG(1, "%s Erase\n%s", bufName_, ii->toString().c_str());
118#endif
119 buf_.erase(ii);
120
121#ifdef MMDEBUG
122 MSYNC_DEBUG(1, "%s", toString().c_str());
123#endif
124}
125
126void
127LoadStoreBuffer::popFront()
128{
129 list<LoadStoreEntry>::iterator ii;
130
131 //assert(buf_.size() > 0);
132 if (buf_.size() == 0) return;
133
134 ii = buf_.begin();
135
136#ifdef MMDEBUG
137 MSYNC_DEBUG(1, "%s Remove (front)\n%s", bufName_, ii->toString().c_str());
138#endif
139
140 buf_.pop_front();
141
142#ifdef MMDEBUG
143 MSYNC_DEBUG(1, "%s", toString().c_str());
144#endif
145}
146
147void
148LoadStoreBuffer::popBack(int count)
149{
150 list<LoadStoreEntry>::iterator ii;
151
152 //assert (buf_.size() >= count);
153 if (buf_.size() < count) return;
154
155 for (int i = 0; i < count; i++) {
156 ii = --(buf_.end());
157#ifdef MMDEBUG
158 MSYNC_DEBUG(1, "%s Remove (back)\n%s", bufName_, ii->toString().c_str());
159#endif
160 buf_.pop_back();
161 }
162
163#ifdef MMDEBUG
164 MSYNC_DEBUG(1, "%s", toString().c_str());
165#endif
166}
167
168list<LoadStoreEntry>::iterator
169LoadStoreBuffer::findMatchY2O(uint64_t addr, uint8_t size_vector)
170{
171 list<LoadStoreEntry>::iterator ii;
172
173 if (buf_.size() == 0) {
174 return buf_.end();
175 }
176
177 ii = buf_.end();
178 do {
179 ii--;
180 assert(ii->isValid());
181 if ((addr & ADDR_MASK) == (ii->getAddr() & ADDR_MASK) &&
182 (size_vector == (size_vector & ii->getSizeV()))) {
183 return (ii);
184 }
185 } while (ii != buf_.begin());
186
187 return (buf_.end()); // use buf_.end() to indicate not found
188}
189
190list<LoadStoreEntry>::iterator
191LoadStoreBuffer::findMatchY2O(uint64_t id, uint64_t addr, uint8_t size_vector)
192{
193 list<LoadStoreEntry>::iterator ii;
194
195 if (buf_.size() == 0) {
196 return buf_.end();
197 }
198
199 ii = buf_.end();
200 do {
201 ii--;
202 assert(ii->isValid());
203 if (id == ii->getId() &&
204 (addr & ADDR_MASK) == (ii->getAddr() & ADDR_MASK) &&
205 size_vector == (size_vector & ii->getSizeV())) {
206 // assert(ii->isLinkValid() == false);
207 return (ii);
208 }
209 } while (ii != buf_.begin());
210
211 return (buf_.end()); // use buf_.end() to indicate not found
212}
213
214list<LoadStoreEntry>::iterator
215LoadStoreBuffer::findMatchO2Y(uint64_t addr, uint8_t size_vector)
216{
217 list<LoadStoreEntry>::iterator ii;
218
219 if (buf_.size() == 0) {
220 return buf_.end();
221 }
222
223 for (ii = buf_.begin(); ii != buf_.end(); ii++) {
224 assert(ii->isValid());;
225 if (ii->isLinkValid() == false &&
226 (addr & ADDR_MASK) == (ii->getAddr() & ADDR_MASK) &&
227 size_vector == (size_vector & ii->getSizeV())) {
228 return (ii);
229 }
230 }
231 return (buf_.end()); // use buf_.end() to indicate not found
232}
233
234list<LoadStoreEntry>::iterator
235LoadStoreBuffer::findMatchO2Y(uint64_t id, uint64_t addr, uint8_t size_vector)
236{
237 list<LoadStoreEntry>::iterator ii;
238
239 if (buf_.size() == 0) {
240 return buf_.end();
241 }
242
243 for (ii = buf_.begin(); ii != buf_.end(); ii++) {
244 assert(ii->isValid());;
245 if (id == ii->getId() &&
246 (addr & ADDR_MASK) == (ii->getAddr() & ADDR_MASK) &&
247 size_vector == ii->getSizeV()) {
248 // assert(ii->isLinkValid() == false);
249 return (ii);
250 }
251 }
252 return (buf_.end()); // use buf_.end() to indicate not found
253}
254
255list<LoadStoreEntry>::iterator
256LoadStoreBuffer::findMatchO2Y(uint64_t addr, enum LS_ENTRY_STATE state, uint64_t addrMask)
257{
258 list<LoadStoreEntry>::iterator ii;
259
260 if (buf_.size() == 0) {
261 return buf_.end();
262 }
263
264 for (ii = buf_.begin(); ii != buf_.end(); ii++) {
265 assert(ii->isValid());;
266 if ((addr & addrMask) == (ii->getAddr() & addrMask) &&
267 state == ii->getState()) {
268 // assert(ii->isLinkValid() == false);
269 return (ii);
270 }
271 }
272 return (buf_.end()); // use buf_.end() to indicate not found
273}
274
275list<LoadStoreEntry>::iterator
276LoadStoreBuffer::findMatchO2Y(uint64_t addr)
277{
278 list<LoadStoreEntry>::iterator ii;
279
280 if (buf_.size() == 0) {
281 return buf_.end();
282 }
283
284 for (ii = buf_.begin(); ii != buf_.end(); ii++) {
285 assert(ii->isValid());;
286 if (addr == ii->getAddr()) {
287 // assert(ii->isLinkValid() == false);
288 return (ii);
289 }
290 }
291 return (buf_.end()); // use buf_.end() to indicate not found
292}
293
294list<LoadStoreEntry>::iterator
295LoadStoreBuffer::findMatchO2Y(uint64_t addr, bool rmo, uint64_t addrMask)
296{
297 list<LoadStoreEntry>::iterator ii;
298
299 if (buf_.size() == 0) {
300 return buf_.end();
301 }
302
303 for (ii = buf_.begin(); ii != buf_.end(); ii++) {
304 assert(ii->isValid());;
305 if (((addr & addrMask) == (ii->getAddr() & addrMask)) &&
306 ((rmo && ii->isRMOstore()) || (!rmo && !ii->isRMOstore()))) {
307 return (ii);
308 }
309 }
310 return (buf_.end()); // use buf_.end() to indicate not found
311}
312
313list<LoadStoreEntry>::iterator
314LoadStoreBuffer::findNotIssuedO2Y(uint64_t addr)
315{
316 list<LoadStoreEntry>::iterator ii;
317
318 if (buf_.size() == 0) {
319 return buf_.end();
320 }
321
322 for (ii = buf_.begin(); ii != buf_.end(); ii++) {
323 assert(ii->isValid());;
324 if (!ii->isIssued() &&
325 (addr == ii->getAddr())) {
326 return (ii);
327 }
328 }
329 return (buf_.end()); // use buf_.end() to indicate not found
330}
331
332list<LoadStoreEntry>::iterator
333LoadStoreBuffer::find1stNoLink(uint64_t id, uint64_t addr, uint64_t addrMask)
334{
335 list<LoadStoreEntry>::iterator ii;
336
337 if (buf_.size() == 0) {
338 return buf_.end();
339 }
340
341 for (ii = buf_.begin(); ii != buf_.end(); ii++) {
342 assert(ii->isValid());;
343 if (!ii->isLinkValid() &&
344 (ii->getId() == id) &&
345 (ii->getAddr() & addrMask) == (addr & addrMask)) {
346 return (ii);
347 }
348 }
349 return (buf_.end()); // use buf_.end() to indicate not found
350}
351
352/* Note that this function exclude prefetch instruction */
353list<LoadStoreEntry>::iterator
354LoadStoreBuffer::find1stNonExe()
355{
356 list<LoadStoreEntry>::iterator ii;
357
358 if (buf_.size() == 0) {
359 return buf_.end();
360 }
361
362 for (ii = buf_.begin(); ii != buf_.end(); ii++) {
363 assert(ii->isValid());;
364 if (!(ii->isExecuted())) {
365 /* Riesling does not access memory for prefetch instruction, and hence
366 no STEP callback. To overcome this issue, the MemorySync model use
367 the next non-prefetch instruction to remove the prefetch instructions
368 in the LoadBuffer and MemoryAccessBuffer by setting its executed_.
369 */
370 if (ii->getItype() != ITYPE_PREFETCH) {
371 return (ii);
372 } else {
373 ii->setExecuted(true);
374 if (!ii->isLinkValid())
375 {
376 MS_ERROR("Found prio prefetch in LoadBuffer does not have LoadData");
377 return buf_.end();
378 }
379 ii->getLink()->setExecuted(true);
380 }
381 }
382 }
383 return (buf_.end()); // use buf_.end() to indicate not found
384}
385
386list<LoadStoreEntry>::iterator
387LoadStoreBuffer::find1stNonExeMatchedAddr(uint64_t addr)
388{
389 list<LoadStoreEntry>::iterator ii;
390
391 if (buf_.size() == 0) {
392 return buf_.end();
393 }
394
395#ifdef MMDEBUG
396 MSYNC_DEBUG(1, "Find addr=%#llx \n%s", addr, toString().c_str());
397// cerr << "FIND addr=0x" << hex << addr << endl;
398// cerr << toString();
399#endif
400
401 for (ii = buf_.begin(); ii != buf_.end(); ii++) {
402 assert(ii->isValid());;
403 if (!(ii->isExecuted()) && addr == ii->getAddr()) {
404 return (ii);
405 }
406 }
407 return (buf_.end()); // use buf_.end() to indicate not found
408}
409
410list<LoadStoreEntry>::iterator
411LoadStoreBuffer::find1stNonExeFetch(uint64_t addr)
412{
413 list<LoadStoreEntry>::iterator ii;
414
415 if (buf_.size() == 0) {
416 return buf_.end();
417 }
418
419#ifdef MMDEBUG
420 MSYNC_DEBUG(1, "Find addr=%#llx \n%s", addr, toString().c_str());
421// cerr << "FIND addr=0x" << hex << addr << endl;
422// cerr << toString();
423#endif
424
425 for (ii = buf_.begin(); ii != buf_.end(); ii++) {
426 assert(ii->isValid());;
427 if (!(ii->isExecuted()) &&
428 // (ii->getState() == LS_ACK) &&
429 addr == ii->getAddr()) {
430 return (ii);
431 }
432 }
433 return (buf_.end()); // use buf_.end() to indicate not found
434}
435
436list<LoadStoreEntry>::iterator
437LoadStoreBuffer::find1stNonExeOrMatchedAddrAtomic(uint64_t addr)
438{
439 list<LoadStoreEntry>::iterator ii;
440
441 if (buf_.size() == 0) {
442 return buf_.end();
443 }
444
445#ifdef MMDEBUG
446 MSYNC_DEBUG(1, "Find addr=%#llx \n%s", addr, toString().c_str());
447// cerr << "FIND addr=0x" << hex << addr << endl;
448// cerr << toString();
449#endif
450
451 for (ii = buf_.begin(); ii != buf_.end(); ii++) {
452 assert(ii->isValid());;
453 if (!(ii->isExecuted())) {
454 if (ii->getItype() != ITYPE_ATOMIC) {
455 return (ii);
456 } else { // atomic
457 if (addr == ii->getAddr()) {
458 return (ii);
459 } else {
460 ii->setExecuted(true);
461 if (ii->isLinkValid()) {
462 ii->getLink()->setExecuted(true);
463 }
464 }
465 }
466 }
467 }
468 return (buf_.end()); // use buf_.end() to indicate not found
469}
470
471list<LoadStoreEntry>::iterator
472LoadStoreBuffer::findNeedTDataO2Y(uint64_t addr)
473{
474 list<LoadStoreEntry>::iterator ii;
475
476 if (buf_.size() == 0) {
477 return buf_.end();
478 }
479
480 for (ii = buf_.begin(); ii != buf_.end(); ii++) {
481 assert(ii->isValid());
482 if (!ii->isIssued() && ii->getState() != LS_TDATA && // only possible states are NEW & RDATA
483 (addr) == (ii->getAddr())) {
484 // assert(ii->isLinkValid() == false);
485 return (ii);
486 }
487 }
488 return (buf_.end()); // use buf_.end() to indicate not found
489}
490
491list<LoadStoreEntry>::iterator
492LoadStoreBuffer::findDataBypassing (uint64_t addr, uint8_t size_vector)
493{
494 list<LoadStoreEntry>::iterator ii;
495 uint8_t overlap;
496
497 if (buf_.size() == 0) {
498 return buf_.end();
499 }
500
501 ii = buf_.end();
502 do {
503 ii--;
504 assert(ii->isValid());
505 if ((addr & ADDR_MASK) == (ii->getAddr() & ADDR_MASK)) {
506 overlap = size_vector & ii->getSizeV();
507 if (overlap == size_vector) { // entry's data is a superset => bypassing
508 return (ii);
509 } else if (overlap == 0) { // no overlap, search for next
510 continue;
511 } else { // partially overlap => access from L2
512 return (buf_.end());
513 }
514 }
515 } while (ii != buf_.begin());
516
517 return (buf_.end()); // use buf_.end() to indicate not found
518}
519
520/******************************************************************************
521 * The store buffer bypassing check criteria is changed on 5/17/04 that treats
522 * multiple hits as partial hit. In other words, no bypassing. To know this,
523 * the algorithm has to check the whole store buffer.
524 ******************************************************************************/
525list<LoadStoreEntry>::iterator
526LoadStoreBuffer::findN2DataBypassing (uint64_t addr, uint8_t size_vector)
527{
528 list<LoadStoreEntry>::iterator ii;
529 list<LoadStoreEntry>::iterator matched_ste;
530 bool matched;
531 uint8_t overlap;
532
533 if (buf_.size() == 0) {
534 return buf_.end();
535 }
536
537 matched = false;
538 for (ii = buf_.begin(); ii != buf_.end(); ii++) {
539 assert(ii->isValid());
540 if ((addr & ADDR_MASK) == (ii->getAddr() & ADDR_MASK)) {
541 overlap = size_vector & ii->getSizeV();
542 if (overlap == size_vector) { // entry's data is a superset => bypassing
543 if (matched) {
544 return (buf_.end()); // multiple hits
545 } else {
546 matched = true;
547 matched_ste = ii;
548 continue;
549 }
550 } else if (overlap == 0) { // no overlap, search for next
551 continue;
552 } else { // partially overlap => access from L2
553 return (buf_.end());
554 }
555 }
556 }
557 return (matched ? matched_ste : buf_.end()); // use buf_.end() to indicate not found
558}
559
560//=============================================================================
561//=============================================================================
562void
563LoadStoreBuffer::empty()
564{
565 //cerr << "DBX: LoadStoreBuffer::empty: " << bufName_ << " size=" << buf_.size() << endl;//DBX
566 //TODO make sure we free the space properly
567 buf_.clear();
568// while (buf_.size() > 0) {
569// buf_.pop_front();
570// }
571}
572
573//=============================================================================
574//=============================================================================
575list<LoadStoreEntry>::iterator
576LoadStoreBuffer::queryBack()
577{
578 list<LoadStoreEntry>::iterator ii;
579
580 if (buf_.size() == 0) {
581 return buf_.end();
582 }
583 else {
584 ii = --(buf_.end());
585 return (ii);
586 }
587}
588
589//=============================================================================
590//=============================================================================
591void
592LoadStoreBuffer::markPop()
593{
594 list<LoadStoreEntry>::iterator ii = buf_.end();
595 int size = buf_.size();
596 while (size > 0) {
597 ii--;
598 size--;
599 if (ii->isLinkValid() && ii->getLink()->isPopped()) {
600 //ii->setExecuted(true);
601 buf_.erase(ii);
602 }
603 }
604}