62 bool m_address_valid =
false;
63 bool m_relative_addresses;
68 template <
unsigned int N = 2>
78 std::array<std::unique_ptr<SubBlock>, (1 <<
N)> m_sub_blocks;
79 bool m_use_sub_blocks =
false;
81 bool m_mapped =
false;
83 bool m_aligned =
false;
93 SCP_WARN((), m_mem.name())(
"Reset (block at offset {:x})", m_address);
94 for (
unsigned int i = 0;
i <
N;
i++) {
95 if (m_sub_blocks[
i]) m_sub_blocks[
i]->doreset();
97 if (m_mem.p_init_mem && m_ptr) {
98 memset(m_ptr, m_mem.p_init_mem_val, m_len);
107 if (m_ptr && !m_use_sub_blocks) {
108 assert(address >= m_address);
111 if (m_len > m_mem.p_max_block_size) {
112 m_use_sub_blocks =
true;
115 if (!m_use_sub_blocks) {
116 if (!((std::string)m_mem.p_mapfile).empty()) {
117 if ((m_ptr = MemoryServices::get().map_file(((std::string)(m_mem.p_mapfile)), m_len, m_address)) !=
125 if (m_mem.p_shmem_prefix.get_value() !=
"")
129 << MemoryServices::get().get_shmem_seg_num();
131 size_t hash = std::hash<std::string>{}(
138 if ((m_ptr = MemoryServices::get().map_mem_create(
shmname, m_len, &
shm_fd)) !=
nullptr) {
149 if (m_mem.p_init_mem)
memset(m_ptr, m_mem.p_init_mem_val, m_len);
154 m_use_sub_blocks =
true;
157 if (m_len < m_mem.p_min_block_size) {
158 SCP_FATAL(m_mem.name()) <<
"Unable to allocate memory!";
162 assert((m_len & ~(-1ll
u <<
N)) == 0);
166 if (!m_sub_blocks[
i]) {
169 return m_sub_blocks[
i]->access(address);
194 uint8_t* get_ptr() {
return m_ptr; }
196 uint64_t get_len() {
return m_len; }
198 uint64_t get_address() {
return m_address; }
202 if (m_shmemID.empty())
return nullptr;
206 void free_raw_alloc()
226 MemoryServices::get().unmap_file(m_ptr, m_len);
234 std::unique_ptr<gs_memory<BUSWIDTH>::SubBlock<>> m_sub_block;
235 cci::cci_broker_handle m_broker;
238 virtual bool get_direct_mem_ptr(
int id, tlm::tlm_generic_payload& txn, tlm::tlm_dmi& dmi_data)
240 if (!p_dmi)
return false;
241 sc_dt::uint64 addr = txn.get_address();
243 if (!m_relative_addresses) {
244 if (addr < m_address) {
245 txn.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
250 if (addr >= m_size) {
251 txn.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
255 SCP_TRACE(()) <<
" : DMI access to address "
256 <<
"0x" << std::hex << addr;
259 dmi_data.allow_read();
261 dmi_data.allow_read_write();
269 dmi_data.set_dmi_ptr(
reinterpret_cast<unsigned char*
>(ptr));
270 if (!m_relative_addresses) {
277 dmi_data.set_read_latency(p_latency);
278 dmi_data.set_write_latency(p_latency);
282 txn.set_extension(
ext);
288 virtual void b_transport(
int id, tlm::tlm_generic_payload& txn, sc_core::sc_time& delay)
290 unsigned int len = txn.get_data_length();
291 unsigned char* ptr = txn.get_data_ptr();
292 sc_dt::uint64 addr = txn.get_address();
293 unsigned char*
byt = txn.get_byte_enable_ptr();
294 unsigned int bel = txn.get_byte_enable_length();
296 if (txn.get_streaming_width() <
len) {
297 SCP_FATAL(()) <<
"using streaming width: 0x" << std::hex << txn.get_streaming_width()
298 <<
" less than data length: 0x" << std::hex <<
len <<
" is not supported.";
300 SCP_INFO(()) <<
"Start b_transport :" << get_txn_command_str(txn) <<
" to address: 0x" << std::hex << addr
301 <<
" len: 0x" << std::hex <<
len;
303 if (!m_relative_addresses) {
304 if (addr < m_address) {
305 txn.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
310 if ((addr +
len) > m_size) {
311 txn.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
315 switch (txn.get_command()) {
316 case tlm::TLM_READ_COMMAND:
318 for (
unsigned int i = 0;
i <
len;
i++)
320 if (!read(&(ptr[
i]), (addr +
i), 1)) {
321 SCP_FATAL(()) <<
"Address + length is out of range of the memory size";
325 if (!read(ptr, addr,
len)) {
326 SCP_FATAL(()) <<
"Address + length is out of range of the memory size";
330 case tlm::TLM_WRITE_COMMAND:
332 txn.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE);
336 for (
unsigned int i = 0;
i <
len;
i++)
338 if (!write(&(ptr[
i]), (addr +
i), 1)) {
339 SCP_FATAL(()) <<
"Address + length is out of range of the memory size";
343 if (!write(ptr, addr,
len)) {
344 SCP_FATAL(()) <<
"Address + length is out of range of the memory size";
349 SCP_FATAL(()) <<
"TLM command not supported";
353 txn.set_response_status(tlm::TLM_OK_RESPONSE);
354 SCP_INFO(()) <<
"Completed b_transport :" << scp::scp_txn_tostring(txn);
356 if (p_dmi) txn.set_dmi_allowed(
true);
359 const char* get_txn_command_str(
const tlm::tlm_generic_payload&
trans)
361 switch (
trans.get_command()) {
362 case tlm::TLM_READ_COMMAND:
364 case tlm::TLM_WRITE_COMMAND:
366 case tlm::TLM_IGNORE_COMMAND:
374 virtual unsigned int transport_dbg(
int id, tlm::tlm_generic_payload& txn)
376 unsigned int len = txn.get_data_length();
377 sc_dt::uint64 addr = txn.get_address();
378 sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
379 SCP_INFO(()) <<
"Start b_transport dbg :" << get_txn_command_str(txn) <<
" to address: 0x" << std::hex << addr
380 <<
" len: 0x" << std::hex <<
len;
381 b_transport(
id, txn, delay);
382 SCP_INFO(()) <<
"Completed b_transport dbg :" << get_txn_command_str(txn) <<
" to address: 0x" << std::hex
383 << addr <<
" len: 0x" << std::hex <<
len <<
" status: " << txn.get_response_string();
384 if (txn.get_response_status() == tlm::TLM_OK_RESPONSE)
396 if (!m_sub_block) before_end_of_elaboration();
401 if (offset +
len > m_size) {
418 if (!m_sub_block) before_end_of_elaboration();
423 if (offset +
len > m_size) {
440 tlm_utils::multi_passthrough_target_socket<gs_memory<BUSWIDTH>,
BUSWIDTH> socket;
442 cci::cci_param<bool> p_rom;
443 cci::cci_param<bool> p_dmi;
444 cci::cci_param<sc_core::sc_time> p_latency;
445 cci::cci_param<std::string> p_mapfile;
446 cci::cci_param<uint64_t> p_max_block_size;
447 cci::cci_param<uint64_t> p_min_block_size;
448 cci::cci_param<bool> p_shmem;
449 cci::cci_param<std::string> p_shmem_prefix;
450 cci::cci_param<bool> p_init_mem;
451 cci::cci_param<int> p_init_mem_val;
461 : m_sub_block(
nullptr)
462 , m_broker(cci::cci_get_broker())
463 , socket(
"target_socket")
465 , p_rom(
"read_only",
false,
"Read Only memory (default false)")
466 , p_dmi(
"dmi_allow",
true,
"DMI allowed (default true)")
467 , p_latency(
"latency", sc_core::sc_time(10, sc_core::SC_NS),
"Latency reported for DMI access")
468 , p_mapfile(
"map_file",
"",
"(optional) file to map this memory")
469 , p_max_block_size(
"max_block_size", 0x100000000,
"Maximum size of the sub bloc")
470 , p_min_block_size(
"min_block_size", get_page_size(),
"Minimum size of the sub bloc")
471 , p_shmem(
"shared_memory",
false,
"Allocate using shared memory")
472 , p_shmem_prefix(
"shared_memory_prefix",
"",
"(optional) prefix_for shared memory file")
473 , p_init_mem(
"init_mem",
false,
"Initialize allocated memory")
474 , p_init_mem_val(
"init_mem_val", 0,
"Value to initialize memory to")
476 if (!write(data, offset,
len)) {
477 SCP_WARN(()) <<
" Offset : 0x" << std::hex << offset <<
" of the out of range";
482 MemoryServices::get().init();
484 std::string
ts_name = std::string(sc_module::name()) +
".target_socket";
485 if (!m_broker.has_preset_value(
ts_name +
".size")) {
486 m_broker.set_preset_cci_value(
ts_name +
".size", cci::cci_value(
_size));
490 socket.register_b_transport(
this, &gs_memory::b_transport);
491 socket.register_transport_dbg(
this, &gs_memory::transport_dbg);
492 socket.register_get_direct_mem_ptr(
this, &gs_memory::get_direct_mem_ptr);
494 reset.register_value_changed_cb([&](
bool value) {
497 m_sub_block->doreset();
502 static size_t get_page_size()
515 void before_end_of_elaboration()
521 std::string
ts_name = std::string(sc_module::name()) +
".target_socket";
526 m_sub_block = std::make_unique<gs_memory<BUSWIDTH>::SubBlock<>>(0, m_size, *
this);
528 SCP_DEBUG(()) <<
"m_address: " << m_address;
531 m_relative_addresses =
true;
532 if (gs::cci_get<bool>(m_broker,
ts_name +
".relative_addresses", m_relative_addresses)) {
533 m_broker.lock_preset_value(
ts_name +
".relative_addresses");
550 std::string
ts_name = std::string(sc_module::name()) +
".target_socket";
554 if (m_broker.has_preset_value(
ts_name +
".size") &&
555 m_broker.get_preset_cci_value(
ts_name +
".size").is_number()) {
557 (
"The configuration alias provided ({}) will be ignored as a valid size is "
565 m_size = gs::cci_get<uint64_t>(m_broker,
ts_name +
".size");
577 if (!m_address_valid) {
578 std::string
ts_name = std::string(sc_module::name()) +
".target_socket";
582 if (gs::cci_get<uint64_t>(m_broker,
ts_name +
".address", m_address)) {
584 (
"The configuration alias provided ({}) will be ignored as a valid address is "
592 if (!m_broker.has_preset_value(
ts_name +
".address")) {
596 m_address = gs::cci_get<uint64_t>(m_broker,
ts_name +
".address");
598 m_broker.lock_preset_value(
ts_name +
".address");
599 m_address_valid =
true;