From a776085e9e601488f1a87a1885804af8025ff1b0 Mon Sep 17 00:00:00 2001 From: andreyess Date: Tue, 1 Dec 2020 10:59:37 +0300 Subject: [PATCH 1/6] Added operation logging to JSON Now when you want to log operations to JSON file - you need to add flag -j or --json-dump and logs will be saved to your current directory to file "logs.json". --- simulator/func_sim/operation.h | 6 +++++ simulator/infra/log.cpp | 4 ++++ simulator/infra/log.h | 4 ++++ simulator/infra/ports/module.cpp | 7 ++++++ simulator/infra/ports/module.h | 2 ++ simulator/modules/core/perf_sim.cpp | 28 +++++++++++++++++++++++ simulator/modules/core/perf_sim.h | 4 ++++ simulator/modules/decode/decode.cpp | 4 ++++ simulator/modules/execute/execute.cpp | 8 +++++++ simulator/modules/fetch/fetch.cpp | 8 +++++++ simulator/modules/fetch/fetch.h | 3 +++ simulator/modules/mem/mem.cpp | 4 ++++ simulator/modules/writeback/writeback.cpp | 17 ++++++++++---- 13 files changed, 95 insertions(+), 4 deletions(-) diff --git a/simulator/func_sim/operation.h b/simulator/func_sim/operation.h index 5c19dde52..8ead39504 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..b0e279f61 100644 --- a/simulator/infra/log.cpp +++ b/simulator/infra/log.cpp @@ -22,3 +22,7 @@ OStreamWrapper::~OStreamWrapper() { ostream.rdbuf( buffer); } + + +std::ofstream* visualizer_logger = new std::ofstream(".\\logs.json", std::ofstream::out); +std::ofstream& Log::jsonout() { return *visualizer_logger; } \ No newline at end of file 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 69ced6c63..3288ad100 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 6af639edb..befa6ecd9 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 @@ -32,6 +34,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 @@ -59,6 +63,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); @@ -68,6 +75,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; @@ -99,6 +109,24 @@ 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"; +} + template void PerfSim::dump_statistics() const { diff --git a/simulator/modules/core/perf_sim.h b/simulator/modules/core/perf_sim.h index 375dd41fe..7096db83e 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 8fe55e8a5..e930bafcd 100644 --- a/simulator/modules/decode/decode.cpp +++ b/simulator/modules/decode/decode.cpp @@ -151,6 +151,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 87037448b..2ef3b3b64 100644 --- a/simulator/modules/execute/execute.cpp +++ b/simulator/modules/execute/execute.cpp @@ -77,6 +77,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 }"; } } @@ -133,6 +137,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 6c13e05fc..71248b4a2 100644 --- a/simulator/modules/fetch/fetch.cpp +++ b/simulator/modules/fetch/fetch.cpp @@ -180,6 +180,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); @@ -188,6 +191,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.generate_disasm() << "\" }" << + ",\n\t{ \"type\": \"Event\", \"id\": " << instr.get_instruction_id() << ", \"cycle\": " << cycle << ", \"stage\": 0 }"; } #include diff --git a/simulator/modules/fetch/fetch.h b/simulator/modules/fetch/fetch.h index f01d8606f..20be0c90d 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 = nullptr; diff --git a/simulator/modules/mem/mem.cpp b/simulator/modules/mem/mem.cpp index 581643feb..2d4875117 100644 --- a/simulator/modules/mem/mem.cpp +++ b/simulator/modules/mem/mem.cpp @@ -50,6 +50,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 cdce32f83..4ac382a33 100644 --- a/simulator/modules/writeback/writeback.cpp +++ b/simulator/modules/writeback/writeback.cpp @@ -73,8 +73,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 @@ -100,8 +105,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 From 1cbb6df7518f5bed5c9d14fc3b3611f820b3cd84 Mon Sep 17 00:00:00 2001 From: "Pavel I. Kryukov" Date: Fri, 5 Feb 2021 22:48:29 +0300 Subject: [PATCH 2/6] Add Andrei Karpyza to LICENSE --- license.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/license.md b/license.md index ab2b975cb..60b2ee3f8 100644 --- a/license.md +++ b/license.md @@ -1,6 +1,6 @@ # The MIT License (MIT) -Copyright © 2012–2021 MIPT-ILab, Alexander Titov, Pavel Kryukov, Igor Smirnov, Igor Burovenko, Kamil Garifullin, Oleg Ladin, Kirill Korolev, Victor Prutyanov, Ivan Korostelev, Alex Seppar, George Korepanov, Alexey Steksov, Kirill Nedostoev, Alexander Misevich, Denis Los, Alexander Timofeev, Konstantin Soshin, Yan Logovskiy, Andrei Sultan, Vyacheslav Kompan, Yauheni Sharamed, Andrey Agrachev, Vsevolod Pukhov, Arsen Davtyan, Egor Bova, Rustem Yunusov, Maxim Davydov, Eric Konks, Igor Bulatov, Kirill Chemrov, Alexandr Vinogradov, Airat Nazmiev, Daniel Kofanov, Nikolay Zernov, Vladimir Prokhorov, Ilya Burtakov, Nikita Gorbachev, Yaroslav Okatev, Roman Zlobin, Yuly Tarasov, Vladimir Graudt, Alexey Shcherbakov, Anton Okley, Egor Titov, Eugene Naydanov, Mihail Fedorov, Vasilii Zaitsev, Ravil Zakiryanov, Ivan Burtakov, and Johannes Pohl. +Copyright © 2012–2021 MIPT-ILab, Alexander Titov, Pavel Kryukov, Igor Smirnov, Igor Burovenko, Kamil Garifullin, Oleg Ladin, Kirill Korolev, Victor Prutyanov, Ivan Korostelev, Alex Seppar, George Korepanov, Alexey Steksov, Kirill Nedostoev, Alexander Misevich, Denis Los, Alexander Timofeev, Konstantin Soshin, Yan Logovskiy, Andrei Sultan, Vyacheslav Kompan, Yauheni Sharamed, Andrey Agrachev, Vsevolod Pukhov, Arsen Davtyan, Egor Bova, Rustem Yunusov, Maxim Davydov, Eric Konks, Igor Bulatov, Kirill Chemrov, Alexandr Vinogradov, Airat Nazmiev, Daniel Kofanov, Nikolay Zernov, Vladimir Prokhorov, Ilya Burtakov, Nikita Gorbachev, Yaroslav Okatev, Roman Zlobin, Yuly Tarasov, Vladimir Graudt, Alexey Shcherbakov, Anton Okley, Egor Titov, Eugene Naydanov, Mihail Fedorov, Vasilii Zaitsev, Ravil Zakiryanov, Ivan Burtakov, Andrei Karpyza, and Johannes Pohl. ---- From f4f4d1e12448f9036b77e024f760c5149fb2ef96 Mon Sep 17 00:00:00 2001 From: "Pavel I. Kryukov" Date: Fri, 5 Feb 2021 22:53:47 +0300 Subject: [PATCH 3/6] Use get_disasm instead of generate_disasm --- simulator/modules/fetch/fetch.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simulator/modules/fetch/fetch.cpp b/simulator/modules/fetch/fetch.cpp index 71248b4a2..419607479 100644 --- a/simulator/modules/fetch/fetch.cpp +++ b/simulator/modules/fetch/fetch.cpp @@ -194,7 +194,7 @@ void Fetch::clock( Cycle cycle) /* JSON dump of Fetch-stage of executing operation */ if (jsonout_enabled) - (jsonout()) << ",\n\t{ \"type\": \"Record\", \"id\": " << instr.get_instruction_id() << ", \"disassembly\": \"" << instr.generate_disasm() << "\" }" << + (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 }"; } From d3f2be01a24cf04010f1cd34023f50594fe8feb7 Mon Sep 17 00:00:00 2001 From: "Pavel I. Kryukov" Date: Sun, 28 Feb 2021 01:04:08 +0300 Subject: [PATCH 4/6] Close JSON output file on exit --- simulator/modules/core/perf_sim.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/simulator/modules/core/perf_sim.cpp b/simulator/modules/core/perf_sim.cpp index befa6ecd9..6ee8322d9 100644 --- a/simulator/modules/core/perf_sim.cpp +++ b/simulator/modules/core/perf_sim.cpp @@ -123,8 +123,10 @@ void PerfSim::start_dump_json() { template void PerfSim::stop_dump_json() { - if (jsonout_enabled) + if (jsonout_enabled) { (jsonout()) << "\n]\n"; + jsonout().close(); + } } template From 412bcc223f2212381cd78236c5a1304a512fda4b Mon Sep 17 00:00:00 2001 From: "Pavel I. Kryukov" Date: Sun, 28 Feb 2021 01:05:10 +0300 Subject: [PATCH 5/6] Use linux-compatible file name for JSON output --- simulator/infra/log.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/simulator/infra/log.cpp b/simulator/infra/log.cpp index b0e279f61..c368bc846 100644 --- a/simulator/infra/log.cpp +++ b/simulator/infra/log.cpp @@ -24,5 +24,6 @@ OStreamWrapper::~OStreamWrapper() } -std::ofstream* visualizer_logger = new std::ofstream(".\\logs.json", std::ofstream::out); -std::ofstream& Log::jsonout() { return *visualizer_logger; } \ No newline at end of file +std::ofstream* visualizer_logger = new std::ofstream("logs.json", std::ofstream::out); +std::ofstream& Log::jsonout() { return *visualizer_logger; } + From 44b91c832819ff481d208e790af80711fdb183c9 Mon Sep 17 00:00:00 2001 From: "Pavel I. Kryukov" Date: Sun, 28 Feb 2021 01:09:00 +0300 Subject: [PATCH 6/6] Match PipelineVis input format --- simulator/modules/core/perf_sim.cpp | 4 ++-- simulator/modules/writeback/writeback.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/simulator/modules/core/perf_sim.cpp b/simulator/modules/core/perf_sim.cpp index 6ee8322d9..e2540856b 100644 --- a/simulator/modules/core/perf_sim.cpp +++ b/simulator/modules/core/perf_sim.cpp @@ -113,7 +113,7 @@ auto get_rate( int total, float64 piece) template void PerfSim::start_dump_json() { if (jsonout_enabled) - (jsonout()) << "[\n" << + (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" << @@ -124,7 +124,7 @@ void PerfSim::start_dump_json() { template void PerfSim::stop_dump_json() { if (jsonout_enabled) { - (jsonout()) << "\n]\n"; + (jsonout()) << "\n]]\n"; jsonout().close(); } } diff --git a/simulator/modules/writeback/writeback.cpp b/simulator/modules/writeback/writeback.cpp index 4ac382a33..9926fbb32 100644 --- a/simulator/modules/writeback/writeback.cpp +++ b/simulator/modules/writeback/writeback.cpp @@ -108,7 +108,7 @@ void Writeback::writeback_bubble( Cycle cycle) 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"; + (jsonout()) << "\n]]\n"; throw Deadlock(""); } }