Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / common / regdef / Block.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: Block.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#include "Block.h"
22#include "Register.h"
23#include "RegisterArray.h"
24
25using namespace std;
26
27static const bool VERBOSE_BLOCK = false;
28static const bool VERBOSE_LOOKUP = false;
29static const bool VERBOSE_REGISTER = false;
30static const bool ASSERT_REGISTER_ERRORS = false;
31static const bool MAP_ENABLE = false;
32static const bool MAP_CHECK = false;
33
34Block::Block(string n) {
35 fullName = n;
36 map = NULL;
37 final = false;
38}
39
40Block::~Block() {
41}
42
43void Block::addRegister (Register *r)
44{
45 assert(!final);
46 regCheck(r);
47 Addr addr = r->getAddr();
48 if (addr < minAddr)
49 minAddr = addr;
50 if (addr > maxAddr)
51 maxAddr = addr;
52 registers.addTail(r);
53}
54
55void Block::addRegisterArray (RegisterArray *r)
56{
57 assert(!final);
58 Addr start = r->getStartAddr();
59 Addr end = r->getEndAddr();
60 regArrayCheck(r);
61 if (start < minAddr)
62 minAddr = start;
63 if (end > maxAddr)
64 maxAddr = end;
65 registerArrays.addTail(r);
66}
67
68void Block::regCheck (Register *r)
69{
70 int errors = 0;
71 Addr thisAddr = r->getAddr();
72
73 ListIterator<Register> regIter(&registers);
74 for (Register *reg = regIter.getHeadItem();
75 reg != NULL;
76 reg = regIter.getNextItem()) {
77 Addr regAddr = reg->getAddr();
78
79 if (thisAddr == regAddr) {
80 cerr << "WARNING: " << r->getFullName()
81 << " at 0x" << hex << thisAddr
82 << " overlaps with " << reg->getFullName()
83 << " at 0x" << regAddr << "\n" << dec;
84 errors++;
85 }
86 }
87
88 ListIterator<RegisterArray> regArrayIter(&registerArrays);
89 for (RegisterArray *regArray = regArrayIter.getHeadItem();
90 regArray != NULL;
91 regArray = regArrayIter.getNextItem()) {
92 Addr arrayStart = regArray->getStartAddr();
93 Addr arrayEnd = regArray->getEndAddr();
94 Addr arrayStep = regArray->getStep();
95
96 if (thisAddr >= arrayStart && thisAddr <= arrayEnd &&
97 ((thisAddr - arrayStart) % arrayStep) == 0) {
98 cerr << "WARNING: " << r->getFullName()
99 << " at 0x" << hex << thisAddr
100 << " overlaps with " << regArray->getFullName()
101 << " at 0x" << arrayStart << " to 0x" << arrayEnd
102 << " step 0x" << arrayStep << "\n" << dec;
103 errors++;
104 }
105 }
106
107 if (ASSERT_REGISTER_ERRORS)
108 assert(errors == 0);
109}
110
111void Block::regArrayCheck (RegisterArray *r)
112{
113 int errors = 0;
114 Addr thisStart = r->getStartAddr();
115 Addr thisEnd = r->getEndAddr();
116 Addr thisStep = r->getStep();
117 uint thisCount = r->getCount();
118
119 ListIterator<Register> regIter(&registers);
120 for (Register *reg = regIter.getHeadItem();
121 reg != NULL;
122 reg = regIter.getNextItem()) {
123 Addr regAddr = reg->getAddr();
124
125 if (regAddr >= thisStart && regAddr <= thisEnd &&
126 ((regAddr - thisStart) % thisStep) == 0) {
127 cerr << "WARNING: " << r->getFullName()
128 << " at 0x" << hex << thisStart << " to 0x" << thisEnd
129 << " step 0x" << thisStep
130 << " overlaps with " << reg->getFullName()
131 << " at 0x" << regAddr << "\n" << dec;
132 errors++;
133 }
134 }
135
136 ListIterator<RegisterArray> regArrayIter(&registerArrays);
137 for (RegisterArray *regArray = regArrayIter.getHeadItem();
138 regArray != NULL;
139 regArray = regArrayIter.getNextItem()) {
140 Addr arrayStart = regArray->getStartAddr();
141 Addr arrayEnd = regArray->getEndAddr();
142 Addr arrayStep = regArray->getStep();
143 uint arrayCount = regArray->getCount();
144
145 if (arrayStart <= thisEnd &&
146 arrayEnd >= thisStart) {
147 bool overlap = false;
148
149 if (arrayCount > thisCount) {
150 for (Addr regAddr=arrayStart; regAddr<=arrayEnd; regAddr+=arrayStep) {
151 if (regAddr >= thisStart && regAddr <= thisEnd &&
152 ((regAddr - thisStart) % thisStep) == 0) {
153 overlap = true;
154 break;
155 }
156 }
157 } else {
158 for (Addr thisAddr=thisStart; thisAddr<=thisEnd; thisAddr+=thisStep) {
159 if (thisAddr >= arrayStart && thisAddr <= arrayEnd &&
160 ((thisAddr - arrayStart) % arrayStep) == 0) {
161 overlap = true;
162 break;
163 }
164 }
165 }
166
167 if (overlap) {
168 cerr << "WARNING: " << r->getFullName()
169 << " at 0x" << hex << thisStart << " to 0x" << thisEnd
170 << " step 0x" << thisStep
171 << " overlaps with " << regArray->getFullName()
172 << " at 0x" << arrayStart << " to 0x" << arrayEnd
173 << " step 0x" << arrayStep << "\n" << dec;
174 errors++;
175 }
176 }
177 }
178
179 if (ASSERT_REGISTER_ERRORS)
180 assert(errors == 0);
181}
182
183bool Block::regRead (Addr a, Data *d)
184{
185 Register *reg;
186 if ((reg = regLookup(a)) != NULL) {
187 *d = reg->read();
188 if (VERBOSE_REGISTER) {
189 cout << "Read value 0x" << hex << *d
190 << " from " << reg->getFullName()
191 << " at address 0x" << a << "\n";
192 }
193 return true;
194 } else {
195 if (VERBOSE_REGISTER) {
196 cout << "Read register at invalid address 0x" << hex << a << "\n";
197 }
198 return false;
199 }
200}
201
202Register *Block::regLookup (Addr a)
203{
204 uint count = 0;
205
206 if (a >= minAddr && a <= maxAddr) {
207 Register *mapReg = NULL;
208
209 if (map != NULL && (mapReg = map->lookup(a)) != NULL) {
210 assert(mapReg->getAddr() == a);
211 if (VERBOSE_LOOKUP) {
212 cout << "Lookup for register " << mapReg->getFullName() << " has "
213 << dec << count << " checks in block " << getFullName()
214 << " (map found)\n";
215 }
216 if (!MAP_CHECK)
217 return mapReg;
218 }
219
220 ListIterator<Register> regIter(&registers);
221 for (Register *reg = regIter.getHeadItem();
222 reg != NULL;
223 reg = regIter.getNextItem()) {
224 count++;
225 if (reg->getAddr() == a) {
226 if (VERBOSE_LOOKUP) {
227 cout << "Lookup for register " << reg->getFullName() << " has "
228 << dec << count << " checks in block " << getFullName()
229 << " (found)\n";
230 }
231 if (MAP_CHECK && mapReg != NULL)
232 assert(mapReg->getPtr() == reg->getPtr());
233 return reg;
234 }
235 }
236
237 ListIterator<RegisterArray> regArrayIter(&registerArrays);
238 for (RegisterArray *regArray = regArrayIter.getHeadItem();
239 regArray != NULL;
240 regArray = regArrayIter.getNextItem()) {
241 Addr startAddr = regArray->getStartAddr();
242 Addr endAddr = regArray->getEndAddr();
243 Addr step = regArray->getStep();
244 count++;
245 if (a >= startAddr && a <= endAddr &&
246 ((a - startAddr) % step) == 0) {
247 uint64 index = (a - startAddr) / step;
248 assert(index < regArray->getCount());
249 uint i = uint(index);
250 if (VERBOSE_LOOKUP) {
251 cout << "Lookup for register " << (*regArray)[i].getFullName()
252 << " has " << dec << count << " checks in block "
253 << getFullName() << " (found)\n";
254 }
255 if (MAP_CHECK && mapReg != NULL)
256 assert(mapReg->getPtr() == (*regArray)[i].getPtr());
257 return &(*regArray)[i];
258 }
259 }
260 }
261
262 if (VERBOSE_LOOKUP) {
263 cout << "Lookup for address 0x" << hex << a << " has " << dec << count
264 << " checks in block " << getFullName() << " (not found)\n";
265 }
266
267 return NULL;
268}
269
270Register *Block::regLookup (string n)
271{
272 uint count = 0;
273
274 ListIterator<Register> regIter(&registers);
275 for (Register *reg = regIter.getHeadItem();
276 reg != NULL;
277 reg = regIter.getNextItem()) {
278 count++;
279 if (reg->getBaseName() == n) {
280 if (VERBOSE_LOOKUP) {
281 cout << "Lookup for register " << reg->getFullName() << " has "
282 << dec << count << " checks in block " << getFullName()
283 << " (found)\n";
284 }
285 return reg;
286 }
287 }
288
289 ListIterator<RegisterArray> regArrayIter(&registerArrays);
290 for (RegisterArray *regArray = regArrayIter.getHeadItem();
291 regArray != NULL;
292 regArray = regArrayIter.getNextItem()) {
293 count++;
294 string basename = regArray->getBaseName();
295 long baselen = basename.length();
296 long nlen = n.length();
297 if (nlen >= baselen + 3 &&
298 basename.compare(0, baselen, n, 0, baselen) == 0 &&
299 n[baselen] == '[' &&
300 n[nlen - 1] == ']') {
301 uint index = 0;
302 bool ok = true;
303 for (uint i=baselen+1; ok && i < nlen-1; i++) {
304 if (isdigit(n[i]))
305 index = 10 * index + (n[i] - '0');
306 else
307 ok = false;
308 }
309 if (ok && index < regArray->getCount()) {
310 if (VERBOSE_LOOKUP) {
311 cout << "Lookup for register " << (*regArray)[index].getFullName()
312 << " has " << dec << count << " checks in block "
313 << getFullName() << " (found)\n";
314 }
315 return &(*regArray)[index];
316 }
317 }
318 }
319
320 if (VERBOSE_LOOKUP) {
321 cout << "Lookup for register " << n << " has " << dec << count
322 << " checks in block " << getFullName() << " (not found)\n";
323 }
324
325 return NULL;
326}
327
328bool Block::regRead (string n, Data *d)
329{
330 Register *reg;
331 if ((reg = regLookup(n)) != NULL) {
332 *d = reg->read();
333 if (VERBOSE_REGISTER) {
334 cout << "Read value 0x" << hex << *d
335 << " from " << reg->getFullName()
336 << " at address 0x" << reg->getAddr() << "\n";
337 }
338 return true;
339 } else {
340 if (VERBOSE_REGISTER) {
341 cout << "Read register with invalid name " << n << "\n";
342 }
343 return false;
344 }
345}
346
347bool Block::regWrite (Addr a, Data d)
348{
349 Register *reg;
350 if ((reg = regLookup(a)) != NULL) {
351 reg->write(d);
352 if (VERBOSE_REGISTER) {
353 cout << "Write value 0x" << hex << d
354 << " to " << reg->getFullName()
355 << " at address 0x" << a << "\n";
356 }
357 return true;
358 } else {
359 if (VERBOSE_REGISTER) {
360 cout << "Write register at invalid address 0x" << hex << a << "\n";
361 }
362 return false;
363 }
364}
365
366bool Block::regWrite (string n, Data d)
367{
368 Register *reg;
369 if ((reg = regLookup(n)) != NULL) {
370 reg->write(d);
371 if (VERBOSE_REGISTER) {
372 cout << "Write value 0x" << hex << d
373 << " to " << reg->getFullName()
374 << " at address 0x" << reg->getAddr() << "\n";
375 }
376 return true;
377 } else {
378 if (VERBOSE_REGISTER) {
379 cout << "Write register with invalid name " << n << "\n";
380 }
381 return false;
382 }
383}
384
385void Block::enableWriteBlockCB ()
386{
387 ListIterator<Register> regIter(&registers);
388 for (Register *reg = regIter.getHeadItem();
389 reg != NULL;
390 reg = regIter.getNextItem())
391 reg->enableWriteBlockCB();
392 ListIterator<RegisterArray> regArrayIter(&registerArrays);
393 for (RegisterArray *regArray = regArrayIter.getHeadItem();
394 regArray != NULL;
395 regArray = regArrayIter.getNextItem())
396 regArray->enableWriteBlockCB();
397}
398
399void Block::disableWriteBlockCB ()
400{
401 ListIterator<Register> regIter(&registers);
402 for (Register *reg = regIter.getHeadItem();
403 reg != NULL;
404 reg = regIter.getNextItem())
405 reg->disableWriteBlockCB();
406 ListIterator<RegisterArray> regArrayIter(&registerArrays);
407 for (RegisterArray *regArray = regArrayIter.getHeadItem();
408 regArray != NULL;
409 regArray = regArrayIter.getNextItem())
410 regArray->disableWriteBlockCB();
411}
412
413void Block::enableReadBlockCB ()
414{
415 ListIterator<Register> regIter(&registers);
416 for (Register *reg = regIter.getHeadItem();
417 reg != NULL;
418 reg = regIter.getNextItem())
419 reg->enableReadBlockCB();
420 ListIterator<RegisterArray> regArrayIter(&registerArrays);
421 for (RegisterArray *regArray = regArrayIter.getHeadItem();
422 regArray != NULL;
423 regArray = regArrayIter.getNextItem())
424 regArray->enableReadBlockCB();
425}
426
427void Block::disableReadBlockCB ()
428{
429 ListIterator<Register> regIter(&registers);
430 for (Register *reg = regIter.getHeadItem();
431 reg != NULL;
432 reg = regIter.getNextItem())
433 reg->disableReadBlockCB();
434 ListIterator<RegisterArray> regArrayIter(&registerArrays);
435 for (RegisterArray *regArray = regArrayIter.getHeadItem();
436 regArray != NULL;
437 regArray = regArrayIter.getNextItem())
438 regArray->disableReadBlockCB();
439}
440
441void Block::printThis (ostream &os)
442{
443 ListIterator<Register> regIter(&registers);
444 for (Register *reg = regIter.getHeadItem();
445 reg != NULL;
446 reg = regIter.getNextItem())
447 reg->printThis(os);
448
449 ListIterator<RegisterArray> regArrayIter(&registerArrays);
450 for (RegisterArray *regArray = regArrayIter.getHeadItem();
451 regArray != NULL;
452 regArray = regArrayIter.getNextItem())
453 regArray->printThis(os);
454}
455
456void Block::resetThis ()
457{
458 finalize();
459
460 ListIterator<Register> regIter(&registers);
461 for (Register *reg = regIter.getHeadItem();
462 reg != NULL;
463 reg = regIter.getNextItem())
464 reg->resetThis();
465
466 ListIterator<RegisterArray> regArrayIter(&registerArrays);
467 for (RegisterArray *regArray = regArrayIter.getHeadItem();
468 regArray != NULL;
469 regArray = regArrayIter.getNextItem())
470 regArray->resetThis();
471}
472
473
474void Block::finalize ()
475{
476 if (!final) {
477 final = true;
478
479 // Map construction is postponed to Block::finalize(). The reason
480 // for this is that the Register indexing and cloning for mapping
481 // of each RegisterArray relies on virtual methods to use the
482 // appropriate index and clone methods of the specific RegisterArray
483 // subclass. Virtual overloading does not work during construction
484 // and this has to be postponed until later, and this is the first
485 // convenient point. If there is any use of regLookup, regRead or
486 // regWrite prior to finalization, then these methods will behave
487 // correctly but there is no mapping optimization - this should
488 // not be a performance problem.
489
490 if (MAP_ENABLE && map == NULL) {
491 map = new Map<Register>(getFullName());
492 }
493
494 uint countReg = 0;
495 ListIterator<Register> regIter(&registers);
496 for (Register *reg = regIter.getHeadItem();
497 reg != NULL;
498 reg = regIter.getNextItem()) {
499 if (MAP_ENABLE && reg->getWidth() == 8) {
500 bool ok = map->insert(reg->getAddr(), reg);
501 if (ASSERT_REGISTER_ERRORS)
502 assert(ok);
503 }
504 countReg++;
505 }
506
507 uint countRegArray = 0;
508 ListIterator<RegisterArray> regArrayIter(&registerArrays);
509 for (RegisterArray *regArray = regArrayIter.getHeadItem();
510 regArray != NULL;
511 regArray = regArrayIter.getNextItem()) {
512 if (MAP_ENABLE && regArray->getWidth() == 8 && !regArray->isHuge()) {
513 uint count = regArray->getCount();
514 for (uint index=0; index<count; index++) {
515 Register &src = (*regArray)[index];
516 Register *reg = src.clone();
517 bool ok = map->insert(reg->getAddr(), reg);
518 if (ASSERT_REGISTER_ERRORS)
519 assert(ok);
520 }
521 }
522 countRegArray++;
523 }
524
525 if (VERBOSE_BLOCK) {
526 cout << "Block " << getFullName() << " has " << dec
527 << countReg << " registers and "
528 << countRegArray << " register arrays\n";
529
530 if (countReg + countRegArray > 0) {
531 cout << "Block " << getFullName() << " has " << hex
532 << "registers in range 0x" << minAddr << " to " << maxAddr
533 << " covering " << dec << maxAddr - minAddr << " bytes\n";
534 }
535 }
536 }
537}