17 #include <boost/filesystem.hpp>
23 #include <ftr/ftr_writer.h>
28 #include <unordered_map>
29 #include <unordered_set>
44 template <
bool COMPRESSED>
struct tx_db {
45 static ftr_writer<COMPRESSED>* db;
46 static void dbCb(
const scv_tr_db& _scv_tr_db, scv_tr_db::callback_reason reason,
void* data) {
48 static string fName(
"DEFAULT_scv_tr_cbor");
50 case scv_tr_db::CREATE:
51 if((_scv_tr_db.get_name() !=
nullptr) && (strlen(_scv_tr_db.get_name()) != 0))
52 fName = _scv_tr_db.get_name();
54 db =
new ftr_writer<COMPRESSED>(fName +
".ftr");
56 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Can't open recording file");
58 if(!db->cw.enc.ofs.is_open()) {
62 double secs = sc_core::sc_time::from_value(1ULL).to_seconds();
63 auto exp = rint(
log(secs) /
log(10.0));
64 db->writeInfo(
static_cast<int8_t
>(exp));
67 case scv_tr_db::DELETE:
71 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Can't close recording file");
75 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Unknown reason in scv_tr_db callback");
79 static void streamCb(
const scv_tr_stream& s, scv_tr_stream::callback_reason reason,
void* data) {
80 if(db && reason == scv_tr_stream::CREATE) {
82 db->writeStream(s.get_id(), s.get_name(), s.get_stream_kind());
83 }
catch(std::runtime_error& e) {
84 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Can't create stream");
89 static inline void recordAttribute(uint64_t
id, event_type event,
const string& name, ftr::data_type type,
const string& value) {
92 db->writeAttribute(
id, event, name, type, value);
93 }
catch(std::runtime_error& e) {
94 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Can't create attribute entry");
98 static inline void recordAttribute(uint64_t
id, event_type event,
const string& name, ftr::data_type type,
char const* value) {
101 db->writeAttribute(
id, event, name, type, value);
102 }
catch(std::runtime_error& e) {
103 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Can't create attribute entry");
107 template <
typename T>
108 static inline void recordAttribute(uint64_t
id, event_type event,
const string& name, ftr::data_type type, T value) {
111 db->writeAttribute(
id, event, name, type, value);
112 }
catch(std::runtime_error& e) {
113 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Can't create attribute entry");
117 static inline std::string get_name(
const char* prefix,
const scv_extensions_if* my_exts_p) {
119 if(!prefix || strlen(prefix) == 0) {
120 name = my_exts_p->get_name();
122 if((my_exts_p->get_name() !=
nullptr) && (strlen(my_exts_p->get_name()) > 0)) {
124 name += my_exts_p->get_name();
127 return (name ==
"") ?
"<unnamed>" : name;
130 static void recordAttributes(uint64_t
id, event_type eventType,
char const* prefix,
const scv_extensions_if* my_exts_p) {
131 if(!db || my_exts_p ==
nullptr)
133 auto name = get_name(prefix, my_exts_p);
134 switch(my_exts_p->get_type()) {
135 case scv_extensions_if::RECORD: {
136 int num_fields = my_exts_p->get_num_fields();
138 for(
int field_counter = 0; field_counter < num_fields; field_counter++) {
139 const scv_extensions_if* field_data_p = my_exts_p->get_field(field_counter);
140 recordAttributes(
id, eventType, prefix, field_data_p);
144 case scv_extensions_if::ENUMERATION:
145 recordAttribute(
id, eventType, name, ftr::data_type::ENUMERATION, my_exts_p->get_enum_string((
int)(my_exts_p->get_integer())));
147 case scv_extensions_if::BOOLEAN:
148 recordAttribute(
id, eventType, name, ftr::data_type::BOOLEAN, my_exts_p->get_bool());
150 case scv_extensions_if::INTEGER:
151 case scv_extensions_if::FIXED_POINT_INTEGER:
152 recordAttribute(
id, eventType, name, ftr::data_type::INTEGER, my_exts_p->get_integer());
154 case scv_extensions_if::UNSIGNED:
155 recordAttribute(
id, eventType, name, ftr::data_type::UNSIGNED, my_exts_p->get_integer());
157 case scv_extensions_if::POINTER:
158 recordAttribute(
id, eventType, name, ftr::data_type::POINTER, (
long long)my_exts_p->get_pointer());
160 case scv_extensions_if::STRING:
161 recordAttribute(
id, eventType, name, ftr::data_type::STRING, my_exts_p->get_string());
163 case scv_extensions_if::FLOATING_POINT_NUMBER:
164 recordAttribute(
id, eventType, name, ftr::data_type::FLOATING_POINT_NUMBER, my_exts_p->get_double());
166 case scv_extensions_if::BIT_VECTOR: {
167 sc_bv_base tmp_bv(my_exts_p->get_bitwidth());
168 my_exts_p->get_value(tmp_bv);
169 recordAttribute(
id, eventType, name, ftr::data_type::BIT_VECTOR, tmp_bv.to_string());
171 case scv_extensions_if::LOGIC_VECTOR: {
172 sc_lv_base tmp_lv(my_exts_p->get_bitwidth());
173 my_exts_p->get_value(tmp_lv);
174 recordAttribute(
id, eventType, name, ftr::data_type::LOGIC_VECTOR, tmp_lv.to_string());
176 case scv_extensions_if::ARRAY:
177 for(
int array_elt_index = 0; array_elt_index < my_exts_p->get_array_size(); array_elt_index++) {
178 const scv_extensions_if* field_data_p = my_exts_p->get_array_elt(array_elt_index);
179 recordAttributes(
id, eventType, prefix, field_data_p);
183 std::array<char, 100> tmpString;
184 sprintf(tmpString.data(),
"Unsupported attribute type = %d", my_exts_p->get_type());
185 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, tmpString.data());
190 static void generatorCb(
const scv_tr_generator_base& g, scv_tr_generator_base::callback_reason reason,
void* data) {
191 if(db && reason == scv_tr_generator_base::CREATE) {
193 db->writeGenerator(g.get_id(), g.get_name(), g.get_scv_tr_stream().get_id());
194 }
catch(std::runtime_error& e) {
195 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Can't create generator entry");
200 static void transactionCb(
const scv_tr_handle& t, scv_tr_handle::callback_reason reason,
void* data) {
201 if(!db || !t.get_scv_tr_stream().get_scv_tr_db() || !t.get_scv_tr_stream().get_scv_tr_db()->get_recording())
203 uint64_t
id = t.get_id();
205 case scv_tr_handle::BEGIN: {
206 db->startTransaction(
id, t.get_scv_tr_generator_base().get_id(), t.get_scv_tr_generator_base().get_scv_tr_stream().get_id(),
207 t.get_begin_sc_time() / sc_core::sc_time(1, sc_core::SC_PS));
209 auto my_exts_p = t.get_begin_exts_p();
210 if(my_exts_p ==
nullptr)
211 my_exts_p = t.get_scv_tr_generator_base().get_begin_exts_p();
213 auto tmp_str = t.get_scv_tr_generator_base().get_begin_attribute_name()
214 ? t.get_scv_tr_generator_base().get_begin_attribute_name()
216 recordAttributes(
id, event_type::BEGIN, tmp_str, my_exts_p);
219 case scv_tr_handle::END: {
220 auto my_exts_p = t.get_end_exts_p();
221 if(my_exts_p ==
nullptr)
222 my_exts_p = t.get_scv_tr_generator_base().get_end_exts_p();
225 t.get_scv_tr_generator_base().get_end_attribute_name() ? t.get_scv_tr_generator_base().get_end_attribute_name() :
"";
226 recordAttributes(
id, event_type::END, tmp_str, my_exts_p);
228 db->endTransaction(
id, t.get_end_sc_time() / sc_core::sc_time(1, sc_core::SC_PS));
234 static void attributeCb(
const scv_tr_handle& t,
const char* name,
const scv_extensions_if* ext,
void* data) {
235 if(!db || !t.get_scv_tr_stream().get_scv_tr_db() || !t.get_scv_tr_stream().get_scv_tr_db()->get_recording())
237 recordAttributes(t.get_id(), event_type::RECORD, name ==
nullptr ?
"" : name, ext);
240 static void relationCb(
const scv_tr_handle& tr_1,
const scv_tr_handle& tr_2,
void* data, scv_tr_relation_handle_t relation_handle) {
241 auto& stream1 = tr_1.get_scv_tr_stream();
242 auto txdb = stream1.get_scv_tr_db();
243 if(!db || !txdb || !txdb->get_recording())
246 auto& stream2 = tr_2.get_scv_tr_stream();
247 db->writeRelation(txdb->get_relation_name(relation_handle), stream1.get_id(), tr_1.get_id(), stream2.get_id(), tr_2.get_id());
248 }
catch(std::runtime_error& e) {
249 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Can't create transaction relation");
253 template <
bool COMPRESSED> ftr_writer<COMPRESSED>* tx_db<COMPRESSED>::db{
nullptr};
256 void scv_tr_ftr_init(
bool compressed) {
258 scv_tr_db::register_class_cb(tx_db<true>::dbCb);
259 scv_tr_stream::register_class_cb(tx_db<true>::streamCb);
260 scv_tr_generator_base::register_class_cb(tx_db<true>::generatorCb);
261 scv_tr_handle::register_class_cb(tx_db<true>::transactionCb);
262 scv_tr_handle::register_record_attribute_cb(tx_db<true>::attributeCb);
263 scv_tr_handle::register_relation_cb(tx_db<true>::relationCb);
266 scv_tr_db::register_class_cb(tx_db<false>::dbCb);
267 scv_tr_stream::register_class_cb(tx_db<false>::streamCb);
268 scv_tr_generator_base::register_class_cb(tx_db<false>::generatorCb);
269 scv_tr_handle::register_class_cb(tx_db<false>::transactionCb);
270 scv_tr_handle::register_record_attribute_cb(tx_db<false>::attributeCb);
271 scv_tr_handle::register_relation_cb(tx_db<false>::relationCb);
log
enum defining the log levels
SystemC Verification Library (SCV) Transaction Recording.