Added tlm3 recording sockets
This commit is contained in:
		
							
								
								
									
										722
									
								
								scv_tr_sqlite/scv4tlm/tlm2_recorder.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										722
									
								
								scv_tr_sqlite/scv4tlm/tlm2_recorder.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,722 @@ | |||||||
|  | /* | ||||||
|  |  * tlm_recording.h | ||||||
|  |  * | ||||||
|  |  *  Created on: 07.11.2015 | ||||||
|  |  *      Author: eyck | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef TLM2_RECORDER_H_ | ||||||
|  | #define TLM2_RECORDER_H_ | ||||||
|  |  | ||||||
|  | #include <scv.h> | ||||||
|  | #include <tlm> | ||||||
|  | #include "tlm_gp_data_ext.h" | ||||||
|  | #include "tlm_recording_extension.h" | ||||||
|  | #include <map> | ||||||
|  | #include <string> | ||||||
|  | #include <vector> | ||||||
|  |  | ||||||
|  | namespace scv4tlm { | ||||||
|  |  | ||||||
|  | /*! \brief The TLM2 transaction extensions recorder interface | ||||||
|  |  * | ||||||
|  |  * This interface is used by the TLM2 transaction recorder. It can be used to register custom recorder functionality | ||||||
|  |  * to also record the payload extensions | ||||||
|  |  */ | ||||||
|  | template< typename TYPES = tlm::tlm_base_protocol_types> | ||||||
|  | struct tlm2_extensions_recording_if { | ||||||
|  | 	/*! \brief recording attributes in extensions at the beginning, it is intended to be overload as it does nothing | ||||||
|  | 	 * | ||||||
|  | 	 */ | ||||||
|  | 	virtual void recordBeginTx(scv_tr_handle& handle, typename TYPES::tlm_payload_type& payload) = 0; | ||||||
|  |  | ||||||
|  | 	/*! \brief recording attributes in extensions at the end, it is intended to be overload as it does nothing | ||||||
|  | 	 * | ||||||
|  | 	 */ | ||||||
|  | 	virtual void recordEndTx(scv_tr_handle& handle, typename TYPES::tlm_payload_type& payload) = 0; | ||||||
|  |  | ||||||
|  | 	virtual ~tlm2_extensions_recording_if(){} | ||||||
|  | }; | ||||||
|  | /*! \brief The TLM2 transaction recorder | ||||||
|  |  * | ||||||
|  |  * This module records all TLM transaction to a SCV transaction stream for further viewing and analysis. | ||||||
|  |  * The handle of the created transaction is storee in an tlm_extension so that another instance of the scv_tlm2_recorder | ||||||
|  |  * e.g. further down the opath can link to it. | ||||||
|  |  */ | ||||||
|  | template< typename TYPES = tlm::tlm_base_protocol_types> | ||||||
|  | class tlm2_recorder: | ||||||
|  | 		public virtual tlm::tlm_fw_transport_if<TYPES>, | ||||||
|  | 		public virtual tlm::tlm_bw_transport_if<TYPES>, | ||||||
|  | 		public sc_core::sc_object { | ||||||
|  | public: | ||||||
|  | 	SC_HAS_PROCESS(tlm2_recorder<TYPES>); | ||||||
|  |  | ||||||
|  | 	//! \brief the attribute to selectively enable/disable recording | ||||||
|  | 	sc_core::sc_attribute<bool> enable; | ||||||
|  |  | ||||||
|  | 	//! \brief the attribute to selectively enable/disable timed recording | ||||||
|  | 	sc_core::sc_attribute<bool> enableTimed; | ||||||
|  |  | ||||||
|  | 	//! \brief the port where fw accesses are forwarded to | ||||||
|  | 	sc_core::sc_port<tlm::tlm_fw_transport_if<TYPES> > fw_port; | ||||||
|  |  | ||||||
|  | 	//! \brief the port where bw accesses are forwarded to | ||||||
|  | 	sc_core::sc_port<tlm::tlm_bw_transport_if<TYPES> > bw_port; | ||||||
|  |  | ||||||
|  | 	/*! \brief The constructor of the component | ||||||
|  | 	 * | ||||||
|  | 	 * \param name is the SystemC module name of the recorder | ||||||
|  | 	 * \param tr_db is a pointer to a transaction recording database. If none is provided the default one is retrieved. | ||||||
|  | 	 *        If this database is not initialized (e.g. by not calling scv_tr_db::set_default_db() ) recording is disabled. | ||||||
|  | 	 */ | ||||||
|  | 	tlm2_recorder(bool recording_enabled = true, scv_tr_db* tr_db = scv_tr_db::get_default_db()){ | ||||||
|  | 		this->tlm2_recorder::tlm2_recorder(sc_core::sc_gen_unique_name("tlm2_recorder"), recording_enabled, tr_db); | ||||||
|  | 	} | ||||||
|  | 	/*! \brief The constructor of the component | ||||||
|  | 	 * | ||||||
|  | 	 * \param name is the SystemC module name of the recorder | ||||||
|  | 	 * \param tr_db is a pointer to a transaction recording database. If none is provided the default one is retrieved. | ||||||
|  | 	 *        If this database is not initialized (e.g. by not calling scv_tr_db::set_default_db() ) recording is disabled. | ||||||
|  | 	 */ | ||||||
|  | 	tlm2_recorder(const char* name, bool recording_enabled = true, scv_tr_db* tr_db = scv_tr_db::get_default_db()) | ||||||
|  | 	: sc_core::sc_object(name) | ||||||
|  | 	, enable("enable", recording_enabled) | ||||||
|  | 	, enableTimed("enableTimed", recording_enabled) | ||||||
|  | 	, fw_port(sc_core::sc_gen_unique_name("fw")) | ||||||
|  | 	, bw_port(sc_core::sc_gen_unique_name("bw")) | ||||||
|  | 	, mm(new RecodingMemoryManager()) | ||||||
|  | 	, b_timed_peq(this, &tlm2_recorder::btx_cb) | ||||||
|  | 	, nb_timed_peq(this, &tlm2_recorder::nbtx_cb) | ||||||
|  | 	, m_db(tr_db) | ||||||
|  | 	, b_streamHandle(NULL) | ||||||
|  | 	, b_streamHandleTimed(NULL) | ||||||
|  | 	, b_trTimedHandle(3) | ||||||
|  | 	, nb_streamHandle(2) | ||||||
|  | 	, nb_streamHandleTimed(2) | ||||||
|  | 	, nb_fw_trHandle(3) | ||||||
|  | 	, nb_txReqHandle(3) | ||||||
|  | 	, nb_bw_trHandle(3) | ||||||
|  | 	, nb_txRespHandle(3) | ||||||
|  | 	, dmi_streamHandle(NULL) | ||||||
|  | 	, dmi_trGetHandle(NULL) | ||||||
|  | 	, dmi_trInvalidateHandle(NULL) | ||||||
|  | 	, extensionRecording(NULL) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	virtual ~tlm2_recorder(){ | ||||||
|  | 		delete b_streamHandle; | ||||||
|  | 		delete b_streamHandleTimed; | ||||||
|  | 		for(size_t i = 0; i<b_trTimedHandle.size(); ++i) delete b_trTimedHandle[i]; | ||||||
|  | 		for(size_t i = 0; i<nb_streamHandle.size(); ++i) delete nb_streamHandle[i]; | ||||||
|  | 		for(size_t i = 0; i<nb_streamHandleTimed.size(); ++i) delete nb_streamHandleTimed[i]; | ||||||
|  | 		for(size_t i = 0; i<nb_fw_trHandle.size(); ++i) delete nb_fw_trHandle[i]; | ||||||
|  | 		for(size_t i = 0; i<nb_txReqHandle.size(); ++i) delete nb_txReqHandle[i]; | ||||||
|  | 		for(size_t i = 0; i<nb_bw_trHandle.size(); ++i) delete nb_bw_trHandle[i]; | ||||||
|  | 		for(size_t i = 0; i<nb_txRespHandle.size(); ++i) delete nb_txRespHandle[i]; | ||||||
|  | 		delete dmi_streamHandle; | ||||||
|  | 		delete dmi_trGetHandle; | ||||||
|  | 		delete dmi_trInvalidateHandle; | ||||||
|  | 		delete extensionRecording; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// TLM-2.0 interface methods for initiator and target sockets, surrounded with Tx Recording | ||||||
|  | 	/*! \brief The non-blocking forward transport function | ||||||
|  | 	 * | ||||||
|  | 	 * This type of transaction is forwarded and recorded to a transaction stream named "nb_fw" with current timestamps. | ||||||
|  | 	 * \param trans is the generic payload of the transaction | ||||||
|  | 	 * \param phase is the current phase of the transaction | ||||||
|  | 	 * \param delay is the annotated delay | ||||||
|  | 	 * \return the sync state of the transaction | ||||||
|  | 	 */ | ||||||
|  | 	virtual tlm::tlm_sync_enum nb_transport_fw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase, | ||||||
|  | 			sc_core::sc_time& delay); | ||||||
|  |  | ||||||
|  | 	/*! \brief The non-blocking backward transport function | ||||||
|  | 	 * | ||||||
|  | 	 * This type of transaction is forwarded and recorded to a transaction stream named "nb_bw" with current timestamps. | ||||||
|  | 	 * \param trans is the generic payload of the transaction | ||||||
|  | 	 * \param phase is the current phase of the transaction | ||||||
|  | 	 * \param delay is the annotated delay | ||||||
|  | 	 * \return the sync state of the transaction | ||||||
|  | 	 */ | ||||||
|  | 	virtual tlm::tlm_sync_enum nb_transport_bw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase, | ||||||
|  | 			sc_core::sc_time& delay); | ||||||
|  |  | ||||||
|  | 	/*! \brief The blocking transport function | ||||||
|  | 	 * | ||||||
|  | 	 * This type of transaction is forwarded and recorded to a transaction stream named "b_tx" with current timestamps. Additionally a "b_tx_timed" | ||||||
|  | 	 * is been created recording the transactions at their annotated delay | ||||||
|  | 	 * \param trans is the generic payload of the transaction | ||||||
|  | 	 * \param delay is the annotated delay | ||||||
|  | 	 */ | ||||||
|  | 	virtual void b_transport(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay); | ||||||
|  |  | ||||||
|  | 	/*! \brief The direct memory interface forward function | ||||||
|  | 	 * | ||||||
|  | 	 * This type of transaction is just forwarded and not recorded. | ||||||
|  | 	 * \param trans is the generic payload of the transaction | ||||||
|  | 	 * \param dmi_data is the structure holding the dmi information | ||||||
|  | 	 * \return if the dmi structure is valid | ||||||
|  | 	 */ | ||||||
|  | 	virtual bool get_direct_mem_ptr(typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data); | ||||||
|  | 	/*! \brief The direct memory interface backward function | ||||||
|  | 	 * | ||||||
|  | 	 * This type of transaction is just forwarded and not recorded. | ||||||
|  | 	 * \param start_addr is the start address of the memory area being invalid | ||||||
|  | 	 * \param end_addr is the end address of the memory area being invalid | ||||||
|  | 	 */ | ||||||
|  | 	virtual void invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr); | ||||||
|  | 	/*! \brief The debug transportfunction | ||||||
|  | 	 * | ||||||
|  | 	 * This type of transaction is just forwarded and not recorded. | ||||||
|  | 	 * \param trans is the generic payload of the transaction | ||||||
|  | 	 * \return the sync state of the transaction | ||||||
|  | 	 */ | ||||||
|  | 	virtual unsigned int transport_dbg(typename TYPES::tlm_payload_type& trans); | ||||||
|  | 	/*! \brief get the current state of transaction recording | ||||||
|  | 	 * | ||||||
|  | 	 * \return if true transaction recording is enabled otherwise transaction recording is bypassed | ||||||
|  | 	 */ | ||||||
|  | 	const bool isRecordingEnabled() const { | ||||||
|  | 		return m_db != NULL && enable.value; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void setExtensionRecording(tlm2_extensions_recording_if<TYPES>* extensionRecording){ | ||||||
|  | 		this->extensionRecording=extensionRecording; | ||||||
|  | 	} | ||||||
|  | private: | ||||||
|  | 	//! \brief the struct to hold the information to be recorded on the timed streams | ||||||
|  | 	struct tlm_recording_payload: public TYPES::tlm_payload_type { | ||||||
|  | 		scv_tr_handle parent; | ||||||
|  | 		uint64 id; | ||||||
|  | 		tlm_recording_payload& operator=(const typename TYPES::tlm_payload_type& x){ | ||||||
|  | 			id=(uint64)&x; | ||||||
|  | 			set_command(x.get_command()); | ||||||
|  | 			set_address(x.get_address()); | ||||||
|  | 			set_data_ptr(x.get_data_ptr()); | ||||||
|  | 			set_data_length(x.get_data_length()); | ||||||
|  | 			set_response_status(x.get_response_status()); | ||||||
|  | 			set_byte_enable_ptr(x.get_byte_enable_ptr()); | ||||||
|  | 			set_byte_enable_length(x.get_byte_enable_length()); | ||||||
|  | 			set_streaming_width(x.get_streaming_width()); | ||||||
|  | 			return (*this); | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  | 		explicit tlm_recording_payload(tlm::tlm_mm_interface* mm) : | ||||||
|  | 				TYPES::tlm_payload_type(mm), parent(), id(0) { | ||||||
|  | 		} | ||||||
|  | 	}; | ||||||
|  | 	//! \brief Memory manager for the tlm_recording_payload | ||||||
|  | 	struct RecodingMemoryManager: public tlm::tlm_mm_interface { | ||||||
|  | 		RecodingMemoryManager() : | ||||||
|  | 				free_list(0), empties(0) { | ||||||
|  | 		} | ||||||
|  | 		tlm_recording_payload* allocate() { | ||||||
|  | 			typename TYPES::tlm_payload_type* ptr; | ||||||
|  | 			if (free_list) { | ||||||
|  | 				ptr = free_list->trans; | ||||||
|  | 				empties = free_list; | ||||||
|  | 				free_list = free_list->next; | ||||||
|  | 			} else { | ||||||
|  | 				ptr = new tlm_recording_payload(this); | ||||||
|  | 			} | ||||||
|  | 			return (tlm_recording_payload*) ptr; | ||||||
|  | 		} | ||||||
|  | 		void free(typename TYPES::tlm_payload_type* trans) { | ||||||
|  | 			trans->reset(); | ||||||
|  | 			if (!empties) { | ||||||
|  | 				empties = new access; | ||||||
|  | 				empties->next = free_list; | ||||||
|  | 				empties->prev = 0; | ||||||
|  | 				if (free_list) | ||||||
|  | 					free_list->prev = empties; | ||||||
|  | 			} | ||||||
|  | 			free_list = empties; | ||||||
|  | 			free_list->trans = trans; | ||||||
|  | 			empties = free_list->prev; | ||||||
|  | 		} | ||||||
|  | 	private: | ||||||
|  | 		struct access { | ||||||
|  | 			typename TYPES::tlm_payload_type* trans; | ||||||
|  | 			access* next; | ||||||
|  | 			access* prev; | ||||||
|  | 		}; | ||||||
|  | 		access *free_list, *empties; | ||||||
|  | 	}; | ||||||
|  | 	RecodingMemoryManager* mm; | ||||||
|  | 	//! peq type definition | ||||||
|  | 	struct recording_types { | ||||||
|  | 		typedef tlm_recording_payload tlm_payload_type; | ||||||
|  | 		typedef typename TYPES::tlm_phase_type tlm_phase_type; | ||||||
|  | 	}; | ||||||
|  | 	//! event queue to hold time points of blocking transactions | ||||||
|  | 	tlm_utils::peq_with_cb_and_phase<tlm2_recorder, recording_types> b_timed_peq; | ||||||
|  | 	//! event queue to hold time points of non-blocking transactions | ||||||
|  | 	tlm_utils::peq_with_cb_and_phase<tlm2_recorder, recording_types> nb_timed_peq; | ||||||
|  | 	/*! \brief The thread processing the blocking accesses with their annotated times | ||||||
|  | 	 *  to generate the timed view of blocking tx | ||||||
|  | 	 */ | ||||||
|  | 	void btx_cb(tlm_recording_payload& rec_parts, const typename TYPES::tlm_phase_type& phase); | ||||||
|  | 	/*! \brief The thread processing the non-blocking requests with their annotated times | ||||||
|  | 	 * to generate the timed view of non-blocking tx | ||||||
|  | 	 */ | ||||||
|  | 	void nbtx_cb(tlm_recording_payload& rec_parts, const typename TYPES::tlm_phase_type& phase); | ||||||
|  | 	//! transaction recording database | ||||||
|  | 	scv_tr_db* m_db; | ||||||
|  | 	//! blocking transaction recording stream handle | ||||||
|  | 	scv_tr_stream* b_streamHandle; | ||||||
|  | 	//! transaction generator handle for blocking transactions | ||||||
|  | 	scv_tr_generator<sc_dt::uint64, sc_dt::uint64>* b_trHandle[3]; | ||||||
|  | 	//! timed blocking transaction recording stream handle | ||||||
|  | 	scv_tr_stream* b_streamHandleTimed; | ||||||
|  | 	//! transaction generator handle for blocking transactions with annotated delays | ||||||
|  | 	std::vector<scv_tr_generator<tlm::tlm_command, tlm::tlm_response_status>*> b_trTimedHandle; | ||||||
|  | 	std::map<uint64, scv_tr_handle> btx_handle_map; | ||||||
|  |  | ||||||
|  | 	enum DIR{FW, BW}; | ||||||
|  | 	//! non-blocking transaction recording stream handle | ||||||
|  | 	std::vector<scv_tr_stream*> nb_streamHandle; | ||||||
|  | 	//! non-blocking transaction recording stream handle | ||||||
|  | 	std::vector<scv_tr_stream*> nb_streamHandleTimed; | ||||||
|  | 	//! transaction generator handle for forward non-blocking transactions | ||||||
|  | 	std::vector<scv_tr_generator<tlm::tlm_phase_enum, tlm::tlm_sync_enum>*> nb_fw_trHandle; | ||||||
|  | 	//! transaction generator handle for forward non-blocking transactions with annotated delays | ||||||
|  | 	std::vector<scv_tr_generator<>*> nb_txReqHandle; | ||||||
|  | 	map<uint64, scv_tr_handle> nbtx_req_handle_map; | ||||||
|  | 	//! transaction generator handle for backward non-blocking transactions | ||||||
|  | 	std::vector<scv_tr_generator<tlm::tlm_phase_enum, tlm::tlm_sync_enum>*> nb_bw_trHandle; | ||||||
|  | 	//! transaction generator handle for backward non-blocking transactions with annotated delays | ||||||
|  | 	std::vector<scv_tr_generator<>*> nb_txRespHandle; | ||||||
|  | 	map<uint64, scv_tr_handle> nbtx_last_req_handle_map; | ||||||
|  |  | ||||||
|  | 	//! dmi transaction recording stream handle | ||||||
|  | 	scv_tr_stream* dmi_streamHandle; | ||||||
|  | 	//! transaction generator handle for DMI transactions | ||||||
|  | 	scv_tr_generator<tlm_gp_data, tlm_dmi_data>* dmi_trGetHandle; | ||||||
|  | 	scv_tr_generator<sc_dt::uint64, sc_dt::uint64>* dmi_trInvalidateHandle; | ||||||
|  |  | ||||||
|  | 	tlm2_extensions_recording_if<TYPES>* extensionRecording; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|  | // implementations of functions | ||||||
|  | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|  |  | ||||||
|  |  | ||||||
|  | template< typename TYPES> | ||||||
|  | void tlm2_recorder<TYPES>::b_transport(typename TYPES::tlm_payload_type& trans, sc_core::sc_time& delay) { | ||||||
|  | 	tlm_recording_payload* req; | ||||||
|  | 	if (!isRecordingEnabled()) { | ||||||
|  | 		fw_port->b_transport(trans, delay); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	if (b_streamHandle == NULL) { | ||||||
|  | 		string basename(this->name()); | ||||||
|  | 		b_streamHandle = new scv_tr_stream((basename + ".blocking").c_str(), "TRANSACTOR", m_db); | ||||||
|  | 		b_trHandle[tlm::TLM_READ_COMMAND] = new scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("read", *b_streamHandle, "start_delay", | ||||||
|  | 				"end_delay"); | ||||||
|  | 		b_trHandle[tlm::TLM_WRITE_COMMAND] = new scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("write", *b_streamHandle, "start_delay", | ||||||
|  | 				"end_delay"); | ||||||
|  | 		b_trHandle[tlm::TLM_IGNORE_COMMAND] = new scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("ignore", *b_streamHandle, "start_delay", | ||||||
|  | 				"end_delay"); | ||||||
|  | 	} | ||||||
|  | 	// Get a handle for the new transaction | ||||||
|  | 	scv_tr_handle h = b_trHandle[trans.get_command()]->begin_transaction(delay.value(), sc_time_stamp()); | ||||||
|  | 	tlm_gp_data tgd(trans); | ||||||
|  |  | ||||||
|  | 	/************************************************************************* | ||||||
|  | 	 * do the timed notification | ||||||
|  | 	 *************************************************************************/ | ||||||
|  | 	if (enableTimed.value) { | ||||||
|  | 		req = mm->allocate(); | ||||||
|  | 		req->acquire(); | ||||||
|  | 		(*req) = trans; | ||||||
|  | 		req->parent = h; | ||||||
|  | 		req->id=h.get_id(); | ||||||
|  | #ifdef DEBUG | ||||||
|  | 		cout<<"notify addition of parent with id "<<req->id<<" to btx_handle_map with delay "<<delay<<std::endl; | ||||||
|  | #endif | ||||||
|  | 		b_timed_peq.notify(*req, tlm::BEGIN_REQ, delay); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if(extensionRecording) extensionRecording->recordBeginTx(h, trans); | ||||||
|  | 	tlm_recording_extension* preExt = NULL; | ||||||
|  |  | ||||||
|  | 	trans.get_extension(preExt); | ||||||
|  | 	if (preExt == NULL) { // we are the first recording this transaction | ||||||
|  | 		preExt = new tlm_recording_extension(h, this); | ||||||
|  | 		trans.set_extension(preExt); | ||||||
|  | 	} else { | ||||||
|  | 		h.add_relation(rel_str(PREDECESSOR_SUCCESSOR), preExt->txHandle); | ||||||
|  | 	} | ||||||
|  | 	scv_tr_handle preTx(preExt->txHandle); | ||||||
|  |  | ||||||
|  | 	fw_port->b_transport(trans, delay); | ||||||
|  | 	trans.get_extension(preExt); | ||||||
|  | 	if (preExt->get_creator() == this) { | ||||||
|  | 		// clean-up the extension if this is the original creator | ||||||
|  | 		delete preExt; | ||||||
|  | 		trans.set_extension((tlm_recording_extension*) NULL); | ||||||
|  | 	} else { | ||||||
|  | 		preExt->txHandle=preTx; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	tgd.set_response_status(trans.get_response_status()); | ||||||
|  | 	h.record_attribute("trans", tgd); | ||||||
|  | 	h.record_attribute("trans.data_value", *(uint64_t*)trans.get_data_ptr()); | ||||||
|  | 	if(extensionRecording) extensionRecording->recordEndTx(h, trans); | ||||||
|  | 	// End the transaction | ||||||
|  | 	b_trHandle[trans.get_command()]->end_transaction(h, delay.value(), sc_time_stamp()); | ||||||
|  | 	// and now the stuff for the timed tx | ||||||
|  | 	if (enableTimed.value){ | ||||||
|  | #ifdef DEBUG | ||||||
|  | 		cout<<"notify removal of parent with id "<<req->id<<" to btx_handle_map with delay "<<delay<<std::endl; | ||||||
|  | #endif | ||||||
|  | 		b_timed_peq.notify(*req, tlm::END_RESP, delay); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template< typename TYPES> | ||||||
|  | void tlm2_recorder<TYPES>::btx_cb(tlm_recording_payload& rec_parts, const typename TYPES::tlm_phase_type& phase) { | ||||||
|  | 	scv_tr_handle h; | ||||||
|  | 	if (b_trTimedHandle[0] == NULL) { | ||||||
|  | 		std::string basename(this->name()); | ||||||
|  | 		b_streamHandleTimed = new scv_tr_stream((basename + ".blocking_annotated").c_str(), "TRANSACTOR", m_db); | ||||||
|  | 		b_trTimedHandle[0] = new scv_tr_generator<tlm::tlm_command, tlm::tlm_response_status>("read", *b_streamHandleTimed); | ||||||
|  | 		b_trTimedHandle[1] = new scv_tr_generator<tlm::tlm_command, tlm::tlm_response_status>("write", *b_streamHandleTimed); | ||||||
|  | 		b_trTimedHandle[2] = new scv_tr_generator<tlm::tlm_command, tlm::tlm_response_status>("ignore", *b_streamHandleTimed); | ||||||
|  | 	} | ||||||
|  | 	// Now process outstanding recordings | ||||||
|  | 	switch (phase) { | ||||||
|  | 	case tlm::BEGIN_REQ: | ||||||
|  | 	{ | ||||||
|  | 		tlm_gp_data tgd(rec_parts); | ||||||
|  | 		h = b_trTimedHandle[rec_parts.get_command()]->begin_transaction(rec_parts.get_command()); | ||||||
|  | 		h.record_attribute("trans", tgd); | ||||||
|  | 		h.add_relation(rel_str(PARENT_CHILD), rec_parts.parent); | ||||||
|  | #ifdef DEBUG | ||||||
|  | 		cout<<"adding parent with id "<<rec_parts.id<<" to btx_handle_map"<<std::endl; | ||||||
|  | #endif | ||||||
|  | 		btx_handle_map[rec_parts.id] = h; | ||||||
|  | 	} | ||||||
|  | 	break; | ||||||
|  | 	case tlm::END_RESP: { | ||||||
|  | #ifdef DEBUG | ||||||
|  | 		cout<<"retrieving parent with id "<<rec_parts.id<<" from btx_handle_map"<<std::endl; | ||||||
|  | #endif | ||||||
|  | 		std::map<uint64, scv_tr_handle>::iterator it = btx_handle_map.find(rec_parts.id); | ||||||
|  | 		sc_assert(it != btx_handle_map.end()); | ||||||
|  | 		h = it->second; | ||||||
|  | 		btx_handle_map.erase(it); | ||||||
|  | 		h.end_transaction(h, rec_parts.get_response_status()); | ||||||
|  | 		rec_parts.release(); | ||||||
|  | 	} | ||||||
|  | 	break; | ||||||
|  | 	default: | ||||||
|  | 		sc_assert(!"phase not supported!"); | ||||||
|  | 	} | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template< typename TYPES> | ||||||
|  | tlm::tlm_sync_enum tlm2_recorder<TYPES>::nb_transport_fw( | ||||||
|  | 		typename TYPES::tlm_payload_type& trans, | ||||||
|  | 		typename TYPES::tlm_phase_type& phase, | ||||||
|  | 		sc_core::sc_time& delay) { | ||||||
|  | 	if (!isRecordingEnabled()) | ||||||
|  | 		return fw_port->nb_transport_fw(trans, phase, delay); | ||||||
|  | 	// initialize stream and generator if not yet done | ||||||
|  | 	if (nb_streamHandle[FW] == NULL) { | ||||||
|  | 		string basename(this->name()); | ||||||
|  | 		nb_streamHandle[FW] = new scv_tr_stream((basename + ".nb_forward").c_str(), "TRANSACTOR", m_db); | ||||||
|  | 		nb_fw_trHandle[tlm::TLM_READ_COMMAND] = new scv_tr_generator<tlm::tlm_phase_enum, tlm::tlm_sync_enum>("read", *nb_streamHandle[FW], "tlm_phase", "tlm_sync"); | ||||||
|  | 		nb_fw_trHandle[tlm::TLM_WRITE_COMMAND] = new scv_tr_generator<tlm::tlm_phase_enum, tlm::tlm_sync_enum>("write", *nb_streamHandle[FW], "tlm_phase", "tlm_sync"); | ||||||
|  | 		nb_fw_trHandle[tlm::TLM_IGNORE_COMMAND] = new scv_tr_generator<tlm::tlm_phase_enum, tlm::tlm_sync_enum>("ignore", *nb_streamHandle[FW], "tlm_phase", "tlm_sync"); | ||||||
|  | 	} | ||||||
|  | 	/************************************************************************* | ||||||
|  | 	 * prepare recording | ||||||
|  | 	 *************************************************************************/ | ||||||
|  | 	// Get a handle for the new transaction | ||||||
|  | 	scv_tr_handle h = nb_fw_trHandle[trans.get_command()]->begin_transaction((tlm::tlm_phase_enum) (unsigned) phase); | ||||||
|  | 	tlm_recording_extension* preExt = NULL; | ||||||
|  | 	trans.get_extension(preExt); | ||||||
|  | 	if (phase == tlm::BEGIN_REQ && preExt == NULL) { // we are the first recording this transaction | ||||||
|  | 		preExt = new tlm_recording_extension(h, this); | ||||||
|  | 		trans.set_extension(preExt); | ||||||
|  | 	} else if (preExt != NULL) { | ||||||
|  | 		// link handle if we have a predecessor | ||||||
|  | 		h.add_relation(rel_str(PREDECESSOR_SUCCESSOR), preExt->txHandle); | ||||||
|  | 	} else { | ||||||
|  | 		sc_assert(preExt!=NULL && "ERROR on forward path in phase other than tlm::BEGIN_REQ"); | ||||||
|  | 	} | ||||||
|  | 	// update the extension | ||||||
|  | 	preExt->txHandle = h; | ||||||
|  | 	h.record_attribute("delay", delay.to_string()); | ||||||
|  | 	if(extensionRecording) extensionRecording->recordBeginTx(h, trans); | ||||||
|  | 	tlm_gp_data tgd(trans); | ||||||
|  | 	/************************************************************************* | ||||||
|  | 	 * do the timed notification | ||||||
|  | 	 *************************************************************************/ | ||||||
|  | 	if (enableTimed.value) { | ||||||
|  | 		tlm_recording_payload* req = mm->allocate(); | ||||||
|  | 		req->acquire(); | ||||||
|  | 		(*req) = trans; | ||||||
|  | 		req->parent = h; | ||||||
|  | 		nb_timed_peq.notify(*req, phase, delay); | ||||||
|  | 	} | ||||||
|  | 	/************************************************************************* | ||||||
|  | 	 * do the access | ||||||
|  | 	 *************************************************************************/ | ||||||
|  | 	tlm::tlm_sync_enum status = fw_port->nb_transport_fw(trans, phase, delay); | ||||||
|  | 	/************************************************************************* | ||||||
|  | 	 * handle recording | ||||||
|  | 	 *************************************************************************/ | ||||||
|  | 	tgd.set_response_status(trans.get_response_status()); | ||||||
|  | 	h.record_attribute("trans", tgd); | ||||||
|  | 	if(extensionRecording) extensionRecording->recordEndTx(h, trans); | ||||||
|  | 	h.record_attribute("tlm_phase[return_path]", (tlm::tlm_phase_enum) (unsigned) phase); | ||||||
|  | 	h.record_attribute("delay[return_path]", delay.to_string()); | ||||||
|  | 	// get the extension and free the memory if it was mine | ||||||
|  | 	if (status == tlm::TLM_COMPLETED || (status == tlm::TLM_ACCEPTED && phase == tlm::END_RESP)) { | ||||||
|  | 		trans.get_extension(preExt); | ||||||
|  | 		if (preExt->get_creator() == this) { | ||||||
|  | 			delete preExt; | ||||||
|  | 			trans.set_extension((tlm_recording_extension*) NULL); | ||||||
|  | 		} | ||||||
|  | 		/************************************************************************* | ||||||
|  | 		 * do the timed notification if req. finished here | ||||||
|  | 		 *************************************************************************/ | ||||||
|  | 		tlm_recording_payload* req = mm->allocate(); | ||||||
|  | 		req->acquire(); | ||||||
|  | 		(*req) = trans; | ||||||
|  | 		req->parent = h; | ||||||
|  | 		nb_timed_peq.notify(*req, (status == tlm::TLM_COMPLETED && phase == tlm::BEGIN_REQ) ? tlm::END_RESP : phase, | ||||||
|  | 				delay); | ||||||
|  | 	} else if (status == tlm::TLM_UPDATED) { | ||||||
|  | 		tlm_recording_payload* req = mm->allocate(); | ||||||
|  | 		req->acquire(); | ||||||
|  | 		(*req) = trans; | ||||||
|  | 		req->parent = h; | ||||||
|  | 		nb_timed_peq.notify(*req, phase, delay); | ||||||
|  | 	} | ||||||
|  | 	// End the transaction | ||||||
|  | 	nb_fw_trHandle[trans.get_command()]->end_transaction(h, status); | ||||||
|  | 	return status; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | template< typename TYPES> | ||||||
|  | tlm::tlm_sync_enum tlm2_recorder<TYPES>::nb_transport_bw(typename TYPES::tlm_payload_type& trans, typename TYPES::tlm_phase_type& phase, | ||||||
|  | 		sc_core::sc_time& delay) { | ||||||
|  | 	if (!isRecordingEnabled()) | ||||||
|  | 		return bw_port->nb_transport_bw(trans, phase, delay); | ||||||
|  | 	if (nb_streamHandle[BW] == NULL) { | ||||||
|  | 		string basename(this->name()); | ||||||
|  | 		nb_streamHandle[BW] = new scv_tr_stream((basename + ".nb_backward").c_str(), "TRANSACTOR", m_db); | ||||||
|  | 		nb_bw_trHandle[0] = new scv_tr_generator<tlm::tlm_phase_enum, tlm::tlm_sync_enum>("read", *nb_streamHandle[BW], "tlm_phase", "tlm_sync"); | ||||||
|  | 		nb_bw_trHandle[1] = new scv_tr_generator<tlm::tlm_phase_enum, tlm::tlm_sync_enum>("write", *nb_streamHandle[BW], "tlm_phase", "tlm_sync"); | ||||||
|  | 		nb_bw_trHandle[2] = new scv_tr_generator<tlm::tlm_phase_enum, tlm::tlm_sync_enum>("ignore", *nb_streamHandle[BW], "tlm_phase", "tlm_sync"); | ||||||
|  | 	} | ||||||
|  | 	/************************************************************************* | ||||||
|  | 	 * prepare recording | ||||||
|  | 	 *************************************************************************/ | ||||||
|  | 	tlm_recording_extension* preExt = NULL; | ||||||
|  | 	trans.get_extension(preExt); | ||||||
|  | 	sc_assert(preExt!=NULL && "ERROR on backward path"); | ||||||
|  | 	// Get a handle for the new transaction | ||||||
|  | 	scv_tr_handle h = nb_bw_trHandle[trans.get_command()]->begin_transaction((tlm::tlm_phase_enum) (unsigned) phase); | ||||||
|  | 	// link handle if we have a predecessor and that's not ourself | ||||||
|  | 	h.add_relation(rel_str(PREDECESSOR_SUCCESSOR), preExt->txHandle); | ||||||
|  | 	// and set the extension handle to this transaction | ||||||
|  | 	preExt->txHandle = h; | ||||||
|  | 	h.record_attribute("delay", delay.to_string()); | ||||||
|  | 	if(extensionRecording) extensionRecording->recordBeginTx(h, trans); | ||||||
|  | 	tlm_gp_data tgd(trans); | ||||||
|  | 	/************************************************************************* | ||||||
|  | 	 * do the timed notification | ||||||
|  | 	 *************************************************************************/ | ||||||
|  | 	if (enableTimed.value) { | ||||||
|  | 		tlm_recording_payload* req = mm->allocate(); | ||||||
|  | 		req->acquire(); | ||||||
|  | 		(*req) = trans; | ||||||
|  | 		req->parent = h; | ||||||
|  | 		nb_timed_peq.notify(*req, phase, delay); | ||||||
|  | 	} | ||||||
|  | 	/************************************************************************* | ||||||
|  | 	 * do the access | ||||||
|  | 	 *************************************************************************/ | ||||||
|  | 	tlm::tlm_sync_enum status = bw_port->nb_transport_bw(trans, phase, delay); | ||||||
|  | 	/************************************************************************* | ||||||
|  | 	 * handle recording | ||||||
|  | 	 *************************************************************************/ | ||||||
|  | 	tgd.set_response_status(trans.get_response_status()); | ||||||
|  | 	h.record_attribute("trans", tgd); | ||||||
|  | 	if(extensionRecording) extensionRecording->recordEndTx(h, trans); | ||||||
|  | 	// phase and delay are already recorded | ||||||
|  | 	h.record_attribute("phase_upd", (tlm::tlm_phase_enum) (unsigned) phase); | ||||||
|  | 	h.record_attribute("delay_upd", delay.to_string()); | ||||||
|  | 	// End the transaction | ||||||
|  | 	nb_bw_trHandle[trans.get_command()]->end_transaction(h, status); | ||||||
|  | 	if (status == tlm::TLM_COMPLETED || (status == tlm::TLM_UPDATED && phase == tlm::END_RESP)) { | ||||||
|  | 		// the transaction is finished | ||||||
|  | 		trans.get_extension(preExt); | ||||||
|  | 		if (preExt->get_creator() == this) { | ||||||
|  | 			// clean-up the extension if this is the original creator | ||||||
|  | 			delete preExt; | ||||||
|  | 			trans.set_extension((tlm_recording_extension*) NULL); | ||||||
|  | 		} | ||||||
|  | 		/************************************************************************* | ||||||
|  | 		 * do the timed notification if req. finished here | ||||||
|  | 		 *************************************************************************/ | ||||||
|  | 		tlm_recording_payload* req = mm->allocate(); | ||||||
|  | 		req->acquire(); | ||||||
|  | 		(*req) = trans; | ||||||
|  | 		req->parent = h; | ||||||
|  | 		nb_timed_peq.notify(*req, phase, delay); | ||||||
|  | 	} | ||||||
|  | 	return status; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template< typename TYPES> | ||||||
|  | void tlm2_recorder<TYPES>::nbtx_cb(tlm_recording_payload& rec_parts, const typename TYPES::tlm_phase_type& phase) { | ||||||
|  | 	scv_tr_handle h; | ||||||
|  | 	std::map<uint64, scv_tr_handle>::iterator it; | ||||||
|  | 	if (nb_streamHandleTimed[FW] == NULL) { | ||||||
|  | 		std::string basename(this->name()); | ||||||
|  | 		nb_streamHandleTimed[FW] = new scv_tr_stream((basename + ".nb_request_annotated").c_str(), "TRANSACTOR", m_db); | ||||||
|  | 		nb_txReqHandle[0] = new scv_tr_generator<>("read", *nb_streamHandleTimed[FW]); | ||||||
|  | 		nb_txReqHandle[1] = new scv_tr_generator<>("write", *nb_streamHandleTimed[FW]); | ||||||
|  | 		nb_txReqHandle[2] = new scv_tr_generator<>("ignore", *nb_streamHandleTimed[FW]); | ||||||
|  | 	} | ||||||
|  | 	if (nb_streamHandleTimed[BW] == NULL) { | ||||||
|  | 		std::string basename(this->name()); | ||||||
|  | 		nb_streamHandleTimed[BW] = new scv_tr_stream((basename + ".nb_response_annotated").c_str(), "TRANSACTOR", m_db); | ||||||
|  | 		nb_txRespHandle[0] = new scv_tr_generator<>("read", *nb_streamHandleTimed[BW]); | ||||||
|  | 		nb_txRespHandle[1] = new scv_tr_generator<>("write", *nb_streamHandleTimed[BW]); | ||||||
|  | 		nb_txRespHandle[2] = new scv_tr_generator<>("ignore", *nb_streamHandleTimed[BW]); | ||||||
|  | 	} | ||||||
|  | 	tlm_gp_data tgd(rec_parts); | ||||||
|  | 	switch (phase) { // Now process outstanding recordings | ||||||
|  | 	case tlm::BEGIN_REQ: | ||||||
|  | 		h = nb_txReqHandle[rec_parts.get_command()]->begin_transaction(); | ||||||
|  | 		h.record_attribute("trans", tgd); | ||||||
|  | 		h.add_relation(rel_str(PARENT_CHILD), rec_parts.parent); | ||||||
|  | #ifdef NBDEBUG | ||||||
|  | 		cout<<"adding parent with id "<<rec_parts.id<<" to nbtx_req_handle_map"<<std::endl; | ||||||
|  | #endif | ||||||
|  | 		nbtx_req_handle_map[rec_parts.id] = h; | ||||||
|  | 		break; | ||||||
|  | 	case tlm::END_REQ: | ||||||
|  | #ifdef NBDEBUG | ||||||
|  | 		cout<<"retrieving parent with id "<<rec_parts.id<<" from nbtx_req_handle_map"<<std::endl; | ||||||
|  | #endif | ||||||
|  | 		it = nbtx_req_handle_map.find(rec_parts.id); | ||||||
|  | 		sc_assert(it != nbtx_req_handle_map.end()); | ||||||
|  | 		h = it->second; | ||||||
|  | 		nbtx_req_handle_map.erase(it); | ||||||
|  | 		h.end_transaction(); | ||||||
|  | 		nbtx_last_req_handle_map[rec_parts.id] = h; | ||||||
|  | 		break; | ||||||
|  | 	case tlm::BEGIN_RESP: | ||||||
|  | #ifdef NBDEBUG | ||||||
|  | 		cout<<"retrieving parent with id "<<rec_parts.id<<" from nbtx_req_handle_map"<<std::endl; | ||||||
|  | #endif | ||||||
|  | 		it = nbtx_req_handle_map.find(rec_parts.id); | ||||||
|  | 		if (it != nbtx_req_handle_map.end()) { | ||||||
|  | 			h = it->second; | ||||||
|  | 			nbtx_req_handle_map.erase(it); | ||||||
|  | 			h.end_transaction(); | ||||||
|  | 			nbtx_last_req_handle_map[rec_parts.id] = h; | ||||||
|  | 		} | ||||||
|  | 		h = nb_txRespHandle[rec_parts.get_command()]->begin_transaction(); | ||||||
|  | 		h.record_attribute("trans", tgd); | ||||||
|  | 		h.add_relation(rel_str(PARENT_CHILD), rec_parts.parent); | ||||||
|  | 		nbtx_req_handle_map[rec_parts.id] = h; | ||||||
|  | 		it = nbtx_last_req_handle_map.find(rec_parts.id); | ||||||
|  | 		if (it != nbtx_last_req_handle_map.end()) { | ||||||
|  | 			scv_tr_handle pred = it->second; | ||||||
|  | 			nbtx_last_req_handle_map.erase(it); | ||||||
|  | 			h.add_relation(rel_str(PREDECESSOR_SUCCESSOR), pred); | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	case tlm::END_RESP: | ||||||
|  | #ifdef NBDEBUG | ||||||
|  | 		cout<<"retrieving parent with id "<<rec_parts.id<<" from nbtx_req_handle_map"<<std::endl; | ||||||
|  | #endif | ||||||
|  | 		it = nbtx_req_handle_map.find(rec_parts.id); | ||||||
|  | 		if (it != nbtx_req_handle_map.end()) { | ||||||
|  | 			h = it->second; | ||||||
|  | 			nbtx_req_handle_map.erase(it); | ||||||
|  | 			h.end_transaction(); | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		sc_assert(!"phase not supported!"); | ||||||
|  | 	} | ||||||
|  | 	rec_parts.release(); | ||||||
|  | 	return; | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template< typename TYPES> | ||||||
|  | bool tlm2_recorder<TYPES>::get_direct_mem_ptr(typename TYPES::tlm_payload_type& trans, tlm::tlm_dmi& dmi_data) { | ||||||
|  | 	if (!isRecordingEnabled()) { | ||||||
|  | 		return fw_port->get_direct_mem_ptr(trans, dmi_data); | ||||||
|  | 	} | ||||||
|  | 	if (dmi_streamHandle == NULL) { | ||||||
|  | 		string basename(this->name()); | ||||||
|  | 		dmi_streamHandle = new scv_tr_stream((basename + ".dmi").c_str(), "TRANSACTOR", m_db); | ||||||
|  | 		dmi_trGetHandle = new scv_tr_generator<tlm_gp_data, tlm_dmi_data>("get_dmi_ptr", *b_streamHandle, "trans", | ||||||
|  | 				"dmi_data"); | ||||||
|  | 		dmi_trInvalidateHandle = new scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("invalidate", *b_streamHandle, "start_delay", | ||||||
|  | 				"end_delay"); | ||||||
|  | 	} | ||||||
|  | 	scv_tr_handle h = dmi_trGetHandle->begin_transaction(tlm_gp_data(trans)); | ||||||
|  | 	bool status= fw_port->get_direct_mem_ptr(trans, dmi_data); | ||||||
|  | 	dmi_trGetHandle->end_transaction(h, tlm_dmi_data(dmi_data)); | ||||||
|  | 	return status; | ||||||
|  | } | ||||||
|  | /*! \brief The direct memory interface backward function | ||||||
|  |  * | ||||||
|  |  * This type of transaction is just forwarded and not recorded. | ||||||
|  |  * \param start_addr is the start address of the memory area being invalid | ||||||
|  |  * \param end_addr is the end address of the memory area being invalid | ||||||
|  |  */ | ||||||
|  | template< typename TYPES> | ||||||
|  | void tlm2_recorder<TYPES>::invalidate_direct_mem_ptr(sc_dt::uint64 start_addr, sc_dt::uint64 end_addr) { | ||||||
|  | 	if (!isRecordingEnabled()) { | ||||||
|  | 		bw_port->invalidate_direct_mem_ptr(start_addr, end_addr); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	if (dmi_streamHandle == NULL) { | ||||||
|  | 		string basename(this->name()); | ||||||
|  | 		dmi_streamHandle = new scv_tr_stream((basename + ".dmi").c_str(), "TRANSACTOR", m_db); | ||||||
|  | 		dmi_trGetHandle = new scv_tr_generator<tlm_gp_data, tlm_dmi_data>("get_dmi_ptr", *b_streamHandle, "trans", | ||||||
|  | 				"dmi_data"); | ||||||
|  | 		dmi_trInvalidateHandle = new scv_tr_generator<sc_dt::uint64, sc_dt::uint64>("invalidate", *b_streamHandle, "start_delay", | ||||||
|  | 				"end_delay"); | ||||||
|  | 	} | ||||||
|  | 	scv_tr_handle h = dmi_trInvalidateHandle->begin_transaction(start_addr); | ||||||
|  | 	bw_port->invalidate_direct_mem_ptr(start_addr, end_addr); | ||||||
|  | 	dmi_trInvalidateHandle->end_transaction(h, end_addr); | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  | /*! \brief The debug transportfunction | ||||||
|  |  * | ||||||
|  |  * This type of transaction is just forwarded and not recorded. | ||||||
|  |  * \param trans is the generic payload of the transaction | ||||||
|  |  * \return the sync state of the transaction | ||||||
|  |  */ | ||||||
|  | template< typename TYPES> | ||||||
|  | unsigned int tlm2_recorder<TYPES>::transport_dbg(typename TYPES::tlm_payload_type& trans) { | ||||||
|  | 	unsigned int count = fw_port->transport_dbg(trans); | ||||||
|  | 	return count; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | } // namespace | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #endif /* TLM2_RECORDER_H_ */ | ||||||
							
								
								
									
										61
									
								
								scv_tr_sqlite/scv4tlm/tlm2_recorder_module.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								scv_tr_sqlite/scv4tlm/tlm2_recorder_module.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | |||||||
|  | /* | ||||||
|  |  * tlm_recorder.h | ||||||
|  |  * | ||||||
|  |  *  Created on: 07.11.2015 | ||||||
|  |  *      Author: eyck | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef TLM2_RECORDER_MODULE_H_ | ||||||
|  | #define TLM2_RECORDER_MODULE_H_ | ||||||
|  |  | ||||||
|  | #include <tlm_utils/simple_initiator_socket.h> | ||||||
|  | #include <tlm_utils/simple_target_socket.h> | ||||||
|  | #include "tlm2_recorder.h" | ||||||
|  |  | ||||||
|  | namespace scv4tlm { | ||||||
|  | /*! \brief The TLM2 transaction recorder | ||||||
|  |  * | ||||||
|  |  * This module records all TLM transaction to a SCV transaction stream for further viewing and analysis. | ||||||
|  |  * The handle of the created transaction is storee in an tlm_extension so that another instance of the scv_tlm2_recorder | ||||||
|  |  * e.g. further down the opath can link to it. | ||||||
|  |  * The transaction recorder is simply bound between an existing pair of initiator and target sockets | ||||||
|  |  */ | ||||||
|  | template<unsigned int BUSWIDTH = 32, typename TYPES=tlm::tlm_base_protocol_types> | ||||||
|  | class tlm2_recorder_module: public sc_core::sc_module, public tlm2_recorder<TYPES> { | ||||||
|  | public: | ||||||
|  | 	SC_HAS_PROCESS(tlm2_recorder_module); | ||||||
|  | 	//! The target socket of the recorder to be bound to the initiator | ||||||
|  | 	tlm::tlm_target_socket<BUSWIDTH, TYPES, 1> target; | ||||||
|  | 	//! The initiator to be bound to the target socket | ||||||
|  | 	tlm::tlm_initiator_socket<BUSWIDTH, TYPES, 1> initiator; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	/*! \brief The constructor of the component | ||||||
|  | 	 * | ||||||
|  | 	 * \param name is the SystemC module name of the recorder | ||||||
|  | 	 * \param tr_db is a pointer to a transaction recording database. If none is provided the default one is retrieved. | ||||||
|  | 	 *        If this database is not initialized (e.g. by not calling scv_tr_db::set_default_db() ) recording is disabled. | ||||||
|  | 	 */ | ||||||
|  | 	tlm2_recorder_module(sc_core::sc_module_name name, bool recording_enabled = true, scv_tr_db* tr_db = scv_tr_db::get_default_db()) | ||||||
|  | 	: sc_module(name) | ||||||
|  | 	, tlm2_recorder<TYPES>(recording_enabled, tr_db) | ||||||
|  | 	{ | ||||||
|  | 		// bind the sockets to the module | ||||||
|  | 		target.bind(*this); | ||||||
|  | 		initiator.bind(*this); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	virtual ~tlm2_recorder_module(){} | ||||||
|  |  | ||||||
|  | 	virtual tlm::tlm_fw_transport_if<tlm::tlm_base_protocol_types>* get_fw_if() { | ||||||
|  | 		return initiator.get_base_port().operator->(); | ||||||
|  | 	} | ||||||
|  | 	virtual tlm::tlm_bw_transport_if<tlm::tlm_base_protocol_types>* get_bw_if() { | ||||||
|  | 		return target.get_base_port().operator->(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | }; | ||||||
|  | } // namespace | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #endif /* TLM2_RECORDER_MODULE_H_ */ | ||||||
							
								
								
									
										557
									
								
								scv_tr_sqlite/scv4tlm/tlm_gp_data.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										557
									
								
								scv_tr_sqlite/scv4tlm/tlm_gp_data.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,557 @@ | |||||||
|  | /* | ||||||
|  |  * tlm_gp_data.h | ||||||
|  |  * | ||||||
|  |  *  Created on: 07.11.2015 | ||||||
|  |  *      Author: eyck | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef TLM_GP_DATA_H_ | ||||||
|  | #define TLM_GP_DATA_H_ | ||||||
|  |  | ||||||
|  | #include <tlm> | ||||||
|  | #include <assert.h> | ||||||
|  |  | ||||||
|  | namespace scv4tlm { | ||||||
|  |  | ||||||
|  | struct tlm_gp_data { | ||||||
|  | 	//--------------- | ||||||
|  | 	// Constructors | ||||||
|  | 	//--------------- | ||||||
|  |  | ||||||
|  | 	// Default constructor | ||||||
|  | 	tlm_gp_data() | ||||||
|  | 	: address(0) | ||||||
|  | 	, command(tlm::TLM_IGNORE_COMMAND) | ||||||
|  | 	, data(0) | ||||||
|  | 	, data_length(0) | ||||||
|  | 	, response_status(tlm::TLM_INCOMPLETE_RESPONSE) | ||||||
|  | 	, dmi(false) | ||||||
|  | 	, byte_enable(0) | ||||||
|  | 	, byte_enable_length(0) | ||||||
|  | 	, streaming_width(0) | ||||||
|  | 	, gp_option(tlm::TLM_MIN_PAYLOAD) | ||||||
|  | 	, m_extensions(tlm::max_num_extensions()) | ||||||
|  | 	, m_ref_count(0) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	explicit tlm_gp_data(tlm::tlm_mm_interface* mm) | ||||||
|  | 	: address(0) | ||||||
|  | 	, command(tlm::TLM_IGNORE_COMMAND) | ||||||
|  | 	, data(0) | ||||||
|  | 	, data_length(0) | ||||||
|  | 	, response_status(tlm::TLM_INCOMPLETE_RESPONSE) | ||||||
|  | 	, dmi(false) | ||||||
|  | 	, byte_enable(0) | ||||||
|  | 	, byte_enable_length(0) | ||||||
|  | 	, streaming_width(0) | ||||||
|  | 	, gp_option(tlm::TLM_MIN_PAYLOAD) | ||||||
|  | 	, m_extensions(tlm::max_num_extensions()) | ||||||
|  | 	, m_ref_count(0) { | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	int get_ref_count() const { | ||||||
|  | 		return m_ref_count; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void reset() { | ||||||
|  | 		//should the other members be reset too? | ||||||
|  | 		gp_option = tlm::TLM_MIN_PAYLOAD; | ||||||
|  | 		m_extensions.free_entire_cache(); | ||||||
|  | 	} | ||||||
|  | 	; | ||||||
|  |  | ||||||
|  | 	tlm_gp_data(const tlm::tlm_generic_payload& x) | ||||||
|  | 	: address(x.get_address()) | ||||||
|  | 	, command(x.get_command()) | ||||||
|  | 	, data(x.get_data_ptr()) | ||||||
|  | 	, data_length(x.get_data_length()) | ||||||
|  | 	, response_status(x.get_response_status()) | ||||||
|  | 	, dmi(x.is_dmi_allowed()) | ||||||
|  | 	, byte_enable(x.get_byte_enable_ptr()) | ||||||
|  | 	, byte_enable_length(x.get_byte_enable_length()) | ||||||
|  | 	, streaming_width(x.get_streaming_width()) | ||||||
|  | 	, gp_option(x.get_gp_option()) | ||||||
|  | 	, m_extensions(tlm::max_num_extensions()) | ||||||
|  | 	, m_ref_count(0) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  | private: | ||||||
|  | 	//disabled copy ctor and assignment operator. | ||||||
|  | 	// Copy constructor | ||||||
|  | 	tlm_gp_data(const tlm_gp_data& x) | ||||||
|  | 	: address(x.get_address()) | ||||||
|  | 	, command(x.get_command()) | ||||||
|  | 	, data(x.get_data_ptr()) | ||||||
|  | 	, data_length(x.get_data_length()) | ||||||
|  | 	, response_status(x.get_response_status()) | ||||||
|  | 	, dmi(x.is_dmi_allowed()) | ||||||
|  | 	, byte_enable(x.get_byte_enable_ptr()) | ||||||
|  | 	, byte_enable_length(x.get_byte_enable_length()) | ||||||
|  | 	, streaming_width(x.get_streaming_width()) | ||||||
|  | 	, gp_option(x.gp_option) | ||||||
|  | 	, m_extensions(tlm::max_num_extensions()) | ||||||
|  | 	, m_ref_count(0) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  | public: | ||||||
|  | 	// Assignment operator needed for SCV introspection | ||||||
|  | 	tlm_gp_data& operator=(const tlm_gp_data& x) { | ||||||
|  | 		command = x.get_command(); | ||||||
|  | 		address = x.get_address(); | ||||||
|  | 		data = x.get_data_ptr(); | ||||||
|  | 		data_length = x.get_data_length(); | ||||||
|  | 		response_status = x.get_response_status(); | ||||||
|  | 		byte_enable = x.get_byte_enable_ptr(); | ||||||
|  | 		byte_enable_length = x.get_byte_enable_length(); | ||||||
|  | 		streaming_width = x.get_streaming_width(); | ||||||
|  | 		gp_option = x.get_gp_option(); | ||||||
|  | 		dmi = x.is_dmi_allowed(); | ||||||
|  |  | ||||||
|  | 		// extension copy: all extension arrays must be of equal size by | ||||||
|  | 		// construction (i.e. it must either be constructed after C++ | ||||||
|  | 		// static construction time, or the resize_extensions() method must | ||||||
|  | 		// have been called prior to using the object) | ||||||
|  | 		for (unsigned int i = 0; i < m_extensions.size(); i++) { | ||||||
|  | 			m_extensions[i] = x.get_extension(i); | ||||||
|  | 		} | ||||||
|  | 		return (*this); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// non-virtual deep-copying of the object | ||||||
|  | 	void deep_copy_from(const scv4tlm::tlm_gp_data & other) { | ||||||
|  | 		command = other.get_command(); | ||||||
|  | 		address = other.get_address(); | ||||||
|  | 		data_length = other.get_data_length(); | ||||||
|  | 		response_status = other.get_response_status(); | ||||||
|  | 		byte_enable_length = other.get_byte_enable_length(); | ||||||
|  | 		streaming_width = other.get_streaming_width(); | ||||||
|  | 		gp_option = other.get_gp_option(); | ||||||
|  | 		dmi = other.is_dmi_allowed(); | ||||||
|  |  | ||||||
|  | 		// deep copy data | ||||||
|  | 		// there must be enough space in the target transaction! | ||||||
|  | 		if (data && other.get_data_ptr()) { | ||||||
|  | 			memcpy(data, other.get_data_ptr(), data_length); | ||||||
|  | 		} | ||||||
|  | 		// deep copy byte enables | ||||||
|  | 		// there must be enough space in the target transaction! | ||||||
|  | 		if (byte_enable && other.get_byte_enable_ptr()) { | ||||||
|  | 			memcpy(byte_enable, other.get_byte_enable_ptr(), byte_enable_length); | ||||||
|  | 		} | ||||||
|  | 		// deep copy extensions (sticky and non-sticky) | ||||||
|  | 		for (unsigned int i = 0; i < other.m_extensions.size(); i++) { | ||||||
|  | 			if (other.get_extension(i)) {                       //original has extension i | ||||||
|  | 				if (!m_extensions[i]) {                   //We don't: clone. | ||||||
|  | 					tlm::tlm_extension_base *ext = other.get_extension(i)->clone(); | ||||||
|  | 					if (ext)     //extension may not be clonable. | ||||||
|  | 					{ | ||||||
|  | 						set_extension(i, ext); | ||||||
|  | 					} | ||||||
|  | 				} else {                   //We already have such extension. Copy original over it. | ||||||
|  | 					m_extensions[i]->copy_from(*other.get_extension(i)); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// To update the state of the original generic payload from a deep copy | ||||||
|  | 	// Assumes that "other" was created from the original by calling deep_copy_from | ||||||
|  | 	// Argument use_byte_enable_on_read determines whether to use or ignores byte enables | ||||||
|  | 	// when copying back the data array on a read command | ||||||
|  |  | ||||||
|  | 	void update_original_from(const tlm::tlm_generic_payload & other, bool use_byte_enable_on_read = true) { | ||||||
|  | 		// Copy back extensions that are present on the original | ||||||
|  | 		// update_extensions_from(other); | ||||||
|  |  | ||||||
|  | 		// Copy back the response status and DMI hint attributes | ||||||
|  | 		response_status = other.get_response_status(); | ||||||
|  | 		dmi = other.is_dmi_allowed(); | ||||||
|  |  | ||||||
|  | 		// Copy back the data array for a read command only | ||||||
|  | 		// deep_copy_from allowed null pointers, and so will we | ||||||
|  | 		// We assume the arrays are the same size | ||||||
|  | 		// We test for equal pointers in case the original and the copy share the same array | ||||||
|  |  | ||||||
|  | 		if (is_read() && data && other.get_data_ptr() && data != other.get_data_ptr()) { | ||||||
|  | 			if (byte_enable && use_byte_enable_on_read) { | ||||||
|  | 				if (byte_enable_length == 8 && data_length % 8 == 0) { | ||||||
|  | 					// Optimized implementation copies 64-bit words by masking | ||||||
|  | 					for (unsigned int i = 0; i < data_length; i += 8) { | ||||||
|  | 						typedef sc_dt::uint64* u; | ||||||
|  | 						*reinterpret_cast<u>(&data[i]) &= ~*reinterpret_cast<u>(byte_enable); | ||||||
|  | 						*reinterpret_cast<u>(&data[i]) |= *reinterpret_cast<u>(&other.get_data_ptr()[i]) | ||||||
|  | 										& *reinterpret_cast<u>(byte_enable); | ||||||
|  | 					} | ||||||
|  | 				} else if (byte_enable_length == 4 && data_length % 4 == 0) { | ||||||
|  | 					// Optimized implementation copies 32-bit words by masking | ||||||
|  | 					for (unsigned int i = 0; i < data_length; i += 4) { | ||||||
|  | 						typedef unsigned int* u; | ||||||
|  | 						*reinterpret_cast<u>(&data[i]) &= ~*reinterpret_cast<u>(byte_enable); | ||||||
|  | 						*reinterpret_cast<u>(&data[i]) |= *reinterpret_cast<u>(&other.get_data_ptr()[i]) | ||||||
|  | 										& *reinterpret_cast<u>(byte_enable); | ||||||
|  | 					} | ||||||
|  | 				} else | ||||||
|  | 					// Unoptimized implementation | ||||||
|  | 					for (unsigned int i = 0; i < data_length; i++) | ||||||
|  | 						if (byte_enable[i % byte_enable_length]) | ||||||
|  | 							data[i] = other.get_data_ptr()[i]; | ||||||
|  | 			} else | ||||||
|  | 				memcpy(data, other.get_data_ptr(), data_length); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	void update_extensions_from(const tlm::tlm_generic_payload & other) { | ||||||
|  | 		// deep copy extensions that are already present | ||||||
|  | 		for (unsigned int i = 0; i < tlm::max_num_extensions(); i++) { | ||||||
|  | 			if (other.get_extension(i)) {                       //original has extension i | ||||||
|  | 				if (m_extensions[i]) {                   //We have it too. copy. | ||||||
|  | 					m_extensions[i]->copy_from(*other.get_extension(i)); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	 */ | ||||||
|  |  | ||||||
|  | 	// Free all extensions. Useful when reusing a cloned transaction that doesn't have memory manager. | ||||||
|  | 	// normal and sticky extensions are freed and extension array cleared. | ||||||
|  | 	void free_all_extensions() { | ||||||
|  | 		m_extensions.free_entire_cache(); | ||||||
|  | 		for (unsigned int i = 0; i < m_extensions.size(); i++) { | ||||||
|  | 			if (m_extensions[i]) { | ||||||
|  | 				m_extensions[i]->free(); | ||||||
|  | 				m_extensions[i] = 0; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	//-------------- | ||||||
|  | 	// Destructor | ||||||
|  | 	//-------------- | ||||||
|  | 	virtual ~tlm_gp_data() { | ||||||
|  | 		for(unsigned int i=0; i<m_extensions.size(); i++) | ||||||
|  | 			if(m_extensions[i]) m_extensions[i]->free(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	//---------------- | ||||||
|  | 	// API (including setters & getters) | ||||||
|  | 	//--------------- | ||||||
|  |  | ||||||
|  | 	// Command related method | ||||||
|  | 	bool is_read() const { | ||||||
|  | 		return (command == tlm::TLM_READ_COMMAND); | ||||||
|  | 	} | ||||||
|  | 	void set_read() { | ||||||
|  | 		command = tlm::TLM_READ_COMMAND; | ||||||
|  | 	} | ||||||
|  | 	bool is_write() const { | ||||||
|  | 		return (command == tlm::TLM_WRITE_COMMAND); | ||||||
|  | 	} | ||||||
|  | 	void set_write() { | ||||||
|  | 		command = tlm::TLM_WRITE_COMMAND; | ||||||
|  | 	} | ||||||
|  | 	tlm::tlm_command get_command() const { | ||||||
|  | 		return command; | ||||||
|  | 	} | ||||||
|  | 	void set_command(const tlm::tlm_command command) { | ||||||
|  | 		this->command = command; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Address related methods | ||||||
|  | 	sc_dt::uint64 get_address() const { | ||||||
|  | 		return address; | ||||||
|  | 	} | ||||||
|  | 	void set_address(const sc_dt::uint64 address) { | ||||||
|  | 		this->address = address; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Data related methods | ||||||
|  | 	unsigned char* get_data_ptr() const { | ||||||
|  | 		return data; | ||||||
|  | 	} | ||||||
|  | 	void set_data_ptr(unsigned char* data) { | ||||||
|  | 		this->data = data; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Transaction length (in bytes) related methods | ||||||
|  | 	unsigned int get_data_length() const { | ||||||
|  | 		return data_length; | ||||||
|  | 	} | ||||||
|  | 	void set_data_length(const unsigned int length) { | ||||||
|  | 		data_length = length; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Response status related methods | ||||||
|  | 	bool is_response_ok() const { | ||||||
|  | 		return (response_status > 0); | ||||||
|  | 	} | ||||||
|  | 	bool is_response_error() const { | ||||||
|  | 		return (response_status <= 0); | ||||||
|  | 	} | ||||||
|  | 	tlm::tlm_response_status get_response_status() const { | ||||||
|  | 		return response_status; | ||||||
|  | 	} | ||||||
|  | 	void set_response_status(const tlm::tlm_response_status response_status) { | ||||||
|  | 		this->response_status = response_status; | ||||||
|  | 	} | ||||||
|  | 	std::string get_response_string() const { | ||||||
|  | 		switch (response_status) { | ||||||
|  | 		case tlm::TLM_OK_RESPONSE: | ||||||
|  | 			return "TLM_OK_RESPONSE"; | ||||||
|  | 		case tlm::TLM_INCOMPLETE_RESPONSE: | ||||||
|  | 			return "TLM_INCOMPLETE_RESPONSE"; | ||||||
|  | 		case tlm::TLM_GENERIC_ERROR_RESPONSE: | ||||||
|  | 			return "TLM_GENERIC_ERROR_RESPONSE"; | ||||||
|  | 		case tlm::TLM_ADDRESS_ERROR_RESPONSE: | ||||||
|  | 			return "TLM_ADDRESS_ERROR_RESPONSE"; | ||||||
|  | 		case tlm::TLM_COMMAND_ERROR_RESPONSE: | ||||||
|  | 			return "TLM_COMMAND_ERROR_RESPONSE"; | ||||||
|  | 		case tlm::TLM_BURST_ERROR_RESPONSE: | ||||||
|  | 			return "TLM_BURST_ERROR_RESPONSE"; | ||||||
|  | 		case tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE: | ||||||
|  | 			return "TLM_BYTE_ENABLE_ERROR_RESPONSE"; | ||||||
|  | 		} | ||||||
|  | 		return "TLM_UNKNOWN_RESPONSE"; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Streaming related methods | ||||||
|  | 	unsigned int get_streaming_width() const { | ||||||
|  | 		return streaming_width; | ||||||
|  | 	} | ||||||
|  | 	void set_streaming_width(const unsigned int streaming_width) { | ||||||
|  | 		this->streaming_width = streaming_width; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Byte enable related methods | ||||||
|  | 	unsigned char* get_byte_enable_ptr() const { | ||||||
|  | 		return byte_enable; | ||||||
|  | 	} | ||||||
|  | 	void set_byte_enable_ptr(unsigned char* byte_enable) { | ||||||
|  | 		this->byte_enable = byte_enable; | ||||||
|  | 	} | ||||||
|  | 	unsigned int get_byte_enable_length() const { | ||||||
|  | 		return byte_enable_length; | ||||||
|  | 	} | ||||||
|  | 	void set_byte_enable_length(const unsigned int byte_enable_length) { | ||||||
|  | 		this->byte_enable_length = byte_enable_length; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// This is the "DMI-hint" a slave can set this to true if it | ||||||
|  | 	// wants to indicate that a DMI request would be supported: | ||||||
|  | 	void set_dmi_allowed(bool dmi_allowed) { | ||||||
|  | 		dmi = dmi_allowed; | ||||||
|  | 	} | ||||||
|  | 	bool is_dmi_allowed() const { | ||||||
|  | 		return dmi; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Use full set of attributes in DMI/debug? | ||||||
|  | 	tlm::tlm_gp_option get_gp_option() const { | ||||||
|  | 		return gp_option; | ||||||
|  | 	} | ||||||
|  | 	void set_gp_option(const tlm::tlm_gp_option gp_opt) { | ||||||
|  | 		gp_option = gp_opt; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | public: | ||||||
|  |  | ||||||
|  | 	/* --------------------------------------------------------------------- */ | ||||||
|  | 	/* Generic Payload attributes:                                           */ | ||||||
|  | 	/* --------------------------------------------------------------------- */ | ||||||
|  | 	/* - m_command         : Type of transaction. Three values supported:    */ | ||||||
|  | 	/*                       - TLM_WRITE_COMMAND                             */ | ||||||
|  | 	/*                       - TLM_READ_COMMAND                              */ | ||||||
|  | 	/*                       - TLM_IGNORE_COMMAND                            */ | ||||||
|  | 	/* - m_address         : Transaction base address (byte-addressing).     */ | ||||||
|  | 	/* - m_data            : When m_command = TLM_WRITE_COMMAND contains a   */ | ||||||
|  | 	/*                       pointer to the data to be written in the target.*/ | ||||||
|  | 	/*                       When m_command = TLM_READ_COMMAND contains a    */ | ||||||
|  | 	/*                       pointer where to copy the data read from the    */ | ||||||
|  | 	/*                       target.                                         */ | ||||||
|  | 	/* - m_length          : Total number of bytes of the transaction.       */ | ||||||
|  | 	/* - m_response_status : This attribute indicates whether an error has   */ | ||||||
|  | 	/*                       occurred during the transaction.                */ | ||||||
|  | 	/*                       Values supported are:                           */ | ||||||
|  | 	/*                       - TLM_OK_RESP                                   */ | ||||||
|  | 	/*                       - TLM_INCOMPLETE_RESP                           */ | ||||||
|  | 	/*                       - TLM_GENERIC_ERROR_RESP                        */ | ||||||
|  | 	/*                       - TLM_ADDRESS_ERROR_RESP                        */ | ||||||
|  | 	/*                       - TLM_COMMAND_ERROR_RESP                        */ | ||||||
|  | 	/*                       - TLM_BURST_ERROR_RESP                          */ | ||||||
|  | 	/*                       - TLM_BYTE_ENABLE_ERROR_RESP                    */ | ||||||
|  | 	/*                                                                       */ | ||||||
|  | 	/* - m_byte_enable     : It can be used to create burst transfers where  */ | ||||||
|  | 	/*                    the address increment between each beat is greater */ | ||||||
|  | 	/*                    than the word length of each beat, or to place     */ | ||||||
|  | 	/*                    words in selected byte lanes of a bus.             */ | ||||||
|  | 	/* - m_byte_enable_length : For a read or a write command, the target    */ | ||||||
|  | 	/*                    interpret the byte enable length attribute as the  */ | ||||||
|  | 	/*                    number of elements in the bytes enable array.      */ | ||||||
|  | 	/* - m_streaming_width  :                                                */ | ||||||
|  | 	/* --------------------------------------------------------------------- */ | ||||||
|  |  | ||||||
|  | 	sc_dt::uint64 address; | ||||||
|  | 	tlm::tlm_command command; | ||||||
|  | 	unsigned char* data; | ||||||
|  | 	unsigned int data_length; | ||||||
|  | 	tlm::tlm_response_status response_status; | ||||||
|  | 	bool dmi; | ||||||
|  | 	unsigned char* byte_enable; | ||||||
|  | 	unsigned int byte_enable_length; | ||||||
|  | 	unsigned int streaming_width; | ||||||
|  | 	tlm::tlm_gp_option gp_option; | ||||||
|  |  | ||||||
|  | public: | ||||||
|  |  | ||||||
|  | 	/* --------------------------------------------------------------------- */ | ||||||
|  | 	/* Dynamic extension mechanism:                                          */ | ||||||
|  | 	/* --------------------------------------------------------------------- */ | ||||||
|  | 	/* The extension mechanism is intended to enable initiator modules to    */ | ||||||
|  | 	/* optionally and transparently add data fields to the                   */ | ||||||
|  | 	/* tlm_generic_payload. Target modules are free to check for extensions  */ | ||||||
|  | 	/* and may or may not react to the data in the extension fields. The     */ | ||||||
|  | 	/* definition of the extensions' semantics is solely in the              */ | ||||||
|  | 	/* responsibility of the user.                                           */ | ||||||
|  | 	/*                                                                       */ | ||||||
|  | 	/* The following rules apply:                                            */ | ||||||
|  | 	/*                                                                       */ | ||||||
|  | 	/* - Every extension class must be derived from tlm_extension, e.g.:     */ | ||||||
|  | 	/*     class my_extension : public tlm_extension<my_extension> { ... }   */ | ||||||
|  | 	/*                                                                       */ | ||||||
|  | 	/* - A tlm_generic_payload object should be constructed after C++        */ | ||||||
|  | 	/*   static initialization time. This way it is guaranteed that the      */ | ||||||
|  | 	/*   extension array is of sufficient size to hold all possible          */ | ||||||
|  | 	/*   extensions. Alternatively, the initiator module can enforce a valid */ | ||||||
|  | 	/*   extension array size by calling the resize_extensions() method      */ | ||||||
|  | 	/*   once before the first transaction with the payload object is        */ | ||||||
|  | 	/*   initiated.                                                          */ | ||||||
|  | 	/*                                                                       */ | ||||||
|  | 	/* - Initiators should use the the set_extension(e) or clear_extension(e)*/ | ||||||
|  | 	/*   methods for manipulating the extension array. The type of the       */ | ||||||
|  | 	/*   argument must be a pointer to the specific registered extension     */ | ||||||
|  | 	/*   type (my_extension in the above example) and is used to             */ | ||||||
|  | 	/*   automatically locate the appropriate index in the array.            */ | ||||||
|  | 	/*                                                                       */ | ||||||
|  | 	/* - Targets can check for a specific extension by calling               */ | ||||||
|  | 	/*   get_extension(e). e will point to zero if the extension is not      */ | ||||||
|  | 	/*   present.                                                            */ | ||||||
|  | 	/*                                                                       */ | ||||||
|  | 	/* --------------------------------------------------------------------- */ | ||||||
|  |  | ||||||
|  | 	// Stick the pointer to an extension into the vector, return the | ||||||
|  | 	// previous value: | ||||||
|  | 	template<typename T> T* set_extension(T* ext) { | ||||||
|  | 		return static_cast<T*>(set_extension(T::ID, ext)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// non-templatized version with manual index: | ||||||
|  | 	tlm::tlm_extension_base* set_extension(unsigned int index, tlm::tlm_extension_base* ext) { | ||||||
|  | 		tlm::tlm_extension_base* tmp = m_extensions[index]; | ||||||
|  | 		m_extensions[index] = ext; | ||||||
|  | 		return tmp; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Check for an extension, ext will point to 0 if not present | ||||||
|  | 	template<typename T> void get_extension(T*& ext) const { | ||||||
|  | 		ext = get_extension<T>(); | ||||||
|  | 	} | ||||||
|  | 	template<typename T> T* get_extension() const { | ||||||
|  | 		return static_cast<T*>(get_extension(T::ID)); | ||||||
|  | 	} | ||||||
|  | 	// Non-templatized version with manual index: | ||||||
|  | 	tlm::tlm_extension_base* get_extension(unsigned int index) const { | ||||||
|  | 		return m_extensions[index]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	//this call just removes the extension from the txn but does not | ||||||
|  | 	// call free() or tells the MM to do so | ||||||
|  | 	// it return false if there was active MM so you are now in an unsafe situation | ||||||
|  | 	// recommended use: when 100% sure there is no MM | ||||||
|  | 	template<typename T> void clear_extension(const T* ext) { | ||||||
|  | 		clear_extension<T>(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	//this call just removes the extension from the txn but does not | ||||||
|  | 	// call free() or tells the MM to do so | ||||||
|  | 	// it return false if there was active MM so you are now in an unsafe situation | ||||||
|  | 	// recommended use: when 100% sure there is no MM | ||||||
|  | 	template<typename T> void clear_extension() { | ||||||
|  | 		clear_extension(T::ID); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	//this call removes the extension from the txn and does | ||||||
|  | 	// call free() or tells the MM to do so when the txn is finally done | ||||||
|  | 	// recommended use: when not sure there is no MM | ||||||
|  | 	template<typename T> void release_extension(T* ext) { | ||||||
|  | 		release_extension<T>(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	//this call removes the extension from the txn and does | ||||||
|  | 	// call free() or tells the MM to do so when the txn is finally done | ||||||
|  | 	// recommended use: when not sure there is no MM | ||||||
|  | 	template<typename T> void release_extension() { | ||||||
|  | 		release_extension(T::ID); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | private: | ||||||
|  | 	// Non-templatized version with manual index | ||||||
|  | 	void clear_extension(unsigned int index) { | ||||||
|  | 		m_extensions[index] = static_cast<tlm::tlm_extension_base*>(0); | ||||||
|  | 	} | ||||||
|  | 	// Non-templatized version with manual index | ||||||
|  | 	void release_extension(unsigned int index) { | ||||||
|  | 		m_extensions[index]->free(); | ||||||
|  | 		m_extensions[index] = static_cast<tlm::tlm_extension_base*>(0); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | public: | ||||||
|  | 	// Make sure the extension array is large enough. Can be called once by | ||||||
|  | 	// an initiator module (before issuing the first transaction) to make | ||||||
|  | 	// sure that the extension array is of correct size. This is only needed | ||||||
|  | 	// if the initiator cannot guarantee that the generic payload object is | ||||||
|  | 	// allocated after C++ static construction time. | ||||||
|  | 	void resize_extensions() { | ||||||
|  | 		m_extensions.expand(tlm::max_num_extensions()); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | private: | ||||||
|  | 	tlm::tlm_array<tlm::tlm_extension_base*> m_extensions; | ||||||
|  | 	unsigned int m_ref_count; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | struct tlm_dmi_data { | ||||||
|  | 	tlm_dmi_data() | ||||||
|  | 	:dmi_ptr(0) | ||||||
|  | 	,dmi_start_address(0) | ||||||
|  | 	,dmi_end_address(0) | ||||||
|  | 	,dmi_access(tlm::tlm_dmi::DMI_ACCESS_NONE) | ||||||
|  | 	,dmi_read_latency(0) | ||||||
|  | 	,dmi_write_latency(0) | ||||||
|  | 	{} | ||||||
|  |  | ||||||
|  | 	tlm_dmi_data(tlm::tlm_dmi& dmi_data) | ||||||
|  | 	:dmi_ptr(dmi_data.get_dmi_ptr()) | ||||||
|  | 	,dmi_start_address(dmi_data.get_start_address()) | ||||||
|  | 	,dmi_end_address(dmi_data.get_end_address()) | ||||||
|  | 	,dmi_access(dmi_data.get_granted_access()) | ||||||
|  | 	,dmi_read_latency(dmi_data.get_read_latency().value()) | ||||||
|  | 	,dmi_write_latency(dmi_data.get_write_latency().value()) | ||||||
|  | 	{} | ||||||
|  | 	//-------------- | ||||||
|  | 	// Destructor | ||||||
|  | 	//-------------- | ||||||
|  | 	virtual ~tlm_dmi_data() {} | ||||||
|  |  | ||||||
|  | 	unsigned char*   dmi_ptr; | ||||||
|  | 	sc_dt::uint64    dmi_start_address; | ||||||
|  | 	sc_dt::uint64    dmi_end_address; | ||||||
|  | 	tlm::tlm_dmi::dmi_access_e     dmi_access; | ||||||
|  | 	sc_dt::uint64 dmi_read_latency; | ||||||
|  | 	sc_dt::uint64 dmi_write_latency; | ||||||
|  |  | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
|  | #endif /* TLM_GP_DATA_H_ */ | ||||||
							
								
								
									
										131
									
								
								scv_tr_sqlite/scv4tlm/tlm_gp_data_ext.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								scv_tr_sqlite/scv4tlm/tlm_gp_data_ext.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,131 @@ | |||||||
|  | /* | ||||||
|  |  * tlm_gp_data_ext.h | ||||||
|  |  * | ||||||
|  |  *  Created on: 07.11.2015 | ||||||
|  |  *      Author: eyck | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef TLM_GP_DATA_EXT_H_ | ||||||
|  | #define TLM_GP_DATA_EXT_H_ | ||||||
|  |  | ||||||
|  | #include "scv.h" | ||||||
|  | #include "tlm_gp_data.h" | ||||||
|  |  | ||||||
|  | template<> | ||||||
|  | class scv_extensions<tlm::tlm_command> : public scv_enum_base<tlm::tlm_command> { | ||||||
|  | public: | ||||||
|  | 	SCV_ENUM_CTOR(tlm::tlm_command) { | ||||||
|  | 		SCV_ENUM(tlm::TLM_READ_COMMAND); | ||||||
|  | 		SCV_ENUM(tlm::TLM_WRITE_COMMAND); | ||||||
|  | 		SCV_ENUM(tlm::TLM_IGNORE_COMMAND); | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template<> | ||||||
|  | class scv_extensions<tlm::tlm_response_status> : public scv_enum_base<tlm::tlm_response_status> { | ||||||
|  | public: | ||||||
|  | 	SCV_ENUM_CTOR(tlm::tlm_response_status) { | ||||||
|  | 		SCV_ENUM(tlm::TLM_OK_RESPONSE); | ||||||
|  | 		SCV_ENUM(tlm::TLM_INCOMPLETE_RESPONSE); | ||||||
|  | 		SCV_ENUM(tlm::TLM_GENERIC_ERROR_RESPONSE); | ||||||
|  | 		SCV_ENUM(tlm::TLM_ADDRESS_ERROR_RESPONSE); | ||||||
|  | 		SCV_ENUM(tlm::TLM_COMMAND_ERROR_RESPONSE); | ||||||
|  | 		SCV_ENUM(tlm::TLM_BURST_ERROR_RESPONSE); | ||||||
|  | 		SCV_ENUM(tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE); | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template<> | ||||||
|  | class scv_extensions<tlm::tlm_gp_option> : public scv_enum_base<tlm::tlm_gp_option> { | ||||||
|  | public: | ||||||
|  | 	SCV_ENUM_CTOR(tlm::tlm_gp_option) { | ||||||
|  | 		SCV_ENUM(tlm::TLM_MIN_PAYLOAD); | ||||||
|  | 		SCV_ENUM(tlm::TLM_FULL_PAYLOAD); | ||||||
|  | 		SCV_ENUM(tlm::TLM_FULL_PAYLOAD_ACCEPTED); | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template<> | ||||||
|  | class scv_extensions<tlm::tlm_phase_enum> : public scv_enum_base<tlm::tlm_phase_enum> { | ||||||
|  | public: | ||||||
|  | 	SCV_ENUM_CTOR(tlm::tlm_phase_enum) { | ||||||
|  | 		SCV_ENUM(tlm::UNINITIALIZED_PHASE); | ||||||
|  | 		SCV_ENUM(tlm::BEGIN_REQ); | ||||||
|  | 		SCV_ENUM(tlm::END_REQ); | ||||||
|  | 		SCV_ENUM(tlm::BEGIN_RESP); | ||||||
|  | 		SCV_ENUM(tlm::END_RESP); | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template<> | ||||||
|  | class scv_extensions<tlm::tlm_sync_enum> : public scv_enum_base<tlm::tlm_sync_enum> { | ||||||
|  | public: | ||||||
|  | 	SCV_ENUM_CTOR(tlm::tlm_sync_enum) { | ||||||
|  | 		SCV_ENUM(tlm::TLM_ACCEPTED); | ||||||
|  | 		SCV_ENUM(tlm::TLM_UPDATED); | ||||||
|  | 		SCV_ENUM(tlm::TLM_COMPLETED); | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template<> | ||||||
|  | class scv_extensions<scv4tlm::tlm_gp_data> : public scv_extensions_base<scv4tlm::tlm_gp_data> { | ||||||
|  | public: | ||||||
|  | 	scv_extensions<sc_dt::uint64>            address; | ||||||
|  | 	scv_extensions<tlm::tlm_command>         command; | ||||||
|  | 	scv_extensions<unsigned char*>           data; | ||||||
|  | 	scv_extensions<unsigned int>             data_length; | ||||||
|  | 	scv_extensions<tlm::tlm_response_status> response_status; | ||||||
|  | 	scv_extensions<bool>                     dmi; | ||||||
|  | 	scv_extensions<unsigned char*>           byte_enable; | ||||||
|  | 	scv_extensions<unsigned int>             byte_enable_length; | ||||||
|  | 	scv_extensions<unsigned int>             streaming_width; | ||||||
|  | 	scv_extensions<tlm::tlm_gp_option>       gp_option; | ||||||
|  |  | ||||||
|  | 	SCV_EXTENSIONS_CTOR(scv4tlm::tlm_gp_data) { | ||||||
|  | 		//must be in order | ||||||
|  | 		SCV_FIELD(address); | ||||||
|  | 		SCV_FIELD(command); | ||||||
|  | 		SCV_FIELD(data); | ||||||
|  | 		SCV_FIELD(data_length); | ||||||
|  | 		SCV_FIELD(response_status); | ||||||
|  | 		SCV_FIELD(dmi); | ||||||
|  | 		SCV_FIELD(byte_enable); | ||||||
|  | 		SCV_FIELD(byte_enable_length); | ||||||
|  | 		SCV_FIELD(streaming_width); | ||||||
|  | 		SCV_FIELD(gp_option); | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template<> | ||||||
|  | class scv_extensions<tlm::tlm_dmi::dmi_access_e> : public scv_enum_base<tlm::tlm_dmi::dmi_access_e> { | ||||||
|  | public: | ||||||
|  | 	SCV_ENUM_CTOR(tlm::tlm_dmi::dmi_access_e) { | ||||||
|  | 		SCV_ENUM(tlm::tlm_dmi::DMI_ACCESS_NONE); | ||||||
|  | 		SCV_ENUM(tlm::tlm_dmi::DMI_ACCESS_READ); | ||||||
|  | 		SCV_ENUM(tlm::tlm_dmi::DMI_ACCESS_WRITE); | ||||||
|  | 		SCV_ENUM(tlm::tlm_dmi::DMI_ACCESS_READ_WRITE); | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template<> | ||||||
|  | class scv_extensions<scv4tlm::tlm_dmi_data> : public scv_extensions_base<scv4tlm::tlm_dmi_data> { | ||||||
|  | public: | ||||||
|  | 	scv_extensions<unsigned char*>   dmi_ptr; | ||||||
|  | 	scv_extensions<sc_dt::uint64>    dmi_start_address; | ||||||
|  | 	scv_extensions<sc_dt::uint64>    dmi_end_address; | ||||||
|  | 	scv_extensions<tlm::tlm_dmi::dmi_access_e> dmi_access; | ||||||
|  | 	scv_extensions<sc_dt::uint64> dmi_read_latency; | ||||||
|  | 	scv_extensions<sc_dt::uint64> dmi_write_latency; | ||||||
|  | 	SCV_EXTENSIONS_CTOR(scv4tlm::tlm_dmi_data) { | ||||||
|  | 		//must be in order | ||||||
|  | 		SCV_FIELD(dmi_ptr); | ||||||
|  | 		SCV_FIELD(dmi_start_address); | ||||||
|  | 		SCV_FIELD(dmi_end_address); | ||||||
|  | 		SCV_FIELD(dmi_access); | ||||||
|  | 		SCV_FIELD(dmi_read_latency); | ||||||
|  | 		SCV_FIELD(dmi_write_latency); | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #endif /* TLM_GP_DATA_EXT_H_ */ | ||||||
							
								
								
									
										125
									
								
								scv_tr_sqlite/scv4tlm/tlm_rec_initiator_socket.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								scv_tr_sqlite/scv4tlm/tlm_rec_initiator_socket.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,125 @@ | |||||||
|  | /* | ||||||
|  |  * tlm_rec_target_socket.h | ||||||
|  |  * | ||||||
|  |  *  Created on: 08.11.2015 | ||||||
|  |  *      Author: eyck | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef TLM_REC_INITIATOR_SOCKET_H_ | ||||||
|  | #define TLM_REC_INITIATOR_SOCKET_H_ | ||||||
|  |  | ||||||
|  | #include <tlm_core/tlm_2/tlm_sockets/tlm_initiator_socket.h> | ||||||
|  |  | ||||||
|  | #include "tlm2_recorder.h" | ||||||
|  |  | ||||||
|  | namespace scv4tlm { | ||||||
|  | template<unsigned int BUSWIDTH = 32, typename TYPES = tlm::tlm_base_protocol_types, int N = 1 | ||||||
|  | #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) | ||||||
|  | 		, sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND | ||||||
|  | #endif | ||||||
|  | 		> | ||||||
|  | class tlm_rec_initiator_socket: public tlm::tlm_initiator_socket<BUSWIDTH | ||||||
|  | , TYPES | ||||||
|  | , N | ||||||
|  | #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) | ||||||
|  | , POL | ||||||
|  | #endif | ||||||
|  | > { | ||||||
|  | 	static std::string gen_name(const char* first, const char* second){ | ||||||
|  | 		std::stringstream ss; | ||||||
|  | 		ss<<first<<"_"<<second; | ||||||
|  | 		return ss.str(); | ||||||
|  | 	} | ||||||
|  | public: | ||||||
|  | 	typedef tlm::tlm_fw_transport_if<TYPES>  fw_interface_type; | ||||||
|  | 	typedef tlm::tlm_bw_transport_if<TYPES>  bw_interface_type; | ||||||
|  | 	typedef sc_core::sc_port<fw_interface_type, N | ||||||
|  | #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) | ||||||
|  | 			, POL | ||||||
|  | #endif | ||||||
|  | 			>   port_type; | ||||||
|  | 	typedef sc_core::sc_export<bw_interface_type> export_type; | ||||||
|  | 	typedef tlm::tlm_base_target_socket_b<BUSWIDTH, | ||||||
|  | 			fw_interface_type, | ||||||
|  | 			bw_interface_type> base_target_socket_type; | ||||||
|  | 	typedef tlm::tlm_base_initiator_socket_b<BUSWIDTH, | ||||||
|  | 			fw_interface_type, | ||||||
|  | 			bw_interface_type> base_type; | ||||||
|  |  | ||||||
|  | 	tlm_rec_initiator_socket() : | ||||||
|  | 		tlm::tlm_initiator_socket<BUSWIDTH | ||||||
|  | 		, TYPES | ||||||
|  | 		, N | ||||||
|  | #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) | ||||||
|  | , POL | ||||||
|  | #endif | ||||||
|  | >() | ||||||
|  | ,recorder() | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | 	explicit tlm_rec_initiator_socket(const char* name) : | ||||||
|  | 						tlm::tlm_initiator_socket<BUSWIDTH | ||||||
|  | 						, TYPES | ||||||
|  | 						, N | ||||||
|  | #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) | ||||||
|  | 						, POL | ||||||
|  | #endif | ||||||
|  | 						>(name) | ||||||
|  | 						,recorder(gen_name(name, "rec").c_str()) | ||||||
|  | 						{ | ||||||
|  | 						} | ||||||
|  |  | ||||||
|  | 	virtual ~tlm_rec_initiator_socket(){} | ||||||
|  |  | ||||||
|  | 	virtual const char* kind() const { | ||||||
|  | 		return "tlm_rec_target_socket"; | ||||||
|  | 	} | ||||||
|  | 	// | ||||||
|  | 	// Bind initiator socket to target socket | ||||||
|  | 	// - Binds the port of the initiator socket to the export of the target | ||||||
|  | 	//   socket | ||||||
|  | 	// - Binds the port of the target socket to the export of the initiator | ||||||
|  | 	//   socket | ||||||
|  | 	// | ||||||
|  | 	virtual void bind(base_target_socket_type& s) { | ||||||
|  | 		// initiator.port -> target.export | ||||||
|  | 		(this->get_base_port())(recorder); | ||||||
|  | 		recorder.fw_port(s.get_base_interface()); | ||||||
|  | 		// target.port -> initiator.export | ||||||
|  | 		(s.get_base_port())(recorder); | ||||||
|  | 		recorder.bw_port(this->get_base_interface()); | ||||||
|  | 	} | ||||||
|  | 	// | ||||||
|  | 	// Bind initiator socket to initiator socket (hierarchical bind) | ||||||
|  | 	// - Binds both the export and the port | ||||||
|  | 	// | ||||||
|  | 	virtual void bind(base_type& s){ | ||||||
|  | 		// port | ||||||
|  | 		(this->get_base_port())(recorder); | ||||||
|  | 		recorder.fw_port(s.get_base_port()); | ||||||
|  | 		// export | ||||||
|  | 		(s.get_base_export())(recorder); | ||||||
|  | 		recorder.bw_port(this->get_base_export()); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// | ||||||
|  | 	// Bind interface to socket | ||||||
|  | 	// - Binds the interface to the export of this socket | ||||||
|  | 	// | ||||||
|  | 	virtual void bind(bw_interface_type& ifs) { | ||||||
|  | 		(this->get_base_export())(ifs); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void setExtensionRecording(tlm_extensions_recording_if<TYPES>* extensionRecording){ | ||||||
|  | 		recorder.setExtensionRecording(extensionRecording); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | protected: | ||||||
|  | 	scv4tlm::tlm2_recorder<TYPES> recorder; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | } | ||||||
|  | // namespace scv4tlm | ||||||
|  |  | ||||||
|  | #endif /* TLM_REC_TARGET_SOCKET_H_ */ | ||||||
							
								
								
									
										119
									
								
								scv_tr_sqlite/scv4tlm/tlm_rec_target_socket.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								scv_tr_sqlite/scv4tlm/tlm_rec_target_socket.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,119 @@ | |||||||
|  | /* | ||||||
|  |  * tlm_rec_target_socket.h | ||||||
|  |  * | ||||||
|  |  *  Created on: 08.11.2015 | ||||||
|  |  *      Author: eyck | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef TLM_REC_TARGET_SOCKET_H_ | ||||||
|  | #define TLM_REC_TARGET_SOCKET_H_ | ||||||
|  |  | ||||||
|  | #include <tlm_core/tlm_2/tlm_sockets/tlm_target_socket.h> | ||||||
|  |  | ||||||
|  | #include "tlm2_recorder.h" | ||||||
|  |  | ||||||
|  | namespace scv4tlm { | ||||||
|  | template<unsigned int BUSWIDTH = 32, typename TYPES = tlm::tlm_base_protocol_types, int N = 1 | ||||||
|  | #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) | ||||||
|  | 		, sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND | ||||||
|  | #endif | ||||||
|  | 		> | ||||||
|  | class tlm_rec_target_socket: public tlm::tlm_target_socket<BUSWIDTH | ||||||
|  | , TYPES | ||||||
|  | , N | ||||||
|  | #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) | ||||||
|  | , POL | ||||||
|  | #endif | ||||||
|  | > { | ||||||
|  | 	static std::string gen_name(const char* first, const char* second){ | ||||||
|  | 		std::stringstream ss; | ||||||
|  | 		ss<<first<<"_"<<second; | ||||||
|  | 		return ss.str(); | ||||||
|  | 	} | ||||||
|  | public: | ||||||
|  | 	typedef tlm::tlm_fw_transport_if<TYPES>  fw_interface_type; | ||||||
|  | 	typedef tlm::tlm_bw_transport_if<TYPES>  bw_interface_type; | ||||||
|  | 	typedef sc_core::sc_port<bw_interface_type, N | ||||||
|  | #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) | ||||||
|  | 			, POL | ||||||
|  | #endif | ||||||
|  | 			>   port_type; | ||||||
|  |  | ||||||
|  | 	typedef sc_core::sc_export<fw_interface_type> export_type; | ||||||
|  | 	typedef tlm::tlm_base_initiator_socket_b<BUSWIDTH, fw_interface_type, bw_interface_type>  base_initiator_socket_type; | ||||||
|  |  | ||||||
|  | 	typedef tlm::tlm_base_target_socket_b<BUSWIDTH,	fw_interface_type, bw_interface_type> base_type; | ||||||
|  |  | ||||||
|  | 	tlm_rec_target_socket() : | ||||||
|  | 		tlm::tlm_target_socket<BUSWIDTH | ||||||
|  | 		, TYPES | ||||||
|  | 		, N | ||||||
|  | #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) | ||||||
|  | 		, POL | ||||||
|  | #endif | ||||||
|  | 		>() | ||||||
|  | 		,recorder() | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	explicit tlm_rec_target_socket(const char* name) : | ||||||
|  | 		tlm::tlm_target_socket<BUSWIDTH | ||||||
|  | 		, TYPES | ||||||
|  | 		, N | ||||||
|  | #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714) | ||||||
|  | 		, POL | ||||||
|  | #endif | ||||||
|  | 		>(name) | ||||||
|  | 		,recorder(gen_name(name, "rec").c_str()) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	virtual ~tlm_rec_target_socket(){} | ||||||
|  |  | ||||||
|  | 	virtual const char* kind() const { | ||||||
|  | 		return "tlm_rec_target_socket"; | ||||||
|  | 	} | ||||||
|  | 	// | ||||||
|  | 	// Bind target socket to target socket (hierarchical bind) | ||||||
|  | 	// - Binds both the export and the port | ||||||
|  | 	// | ||||||
|  | 	virtual void bind(base_type& s) { | ||||||
|  | 		// export | ||||||
|  | 		(this->get_base_export())(s.get_base_export()); // will be handled by bind(fw_interface_type& ifs) | ||||||
|  | 		// port | ||||||
|  | 		(s.get_base_port())(recorder); // bind the recording interface to the port, recording will use the m_port | ||||||
|  | 	} | ||||||
|  | 	// | ||||||
|  | 	// Bind interface to socket | ||||||
|  | 	// - Binds the interface to the export | ||||||
|  | 	// | ||||||
|  | 	virtual void bind(fw_interface_type& ifs){ | ||||||
|  | 		export_type* exp = &this->get_base_export(); | ||||||
|  | 		if( this == exp ) { | ||||||
|  | 			export_type::bind(recorder); // non-virtual function call | ||||||
|  | 			recorder.fw_port(ifs); | ||||||
|  | 			recorder.bw_port(this->get_base_port()); | ||||||
|  | 		} else { | ||||||
|  | 			exp->bind( ifs ); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  | 	// | ||||||
|  | 	// Forward to 'operator->()' of port class | ||||||
|  | 	// | ||||||
|  | 	bw_interface_type* operator->() { | ||||||
|  | 		return &recorder; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	scv4tlm::tlm2_recorder<TYPES>& get_recorder(){ | ||||||
|  | 		return recorder; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | protected: | ||||||
|  | 	scv4tlm::tlm2_recorder<TYPES> recorder; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | } | ||||||
|  | // namespace scv4tlm | ||||||
|  |  | ||||||
|  | #endif /* TLM_REC_TARGET_SOCKET_H_ */ | ||||||
							
								
								
									
										77
									
								
								scv_tr_sqlite/scv4tlm/tlm_recording_extension.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								scv_tr_sqlite/scv4tlm/tlm_recording_extension.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | |||||||
|  | /* | ||||||
|  |  * tlm2_tx_record_extension.h | ||||||
|  |  * | ||||||
|  |  *  Created on: 07.11.2015 | ||||||
|  |  *      Author: eyck | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef TLM_RECORDING_EXTENSION_H_ | ||||||
|  | #define TLM_RECORDING_EXTENSION_H_ | ||||||
|  |  | ||||||
|  | #include <scv.h> | ||||||
|  |  | ||||||
|  | namespace scv4tlm { | ||||||
|  |  | ||||||
|  | //! transaction relationships | ||||||
|  | enum tx_rel { | ||||||
|  | 	PARENT_CHILD = 0, /*!< indicates parent child relationship */ | ||||||
|  | 	PREDECESSOR_SUCCESSOR /*!< indicates predecessor successor relationship */ | ||||||
|  | }; | ||||||
|  | //! the string representation of the tx_rel | ||||||
|  | static char const* tx_rel_str[] = { "PARENT/CHILD", "PRED/SUCC" }; | ||||||
|  | /*! \brief cast the tx_rel enum to a string | ||||||
|  |  * | ||||||
|  |  * \param tc_rel is the relationship enum | ||||||
|  |  */ | ||||||
|  | inline const char* rel_str(tx_rel rel) { | ||||||
|  | 	return (tx_rel_str[rel]); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /*! \brief generic payload extension class holding the handle of the last recorded SCV transaction | ||||||
|  |  * | ||||||
|  |  * This extension is been used in the \ref scv_tlm2_recorder. The recorder stores the handle to the generated SCV transaction and | ||||||
|  |  * forwrds it along with the generic payload. If the recorder finds an extension containing a valid handle it links the generated | ||||||
|  |  * SCV transdaction to the found one using the \ref PREDECESSOR releationship | ||||||
|  |  */ | ||||||
|  | struct tlm_recording_extension: public tlm::tlm_extension<tlm_recording_extension> { | ||||||
|  | 	/*! \brief clone the given extension and duplicate the SCV transaction handle. | ||||||
|  | 	 * | ||||||
|  | 	 */ | ||||||
|  | 	virtual tlm_extension_base* clone() const { | ||||||
|  | 		tlm_recording_extension* t = new tlm_recording_extension(this->txHandle, this->creator); | ||||||
|  | 		return t; | ||||||
|  | 	} | ||||||
|  | 	/*! \brief copy data between extensions. | ||||||
|  | 	 * | ||||||
|  | 	 * \param from is the source extension. | ||||||
|  | 	 */ | ||||||
|  | 	virtual void copy_from(tlm_extension_base const& from) { | ||||||
|  | 		txHandle = static_cast<tlm_recording_extension const &>(from).txHandle; | ||||||
|  | 		creator = static_cast<tlm_recording_extension const &>(from).creator; | ||||||
|  | 	} | ||||||
|  | 	/*! \brief constructor storing the handle of the transaction and the owner of this extension | ||||||
|  | 	 * | ||||||
|  | 	 * \param handle is the handle of the created SCV transaction. | ||||||
|  | 	 * \param creator_ is the pointer to the owner of this extension (usually an instance of scv_tlm2_recorder). | ||||||
|  | 	 */ | ||||||
|  | 	tlm_recording_extension(scv_tr_handle handle, void* creator_) : | ||||||
|  | 			txHandle(handle), creator(creator_) { | ||||||
|  | 	} | ||||||
|  | 	/*! \brief accessor to the owner, the property is read only. | ||||||
|  | 	 * | ||||||
|  | 	 */ | ||||||
|  | 	void* get_creator() { | ||||||
|  | 		return creator; | ||||||
|  | 	} | ||||||
|  | 	/*! \brief accessor to the SCV transaction handle. | ||||||
|  | 	 * | ||||||
|  | 	 */ | ||||||
|  | 	scv_tr_handle txHandle; | ||||||
|  | private: | ||||||
|  | 	//! the owner of this transaction | ||||||
|  | 	void* creator; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #endif /* TLM_RECORDING_EXTENSION_H_ */ | ||||||
		Reference in New Issue
	
	Block a user