def characterize(args, adcs, seed): with misc.push_random_state(): np.random.seed(seed) seeds = [np.random.randint(0, 4294967296) for _ in range(3)] assert not args.relative_snr_ref, "TODO implement relative" assert not args.relative_snr_thres, "TODO implement relative" min_snr_ref_v = args.min_snr_ref_v min_snr_thres_v = args.min_snr_thres_v fsr = adcs[0].stages[0].meta.fsr n_bits = int(np.sum([np.floor(stage.meta.n_bits) for stage in adcs[0].stages])) n_bits += int(gen.infer_thres_bits(adcs[0].tail)[0]) lsb = gen.compute_lsb(n_bits, *fsr) if min_snr_ref_v is None: min_snr_ref_v = lsb/2 if min_snr_thres_v is None: min_snr_thres_v = lsb/2 snr_ref_inv = np.linspace(0, min_snr_ref_v, args.samples_snr_ref) snr_thres_inv = np.linspace(0, min_snr_thres_v, args.samples_snr_thres) snr_ref = np.power((fsr[1] - fsr[0]), 2)/np.power(snr_ref_inv, 2) snr_thres = np.power((fsr[1] - fsr[0]), 2)/np.power(snr_thres_inv, 2) snr_ref[0] = 0 snr_thres[0] = 0 real_thres_s = data.at_least_ndarray(args.real_thres_s) shape = (np.size(real_thres_s), np.size(adcs),) adcs_sweep = np.tile(np.array(adcs, dtype=object), shape[:-1] + (1,)) # Sweep thres with misc.push_random_state(): np.random.seed(seed) for idx in cartesian(*tuple(range(s) for s in shape)): r_thres_s = real_thres_s[idx[0]] adcs_sweep[idx] = copy.deepcopy(adcs_sweep[idx]) for stage in adcs_sweep[idx].stages: r_thres_s_local = r_thres_s * stage.meta.lsb stage._thres = np.random.normal(stage.thres, r_thres_s_local) adcs_sweep[idx]._tail = np.random.normal(adcs_sweep[idx].tail, r_thres_s) uncertain = characterize_uncertanty(args, adcs_sweep, seed, real_thres_s) ref = characterize_noise(args, adcs_sweep, seed, snr_ref, real_thres_s, ref=True) thres = characterize_noise(args, adcs_sweep, seed, snr_thres, real_thres_s, ref=False) return uncertain, ref, thres
def system(self, x, scalar=False, use_bands=None, sum_conf=None, limit_samples=None, lsb_scale=1): if scalar: x = [x] cm, eff, caps, refs, thres, ins = self._map_internal(x) ext_codes = self._codes[:, np.newaxis, ...] if not hasattr(self, "_cache"): self._cache = {} base_shape = np.shape(x)[:-1] if base_shape not in self._cache: print("Generating cache for {}".format(base_shape)) self._cache[base_shape] = self.recreate_cache( eff, caps, refs, thres, ins, cm, self._configuration_sequence, ext_codes) use_bands = default(use_bands, self.use_bands) sum_conf = default(sum_conf, self.sum_conf) ext_codes = self._codes[:, np.newaxis, ...] u = self.recreate(eff, caps, refs, thres, ins, cm, self._configuration_sequence, self._cache[base_shape], limit_samples=limit_samples) meta = self._configuration_sequence.meta # Ignore last u since it is not converted to code u = np.diff(u[:-1, :, ...], axis=-1) if meta.differential else u[:-1, :, ..., -1] samples = np.size(u, 0) u_center, lsb = self._compute_u_center(thres) thres_bits, thres_half = gen.infer_thres_bits(thres[0, ...]) ideal_lsb = gen.compute_lsb(thres_bits, *self._start.meta.fsr, thres_half) lsb = lsb + ideal_lsb * (lsb_scale - 1) if use_bands else np.zeros(( samples, 1, 1, )) result = np.maximum( np.abs(u - u_center[:samples, ...]) - lsb[:samples, ...] / 2, 0) if DEBUG: # FIXME import matplotlib.pyplot as plots try: print(np.shape(result)) sum_axis = tuple(range(len(np.shape(result)) - 1)) cut = (np.sum(result, axis=sum_axis) > 0).tolist().index(True) print("Found cut {}".format(cut)) except: cut = 10 print("Not found cut") x_thres = np.stack(( np.zeros_like(thres[0, :]), np.full_like(thres[0, :], samples), ), axis=0) y_thres = np.stack((thres[0, :], ) * 2, axis=0) plots.plot(x_thres, y_thres, c='orange', linestyle='-.') plots.plot(u[:, 0, cut, ...], 'r') internal, _ = self.configuration_sequence.configuration_sets[ 0].generate_in(self.configuration_sequence. configuration_sets[0].ds_samples) internal = np.sum(internal, axis=( -2, -1, )) plots.plot(0.25 * (internal[:, cut, ...] - 1.5), 'cyan') #plots.plot(internal[:samples, cut, ...], 'k') adj_codes = (0.5 / (np.max(self._codes))) * (self._codes - np.max(self._codes) / 2) plots.plot(adj_codes[:samples, cut, ...], 'k') plots.plot(u_center[:samples, 0, cut, ...], 'b') plots.plot(u_center[:samples, 0, cut, ...] + lsb[:samples, 0, cut, ...] / 2, 'g', linestyle='--') plots.plot(u_center[:samples, 0, cut, ...] - lsb[:samples, 0, cut, ...] / 2, 'g', linestyle='--') plots.show() if scalar: result = result[:, 0, ...] else: result = np.transpose(result, ( 1, 0, ) + tuple(range(2, len(np.shape(result))))) sum_axis = ( -2, -1, ) if sum_conf else (-2, ) result = np.sum(result, axis=sum_axis) if PRINT_ERROR: print("System error: {}".format(np.sum(np.power(result, 2)))) return result
def run(args): assert len(args.bits) == len(args.seed) directory = args.location mkdir(misc.Namespace(directory=directory, mode="750")) path_context = data.PathContext.relative() names = [ "paper_set_{}{}".format(ii, "_DRY" if DRY_RUN else "") for ii in range(len(args.bits)) ] if not JUST_PLOT: for ii, bits, seed, name in zip(count(), args.bits, args.seed, names): print("SET {}/{}".format(ii + 1, len(args.bits))) adcs = gen_adc(bits, seed, args, args.n_adcs) uncertain, ref, thres = characterize(args, adcs, seed) if 0 in TESTS: uncertain = prepickle_data(uncertain, path_context, directory, "{}.{}".format(name, "uncertain")) else: uncertain = None if 1 in TESTS: ref = prepickle_data(ref, path_context, directory, "{}.{}".format(name, "ref")) else: ref = None if 2 in TESTS: thres = prepickle_data(thres, path_context, directory, "{}.{}".format(name, "thres")) else: thres = None with open(name, 'wb') as f: pickle.dump(( uncertain, ref, thres, ), f, protocol=pickle.HIGHEST_PROTOCOL) for name in names: with open(name, 'rb') as f: dat = pickle.load(f) uncertain, ref, thres = dat uncertain = postpickle_data(uncertain, path_context) ref = postpickle_data(ref, path_context) thres = postpickle_data(thres, path_context) dat = ( uncertain, ref, thres, ) real_thres_s = data.at_least_ndarray(args.real_thres_s) sample_adc = dat[TESTS[0]][0][0, 0, 0] fsr = sample_adc.stages[0].meta.fsr n_bits = int( np.sum([ np.floor(stage.meta.n_bits) for stage in sample_adc.stages ])) n_bits += int(gen.infer_thres_bits(sample_adc.tail)[0]) lsb = gen.compute_lsb(n_bits, *fsr) min_snr_ref_v = args.min_snr_ref_v min_snr_thres_v = args.min_snr_thres_v if min_snr_ref_v is None: min_snr_ref_v = lsb / 2 if min_snr_thres_v is None: min_snr_thres_v = lsb / 2 snr_ref_inv = np.linspace(0, min_snr_ref_v, args.samples_snr_ref) snr_thres_inv = np.linspace(0, min_snr_thres_v, args.samples_snr_thres) u_args = ( "{}.uncertain".format(name), uncertain, ( "Real threshold voltage standard deviation (LSB)", "Modeled std (LSB)", ), ) u_kwargs = {"x_axes": real_thres_s, "y_axes": real_thres_s} t_args = ( "{}.thres".format(name), thres, ( "Real threshold voltage standard deviation (LSB)", "Thres. noise (SNR)", ), ) t_kwargs = { "x_axes": real_thres_s, "y_axes": snr_thres_inv, "noise": True } r_args = ( "{}.ref".format(name), ref, ( "Real threshold voltage standard deviation (LSB)", "Ref. noise (SNR)", ), ) r_kwargs = { "x_axes": real_thres_s, "y_axes": snr_ref_inv, "noise": True } if TOGETHER: f = plots.figure(figsize=( 10, 4, ) if FULL_SIZE else ( 5 * 1.5, 2 * 1.5, )) ax = f.add_subplot(111) h0 = [] h1 = [] h2 = [] brightness = 1 if 0 in TESTS: f, ax, h0 = plot2d(*u_args, **u_kwargs, ax=ax, color=(brightness, 0, 0), first_black=True, index=0, legend_handlers=h0, hide_constants=False) h0 = reversed(h0) if 2 in TESTS: f, ax, h2 = plot2d(*t_args, **t_kwargs, ax=ax, color=(0, 0, brightness), first_black=None, index=2, legend_handlers=h2) h2 = reversed(h2) if 1 in TESTS: f, ax, h1 = plot2d(*r_args, **r_kwargs, ax=ax, color=(0, brightness, 0), first_black=None, index=1, legend_handlers=h1) h1 = reversed(h1) h = [] for hh in (h0, h1, h2): h.extend(hh) proportion = 0.65 box = ax.get_position() ax.set_position( [box.x0, box.y0, box.width * proportion, box.height]) ax.set_facecolor((0.85, ) * 3) legend_handlers = h paths, names = tuple(zip(*legend_handlers)) f.legend(paths, names, loc='center left', bbox_to_anchor=(proportion, 0.5)) prev = mpl.rcParams['hatch.linewidth'] mpl.rcParams['hatch.linewidth'] = 5.0 f.savefig("{}.png".format(name), dpi=300) plots.show() mpl.rcParams['hatch.linewidth'] = prev else: if 0 in TESTS: plot2d(*u_args, **u_kwargs, color=(0.8, 0, 1), hide_constants=False) if 1 in TESTS: plot2d(*r_args, **r_kwargs, color=(0.8, 0, 1), hide_constants=False) if 2 in TESTS: plot2d(*t_args, **t_kwargs, color=(0.8, 0, 1), hide_constants=False) print("DONE")
def bits_to_required_eff(n_bits, half_bit=None, lsb_req=0.5): lsb = gen.compute_lsb(n_bits, 0, 1, half_bit=half_bit) eff = 1 - lsb * lsb_req return eff
# Generation args args.bits = [[3.5, 3.5, 2.5, 4]] # args.bits = [4.5, 3.5, 3.5, 4] args.seed = [486582] args.s_cap = 0.0025 args.s_ref = None # Characterization args args.real_thres_s = np.linspace(0, 0.5 / 3, SAMPLES) # In lsb args.confidence = 0.95 args.n_adcs = N_FOR_STD args.min_snr_ref_v = gen.compute_lsb(8, 0, 1) / 2 args.min_snr_thres_v = gen.compute_lsb(8, 0, 1) / 2 args.samples_snr_ref = SAMPLES_REF args.samples_snr_thres = SAMPLES_THRES args.relative_snr_ref = False args.relative_snr_thres = False # Configuration args args.samples = [64] args.inputs = "random" args.ic = "precharge" args.full = False args.loop = 1