scc 2026.07
SystemC components library
tl_tlm.cpp
1/*******************************************************************************
2 * Copyright 2019-2024 MINRES Technologies GmbH
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *******************************************************************************/
16
17#include <array>
18#include <fmt/format.h>
19#include <tilelink/tl_tlm.h>
20#include <tlm/scc/scv/tlm_extension_recording_registry.h>
21#include <util/ities.h>
22
23namespace tilelink {
24namespace {
25const std::array<std::string, 3> cmd_str{"R", "W", "I"};
26}
27
28template <> const char* to_char<opcode_e>(opcode_e v) {
29 switch(v) {
30 case opcode_e::Get:
31 return "Get";
32 case opcode_e::AccessAckData:
33 return "AccessAckData";
34 case opcode_e::PutFullData:
35 return "PutFullData";
36 case opcode_e::PutPartialData:
37 return "PutPartialData";
38 case opcode_e::AccessAck:
39 return "AccessAck";
40 case opcode_e::ArithmeticData:
41 return "ArithmeticData";
42 case opcode_e::LogicalData:
43 return "LogicalData";
44 case opcode_e::Intent:
45 return "Intent";
46 case opcode_e::HintAck:
47 return "HintAck";
48 case opcode_e::AcquireBlock:
49 return "AcquireBlock";
50 case opcode_e::AcquirePerm:
51 return "AcquirePerm";
52 case opcode_e::Grant:
53 return "Grant";
54 case opcode_e::GrantData:
55 return "GrantData";
56 case opcode_e::GrantAck:
57 return "GrantAck";
58 case opcode_e::ProbeBlock:
59 return "ProbeBlock";
60 case opcode_e::ProbePerm:
61 return "ProbePerm";
62 case opcode_e::ProbeAck:
63 return "ProbeAck";
64 case opcode_e::ProbeAckData:
65 return "ProbeAckData";
66 case opcode_e::Release:
67 return "Release";
68 case opcode_e::ReleaseData:
69 return "ReleaseData";
70 case opcode_e::ReleaseAck:
71 return "ReleaseAck";
72 default:
73 return "UNKNOWN";
74 }
75}
76
77template <> const char* to_char<param_e>(param_e v) {
78 switch(v) {
79 case param_e::CAP_2T:
80 return "Cap:2T (0)";
81 case param_e::CAP_2B:
82 return "Cap:2B (1)";
83 case param_e::CAP_2N:
84 return "Cap:2N (2)";
85 case param_e::GROW_N2B:
86 return "Grow:N2B (0)";
87 case param_e::GROW_N2T:
88 return "Grow:N2T (1)";
89 case param_e::GROW_B2T:
90 return "Grow:B2T (2)";
91 case param_e::PRUNE_T2B:
92 return "Prune:T2B (0)";
93 case param_e::PRUNE_T2N:
94 return "Prune:T2N (1)";
95 case param_e::PRUNE_B2N:
96 return "Prune:B2N (2)";
97 case param_e::REP_T2T:
98 return "Report:T2T (0)";
99 case param_e::REP_B2B:
100 return "Report:B2B (1)";
101 case param_e::REP_N2N:
102 return "Report:N2N (2)";
103 default:
104 return "UNKNOWN";
105 }
106}
107
108std::ostream& operator<<(std::ostream& os, const tlm::tlm_generic_payload& t) {
109 os << "CMD:" << cmd_str[t.get_command()] << ", "
110 << "ADDR:0x" << std::hex << t.get_address() << ", TXLEN:0x" << t.get_data_length();
111 if(auto e = t.get_extension<tilelink::tilelink_extension>()) {
112 os << ", "
113 << "OPC:0x" << std::hex << static_cast<unsigned>(e->get_opcode()) << "PARAM:" << e->get_param();
114 }
115 os << " [ptr:" << &t << "]";
116 return os;
117}
118
119using namespace tlm::scc::scv;
120
121struct tlc_ext_record : public tlm_extension_record_if {
122
123 tlc_ext_record() { recordBegin = &tlc_ext_record::recordBeginTx; }
124
125 static void recordBeginTx(SCVNS scv_tr_handle& handle, tlm::tlm_extension_base* e, std::string const& prefix) {
126 if(auto ext = dynamic_cast<tilelink_extension*>(e)) {
127 handle.record_attribute(fmt::format("{}opcode", prefix).c_str(), std::string(to_char(ext->get_opcode())));
128 handle.record_attribute(fmt::format("{}param", prefix).c_str(), std::string(to_char(ext->get_param())));
129 handle.record_attribute(fmt::format("{}source", prefix).c_str(), ext->get_source());
130 handle.record_attribute(fmt::format("{}sink", prefix).c_str(), ext->get_sink());
131 handle.record_attribute(fmt::format("{}corrupt", prefix).c_str(), ext->is_corrupt());
132 handle.record_attribute(fmt::format("{}denied", prefix).c_str(), ext->is_denied());
133 }
134 }
135};
136
137struct tlc_ext_recording : public tlm_extensions_recording_if<tl_protocol_types> {
138
139 tlc_ext_recording() { recordBegin = &tlc_ext_recording::recordBeginTx; }
140
141 static void recordBeginTx(SCVNS scv_tr_handle& handle, tl_protocol_types::tlm_payload_type& trans) {
142 tlm_extension_record_registry::get().recordBeginTx(tilelink_extension::ID, handle, trans.get_extension<tilelink_extension>(),
143 "trans.tl.");
144 }
145};
146
147namespace scv {
148using namespace tlm::scc::scv;
149#if defined(__GNUG__)
150__attribute__((constructor))
151#endif
152bool register_extensions() {
153 tilelink::tilelink_extension ext; // NOLINT
154 tlm_extension_recording_registry<tilelink::tl_protocol_types>::get().register_ext_rec(ext.ID,
155 util::make_unique<tlc_ext_recording>()); // NOLINT
156 tlm_extension_record_registry::get().register_ext_rec(ext.ID, util::make_unique<tlc_ext_record>()); // NOLINT
157 return true; // NOLINT
158}
159bool registered = register_extensions();
160} // namespace scv
161} // namespace tilelink
SCC SCV4TLM classes and functions.
util::delegate< void(SCVNS scv_tr_handle &, tlm::tlm_extension_base *, std::string const &)> recordBegin
recording attributes in extensions at the beginning, it is intended to be overload as it does nothing
The TLM transaction extensions recorder interface.
void recordBeginTx(SCVNS scv_tr_handle &h, typename TYPES::tlm_payload_type &trans)
recording attributes in extensions at the beginning, it is intended to be overload as it does nothing