diff --git a/src/sysc/core2sc_adapter.h b/src/sysc/core2sc_adapter.h index e3c9a4e..5b93f22 100644 --- a/src/sysc/core2sc_adapter.h +++ b/src/sysc/core2sc_adapter.h @@ -114,7 +114,7 @@ template class core2sc_adapter : public PLAT, public sc2core_if auto cycle_incr = owner->get_last_bus_cycles(); if(cycle_incr > 1) this->instr_if.update_last_instr_cycles(cycle_incr); - owner->sync(this->instr_if.get_total_cycles()); + owner->qk_sync(this->instr_if.get_total_cycles()); } first = false; } @@ -270,12 +270,14 @@ template class core2sc_adapter : public PLAT, public sc2core_if if(is_debugger_stop_evt) break; } - SCCINFO(this->owner->hier_name()) << "Got WFI event"; + SCCDEBUG(this->owner->hier_name()) << "Got WFI event"; auto duration = sc_core::sc_time_stamp() - start; if(clk_if && duration > sc_core::SC_ZERO_TIME) { auto cycles = duration.value() / clk_if->read().value(); this->reg.cycle += cycles; + SCCDEBUG(owner->hier_name()) << "Increasing cycles by " << cycles << " after WFI"; } + owner->qk_reset(this->instr_if.get_total_cycles()); }; owner->exec_on_sysc(f); wfi_inst.store(false, std::memory_order_relaxed); diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index bcab159..02f33ca 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -434,15 +434,20 @@ bool core_complex::read_mem(const addr_t& addr, unsigned length, u gp.set_extension>(nullptr); }; auto pre_delay = delay; + auto transport_start = sc_core::sc_time_stamp(); exec_b_transport(gp, delay, is_fetch); - if(pre_delay > delay) { - quantum_keeper.reset(); - } else { - auto incr = (delay - quantum_keeper.get_local_time()) / curr_clk; - if(is_fetch) - ibus_inc += incr; - else - dbus_inc += incr; + auto transport_time = sc_core::sc_time_stamp() - transport_start; + auto completion = delay + sc_core::sc_time_stamp(); + auto time_taken = (completion) - (pre_delay + transport_start); + auto incr = time_taken.value() / curr_clk.read().value(); + if(is_fetch) + ibus_inc += incr; + else + dbus_inc += incr; + + if(transport_time.value()) { + quantum_keeper.reset(completion); + qk_preaccounted_cycles += incr; } SCCTRACE(this->name()) << "[local offset: +" << delay << "]: finish read_mem(0x" << std::hex << addr.val << ") : 0x" << (length == 4 ? *(uint32_t*)data @@ -497,11 +502,18 @@ bool core_complex::write_mem(const addr_t& addr, unsigned length, gp.set_extension>(nullptr); }; auto pre_delay = delay; + auto transport_start = sc_core::sc_time_stamp(); exec_b_transport(gp, delay); - if(pre_delay > delay) - quantum_keeper.reset(); - else - dbus_inc += (delay - quantum_keeper.get_local_time()) / curr_clk; + auto transport_time = sc_core::sc_time_stamp() - transport_start; + auto completion = delay + sc_core::sc_time_stamp(); + auto time_taken = (completion) - (pre_delay + transport_start); + auto incr = time_taken.value() / curr_clk.read().value(); + dbus_inc += incr; + + if(transport_time.value()) { + quantum_keeper.reset(completion); + qk_preaccounted_cycles += incr; + } SCCTRACE(this->name()) << "[local offset: +" << delay << "]: finish write_mem(0x" << std::hex << addr.val << ") : 0x" << (length == 4 ? *(uint32_t*)data : length == 2 ? *(uint16_t*)data diff --git a/src/sysc/core_complex.h b/src/sysc/core_complex.h index 5f5019b..f76b44a 100644 --- a/src/sysc/core_complex.h +++ b/src/sysc/core_complex.h @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -184,11 +185,19 @@ class core_complex : public sc_core::sc_module, public scc::traceable, public co return mem_incr > 1 ? mem_incr : 1; } - void sync(uint64_t cycle) override { - auto core_inc = curr_clk * (cycle - last_sync_cycle); + void qk_sync(uint64_t cycle) override { + auto cycle_delta = cycle - last_sync_cycle; + auto preaccounted = std::min(cycle_delta, qk_preaccounted_cycles); + qk_preaccounted_cycles -= preaccounted; + assert(qk_preaccounted_cycles <= cycle_delta); + auto core_inc = curr_clk * (cycle_delta - preaccounted); quantum_keeper.check_and_sync(core_inc); last_sync_cycle = cycle; } + void qk_reset(uint64_t cycle) override { + quantum_keeper.reset(quantum_keeper.get_local_absolute_time()); + last_sync_cycle = cycle; + } bool read_mem(const iss::addr_t& a, unsigned length, uint8_t* const data) override; @@ -300,6 +309,7 @@ class core_complex : public sc_core::sc_module, public scc::traceable, public co // /////////////////////////////////////////////////////////////////////////////// uint64_t last_sync_cycle = 0; + uint64_t qk_preaccounted_cycles{0}; util::range_lut fetch_lut{tlm_dmi_ext()}; util::range_lut& get_read_lut(unsigned space) { return space < dmi_read_luts.size() ? dmi_read_luts[space] : get_lut(dmi_read_luts, space); diff --git a/src/sysc/core_complex_if.h b/src/sysc/core_complex_if.h index 6eff667..2d39bea 100644 --- a/src/sysc/core_complex_if.h +++ b/src/sysc/core_complex_if.h @@ -61,7 +61,9 @@ struct core_complex_if { virtual unsigned get_last_bus_cycles() = 0; //! Allow quantum keeper handling - virtual void sync(uint64_t) = 0; + virtual void qk_sync(uint64_t) = 0; + + virtual void qk_reset(uint64_t) = 0; util::delegate&)> exec_on_sysc;