diff --git a/artiq/coredevice/pcu.py b/artiq/coredevice/pcu.py new file mode 100644 index 000000000..e819aa239 --- /dev/null +++ b/artiq/coredevice/pcu.py @@ -0,0 +1,72 @@ +from .spr import mtspr, mfspr +from artiq.language.core import kernel + + +_MAX_SPRS_PER_GRP_BITS = 11 +_SPRGROUP_PC = 7 << _MAX_SPRS_PER_GRP_BITS +_SPR_PCMR_CP = 0x00000001 # Counter present +_SPR_PCMR_CISM = 0x00000004 # Count in supervisor mode +_SPR_PCMR_CIUM = 0x00000008 # Count in user mode +_SPR_PCMR_LA = 0x00000010 # Load access event +_SPR_PCMR_SA = 0x00000020 # Store access event +_SPR_PCMR_IF = 0x00000040 # Instruction fetch event +_SPR_PCMR_DCM = 0x00000080 # Data cache miss event +_SPR_PCMR_ICM = 0x00000100 # Insn cache miss event +_SPR_PCMR_IFS = 0x00000200 # Insn fetch stall event +_SPR_PCMR_LSUS = 0x00000400 # LSU stall event +_SPR_PCMR_BS = 0x00000800 # Branch stall event +_SPR_PCMR_DTLBM = 0x00001000 # DTLB miss event +_SPR_PCMR_ITLBM = 0x00002000 # ITLB miss event +_SPR_PCMR_DDS = 0x00004000 # Data dependency stall event +_SPR_PCMR_WPE = 0x03ff8000 # Watchpoint events + + +@kernel(flags={"nowrite", "nounwind"}) +def _PCCR(n): + return _SPRGROUP_PC + n + + +@kernel(flags={"nowrite", "nounwind"}) +def _PCMR(n): + return _SPRGROUP_PC + 8 + n + + +@kernel +def pc_start(): + """ + Configure and clear the kernel CPU performance counters. + + The eight counters are configures to count the folloging events: + * Load or store + * Instruction fetch + * Data cache miss + * Instruction cache miss + * Instruction fetch stall + * Load-store-unit stall + * Branch stall + * Data dependency stall + """ + for i in range(8): + if not mfspr(_PCMR(i)) & _SPR_PCMR_CP: + raise ValueError("counter not present") + mtspr(_PCMR(i), 0) + mtspr(_PCCR(i), 0) + mtspr(_PCMR(0), _SPR_PCMR_CISM | _SPR_PCMR_LA | _SPR_PCMR_SA) + mtspr(_PCMR(1), _SPR_PCMR_CISM | _SPR_PCMR_IF) + mtspr(_PCMR(2), _SPR_PCMR_CISM | _SPR_PCMR_DCM) + mtspr(_PCMR(3), _SPR_PCMR_CISM | _SPR_PCMR_ICM) + mtspr(_PCMR(4), _SPR_PCMR_CISM | _SPR_PCMR_IFS) + mtspr(_PCMR(5), _SPR_PCMR_CISM | _SPR_PCMR_LSUS) + mtspr(_PCMR(6), _SPR_PCMR_CISM | _SPR_PCMR_BS) + mtspr(_PCMR(7), _SPR_PCMR_CISM | _SPR_PCMR_DDS) + + +@kernel +def pc_get(r): + """ + Read the performance counters and store the counts in the array provided. + + :param list[int] r: array to store the counter values + """ + for i in range(8): + r[i] = mfspr(_PCCR(i)) diff --git a/artiq/coredevice/spr.py b/artiq/coredevice/spr.py new file mode 100644 index 000000000..4f968d794 --- /dev/null +++ b/artiq/coredevice/spr.py @@ -0,0 +1,12 @@ +from artiq.language.core import syscall +from artiq.language.types import TInt32, TNone + + +@syscall(flags={"nounwind", "nowrite"}) +def mfspr(spr: TInt32) -> TInt32: + raise NotImplementedError("syscall not simulated") + + +@syscall(flags={"nowrite", "nowrite"}) +def mtspr(spr: TInt32, value: TInt32) -> TNone: + raise NotImplementedError("syscall not simulated") diff --git a/artiq/firmware/ksupport/api.rs b/artiq/firmware/ksupport/api.rs index a38d17f9a..ce07c5aa4 100644 --- a/artiq/firmware/ksupport/api.rs +++ b/artiq/firmware/ksupport/api.rs @@ -94,6 +94,9 @@ static mut API: &'static [(&'static str, *const ())] = &[ api!(cache_get = ::cache_get), api!(cache_put = ::cache_put), + api!(mfspr = ::board::spr::mfspr), + api!(mtspr = ::board::spr::mtspr), + /* direct syscalls */ api!(rtio_init = ::rtio::init), api!(rtio_get_counter = ::rtio::get_counter),