def test_sim(simulator_name, n=8): # set defaults if simulator_name is None: if shutil.which('iverilog'): simulator_name = 'iverilog' else: simulator_name = 'ncsim' # declare circuit class dut(m.Circuit): name = 'histogram_data_gen' io = m.IO(clk=m.ClockIn, mode=m.In(m.Bits[3]), in0=m.In(m.Bits[n]), in1=m.In(m.Bits[n]), out=m.Out(m.Bits[n])) # create tester t = fault.Tester(dut, dut.clk) # initialize with the right equation t.zero_inputs() # run a few cycles t.step(10) # test uniform mode t.poke(dut.mode, UNIFORM) t.step(4) unif_vec = [] for _ in range(1 << n): unif_vec.append(t.get_value(dut.out)) t.step(2) # test constant mode t.poke(dut.mode, CONSTANT) t.poke(dut.in0, 42) t.step(4) const_vec = [] for _ in range(1 << n): const_vec.append(t.get_value(dut.out)) t.step(2) # test "include" mode t.poke(dut.mode, INCL) t.poke(dut.in0, 34) t.poke(dut.in1, 56) t.step(4) incl_vec = [] for _ in range(1 << n): incl_vec.append(t.get_value(dut.out)) t.step(2) # test "exclude" mode t.poke(dut.mode, EXCL) t.poke(dut.in0, 12) t.poke(dut.in1, 243) t.step(4) excl_vec = [] for _ in range(1 << n): excl_vec.append(t.get_value(dut.out)) t.step(2) # test "alternate" mode t.poke(dut.mode, ALT) t.poke(dut.in0, 78) t.poke(dut.in1, 89) t.step(4) alt_vec = [] for _ in range(1 << n): alt_vec.append(t.get_value(dut.out)) t.step(2) ################## # run simulation # ################## t.compile_and_run( target='system-verilog', simulator=simulator_name, ext_srcs=get_deps_cpu_sim(cell_name='histogram_data_gen'), parameters={ 'n': n, }, ext_model_file=True, disp_type='realtime', dump_waveforms=False, directory=BUILD_DIR, num_cycles=1e12) ################### # convert results # ################### def conv(x): return [elem.value for elem in x] unif_vec = conv(unif_vec) const_vec = conv(const_vec) incl_vec = conv(incl_vec) excl_vec = conv(excl_vec) alt_vec = conv(alt_vec) ################# # print results # ################# print(f'unif_vec: {unif_vec}') print() print(f'const_vec: {const_vec}') print() print(f'incl_vec: {incl_vec}') print() print(f'excl_vec: {excl_vec}') print() print(f'alt_vec: {alt_vec}') print() ################# # check results # ################# # uniform assert list(sorted(unif_vec)) == list( range(1 << n)), 'Output of uniform data generator unexpected.' # constant assert const_vec == [42] * ( 1 << n), 'Output of constant data generator unexpected.' # include per = 56 - 34 + 1 nper = len(incl_vec) // per expct = [] for k in range(34, 57): expct += [k] * nper assert list(sorted( incl_vec[:nper * per])) == expct, 'Output of "include" pattern unexpected.' # exclude per = (11 - 0 + 1) + (255 - 244 + 1) nper = len(excl_vec) // per expct = [] for k in range(0, 12): expct += [k] * nper for k in range(244, 256): expct += [k] * nper assert list(sorted( excl_vec[:nper * per])) == expct, 'Output of "exclude" pattern unexpected.' # alternating assert alt_vec[:2] == [78, 89] or alt_vec[:2] == [89, 78] assert alt_vec == alt_vec[:2] * ( 1 << (n - 1)), 'Output of alternating data generator unexpected.' ################### # declare success # ################### print('Success!')
t.zero_inputs() t.poke(dut.rst, 1) t.step(2) # clear reset t.poke(dut.rst, 0) t.step(2) # read out bits hist = [] for _ in range(32 * 16): hist.append(t.get_value(dut.out)) t.step(2) # run the simulation ext_srcs = get_deps_cpu_sim(impl_file=THIS_DIR / 'gather.sv') t.compile_and_run(target='system-verilog', directory=BUILD_DIR, simulator='iverilog', ext_srcs=ext_srcs, ext_model_file=True, disp_type='realtime', dump_waveforms=True) # print result hist = [elem.value for elem in hist] inits = [list() for _ in range(16)] for k, elem in enumerate(hist): inits[k % 16].append(elem) for k, init in enumerate(inits): assert len(init) == 32
def test_sim(simulator_name, Nadc=8, Nrange=4, Navg=10): # set defaults if simulator_name is None: if shutil.which('iverilog'): simulator_name = 'iverilog' else: simulator_name = 'ncsim' # declare circuit class dut(m.Circuit): name = 'calib_sample_avg' io = m.IO(din=m.In(m.SInt[Nadc]), Navg=m.In(m.Bits[Nrange]), clk=m.ClockIn, update=m.BitIn, rstb=m.BitIn, avg_out=m.Out(m.SInt[Nadc]), sum_out=m.Out(m.SInt[Nadc + (2**Nrange)])) # create tester t = fault.Tester(dut, dut.clk) # define data vectors data_vecs = [ [-42] * (1 << Navg), [+42] * (1 << Navg), [0] * (1 << Navg), [ random.randint(-(1 << (Nadc - 1)), (1 << (Nadc - 1)) - 1) for _ in range(1 << Navg) ], [random.randint(0, (1 << (Nadc - 1)) - 1) for _ in range(1 << Navg)], [random.randint(-(1 << (Nadc - 1)), 0) for _ in range(1 << Navg)] ] # define averaging test def run_avg(data, last): # middle values t.poke(dut.update, 0) for elem in data[1:]: t.poke(dut.din, elem) t.step(2) # final value t.poke(dut.update, 1) t.poke(dut.din, last) t.step(2) # get values for average and sum avg_out = t.get_value(dut.avg_out) sum_out = t.get_value(dut.sum_out) return avg_out, sum_out # initialize t.zero_inputs() t.poke(dut.Navg, Navg) # run a few cycles t.step(10) t.poke(dut.rstb, 1) t.step(2) # first value t.poke(dut.update, 1) t.poke(dut.din, data_vecs[0][0]) t.step(2) # run averaging trials results = [] for k in range(len(data_vecs)): if k <= (len(data_vecs) - 2): last = data_vecs[k + 1][0] else: last = 0 results.append(run_avg(data_vecs[k], last)) # run a few extra cycles for better visibility t.poke(dut.update, 0) t.step(10) ################## # run simulation # ################## t.compile_and_run(target='system-verilog', simulator=simulator_name, ext_srcs=get_deps_cpu_sim(cell_name=dut.name), parameters={ 'Nadc': Nadc, 'Nrange': Nrange }, ext_model_file=True, disp_type='realtime', dump_waveforms=False, directory=BUILD_DIR, num_cycles=1e12) ################## # convert values # ################## def to_signed(x, n): if x >= (1 << (n - 1)): return x - (1 << n) else: return x results = [(to_signed(res[0].value, Nadc), to_signed(res[1].value, Nadc + (2**Nrange))) for res in results] print('results', results) ################ # check values # ################ for (avg_out, sum_out), data_vec in zip(results, data_vecs): assert sum_out == sum(data_vec), 'Mismatch in sum.' assert avg_out == sum(data_vec) >> Navg, 'Mismatch in average.' ################### # declare success # ################### print('Success!')
def test_sim(simulator_name, Nadc=8, Nrange=4, Navg=7, Nbin=6, DZ=3): # set defaults if simulator_name is None: if shutil.which('iverilog'): simulator_name = 'iverilog' else: simulator_name = 'ncsim' # declare circuit class dut(m.Circuit): name = 'calib_hist_measure' io = m.IO(rstb=m.BitIn, clk=m.ClockIn, update=m.BitIn, din=m.In(m.SInt[Nadc]), din_avg=m.In(m.SInt[Nadc]), Nbin=m.In(m.Bits[Nrange]), DZ=m.In(m.Bits[Nrange]), flip_feedback=m.BitIn, hist_center=m.Out(m.Bits[2**Nrange]), hist_side=m.Out(m.Bits[2**Nrange]), hist_comp_out=m.Out(m.SInt[2])) # create tester t = fault.Tester(dut, dut.clk) # define data vectors data_vecs = [ [0] * (1 << Navg), [+13] * (1 << Navg), [-13] * (1 << Navg), [+25] * (1 << Navg), [-25] * (1 << Navg), [random.randint(-25, 25) for _ in range(1 << Navg)], [random.randint(0, 25) for _ in range(1 << Navg)], [random.randint(-25, 0) for _ in range(1 << Navg)], ] # define averaging test def run_hist(data): # first value t.poke(dut.update, 1) t.poke(dut.din, data[0]) t.step(2) # middle values t.poke(dut.update, 0) for elem in data[1:]: t.poke(dut.din, elem) t.step(2) # get values for average and sum hist_center = t.get_value(dut.hist_center) hist_side = t.get_value(dut.hist_side) hist_comp_out = t.get_value(dut.hist_comp_out) return hist_center, hist_side, hist_comp_out # initialize t.zero_inputs() t.poke(dut.din_avg, 0) t.poke(dut.Nbin, Nbin) t.poke(dut.DZ, DZ) # run a few cycles t.step(10) t.poke(dut.rstb, 1) t.step(2) # run averaging trials results = [] for k in range(len(data_vecs)): results.append(run_hist(data_vecs[k])) # run a few extra cycles for better visibility t.step(10) ################## # run simulation # ################## t.compile_and_run(target='system-verilog', simulator=simulator_name, ext_srcs=get_deps_cpu_sim(cell_name=dut.name), parameters={ 'Nadc': Nadc, 'Nrange': Nrange }, ext_model_file=True, disp_type='realtime', dump_waveforms=False, directory=BUILD_DIR, num_cycles=1e12) ################## # convert values # ################## def to_signed(x, n): if x >= (1 << (n - 1)): return x - (1 << n) else: return x results = [(res[0].value, res[1].value, to_signed(res[2].value, 2)) for res in results] print('results', results) ################ # check values # ################ for result, data_vec in zip(results, data_vecs): assert result == model(data=data_vec, Nbin=Nbin, DZ=DZ), \ 'Mismatch in measured vs. expected results.' ################### # declare success # ################### print('Success!')
def test_tx_data_gen(simulator_name, dump_waveforms, n_prbs=32, n_ti=16, sq_per=4, pulse_per=3, const_val=42, prbs_eqn=0x100002): # set defaults if simulator_name is None: if shutil.which('iverilog'): simulator_name = 'iverilog' else: simulator_name = 'ncsim' # declare circuit class dut(m.Circuit): name = 'test' io = m.IO(clk=m.ClockIn, rst=m.BitIn, data_mode=m.In(m.Bits[3]), data_per=m.In(m.Bits[16]), data_in=m.In(m.Bits[n_ti]), data_out=m.Out(m.Bits[n_ti]), prbs_eqn=m.In(m.Bits[n_prbs])) # create tester t = fault.Tester(dut, dut.clk) # initialize with the right equation t.zero_inputs() t.poke(dut.rst, 1) t.poke(dut.data_mode, CONSTANT) t.poke(dut.data_in, const_val) t.poke(dut.prbs_eqn, prbs_eqn) # reset for _ in range(3): t.step(2) # run CONSTANT mode t.poke(dut.rst, 0) const_vals = [] for _ in range(50): t.step(2) const_vals.append(t.get_value(dut.data_out)) # reset t.poke(dut.rst, 1) for _ in range(3): t.step(2) # run PULSE mode t.poke(dut.rst, 0) t.poke(dut.data_mode, PULSE) t.poke(dut.data_in, 1) t.poke(dut.data_per, pulse_per - 1) pulse_vals = [] for _ in range(50): t.step(2) pulse_vals.append(t.get_value(dut.data_out)) # reset t.poke(dut.rst, 1) for _ in range(3): t.step(2) # run SQUARE mode t.poke(dut.rst, 0) t.poke(dut.data_mode, SQUARE) t.poke(dut.data_per, sq_per - 1) square_vals = [] for _ in range(50): t.step(2) square_vals.append(t.get_value(dut.data_out)) # reset t.poke(dut.rst, 1) for _ in range(3): t.step(2) # run PRBS mode t.poke(dut.rst, 0) t.poke(dut.data_mode, PRBS) prbs_vals = [] for _ in range(50): t.step(2) prbs_vals.append(t.get_value(dut.data_out)) # run the test ext_srcs = get_deps_cpu_sim(impl_file=THIS_DIR / 'test.sv') parameters = {'Nti': n_ti, 'Nprbs': n_prbs} t.compile_and_run(target='system-verilog', simulator=simulator_name, ext_srcs=ext_srcs, parameters=parameters, ext_model_file=True, disp_type='realtime', dump_waveforms=dump_waveforms, directory=BUILD_DIR, num_cycles=1e12) # process results const_vals = [x.value for x in const_vals] pulse_vals = [x.value for x in pulse_vals] square_vals = [x.value for x in square_vals] prbs_vals = [x.value for x in prbs_vals] # check constant results const_vals = const_vals[5:] assert all(x == const_val for x in const_vals) # check pulse results pulse_vals = pulse_vals[pulse_vals.index(1):] pulse_vals = pulse_vals[:(len(pulse_vals) // pulse_per) * pulse_per] assert pulse_vals == ([1] + [0] * (pulse_per - 1)) * (len(pulse_vals) // pulse_per) # check square wave results sq_hi = (1 << n_ti) - 1 sq_lo = 0 square_vals = square_vals[square_vals.index(sq_hi):] square_vals = square_vals[:(len(square_vals) // (2 * sq_per)) * (2 * sq_per)] assert square_vals == ([sq_hi] * sq_per + [sq_lo] * sq_per) * (len(square_vals) // (2 * sq_per)) # check PRBS results prbs_vals = prbs_vals[5:] # first couple of values are invalid verify_prbs(prbs_vals=prbs_vals, prbs_eqn=prbs_eqn, n_ti=n_ti, n_prbs=n_prbs) # declare success print('Success!')
def test_sim(simulator_name, ndiv, N=4, nper=5): # set defaults if simulator_name is None: if shutil.which('iverilog'): simulator_name = 'iverilog' else: simulator_name = 'ncsim' # declare circuit class dut(m.Circuit): name = 'avg_pulse_gen' io = m.IO(clk=m.ClockIn, rstb=m.BitIn, ndiv=m.In(m.Bits[N]), out=m.BitOut) # create tester t = fault.Tester(dut, dut.clk) # initialize t.zero_inputs() t.poke(dut.ndiv, ndiv) # run a few cycles t.step(10) t.poke(dut.rstb, 1) # capture output results = [] for k in range(nper * (2**ndiv)): results.append(t.get_value(dut.out)) t.step(2) ################## # run simulation # ################## t.compile_and_run(target='system-verilog', simulator=simulator_name, ext_srcs=get_deps_cpu_sim(cell_name='avg_pulse_gen'), parameters={ 'N': N, }, ext_model_file=True, disp_type='realtime', dump_waveforms=False, directory=BUILD_DIR, num_cycles=1e12) ################## # convert values # ################## results = [elem.value for elem in results] ################ # check values # ################ # trim initial zeros results = results[results.index(1):] # print the beginning of the list print('results', list_head(results)) # trim to an integer number of periods nper_meas = len(results) // (2**ndiv) assert nper_meas >= (nper - 1), 'Not enough output periods observed.' results = results[:nper_meas * (2**ndiv)] # check that results match expectations expct = [] for _ in range(nper_meas): expct += [1] expct += [0] * ((2**ndiv) - 1) # compare observed and expected outputs assert results == expct, 'Mismatch in measured vs. expected outputs.' ################### # declare success # ################### print('Success!')
def test_sim(simulator_name, n_data=8, n_count=64): # set the random seed for repeatable results seed(1) # set defaults if simulator_name is None: if shutil.which('iverilog'): simulator_name = 'iverilog' else: simulator_name = 'ncsim' # determine the stimulus vector counts = [randint(0, 4) for _ in range(1 << n_data)] data_vec = [] for k, count in enumerate(counts): data_vec += [k] * count shuffle(data_vec) # declare circuit class dut(m.Circuit): name = 'histogram' io = m.IO(clk=m.ClockIn, sram_ceb=m.BitIn, mode=m.In(m.Bits[3]), data=m.In(m.Bits[n_data]), addr=m.In(m.Bits[n_data]), count=m.Out(m.Bits[n_count]), total=m.Out(m.Bits[n_count])) # create tester t = fault.Tester(dut, dut.clk) # initialize inputs t.zero_inputs() t.poke(dut.data, data_vec[0]) # run a few cycles t.step(10) # clear the memory t.poke(dut.mode, CLEAR) t.step(2 * 300) # write values t.poke(dut.mode, RUN) for elem in data_vec[1:]: t.poke(dut.data, elem) t.step(2) # poke one final value # (will not be included in histogram) t.poke(dut.data, 0) t.step(2) # read values t.poke(dut.mode, FREEZE) results = [] for k in range(1 << n_data): t.poke(dut.addr, k) t.step(8) results.append(t.get_value(dut.count)) total = t.get_value(dut.total) # run the test t.compile_and_run(target='system-verilog', simulator=simulator_name, ext_srcs=get_deps_cpu_sim(cell_name='histogram'), parameters={ 'n_data': n_data, 'n_count': n_count }, ext_model_file=True, disp_type='realtime', dump_waveforms=False, directory=BUILD_DIR, num_cycles=1e12) # convert results results = [result.value for result in results] total = total.value # print results print(f'total: {total}') print(f'results: {results}') # check results assert sum( results) == total, 'Mismatch between sum of bins and reported total.' assert sum(counts) == total, 'Total number of counts is unexpected.' assert counts == results, 'Mismatch in one or more histogram bins.' # declare success print('Success!')
step_both() # read out bits from "a" hist_a = [] for _ in range(100 * 16): hist_a.append(t.get_value(dut.out_a)) step_a() # read out bits from "b" hist_b = [] for _ in range(100): hist_b.append(t.get_value(dut.out_b)) step_b() # run the simulation ext_srcs = get_deps_cpu_sim(impl_file=THIS_DIR / 'test.sv') t.compile_and_run(target='system-verilog', directory=BUILD_DIR, simulator='iverilog', ext_srcs=ext_srcs, ext_model_file=True, disp_type='realtime', dump_waveforms=True) # extract values hist_a = [elem.value for elem in hist_a] hist_b = [elem.value for elem in hist_b] # post-process hist_b so that it can be directly compared with hist_a hist_b_post = [] for elem in hist_b:
def test_ext_offset(simulator_name, offset): # set defaults if simulator_name is None: if shutil.which('iverilog'): simulator_name = 'iverilog' else: simulator_name = 'ncsim' # create tester t = fault.Tester(dut, dut.clk) # initialize t.zero_inputs() t.poke(dut.en_pfd_cal, 0) t.poke(dut.en_ext_pfd_offset, 1) t.poke(dut.ext_pfd_offset, offset) t.poke(dut.Nbin, Nbin) t.poke(dut.Navg, Navg) t.poke(dut.DZ, DZ) # run a few cycles t.step(10) t.poke(dut.rstb, 1) t.step(2) # send in data data_in = [] data_out = [] for k in range(-((1 << Nadc) - 1), 1 << Nadc): data_in.append(k) sgn, mag = adc_model(k, offset=offset) t.poke(dut.sign_out, sgn) t.poke(dut.din, mag) t.step(2) data_out.append(t.get_value(dut.dout)) # run a few extra cycles for better visibility t.step(10) ################## # run simulation # ################## t.compile_and_run(target='system-verilog', simulator=simulator_name, ext_srcs=get_deps_cpu_sim(cell_name=dut.name), parameters={ 'Nadc': Nadc, 'Nrange': Nrange }, ext_model_file=True, disp_type='realtime', dump_waveforms=False, directory=BUILD_DIR, num_cycles=1e12) ################## # convert values # ################## def to_signed(x, n): if x >= (1 << (n - 1)): return x - (1 << n) else: return x data_out = [to_signed(elem.value, Nadc) for elem in data_out] ################ # check values # ################ for x, y in zip(data_in, data_out): if x <= -(1 << (Nadc - 1)): assert y == -(1 << (Nadc - 1)) elif x >= (1 << (Nadc - 1)) - 1: assert y == (1 << (Nadc - 1)) - 1 else: assert x == y ################### # declare success # ################### print('Success!')
def test_int_offset(simulator_name, offset, init): # set defaults if simulator_name is None: if shutil.which('iverilog'): simulator_name = 'iverilog' else: simulator_name = 'ncsim' # create tester t = fault.Tester(dut, dut.clk) # initialize t.zero_inputs() t.poke(dut.en_pfd_cal, 0) t.poke(dut.en_ext_pfd_offset, 0) t.poke(dut.ext_pfd_offset, init) t.poke(dut.Nbin, Nbin) t.poke(dut.Navg, Navg) t.poke(dut.DZ, DZ) # run a few cycles t.step(10) t.poke(dut.rstb, 1) t.step(2) # run one update cycle t.poke(dut.update, 1) t.step(2) t.poke(dut.update, 0) t.step(2) # send in data n_data = 25 * (1 << Navg) data_in = [ int(round(100 * sin(2 * pi * n / 123.456))) for n in range(n_data) ] data_out = [] t.poke(dut.en_pfd_cal, 1) for k in range(n_data): # manage the update pulse if k % (1 << Navg) == 0: t.poke(dut.update, 1) else: t.poke(dut.update, 0) # send in the data sgn, mag = adc_model(data_in[k], offset=offset) t.poke(dut.sign_out, sgn) t.poke(dut.din, mag) t.step(2) data_out.append(t.get_value(dut.dout)) # read out the pfd offset pfd_offset = t.get_value(dut.pfd_offset) # run a few extra cycles for better visibility t.step(10) ################## # run simulation # ################## t.compile_and_run(target='system-verilog', simulator=simulator_name, ext_srcs=get_deps_cpu_sim(cell_name=dut.name), parameters={ 'Nadc': Nadc, 'Nrange': Nrange }, ext_model_file=True, disp_type='realtime', dump_waveforms=False, directory=BUILD_DIR, num_cycles=1e12) ################## # convert values # ################## def to_signed(x, n): if x >= (1 << (n - 1)): return x - (1 << n) else: return x pfd_offset = to_signed(pfd_offset.value, Nadc) print('pfd_offset', pfd_offset) data_out = [to_signed(elem.value, Nadc) for elem in data_out] ################ # check values # ################ assert int_is_close(pfd_offset, offset), 'Estimated pfd_offset is wrong.' for x, y in zip(data_in[-1000:], data_out[-1000:]): assert int_is_close(x, y), 'Mismatch in input and output data' ################### # declare success # ################### print('Success!')