// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: Block.cc
// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
// The above named program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License version 2 as published by the Free Software Foundation.
// The above named program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
// You should have received a copy of the GNU General Public
// License along with this work; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
// ========== Copyright Header End ============================================
#include "RegisterArray.h"
static const bool VERBOSE_BLOCK
= false;
static const bool VERBOSE_LOOKUP
= false;
static const bool VERBOSE_REGISTER
= false;
static const bool ASSERT_REGISTER_ERRORS
= false;
static const bool MAP_ENABLE
= false;
static const bool MAP_CHECK
= false;
void Block::addRegister (Register
*r
)
Addr addr
= r
->getAddr();
void Block::addRegisterArray (RegisterArray
*r
)
Addr start
= r
->getStartAddr();
Addr end
= r
->getEndAddr();
registerArrays
.addTail(r
);
void Block::regCheck (Register
*r
)
Addr thisAddr
= r
->getAddr();
ListIterator
<Register
> regIter(®isters
);
for (Register
*reg
= regIter
.getHeadItem();
reg
= regIter
.getNextItem()) {
Addr regAddr
= reg
->getAddr();
if (thisAddr
== regAddr
) {
cerr
<< "WARNING: " << r
->getFullName()
<< " at 0x" << hex
<< thisAddr
<< " overlaps with " << reg
->getFullName()
<< " at 0x" << regAddr
<< "\n" << dec
;
ListIterator
<RegisterArray
> regArrayIter(®isterArrays
);
for (RegisterArray
*regArray
= regArrayIter
.getHeadItem();
regArray
= regArrayIter
.getNextItem()) {
Addr arrayStart
= regArray
->getStartAddr();
Addr arrayEnd
= regArray
->getEndAddr();
Addr arrayStep
= regArray
->getStep();
if (thisAddr
>= arrayStart
&& thisAddr
<= arrayEnd
&&
((thisAddr
- arrayStart
) % arrayStep
) == 0) {
cerr
<< "WARNING: " << r
->getFullName()
<< " at 0x" << hex
<< thisAddr
<< " overlaps with " << regArray
->getFullName()
<< " at 0x" << arrayStart
<< " to 0x" << arrayEnd
<< " step 0x" << arrayStep
<< "\n" << dec
;
if (ASSERT_REGISTER_ERRORS
)
void Block::regArrayCheck (RegisterArray
*r
)
Addr thisStart
= r
->getStartAddr();
Addr thisEnd
= r
->getEndAddr();
Addr thisStep
= r
->getStep();
uint thisCount
= r
->getCount();
ListIterator
<Register
> regIter(®isters
);
for (Register
*reg
= regIter
.getHeadItem();
reg
= regIter
.getNextItem()) {
Addr regAddr
= reg
->getAddr();
if (regAddr
>= thisStart
&& regAddr
<= thisEnd
&&
((regAddr
- thisStart
) % thisStep
) == 0) {
cerr
<< "WARNING: " << r
->getFullName()
<< " at 0x" << hex
<< thisStart
<< " to 0x" << thisEnd
<< " step 0x" << thisStep
<< " overlaps with " << reg
->getFullName()
<< " at 0x" << regAddr
<< "\n" << dec
;
ListIterator
<RegisterArray
> regArrayIter(®isterArrays
);
for (RegisterArray
*regArray
= regArrayIter
.getHeadItem();
regArray
= regArrayIter
.getNextItem()) {
Addr arrayStart
= regArray
->getStartAddr();
Addr arrayEnd
= regArray
->getEndAddr();
Addr arrayStep
= regArray
->getStep();
uint arrayCount
= regArray
->getCount();
if (arrayStart
<= thisEnd
&&
if (arrayCount
> thisCount
) {
for (Addr regAddr
=arrayStart
; regAddr
<=arrayEnd
; regAddr
+=arrayStep
) {
if (regAddr
>= thisStart
&& regAddr
<= thisEnd
&&
((regAddr
- thisStart
) % thisStep
) == 0) {
for (Addr thisAddr
=thisStart
; thisAddr
<=thisEnd
; thisAddr
+=thisStep
) {
if (thisAddr
>= arrayStart
&& thisAddr
<= arrayEnd
&&
((thisAddr
- arrayStart
) % arrayStep
) == 0) {
cerr
<< "WARNING: " << r
->getFullName()
<< " at 0x" << hex
<< thisStart
<< " to 0x" << thisEnd
<< " step 0x" << thisStep
<< " overlaps with " << regArray
->getFullName()
<< " at 0x" << arrayStart
<< " to 0x" << arrayEnd
<< " step 0x" << arrayStep
<< "\n" << dec
;
if (ASSERT_REGISTER_ERRORS
)
bool Block::regRead (Addr a
, Data
*d
)
if ((reg
= regLookup(a
)) != NULL
) {
cout
<< "Read value 0x" << hex
<< *d
<< " from " << reg
->getFullName()
<< " at address 0x" << a
<< "\n";
cout
<< "Read register at invalid address 0x" << hex
<< a
<< "\n";
Register
*Block::regLookup (Addr a
)
if (a
>= minAddr
&& a
<= maxAddr
) {
if (map
!= NULL
&& (mapReg
= map
->lookup(a
)) != NULL
) {
assert(mapReg
->getAddr() == a
);
cout
<< "Lookup for register " << mapReg
->getFullName() << " has "
<< dec
<< count
<< " checks in block " << getFullName()
ListIterator
<Register
> regIter(®isters
);
for (Register
*reg
= regIter
.getHeadItem();
reg
= regIter
.getNextItem()) {
if (reg
->getAddr() == a
) {
cout
<< "Lookup for register " << reg
->getFullName() << " has "
<< dec
<< count
<< " checks in block " << getFullName()
if (MAP_CHECK
&& mapReg
!= NULL
)
assert(mapReg
->getPtr() == reg
->getPtr());
ListIterator
<RegisterArray
> regArrayIter(®isterArrays
);
for (RegisterArray
*regArray
= regArrayIter
.getHeadItem();
regArray
= regArrayIter
.getNextItem()) {
Addr startAddr
= regArray
->getStartAddr();
Addr endAddr
= regArray
->getEndAddr();
Addr step
= regArray
->getStep();
if (a
>= startAddr
&& a
<= endAddr
&&
((a
- startAddr
) % step
) == 0) {
uint64 index
= (a
- startAddr
) / step
;
assert(index
< regArray
->getCount());
cout
<< "Lookup for register " << (*regArray
)[i
].getFullName()
<< " has " << dec
<< count
<< " checks in block "
<< getFullName() << " (found)\n";
if (MAP_CHECK
&& mapReg
!= NULL
)
assert(mapReg
->getPtr() == (*regArray
)[i
].getPtr());
cout
<< "Lookup for address 0x" << hex
<< a
<< " has " << dec
<< count
<< " checks in block " << getFullName() << " (not found)\n";
Register
*Block::regLookup (string n
)
ListIterator
<Register
> regIter(®isters
);
for (Register
*reg
= regIter
.getHeadItem();
reg
= regIter
.getNextItem()) {
if (reg
->getBaseName() == n
) {
cout
<< "Lookup for register " << reg
->getFullName() << " has "
<< dec
<< count
<< " checks in block " << getFullName()
ListIterator
<RegisterArray
> regArrayIter(®isterArrays
);
for (RegisterArray
*regArray
= regArrayIter
.getHeadItem();
regArray
= regArrayIter
.getNextItem()) {
string basename
= regArray
->getBaseName();
long baselen
= basename
.length();
if (nlen
>= baselen
+ 3 &&
basename
.compare(0, baselen
, n
, 0, baselen
) == 0 &&
for (uint i
=baselen
+1; ok
&& i
< nlen
-1; i
++) {
index
= 10 * index
+ (n
[i
] - '0');
if (ok
&& index
< regArray
->getCount()) {
cout
<< "Lookup for register " << (*regArray
)[index
].getFullName()
<< " has " << dec
<< count
<< " checks in block "
<< getFullName() << " (found)\n";
return &(*regArray
)[index
];
cout
<< "Lookup for register " << n
<< " has " << dec
<< count
<< " checks in block " << getFullName() << " (not found)\n";
bool Block::regRead (string n
, Data
*d
)
if ((reg
= regLookup(n
)) != NULL
) {
cout
<< "Read value 0x" << hex
<< *d
<< " from " << reg
->getFullName()
<< " at address 0x" << reg
->getAddr() << "\n";
cout
<< "Read register with invalid name " << n
<< "\n";
bool Block::regWrite (Addr a
, Data d
)
if ((reg
= regLookup(a
)) != NULL
) {
cout
<< "Write value 0x" << hex
<< d
<< " to " << reg
->getFullName()
<< " at address 0x" << a
<< "\n";
cout
<< "Write register at invalid address 0x" << hex
<< a
<< "\n";
bool Block::regWrite (string n
, Data d
)
if ((reg
= regLookup(n
)) != NULL
) {
cout
<< "Write value 0x" << hex
<< d
<< " to " << reg
->getFullName()
<< " at address 0x" << reg
->getAddr() << "\n";
cout
<< "Write register with invalid name " << n
<< "\n";
void Block::enableWriteBlockCB ()
ListIterator
<Register
> regIter(®isters
);
for (Register
*reg
= regIter
.getHeadItem();
reg
= regIter
.getNextItem())
reg
->enableWriteBlockCB();
ListIterator
<RegisterArray
> regArrayIter(®isterArrays
);
for (RegisterArray
*regArray
= regArrayIter
.getHeadItem();
regArray
= regArrayIter
.getNextItem())
regArray
->enableWriteBlockCB();
void Block::disableWriteBlockCB ()
ListIterator
<Register
> regIter(®isters
);
for (Register
*reg
= regIter
.getHeadItem();
reg
= regIter
.getNextItem())
reg
->disableWriteBlockCB();
ListIterator
<RegisterArray
> regArrayIter(®isterArrays
);
for (RegisterArray
*regArray
= regArrayIter
.getHeadItem();
regArray
= regArrayIter
.getNextItem())
regArray
->disableWriteBlockCB();
void Block::enableReadBlockCB ()
ListIterator
<Register
> regIter(®isters
);
for (Register
*reg
= regIter
.getHeadItem();
reg
= regIter
.getNextItem())
reg
->enableReadBlockCB();
ListIterator
<RegisterArray
> regArrayIter(®isterArrays
);
for (RegisterArray
*regArray
= regArrayIter
.getHeadItem();
regArray
= regArrayIter
.getNextItem())
regArray
->enableReadBlockCB();
void Block::disableReadBlockCB ()
ListIterator
<Register
> regIter(®isters
);
for (Register
*reg
= regIter
.getHeadItem();
reg
= regIter
.getNextItem())
reg
->disableReadBlockCB();
ListIterator
<RegisterArray
> regArrayIter(®isterArrays
);
for (RegisterArray
*regArray
= regArrayIter
.getHeadItem();
regArray
= regArrayIter
.getNextItem())
regArray
->disableReadBlockCB();
void Block::printThis (ostream
&os
)
ListIterator
<Register
> regIter(®isters
);
for (Register
*reg
= regIter
.getHeadItem();
reg
= regIter
.getNextItem())
ListIterator
<RegisterArray
> regArrayIter(®isterArrays
);
for (RegisterArray
*regArray
= regArrayIter
.getHeadItem();
regArray
= regArrayIter
.getNextItem())
ListIterator
<Register
> regIter(®isters
);
for (Register
*reg
= regIter
.getHeadItem();
reg
= regIter
.getNextItem())
ListIterator
<RegisterArray
> regArrayIter(®isterArrays
);
for (RegisterArray
*regArray
= regArrayIter
.getHeadItem();
regArray
= regArrayIter
.getNextItem())
// Map construction is postponed to Block::finalize(). The reason
// for this is that the Register indexing and cloning for mapping
// of each RegisterArray relies on virtual methods to use the
// appropriate index and clone methods of the specific RegisterArray
// subclass. Virtual overloading does not work during construction
// and this has to be postponed until later, and this is the first
// convenient point. If there is any use of regLookup, regRead or
// regWrite prior to finalization, then these methods will behave
// correctly but there is no mapping optimization - this should
// not be a performance problem.
if (MAP_ENABLE
&& map
== NULL
) {
map
= new Map
<Register
>(getFullName());
ListIterator
<Register
> regIter(®isters
);
for (Register
*reg
= regIter
.getHeadItem();
reg
= regIter
.getNextItem()) {
if (MAP_ENABLE
&& reg
->getWidth() == 8) {
bool ok
= map
->insert(reg
->getAddr(), reg
);
if (ASSERT_REGISTER_ERRORS
)
ListIterator
<RegisterArray
> regArrayIter(®isterArrays
);
for (RegisterArray
*regArray
= regArrayIter
.getHeadItem();
regArray
= regArrayIter
.getNextItem()) {
if (MAP_ENABLE
&& regArray
->getWidth() == 8 && !regArray
->isHuge()) {
uint count
= regArray
->getCount();
for (uint index
=0; index
<count
; index
++) {
Register
&src
= (*regArray
)[index
];
Register
*reg
= src
.clone();
bool ok
= map
->insert(reg
->getAddr(), reg
);
if (ASSERT_REGISTER_ERRORS
)
cout
<< "Block " << getFullName() << " has " << dec
<< countReg
<< " registers and "
<< countRegArray
<< " register arrays\n";
if (countReg
+ countRegArray
> 0) {
cout
<< "Block " << getFullName() << " has " << hex
<< "registers in range 0x" << minAddr
<< " to " << maxAddr
<< " covering " << dec
<< maxAddr
- minAddr
<< " bytes\n";