quic/qbox
Loading...
Searching...
No Matches
riscv-aclint-mtimer.h
1/*
2 * This file is part of libqbox
3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
4 * Author: GreenSocs 2022
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9#pragma once
10
11#include <vector>
12
13#include <cci_configuration>
14
15#include <libqemu-cxx/target/riscv.h>
16#include <module_factory_registery.h>
17
18#include <ports/target.h>
19#include <ports/qemu-initiator-signal-socket.h>
20#include <device.h>
21
23{
24public:
25 cci::cci_param<uint32_t> p_hartid_base;
26 cci::cci_param<unsigned int> p_num_harts;
27 cci::cci_param<uint64_t> p_timecmp_base;
28 cci::cci_param<uint64_t> p_time_base;
29 cci::cci_param<uint64_t> p_aperture_size;
30 cci::cci_param<uint32_t> p_timebase_freq;
31 cci::cci_param<bool> p_provide_rdtime;
32
33 QemuTargetSocket<> socket;
34 sc_core::sc_vector<QemuInitiatorSignalSocket> timer_irq;
35
36 riscv_aclint_mtimer(const sc_core::sc_module_name& name, sc_core::sc_object* o)
37 : riscv_aclint_mtimer(name, *(dynamic_cast<QemuInstance*>(o)))
38 {
39 }
40 riscv_aclint_mtimer(sc_core::sc_module_name nm, QemuInstance& inst)
41 : QemuDevice(nm, inst, "riscv.aclint.mtimer")
42 , p_hartid_base("hartid_base", 0, "Base hart ID for this ACLINT MTimer")
43 , p_num_harts("num_harts", 0, "Number of HARTS this CLINT is connected to")
44 , p_timecmp_base("timecmp_base", 0, "Base address for the TIMECMP registers")
45 , p_time_base("time_base", 0, "Base address for the TIME registers")
46 , p_aperture_size("aperture_size", 0, "Size of the whole CLINT address space")
47 , p_timebase_freq("timebase_freq", 10000000, "")
48 , p_provide_rdtime("provide_rdtime", false,
49 "If true, provide the CPU with "
50 "a rdtime register")
51 , socket("mem", inst)
52 , timer_irq("timer_irq")
53 {
54 }
55
56 void before_end_of_elaboration() override
57 {
58 QemuDevice::before_end_of_elaboration();
59
60 // Initialize timer_irq vector with the correct size based on p_num_harts (if not already done)
61 if (timer_irq.size() == 0) {
62 timer_irq.init(p_num_harts, [](const char* n, size_t i) { return new QemuInitiatorSignalSocket(n); });
63 }
64
65 if (timer_irq.size() != p_num_harts) {
66 SCP_WARN(SCMOD) << "Timer IRQ size mismatch: timer_irq.size()=" << timer_irq.size()
67 << " != p_num_harts=" << (unsigned int)p_num_harts;
68 }
69
70 m_dev.set_prop_int("hartid-base", p_hartid_base);
71 m_dev.set_prop_int("num-harts", p_num_harts);
72 m_dev.set_prop_int("timecmp-base", p_timecmp_base);
73 m_dev.set_prop_int("time-base", p_time_base);
74 m_dev.set_prop_int("aperture-size", p_aperture_size);
75 m_dev.set_prop_int("timebase-freq", p_timebase_freq);
76 m_dev.set_prop_bool("provide-rdtime", p_provide_rdtime);
77 }
78
79 void end_of_elaboration() override
80 {
81 QemuDevice::set_sysbus_as_parent_bus();
82 QemuDevice::end_of_elaboration();
83
84 qemu::SysBusDevice sbd(get_qemu_dev());
85 socket.init(qemu::SysBusDevice(m_dev), 0);
86
87 // Initialize timer interrupt outputs for all harts (GPIO outputs)
88 for (unsigned int i = 0; i < p_num_harts; i++) {
89 timer_irq[i].init(m_dev, i);
90 }
91
92 // Timer IRQ GPIO outputs are now ready for connection
93 SCP_INFO(SCMOD) << "Timer IRQ GPIO outputs ready for connection";
94 }
95};
96
97extern "C" void module_register();
QEMU device abstraction as a SystemC module.
Definition device.h:37
A QEMU output GPIO exposed as a InitiatorSignalSocket<bool>
Definition qemu-initiator-signal-socket.h:40
This class encapsulates a libqemu-cxx qemu::LibQemu instance. It handles QEMU parameters and instance...
Definition qemu-instance.h:89
Definition target.h:160
Definition libqemu-cxx.h:627
Definition riscv-aclint-mtimer.h:23