def gen_model(myfunc, order=0, numel=512, real_type=RealType.FixedPoint, func_mode='sync'): # create mixed-signal model model = MixedSignalModel('model', build_dir=BUILD_DIR, real_type=real_type) model.add_analog_input('in_') model.add_analog_output('out') model.add_digital_input('clk') model.add_digital_input('rst') # create function write_tables = (func_mode in {'sync'}) real_func = model.make_function(myfunc, domain=[-DOMAIN, +DOMAIN], order=order, numel=numel, write_tables=write_tables) # apply function model.set_from_func(model.out, real_func, model.in_, clk=model.clk, rst=model.rst, func_mode=func_mode) # write the model return model.compile_to_file(VerilogGenerator())
def gen_model(real_type): # create mixed-signal model model = MixedSignalModel('model', build_dir=BUILD_DIR, real_type=real_type) model.add_digital_input('in_', width=N_BITS) model.add_analog_output('out') model.add_digital_input('clk') model.add_digital_input('rst') # create function domain = [map_f(0), map_f((1 << N_BITS) - 1)] real_func = model.make_function( lambda x: inv_cdf(unmap_f(x) / (1 << (N_BITS + 1))), domain=domain, order=1, numel=512) # apply function mapped = compress_uint(model.in_) model.set_from_sync_func(model.out, real_func, mapped, clk=model.clk, rst=model.rst) # write the model return model.compile_to_file(VerilogGenerator())
def gen_model(mean=0.0, std=1.0, num_sigma=6.0, order=1, numel=512, real_type=RealType.FixedPoint): # create mixed-signal model model = MixedSignalModel('model', build_dir=BUILD_DIR, real_type=real_type) model.add_digital_input('clk') model.add_digital_input('rst') model.add_analog_output('real_out') # compute the inverse CDF of the distribution (truncated to 0, 1 domain) inv_cdf = lambda x: truncnorm.ppf( x, -num_sigma, +num_sigma, loc=mean, scale=std) # create the function object inv_cdf_func = model.make_function(inv_cdf, domain=[0.0, 1.0], order=order, numel=numel) model.set_this_cycle( model.real_out, model.arbitrary_noise(inv_cdf_func, clk=model.clk, rst=model.rst)) # write the model return model.compile_to_file(VerilogGenerator())
def gen_model(cap=0.16e-6, ind=0.16e-6, res=0.1, dt=0.01e-6, real_type=RealType.FixedPoint): # declare model m = MixedSignalModel('model', dt=dt, real_type=real_type) m.add_analog_input('v_in') m.add_analog_output('v_out') m.add_digital_input('clk') m.add_digital_input('rst') # declare system of equations m.add_analog_state('i_ind', 10) # TODO: can this be tightened down a bit? v_l = AnalogSignal('v_l') v_r = AnalogSignal('v_r') eqns = [ Deriv(m.i_ind) == v_l / ind, Deriv(m.v_out) == m.i_ind / cap, v_r == m.i_ind * res, m.v_in == m.v_out + v_l + v_r ] m.add_eqn_sys(eqns, clk=m.clk, rst=m.rst) BUILD_DIR.mkdir(parents=True, exist_ok=True) model_file = BUILD_DIR / 'model.sv' m.compile_to_file(VerilogGenerator(), filename=model_file) return model_file
def gen_model(real_type): # declare module m = MixedSignalModel('model', real_type=real_type) m.add_digital_input('clk') m.add_digital_input('rst') m.add_analog_output('g') # bind expression to internal signal m.add_digital_param('param_a') m.add_digital_param('param_b') m.add_digital_param('param_c', width=2, signed=True) m.add_digital_param('param_d', width=2, signed=True) m.add_real_param('param_e') m.add_real_param('param_f') # create state signals m.add_digital_state('sig1', init=m.param_a) m.add_digital_state('sig2', init=m.param_c, width=2, signed=True) m.add_analog_state('sig3', init=m.param_e, range_=25) # create main logic m.set_next_cycle(m.sig1, m.param_b, clk=m.clk, rst=m.rst) m.set_next_cycle(m.sig2, m.param_d, clk=m.clk, rst=m.rst) m.set_next_cycle(m.sig3, m.param_f, clk=m.clk, rst=m.rst) # sum signals to output m.set_this_cycle(m.g, m.sig1 + m.sig2 + m.sig3) # compile to a file BUILD_DIR.mkdir(parents=True, exist_ok=True) model_file = BUILD_DIR / 'model.sv' m.compile_to_file(VerilogGenerator(), filename=model_file) # return file location return model_file
def gen_model(tau, real_type): # create mixed-signal model m = MixedSignalModel('model', build_dir=BUILD_DIR, real_type=real_type) # define I/O x = m.add_analog_input('x') dt = m.add_analog_input('dt') y = m.add_analog_output('y') clk = m.add_digital_input('clk') rst = m.add_digital_input('rst') # create function func = m.make_function(lambda t: np.exp(-t / tau), domain=[0, 1e-6], order=1) # apply function f = m.set_from_sync_func('f', func, dt, clk=clk, rst=rst) # update output x_prev = m.cycle_delay(x, 1, clk=clk, rst=rst) y_prev = m.cycle_delay(y, 1, clk=clk, rst=rst) m.set_this_cycle(y, f * y_prev + (1 - f) * x_prev) # write the model return m.compile_to_file(VerilogGenerator())
def main(num=(1e12, ), den=( 1, 8e5, 1e12, )): print('Running model generator...') # parse command line arguments parser = ArgumentParser() parser.add_argument('-o', '--output', type=str) parser.add_argument('--dt', type=float) args = parser.parse_args() # create the model model = MixedSignalModel('filter', AnalogInput('v_in'), AnalogOutput('v_out'), dt=args.dt) model.set_tf(input_=model.v_in, output=model.v_out, tf=(num, den)) # determine the output filename filename = os.path.join(get_full_path(args.output), f'{model.module_name}.sv') print('Model will be written to: ' + filename) # generate the model model.compile_to_file(VerilogGenerator(), filename)
def main(tau=1e-6): print('Running model generator...') # parse command line arguments parser = ArgumentParser() parser.add_argument('-o', '--output', type=str) parser.add_argument('--dt', type=float) args = parser.parse_args() # create the model m = MixedSignalModel('filter', dt=args.dt) m.add_analog_input('v_in') m.add_analog_output('v_out') c = m.make_circuit() gnd = c.make_ground() c.voltage('net_v_in', gnd, m.v_in) c.diode('net_v_in', 'net_v_x', vf=0) c.resistor('net_v_x', 'net_v_out', 1e3) v_out = c.capacitor('net_v_out', gnd, 1e-9, voltage_range=1.5) m.set_this_cycle(m.v_out, v_out) # determine the output filename filename = os.path.join(get_full_path(args.output), f'{m.module_name}.sv') print('Model will be written to: ' + filename) # generate the model m.compile_to_file(VerilogGenerator(), filename)
def gen_model(r_off=2.6e3, current_range=100, real_type=RealType.FixedPoint): # declare model m = MixedSignalModel('model', dt=1e-9, real_type=real_type) m.add_analog_input('v_in') m.add_analog_output('v_out') m.add_digital_input('sw1') m.add_digital_input('sw2') m.add_digital_input('clk') m.add_digital_input('rst') # create test circuit c = m.make_circuit(clk=m.clk, rst=m.rst) gnd = c.make_ground() c.voltage('net_v_in', gnd, m.v_in) c.switch('net_v_in', 'net_v_x', m.sw1, r_off=r_off) c.switch('net_v_x', gnd, m.sw2, r_off=r_off) c.inductor('net_v_in', 'net_v_x', 1.0, current_range=current_range) c.add_eqns(AnalogSignal('net_v_x') == m.v_out) # compile to a file BUILD_DIR.mkdir(parents=True, exist_ok=True) model_file = BUILD_DIR / 'model.sv' m.compile_to_file(VerilogGenerator(), filename=model_file) # return file location return model_file
def gen_model(rp1, rn1, rp2, rn2, real_type, dt=0.1e-6): # declare model m = MixedSignalModel('model', dt=dt, real_type=real_type) # declare I/O m.add_analog_input('v_in') m.add_analog_output('v_out') m.add_digital_input('sw1') m.add_digital_input('sw2') # declare switch circuit c = m.make_circuit() gnd = c.make_ground() c.voltage('net_v_in', gnd, m.v_in) c.switch('net_v_in', 'net_v_x', m.sw1, r_on=rp1, r_off=rn1) c.switch('net_v_x', gnd, m.sw2, r_on=rp2, r_off=rn2) c.add_eqns(AnalogSignal('net_v_x') == m.v_out) # compile to a file BUILD_DIR.mkdir(parents=True, exist_ok=True) model_file = BUILD_DIR / 'model.sv' m.compile_to_file(VerilogGenerator(), filename=model_file) # return file location return model_file
def gen_model(real_vals, sint_vals, uint_vals, addr_bits, sint_bits, uint_bits, real_type): # create mixed-signal model model = MixedSignalModel('model', build_dir=BUILD_DIR, real_type=real_type) model.add_digital_input('addr', width=addr_bits) model.add_digital_input('clk') model.add_analog_output('real_out') model.add_digital_output('sint_out', width=sint_bits) model.add_digital_output('uint_out', width=uint_bits) # create tables real_table = model.make_real_table(real_vals) sint_table = model.make_sint_table(sint_vals) uint_table = model.make_uint_table(uint_vals) # assign values model.set_from_sync_rom(model.real_out, real_table, model.addr, clk=model.clk) model.set_from_sync_rom(model.sint_out, sint_table, model.addr, clk=model.clk) model.set_from_sync_rom(model.uint_out, uint_table, model.addr, clk=model.clk) # write the model return model.compile_to_file(VerilogGenerator())
def main(): model = MixedSignalModel('model') model.add_analog_input('a') model.add_analog_input('b') model.bind_name('c', model.a + model.b) model.compile_and_print(VerilogGenerator())
def __init__(self, filename=None, **system_values): # set a fixed random seed for repeatability np.random.seed(2) module_name = Path(filename).stem build_dir = Path(filename).parent print(f'Running model generator for {module_name}...') assert (all([req_val in system_values for req_val in self.required_values()])), \ f'Cannot build {module_name}, Missing parameter in config file' m = MixedSignalModel(module_name, dt=system_values['dt'], build_dir=build_dir, real_type=get_dragonphy_real_type()) m.add_real_param('t_del', 0) m.add_digital_input('emu_rst') m.add_digital_input('emu_clk') m.add_analog_input('t_lo') m.add_analog_input('t_hi') m.add_analog_input('emu_dt') m.add_analog_output('dt_req', init=m.t_del) m.add_digital_output('clk_val') # determine if the request was granted m.bind_name('req_grant', m.dt_req == m.emu_dt) # update the clock value m.add_digital_state('prev_clk_val') m.set_next_cycle(m.prev_clk_val, m.clk_val, clk=m.emu_clk, rst=m.emu_rst) m.set_this_cycle(m.clk_val, if_(m.req_grant, ~m.prev_clk_val, m.prev_clk_val)) # determine arguments for formating time steps # TODO: clean this up dt_fmt_kwargs = dict( range_=m.emu_dt.format_.range_, width=m.emu_dt.format_.width, exponent=m.emu_dt.format_.exponent ) array_fmt_kwargs = deepcopy(dt_fmt_kwargs) array_fmt_kwargs['real_range_hint'] = m.emu_dt.format_.range_ del array_fmt_kwargs['range_'] # determine the next period dt_req_next_array = array([m.t_hi, m.t_lo], m.prev_clk_val, **array_fmt_kwargs) m.bind_name('dt_req_next', dt_req_next_array, **dt_fmt_kwargs) # increment the time request m.bind_name('dt_req_incr', m.dt_req - m.emu_dt, **dt_fmt_kwargs) # determine the next period dt_req_imm_array = array([m.dt_req_incr, m.dt_req_next], m.req_grant, **array_fmt_kwargs) m.bind_name('dt_req_imm', dt_req_imm_array, **dt_fmt_kwargs) m.set_next_cycle(m.dt_req, m.dt_req_imm, clk=m.emu_clk, rst=m.emu_rst) # generate the model m.compile_to_file(VerilogGenerator()) self.generated_files = [filename]
def test_distribute_mult(): a = AnalogSignal('a') b = AnalogSignal('b') c = AnalogSignal('c') d = AnalogSignal('d') e = a + 3.4 * (b + 5.6 * (c + 7.8 * d)) print('Original expression:') print(e) print('') f = distribute_mult(e) print('Flattened expresion:') print(f) print('') v = VerilogGenerator() v.text = '' v.expr_to_signal(f) print('Compiled expression:') print(v.text) print('') # check that the flattened expression is OK assert (isinstance(f, Sum)) res = {} for op in f.operands: if isinstance(op, Product): subops = op.operands sig = subops[0] if isinstance(subops[0], AnalogSignal) else subops[1] val = subops[1] if isinstance(subops[0], AnalogSignal) else subops[0] res[sig.name] = val.value elif isinstance(op, AnalogSignal): res[op.name] = 1.0 print('Dictionary mapping signal names to coefficients:') print(res) assert len(res) == 4 assert isclose(res['a'], 1) assert isclose(res['b'], 3.4) assert isclose(res['c'], 3.4 * 5.6) assert isclose(res['d'], 3.4 * 5.6 * 7.8)
def main(): tau = 1e-6 dt = 0.1e-6 model = MixedSignalModel('model', dt=dt) model.add_analog_input('v_in') model.add_analog_output('v_out', init=1.23) model.add_eqn_sys([Deriv(model.v_out) == (model.v_in - model.v_out)/tau]) model.compile_and_print(VerilogGenerator())
def main(): dt = 0.1e-6 m = MixedSignalModel('model', dt=dt) m.add_analog_input('v_in') m.add_analog_output('v_out') m.add_eqn_sys([m.v_out == 0.123 * m.v_in]) m.compile_and_print(VerilogGenerator())
def main(): a = AnalogSignal('a') b = AnalogSignal('b') c = AnalogSignal('c') d = AnalogSignal('d') e = 1.2 * (a + 3.4 * (b + 5.6 * (c + 7.8 * d))) print('Original expression:') print(e) print('') print('Expression after flattening:') print(distribute_mult(e)) print('') print('Compiled expression') v = VerilogGenerator() v.text = '' v.expr_to_signal(distribute_mult(e)) print(v.text)
def main(): model = MixedSignalModel('model') model.add_analog_input('a') model.add_digital_input('b', width=8) model.add_digital_output('c', width=12) model.bind_name('d', model.a + model.b) clamped = clamp(to_sint(model.d, width=model.c.width + 1), 0, 1023) model.set_next_cycle(model.c, to_uint(clamped, width=model.c.width)) model.compile_and_print(VerilogGenerator())
def main(): dt = 0.1e-6 num = (1e12,) den = (1, 8e5, 1e12,) model = MixedSignalModel('model', dt=dt) model.add_analog_input('v_in') model.add_analog_output('v_out') model.set_tf(input_=model.v_in, output=model.v_out, tf=(num, den)) model.compile_and_print(VerilogGenerator())
def test_tanh(simulator, real_type, err_lim=2.5e-4): # set the random seed for repeatable results np.random.seed(0) # generate model model = SaturationModel(module_name='model', build_dir=BUILD_DIR, real_type=real_type) model_file = model.compile_to_file(VerilogGenerator()) # declare circuit class dut(m.Circuit): name = 'test_tanh' io = m.IO( in_=fault.RealIn, out=fault.RealOut ) # create the tester tester = MsdslTester(dut) # save the outputs inpts = np.random.uniform(-2, +2, 100) apprx = [] for in_ in inpts: tester.poke(dut.in_, in_) tester.eval() apprx.append(tester.get_value(dut.out)) # run the simulation parameters = { 'in_range': 2.5, 'out_range': 2.5 } tester.compile_and_run( directory=BUILD_DIR, simulator=simulator, ext_srcs=[model_file, get_file('tanh/test_tanh.sv')], parameters=parameters, real_type=real_type ) # evaluate the outputs apprx = np.array([elem.value for elem in apprx], dtype=float) # compute the exact response to inputs exact = model.func(inpts) # check the result err = np.sqrt(np.mean((exact-apprx)**2)) print(f'RMS error: {err}') assert err <= err_lim
def main(): # define ports m = MixedSignalModel('comparator') m.add_analog_input('in_p') m.add_analog_input('in_n') m.add_digital_output('out', init=0) m.add_digital_input('clk') # define behavior m.immediate_assign('out_async', m.in_p > m.in_n) m.next_cycle_assign(m.out, m.out_async, clk=m.clk) # write model m.compile_and_print(VerilogGenerator())
def test_check_format(in_type, in_opt, out_type, out_opt, check_format, cycle, expected_result, init_val): # declare model I/O m = MixedSignalModel('model') if in_type == 'uint': m.add_digital_input('a', width=in_opt) elif in_type == 'sint': m.add_digital_input('a', width=in_opt, signed=True) elif in_type == 'real': m.add_analog_input('a') else: raise Exception(f'Invalid in_type: {in_type}') if out_type == 'uint': m.add_digital_state('y', width=out_opt, init=init_val) elif out_type == 'sint': m.add_digital_state('y', width=out_opt, signed=True, init=init_val) elif out_type == 'real': m.add_analog_state('y', range_=out_opt) else: raise Exception(f'Invalid out_type: {out_type}') if cycle == 'this': m.set_this_cycle(m.y, m.a, check_format=check_format) elif cycle == 'next': m.set_next_cycle(m.y, m.a, check_format=check_format) else: raise Exception(f'Invalid cycle type: {cycle}') # compile to a file if expected_result is not None: with pytest.raises(Exception) as e: m.compile(VerilogGenerator()) assert expected_result in str(e.value) else: m.compile(VerilogGenerator())
def gen_model(const=1.23, real_type=RealType.FixedPoint): # declare module m = MixedSignalModel('model', real_type=real_type) m.add_analog_input('a') m.add_analog_output('b') m.add_eqn_sys([m.b == const * m.a]) # compile to a file BUILD_DIR.mkdir(parents=True, exist_ok=True) model_file = BUILD_DIR / 'model.sv' m.compile_to_file(VerilogGenerator(), filename=model_file) # return file location return model_file
def main(): tau = 1e-6 dt = 0.1e-6 model = MixedSignalModel('model', dt=dt) model.add_analog_input('v_in') model.add_analog_output('v_out') model.add_digital_input('ctrl') model.add_eqn_sys([ Deriv( model.v_out) == eqn_case([0, 1 / tau], [model.ctrl]) * model.v_in - model.v_out / tau ]) model.compile_and_print(VerilogGenerator())
def gen_model(tau, dt, real_type): model = MixedSignalModel('model', dt=dt, real_type=real_type) model.add_analog_input('v_in') model.add_analog_output('v_out') model.add_digital_input('clk') model.add_digital_input('rst') model.add_eqn_sys([Deriv(model.v_out) == (model.v_in - model.v_out) / tau], clk=model.clk, rst=model.rst) BUILD_DIR.mkdir(parents=True, exist_ok=True) model_file = BUILD_DIR / 'model.sv' model.compile_to_file(VerilogGenerator(), filename=model_file) return model_file
def gen_model(real_type): # declare module m = MixedSignalModel('model', real_type=real_type) m.add_analog_input('a') m.add_analog_input('b') # bind expression to internal signal m.bind_name('c', m.a + m.b) # compile to a file BUILD_DIR.mkdir(parents=True, exist_ok=True) model_file = BUILD_DIR / 'model.sv' m.compile_to_file(VerilogGenerator(), filename=model_file) # return file location return model_file
def main(): tau_det_fast = 1e-9 tau_det_slow = 360e-9 dt = 4.6e-9 m = MixedSignalModel('model', dt=dt) m.add_analog_input('v_in') m.add_analog_output('v_out') m.bind_name('in_gt_out', m.v_in > m.v_out) # detector dynamics m.add_eqn_sys([ Deriv(m.v_out) == eqn_case([0, 1 / tau_det_fast], [m.in_gt_out]) * (m.v_in - m.v_out) - (m.v_out / tau_det_slow) ]) m.compile_and_print(VerilogGenerator())
def main(): print('Running model generator...') # parse command line arguments parser = ArgumentParser() parser.add_argument('-o', '--output', type=str) parser.add_argument('--dt', type=float) args = parser.parse_args() # create the model model = Filter(dt=args.dt) # determine the output filename filename = os.path.join(get_full_path(args.output), f'{model.module_name}.sv') print('Model will be written to: ' + filename) # generate the model model.compile_to_file(VerilogGenerator(), filename)
def gen_model(): # declare model I/O m = MixedSignalModel('model') m.add_digital_input('a', width=63, signed=True) m.add_digital_input('b', width=63, signed=True) m.add_digital_output('c', width=64, signed=True) # assign expression to output m.bind_name('d', m.a - m.b) m.set_this_cycle(m.c, m.d) # compile to a file BUILD_DIR.mkdir(parents=True, exist_ok=True) model_file = BUILD_DIR / 'model.sv' m.compile_to_file(VerilogGenerator(), filename=model_file) # return file location return model_file
def gen_model(tau=1e-6, dt=0.1e-6, real_type=RealType.FixedPoint): m = MixedSignalModel('model', dt=dt, real_type=real_type) m.add_analog_input('v_in') m.add_analog_output('v_out') m.add_digital_input('clk') m.add_digital_input('rst') m.set_tf(input_=m.v_in, output=m.v_out, tf=((1, ), (tau, 1)), clk=m.clk, rst=m.rst) BUILD_DIR.mkdir(parents=True, exist_ok=True) model_file = BUILD_DIR / 'model.sv' m.compile_to_file(VerilogGenerator(), filename=model_file) return model_file