C++ Device API Reference Manual
Reference documentation for the Simics C++ Device API.
 
Loading...
Searching...
No Matches
mappable-conf-object.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_MAPPABLE_CONF_OBJECT_H
17#define SIMICS_MAPPABLE_CONF_OBJECT_H
18
19#include <simics/base/log.h> // SIM_LOG_ERROR
20#include <string_view>
21#include <string>
22#include <stdexcept>
23#include <unordered_map>
24#include <unordered_set>
25#include <set>
26#include <tuple>
27#include <vector>
28#include <functional> // hash
29
30#include "conf-object.h"
33#include "type/bank-type.h"
34
35namespace simics {
36
37// Class supports get/set a pointer to IFACE with a string name
38template <typename IFACE>
40 public:
41 static size_t hash_str(const std::string &name) {
42 return std::hash<std::string>{}(name);
43 }
44
45 // MapNameToInterface<IFACE>
46 void set_iface(const std::string &name, IFACE *iface) override {
47 if (!iface) {
48 throw std::invalid_argument {
49 "Cannot set with NULL interface"
50 };
51 } else if (name.empty()) {
52 throw std::invalid_argument {
53 "Cannot set with empty name string"
54 };
55 } else {
56 name_to_iface_[hash_str(name)] = iface;
57 }
58 }
59 IFACE *get_iface(const std::string &name) const override {
60 auto hashed = hash_str(name);
61 if (name_to_iface_.find(hashed) == name_to_iface_.end()) {
62 return nullptr;
63 }
64 return name_to_iface_.at(hashed);
65 }
66 void erase_iface(const std::string &name) override {
67 name_to_iface_.erase(hash_str(name));
68 }
69
70 private:
71 std::unordered_map<size_t, IFACE *> name_to_iface_;
72};
73
74class BankInterface;
75class FieldInterface;
76
77// Specialization of template Class MapNameToInterfaceObject
78// it supports get/set a pointer to RegisterInterface with a string name
79// and tracks all the names currently in use.
80template <>
82 : public MapNameToInterface<RegisterInterface> {
83 public:
84 static size_t hash_str(const std::string &name) {
85 return std::hash<std::string>{}(name);
86 }
87
88 // MapNameToInterface<RegisterInterface>
89 void set_iface(const std::string &name, RegisterInterface *iface) override {
90 if (!iface) {
91 throw std::invalid_argument {
92 "Cannot set with NULL interface"
93 };
94 } else if (name.empty()) {
95 throw std::invalid_argument {
96 "Cannot set with empty name string"
97 };
98 } else {
99 name_to_iface_[hash_str(name)] = iface;
100 all_registers_.insert(name);
101 }
102 }
103 RegisterInterface *get_iface(const std::string &name) const override {
104 return get_iface(hash_str(name));
105 }
106 void erase_iface(const std::string &name) override {
107 name_to_iface_.erase(hash_str(name));
108 all_registers_.erase(name);
109 }
110
111 RegisterInterface *get_iface(size_t name_hash) const {
112 if (name_to_iface_.find(name_hash) == name_to_iface_.end()) {
113 return nullptr;
114 }
115 return name_to_iface_.at(name_hash);
116 }
117
118 std::unordered_set<std::string> all_registers_;
119
120 private:
121 std::unordered_map<size_t, RegisterInterface *> name_to_iface_;
122};
123
124/*
125 * A class inherited by a model class to support memory mapped I/O
126 *
127 * It manages a container which associates a unique name to its corresponding
128 * operational interface. These 3 object types are supported: bank, register
129 * and field.
130 */
132 public:
135
136 // Set the object interface by a name.
137 template <typename IFACE>
138 void set_iface(const std::string &name, IFACE *iface) {
139 if (finalized()) {
140 SIM_LOG_ERROR(obj(), 0,
141 "Cannot set interface for %s when ConfObject"
142 " has been finalized", name.c_str());
143 return;
144 }
145
146 auto current_iface = get_iface<IFACE>(name);
147 if (current_iface && current_iface != iface) {
148 if (is_bank_initialized(name)) {
149 SIM_LOG_INFO(4, obj(), 0,
150 "Interface for %s ignored since bank"
151 " has been initialized", name.c_str());
152 return;
153 }
154 // TODO(xiuliang): Logs when interface is overridden
155 }
156
157 try {
158 std::get<MapNameToInterfaceObject<IFACE>>(
159 objects_).set_iface(name, iface);
160 } catch (std::exception &e) {
161 SIM_LOG_ERROR(obj(), 0, "%s", e.what());
162 }
163 }
164
165 /* Get the object interface by a name.
166 *
167 * User should check if the return pointer is nullptr before use.
168 */
169 template <typename IFACE>
170 IFACE *get_iface(const std::string &name) const {
171 return std::get<MapNameToInterfaceObject<IFACE>>(
172 objects_).get_iface(name);
173 }
174
175 RegisterInterface *get_iface(size_t name_hash) const {
176 return std::get<MapNameToInterfaceObject<RegisterInterface>>(
177 objects_).get_iface(name_hash);
178 }
179
180 // Erase the object interface by name.
181 template <typename IFACE>
182 void erase_iface(const std::string &name) {
183 std::get<MapNameToInterfaceObject<IFACE>>(objects_).erase_iface(name);
184 }
185
186 // Whether to represent the bits in big endian, i.e, whether the bit
187 // number 0 refers to the most significant bit.
188 virtual bool big_endian_bitorder() {
189 return false;
190 }
191
192 // @return all registers' names currently in use
193 const std::unordered_set<std::string> &all_registers() const {
194 return std::get<MapNameToInterfaceObject<
195 RegisterInterface>>(objects_).all_registers_;
196 }
197
198 std::vector<size_t> register_dimensions(const std::string &name) {
199 auto reg_name = name.substr(name.rfind('.') + 1);
200 auto num_dims = std::count(reg_name.cbegin(), reg_name.cend(), '[');
201 if (num_dims == 0) {
202 return {};
203 }
204 std::vector<size_t> dims(num_dims);
205
206 auto all_regs = all_registers();
207 auto base_name = name.substr(0, name.rfind('.') + 1) + \
208 reg_name.substr(0, reg_name.find('['));
209 for (int dim_index = 0; dim_index < num_dims; ++dim_index) {
210 auto prefix = base_name;
211 for (int prefix_index = 0; prefix_index < dim_index;
212 ++prefix_index) {
213 prefix.append("[0]");
214 }
215 std::string postfix;
216 for (int postfix_index = dim_index + 1; postfix_index < num_dims;
217 ++postfix_index) {
218 postfix.append("[0]");
219 }
220 size_t s = 0;
221
222 while (true) {
223 std::string check_name = prefix + '[' + std::to_string(s) + \
224 ']' + postfix;
225 if (all_regs.find(check_name) != all_regs.end()) {
226 ++s;
227 } else {
228 break;
229 }
230 }
231 dims[dim_index] = s;
232 }
233 return dims;
234 }
235
236 void set_bank_as_initialized(const std::string &name) {
237 initialized_banks_.insert(name);
238 }
239
240 // Return the pointer to bank memory by a name
241 bank_memory_t *get_bank_memory(std::string_view name_of_memory) {
242 return &allocated_bank_memories_[name_of_memory.data()];
243 }
244
245 private:
246 bool is_bank_initialized(const std::string &name) {
247 const auto &bank_name = name.substr(0, name.find('.'));
248 return initialized_banks_.find(bank_name) != initialized_banks_.end();
249 }
250
251 // @internal tracks the name to interface associations
252 std::tuple<MapNameToInterfaceObject<BankInterface>,
253 MapNameToInterfaceObject<RegisterInterface>,
254 MapNameToInterfaceObject<FieldInterface>> objects_;
255
256 // The name of initialized banks
257 std::unordered_set<std::string> initialized_banks_;
258
259 /*
260 * The allocated_bank_memories_ maps a string key to a
261 * value of type bank_memory_t.
262 *
263 * This structure groups bytes memory for all banks, can be used
264 * to efficiently store and access byte-level data using the name
265 * and byte offset as keys.
266 *
267 * By default, each bank uses its bank name as the key to get the
268 * bank memory. For SharedMemoryBank, multiple banks can share the
269 * same bank memory by using the same key. The key can be any unique
270 * string.
271 */
272 std::unordered_map<std::string,
273 bank_memory_t> allocated_bank_memories_;
274};
275
276} // namespace simics
277
278#endif
Represents Simics C type conf_object_t.
Definition: conf-object.h:37
A class inherited by a model class to support Simics configuration.
Definition: conf-object.h:114
virtual bool finalized()
Return if the finalize method has been called.
Definition: conf-object.h:137
ConfObjectRef obj() const
Return a ConfObjectRef represents this object.
Definition: conf-object.h:134
void erase_iface(const std::string &name) override
Definition: mappable-conf-object.h:106
static size_t hash_str(const std::string &name)
Definition: mappable-conf-object.h:84
void set_iface(const std::string &name, RegisterInterface *iface) override
Definition: mappable-conf-object.h:89
RegisterInterface * get_iface(size_t name_hash) const
Definition: mappable-conf-object.h:111
RegisterInterface * get_iface(const std::string &name) const override
Definition: mappable-conf-object.h:103
std::unordered_set< std::string > all_registers_
Definition: mappable-conf-object.h:118
Definition: mappable-conf-object.h:39
void set_iface(const std::string &name, IFACE *iface) override
Definition: mappable-conf-object.h:46
IFACE * get_iface(const std::string &name) const override
Definition: mappable-conf-object.h:59
void erase_iface(const std::string &name) override
Definition: mappable-conf-object.h:66
static size_t hash_str(const std::string &name)
Definition: mappable-conf-object.h:41
Definition: map-name-to-interface.h:24
Definition: mappable-conf-object.h:131
const std::unordered_set< std::string > & all_registers() const
Definition: mappable-conf-object.h:193
std::vector< size_t > register_dimensions(const std::string &name)
Definition: mappable-conf-object.h:198
void erase_iface(const std::string &name)
Definition: mappable-conf-object.h:182
RegisterInterface * get_iface(size_t name_hash) const
Definition: mappable-conf-object.h:175
bank_memory_t * get_bank_memory(std::string_view name_of_memory)
Definition: mappable-conf-object.h:241
virtual bool big_endian_bitorder()
Definition: mappable-conf-object.h:188
virtual ~MappableConfObject()
Definition: mappable-conf-object.h:134
void set_iface(const std::string &name, IFACE *iface)
Definition: mappable-conf-object.h:138
IFACE * get_iface(const std::string &name) const
Definition: mappable-conf-object.h:170
MappableConfObject(ConfObjectRef obj)
Definition: mappable-conf-object.h:133
void set_bank_as_initialized(const std::string &name)
Definition: mappable-conf-object.h:236
Definition: register-interface.h:36
Definition: attr-value.h:23
std::unordered_map< Offset, uint8_t > bank_memory_t
Definition: bank-type.h:48