app: stacked_cores: 60-xx: new experiment that tries moving a value along a 4-core loop
it does this in a non-complementary way; and it doesn't get more than about 0.60 amplification
This commit is contained in:
parent
e13ddbdc1f
commit
eccd865cf7
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from natsort import natsorted
|
||||
|
||||
from stacked_cores_52xx import *
|
||||
from stacked_cores_52xx_plotters import *
|
||||
|
||||
|
||||
def extract_60xx_tx(meas_rows: list) -> tuple:
|
||||
"""
|
||||
extracts a flat tuple of input/output M mappings from a 60xx run
|
||||
"""
|
||||
|
||||
return (
|
||||
meas_rows[0].m[0], # input
|
||||
meas_rows[1].m[2], # output
|
||||
# meas_rows[1].m[1], # intermediate
|
||||
# meas_rows[1].m[3], # intermediate
|
||||
)
|
||||
|
||||
|
||||
buf_gates = read_db(lambda name: name.startswith("60-"))
|
||||
|
||||
sweep_inv_input = lambda points=101: [(m, None) for m in sweep_1d(points)]
|
||||
|
||||
|
||||
for name, meas in natsorted(buf_gates.items()):
|
||||
trace = eval_series(meas, sweep_inv_input(41), extract_60xx_tx, y_idx=1)
|
||||
plot(f"{name}", "M", trace)
|
||||
plot_slope(f"slope {name}", "M", trace)
|
|
@ -11,7 +11,7 @@ from stacked_cores_52xx_db import DB
|
|||
## CONSTANTS/CONFIGURATION
|
||||
|
||||
# list of sims to extract details for
|
||||
PREFIXES = { "52", "53", "54", "55", "56", "57", "58", "59" }
|
||||
PREFIXES = { "52", "53", "54", "55", "56", "57", "58", "59", "60" }
|
||||
|
||||
def times_of_interest(sim_name: str) -> list:
|
||||
# could be more intelligent, extracting e.g. the clock duration from the name
|
||||
|
@ -33,6 +33,8 @@ def times_of_interest(sim_name: str) -> list:
|
|||
return [2e-9, 4e-9]
|
||||
if sim_name.startswith("59-buf-edge_input-"):
|
||||
return [4e-9, 6e-9]
|
||||
if sim_name.startswith("60-"):
|
||||
return [4e-9, 6e-9]
|
||||
|
||||
|
||||
## USER-FACING FUNCTIONS
|
||||
|
|
|
@ -3488,4 +3488,212 @@ DB = {
|
|||
MeasRow(4e-09, [ 5102, -29626, -29628, -10949]),
|
||||
],
|
||||
}),
|
||||
'60-inv-0.0004rad-2000ctl_cond-20000coupling_cond-2000ps-100ps-6coupling-1_1_3_1_winding-5e9-drive-': ParameterizedMeas({
|
||||
(-1.000,): [
|
||||
MeasRow(4e-09, [-17060, -17411, 16421, -16835]),
|
||||
MeasRow(6e-09, [-28790, -9371, 9324, -9708]),
|
||||
],
|
||||
(-0.300,): [
|
||||
MeasRow(4e-09, [-16782, -17297, 16486, -16857]),
|
||||
MeasRow(6e-09, [-28777, -9153, 9311, -9666]),
|
||||
],
|
||||
(-0.200,): [
|
||||
MeasRow(4e-09, [-12487, -16983, 16564, -16784]),
|
||||
MeasRow(6e-09, [-28768, -6700, 7575, -7804]),
|
||||
],
|
||||
(-0.100,): [
|
||||
MeasRow(4e-09, [ 1943, -16993, 16570, -16790]),
|
||||
MeasRow(6e-09, [-28767, 728, 1156, -1392]),
|
||||
],
|
||||
( 0.000,): [
|
||||
MeasRow(4e-09, [ 12707, -16959, 16644, -16804]),
|
||||
MeasRow(6e-09, [-28764, 5622, -2835, 2635]),
|
||||
],
|
||||
( 0.100,): [
|
||||
MeasRow(4e-09, [ 14452, -16908, 16735, -16810]),
|
||||
MeasRow(6e-09, [-28769, 6384, -3326, 3208]),
|
||||
],
|
||||
( 0.200,): [
|
||||
MeasRow(4e-09, [ 15334, -16882, 16779, -16815]),
|
||||
MeasRow(6e-09, [-28765, 6759, -3565, 3482]),
|
||||
],
|
||||
( 0.300,): [
|
||||
MeasRow(4e-09, [ 15871, -16865, 16808, -16821]),
|
||||
MeasRow(6e-09, [-28763, 6995, -3714, 3653]),
|
||||
],
|
||||
( 1.000,): [
|
||||
MeasRow(4e-09, [ 16848, -16837, 16846, -16846]),
|
||||
MeasRow(6e-09, [-28752, 7405, -3987, 3941]),
|
||||
],
|
||||
}),
|
||||
'60-inv-0.0004rad-2000ctl_cond-20000coupling_cond-2000ps-100ps-6coupling-3_1_1_1_winding-5e9-drive-': ParameterizedMeas({
|
||||
(-1.000,): [
|
||||
MeasRow(4e-09, [-19897, -19577, 16316, -17616]),
|
||||
MeasRow(6e-09, [-28895, -11361, 9590, -9866]),
|
||||
],
|
||||
(-0.300,): [
|
||||
MeasRow(4e-09, [-18753, -18946, 16391, -17423]),
|
||||
MeasRow(6e-09, [-28855, -9953, 9059, -9051]),
|
||||
],
|
||||
(-0.200,): [
|
||||
MeasRow(4e-09, [ -9981, -17654, 16175, -16906]),
|
||||
MeasRow(6e-09, [-28764, -2270, 4059, -3290]),
|
||||
],
|
||||
(-0.100,): [
|
||||
MeasRow(4e-09, [ 3502, -17663, 16185, -16917]),
|
||||
MeasRow(6e-09, [-28765, 7363, -2695, 4296]),
|
||||
],
|
||||
(-0.050,): [
|
||||
MeasRow(4e-09, [ 8439, -17547, 16297, -16911]),
|
||||
MeasRow(6e-09, [-28764, 10713, -4671, 6750]),
|
||||
],
|
||||
( 0.000,): [
|
||||
MeasRow(4e-09, [ 11342, -17361, 16462, -16898]),
|
||||
MeasRow(6e-09, [-28764, 12716, -5623, 8081]),
|
||||
],
|
||||
( 0.050,): [
|
||||
MeasRow(4e-09, [ 13669, -17160, 16624, -16882]),
|
||||
MeasRow(6e-09, [-28772, 14256, -6291, 9100]),
|
||||
],
|
||||
( 0.100,): [
|
||||
MeasRow(4e-09, [ 14653, -17063, 16695, -16874]),
|
||||
MeasRow(6e-09, [-28766, 14846, -6545, 9506]),
|
||||
],
|
||||
( 0.200,): [
|
||||
MeasRow(4e-09, [ 15443, -16990, 16747, -16869]),
|
||||
MeasRow(6e-09, [-28763, 15222, -6737, 9820]),
|
||||
],
|
||||
( 0.300,): [
|
||||
MeasRow(4e-09, [ 15880, -16951, 16774, -16866]),
|
||||
MeasRow(6e-09, [-28760, 15353, -6840, 9991]),
|
||||
],
|
||||
( 1.000,): [
|
||||
MeasRow(4e-09, [ 16860, -16843, 16834, -16857]),
|
||||
MeasRow(6e-09, [-28752, 15582, -7052, 10360]),
|
||||
],
|
||||
}),
|
||||
'60-inv-0.0004rad-2000ctl_cond-20000coupling_cond-2000ps-100ps-6coupling-3_1_3_1_winding-5e9-drive-': ParameterizedMeas({
|
||||
(-1.000,): [
|
||||
MeasRow(4e-09, [-19732, -19469, 16457, -17437]),
|
||||
MeasRow(6e-09, [-28893, -11232, 8909, -9545]),
|
||||
],
|
||||
(-0.300,): [
|
||||
MeasRow(4e-09, [-18578, -18889, 16463, -17285]),
|
||||
MeasRow(6e-09, [-28859, -9891, 8264, -8751]),
|
||||
],
|
||||
(-0.250,): [
|
||||
MeasRow(4e-09, [-16089, -17936, 16321, -16947]),
|
||||
MeasRow(6e-09, [-28809, -7290, 6693, -6974]),
|
||||
],
|
||||
(-0.200,): [
|
||||
MeasRow(4e-09, [ -9962, -17729, 16234, -16843]),
|
||||
MeasRow(6e-09, [-28763, -2636, 2763, -2991]),
|
||||
],
|
||||
(-0.150,): [
|
||||
MeasRow(4e-09, [ -3230, -17728, 16239, -16847]),
|
||||
MeasRow(6e-09, [-28763, 2034, -1202, 1028]),
|
||||
],
|
||||
(-0.100,): [
|
||||
MeasRow(4e-09, [ 3493, -17732, 16249, -16854]),
|
||||
MeasRow(6e-09, [-28764, 6447, -4842, 4721]),
|
||||
],
|
||||
(-0.050,): [
|
||||
MeasRow(4e-09, [ 8219, -17583, 16359, -16856]),
|
||||
MeasRow(6e-09, [-28764, 9484, -7059, 7098]),
|
||||
],
|
||||
( 0.000,): [
|
||||
MeasRow(4e-09, [ 11174, -17372, 16511, -16852]),
|
||||
MeasRow(6e-09, [-28762, 11392, -8242, 8474]),
|
||||
],
|
||||
( 0.050,): [
|
||||
MeasRow(4e-09, [ 13562, -17141, 16670, -16842]),
|
||||
MeasRow(6e-09, [-28772, 12924, -9084, 9511]),
|
||||
],
|
||||
( 0.100,): [
|
||||
MeasRow(4e-09, [ 14572, -17033, 16742, -16839]),
|
||||
MeasRow(6e-09, [-28764, 13545, -9410, 9927]),
|
||||
],
|
||||
( 0.150,): [
|
||||
MeasRow(4e-09, [ 15032, -16990, 16770, -16840]),
|
||||
MeasRow(6e-09, [-28763, 13815, -9555, 10107]),
|
||||
],
|
||||
( 0.200,): [
|
||||
MeasRow(4e-09, [ 15384, -16958, 16792, -16842]),
|
||||
MeasRow(6e-09, [-28762, 14013, -9663, 10240]),
|
||||
],
|
||||
( 0.250,): [
|
||||
MeasRow(4e-09, [ 15638, -16937, 16807, -16844]),
|
||||
MeasRow(6e-09, [-28761, 14153, -9743, 10336]),
|
||||
],
|
||||
( 0.300,): [
|
||||
MeasRow(4e-09, [ 15835, -16922, 16817, -16846]),
|
||||
MeasRow(6e-09, [-28760, 14258, -9805, 10408]),
|
||||
],
|
||||
( 1.000,): [
|
||||
MeasRow(4e-09, [ 16858, -16849, 16850, -16856]),
|
||||
MeasRow(6e-09, [-28753, 14774, -10128, 10772]),
|
||||
],
|
||||
}),
|
||||
'60-inv-0.0004rad-2000ctl_cond-20000coupling_cond-2000ps-100ps-8coupling-2_1_2_1_winding-5e9-drive-': ParameterizedMeas({
|
||||
(-1.000,): [
|
||||
MeasRow(4e-09, [-19461, -19286, 16436, -17402]),
|
||||
MeasRow(6e-09, [-29671, -10410, 8545, -9195]),
|
||||
],
|
||||
(-0.300,): [
|
||||
MeasRow(4e-09, [-19131, -19093, 16451, -17367]),
|
||||
MeasRow(6e-09, [-29663, -10010, 8380, -8983]),
|
||||
],
|
||||
(-0.250,): [
|
||||
MeasRow(4e-09, [-18817, -18946, 16459, -17329]),
|
||||
MeasRow(6e-09, [-29661, -9671, 8215, -8771]),
|
||||
],
|
||||
(-0.200,): [
|
||||
MeasRow(4e-09, [-16478, -17983, 16407, -17025]),
|
||||
MeasRow(6e-09, [-29658, -7241, 6850, -7130]),
|
||||
],
|
||||
(-0.150,): [
|
||||
MeasRow(4e-09, [ -8997, -17635, 16283, -16862]),
|
||||
MeasRow(6e-09, [-29645, -1566, 2150, -2326]),
|
||||
],
|
||||
(-0.100,): [
|
||||
MeasRow(4e-09, [ -343, -17642, 16287, -16867]),
|
||||
MeasRow(6e-09, [-29646, 4488, -2971, 2874]),
|
||||
],
|
||||
(-0.050,): [
|
||||
MeasRow(4e-09, [ 7227, -17595, 16333, -16872]),
|
||||
MeasRow(6e-09, [-29645, 9590, -7083, 7103]),
|
||||
],
|
||||
( 0.000,): [
|
||||
MeasRow(4e-09, [ 11105, -17368, 16509, -16867]),
|
||||
MeasRow(6e-09, [-29644, 12253, -8907, 9164]),
|
||||
],
|
||||
( 0.050,): [
|
||||
MeasRow(4e-09, [ 13785, -17127, 16688, -16854]),
|
||||
MeasRow(6e-09, [-29653, 14087, -10054, 10523]),
|
||||
],
|
||||
( 0.100,): [
|
||||
MeasRow(4e-09, [ 14562, -17051, 16741, -16850]),
|
||||
MeasRow(6e-09, [-29647, 14598, -10365, 10899]),
|
||||
],
|
||||
( 0.150,): [
|
||||
MeasRow(4e-09, [ 15048, -17005, 16773, -16849]),
|
||||
MeasRow(6e-09, [-29645, 14879, -10559, 11133]),
|
||||
],
|
||||
( 0.200,): [
|
||||
MeasRow(4e-09, [ 15383, -16974, 16794, -16848]),
|
||||
MeasRow(6e-09, [-29644, 15040, -10693, 11293]),
|
||||
],
|
||||
( 0.250,): [
|
||||
MeasRow(4e-09, [ 15636, -16951, 16808, -16849]),
|
||||
MeasRow(6e-09, [-29643, 15134, -10794, 11412]),
|
||||
],
|
||||
( 0.300,): [
|
||||
MeasRow(4e-09, [ 15833, -16935, 16818, -16850]),
|
||||
MeasRow(6e-09, [-29642, 15200, -10874, 11504]),
|
||||
],
|
||||
( 1.000,): [
|
||||
MeasRow(4e-09, [ 16859, -16848, 16849, -16857]),
|
||||
MeasRow(6e-09, [-29635, 15487, -11297, 11974]),
|
||||
],
|
||||
}),
|
||||
}
|
|
@ -195,10 +195,10 @@ impl Params {
|
|||
assert!(self.hardcoded_control_and_sense);
|
||||
Torus::new_xz(Meters::new(self.sx() - self.s_major, self.sy(), self.sz(n)), self.io_major, self.io_minor)
|
||||
}
|
||||
/// the last core gets an external output in place of its coupling loop
|
||||
fn sense(&self, n: u32) -> Torus {
|
||||
Torus::new_xz(Meters::new(self.sx() + self.s_major, self.sy(), self.sz(n)), self.io_major, self.io_minor)
|
||||
}
|
||||
// the last core gets an external output in place of its coupling loop
|
||||
// fn sense(&self, n: u32) -> Torus {
|
||||
// Torus::new_xz(Meters::new(self.sx() + self.s_major, self.sy(), self.sz(n)), self.io_major, self.io_minor)
|
||||
// }
|
||||
fn s(&self, n: u32) -> Torus {
|
||||
Torus::new_xy(Meters::new(self.sx(), self.sy(), self.sz(n)), self.s_major, self.s_minor)
|
||||
}
|
||||
|
@ -1459,6 +1459,20 @@ fn drive_map_buf_58(amp0: f32, amp1: f32) -> [[ClockState; 6]; 3] {
|
|||
]
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
fn drive_map_quad_loop_60(amp: f32) -> [[ClockState; 4]; 3] {
|
||||
use ClockState as C;
|
||||
// amplitudes are inverted from what you would expect.
|
||||
// hold(-1) puts the core into a positive M
|
||||
[
|
||||
// init S0 pos; charge S1 neg, S3 neg, S2 pos
|
||||
[C::hold(-amp), C::hold_high(), C::hold_low(), C::hold_high(), ],
|
||||
[C::release(-amp), C::release_high(), C::release_low(), C::release_high(),],
|
||||
// clear (S0 -> S1, S3) -> S2
|
||||
[C::hold_high(), C::float(), C::float(), 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 {
|
||||
|
@ -1536,6 +1550,21 @@ fn asymmetric_inverter_name_v3(p: &Params, sim_id: &str, ctl_loops: u32, couplin
|
|||
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}")
|
||||
}
|
||||
|
||||
/// v4 has separate windings_a and windings_b
|
||||
/// and we drop ctl_loops
|
||||
fn asymmetric_inverter_name_v4(p: &Params, sim_id: &str, coupling_loops: u32, windings_a: u32, windings_b: 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;
|
||||
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-{coupling_loops}coupling-{windings_a}_1_{windings_b}_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);
|
||||
|
@ -6752,7 +6781,7 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
if true {
|
||||
if false {
|
||||
for init_set in [
|
||||
&[
|
||||
// establish rough domain/range
|
||||
|
@ -6888,6 +6917,144 @@ fn main() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if true {
|
||||
for init_set in [
|
||||
&[
|
||||
// establish rough domain/range
|
||||
1.00,
|
||||
-1.00,
|
||||
][..],
|
||||
&[
|
||||
0.00,
|
||||
0.30,
|
||||
-0.30,
|
||||
0.20,
|
||||
-0.20,
|
||||
0.10,
|
||||
-0.10,
|
||||
][..],
|
||||
&[
|
||||
// more detailed sweep
|
||||
0.05,
|
||||
-0.05,
|
||||
0.15,
|
||||
-0.15,
|
||||
0.25,
|
||||
-0.25,
|
||||
][..],
|
||||
&[
|
||||
// even more verbosity
|
||||
0.02,
|
||||
-0.02,
|
||||
0.07,
|
||||
-0.07,
|
||||
0.12,
|
||||
-0.12,
|
||||
0.17,
|
||||
-0.17,
|
||||
0.22,
|
||||
-0.22,
|
||||
][..],
|
||||
&[
|
||||
0.01,
|
||||
-0.01,
|
||||
0.03,
|
||||
-0.03,
|
||||
0.04,
|
||||
-0.04,
|
||||
0.06,
|
||||
-0.06,
|
||||
0.08,
|
||||
-0.08,
|
||||
0.13,
|
||||
-0.13,
|
||||
0.18,
|
||||
-0.18,
|
||||
0.23,
|
||||
-0.23,
|
||||
][..],
|
||||
] {
|
||||
for (ctl_cond, coupling_cond, clock_duration, clock_decay, coupling_loops, inp_loops, out_loops, s_major, cur_flt) in [
|
||||
// total slot use is L*(2*max(inp_loops, out_loops) + 1),
|
||||
// where L is the "coupling loops" (control loops)
|
||||
// e.g. L=13, inp=1, out=1 gives 39
|
||||
// e.g. L=8, inp<=2, out<=2 gives 40
|
||||
// e.g. L=6, inp<=3, out<=3 gives 42
|
||||
// e.g. L=4, inp<=4, out<=4 gives 36
|
||||
// e.g. L=3, inp<=6, out<=6 gives 39
|
||||
|
||||
// (2e3, 2e4, ps(2000), ps(100), 3, 6, 1, um(400), 5e9),
|
||||
// (2e3, 2e4, ps(2000), ps(100), 13, 1, 1, um(400), 5e9),
|
||||
|
||||
// maps to [7700, -11900]
|
||||
// slope: -0.63 peak
|
||||
(2e3, 2e4, ps(2000), ps(100), 8, 2, 2, um(400), 5e9),
|
||||
// maps to [7900, -10700]
|
||||
// slope: -0.64 peak
|
||||
(2e3, 2e4, ps(2000), ps(100), 6, 3, 3, um(400), 5e9),
|
||||
// maps to [8600, -7500]
|
||||
// slope: -0.57 peak
|
||||
(2e3, 2e4, ps(2000), ps(100), 6, 3, 1, um(400), 5e9),
|
||||
// maps to [9700, -4400]
|
||||
// slope: -0.44 peak
|
||||
(2e3, 2e4, ps(2000), ps(100), 6, 1, 3, um(400), 5e9),
|
||||
] {
|
||||
for &init_flt in init_set {
|
||||
// ideal layout... but this would require 3 slots
|
||||
// /--------\
|
||||
// M0 -> M1 M2 -> M3
|
||||
// \---------/
|
||||
//
|
||||
// actual layout: 2 slots
|
||||
// M0 -> M1 -> M2 <- M3
|
||||
// \-------->-------/
|
||||
let slot_group_size = inp_loops.max(out_loops);
|
||||
let net_slots = 2*slot_group_size + 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..inp_loops {
|
||||
// couple input M0 -> M1
|
||||
params = params.with_coupling(0, 1, 1+i, net_slots, CouplingMethod::Direct);
|
||||
// couple input M0 -> M3
|
||||
params = params.with_coupling(0, 3, 1+slot_group_size+i, net_slots, CouplingMethod::Outside);
|
||||
}
|
||||
for i in 0..out_loops {
|
||||
// couple intermediary M1 -> M2
|
||||
params = params.with_coupling(1, 2, 1+slot_group_size+i, net_slots, CouplingMethod::Direct);
|
||||
// couple intermediary M3 -> M2
|
||||
params = params.with_coupling(3, 2, 1+i, net_slots, CouplingMethod::Direct);
|
||||
}
|
||||
|
||||
let name = asymmetric_inverter_name_v4(
|
||||
¶ms,
|
||||
"60-inv",
|
||||
coupling_loops,
|
||||
inp_loops,
|
||||
out_loops,
|
||||
init_flt,
|
||||
);
|
||||
run_sim(
|
||||
&name,
|
||||
drive_map_quad_loop_60(init_flt),
|
||||
params,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue