Browse Source

merged changeds

master
Eyck Jentzsch 2 weeks ago
parent
commit
5766c45382
30 changed files with 1244 additions and 189 deletions
  1. +4
    -0
      CMakeLists.txt
  2. +4
    -4
      cmake/CodeCoverage.cmake
  3. +1
    -1
      cmake/Conan.cmake
  4. +4
    -4
      incl/scc/ordered_semaphore.h
  5. +16
    -8
      incl/scc/peq.h
  6. +6
    -6
      incl/scc/report.h
  7. +0
    -9
      incl/scc/tracer.h
  8. +20
    -2
      incl/scc/tracer_base.h
  9. +2
    -18
      incl/scv4tlm/tlm2_recorder.h
  10. +0
    -6
      incl/scv4tlm/tlm2_recorder_module.h
  11. +2
    -2
      incl/scv4tlm/tlm_recording_extension.h
  12. +12
    -14
      incl/tlm/ahb/ahb_tlm.h
  13. +0
    -2
      incl/tlm/ahb/bfm/initiator.h
  14. +0
    -2
      incl/tlm/ahb/bfm/target.h
  15. +156
    -0
      incl/tlm/ahb/pe/ahb_initiator.h
  16. +153
    -0
      incl/tlm/ahb/pe/ahb_target.h
  17. +148
    -0
      incl/tlm/apb/pe/apb_initiator.h
  18. +152
    -0
      incl/tlm/apb/pe/apb_target.h
  19. +31
    -0
      incl/tlm/atp/timing_params.h
  20. +3
    -0
      incl/tlm/tlm_mm.h
  21. +7
    -7
      incl/util/range_lut.h
  22. +162
    -0
      src/ahb_initiator.cpp
  23. +100
    -0
      src/ahb_target.cpp
  24. +76
    -0
      src/apb_initiator.cpp
  25. +112
    -0
      src/apb_target.cpp
  26. +4
    -1
      src/ordered_semaphore.cpp
  27. +46
    -46
      src/report.cpp
  28. +11
    -11
      src/tlm_ahb_bfm_initiator.cpp
  29. +11
    -11
      src/tlm_ahb_bfm_target.cpp
  30. +1
    -35
      src/tracer.cpp

+ 4
- 0
CMakeLists.txt View File

@ -71,6 +71,10 @@ set(LIB_SOURCES
src/jsoncpp.cpp
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
src/tracer.cpp
src/mt19937_rng.cpp

+ 4
- 4
cmake/CodeCoverage.cmake View File

@ -220,7 +220,7 @@ function(setup_target_for_coverage_lcov)
endif() # NOT GENHTML_PATH
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
if(${<span class="nv">Coverage_BASE_DIRECTORY})
if(Coverage_BASE_DIRECTORY)
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
else()
set(BASEDIR ${PROJECT_SOURCE_DIR})
@ -316,7 +316,7 @@ function(setup_target_for_coverage_gcovr_xml)
endif() # NOT GCOVR_PATH
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
if(${<span class="nv">Coverage_BASE_DIRECTORY})
if(Coverage_BASE_DIRECTORY)
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
else()
set(BASEDIR ${PROJECT_SOURCE_DIR})
@ -388,12 +388,12 @@ function(setup_target_for_coverage_gcovr_html)
endif() # NOT GCOVR_PATH
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
if(${<span class="nv">Coverage_BASE_DIRECTORY})
if(Coverage_BASE_DIRECTORY)
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
else()
set(BASEDIR ${PROJECT_SOURCE_DIR})
endif()
# Collect excludes (CMake 3.4+: Also compute absolute paths)
set(GCOVR_EXCLUDES "")
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})

+ 1
- 1
cmake/Conan.cmake View File

@ -1,5 +1,5 @@
macro(setup_conan)
set(options Release Debug TARGETS)
set(options Release Debug RelWithDebInfo TARGETS)
set(oneValueArgs PROFILE)
cmake_parse_arguments(MARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
if(MARGS_Release)

+ 4
- 4
incl/scc/ordered_semaphore.h View File

@ -70,12 +70,12 @@ public:
protected:
// support methods
bool in_use() {
bool avail = value > 0 && queue.front() == sc_core::sc_get_current_process_handle();
if(avail)
if(value > 0 && queue.front() == sc_core::sc_get_current_process_handle()){
queue.pop_front();
return (!avail);
return false;
} else
return true;
}
// error reporting

+ 16
- 8
incl/scc/peq.h View File

@ -63,16 +63,15 @@ template struct peq : public sc_core::sc_object {
boost::optional<TYPE> get_next() {
if(m_scheduled_events.empty())
return boost::none;
;
sc_core::sc_time now = sc_core::sc_time_stamp();
if(m_scheduled_events.begin()->first <= now) {
if(m_scheduled_events.begin()->first > now){
m_event.notify(m_scheduled_events.begin()->first - now);
return boost::none;
} else {
auto entry = m_scheduled_events.begin()->second;
m_scheduled_events.erase(m_scheduled_events.begin());
return entry;
}
m_event.notify(m_scheduled_events.begin()->first - now);
return boost::none;
;
}
/**
* blocking get
@ -80,12 +79,11 @@ template struct peq : public sc_core::sc_object {
* @return copy of the next entry.
*/
TYPE get() {
while(m_scheduled_events.empty() || m_scheduled_events.begin()->first >= sc_core::sc_time_stamp()) {
::sc_core::wait(m_event, simcontext());
while(!has_next()) {
sc_core::wait(event());
}
auto entry = m_scheduled_events.begin()->second;
m_scheduled_events.erase(m_scheduled_events.begin());
m_event.notify(m_scheduled_events.begin()->first - sc_core::sc_time_stamp());
return entry;
}
@ -97,6 +95,16 @@ template struct peq : public sc_core::sc_object {
m_event.cancel();
}
bool has_next() {
if(m_scheduled_events.empty()) return false;
sc_core::sc_time now = sc_core::sc_time_stamp();
if(m_scheduled_events.begin()->first > now){
m_event.notify(m_scheduled_events.begin()->first - now);
return false;
} else {
return true;
}
}
private:
std::multimap<const sc_core::sc_time, TYPE> m_scheduled_events;
sc_core::sc_event m_event;

+ 6
- 6
incl/scc/report.h View File

@ -131,19 +131,19 @@ inline sc_core::sc_verbosity get_log_verbosity(){
return static_cast<sc_core::sc_verbosity>(::sc_core::sc_report_handler::get_verbosity_level());
}
/**
* return a scope specific verbosity level if defined. Otherwise the global verbosity level
* return an scope specific verbosity level if defined. Otherwise the global verbosity level
* @param t
* @return
*/
inline sc_core::sc_verbosity get_log_verbosity(std::string const& t){
return get_log_verbosity(t.c_str());
}
sc_core::sc_verbosity get_log_verbosity(char const* t);
/**
* return an scope specific verbosity level if defined. Otherwise the global verbosity level
* return a scope specific verbosity level if defined. Otherwise the global verbosity level
* @param t
* @return
*/
sc_core::sc_verbosity get_log_verbosity(char const* t);
inline sc_core::sc_verbosity get_log_verbosity(std::string const& t){
return get_log_verbosity(t.c_str());
}
/**
* the logger class
*/

+ 0
- 9
incl/scc/tracer.h View File

@ -48,14 +48,6 @@ public:
* @param enable enable VCD (signal and POD) tracing
*/
tracer(const std::string&&, file_type, bool = true);
/**
* the constructor
*
* @param name base name of the trace file(s)
* @param type type of trace file for transactions
* @param the trace file to use for signal and POD tracing
*/
tracer(const std::string&&, file_type, sc_core::sc_trace_file* = nullptr);
/**
* the destructor
*/
@ -77,7 +69,6 @@ public:
protected:
void end_of_elaboration() override;
bool owned{false};
#ifdef WITH_SCV
scv_tr_db* txdb;
#endif

+ 20
- 2
incl/scc/tracer_base.h View File

@ -39,13 +39,29 @@ public:
tracer_base(const sc_core::sc_module_name& nm)
: sc_core::sc_module(nm) {}
tracer_base(const sc_core::sc_module_name& nm, sc_core::sc_trace_file* tf)
: sc_core::sc_module(nm), trf(tf) {}
tracer_base(const sc_core::sc_module_name& nm, sc_core::sc_trace_file* tf, bool owned=true)
: sc_core::sc_module(nm), trf(tf), owned(owned) {}
~tracer_base(){
if(trf && owned)
sc_close_vcd_trace_file(trf);
}
void set_trace_types(trace_types t){
types_to_trace=t;
}
const sc_core::sc_trace_file* get_trace_file() const {
return trf;
}
void set_trace_file(sc_core::sc_trace_file* trf) {
if(this->trf && owned)
sc_close_vcd_trace_file(trf);
this->trf=trf;
owned=false;
}
protected:
virtual void descend(const sc_core::sc_object*, bool trace_all = false);
@ -53,6 +69,8 @@ protected:
sc_core::sc_trace_file* trf{nullptr};
bool owned{false};
trace_types types_to_trace{trace_types::ALL};
};

+ 2
- 18
incl/scv4tlm/tlm2_recorder.h View File

@ -113,10 +113,10 @@ public:
id = reinterpret_cast<uintptr_t>(&x);
this->set_command(x.get_command());
this->set_address(x.get_address());
this->set_data_ptr(x.get_data_ptr());
this->set_data_ptr(nullptr);
this->set_data_length(x.get_data_length());
this->set_response_status(x.get_response_status());
this->set_byte_enable_ptr(x.get_byte_enable_ptr());
this->set_byte_enable_ptr(nullptr);
this->set_byte_enable_length(x.get_byte_enable_length());
this->set_streaming_width(x.get_streaming_width());
return (*this);
@ -306,10 +306,6 @@ public:
*/
const bool isRecordingEnabled() const { return m_db != NULL && enableTracing.value; }
protected:
sc_core::sc_clock* clk_if{nullptr};
sc_core::sc_time period{};
private:
//! event queue to hold time points of blocking transactions
tlm_utils::peq_with_cb_and_phase<tlm2_recorder, recording_types> b_timed_peq;
@ -339,7 +335,6 @@ private:
std::map<uint64, scv_tr_handle> btx_handle_map;
enum DIR { FW, BW };
scv_tr_generator<>* clk_gen{nullptr};
//! non-blocking transaction recording stream handle
std::vector<scv_tr_stream*> nb_streamHandle;
//! non-blocking transaction recording stream handle
@ -502,17 +497,6 @@ tlm::tlm_sync_enum tlm2_recorder::nb_transport_fw(typename TYPES::tlm_pay
"write", *nb_streamHandle[FW], "tlm_phase", "tlm_sync");
nb_fw_trHandle[tlm::TLM_IGNORE_COMMAND] = new scv_tr_generator<std::string, tlm::tlm_sync_enum>(
"ignore", *nb_streamHandle[FW], "tlm_phase", "tlm_sync");
if(clk_if){
clk_gen = new scv_tr_generator<>{"clock", *nb_streamHandle[FW]};
}
}
if(clk_if && clk_if->period()!=period) {
auto hndl = clk_gen->begin_transaction();
hndl.record_attribute("old_period", period/sc_core::sc_time(1, sc_core::SC_PS));
hndl.record_attribute("new_period", clk_if->period()/sc_core::sc_time(1, sc_core::SC_PS));
hndl.record_attribute("unit", "ps");
hndl.end_transaction();
period=clk_if->period();
}
/*************************************************************************
* prepare recording

+ 0
- 6
incl/scv4tlm/tlm2_recorder_module.h View File

@ -40,8 +40,6 @@ public:
tlm::tlm_target_socket<BUSWIDTH, TYPES, 1> ts{"ts"};
//! The initiator to be bound to the target socket
tlm::tlm_initiator_socket<BUSWIDTH, TYPES, 1> is{"is"};
//! (optional) port to get the clock period
sc_port<sc_signal_in_if<bool>,1,SC_ZERO_OR_MORE_BOUND> clk_i{"clk_i"};
/*! \brief The constructor of the component
*
* \param name is the SystemC module name of the recorder
@ -61,10 +59,6 @@ public:
virtual ~tlm2_recorder_module() {}
private:
void end_of_elaboration() override {
tlm2_recorder<TYPES>::clk_if = dynamic_cast<sc_core::sc_clock*>(clk_i.get_interface());
}
};
} // namespace scv4tlm

+ 2
- 2
incl/scv4tlm/tlm_recording_extension.h View File

@ -14,8 +14,8 @@
* limitations under the License.
*******************************************************************************/
#ifndef TLM_RECORDING_EXTENSION_H_
#define TLM_RECORDING_EXTENSION_H_
#ifndef _SCV4TLM_TLM_RECORDING_EXTENSION_H_
#define _SCV4TLM_TLM_RECORDING_EXTENSION_H_
#include <array>
#include <scv.h>

+ 12
- 14
incl/tlm/ahb/ahb_tlm.h View File

@ -12,7 +12,6 @@
#include <cstdint>
#include <tlm>
namespace tlm {
namespace ahb {
enum class lock_e : uint8_t { NORMAL = 0x0, EXLUSIVE = 0x1, LOCKED = 0x2 };
@ -51,9 +50,7 @@ struct ahb_extension : public tlm::tlm_extension {
uint8_t get_protection() const;
void set_protection(uint8_t);
uint8_t get_burst() const;
burst_e get_burst_e() const;
void set_burst(uint8_t);
burst_e get_burst() const;
void set_burst(burst_e);
/**
@ -84,6 +81,15 @@ private:
burst_e burst{burst_e::SINGLE};
};
/**
* definition of the additional protocol phases
*/
DECLARE_EXTENDED_PHASE(BEGIN_PARTIAL_RESP);
DECLARE_EXTENDED_PHASE(END_PARTIAL_RESP);
/*****************************************************************************
* Implementation details
*****************************************************************************/
inline bool ahb_extension::is_instruction() const { return prot & INSTR; }
inline void ahb_extension::set_instruction(bool instr) {
@ -128,14 +134,7 @@ inline bool ahb_extension::is_locked() const { return lock == lock_e::LOCKED; }
inline void ahb_extension::set_locked(bool locked) { lock = locked ? lock_e::LOCKED : lock_e::NORMAL; }
inline uint8_t ahb_extension::get_burst() const { return static_cast<uint8_t>(burst); }
inline burst_e ahb_extension::get_burst_e() const { return burst; }
inline void ahb_extension::set_burst(uint8_t b) {
assert(b <= static_cast<uint8_t>(burst_e::INCR16));
burst = static_cast<burst_e>(b);
}
inline burst_e ahb_extension::get_burst() const { return burst; }
inline void ahb_extension::set_burst(burst_e b) { burst = b; }
@ -148,6 +147,5 @@ inline void ahb_extension::copy_from(const tlm::tlm_extension_base& ext) {
}
} // namespace ahb
} // namespace tlm
#endif /* SYSTEMC_COMPONENTS_AHB_TLM_H_ */
#endif /* _AHB_TLM_H_ */

+ 0
- 2
incl/tlm/ahb/bfm/initiator.h View File

@ -13,7 +13,6 @@
#include <tlm_utils/peq_with_get.h>
#include <type_traits>
namespace tlm {
namespace ahb {
namespace bfm {
@ -55,6 +54,5 @@ private:
} /* namespace bfm */
} /* namespace ahb */
} /* namespace tlm */
#endif /* AHB_TARGET_BFM_H_ */

+ 0
- 2
incl/tlm/ahb/bfm/target.h View File

@ -11,7 +11,6 @@
#include <scc/initiator_mixin.h>
#include <tlm>
namespace tlm {
namespace ahb {
namespace bfm {
@ -50,6 +49,5 @@ private:
} /* namespace bfm */
} /* namespace ahb */
} /* namespace tlm */
#endif /* AHB_TARGET_BFM_H_ */

+ 156
- 0
incl/tlm/ahb/pe/ahb_initiator.h View File

@ -0,0 +1,156 @@
/*
* ahb_rn_initiator.h
*
* Created on: 16.03.2020
* Author: eyckj
*/
#ifndef _TLM_AHB_PE_AHB_INITIATOR_H_
#define _TLM_AHB_PE_AHB_INITIATOR_H_
#include <tlm/ahb/ahb_tlm.h>
#include <scc/ordered_semaphore.h>
#include <scc/peq.h>
#include <systemc>
#include <tlm_utils/peq_with_get.h>
#include <tuple>
#include <unordered_map>
namespace ahb {
namespace pe {
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);
using payload_type = tlm::tlm_generic_payload;
using phase_type = tlm::tlm_phase;
sc_core::sc_in<bool> clk_i{"clk_i"};
/** @defgroup bw_if Initiator backward interface
* @{
*/
tlm::tlm_sync_enum nb_transport_bw(payload_type& trans, phase_type& phase, sc_core::sc_time& t);
void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, sc_dt::uint64 end_range);
/** @} */ // end of bw_if
size_t get_transferwith_in_bytes() const { return transfer_width_in_bytes; }
/** @} */ // end of config
/**
* @brief The forward transport function. It behaves blocking and is re-entrant.
*
* This function initiates the forward transport either using b_transport() if blocking=true
* or the nb_transport_* interface.
*
* @param trans the transaction to send
* @param blocking execute in using the blocking interface
*/
void transport(payload_type& trans, bool blocking);
ahb_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);
virtual ~ahb_initiator_b();
ahb_initiator_b() = delete;
ahb_initiator_b(ahb_initiator_b const&) = delete;
ahb_initiator_b(ahb_initiator_b&&) = delete;
ahb_initiator_b& operator=(ahb_initiator_b const&) = delete;
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
sc_core::sc_attribute<unsigned> awtv{"awtv", 0};
//! Write data handshake to next beat valid
sc_core::sc_attribute<unsigned> wbv{"wbv", 0};
//! Read data valid to same beat ready
sc_core::sc_attribute<unsigned> rbr{"rbr", 0};
//! Write response valid to ready
sc_core::sc_attribute<unsigned> br{"br", 0};
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;
std::function<unsigned(payload_type& trans)>* snoop_cb{nullptr};
struct tx_state {
payload_type* active_tx{nullptr};
scc::peq<std::tuple<payload_type*, tlm::tlm_phase>> peq;
//scc::ordered_semaphore mtx{1};
};
std::unordered_map<payload_type*, tx_state*> tx_state_by_id;
scc::ordered_semaphore_t<1> addr_chnl;
scc::ordered_semaphore_t<1> data_chnl;
sc_core::sc_event any_tx_finished;
sc_core::sc_time clk_period{10, sc_core::SC_NS};
private:
sc_core::sc_clock* clk_if{nullptr};
void end_of_elaboration() override { clk_if = dynamic_cast<sc_core::sc_clock*>(clk_i.get_interface()); }
tlm::tlm_phase send(payload_type& trans, ahb_initiator_b::tx_state* txs, tlm::tlm_phase phase);
unsigned m_clock_counter{0};
unsigned m_prev_clk_cnt{0};
};
/**
* the ahb initiator socket protocol engine adapted to a particular initiator socket configuration
*/
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 ahb3_initiator : public ahb_initiator_b {
public:
using base = ahb_initiator_b;
using payload_type = base::payload_type;
using phase_type = base::phase_type;
/**
* @brief the constructor
* @param socket reference to the initiator socket used to send and receive transactions
*/
ahb3_initiator(const sc_core::sc_module_name& nm, tlm::tlm_initiator_socket<BUSWIDTH, TYPES, N, POL>& socket_)
: ahb_initiator_b(nm, socket_.get_base_port(), BUSWIDTH, false)
, socket(socket_) {
socket(*this);
}
ahb3_initiator() = delete;
ahb3_initiator(ahb3_initiator const&) = delete;
ahb3_initiator(ahb3_initiator&&) = delete;
ahb3_initiator& operator=(ahb3_initiator const&) = delete;
ahb3_initiator& operator=(ahb3_initiator&&) = delete;
private:
tlm::tlm_initiator_socket<BUSWIDTH, TYPES, N, POL>& socket;
};
} /* namespace pe */
} /* namespace ahb */
#endif /* OSCI_LIB_TLM_ahb_PE_ahb_RN_INITIATOR_H_ */

+ 153
- 0
incl/tlm/ahb/pe/ahb_target.h View File

@ -0,0 +1,153 @@
#ifndef _TLM_AHB_PE_AHB_TARGET_H_
#define SC_INCLUDE_DYNAMIC_PROCESSES
#include <tlm/ahb/ahb_tlm.h>
#include <array>
#include <functional>
#include <scc/ordered_semaphore.h>
#include <unordered_set>
namespace ahb {
namespace pe {
/**
* the target protocol engine base class
*/
class ahb_target_b : public sc_core::sc_module, public tlm::tlm_fw_transport_if<tlm::tlm_base_protocol_types> {
public:
SC_HAS_PROCESS(ahb_target_b);
using payload_type = tlm::tlm_base_protocol_types::tlm_payload_type;
using phase_type = tlm::tlm_base_protocol_types::tlm_phase_type;
sc_core::sc_in<bool> clk_i{"clk_i"};
/**
* @brief the latency between between BEGIN(_PARTIAL)_REQ and END(_PARTIAL)_REQ (AWVALID to AWREADY and WVALID to WREADY)
*/
sc_core::sc_attribute<unsigned> wr_data_accept_delay{"wr_data_accept_delay", 0};
/**
* @brief the latency between between BEGIN_REQ and END_REQ (ARVALID to ARREADY)
*/
sc_core::sc_attribute<unsigned> rd_addr_accept_delay{"rd_addr_accept_delay", 0};
/**
* @brief the latency between between END(_PARTIAL)_RESP and BEGIN(_PARTIAL)_RESP (RREADY to RVALID)
*/
sc_core::sc_attribute<unsigned> rd_data_beat_delay{"rd_data_beat_delay", 0};
/**
* @brief the latency between request and response phase. Will be overwritten by the return of the callback function (if registered)
*/
sc_core::sc_attribute<unsigned> rd_resp_delay{"rd_resp_delay", 0};
/**
* @brief the latency between request and response phase. Will be overwritten by the return of the callback function (if registered)
*/
sc_core::sc_attribute<unsigned> wr_resp_delay{"wr_resp_delay", 0};
/** @defgroup fw_if Initiator foreward interface
* @{
*/
void b_transport(payload_type& trans, sc_core::sc_time& t) override;
tlm::tlm_sync_enum nb_transport_fw(payload_type& trans, phase_type& phase, sc_core::sc_time& t) override;
bool get_direct_mem_ptr(payload_type& trans, tlm::tlm_dmi& dmi_data) override;
unsigned int transport_dbg(payload_type& trans) override;
/** @} */ // end of fw_if
/** @defgroup config Initiator configuration interface
* @{
*/
/**
* @brief Set the operation callback function
*
* This callback is invoked once a transaction arrives. This function is not allowed to block and returns the
* latency of the operation i.e. the duration until the reponse phase starts
* @todo refine API
*
* @param cb the callback function
*/
void set_operation_cb(std::function<unsigned(payload_type& trans)> cb) { operation_cb = cb; }
/**
*
* @param trans
* @param sync
*/
void operation_resp(payload_type& trans, bool sync = false);
protected:
/**
* the constructor. Protected as it should only be called by derived classes
* @param port
* @param transfer_width
*/
explicit ahb_target_b(const sc_core::sc_module_name& nm, sc_core::sc_port_b<tlm::tlm_bw_transport_if<tlm::tlm_base_protocol_types>>& port,
size_t transfer_width);
ahb_target_b() = delete;
ahb_target_b(ahb_target_b const&) = delete;
ahb_target_b(ahb_target_b&&) = delete;
ahb_target_b& operator=(ahb_target_b const&) = delete;
ahb_target_b& operator=(ahb_target_b&&) = delete;
void send_resp_thread();
sc_core::sc_port_b<tlm::tlm_bw_transport_if<tlm::tlm_base_protocol_types>>& socket_bw;
sc_core::sc_semaphore sn_sem{1};
sc_core::sc_mutex wr, rd, sn;
bool fast_resp{false};
bool fast_req{false};
std::function<unsigned(payload_type& trans)> operation_cb;
scc::ordered_semaphore rd_resp{1}, wr_resp{1};
sc_core::sc_clock* clk_if{nullptr};
void end_of_elaboration() override;
};
/**
* the target socket protocol engine adapted to a particular target socket configuration
*/
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 ahb3_target : public ahb_target_b {
public:
using base = ahb_target_b;
using payload_type = base::payload_type;
using phase_type = base::phase_type;
/**
* @brief the constructor
* @param socket reference to the initiator socket used to send and receive transactions
*/
ahb3_target(tlm::tlm_target_socket<BUSWIDTH, TYPES, N, POL>& socket)
: // @suppress("Class members should be properly initialized")
ahb3_target(sc_core::sc_gen_unique_name("simple_target"), socket) {}
ahb3_target(const sc_core::sc_module_name& nm, tlm::tlm_target_socket<BUSWIDTH, TYPES, N, POL>& socket)
: ahb_target_b(nm, socket.get_base_port(), BUSWIDTH)
, socket(socket) {
socket(*this);
}
ahb3_target() = delete;
ahb3_target(ahb3_target const&) = delete;
ahb3_target(ahb3_target&&) = delete;
ahb3_target& operator=(ahb3_target const&) = delete;
ahb3_target& operator=(ahb3_target&&) = delete;
private:
tlm::tlm_target_socket<BUSWIDTH, TYPES, N, POL>& socket;
};
} // namespace pe
} // namespace ahb
#endif

+ 148
- 0
incl/tlm/apb/pe/apb_initiator.h View File

@ -0,0 +1,148 @@
/*******************************************************************************
* Copyright (C) 2020, MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* Contributors:
* eyck@minres.com - initial API and implementation
******************************************************************************/
#ifndef _TLM_APB_PE_APB_INITIATOR_H_
#define _TLM_APB_PE_APB_INITIATOR_H_
#include <tlm>
#include <scc/peq.h>
#include <scc/ordered_semaphore.h>
namespace apb {
namespace pe {
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);
using payload_type = tlm::tlm_generic_payload;
using phase_type = tlm::tlm_phase;
sc_core::sc_in<bool> clk_i{"clk_i"};
/** @defgroup bw_if Initiator backward interface
* @{
*/
tlm::tlm_sync_enum nb_transport_bw(payload_type& trans, phase_type& phase, sc_core::sc_time& t);
void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, sc_dt::uint64 end_range);
/** @} */ // end of bw_if
size_t get_transferwith_in_bytes() const { return transfer_width_in_bytes; }
/** @} */ // end of config
/**
* @brief The forward transport function. It behaves blocking and is re-entrant.
*
* This function initiates the forward transport either using b_transport() if blocking=true
* or the nb_transport_* interface.
*
* @param trans the transaction to send
* @param blocking execute in using the blocking interface
*/
void transport(payload_type& trans, bool blocking);
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);
virtual ~apb_initiator_b();
apb_initiator_b() = delete;
apb_initiator_b(apb_initiator_b const&) = delete;
apb_initiator_b(apb_initiator_b&&) = delete;
apb_initiator_b& operator=(apb_initiator_b const&) = delete;
apb_initiator_b& operator=(apb_initiator_b&&) = delete;
protected:
const size_t transfer_width_in_bytes;
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;
sc_core::sc_time clk_period{10, sc_core::SC_NS};
private:
sc_core::sc_clock* clk_if{nullptr};
void end_of_elaboration() override { clk_if = dynamic_cast<sc_core::sc_clock*>(clk_i.get_interface()); }
unsigned m_clock_counter{0};
unsigned m_prev_clk_cnt{0};
};
/**
* the apb initiator socket protocol engine adapted to a particular initiator socket configuration
*/
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 apb_initiator : public apb_initiator_b {
public:
using base = apb_initiator_b;
using payload_type = base::payload_type;
using phase_type = base::phase_type;
/**
* @brief the constructor
* @param socket reference to the initiator socket used to send and receive transactions
*/
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);
}
apb_initiator() = delete;
apb_initiator(apb_initiator const&) = delete;
apb_initiator(apb_initiator&&) = delete;
apb_initiator& operator=(apb_initiator const&) = delete;
apb_initiator& operator=(apb_initiator&&) = delete;
private:
tlm::tlm_initiator_socket<BUSWIDTH, TYPES, N, POL>& socket;
};
} /* namespace pe */
} /* namespace apb */
#endif /* _TLM_APB_PE_APB_INITIATOR_H_ */

+ 152
- 0
incl/tlm/apb/pe/apb_target.h View File

@ -0,0 +1,152 @@
/*******************************************************************************
* Copyright (C) 2020, MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* Contributors:
* eyck@minres.com - initial API and implementation
******************************************************************************/
#ifndef _TLM_APB_PE_APB_TARGET_H_
#include <tlm>
#include <functional>
#include <scc/ordered_semaphore.h>
namespace apb {
namespace pe {
/**
* the target protocol engine base class
*/
class apb_target_b : public sc_core::sc_module, public tlm::tlm_fw_transport_if<tlm::tlm_base_protocol_types> {
public:
SC_HAS_PROCESS(apb_target_b);
using payload_type = tlm::tlm_base_protocol_types::tlm_payload_type;
using phase_type = tlm::tlm_base_protocol_types::tlm_phase_type;
sc_core::sc_in<bool> clk_i{"clk_i"};
/** @defgroup fw_if Initiator foreward interface
* @{
*/
void b_transport(payload_type& trans, sc_core::sc_time& t) override;
tlm::tlm_sync_enum nb_transport_fw(payload_type& trans, phase_type& phase, sc_core::sc_time& t) override;
bool get_direct_mem_ptr(payload_type& trans, tlm::tlm_dmi& dmi_data) override;
unsigned int transport_dbg(payload_type& trans) override;
/** @} */ // end of fw_if
/** @defgroup config Initiator configuration interface
* @{
*/
/**
* @brief Set the operation callback function
*
* This callback is invoked once a transaction arrives. This function is not allowed to block and returns the
* latency of the operation i.e. the duration until the reponse phase starts
* @todo refine API
*
* @param cb the callback function
*/
void set_operation_cb(std::function<unsigned(payload_type& trans)> cb) { operation_cb = cb; }
protected:
/**
* the constructor. Protected as it should only be called by derived classes
* @param port
* @param transfer_width
*/
explicit apb_target_b(const sc_core::sc_module_name& nm, sc_core::sc_port_b<tlm::tlm_bw_transport_if<tlm::tlm_base_protocol_types>>& port,
size_t transfer_width);
apb_target_b() = delete;
apb_target_b(apb_target_b const&) = delete;
apb_target_b(apb_target_b&&) = delete;
apb_target_b& operator=(apb_target_b const&) = delete;
apb_target_b& operator=(apb_target_b&&) = delete;
tlm::tlm_generic_payload* active_tx{nullptr};
void response();
sc_core::sc_port_b<tlm::tlm_bw_transport_if<tlm::tlm_base_protocol_types>>& socket_bw;
std::function<unsigned(payload_type& trans)> operation_cb;
sc_core::sc_clock* clk_if{nullptr};
void end_of_elaboration() override;
sc_core::sc_process_handle mhndl;
};
/**
* the target socket protocol engine adapted to a particular target socket configuration
*/
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 apb_target : public apb_target_b {
public:
using base = apb_target_b;
using payload_type = base::payload_type;
using phase_type = base::phase_type;
/**
* @brief the constructor
* @param socket reference to the initiator socket used to send and receive transactions
*/
apb_target(tlm::tlm_target_socket<BUSWIDTH, TYPES, N, POL>& socket)
: // @suppress("Class members should be properly initialized")
apb_target(sc_core::sc_gen_unique_name("simple_target"), socket) {}
apb_target(const sc_core::sc_module_name& nm, tlm::tlm_target_socket<BUSWIDTH, TYPES, N, POL>& socket)
: apb_target_b(nm, socket.get_base_port(), BUSWIDTH)
, socket(socket) {
socket(*this);
}
apb_target() = delete;
apb_target(apb_target const&) = delete;
apb_target(apb_target&&) = delete;
apb_target& operator=(apb_target const&) = delete;
apb_target& operator=(apb_target&&) = delete;
private:
tlm::tlm_target_socket<BUSWIDTH, TYPES, N, POL>& socket;
};
} // namespace pe
} // namespace ahb
#endif /*_TLM_APB_PE_APB_TARGET_H_*/

+ 31
- 0
incl/tlm/atp/timing_params.h View File

@ -0,0 +1,31 @@
#ifndef _TLM_TIMING_PARAMS_H_
#define _TLM_TIMING_PARAMS_H_
#include <tlm>
namespace atp {
struct timing_params : public tlm::tlm_extension<timing_params> {
tlm_extension_base* clone() const override {
timing_params* e = new timing_params(artv, awtv, wbv, rbr, br);
return e;
}
void copy_from(tlm_extension_base const& from) override { assert(false && "copy_from() not supported"); }
timing_params() = delete;
timing_params(unsigned artv, unsigned awtv, unsigned wbv, unsigned rbr, unsigned br)
: artv(artv)
, awtv(awtv)
, wbv(wbv)
, rbr(rbr)
, br(br) {}
const unsigned artv;
const unsigned awtv;
const unsigned wbv;
const unsigned rbr;
const unsigned br;
};
} // namespace atp
#endif /* _TLM_TIMING_PARAMS_H_ */

+ 3
- 0
incl/tlm/tlm_mm.h View File

@ -100,6 +100,9 @@ template typename tlm_mm::payload_type* tlm_mm::a
}
template <typename TYPES> void tlm_mm<TYPES>::free(tlm::tlm_generic_payload* trans) {
if(trans->get_data_ptr())
delete [] trans->get_data_ptr();
trans->set_data_ptr(nullptr);
trans->reset();
trans->~tlm_generic_payload();
allocator.free(trans);

+ 7
- 7
incl/util/range_lut.h View File

@ -67,18 +67,18 @@ public:
*
* @return the size of the underlying container
*/
size_t size() { return m_size; }
size_t size() const { return m_size; }
/**
* remove all entries from the lut
*/
void clear() { m_lut.clear(); }
void clear() { m_lut.clear(); m_size=0;}
/**
* get the entry T associated with a given address
*
* @param addr the address
* @return the entry belonging to the address
*/
inline T getEntry(uint64_t addr) {
inline T getEntry(uint64_t addr) const {
auto iter = m_lut.lower_bound(addr);
return (iter != m_lut.end() && (iter->second.type == END_RANGE || iter->first == addr)) ? iter->second.index
: null_entry;
@ -86,14 +86,14 @@ public:
/**
* validate the lookup table wrt. overlaps
*/
void validate();
void validate() const;
/**
* create a textual representation of the address map (address range->entry
* association)
*
* @return
*/
std::string toString();
std::string toString() const;
//! the null entry
const T null_entry;
@ -148,7 +148,7 @@ template inline bool range_lut::removeEntry(T i) {
return false;
}
template <typename T> inline void range_lut<T>::validate() {
template <typename T> inline void range_lut<T>::validate() const {
auto mapped = false;
for(auto iter = m_lut.begin(); iter != m_lut.end(); iter++) {
switch(iter->second.type) {
@ -175,7 +175,7 @@ template inline void range_lut::validate() {
}
}
template <typename T> inline std::string range_lut<T>::toString() {
template <typename T> inline std::string range_lut<T>::toString() const {
std::ostringstream buf;
for(auto iter = m_lut.begin(); iter != m_lut.end(); ++iter) {
switch(iter->second.type) {

+ 162
- 0
src/ahb_initiator.cpp View File

@ -0,0 +1,162 @@
/*
* axi_rn_initiator.cpp
*
* Created on: 16.03.2020
* Author: eyckj
*/
#include <tlm/ahb/pe/ahb_initiator.h>
#include <tlm/atp/timing_params.h>
#include <scc/report.h>
using namespace sc_core;
using namespace ahb;
using namespace ahb::pe;
namespace {
uint8_t log2n(uint8_t siz) { return ((siz > 1) ? 1 + log2n(siz >> 1) : 0); }
} // anonymous namespace
ahb_initiator_b::ahb_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)
, coherent(coherent) {
add_attribute(artv);
add_attribute(awtv);
add_attribute(wbv);
add_attribute(rbr);
add_attribute(br);
}
ahb_initiator_b::~ahb_initiator_b() {
for(auto& e : tx_state_by_id)
delete e.second;
}
tlm::tlm_sync_enum ahb_initiator_b::nb_transport_bw(payload_type& trans, phase_type& phase, sc_core::sc_time& t) {
auto it = tx_state_by_id.find(&trans);
sc_assert(it != tx_state_by_id.end());
it->second->peq.notify(std::make_tuple(&trans, phase), t);
return tlm::TLM_ACCEPTED;
}
void ahb_initiator_b::invalidate_direct_mem_ptr(sc_dt::uint64 start_range, sc_dt::uint64 end_range) {}
tlm::tlm_phase ahb_initiator_b::send(payload_type& trans, ahb_initiator_b::tx_state* txs, tlm::tlm_phase phase) {
sc_core::sc_time delay;
SCCTRACE(SCMOD) << "Send REQ";
tlm::tlm_sync_enum ret = socket_fw->nb_transport_fw(trans, phase, delay);
if(ret == tlm::TLM_UPDATED) {
wait(delay);
return phase;
} else {
auto entry = txs->peq.get();
sc_assert(std::get<0>(entry) == &trans);
return std::get<1>(entry);
}
}
void ahb_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 {
auto it = tx_state_by_id.find(&trans);
if(it == tx_state_by_id.end()) {
bool success;
std::tie(it, success) = tx_state_by_id.insert(std::make_pair(&trans, new tx_state()));
}
auto& txs = it->second;
auto timing_e = trans.set_extension<atp::timing_params>(nullptr);
txs->active_tx = &trans;
SCCTRACE(SCMOD) << "start transport req for id=" << &trans;
auto* ext = trans.get_extension<ahb::ahb_extension>();
/// Timing
auto delay_in_cycles = trans.is_read() ? timing_e ? timing_e->artv : artv.value : timing_e ? timing_e->awtv : awtv.value;
for(unsigned i = 0; i < delay_in_cycles; ++i)
wait(clk_i.posedge_event());
auto burst_length = 0U;
switch(ext->get_burst()){
case ahb::burst_e::SINGLE:
burst_length=1;
break;
case ahb::burst_e::INCR:
burst_length=1;
break;
case ahb::burst_e::WRAP4:
case ahb::burst_e::INCR4:
burst_length=4;
break;
case ahb::burst_e::WRAP8:
case ahb::burst_e::INCR8:
burst_length=8;
break;
case ahb::burst_e::WRAP16:
case ahb::burst_e::INCR16:
burst_length=16;
break;
}
tlm::tlm_phase next_phase{tlm::UNINITIALIZED_PHASE};
addr_chnl.wait();
SCCTRACE(SCMOD) << "starting read address phase of tx with id=" << &trans;
auto res = send(trans, txs, tlm::BEGIN_REQ);
if(res == ahb::BEGIN_PARTIAL_RESP || res == tlm::BEGIN_RESP)
next_phase=res;
else if(res != tlm::END_REQ)
SCCERR(SCMOD)<<"target did not repsond with END_REQ to a BEGIN_REQ";
wait(clk_i.posedge_event());
auto finished = false;
const auto exp_burst_length=burst_length;
data_chnl.wait();
addr_chnl.post();
do {
// waiting for response
auto entry = next_phase == tlm::UNINITIALIZED_PHASE ? txs->peq.get() : std::make_tuple(&trans, next_phase);
next_phase = tlm::UNINITIALIZED_PHASE;
// Handle optional CRESP response
if(std::get<0>(entry) == &trans && std::get<1>(entry) == tlm::BEGIN_RESP) {
SCCTRACE(SCMOD) << "received last beat of tx with id=" << &trans;
auto delay_in_cycles = timing_e ? (trans.is_read() ? timing_e->rbr : timing_e->br) : br.value;
for(unsigned i = 0; i < delay_in_cycles; ++i)
wait(clk_i.posedge_event());
trans.set_response_status(tlm::TLM_OK_RESPONSE);
burst_length--;
tlm::tlm_phase phase = tlm::END_RESP;
sc_time delay = clk_if ? clk_if->period() - 1_ps : SC_ZERO_TIME;
socket_fw->nb_transport_fw(trans, phase, delay);
if(burst_length)
SCCWARN(SCMOD) << "got wrong number of burst beats, expected "<<exp_burst_length<<", got "<<exp_burst_length-burst_length;
wait(clk_i.posedge_event());
finished = true;
} else if(std::get<0>(entry) == &trans && std::get<1>(entry) == ahb::BEGIN_PARTIAL_RESP) { // RDAT without CRESP case
SCCTRACE(SCMOD) << "received beat of tx with id=" << &trans;
auto delay_in_cycles = timing_e ? timing_e->rbr : rbr.value;
for(unsigned i = 0; i < delay_in_cycles; ++i)
wait(clk_i.posedge_event());
burst_length--;
tlm::tlm_phase phase = ahb::END_PARTIAL_RESP;
sc_time delay = clk_if ? clk_if->period() - 1_ps : SC_ZERO_TIME;
auto res = socket_fw->nb_transport_fw(trans, phase, delay);
if(res == tlm::TLM_UPDATED) {
next_phase = phase;
wait(delay);
}
}
} while(!finished);
data_chnl.post();
SCCTRACE(SCMOD) << "finished non-blocking protocol";
txs->active_tx = nullptr;
any_tx_finished.notify(SC_ZERO_TIME);
}
SCCTRACE(SCMOD) << "finished transport req for id=" << &trans;
}

+ 100
- 0
src/ahb_target.cpp View File

@ -0,0 +1,100 @@
/*******************************************************************************
* Copyright (C) 2020, MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* Contributors:
* eyck@minres.com - initial API and implementation
******************************************************************************/
#define SC_INCLUDE_DYNAMIC_PROCESSES
#include <tlm/ahb/pe/ahb_target.h>
#include <scc/report.h>
#include <systemc>
#include <tuple>
using namespace sc_core;
using namespace tlm;
using namespace ahb;
using namespace ahb::pe;
/******************************************************************************
* target
******************************************************************************/
ahb_target_b::ahb_target_b(const sc_core::sc_module_name& nm, sc_core::sc_port_b<tlm::tlm_bw_transport_if<tlm_base_protocol_types>>& port,
size_t transfer_width)
: sc_module(nm)
, socket_bw(port) {
add_attribute(wr_data_accept_delay);
add_attribute(rd_addr_accept_delay);
add_attribute(rd_data_beat_delay);
add_attribute(rd_resp_delay);
add_attribute(wr_resp_delay);
dont_initialize();
sensitive << clk_i.pos();
}
void ahb_target_b::end_of_elaboration() {
clk_if = dynamic_cast<sc_core::sc_clock*>(clk_i.get_interface());
}
void ahb_target_b::b_transport(payload_type& trans, sc_time& t) {
auto latency = operation_cb ? operation_cb(trans) : trans.is_read() ? rd_resp_delay.value : wr_resp_delay.value;
trans.set_dmi_allowed(false);
trans.set_response_status(tlm::TLM_OK_RESPONSE);
auto* i = clk_i.get_interface();
if(clk_if) {
t += clk_if->period() * latency;
}
}
tlm_sync_enum ahb_target_b::nb_transport_fw(payload_type& trans, phase_type& phase, sc_time& t){
//TODO:
}
bool ahb_target_b::get_direct_mem_ptr(payload_type& trans, tlm_dmi& dmi_data) {
trans.set_dmi_allowed(false);
return false;
}
unsigned int ahb_target_b::transport_dbg(payload_type& trans) { return 0; }
void ahb_target_b::operation_resp(payload_type& trans, bool sync){
//TODO
}
void ahb_target_b::send_resp_thread() {
while(true) {
// waiting for responses to send
//TODO
}
}

+ 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);