Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / common / regdef / RegisterArray.cc
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: RegisterArray.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 <iostream>
#include <stdlib.h>
#include <assert.h>
#include "Object.h"
#include "RegisterArray.h"
#include "Signature.h"
using namespace std;
RegisterArray::RegisterArray (string n, Block *b, Addr a, uint c,
Addr s, uint w) :
valueR(n, NULL, a, w)
{
assert(b != NULL);
assert(w == 1 || w == 2 || w == 4 || w == 8);
assert((a % w) == 0);
assert(c > 0);
assert(s > 0 && (s % w) == 0);
baseName = n;
fullName = b->getFullName() + "." + n;
block = b;
startAddr = a;
endAddr = a + (c - 1) * s;
count = c;
step = s;
regType = NULL; // no RegisterType yet
regState = new RegisterState[count]; // undefined value
regInfo = new RegisterInfo[count]; // unassigned and dirty
mySignature = NULL; // allocated lazily
reinitRegister(&valueR);
b->addRegisterArray(this);
}
RegisterArray::~RegisterArray ()
{
delete regType;
delete[] regState;
delete[] regInfo;
if (mySignature) {
for (uint i=0; i<count; i++)
delete mySignature[i];
delete[] mySignature;
}
}
void RegisterArray::printThis (ostream &os)
{
assert(regType != NULL);
os << getFullName() << " (0x" << hex << startAddr << " to 0x" << endAddr
<< ", count " << dec << count << ", step 0x" << hex << step
<< ", width " << dec << regType->widthBytes << " bytes)\n" << dec;
if (isSmall()) {
for (uint index=0; index<count; index++) {
Register *reg = &(*this)[index];
reg->printThis(os);
}
}
}
void RegisterArray::resetThis ()
{
assert(regType != NULL);
regType->check(getFullName());
if (regType->resetValue == 0)
memset(regState, 0, sizeof(RegisterState) * count);
else
for (uint index=0; index<count; index++)
regState[index].value = regType->resetValue;
if (regType->resetAssigned == 0)
memset(regInfo, 0, sizeof(RegisterInfo) * count);
else
for (uint index=0; index<count; index++) {
regInfo[index].assigned = (regType->resetAssigned != 0);
regInfo[index].clean = false;
}
}
void RegisterArray::signThis (ofstream &ofs)
{
assert(regType != NULL);
regType->check(getFullName());
if (mySignature == NULL) {
mySignature = new Signature*[count];
for (uint i=0; i<count; i++) {
mySignature[i] = NULL;
}
}
Signature::signScopeBegin(ofs, getFullName());
for (uint index=0; index<count; index++) {
ostringstream o;
o << index;
string s = "[" + o.str() + "]";
string n = getBaseName() + s;
string f = getFullName() + s;
mySignature[index] = new Signature;
mySignature[index]->add(new SignData(f, "", &regState[index].value));
mySignature[index]->sign(ofs, n, "Register");
}
Signature::signScopeClose(ofs, getFullName());
}
void RegisterArray::traceThis (ofstream &ofs)
{
for (uint index=0; index<count; index++) {
if (mySignature && mySignature[index] && !regInfo[index].clean) {
mySignature[index]->printThis(ofs);
regInfo[index].clean = true;
}
}
}
bool RegisterArray::lookup (Addr a, uint *i)
{
if (a >= startAddr &&
a <= endAddr &&
(a - startAddr) % step == 0) {
uint64 index = (a - startAddr) / step;
assert(index < count);
if (i != NULL)
*i = uint(index);
return true;
}
else
return false;
}
Register &RegisterArray::operator[] (uint index)
{
bindRegisterToIndex(&valueR, index);
return valueR; // return Register value by reference
}
void RegisterArray::reinitRegister (Register *r)
{
assert(r != NULL);
assert(r->regType != NULL);
if (regType != NULL)
delete regType;
regType = r->regType; // set array regType to instance regType
delete r->regInfo; // clear out register pointers
delete r->regState;
r->regInfo = NULL;
r->regState = NULL;
r->derived = true; // do not delete dynamic state in ~Register
}
void RegisterArray::bindRegisterToIndex (Register *r, uint index)
{
assert(regType != NULL);
assert(index < count);
Signature *signature = NULL;
if (mySignature != NULL)
signature = mySignature[index];
r->init(block, startAddr + step * index, true, index,
regType, &regState[index], &regInfo[index], signature);
}