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;
98 sc_core::sc_time& clk;
107 tlm::tlm_target_socket<BUSWIDTH>& target;
108 ::sc_dt::uint64 start;
109 ::sc_dt::uint64 size;
116 ::sc_dt::uint64 start;
117 ::sc_dt::uint64 size;
119 template <
unsigned int BUSWIDTH = LT,
unsigned int ADDR_UNIT_WIDTH = 8>
121 tlm_target_mod(sc_core::sc_module_name nm, sc_core::sc_time& clk_period)
128 template <
unsigned int BUSWIDTH,
unsigned int ADDR_UNIT_WIDTH>
130 : socket(socket_name)
132 , socket_map(std::make_pair(nullptr, 0)) {
133 socket.register_b_transport([=](tlm::tlm_generic_payload& gp, sc_core::sc_time& delay) ->
void { this->
b_tranport_cb(gp, delay); });
134 socket.register_transport_dbg([=](tlm::tlm_generic_payload& gp) ->
unsigned {
return this->
tranport_dbg_cb(gp); });
137 template <
unsigned int BUSWIDTH,
unsigned int ADDR_UNIT_WIDTH>
141 std::tie(ra, base) = socket_map.getEntry(gp.get_address());
144 auto len = gp.get_data_length();
145 auto contigous =
true;
146 if(gp.get_byte_enable_ptr()) {
147 auto lower = std::numeric_limits<unsigned>::max();
148 auto upper = std::numeric_limits<unsigned>::max();
150 auto p = gp.get_byte_enable_ptr();
152 for(; i < gp.get_byte_enable_length(); ++i, ++p) {
154 if(lower != std::numeric_limits<unsigned>::max()) {
163 if(upper != std::numeric_limits<unsigned>::max()) {
172 if(i == gp.get_byte_enable_length() && upper == std::numeric_limits<unsigned>::max())
179 if(gp.get_data_length() > ra->
size()) {
180 gp.set_response_status(tlm::TLM_BURST_ERROR_RESPONSE);
181 }
else if(gp.get_data_length() != gp.get_streaming_width()) {
182 gp.set_response_status(tlm::TLM_GENERIC_ERROR_RESPONSE);
183 }
else if(gp.get_byte_enable_ptr() !=
nullptr && !(contigous && gp.get_byte_enable_length() == gp.get_data_length())) {
184 gp.set_response_status(tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE);
186 gp.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE);
187 switch(gp.get_command()) {
188 case tlm::TLM_READ_COMMAND:
189 if(ra->read(gp.get_data_ptr() + offset, len, (gp.get_address() - base + offset), delay))
190 gp.set_response_status(tlm::TLM_OK_RESPONSE);
192 case tlm::TLM_WRITE_COMMAND:
193 if(ra->write(gp.get_data_ptr() + offset, len, (gp.get_address() - base + offset), delay))
194 gp.set_response_status(tlm::TLM_OK_RESPONSE);
199 gp.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
204 template <
unsigned int BUSWIDTH,
unsigned int ADDR_UNIT_WIDTH>
208 std::tie(ra, base) = socket_map.getEntry(gp.get_address());
210 if(gp.get_data_length() == ra->
size() && gp.get_byte_enable_ptr() ==
nullptr && gp.get_data_length() == gp.get_streaming_width()) {
211 if(gp.get_command() == tlm::TLM_READ_COMMAND) {
212 if(ra->
read_dbg(gp.get_data_ptr(), gp.get_data_length(), (gp.get_address() - base) / ra->
size()))
213 return gp.get_data_length();
214 }
else if(gp.get_command() == tlm::TLM_WRITE_COMMAND) {
215 if(ra->
write_dbg(gp.get_data_ptr(), gp.get_data_length(), (gp.get_address() - base) / ra->
size()))
216 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