58class port_fnct :
public tlm_utils::simple_target_socket<port_fnct, DEFAULT_TLM_BUSWIDTH>
60 SCP_LOGGER((),
"register");
61 std::vector<std::shared_ptr<tlm_fnct>> m_pre_read_fncts;
62 std::vector<std::shared_ptr<tlm_fnct>> m_pre_write_fncts;
63 std::vector<std::shared_ptr<tlm_fnct>> m_post_read_fncts;
64 std::vector<std::shared_ptr<tlm_fnct>> m_post_write_fncts;
65 cci::cci_param<bool> p_is_callback;
66 bool m_in_callback =
false;
68 std::function<
unsigned int(tlm::tlm_generic_payload&)> transport_dbg_func;
72 std::string
n(name());
73 n =
n.substr(0,
n.length() -
strlen(
"_target_socket"));
74 n =
n.substr(
n.find_last_of(
".") + 1);
79 unsigned int transport_dbg(tlm::tlm_generic_payload&
txn)
81 if (transport_dbg_func) {
82 return transport_dbg_func(
txn);
87 void b_transport(tlm::tlm_generic_payload&
txn, sc_core::sc_time& delay)
89 if (m_pre_read_fncts.size() || m_pre_write_fncts.size() || m_post_read_fncts.size() ||
90 m_post_write_fncts.size()) {
93 switch (
txn.get_response_status()) {
94 case tlm::TLM_INCOMPLETE_RESPONSE:
95 switch (
txn.get_command()) {
96 case tlm::TLM_READ_COMMAND:
97 if (m_pre_read_fncts.size()) {
98 SCP_INFO(())(
"Pre-Read callbacks: {}", my_name());
99 for (
auto&
cb : m_pre_read_fncts) (*
cb)(
txn, delay);
102 case tlm::TLM_WRITE_COMMAND:
103 if (m_pre_write_fncts.size()) {
104 SCP_INFO(())(
"Pre-Write callbacks: {}", my_name());
105 for (
auto&
cb : m_pre_write_fncts) (*
cb)(
txn, delay);
111 capture_txn_pre(
txn);
113 case tlm::TLM_OK_RESPONSE:
114 handle_mask_post(
txn);
115 switch (
txn.get_command()) {
116 case tlm::TLM_READ_COMMAND:
117 if (m_post_read_fncts.size()) {
118 SCP_INFO(())(
"Post-Read callbacks: {}", my_name());
119 for (
auto&
cb : m_post_read_fncts) (*
cb)(
txn, delay);
122 case tlm::TLM_WRITE_COMMAND:
123 if (m_post_write_fncts.size()) {
124 SCP_INFO(())(
"Post-Write callbacks: {}", my_name());
125 for (
auto&
cb : m_post_write_fncts) (*
cb)(
txn, delay);
135 m_in_callback =
false;
138 txn.set_dmi_allowed(
false);
149 void pre_read(tlm_fnct::TLMFUNC
cb) { m_pre_read_fncts.push_back(std::make_shared<tlm_fnct>(
cb)); }
150 void pre_write(tlm_fnct::TLMFUNC
cb) { m_pre_write_fncts.push_back(std::make_shared<tlm_fnct>(
cb)); }
151 void post_read(tlm_fnct::TLMFUNC
cb) { m_post_read_fncts.push_back(std::make_shared<tlm_fnct>(
cb)); }
152 void post_write(tlm_fnct::TLMFUNC
cb) { m_post_write_fncts.push_back(std::make_shared<tlm_fnct>(
cb)); }
153 virtual void capture_txn_pre(tlm::tlm_generic_payload&
txn) = 0;
154 virtual void handle_mask_post(tlm::tlm_generic_payload&
txn) = 0;
159 , p_is_callback(
path_name +
".target_socket.is_callback",
true,
"Is a callback (true)")
161 SCP_LOGGER_NAME().features[0] = parent(sc_core::sc_object::name()) +
"." + name;
163 p_is_callback =
true;
164 p_is_callback.lock();
165 tlm_utils::simple_target_socket<port_fnct, DEFAULT_TLM_BUSWIDTH>::register_b_transport(
this,
166 &port_fnct::b_transport);
167 tlm_utils::simple_target_socket<port_fnct, DEFAULT_TLM_BUSWIDTH>::register_transport_dbg(
168 this, &port_fnct::transport_dbg);
171 void register_transport_dbg_func(std::function<
unsigned int(tlm::tlm_generic_payload&)>
fn)
173 transport_dbg_func =
fn;
177 std::string parent(std::string name) {
return name.substr(0, name.find_last_of(
'.')); }
187 scp::scp_logger_cache& SCP_LOGGER_NAME();
188 TYPE* m_dmi =
nullptr;
192 tlm::tlm_generic_payload m_txn;
194 m_txn.set_byte_enable_length(0);
195 m_txn.set_dmi_allowed(
false);
196 m_txn.set_command(tlm::TLM_IGNORE_COMMAND);
197 m_txn.set_data_ptr(
nullptr);
198 m_txn.set_address(p_offset);
199 m_txn.set_data_length(
sizeof(TYPE) * p_number);
200 m_txn.set_streaming_width(
sizeof(TYPE) * p_number);
201 m_txn.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
202 if (initiator_socket->get_direct_mem_ptr(m_txn,
m_dmi_data)) {
205 ptr += (p_offset - start);
207 m_dmi =
reinterpret_cast<TYPE*
>(
ptr);
212 std::string m_path_name;
213 cci::cci_param<uint64_t> p_number;
214 cci::cci_param<uint64_t> p_offset;
215 cci::cci_param<uint64_t> p_size;
216 cci::cci_param<TYPE> p_mask;
217 cci::cci_param<bool> p_relative_addresses;
219 tlm_utils::simple_initiator_socket<proxy_data_array, DEFAULT_TLM_BUSWIDTH> initiator_socket;
226 SCP_TRACE(())(
"Got value (DMI) : [{:#x}]", fmt::join(std::vector<TYPE>(&
dst[0], &
dst[length]),
","));
228 tlm::tlm_generic_payload m_txn;
229 sc_core::sc_time dummy;
230 m_txn.set_byte_enable_length(0);
231 m_txn.set_dmi_allowed(
false);
232 m_txn.set_command(tlm::TLM_READ_COMMAND);
233 m_txn.set_data_ptr(
reinterpret_cast<unsigned char*
>(
dst));
234 m_txn.set_address(p_offset + (
sizeof(TYPE) *
idx));
235 m_txn.set_data_length(
sizeof(TYPE) * length);
236 m_txn.set_streaming_width(
sizeof(TYPE) * length);
237 m_txn.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
238 initiator_socket->b_transport(m_txn, dummy);
239 sc_assert(m_txn.get_response_status() == tlm::TLM_OK_RESPONSE);
240 SCP_TRACE(())(
"Got value (transport) : [{:#x}]", fmt::join(std::vector<TYPE>(&
dst[0], &
dst[length]),
","));
241 if (m_txn.is_dmi_allowed()) {
251 SCP_TRACE(())(
"Set value (DMI) : [{:#x}]", fmt::join(std::vector<TYPE>(&
src[0], &
src[length]),
","));
256 write_with_mask(
src,
reinterpret_cast<TYPE*
>(&m_dmi[
idx]), length);
259 tlm::tlm_generic_payload m_txn;
260 sc_core::sc_time dummy;
263 m_txn.set_data_ptr(
reinterpret_cast<unsigned char*
>(
src));
266 get(
reinterpret_cast<TYPE*
>(
curr_data.data()),
idx, length);
267 write_with_mask(
src,
reinterpret_cast<TYPE*
>(
curr_data.data()), length);
268 m_txn.set_data_ptr(
reinterpret_cast<unsigned char*
>(
curr_data.data()));
270 m_txn.set_byte_enable_length(0);
271 m_txn.set_dmi_allowed(
false);
272 m_txn.set_command(tlm::TLM_WRITE_COMMAND);
273 m_txn.set_address(p_offset + (
sizeof(TYPE) *
idx));
274 m_txn.set_data_length(
sizeof(TYPE) * length);
275 m_txn.set_streaming_width(
sizeof(TYPE) * length);
276 m_txn.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
277 SCP_TRACE(())(
"Set value (transport) : [{:#x}]", fmt::join(std::vector<TYPE>(&
src[0], &
src[length]),
","));
278 initiator_socket->b_transport(m_txn, dummy);
279 sc_assert(m_txn.get_response_status() == tlm::TLM_OK_RESPONSE);
280 if (m_txn.is_dmi_allowed()) {
289 SCP_FATAL(())(
"write_with_mask(): src pointer is NULL");
292 SCP_FATAL(())(
"write_with_mask(): dst pointer is NULL");
306 TYPE& operator[](
int idx)
311 SCP_FATAL(())(
"Operator[] can only be used for DMI'able registers");
314 SCP_TRACE(())(
"Access value (DMI) using operator [] at idx {}",
idx);
316 SCP_FATAL(()) <<
"operator[](): Register Mask: 0x" << std::hex << p_mask.get_value()
317 <<
" has readonly bits, please use set(TYPE* src, uint64_t idx, uint64_t length) and "
318 "get(TYPE* dst, uint64_t idx, uint64_t length) instead";
322 void invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end) { m_dmi =
nullptr; }
326 : SCP_LOGGER_NAME()(
logger)
328 , p_number(
path_name +
".number",
number,
"number of elements in this register")
329 , initiator_socket((name +
"_initiator_socket").
c_str())
330 , p_offset(
path_name +
".target_socket.address",
_offset,
"Offset of this register")
331 , p_size(
path_name +
".target_socket.size",
sizeof(TYPE) *
number,
"size of this register")
332 , p_mask(
path_name +
".target_socket.mask",
mask,
" R/W mask, 0 means read only, and 1 means write/read")
333 , p_relative_addresses(
path_name +
".target_socket.relative_addresses",
true,
334 "allow relative_addresses for this register")
337 initiator_socket.register_invalidate_direct_mem_ptr(
this,
385 SCP_LOGGER((),
"register");
388 std::string m_regname;
390 std::vector<unsigned char> captured_txn_data;
401 std::string
n(name());
402 SCP_LOGGER_NAME().features[0] = parent(
n) +
"." +
_name;
403 n =
n.substr(0,
n.length() -
strlen(
"_target_socket"));
406 register_transport_dbg_func([&](tlm::tlm_generic_payload&
txn) {
407 if (
txn.get_data_length() <
sizeof(TYPE))
return (
unsigned int)0;
408 unsigned char* data =
txn.get_data_ptr();
409 if (
txn.get_command() == tlm::TLM_READ_COMMAND) {
410 TYPE tmp = proxy_data<TYPE>::get();
411 memset(data, 0, txn.get_data_length());
412 memcpy(data, &tmp, sizeof(TYPE));
413 return (unsigned int)sizeof(TYPE);
415 if (
txn.get_command() == tlm::TLM_WRITE_COMMAND) {
417 memcpy(&tmp, data, sizeof(TYPE));
418 proxy_data<TYPE>::set(tmp);
419 return (unsigned int)sizeof(TYPE);
430 void operator/=(TYPE
other)
432 if (
other == 0)
SCP_FATAL(())(
"Trying to divide a register value by 0!");
450 std::string get_regname()
const {
return m_regname; }
451 std::string get_path()
const {
return m_path; }
454 void set_mask(TYPE
mask)
460 void capture_txn_pre(tlm::tlm_generic_payload&
txn)
override
463 (
txn.get_command() != tlm::tlm_command::TLM_WRITE_COMMAND)) {
468 SCP_FATAL(()) <<
"capture_txn_pre(): txn data length should be n * sizeof(TYPE) where n >= 1";
476 captured_txn_data.clear();
478 get(
reinterpret_cast<TYPE*
>(captured_txn_data.data()),
idx,
txn_data_len /
sizeof(TYPE));
480 void handle_mask_post(tlm::tlm_generic_payload&
txn)
override
483 (
txn.get_command() != tlm::tlm_command::TLM_WRITE_COMMAND)) {
488 SCP_FATAL(()) <<
"handle_mask_post(): txn data length should be n * sizeof(TYPE) where n >= 1";
498 reinterpret_cast<TYPE*
>(captured_txn_data.data()),
500 set(
reinterpret_cast<TYPE*
>(captured_txn_data.data()),
idx,
txn_data_len /
sizeof(TYPE),
false);