From 9a3b0dccb3dcb958b6a5c0cd72e8684887b4c4bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karel=20Ko=C4=8D=C3=AD?= Date: Thu, 11 Jan 2018 22:44:27 +0100 Subject: Allow instruction trace from any stage In reality this internally allows us to see stages even it we are not using pipelining but that is hidden from outside simply to not confuse user. --- qtmips_cli/main.cpp | 16 +++++++++++++++- qtmips_cli/tracer.cpp | 38 +++++++++++++++++++++++++++++++++++--- qtmips_cli/tracer.h | 14 +++++++++++--- qtmips_machine/core.cpp | 28 ++++++++++++++++------------ qtmips_machine/core.h | 18 ++++++++++++------ qtmips_machine/instruction.cpp | 2 +- qtmips_machine/instruction.h | 2 +- 7 files changed, 91 insertions(+), 27 deletions(-) diff --git a/qtmips_cli/main.cpp b/qtmips_cli/main.cpp index 57187ce..fedf14d 100644 --- a/qtmips_cli/main.cpp +++ b/qtmips_cli/main.cpp @@ -18,7 +18,11 @@ void create_parser(QCommandLineParser &p) { p.addOptions({ {"pipelined", "Configure CPU to use five stage pipeline."}, {"no-delay-slot", "Disable jump delay slot."}, - {{"trace-fetch", "tr-fetch"}, "Trace fetched instruction."}, + {{"trace-fetch", "tr-fetch"}, "Trace fetched instruction (for both pipelined and not core)."}, + {{"trace-decode", "tr-decode"}, "Trace instruction in decode stage. (only for pipelined core)"}, + {{"trace-execute", "tr-execute"}, "Trace instruction in execute stage. (only for pipelined core)"}, + {{"trace-memory", "tr-memory"}, "Trace instruction in memory stage. (only for pipelined core)"}, + {{"trace-writeback", "tr-writeback"}, "Trace instruction in write back stage. (only for pipelined core)"}, {{"trace-pc", "tr-pc"}, "Print program counter register changes."}, {{"trace-gp", "tr-gp"}, "Print general purpose register changes. You can use * for all registers.", "REG"}, {{"trace-lo", "tr-lo"}, "Print LO register changes."}, @@ -44,6 +48,16 @@ void configure_machine(QCommandLineParser &p, MachineConfig &cc) { void configure_tracer(QCommandLineParser &p, Tracer &tr) { if (p.isSet("trace-fetch")) tr.fetch(); + if (p.isSet("pipelined")) { // Following are added only if we have stages + if (p.isSet("trace-decode")) + tr.decode(); + if (p.isSet("trace-execute")) + tr.execute(); + if (p.isSet("trace-memory")) + tr.memory(); + if (p.isSet("trace-writeback")) + tr.writeback(); + } if (p.isSet("trace-pc")) tr.reg_pc(); diff --git a/qtmips_cli/tracer.cpp b/qtmips_cli/tracer.cpp index ca66e09..4438fd8 100644 --- a/qtmips_cli/tracer.cpp +++ b/qtmips_cli/tracer.cpp @@ -25,7 +25,23 @@ Tracer::Tracer(QtMipsMachine *machine) { } while(false) void Tracer::fetch() { - CON(con_fetch, machine->core(), instruction_fetched(machine::Instruction&), instruction_fetch(machine::Instruction&)); + CON(con_fetch, machine->core(), instruction_fetched(const machine::Instruction&), instruction_fetch(const machine::Instruction&)); +} + +void Tracer::decode() { + CON(con_fetch, machine->core(), instruction_decoded(const machine::Instruction&), instruction_decode(const machine::Instruction&)); +} + +void Tracer::execute() { + CON(con_fetch, machine->core(), instruction_executed(const machine::Instruction&), instruction_execute(const machine::Instruction&)); +} + +void Tracer::memory() { + CON(con_fetch, machine->core(), instruction_memory(const machine::Instruction&), instruction_memory(const machine::Instruction&)); +} + +void Tracer::writeback() { + CON(con_fetch, machine->core(), instruction_writeback(const machine::Instruction&), instruction_writeback(const machine::Instruction&)); } void Tracer::reg_pc() { @@ -48,8 +64,24 @@ void Tracer::reg_hi() { r_hi = true; } -void Tracer::instruction_fetch(Instruction &inst) { - cout << inst.to_str().toStdString() << endl; +void Tracer::instruction_fetch(const Instruction &inst) { + cout << "Fetch: " << inst.to_str().toStdString() << endl; +} + +void Tracer::instruction_decode(const machine::Instruction &inst) { + cout << "Decode: " << inst.to_str().toStdString() << endl; +} + +void Tracer::instruction_execute(const machine::Instruction &inst) { + cout << "Execute: " << inst.to_str().toStdString() << endl; +} + +void Tracer::instruction_memory(const machine::Instruction &inst) { + cout << "Memory: " << inst.to_str().toStdString() << endl; +} + +void Tracer::instruction_writeback(const machine::Instruction &inst) { + cout << "Writeback: " << inst.to_str().toStdString() << endl; } void Tracer::regs_pc_update(std::uint32_t val) { diff --git a/qtmips_cli/tracer.h b/qtmips_cli/tracer.h index 913687c..53fd3e7 100644 --- a/qtmips_cli/tracer.h +++ b/qtmips_cli/tracer.h @@ -9,8 +9,12 @@ class Tracer : public QObject { public: Tracer(machine::QtMipsMachine *machine); - // Trace fetched instruction + // Trace instructions in different stages/sections void fetch(); + void decode(); + void execute(); + void memory(); + void writeback(); // Trace registers void reg_pc(); void reg_gp(std::uint8_t i); @@ -18,8 +22,12 @@ public: void reg_hi(); private slots: - void instruction_fetch(machine::Instruction &inst); - // TODO fetch + void instruction_fetch(const machine::Instruction &inst); + void instruction_decode(const machine::Instruction &inst); + void instruction_execute(const machine::Instruction &inst); + void instruction_memory(const machine::Instruction &inst); + void instruction_writeback(const machine::Instruction &inst); + void regs_pc_update(std::uint32_t val); void regs_gp_update(std::uint8_t i, std::uint32_t val); void regs_hi_lo_update(bool hi, std::uint32_t val); diff --git a/qtmips_machine/core.cpp b/qtmips_machine/core.cpp index faebd87..805d9be 100644 --- a/qtmips_machine/core.cpp +++ b/qtmips_machine/core.cpp @@ -103,8 +103,9 @@ struct Core::dtFetch Core::fetch() { }; } -struct Core::dtDecode Core::decode(struct dtFetch dt) { - struct DecodeMap dec = dmap[dt.inst.opcode()]; +struct Core::dtDecode Core::decode(const struct dtFetch &dt) { + emit instruction_decoded(dt.inst); + const struct DecodeMap &dec = dmap[dt.inst.opcode()]; if (!(dec.flags & DM_SUPPORTED)) // TODO message throw QTMIPS_EXCEPTION(UnsupportedInstruction, "", ""); @@ -128,8 +129,8 @@ struct Core::dtDecode Core::decode(struct dtFetch dt) { // TODO on jump there should be delay slot. Does processor addes it or compiler. And do we care? } -struct Core::dtExecute Core::execute(struct dtDecode dt) { - // TODO signals +struct Core::dtExecute Core::execute(const struct dtDecode &dt) { + emit instruction_executed(dt.inst); // Handle conditional move (we have to change regwrite signal if conditional is not met) // TODO can't we do this some cleaner way? @@ -142,6 +143,7 @@ struct Core::dtExecute Core::execute(struct dtDecode dt) { alu_sec = ((dt.inst.immediate() & 0x8000) << 16) | (dt.inst.immediate() & 0x7FFF); // Sign extend to 32bit return { + .inst = dt.inst, .memread = dt.memread, .memwrite = dt.memwrite, .regwrite = regwrite, @@ -152,8 +154,8 @@ struct Core::dtExecute Core::execute(struct dtDecode dt) { }; } -struct Core::dtMemory Core::memory(struct dtExecute dt) { - // TODO signals +struct Core::dtMemory Core::memory(const struct dtExecute &dt) { + emit instruction_memory(dt.inst); std::uint32_t towrite_val = dt.alu_val; if (dt.memwrite) @@ -162,20 +164,20 @@ struct Core::dtMemory Core::memory(struct dtExecute dt) { towrite_val = mem->read_ctl(dt.memctl, dt.alu_val); return { + .inst = dt.inst, .regwrite = dt.regwrite, .rwrite = dt.rwrite, .towrite_val = towrite_val, }; } -void Core::writeback(struct dtMemory dt) { - if (dt.regwrite) { +void Core::writeback(const struct dtMemory &dt) { + emit instruction_writeback(dt.inst); + if (dt.regwrite) regs->write_gp(dt.rwrite, dt.towrite_val); - } } -void Core::handle_pc(struct dtDecode dt) { - // TODO signals +void Core::handle_pc(const struct dtDecode &dt) { bool branch = false; bool link = false; // TODO implement link @@ -242,6 +244,7 @@ void Core::dtDecodeInit(struct dtDecode &dt) { } void Core::dtExecuteInit(struct dtExecute &dt) { + dt.inst = Instruction(0x00); dt.memread = false; dt.memwrite = false; dt.regwrite = false; @@ -252,6 +255,7 @@ void Core::dtExecuteInit(struct dtExecute &dt) { } void Core::dtMemoryInit(struct dtMemory &dt) { + dt.inst = Instruction(0x00); dt.regwrite = false; dt.rwrite = false; dt.towrite_val = 0; @@ -297,7 +301,7 @@ CorePipelined::CorePipelined(Registers *regs, MemoryAccess *mem) : \ void CorePipelined::step() { // TODO implement forward unit writeback(dt_m); - dt_m =memory(dt_e); + dt_m = memory(dt_e); dt_e = execute(dt_d); dt_d = decode(dt_f); dt_f = fetch(); diff --git a/qtmips_machine/core.h b/qtmips_machine/core.h index 1878bfc..3078c95 100644 --- a/qtmips_machine/core.h +++ b/qtmips_machine/core.h @@ -20,7 +20,11 @@ public: virtual void reset() = 0; // Reset core (only core, memory and registers has to be reseted separately) signals: - void instruction_fetched(machine::Instruction &inst); + void instruction_fetched(const machine::Instruction &inst); + void instruction_decoded(const machine::Instruction &inst); + void instruction_executed(const machine::Instruction &inst); + void instruction_memory(const machine::Instruction &inst); + void instruction_writeback(const machine::Instruction &inst); protected: Registers *regs; @@ -42,6 +46,7 @@ protected: std::uint32_t val_rt; // Value from register rt }; struct dtExecute { + Instruction inst; bool memread; bool memwrite; bool regwrite; @@ -51,17 +56,18 @@ protected: std::uint32_t alu_val; // Result of ALU execution }; struct dtMemory { + Instruction inst; bool regwrite; std::uint8_t rwrite; std::uint32_t towrite_val; }; struct dtFetch fetch(); - struct dtDecode decode(struct dtFetch); - struct dtExecute execute(struct dtDecode); - struct dtMemory memory(struct dtExecute); - void writeback(struct dtMemory); - void handle_pc(struct dtDecode); + struct dtDecode decode(const struct dtFetch&); + struct dtExecute execute(const struct dtDecode&); + struct dtMemory memory(const struct dtExecute&); + void writeback(const struct dtMemory&); + void handle_pc(const struct dtDecode&); // Initialize structures to NOPE instruction void dtFetchInit(struct dtFetch &dt); diff --git a/qtmips_machine/instruction.cpp b/qtmips_machine/instruction.cpp index edb6305..4ef65a4 100644 --- a/qtmips_machine/instruction.cpp +++ b/qtmips_machine/instruction.cpp @@ -228,7 +228,7 @@ static const struct AluInstructionMap alu_instruction_map[] = { }; #undef AIM_UNKNOWN -QString Instruction::to_str() { +QString Instruction::to_str() const { // TODO there are exception where some fields are zero and such so we should not print them in sych case if (opcode() >= (sizeof(instruction_map) / sizeof(struct InstructionMap))) return QString("UNKNOWN"); diff --git a/qtmips_machine/instruction.h b/qtmips_machine/instruction.h index 6232d3e..d84b0cb 100644 --- a/qtmips_machine/instruction.h +++ b/qtmips_machine/instruction.h @@ -29,7 +29,7 @@ public: bool operator!=(const Instruction &c) const; Instruction &operator=(const Instruction &c); - QString to_str(); + QString to_str() const; private: std::uint32_t dt; -- cgit v1.2.3