C++ Device API Reference Manual
Reference documentation for the Simics C++ Device API.
 
Loading...
Searching...
No Matches
field-templates.h
Go to the documentation of this file.
1// -*- mode: C++; c-file-style: "virtutech-c++" -*-
2
3/*
4 © 2022 Intel Corporation
5
6 This software and the related documents are Intel copyrighted materials, and
7 your use of them is governed by the express license under which they were
8 provided to you ("License"). Unless the License provides otherwise, you may
9 not use, modify, copy, publish, distribute, disclose or transmit this software
10 or the related documents without Intel's prior written permission.
11
12 This software and the related documents are provided as is, with no express or
13 implied warranties, other than those that are expressly stated in the License.
14*/
15
16#ifndef SIMICS_FIELD_TEMPLATES_H
17#define SIMICS_FIELD_TEMPLATES_H
18
19#include <fmt/fmt/format.h>
20
21#include <limits>
22#include <string>
23
24#include "simics/field.h"
25#include "simics/log.h"
27
28namespace simics {
29
30/*
31 * Field with map information
32 * This class creates a field object and add it to the <arg>reg_iface</arg>.
33 * Customized fields such as ReadConstantField takes additional arguments.
34 */
35template <typename TField = Field, typename... Args>
36class RegisterField : public TField {
37 static_assert(std::is_base_of<Field, TField>::value,
38 "TField must be derived from Field");
39 public:
41 Offset offset, BitWidth size, Args... args)
42 : TField(reg_iface, name, args ...) {
43 reg_iface->add_field(name, desc, offset, size);
44 }
45};
46
47// Templates
48// Writes are ignored.
49class IgnoreWriteField : public Field {
50 public:
51 using Field::Field;
52
53 void write(uint64_t value, uint64_t enabled_bits) override {}
54};
55
56// Reads return 0. Writes are unaffected by this template.
57class Read0Field : public Field {
58 public:
59 using Field::Field;
60
61 uint64_t read(uint64_t enabled_bits) override {
63 fmt::format("Read from read-zero field {} -> 0x0.",
64 name()));
65 return 0;
66 }
67};
68
69// Write only and reads return 0. Same as Read0Field thus derived from it.
70class WriteOnlyField : public Read0Field {
71 public:
72 using Read0Field::Read0Field;
73
74 uint64_t read(uint64_t enabled_bits) override {
76 fmt::format("Read from write-only field {} -> 0x0.",
77 name()));
78 return 0;
79 }
80};
81
82// The object value is read-only for software, the object value
83// can be modified by hardware.
84class ReadOnlyField : public Field {
85 public:
86 using Field::Field;
87
88 void write(uint64_t value, uint64_t enabled_bits) override {
89 if ((value & enabled_bits) != (get() & enabled_bits)) {
90 SIM_LOG_SPEC_VIOLATION_STR(logged_once_ ? 2 : 1, bank_obj_ref(), 0,
91 fmt::format("Write to read-only field {} (value written"
92 " = {:#010x}, contents = {:#010x}).",
93 name(), value & enabled_bits, get()));
94 logged_once_ = true;
95 }
96 }
97
98 private:
99 bool logged_once_ {false};
100};
101
102// Software can only clear bits. This feature is often used when
103// hardware sets bits and software clears them to acknowledge.
104// Software write 1's to clear bits. The new object value is a
105// bitwise AND of the old object value and the bitwise complement
106// of the value written by software.
107class Write1ClearsField : public Field {
108 public:
109 using Field::Field;
110
111 void write(uint64_t value, uint64_t enabled_bits) override {
112 Field::write(~value, enabled_bits & value);
113 }
114};
115
116// Software reads return the object value. The object value is
117// then reset to 0 as a side-effect of the read.
118class ClearOnReadField : public Field {
119 public:
120 using Field::Field;
121
122 uint64_t read(uint64_t enabled_bits) override {
123 uint64_t value = get();
124 set(0);
125 return value & enabled_bits;
126 }
127};
128
129// Software can only set bits to 1. The new object value is
130// the bitwise OR of the old object value and the value written
131// by software.
132class Write1OnlyField : public Field {
133 public:
134 using Field::Field;
135
136 void write(uint64_t value, uint64_t enabled_bits) override {
137 Field::write(get() | value, enabled_bits);
138 }
139};
140
141// Software can only set bits to 0. The new object value is
142// the bitwise AND of the old object value and the value
143// written by software.
144class Write0OnlyField : public Field {
145 public:
146 using Field::Field;
147
148 void write(uint64_t value, uint64_t enabled_bits) override {
149 Field::write(value & get(), enabled_bits);
150 }
151};
152
153// Reads return a constant value
154class ReadConstantField : public Field {
155 public:
156 ReadConstantField(MappableConfObject *obj, const std::string &name,
157 uint64_t read_val) :
158 Field(obj, name),
159 read_val_(read_val) {}
160
161 ReadConstantField(RegisterInterface *parent, std::string_view field_name,
162 uint64_t read_val) :
163 Field(parent, field_name),
164 read_val_(read_val) {}
165
166 uint64_t read(uint64_t enabled_bits) override {
167 return read_val_ & enabled_bits;
168 }
169
170 private:
171 uint64_t read_val_;
172};
173
174// Writes are forbidden and have no effect. TODO(xiuliang): no_reset?
175class ConstantField : public Field {
176 public:
177 ConstantField(MappableConfObject *obj, const std::string &name,
178 uint64_t init_val) :
179 Field(obj, name),
180 init_val_(init_val) {}
181
182 ConstantField(RegisterInterface *parent, std::string_view field_name,
183 uint64_t init_val) :
184 Field(parent, field_name),
185 init_val_(init_val) {}
186
187 void write(uint64_t value, uint64_t enabled_bits) override {
188 if ((value & enabled_bits) != (get() & enabled_bits)) {
189 SIM_LOG_SPEC_VIOLATION_STR(logged_once_ ? 2 : 1, bank_obj_ref(), 0,
190 fmt::format("Write to constant field {} (value written"
191 " = {:#010x}, contents = {:#010x}).", name(),
192 value & enabled_bits, get()));
193 logged_once_ = true;
194 }
195 }
196
197 void init(std::string_view desc, const bits_type &bits,
198 int8_t offset) override {
199 Field::init(desc, bits, offset);
200 set(init_val_);
201 }
202
203 private:
204 bool logged_once_ {false};
205 uint64_t init_val_;
206};
207
208// The object value will remain constant. Writes are ignored
209// and do not update the object value.
211 public:
213
214 void write(uint64_t value, uint64_t enabled_bits) override {}
215};
216
217// The object value is constant 0. Software writes are forbidden
218// and do not update the object value.
219class ZerosField : public ConstantField {
220 public:
221 ZerosField(MappableConfObject *obj, const std::string &name)
222 : ConstantField(obj, name, 0) {}
223
224 ZerosField(RegisterInterface *parent, std::string_view field_name)
225 : ConstantField(parent, field_name, 0) {}
226};
227
228// The object is constant all 1's. Software writes do not update
229// the object value.
230class OnesField : public ConstantField {
231 public:
232 OnesField(MappableConfObject *obj, const std::string &name)
233 : ConstantField(obj, name,
234 (std::numeric_limits<uint64_t>::max)()) {}
235
236 OnesField(RegisterInterface *parent, std::string_view field_name)
237 : ConstantField(parent, field_name,
238 (std::numeric_limits<uint64_t>::max)()) {}
239};
240
241// The object's functionality is unimportant. Reads return 0.
242// Writes are ignored.
244 public:
245 using IgnoreWriteField::IgnoreWriteField;
246
247 uint64_t read(uint64_t enabled_bits) override {
248 return 0;
249 }
250};
251
252// The object is marked reserved and should not be used by software.
253// Writes update the object value. Reads return the object value.
254class ReservedField : public Field {
255 public:
256 using Field::Field;
257
258 void write(uint64_t value, uint64_t enabled_bits) override {
259 if (!has_logged_ && (value & enabled_bits) != (get() & enabled_bits)) {
261 fmt::format("Write to reserved field {} (value written"
262 " = {:#010x}, contents = {:#010x}), will not warn"
263 " again.", name(), value & enabled_bits, get()));
264 has_logged_ = true;
265 }
266 Field::write(value, enabled_bits);
267 }
268
269 private:
270 bool has_logged_ {false};
271};
272
273// The object functionality associated to a read access is
274// unimplemented. Write access is using default implementation.
275class ReadUnimplField : public Field {
276 public:
277 ReadUnimplField(MappableConfObject *obj, const std::string &name)
278 : Field(obj, name) {
279 set_description("Read access not implemented. " + description());
280 }
281
282 ReadUnimplField(RegisterInterface *parent, std::string_view field_name)
283 : Field(parent, field_name) {
284 set_description("Read access not implemented. " + description());
285 }
286
287 uint64_t read(uint64_t enabled_bits) override {
288 return get() & enabled_bits;
289 }
290};
291
292// The object functionality is unimplemented. Warn when software
293// is using the object. Writes and reads are implemented as default
294// writes and reads.
295class UnimplField : public Field {
296 public:
297 UnimplField(MappableConfObject *obj, const std::string &name)
298 : Field(obj, name) {
299 set_description("Not implemented. " + description());
300 }
301
302 UnimplField(RegisterInterface *parent, std::string_view field_name)
303 : Field(parent, field_name) {
304 set_description("Not implemented. " + description());
305 }
306
307 uint64_t read(uint64_t enabled_bits) override {
308 return get() & enabled_bits;
309 }
310
311 void write(uint64_t value, uint64_t enabled_bits) override {
312 if ((value & enabled_bits) != (get() & enabled_bits)) {
313 SIM_LOG_UNIMPLEMENTED_STR(logged_once_ ? 3 : 1, bank_obj_ref(), 0,
314 fmt::format("Write to unimplemented field {} (value written"
315 " = {:#010x}, contents = {:#010x}).",
316 name(), value & enabled_bits, get()));
317 logged_once_ = true;
318 }
319 Field::write(value, enabled_bits);
320 }
321
322 private:
323 bool logged_once_ {false};
324};
325
326// The object functionality associated to a write access is
327// unimplemented. Read access is using default implementation.
328class WriteUnimplField : public Field {
329 public:
330 WriteUnimplField(MappableConfObject *obj, const std::string &name)
331 : Field(obj, name) {
332 set_description("Write access not implemented. " + description());
333 }
334
335 WriteUnimplField(RegisterInterface *parent, std::string_view field_name)
336 : Field(parent, field_name) {
337 set_description("Write access not implemented. " + description());
338 }
339
340 void write(uint64_t value, uint64_t enabled_bits) override {
341 if ((value & enabled_bits) != (get() & enabled_bits)) {
342 SIM_LOG_UNIMPLEMENTED_STR(logged_once_ ? 3 : 1, bank_obj_ref(), 0,
343 fmt::format("Write to unimplemented field {} (value written"
344 " = {:#010x}, contents = {:#010x}).",
345 name(), value & enabled_bits, get()));
346 logged_once_ = true;
347 }
348 Field::write(value, enabled_bits);
349 }
350
351 private:
352 bool logged_once_ {false};
353};
354
355// The object functionality is unimplemented, but do not print
356// a lot of log-messages when reading or writing. Writes and
357// reads are implemented as default writes and reads.
358class SilentUnimplField : public Field {
359 public:
360 using Field::Field;
361
362 uint64_t read(uint64_t enabled_bits) override {
363 return get() & enabled_bits;
364 }
365
366 void write(uint64_t value, uint64_t enabled_bits) override {
367 if ((value & enabled_bits) != (get() & enabled_bits)) {
368 SIM_LOG_UNIMPLEMENTED_STR(logged_once_ ? 3 : 2, bank_obj_ref(), 0,
369 fmt::format("Write to unimplemented field {} (value written"
370 " = {:#010x}, contents = {:#010x}).",
371 name(), value & enabled_bits, get()));
372 logged_once_ = true;
373 }
374 Field::write(value, enabled_bits);
375 }
376
377 private:
378 bool logged_once_ {false};
379};
380
381// The object functionality is undocumented or poorly documented.
382// Writes and reads are implemented as default writes and reads.
383class UndocumentedField : public Field {
384 public:
385 using Field::Field;
386
387 uint64_t read(uint64_t enabled_bits) override {
388 SIM_LOG_SPEC_VIOLATION_STR(logged_once_read_ ? 2 : 1, bank_obj_ref(), 0,
389 fmt::format("Read from poorly or non-documented field {}"
390 " (contents = {:#010x}).",
391 name(), get() & enabled_bits));
392 logged_once_read_ = true;
393 return get() & enabled_bits;
394 }
395
396 void write(uint64_t value, uint64_t enabled_bits) override {
397 SIM_LOG_SPEC_VIOLATION_STR(logged_once_read_ ? 2 : 1, bank_obj_ref(), 0,
398 fmt::format("Write to poorly or non-documented field {} (value"
399 " written = {:#010x}, contents = {:#010x}).",
400 name(), value & enabled_bits, get()));
401 logged_once_write_ = true;
402 Field::write(value, enabled_bits);
403 }
404
405 private:
406 bool logged_once_read_ {false};
407 bool logged_once_write_ {false};
408};
409
410// The object's functionality is not in the model's scope and has been
411// left unimplemented as a design decision. Software and hardware writes
412// and reads are implemented as default writes and reads. Debug fields
413// are a prime example of when to use this template. This is different from
414// unimplemented which is intended to be implement (if required) but is a
415// limitation in the current model.
417 public:
419 : Field(obj, name) {
420 set_description(std::string("Not implemented (design limitation).")
421 + " This field is a dummy field with no side effects. "
422 + description());
423 }
424
426 std::string_view field_name)
427 : Field(parent, field_name) {
428 set_description(std::string("Not implemented (design limitation).")
429 + " This field is a dummy field with no side effects. "
430 + description());
431 }
432};
433
434// The object value can be written only once
435class WriteOnceField : public Field {
436 public:
437 using Field::Field;
438
439 void write(uint64_t value, uint64_t enabled_bits) override {
440 if (written_) {
442 fmt::format("Write to write-once field {} (value written"
443 " = {:#010x}, contents = {:#010x})",
444 name(), value & enabled_bits, get()));
445 return;
446 }
447 Field::write(value, enabled_bits);
448 written_ = true;
449 }
450
451 private:
452 bool written_ {false};
453};
454
455// Combinations of the basic templates
456// Software reads return the object value. The object value is
457// read-only for software then reset to 0 as a side-effect of the read.
459 public:
460 using ReadOnlyField::ReadOnlyField;
461
462 uint64_t read(uint64_t enabled_bits) override {
463 uint64_t value = get();
464 set(0);
465 return value & enabled_bits;
466 }
467};
468
469} // namespace simics
470
471#endif
Definition: field-templates.h:118
uint64_t read(uint64_t enabled_bits) override
Definition: field-templates.h:122
Definition: field-templates.h:175
ConstantField(MappableConfObject *obj, const std::string &name, uint64_t init_val)
Definition: field-templates.h:177
ConstantField(RegisterInterface *parent, std::string_view field_name, uint64_t init_val)
Definition: field-templates.h:182
void write(uint64_t value, uint64_t enabled_bits) override
Definition: field-templates.h:187
void init(std::string_view desc, const bits_type &bits, int8_t offset) override
Initialize the field with a description, size in bits and an offset.
Definition: field-templates.h:197
Definition: field-templates.h:416
DesignLimitationField(RegisterInterface *parent, std::string_view field_name)
Definition: field-templates.h:425
DesignLimitationField(MappableConfObject *obj, const std::string &name)
Definition: field-templates.h:418
Base class to represent a Simics field.
Definition: field.h:38
RegisterInterface * parent() const override
void write(uint64_t value, uint64_t enabled_bits) override
uint64_t get() const override
size_t offset() const
const std::string & description() const override
Get the description of the field.
std::string_view name() const override
Get the name of the field without level delimiters.
Field(MappableConfObject *dev_obj, const std::string &name)
void set(uint64_t value) override
ConfObjectRef bank_obj_ref() const override
void set_description(std::string_view desc) override
Definition: field-templates.h:243
uint64_t read(uint64_t enabled_bits) override
Definition: field-templates.h:247
Definition: field-templates.h:49
void write(uint64_t value, uint64_t enabled_bits) override
Definition: field-templates.h:53
Definition: mappable-conf-object.h:134
Definition: field-templates.h:230
OnesField(RegisterInterface *parent, std::string_view field_name)
Definition: field-templates.h:236
OnesField(MappableConfObject *obj, const std::string &name)
Definition: field-templates.h:232
Definition: field-templates.h:57
uint64_t read(uint64_t enabled_bits) override
Definition: field-templates.h:61
Definition: field-templates.h:154
ReadConstantField(MappableConfObject *obj, const std::string &name, uint64_t read_val)
Definition: field-templates.h:156
ReadConstantField(RegisterInterface *parent, std::string_view field_name, uint64_t read_val)
Definition: field-templates.h:161
uint64_t read(uint64_t enabled_bits) override
Definition: field-templates.h:166
Definition: field-templates.h:458
uint64_t read(uint64_t enabled_bits) override
Definition: field-templates.h:462
Definition: field-templates.h:84
void write(uint64_t value, uint64_t enabled_bits) override
Definition: field-templates.h:88
Definition: field-templates.h:275
ReadUnimplField(RegisterInterface *parent, std::string_view field_name)
Definition: field-templates.h:282
ReadUnimplField(MappableConfObject *obj, const std::string &name)
Definition: field-templates.h:277
uint64_t read(uint64_t enabled_bits) override
Definition: field-templates.h:287
Definition: field-templates.h:36
RegisterField(RegisterInterface *reg_iface, Name name, Description desc, Offset offset, BitWidth size, Args... args)
Definition: field-templates.h:40
Definition: register-interface.h:37
virtual void add_field(std::string_view field_name, std::string_view desc, Offset offset, BitWidth width)=0
Add a field to the register.
Definition: field-templates.h:254
void write(uint64_t value, uint64_t enabled_bits) override
Definition: field-templates.h:258
Definition: field-templates.h:210
void write(uint64_t value, uint64_t enabled_bits) override
Definition: field-templates.h:214
Definition: field-templates.h:358
uint64_t read(uint64_t enabled_bits) override
Definition: field-templates.h:362
void write(uint64_t value, uint64_t enabled_bits) override
Definition: field-templates.h:366
Definition: field-templates.h:383
uint64_t read(uint64_t enabled_bits) override
Definition: field-templates.h:387
void write(uint64_t value, uint64_t enabled_bits) override
Definition: field-templates.h:396
Definition: field-templates.h:295
UnimplField(MappableConfObject *obj, const std::string &name)
Definition: field-templates.h:297
void write(uint64_t value, uint64_t enabled_bits) override
Definition: field-templates.h:311
UnimplField(RegisterInterface *parent, std::string_view field_name)
Definition: field-templates.h:302
uint64_t read(uint64_t enabled_bits) override
Definition: field-templates.h:307
Definition: field-templates.h:144
void write(uint64_t value, uint64_t enabled_bits) override
Definition: field-templates.h:148
Definition: field-templates.h:107
void write(uint64_t value, uint64_t enabled_bits) override
Definition: field-templates.h:111
Definition: field-templates.h:132
void write(uint64_t value, uint64_t enabled_bits) override
Definition: field-templates.h:136
Definition: field-templates.h:435
void write(uint64_t value, uint64_t enabled_bits) override
Definition: field-templates.h:439
Definition: field-templates.h:70
uint64_t read(uint64_t enabled_bits) override
Definition: field-templates.h:74
Definition: field-templates.h:328
WriteUnimplField(MappableConfObject *obj, const std::string &name)
Definition: field-templates.h:330
void write(uint64_t value, uint64_t enabled_bits) override
Definition: field-templates.h:340
WriteUnimplField(RegisterInterface *parent, std::string_view field_name)
Definition: field-templates.h:335
Definition: field-templates.h:219
ZerosField(MappableConfObject *obj, const std::string &name)
Definition: field-templates.h:221
ZerosField(RegisterInterface *parent, std::string_view field_name)
Definition: field-templates.h:224
Literal type that extends size_t type.
Definition: common-types.h:30
Represents name of a bank/register/field.
Definition: hierarchical-object-name.h:44
#define SIM_LOG_UNIMPLEMENTED_STR(level, obj, group, str)
Definition: log.h:36
#define SIM_LOG_INFO_STR(level, obj, group, str)
Special macro to handle string object (for example, fmt::format)
Definition: log.h:30
#define SIM_LOG_SPEC_VIOLATION_STR(level, obj, group, str)
Definition: log.h:33
Definition: after-bank.h:33
std::vector< std::pair< uint8_t *, uint8_t > > bits_type
Definition: field-interface.h:30
std::string_view Description
Type used to describe a resource.
Definition: common-types.h:46
Definition: common-types.h:66