17#include <boost/filesystem.hpp>
22#include <ftr/ftr_writer.h>
38template <
bool COMPRESSED>
struct tx_db {
39 static ftr_writer<COMPRESSED>* db;
40 static void dbCb(
const scv_tr_db& _scv_tr_db, scv_tr_db::callback_reason reason,
void* data) {
42 static string fName(
"DEFAULT_scv_tr_cbor");
44 case scv_tr_db::CREATE:
45 if((_scv_tr_db.get_name() !=
nullptr) && (strlen(_scv_tr_db.get_name()) != 0))
46 fName = _scv_tr_db.get_name();
48 db =
new ftr_writer<COMPRESSED>(fName +
".ftr");
50 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Can't open recording file");
52 if(!db->cw.enc.ofs.is_open()) {
56 double secs = sc_core::sc_time::from_value(1ULL).to_seconds();
57 auto exp = rint(
log(secs) /
log(10.0));
58 db->writeInfo(
static_cast<int8_t
>(exp));
61 case scv_tr_db::DELETE:
65 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Can't close recording file");
69 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Unknown reason in scv_tr_db callback");
73 static void streamCb(
const scv_tr_stream& s, scv_tr_stream::callback_reason reason,
void* data) {
74 if(db && reason == scv_tr_stream::CREATE) {
76 db->writeStream(s.get_id(), s.get_name(), s.get_stream_kind());
77 }
catch(std::runtime_error& e) {
78 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Can't create stream");
83 static inline void recordAttribute(uint64_t
id, event_type event,
const string& name, ftr::data_type type,
const string& value) {
86 db->writeAttribute(
id, event, name, type, value);
87 }
catch(std::runtime_error& e) {
88 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Can't create attribute entry");
92 static inline void recordAttribute(uint64_t
id, event_type event,
const string& name, ftr::data_type type,
char const* value) {
95 db->writeAttribute(
id, event, name, type, value);
96 }
catch(std::runtime_error& e) {
97 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Can't create attribute entry");
101 template <
typename T>
102 static inline void recordAttribute(uint64_t
id, event_type event,
const string& name, ftr::data_type type, T value) {
105 db->writeAttribute(
id, event, name, type, value);
106 }
catch(std::runtime_error& e) {
107 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Can't create attribute entry");
111 static inline std::string get_name(
const char* prefix,
const scv_extensions_if* my_exts_p) {
113 if(!prefix || strlen(prefix) == 0) {
114 name = my_exts_p->get_name();
116 if((my_exts_p->get_name() !=
nullptr) && (strlen(my_exts_p->get_name()) > 0)) {
118 name += my_exts_p->get_name();
121 return (name ==
"") ?
"<unnamed>" : name;
124 static void recordAttributes(uint64_t
id, event_type eventType,
char const* prefix,
const scv_extensions_if* my_exts_p) {
125 if(!db || my_exts_p ==
nullptr)
127 auto name = get_name(prefix, my_exts_p);
128 switch(my_exts_p->get_type()) {
129 case scv_extensions_if::RECORD: {
130 int num_fields = my_exts_p->get_num_fields();
132 for(
int field_counter = 0; field_counter < num_fields; field_counter++) {
133 const scv_extensions_if* field_data_p = my_exts_p->get_field(field_counter);
134 recordAttributes(
id, eventType, prefix, field_data_p);
138 case scv_extensions_if::ENUMERATION:
139 recordAttribute(
id, eventType, name, ftr::data_type::ENUMERATION, my_exts_p->get_enum_string((
int)(my_exts_p->get_integer())));
141 case scv_extensions_if::BOOLEAN:
142 recordAttribute(
id, eventType, name, ftr::data_type::BOOLEAN, my_exts_p->get_bool());
144 case scv_extensions_if::INTEGER:
145 case scv_extensions_if::FIXED_POINT_INTEGER:
146 recordAttribute(
id, eventType, name, ftr::data_type::INTEGER, my_exts_p->get_integer());
148 case scv_extensions_if::UNSIGNED:
149 recordAttribute(
id, eventType, name, ftr::data_type::UNSIGNED, my_exts_p->get_integer());
151 case scv_extensions_if::POINTER:
152 recordAttribute(
id, eventType, name, ftr::data_type::POINTER, (
long long)my_exts_p->get_pointer());
154 case scv_extensions_if::STRING:
155 recordAttribute(
id, eventType, name, ftr::data_type::STRING, my_exts_p->get_string());
157 case scv_extensions_if::FLOATING_POINT_NUMBER:
158 recordAttribute(
id, eventType, name, ftr::data_type::FLOATING_POINT_NUMBER, my_exts_p->get_double());
160 case scv_extensions_if::BIT_VECTOR: {
161 sc_bv_base tmp_bv(my_exts_p->get_bitwidth());
162 my_exts_p->get_value(tmp_bv);
163 recordAttribute(
id, eventType, name, ftr::data_type::BIT_VECTOR, tmp_bv.to_string());
165 case scv_extensions_if::LOGIC_VECTOR: {
166 sc_lv_base tmp_lv(my_exts_p->get_bitwidth());
167 my_exts_p->get_value(tmp_lv);
168 recordAttribute(
id, eventType, name, ftr::data_type::LOGIC_VECTOR, tmp_lv.to_string());
170 case scv_extensions_if::ARRAY:
171 for(
int array_elt_index = 0; array_elt_index < my_exts_p->get_array_size(); array_elt_index++) {
172 const scv_extensions_if* field_data_p = my_exts_p->get_array_elt(array_elt_index);
173 recordAttributes(
id, eventType, prefix, field_data_p);
177 std::array<char, 100> tmpString;
178 sprintf(tmpString.data(),
"Unsupported attribute type = %d", my_exts_p->get_type());
179 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, tmpString.data());
184 static void generatorCb(
const scv_tr_generator_base& g, scv_tr_generator_base::callback_reason reason,
void* data) {
185 if(db && reason == scv_tr_generator_base::CREATE) {
187 db->writeGenerator(g.get_id(), g.get_name(), g.get_scv_tr_stream().get_id());
188 }
catch(std::runtime_error& e) {
189 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Can't create generator entry");
194 static void transactionCb(
const scv_tr_handle& t, scv_tr_handle::callback_reason reason,
void* data) {
195 if(!db || !t.get_scv_tr_stream().get_scv_tr_db() || !t.get_scv_tr_stream().get_scv_tr_db()->get_recording())
197 uint64_t
id = t.get_id();
199 case scv_tr_handle::BEGIN: {
200 db->startTransaction(
id, t.get_scv_tr_generator_base().get_id(), t.get_scv_tr_generator_base().get_scv_tr_stream().get_id(),
201 t.get_begin_sc_time() / sc_core::sc_time(1, sc_core::SC_PS));
203 auto my_exts_p = t.get_begin_exts_p();
204 if(my_exts_p ==
nullptr)
205 my_exts_p = t.get_scv_tr_generator_base().get_begin_exts_p();
207 auto tmp_str = t.get_scv_tr_generator_base().get_begin_attribute_name()
208 ? t.get_scv_tr_generator_base().get_begin_attribute_name()
210 recordAttributes(
id, event_type::BEGIN, tmp_str, my_exts_p);
213 case scv_tr_handle::END: {
214 auto my_exts_p = t.get_end_exts_p();
215 if(my_exts_p ==
nullptr)
216 my_exts_p = t.get_scv_tr_generator_base().get_end_exts_p();
219 t.get_scv_tr_generator_base().get_end_attribute_name() ? t.get_scv_tr_generator_base().get_end_attribute_name() :
"";
220 recordAttributes(
id, event_type::END, tmp_str, my_exts_p);
222 db->endTransaction(
id, t.get_end_sc_time() / sc_core::sc_time(1, sc_core::SC_PS));
228 static void attributeCb(
const scv_tr_handle& t,
const char* name,
const scv_extensions_if* ext,
void* data) {
229 if(!db || !t.get_scv_tr_stream().get_scv_tr_db() || !t.get_scv_tr_stream().get_scv_tr_db()->get_recording())
231 recordAttributes(t.get_id(), event_type::RECORD, name ==
nullptr ?
"" : name, ext);
234 static void relationCb(
const scv_tr_handle& tr_1,
const scv_tr_handle& tr_2,
void* data, scv_tr_relation_handle_t relation_handle) {
235 auto& stream1 = tr_1.get_scv_tr_stream();
236 auto txdb = stream1.get_scv_tr_db();
237 if(!db || !txdb || !txdb->get_recording())
240 auto& stream2 = tr_2.get_scv_tr_stream();
241 db->writeRelation(txdb->get_relation_name(relation_handle), stream1.get_id(), tr_1.get_id(), stream2.get_id(), tr_2.get_id());
242 }
catch(std::runtime_error& e) {
243 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Can't create transaction relation");
247template <
bool COMPRESSED> ftr_writer<COMPRESSED>* tx_db<COMPRESSED>::db{
nullptr};
250void scv_tr_ftr_init(
bool compressed) {
252 scv_tr_db::register_class_cb(tx_db<true>::dbCb);
253 scv_tr_stream::register_class_cb(tx_db<true>::streamCb);
254 scv_tr_generator_base::register_class_cb(tx_db<true>::generatorCb);
255 scv_tr_handle::register_class_cb(tx_db<true>::transactionCb);
256 scv_tr_handle::register_record_attribute_cb(tx_db<true>::attributeCb);
257 scv_tr_handle::register_relation_cb(tx_db<true>::relationCb);
260 scv_tr_db::register_class_cb(tx_db<false>::dbCb);
261 scv_tr_stream::register_class_cb(tx_db<false>::streamCb);
262 scv_tr_generator_base::register_class_cb(tx_db<false>::generatorCb);
263 scv_tr_handle::register_class_cb(tx_db<false>::transactionCb);
264 scv_tr_handle::register_record_attribute_cb(tx_db<false>::attributeCb);
265 scv_tr_handle::register_relation_cb(tx_db<false>::relationCb);
log
enum defining the log levels
SystemC Verification Library (SCV) Transaction Recording.