Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / common / regdef / Register.cc
CommitLineData
920dae64
AT
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"
27using namespace std;
28
29static const bool ASSERT_REGISTER_ERRORS = false;
30
31RegisterType::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
51void 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
76Register::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
90Register::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
112Register::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
126Register::~Register ()
127{
128 if (!derived) {
129 delete regType;
130 delete regState;
131 delete regInfo;
132 delete mySignature;
133 }
134}
135
136void 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
153Register &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
177string 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
188string Register::getFullName() const
189{
190 return (block == NULL) ? getBaseName()
191 : block->getFullName() + "." + getBaseName();
192}
193
194void 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(&regType->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
216void Register::resetThis ()
217{
218 regType->check(getFullName());
219 regState->value = regType->resetValue;
220 regInfo->assigned = (regType->resetAssigned != 0);
221 regInfo->clean = false;
222}
223
224void Register::signThis (ofstream &ofs)
225{
226 regType->check(getFullName());
227 mySignature = new Signature;
228 mySignature->add(new SignData(getFullName(), "", &regState->value));
229 mySignature->sign(ofs, getBaseName(), "Register");
230}
231
232void Register::traceThis (ofstream &ofs)
233{
234 if (mySignature && !regInfo->clean) {
235 mySignature->printThis(ofs);
236 regInfo->clean = true;
237 }
238}
239
240FieldType::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
312string 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
328bool FieldType::overlap (FieldType *f)
329{
330 return (regMask & f->regMask) != 0;
331}
332
333void 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
352Field::Field ()
353{
354 derived = false;
355 reg = NULL;
356 fieldType = NULL;
357}
358
359Field::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
369Field::Field (const Field &f)
370{
371 derived = true;
372 reg = f.reg;
373 fieldType = f.fieldType;
374}
375
376Field::~Field ()
377{
378 if (!derived)
379 delete fieldType;
380}
381
382Field &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
395string Field::getBaseName() const
396{
397 return fieldType->getBaseName();
398}
399
400string Field::getFullName() const
401{
402 return reg->getFullName() + "." + getBaseName();
403;
404}