From a45c0c4324f5fa026739df5bfd79a9ae4819bb2e Mon Sep 17 00:00:00 2001 From: colin Date: Thu, 3 Nov 2022 05:42:38 -0700 Subject: [PATCH] app: stacked_cores: new 53-xx run, where we buffer differential signals --- crates/applications/stacked_cores/src/main.rs | 160 +++++++++++++++++- 1 file changed, 157 insertions(+), 3 deletions(-) diff --git a/crates/applications/stacked_cores/src/main.rs b/crates/applications/stacked_cores/src/main.rs index 793153b..e5c3b94 100644 --- a/crates/applications/stacked_cores/src/main.rs +++ b/crates/applications/stacked_cores/src/main.rs @@ -341,8 +341,10 @@ impl Params { ) ); // how far to bring the wire past the center of the torus circle - let outside_small = self.s_minor * 2.0; - let outside_large = self.s_minor * 2.0 + self.coupling_minor * 4.0; + // self.s_minor * 2.0 works to dodge the core itself, + // but larger values are required to also dodge direct couplings we might be near to. + let outside_small = self.s_minor * 4.0; + let outside_large = self.s_minor * 4.0 + self.coupling_minor * 4.0; let outside_top_center_z = self.coupling_major; let outside_bot_center_z = -self.coupling_major; let bring_outside_top_small = Cube::new( @@ -1343,6 +1345,20 @@ fn drive_map_or_gate(amp0: f32, amp1: f32) -> [[ClockState; 4]; 4] { ] } + +#[allow(unused)] +fn drive_map_buf_53(amp0: f32, amp1: f32) -> [[ClockState; 4]; 2] { + use ClockState as C; + // amplitudes are inverted from what you would expect. + // hold(-1) puts the core into a positive M + [ + // init S1 pos, S2 pos; charge S0 neg, S3 neg + [C::release_high(), C::release(-amp0), C::release(-amp1), C::release_high()], + // clear S1 -> S0, S2 -> S3 + [C::float(), 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 { @@ -1487,6 +1503,7 @@ fn couple_asymmetric_buffer(params: &Params, sender: u32, loops: u32, slot_offse let slots_per_asym = 2*loops; // couple c to c+1 let c1 = c0+1; + // wires which actually connect c0 to c1 let mut params = params .with_coupling(c0, c1, slot_offset, net_slots, CouplingMethod::direct_half_exterior()) .with_coupling(c0, c1, slot_offset + slots_per_asym - 1, net_slots, CouplingMethod::direct_half_interior()) @@ -1514,6 +1531,63 @@ fn couple_asymmetric_buffer(params: &Params, sender: u32, loops: u32, slot_offse params } +fn couple_asymmetric_buffer_bi(params: &Params, c0: u32, c0_loops: u32, c1_loops: u32, slot_offset: u32, net_slots: u32) -> Params { + let slots_per_asym = 2*(c0_loops.max(c1_loops)); + // couple c to c+1 + let c1 = c0+1; + // wires which actually connect c0 to c1 + let mut params = params + .with_coupling(c0, c1, slot_offset, net_slots, CouplingMethod::direct_half_exterior()) + .with_coupling(c0, c1, slot_offset + slots_per_asym - 1, net_slots, CouplingMethod::direct_half_interior()) + ; + + // loops for sender c0 + for i in 0..slots_per_asym { + if i < 2*c0_loops { + if i % 2 == 0 { + // bring up + params = params.with_coupling(c0, c0, slot_offset + i, net_slots, CouplingMethod::SelfLoopHalfInterior); + // bring to next slot + params = params.with_coupling(c0, c0, slot_offset + i, net_slots, CouplingMethod::SelfAngularTop); + } else { + // bring down + params = params.with_coupling(c0, c0, slot_offset + i, net_slots, CouplingMethod::SelfLoopHalfExterior); + if i + 1 != slots_per_asym { + // bring to next slot -- if there is one + params = params.with_coupling(c0, c0, slot_offset + i, net_slots, CouplingMethod::SelfAngularBot); + } + } + } else if i + 1 != slots_per_asym { + // bring to next slot -- if there is one + params = params.with_coupling(c0, c0, slot_offset + i, net_slots, CouplingMethod::SelfAngularBot); + } + } + + // loops for receiver c1 + for i in 0..slots_per_asym { + if i < 2*c1_loops { + if i % 2 == 0 { + // bring down + params = params.with_coupling(c1, c1, slot_offset + i, net_slots, CouplingMethod::SelfLoopHalfInterior); + // bring to next slot + params = params.with_coupling(c1, c1, slot_offset + i, net_slots, CouplingMethod::SelfAngularBot); + } else { + // bring up + params = params.with_coupling(c1, c1, slot_offset + i, net_slots, CouplingMethod::SelfLoopHalfExterior); + if i + 1 != slots_per_asym { + // bring to next slot -- if there is one + params = params.with_coupling(c1, c1, slot_offset + i, net_slots, CouplingMethod::SelfAngularTop); + } + } + } else if i + 1 != slots_per_asym { + // bring to next slot -- if there is one + params = params.with_coupling(c1, c1, slot_offset + i, net_slots, CouplingMethod::SelfAngularTop); + } + } + + params +} + fn main() { coremem::init_logging(); // coremem::init_debug(); @@ -5680,7 +5754,7 @@ fn main() { } } - if true { + if false { for init_set in [ &[ // establish domain/range for M0 fixed at -1 @@ -5788,6 +5862,86 @@ fn main() { } } } + + if true { + for init_set in [ + &[ + // establish rough domain/range + (-1.00, 1.00), + (-1.00, -1.00), + ( 0.00, 0.00), + ( 0.20, -0.20), + ( 0.10, -0.10), + ][..], + &[ + // more detailed sweep + ( 0.30, -0.30), + ( 0.05, -0.05), + ( 0.15, -0.15), + ( 0.25, -0.25), + ][..], + &[ + // test some asymmetries -- specifically where A1 is higher than expected + ( 0.20, 0.00), + ( 0.20, -0.10), + ( 0.20, 0.10), + ( 0.30, 0.00), + ( 0.30, -0.20), + ( 0.30, -0.10), + ( 0.10, 0.00), + ][..], + ] { + for (ctl_cond, coupling_cond, clock_duration, clock_decay, coupling_loops, inp_loops, s_major, cur_flt) in [ + // total slot use count is L*(4*A + 1), + // where L is the "coupling loops" and A is the inp_loops ("asymmetric loops") + // e.g. L=8, A=1 gives 40 + (2e3, 2e4, ps(2000), ps(100), 8, 1, um(400), 3e10), + (2e3, 2e4, ps(2000), ps(100), 8, 1, um(400), 2e10), + ] { + for &(init_flt_a, init_flt_b) in init_set { + // each core is coupled to 2 others + control slots + // M1 <-> M2 is symmetric (inputs) + // M1 -> M0 & M2 -> M3 are asymmetric (tx input -> output) + // M0 <-> M3 is symmetrics (outputs) + let slots_per_asym = 2*inp_loops; + let net_slots = 2*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 output core 0 to core 3 + params = params.with_coupling(0, 3, 1+i, net_slots, CouplingMethod::Outside); + // couple input core 1 to core 2 + params = params.with_coupling(1, 2, 1+i, net_slots, CouplingMethod::Direct); + } + // couple input M1 -> output M0 + params = couple_asymmetric_buffer_bi(¶ms, 0 /* low core */, 0, inp_loops, 1 + slots_per_asym /* slot offset */, net_slots); + // couple input M2 -> output M3 + params = couple_asymmetric_buffer_bi(¶ms, 2 /* low core */, inp_loops, 0, 1 + slots_per_asym /* slot offset */, net_slots); + + let name = asymmetric_binary_gate_name( + ¶ms, "53-buf-", coupling_loops /* ctl loops */, coupling_loops, 2*inp_loops + 1, init_flt_a, init_flt_b + ); + run_sim( + &name, + drive_map_buf_53(init_flt_a, init_flt_b), + params, + ); + } + } + } + } }