def test_root_buffering(parser): """Make sure that nodes with two inputs where only one of the inputs is a root node gets an unbuffered node in between. Furthermore, check that after topographic sorting, the root nodes are all at the top.""" parser.parse_file(get_path(u'basic_root_buffering.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) assert len(sg.nodes) == 21 #This check is to ensure that all root (input) nodes at the beginning after sorting. root_node_section_passed = False for node in sg.nodes: if not root_node_section_passed: if 'input' not in str(node): root_node_section_passed = True else: assert 'input' not in str(node) # Now make sure it produces the right output output11 = log.create_walker(DataStreamSelector.FromString('output 11')) output12 = log.create_walker(DataStreamSelector.FromString('output 12')) output13 = log.create_walker(DataStreamSelector.FromString('output 13')) output14 = log.create_walker(DataStreamSelector.FromString('output 14')) output15 = log.create_walker(DataStreamSelector.FromString('output 15')) sg.load_constants() sim = SensorGraphSimulator(sg) sim.stop_condition('run_time 20 minutes') sim.stimulus("1 minute: input 1 = 1") sim.stimulus("1 minute: input 2 = 1") sim.stimulus("11 minute: input 1 = 2") sim.run() sg.load_constants() print([str(x) for x in log._last_values.keys()]) assert output11.count() == 2 assert output12.count() == 2 assert output13.count() == 2 assert output14.count() == 2 assert output15.count() == 1
def test_tick1(tick1_sg): """Make sure we receive tick_1 ticks in the simulation.""" assert tick1_sg.get_tick('user1') == 2 sim = SensorGraphSimulator(tick1_sg) sim.stop_condition('run_time 100 seconds') sim.run() # Make sure the sensor graph ran correctly last_input = tick1_sg.sensor_log.inspect_last( DataStream.FromString('system input 5')) last_output = tick1_sg.sensor_log.inspect_last( DataStream.FromString('counter 1')) assert last_input.value == 100 assert last_output.value == 100 sim.run() # Make sure the sensor graph ran correctly last_input = tick1_sg.sensor_log.inspect_last( DataStream.FromString('system input 5')) last_output = tick1_sg.sensor_log.inspect_last( DataStream.FromString('counter 1')) assert last_input.value == 200 assert last_output.value == 200
def test_copy_constant_statement(parser): """Make sure we can copy constant values.""" parser.parse_file(get_path(u'basic_copy_constant.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) sg.load_constants() output1 = log.create_walker(DataStreamSelector.FromString('output 1')) sim = SensorGraphSimulator(sg) sim.stop_condition('run_time 10 seconds') sim.run() assert output1.count() == 1 assert output1.pop().value == 15 sim.step(DataStream.FromString('input 1'), 10) assert output1.count() == 1 assert output1.pop().value == 0x10
def test_multiple_run_calls(callrpc_sg): """Make sure we can call run multiple times.""" sim = SensorGraphSimulator(callrpc_sg) sim.stop_condition('run_time 100 seconds') sim.run() # Make sure the sensor graph ran correctly last_input = callrpc_sg.sensor_log.inspect_last( DataStream.FromString('system input 2')) last_output = callrpc_sg.sensor_log.inspect_last( DataStream.FromString('unbuffered 2')) assert last_input.value == 100 assert last_output.value == 0 sim.run() # Make sure the sensor graph ran correctly last_input = callrpc_sg.sensor_log.inspect_last( DataStream.FromString('system input 2')) last_output = callrpc_sg.sensor_log.inspect_last( DataStream.FromString('unbuffered 2')) assert last_input.value == 200 assert last_output.value == 0
def test_copy_count_statement(parser): """Make sure we can copy data count using copy count.""" parser.parse_file(get_path(u'count.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) sg.load_constants() output = log.create_walker(DataStreamSelector.FromString('output 1')) sim = SensorGraphSimulator(sg) sim.stop_condition('run_time 3 seconds') sim.step(user_connected, 8) # Simulates a connected user sim.run() print(output) assert output.count() == 1 print(output)
def test_copy_statement(parser): """Make sure we can copy data using copy.""" parser.parse_file(get_path(u'basic_copy.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) sg.load_constants() output1 = log.create_walker(DataStreamSelector.FromString('output 1')) output2 = log.create_walker(DataStreamSelector.FromString('output 2')) output3 = log.create_walker(DataStreamSelector.FromString('output 3')) sim = SensorGraphSimulator(sg) sim.stop_condition('run_time 60 seconds') sim.run() assert output1.count() == 1 assert output2.count() == 1 assert output3.count() == 1 val1 = output1.pop() val2 = output2.pop() val3 = output3.pop() assert val1.value == 0 assert val2.value == 60 assert val3.value == 1
def test_every_block_compilation(parser): """Make sure we can compile a simple every block.""" parser.parse_file(get_path(u'basic_every_1min.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) assert len(sg.nodes) == 7 sg.load_constants() # Now make sure it produces the right output counter15 = log.create_walker(DataStreamSelector.FromString('counter 15')) counter16 = log.create_walker(DataStreamSelector.FromString('counter 16')) sim = SensorGraphSimulator(sg) sim.stop_condition('run_time 120 seconds') sim.run() assert counter15.count() == 2 assert counter16.count() == 2
def test_on_block(parser): """Make sure on count(stream), on value(stream) and on stream work.""" parser.parse_file(get_path(u'basic_on.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) sg.load_constants() counter1 = log.create_walker(DataStreamSelector.FromString('counter 1')) counter2 = log.create_walker(DataStreamSelector.FromString('counter 2')) counter3 = log.create_walker(DataStreamSelector.FromString('counter 3')) sim = SensorGraphSimulator(sg) sim.step(DataStream.FromString('input 1'), 8) assert counter1.count() == 0 assert counter2.count() == 0 assert counter3.count() == 0 for i in range(0, 10): sim.step(DataStream.FromString('input 1'), 5) assert counter1.count() == 10 assert counter2.count() == 5 assert counter3.count() == 5
def test_when_block_on_event(parser): """Make sure on connect and on disconnect work.""" parser.parse_file(get_path(u'basic_when_on.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) sg.load_constants() sim = SensorGraphSimulator(sg) # We should only get a reading in unbuffered 1 on connect and unbuffered 2 on disconnect with pytest.raises(StreamEmptyError): log.inspect_last(DataStream.FromString('unbuffered 2')) sim.step(DataStream.FromString('system input 1025'), 8) assert log.inspect_last(DataStream.FromString('unbuffered 1')).value == 0 with pytest.raises(StreamEmptyError): log.inspect_last(DataStream.FromString('unbuffered 2')) sim.step(DataStream.FromString('system input 1026'), 8) assert log.inspect_last(DataStream.FromString('unbuffered 2')).value == 0
def test_every_block_with_buffering(parser): """Make sure we can compile and simulate an every block with buffered data.""" parser.parse_file(get_path(u'basic_output.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) assert len(sg.nodes) == 7 sg.load_constants() # Now make sure it produces the right output output1 = log.create_walker(DataStreamSelector.FromString('output 1')) buffered1 = log.create_walker(DataStreamSelector.FromString('buffered 1')) sim = SensorGraphSimulator(sg) sim.stop_condition('run_time 120 seconds') sim.run() assert output1.count() == 12 assert buffered1.count() == 12
def test_every_block_splitting(parser): """Make sure we can split nodes in an every block.""" parser.parse_file(get_path(u'basic_every_split.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) assert len(sg.nodes) == 10 # Now make sure it produces the right output counter15 = log.create_walker(DataStreamSelector.FromString('counter 15')) counter16 = log.create_walker(DataStreamSelector.FromString('counter 16')) counter17 = log.create_walker(DataStreamSelector.FromString('counter 16')) counter18 = log.create_walker(DataStreamSelector.FromString('counter 16')) sg.load_constants() sim = SensorGraphSimulator(sg) sim.stop_condition('run_time 120 seconds') sim.run() sg.load_constants() print([str(x) for x in log._last_values.keys()]) assert counter15.count() == 2 assert counter16.count() == 2 assert counter17.count() == 2 assert counter18.count() == 2
def test_rpc_sim(callrpc_sg): """Make sure we can run a very simple sensor graph and have it work.""" sim = SensorGraphSimulator(callrpc_sg) sim.stop_condition('run_time 1000 seconds') sim.run() # Make sure the sensor graph ran correctly last_input = callrpc_sg.sensor_log.inspect_last( DataStream.FromString('system input 2')) last_output = callrpc_sg.sensor_log.inspect_last( DataStream.FromString('unbuffered 2')) assert last_input.value == 1000 assert last_output.value == 0
def test_user_tick_optimization(usertick_gate, usertick_gate_opt): """Make sure the optimized version runs identically to the unoptimized.""" sg, sg_opt = usertick_gate, usertick_gate_opt for node in sg_opt.nodes: print(node) sim1 = SensorGraphSimulator(sg) sim1.stop_condition("run_time 10 minutes") sg.load_constants() sim1.record_trace() sim1.run() sim2 = SensorGraphSimulator(sg_opt) sim2.stop_condition("run_time 10 minutes") sg_opt.load_constants() sim2.record_trace() sim2.run() assert len(sim1.trace) == 0 assert len(sim2.trace) == 0 sim1.step(DataStream.FromString("system input 1034"), 1) sim2.step(DataStream.FromString("system input 1034"), 1) sim1.run() sim2.run() print("Unoptimized Output") for x in sim1.trace: print("%08d %s: %d" % (x.raw_time, DataStream.FromEncoded(x.stream), x.value)) print("\nOptimized Output") for x in sim2.trace: print("%08d %s: %d" % (x.raw_time, DataStream.FromEncoded(x.stream), x.value)) assert len(sim1.trace) == 4 assert len(sim2.trace) == 4 assert sim1.trace == sim2.trace
def test_complex_gate_optimization(complex_gate, complex_gate_opt): """Make sure the optimized version runs identically to the unoptimized.""" sg, sg_opt = complex_gate, complex_gate_opt sim1 = SensorGraphSimulator(sg) sim1.stop_condition("run_time 10 minutes") sg.load_constants() sim1.record_trace() sim1.run() sim2 = SensorGraphSimulator(sg_opt) sim2.stop_condition("run_time 10 minutes") sg_opt.load_constants() sim2.record_trace() sim2.run() assert len(sim1.trace) == 0 assert len(sim2.trace) == 0 sim1.step(DataStream.FromString("system input 1034"), 1) sim2.step(DataStream.FromString("system input 1034"), 1) sim1.run() sim2.run() print("Unoptimized Output") for x in sim1.trace: print("%08d %s: %d" % (x.raw_time, DataStream.FromEncoded(x.stream), x.value)) print("\nOptimized Output") for x in sim2.trace: print("%08d %s: %d" % (x.raw_time, DataStream.FromEncoded(x.stream), x.value)) assert len(sim1.trace) == 4 assert len(sim2.trace) == 4 assert sim1.trace == sim2.trace #Check that number of trigger streamer commands is same for optimized and unoptimized trigger_nodes = [ node for node in complex_gate.nodes if node.func_name == 'trigger_streamer' ] trigger_nodes_opt = [ node for node in complex_gate_opt.nodes if node.func_name == 'trigger_streamer' ] assert len(trigger_nodes) == len(trigger_nodes_opt)
def test_on_block_dual(parser): """Make sure on with two conditions works.""" parser.parse_file(get_path(u'basic_on_dual.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) sg.load_constants() counter1 = log.create_walker(DataStreamSelector.FromString('counter 1')) sim = SensorGraphSimulator(sg) sim.step(DataStream.FromString('input 1'), 5) assert counter1.count() == 0 sim.step(DataStream.FromString('input 2'), 1) for _i in range(0, 10): sim.step(DataStream.FromString('input 1'), 5) assert counter1.count() == 11 sim.step(DataStream.FromString('input 2'), 0) for _i in range(0, 10): sim.step(DataStream.FromString('input 1'), 5) assert counter1.count() == 11
def test_latch_block(parser): """Make sure that we can compile and run latch blocks.""" parser.parse_file(get_path(u'basic_latch.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) sg.load_constants() assert sg.get_tick('fast') == 1 # Now make sure it produces the right output counter15 = log.create_walker(DataStreamSelector.FromString('counter 15')) sim = SensorGraphSimulator(sg) sim.stop_condition('run_time 60 seconds') sim.run() assert counter15.count() == 0 sim.step(DataStream.FromString('input 10'), 1) assert log.inspect_last(DataStream.FromString('constant 1')).value == 1 assert log.inspect_last(DataStream.FromString('constant 1024')).value == 1 counter15.skip_all() sim.run() assert counter15.count() == 60 counter15.skip_all() sim.step(DataStream.FromString('input 10'), 0) sim.run() assert counter15.count() == 0
def main(argv=None): """Main entry point for iotile sensorgraph simulator. This is the iotile-sgrun command line program. It takes an optional set of command line parameters to allow for testing. Args: argv (list of str): An optional set of command line parameters. If not passed, these are taken from sys.argv. """ if argv is None: argv = sys.argv[1:] try: executor = None parser = build_args() args = parser.parse_args(args=argv) model = DeviceModel() parser = SensorGraphFileParser() parser.parse_file(args.sensor_graph) parser.compile(model) if not args.disable_optimizer: opt = SensorGraphOptimizer() opt.optimize(parser.sensor_graph, model=model) graph = parser.sensor_graph sim = SensorGraphSimulator(graph) for stop in args.stop: sim.stop_condition(stop) for watch in args.watch: watch_sel = DataStreamSelector.FromString(watch) graph.sensor_log.watch(watch_sel, watch_printer) # If we are semihosting, create the appropriate executor connected to the device if args.semihost_device is not None: executor = SemihostedRPCExecutor(args.port, args.semihost_device) sim.rpc_executor = executor for mock in args.mock_rpc: slot, rpc_id, value = process_mock_rpc(mock) sim.rpc_executor.mock(slot, rpc_id, value) for stim in args.stimulus: sim.stimulus(stim) graph.load_constants() if args.trace is not None: sim.record_trace() try: if args.connected: sim.step(user_connected, 8) sim.run(accelerated=not args.realtime) except KeyboardInterrupt: pass if args.trace is not None: sim.trace.save(args.trace) finally: if executor is not None: executor.hw.close() return 0
def test_when_block_clock(parser): """Make sure we can compile when blocks (without identifiers).""" parser.parse_file(get_path(u'basic_when.sgf')) model = DeviceModel() parser.compile(model=model) sg = parser.sensor_graph log = sg.sensor_log for x in sg.dump_nodes(): print(x) sg.load_constants() assert sg.get_tick('fast') == 1 # Now make sure it produces the right output counter15 = log.create_walker(DataStreamSelector.FromString('counter 15')) sim = SensorGraphSimulator(sg) sim.stop_condition('run_time 60 seconds') sim.run() assert counter15.count() == 0 sim.step(DataStream.FromString('system input 1025'), 8) assert counter15.count() == 1 counter15.skip_all() sim.run() assert counter15.count() == 60 counter15.skip_all() sim.step(DataStream.FromString('system input 1026'), 8) sim.run() assert counter15.count() == 0