Example #1
0
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())
Example #2
0
def main(cap=1e-12, res=600, n_array=47):
    ctrl = ExampleControl()

    # define ports
    m = MixedSignalModel('current_switch_array', dt=ctrl.dt)
    m.add_digital_input('ctrl', n_array)
    m.add_analog_input('v_in')
    m.add_analog_output('v_out', init=0)  # can change initial value if desired

    # find number of zeros
    m.immediate_assign(
        'n_on', n_array - sum_op([m.ctrl[k] for k in range(m.ctrl.width)]))

    # compute the unit current
    m.immediate_assign('i_unit', (m.v_in - m.v_out) / res)

    # compute the array current
    m.immediate_assign('i_array', m.n_on * m.i_unit)

    # define the voltage update on the cap
    m.next_cycle_assign(m.v_out,
                        m.v_out + m.i_array / (n_array * cap) * ctrl.dt)

    # write model
    ctrl.write_model(m)
Example #3
0
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)
Example #4
0
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())
Example #5
0
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())
Example #6
0
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 __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]
Example #8
0
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())
Example #9
0
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())
Example #10
0
File: tf.py Project: xlchan/msdsl
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())
Example #11
0
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
Example #12
0
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())
Example #13
0
File: det.py Project: xlchan/msdsl
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())
Example #14
0
def gen_model(real_type, gen_type):
    # 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_input('mean_in')
    model.add_analog_input('std_in')
    model.add_analog_output('real_out')

    # apply noise
    model.set_gaussian_noise(model.real_out,
                             std=model.std_in,
                             mean=model.mean_in,
                             clk=model.clk,
                             rst=model.rst,
                             gen_type=gen_type)

    # write the model
    return model.compile_to_file(VerilogGenerator())
Example #15
0
def main():
    dt = 0.1e-6
    res = 1e3
    cap = 1e-9

    m = MixedSignalModel('model', dt=dt)

    m.add_analog_input('v_in')
    m.add_analog_output('v_out')

    c = m.make_circuit()
    gnd = c.make_ground()

    c.capacitor('net_v_out', gnd, cap, voltage_range=RangeOf(m.v_out))
    c.resistor('net_v_in', 'net_v_out', res)
    c.voltage('net_v_in', gnd, m.v_in)

    c.add_eqns(AnalogSignal('net_v_out') == m.v_out)

    m.compile_and_print(VerilogGenerator())
Example #16
0
def main():
    model = MixedSignalModel('model')

    model.add_analog_input('a_in')
    model.add_digital_output('d_out', width=8)

    model.add_analog_output('a_out')
    model.add_digital_input('d_in', width=8)

    # DAC from 0 to 1V as the input code varies from 0-255

    clamped = clamp(to_sint(model.a_in * 255, width=model.d_out.width + 1), 0,
                    255)
    model.set_this_cycle(model.d_out, to_uint(clamped,
                                              width=model.d_out.width))

    # ADC code goes from 0-255 as input voltage goes from 0 to 1V
    model.set_this_cycle(model.a_out, model.d_in / 255)

    model.compile_and_print(VerilogGenerator())
Example #17
0
    def __init__(self, filename=None, **system_values):
        # set a fixed random seed for repeatability
        np.random.seed(4)

        module_name = Path(filename).stem
        build_dir = Path(filename).parent

        #This is a wonky way of validating this.. :(
        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_digital_input('in_')
        m.add_analog_output('out')
        m.add_digital_input('cke')
        m.add_digital_input('clk')
        m.add_digital_input('rst')

        # save previous value of cke
        m.add_digital_state('cke_prev', init=0)
        m.set_next_cycle(m.cke_prev, m.cke, clk=m.clk, rst=m.rst)

        # detect positive edge of cke
        m.add_digital_signal('cke_posedge')
        m.set_this_cycle(m.cke_posedge, m.cke & (~m.cke_prev))

        # define model behavior
        vp, vn = system_values['vp'], system_values['vn']
        m.set_next_cycle(m.out,
                         if_(m.in_, vp, vn),
                         clk=m.clk,
                         rst=m.rst,
                         ce=m.cke_posedge)

        # generate the model
        m.compile_to_file(VerilogGenerator())

        self.generated_files = [filename]
Example #18
0
def main(cap=1e-12, res=600):
    ctrl = ExampleControl()

    # define ports
    m = MixedSignalModel('current_switch', dt=ctrl.dt)
    m.add_digital_input('ctrl')
    m.add_analog_input('v_in')
    m.add_analog_output('v_out')

    # define the circuit
    c = m.make_circuit()
    gnd = c.make_ground()

    c.switch('net_v_in', 'net_v_out', m.ctrl, r_on=res, r_off=10e3 * res)
    c.capacitor('net_v_out', gnd, cap, voltage_range=RangeOf(m.v_out))
    c.voltage('net_v_in', gnd, m.v_in)

    c.add_eqns(m.v_out == AnalogSignal('net_v_out'))

    # write model
    ctrl.write_model(m)
Example #19
0
def main():
    dt = 0.01e-6
    cap = 0.16e-6
    ind = 0.16e-6
    res = 0.1

    model = MixedSignalModel('model', dt=dt)
    model.add_analog_input('v_in')
    model.add_analog_output('v_out')

    model.add_analog_state('i_ind', 100)

    v_l = AnalogSignal('v_l')
    v_r = AnalogSignal('v_r')
    eqns = [
        Deriv(model.i_ind) == v_l / ind,
        Deriv(model.v_out) == model.i_ind / cap, v_r == model.i_ind * res,
        model.v_in == model.v_out + v_l + v_r
    ]
    model.add_eqn_sys(eqns)

    model.compile_and_print(VerilogGenerator())
Example #20
0
def main():
    dt = 1e-9

    m = MixedSignalModel('model', dt=dt)

    m.add_analog_input('v_in')
    m.add_analog_output('v_out')
    m.add_digital_input('sw1')
    m.add_digital_input('sw2')

    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)
    c.switch('net_v_x', gnd, m.sw2)

    c.inductor('net_v_in', 'net_v_x', 1, current_range=100)

    c.add_eqns(AnalogSignal('net_v_x') == m.v_out)

    m.compile_and_print(VerilogGenerator())
Example #21
0
def gen_model(order, numel, build_dir):
    # settings:
    # order=0, numel=512 => rms_error <= 0.0105
    # order=1, numel=128 => rms_error <= 0.000318
    # order=2, numel= 32 => rms_error <= 0.000232

    # create mixed-signal model
    m = MixedSignalModel('model', build_dir=build_dir)
    m.add_analog_input('in_')
    m.add_analog_output('out')

    # create function
    real_func = m.make_function(myfunc,
                                domain=[-np.pi, +np.pi],
                                order=order,
                                numel=numel)

    # apply function
    m.set_from_sync_func(m.out, real_func, m.in_)

    # write the model
    return m.compile_to_file(VerilogGenerator())
Example #22
0
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_digital_input('sw1')
    m.add_digital_input('sw2')

    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=1.0, r_off=2.0)
    c.switch('net_v_x', gnd, m.sw2, r_on=3.0, r_off=4.0)

    c.add_eqns(
        AnalogSignal('net_v_x') == m.v_out
    )

    m.compile_and_print(VerilogGenerator())
Example #23
0
def gen_model(placeholder, real_type, addr_bits, data_bits):
    # 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')
    model.add_digital_input('wdata0', width=data_bits, signed=True)
    model.add_digital_input('wdata1', width=data_bits, signed=True)
    model.add_digital_input('waddr', width=addr_bits)
    model.add_digital_input('we')

    # apply function
    model.set_from_sync_func(model.out,
                             placeholder,
                             model.in_,
                             clk=model.clk,
                             rst=model.rst,
                             wdata=[model.wdata0, model.wdata1],
                             waddr=model.waddr,
                             we=model.we)

    # write the model
    return model.compile_to_file(VerilogGenerator())
Example #24
0
def main():
    print('Running model generator...')

    # parse command line arguments
    parser = ArgumentParser()
    parser.add_argument('-o', '--output', type=str, default='build')
    parser.add_argument('--dt', type=float, default=0.1e-6)
    parser.add_argument('--tau', type=float, default=1.0e-6)
    a = parser.parse_args()

    # create the model
    m = MixedSignalModel('model', dt=a.dt)
    m.add_analog_input('v_in')
    m.add_analog_output('v_out')

    # apply dynamics
    m.set_next_cycle(m.v_out, m.v_out*exp(-a.dt/a.tau) + m.v_in*(1-exp(-a.dt/a.tau)))

    # determine the output filename
    filename = Path(a.output).resolve() / f'{m.module_name}.sv'
    print(f'Model will be written to: {filename}')

    # generate the model
    m.compile_to_file(VerilogGenerator(), filename)
Example #25
0
    def __init__(self, filename=None, **system_values):
        # set a fixed random seed for repeatability
        np.random.seed(1)

        module_name = Path(filename).stem
        build_dir   = Path(filename).parent

        #This is a wonky way of validating this.. :(
        assert (all([req_val in system_values for req_val in self.required_values()])), \
            f'Cannot build {module_name}, Missing parameter in config file'

        # instantiate model
        m = MixedSignalModel(module_name, dt=system_values['dt'], build_dir=build_dir)

        # main I/O: delay code and gain
        m.add_digital_input('code', width=system_values['n_bits'])
        m.add_digital_input('clk_i_val')
        m.add_digital_output('clk_o_val')

        # timestep control: DT request and response
        m.add_analog_output('dt_req')
        m.add_analog_input('emu_dt')

        # emulator clock and reset
        m.add_digital_input('emu_clk')
        m.add_digital_input('emu_rst')

        # additional input: maximum timestep
        # TODO: clean this up
        m.add_analog_input('dt_req_max')

        # jitter control
        m.add_digital_input('jitter_seed', width=32)
        m.add_analog_input('jitter_rms')

        # compute the delay (with no jitter)
        m.bind_name('delay_amt_pre', m.code * (system_values['t_per'] / (2.0 ** system_values['n_bits'])))

        # add jitter to the delay amount (which might possibly yield a negative value)
        m.set_gaussian_noise('t_jitter', std=m.jitter_rms, clk=m.emu_clk,
                             rst=m.emu_rst, lfsr_init=m.jitter_seed)
        m.bind_name('delay_amt_noisy', m.delay_amt_pre + m.t_jitter)

        # make the delay amount non-negative
        m.bind_name('delay_amt', if_(m.delay_amt_noisy >= 0.0, m.delay_amt_noisy, 0.0))

        # determine when the clock value has changed
        m.add_digital_state('clk_i_val_prev')
        m.set_next_cycle(m.clk_i_val_prev, m.clk_i_val, clk=m.emu_clk, rst=m.emu_rst)
        m.bind_name('clk_edge', m.clk_i_val ^ m.clk_i_val_prev)

        # create pointer that advances each time there is a clock edge
        depth = system_values['depth']
        dbits = int(ceil(log2(depth)))
        m.add_digital_state('addr', width=dbits)
        m.add_digital_state('next_addr', width=dbits)
        m.set_this_cycle(m.next_addr, if_(m.addr == (depth-1), 0, m.addr+1))
        m.set_next_cycle(m.addr, m.next_addr, clk=m.emu_clk, rst=m.emu_rst, ce=m.clk_edge)

        # convenience function for formatting DT signals
        def add_dt_state(*args, range_=m.emu_dt.format_.range_, width=m.emu_dt.format_.width,
                         exponent=m.emu_dt.format_.exponent, **kwargs):
            return m.add_analog_state(*args, range_=range_, width=width, exponent=exponent, **kwargs)

        # convenience function for formatting DT signals
        def dt_array(*args, real_range_hint=m.emu_dt.format_.range_, width=m.emu_dt.format_.width,
                     exponent=m.emu_dt.format_.exponent, **kwargs):
            return array(*args, real_range_hint=real_range_hint, width=width, exponent=exponent,
                         **kwargs)

        # instantiate delay "units" that each keep track of one edge

        dt_req = []
        req_data = []
        req_grant = []
        req_valid = []

        for k in range(depth):
            # should load data if there is a clock edge and this slice is selected
            load_data = m.bind_name(f'load_data_{k}', m.clk_edge & (k == m.addr))

            # handle update of dt_req
            dt_req.append(add_dt_state(f'dt_req_{k}'))
            m.set_next_cycle(
                dt_req[-1],
                if_(load_data, m.delay_amt, dt_req[-1] - m.emu_dt),
                clk=m.emu_clk,
                rst=m.emu_rst
            )

            # handle update of req_data
            req_data.append(m.add_digital_state(f'req_data_{k}'))
            m.set_next_cycle(req_data[-1], m.clk_i_val, ce=load_data,
                             clk=m.emu_clk, rst=m.emu_rst)

            # handle update of req_grant
            req_grant.append(m.bind_name(f'req_grant_{k}', dt_req[-1] == m.emu_dt))

            # handle update of req_valid
            req_valid.append(m.add_digital_state(f'req_valid_{k}'))
            m.set_next_cycle(req_valid[-1], (req_valid[-1] & (~req_grant[-1])) | load_data,
                             clk=m.emu_clk, rst=m.emu_rst)

        # replace dt_req with dt_req_max for invalid requests

        dt_req_mux = []
        for k in range(depth):
            dt_req_mux.append(
                m.bind_name(
                    f'dt_req_mux_{k}',
                    dt_array(
                        [m.dt_req_max, dt_req[k]],
                        req_valid[k],
                    )
                )
            )

        # convenience function to find the minimum DT request using a tree structure

        counter = count()
        def tree_min(data):
            # check cases
            if len(data) == 0:
                raise Exception("This shouldn't happen...")
            elif len(data) == 1:
                return data[0]
            else:
                val0 = tree_min(data[:len(data)//2])
                val1 = tree_min(data[len(data)//2:])
                return m.bind_name(
                    f'dt_intern_{next(counter)}',
                    dt_array(
                        [val0, val1],
                        val1 < val0,
                    )
                )

        # set the "dt_req" output to the minimum time request (where invalid requests
        # are replaced with "dt_req_max"

        m.set_this_cycle(m.dt_req, tree_min(dt_req_mux))

        # determine if the output should be set or cleared

        set_out = req_grant[0] & req_valid[0] & req_data[0]
        clr_out = req_grant[0] & req_valid[0] & (~req_data[0])

        for k in range(1, depth):
            set_out = set_out | (req_grant[k] & req_valid[k] & req_data[k])
            clr_out = clr_out | (req_grant[k] & req_valid[k] & (~req_data[k]))

        m.bind_name('set_out', set_out)
        m.bind_name('clr_out', clr_out)

        # set output, clear output, or keep it the same

        m.add_digital_state('clk_o_val_prev')
        m.set_next_cycle(m.clk_o_val_prev, m.clk_o_val, clk=m.emu_clk, rst=m.emu_rst)
        m.set_this_cycle(m.clk_o_val, (m.clk_o_val_prev & (~m.clr_out)) | (m.set_out))

        # generate the model
        m.compile_to_file(VerilogGenerator())

        self.generated_files = [filename]
Example #26
0
    def __init__(self, filename=None, **system_values):
        # set a fixed random seed for repeatability
        np.random.seed(0)

        module_name = Path(filename).stem
        build_dir = Path(filename).parent

        #This is a wonky way of validating this.. :(
        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_analog_input('in_')
        m.add_analog_output('out')
        m.add_analog_input('dt_sig')
        m.add_digital_input('clk')
        m.add_digital_input('cke')
        m.add_digital_input('rst')

        # Create "placeholder function" that can be updated
        # at runtime with the channel function
        chan_func = PlaceholderFunction(
            domain=system_values['func_domain'],
            order=system_values['func_order'],
            numel=system_values['func_numel'],
            coeff_widths=system_values['func_widths'],
            coeff_exps=system_values['func_exps'])

        # Check the function on a representative test case
        chan = Filter.from_file(get_file('build/chip_src/adapt_fir/chan.npy'))
        self.check_func_error(chan_func, chan.interp)

        # Add digital inputs that will be used to reconfigure the function at runtime
        wdata, waddr, we = add_placeholder_inputs(m=m, f=chan_func)

        # create a history of past inputs
        cke_d = m.add_digital_state('cke_d')
        m.set_next_cycle(cke_d, m.cke, clk=m.clk, rst=m.rst)
        value_hist = m.make_history(m.in_,
                                    system_values['num_terms'] + 1,
                                    clk=m.clk,
                                    rst=m.rst,
                                    ce=cke_d)

        # create a history times in the past when the input changed
        time_incr = []
        time_mux = []
        for k in range(system_values['num_terms'] + 1):
            if k == 0:
                time_incr.append(m.dt_sig)
                time_mux.append(None)
            else:
                # create the signal
                mem_sig = AnalogState(name=f'time_mem_{k}',
                                      range_=m.dt_sig.format_.range_,
                                      width=m.dt_sig.format_.width,
                                      exponent=m.dt_sig.format_.exponent,
                                      init=0.0)
                m.add_signal(mem_sig)

                # increment time by dt_sig (this is the output from the current tap)
                incr_sig = m.bind_name(f'time_incr_{k}', mem_sig + m.dt_sig)
                time_incr.append(incr_sig)

                # mux input of DFF between current and previous memory value
                mux_sig = m.bind_name(
                    f'time_mux_{k}',
                    if_(m.cke_d, time_incr[k - 1], time_incr[k]))
                time_mux.append(mux_sig)

                # delayed assignment
                m.set_next_cycle(signal=mem_sig,
                                 expr=mux_sig,
                                 clk=m.clk,
                                 rst=m.rst)

        # evaluate step response function
        step = []
        for k in range(system_values['num_terms']):
            step_sig = m.set_from_sync_func(f'step_{k}',
                                            chan_func,
                                            time_mux[k + 1],
                                            clk=m.clk,
                                            rst=m.rst,
                                            wdata=wdata,
                                            waddr=waddr,
                                            we=we)
            step.append(step_sig)

        # compute the products to be summed
        prod = []
        for k in range(system_values['num_terms']):
            if k == 0:
                prod_sig = m.bind_name(f'prod_{k}',
                                       value_hist[k + 1] * step[k])
            else:
                prod_sig = m.bind_name(
                    f'prod_{k}', value_hist[k + 1] * (step[k] - step[k - 1]))
            prod.append(prod_sig)

        # define model behavior
        m.set_this_cycle(m.out, sum_op(prod))

        # generate the model
        m.compile_to_file(VerilogGenerator())

        self.generated_files = [filename]