39 void free()
override { }
43 std::shared_ptr<qemu::Timer> m_deadline_timer;
49 sc_core::sc_event_or_list m_external_ev;
50 sc_core::sc_process_handle m_sc_thread;
52 std::atomic<bool> m_signaled;
53 std::mutex m_signaled_lock;
54 std::condition_variable m_signaled_cond;
56 std::shared_ptr<gs::tlm_quantumkeeper_extended> m_qk;
57 std::atomic<bool> m_finished =
false;
58 std::atomic<bool> m_started =
false;
59 enum { none, start_reset, hold_reset, finish_reset } m_resetting = none;
62 std::mutex m_can_delete;
70 void create_quantum_keeper()
75 SCP_FATAL(()) <<
"qbox : Sync policy unknown";
85 void set_coroutine_mode()
87 switch (m_qk->get_thread_type()) {
88 case gs::SyncPolicy::SYSTEMC_THREAD:
92 case gs::SyncPolicy::OS_THREAD:
116 if (m_inst.
get_tcg_mode() != QemuInstance::TCG_SINGLE) {
117 std::lock_guard<std::mutex>
lock(m_signaled_lock);
119 m_signaled_cond.notify_all();
121 std::lock_guard<std::mutex>
lock(m_inst.g_signaled_lock);
122 m_inst.g_signaled =
true;
123 m_inst.g_signaled_cond.notify_all();
131 void watch_external_ev()
145 SCP_TRACE(())(
"QEMU deadline KICK callback");
147 if (!m_finished) m_qemu_kick_ev.async_notify();
159 void deadline_timer_cb()
161 SCP_TRACE(())(
"QEMU deadline timer callback");
166 rearm_deadline_timer();
170 sc_core::sc_time
sc_t = sc_core::sc_time_stamp();
171 if (sc_core::sc_time(
now, sc_core::SC_NS) >
sc_t) {
172 m_qk->set(sc_core::sc_time(
now, sc_core::SC_NS) -
sc_t);
190 if (m_finished)
return;
193 m_on_sysc.
run_on_sysc([
this]() { wait(m_external_ev); });
195 if (m_inst.
get_tcg_mode() != QemuInstance::TCG_SINGLE) {
196 std::unique_lock<std::mutex>
lock(m_signaled_lock);
197 m_signaled_cond.wait(
lock, [
this] {
return m_signaled || m_finished; });
200 std::unique_lock<std::mutex>
lock(m_inst.g_signaled_lock);
201 m_inst.g_signaled_cond.wait(
lock, [
this] {
return m_inst.g_signaled || m_finished; });
202 m_inst.g_signaled =
false;
205 if (m_finished)
return;
213 void rearm_deadline_timer()
217 m_deadline_timer->mod(m_inst.
get().get_virtual_clock() + m_quantum_ns);
224 void prepare_run_cpu()
233 if (m_inst.
get_tcg_mode() == QemuInstance::TCG_SINGLE) {
234 while (!m_inst.can_run() && !m_finished) {
238 while (!m_cpu.can_run() && !m_finished) {
239 if (!m_coroutines && !m_inst.is_tcg_enabled()) {
243 SCP_TRACE(())(
"Stopping QK (accelerator)");
252 m_cpu.set_soft_stopped(
false);
259 m_inst.
get().lock_iothread();
273 for (
int i = 0;
i < m_inst.number_devices();
i++) {
274 if ((m_inst.
get().get_virtual_clock() ==
last_vclock) && (m_cpu.can_run())) {
284 void sync_with_kernel()
288 m_cpu.set_soft_stopped(
true);
290 m_inst.
get().unlock_iothread();
294 sc_core::sc_time
sc_t = sc_core::sc_time_stamp();
295 if (sc_core::sc_time(
now, sc_core::SC_NS) >
sc_t) {
296 m_qk->set(sc_core::sc_time(
now, sc_core::SC_NS) -
sc_t);
307 void end_of_loop_cb()
310 if (m_finished)
return;
316 if (!m_started)
return;
319 m_inst.
get().coroutine_yield();
321 std::lock_guard<std::mutex>
lock(m_can_delete);
330 void mainloop_thread_coroutine()
332 m_cpu.register_thread();
334 for (; !m_finished;) {
342 cci::cci_param<unsigned int> p_gdb_port;
354 , m_qemu_kick_ev(
false)
356 , p_gdb_port(
"gdb_port", 0,
"Wait for gdb connection on TCP port <gdb_port>")
357 , socket(
"mem", *
this, inst)
359 using namespace std::placeholders;
361 m_external_ev |= m_qemu_kick_ev;
363 auto haltcb = std::bind(&QemuCpu::halt_cb,
this,
_1);
364 halt.register_value_changed_cb(
haltcb);
365 auto resetcb = std::bind(&QemuCpu::reset_cb,
this,
_1);
366 reset.register_value_changed_cb(
resetcb);
368 create_quantum_keeper();
369 set_coroutine_mode();
375 m_inst.add_dev(
this);
377 m_start_reset_done_ev.async_detach_suspending();
383 while (!m_can_delete.try_lock()) {
386 m_inst.del_dev(
this);
391 void end_of_simulation()
override
393 if (m_finished)
return;
396 if (!m_cpu.valid()) {
405 m_inst.
get().lock_iothread();
407 m_cpu.clear_callbacks();
411 m_inst.
get().unlock_iothread();
430 m_cpu.set_unplug(
true);
433 m_inst.
get().unlock_iothread();
440 bool can_run()
override {
return m_cpu.can_run(); }
442 void before_end_of_elaboration()
override
444 QemuDevice::before_end_of_elaboration();
449 m_sc_thread = sc_core::sc_spawn(std::bind(&QemuCpu::mainloop_thread_coroutine,
this));
452 socket.init(m_dev,
"memory");
454 m_cpu.set_soft_stopped(
true);
456 m_cpu.set_end_of_loop_callback(std::bind(&QemuCpu::end_of_loop_cb,
this));
457 m_cpu.set_kick_callback(std::bind(&QemuCpu::kick_cb,
this));
459 m_deadline_timer = m_inst.
get().timer_new();
460 m_deadline_timer->set_callback(std::bind(&QemuCpu::deadline_timer_cb,
this));
462 m_cpu_hint_ext.set_cpu(m_cpu);
465 void halt_cb(
const bool&
val)
470 m_deadline_timer->del();
474 rearm_deadline_timer();
476 m_inst.
get().lock_iothread();
478 m_inst.
get().unlock_iothread();
479 m_qemu_kick_ev.async_notify();
484 void reset_cb(
const bool&
val)
487 if (m_finished)
return;
490 if (m_resetting != none)
return;
492 m_resetting = start_reset;
493 m_cpu.async_safe_run([&] {
495 m_resetting = hold_reset;
496 m_start_reset_done_ev.async_notify();
499 if (m_resetting == none)
return;
500 while (m_resetting == start_reset) {
502 sc_core::wait(m_start_reset_done_ev);
504 m_inst.
get().lock_iothread();
506 m_inst.
get().unlock_iothread();
510 m_qemu_kick_ev.async_notify();
514 m_qemu_kick_ev.async_notify();
516 virtual void end_of_elaboration()
override
518 QemuDevice::end_of_elaboration();
520 if (!p_gdb_port.is_default_value()) {
521 std::stringstream
ss;
522 SCP_INFO(()) <<
"Starting gdb server on TCP port " << p_gdb_port;
523 ss <<
"tcp::" << p_gdb_port;
524 m_inst.
get().start_gdb_server(
ss.str());
528 virtual void start_of_simulation()
override
530 m_quantum_ns =
int64_t(tlm_utils::tlm_quantumkeeper::get_global_quantum().
to_seconds() * 1
e9);
532 QemuDevice::start_of_simulation();
533 if (m_inst.
get_tcg_mode() == QemuInstance::TCG_SINGLE) {
534 if (m_inst.can_run()) {
537 }
else if (!m_coroutines) {
569 m_inst.
get().lock_iothread();
570 m_cpu.set_soft_stopped(
false);
571 rearm_deadline_timer();
573 m_inst.
get().unlock_iothread();
580 m_cpu.set_vcpu_dirty(
true);
584 virtual void initiator_customize_tlm_payload(TlmPayload&
payload)
override
587 payload.set_extension(&m_cpu_hint_ext);
590 virtual void initiator_tidy_tlm_payload(TlmPayload&
payload)
override {
payload.clear_extension(&m_cpu_hint_ext); }
596 virtual sc_core::sc_time initiator_get_local_time()
override
598 using sc_core::sc_time;
599 using sc_core::SC_NS;
604 sc_core::sc_time
sc_t = sc_core::sc_time_stamp();
607 return m_qk->get_local_time();
609 return sc_core::SC_ZERO_TIME;
617 virtual void initiator_set_local_time(
const sc_core::sc_time&
t)
override
621 if (m_qk->need_sync()) {
631 virtual void initiator_async_run(qemu::Cpu::AsyncJobFn
job)
override
633 if (!m_finished) m_cpu.async_run(
job);