From 9d356ed93bc72fd9c9238e3f4d8a3da207066463 Mon Sep 17 00:00:00 2001
From: whitequark <whitequark@whitequark.org>
Date: Mon, 16 Oct 2017 15:29:42 +0000
Subject: [PATCH] firmware: implement board::pcr.

---
 artiq/firmware/Cargo.lock          |  7 +++++
 artiq/firmware/libboard/Cargo.toml |  1 +
 artiq/firmware/libboard/lib.rs     |  3 ++
 artiq/firmware/libboard/pcr.rs     | 44 ++++++++++++++++++++++++++++++
 4 files changed, 55 insertions(+)
 create mode 100644 artiq/firmware/libboard/pcr.rs

diff --git a/artiq/firmware/Cargo.lock b/artiq/firmware/Cargo.lock
index dfddf22e7..4797ee6c6 100644
--- a/artiq/firmware/Cargo.lock
+++ b/artiq/firmware/Cargo.lock
@@ -17,10 +17,16 @@ dependencies = [
  "board 0.0.0",
 ]
 
+[[package]]
+name = "bitflags"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "board"
 version = "0.0.0"
 dependencies = [
+ "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "build_artiq 0.0.0",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -211,6 +217,7 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [metadata]
+"checksum bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5cde24d1b2e2216a726368b2363a273739c91f4e3eb4e0dd12d672d396ad989"
 "checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8"
 "checksum compiler_builtins 0.1.0 (git+https://github.com/rust-lang-nursery/compiler-builtins?rev=631b568)" = "<none>"
 "checksum cslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f8cb7306107e4b10e64994de6d3274bd08996a7c1322a27b86482392f96be0a"
diff --git a/artiq/firmware/libboard/Cargo.toml b/artiq/firmware/libboard/Cargo.toml
index e3fed9298..825c9cf81 100644
--- a/artiq/firmware/libboard/Cargo.toml
+++ b/artiq/firmware/libboard/Cargo.toml
@@ -13,6 +13,7 @@ build_artiq = { path = "../libbuild_artiq" }
 
 [dependencies]
 log = { version = "0.3", default-features = false }
+bitflags = { version = "1.0" }
 
 [features]
 uart_console = []
diff --git a/artiq/firmware/libboard/lib.rs b/artiq/firmware/libboard/lib.rs
index 738740273..31df0e4b3 100644
--- a/artiq/firmware/libboard/lib.rs
+++ b/artiq/firmware/libboard/lib.rs
@@ -3,6 +3,8 @@
 
 #[macro_use]
 extern crate log;
+#[macro_use]
+extern crate bitflags;
 
 use core::{cmp, ptr, str};
 
@@ -11,6 +13,7 @@ include!(concat!(env!("BUILDINC_DIRECTORY"), "/generated/csr.rs"));
 pub mod spr;
 pub mod irq;
 pub mod cache;
+pub mod pcr;
 pub mod clock;
 pub mod uart;
 #[cfg(feature = "uart_console")]
diff --git a/artiq/firmware/libboard/pcr.rs b/artiq/firmware/libboard/pcr.rs
new file mode 100644
index 000000000..59518e8bf
--- /dev/null
+++ b/artiq/firmware/libboard/pcr.rs
@@ -0,0 +1,44 @@
+use spr::*;
+
+bitflags! {
+    pub struct Counters: u32 {
+        const LA     = SPR_PCMR_LA;
+        const SA     = SPR_PCMR_SA;
+        const IF     = SPR_PCMR_IF;
+        const DCM    = SPR_PCMR_DCM;
+        const ICM    = SPR_PCMR_ICM;
+        const IFS    = SPR_PCMR_IFS;
+        const LSUS   = SPR_PCMR_LSUS;
+        const BS     = SPR_PCMR_BS;
+        const DTLBM  = SPR_PCMR_DTLBM;
+        const ITLBM  = SPR_PCMR_ITLBM;
+        const DDS    = SPR_PCMR_DDS;
+
+        const INSTRN = Self::IF.bits;
+        const MEMORY = Self::LA.bits    | Self::SA.bits;
+        const STALL  = Self::DCM.bits   | Self::ICM.bits   | Self::IFS.bits |
+                       Self::LSUS.bits  | Self::BS.bits    | Self::DDS.bits ;
+        const MISS   = Self::DTLBM.bits | Self::ITLBM.bits ;
+    }
+}
+
+fn is_valid(index: u32) -> bool {
+    index < 8 && unsafe { mfspr(SPR_PCMR0 + index) } & SPR_PCMR_CP != 0
+}
+
+#[inline]
+pub fn setup(index: u32, counters: Counters) {
+    debug_assert!(is_valid(index));
+
+    unsafe {
+        mtspr(SPR_PCMR0 + index, SPR_PCMR_CISM | SPR_PCMR_CIUM | counters.bits);
+        mtspr(SPR_PCCR0 + index, 0);
+    }
+}
+
+#[inline]
+pub fn read(index: u32) -> u32 {
+    unsafe {
+        mfspr(SPR_PCCR0 + index)
+    }
+}