From 47aab53a5c4deadb00cda63ee5bb8fb08c5c1355 Mon Sep 17 00:00:00 2001 From: Rich Neswold Date: Sun, 4 Oct 2026 12:49:09 -0500 Subject: [PATCH] :sparkles: add "integrate" driver --- drmemd/src/driver.rs | 14 +++ drmemd/src/driver/integrate.rs | 5 + drmemd/src/driver/integrate/config.rs | 12 ++ drmemd/src/driver/integrate/device.rs | 44 +++++++ drmemd/src/driver/integrate/driver.rs | 122 +++++++++++++++++++ drmemd/src/driver/integrate/drv_integrate.md | 23 ++++ 6 files changed, 220 insertions(+) create mode 100644 drmemd/src/driver/integrate.rs create mode 100644 drmemd/src/driver/integrate/config.rs create mode 100644 drmemd/src/driver/integrate/device.rs create mode 100644 drmemd/src/driver/integrate/driver.rs create mode 100644 drmemd/src/driver/integrate/drv_integrate.md diff --git a/drmemd/src/driver.rs b/drmemd/src/driver.rs index c41fa41..c7bb164 100644 --- a/drmemd/src/driver.rs +++ b/drmemd/src/driver.rs @@ -11,6 +11,7 @@ use tracing::{error, field, info, info_span, warn, Instrument}; mod counter; mod cycle; +mod integrate; mod latch; mod map; mod memory; @@ -175,6 +176,19 @@ impl DriverDb { ); } + { + use integrate::Instance; + + table.insert( + Instance::NAME.into(), + ( + Instance::SUMMARY, + Instance::DESCRIPTION, + manage_instance::, + ), + ); + } + { use latch::Instance; diff --git a/drmemd/src/driver/integrate.rs b/drmemd/src/driver/integrate.rs new file mode 100644 index 0000000..f713ec9 --- /dev/null +++ b/drmemd/src/driver/integrate.rs @@ -0,0 +1,5 @@ +mod config; +mod device; +mod driver; + +pub use driver::Instance; diff --git a/drmemd/src/driver/integrate/config.rs b/drmemd/src/driver/integrate/config.rs new file mode 100644 index 0000000..94d7747 --- /dev/null +++ b/drmemd/src/driver/integrate/config.rs @@ -0,0 +1,12 @@ +use drmem_api::{driver::DriverConfig, Error}; + +#[derive(serde::Deserialize)] +pub struct Params; + +impl TryFrom for Params { + type Error = Error; + + fn try_from(_cfg: DriverConfig) -> std::result::Result { + Ok(Params) + } +} diff --git a/drmemd/src/driver/integrate/device.rs b/drmemd/src/driver/integrate/device.rs new file mode 100644 index 0000000..32d0108 --- /dev/null +++ b/drmemd/src/driver/integrate/device.rs @@ -0,0 +1,44 @@ +use drmem_api::{ + device::Path, + driver::{self, Reporter, ResettableState}, + Result, +}; + +use super::config; + +pub struct Set { + pub d_sum: driver::ReadOnlyDevice, + pub d_data: driver::ReadWriteDevice, + pub d_reset: driver::ReadWriteDevice, +} + +impl driver::Registrator for Set { + type Config = config::Params; + + async fn register_devices( + core: &mut driver::RequestChan, + subpath: Option<&Path>, + _cfg: &Self::Config, + max_history: Option, + ) -> Result { + // Define the devices managed by this driver. + + let d_sum = core + .add_ro_device("sum", subpath, None, max_history) + .await?; + let d_data = core + .add_rw_device("data", subpath, None, max_history) + .await?; + let d_reset = core + .add_rw_device("reset", subpath, None, max_history) + .await?; + + Ok(Set { + d_sum, + d_data, + d_reset, + }) + } +} + +impl ResettableState for Set {} diff --git a/drmemd/src/driver/integrate/driver.rs b/drmemd/src/driver/integrate/driver.rs new file mode 100644 index 0000000..bfa9603 --- /dev/null +++ b/drmemd/src/driver/integrate/driver.rs @@ -0,0 +1,122 @@ +use drmem_api::{ + driver::{self, Reporter}, + Result, +}; +use std::convert::Infallible; + +use super::{config, device}; + +// The state of a driver instance. + +pub enum Instance { + Primed(f64), + Reset(f64), +} + +impl Instance { + pub const NAME: &'static str = "integrate"; + + pub const SUMMARY: &'static str = "Accumulates values that have occurred"; + + pub const DESCRIPTION: &'static str = include_str!("drv_integrate.md"); + + /// Creates a new, idle `Instance`. + pub fn new() -> Instance { + Instance::Primed(0.0) + } + + pub fn accumulate(&mut self, val: f64) { + match self { + Instance::Primed(v) | Instance::Reset(v) => *v = *v + val, + } + } + + pub fn reset(&mut self, val: bool) -> bool { + match self { + Instance::Primed(_) => { + if val { + *self = Instance::Reset(0.0); + true + } else { + false + } + } + Instance::Reset(v) => { + if !val { + *self = Instance::Primed(*v); + true + } else { + false + } + } + } + } + + pub fn get_sum(&self) -> f64 { + match self { + Instance::Primed(v) => *v, + Instance::Reset(v) => *v, + } + } +} + +impl driver::API for Instance { + type Config = config::Params; + type HardwareType = device::Set; + + async fn create_instance(_cfg: &Self::Config) -> Result> { + Ok(Box::new(Instance::new())) + } + + async fn run(&mut self, devices: &mut Self::HardwareType) -> Infallible { + devices.d_sum.report_update(self.get_sum()).await; + + loop { + let mut report = true; + + #[rustfmt::skip] + tokio::select! { + Some((b, reply)) = devices.d_data.next_setting() => { + reply.ok(b); + devices.d_data.report_update(b).await; + self.accumulate(b); + } + Some((b, reply)) = devices.d_reset.next_setting() => { + reply.ok(b); + devices.d_reset.report_update(b).await; + report = self.reset(b); + } + } + + if report { + devices.d_sum.report_update(self.get_sum()).await + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_state_changes() { + let mut accum = Instance::new(); + + assert_eq!(accum.get_sum(), 0.0); + accum.accumulate(1.0); + assert_eq!(accum.get_sum(), 1.0); + accum.accumulate(2.0); + assert_eq!(accum.get_sum(), 3.0); + accum.reset(false); + assert_eq!(accum.get_sum(), 3.0); + accum.reset(true); + assert_eq!(accum.get_sum(), 0.0); + accum.accumulate(1.0); + assert_eq!(accum.get_sum(), 1.0); + accum.accumulate(2.0); + assert_eq!(accum.get_sum(), 3.0); + accum.reset(true); + assert_eq!(accum.get_sum(), 3.0); + } +} diff --git a/drmemd/src/driver/integrate/drv_integrate.md b/drmemd/src/driver/integrate/drv_integrate.md new file mode 100644 index 0000000..26ea365 --- /dev/null +++ b/drmemd/src/driver/integrate/drv_integrate.md @@ -0,0 +1,23 @@ +# drmem-drv-integrate + +Implements a floating point accumulator that sums every value applied to the `data` device. The `output` device reports the latest sum as a floating point value. `data` accepts floating point values. Boolean values are converted to `0` and `1`. When the `reset` device is set to `true`, the sum is reset to `0.0`. + +This driver is always available in DrMem. + +## Configuration + +This driver has no configuration parameters. + +## Devices + +The driver creates these devices: + +| Base Name | Type | Units | Comment | +|-----------|----------|-------|--------------------------------------------------------| +| `data` | float, RW | | Value is added to sum. | +| `reset` | bool, RW | | A `false` to `true` transition resets the sum to 0. | +| `output` | float, RO | | The current sum. | + +## History + +Added in v0.8.0.