245 unsigned int transport_dbg(
typename TYPES::tlm_payload_type& trans)
override;
261 sc_core::sc_port<tlm::tlm_fw_transport_if<TYPES>>
fw_port{
"fw_port"};
264 sc_core::sc_port<tlm::tlm_bw_transport_if<TYPES>>
bw_port{
"bw_port"};
267 std::string
const full_name;
276 tx_db* m_db{
nullptr};
278 ::lwtr::tx_relation_handle pred_succ_hndl{0}, par_chld_hndl{0};
280 tx_fiber* b_streamHandle{
nullptr};
282 std::array<tx_generator<sc_core::sc_time, sc_core::sc_time>*, 3> b_trHandle{{
nullptr,
nullptr,
nullptr}};
284 tx_fiber* b_streamHandleTimed{
nullptr};
287 std::array<tx_generator<>*, 3> b_trTimedHandle{{
nullptr,
nullptr,
nullptr}};
289 enum DIR { FW, BW, REQ = FW, RESP = BW };
291 tx_fiber* nb_streamHandle{
nullptr};
293 tx_fiber* nb_streamHandleTimed{
nullptr};
295 std::array<tx_generator<std::string, std::string>*, 2> nb_trHandle{{
nullptr,
nullptr}};
297 std::array<tx_generator<>*, 2> nb_trTimedHandle{{
nullptr,
nullptr}};
298 std::unordered_map<uint64_t, tx_handle> nbtx_req_handle_map;
299 std::unordered_map<uint64_t, tx_handle> nbtx_last_req_handle_map;
302 tx_fiber* dmi_streamHandle{
nullptr};
304 tx_generator<>* dmi_trGetHandle{
nullptr};
305 tx_generator<sc_dt::uint64, sc_dt::uint64>* dmi_trInvalidateHandle{
nullptr};
308 void initialize_streams() {
310 pred_succ_hndl = m_db->create_relation(
"PREDECESSOR_SUCCESSOR");
311 par_chld_hndl = m_db->create_relation(
"PARENT_CHILD");
314 b_streamHandle =
new tx_fiber((full_name +
"_bl").c_str(),
"[TLM][base-protocol][b]", m_db);
315 b_trHandle[tlm::TLM_READ_COMMAND] =
316 new tx_generator<sc_core::sc_time, sc_core::sc_time>(
"read", *b_streamHandle,
"start_delay",
"end_delay");
317 b_trHandle[tlm::TLM_WRITE_COMMAND] =
318 new tx_generator<sc_core::sc_time, sc_core::sc_time>(
"write", *b_streamHandle,
"start_delay",
"end_delay");
319 b_trHandle[tlm::TLM_IGNORE_COMMAND] =
320 new tx_generator<sc_core::sc_time, sc_core::sc_time>(
"ignore", *b_streamHandle,
"start_delay",
"end_delay");
322 b_streamHandleTimed =
new tx_fiber((full_name +
"_bl_timed").c_str(),
"[TLM][base-protocol][b][timed]", m_db);
323 b_trTimedHandle[tlm::TLM_READ_COMMAND] =
new tx_generator<>(
"read", *b_streamHandleTimed);
324 b_trTimedHandle[tlm::TLM_WRITE_COMMAND] =
new tx_generator<>(
"write", *b_streamHandleTimed);
325 b_trTimedHandle[tlm::TLM_IGNORE_COMMAND] =
new tx_generator<>(
"ignore", *b_streamHandleTimed);
329 nb_streamHandle =
new tx_fiber((full_name +
"_nb").c_str(),
"[TLM][base-protocol][nb]", m_db);
330 nb_trHandle[FW] =
new tx_generator<std::string, std::string>(
"fw", *nb_streamHandle,
"tlm_phase",
"tlm_phase[return_path]");
331 nb_trHandle[BW] =
new tx_generator<std::string, std::string>(
"bw", *nb_streamHandle,
"tlm_phase",
"tlm_phase[return_path]");
333 nb_streamHandleTimed =
new tx_fiber((full_name +
"_nb_timed").c_str(),
"[TLM][base-protocol][nb][timed]", m_db);
334 nb_trTimedHandle[FW] =
new tx_generator<>(
"request", *nb_streamHandleTimed);
335 nb_trTimedHandle[BW] =
new tx_generator<>(
"response", *nb_streamHandleTimed);
339 dmi_streamHandle =
new tx_fiber((full_name +
"_dmi").c_str(),
"[TLM][base-protocol][dmi]", m_db);
340 dmi_trGetHandle =
new tx_generator<>(
"get", *dmi_streamHandle);
341 dmi_trInvalidateHandle =
342 new tx_generator<sc_dt::uint64, sc_dt::uint64>(
"invalidate", *dmi_streamHandle,
"start_addr",
"end_addr");
347 inline std::string phase2string(
const tlm::tlm_phase& p) {
348 std::stringstream ss;
354template <
unsigned BUSWIDTH = 32,
typename TYPES = tlm::tlm_base_protocol_types,
int N = 1,
355 sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND>
356class tlm2_lwtr_recorder :
public sc_core::sc_module,
public tlm2_lwtr<TYPES> {
358 tlm::tlm_target_socket<BUSWIDTH, TYPES, N, POL> ts{
"ts"};
359 tlm::tlm_initiator_socket<BUSWIDTH, TYPES, N, POL> is{
"is"};
361 tlm2_lwtr_recorder(sc_core::sc_module_name nm,
bool recording_enabled =
true, tx_db* tr_db = tx_db::get_default_db())
362 : sc_core::sc_module(nm)
363 , tlm2_lwtr<TYPES>(name(), recording_enabled, tr_db) {
366 this->
bw_port(ts.get_base_port());
367 this->
fw_port(is.get_base_port());
377 fw_port->b_transport(trans, delay);
381 tx_handle h = b_trHandle[trans.get_command()]->begin_tx(delay);
386 if(b_streamHandleTimed)
387 htim = b_trTimedHandle[trans.get_command()]->begin_tx_delayed(sc_core::sc_time_stamp() + delay, par_chld_hndl, h);
390 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
391 if(extensionRecording) {
392 extensionRecording->recordBeginTx(h, trans);
394 extensionRecording->recordBeginTx(htim, trans);
398 trans.get_extension(preExt);
399 if(preExt ==
nullptr) {
402 trans.set_auto_extension(preExt);
404 trans.set_extension(preExt);
406 h.add_relation(pred_succ_hndl, preExt->txHandle);
408 tx_handle preTx{preExt->txHandle};
409 preExt->txHandle = h;
410 fw_port->b_transport(trans, delay);
411 trans.get_extension(preExt);
412 if(preExt->creator ==
this) {
415 if(!trans.has_mm()) {
419 preExt->txHandle = preTx;
421 h.record_attribute(
"trans", trans);
423 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
424 if(extensionRecording) {
425 extensionRecording->recordEndTx(h, trans);
427 extensionRecording->recordEndTx(htim, trans);
432 if(htim.is_valid()) {
433 htim.record_attribute(
"trans", trans);
434 htim.end_tx_delayed(sc_core::sc_time_stamp() + delay);
438template <
typename TYPES>
440 sc_core::sc_time& delay) {
442 return fw_port->nb_transport_fw(trans, phase, delay);
447 tx_handle h = nb_trHandle[FW]->begin_tx(phase2string(phase));
449 trans.get_extension(preExt);
450 if(preExt ==
nullptr) {
453 trans.set_auto_extension(preExt);
455 trans.set_extension(preExt);
458 h.add_relation(pred_succ_hndl, preExt->txHandle);
461 preExt->txHandle = h;
462 h.record_attribute(
"delay", delay);
464 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
465 if(extensionRecording)
466 extensionRecording->recordBeginTx(h, trans);
470 if(nb_streamHandleTimed) {
472 rec.tr->deep_copy_from(trans);
473 nb_timed_peq.notify(rec, delay);
478 tlm::tlm_sync_enum status =
fw_port->nb_transport_fw(trans, phase, delay);
482 h.record_attribute(
"tlm_sync", status);
483 h.record_attribute(
"delay[return_path]", delay);
484 h.record_attribute(
"trans", trans);
486 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
487 if(extensionRecording)
488 extensionRecording->recordEndTx(h, trans);
490 if(status == tlm::TLM_COMPLETED || (status == tlm::TLM_ACCEPTED && phase == tlm::END_RESP)) {
491 trans.get_extension(preExt);
492 if(preExt && preExt->creator ==
this) {
494 if(!trans.has_mm()) {
501 if(nb_streamHandleTimed) {
503 rec.tr->deep_copy_from(trans);
504 nb_timed_peq.notify(rec, delay);
506 }
else if(nb_streamHandleTimed && status == tlm::TLM_UPDATED) {
508 rec.tr->deep_copy_from(trans);
509 nb_timed_peq.notify(rec, delay);
512 nb_trHandle[FW]->end_tx(h, phase2string(phase));
516template <
typename TYPES>
518 sc_core::sc_time& delay) {
520 return bw_port->nb_transport_bw(trans, phase, delay);
525 trans.get_extension(preExt);
527 tx_handle h = nb_trHandle[BW]->begin_tx(phase2string(phase));
530 h.add_relation(pred_succ_hndl, preExt->txHandle);
532 preExt->txHandle = h;
535 h.record_attribute(
"delay", delay);
536 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
537 if(extensionRecording)
538 extensionRecording->recordBeginTx(h, trans);
542 if(nb_streamHandleTimed) {
544 rec.tr->deep_copy_from(trans);
545 nb_timed_peq.notify(rec, delay);
550 tlm::tlm_sync_enum status =
bw_port->nb_transport_bw(trans, phase, delay);
554 h.record_attribute(
"tlm_sync", status);
555 h.record_attribute(
"delay[return_path]", delay);
556 h.record_attribute(
"trans", trans);
558 for(
auto& extensionRecording : lwtr4tlm2_extension_registry<TYPES>::inst().get())
559 if(extensionRecording)
560 extensionRecording->recordEndTx(h, trans);
562 nb_trHandle[BW]->end_tx(h, phase2string(phase));
564 if(status == tlm::TLM_COMPLETED || (status == tlm::TLM_UPDATED && phase == tlm::END_RESP)) {
566 if(preExt && preExt->creator ==
this) {
569 if(!trans.has_mm()) {
576 if(nb_streamHandleTimed) {
578 rec.tr->deep_copy_from(trans);
579 nb_timed_peq.notify(rec, delay);
585template <
typename TYPES>
void tlm2_lwtr<TYPES>::nbtx_cb() {
592 h = nb_trTimedHandle[REQ]->begin_tx(par_chld_hndl, e.parent);
593 nbtx_req_handle_map[e.id] = h;
596 auto it = nbtx_req_handle_map.find(e.id);
597 sc_assert(it != nbtx_req_handle_map.end());
599 nbtx_req_handle_map.erase(it);
600 h.record_attribute(
"trans", *e.tr);
602 nbtx_last_req_handle_map[e.id] = h;
604 case tlm::BEGIN_RESP: {
605 auto it = nbtx_req_handle_map.find(e.id);
606 if(it != nbtx_req_handle_map.end()) {
608 nbtx_req_handle_map.erase(it);
609 h.record_attribute(
"trans", *e.tr);
611 nbtx_last_req_handle_map[e.id] = h;
613 h = nb_trTimedHandle[RESP]->begin_tx(par_chld_hndl, e.parent);
614 nbtx_req_handle_map[e.id] = h;
615 it = nbtx_last_req_handle_map.find(e.id);
616 if(it != nbtx_last_req_handle_map.end()) {
617 tx_handle pred = it->second;
618 nbtx_last_req_handle_map.erase(it);
619 h.add_relation(pred_succ_hndl, pred);
622 case tlm::END_RESP: {
623 auto it = nbtx_req_handle_map.find(e.id);
624 if(it != nbtx_req_handle_map.end()) {
626 nbtx_req_handle_map.erase(it);
627 h.record_attribute(
"trans", *e.tr);
641 return fw_port->get_direct_mem_ptr(trans, dmi_data);
642 tx_handle h = dmi_trGetHandle->begin_tx();
643 bool status =
fw_port->get_direct_mem_ptr(trans, dmi_data);
644 h.record_attribute(
"trans", trans);
645 h.record_attribute(
"dmi_data", dmi_data);
657 bw_port->invalidate_direct_mem_ptr(start_addr, end_addr);
660 tx_handle h = dmi_trInvalidateHandle->begin_tx(start_addr);
661 bw_port->invalidate_direct_mem_ptr(start_addr, end_addr);
662 dmi_trInvalidateHandle->end_tx(h, end_addr);
672 return fw_port->transport_dbg(trans);