def test_declare_interface_polarity(): And2Decl = m.DeclareCircuit("And2", "I0", m.In(m.Bit), "I1", m.In(m.Bit), "O", m.Out(m.Bit)) And2Defn = m.DefineCircuit("And2", "I0", m.In(m.Bit), "I1", m.In(m.Bit), "O", m.Out(m.Bit)) assert And2Decl.interface.ports["I0"].isinput() == \ And2Defn.interface.ports["I0"].isinput()
def test_ext_vlog(target, simulator): tester = fault.Tester(m.DeclareCircuit('mytb')) tester.compile_and_run(target=target, simulator=simulator, ext_srcs=[Path('tests/verilog/mytb.sv').resolve()], ext_test_bench=True, tmp_dir=True)
def test_spice_port_order(): # declare a circuit with circ = m.DeclareCircuit('s', 'p', fault.ElectIn, 'i', m.BitIn, 'c', m.Out(m.Bits[3]), 'e', fault.RealOut) target = SpiceTarget(circ) ports = target.get_ordered_ports() assert ports == ['c<2>', 'c<1>', 'c<0>', 'e', 'i', 'p']
def test_get_value_analog(target, simulator): # declare circuit myblend = m.DeclareCircuit( 'myblend', 'a', fault.RealIn, 'b', fault.RealIn, 'c', fault.RealOut, ) # wrap if needed if target == 'verilog-ams': dut = fault.VAMSWrap(myblend) else: dut = myblend # create the tester tester = fault.Tester(dut) # define the test stim = [(5.6, 7.8), (-6.5, -8.7)] output = [] for a, b in stim: tester.poke(dut.a, a) tester.poke(dut.b, b) tester.delay(1e-6) output.append(tester.get_value(dut.c)) # set options kwargs = dict(target=target, simulator=simulator, tmp_dir=True) verilog_model = Path('tests/verilog/myblend.sv').resolve() spice_model = Path('tests/spice/myblend.sp').resolve() if target == 'verilog-ams': kwargs['model_paths'] = [spice_model] kwargs['use_spice'] = ['myblend'] elif target == 'spice': kwargs['model_paths'] = [spice_model] elif target == 'system-verilog': kwargs['ext_libs'] = [verilog_model] kwargs['ext_model_file'] = True # run the simulation tester.compile_and_run(**kwargs) # check the results using Python assertions def model(a, b): return (1.2 * b + 3.4 * a) / (1.2 + 3.4) for (a, b), c in zip(stim, output): lb = model(a, b) - 0.01 ub = model(a, b) + 0.01 assert lb <= c.value <= ub
def test_ext_vlog(target, simulator): # declare circuit myinv = m.DeclareCircuit('myinv', 'in_', m.In(m.Bit), 'out', m.Out(m.Bit)) # define test tester = fault.InvTester(myinv) # run the test tester.compile_and_run(target=target, simulator=simulator, ext_libs=[Path('tests/verilog/myinv.v').resolve()], ext_model_file=True, tmp_dir=True)
def test_inv_tf(target, simulator, vsup=1.5, vil_rel=0.4, vih_rel=0.6, vol_rel=0.1, voh_rel=0.9): #target = 'verilog-ams' #simulator = 'ncsim' target = 'spice' simulator = 'ngspice' # declare circuit myinv = m.DeclareCircuit('myinv', 'in_', fault.RealIn, 'out', fault.RealOut, 'vdd', fault.RealIn, 'vss', fault.RealIn) # wrap if needed if target == 'verilog-ams': dut = fault.VAMSWrap(myinv) else: dut = myinv # define the test tester = fault.Tester(dut) tester.poke(dut.vdd, vsup) tester.poke(dut.vss, 0) for k in [.4, .5, .6]: in_ = k * vsup tester.poke(dut.in_, in_) # We might not know the expected value now but will want to check later tester.expect(dut.out, 0, save_for_later=True) # set options kwargs = dict(target=target, simulator=simulator, model_paths=[Path('tests/spice/myinv.sp').resolve()], vsup=vsup, tmp_dir=True) if target == 'verilog-ams': kwargs['use_spice'] = ['myinv'] # run the simulation tester.compile_and_run(**kwargs) # look at the results we decided to save earlier results = tester.targets[target].saved_for_later a, b, c = results # now we can save these to a file, post-process them, or use them # for our own tests assert b <= a, "Inverter tf is not always decreasing" assert c <= b, "Inverter tf is not always decreasing"
def test_vams_wrap(): # declare the circuit myblk = m.DeclareCircuit('myblk', 'a', RealIn, 'b', RealOut, 'c', m.In(m.Bit), 'd', m.Out(m.Bits[2]), 'e', ElectIn, 'f', ElectOut) wrap_circ = VAMSWrap(myblk) # check magma representation of wrapped circuit assert wrap_circ.IO.ports['a'] is RealIn assert wrap_circ.IO.ports['b'] is RealOut assert wrap_circ.IO.ports['c'] is m.In(m.Bit) assert wrap_circ.IO.ports['d'] is m.Out(m.Bits[2]) assert wrap_circ.IO.ports['e'] is ElectIn assert wrap_circ.IO.ports['f'] is ElectOut # check Verilog-AMS code itself assert wrap_circ.vams_code == '''\
def test_unwired_ports_warnings(caplog): caplog.set_level(logging.WARN) And2 = m.DeclareCircuit('And2', "I0", m.In(m.Bit), "I1", m.In(m.Bit), "O", m.Out(m.Bit)) main = m.DefineCircuit("main", "I", m.In(m.Bits[2]), "O", m.Out(m.Bit)) and2 = And2() m.wire(main.I[1], and2.I1) m.EndCircuit() m.compile("build/test_unwired_output", main) assert check_files_equal(__file__, f"build/test_unwired_output.v", f"gold/test_unwired_output.v") assert caplog.records[-2].msg == "main.And2_inst0.I0 not connected" assert caplog.records[-1].msg == "main.O is unwired"
def test_str_repr_anon(): And2 = m.DeclareCircuit('And2', "I0", m.In(m.Bit), "I1", m.In(m.Bit), "O", m.Out(m.Bit)) circ = m.DefineCircuit("Test", "I0", m.In(m.Bits[3]), "I1", m.In(m.Bits[3]), "O", m.Out(m.Bits[3])) anon = m.join(m.map_(And2, 3)) m.wire(circ.I0, anon.I0) m.wire(circ.I1, anon.I1) m.wire(circ.O, anon.O) m.EndCircuit() string = str(anon) assert string[:len("AnonymousCircuitInst")] == "AnonymousCircuitInst" assert string[-len( "<I0: Array[3, In(Bit)], I1: Array[3, In(Bit)], O: Array[3, Out(Bit)]>" ):] == "<I0: Array[3, In(Bit)], I1: Array[3, In(Bit)], O: Array[3, Out(Bit)]>" assert repr( anon ) == 'AnonymousCircuitType("I0", array([And2_inst0.I0, And2_inst1.I0, And2_inst2.I0]), "I1", array([And2_inst0.I1, And2_inst1.I1, And2_inst2.I1]), "O", array([And2_inst0.O, And2_inst1.O, And2_inst2.O]))'
def test_inv_tf(target, simulator, n_steps=100, vsup=1.5, vil_rel=0.4, vih_rel=0.6, vol_rel=0.1, voh_rel=0.9): # declare circuit myinv = m.DeclareCircuit('myinv', 'in_', fault.RealIn, 'out', fault.RealOut, 'vdd', fault.RealIn, 'vss', fault.RealIn) # wrap if needed if target == 'verilog-ams': dut = fault.VAMSWrap(myinv) else: dut = myinv # define the test tester = fault.Tester(dut) tester.poke(dut.vdd, vsup) tester.poke(dut.vss, 0) for k in range(n_steps): in_ = k * vsup / (n_steps - 1) tester.poke(dut.in_, in_) tester.eval() if in_ <= vil_rel * vsup: tester.expect(dut.out, vsup, above=voh_rel * vsup) elif in_ >= vih_rel * vsup: tester.expect(dut.out, 0, below=vol_rel * vsup) # set options kwargs = dict(target=target, simulator=simulator, model_paths=[Path('tests/spice/myinv.sp').resolve()], vsup=vsup, tmp_dir=True) if target == 'verilog-ams': kwargs['use_spice'] = ['myinv'] # run the simulation tester.compile_and_run(**kwargs)
def definition(io): load = io.LOAD baud = rising(io.SCK) | falling(io.SCK) valid_counter = mantle.CounterModM(buf_size, 12, has_ce=True) m.wire(load & baud, valid_counter.CE) valid_list = [wi * (b - 1) + i * a - 1 for i in range(1, wo + 1)] # len = 32 valid = m.GND for i in valid_list: valid = valid | mantle.Decode(i, 12)(valid_counter.O) # register on input st_in = mantle.Register(width, has_ce=True) st_in(io.DATA) m.wire(load, st_in.CE) # --------------------------DOWNSCALING----------------------------- # # downscale the image from 352x288 to 32x32 Downscale = m.DeclareCircuit( 'Downscale', "I_0_0", m.In(m.Array(1, m.Array(1, m.Array(width, m.Bit)))), "WE", m.In(m.Bit), "CLK", m.In(m.Clock), "O", m.Out(m.Array(width, m.Bit)), "V", m.Out(m.Bit)) dscale = Downscale() m.wire(st_in.O, dscale.I_0_0[0][0]) m.wire(1, dscale.WE) m.wire(load, dscale.CLK) add16 = mantle.Add(width) # needed for Add16 definition # threshold the downscale output px_bit = mantle.ULE(16)(dscale.O, m.uint(THRESH, 16)) & valid # ---------------------------UART OUTPUT----------------------------- # m.wire(px_bit, io.O) m.wire(valid, io.VALID)
def test_real_val(target, simulator): # define the circuit realadd = m.DeclareCircuit('realadd', 'a_val', fault.RealIn, 'b_val', fault.RealIn, 'c_val', fault.RealOut) # define test content tester = fault.Tester(realadd) tester.poke(realadd.a_val, 1.125) tester.poke(realadd.b_val, 2.5) tester.expect(realadd.c_val, 3.625, abs_tol=1e-4) # run the test tester.compile_and_run( target=target, simulator=simulator, ext_libs=[Path('tests/verilog/realadd.sv').resolve()], defines={f'__{simulator.upper()}__': None}, ext_model_file=True, tmp_dir=True)
def test_spice_bus(target, simulator, vsup=1.5): # declare circuit dut = m.DeclareCircuit('mybus', 'a', m.In(m.Bits[2]), 'b', m.Out(m.Bits[3]), 'vdd', m.BitIn, 'vss', m.BitIn) # define the test tester = fault.Tester(dut) tester.poke(dut.vdd, 1) tester.poke(dut.vss, 0) # step through all possible inputs tester.poke(dut.a, 0b000) tester.expect(dut.b, 0b101) tester.poke(dut.a, 0b001) tester.expect(dut.b, 0b100) tester.poke(dut.a, 0b010) tester.expect(dut.b, 0b111) tester.poke(dut.a, 0b011) tester.expect(dut.b, 0b110) # test one bit of the bus at a time tester.poke(dut.a[0], 0) tester.expect(dut.b[0], 1) tester.poke(dut.a[0], 1) tester.expect(dut.b[0], 0) tester.expect(dut.b[2], 1) tester.poke(dut.a[1], 0) tester.expect(dut.b[1], 0) tester.poke(dut.a[1], 1) tester.expect(dut.b[1], 1) tester.expect(dut.b[2], 1) # set options kwargs = dict(target=target, simulator=simulator, model_paths=[Path('tests/spice/mybus.sp').resolve()], vsup=vsup, tmp_dir=True) # run the simulation tester.compile_and_run(**kwargs)
def test_2d_array_error(caplog): And2 = m.DeclareCircuit('And2', "I0", m.In(m.Bit), "I1", m.In(m.Bit), "O", m.Out(m.Bit)) main = m.DefineCircuit("main", "I", m.In(m.Array[2, m.Array[3, m.Bit]]), "O", m.Out(m.Bit)) and2 = And2() m.wire(main.I[1][0], and2.I1) m.EndCircuit() try: m.compile("build/test_unwired_output", main) assert False, "Should raise exception" except Exception as e: assert str( e ) == "Argument main.I of type Array[2, Array[3, Out(Bit)]] is not supported, the verilog backend only supports simple 1-d array of bits of the form Array(N, Bit)" # noqa
def run(noise=0.0): # declare circuit dut = m.DeclareCircuit( CIRCUIT_NAME, 'lbl', m.BitInOut, 'lblb', m.BitInOut, 'vdd', m.BitIn, 'vss', m.BitIn, 'wl', m.BitIn ) # instantiate the tester tester = fault.Tester(dut, poke_delay_default=0) # initialize tester.poke(dut.lbl, fault.HiZ) tester.poke(dut.lblb, fault.HiZ) tester.poke(dut.vdd, True) tester.poke(dut.vss, False) tester.poke(dut.wl, True) tester.delay(TD) # read back data, expecting "0" tester.expect(dut.lbl, False) tester.expect(dut.lblb, True) # specify initial conditions ic = {tester.internal('lbl_x'): noise, tester.internal('lblb_x'): VDD - noise, dut.lbl: VDD, dut.lblb: VDD} # run the test tester.compile_and_run( ic=ic, vsup=VDD, target='spice', simulator=SIMULATOR, model_paths=[CIRCUIT_PATH] )
def test_anon_value(target, suffix, T): And2 = m.DeclareCircuit('And2', "I0", m.In(T), "I1", m.In(T), "O", m.Out(T)) main = m.DefineCircuit("main", "I0", m.In(T), "I1", m.In(T), "O", m.Out(T)) and2 = And2() m.wire(main.I0, and2.I0) m.wire(main.I1, and2.I1) tmp = T() m.wire(and2.O, tmp) m.wire(tmp, main.O) m.EndCircuit() type_str = str(T).replace("[", "(").replace("]", ")") m.compile(f"build/test_anon_value_{type_str}", main, target) assert check_files_equal(__file__, f"build/test_anon_value_{type_str}.{suffix}", f"gold/test_anon_value_{type_str}.{suffix}")
def test_ngspice(): import magma as m import fault MyAmp = m.DeclareCircuit('myamp', 'in_', fault.RealIn, 'out', fault.RealOut, 'vdd', fault.RealIn, 'vss', fault.RealIn) tester = fault.Tester(MyAmp) tester.poke(MyAmp.vss, 0) tester.poke(MyAmp.vdd, 1.2) tester.poke(MyAmp.in_, 0.7) tester.expect(MyAmp.out, .81, above=0.81, below=0.82) tester.poke(MyAmp.in_, 0.8) tester.expect(MyAmp.out, .5, above=0.50, below=0.51) tester.compile_and_run( 'spice', simulator='ngspice', model_paths=[Path('tests/spice/myamp.sp').resolve()])
def test_while_loop(target, simulator, n_cyc=3, n_bits=8): dut = m.DeclareCircuit('clkdelay', 'clk', m.In(m.Clock), 'rst', m.In(m.Reset), 'count', m.Out(m.Bits[n_bits]), 'n_done', m.Out(m.Bit)) # instantiate the tester tester = fault.Tester(dut, clock=dut.clk, reset=dut.rst) tester.circuit.clk = 0 # reset tester.sync_reset() # check initial state tester.expect(dut.n_done, 1) tester.expect(dut.count, 0) # wait for the loop to complete tester.poke(dut.rst, 0) loop = tester._while(dut.n_done) debug_print(loop, dut) loop.step() loop.step() debug_print(tester, dut) # check final state tester.expect(dut.count, n_cyc - 1) tester.expect(dut.n_done, 0) # run the test tester.compile_and_run( target=target, simulator=simulator, tmp_dir=True, ext_libs=[Path('tests/verilog/clkdelay.sv').resolve()], ext_model_file=True, defines={ 'N_CYC': n_cyc, 'N_BITS': n_bits })
def test_init_cond(target, simulator, va=1.234, vb=2.345, vc=3.456, abs_tol=1e-3): # declare circuit mycirc = m.DeclareCircuit('my_init_cond', 'va', fault.RealOut, 'vb', fault.RealOut, 'vc', fault.RealOut) # wrap if needed if target == 'verilog-ams': dut = fault.VAMSWrap(mycirc) else: dut = mycirc # define the test tester = fault.Tester(dut) tester.delay(10e-9) tester.expect(dut.va, va, abs_tol=abs_tol) tester.expect(dut.vb, vb, abs_tol=abs_tol) tester.expect(dut.vc, vc, abs_tol=abs_tol) # set options ic = { dut.va: va, tester.internal('vb_x'): vb, tester.internal('Xe', 'vc_x'): vc } kwargs = dict(target=target, simulator=simulator, model_paths=[Path('tests/spice/my_init_cond.sp').resolve()], ic=ic, tmp_dir=True) if target == 'verilog-ams': kwargs['use_spice'] = ['my_init_cond'] # run the simulation tester.compile_and_run(**kwargs)
def sim(): # declare circuit dut = m.DeclareCircuit('myinv', 'in_', m.BitIn, 'out', m.BitOut, 'vdd', m.BitIn, 'vss', m.BitIn) # define the test t = fault.Tester(dut, poke_delay_default=0) t.zero_inputs() t.delay(1e-9) t.poke(dut.vdd, True, delay=2e-9) t.expect(dut.out, True) t.poke(dut.in_, True, delay=2e-9) t.expect(dut.out, False) # run the test t.compile_and_run(target='spice', simulator='ngspice', vsup=1.5, t_tr=1e-9, vil_rel=0.4, vih_rel=0.6, model_paths=[THIS_DIR / 'myinv.sp'])
def test_simple_def(target, suffix): m.set_codegen_debug_info(True) And2 = m.DeclareCircuit('And2', "I0", m.In(m.Bit), "I1", m.In(m.Bit), "O", m.Out(m.Bit)) main = m.DefineCircuit("main", "I", m.In(m.Bits[2]), "O", m.Out(m.Bit)) and2 = And2() m.wire(main.I[0], and2.I0) m.wire(main.I[1], and2.I1) m.wire(and2.O, main.O) m.EndCircuit() m.compile("build/test_simple_def", main, output=target) assert check_files_equal(__file__, f"build/test_simple_def.{suffix}", f"gold/test_simple_def.{suffix}") # Check that the subclassing pattern produces the same annotations class Main(m.Circuit): IO = ["I", m.In(m.Bits[2]), "O", m.Out(m.Bit)] @classmethod def definition(io): and2 = And2() m.wire(io.I[0], and2.I0) m.wire(io.I[1], and2.I1) m.wire(and2.O, io.O) # Create a fresh context for second compilation. m.compile("build/test_simple_def_class", Main, output=target, context=coreir.Context()) m.set_codegen_debug_info(False) assert check_files_equal(__file__, f"build/test_simple_def_class.{suffix}", f"gold/test_simple_def_class.{suffix}")
def test_include_verilog(target, simulator): SB_DFF = m.DeclareCircuit('SB_DFF', "D", m.In(m.Bit), "Q", m.Out(m.Bit), "C", m.In(m.Clock)) main = m.DefineCircuit('main', "I", m.In(m.Bit), "O", m.Out(m.Bit), *m.ClockInterface()) ff = SB_DFF() m.wire(ff.D, main.I) m.wire(ff.Q, main.O) m.EndDefine() tester = fault.Tester(main, main.CLK) tester.poke(main.CLK, 0) tester.poke(main.I, 1) tester.eval() tester.expect(main.O, 0) tester.step(2) tester.expect(main.O, 1) sb_dff_filename = pathlib.Path("tests/sb_dff_sim.v").resolve() kwargs = {} if simulator is not None: kwargs["simulator"] = simulator with tempfile.TemporaryDirectory(dir=".") as tmp_dir: tester.compile_and_run(target=target, directory=tmp_dir, include_verilog_libraries=[sb_dff_filename], **kwargs) if target in ["verilator"]: # Should work by including the tests/ directory which contains the # verilog file SB_DFF.v dir_path = os.path.dirname(os.path.realpath(__file__)) with tempfile.TemporaryDirectory(dir=".") as tmp_dir: tester.compile_and_run(target=target, directory=tmp_dir, include_directories=[dir_path], **kwargs)
def sim(): # declare circuit dut = m.DeclareCircuit('myinv', 'in_', fault.RealIn, 'out', fault.RealOut, 'vdd', fault.RealIn, 'vss', fault.RealIn) t = fault.Tester(dut, poke_delay_default=0) t.zero_inputs() t.poke(dut.vdd, 1.5, delay=2e-9) out = [] for in_ in np.linspace(0, 1.5, 100): t.poke(dut.in_, in_, delay=2e-9) out.append(t.get_value(dut.out)) # run the test t.compile_and_run(target='spice', simulator='ngspice', vsup=1.5, t_tr=1e-9, model_paths=[THIS_DIR / 'myinv.sp']) # extract outputs out = [elem.value for elem in out] return out
def DeclareFromSpice(file_name, subckt_name=None, mode='digital'): # parse the netlist spice_model_path = Path(file_name).resolve() parser = SimulatorNetlist(f'{spice_model_path}') # use the first subcircuit defined if none is specified if subckt_name is None: subckts = parser.get('subckts') if len(subckts) == 0: raise Exception( f'Could not find any circuit definitions in {file_name}.' ) # noqa else: subckt_name = parser.get('subckts')[0] # get the port list for the subcircuit search_name = f'{subckt_name}'.lower() ports = parser.get_subckt(search_name, detail='ports') # declare the circuit and return it args = [] args += [subckt_name] for port in ports: args += [f'{port}'] if mode == 'digital': args += [m.BitInOut] elif mode == 'analog': args += [RealInOut] else: raise ValueError(f'Unknown mode: {mode}') # Declare spice circuit and specify source location circuit = m.DeclareCircuit(*args) circuit.spice_model_path = spice_model_path # Return the circuit return circuit
def test_ngspice2(): import magma as m import fault MyAmpTest = m.DeclareCircuit('myamptest', 'in_', fault.RealIn, 'out', fault.RealOut, 'vdd', fault.RealIn, 'vsstest', fault.RealIn) class MyAmp(m.Circuit): name = 'myamp' # IO = [ # 'in_', fault.RealIn, # 'out', fault.RealOut, # 'vdd', fault.RealIn, # 'vss', fault.RealIn # ] io = m.IO(in_=fault.RealIn, out=fault.RealOut, vdd=fault.RealIn, vss=fault.RealIn) tester = fault.Tester(MyAmp) tester.poke(MyAmp.vss, 0) tester.poke(MyAmp.vdd, 1.2) tester.poke(MyAmp.in_, 0.7) tester.expect(MyAmp.out, .81, above=0.81, below=0.82) tester.delay(1e-3) tester.poke(MyAmp.in_, 0.8) tester.expect(MyAmp.out, .5, above=0.50, below=0.51) tester.compile_and_run( 'spice', simulator='ngspice', model_paths=[Path('tests/spice/myamp.sp').resolve()])
bit_counter = mantle.Counter(5, has_ce=True) m.wire(baud, bit_counter.CE) load = mantle.Decode(0, 5)(bit_counter.O) # # "test" data # init = [m.uint(i, 16) for i in range(16)] # printf = mantle.Counter(4, has_ce=True) # rom = ROM16(4, init, printf.O) # m.wire(load & baud, printf.CE) #---------------------------STENCILING-----------------------------# ReduceHybrid = m.DeclareCircuit('ReduceHybrid', 'I_0', m.In(m.Array(a, TIN)), 'I_1', m.In(m.Array(a, TIN)), 'O', TOUT, 'WE', m.BitIn, 'V', m.Out(m.Bit), 'CLK', m.In(m.Clock)) redHybrid = ReduceHybrid() m.wire(m.bits(0, 16), redHybrid.I_0[0]) m.wire(m.bits(1, 16), redHybrid.I_1[0]) m.wire(1, redHybrid.WE) m.wire(load, redHybrid.CLK) add16 = mantle.Add(16) # needed for Add16 definition # ---------------------------UART OUTPUT----------------------------- # uart_red = UART(16) uart_red(CLK=main.CLKIN, BAUD=baud, DATA=redHybrid.O, LOAD=load)
def definition(io): load = io.LOAD baud = rising(io.SCK) | falling(io.SCK) valid_counter = mantle.CounterModM(buf_size, 12, has_ce=True) m.wire(load & baud, valid_counter.CE) valid_list = [wi * (b - 1) + i * a - 1 for i in range(1, wo + 1)] # len = 32 valid = m.GND for i in valid_list: valid = valid | mantle.Decode(i, 12)(valid_counter.O) # register on input st_in = mantle.Register(width, has_ce=True) st_in(io.DATA) m.wire(load, st_in.CE) # --------------------------DOWNSCALING----------------------------- # # downscale the image from 352x288 to 32x32 Downscale = m.DeclareCircuit( 'Downscale', "I_0_0", m.In(m.Array(1, m.Array(1, m.Array(width, m.Bit)))), "WE", m.In(m.Bit), "CLK", m.In(m.Clock), "O", m.Out(m.Array(width, m.Bit)), "V", m.Out(m.Bit)) dscale = Downscale() m.wire(st_in.O, dscale.I_0_0[0][0]) m.wire(1, dscale.WE) m.wire(load, dscale.CLK) add16 = mantle.Add(width) # needed for Add16 definition # --------------------------FILL IMG RAM--------------------------- # # each valid output of dscale represents an entry of 32x32 binary image # accumulate each group of 32 entries into a 32-bit value representing a row col = mantle.CounterModM(32, 6, has_ce=True) col_ce = rising(valid) m.wire(col_ce, col.CE) # shift each bit in one at a time until we get an entire row px_bit = mantle.ULE(16)(dscale.O, m.uint(THRESH, 16)) & valid row_reg = mantle.SIPO(32, has_ce=True) row_reg(px_bit) m.wire(col_ce, row_reg.CE) # reverse the row bits since the image is flipped row = reverse(row_reg.O) rowaddr = mantle.Counter(6, has_ce=True) img_full = mantle.SRFF(has_ce=True) img_full(mantle.EQ(6)(rowaddr.O, m.bits(32, 6)), 0) m.wire(falling(col.COUT), img_full.CE) row_ce = rising(col.COUT) & ~img_full.O m.wire(row_ce, rowaddr.CE) waddr = rowaddr.O[:5] rdy = col.COUT & ~img_full.O pulse_count = mantle.Counter(2, has_ce=True) we = mantle.UGE(2)(pulse_count.O, m.uint(1, 2)) pulse_count(CE=(we|rdy)) # ---------------------------UART OUTPUT----------------------------- # row_load = row_ce row_baud = mantle.FF()(baud) uart_row = UART(32) uart_row(CLK=io.CLK, BAUD=row_baud, DATA=row, LOAD=row_load) uart_addr = UART(5) uart_addr(CLK=io.CLK, BAUD=row_baud, DATA=waddr, LOAD=row_load) m.wire(waddr, io.WADDR) m.wire(img_full, io.DONE) #img_full m.wire(uart_row, io.UART) #uart_st m.wire(row, io.O) m.wire(we, io.VALID) m.wire(valid, io.T0) m.wire(uart_addr, io.T1)
for i in valid_list: valid = valid | mantle.Decode(i, 13)(valid_counter.O) m.wire(load & baud, printf.CE) px_val = rom.O # register on input st_in = mantle.Register(16, has_ce=True) st_in(px_val) m.wire(load, st_in.CE) # ---------------------------STENCILING----------------------------- # Downscale = m.DeclareCircuit('Downscale', "I_0_0", m.In(m.Array(1, m.Array(1, m.Array(16, m.Bit)))), "WE", m.In(m.Bit), "CLK", m.In(m.Clock), "O", m.Out(m.Array(16, m.Bit)), "V", m.Out(m.Bit)) dscale = Downscale() m.wire(st_in.O, dscale.I_0_0[0][0]) m.wire(1, dscale.WE) m.wire(load, dscale.CLK) add16 = mantle.Add(16) # needed for Add16 definition # ---------------------------UART OUTPUT----------------------------- # uart_px = UART(16) uart_px(CLK=main.CLKIN, BAUD=baud, DATA=px_val, LOAD=load)
def DeclareAnd(width): T = m.util.BitOrBits(width) return m.DeclareCircuit(f'And{width}', "I0", m.In(T), "I1", m.In(T), "O", m.Out(T))
def test_sin_spice(vsup=1.5, vil_rel=0.4, vih_rel=0.6, vol_rel=0.1, voh_rel=0.9): # TODO make pytest choose target/simulator target = 'spice' simulator = 'ngspice' # declare circuit myinv = m.DeclareCircuit('myinv', 'in_', fault.RealIn, 'out', fault.RealOut, 'vdd', fault.RealIn, 'vss', fault.RealIn) # wrap if needed if target == 'verilog-ams': dut = fault.VAMSWrap(myinv) else: dut = myinv # define the test tester = fault.Tester(dut) tester.poke(dut.vdd, vsup) tester.poke(dut.vss, 0) freq = 1e3 tester.poke(dut.in_, 0, delay={ 'type': 'sin', 'freq': freq, 'amplitude': 0.4, 'offset': 0.6, 'phase_degrees': 90 }) num_reads = 100 xs = [] dt = 1 / (freq * 50) for k in range(num_reads): tester.expect(dut.in_, 0, save_for_later=True) tester.delay(dt) xs.append(k * dt) #for k in [.4, .5, .6]: # in_ = k * vsup # tester.poke(dut.in_, in_) # # We might not know the expected value now but will want to check later # tester.expect(dut.out, 0, save_for_later=True) # set options kwargs = dict(target=target, simulator=simulator, model_paths=[Path('tests/spice/myinv.sp').resolve()], vsup=vsup, tmp_dir=True, clock_step_delay=0) if target == 'verilog-ams': kwargs['use_spice'] = ['myinv'] # run the simulation tester.compile_and_run(**kwargs) ys = [] for k in range(num_reads): value = tester.targets[target].saved_for_later[k] ys.append(value) print('%2d\t' % k, value) plot(xs, ys)