app: stacked_cores: define an "or gate" sim + script for post-processing
extract transfer characteristics with e.g. ``` extract_meas.py ../../../out/applications/stacked_cores/52-or--0.0004rad-5000ctl_cond-20000coupling_cond-2000ps-100ps-3ctl-3coupling-3_1_winding-49999998976e0-drive- 2e-9 4e-9 8e-9 ```
This commit is contained in:
parent
9d2fbf8b07
commit
87366cf473
|
@ -0,0 +1,102 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
invoke with the path to a meas.csv file for the stacked_core 51-xx or later demos
|
||||
to extract higher-level info from them.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
|
||||
from stacked_cores import load_csv, labeled_rows, last_row_before_t, extract_m
|
||||
from stacked_cores_39xx import extract_polarity
|
||||
|
||||
class MeasRow:
|
||||
def __init__(self, t_sec: float, m: list):
|
||||
self.t_sec = t_sec
|
||||
self.m = m
|
||||
|
||||
def __repr__(self) -> str:
|
||||
m = ", ".join(f"{v:6}" for v in self.m)
|
||||
return f"MeasRow({self.t_sec}, [{m}])"
|
||||
|
||||
@staticmethod
|
||||
def from_dict(row_data: dict) -> 'MeasRow':
|
||||
t_sec = row_data["time"]
|
||||
m = [int(m + 0.5) for m in extract_m(row_data)]
|
||||
return MeasRow(t_sec, m)
|
||||
|
||||
def format_float_tuple(t: tuple) -> str:
|
||||
formatted_elems = [f"{e:= 05.3f}," for e in t]
|
||||
return f"({' '.join(formatted_elems)})"
|
||||
|
||||
def format_list(l: list) -> str:
|
||||
if len(l) == 0: return "[]"
|
||||
if len(l) == 1: return f"{l}"
|
||||
formatted_elems = [f"\t{e}" for e in l]
|
||||
return "\n".join(["["] + formatted_elems + ["]"])
|
||||
|
||||
def indented(s: str) -> str:
|
||||
return s.replace('\n', '\n\t')
|
||||
|
||||
class ParameterizedMeas:
|
||||
def __init__(self, meas = None):
|
||||
self.meas = meas or {}
|
||||
|
||||
def add_meas(self, params: tuple, meas_rows: list):
|
||||
self.meas[tuple(params)] = meas_rows
|
||||
|
||||
def __repr__(self) -> str:
|
||||
meas_entries = "\n".join(
|
||||
f"\t{format_float_tuple(k)}: {indented(format_list(v))}," for (k, v) in sorted(self.meas.items())
|
||||
)
|
||||
return f"ParameterizedMeas({{\n{meas_entries}\n}})"
|
||||
|
||||
def extract_rows(path: str, times: list) -> list:
|
||||
header, raw_rows = load_csv(path)
|
||||
rows = labeled_rows(header, raw_rows)
|
||||
|
||||
meas_rows = []
|
||||
for t in times:
|
||||
row = last_row_before_t(rows, t)
|
||||
if not row: return None
|
||||
meas_rows.append(MeasRow.from_dict(row))
|
||||
|
||||
# validate the sim has run to completion
|
||||
if meas_rows[-1].t_sec < 0.95 * t: return None
|
||||
meas_rows[-1].t_sec = t # make pretty
|
||||
|
||||
return meas_rows
|
||||
|
||||
def parse_param(s: str) -> float:
|
||||
""" parse a parameter in the form of 'p050' or 'n0015' or '000' """
|
||||
if s == "000":
|
||||
return 0.0
|
||||
|
||||
sign = {'n': -1, 'p': 1}[s[0]]
|
||||
mag = int(s[1:])
|
||||
max_mag = 10**(len(s[1:]) - 1)
|
||||
return sign * mag / max_mag
|
||||
|
||||
def extract_params(pstr: str) -> list:
|
||||
""" extract parameters from a string like -n100-000 """
|
||||
pieces = [p for p in pstr.split("-") if p]
|
||||
return [parse_param(p) for p in pieces]
|
||||
|
||||
def extract_parameterized_meas(stem: str, times: list) -> ParameterizedMeas:
|
||||
""" given some stem, parse all parameterized measurements associated with that stem """
|
||||
base_dir, prefix = os.path.split(stem)
|
||||
|
||||
built = ParameterizedMeas()
|
||||
for entry in os.listdir(base_dir):
|
||||
if entry.startswith(prefix):
|
||||
meas_rows = extract_rows(os.path.join(base_dir, entry, "meas.csv"), times)
|
||||
if not meas_rows: continue
|
||||
params = extract_params(entry[len(prefix):])
|
||||
built.add_meas(params, meas_rows)
|
||||
|
||||
return built
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(extract_parameterized_meas(sys.argv[1], [float(f) for f in sys.argv[2:]]))
|
|
@ -1324,6 +1324,25 @@ fn drive_map_fork_then_join_m2_out(amp0: f32) -> [[ClockState; 4]; 3] {
|
|||
]
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
fn drive_map_or_gate(amp0: f32, amp1: f32) -> [[ClockState; 4]; 4] {
|
||||
use ClockState as C;
|
||||
// amplitudes are inverted from what you would expect.
|
||||
// hold(-1) puts the core into a positive M
|
||||
[
|
||||
// init S0 pos, S1 pos; charge S2 neg, S3 neg
|
||||
[C::release(-amp0), C::release(-amp1), C::release_high(), C::release_high()],
|
||||
// clear S0 -> S2, S1 -> S2
|
||||
// NB: we might slightly prefer to do this in two separate steps, but doing it in one cycle is
|
||||
// quicker to simulate.
|
||||
[C::hold_high(), C::hold_high(), C::float(), C::float()],
|
||||
// relax S0, S1, so that S2 isn't unnecessarily loaded in the next cycle
|
||||
[C::release_high(), C::release_high(), C::float(), C::float()],
|
||||
// clear S2 -> S3
|
||||
[C::hold_high(), C::hold_high(), C::hold_high(), C::float()],
|
||||
]
|
||||
}
|
||||
|
||||
fn asymmetric_inverter_name(p: &Params, sim_id: &str, windings: u32, init_flt: f32) -> String {
|
||||
let init_int = (init_flt.abs() * 100.0 + 0.5) as u32;
|
||||
let init_level = if init_flt > 0.0 {
|
||||
|
@ -1337,13 +1356,8 @@ fn asymmetric_inverter_name(p: &Params, sim_id: &str, windings: u32, init_flt: f
|
|||
let s_major = p.s_major;
|
||||
let coupling_loops = p.coupling_loops;
|
||||
|
||||
let mut input_leading = p.input_magnitude as u64;
|
||||
let mut input_exp = 0;
|
||||
while input_leading != 0 && input_leading % 10 == 0 {
|
||||
input_leading /= 10;
|
||||
input_exp += 1;
|
||||
}
|
||||
format!("{sim_id}-{s_major}rad-{coupling_loops}coupling-{windings}_1_winding-{input_leading}e{input_exp}-drive-{init_level}")
|
||||
let input_str = exp_format(p.input_magnitude);
|
||||
format!("{sim_id}-{s_major}rad-{coupling_loops}coupling-{windings}_1_winding-{input_str}-drive-{init_level}")
|
||||
}
|
||||
|
||||
|
||||
|
@ -1360,18 +1374,11 @@ fn asymmetric_inverter_name_v2(p: &Params, sim_id: &str, ctl_loops: u32, couplin
|
|||
|
||||
let s_major = p.s_major;
|
||||
|
||||
let mut input_leading = p.input_magnitude as u64;
|
||||
let mut input_exp = 0;
|
||||
while input_leading != 0 && input_leading % 10 == 0 {
|
||||
input_leading /= 10;
|
||||
input_exp += 1;
|
||||
}
|
||||
format!("{sim_id}-{s_major}rad-{ctl_loops}ctl-{coupling_loops}coupling-{windings}_1_winding-{input_leading}e{input_exp}-drive-{init_level}")
|
||||
let input_str = exp_format(p.input_magnitude);
|
||||
format!("{sim_id}-{s_major}rad-{ctl_loops}ctl-{coupling_loops}coupling-{windings}_1_winding-{input_str}-drive-{init_level}")
|
||||
}
|
||||
|
||||
/// v3 has coupling_loops specified externally,
|
||||
/// and encodes conductivities + clocks
|
||||
fn asymmetric_inverter_name_v3(p: &Params, sim_id: &str, ctl_loops: u32, coupling_loops: u32, windings: u32, init_flt: f32) -> String {
|
||||
fn init_float_str(init_flt: f32) -> String {
|
||||
let init_int = (init_flt.abs() * 1000.0 + 0.5) as u32;
|
||||
let init_int_str = if init_int % 10 == 0 {
|
||||
format!("{:03}", init_int / 10)
|
||||
|
@ -1379,13 +1386,29 @@ fn asymmetric_inverter_name_v3(p: &Params, sim_id: &str, ctl_loops: u32, couplin
|
|||
format!("{:04}", init_int)
|
||||
};
|
||||
|
||||
let init_level = if init_flt > 0.0 {
|
||||
if init_flt > 0.0 {
|
||||
format!("p{init_int_str}")
|
||||
} else if init_flt < 0.0 {
|
||||
format!("n{init_int_str}")
|
||||
} else {
|
||||
init_int_str
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn exp_format(e: f32) -> String {
|
||||
let mut e_leading = e as u64;
|
||||
let mut e_exp = 0;
|
||||
while e_leading != 0 && e_leading % 10 == 0 {
|
||||
e_leading /= 10;
|
||||
e_exp += 1;
|
||||
}
|
||||
format!("{}e{}", e_leading, e_exp)
|
||||
}
|
||||
|
||||
/// v3 has coupling_loops specified externally,
|
||||
/// and encodes conductivities + clocks
|
||||
fn asymmetric_inverter_name_v3(p: &Params, sim_id: &str, ctl_loops: u32, coupling_loops: u32, windings: u32, init_flt: f32) -> String {
|
||||
let init_level = init_float_str(init_flt);
|
||||
|
||||
let s_major = p.s_major;
|
||||
let ctl_cond = p.ctl_conductivity as u64;
|
||||
|
@ -1393,13 +1416,22 @@ fn asymmetric_inverter_name_v3(p: &Params, sim_id: &str, ctl_loops: u32, couplin
|
|||
let clock_length = (p.clock_phase_duration * 1e12 + 0.5) as u64;
|
||||
let clock_decay = (p.clock_decay * 1e12 + 0.5) as u64;
|
||||
|
||||
let mut input_leading = p.input_magnitude as u64;
|
||||
let mut input_exp = 0;
|
||||
while input_leading != 0 && input_leading % 10 == 0 {
|
||||
input_leading /= 10;
|
||||
input_exp += 1;
|
||||
}
|
||||
format!("{sim_id}-{s_major}rad-{ctl_cond}ctl_cond-{coupling_cond}coupling_cond-{clock_length}ps-{clock_decay}ps-{ctl_loops}ctl-{coupling_loops}coupling-{windings}_1_winding-{input_leading}e{input_exp}-drive-{init_level}")
|
||||
let input_str = exp_format(p.input_magnitude);
|
||||
format!("{sim_id}-{s_major}rad-{ctl_cond}ctl_cond-{coupling_cond}coupling_cond-{clock_length}ps-{clock_decay}ps-{ctl_loops}ctl-{coupling_loops}coupling-{windings}_1_winding-{input_str}-drive-{init_level}")
|
||||
}
|
||||
|
||||
fn asymmetric_binary_gate_name(p: &Params, sim_id: &str, ctl_loops: u32, coupling_loops: u32, windings: u32, init_flt_a: f32, init_flt_b: f32) -> String {
|
||||
let init_level_a = init_float_str(init_flt_a);
|
||||
let init_level_b = init_float_str(init_flt_b);
|
||||
|
||||
let s_major = p.s_major;
|
||||
let ctl_cond = p.ctl_conductivity as u64;
|
||||
let coupling_cond = p.coupling_conductivity as u64;
|
||||
let clock_length = (p.clock_phase_duration * 1e12 + 0.5) as u64;
|
||||
let clock_decay = (p.clock_decay * 1e12 + 0.5) as u64;
|
||||
|
||||
let input_str = exp_format(p.input_magnitude);
|
||||
format!("{sim_id}-{s_major}rad-{ctl_cond}ctl_cond-{coupling_cond}coupling_cond-{clock_length}ps-{clock_decay}ps-{ctl_loops}ctl-{coupling_loops}coupling-{windings}_1_winding-{input_str}-drive-{init_level_a}-{init_level_b}")
|
||||
}
|
||||
|
||||
/// couple `sender` to the `sender+1` core by using `loops` loops, including a crossover so that
|
||||
|
@ -5135,7 +5167,7 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
if true {
|
||||
if false {
|
||||
for init_set in [
|
||||
&[
|
||||
// targeted for (5e2, 5e3, ps(1000), ps(50), 9, 1, um(400), 1e10)
|
||||
|
@ -5647,6 +5679,74 @@ fn main() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if true {
|
||||
for init_set in [
|
||||
&[
|
||||
// targeted
|
||||
][..],
|
||||
&[
|
||||
// establish the domain/range
|
||||
( 1.00, 1.00),
|
||||
(-1.00, -1.00),
|
||||
(-1.00, 1.00),
|
||||
( 1.00, -1.00),
|
||||
][..],
|
||||
&[
|
||||
(0.00, 0.00),
|
||||
(-1.00, 0.00),
|
||||
][..],
|
||||
] {
|
||||
for (ctl_cond, coupling_cond, clock_duration, clock_decay, coupling_loops, s0_loops, s_major, cur_flt) in [
|
||||
(5e3, 2e4, ps(2000), ps(100), 3, 1, um(400), 5e10),
|
||||
(5e2, 2e4, ps(2000), ps(100), 3, 1, um(400), 5e10),
|
||||
|
||||
(1e3, 2e4, ps(2000), ps(100), 3, 1, um(400), 2e10),
|
||||
(2e3, 2e4, ps(2000), ps(100), 3, 1, um(400), 1e10),
|
||||
(2e3, 2e4, ps(2000), ps(100), 3, 1, um(400), 2e10),
|
||||
(2e3, 2e4, ps(2000), ps(100), 3, 1, um(400), 3e10),
|
||||
(5e3, 2e4, ps(2000), ps(100), 3, 1, um(400), 3e10),
|
||||
|
||||
] {
|
||||
for &(init_flt_a, init_flt_b) in init_set {
|
||||
// coupling loops (M0 -> M2) + (M1 -> M2) + (M2 -> M3) + control slots
|
||||
let slots_per_asym = 2*s0_loops;
|
||||
let net_slots = 3*slots_per_asym + 1;
|
||||
let mut params = params_v2
|
||||
.with_clock_phase_duration(clock_duration)
|
||||
.with_clock_decay(clock_decay)
|
||||
.with_ctl_conductivity(ctl_cond)
|
||||
.with_coupling_conductivity(coupling_cond)
|
||||
.with_s_major(s_major)
|
||||
.with_coupling_loops(coupling_loops)
|
||||
.with_input_magnitude(cur_flt)
|
||||
// control loops
|
||||
.with_coupling(0, 0, 0, net_slots, CouplingMethod::Control)
|
||||
.with_coupling(1, 1, 0, net_slots, CouplingMethod::Control)
|
||||
.with_coupling(2, 2, 0, net_slots, CouplingMethod::Control)
|
||||
.with_coupling(3, 3, 0, net_slots, CouplingMethod::Control)
|
||||
;
|
||||
for i in 0..slots_per_asym {
|
||||
// couple input core 0 to core 2
|
||||
params = params.with_coupling(0, 2, 1+i, net_slots, CouplingMethod::Outside);
|
||||
// couple input core 1 to core 2
|
||||
params = params.with_coupling(1, 2, 1+i + slots_per_asym, net_slots, CouplingMethod::Direct);
|
||||
}
|
||||
// couple OR gate core 2 to output core 3
|
||||
params = couple_asymmetric_buffer(¶ms, 2 /* sender core */, s0_loops, 1 + 2*slots_per_asym /* slot offset */, net_slots);
|
||||
|
||||
let name = asymmetric_binary_gate_name(
|
||||
¶ms, "52-or-", coupling_loops /* ctl loops */, coupling_loops, 2*s0_loops + 1, init_flt_a, init_flt_b
|
||||
);
|
||||
run_sim(
|
||||
&name,
|
||||
drive_map_or_gate(init_flt_a, init_flt_b),
|
||||
params,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue