// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: Register.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 ============================================
static const bool ASSERT_REGISTER_ERRORS
= false;
RegisterType::RegisterType (uint w
)
assert(w
== 1 || w
== 2 || w
== 4 || w
== 8);
widthMask
= (widthBits
== 64) ? ~Data(0) : (Data(1) << widthBits
) - 1;
resetValue
= UNDEFINED_DATA
& widthMask
;
void RegisterType::check (string n
)
// cerr << hex << "check " << n << " " << checkMask << " " << widthMask << " " << endl;
if (checkMask
!= widthMask
) {
assert((checkMask
& ~widthMask
) == 0);
for (uint i
=0; i
<widthBits
; i
++) {
if ((checkMask
& (1ULL << i
)) == 0) {
for (i
++; i
<widthBits
; i
++) {
if ((checkMask
& (1ULL << i
)) != 0)
cerr
<< "WARNING: Register bits " << n
<< "[" << end
<< ":" << start
<< "]"
<< " do not belong to any field\n";
if (ASSERT_REGISTER_ERRORS
)
Register::Register (string n
, Block
*b
, Addr a
, uint w
)
regType
= new RegisterType(w
);
regState
= new RegisterState(UNDEFINED_DATA
); // undefined value
regInfo
= new RegisterInfo(false, false); // unassigned and dirty
// cerr << "REG " << n << hex << " chk " << regType->checkMask << " width " << regType->widthMask << endl;
// The address is only used/checked when the Register has a Block
assert((a
% regType
->widthBytes
) == 0);
Register::Register (const Register
&r
)
mySignature
= r
.mySignature
;
void Register::init (Block
*b
, Addr a
, bool e
, uint i
, RegisterType
*rt
,
RegisterState
*rs
, RegisterInfo
*ri
, Signature
*s
)
assert(rt
!= NULL
&& rs
!= NULL
&& ri
!= NULL
);
assert((a
% rt
->widthBytes
) == 0);
Register
&Register::operator= (const Register
&r
)
mySignature
= r
.mySignature
;
string
Register::getBaseName() const
return baseName
+ "[" + o
.str() + "]";
string
Register::getFullName() const
return (block
== NULL
) ? getBaseName()
: block
->getFullName() + "." + getBaseName();
void Register::printThis (ostream
&os
)
os
<< getFullName() << " (0x" << hex
<< addr
<< ", width " << dec
<< regType
->widthBytes
<< " bytes) = 0x"
<< hex
<< regState
->value
<< "\n" << dec
;
ListIterator
<FieldType
> iter(®Type
->fieldTypes
);
for (FieldType
*fieldType
= iter
.getHeadItem();
fieldType
= iter
.getNextItem()) {
Data v
= (regState
->value
>> fieldType
->start
) & fieldType
->fieldMask
;
string s
= fieldType
->getAccessType();
os
<< "\t" << getFullName() << "." << fieldType
->getBaseName()
<< " (" << dec
<< fieldType
->end
<< ":" << fieldType
->start
<< ") = 0x" << hex
<< v
<< " (" << s
<< ")\n" << dec
;
void Register::resetThis ()
regType
->check(getFullName());
regState
->value
= regType
->resetValue
;
regInfo
->assigned
= (regType
->resetAssigned
!= 0);
void Register::signThis (ofstream
&ofs
)
regType
->check(getFullName());
mySignature
= new Signature
;
mySignature
->add(new SignData(getFullName(), "", ®State
->value
));
mySignature
->sign(ofs
, getBaseName(), "Register");
void Register::traceThis (ofstream
&ofs
)
if (mySignature
&& !regInfo
->clean
) {
mySignature
->printThis(ofs
);
FieldType::FieldType (string f
, string n
, RegisterType
*r
, AccessType a
,
uint e
, uint s
, bool b
, Data d
)
assert(a
== Access_RO
|| a
== Access_RW
|| a
== Access_RC
||
a
== Access_RW1C
|| a
== Access_RW1S
||
a
== Access_RCW1C
|| a
== Access_RCW1S
||
a
== Access_WO
|| a
== Access_L
);
d
= b
? d
: (UNDEFINED_DATA
>> s
);
cerr
<< "WARNING: Register field " << f
<< "." << n
<< "[" << e
<< ":" << s
<< "]"
<< " has inverted field positions\n";
cerr
<< "WARNING: Register field " << f
<< "." << n
<< "[" << e
<< ":" << s
<< "]"
<< " has out of range end position\n";
assert(s
<= e
&& e
< r
->widthBits
);
regMask
= - (Data(1) << s
);
regMask
= (Data(1) << (e
+1)) - (Data(1) << s
);
fieldMask
= regMask
>> s
;
resetValue
= d
& fieldMask
;
regType
->fieldTypes
.addTail(this);
regType
->resetValue
= (regType
->resetValue
& ~regMask
) |
regType
->resetAssigned
|= regMask
;
regType
->checkMask
|= regMask
;
// cerr << "reg " << n << " field " << f << " s " << s << " e " << e << " chk " << hex << regType->checkMask << " width " << regType->widthMask << endl;
if (a
== Access_RW1C
|| a
== Access_RCW1C
)
regType
->writeOneToClearMask
|= regMask
;
else if (a
== Access_RW1S
|| a
== Access_RCW1S
)
regType
->writeOneToSetMask
|= regMask
;
regType
->writeMask
|= regMask
;
regType
->readAsUndefinedMask
|= regMask
;
regType
->readAsZeroMask
|= regMask
;
regType
->readMask
|= regMask
;
if (a
== Access_RC
|| a
== Access_RCW1C
|| a
== Access_RCW1S
)
regType
->readToClearMask
|= regMask
;
string
FieldType::getAccessType () const
case Access_RC
: return "RC";
case Access_RO
: return "RO";
case Access_RW
: return "R/W";
case Access_RW1C
: return "R/W1C";
case Access_RW1S
: return "R/W1S";
case Access_RCW1C
: return "RC/W1C";
case Access_RCW1S
: return "RC/W1S";
case Access_WO
: return "WO";
case Access_L
: return "L";
default: assert(0); return "";
bool FieldType::overlap (FieldType
*f
)
return (regMask
& f
->regMask
) != 0;
void FieldType::check (RegisterType
*r
, string n
)
ListIterator
<FieldType
> iter(&r
->fieldTypes
);
for (FieldType
*fieldType
= iter
.getHeadItem();
fieldType
= iter
.getNextItem()) {
if (fieldType
!= this && overlap(fieldType
)) {
cerr
<< "WARNING: Register field " << n
<< "[" << end
<< ":" << start
<< "]"
<< " overlaps with existing field "
<< fieldType
->getBaseName() << "\n";
if (ASSERT_REGISTER_ERRORS
)
Field::Field (string n
, Register
*r
, AccessType a
,
uint e
, uint s
, bool b
, Data d
)
fieldType
= new FieldType(r
->getFullName(), n
, r
->regType
, a
, e
, s
, b
, d
);
fieldType
->check(r
->regType
, getFullName());
Field::Field (const Field
&f
)
Field
&Field::operator= (const Field
&f
)
string
Field::getBaseName() const
return fieldType
->getBaseName();
string
Field::getFullName() const
return reg
->getFullName() + "." + getBaseName();