17 #ifndef _SYSC_TLM_TARGET_H_
18 #define _SYSC_TLM_TARGET_H_
20 #include "resource_access_if.h"
23 #include <scc/utilities.h>
24 #include <tlm/scc/scv/tlm_rec_target_socket.h>
25 #include <tlm/scc/target_mixin.h>
26 #include <util/range_lut.h>
44 template <
unsigned int BUSWIDTH = LT,
unsigned int ADDR_UNIT_WIDTH = 8>
class tlm_target {
54 tlm_target(sc_core::sc_time& clock,
const char* socket_name =
"socket");
81 socket_map.addEntry(std::make_pair(&rai, base_addr), base_addr, std::max<size_t>(1, rai.
size() / (ADDR_UNIT_WIDTH / 8)));
90 for(
size_t idx = 0; idx < irai.
size(); ++idx) {
91 auto irai_size = std::max<size_t>(1, irai[idx].size() / (ADDR_UNIT_WIDTH / 8));
92 socket_map.addEntry(std::make_pair(&irai[idx], base_addr), base_addr, irai_size);
93 base_addr += irai_size;
99 for(
auto& e : socket_map) {
100 res = std::max<size_t>(res, e.first + e.second.index.second);
106 sc_core::sc_time& clk;
115 tlm::tlm_target_socket<BUSWIDTH>& target;
116 ::sc_dt::uint64 start;
117 ::sc_dt::uint64 size;
124 ::sc_dt::uint64 start;
125 ::sc_dt::uint64 size;
127 template <
unsigned int BUSWIDTH = LT,
unsigned int ADDR_UNIT_WIDTH = 8>
129 tlm_target_mod(sc_core::sc_module_name nm, sc_core::sc_time& clk_period)
136 template <
unsigned int BUSWIDTH,
unsigned int ADDR_UNIT_WIDTH>
138 : socket(socket_name)
140 , socket_map(std::make_pair(nullptr, 0)) {
141 socket.register_b_transport([=](tlm::tlm_generic_payload& gp, sc_core::sc_time& delay) ->
void { this->
b_tranport_cb(gp, delay); });
142 socket.register_transport_dbg([=](tlm::tlm_generic_payload& gp) ->
unsigned {
return this->
tranport_dbg_cb(gp); });
145 template <
unsigned int BUSWIDTH,
unsigned int ADDR_UNIT_WIDTH>
149 std::tie(ra, base) = socket_map.getEntry(gp.get_address());
152 auto len = gp.get_data_length();
153 auto contigous =
true;
154 if(gp.get_byte_enable_ptr()) {
155 auto lower = std::numeric_limits<unsigned>::max();
156 auto upper = std::numeric_limits<unsigned>::max();
158 auto p = gp.get_byte_enable_ptr();
160 for(; i < gp.get_byte_enable_length(); ++i, ++p) {
162 if(lower != std::numeric_limits<unsigned>::max()) {
171 if(upper != std::numeric_limits<unsigned>::max()) {
180 if(i == gp.get_byte_enable_length() && upper == std::numeric_limits<unsigned>::max())
187 if(gp.get_data_length() > ra->
size()) {
188 gp.set_response_status(tlm::TLM_BURST_ERROR_RESPONSE);
189 }
else if(gp.get_data_length() != gp.get_streaming_width()) {
190 gp.set_response_status(tlm::TLM_GENERIC_ERROR_RESPONSE);
191 }
else if(gp.get_byte_enable_ptr() !=
nullptr && !(contigous && gp.get_byte_enable_length() == gp.get_data_length())) {
192 gp.set_response_status(tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE);
194 gp.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE);
195 switch(gp.get_command()) {
196 case tlm::TLM_READ_COMMAND:
197 if(ra->read(gp.get_data_ptr() + offset, len, (gp.get_address() - base + offset), delay))
198 gp.set_response_status(tlm::TLM_OK_RESPONSE);
200 case tlm::TLM_WRITE_COMMAND:
201 if(ra->write(gp.get_data_ptr() + offset, len, (gp.get_address() - base + offset), delay))
202 gp.set_response_status(tlm::TLM_OK_RESPONSE);
207 gp.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
212 template <
unsigned int BUSWIDTH,
unsigned int ADDR_UNIT_WIDTH>
216 std::tie(ra, base) = socket_map.getEntry(gp.get_address());
218 if(gp.get_data_length() == ra->
size() && gp.get_byte_enable_ptr() ==
nullptr && gp.get_data_length() == gp.get_streaming_width()) {
219 if(gp.get_command() == tlm::TLM_READ_COMMAND) {
220 if(ra->
read_dbg(gp.get_data_ptr(), gp.get_data_length(), (gp.get_address() - base) / ra->
size()))
221 return gp.get_data_length();
222 }
else if(gp.get_command() == tlm::TLM_WRITE_COMMAND) {
223 if(ra->
write_dbg(gp.get_data_ptr(), gp.get_data_length(), (gp.get_address() - base) / ra->
size()))
224 return gp.get_data_length();
interface defining access to an indexed resource e.g. register file
virtual std::size_t size()=0
get the size of the resource
interface defining access to a resource e.g. a register
virtual std::size_t size() const =0
return the size of the resource
virtual bool read_dbg(uint8_t *data, std::size_t length, uint64_t offset=0) const =0
debug read the data from the resource
virtual bool write_dbg(const uint8_t *data, std::size_t length, uint64_t offset=0)=0
debug write to the resource
a simple access-width based bus interface (no DMI support)
void addResource(resource_access_if &rai, uint64_t base_addr)
add a resource to this target at a certain address within the socket address range
tlm_target(sc_core::sc_time &clock, const char *socket_name="socket")
the constructor
unsigned int tranport_dbg_cb(tlm::tlm_generic_payload &gp)
the debug transport callback
void b_tranport_cb(tlm::tlm_generic_payload &gp, sc_core::sc_time &d)
the blocking transport callback
tlm::scc::target_mixin< tlm::scc::scv::tlm_rec_target_socket< BUSWIDTH > > socket
the target socket
void addResource(indexed_resource_access_if &irai, uint64_t base_addr)
add an indexed resource to this target at a certain address within the socket address range
struct representing address range