17 #include "simple_initiator.h" 
   18 #include <axi/fsm/protocol_fsm.h> 
   19 #include <axi/fsm/types.h> 
   20 #include <scc/report.h> 
   22 #include <tlm/scc/tlm_id.h> 
   24 using namespace sc_core;
 
   27 using namespace axi::fsm;
 
   35 simple_initiator_b::simple_initiator_b(
const sc_core::sc_module_name& nm,
 
   37                                        size_t transfer_width, 
bool ack_phase)
 
   39 , 
base(transfer_width, ack_phase)
 
   46     SC_METHOD(fsm_clk_method);
 
   48     sensitive << clk_i.pos();
 
   49     SC_METHOD(process_snoop_resp);
 
   50     sensitive << clk_i.pos();
 
   51     snp_resp_queue.set_avail_cb([
this]() {
 
   52         if(snp_resp_queue_hndl.valid())
 
   53             snp_resp_queue_hndl.enable();
 
   55     snp_resp_queue.set_empty_cb([
this]() {
 
   56         if(snp_resp_queue_hndl.valid())
 
   57             snp_resp_queue_hndl.disable();
 
   61     sensitive << cbpeq.event();
 
   64 void simple_initiator_b::end_of_elaboration() { clk_if = 
dynamic_cast<sc_core::sc_clock*
>(clk_i.get_interface()); }
 
   70     SCCTRACE(SCMOD) << 
"got transport req for trans " << trans;
 
   73         socket_fw->b_transport(trans, t);
 
   78             wait(clk_i.posedge_event());
 
   81             wait(clk_i.posedge_event());
 
   83         react(RequestPhaseBeg, fsm);
 
   84         SCCTRACE(SCMOD) << 
"started non-blocking protocol";
 
   85         sc_core::wait(fsm->
finish);
 
   86         SCCTRACE(SCMOD) << 
"finished non-blocking protocol";
 
   93     fsm_hndl->
fsm->cb[RequestPhaseBeg] = [
this, fsm_hndl]() -> 
void {
 
   95         auto& f = protocol_cb[RequestPhaseBeg];
 
   99     fsm_hndl->
fsm->cb[BegPartReqE] = [
this, fsm_hndl]() -> 
void {
 
  101         tlm::tlm_phase phase = axi::BEGIN_PARTIAL_REQ;
 
  102         auto ret = socket_fw->nb_transport_fw(*fsm_hndl->
trans, phase, t);
 
  103         if(ret == tlm::TLM_UPDATED) {
 
  104             schedule(EndPartReqE, fsm_hndl->
trans, t, 
true);
 
  106         if((
bool)protocol_cb[BegPartReqE])
 
  107             cbpeq.notify(std::make_tuple(BegPartReqE, fsm_hndl->
trans, fsm_hndl->
is_snoop), sc_core::SC_ZERO_TIME);
 
  109     fsm_hndl->
fsm->cb[EndPartReqE] = [
this, fsm_hndl]() -> 
void {
 
  112             if(::scc::get_value(wr_data_beat_delay) > 0)
 
  113                 schedule(BegPartReqE, fsm_hndl->
trans, ::scc::get_value(wr_data_beat_delay) - 1);
 
  115                 schedule(BegPartReqE, fsm_hndl->
trans, SC_ZERO_TIME);
 
  116         else if(::scc::get_value(wr_data_beat_delay) > 0)
 
  117             schedule(BegReqE, fsm_hndl->
trans, ::scc::get_value(wr_data_beat_delay) - 1);
 
  119             schedule(BegReqE, fsm_hndl->
trans, 0);
 
  120         if((
bool)protocol_cb[EndPartReqE])
 
  121             cbpeq.notify(std::make_tuple(EndPartReqE, fsm_hndl->
trans, fsm_hndl->
is_snoop), sc_core::SC_ZERO_TIME);
 
  123     fsm_hndl->
fsm->cb[BegReqE] = [
this, fsm_hndl]() -> 
void {
 
  125             schedule(EndReqE, fsm_hndl->
trans, SC_ZERO_TIME);
 
  128             tlm::tlm_phase phase = tlm::BEGIN_REQ;
 
  129             auto ret = socket_fw->nb_transport_fw(*fsm_hndl->
trans, phase, t);
 
  130             if(ret == tlm::TLM_UPDATED) {
 
  131                 schedule(EndReqE, fsm_hndl->
trans, t, 
true);
 
  134         if((
bool)protocol_cb[BegReqE])
 
  135             cbpeq.notify(std::make_tuple(BegReqE, fsm_hndl->
trans, fsm_hndl->
is_snoop), sc_core::SC_ZERO_TIME);
 
  137     fsm_hndl->
fsm->cb[EndReqE] = [
this, fsm_hndl]() -> 
void {
 
  139             tlm::tlm_phase phase = tlm::END_REQ;
 
  140             sc_time t(clk_if ? ::scc::time_to_next_posedge(clk_if) - 1_ps : SC_ZERO_TIME);
 
  141             auto ret = socket_fw->nb_transport_fw(*fsm_hndl->
trans, phase, t);
 
  143             sc_assert(ext && 
"No ACE extension found for snoop access");
 
  145             fsm_hndl->
trans->set_response_status(tlm::TLM_OK_RESPONSE);
 
  146             auto latency = snoop_latency;
 
  147             if(bw_o.get_interface()) {
 
  149                 if(thread_avail == 0) {
 
  150                     sc_core::sc_spawn_options opts;
 
  151                     opts.set_stack_size(0x10000);
 
  157                                 auto req = dispatch_queue.read();
 
  158                                 sc_assert(thread_avail > 0);
 
  160                                 auto latency = bw_o->transport(*req);
 
  161                                 if(latency < std::numeric_limits<unsigned>::max()) {
 
  164                                     auto evt = ext->is_snoop_data_transfer() && length > 1 ? BegPartRespE : BegRespE;
 
  165                                     snp_resp_queue.push_back(std::make_tuple(evt, req.get(), latency));
 
  171                 dispatch_queue.write(fsm_hndl->
trans);
 
  172                 latency = std::numeric_limits<unsigned>::max();
 
  173             } 
else if(snoop_cb) {
 
  174                 latency = snoop_cb(*fsm_hndl->
trans);
 
  176                 ext->set_snoop_data_transfer(
false);
 
  177                 ext->set_snoop_error(
false);
 
  178                 ext->set_pass_dirty(
false);
 
  179                 ext->set_shared(
false);
 
  180                 ext->set_snoop_was_unique(
false);
 
  182             if(latency < std::numeric_limits<unsigned>::max()) {
 
  184                 auto evt = ext->is_snoop_data_transfer() && length > 1 ? BegPartRespE : BegRespE;
 
  185                 snp_resp_queue.push_back(std::make_tuple(evt, fsm_hndl->
trans.
get(), latency));
 
  189             if(fsm_hndl->
trans->is_write())
 
  194         if((
bool)protocol_cb[EndReqE])
 
  195             cbpeq.notify(std::make_tuple(EndReqE, fsm_hndl->
trans, fsm_hndl->
is_snoop), sc_core::SC_ZERO_TIME);
 
  197     fsm_hndl->
fsm->cb[BegPartRespE] = [
this, fsm_hndl]() -> 
void {
 
  199             tlm::tlm_phase phase = axi::BEGIN_PARTIAL_RESP;
 
  201             auto ret = socket_fw->nb_transport_fw(*fsm_hndl->
trans, phase, t);
 
  203             if(::scc::get_value(rd_data_accept_delay))
 
  204                 schedule(EndPartRespE, fsm_hndl->
trans, ::scc::get_value(rd_data_accept_delay));
 
  206                 schedule(EndPartRespE, fsm_hndl->
trans, SC_ZERO_TIME);
 
  208         if((
bool)protocol_cb[BegPartRespE])
 
  209             cbpeq.notify(std::make_tuple(BegPartRespE, fsm_hndl->
trans, fsm_hndl->
is_snoop), sc_core::SC_ZERO_TIME);
 
  211     fsm_hndl->
fsm->cb[EndPartRespE] = [
this, fsm_hndl]() -> 
void {
 
  215             schedule(fsm_hndl->
beat_count < (size-1) ? BegPartRespE : BegRespE, fsm_hndl->
trans, 0);
 
  217             sc_time t(clk_if ? ::scc::time_to_next_posedge(clk_if) - 1_ps : SC_ZERO_TIME);
 
  218             tlm::tlm_phase phase = axi::END_PARTIAL_RESP;
 
  219             auto ret = socket_fw->nb_transport_fw(*fsm_hndl->
trans, phase, t);
 
  222         if((
bool)protocol_cb[EndPartRespE])
 
  223             cbpeq.notify(std::make_tuple(EndPartRespE, fsm_hndl->
trans, fsm_hndl->
is_snoop), sc_core::SC_ZERO_TIME);
 
  225     fsm_hndl->
fsm->cb[BegRespE] = [
this, fsm_hndl]() -> 
void {
 
  227             tlm::tlm_phase phase = tlm::BEGIN_RESP;
 
  229             auto ret = socket_fw->nb_transport_fw(*fsm_hndl->
trans, phase, t);
 
  231             auto del = fsm_hndl->
trans->is_read() ? ::scc::get_value(rd_data_accept_delay)
 
  232                                                   : ::scc::get_value(wr_resp_accept_delay);
 
  234                 schedule(EndRespE, fsm_hndl->
trans, del);
 
  236                 schedule(EndRespE, fsm_hndl->
trans, SC_ZERO_TIME);
 
  238         if((
bool)protocol_cb[BegRespE])
 
  239             cbpeq.notify(std::make_tuple(BegRespE, fsm_hndl->
trans, fsm_hndl->
is_snoop), sc_core::SC_ZERO_TIME);
 
  241     fsm_hndl->
fsm->cb[EndRespE] = [
this, fsm_hndl]() -> 
void {
 
  245             sc_time t(clk_if ? ::scc::time_to_next_posedge(clk_if) - 1_ps : SC_ZERO_TIME);
 
  246             tlm::tlm_phase phase = tlm::END_RESP;
 
  247             auto ret = socket_fw->nb_transport_fw(*fsm_hndl->
trans, phase, t);
 
  249                 schedule(Ack, fsm_hndl->
trans, ::scc::get_value(ack_resp_delay));
 
  251                 fsm_hndl->
finish.notify(sc_core::SC_ZERO_TIME);
 
  253         if((
bool)protocol_cb[EndRespE])
 
  254             cbpeq.notify(std::make_tuple(EndRespE, fsm_hndl->
trans, fsm_hndl->
is_snoop), sc_core::SC_ZERO_TIME);
 
  256     fsm_hndl->
fsm->cb[Ack] = [
this, fsm_hndl]() -> 
void {
 
  258         tlm::tlm_phase phase = axi::ACK;
 
  259         auto ret = socket_fw->nb_transport_fw(*fsm_hndl->
trans, phase, t);
 
  260         fsm_hndl->
finish.notify(sc_core::SC_ZERO_TIME);
 
  261         if((
bool)protocol_cb[Ack])
 
  262             cbpeq.notify(std::make_tuple(Ack, fsm_hndl->
trans, fsm_hndl->
is_snoop), sc_core::SC_ZERO_TIME);
 
  266 tlm_sync_enum simple_initiator_b::nb_transport_bw(payload_type& trans, phase_type& phase, sc_time& t) {
 
  267     auto ret = TLM_ACCEPTED;
 
  268     SCCTRACE(SCMOD) << 
"nb_transport_bw " << phase << 
" of trans " << trans;
 
  269     if(phase == END_PARTIAL_REQ || phase == END_REQ) { 
 
  270         schedule(phase == END_REQ ? EndReqE : EndPartReqE, &trans, t, 
false);
 
  271     } 
else if(phase == BEGIN_PARTIAL_RESP || phase == BEGIN_RESP) { 
 
  272         schedule(phase == BEGIN_RESP ? BegRespE : BegPartRespE, &trans, t, 
false);
 
  273     } 
else if(phase == BEGIN_REQ) { 
 
  275         fsm_hndl->is_snoop = 
true;
 
  277     } 
else if(phase == END_PARTIAL_RESP || phase == END_RESP) { 
 
  278         schedule(phase == END_RESP ? EndRespE : EndPartRespE, &trans, t);
 
  283 void simple_initiator_b::b_snoop(payload_type& trans, sc_time& t) {
 
  284     if(bw_o.get_interface()) {
 
  285         auto latency = bw_o->transport(trans);
 
  286         if(latency < std::numeric_limits<unsigned>::max())
 
  287             t += latency * clk_period;
 
  288     } 
else if(snoop_cb) {
 
  289         auto latency = snoop_cb(trans);
 
  290         if(latency < std::numeric_limits<unsigned>::max())
 
  291             t += latency * clk_period;
 
  295 void simple_initiator_b::process_snoop_resp() {
 
  296     if(!snp_resp_queue_hndl.valid())
 
  297         snp_resp_queue_hndl = sc_process_handle(sc_get_current_process_handle());
 
  298     if(snp_resp_queue.avail())
 
  299         while(snp_resp_queue.avail()) {
 
  300             auto entry = snp_resp_queue.front();
 
  301             if(std::get<2>(entry) == 0) {
 
  303                     snp_resp_queue.push_back(entry);
 
  306                     auto gp = std::get<1>(entry);
 
  307                     SCCTRACE(instance_name)
 
  308                         << 
"processing event " << evt2str(std::get<0>(entry)) << 
" of trans " << *gp;
 
  309                     react(std::get<0>(entry), std::get<1>(entry));
 
  312                 std::get<2>(entry) -= 1;
 
  313                 snp_resp_queue.push_back(entry);
 
  315             snp_resp_queue.pop_front();
 
  319         snp_resp_queue_hndl.disable();
 
  324     sc_assert(fsm_hndl != 
nullptr);
 
  326     auto size = ext->get_length();
 
  327     protocol_time_point_e e = ext->is_snoop_data_transfer() && size > 0 ? BegPartRespE : BegRespE;
 
  329         snp_resp_queue.push_back(std::make_tuple(e, &trans, 0));
 
  339 void simple_initiator_b::cbpeq_cb() {
 
  340     while(cbpeq.has_next()) {
 
  341         auto e = cbpeq.get();
 
  342         protocol_cb[std::get<0>(e)](*std::get<1>(e), std::get<2>(e));
 
void setup_callbacks(axi::fsm::fsm_handle *) override
 
axi::fsm::fsm_handle * create_fsm_handle() override
 
void snoop_resp(payload_type &trans, bool sync=false) override
triggers a non-blocking snoop response if the snoop callback does not do so.
 
sc_core::sc_attribute< unsigned > rd_data_accept_delay
the latency between between BEGIN(_PARTIAL)_RESP and END(_PARTIAL)_RESP (RVALID to RREADY)
 
sc_core::sc_attribute< unsigned > wr_resp_accept_delay
the latency between between BEGIN_RESP and END_RESP (BVALID to BREADY)
 
sc_core::sc_attribute< unsigned > ack_resp_delay
the latency between between BEGIN_RESP and END_RESP (BVALID to BREADY)
 
sc_core::sc_attribute< unsigned > wr_data_beat_delay
the latency between between END(_PARTIAL)_REQ and BEGIN(_PARTIAL)_REQ (AWREADY to AWVALID and WREADY ...
 
void transport(payload_type &trans, bool blocking) override
The forward transport function. It behaves blocking and is re-entrant.
 
int get_value() const override
get the value of the semaphore
 
int wait() override
lock (take) the semaphore, block if not available
 
T * get() const noexcept
Return the stored pointer.
 
protocol engine implementations
 
TLM2.0 components modeling AHB.
 
unsigned get_burst_length(const request &r)
 
tlm::tlm_fw_transport_if< TYPES > axi_fw_transport_if
alias declaration for the forward interface
 
base class of all AXITLM based adapters and interfaces.
 
void react(axi::fsm::protocol_time_point_e event, tlm::scc::tlm_gp_shared_ptr &trans)
triggers the FSM with event and given transaction
 
void schedule(axi::fsm::protocol_time_point_e e, tlm::scc::tlm_gp_shared_ptr &gp, unsigned cycles)
processes the fsm_sched_queue and propagates events to fsm_clk_queue. Should be registered as falling...
 
axi::fsm::fsm_handle * find_or_create(payload_type *gp=nullptr, bool ace=false)
retrieve the FSM handle based on the transaction passed. If non exist one will be created
 
axi::axi_protocol_types::tlm_payload_type payload_type
aliases used in the class
 
tlm::scc::tlm_gp_shared_ptr trans
pointer to the associated AXITLM payload
 
sc_core::sc_event finish
event indicating the end of the transaction
 
size_t beat_count
beat count of this transaction
 
AxiProtocolFsm *const fsm
pointer to the FSM
 
bool is_snoop
indicator if this is a snoop access
 
uint8_t get_length() const
get the AxLEN value of the transaction, the value denotes the burst length - 1