C++ Device API Reference Manual
Reference documentation for the Simics C++ Device API.
 
Loading...
Searching...
No Matches
connect-templates.h
Go to the documentation of this file.
1// -*- mode: C++; c-file-style: "virtutech-c++" -*-
2
3/*
4 © 2024 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_CONNECT_TEMPLATES_H
17#define SIMICS_CONNECT_TEMPLATES_H
18
19#include <fmt/fmt/format.h>
20#include <simics/base/map-target.h>
21#include <simics/base/sim-exception.h> // SIM_clear_exception
22#include <simics/base/transaction.h>
23
24#include <string>
25#include <vector>
26
27#include "simics/conf-object.h"
28#include "simics/connect.h"
29#include "simics/detail/attribute-exceptions.h" // InterfaceNotFound
30#include "simics/log.h"
31
32namespace simics {
33
34// A Connect default connects to its descendant
35template<typename FirstIface, typename... RestIfaces>
36class ConnectToDescendant: public Connect<FirstIface, RestIfaces...> {
37 public:
39 const std::string &descendant)
40 : Connect<FirstIface, RestIfaces...>(device->obj()) {
41 const ConfObjectRef dev_obj = device->obj();
42 // Port must be registered using SIM_register_port
43 if (!SIM_class_port(SIM_object_class(dev_obj), descendant.c_str())) {
44 SIM_LOG_CRITICAL_STR(dev_obj, 0,
45 fmt::format("Port {} is not registered yet",
46 descendant));
47 return;
48 }
49
50 conf_object_t *obj = SIM_object_descendant(dev_obj,
51 descendant.c_str());
52 if (obj) {
54 } else {
55 SIM_LOG_INFO_STR(3, dev_obj, 0,
56 fmt::format("Descendant object {} not found",
57 descendant));
58 }
59 }
60};
61
62/*
63 * A map target can be viewed as an opaque representation of an
64 * object/interface pair which can function either as an endpoint for a memory
65 * transaction or as an address space where a memory transaction can be
66 * performed.
67 *
68 * The interfaces are tried in the order of on the object:
69 * ram, rom, io_memory, port_space, translator, transaction_translator,
70 * transaction and memory_space
71 */
72class MapTarget {
73 public:
74 explicit MapTarget(const ConfObjectRef &device) : device_(device) {}
75 virtual ~MapTarget() {
76 SIM_free_map_target(map_target_);
77 }
78
79 bool set_map_target(const ConfObjectRef &obj) {
80 SIM_free_map_target(map_target_);
81 if (!obj) {
82 map_target_ = nullptr;
83 return true;
84 }
85
86 map_target_t *tmp = SIM_new_map_target(obj, nullptr, nullptr);
87 if (tmp == nullptr) {
88 (void)SIM_clear_exception();
89 throw detail::SetInterfaceNotFound {SIM_last_error()};
90 return false;
91 }
92 map_target_ = tmp;
93 return true;
94 }
95
96 uint64_t read(uint64_t addr, uint64_t size) {
97 if (size > 8) {
98 SIM_LOG_ERROR(device_, 0, "size must be less than or equal to 8");
99 return 0;
100 }
101 std::vector<uint8_t> val(size);
102 std::vector<atom_t> atoms {
103 ATOM_data(val.data()),
104 ATOM_size(size),
105 ATOM_initiator(device_),
106 ATOM_list_end(0)
107 };
108 transaction_t t {};
109 t.atoms = atoms.data();
110 auto exc = issue(&t, addr);
111 if (exc != Sim_PE_No_Exception) {
112 SIM_LOG_ERROR_STR(device_, 0,
113 fmt::format("unexpected exception: {}",
114 static_cast<int>(exc)));
115 return 0;
116 }
117 return SIM_get_transaction_value_le(&t);
118 }
119
120 void read_bytes(uint64_t addr, uint64_t size, uint8_t *bytes) {
121 std::vector<atom_t> atoms {
122 ATOM_data(bytes),
123 ATOM_size(size),
124 ATOM_initiator(device_),
125 ATOM_list_end(0),
126 };
127 transaction_t t {};
128 t.atoms = atoms.data();
129 issue(&t, addr);
130 }
131
132 void write(uint64_t addr, uint64_t size, uint64_t value) {
133 if (size > 8) {
134 SIM_LOG_ERROR(device_, 0, "size must be less than or equal to 8");
135 return;
136 }
137 std::vector<uint8_t> buf(size);
138 std::vector<atom_t> atoms {
139 ATOM_data(buf.data()),
140 ATOM_size(size),
141 ATOM_flags(Sim_Transaction_Write),
142 ATOM_initiator(device_),
143 ATOM_list_end(0)
144 };
145 transaction_t t {};
146 t.atoms = atoms.data();
147 SIM_set_transaction_value_le(&t, value);
148 issue(&t, addr);
149 }
150
151 void write_bytes(uint64_t addr, uint64_t size, uint8_t *bytes) {
152 std::vector<atom_t> atoms {
153 ATOM_flags(Sim_Transaction_Write),
154 ATOM_data(bytes),
155 ATOM_size(size),
156 ATOM_initiator(device_),
157 ATOM_list_end(0),
158 };
159 transaction_t t {};
160 t.atoms = atoms.data();
161 issue(&t, addr);
162 }
163
164 exception_type_t issue(transaction_t *t, uint64_t addr) {
165 if (t == nullptr) {
166 SIM_LOG_INFO(2, device_, 0,
167 "null transaction is terminated");
168 return Sim_PE_IO_Not_Taken;
169 }
170
171 if (!map_target_) {
172 SIM_LOG_INFO(2, device_, 0,
173 "map_target not set, transaction terminated");
174 return Sim_PE_IO_Not_Taken;
175 }
176
177 exception_type_t exc = SIM_issue_transaction(map_target_, t, addr);
178 std::string op {SIM_transaction_is_read(t) ? "read" : "write"};
179 if (exc == Sim_PE_No_Exception) {
180 SIM_LOG_INFO_STR(4, device_, 0,
181 fmt::format("{} {} bytes @0x{:x} in {}",
182 op, SIM_transaction_size(t),
183 addr, SIM_object_name(device_)));
184 } else {
185 SIM_LOG_INFO_STR(2, device_, 0,
186 fmt::format("failed to {} {} bytes @0x{:x} in {}",
187 op, SIM_transaction_size(t),
188 addr, SIM_object_name(device_)));
189 }
190 return Sim_PE_No_Exception;
191 }
192
193 const map_target_t *map_target() const {
194 return map_target_;
195 }
196
197 private:
198 conf_object_t *device_ {nullptr};
199 map_target_t *map_target_ {nullptr};
200};
201
202class MapTargetConnect : public ConnectBase, public MapTarget {
203 public:
204 explicit MapTargetConnect(const ConfObjectRef &device)
205 : MapTarget(device) {}
206
207 // ConnectBase
208 bool set(const ConfObjectRef &o) override {
209 bool success = MapTarget::set_map_target(o);
210 if (success) {
211 obj_ = o;
212 }
213 return success;
214 }
215};
216
217} // namespace simics
218
219#endif
Represents Simics C type conf_object_t.
Definition: conf-object.h:38
Base class for all Simics configuration objects.
Definition: conf-object.h:126
A base class for Simics C++ interface connect class.
Definition: connect.h:36
ConfObjectRef obj_
Definition: connect.h:64
Definition: connect-templates.h:36
ConnectToDescendant(const ConfObject *device, const std::string &descendant)
Definition: connect-templates.h:38
A class for connecting with another Simics object.
Definition: connect.h:118
conf_object_t * device() const
Return the device object which can be used for logging purpose.
Definition: connect.h:177
bool set(const ConfObjectRef &o) override
Set the connected configuration object.
Definition: connect.h:130
Definition: connect-templates.h:202
bool set(const ConfObjectRef &o) override
Set the connected configuration object.
Definition: connect-templates.h:208
MapTargetConnect(const ConfObjectRef &device)
Definition: connect-templates.h:204
Definition: connect-templates.h:72
MapTarget(const ConfObjectRef &device)
Definition: connect-templates.h:74
bool set_map_target(const ConfObjectRef &obj)
Definition: connect-templates.h:79
void write(uint64_t addr, uint64_t size, uint64_t value)
Definition: connect-templates.h:132
void write_bytes(uint64_t addr, uint64_t size, uint8_t *bytes)
Definition: connect-templates.h:151
virtual ~MapTarget()
Definition: connect-templates.h:75
exception_type_t issue(transaction_t *t, uint64_t addr)
Definition: connect-templates.h:164
void read_bytes(uint64_t addr, uint64_t size, uint8_t *bytes)
Definition: connect-templates.h:120
uint64_t read(uint64_t addr, uint64_t size)
Definition: connect-templates.h:96
const map_target_t * map_target() const
Definition: connect-templates.h:193
Definition: attribute-exceptions.h:25
#define SIM_LOG_CRITICAL_STR(obj, group, str)
Definition: log.h:42
#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_ERROR_STR(obj, group, str)
Definition: log.h:39
Definition: after-bank.h:33