diff --git a/simulator/func_sim/operation.h b/simulator/func_sim/operation.h index c131863fb..129663bdb 100644 --- a/simulator/func_sim/operation.h +++ b/simulator/func_sim/operation.h @@ -125,6 +125,10 @@ class Operation void set_sequence_id( uint64 id) { sequence_id = id; } auto get_sequence_id() const { return sequence_id; } + // instruction_id initialization and return - functions + void set_instruction_id(uint64 id) { instruction_id = id; } + auto get_instruction_id() const { return instruction_id; } + auto get_delayed_slots() const { return delayed_slots; } Addr get_decoded_target() const { return target; } auto get_new_PC() const { return new_PC; } @@ -151,6 +155,8 @@ class Operation private: OperationType operation = OUT_UNKNOWN; uint64 sequence_id = NO_VAL64; + // instruction_id initialization + uint64 instruction_id = NO_VAL64; }; template diff --git a/simulator/infra/log.cpp b/simulator/infra/log.cpp index 759e2a559..c368bc846 100644 --- a/simulator/infra/log.cpp +++ b/simulator/infra/log.cpp @@ -22,3 +22,8 @@ OStreamWrapper::~OStreamWrapper() { ostream.rdbuf( buffer); } + + +std::ofstream* visualizer_logger = new std::ofstream("logs.json", std::ofstream::out); +std::ofstream& Log::jsonout() { return *visualizer_logger; } + diff --git a/simulator/infra/log.h b/simulator/infra/log.h index bdf6d2dca..9244a8fde 100644 --- a/simulator/infra/log.h +++ b/simulator/infra/log.h @@ -9,6 +9,7 @@ #define LOG_H #include +#include "fstream" class LogOstream { @@ -49,6 +50,9 @@ class Log mutable LogOstream sout; mutable LogOstream serr; + std::ofstream& jsonout(); + bool jsonout_enabled = false; + Log(); // Rule of five diff --git a/simulator/infra/ports/module.cpp b/simulator/infra/ports/module.cpp index 3b51136ac..f13daa8df 100644 --- a/simulator/infra/ports/module.cpp +++ b/simulator/infra/ports/module.cpp @@ -48,6 +48,13 @@ void Module::enable_logging_impl( const std::unordered_set& names) c->enable_logging_impl( names); } +// enable logging function implementation +void Module::enable_json_logging(bool key) { + jsonout_enabled = key; + for (const auto& c : children) + c->enable_json_logging(key); +} + pt::ptree Module::write_ports_dumping() const { pt::ptree result; diff --git a/simulator/infra/ports/module.h b/simulator/infra/ports/module.h index 71e5cb866..13eb2ef52 100644 --- a/simulator/infra/ports/module.h +++ b/simulator/infra/ports/module.h @@ -42,6 +42,8 @@ class Module : public Log void enable_logging_impl( const std::unordered_set& names); boost::property_tree::ptree topology_dumping_impl() const; + // enable-logging function initialization + void enable_json_logging(bool key); private: // NOLINTNEXTLINE(misc-no-recursion) Recursive, but must be finite virtual std::shared_ptr get_portmap() const { return parent->get_portmap(); } diff --git a/simulator/modules/core/perf_sim.cpp b/simulator/modules/core/perf_sim.cpp index 30a862e24..0cd71f68b 100644 --- a/simulator/modules/core/perf_sim.cpp +++ b/simulator/modules/core/perf_sim.cpp @@ -13,6 +13,8 @@ namespace config { static const AliasedValue units_to_log = { "l", "logs", "nothing", "print logs for modules"}; static const Switch topology_dump = { "tdump", "module topology dump into topology.json" }; + // command line flag argument for enable/disable json logging + static const AliasedSwitch json_dump = { "j", "json-dump", "json logs in .\\logs.json" }; } // namespace config template @@ -30,6 +32,8 @@ PerfSim::PerfSim( std::endian endian, std::string_view isa) init_portmap(); enable_logging( config::units_to_log); topology_dumping( config::topology_dump, "topology.json"); + // json logger configuration + enable_json_logging(config::json_dump); } template @@ -57,6 +61,9 @@ Addr PerfSim::get_pc() const template Trap PerfSim::run( uint64 instrs_to_run) { + /* start json dump strings */ + start_dump_json(); + current_trap = Trap( Trap::NO_TRAP); writeback.set_instrs_to_run( instrs_to_run); @@ -66,6 +73,9 @@ Trap PerfSim::run( uint64 instrs_to_run) while (current_trap == Trap::NO_TRAP) clock(); + /* end strings */ + stop_dump_json(); + dump_statistics(); return current_trap; @@ -97,6 +107,26 @@ auto get_rate( int total, float64 piece) return total != 0 ? ( piece / total * 100) : 0; } +/* standard lines loggers implementation */ +template +void PerfSim::start_dump_json() { + if (jsonout_enabled) + (jsonout()) << "[[\n" << + "\t{ \"type\": \"Stage\", \"id\": 0, \"description\": \"Fetch\" },\n" << + "\t{ \"type\": \"Stage\", \"id\": 1, \"description\": \"Decode\" },\n" << + "\t{ \"type\": \"Stage\", \"id\": 2, \"description\": \"Execute\" },\n" << + "\t{ \"type\": \"Stage\", \"id\": 3, \"description\": \"Memory\" },\n" << + "\t{ \"type\": \"Stage\", \"id\": 4, \"description\": \"Writeback\" }"; +} + +template +void PerfSim::stop_dump_json() { + if (jsonout_enabled) { + (jsonout()) << "\n]]\n"; + jsonout().close(); + } +} + template void PerfSim::dump_statistics() const { diff --git a/simulator/modules/core/perf_sim.h b/simulator/modules/core/perf_sim.h index eda02b0d1..f97b23f94 100644 --- a/simulator/modules/core/perf_sim.h +++ b/simulator/modules/core/perf_sim.h @@ -83,6 +83,10 @@ class PerfSim : public CycleAccurateSimulator uint64 read_register( Register index) const { return narrow_cast( rf.read( index)); } void write_register( Register index, uint64 value) { rf.write( index, narrow_cast( value)); } + + /* default lines initialization */ + void start_dump_json(); + void stop_dump_json(); }; #endif diff --git a/simulator/modules/decode/decode.cpp b/simulator/modules/decode/decode.cpp index b83120c0c..85cdc6a8b 100644 --- a/simulator/modules/decode/decode.cpp +++ b/simulator/modules/decode/decode.cpp @@ -134,6 +134,10 @@ void Decode::clock( Cycle cycle) sout << instr << std::endl; wp_datapath->write( std::move( instr), cycle); + + /* JSON dump of Decode-stage of executing operation */ + if (jsonout_enabled) + (jsonout()) << ",\n\t{ \"type\": \"Event\", \"id\": " << instr.get_instruction_id() << ", \"cycle\": " << cycle << ", \"stage\": 1 }"; } diff --git a/simulator/modules/execute/execute.cpp b/simulator/modules/execute/execute.cpp index 9b18ef074..6faa8c763 100644 --- a/simulator/modules/execute/execute.cpp +++ b/simulator/modules/execute/execute.cpp @@ -63,6 +63,10 @@ void Execute::clock( Cycle cycle) { wp_long_arithmetic_bypass->write( instr.get_v_dst(), cycle); wp_writeback_datapath->write( instr, cycle); + + /* JSON dump of Execute-stage of executing operation */ + if (jsonout_enabled) + (jsonout()) << ",\n\t{ \"type\": \"Event\", \"id\": " << instr.get_instruction_id() << ", \"cycle\": " << cycle << ", \"stage\": 2 }"; } } @@ -119,6 +123,10 @@ void Execute::clock( Cycle cycle) { wp_writeback_datapath->write( std::move( instr), cycle); } + + /* JSON dump of Execute-stage of executing operation */ + if (jsonout_enabled) + (jsonout()) << ",\n\t{ \"type\": \"Event\", \"id\": " << instr.get_instruction_id() << ", \"cycle\": " << cycle << ", \"stage\": 2 }"; } } diff --git a/simulator/modules/fetch/fetch.cpp b/simulator/modules/fetch/fetch.cpp index 168316bdd..8cfff8874 100644 --- a/simulator/modules/fetch/fetch.cpp +++ b/simulator/modules/fetch/fetch.cpp @@ -173,6 +173,9 @@ void Fetch::clock( Cycle cycle) Instr instr( memory->fetch_instr( target.address), bp_info); instr.set_sequence_id( target.sequence_id); + /* instruction unique id initialization */ + instr.set_instruction_id(curr_id++); + /* set next target according to prediction */ wp_target->write( instr.get_predicted_target(), cycle); @@ -182,6 +185,11 @@ void Fetch::clock( Cycle cycle) /* sending to decode */ wp_datapath->write( std::move( instr), cycle); + /* JSON dump of Fetch-stage of executing operation */ + if (jsonout_enabled) + (jsonout()) << ",\n\t{ \"type\": \"Record\", \"id\": " << instr.get_instruction_id() << ", \"disassembly\": \"" << instr.get_disasm() << "\" }" << + ",\n\t{ \"type\": \"Event\", \"id\": " << instr.get_instruction_id() << ", \"cycle\": " << cycle << ", \"stage\": 0 }"; + if ( _prefetch_method != "no-prefetch" && !is_wrong_path) // prefetch next line if enabled and wrong path isn't used prefetch_next_line( target.address); } diff --git a/simulator/modules/fetch/fetch.h b/simulator/modules/fetch/fetch.h index f7989d8c1..9f608fc84 100644 --- a/simulator/modules/fetch/fetch.h +++ b/simulator/modules/fetch/fetch.h @@ -30,6 +30,9 @@ class Fetch : public Module std::unique_ptr> memory = nullptr; std::unique_ptr bp = nullptr; std::unique_ptr tags = nullptr; + + /* counter for instruction_id implementation */ + int curr_id = 0; /* Input signals */ ReadPort* rp_stall = make_read_port("DECODE_2_FETCH_STALL", Port::LATENCY); diff --git a/simulator/modules/mem/mem.cpp b/simulator/modules/mem/mem.cpp index f1cfefcb4..a967cadf3 100644 --- a/simulator/modules/mem/mem.cpp +++ b/simulator/modules/mem/mem.cpp @@ -44,6 +44,10 @@ void Mem::clock( Cycle cycle) /* data path */ wp_datapath->write( std::move( instr), cycle); + + /* JSON dump of Memory-stage of executing operation */ + if (jsonout_enabled) + (jsonout()) << ",\n\t{ \"type\": \"Event\", \"id\": " << instr.get_instruction_id() << ", \"cycle\": " << cycle << ", \"stage\": 3 }"; } diff --git a/simulator/modules/writeback/writeback.cpp b/simulator/modules/writeback/writeback.cpp index 5d2a631b9..076c1f65b 100644 --- a/simulator/modules/writeback/writeback.cpp +++ b/simulator/modules/writeback/writeback.cpp @@ -65,8 +65,13 @@ void Writeback::clock( Cycle cycle) if ( instrs.empty()) writeback_bubble( cycle); - else for ( auto& instr : instrs) - writeback_instruction_system( &instr, cycle); + else for (auto& instr : instrs) { + writeback_instruction_system(&instr, cycle); + + /* JSON dump of Writeback-stage of executing operation */ + if (jsonout_enabled) + (jsonout()) << ",\n\t{ \"type\": \"Event\", \"id\": " << instr.get_instruction_id() << ", \"cycle\": " << cycle << ", \"stage\": 4 }"; + } } template @@ -92,8 +97,12 @@ template void Writeback::writeback_bubble( Cycle cycle) { sout << "bubble\n"; - if ( cycle >= last_writeback_cycle + 100_lt) - throw Deadlock( ""); + if (cycle >= last_writeback_cycle + 100_lt) { + /* If will be throwed Deadlock - we need to close brackets in the logs-file */ + if (jsonout_enabled) + (jsonout()) << "\n]]\n"; + throw Deadlock(""); + } } template