Browse Source

add APB initiator

master
Eyck Jentzsch 2 months ago
parent
commit
07255ecd5c
4 changed files with 95 additions and 19 deletions
  1. +1
    -0
      CMakeLists.txt
  2. +5
    -3
      incl/tlm/ahb/pe/ahb_initiator.h
  3. +13
    -16
      incl/tlm/apb/pe/apb_initiator.h
  4. +76
    -0
      src/apb_initiator.cpp

+ 1
- 0
CMakeLists.txt View File

@ -72,6 +72,7 @@ set(LIB_SOURCES
src/tlm_ahb_bfm_initiator.cpp
src/tlm_ahb_bfm_target.cpp
src/ahb_initiator.cpp
src/apb_initiator.cpp
src/ahb_target.cpp
src/apb_target.cpp
src/tracer_base.cpp

+ 5
- 3
incl/tlm/ahb/pe/ahb_initiator.h View File

@ -19,7 +19,7 @@
namespace ahb {
namespace pe {
class ahb_initiator_b : public sc_core::sc_module {
class ahb_initiator_b : public sc_core::sc_module, public tlm::tlm_bw_transport_if<tlm::tlm_base_protocol_types> {
public:
SC_HAS_PROCESS(ahb_initiator_b);
@ -64,6 +64,8 @@ public:
ahb_initiator_b& operator=(ahb_initiator_b&&) = delete;
void snoop_resp(payload_type& trans, bool sync = false){}
//! Read address valid to next read address valid
sc_core::sc_attribute<unsigned> artv{"artv", 0};
//! Write address valid to next write address valid
@ -95,9 +97,9 @@ protected:
};
std::unordered_map<payload_type*, tx_state*> tx_state_by_id;
scc::ordered_semaphore addr_chnl{1};
scc::ordered_semaphore_t<1> addr_chnl;
scc::ordered_semaphore data_chnl{1};
scc::ordered_semaphore_t<1> data_chnl;
sc_core::sc_event any_tx_finished;

+ 13
- 16
incl/tlm/apb/pe/apb_initiator.h View File

@ -35,12 +35,13 @@
#define _TLM_APB_PE_APB_INITIATOR_H_
#include <tlm>
#include <tlm_utils/peq_with_get.h>
#include <scc/peq.h>
#include <scc/ordered_semaphore.h>
namespace apb {
namespace pe {
class apb_initiator_b : public sc_core::sc_module {
class apb_initiator_b : public sc_core::sc_module, public tlm::tlm_bw_transport_if<tlm::tlm_base_protocol_types> {
public:
SC_HAS_PROCESS(apb_initiator_b);
@ -86,17 +87,13 @@ public:
apb_initiator_b& operator=(apb_initiator_b&&) = delete;
protected:
unsigned calculate_beats(payload_type& p) {
sc_assert(p.get_data_length() > 0);
return p.get_data_length() < transfer_width_in_bytes ? 1 : p.get_data_length() / transfer_width_in_bytes;
}
const size_t transfer_width_in_bytes;
const bool coherent;
sc_core::sc_port_b<tlm::tlm_fw_transport_if<tlm::tlm_base_protocol_types>>& socket_fw;
scc::peq<std::tuple<payload_type*, tlm::tlm_phase>> peq;
scc::ordered_semaphore_t<1> chnl;
sc_core::sc_event any_tx_finished;
@ -115,7 +112,7 @@ private:
*/
template <unsigned int BUSWIDTH = 32, typename TYPES = tlm::tlm_base_protocol_types, int N = 1,
sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
class apb3_initiator : public apb_initiator_b {
class apb_initiator : public apb_initiator_b {
public:
using base = apb_initiator_b;
@ -125,21 +122,21 @@ public:
* @brief the constructor
* @param socket reference to the initiator socket used to send and receive transactions
*/
apb3_initiator(const sc_core::sc_module_name& nm, tlm::tlm_initiator_socket<BUSWIDTH, TYPES, N, POL>& socket_)
apb_initiator(const sc_core::sc_module_name& nm, tlm::tlm_initiator_socket<BUSWIDTH, TYPES, N, POL>& socket_)
: apb_initiator_b(nm, socket_.get_base_port(), BUSWIDTH, false)
, socket(socket_) {
socket(*this);
}
apb3_initiator() = delete;
apb_initiator() = delete;
apb3_initiator(apb3_initiator const&) = delete;
apb_initiator(apb_initiator const&) = delete;
apb3_initiator(apb3_initiator&&) = delete;
apb_initiator(apb_initiator&&) = delete;
apb3_initiator& operator=(apb3_initiator const&) = delete;
apb_initiator& operator=(apb_initiator const&) = delete;
apb3_initiator& operator=(apb3_initiator&&) = delete;
apb_initiator& operator=(apb_initiator&&) = delete;
private:
tlm::tlm_initiator_socket<BUSWIDTH, TYPES, N, POL>& socket;

+ 76
- 0
src/apb_initiator.cpp View File

@ -0,0 +1,76 @@
/*
* axi_rn_initiator.cpp
*
* Created on: 16.03.2020
* Author: eyckj
*/
#include <tlm/apb/pe/apb_initiator.h>
#include <tlm/atp/timing_params.h>
#include <scc/report.h>
using namespace sc_core;
using namespace apb;
using namespace apb::pe;
namespace {
uint8_t log2n(uint8_t siz) { return ((siz > 1) ? 1 + log2n(siz >> 1) : 0); }
} // anonymous namespace
apb_initiator_b::apb_initiator_b(sc_core::sc_module_name nm,
sc_core::sc_port_b<tlm::tlm_fw_transport_if<tlm::tlm_base_protocol_types>>& port,
size_t transfer_width, bool coherent)
: sc_module(nm)
, socket_fw(port)
, transfer_width_in_bytes(transfer_width / 8)
{
}
apb_initiator_b::~apb_initiator_b() {
}
tlm::tlm_sync_enum apb_initiator_b::nb_transport_bw(payload_type& trans, phase_type& phase, sc_core::sc_time& t) {
peq.notify(std::make_tuple(&trans, phase), t);
return tlm::TLM_ACCEPTED;
}
void apb_initiator_b::invalidate_direct_mem_ptr(sc_dt::uint64 start_range, sc_dt::uint64 end_range) {}
void apb_initiator_b::transport(payload_type& trans, bool blocking) {
SCCTRACE(SCMOD) << "got transport req for id=" << &trans;
if(blocking) {
sc_time t;
socket_fw->b_transport(trans, t);
} else {
scc::ordered_semaphore::lock lock(chnl);
SCCTRACE(SCMOD) << "start transport req for id=" << &trans;
payload_type* gp{nullptr};
tlm::tlm_phase phase{tlm::BEGIN_REQ};
sc_time t;
auto res = socket_fw->nb_transport_fw(trans, phase, t);
if(res==tlm::TLM_COMPLETED || (res==tlm::TLM_UPDATED && phase!=tlm::END_REQ && phase!=tlm::BEGIN_RESP))
SCCFATAL(SCMOD)<<"target did not respsond with END_REQ or BEGIN_RESP to a BEGIN_REQ";
if(res!=tlm::TLM_UPDATED || phase != tlm::BEGIN_RESP) {
payload_type* gp{nullptr};
while(phase != tlm::BEGIN_RESP) {
std::tie(gp, phase) = peq.get();
if(gp!=&trans)
SCCFATAL(SCMOD)<<"target did send the wrong transaction";
if(phase!=tlm::END_REQ && phase!=tlm::BEGIN_RESP)
SCCFATAL(SCMOD)<<"target did not respsond with END_REQ or BEGIN_RESP to a BEGIN_REQ";
if(phase==tlm::END_REQ)
wait(clk_i.posedge_event());
}
}
phase=tlm::END_RESP;
t=SC_ZERO_TIME;
socket_fw->nb_transport_fw(trans, phase, t);
SCCTRACE(SCMOD) << "finished non-blocking protocol";
any_tx_finished.notify(SC_ZERO_TIME);
}
SCCTRACE(SCMOD) << "finished transport req for id=" << &trans;
}

Loading…
Cancel
Save