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) {
250 m_cpu.set_soft_stopped(
false);
257 m_inst.
get().lock_iothread();
271 for (
int i = 0;
i < m_inst.number_devices();
i++) {
272 if ((m_inst.
get().get_virtual_clock() ==
last_vclock) && (m_cpu.can_run())) {
282 void sync_with_kernel()
286 m_cpu.set_soft_stopped(
true);
288 m_inst.
get().unlock_iothread();
292 sc_core::sc_time
sc_t = sc_core::sc_time_stamp();
293 if (sc_core::sc_time(
now, sc_core::SC_NS) >
sc_t) {
294 m_qk->set(sc_core::sc_time(
now, sc_core::SC_NS) -
sc_t);
305 void end_of_loop_cb()
308 if (m_finished)
return;
310 m_inst.
get().coroutine_yield();
312 std::lock_guard<std::mutex>
lock(m_can_delete);
321 void mainloop_thread_coroutine()
323 m_cpu.register_thread();
325 for (; !m_finished;) {
333 cci::cci_param<unsigned int> p_gdb_port;
345 , m_qemu_kick_ev(
false)
347 , p_gdb_port(
"gdb_port", 0,
"Wait for gdb connection on TCP port <gdb_port>")
348 , socket(
"mem", *
this, inst)
350 using namespace std::placeholders;
352 m_external_ev |= m_qemu_kick_ev;
354 auto haltcb = std::bind(&QemuCpu::halt_cb,
this,
_1);
355 halt.register_value_changed_cb(
haltcb);
356 auto resetcb = std::bind(&QemuCpu::reset_cb,
this,
_1);
357 reset.register_value_changed_cb(
resetcb);
359 create_quantum_keeper();
360 set_coroutine_mode();
366 m_inst.add_dev(
this);
368 m_start_reset_done_ev.async_detach_suspending();
374 while (!m_can_delete.try_lock()) {
377 m_inst.del_dev(
this);
382 void end_of_simulation()
override
384 if (m_finished)
return;
387 if (!m_cpu.valid()) {
396 m_inst.
get().lock_iothread();
398 m_cpu.clear_callbacks();
402 m_inst.
get().unlock_iothread();
421 m_cpu.set_unplug(
true);
424 m_inst.
get().unlock_iothread();
431 bool can_run()
override {
return m_cpu.can_run(); }
433 void before_end_of_elaboration()
override
435 QemuDevice::before_end_of_elaboration();
440 m_sc_thread = sc_core::sc_spawn(std::bind(&QemuCpu::mainloop_thread_coroutine,
this));
443 socket.init(m_dev,
"memory");
445 m_cpu.set_soft_stopped(
true);
447 m_cpu.set_end_of_loop_callback(std::bind(&QemuCpu::end_of_loop_cb,
this));
448 m_cpu.set_kick_callback(std::bind(&QemuCpu::kick_cb,
this));
450 m_deadline_timer = m_inst.
get().timer_new();
451 m_deadline_timer->set_callback(std::bind(&QemuCpu::deadline_timer_cb,
this));
453 m_cpu_hint_ext.set_cpu(m_cpu);
456 void halt_cb(
const bool&
val)
461 m_deadline_timer->del();
465 rearm_deadline_timer();
467 m_inst.
get().lock_iothread();
469 m_inst.
get().unlock_iothread();
470 m_qemu_kick_ev.async_notify();
475 void reset_cb(
const bool&
val)
478 if (m_finished)
return;
481 if (m_resetting != none)
return;
483 m_resetting = start_reset;
484 m_cpu.async_safe_run([&] {
486 m_resetting = hold_reset;
487 m_start_reset_done_ev.async_notify();
490 if (m_resetting == none)
return;
491 while (m_resetting == start_reset) {
493 sc_core::wait(m_start_reset_done_ev);
499 m_qemu_kick_ev.async_notify();
503 m_qemu_kick_ev.async_notify();
505 virtual void end_of_elaboration()
override
507 QemuDevice::end_of_elaboration();
509 if (!p_gdb_port.is_default_value()) {
510 std::stringstream
ss;
511 SCP_INFO(()) <<
"Starting gdb server on TCP port " << p_gdb_port;
512 ss <<
"tcp::" << p_gdb_port;
513 m_inst.
get().start_gdb_server(
ss.str());
517 virtual void start_of_simulation()
override
519 m_quantum_ns =
int64_t(tlm_utils::tlm_quantumkeeper::get_global_quantum().
to_seconds() * 1
e9);
521 QemuDevice::start_of_simulation();
522 if (m_inst.
get_tcg_mode() == QemuInstance::TCG_SINGLE) {
523 if (m_inst.can_run()) {
529 m_cpu.set_soft_stopped(
false);
530 rearm_deadline_timer();
538 m_cpu.set_vcpu_dirty(
true);
544 virtual void initiator_customize_tlm_payload(TlmPayload&
payload)
override
547 payload.set_extension(&m_cpu_hint_ext);
550 virtual void initiator_tidy_tlm_payload(TlmPayload&
payload)
override {
payload.clear_extension(&m_cpu_hint_ext); }
556 virtual sc_core::sc_time initiator_get_local_time()
override
558 using sc_core::sc_time;
559 using sc_core::SC_NS;
564 sc_core::sc_time
sc_t = sc_core::sc_time_stamp();
567 return m_qk->get_local_time();
569 return sc_core::SC_ZERO_TIME;
577 virtual void initiator_set_local_time(
const sc_core::sc_time&
t)
override
581 if (m_qk->need_sync()) {
591 virtual void initiator_async_run(qemu::Cpu::AsyncJobFn
job)
override
593 if (!m_finished) m_cpu.async_run(
job);