17 #include <boost/filesystem.hpp>
27 #include <unordered_map>
28 #include <unordered_set>
43 enum EventType { BEGIN, RECORD, END };
44 using data_type = scv_extensions_if::data_type;
49 boost::filesystem::path dir;
52 std::array<char, 1024> buffer;
53 Base(
const std::string& name)
56 , is_open(out.is_open()) {
67 struct Database : Base {
69 Database(
const std::string& name)
72 inline uint64_t getIdOf(
const std::string& str) {
return idx; }
74 inline void writeStream(uint64_t
id, std::string
const& name, std::string
const& kind) {
76 auto len = sprintf(buffer.data(),
"scv_tr_stream (ID %lu, name \"%s\", kind \"%s\")\n",
id, name.c_str(), kind.c_str());
77 out.write(buffer.data(), len);
81 inline void writeGenerator(uint64_t
id, std::string
const& name, uint64_t stream) {
83 auto len = sprintf(buffer.data(),
"scv_tr_generator (ID %lu, name \"%s\", scv_tr_stream %lu,\n",
id, name.c_str(), stream);
84 out.write(buffer.data(), len);
88 inline uint64_t writeTransaction(uint64_t
id, uint64_t generator) {
92 inline void writeTxTimepoint(uint64_t
id,
int type, uint64_t time, uint64_t file_offset) {
96 inline void writeAttribute(uint64_t
id, EventType event,
const string& name, data_type type,
const string& value) {
100 inline void writeAttribute(uint64_t
id, EventType event,
const string& name, data_type type, uint64_t value) {
104 inline void writeAttribute(uint64_t
id, EventType event,
const string& name, data_type type,
double value) {
109 inline void writeRelation(
const std::string& name, uint64_t sink_id, uint64_t src_id) {
115 std::unordered_map<uint64_t, uint64_t> id2offset;
117 void dbCb(
const scv_tr_db& _scv_tr_db, scv_tr_db::callback_reason reason,
void* data) {
119 static string fName(
"DEFAULT_scv_tr_sqlite");
121 case scv_tr_db::CREATE:
122 if((_scv_tr_db.get_name() !=
nullptr) && (strlen(_scv_tr_db.get_name()) != 0))
123 fName = _scv_tr_db.get_name();
125 db =
new Database(fName);
127 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Can't open recording file");
130 case scv_tr_db::DELETE:
134 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Can't close recording file");
138 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Unknown reason in scv_tr_db callback");
142 void streamCb(
const scv_tr_stream& s, scv_tr_stream::callback_reason reason,
void* data) {
143 if(reason == scv_tr_stream::CREATE) {
145 db->writeStream(s.get_id(), s.get_name(), s.get_stream_kind());
146 }
catch(std::runtime_error& e) {
147 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Can't create stream");
152 inline void recordAttribute(uint64_t
id, EventType event,
const string& name, data_type type,
const string& value) {
154 db->writeAttribute(
id, event, name, type, value);
155 }
catch(std::runtime_error& e) {
156 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Can't create attribute entry");
160 inline void recordAttribute(uint64_t
id, EventType event,
const string& name, data_type type,
long long value) {
162 db->writeAttribute(
id, event, name, type,
static_cast<uint64_t
>(value));
163 }
catch(std::runtime_error& e) {
164 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Can't create attribute entry");
168 inline void recordAttribute(uint64_t
id, EventType event,
const string& name, data_type type,
double value) {
170 db->writeAttribute(
id, event, name, type, value);
171 }
catch(std::runtime_error& e) {
172 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Can't create attribute entry");
176 inline std::string get_name(
const char* prefix,
const scv_extensions_if* my_exts_p) {
177 static thread_local std::unordered_map<const scv_extensions_if*, std::string> name_lut;
178 auto it = name_lut.find(my_exts_p);
179 if(it != name_lut.end())
182 if(!prefix || strlen(prefix) == 0) {
183 name = my_exts_p->get_name();
185 if((my_exts_p->get_name() ==
nullptr) || (strlen(my_exts_p->get_name()) == 0)) {
188 name = std::string(prefix) +
"." + my_exts_p->get_name();
191 name_lut[my_exts_p] = (name ==
"") ?
"<unnamed>" : name;
192 return (name ==
"") ?
"<unnamed>" : name;
196 void recordAttributes(uint64_t
id, EventType eventType,
char const* prefix,
const scv_extensions_if* my_exts_p) {
197 if(my_exts_p ==
nullptr)
199 auto name = get_name(prefix, my_exts_p);
200 switch(my_exts_p->get_type()) {
201 case scv_extensions_if::RECORD: {
202 int num_fields = my_exts_p->get_num_fields();
204 for(
int field_counter = 0; field_counter < num_fields; field_counter++) {
205 const scv_extensions_if* field_data_p = my_exts_p->get_field(field_counter);
206 recordAttributes(
id, eventType, prefix, field_data_p);
210 case scv_extensions_if::ENUMERATION:
211 recordAttribute(
id, eventType, name, scv_extensions_if::ENUMERATION, my_exts_p->get_enum_string((
int)(my_exts_p->get_integer())));
213 case scv_extensions_if::BOOLEAN:
214 recordAttribute(
id, eventType, name, scv_extensions_if::BOOLEAN, my_exts_p->get_bool() ?
"TRUE" :
"FALSE");
216 case scv_extensions_if::INTEGER:
217 case scv_extensions_if::FIXED_POINT_INTEGER:
218 recordAttribute(
id, eventType, name, scv_extensions_if::INTEGER, my_exts_p->get_integer());
220 case scv_extensions_if::UNSIGNED:
221 recordAttribute(
id, eventType, name, scv_extensions_if::UNSIGNED, my_exts_p->get_integer());
223 case scv_extensions_if::POINTER:
224 recordAttribute(
id, eventType, name, scv_extensions_if::POINTER, (
long long)my_exts_p->get_pointer());
226 case scv_extensions_if::STRING:
227 recordAttribute(
id, eventType, name, scv_extensions_if::STRING, my_exts_p->get_string());
229 case scv_extensions_if::FLOATING_POINT_NUMBER:
230 recordAttribute(
id, eventType, name, scv_extensions_if::FLOATING_POINT_NUMBER, my_exts_p->get_double());
232 case scv_extensions_if::BIT_VECTOR: {
233 sc_bv_base tmp_bv(my_exts_p->get_bitwidth());
234 my_exts_p->get_value(tmp_bv);
235 recordAttribute(
id, eventType, name, scv_extensions_if::BIT_VECTOR, tmp_bv.to_string());
237 case scv_extensions_if::LOGIC_VECTOR: {
238 sc_lv_base tmp_lv(my_exts_p->get_bitwidth());
239 my_exts_p->get_value(tmp_lv);
240 recordAttribute(
id, eventType, name, scv_extensions_if::LOGIC_VECTOR, tmp_lv.to_string());
242 case scv_extensions_if::ARRAY:
243 for(
int array_elt_index = 0; array_elt_index < my_exts_p->get_array_size(); array_elt_index++) {
244 const scv_extensions_if* field_data_p = my_exts_p->get_array_elt(array_elt_index);
245 recordAttributes(
id, eventType, prefix, field_data_p);
249 std::array<char, 100> tmpString;
250 sprintf(tmpString.data(),
"Unsupported attribute type = %d", my_exts_p->get_type());
251 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL, tmpString.data());
256 void generatorCb(
const scv_tr_generator_base& g, scv_tr_generator_base::callback_reason reason,
void* data) {
257 if(reason == scv_tr_generator_base::CREATE && db) {
259 db->writeGenerator(g.get_id(), g.get_name(), g.get_scv_tr_stream().get_id());
260 }
catch(std::runtime_error& e) {
261 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Can't create generator entry");
266 void transactionCb(
const scv_tr_handle& t, scv_tr_handle::callback_reason reason,
void* data) {
269 if(t.get_scv_tr_stream().get_scv_tr_db() ==
nullptr)
271 if(t.get_scv_tr_stream().get_scv_tr_db()->get_recording() ==
false)
274 uint64_t
id = t.get_id();
275 vector<uint64_t>::size_type concurrencyIdx;
276 const scv_extensions_if* my_exts_p;
278 case scv_tr_handle::BEGIN: {
279 my_exts_p = t.get_begin_exts_p();
280 if(my_exts_p ==
nullptr)
281 my_exts_p = t.get_scv_tr_generator_base().get_begin_exts_p();
284 t.get_scv_tr_generator_base().get_begin_attribute_name() ? t.get_scv_tr_generator_base().get_begin_attribute_name() :
"";
285 recordAttributes(
id, BEGIN, tmp_str, my_exts_p);
288 case scv_tr_handle::END: {
289 my_exts_p = t.get_end_exts_p();
290 if(my_exts_p ==
nullptr)
291 my_exts_p = t.get_scv_tr_generator_base().get_end_exts_p();
294 t.get_scv_tr_generator_base().get_end_attribute_name() ? t.get_scv_tr_generator_base().get_end_attribute_name() :
"";
295 recordAttributes(t.get_id(), END, tmp_str, my_exts_p);
302 void attributeCb(
const scv_tr_handle& t,
const char* name,
const scv_extensions_if* ext,
void* data) {
305 if(t.get_scv_tr_stream().get_scv_tr_db() ==
nullptr)
307 if(t.get_scv_tr_stream().get_scv_tr_db()->get_recording() ==
false)
309 recordAttributes(t.get_id(), RECORD, name ==
nullptr ?
"" : name, ext);
312 void relationCb(
const scv_tr_handle& tr_1,
const scv_tr_handle& tr_2,
void* data, scv_tr_relation_handle_t relation_handle) {
315 if(tr_1.get_scv_tr_stream().get_scv_tr_db() ==
nullptr)
317 if(tr_1.get_scv_tr_stream().get_scv_tr_db()->get_recording() ==
false)
320 db->writeRelation(tr_1.get_scv_tr_stream().get_scv_tr_db()->get_relation_name(relation_handle), tr_1.get_id(), tr_2.get_id());
321 }
catch(std::runtime_error& e) {
322 _scv_message::message(_scv_message::TRANSACTION_RECORDING_INTERNAL,
"Can't create transaction relation");
328 scv_tr_db::register_class_cb(dbCb);
329 scv_tr_stream::register_class_cb(streamCb);
330 scv_tr_generator_base::register_class_cb(generatorCb);
331 scv_tr_handle::register_class_cb(transactionCb);
332 scv_tr_handle::register_record_attribute_cb(attributeCb);
333 scv_tr_handle::register_relation_cb(relationCb);
SystemC Verification Library (SCV) Transaction Recording.
void scv_tr_mtc_init()
initializes the infrastructure to use a compressed text based transaction recording database with a m...