scc 2025.09
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 <iostream>
19#include <tlm/scc/scv/tlm_extension_recording_registry.h>
20
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 return "RESERVED";
135}
136
137template <> const char* to_char<dat_optype_e>(dat_optype_e v) {
138 switch(v) {
139 case dat_optype_e::DataLCrdReturn:
140 return "DataLCrdReturn";
141 case dat_optype_e::SnpRespData:
142 return "SnpRespData";
143 case dat_optype_e::CopyBackWrData:
144 return "CopyBackWrData";
145 case dat_optype_e::NonCopyBackWrData:
146 return "NonCopyBackWrData";
147 case dat_optype_e::CompData:
148 return "CompData";
149 case dat_optype_e::SnpRespDataPtl:
150 return "SnpRespDataPtl";
151 case dat_optype_e::SnpRespDataFwded:
152 return "SnpRespDataFwded";
153 case dat_optype_e::WriteDataCancel:
154 return "WriteDataCancel";
155 case dat_optype_e::DataSepResp:
156 return "DataSepResp";
157 case dat_optype_e::NCBWrDataCompAck:
158 return "NCBWrDataCompAck";
159 default:
160 return "UNKNOWN_dat_optype_e";
161 }
162}
163
164template <> const char* to_char<rsp_optype_e>(rsp_optype_e v) {
165 switch(v) {
166 case rsp_optype_e::RespLCrdReturn:
167 return "RespLCrdReturn";
168 case rsp_optype_e::SnpResp:
169 return "SnpResp";
170 case rsp_optype_e::CompAck:
171 return "CompAck";
172 case rsp_optype_e::RetryAck:
173 return "RetryAck";
174 case rsp_optype_e::Comp:
175 return "Comp";
176 case rsp_optype_e::CompDBIDResp:
177 return "CompDBIDResp";
178 case rsp_optype_e::DBIDResp:
179 return "DBIDResp";
180 case rsp_optype_e::PCrdGrant:
181 return "PCrdGrant";
182 case rsp_optype_e::ReadReceipt:
183 return "ReadReceipt";
184 case rsp_optype_e::SnpRespFwded:
185 return "SnpRespFwded";
186 case rsp_optype_e::TagMatch:
187 return "TagMatch";
188 case rsp_optype_e::RespSepData:
189 return "RespSepData";
190 case rsp_optype_e::Persist:
191 return "Persist";
192 case rsp_optype_e::CompPersist:
193 return "CompPersist";
194 case rsp_optype_e::DBIDRespOrd:
195 return "DBIDRespOrd";
196 case rsp_optype_e::StashDone:
197 return "StashDone";
198 case rsp_optype_e::CompStashDone:
199 return "CompStashDone";
200 case rsp_optype_e::CompCMO:
201 return "CompCMO";
202 case rsp_optype_e::INVALID:
203 return "---";
204 default:
205 return "UNKNOWN_rsp_optype_e";
206 }
207}
208
209template <> const char* to_char<snp_optype_e>(snp_optype_e v) {
210 switch(v) {
211 case snp_optype_e::SnpLCrdReturn:
212 return "SnpLCrdReturn";
213 case snp_optype_e::SnpShared:
214 return "SnpShared";
215 case snp_optype_e::SnpClean:
216 return "SnpClean";
217 case snp_optype_e::SnpOnce:
218 return "SnpOnce";
219 case snp_optype_e::SnpNotSharedDirty:
220 return "SnpNotSharedDirty";
221 case snp_optype_e::SnpUniqueStash:
222 return "SnpUniqueStash";
223 case snp_optype_e::SnpMakeInvalidStash:
224 return "SnpMakeInvalidStash";
225 case snp_optype_e::SnpUnique:
226 return "SnpUnique";
227 case snp_optype_e::SnpCleanShared:
228 return "SnpCleanShared";
229 case snp_optype_e::SnpCleanInvalid:
230 return "SnpCleanInvalid";
231 case snp_optype_e::SnpMakeInvalid:
232 return "SnpMakeInvalid";
233 case snp_optype_e::SnpStashUnique:
234 return "SnpStashUnique";
235 case snp_optype_e::SnpStashShared:
236 return "SnpStashShared";
237 case snp_optype_e::SnpDVMOp:
238 return "SnpDVMOp";
239 case snp_optype_e::SnpSharedFwd:
240 return "SnpSharedFwd";
241 case snp_optype_e::SnpCleanFwd:
242 return "SnpCleanFwd";
243 case snp_optype_e::SnpOnceFwd:
244 return "SnpOnceFwd";
245 case snp_optype_e::SnpNotSharedDirtyFwd:
246 return "SnpNotSharedDirtyFwd";
247 case snp_optype_e::SnpUniqueFwd:
248 return "SnpUniqueFwd";
249 default:
250 return "UNKNOWN_snp_optype_e";
251 }
252}
253
254template <> const char* to_char<dat_resptype_e>(dat_resptype_e v) {
255 switch(v) {
256 // case CompData_I: return "CompData_I";
257 // case DataSepResp_I: return "DataSepResp_I";
258 // case RespSepData_I: return "RespSepData_I";
259 // case CompData_UC: return "CompData_UC";
260 // case DataSepResp_UC: return "DataSepResp_UC";
261 // case RespSepData_UC: return "RespSepData_UC";
262 // case CompData_SC: return "CompData_SC";
263 // case DataSepResp_SC: return "DataSepResp_SC";
264 // case RespSepData_SC: return "RespSepData_SC";
265 case dat_resptype_e::CompData_UD_PD:
266 return "CompData_UD_PD";
267 case dat_resptype_e::CompData_SD_PD:
268 return "CompData_SD_PD";
269 case dat_resptype_e::Comp_I:
270 return "Comp_I";
271 case dat_resptype_e::Comp_UC:
272 return "Comp_UC";
273 case dat_resptype_e::Comp_SC:
274 return "Comp_SC";
275 // case CopyBackWrData_I: return "CopyBackWrData_I";
276 // case CopyBackWrData_UC: return "CopyBackWrData_UC";
277 // case CopyBackWrData_SC: return "CopyBackWrData_SC";
278 // case CopyBackWrData_UD_PD: return "CopyBackWrData_UD_PD";
279 // case CopyBackWrData_SD_PD: return "CopyBackWrData_SD_PD";
280 // case NonCopyBackWrData: return "NonCopyBackWrData";
281 // case NCBWrDataCompAck: return "NCBWrDataCompAck";
282 default:
283 return "UNKNOWN_dat_resptype_e";
284 }
285}
286
287template <> const char* to_char<rsp_resptype_e>(rsp_resptype_e v) {
288 switch(v) {
289 case rsp_resptype_e::SnpResp_I:
290 return "SnpResp_I";
291 case rsp_resptype_e::SnpResp_SC:
292 return "SnpResp_SC";
293 case rsp_resptype_e::SnpResp_UC:
294 return "SnpResp_UC";
295 // case SnpResp_UD: return "SnpResp_UD";
296 case rsp_resptype_e::SnpResp_SD:
297 return "SnpResp_SD";
298 default:
299 return "UNKNOWN_rsp_resptype_e";
300 }
301}
302
303template <> const char* to_char<rsp_resperrtype_e>(rsp_resperrtype_e v) {
304 switch(v) {
305 case rsp_resperrtype_e::OK:
306 return "OK";
307 case rsp_resperrtype_e::EXOK:
308 return "EXOK";
309 case rsp_resperrtype_e::DERR:
310 return "DERR";
311 case rsp_resperrtype_e::NDERR:
312 return "NDERR";
313 default:
314 return "rsp_resperrtype_e";
315 }
316}
317
318template <> const char* to_char<credit_type_e>(credit_type_e v) {
319 switch(v) {
320 case credit_type_e::LINK:
321 return "LINK";
322 case credit_type_e::REQ:
323 return "REQ";
324 case credit_type_e::RESP:
325 return "RESP";
326 case credit_type_e::DATA:
327 return "DATA";
328 default:
329 return "credit_type_e";
330 }
331}
332
333std::ostream& operator<<(std::ostream& os, const tlm::tlm_generic_payload& t) {
334 char const* ch =
335 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) return "Coherent transactions allow only cache line size data transfers";
361 }
362 return nullptr;
363}
364
365} // namespace chi
366
367#include <tlm/scc/scv/tlm_recorder.h>
368#include <tlm/scc/tlm_id.h>
369namespace chi {
370using namespace tlm::scc::scv;
371
372class tlm_id_ext_recording : public tlm_extensions_recording_if<chi_protocol_types> {
373
374 void recordBeginTx(SCVNS scv_tr_handle& handle, chi_protocol_types::tlm_payload_type& trans) override {
375 if(auto ext = trans.get_extension<tlm::scc::tlm_id_extension>()) {
376 handle.record_attribute("trans.uid", ext->id);
377 }
378 }
379
380 void recordEndTx(SCVNS scv_tr_handle& handle, tlm::tlm_base_protocol_types::tlm_payload_type& trans) override {
381 }
382};
383
384class chi_ctrl_ext_recording : public tlm_extensions_recording_if<chi_protocol_types> {
385
386 void recordBeginTx(SCVNS scv_tr_handle& handle, chi_protocol_types::tlm_payload_type& trans) override {
387 auto ext = trans.get_extension<chi_ctrl_extension>();
388 if(ext) {
389 handle.record_attribute("trans.chi_c.qos", ext->get_qos());
390 handle.record_attribute("trans.chi_c.src_id", ext->get_src_id());
391 handle.record_attribute("trans.chi_c.txn_id", ext->get_txn_id());
392 handle.record_attribute("trans.chi_c.tgt_id", ext->req.get_tgt_id());
393 handle.record_attribute("trans.chi_c.lp_id", ext->req.get_lp_id());
394 handle.record_attribute("trans.chi_c.return_txn_id", ext->req.get_return_txn_id());
395 handle.record_attribute("trans.chi_c.stash_lp_id", ext->req.get_stash_lp_id());
396 handle.record_attribute("trans.chi_c.size", ext->req.get_size());
397 handle.record_attribute("trans.chi_c.mem_attr", ext->req.get_mem_attr());
398 handle.record_attribute("trans.chi_c.req.pcrd_type", ext->req.get_pcrd_type());
399 handle.record_attribute("trans.chi_c.order", ext->req.get_order());
400 handle.record_attribute("trans.chi_c.endian", ext->req.is_endian());
401 handle.record_attribute("trans.chi_c.req.trace_tag", ext->req.is_trace_tag());
402 handle.record_attribute("trans.chi_c.return_n_id", ext->req.get_return_n_id());
403 handle.record_attribute("trans.chi_c.stash_n_id", ext->req.get_stash_n_id());
404 handle.record_attribute("trans.chi_c.opcode", std::string(to_char(ext->req.get_opcode())));
405 handle.record_attribute("trans.chi_c.stash_nnode_id_valid", ext->req.is_stash_n_id_valid());
406 handle.record_attribute("trans.chi_c.stash_lp_id_valid", ext->req.is_stash_lp_id_valid());
407 handle.record_attribute("trans.chi_c.non_secure", ext->req.is_non_secure());
408 handle.record_attribute("trans.chi_c.exp_comp_ack", ext->req.is_exp_comp_ack());
409 handle.record_attribute("trans.chi_c.allow_retry", ext->req.is_allow_retry());
410 handle.record_attribute("trans.chi_c.snp_attr", ext->req.is_snp_attr());
411 handle.record_attribute("trans.chi_c.excl", ext->req.is_excl());
412 handle.record_attribute("trans.chi_c.snoop_me", ext->req.is_snoop_me());
413 handle.record_attribute("trans.chi_c.likely_shared", ext->req.is_likely_shared());
414 handle.record_attribute("trans.chi_c.txn_rsvdc", ext->req.get_rsvdc()); // Reserved for customer use.
415 handle.record_attribute("trans.chi_c.tag_op", ext->req.get_tag_op());
416 handle.record_attribute("trans.chi_c.tag_group_id", ext->req.get_tag_group_id());
417 handle.record_attribute("trans.chi_c.mpam", ext->req.get_mpam());
418 handle.record_attribute("trans.chi_c.rsp.db_id", ext->resp.get_db_id());
419 handle.record_attribute("trans.chi_c.rsp.pcrd_type", ext->resp.get_pcrd_type());
420 handle.record_attribute("trans.chi_c.rsp.resp_err", std::string(to_char(ext->resp.get_resp_err())));
421 handle.record_attribute("trans.chi_c.rsp.fwd_state", ext->resp.get_fwd_state());
422 handle.record_attribute("trans.chi_c.rsp.data_pull", ext->resp.get_data_pull());
423 handle.record_attribute("trans.chi_c.rsp.opcode", std::string(to_char(ext->resp.get_opcode())));
424 handle.record_attribute("trans.chi_c.rsp.resp", std::string(to_char(ext->resp.get_resp())));
425 handle.record_attribute("trans.chi_c.rsp.tgt_id", ext->resp.get_tgt_id());
426 handle.record_attribute("trans.chi_c.rsp.trace_tag", ext->resp.is_trace_tag());
427 handle.record_attribute("trans.chi_c.rsp.tag_op", ext->resp.get_tag_op());
428 handle.record_attribute("trans.chi_c.rsp.tag_group_id", ext->resp.get_tag_group_id());
429 }
430 }
431
432 void recordEndTx(SCVNS scv_tr_handle& handle, chi_protocol_types::tlm_payload_type& trans) override {}
433};
434
435class chi_data_ext_recording : public tlm_extensions_recording_if<chi_protocol_types> {
436
437 void recordBeginTx(SCVNS scv_tr_handle& handle, chi_protocol_types::tlm_payload_type& trans) override {
438 auto ext = trans.get_extension<chi_data_extension>();
439 if(ext) {
440 handle.record_attribute("trans.chi_d.qos", ext->get_qos());
441 handle.record_attribute("trans.chi_d.src_id", ext->get_src_id());
442 handle.record_attribute("trans.chi_d.txn_id", ext->get_txn_id());
443 handle.record_attribute("trans.chi_d.db_id", ext->dat.get_db_id());
444 handle.record_attribute("trans.chi_d.resp_err", std::string(to_char(ext->dat.get_resp_err())));
445 handle.record_attribute("trans.chi_d.resp", std::string(to_char(ext->dat.get_resp())));
446 handle.record_attribute("trans.chi_d.fwd_state", ext->dat.get_fwd_state());
447 handle.record_attribute("trans.chi_d.data_pull", ext->dat.get_data_pull());
448 handle.record_attribute("trans.chi_d.data_source", ext->dat.get_data_source());
449 handle.record_attribute("trans.chi_d.cc_id", ext->dat.get_cc_id());
450 handle.record_attribute("trans.chi_d.data_id", ext->dat.get_data_id());
451 handle.record_attribute("trans.chi_d.poison", ext->dat.get_poison());
452 handle.record_attribute("trans.chi_d.tgt_id", ext->dat.get_tgt_id());
453 handle.record_attribute("trans.chi_d.home_node_id", ext->dat.get_home_n_id());
454 handle.record_attribute("trans.chi_d.opcode", std::string(to_char(ext->dat.get_opcode())));
455 handle.record_attribute("trans.chi_d.rsvdc", ext->dat.get_rsvdc());
456 handle.record_attribute("trans.chi_d.data_check", ext->dat.get_data_check());
457 handle.record_attribute("trans.chi_d.trace_tag", ext->dat.is_trace_tag());
458 handle.record_attribute("trans.chi_d.tag_op", ext->dat.get_tag_op());
459 handle.record_attribute("trans.chi_c.tag", ext->dat.get_tag());
460 handle.record_attribute("trans.chi_c.tu", ext->dat.get_tu());
461 }
462 }
463
464 void recordEndTx(SCVNS scv_tr_handle& handle, chi_protocol_types::tlm_payload_type& trans) override {}
465};
466
467class chi_snp_ext_recording : public tlm_extensions_recording_if<chi_protocol_types> {
468
469 void recordBeginTx(SCVNS scv_tr_handle& handle, chi_protocol_types::tlm_payload_type& trans) override {
470 auto ext = trans.get_extension<chi_snp_extension>();
471 if(ext) {
472 handle.record_attribute("trans.chi_s.qos", ext->get_qos());
473 handle.record_attribute("trans.chi_s.src_id", ext->get_src_id());
474 handle.record_attribute("trans.chi_s.txn_id", ext->get_txn_id());
475 handle.record_attribute("trans.chi_s.fwd_txn_id", ext->req.get_fwd_txn_id());
476 handle.record_attribute("trans.chi_s.stash_lp_id", ext->req.get_stash_lp_id());
477 handle.record_attribute("trans.chi_s.vm_id_ext", ext->req.get_vm_id_ext());
478 handle.record_attribute("trans.chi_s.stash_lp_id_valid", ext->req.is_stash_lp_id_valid());
479 handle.record_attribute("trans.chi_s.opcode", std::string(to_char(ext->req.get_opcode())));
480 handle.record_attribute("trans.chi_s.fwd_n_id", ext->req.get_fwd_n_id());
481 handle.record_attribute("trans.chi_s.non_secure", ext->req.is_non_secure());
482 handle.record_attribute("trans.chi_s.do_not_goto_sd", ext->req.is_do_not_goto_sd());
483 handle.record_attribute("trans.chi_s.do_not_data_pull", ext->req.is_do_not_data_pull());
484 handle.record_attribute("trans.chi_s.ret_to_src", ext->req.is_ret_to_src());
485 handle.record_attribute("trans.chi_s.trace_tag", ext->req.is_trace_tag());
486 handle.record_attribute("trans.chi_s.rsp.db_id", ext->resp.get_db_id());
487 handle.record_attribute("trans.chi_s.rsp.pcrd_type", ext->resp.get_pcrd_type());
488 handle.record_attribute("trans.chi_s.rsp.resp_err", std::string(to_char(ext->resp.get_resp_err())));
489 handle.record_attribute("trans.chi_s.rsp.fwd_state", ext->resp.get_fwd_state());
490 handle.record_attribute("trans.chi_s.rsp.data_pull", ext->resp.get_data_pull());
491 handle.record_attribute("trans.chi_s.rsp.opcode", std::string(to_char(ext->resp.get_opcode())));
492 handle.record_attribute("trans.chi_s.rsp.resp", std::string(to_char(ext->resp.get_resp())));
493 handle.record_attribute("trans.chi_s.rsp.tgt_id", ext->resp.get_tgt_id());
494 handle.record_attribute("trans.chi_s.rsp.trace_tag", ext->resp.is_trace_tag());
495 }
496 }
497
498 void recordEndTx(SCVNS scv_tr_handle& handle, chi_protocol_types::tlm_payload_type& trans) override {}
499};
500
501class chi_credit_ext_recording : public tlm_extensions_recording_if<chi_protocol_types> {
502
503 void recordBeginTx(SCVNS scv_tr_handle& handle, chi_protocol_types::tlm_payload_type& trans) override {
504 auto ext = trans.get_extension<chi_credit_extension>();
505 if(ext) {
506 handle.record_attribute("trans.chi_credit.type", std::string(to_char(ext->type)));
507 handle.record_attribute("trans.chi_credit.count", ext->count);
508 }
509 }
510
511 void recordEndTx(SCVNS scv_tr_handle& handle, chi_protocol_types::tlm_payload_type& trans) override {
512 auto ext = trans.get_extension<chi_credit_extension>();
513 if(ext) {
514 handle.record_attribute("trans.chi_credit.type", std::string(to_char(ext->type)));
515 handle.record_attribute("trans.chi_credit.count", ext->count);
516 }
517 }
518};
519namespace scv {
520using namespace tlm::scc::scv;
521#if defined(__GNUG__)
522__attribute__((constructor))
523#endif
524bool register_extensions() {
525 tlm::scc::tlm_id_extension ext(nullptr); // NOLINT
526 tlm_extension_recording_registry<chi::chi_protocol_types>::inst().register_ext_rec(
527 ext.ID, new tlm_id_ext_recording()); // NOLINT
528 chi::chi_ctrl_extension extchi_req; // NOLINT
529 tlm_extension_recording_registry<chi::chi_protocol_types>::inst().register_ext_rec(
530 extchi_req.ID,
531 new chi::chi_ctrl_ext_recording()); // NOLINT
532 chi::chi_data_extension extchi_data; // NOLINT
533 tlm_extension_recording_registry<chi::chi_protocol_types>::inst().register_ext_rec(
534 extchi_data.ID,
535 new chi::chi_data_ext_recording()); // NOLINT
536 chi::chi_snp_extension extchi_snp; // NOLINT
537 tlm_extension_recording_registry<chi::chi_protocol_types>::inst().register_ext_rec(
538 extchi_snp.ID,
539 new chi::chi_snp_ext_recording()); // NOLINT
540 chi::chi_credit_extension extchi_credit; // NOLINT
541 tlm_extension_recording_registry<chi::chi_protocol_types>::inst().register_ext_rec(
542 extchi_credit.ID,
543 new chi::chi_credit_ext_recording()); // NOLINT
544 return true; // NOLINT
545}
546bool registered = register_extensions();
547} // namespace scv
548} // namespace chi
The TLM transaction extensions recorder interface.
TLM2.0 components modeling CHI.
Definition chi_tlm.cpp:21
const char * to_char(E t)
SCC SCV4TLM classes and functions.