16#ifndef SIMICS_BANK_PORT_H
17#define SIMICS_BANK_PORT_H
19#include <simics/base/attr-value.h>
20#include <simics/base/memory.h>
21#include <simics/base/notifier.h>
22#include <simics/simulator-api.h>
23#include <simics/c++/model-iface/bank-instrumentation.h>
24#include <simics/c++/model-iface/register-view.h>
25#include <simics/c++/model-iface/register-view-read-only.h>
26#include <simics/c++/model-iface/transaction.h>
28#include <initializer_list>
52class RegisterInterface;
64template <
typename TParent>
68 public iface::RegisterViewInterface,
69 public iface::RegisterViewReadOnlyInterface,
70 public iface::RegisterViewCatalogInterface,
71 public iface::TransactionInterface {
73 std::is_base_of<MappableConfObject, TParent>::value,
74 "BankPort requires the parent class be a MappableConfObject");
83 set_bank_name_from_port_name(o.
name());
84 SIM_hap_add_callback_obj(
85 "Core_Conf_Object_Created", o.
object(), 0,
86 reinterpret_cast<obj_hap_func_t
>(object_created),
nullptr);
95 if (bank ==
nullptr) {
96 throw std::invalid_argument(
"Bank pointer cannot be nullptr");
106 SIM_hap_delete_callback_obj(
108 reinterpret_cast<obj_hap_func_t
>(object_created),
nullptr);
113 cls->
add(iface::TransactionInterface::Info());
114 cls->
add(iface::RegisterViewInterface::Info());
115 cls->
add(iface::RegisterViewReadOnlyInterface::Info());
116 cls->
add(iface::RegisterViewCatalogInterface::Info());
117 cls->
add(iface::BankInstrumentationSubscribeInterface::Info());
118 cls->
add(iface::InstrumentationOrderInterface::Info());
120 "Register_Read_Exception",
121 "Register_Write_Exception"});
122 SIM_register_notifier(*cls, Sim_Notify_Bank_Register_Value_Change,
142 "bank iface can only be set once");
146 bank_iface_ =
dev_obj()->template get_iface<BankInterface>(bank_name_);
149 "Used user defined bank for %s",
152 allocated_bank_.reset(
new Bank(
dev_obj(), bank_name_));
153 bank_iface_ = allocated_bank_.get();
155 "Created a new default bank for %s",
158 auto &[
name, desc, registers] = bank;
161 for (
const auto ® : registers) {
167 exception_type_t
issue(transaction_t *t, uint64 addr)
override {
168 if (!validate_bank_iface()) {
169 return Sim_PE_IO_Not_Taken;
176 if (!validate_bank_iface()) {
185 return regs_offsets_.size();
188 auto [reg_offset, reg_iface] = register_at_index(reg);
194 return SIM_make_attr_nil();
198 std::tie(std::ignore, iface) = register_at_index(reg);
206 std::tie(std::ignore, iface) = register_at_index(reg);
215 std::tie(std::ignore, iface) = register_at_index(reg);
222 attr_value_t ret = SIM_alloc_attr_list(number_of_regs);
224 for (
unsigned i = 0; i < number_of_regs; ++i) {
225 std::tie(std::ignore, iface) = register_at_index(i);
226 if (iface ==
nullptr) {
228 "Invalid register index %d", i);
229 SIM_attr_list_set_item(&ret, i, SIM_make_attr_nil());
232 SIM_attr_list_set_item(&ret, i,
233 SIM_make_attr_string(iface->
name().data()));
243 bool validate_bank_iface()
const override {
244#if __cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
245 if (bank_iface_ ==
nullptr) { [[unlikely]]
247 if (bank_iface_ ==
nullptr) {
250 "BankPort should have one bank");
258 void init_register_offsets() {
260 regs_offsets_.clear();
261 regs_offsets_.reserve(mapped_regs.size());
262 for (
const auto& pair : mapped_regs) {
263 regs_offsets_.push_back(pair.first);
268 static void object_created(lang_void *, conf_object_t *
obj) {
269 auto *iface = detail::get_interface<BankPort<TParent>>(
obj);
270 if (iface->validate_bank_iface()) {
273 iface->init_register_offsets();
278 const RegisterInterface *i) {
279 attr_value_t info = SIM_alloc_attr_list(6);
280 SIM_attr_list_set_item(&info, 0,
281 SIM_make_attr_string(i->name().data()));
282 SIM_attr_list_set_item(&info, 1,
283 SIM_make_attr_string(i->description().c_str()));
284 SIM_attr_list_set_item(&info, 2,
285 SIM_make_attr_uint64(i->number_of_bytes()));
286 SIM_attr_list_set_item(&info, 3, SIM_make_attr_uint64(address));
288 auto fields_info = i->fields_info();
289 auto number_of_fields = fields_info.size();
292 attr_value_t fields = SIM_alloc_attr_list(
293 static_cast<unsigned>(number_of_fields));
295 for (
const auto &[
name, desc, offset, width] : fields_info) {
297 attr_value_t field_info = SIM_alloc_attr_list(4);
298 SIM_attr_list_set_item(&field_info, 0,
299 SIM_make_attr_string(
name.data()));
300 SIM_attr_list_set_item(&field_info, 1,
301 SIM_make_attr_string(desc.data()));
302 SIM_attr_list_set_item(&field_info, 2,
303 SIM_make_attr_uint64(offset));
304 SIM_attr_list_set_item(&field_info, 3,
305 SIM_make_attr_uint64(offset + width - 1));
306 SIM_attr_list_set_item(&fields,
index++, field_info);
308 SIM_attr_list_set_item(&info, 4, fields);
309 SIM_attr_list_set_item(&info, 5,
316 void set_bank_name_from_port_name(
const std::string &port_name) {
317 auto pos = port_name.rfind(
".bank.");
318 if (pos == std::string::npos) {
319 throw std::invalid_argument(
320 "Invalid bank port name (" + port_name +
")");
322 bank_name_ = port_name.substr(pos + 6);
325 std::pair<size_t, RegisterInterface *> register_at_index(
unsigned index) {
326 size_t reg_offset {0};
327 RegisterInterface *reg_iface {
nullptr};
329 reg_offset = regs_offsets_.at(
index);
330 }
catch (
const std::out_of_range &) {
332 "Invalid register index %d",
index);
333 return {reg_offset, reg_iface};
335 if (validate_bank_iface()) {
338 return {reg_offset, reg_iface};
342 BankInterface *bank_iface_ {
nullptr };
344 std::string bank_name_;
346 std::unique_ptr<BankInterface> allocated_bank_;
348 std::vector<size_t> regs_offsets_;
353template<
typename TPortBank,
typename... Args>
358 b(this,
"A bank created through the SimicsBankPort utility class",
395 static_assert(std::is_base_of<BankPort<typename TBankPort::ParentType>,
397 "TBankPort must be derived from BankPort");
398 auto port = make_class<TBankPort>(
name,
"", desc);
399 TBankPort::addBankProperties(port.get());
402template <
typename TBankPort,
typename TArg>
ConfClassPtr
404 static_assert(std::is_base_of<BankPort<typename TBankPort::ParentType>,
406 "TBankPort must be derived from BankPort");
407 auto port = make_class<TBankPort>(
name,
"", desc, arg);
408 TBankPort::addBankProperties(port.get());
430template <
typename TParent>
432 const auto &[
name, desc, registers] = bank;
434 cls->
name() + SEPARATOR + std::string(
name.base_name()),
436 std::string(
"bank.") +
name.data());
440template <
typename TParent>
442 ConfClass *cls, std::initializer_list<bank_t> register_data) {
443 for (
const auto &bank : register_data) {
444 create_hierarchy_from_register_data<TParent>(cls, bank);
#define NULL
Definition: _null.h:24
Definition: bank-instrumentation-subscribe-connection.h:46
An interface implemented by a Simics bank.
Definition: bank-interface.h:47
virtual void set_description(std::string_view desc)=0
Set the description for the bank.
virtual void add_register(const register_t ®)=0
Parse a register name and add register to the bank.
virtual void set_callbacks(BankIssueCallbacksInterface *callbacks)=0
Set the callbacks for bank issues.
virtual const std::map< size_t, RegisterInterface * > & mapped_registers() const =0
Get all mapped registers on the bank ordered by offset.
virtual exception_type_t transaction_access(transaction_t *t, uint64_t offset)=0
Entry point for a memory access from the transaction interface.
virtual const std::string & description() const =0
Get the description of the bank.
virtual ByteOrder get_byte_order() const =0
Get the byte order of the bank.
Definition: bank-port-interface.h:31
Extends Port with bank required interfaces.
Definition: bank-port.h:71
BankPort & operator=(const BankPort &)=delete
const char * description() override
Definition: bank-port.h:175
std::string_view bank_name() const override
Definition: bank-port.h:127
BankPort(ConfObjectRef o, const bank_t *bank)
Definition: bank-port.h:94
void set_bank(const bank_t &bank) override
Definition: bank-port.h:139
attr_value_t register_names() override
Definition: bank-port.h:220
static void addBankProperties(ConfClass *cls)
Adds bank properties to the given class.
Definition: bank-port.h:112
uint64 get_register_value(unsigned reg) override
Definition: bank-port.h:196
bool is_read_only(unsigned reg) override
Definition: bank-port.h:213
virtual ~BankPort()
Definition: bank-port.h:105
attr_value_t register_offsets() override
Definition: bank-port.h:238
bool big_endian_bitorder() override
Definition: bank-port.h:181
unsigned number_of_registers() override
Definition: bank-port.h:184
BankPort(const BankPort &)=delete
exception_type_t issue(transaction_t *t, uint64 addr) override
Definition: bank-port.h:167
const BankInterface * bank_iface() const override
Definition: bank-port.h:131
attr_value_t register_info(unsigned reg) override
Definition: bank-port.h:187
MappableConfObject * dev_obj() const override
Definition: bank-port.h:135
void set_register_value(unsigned reg, uint64 val) override
Definition: bank-port.h:204
BankPort(ConfObjectRef o)
Definition: bank-port.h:82
Base class to represent a Simics register bank.
Definition: bank.h:51
Represents Simics C type conf_class_t.
Definition: conf-class.h:52
const std::string & name() const
Return the class name.
ConfClass * add(const iface::InterfaceInfo &iface)
Stores the provided InterfaceInfo for later registration.
Represents Simics C type conf_object_t.
Definition: conf-object.h:38
conf_object_t * object() const
Get a pointer to the configuration object represented by this ConfObjectRef.
Definition: conf-object.h:54
std::string name() const
Get the name of the underlying configuration object.
ConfObjectRef obj() const
Return a ConfObjectRef represents this object.
Definition: conf-object.h:137
Definition: mappable-conf-object.h:134
Extends ConfObject to add utilities to a Simics port object.
Definition: port.h:45
int index() const
Definition: port.h:76
const std::string & name() const
Definition: port.h:70
ParentType * parent() const
Definition: port.h:65
Definition: register-interface.h:37
virtual std::string_view name() const =0
Get the name of the register without level delimiters.
virtual bool is_read_only() const =0
Definition: bank-port.h:354
TPortBank b
Definition: bank-port.h:361
SimpleBankPort(ConfObjectRef o, Args... args)
Definition: bank-port.h:356
virtual uint64_t get() const =0
virtual void set(uint64_t value)=0
Definition: after-bank.h:33
std::initializer_list< std::string > LogGroups
Type used for log group names.
Definition: log.h:27
std::unique_ptr< ConfClass > ConfClassPtr
Definition: conf-class.h:38
std::tuple< Name, Description, std::vector< register_t > > bank_t
Definition: bank-type.h:38
ByteOrder
Definition: bank-interface.h:33
void create_hierarchy_from_register_data(ConfClass *cls, const bank_t &bank)
Registers bank data as port objects within a configuration class hierarchy.
Definition: bank-port.h:431
ConfClassPtr make_bank_port(const std::string &name, const std::string &desc)
Creates a bank port configuration class with specified attributes.
Definition: bank-port.h:394
void checkSizeOverflowSimicsAttribute(size_t size)
The maximum supported size for a Simics attribute dictionary/list/data is 2**32-1 bytes.
Definition: attribute-traits.h:40
std::enable_if< std::is_enum< T >::value, attr_value_t >::type std_to_attr(const T &src)
Function transforms C++ enum type T to Simics attr_value_t.
Definition: attribute-traits.h:163