| 1 | // ========== Copyright Header Begin ========================================== |
| 2 | // |
| 3 | // OpenSPARC T2 Processor File: Register.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 <iostream> |
| 22 | #include <stdlib.h> |
| 23 | #include <assert.h> |
| 24 | #include "Object.h" |
| 25 | #include "Register.h" |
| 26 | #include "Signature.h" |
| 27 | using namespace std; |
| 28 | |
| 29 | static const bool ASSERT_REGISTER_ERRORS = false; |
| 30 | |
| 31 | RegisterType::RegisterType (uint w) |
| 32 | { |
| 33 | assert(w == 1 || w == 2 || w == 4 || w == 8); |
| 34 | widthBytes = w; |
| 35 | widthBits = w << 3; |
| 36 | widthMask = (widthBits == 64) ? ~Data(0) : (Data(1) << widthBits) - 1; |
| 37 | checkMask = 0; |
| 38 | writeMask = 0; |
| 39 | writeOneToClearMask = 0; |
| 40 | writeOneToSetMask = 0; |
| 41 | readMask = 0; |
| 42 | readAsUndefinedMask = 0; |
| 43 | readAsZeroMask = 0; |
| 44 | readToClearMask = 0; |
| 45 | resetValue = UNDEFINED_DATA & widthMask; |
| 46 | resetAssigned = 0; |
| 47 | writeBlockCB = false; |
| 48 | readBlockCB = false; |
| 49 | } |
| 50 | |
| 51 | void RegisterType::check (string n) |
| 52 | { |
| 53 | // cerr << hex << "check " << n << " " << checkMask << " " << widthMask << " " << endl; |
| 54 | if (checkMask != widthMask) { |
| 55 | assert((checkMask & ~widthMask) == 0); |
| 56 | int errors = 0; |
| 57 | for (uint i=0; i<widthBits; i++) { |
| 58 | if ((checkMask & (1ULL << i)) == 0) { |
| 59 | int start = i; |
| 60 | for (i++; i<widthBits; i++) { |
| 61 | if ((checkMask & (1ULL << i)) != 0) |
| 62 | break; |
| 63 | } |
| 64 | int end = i-1; |
| 65 | cerr << "WARNING: Register bits " << n |
| 66 | << "[" << end << ":" << start << "]" |
| 67 | << " do not belong to any field\n"; |
| 68 | errors++; |
| 69 | } |
| 70 | } |
| 71 | if (ASSERT_REGISTER_ERRORS) |
| 72 | assert(errors == 0); |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | Register::Register () |
| 77 | { |
| 78 | baseName = ""; |
| 79 | block = NULL; |
| 80 | addr = 0; |
| 81 | derived = false; |
| 82 | element = false; |
| 83 | index = 0; |
| 84 | regType = NULL; |
| 85 | regState = NULL; |
| 86 | regInfo = NULL; |
| 87 | mySignature = NULL; |
| 88 | } |
| 89 | |
| 90 | Register::Register (string n, Block *b, Addr a, uint w) |
| 91 | { |
| 92 | baseName = n; |
| 93 | block = b; |
| 94 | addr = a; |
| 95 | derived = false; |
| 96 | element = false; |
| 97 | index = 0; |
| 98 | regType = new RegisterType(w); |
| 99 | regState = new RegisterState(UNDEFINED_DATA); // undefined value |
| 100 | regInfo = new RegisterInfo(false, false); // unassigned and dirty |
| 101 | mySignature = NULL; |
| 102 | |
| 103 | // cerr << "REG " << n << hex << " chk " << regType->checkMask << " width " << regType->widthMask << endl; |
| 104 | |
| 105 | if (b != NULL) { |
| 106 | // The address is only used/checked when the Register has a Block |
| 107 | assert((a % regType->widthBytes) == 0); |
| 108 | b->addRegister(this); |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | Register::Register (const Register &r) |
| 113 | { |
| 114 | baseName = r.baseName; |
| 115 | block = r.block; |
| 116 | addr = r.addr; |
| 117 | derived = true; |
| 118 | element = r.element; |
| 119 | index = r.index; |
| 120 | regType = r.regType; |
| 121 | regState = r.regState; |
| 122 | regInfo = r.regInfo; |
| 123 | mySignature = r.mySignature; |
| 124 | } |
| 125 | |
| 126 | Register::~Register () |
| 127 | { |
| 128 | if (!derived) { |
| 129 | delete regType; |
| 130 | delete regState; |
| 131 | delete regInfo; |
| 132 | delete mySignature; |
| 133 | } |
| 134 | } |
| 135 | |
| 136 | void Register::init (Block *b, Addr a, bool e, uint i, RegisterType *rt, |
| 137 | RegisterState *rs, RegisterInfo *ri, Signature *s) |
| 138 | { |
| 139 | assert(rt != NULL && rs != NULL && ri != NULL); |
| 140 | assert((a % rt->widthBytes) == 0); |
| 141 | |
| 142 | block = b; |
| 143 | addr = a; |
| 144 | derived = true; |
| 145 | element = e; |
| 146 | index = i; |
| 147 | regType = rt; |
| 148 | regState = rs; |
| 149 | regInfo = ri; |
| 150 | mySignature = s; |
| 151 | } |
| 152 | |
| 153 | Register &Register::operator= (const Register &r) |
| 154 | { |
| 155 | if (this != &r) { |
| 156 | if (!derived) { |
| 157 | delete regType; |
| 158 | delete regState; |
| 159 | delete regInfo; |
| 160 | delete mySignature; |
| 161 | } |
| 162 | |
| 163 | baseName = r.baseName; |
| 164 | block = r.block; |
| 165 | addr = r.addr; |
| 166 | derived = true; |
| 167 | element = r.element; |
| 168 | index = r.index; |
| 169 | regType = r.regType; |
| 170 | regState = r.regState; |
| 171 | regInfo = r.regInfo; |
| 172 | mySignature = r.mySignature; |
| 173 | } |
| 174 | return *this; |
| 175 | } |
| 176 | |
| 177 | string Register::getBaseName() const |
| 178 | { |
| 179 | if (element) { |
| 180 | ostringstream o; |
| 181 | o << index; |
| 182 | return baseName + "[" + o.str() + "]"; |
| 183 | } |
| 184 | else |
| 185 | return baseName; |
| 186 | } |
| 187 | |
| 188 | string Register::getFullName() const |
| 189 | { |
| 190 | return (block == NULL) ? getBaseName() |
| 191 | : block->getFullName() + "." + getBaseName(); |
| 192 | } |
| 193 | |
| 194 | void Register::printThis (ostream &os) |
| 195 | { |
| 196 | os << getFullName() << " (0x" << hex << addr |
| 197 | << ", width " << dec << regType->widthBytes << " bytes) = 0x" |
| 198 | << hex << regState->value << "\n" << dec; |
| 199 | |
| 200 | ListIterator<FieldType> iter(®Type->fieldTypes); |
| 201 | |
| 202 | for (FieldType *fieldType = iter.getHeadItem(); |
| 203 | fieldType != NULL; |
| 204 | fieldType = iter.getNextItem()) { |
| 205 | |
| 206 | Data v = (regState->value >> fieldType->start) & fieldType->fieldMask; |
| 207 | string s = fieldType->getAccessType(); |
| 208 | |
| 209 | if ( v != 0 ) |
| 210 | os << "\t" << getFullName() << "." << fieldType->getBaseName() |
| 211 | << " (" << dec << fieldType->end << ":" << fieldType->start |
| 212 | << ") = 0x" << hex << v << " (" << s << ")\n" << dec; |
| 213 | } |
| 214 | } |
| 215 | |
| 216 | void Register::resetThis () |
| 217 | { |
| 218 | regType->check(getFullName()); |
| 219 | regState->value = regType->resetValue; |
| 220 | regInfo->assigned = (regType->resetAssigned != 0); |
| 221 | regInfo->clean = false; |
| 222 | } |
| 223 | |
| 224 | void Register::signThis (ofstream &ofs) |
| 225 | { |
| 226 | regType->check(getFullName()); |
| 227 | mySignature = new Signature; |
| 228 | mySignature->add(new SignData(getFullName(), "", ®State->value)); |
| 229 | mySignature->sign(ofs, getBaseName(), "Register"); |
| 230 | } |
| 231 | |
| 232 | void Register::traceThis (ofstream &ofs) |
| 233 | { |
| 234 | if (mySignature && !regInfo->clean) { |
| 235 | mySignature->printThis(ofs); |
| 236 | regInfo->clean = true; |
| 237 | } |
| 238 | } |
| 239 | |
| 240 | FieldType::FieldType (string f, string n, RegisterType *r, AccessType a, |
| 241 | uint e, uint s, bool b, Data d) |
| 242 | { |
| 243 | assert(a == Access_RO || a == Access_RW || a == Access_RC || |
| 244 | a == Access_RW1C || a == Access_RW1S || |
| 245 | a == Access_RCW1C || a == Access_RCW1S || |
| 246 | a == Access_WO || a == Access_L); |
| 247 | |
| 248 | d = b ? d : (UNDEFINED_DATA >> s); |
| 249 | |
| 250 | baseName = n; |
| 251 | |
| 252 | if (s > e) { |
| 253 | cerr << "WARNING: Register field " << f << "." << n |
| 254 | << "[" << e << ":" << s << "]" |
| 255 | << " has inverted field positions\n"; |
| 256 | int t = e; |
| 257 | e = s; |
| 258 | s = t; |
| 259 | } |
| 260 | |
| 261 | if (e >= r->widthBits) { |
| 262 | cerr << "WARNING: Register field " << f << "." << n |
| 263 | << "[" << e << ":" << s << "]" |
| 264 | << " has out of range end position\n"; |
| 265 | e = r->widthBits - 1; |
| 266 | } |
| 267 | |
| 268 | assert(s <= e && e < r->widthBits); |
| 269 | |
| 270 | access = a; |
| 271 | start = s; |
| 272 | end = e; |
| 273 | |
| 274 | if (e == 63) |
| 275 | regMask = - (Data(1) << s); |
| 276 | else |
| 277 | regMask = (Data(1) << (e+1)) - (Data(1) << s); |
| 278 | fieldMask = regMask >> s; |
| 279 | resetValue = d & fieldMask; |
| 280 | |
| 281 | regType = r; |
| 282 | regType->fieldTypes.addTail(this); |
| 283 | |
| 284 | regType->resetValue = (regType->resetValue & ~regMask) | |
| 285 | (resetValue << start); |
| 286 | |
| 287 | if (b) |
| 288 | regType->resetAssigned |= regMask; |
| 289 | |
| 290 | regType->checkMask |= regMask; |
| 291 | |
| 292 | // cerr << "reg " << n << " field " << f << " s " << s << " e " << e << " chk " << hex << regType->checkMask << " width " << regType->widthMask << endl; |
| 293 | |
| 294 | if (a == Access_RW1C || a == Access_RCW1C) |
| 295 | regType->writeOneToClearMask |= regMask; |
| 296 | else if (a == Access_RW1S || a == Access_RCW1S) |
| 297 | regType->writeOneToSetMask |= regMask; |
| 298 | else if (a != Access_RO) |
| 299 | regType->writeMask |= regMask; |
| 300 | |
| 301 | if (a == Access_WO) |
| 302 | regType->readAsUndefinedMask |= regMask; |
| 303 | else if (a == Access_L) |
| 304 | regType->readAsZeroMask |= regMask; |
| 305 | else |
| 306 | regType->readMask |= regMask; |
| 307 | |
| 308 | if (a == Access_RC || a == Access_RCW1C || a == Access_RCW1S) |
| 309 | regType->readToClearMask |= regMask; |
| 310 | } |
| 311 | |
| 312 | string FieldType::getAccessType () const |
| 313 | { |
| 314 | switch (access) { |
| 315 | case Access_RC: return "RC"; |
| 316 | case Access_RO: return "RO"; |
| 317 | case Access_RW: return "R/W"; |
| 318 | case Access_RW1C: return "R/W1C"; |
| 319 | case Access_RW1S: return "R/W1S"; |
| 320 | case Access_RCW1C: return "RC/W1C"; |
| 321 | case Access_RCW1S: return "RC/W1S"; |
| 322 | case Access_WO: return "WO"; |
| 323 | case Access_L: return "L"; |
| 324 | default: assert(0); return ""; |
| 325 | } |
| 326 | } |
| 327 | |
| 328 | bool FieldType::overlap (FieldType *f) |
| 329 | { |
| 330 | return (regMask & f->regMask) != 0; |
| 331 | } |
| 332 | |
| 333 | void FieldType::check (RegisterType *r, string n) |
| 334 | { |
| 335 | int errors = 0; |
| 336 | ListIterator<FieldType> iter(&r->fieldTypes); |
| 337 | for (FieldType *fieldType = iter.getHeadItem(); |
| 338 | fieldType != NULL; |
| 339 | fieldType = iter.getNextItem()) { |
| 340 | if (fieldType != this && overlap(fieldType)) { |
| 341 | cerr << "WARNING: Register field " << n |
| 342 | << "[" << end << ":" << start << "]" |
| 343 | << " overlaps with existing field " |
| 344 | << fieldType->getBaseName() << "\n"; |
| 345 | errors++; |
| 346 | } |
| 347 | } |
| 348 | if (ASSERT_REGISTER_ERRORS) |
| 349 | assert(errors == 0); |
| 350 | } |
| 351 | |
| 352 | Field::Field () |
| 353 | { |
| 354 | derived = false; |
| 355 | reg = NULL; |
| 356 | fieldType = NULL; |
| 357 | } |
| 358 | |
| 359 | Field::Field (string n, Register *r, AccessType a, |
| 360 | uint e, uint s, bool b, Data d) |
| 361 | { |
| 362 | assert(r != NULL); |
| 363 | derived = false; |
| 364 | reg = r; |
| 365 | fieldType = new FieldType(r->getFullName(), n, r->regType, a, e, s, b, d); |
| 366 | fieldType->check(r->regType, getFullName()); |
| 367 | } |
| 368 | |
| 369 | Field::Field (const Field &f) |
| 370 | { |
| 371 | derived = true; |
| 372 | reg = f.reg; |
| 373 | fieldType = f.fieldType; |
| 374 | } |
| 375 | |
| 376 | Field::~Field () |
| 377 | { |
| 378 | if (!derived) |
| 379 | delete fieldType; |
| 380 | } |
| 381 | |
| 382 | Field &Field::operator= (const Field &f) |
| 383 | { |
| 384 | if (this != &f) { |
| 385 | if (!derived) |
| 386 | delete fieldType; |
| 387 | |
| 388 | derived = true; |
| 389 | reg = f.reg; |
| 390 | fieldType = f.fieldType; |
| 391 | } |
| 392 | return *this; |
| 393 | } |
| 394 | |
| 395 | string Field::getBaseName() const |
| 396 | { |
| 397 | return fieldType->getBaseName(); |
| 398 | } |
| 399 | |
| 400 | string Field::getFullName() const |
| 401 | { |
| 402 | return reg->getFullName() + "." + getBaseName(); |
| 403 | ; |
| 404 | } |