app: multi-core-inverter: implement 2-core inverter

this is a simpler test-bed to explore things like clock duration
This commit is contained in:
2022-08-22 18:14:28 -07:00
parent b160823a81
commit 5fff872890

View File

@@ -40,13 +40,15 @@
use coremem::geom::{Coord as _, Meters, Torus}; use coremem::geom::{Coord as _, Meters, Torus};
use coremem::mat::{Ferroxcube3R1MH, IsoConductorOr, IsomorphicConductor}; use coremem::mat::{Ferroxcube3R1MH, IsoConductorOr, IsomorphicConductor};
use coremem::meas; use coremem::meas;
#[allow(unused)]
use coremem::real::{self, Real as _}; use coremem::real::{self, Real as _};
use coremem::sim::spirv::{self, SpirvSim}; use coremem::sim::spirv::{self, SpirvSim};
use coremem::sim::units::Seconds; use coremem::sim::units::Seconds;
use coremem::stim::{CurlVectorField, Exp, Gated, ModulatedVectorField, Scaled, Shifted, StimExt as _}; use coremem::stim::{CurlVectorField, Exp, Gated, ModulatedVectorField, Scaled, Shifted, StimExt as _};
use coremem::Driver; use coremem::Driver;
type R = real::R32; // type R = real::R32;
type R = f32;
type Mat = IsoConductorOr<R, Ferroxcube3R1MH>; type Mat = IsoConductorOr<R, Ferroxcube3R1MH>;
// type Backend = spirv::CpuBackend; // type Backend = spirv::CpuBackend;
type Backend = spirv::WgpuBackend; type Backend = spirv::WgpuBackend;
@@ -165,41 +167,11 @@ impl Params {
} }
} }
/// 5 cores in sequence; analyze how they propagate a *specific* input signal
fn main() { #[allow(unused)]
coremem::init_logging(); fn drive_map_5_core_inv(s0_init_state: ClockState, s0_rel_state: ClockState) -> [[ClockState; 5]; 14] {
// coremem::init_debug();
// let ns = |n| n as f32 * 1e-9;
let feat_size = um(10);
let params = Params {
input_magnitude: 1.0e7,
clock_phase_duration: ps(4000),
clock_decay: ps(1000),
// 's' = core (ferromagnetic part)
s_major: um(160),
s_minor: um(30),
// 'io' = drive/control wire
io_major: um(80),
io_minor: um(30),
coupling_major: um(130),
coupling_minor: um(30),
// coords for core 'n'
sy: um(400),
sz: um(280),
};
let sim_bounds = |num_cores| Meters::new(params.sx(num_cores), params.sy * 2.0, params.sz * 2.0);
let sim_padding = Meters::new(um(80), um(80), um(80));
//////// define the control signals/transitions
// each row N denotes the drive currents at clock cycle N.
// each col M denotes the drive current at core M.
use ClockState::*; use ClockState::*;
// let s0_init_state = HoldHigh; // logic high [
let s0_init_state = HoldLow; // logic low
let s0_rel_state = ReleaseLow;
let drive_map = [
// charge each device to '1' // charge each device to '1'
[s0_init_state,HoldHigh, HoldHigh, HoldHigh, HoldHigh], [s0_init_state,HoldHigh, HoldHigh, HoldHigh, HoldHigh],
// this is when we'd ordinarily open S0 for write // this is when we'd ordinarily open S0 for write
@@ -234,7 +206,62 @@ fn main() {
[Float, HoldHigh, HoldHigh, HoldLow, HoldLow], [Float, HoldHigh, HoldHigh, HoldLow, HoldLow],
// open S1 for write // open S1 for write
[Float, ReleaseHigh, HoldHigh, HoldLow, HoldLow], [Float, ReleaseHigh, HoldHigh, HoldLow, HoldLow],
]; ]
}
/// minimal 2-core inverter.
/// analyze how the inverter transfers a zero v.s. a one.
fn drive_map_isolated_inv() -> [[ClockState; 2]; 6] {
use ClockState::*;
[
// charge each device to '1'
[HoldHigh, HoldHigh ],
// let the cores settle
[ReleaseHigh,ReleaseHigh],
// write S0 -> S1. S1 should be *cleared* to 0.
[HoldLow, Float ],
// charge S0=0, reset S1 for next write
[HoldLow, HoldHigh ],
// let the cores settle
[ReleaseLow, ReleaseHigh],
// write S0 -> S1. S1 should *keep its state* of 1.
[HoldLow, Float ],
]
}
fn main() {
coremem::init_logging();
// coremem::init_debug();
// let ns = |n| n as f32 * 1e-9;
let feat_size = um(10);
let params = Params {
input_magnitude: 1.0e7,
clock_phase_duration: ps(40000),
clock_decay: ps(6000),
// 's' = core (ferromagnetic part)
s_major: um(160),
s_minor: um(30),
// 'io' = drive/control wire
io_major: um(80),
io_minor: um(30),
coupling_major: um(130),
coupling_minor: um(30),
// coords for core 'n'
sy: um(400),
sz: um(280),
};
let sim_bounds = |num_cores| Meters::new(params.sx(num_cores), params.sy * 2.0, params.sz * 2.0);
let sim_padding = Meters::new(um(80), um(80), um(80));
//////// define the control signals/transitions
// each row N denotes the drive currents at clock cycle N.
// each col M denotes the drive current at core M.
// let drive_map = drive_map_5_core_inv(ClockState::HoldLow, ClockState::ReleaseLow);
let drive_map = drive_map_isolated_inv();
let num_cycles = drive_map.len() as u32; let num_cycles = drive_map.len() as u32;
let num_cores = drive_map[0].len() as u32; let num_cores = drive_map[0].len() as u32;
let mut core_drivers = vec![Vec::default(); num_cores as usize]; let mut core_drivers = vec![Vec::default(); num_cores as usize];
@@ -253,7 +280,7 @@ fn main() {
ModulatedVectorField::new(v_field, time_varying.scaled(amp.cast::<R>())) ModulatedVectorField::new(v_field, time_varying.scaled(amp.cast::<R>()))
}) })
.collect(); .collect();
assert_eq!(stim.len(), 5); assert_eq!(stim.len(), num_cores as usize);
let wire_mat = IsomorphicConductor::new(1e6f32.cast::<R>()); let wire_mat = IsomorphicConductor::new(1e6f32.cast::<R>());
@@ -306,7 +333,7 @@ fn main() {
} }
let duration = Seconds(params.clock_phase_duration * (num_cycles + 3) as f32); let duration = Seconds(params.clock_phase_duration * num_cycles as f32);
// let stim = DynStimuli::from_vec(stim.map(MapIntoBoxStimulus).into_vec()); // let stim = DynStimuli::from_vec(stim.map(MapIntoBoxStimulus).into_vec());
let mut driver = driver.with_modulated_stimulus(); let mut driver = driver.with_modulated_stimulus();
@@ -314,12 +341,13 @@ fn main() {
driver.add_stimulus(s); driver.add_stimulus(s);
} }
let prefix = "out/applications/multi_core_inverter/23-4ns-1e7A/"; let prefix = "out/applications/multi_core_inverter/26-40ns-6ns-1e7A/";
let _ = std::fs::create_dir_all(&prefix); let _ = std::fs::create_dir_all(&prefix);
driver.add_state_file(&*format!("{}state.bc", prefix), 6400); driver.add_state_file(&*format!("{}state.bc", prefix), 25600);
driver.add_serializer_renderer(&*format!("{}frame-", prefix), 6400, None); // driver.add_serializer_renderer(&*format!("{}frame-", prefix), 6400, None);
// driver.add_csv_renderer(&*format!("{}meas-detailed.csv", prefix), 100, None); // driver.add_csv_renderer(&*format!("{}meas-detailed.csv", prefix), 100, None);
driver.add_csv_renderer(&*format!("{}meas.csv", prefix), 800, None); driver.add_csv_renderer(&*format!("{}meas.csv", prefix), 1600, None);
driver.add_csv_renderer(&*format!("{}meas-sparse.csv", prefix), 12800, None);
driver.set_steps_per_stimulus(200); driver.set_steps_per_stimulus(200);
driver.step_until(duration); driver.step_until(duration);