59 bool m_address_valid =
false;
60 bool m_relative_addresses;
65 template <
unsigned int N = 2>
75 std::array<std::unique_ptr<SubBlock>, (1 <<
N)> m_sub_blocks;
76 bool m_use_sub_blocks =
false;
78 bool m_mapped =
false;
89 SCP_WARN((), m_mem.name())(
"Reset (block at offset {:x})", m_address);
90 for (
unsigned int i = 0;
i <
N;
i++) {
91 if (m_sub_blocks[
i]) m_sub_blocks[
i]->doreset();
93 if (m_mem.p_init_mem && m_ptr) {
94 memset(m_ptr, m_mem.p_init_mem_val, m_len);
102 if (m_ptr && !m_use_sub_blocks) {
103 assert(address >= m_address);
106 if (m_len > m_mem.p_max_block_size) {
107 m_use_sub_blocks =
true;
110 if (!m_use_sub_blocks) {
111 if (!((std::string)m_mem.p_mapfile).empty()) {
112 if ((m_ptr = MemoryServices::get().map_file(((std::string)(m_mem.p_mapfile)).c_str(), m_len,
113 m_address)) !=
nullptr) {
120 if (m_mem.p_shmem_prefix.get_value() !=
"")
124 << MemoryServices::get().get_shmem_seg_num();
126 size_t hash = std::hash<std::string>{}(
133 if ((m_ptr = MemoryServices::get().map_mem_create(
shmname.c_str(), m_len, &
shm_fd)) !=
nullptr) {
139 if ((m_ptr = MemoryServices::get().alloc(m_len)) !=
nullptr) {
140 if (m_mem.p_init_mem)
memset(m_ptr, m_mem.p_init_mem_val, m_len);
145 m_use_sub_blocks =
true;
148 if (m_len < m_mem.p_min_block_size) {
149 SCP_FATAL(m_mem.name()) <<
"Unable to allocate memory!";
153 assert((m_len & ~(-1ll
u <<
N)) == 0);
157 if (!m_sub_blocks[
i]) {
160 return m_sub_blocks[
i]->access(address);
185 uint8_t* get_ptr() {
return m_ptr; }
187 uint64_t get_len() {
return m_len; }
189 uint64_t get_address() {
return m_address; }
193 if (m_shmemID.empty())
return nullptr;
202 if (m_ptr) free(m_ptr);
208 std::unique_ptr<gs_memory<BUSWIDTH>::SubBlock<>> m_sub_block;
209 cci::cci_broker_handle m_broker;
212 virtual bool get_direct_mem_ptr(
int id, tlm::tlm_generic_payload&
txn, tlm::tlm_dmi& dmi_data)
214 if (!p_dmi)
return false;
215 sc_dt::uint64
addr =
txn.get_address();
217 if (!m_relative_addresses) {
218 if (
addr < m_address) {
219 txn.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
224 if (
addr >= m_size) {
225 txn.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
229 SCP_TRACE(()) <<
" : DMI access to address "
230 <<
"0x" << std::hex <<
addr;
233 dmi_data.allow_read();
235 dmi_data.allow_read_write();
243 dmi_data.set_dmi_ptr(
reinterpret_cast<unsigned char*
>(
ptr));
244 if (!m_relative_addresses) {
251 dmi_data.set_read_latency(p_latency);
252 dmi_data.set_write_latency(p_latency);
262 virtual void b_transport(
int id, tlm::tlm_generic_payload&
txn, sc_core::sc_time& delay)
264 unsigned int len =
txn.get_data_length();
265 unsigned char*
ptr =
txn.get_data_ptr();
266 sc_dt::uint64
addr =
txn.get_address();
267 unsigned char*
byt =
txn.get_byte_enable_ptr();
268 unsigned int bel =
txn.get_byte_enable_length();
270 if (
txn.get_streaming_width() <
len) {
271 SCP_FATAL(()) <<
"using streaming width: 0x" << std::hex <<
txn.get_streaming_width()
272 <<
" less than data length: 0x" << std::hex <<
len <<
" is not supported.";
274 SCP_INFO(()) <<
"Start b_transport :" << get_txn_command_str(
txn) <<
" to address: 0x" << std::hex <<
addr
275 <<
" len: 0x" << std::hex <<
len;
277 if (!m_relative_addresses) {
278 if (
addr < m_address) {
279 txn.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
285 txn.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
289 switch (
txn.get_command()) {
290 case tlm::TLM_READ_COMMAND:
292 for (
unsigned int i = 0;
i <
len;
i++)
295 SCP_FATAL(()) <<
"Address + length is out of range of the memory size";
300 SCP_FATAL(()) <<
"Address + length is out of range of the memory size";
304 case tlm::TLM_WRITE_COMMAND:
306 txn.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE);
310 for (
unsigned int i = 0;
i <
len;
i++)
313 SCP_FATAL(()) <<
"Address + length is out of range of the memory size";
318 SCP_FATAL(()) <<
"Address + length is out of range of the memory size";
323 SCP_FATAL(()) <<
"TLM command not supported";
327 txn.set_response_status(tlm::TLM_OK_RESPONSE);
328 SCP_INFO(()) <<
"Completed b_transport :" << scp::scp_txn_tostring(
txn);
330 if (p_dmi)
txn.set_dmi_allowed(
true);
333 const char* get_txn_command_str(
const tlm::tlm_generic_payload&
trans)
335 switch (
trans.get_command()) {
336 case tlm::TLM_READ_COMMAND:
338 case tlm::TLM_WRITE_COMMAND:
340 case tlm::TLM_IGNORE_COMMAND:
348 virtual unsigned int transport_dbg(
int id, tlm::tlm_generic_payload&
txn)
350 unsigned int len =
txn.get_data_length();
351 sc_dt::uint64
addr =
txn.get_address();
352 sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
353 SCP_INFO(()) <<
"Start b_transport dbg :" << get_txn_command_str(
txn) <<
" to address: 0x" << std::hex <<
addr
354 <<
" len: 0x" << std::hex <<
len;
355 b_transport(
id,
txn, delay);
356 SCP_INFO(()) <<
"Completed b_transport dbg :" << get_txn_command_str(
txn) <<
" to address: 0x" << std::hex
357 <<
addr <<
" len: 0x" << std::hex <<
len <<
" status: " <<
txn.get_response_string();
358 if (
txn.get_response_status() == tlm::TLM_OK_RESPONSE)
370 if (!m_sub_block) before_end_of_elaboration();
375 if (offset +
len > m_size) {
392 if (!m_sub_block) before_end_of_elaboration();
397 if (offset +
len > m_size) {
414 tlm_utils::multi_passthrough_target_socket<gs_memory<BUSWIDTH>,
BUSWIDTH> socket;
416 cci::cci_param<bool> p_rom;
417 cci::cci_param<bool> p_dmi;
418 cci::cci_param<sc_core::sc_time> p_latency;
419 cci::cci_param<std::string> p_mapfile;
420 cci::cci_param<uint64_t> p_max_block_size;
421 cci::cci_param<uint64_t> p_min_block_size;
422 cci::cci_param<bool> p_shmem;
423 cci::cci_param<std::string> p_shmem_prefix;
424 cci::cci_param<bool> p_init_mem;
425 cci::cci_param<int> p_init_mem_val;
435 : m_sub_block(
nullptr)
436 , m_broker(cci::cci_get_broker())
437 , socket(
"target_socket")
439 , p_rom(
"read_only",
false,
"Read Only memory (default false)")
440 , p_dmi(
"dmi_allow",
true,
"DMI allowed (default true)")
441 , p_latency(
"latency", sc_core::sc_time(10, sc_core::SC_NS),
"Latency reported for DMI access")
442 , p_mapfile(
"map_file",
"",
"(optional) file to map this memory")
443 , p_max_block_size(
"max_block_size", 0x100000000,
"Maximum size of the sub bloc")
445 , p_shmem(
"shared_memory",
false,
"Allocate using shared memory")
446 , p_shmem_prefix(
"shared_memory_prefix",
"",
"(optional) prefix_for shared memory file")
447 , p_init_mem(
"init_mem",
false,
"Initialize allocated memory")
448 , p_init_mem_val(
"init_mem_val", 0,
"Value to initialize memory to")
450 if (!write(data, offset,
len)) {
451 SCP_WARN(()) <<
" Offset : 0x" << std::hex << offset <<
" of the out of range";
456 MemoryServices::get().init();
458 std::string
ts_name = std::string(sc_module::name()) +
".target_socket";
459 if (!m_broker.has_preset_value(
ts_name +
".size")) {
460 m_broker.set_preset_cci_value(
ts_name +
".size", cci::cci_value(
_size));
464 socket.register_b_transport(
this, &gs_memory::b_transport);
465 socket.register_transport_dbg(
this, &gs_memory::transport_dbg);
466 socket.register_get_direct_mem_ptr(
this, &gs_memory::get_direct_mem_ptr);
468 reset.register_value_changed_cb([&](
bool value) {
471 m_sub_block->doreset();
477 void before_end_of_elaboration()
483 std::string
ts_name = std::string(sc_module::name()) +
".target_socket";
488 m_sub_block = std::make_unique<gs_memory<BUSWIDTH>::SubBlock<>>(0, m_size, *
this);
490 SCP_DEBUG(()) <<
"m_address: " << m_address;
493 m_relative_addresses =
true;
494 if (gs::cci_get<bool>(m_broker,
ts_name +
".relative_addresses", m_relative_addresses)) {
495 m_broker.lock_preset_value(
ts_name +
".relative_addresses");
512 std::string
ts_name = std::string(sc_module::name()) +
".target_socket";
516 if (m_broker.has_preset_value(
ts_name +
".size") &&
517 m_broker.get_preset_cci_value(
ts_name +
".size").is_number()) {
519 (
"The configuration alias provided ({}) will be ignored as a valid size is "
527 m_size = gs::cci_get<uint64_t>(m_broker,
ts_name +
".size");
539 if (!m_address_valid) {
540 std::string
ts_name = std::string(sc_module::name()) +
".target_socket";
544 if (gs::cci_get<uint64_t>(m_broker,
ts_name +
".address", m_address)) {
546 (
"The configuration alias provided ({}) will be ignored as a valid address is "
554 if (!m_broker.has_preset_value(
ts_name +
".address")) {
558 m_address = gs::cci_get<uint64_t>(m_broker,
ts_name +
".address");
560 m_broker.lock_preset_value(
ts_name +
".address");
561 m_address_valid =
true;