17 #ifndef _BUS_TLM_PIN_OCP_TARGET_H_
18 #define _BUS_TLM_PIN_OCP_TARGET_H_
20 #include <interfaces/ocp/ocp_tlm.h>
22 #include <scc/report.h>
23 #include <scc/utilities.h>
25 #include <tlm/scc/tlm_gp_shared.h>
26 #include <tlm/scc/tlm_mm.h>
27 #include <util/ities.h>
34 #define OCP_CLK_DELAY 1_ps
36 template <
unsigned DATA_WIDTH,
unsigned ADDR_WIDTH,
unsigned BUSWIDTH = DATA_WIDTH>
37 struct target :
public sc_core::sc_module,
public tlm::tlm_bw_transport_if<tlm::tlm_base_protocol_types> {
40 using payload_type = tlm::tlm_base_protocol_types::tlm_payload_type;
41 using phase_type = tlm::tlm_base_protocol_types::tlm_phase_type;
43 sc_core::sc_in<bool> clk_i{
"clk_i"};
44 sc_core::sc_in<bool> reset{
""};
46 sc_core::sc_in<sc_uint<3>> MCmd{
"MCmd"};
47 sc_core::sc_in<sc_uint<ADDR_WIDTH>> MAddr{
"MAddr"};
48 sc_core::sc_in<sc_uint<DATA_WIDTH>> MData{
"MData"};
49 sc_core::sc_in<sc_uint<DATA_WIDTH / 8>> MByteEn{
"MByteEn"};
50 sc_core::sc_out<bool> SCmdAccept{
"SCmdAccept"};
52 sc_core::sc_out<sc_uint<2>> SResp{
"SResp"};
53 sc_core::sc_out<sc_uint<DATA_WIDTH>> SData{
"SData"};
54 sc_core::sc_in<bool> MRespAccept{
"MRespAccept"};
56 tlm::tlm_initiator_socket<BUSWIDTH> isckt{
"isckt"};
58 target(sc_core::sc_module_name
const& nm)
59 : sc_core::sc_module(nm) {
62 sensitive << clk_i.pos();
69 tlm::tlm_sync_enum nb_transport_bw(payload_type& trans, phase_type& phase, sc_core::sc_time& t)
override;
71 void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, sc_dt::uint64 end_range)
override;
73 void end_of_elaboration()
override { clk_if =
dynamic_cast<sc_core::sc_clock*
>(clk_i.get_interface()); }
75 void clk_delay() { clk_delayed.notify(OCP_CLK_DELAY); }
78 sc_core::sc_clock* clk_if{
nullptr};
79 sc_core::sc_event clk_delayed, end_req_received_evt, wdata_end_req_evt;
86 template <
unsigned DATA_WIDTH,
unsigned ADDR_WIDTH,
unsigned BUSWIDTH>
88 sc_core::sc_time& t) {
89 if(phase == tlm::END_REQ) {
90 end_req_received_evt.notify(sc_core::SC_ZERO_TIME);
91 }
else if(phase == tlm::BEGIN_RESP) {
93 t += clk_if->period().value() ? clk_if->period() : sc_core::SC_ZERO_TIME;
95 return tlm::TLM_ACCEPTED;
99 template <
unsigned DATA_WIDTH,
unsigned ADDR_WIDTH,
unsigned BUSWIDTH>
101 sc_dt::uint64 end_range) {}
103 template <
unsigned DATA_WIDTH,
unsigned ADDR_WIDTH,
unsigned BUSWIDTH>
105 this->SCmdAccept.write(
false);
106 wait(sc_core::SC_ZERO_TIME);
109 this->SCmdAccept.write(
false);
110 while(!this->MCmd.read()) {
111 wait(this->MCmd.default_event());
113 auto cmd =
static_cast<ocp::cmd_e
>(this->MCmd.read().to_uint());
115 gp->set_streaming_width(DATA_WIDTH / 8);
116 gp->set_data_length(DATA_WIDTH / 8);
117 auto addr = this->MAddr.read().to_uint64();
118 gp->set_address(addr);
121 case cmd_e::WRITE_CONDITIONAL:
122 case cmd_e::WRITE_NON_POSTED: {
123 gp->set_command(tlm::TLM_WRITE_COMMAND);
124 auto data = this->MData.read();
125 auto strb = this->MByteEn.read();
126 auto dptr = gp->get_data_ptr();
128 for(
size_t i = 0; i < DATA_WIDTH / 8; ++i) {
129 auto be = strb[i] ? 0xff : 0;
133 *dptr = data((i << 3) + 7, i << 3).to_uint();
138 gp->set_address(addr);
139 gp->set_streaming_width(len);
140 gp->set_data_length(len);
144 case cmd_e::READ_LINKED:
145 gp->set_command(tlm::TLM_READ_COMMAND);
148 SCCFATAL(SCMOD) <<
"not supported";
152 SCCDEBUG(SCMOD) <<
"received OCP bus transaction req " << *gp;
153 tlm::tlm_phase ph = tlm::BEGIN_REQ;
154 auto t{sc_core::SC_ZERO_TIME};
155 auto status = isckt->nb_transport_fw(*gp, ph, t);
156 if(status == tlm::TLM_ACCEPTED) {
157 wait(end_req_received_evt);
159 this->SCmdAccept.write(
true);
160 wait(clk_i.posedge_event());
164 template <
unsigned DATA_WIDTH,
unsigned ADDR_WIDTH,
unsigned BUSWIDTH>
166 this->SResp.write(
static_cast<unsigned>(ocp::resp_e::NULL_));
167 wait(sc_core::SC_ZERO_TIME);
170 wait(clk_i.posedge_event());
171 this->SResp.write(
static_cast<unsigned>(ocp::resp_e::NULL_));
172 if(resp_queue.has_next()) {
173 auto gp = resp_queue.get();
174 SCCDEBUG(SCMOD) <<
"received OCP bus transaction resp " << *gp;
175 this->SResp.write(
static_cast<unsigned>(ocp::resp_e::DVA));
177 auto d = gp->get_data_ptr();
178 this->SData.write(bit_comb<uint32_t>(d[0], d[1], d[2], d[3]));
181 wait(this->MRespAccept.default_event() | clk_delayed);
182 }
while(!this->MRespAccept.read());
183 tlm::tlm_phase ph = tlm::END_RESP;
184 auto t{sc_core::SC_ZERO_TIME};
185 auto status = isckt->nb_transport_fw(*gp, ph, t);
payload_type * allocate()
get a plain tlm_payload_type without extensions
TLM2.0 components modeling OCP.
static tlm_mm & get()
accessor function of the singleton