C++ Device API Reference Manual
Reference documentation for the Simics C++ Device API.
 
Loading...
Searching...
No Matches
field.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_H
17#define SIMICS_FIELD_H
18
19#include <simics/base/notifier.h> // SIM_notify
20#include <string>
21#include <cstdint>
22#include <utility> // move
23#include <bitset>
24
25#include "hierarchical-object.h"
27
28namespace simics {
29
30class MappableConfObject;
31
32/*
33 * A field with default behavior
34 *
35 * A field consists of several or all bits from a register. The default
36 * behavior is all bits support both read and write without any side effects.
37 */
38// coverity[rule_of_five_violation:FALSE]
40 public FieldInterface {
41 public:
42 // Construct from hierarchical name
43 // @param name begins with the bank name, e.g, "bankA.registerB.fieldC"
44 Field(MappableConfObject *dev_obj, const std::string &name)
46
47 // Construct from parent
48 Field(RegisterInterface *parent, std::string_view field_name)
50 parent->dev_obj(),
51 parent->hierarchical_name() + SEPARATOR + field_name.data(),
52 this),
53 parent_(parent) {}
54
55 // No duplication
56 Field(const Field&) = delete;
57 Field& operator=(const Field&) = delete;
58
59 Field(Field &&rhs)
60 : HierarchicalObject(std::move(rhs)),
61 bits_(std::move(rhs.bits_)),
62 number_of_bits_(std::move(rhs.number_of_bits_)),
63 offset_(std::move(rhs.offset_)) {
64 rhs.number_of_bits_ = 0;
65 rhs.offset_ = -1;
67 }
69 // check for self-assignment
70 if (this == &rhs)
71 return *this;
72
73 HierarchicalObject::operator=(std::move(rhs));
75 bits_ = std::move(rhs.bits_);
76 number_of_bits_ = rhs.number_of_bits_;
77 rhs.number_of_bits_ = 0;
78 offset_ = rhs.offset_;
79 rhs.offset_ = -1;
80 return *this;
81 }
82
83 // FieldInterface
84 std::string_view name() const override {
86 }
87
88 const std::string &description() const override {
90 }
91
92 unsigned number_of_bits() const override {
93 return number_of_bits_;
94 }
95
96 void init(std::string_view desc, const bits_type &bits,
97 int8_t offset) override {
98 if (number_of_bits_ != 0) {
100 fmt::format("Re-init field ({}) is not allowed",
102 return;
103 }
104 set_description(desc);
105 set_bits(bits);
106 offset_ = offset;
107 if (parent_ == nullptr) {
108 parent_ = dev_obj()->get_iface<RegisterInterface>(
109 std::string(parent_name()));
110 }
111 }
112
113 RegisterInterface *parent() const override {
114 return parent_;
115 }
116
117 uint64_t get() const override {
118 uint64_t result = 0;
119 int num_bytes = bits_.size();
120 for (int i = 0; i < num_bytes; ++i) {
121 const auto &[ptr, mask] = bits_[i];
122 uint64_t byte = *ptr & mask;
123 result |= byte << (8 * i);
124 }
125 return result >> (offset_ % 8);
126 }
127
128 void set(uint64_t value) override {
129 bool changed = false;
130 value <<= (offset_ % 8);
131 int num_bytes = bits_.size();
132 for (int i = 0; i < num_bytes; ++i) {
133 const auto &[ptr, mask] = bits_[i];
134 uint8_t byte = *ptr & mask;
135 if (!changed && (value & mask) != byte) {
136 changed = true;
137 }
138 *ptr = (value & mask) | (*ptr & ~mask);
139 value >>= 8;
140 }
141
142 if (changed) {
143 SIM_notify(bank_obj_ref(), Sim_Notify_Bank_Register_Value_Change);
144 }
145 }
146
147 uint64_t read(uint64_t enabled_bits) override {
148 if (enabled_bits == 0) {
149 return 0;
150 }
151 return get() & enabled_bits;
152 }
153
154 void write(uint64_t value, uint64_t enabled_bits) override {
155 if (enabled_bits != 0) {
156 set((enabled_bits & value) | (~enabled_bits & get()));
157 }
158 }
159
160 size_t offset() const {
161 return offset_;
162 }
163
164 // Set the bits for this field. They are references to the bits
165 // in the corresponding register
166 void set_bits(const bits_type &bits) {
167 if (dev_obj()->finalized()) {
169 fmt::format("Cannot set bits for field ({}) when"
170 " device has finalized",
172 return;
173 }
174 bits_ = bits;
175 for (const auto &[_, bits_mask] : bits_) {
176 number_of_bits_ += std::bitset<8>(bits_mask).count();
177 }
178 }
179
180 private:
181 // The bits are represented by the byte pointer and bits mask see @bits_type
182 // The first bit corresponds to the least significant digit of
183 // the value and the last bit corresponds to the most significant digit
184 bits_type bits_;
185 // The number of total bits of the field
186 std::uint8_t number_of_bits_ {0};
187 // The offset of the first bit in containing register
188 std::int8_t offset_ {-1};
189
190 // The parent interface
191 RegisterInterface *parent_ {nullptr};
192};
193
194} // namespace simics
195
196#endif
Definition: field-interface.h:34
Definition: field.h:40
unsigned number_of_bits() const override
Definition: field.h:92
void init(std::string_view desc, const bits_type &bits, int8_t offset) override
Definition: field.h:96
RegisterInterface * parent() const override
Definition: field.h:113
void write(uint64_t value, uint64_t enabled_bits) override
Definition: field.h:154
uint64_t get() const override
Definition: field.h:117
size_t offset() const
Definition: field.h:160
Field & operator=(const Field &)=delete
Field(RegisterInterface *parent, std::string_view field_name)
Definition: field.h:48
const std::string & description() const override
Definition: field.h:88
std::string_view name() const override
Definition: field.h:84
void set_bits(const bits_type &bits)
Definition: field.h:166
Field(Field &&rhs)
Definition: field.h:59
uint64_t read(uint64_t enabled_bits) override
Definition: field.h:147
Field & operator=(Field &&rhs)
Definition: field.h:68
Field(MappableConfObject *dev_obj, const std::string &name)
Definition: field.h:44
void set(uint64_t value) override
Definition: field.h:128
Field(const Field &)=delete
Definition: hierarchical-object.h:43
void init_iface(BankInterface *iface)
Definition: hierarchical-object.h:113
HierarchicalObject & operator=(const HierarchicalObject &)=delete
ConfObjectRef bank_obj_ref() const override
Definition: hierarchical-object.h:181
std::string_view name() const override
Definition: hierarchical-object.h:147
std::string_view parent_name() const override
Definition: hierarchical-object.h:191
const std::string & description() const override
Definition: hierarchical-object.h:156
void set_description(std::string_view desc) override
Definition: hierarchical-object.h:160
MappableConfObject * dev_obj() const override
Definition: hierarchical-object.h:177
const std::string & hierarchical_name() const override
Definition: hierarchical-object.h:143
Definition: mappable-conf-object.h:131
IFACE * get_iface(const std::string &name) const
Definition: mappable-conf-object.h:170
Definition: register-interface.h:36
#define SIM_LOG_ERROR_STR(obj, group, str)
Definition: log.h:40
Definition: attr-value.h:23
std::vector< std::pair< uint8_t *, uint8_t > > bits_type
Definition: field-interface.h:30
Definition: common-types.h:63