Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / common / csr_common.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: csr_common.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/*
22 * Copyright (c) 2003-2004 by Sun Microsystems, Inc.
23 * All rights reserved.
24 */
25
26#include "csr_common.h"
27#include "string.h"
28#include "assert.h"
29
30/*******************************************************************************
31 * csr_get_reg
32 *
33 * Given a register's offset, find the register in the given list of
34 * registers. If it does not exist, create it and insert it in the
35 * list.
36 */
37csr_reg_t *
38common_csr::csr_get_reg (csr_reg_t **csr_list, uint64_t offset,csrtab_t *csrtab,csr_field_t *csr_fields,uint64_t *cumsum)
39{
40 return csr_get_regtype(csr_list, csr_offset2reg(offset),csrtab,csr_fields,cumsum);
41
42} /* csr_get_reg */
43
44/*******************************************************************************
45 * csr_get_regtype
46 *
47 * Given a register's type, find the register in the given list of
48 * registers. If it does not exist, create it and insert it in the
49 * list.
50 */
51csr_reg_t *
52common_csr::csr_get_regtype (csr_reg_t **csr_list, csr_reg_type_t reg_type,csrtab_t *csrtab,csr_field_t *csr_fields,uint64_t *cumsum)
53{
54 csr_reg_t *p=NULL, **pb=NULL, *new_csr=NULL;
55 assert(csr_list);
56
57 for (pb = csr_list; (p = *pb) != NULL; pb = (csr_reg_t **)&p->next)
58 if (reg_type <= p->reg_type)
59 break;
60
61 if (p && reg_type == p->reg_type)
62 return p;
63
64 new_csr = (csr_reg_t *)new csr_reg_t;
65
66 init_csr_reg (new_csr, reg_type,csrtab,csr_fields,cumsum);
67
68 new_csr->next = p;
69 *pb = new_csr;
70
71 return new_csr;
72
73
74} /* csr_get_regtype */
75
76/*******************************************************************************
77 * csr_read_reg
78 *
79 * Read csr from its storage object
80 */
81int
82common_csr::csr_read_reg (Module *csr_obj, csr_reg_t *csr_reg, uint64_t offset,
83 uint64_t *value)
84{
85 int idx = (int)((offset - csr_reg->offset) / 8);
86 if(idx >=0){
87 if(csr_obj){
88 csr_obj->debug_more("%s: csr_read_reg:%s value:%016llx\n",csr_obj->getName(), csr_reg->name,csr_reg->value[idx]);
89 }
90 *value = csr_reg->value[idx];
91 return TRUE;
92 }
93 csr_obj->debug_err("%s:csr_read_reg :%s invalid offset:%016llx\n",csr_obj->getName(), csr_reg->name,offset);
94 return FALSE;
95} /* csr_read_reg */
96
97/*******************************************************************************
98 * csr_write_reg
99 *
100 * Write csr to its storage object
101 */
102int
103common_csr::csr_write_reg (Module *csr_obj, csr_reg_t *csr_reg, uint64_t offset,
104 uint64_t reg_value)
105{
106 int idx = (int)((offset - csr_reg->offset) / 8);
107 if(idx >= 0){
108 csr_reg->value[idx] = reg_value;
109
110 if(csr_obj){
111 csr_obj->debug_more("%s:csr_write_reg :%s value:%016llx\n",csr_obj->getName(), csr_reg->name,reg_value);
112 }
113 return TRUE;
114 }
115 csr_obj->debug_err("%s:csr_write_reg :%s invalid offset:%016llx\n",csr_obj->getName(), csr_reg->name,offset);
116 return FALSE;
117} /* csr_write_reg */
118
119/*******************************************************************************
120 * csr_get_field
121 *
122 * Given a register's field name, extract its value
123 */
124uint64_t
125common_csr::csr_get_field(Module *csr_obj, csr_reg_t *csr_reg, const char *field_name,
126 uint64_t offset)
127{
128 int i;
129 uint64_t reg_value = 0;
130
131 csr_read_reg(csr_obj, csr_reg, offset, &reg_value);
132
133 for (i = 0; i < csr_reg->num_fields; i++) {
134 if (!strcmp(csr_reg->fields[i].name, field_name)) {
135 uint64_t mask;
136
137 mask = LWord(-1) >>
138 (63 - (csr_reg->fields[i].l - csr_reg->fields[i].r));
139
140 reg_value >>= csr_reg->fields[i].r;
141 reg_value &= mask;
142
143 if (csr_obj)
144 csr_obj->debug_more("%s:Get field %s.%s: 0x%llx\n", csr_obj->getName(),csr_reg->name, field_name, reg_value);
145 return reg_value;
146 }
147 }
148 if (csr_obj)
149 csr_obj->debug_err("%s:unknown field '%s' in register '%s'\n",csr_obj->getName(),field_name, csr_reg->name);
150 return 0;
151
152} /* csr_get_field */
153
154/*******************************************************************************
155 * csr_set_field
156 *
157 * Given a register's field name, set its value
158 */
159uint64_t
160common_csr::csr_set_field(Module *csr_obj, csr_reg_t *csr_reg, const char *field_name ,
161 uint64_t field_value, uint64_t offset)
162{
163 int i;
164 uint64_t reg_value = 0;
165
166 csr_read_reg(csr_obj, csr_reg, offset, &reg_value);
167
168 for (i = 0; i < csr_reg->num_fields; i++) {
169 if (!strcmp(csr_reg->fields[i].name, field_name)) {
170 uint64_t maskl =
171 LWord(-1) >> (63 - csr_reg->fields[i].l);
172 uint64_t maskr =
173 LWord(-1) << (csr_reg->fields[i].r);
174 uint64_t mask = maskl & maskr;
175
176 if (csr_obj)
177 csr_obj->debug_more("%s:Set field %s.%s: 0x%llx\n",csr_obj->getName(),csr_reg->name, field_name, field_value);
178
179 field_value <<= csr_reg->fields[i].r;
180 field_value &= mask;
181
182 reg_value &= ~mask;
183 reg_value |= field_value;
184
185 csr_write_reg(csr_obj, csr_reg, offset, reg_value);
186 return reg_value;
187 }
188 }
189
190 if (csr_obj)
191 csr_obj->debug_err("%s:unknown field '%s' in register '%s'\n",csr_obj->getName(), field_name, csr_reg->name);
192
193 return reg_value;
194
195} /* csr_set_field */
196
197/*******************************************************************************
198 * csr_get_reg_by_name
199 * Given a register's name, get its regtype
200 * Return -1 if not found.
201 */
202csr_reg_type_t
203common_csr::csr_get_reg_by_name(char *regname,csrtab_t *csrtab,uint64_t ncsrtab)
204{
205 int64_t i;
206
207 for (i = ncsrtab; 0 <= --i; )
208 if (!strcmp(regname, csrtab[i].name))
209 return csrtab[i].type;
210
211 return (csr_reg_type_t)(-1);
212
213} /* csr_get_reg_by_name */
214
215/*
216 * csr_value_get_field
217 *
218 * Side-effect free way to extract a value of a register's field. csr_reg must
219 * point to a valid register object, but its value will be ignored: instead,
220 * 'reg_value' will be used.
221 */
222uint64_t
223common_csr::csr_value_get_field(Module *csr_obj, csr_reg_t *csr_reg,
224 const char *field_name, uint64_t reg_value)
225{
226 int i;
227 for (i = 0; i < csr_reg->num_fields; i++) {
228 if (!strcmp(csr_reg->fields[i].name, field_name)) {
229 uint64_t mask;
230
231 mask = LWord(-1) >>
232 (63 - (csr_reg->fields[i].l - csr_reg->fields[i].r));
233
234 reg_value >>= csr_reg->fields[i].r;
235 reg_value &= mask;
236
237 if(csr_obj){
238 csr_obj->debug_more("%s:Get field %s.%s: 0x%llx\n",csr_obj->getName(),csr_reg->name, field_name, reg_value);
239 }
240
241 return reg_value;
242 }
243 }
244
245 if(csr_obj){
246 csr_obj->debug_err("%s:unknown field '%s' in register '%s'\n", csr_obj->getName(),field_name, csr_reg->name);
247 }
248
249 return 0;
250}
251
252/*
253 * csr_field_changed
254 *
255 * Returns true if the field specified by 'field_name' for the given register
256 * object has changed values between 'reg_value1' and 'reg_value2'
257 */
258int
259common_csr::csr_field_changed(Module *csr_obj, csr_reg_t *csr_reg,
260 const char *field_name,
261 uint64_t reg_value1, uint64_t reg_value2)
262{
263 uint64_t first, second;
264
265 first = csr_value_get_field(csr_obj, csr_reg, field_name, reg_value1);
266 second = csr_value_get_field(csr_obj, csr_reg, field_name, reg_value2);
267
268 return first != second;
269}
270
271
272/*******************************************************************************
273 * csr_get_field_name
274 *
275 * Given 'csr_reg' and 'reg_value', check the field at the given 'bit' position
276 * and return the field name if that bit field is set.
277 */
278const char *
279common_csr::csr_get_field_name(Module *csr_obj, csr_reg_t *csr_reg, int bit, uint64_t reg_value)
280{
281 uint64_t mask, bit_value;
282 const char *name = NULL;
283
284 mask = LWord(-1) >>
285 (63 - (csr_reg->fields[bit].l - csr_reg->fields[bit].r));
286
287 bit_value = (reg_value >> csr_reg->fields[bit].r) & mask;
288
289 if (bit_value) {
290 name = csr_reg->fields[bit].name;
291
292 if (csr_obj)
293 csr_obj->debug_more("%s:Get field name %s.%s: 0x%llx\n",csr_obj->getName(),csr_reg->name, name, reg_value);
294 }
295
296 return name;
297
298} /* csr_get_field_name*/
299
300/*******************************************************************************
301 * csr_reset_reg
302 *
303 * Write the csr reset value to its storage object
304 */
305bool
306common_csr::csr_reset_reg(Module *csr_obj, csr_reg_t **csr_list,uint64_t value, csr_reg_type_t type,csrtab_t *csrtab,csr_field_t *csr_fields,uint64_t *cumsum, uint64_t offset)
307{
308 bool rc = FALSE;
309 csr_reg_t *csr_reg;
310
311 csr_reg = csr_get_regtype(csr_list, type,csrtab,csr_fields,cumsum);
312 rc = csr_write_reg(csr_obj, csr_reg, offset, value);
313
314 return rc;
315
316} /* csr_reset_reg */
317
318
319/*******************************************************************************
320 * csr_write_mask_reg
321 *
322 * This function operates on a pair of aliased CSRs whose types are indicated
323 * by the input value of the last three arguments either as
324 *
325 * case A: (rw1c, rw1s, 0)
326 * or
327 * case B: (rw1c, 0, rw)
328 *
329 * For either case, it computes the new value of the given aliased register
330 * csr_reg whose type is one of the rw1c, rw1c and rw, and updates both the
331 * aliased registers. The purpose is to keep the stored csr value of the pair
332 * in sync so either one can be used for the corresponding read op).
333 */
334bool
335common_csr::csr_write_mask_reg(Module *csr_obj, csr_reg_t **csr_list,csr_reg_type_t type,csrtab_t *csrtab,csr_field_t *csr_fields,uint64_t *cumsum,uint64_t old_value, uint64_t *new_value, csr_reg_type_t rw1c, csr_reg_type_t rw1s, csr_reg_type_t rw, uint64_t offset)
336{
337 csr_reg_t *csr_reg_alias;
338 bool rc = FALSE;
339
340 if (type == rw1c) {
341 *new_value = old_value & ~*new_value;
342
343 csr_reg_alias = csr_get_regtype(csr_list, rw1s ? rw1s : rw,csrtab,csr_fields,cumsum);
344 }
345 else {
346 if (type == rw1s)
347 *new_value = old_value | *new_value;
348
349 csr_reg_alias = csr_get_regtype(csr_list, rw1c,csrtab,csr_fields,cumsum);
350 }
351
352 assert(csr_reg_alias->depth == 1);
353 rc = csr_write_reg(csr_obj, csr_reg_alias, csr_reg_alias->offset, *new_value);
354
355 // update the actual register as well.
356 csr_reg_t * csr_reg = csr_get_regtype(csr_list,type,csrtab,csr_fields,cumsum);
357 rc |= csr_write_reg(csr_obj,csr_reg,csr_reg->offset, *new_value);
358
359 return rc;
360
361} /* csr_write_mask_reg */
362
363
364
365/*******************************************************************************
366 * csr_set_mask_field
367 *
368 * This function operates on a pair of aliased CSR 'csr_reg' of type
369 *
370 * ('rw1c', 'rw').
371 *
372 * Given the 'field_name' and 'field_value', it computes the new value of the
373 * given CSR 'csr_reg' in terms of its type (either rw1c or rw), and stores
374 * the new value in the storage for both CSRs. The purpose is to keep the
375 * stored csr value of the pair in sync so either one can be used for the
376 * corresponding read op.
377 */
378bool
379common_csr::csr_set_mask_field(Module *csr_obj,csr_reg_t **csr_list,csrtab_t *csrtab,csr_field_t *csr_fields,uint64_t *cumsum,csr_reg_t *csr_reg,const char *field_name,uint64_t field_value, csr_reg_type_t rw1c, csr_reg_type_t rw, uint64_t offset)
380{
381 int i;
382 uint64_t old_value = 0, new_value;
383 bool rc = FALSE;
384
385 /* read the old value in csr_reg */
386// csr_read_reg(csr_obj, csr_reg, offset, &old_value);
387
388 csr_reg_t* csr_rw1c = csr_get_regtype(csr_list,rw1c,csrtab,csr_fields,cumsum);
389 csr_set_field(csr_obj,csr_rw1c,field_name,field_value,csr_rw1c->offset);
390 csr_reg_t* csr_rw = csr_get_regtype(csr_list,rw,csrtab,csr_fields,cumsum);
391 csr_set_field(csr_obj,csr_rw,field_name,field_value,csr_rw->offset);
392
393 /* left shift the field_value to a 64 bit value */
394/* for (i = 0; i < csr_reg->num_fields; i++) {
395 if (!strcmp(csr_reg->fields[i].name, field_name)) {
396 uint64_t maskl =
397 UINT64_C(-1) >> (63 - csr_reg->fields[i].l);
398 uint64_t maskr =
399 UINT64_C(-1) << (csr_reg->fields[i].r);
400 uint64_t mask = maskl & maskr;
401
402 new_value = field_value << csr_reg->fields[i].r;
403 new_value &= mask;
404 break;
405 }
406 }
407*/
408 /*
409 * computes the new_value of the given register 'csr_reg' and update
410 * the other aliased register
411 */
412// rc = csr_write_mask_reg(csr_obj, csr_list,csr_reg->reg_type,csrtab,csr_fields,cumsum,old_value,&new_value, rw1c, 0, rw, offset);
413
414 /*
415 * finally update the given register with the new_value
416 */
417 //rc = csr_write_reg(csr_obj, csr_reg, offset, new_value);
418
419 if (csr_obj){
420 csr_obj->debug_more("%s:csr_set_mask_field:Set field '%s' in register '%s','%s'\n", csr_obj->getName() ,field_name, csr_rw->name,csr_rw1c->name);
421 }
422
423 return rc;
424
425} /* csr_set_mask_field */
426
427void
428common_csr::init_csr_reg (csr_reg_t *csr_reg, csr_reg_type_t reg_type,csrtab_t *csrtab,csr_field_t *csr_fields, uint64_t *cumsum) {
429
430 int i;
431 /* initialize the structure */
432 csr_reg->reg_type = reg_type;
433 csr_reg->name = csrtab[reg_type].name;
434 csr_reg->offset = csrtab[reg_type].offset;
435 csr_reg->read_mask = csrtab[reg_type].read_mask;
436 csr_reg->read_only_mask = csrtab[reg_type].read_only_mask;
437 csr_reg->write_mask = csrtab[reg_type].write_mask;
438 csr_reg->write_only_mask = csrtab[reg_type].write_only_mask;
439 csr_reg->clear_mask = csrtab[reg_type].clear_mask;
440 csr_reg->set_mask = csrtab[reg_type].set_mask;
441 csr_reg->power_on_reset = csrtab[reg_type].power_on_reset;
442 csr_reg->depth = csrtab[reg_type].depth;
443 csr_reg->num_fields = csrtab[reg_type].num_fields;
444 csr_reg->value = (uint64_t *)new uint64_t[csrtab[reg_type].depth];
445 for(i=0; i<csrtab[reg_type].depth; i++) {
446 csr_reg->value[i] = csr_reg->power_on_reset;
447 }
448 csr_reg->fields = (csr_field_t *) new csr_field_t[(csrtab[reg_type].num_fields)];
449 for(i=0; i<csrtab[reg_type].num_fields; i++) {
450 csr_reg->fields[i].name = csr_fields[cumsum[reg_type]+i].name;
451 csr_reg->fields[i].l = csr_fields[cumsum[reg_type]+i].l;
452 csr_reg->fields[i].r = csr_fields[cumsum[reg_type]+i].r;
453 }
454 csr_reg->sp_access = csrtab[reg_type].sp_access;
455 csr_reg->jtag_access = csrtab[reg_type].jtag_access;
456 csr_reg->domain_access = csrtab[reg_type].domain_access;
457 csr_reg->next = NULL;
458
459} /* init_csr_reg */
460
461
462