C++ Device API Reference Manual
Reference documentation for the Simics C++ Device API.
 
Loading...
Searching...
No Matches
bank-port.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_BANK_PORT_H
17#define SIMICS_BANK_PORT_H
18
19#include <simics/base/attr-value.h>
20#include <simics/base/notifier.h> // SIM_register_notifier
21#include <simics/simulator-api.h> // SIM_hap_XXX
22#include <simics/c++/model-iface/transaction.h>
23#include <simics/c++/model-iface/register-view.h>
24#include <simics/c++/model-iface/register-view-read-only.h>
25#include <string>
26#include <memory>
27#include <type_traits> // is_base_of
28#include <exception>
29
30#include "conf-object.h"
31#include "port.h"
32#include "bank.h"
38#include "type/bank-type.h"
39
40namespace simics {
41
42/*
43 * The class for bank port objects
44 *
45 * In Simics, each port object contains exactly one bank, the name of the
46 * bank is determined by the CTOR parameter o. The instance of this class
47 * must have a valid bank interface to direct the received Simics interface
48 * calls.
49 *
50 * @param template parameter TParent must set to the class of the
51 * parent device
52 */
53template <typename TParent>
54// coverity[rule_of_three_violation:FALSE]
55class BankPort : public Port<TParent>,
56 public BankPortInterface,
58 public iface::RegisterViewInterface,
59 public iface::RegisterViewReadOnlyInterface,
60 public iface::TransactionInterface {
61 static_assert(
62 std::is_base_of<MappableConfObject, TParent>::value,
63 "BankPort requires the parent class be a MappableConfObject");
64
65 public:
66 /*
67 * Used by the "by code" option to set a bank on the port
68 * By this option, the bank is created as a class member variable of
69 * the user defined bank port class. Thus no need to initialize the
70 * bank_iface here.
71 */
73 : Port<TParent>(o),
74 bank_name_(bank_name_from_port_obj(o)) {
75 dev_obj()->set_bank_as_initialized(bank_name_);
76 SIM_hap_add_callback_obj(
77 "Core_Conf_Object_Created", o.object(), 0,
78 reinterpret_cast<obj_hap_func_t>(object_created), nullptr);
79 }
80
81 /*
82 * Used by the "by data" option to set a bank on the port
83 * By this option, bank is created and initialized here.
84 */
86 : BankPort(o) {
87 if (bank == nullptr) {
88 throw std::invalid_argument("Bank pointer cannot be nullptr");
89 }
90 set_bank(*bank);
91 }
92
93 // non-copyable
94 BankPort(const BankPort &) = delete;
95 BankPort &operator=(const BankPort &) = delete;
96
97 virtual ~BankPort() {
98 SIM_hap_delete_callback_obj(
99 "Core_Conf_Object_Created", Port<TParent>::obj().object(),
100 reinterpret_cast<obj_hap_func_t>(object_created), nullptr);
101 }
102
103 // BankPortInterface
104 std::string_view bank_name() const override {
105 return bank_name_;
106 }
107
108 const BankInterface *bank_iface() const override {
109 return bank_iface_;
110 }
111
112 MappableConfObject *dev_obj() const override {
113 return Port<TParent>::parent();
114 };
115
116 bool validate_bank_iface() const override {
117#if __cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
118 if (bank_iface_ == nullptr) { [[unlikely]]
119#else
120 if (bank_iface_ == nullptr) {
121#endif
122 SIM_LOG_ERROR(Port<TParent>::obj(), 0,
123 "BankPort should have one bank");
124 return false;
125 }
126 return true;
127 }
128
129 void set_bank(const bank_t &bank) override {
130 if (bank_iface_) {
131 SIM_LOG_ERROR(Port<TParent>::obj(), 0,
132 "bank iface can only be set once");
133 return;
134 }
135
136 bank_iface_ = dev_obj()->template get_iface<BankInterface>(bank_name_);
137 if (bank_iface_) {
138 SIM_LOG_INFO(3, Port<TParent>::obj(), 0,
139 "Used user defined bank for %s",
140 bank_name_.c_str());
141 } else {
142 allocated_bank_.reset(new Bank(dev_obj(), bank_name_));
143 bank_iface_ = allocated_bank_.get();
144 SIM_LOG_INFO(3, Port<TParent>::obj(), 0,
145 "Created a new default bank for %s",
146 bank_name_.c_str());
147 }
148 auto &[name, desc, registers] = bank;
149 bank_iface_->set_description(desc);
150 bank_iface_->set_callbacks(this);
151 for (auto &reg : registers) {
152 bank_iface_->add_register(reg);
153 }
154 }
155
156 // iface::TransactionInterface
157 exception_type_t issue(transaction_t *t, uint64 addr) override {
158 if (!validate_bank_iface()) {
159 return Sim_PE_IO_Not_Taken;
160 }
161 return bank_iface_->transaction_access(t, addr);
162 }
163
164 // iface::RegisterViewInterface
165 const char *description() override {
166 if (!validate_bank_iface()) {
167 return nullptr;
168 }
169 return bank_iface_->description().data();
170 }
171 bool big_endian_bitorder() override {
172 return Port<TParent>::parent()->big_endian_bitorder();
173 }
174 unsigned number_of_registers() override {
175 if (!validate_bank_iface()) {
176 return 0;
177 }
178 return bank_iface_->number_of_registers();
179 }
180 attr_value_t register_info(unsigned reg) override {
181 if (!validate_bank_iface()) {
182 return SIM_make_attr_nil();
183 }
184 auto[reg_offset, reg_iface] = bank_iface_->register_at_index(reg);
185 if (reg_iface) {
186 return register_info(reg_offset,
187 bank_iface_->get_byte_order(),
188 reg_iface);
189 }
190 return SIM_make_attr_nil();
191 }
192 uint64 get_register_value(unsigned reg) override {
193 if (!validate_bank_iface()) {
194 return 0;
195 }
196 auto[reg_offset, reg_iface] = bank_iface_->register_at_index(reg);
197 return reg_iface ? reg_iface->get() : 0;
198 }
199 void set_register_value(unsigned reg, uint64 val) override {
200 if (validate_bank_iface()) {
201 auto[reg_offset, reg_iface] = bank_iface_->register_at_index(reg);
202 if (reg_iface) {
203 reg_iface->set(val);
204 }
205 }
206 }
207
208 // iface::RegisterViewReadOnlyInterface
209 bool is_read_only(unsigned reg) override {
210 if (!validate_bank_iface()) {
211 return false;
212 }
213 auto[reg_offset, reg_iface] = bank_iface_->register_at_index(reg);
214 return reg_iface ? reg_iface->is_read_only() : false;
215 }
216
217 private:
218 // Function get called when the object is created and finalized
219 static void object_created(lang_void *, conf_object_t *obj) {
220 get_interface<BankPortInterface>(obj)->validate_bank_iface();
221 }
222
223 static std::string_view bank_name_from_port_obj(ConfObjectRef port_obj) {
224 std::string_view port_name = port_obj.name();
225 if (port_name.find(bank_name_keyword) == std::string::npos) {
226 throw std::invalid_argument(
227 "Invalid bank port name (" + port_obj.name() + ")");
228 }
229 return port_name.substr(port_name.rfind(bank_name_keyword) + \
230 bank_name_keyword.size());
231 }
232
233 static attr_value_t register_info(size_t address, ByteOrder bo,
234 const RegisterInterface *i) {
235 attr_value_t info = SIM_alloc_attr_list(6);
236 SIM_attr_list_set_item(&info, 0,
237 SIM_make_attr_string(i->name().data()));
238 SIM_attr_list_set_item(&info, 1,
239 SIM_make_attr_string(i->description().c_str()));
240 SIM_attr_list_set_item(&info, 2,
241 SIM_make_attr_uint64(i->number_of_bytes()));
242 SIM_attr_list_set_item(&info, 3, SIM_make_attr_uint64(address));
243
244 auto fields_info = i->fields_info();
245 // The forth attr in info is a list fields
246 attr_value_t fields = SIM_alloc_attr_list(fields_info.size());
247 unsigned index = 0;
248 for (const auto &[name, desc, offset, width] : fields_info) {
249 // Each attr in fields is another list field_info
250 attr_value_t field_info = SIM_alloc_attr_list(4);
251 SIM_attr_list_set_item(&field_info, 0,
252 SIM_make_attr_string(name.data()));
253 SIM_attr_list_set_item(&field_info, 1,
254 SIM_make_attr_string(desc.data()));
255 SIM_attr_list_set_item(&field_info, 2,
256 SIM_make_attr_uint64(offset));
257 SIM_attr_list_set_item(&field_info, 3,
258 SIM_make_attr_uint64(offset + width - 1));
259 SIM_attr_list_set_item(&fields, index++, field_info);
260 }
261 SIM_attr_list_set_item(&info, 4, fields);
262 SIM_attr_list_set_item(&info, 5,
263 SIM_make_attr_boolean(bo == ByteOrder::BE));
264 return info;
265 }
266
267 // A keyword exists in the name of all bank ports
268 static constexpr std::string_view bank_name_keyword {".bank."};
269 // Points to the actual bank interface
270 BankInterface *bank_iface_ { nullptr };
271 // Name of the bank
272 std::string bank_name_;
273 // @internal: record the heap allocated Bank
274 std::unique_ptr<BankInterface> allocated_bank_;
275};
276
277template <typename TBankPort> ConfClassPtr
278make_bank_port(const std::string &name, const std::string &desc) {
279 auto port = simics::make_class<TBankPort>(name, "", desc);
280 port->add(simics::iface::TransactionInterface::Info());
281 port->add(simics::iface::RegisterViewInterface::Info());
282 port->add(simics::iface::RegisterViewReadOnlyInterface::Info());
283 port->add(simics::iface::BankInstrumentationSubscribeInterface::Info());
284 port->add(simics::iface::InstrumentationOrderInterface::Info());
285 port->add(simics::LogGroups{"Register_Read", "Register_Write"});
286 SIM_register_notifier(*port, Sim_Notify_Bank_Register_Value_Change,
287 NULL /* default description works well */);
288 return port;
289}
290
291template <typename TBankPort, typename TArg> ConfClassPtr
292make_bank_port(const std::string &name, const std::string &desc, TArg *arg) {
293 auto port = simics::make_class<TBankPort>(name, "", desc, arg);
294 port->add(simics::iface::TransactionInterface::Info());
295 port->add(simics::iface::RegisterViewInterface::Info());
296 port->add(simics::iface::RegisterViewReadOnlyInterface::Info());
297 port->add(simics::iface::BankInstrumentationSubscribeInterface::Info());
298 port->add(simics::iface::InstrumentationOrderInterface::Info());
299 port->add(simics::LogGroups{"Register_Read", "Register_Write"});
300 SIM_register_notifier(*port, Sim_Notify_Bank_Register_Value_Change,
301 NULL /* default description works well */);
302 return port;
303}
304
305/*
306 * Register the bank as port object, pass the pointer to the registers as
307 * the class data.
308 */
309template <typename TParent>
311 const auto &[name, desc, registers] = bank;
313 cls->name() + SEPARATOR + std::string(name.base_name()),
314 desc.data(), &bank),
315 std::string("bank.") + name.data());
316}
317
318template <typename TParent>
320 ConfClass *cls, std::initializer_list<bank_t> register_data) {
321 for (auto &bank : register_data) {
322 create_hierarchy_from_register_data<TParent>(cls, bank);
323 }
324}
325
326} // namespace simics
327
328#endif
#define NULL
Definition: _null.h:24
struct transaction transaction_t
Definition: bank-interface.h:30
struct conf_object conf_object_t
Definition: bank-issue-callbacks-interface.h:23
Definition: bank-instrumentation-subscribe-connection.h:44
Definition: bank-interface.h:45
virtual void set_description(std::string_view desc)=0
virtual unsigned number_of_registers() const =0
virtual void add_register(const register_t &reg)=0
virtual void set_callbacks(BankIssueCallbacksInterface *callbacks)=0
virtual exception_type_t transaction_access(transaction_t *t, uint64_t offset)=0
virtual std::pair< size_t, RegisterInterface * > register_at_index(unsigned index) const =0
virtual const std::string & description() const =0
virtual ByteOrder get_byte_order() const =0
Definition: bank-port-interface.h:30
Definition: bank-port.h:60
BankPort & operator=(const BankPort &)=delete
const char * description() override
Definition: bank-port.h:165
std::string_view bank_name() const override
Definition: bank-port.h:104
BankPort(ConfObjectRef o, const bank_t *bank)
Definition: bank-port.h:85
void set_bank(const bank_t &bank) override
Definition: bank-port.h:129
bool validate_bank_iface() const override
Definition: bank-port.h:116
uint64 get_register_value(unsigned reg) override
Definition: bank-port.h:192
bool is_read_only(unsigned reg) override
Definition: bank-port.h:209
virtual ~BankPort()
Definition: bank-port.h:97
bool big_endian_bitorder() override
Definition: bank-port.h:171
unsigned number_of_registers() override
Definition: bank-port.h:174
BankPort(const BankPort &)=delete
exception_type_t issue(transaction_t *t, uint64 addr) override
Definition: bank-port.h:157
const BankInterface * bank_iface() const override
Definition: bank-port.h:108
attr_value_t register_info(unsigned reg) override
Definition: bank-port.h:180
MappableConfObject * dev_obj() const override
Definition: bank-port.h:112
void set_register_value(unsigned reg, uint64 val) override
Definition: bank-port.h:199
BankPort(ConfObjectRef o)
Definition: bank-port.h:72
Definition: bank.h:63
Represents Simics C type conf_class_t.
Definition: conf-class.h:63
const std::string & name() const
Return the class name.
Definition: conf-class.h:96
ConfClass * add(const iface::InterfaceInfo &iface)
A function to register that ConfClass implements the iface interface.
Represents Simics C type conf_object_t.
Definition: conf-object.h:37
conf_object_t * object() const
Get a pointer to the configuration object represented by this ConfObjectRef.
Definition: conf-object.h:57
ConfObjectRef obj() const
Return a ConfObjectRef represents this object.
Definition: conf-object.h:134
Definition: mappable-conf-object.h:131
void set_bank_as_initialized(const std::string &name)
Definition: mappable-conf-object.h:236
Represents a Simics port object base class.
Definition: port.h:35
TParent * parent() const
Return a pointer to the C++ object associated with the Simics parent object.
Definition: port.h:47
const std::string & name()
Return the port name.
Definition: port.h:52
int index() const
Return the index of an array-type object name.
Definition: port.h:57
Definition: attr-value.h:23
std::initializer_list< std::string > LogGroups
Type used for log group names.
Definition: log.h:26
std::unique_ptr< ConfClass > ConfClassPtr
Definition: conf-class.h:35
std::tuple< Name, Description, std::vector< register_t > > bank_t
Definition: bank-type.h:38
ByteOrder
Definition: bank-interface.h:34
void create_hierarchy_from_register_data(ConfClass *cls, const bank_t &bank)
Definition: bank-port.h:310
ConfClassPtr make_bank_port(const std::string &name, const std::string &desc)
Definition: bank-port.h:278