1+ #pragma once
2+
3+ #include " scv-tr/scv_tr.h"
4+ #include < rigtorp/SPSCQueue.h>
5+ #include < tlm/scc/quantum_keeper.h>
6+ #include < tlm/scc/scv/tlm_recording_extension.h>
7+ #ifdef HAS_SCV
8+ #include < scv.h>
9+ #else
10+ #include < scv-tr.h>
11+ #ifndef SCVNS
12+ #define SCVNS ::scv_tr::
13+ #endif
14+ #endif
15+
16+ namespace sysc {
17+ namespace riscv {
18+
19+ struct instr_recorder_b {
20+ bool init (std::string const & basename) {
21+ if (m_db != nullptr ) {
22+ stream_handle = new SCVNS scv_tr_stream ((basename + " .instr" ).c_str (), " TRANSACTOR" , m_db);
23+ instr_tr_handle = new SCVNS scv_tr_generator<>(" execute" , *stream_handle);
24+ return true ;
25+ }
26+ return false ;
27+ }
28+ instr_recorder_b (SCVNS scv_tr_db* m_db = SCVNS scv_tr_db::get_default_db ())
29+ : m_db(m_db) {}
30+ void record_instr (uint64_t pc, std::string const & instr_str, char mode, uint64_t status, sc_core::sc_time ltime) {
31+ if (stream_handle == nullptr )
32+ return ;
33+ if (tr_handle.is_active ())
34+ tr_handle.end_transaction ();
35+ tr_handle = instr_tr_handle->begin_transaction ();
36+ tr_handle.record_attribute (" PC" , pc);
37+ tr_handle.record_attribute (" INSTR" , instr_str);
38+ tr_handle.record_attribute (" MODE" , mode);
39+ tr_handle.record_attribute (" MSTATUS" , status);
40+ tr_handle.record_attribute (" LTIME_START" , ltime / 1_ns);
41+ }
42+
43+ tlm::scc::scv::tlm_recording_extension* get_recording_extension (bool finish_instr) {
44+ if (m_db != nullptr && tr_handle.is_valid ()) {
45+ if (finish_instr && tr_handle.is_active ())
46+ tr_handle.end_transaction ();
47+ return new tlm::scc::scv::tlm_recording_extension (tr_handle, this );
48+ }
49+ return nullptr ;
50+ }
51+
52+ protected:
53+ // ! transaction recording database
54+ SCVNS scv_tr_db* m_db{nullptr };
55+ // ! blocking transaction recording stream handle
56+ SCVNS scv_tr_stream* stream_handle{nullptr };
57+ // ! transaction generator handle for blocking transactions
58+ SCVNS scv_tr_generator<SCVNS _scv_tr_generator_default_data, SCVNS _scv_tr_generator_default_data>* instr_tr_handle{nullptr };
59+ SCVNS scv_tr_handle tr_handle;
60+ };
61+
62+ template <typename QK> struct instr_recorder : instr_recorder_b {};
63+
64+ template <> struct instr_recorder <tlm::scc::quantumkeeper> : instr_recorder_b {
65+ void disass_output (uint64_t pc, std::string const & instr_str, char mode, uint64_t status) {
66+ if (stream_handle == nullptr )
67+ return ;
68+ record_instr (pc, instr_str, mode, status, quantum_keeper.get_local_absolute_time ());
69+ }
70+ instr_recorder (tlm::scc::quantumkeeper& quantum_keeper)
71+ : quantum_keeper(quantum_keeper) {}
72+
73+ protected:
74+ tlm::scc::quantumkeeper& quantum_keeper;
75+ };
76+
77+ template <> struct instr_recorder <tlm::scc::quantumkeeper_mt> : instr_recorder_b {
78+ void disass_output (uint64_t pc, std::string const & instr_str, char mode, uint64_t status) {
79+ if (stream_handle == nullptr )
80+ return ;
81+ que.push (instr_record{pc, instr_str, mode, status, quantum_keeper.get_local_absolute_time ()});
82+ }
83+
84+ void record () {
85+ while (auto r = que.front ()) {
86+ record_instr (r->pc , r->instr_str , r->mode , r->status , r->start_time );
87+ que.pop ();
88+ }
89+ }
90+
91+ struct callback : sc_core::sc_stage_callback_if {
92+ void stage_callback (const sc_core::sc_stage& stage) override { owner->record (); }
93+ callback (instr_recorder<tlm::scc::quantumkeeper_mt>* owner)
94+ : owner(owner) {}
95+ instr_recorder<tlm::scc::quantumkeeper_mt>* owner;
96+ } stage_cb{this };
97+
98+ instr_recorder (tlm::scc::quantumkeeper_mt& quantum_keeper)
99+ : quantum_keeper(quantum_keeper)
100+ , que(8 * 1024 ) {
101+ sc_core::sc_register_stage_callback (stage_cb, sc_core::SC_PRE_TIMESTEP);
102+ }
103+
104+ protected:
105+ struct instr_record {
106+ uint64_t pc;
107+ std::string const instr_str;
108+ char mode;
109+ uint64_t status;
110+ sc_core::sc_time start_time;
111+ };
112+ tlm::scc::quantumkeeper_mt& quantum_keeper;
113+ rigtorp::SPSCQueue<instr_record> que;
114+ };
115+ } // namespace riscv
116+ } // namespace sysc
0 commit comments