Skip to content

Commit 2eeda94

Browse files
committed
test(port_arm): implement kernel_benchmarks::Driver::performance_time using PMU cycle counter
The kernel benchmark tests can now run on GR-PEACH.
1 parent f82e4f3 commit 2eeda94

File tree

3 files changed

+97
-4
lines changed

3 files changed

+97
-4
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,4 +177,5 @@ The `-b` option instructs `constance_test_runner` to run benchmark tests. Note t
177177

178178
- Hosted platform: `cargo bench -p constance_port_std`
179179
- The Armv7-M port and NUCLEO-F401RE: `cargo run -p constance_test_runner -- -t nucleo_f401re -b`
180+
- The Armv7-A port and GR-PEACH: `cargo run -p constance_test_runner -- -t gr_peach -b`
180181
- The RISC-V port and RED-V (SPI flash XIP): `cargo run -p constance_test_runner -- -t red_v -b`

src/constance_port_arm_test_driver/src/main.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ mod logger_semihosting;
2424
#[cfg(feature = "output-semihosting")]
2525
mod panic_semihosting;
2626

27+
#[cfg(feature = "kernel_benchmarks")]
28+
mod pmu;
29+
2730
#[allow(unused_macros)]
2831
macro_rules! instantiate_test {
2932
// If a test case is specified, instantiate the test case
@@ -129,12 +132,11 @@ macro_rules! instantiate_test {
129132
}
130133

131134
fn performance_time() -> u32 {
132-
// SP804 Timer1
133-
!unsafe { ((<System as port::Sp804Options>::SP804_BASE + 4)
134-
as *const u32).read_volatile() }
135+
use register::cpu::RegisterReadWrite;
136+
pmu::PMCCNTR.get()
135137
}
136138

137-
const PERFORMANCE_TIME_UNIT: &'static str = "μs";
139+
const PERFORMANCE_TIME_UNIT: &'static str = "CPU cycles";
138140

139141
// Chose PPIs.
140142
// SGIs (software-generated interrupts) don't support disabling.
@@ -171,6 +173,14 @@ macro_rules! instantiate_test {
171173
#[cfg(feature = "board-rza1")]
172174
System::configure_os_timer(b);
173175

176+
// Start PMU cycle counter
177+
#[cfg(feature = "kernel_benchmarks")]
178+
StartupHook::build().start(|_| {
179+
use register::cpu::RegisterReadWrite;
180+
pmu::PMCR.modify(pmu::PMCR::E::SET + pmu::PMCR::D::DivideBy1);
181+
pmu::PMCNTENSET.modify(pmu::PMCNTENSET::C::SET);
182+
}).finish(b);
183+
174184
// Redirect the log output to stderr
175185
#[cfg(all(feature = "output-semihosting", not(feature = "board-rza1")))]
176186
StartupHook::build().start(|_| {
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
//! Arm PMU
2+
macro_rules! sys_coproc_read_raw {
3+
($width:ty, [$cp:ident, $crn:ident, $opc1:literal, $crm:ident, $opc2:literal]) => {
4+
#[inline]
5+
fn get(&self) -> u32 {
6+
let reg;
7+
unsafe {
8+
asm!(
9+
concat!(
10+
"mrc ", stringify!($cp), ", ", stringify!($opc1), ", {}, ",
11+
stringify!($crn), ", ", stringify!($crm), ", ", stringify!($opc2)
12+
),
13+
out(reg)reg,
14+
);
15+
}
16+
reg
17+
}
18+
};
19+
}
20+
/// Implements `register::cpu::RegisterReadWrite::set`.
21+
macro_rules! sys_coproc_write_raw {
22+
($width:ty, [$cp:ident, $crn:ident, $opc1:literal, $crm:ident, $opc2:literal]) => {
23+
#[inline]
24+
fn set(&self, value: u32) {
25+
unsafe {
26+
asm!(
27+
concat!(
28+
"mcr ", stringify!($cp), ", ", stringify!($opc1), ", {}, ",
29+
stringify!($crn), ", ", stringify!($crm), ", ", stringify!($opc2)
30+
),
31+
in(reg)value,
32+
);
33+
}
34+
}
35+
};
36+
}
37+
38+
register::register_bitfields! {u32,
39+
pub PMCNTENSET [
40+
/// PMCCNTR enable bit.
41+
C OFFSET(31) NUMBITS(1) []
42+
]
43+
}
44+
45+
/// Performance Monitors Count Enable Set register
46+
pub const PMCNTENSET: PMCNTENSETAccessor = PMCNTENSETAccessor;
47+
pub struct PMCNTENSETAccessor;
48+
49+
impl register::cpu::RegisterReadWrite<u32, PMCNTENSET::Register> for PMCNTENSETAccessor {
50+
sys_coproc_read_raw!(u32, [p15, c9, 0, c12, 1]);
51+
sys_coproc_write_raw!(u32, [p15, c9, 0, c12, 1]);
52+
}
53+
54+
register::register_bitfields! {u32,
55+
pub PMCR [
56+
/// Clock divider.
57+
D OFFSET(3) NUMBITS(1) [
58+
DivideBy1 = 0,
59+
DivideBy64 = 1
60+
],
61+
/// Enable.
62+
E OFFSET(0) NUMBITS(1) []
63+
]
64+
}
65+
66+
/// Performance Monitors Control Register
67+
pub const PMCR: PMCRAccessor = PMCRAccessor;
68+
pub struct PMCRAccessor;
69+
70+
impl register::cpu::RegisterReadWrite<u32, PMCR::Register> for PMCRAccessor {
71+
sys_coproc_read_raw!(u32, [p15, c9, 0, c12, 0]);
72+
sys_coproc_write_raw!(u32, [p15, c9, 0, c12, 0]);
73+
}
74+
75+
/// Performance Monitors Cycle Count Register
76+
pub const PMCCNTR: PMCCNTRAccessor = PMCCNTRAccessor;
77+
pub struct PMCCNTRAccessor;
78+
79+
impl register::cpu::RegisterReadWrite<u32, ()> for PMCCNTRAccessor {
80+
sys_coproc_read_raw!(u32, [p15, c9, 0, c13, 0]);
81+
sys_coproc_write_raw!(u32, [p15, c9, 0, c13, 0]);
82+
}

0 commit comments

Comments
 (0)