scc 2026.07
SystemC components library
chi_tlm.cpp
1/*
2 * Copyright 2020 Arteris IP
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 "chi_tlm.h"
18#include <fmt/format.h>
19#include <iostream>
20#include <tlm/scc/scv/tlm_extension_recording_registry.h>
21namespace chi {
22namespace {
23std::array<std::string, 3> cmd_str{"R", "W", "I"};
24}
25std::array<char const*, 103> opc2str = {
26 "ReqLCrdReturn",
27 "ReadShared",
28 "ReadClean",
29 "ReadOnce",
30 "ReadNoSnp",
31 "PCrdReturn",
32 "Reserved",
33 "ReadUnique",
34 "CleanShared",
35 "CleanInvalid",
36 "MakeInvalid",
37 "CleanUnique",
38 "MakeUnique",
39 "Evict",
40 "EOBarrier",
41 "ECBarrier",
42 "RESERVED",
43 "ReadNoSnpSep",
44 "RESERVED",
45 "CleanSharedPersistSep",
46 "DVMOp",
47 "WriteEvictFull",
48 "WriteCleanPtl",
49 "WriteCleanFull",
50 "WriteUniquePtl",
51 "WriteUniqueFull",
52 "WriteBackPtl",
53 "WriteBackFull",
54 "WriteNoSnpPtl",
55 "WriteNoSnpFull",
56 "RESERVED",
57 "RESERVED",
58 "WriteUniqueFullStash",
59 "WriteUniquePtlStash",
60 "StashOnceShared",
61 "StashOnceUnique",
62 "ReadOnceCleanInvalid",
63 "ReadOnceMakeInvalid",
64 "ReadNotSharedDirty",
65 "CleanSharedPersist",
66 "AtomicStoreAdd",
67 "AtomicStoreClr",
68 "AtomicStoreEor",
69 "AtomicStoreSet",
70 "AtomicStoreSmax",
71 "AtomicStoreSmin",
72 "AtomicStoreUmax",
73 "AtomicStoreUmin",
74 "AtomicLoadAdd",
75 "AtomicLoadClr",
76 "AtomicLoadEor",
77 "AtomicLoadSet",
78 "AtomicLoadSmax",
79 "AtomicLoadSmin",
80 "AtomicLoadUmax",
81 "AtomicLoadUmin",
82 "AtomicSwap",
83 "AtomicCompare",
84 "PrefetchTgt",
85 "RESERVED",
86 "RESERVED",
87 "RESERVED",
88 "RESERVED",
89 "RESERVED",
90 "RESERVED",
91 "MakeReadUnique",
92 "WriteEvictOrEvict",
93 "WriteUniqueZero",
94 "WriteNoSnpZero",
95 "RESERVED",
96 "RESERVED",
97 "StashOnceSepShared",
98 "StashOnceSepUnique",
99 "RESERVED",
100 "RESERVED",
101 "RESERVED",
102 "ReadPreferUnique",
103 "RESERVED",
104 "RESERVED",
105 "RESERVED",
106 "WriteNoSnpFullCleanSh",
107 "WriteNoSnpFullCleanInv",
108 "WriteNoSnpFullCleanShPerSep",
109 "RESERVED",
110 "WriteUniqueFullCleanSh",
111 "RESERVED",
112 "WriteUniqueFullCleanShPerSep",
113 "RESERVED",
114 "WriteBackFullCleanSh",
115 "WriteBackFullCleanInv",
116 "WriteBackFullCleanShPerSep",
117 "RESERVED",
118 "WriteCleanFullCleanSh",
119 "RESERVED",
120 "WriteCleanFullCleanShPerSep",
121 "RESERVED",
122 "WriteNoSnpPtlCleanSh",
123 "WriteNoSnpPtlCleanInv",
124 "WriteNoSnpPtlCleanShPerSep",
125 "RESERVED",
126 "WriteUniquePtlCleanSh",
127 "RESERVED",
128 "WriteUniquePtlCleanShPerSep",
129};
130template <> const char* to_char<req_optype_e>(req_optype_e v) {
131 auto idx = static_cast<unsigned>(v);
132 if(idx < opc2str.size())
133 return opc2str[idx];
134 else
135 return "RESERVED";
136}
137
138template <> const char* to_char<dat_optype_e>(dat_optype_e v) {
139 switch(v) {
140 case dat_optype_e::DataLCrdReturn:
141 return "DataLCrdReturn";
142 case dat_optype_e::SnpRespData:
143 return "SnpRespData";
144 case dat_optype_e::CopyBackWrData:
145 return "CopyBackWrData";
146 case dat_optype_e::NonCopyBackWrData:
147 return "NonCopyBackWrData";
148 case dat_optype_e::CompData:
149 return "CompData";
150 case dat_optype_e::SnpRespDataPtl:
151 return "SnpRespDataPtl";
152 case dat_optype_e::SnpRespDataFwded:
153 return "SnpRespDataFwded";
154 case dat_optype_e::WriteDataCancel:
155 return "WriteDataCancel";
156 case dat_optype_e::DataSepResp:
157 return "DataSepResp";
158 case dat_optype_e::NCBWrDataCompAck:
159 return "NCBWrDataCompAck";
160 default:
161 return "UNKNOWN_dat_optype_e";
162 }
163}
164
165template <> const char* to_char<rsp_optype_e>(rsp_optype_e v) {
166 switch(v) {
167 case rsp_optype_e::RespLCrdReturn:
168 return "RespLCrdReturn";
169 case rsp_optype_e::SnpResp:
170 return "SnpResp";
171 case rsp_optype_e::CompAck:
172 return "CompAck";
173 case rsp_optype_e::RetryAck:
174 return "RetryAck";
175 case rsp_optype_e::Comp:
176 return "Comp";
177 case rsp_optype_e::CompDBIDResp:
178 return "CompDBIDResp";
179 case rsp_optype_e::DBIDResp:
180 return "DBIDResp";
181 case rsp_optype_e::PCrdGrant:
182 return "PCrdGrant";
183 case rsp_optype_e::ReadReceipt:
184 return "ReadReceipt";
185 case rsp_optype_e::SnpRespFwded:
186 return "SnpRespFwded";
187 case rsp_optype_e::TagMatch:
188 return "TagMatch";
189 case rsp_optype_e::RespSepData:
190 return "RespSepData";
191 case rsp_optype_e::Persist:
192 return "Persist";
193 case rsp_optype_e::CompPersist:
194 return "CompPersist";
195 case rsp_optype_e::DBIDRespOrd:
196 return "DBIDRespOrd";
197 case rsp_optype_e::StashDone:
198 return "StashDone";
199 case rsp_optype_e::CompStashDone:
200 return "CompStashDone";
201 case rsp_optype_e::CompCMO:
202 return "CompCMO";
203 case rsp_optype_e::INVALID:
204 return "---";
205 default:
206 return "UNKNOWN_rsp_optype_e";
207 }
208}
209
210template <> const char* to_char<snp_optype_e>(snp_optype_e v) {
211 switch(v) {
212 case snp_optype_e::SnpLCrdReturn:
213 return "SnpLCrdReturn";
214 case snp_optype_e::SnpShared:
215 return "SnpShared";
216 case snp_optype_e::SnpClean:
217 return "SnpClean";
218 case snp_optype_e::SnpOnce:
219 return "SnpOnce";
220 case snp_optype_e::SnpNotSharedDirty:
221 return "SnpNotSharedDirty";
222 case snp_optype_e::SnpUniqueStash:
223 return "SnpUniqueStash";
224 case snp_optype_e::SnpMakeInvalidStash:
225 return "SnpMakeInvalidStash";
226 case snp_optype_e::SnpUnique:
227 return "SnpUnique";
228 case snp_optype_e::SnpCleanShared:
229 return "SnpCleanShared";
230 case snp_optype_e::SnpCleanInvalid:
231 return "SnpCleanInvalid";
232 case snp_optype_e::SnpMakeInvalid:
233 return "SnpMakeInvalid";
234 case snp_optype_e::SnpStashUnique:
235 return "SnpStashUnique";
236 case snp_optype_e::SnpStashShared:
237 return "SnpStashShared";
238 case snp_optype_e::SnpDVMOp:
239 return "SnpDVMOp";
240 case snp_optype_e::SnpSharedFwd:
241 return "SnpSharedFwd";
242 case snp_optype_e::SnpCleanFwd:
243 return "SnpCleanFwd";
244 case snp_optype_e::SnpOnceFwd:
245 return "SnpOnceFwd";
246 case snp_optype_e::SnpNotSharedDirtyFwd:
247 return "SnpNotSharedDirtyFwd";
248 case snp_optype_e::SnpUniqueFwd:
249 return "SnpUniqueFwd";
250 default:
251 return "UNKNOWN_snp_optype_e";
252 }
253}
254
255template <> const char* to_char<dat_resptype_e>(dat_resptype_e v) {
256 switch(v) {
257 // case CompData_I: return "CompData_I";
258 // case DataSepResp_I: return "DataSepResp_I";
259 // case RespSepData_I: return "RespSepData_I";
260 // case CompData_UC: return "CompData_UC";
261 // case DataSepResp_UC: return "DataSepResp_UC";
262 // case RespSepData_UC: return "RespSepData_UC";
263 // case CompData_SC: return "CompData_SC";
264 // case DataSepResp_SC: return "DataSepResp_SC";
265 // case RespSepData_SC: return "RespSepData_SC";
266 case dat_resptype_e::CompData_UD_PD:
267 return "CompData_UD_PD";
268 case dat_resptype_e::CompData_SD_PD:
269 return "CompData_SD_PD";
270 case dat_resptype_e::Comp_I:
271 return "Comp_I";
272 case dat_resptype_e::Comp_UC:
273 return "Comp_UC";
274 case dat_resptype_e::Comp_SC:
275 return "Comp_SC";
276 // case CopyBackWrData_I: return "CopyBackWrData_I";
277 // case CopyBackWrData_UC: return "CopyBackWrData_UC";
278 // case CopyBackWrData_SC: return "CopyBackWrData_SC";
279 // case CopyBackWrData_UD_PD: return "CopyBackWrData_UD_PD";
280 // case CopyBackWrData_SD_PD: return "CopyBackWrData_SD_PD";
281 // case NonCopyBackWrData: return "NonCopyBackWrData";
282 // case NCBWrDataCompAck: return "NCBWrDataCompAck";
283 default:
284 return "UNKNOWN_dat_resptype_e";
285 }
286}
287
288template <> const char* to_char<rsp_resptype_e>(rsp_resptype_e v) {
289 switch(v) {
290 case rsp_resptype_e::SnpResp_I:
291 return "SnpResp_I";
292 case rsp_resptype_e::SnpResp_SC:
293 return "SnpResp_SC";
294 case rsp_resptype_e::SnpResp_UC:
295 return "SnpResp_UC";
296 // case SnpResp_UD: return "SnpResp_UD";
297 case rsp_resptype_e::SnpResp_SD:
298 return "SnpResp_SD";
299 default:
300 return "UNKNOWN_rsp_resptype_e";
301 }
302}
303
304template <> const char* to_char<rsp_resperrtype_e>(rsp_resperrtype_e v) {
305 switch(v) {
306 case rsp_resperrtype_e::OK:
307 return "OK";
308 case rsp_resperrtype_e::EXOK:
309 return "EXOK";
310 case rsp_resperrtype_e::DERR:
311 return "DERR";
312 case rsp_resperrtype_e::NDERR:
313 return "NDERR";
314 default:
315 return "rsp_resperrtype_e";
316 }
317}
318
319template <> const char* to_char<credit_type_e>(credit_type_e v) {
320 switch(v) {
321 case credit_type_e::LINK:
322 return "LINK";
323 case credit_type_e::REQ:
324 return "REQ";
325 case credit_type_e::RESP:
326 return "RESP";
327 case credit_type_e::DATA:
328 return "DATA";
329 default:
330 return "credit_type_e";
331 }
332}
333
334std::ostream& operator<<(std::ostream& os, const tlm::tlm_generic_payload& t) {
335 char const* ch = t.get_command() == tlm::TLM_READ_COMMAND ? "AR" : (t.get_command() == tlm::TLM_WRITE_COMMAND ? "AW" : "");
336 os << "CMD:" << cmd_str[t.get_command()] << ", " << ch << "ADDR:0x" << std::hex << t.get_address() << ", TXLEN:0x"
337 << t.get_data_length();
338 if(auto ext = t.get_extension<chi::chi_ctrl_extension>()) {
339 os << ", TXNID:" << ext->get_txn_id();
340 os << ", OPC:" << chi::to_char(ext->req.get_opcode());
341 } else if(auto ext = t.get_extension<chi::chi_snp_extension>()) {
342 os << ", TXNID:" << ext->get_txn_id();
343 os << ", OPC:" << chi::to_char(ext->req.get_opcode());
344 }
345 os << " [ptr:" << &t << "]";
346 return os;
347}
348template <> const char* is_valid_msg<chi::chi_ctrl_extension>(chi_ctrl_extension* ext) {
349 auto sz = ext->req.get_size();
350 if(sz > 6)
351 return "Illegal size setting, maximum is 6";
352 switch(ext->req.get_opcode()) {
353 case req_optype_e::ReadNoSnp:
354 case req_optype_e::ReadNoSnpSep:
355 case req_optype_e::WriteNoSnpPtl:
356 case req_optype_e::WriteUniquePtl:
357 case req_optype_e::WriteUniquePtlStash:
358 break;
359 default:
360 if(!is_dataless(ext) && sz < 6)
361 return "Coherent transactions allow only cache line size data transfers";
362 }
363 return nullptr;
364}
365
366} // namespace chi
367
368#include <tlm/scc/scv/tlm_recorder.h>
369#include <tlm/scc/tlm_id.h>
370namespace chi {
371using namespace tlm::scc::scv;
372
373struct tlm_id_ext_recording : public tlm_extensions_recording_if<chi::chi_protocol_types> {
374
375 tlm_id_ext_recording() { recordBegin = &recordBeginTx; }
376
377 static void recordBeginTx(SCVNS scv_tr_handle& handle, chi::chi_protocol_types::tlm_payload_type& trans) {
378 tlm_extension_record_registry::get().recordBeginTx(tlm::scc::tlm_id_extension::ID, handle,
379 trans.get_extension<tlm::scc::tlm_id_extension>(), "trans.");
380 }
381};
382
383struct chi_ctrl_ext_record : public tlm_extension_record_if {
384
385 chi_ctrl_ext_record() { recordBegin = &chi_ctrl_ext_record::record; }
386
387 static void record(SCVNS scv_tr_handle& handle, tlm::tlm_extension_base* e, std::string const& prefix) {
388 if(auto ext = dynamic_cast<chi_ctrl_extension*>(e)) {
389 handle.record_attribute(fmt::format("{}qos", prefix).c_str(), ext->get_qos());
390 handle.record_attribute(fmt::format("{}src_id", prefix).c_str(), ext->get_src_id());
391 handle.record_attribute(fmt::format("{}txn_id", prefix).c_str(), ext->get_txn_id());
392 handle.record_attribute(fmt::format("{}tgt_id", prefix).c_str(), ext->req.get_tgt_id());
393 handle.record_attribute(fmt::format("{}lp_id", prefix).c_str(), ext->req.get_lp_id());
394 handle.record_attribute(fmt::format("{}return_txn_id", prefix).c_str(), ext->req.get_return_txn_id());
395 handle.record_attribute(fmt::format("{}stash_lp_id", prefix).c_str(), ext->req.get_stash_lp_id());
396 handle.record_attribute(fmt::format("{}size", prefix).c_str(), ext->req.get_size());
397 handle.record_attribute(fmt::format("{}mem_attr", prefix).c_str(), ext->req.get_mem_attr());
398 handle.record_attribute(fmt::format("{}req.pcrd_type", prefix).c_str(), ext->req.get_pcrd_type());
399 handle.record_attribute(fmt::format("{}order", prefix).c_str(), ext->req.get_order());
400 handle.record_attribute(fmt::format("{}endian", prefix).c_str(), ext->req.is_endian());
401 handle.record_attribute(fmt::format("{}req.trace_tag", prefix).c_str(), ext->req.is_trace_tag());
402 handle.record_attribute(fmt::format("{}return_n_id", prefix).c_str(), ext->req.get_return_n_id());
403 handle.record_attribute(fmt::format("{}stash_n_id", prefix).c_str(), ext->req.get_stash_n_id());
404 handle.record_attribute(fmt::format("{}opcode", prefix).c_str(), std::string(to_char(ext->req.get_opcode())));
405 handle.record_attribute(fmt::format("{}stash_nnode_id_valid", prefix).c_str(), ext->req.is_stash_n_id_valid());
406 handle.record_attribute(fmt::format("{}stash_lp_id_valid", prefix).c_str(), ext->req.is_stash_lp_id_valid());
407 handle.record_attribute(fmt::format("{}non_secure", prefix).c_str(), ext->req.is_non_secure());
408 handle.record_attribute(fmt::format("{}exp_comp_ack", prefix).c_str(), ext->req.is_exp_comp_ack());
409 handle.record_attribute(fmt::format("{}allow_retry", prefix).c_str(), ext->req.is_allow_retry());
410 handle.record_attribute(fmt::format("{}snp_attr", prefix).c_str(), ext->req.is_snp_attr());
411 handle.record_attribute(fmt::format("{}excl", prefix).c_str(), ext->req.is_excl());
412 handle.record_attribute(fmt::format("{}snoop_me", prefix).c_str(), ext->req.is_snoop_me());
413 handle.record_attribute(fmt::format("{}likely_shared", prefix).c_str(), ext->req.is_likely_shared());
414 handle.record_attribute(fmt::format("{}txn_rsvdc", prefix).c_str(), ext->req.get_rsvdc()); // Reserved for customer use.
415 handle.record_attribute(fmt::format("{}tag_op", prefix).c_str(), ext->req.get_tag_op());
416 handle.record_attribute(fmt::format("{}tag_group_id", prefix).c_str(), ext->req.get_tag_group_id());
417 handle.record_attribute(fmt::format("{}mpam", prefix).c_str(), ext->req.get_mpam());
418 handle.record_attribute(fmt::format("{}rsp.db_id", prefix).c_str(), ext->resp.get_db_id());
419 handle.record_attribute(fmt::format("{}rsp.pcrd_type", prefix).c_str(), ext->resp.get_pcrd_type());
420 handle.record_attribute(fmt::format("{}rsp.resp_err", prefix).c_str(), std::string(to_char(ext->resp.get_resp_err())));
421 handle.record_attribute(fmt::format("{}rsp.fwd_state", prefix).c_str(), ext->resp.get_fwd_state());
422 handle.record_attribute(fmt::format("{}rsp.data_pull", prefix).c_str(), ext->resp.get_data_pull());
423 handle.record_attribute(fmt::format("{}rsp.opcode", prefix).c_str(), std::string(to_char(ext->resp.get_opcode())));
424 handle.record_attribute(fmt::format("{}rsp.resp", prefix).c_str(), std::string(to_char(ext->resp.get_resp())));
425 handle.record_attribute(fmt::format("{}rsp.tgt_id", prefix).c_str(), ext->resp.get_tgt_id());
426 handle.record_attribute(fmt::format("{}rsp.trace_tag", prefix).c_str(), ext->resp.is_trace_tag());
427 handle.record_attribute(fmt::format("{}rsp.tag_op", prefix).c_str(), ext->resp.get_tag_op());
428 handle.record_attribute(fmt::format("{}rsp.tag_group_id", prefix).c_str(), ext->resp.get_tag_group_id());
429 }
430 }
431};
432
433struct chi_ctrl_ext_recording : public tlm_extensions_recording_if<chi::chi_protocol_types> {
434
435 chi_ctrl_ext_recording() { recordBegin = &recordBeginTx; }
436
437 static void recordBeginTx(SCVNS scv_tr_handle& handle, chi::chi_protocol_types::tlm_payload_type& trans) {
438 tlm_extension_record_registry::get().recordBeginTx(chi_ctrl_extension::ID, handle, trans.get_extension<chi_ctrl_extension>(),
439 "trans.chi_c.");
440 }
441};
442
443struct chi_data_ext_record : public tlm_extension_record_if {
444
445 chi_data_ext_record() { recordBegin = &record; }
446
447 static void record(SCVNS scv_tr_handle& handle, tlm::tlm_extension_base* e, std::string const& prefix) {
448 if(auto ext = dynamic_cast<chi_data_extension*>(e)) {
449 handle.record_attribute(fmt::format("{}qos", prefix).c_str(), ext->get_qos());
450 handle.record_attribute(fmt::format("{}src_id", prefix).c_str(), ext->get_src_id());
451 handle.record_attribute(fmt::format("{}txn_id", prefix).c_str(), ext->get_txn_id());
452 handle.record_attribute(fmt::format("{}db_id", prefix).c_str(), ext->dat.get_db_id());
453 handle.record_attribute(fmt::format("{}resp_err", prefix).c_str(), std::string(to_char(ext->dat.get_resp_err())));
454 handle.record_attribute(fmt::format("{}resp", prefix).c_str(), std::string(to_char(ext->dat.get_resp())));
455 handle.record_attribute(fmt::format("{}fwd_state", prefix).c_str(), ext->dat.get_fwd_state());
456 handle.record_attribute(fmt::format("{}data_pull", prefix).c_str(), ext->dat.get_data_pull());
457 handle.record_attribute(fmt::format("{}data_source", prefix).c_str(), ext->dat.get_data_source());
458 handle.record_attribute(fmt::format("{}cc_id", prefix).c_str(), ext->dat.get_cc_id());
459 handle.record_attribute(fmt::format("{}data_id", prefix).c_str(), ext->dat.get_data_id());
460 handle.record_attribute(fmt::format("{}poison", prefix).c_str(), ext->dat.get_poison());
461 handle.record_attribute(fmt::format("{}tgt_id", prefix).c_str(), ext->dat.get_tgt_id());
462 handle.record_attribute(fmt::format("{}home_node_id", prefix).c_str(), ext->dat.get_home_n_id());
463 handle.record_attribute(fmt::format("{}opcode", prefix).c_str(), std::string(to_char(ext->dat.get_opcode())));
464 handle.record_attribute(fmt::format("{}rsvdc", prefix).c_str(), ext->dat.get_rsvdc());
465 handle.record_attribute(fmt::format("{}data_check", prefix).c_str(), ext->dat.get_data_check());
466 handle.record_attribute(fmt::format("{}trace_tag", prefix).c_str(), ext->dat.is_trace_tag());
467 handle.record_attribute(fmt::format("{}tag_op", prefix).c_str(), ext->dat.get_tag_op());
468 handle.record_attribute(fmt::format("{}tag", prefix).c_str(), ext->dat.get_tag());
469 handle.record_attribute(fmt::format("{}tu", prefix).c_str(), ext->dat.get_tu());
470 }
471 }
472};
473
474struct chi_data_ext_recording : public tlm_extensions_recording_if<chi::chi_protocol_types> {
475
476 chi_data_ext_recording() { recordBegin = &recordBeginTx; }
477
478 static void recordBeginTx(SCVNS scv_tr_handle& handle, chi::chi_protocol_types::tlm_payload_type& trans) {
479 tlm_extension_record_registry::get().recordBeginTx(chi_data_extension::ID, handle, trans.get_extension<chi_data_extension>(),
480 "trans.chi_d.");
481 }
482};
483
484struct chi_snp_ext_record : public tlm_extension_record_if {
485
486 chi_snp_ext_record() { recordBegin = &record; }
487
488 static void record(SCVNS scv_tr_handle& handle, tlm::tlm_extension_base* e, std::string const& prefix) {
489 if(auto ext = dynamic_cast<chi_snp_extension*>(e)) {
490 handle.record_attribute(fmt::format("{}qos", prefix).c_str(), ext->get_qos());
491 handle.record_attribute(fmt::format("{}src_id", prefix).c_str(), ext->get_src_id());
492 handle.record_attribute(fmt::format("{}txn_id", prefix).c_str(), ext->get_txn_id());
493 handle.record_attribute(fmt::format("{}fwd_txn_id", prefix).c_str(), ext->req.get_fwd_txn_id());
494 handle.record_attribute(fmt::format("{}stash_lp_id", prefix).c_str(), ext->req.get_stash_lp_id());
495 handle.record_attribute(fmt::format("{}vm_id_ext", prefix).c_str(), ext->req.get_vm_id_ext());
496 handle.record_attribute(fmt::format("{}stash_lp_id_valid", prefix).c_str(), ext->req.is_stash_lp_id_valid());
497 handle.record_attribute(fmt::format("{}opcode", prefix).c_str(), std::string(to_char(ext->req.get_opcode())));
498 handle.record_attribute(fmt::format("{}fwd_n_id", prefix).c_str(), ext->req.get_fwd_n_id());
499 handle.record_attribute(fmt::format("{}non_secure", prefix).c_str(), ext->req.is_non_secure());
500 handle.record_attribute(fmt::format("{}do_not_goto_sd", prefix).c_str(), ext->req.is_do_not_goto_sd());
501 handle.record_attribute(fmt::format("{}do_not_data_pull", prefix).c_str(), ext->req.is_do_not_data_pull());
502 handle.record_attribute(fmt::format("{}ret_to_src", prefix).c_str(), ext->req.is_ret_to_src());
503 handle.record_attribute(fmt::format("{}trace_tag", prefix).c_str(), ext->req.is_trace_tag());
504 handle.record_attribute(fmt::format("{}rsp.db_id", prefix).c_str(), ext->resp.get_db_id());
505 handle.record_attribute(fmt::format("{}rsp.pcrd_type", prefix).c_str(), ext->resp.get_pcrd_type());
506 handle.record_attribute(fmt::format("{}rsp.resp_err", prefix).c_str(), std::string(to_char(ext->resp.get_resp_err())));
507 handle.record_attribute(fmt::format("{}rsp.fwd_state", prefix).c_str(), ext->resp.get_fwd_state());
508 handle.record_attribute(fmt::format("{}rsp.data_pull", prefix).c_str(), ext->resp.get_data_pull());
509 handle.record_attribute(fmt::format("{}rsp.opcode", prefix).c_str(), std::string(to_char(ext->resp.get_opcode())));
510 handle.record_attribute(fmt::format("{}rsp.resp", prefix).c_str(), std::string(to_char(ext->resp.get_resp())));
511 handle.record_attribute(fmt::format("{}rsp.tgt_id", prefix).c_str(), ext->resp.get_tgt_id());
512 handle.record_attribute(fmt::format("{}rsp.trace_tag", prefix).c_str(), ext->resp.is_trace_tag());
513 }
514 }
515};
516
517struct chi_snp_ext_recording : public tlm_extensions_recording_if<chi::chi_protocol_types> {
518
519 chi_snp_ext_recording() { recordBegin = &recordBeginTx; }
520
521 static void recordBeginTx(SCVNS scv_tr_handle& handle, chi::chi_protocol_types::tlm_payload_type& trans) {
522 tlm_extension_record_registry::get().recordBeginTx(chi_snp_extension::ID, handle, trans.get_extension<chi_snp_extension>(),
523 "trans.chi_s.");
524 }
525};
526
527namespace {
528std::array<std::string, 4> credit_name = {"LINK", "REQ", "RESP", "DATA"};
529}
530struct chi_req_credit_ext_record : public tlm_extension_record_if {
531
532 chi_req_credit_ext_record() { recordEnd = &record_end; }
533
534 static void record_end(SCVNS scv_tr_handle& handle, tlm::tlm_extension_base* e, std::string const& prefix) {
535 if(auto ext = dynamic_cast<chi_credit_extension<credit_type_e::REQ>*>(e)) {
536 handle.record_attribute(fmt::format("{}type", prefix).c_str(), credit_name[1]);
537 handle.record_attribute(fmt::format("{}count", prefix).c_str(), ext->count);
538 }
539 }
540};
541
542struct chi_resp_credit_ext_record : public tlm_extension_record_if {
543
544 chi_resp_credit_ext_record() { recordEnd = &record_end; }
545
546 static void record_end(SCVNS scv_tr_handle& handle, tlm::tlm_extension_base* e, std::string const& prefix) {
547 if(auto ext = dynamic_cast<chi_credit_extension<credit_type_e::RESP>*>(e)) {
548 handle.record_attribute(fmt::format("{}type", prefix).c_str(), credit_name[2]);
549 handle.record_attribute(fmt::format("{}count", prefix).c_str(), ext->count);
550 }
551 }
552};
553
554struct chi_data_credit_ext_record : public tlm_extension_record_if {
555
556 chi_data_credit_ext_record() { recordEnd = &record_end; }
557
558 static void record_end(SCVNS scv_tr_handle& handle, tlm::tlm_extension_base* e, std::string const& prefix) {
559 if(auto ext = dynamic_cast<chi_credit_extension<credit_type_e::DATA>*>(e)) {
560 handle.record_attribute(fmt::format("{}type", prefix).c_str(), credit_name[2]);
561 handle.record_attribute(fmt::format("{}count", prefix).c_str(), ext->count);
562 }
563 }
564};
565
566struct chi_credit_ext_recording : public tlm_extensions_recording_if<chi_protocol_types> {
567
568 chi_credit_ext_recording() { recordEnd = &recordEndTx; }
569
570 static void recordEndTx(SCVNS scv_tr_handle& handle, chi_protocol_types::tlm_payload_type& trans) {
571 if(auto ext = trans.get_extension<chi_credit_extension<credit_type_e::REQ>>())
572 tlm_extension_record_registry::get().recordEndTx(chi_credit_extension<credit_type_e::REQ>::ID, handle, ext,
573 "trans.chi_credit.");
574 else if(auto ext = trans.get_extension<chi_credit_extension<credit_type_e::RESP>>())
575 tlm_extension_record_registry::get().recordEndTx(chi_credit_extension<credit_type_e::RESP>::ID, handle, ext,
576 "trans.chi_credit.");
577 else if(auto ext = trans.get_extension<chi_credit_extension<credit_type_e::DATA>>())
578 tlm_extension_record_registry::get().recordEndTx(chi_credit_extension<credit_type_e::DATA>::ID, handle, ext,
579 "trans.chi_credit.");
580 }
581};
582
583namespace scv {
584using namespace tlm::scc::scv;
585#if defined(__GNUG__)
586__attribute__((constructor))
587#endif
588bool register_extensions() {
589 tlm::scc::tlm_id_extension ext(nullptr); // NOLINT
590 if(!tlm_extension_recording_registry<chi::chi_protocol_types>::get().is_ext_registered(ext.ID)) // NOLINT
591 tlm_extension_recording_registry<chi::chi_protocol_types>::get().register_ext_rec(
592 ext.ID,
593 util::make_unique<tlm_id_ext_recording>()); // NOLINT
594 /********************************************************************************************************************/
595 chi::chi_ctrl_extension extchi_req; // NOLINT
596 if(!tlm_extension_recording_registry<chi::chi_protocol_types>::get().is_ext_registered(extchi_req.ID)) // NOLINT
597 tlm_extension_recording_registry<chi::chi_protocol_types>::get().register_ext_rec(
598 extchi_req.ID,
599 util::make_unique<chi::chi_ctrl_ext_recording>()); // NOLINT
600 if(!tlm_extension_record_registry::get().is_ext_registered(extchi_req.ID))
601 tlm_extension_record_registry::get().register_ext_rec(extchi_req.ID, util::make_unique<chi::chi_ctrl_ext_record>()); // NOLINT
602 /********************************************************************************************************************/
603 chi::chi_data_extension extchi_data; // NOLINT
604 if(!tlm_extension_recording_registry<chi::chi_protocol_types>::get().is_ext_registered(extchi_data.ID)) // NOLINT
605 tlm_extension_recording_registry<chi::chi_protocol_types>::get().register_ext_rec(
606 extchi_data.ID,
607 util::make_unique<chi::chi_data_ext_recording>()); // NOLINT
608 if(!tlm_extension_record_registry::get().is_ext_registered(extchi_data.ID))
609 tlm_extension_record_registry::get().register_ext_rec(extchi_data.ID, util::make_unique<chi::chi_data_ext_record>()); // NOLINT
610 /********************************************************************************************************************/
611 chi::chi_snp_extension extchi_snp; // NOLINT
612 if(!tlm_extension_recording_registry<chi::chi_protocol_types>::get().is_ext_registered(extchi_snp.ID)) // NOLINT
613 tlm_extension_recording_registry<chi::chi_protocol_types>::get().register_ext_rec(
614 extchi_snp.ID,
615 util::make_unique<chi::chi_snp_ext_recording>()); // NOLINT
616 if(!tlm_extension_record_registry::get().is_ext_registered(extchi_snp.ID))
617 tlm_extension_record_registry::get().register_ext_rec(extchi_snp.ID,
618 util::make_unique<chi::chi_snp_ext_record>()); // NOLINT
619 /********************************************************************************************************************/
620 chi::chi_credit_extension<credit_type_e::REQ> extchi_req_credit; // NOLINT
621 if(!tlm_extension_recording_registry<chi::chi_protocol_types>::get().is_ext_registered(extchi_req_credit.ID)) // NOLINT
622 tlm_extension_recording_registry<chi::chi_protocol_types>::get().register_ext_rec(
623 extchi_req_credit.ID,
624 util::make_unique<chi::chi_credit_ext_recording>()); // NOLINT
625 if(!tlm_extension_record_registry::get().is_ext_registered(extchi_req_credit.ID))
626 tlm_extension_record_registry::get().register_ext_rec(extchi_req_credit.ID,
627 util::make_unique<chi::chi_req_credit_ext_record>()); // NOLINT
628 chi::chi_credit_extension<credit_type_e::RESP> extchi_resp_credit; // NOLINT
629 if(!tlm_extension_record_registry::get().is_ext_registered(extchi_resp_credit.ID))
630 tlm_extension_record_registry::get().register_ext_rec(extchi_resp_credit.ID,
631 util::make_unique<chi::chi_resp_credit_ext_record>()); // NOLINT
632 chi::chi_credit_extension<credit_type_e::DATA> extchi_data_credit; // NOLINT
633 if(!tlm_extension_record_registry::get().is_ext_registered(extchi_data_credit.ID))
634 tlm_extension_record_registry::get().register_ext_rec(extchi_data_credit.ID,
635 util::make_unique<chi::chi_data_credit_ext_record>()); // NOLINT
636 return true; // NOLINT
637}
638bool registered = register_extensions();
639} // namespace scv
640} // namespace chi
TLM2.0 components modeling CHI.
Definition chi_tlm.cpp:21
const char * to_char(E t)
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
util::delegate< void(SCVNS scv_tr_handle &, tlm::tlm_extension_base *, std::string const &)> recordEnd
recording attributes in extensions at the end, 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
void recordEndTx(SCVNS scv_tr_handle &h, typename TYPES::tlm_payload_type &trans)
recording attributes in extensions at the end, it is intended to be overload as it does nothing