90 std::string get_parent(
char const* hier_name) {
91 std::string ret(hier_name);
92 auto pos = ret.rfind(
'.');
93 return pos == std::string::npos ? ret : ret.substr(0, pos);
99 using payload_type =
typename TYPES::tlm_payload_type;
115 sc_core::sc_port_b<tlm::nw::tlm_network_fw_transport_if<TYPES>>&
fw_port;
118 sc_core::sc_port_b<tlm::nw::tlm_network_bw_transport_if<TYPES>>&
bw_port;
135 SCVNS scv_tr_db* tr_db = SCVNS scv_tr_db::get_default_db())
136 : tlm_recorder(sc_core::sc_gen_unique_name(
"tlm_recorder"),
fw_port,
bw_port, recording_enabled, tr_db) {}
153 SCVNS scv_tr_db* tr_db = SCVNS scv_tr_db::get_default_db())
159 , fixed_basename(name) {}
161 virtual ~tlm_recorder()
override {
162 delete b_streamHandle;
163 for(
auto* p : b_trHandle)
165 delete b_streamHandleTimed;
166 for(
auto* p : b_trTimedHandle)
168 delete nb_streamHandle;
169 for(
auto* p : nb_trHandle)
171 delete nb_streamHandleTimed;
172 for(
auto* p : nb_trTimedHandle)
187 tlm::tlm_sync_enum
nb_transport_fw(payload_type& trans,
typename TYPES::tlm_phase_type& phase, sc_core::sc_time& delay)
override;
198 tlm::tlm_sync_enum
nb_transport_bw(payload_type& trans,
typename TYPES::tlm_phase_type& phase, sc_core::sc_time& delay)
override;
208 void b_transport(payload_type& trans, sc_core::sc_time& delay)
override;
231 SCVNS scv_tr_db* m_db{
nullptr};
233 SCVNS scv_tr_stream* b_streamHandle{
nullptr};
235 std::array<SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>*, 3> b_trHandle{{
nullptr,
nullptr,
nullptr}};
237 SCVNS scv_tr_stream* b_streamHandleTimed{
nullptr};
240 std::array<SCVNS scv_tr_generator<>*, 3> b_trTimedHandle{{
nullptr,
nullptr,
nullptr}};
242 enum DIR { FW, BW, REQ = FW, RESP = BW };
244 SCVNS scv_tr_stream* nb_streamHandle{
nullptr};
246 SCVNS scv_tr_stream* nb_streamHandleTimed{
nullptr};
248 std::array<SCVNS scv_tr_generator<std::string, std::string>*, 2> nb_trHandle{{
nullptr,
nullptr}};
250 std::array<SCVNS scv_tr_generator<>*, 2> nb_trTimedHandle{{
nullptr,
nullptr}};
251 std::unordered_map<payload_type*, SCVNS scv_tr_handle> pending_fw_resp;
252 std::unordered_map<payload_type*, SCVNS scv_tr_handle> pending_bw_resp;
255 void initialize_streams() {
257 b_streamHandle =
new SCVNS scv_tr_stream((fixed_basename +
"_bl").c_str(),
"[TLM][base-protocol][b]", m_db);
258 b_trHandle[tlm::TLM_READ_COMMAND] =
259 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
"read", *b_streamHandle,
"start_delay",
"end_delay");
260 b_trHandle[tlm::TLM_WRITE_COMMAND] =
261 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
"write", *b_streamHandle,
"start_delay",
"end_delay");
262 b_trHandle[tlm::TLM_IGNORE_COMMAND] =
263 new SCVNS scv_tr_generator<sc_dt::uint64, sc_dt::uint64>(
"ignore", *b_streamHandle,
"start_delay",
"end_delay");
265 b_streamHandleTimed =
266 new SCVNS scv_tr_stream((fixed_basename +
"_bl_timed").c_str(),
"[TLM][base-protocol][b][timed]", m_db);
267 b_trTimedHandle[tlm::TLM_READ_COMMAND] =
new SCVNS scv_tr_generator<>(
"read", *b_streamHandleTimed);
268 b_trTimedHandle[tlm::TLM_WRITE_COMMAND] =
new SCVNS scv_tr_generator<>(
"write", *b_streamHandleTimed);
269 b_trTimedHandle[tlm::TLM_IGNORE_COMMAND] =
new SCVNS scv_tr_generator<>(
"ignore", *b_streamHandleTimed);
273 nb_streamHandle =
new SCVNS scv_tr_stream((fixed_basename +
"_nb").c_str(),
"[TLM][base-protocol][nb]", m_db);
275 new SCVNS scv_tr_generator<std::string, std::string>(
"fw", *nb_streamHandle,
"tlm_phase",
"tlm_phase[return_path]");
277 new SCVNS scv_tr_generator<std::string, std::string>(
"bw", *nb_streamHandle,
"tlm_phase",
"tlm_phase[return_path]");
279 nb_streamHandleTimed =
280 new SCVNS scv_tr_stream((fixed_basename +
"_nb_timed").c_str(),
"[TLM][base-protocol][nb][timed]", m_db);
281 nb_trTimedHandle[FW] =
new SCVNS scv_tr_generator<>(
"request", *nb_streamHandleTimed);
282 nb_trTimedHandle[BW] =
new SCVNS scv_tr_generator<>(
"response", *nb_streamHandleTimed);
288 const std::string fixed_basename;
289 inline std::string phase2string(
const tlm::tlm_phase& p) {
290 std::stringstream ss;
301 tlm_recording_payload* req{
nullptr};
303 fw_port->b_transport(trans, delay);
305 }
else if(!b_streamHandle)
306 initialize_streams();
308 SCVNS scv_tr_handle h =
309 b_trHandle[
static_cast<unsigned>(trans.get_command())]->begin_transaction(delay.value(), sc_core::sc_time_stamp());
313 SCVNS scv_tr_handle bh;
314 if(b_streamHandleTimed) {
315 bh = b_trTimedHandle[
static_cast<unsigned>(trans.get_command())]->begin_transaction(sc_core::sc_time_stamp() + delay);
319 if(trans.get_extension_count())
320 for(
auto& extensionRecording : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
321 if(extensionRecording)
322 extensionRecording->recordBeginTx(h, trans);
325 trans.get_extension(preExt);
326 if(preExt ==
nullptr) {
329 trans.set_auto_extension(preExt);
331 trans.set_extension(preExt);
335 SCVNS scv_tr_handle preTx{preExt->
txHandle};
337 fw_port->b_transport(trans, delay);
341 if(!trans.has_mm()) {
348 if(trans.get_extension_count())
349 for(
auto& extensionRecording : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
350 if(extensionRecording)
351 extensionRecording->recordEndTx(h, trans);
353 b_trHandle[
static_cast<unsigned>(trans.get_command())]->end_transaction(h, delay.value(), sc_core::sc_time_stamp());
355 if(b_streamHandleTimed) {
357 b_trTimedHandle[
static_cast<unsigned>(trans.get_command())]->end_transaction(bh, sc_core::sc_time_stamp() + delay);
363 sc_core::sc_time& delay) {
365 return fw_port->nb_transport_fw(trans, phase, delay);
366 else if(!nb_streamHandle)
367 initialize_streams();
372 SCVNS scv_tr_handle h = nb_trHandle[FW]->begin_transaction(phase2string(phase));
374 trans.get_extension(preExt);
375 if(preExt ==
nullptr) {
378 trans.set_auto_extension(preExt);
380 trans.set_extension(preExt);
388 h.record_attribute(
"delay", delay.to_string());
389 if(trans.get_extension_count())
390 for(
auto& extensionRecording : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
391 if(extensionRecording)
392 extensionRecording->recordBeginTx(h, trans);
396 SCVNS scv_tr_handle bh;
397 if(nb_streamHandleTimed) {
398 if(phase == tlm::nw::REQUEST || phase == tlm::nw::INDICATION) {
399 bh = nb_trTimedHandle[
static_cast<unsigned>(trans.get_command())]->begin_transaction(sc_core::sc_time_stamp() + delay);
406 tlm::tlm_sync_enum status =
fw_port->nb_transport_fw(trans, phase, delay);
411 h.record_attribute(
"delay[return_path]", delay.to_string());
413 if(trans.get_extension_count())
414 for(
auto& extensionRecording : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
415 if(extensionRecording)
416 extensionRecording->recordEndTx(h, trans);
418 if(status == tlm::TLM_COMPLETED || (status == tlm::TLM_UPDATED && (phase == tlm::nw::CONFIRM || phase == tlm::nw::RESPONSE))) {
419 trans.get_extension(preExt);
422 if(!trans.has_mm()) {
429 if(nb_streamHandleTimed) {
430 if(trans.get_command() == cxs::CXS_CMD::FLIT) {
432 nb_trTimedHandle[
static_cast<unsigned>(trans.get_command())]->end_transaction(bh, sc_core::sc_time_stamp() + delay);
434 auto it = pending_fw_resp.find(&trans);
435 if(it != pending_fw_resp.end()) {
436 nb_trTimedHandle[
static_cast<unsigned>(trans.get_command())]->end_transaction(it->second,
437 sc_core::sc_time_stamp() + delay);
438 pending_fw_resp.erase(it);
440 SCCWARN(fixed_basename.c_str()) <<
"Could not find entry in pending_bw_resp";
444 }
else if(nb_streamHandleTimed) {
445 if(status == tlm::TLM_ACCEPTED && (phase == tlm::nw::REQUEST || phase == tlm::nw::INDICATION))
446 pending_bw_resp.insert({&trans, bh});
449 nb_trHandle[FW]->end_transaction(h, phase2string(phase));
455 sc_core::sc_time& delay) {
457 return bw_port->nb_transport_bw(trans, phase, delay);
458 else if(!nb_streamHandle)
459 initialize_streams();
464 trans.get_extension(preExt);
467 SCVNS scv_tr_handle h = nb_trHandle[BW]->begin_transaction(phase2string(phase));
474 h.record_attribute(
"delay", delay.to_string());
475 if(trans.get_extension_count())
476 for(
auto& extensionRecording : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
477 if(extensionRecording)
478 extensionRecording->recordBeginTx(h, trans);
482 SCVNS scv_tr_handle bh;
483 if(nb_streamHandleTimed) {
484 if(trans.get_command() != cxs::CXS_CMD::FLIT) {
485 bh = nb_trTimedHandle[
static_cast<unsigned>(trans.get_command())]->begin_transaction(sc_core::sc_time_stamp() + delay);
492 tlm::tlm_sync_enum status =
bw_port->nb_transport_bw(trans, phase, delay);
497 h.record_attribute(
"delay[return_path]", delay.to_string());
499 if(trans.get_extension_count())
500 for(
auto& extensionRecording : tlm::scc::scv::tlm_extension_recording_registry<TYPES>::inst().get())
501 if(extensionRecording)
502 extensionRecording->recordEndTx(h, trans);
504 nb_trHandle[BW]->end_transaction(h, phase2string(phase));
505 if(status == tlm::TLM_COMPLETED || (status == tlm::TLM_UPDATED && (phase == tlm::nw::CONFIRM || tlm::nw::RESPONSE))) {
510 if(!trans.has_mm()) {
517 if(nb_streamHandleTimed) {
518 if(trans.get_command() != cxs::CXS_CMD::FLIT) {
520 nb_trTimedHandle[
static_cast<unsigned>(trans.get_command())]->end_transaction(bh, sc_core::sc_time_stamp() + delay);
522 auto it = pending_bw_resp.find(&trans);
523 if(it != pending_bw_resp.end()) {
524 nb_trTimedHandle[
static_cast<unsigned>(trans.get_command())]->end_transaction(it->second,
525 sc_core::sc_time_stamp() + delay);
526 pending_bw_resp.erase(it);
528 SCCWARN(fixed_basename.c_str()) <<
"Could not find entry in pending_bw_resp";
532 }
else if(nb_streamHandleTimed) {
533 if(status == tlm::TLM_ACCEPTED && (phase == tlm::nw::REQUEST || phase == tlm::nw::INDICATION))
534 pending_fw_resp.insert({&trans, bh});