def test_log(config): config['sim.log.enable'] = True simulate(config, TopTest) log_path = os.path.join(config['sim.workspace'], config['sim.log.file']) assert os.path.exists(log_path) last_line = open(log_path).readlines()[-1] assert last_line == 'INFO 9.000 us: top.container: 1\n'
def test_vcd_persist(config): config['sim.vcd.enable'] = True config['sim.vcd.persist'] = False simulate(config, TopTest) dump_path = os.path.join(config['sim.workspace'], config['sim.vcd.dump_file']) assert not os.path.exists(dump_path)
def test_log_stderr(config, capsys): config['sim.log.enable'] = True config['sim.log.file'] = '' simulate(config, TopTest) out, err = capsys.readouterr() assert out == '' assert err.endswith('INFO 9.000 us: top.container: 1\n')
def test_sim_invalid_result_format(config): config['sim.result.file'] = 'result.bogus' with pytest.raises(ValueError): simulate(config, TopTest) result = simulate(config, TopTest, reraise=False) assert result['sim.exception'] is not None
def test_db(config): config['sim.db.enable'] = True simulate(config, TopTest) db_path = os.path.join(config['sim.workspace'], config['sim.db.file']) assert os.path.exists(db_path) db = sqlite3.connect(db_path) assert db.execute('SELECT COUNT() FROM trace').fetchone()[0] == 15
def demo_15_db_include_pat(config, factors=None): dir1 = os.getcwd() dst = '.resource' create_dir(dst) # copy db file created in demo_13 fdb = 'sim_13_db.sqlite' src = dir1 + '/' + config['sim.workspace'] + '/' + fdb dir2 = dir1 + '/' + dst dst = dir2 + '/' + fdb dst = copy_file(src, dst) assert os.path.exists(dst) db_dir, db_file = os.path.split(dst) config['sim.result.file'] = 'result_15_db_include_pat.yaml' config['sim.db.file'] = db_file config['sim.db.enable'] = True config['sim.db.include_pat'] = [db_dir] if factors: simulate_factors(config, factors, Top) else: simulate(config, Top) # TODO: verify sim updated db file timestamp # assert test used in demo_13 db = sqlite3.connect(dst) assert db.execute('SELECT COUNT() FROM trace').fetchone()[0] == 15
def test_log_persist(config): config['sim.log.enable'] = True config['sim.log.persist'] = False simulate(config, TopTest) log_path = os.path.join(config['sim.workspace'], config['sim.log.file']) assert not os.path.exists(log_path) config['sim.log.file'] = '' simulate(config, TopTest)
def test_vcd_timescale(config): config['sim.vcd.enable'] = True config['sim.vcd.timescale'] = '10 s' simulate(config, TopTest) dump_path = os.path.join(config['sim.workspace'], config['sim.vcd.dump_file']) with open(dump_path) as dump: vcd_str = dump.read() assert '$timescale 10 s' in vcd_str
def test_vcd_stop(config): config['sim.vcd.enable'] = True config['sim.vcd.stop_time'] = '5 us' simulate(config, TopTest) dump_path = os.path.join(config['sim.workspace'], config['sim.vcd.dump_file']) with open(dump_path) as dump: vcd_str = dump.read() assert 'dumpoff' in vcd_str assert '#6' not in vcd_str
def test_exception(config): config['sim.log.enable'] = True config['test.raise'] = True with pytest.raises(Exception): simulate(config, TopTest) log_path = os.path.join(config['sim.workspace'], config['sim.log.file']) assert os.path.exists(log_path) with open(log_path) as f: log = f.read() assert 'ERROR' in log
def test_vcd(config): config['sim.vcd.enable'] = True simulate(config, TopTest) dump_path = os.path.join(config['sim.workspace'], config['sim.vcd.dump_file']) assert os.path.exists(dump_path) with open(dump_path) as dump: vcd_str = dump.read() for t in range(1, 11): assert '#{}\n'.format(t) in vcd_str
def test_defaults(config): simulate(config, TopTest) workspace = config['sim.workspace'] assert os.path.isdir(workspace) assert os.path.exists(os.path.join(workspace, config['sim.result.file'])) for filename_key in ['sim.log.file', 'sim.vcd.dump_file', 'sim.vcd.gtkw_file']: assert not os.path.exists(os.path.join(workspace, config[filename_key]))
def test_workspace_env_init(config): class TestEnvironment(SimEnvironment): def __init__(self, config): super().__init__(config) assert os.path.split(os.getcwd())[-1] == config['sim.workspace'] workspace = config['sim.workspace'] assert not os.path.exists(workspace) simulate(config, TopTest, TestEnvironment) assert os.path.exists(workspace)
def test_defaults(config): simulate(config, TopTest) workspace = config['sim.workspace'] assert os.path.isdir(workspace) assert os.path.exists(os.path.join(workspace, config['sim.result.file'])) for filename_key in [ 'sim.log.file', 'sim.vcd.dump_file', 'sim.vcd.gtkw_file', 'sim.db.file' ]: assert not os.path.exists(os.path.join(workspace, config[filename_key]))
def demo_14_db_persist(config, factors=None): config['sim.result.file'] = 'result_14_db_persist.yaml' config['sim.db.file'] = 'sim_14_db_persist.sqlite' config['sim.db.enable'] = True config['sim.db.persist'] = False if factors: simulate_factors(config, factors, Top) else: simulate(config, Top) db_path = os.path.join(config['sim.workspace'], config['sim.db.file']) assert not os.path.exists(db_path)
def demo_13_db(config, factors=None): config['sim.result.file'] = 'result_13_db.yaml' config['sim.db.file'] = 'sim_13_db.sqlite' config['sim.db.enable'] = True if factors: simulate_factors(config, factors, Top) else: simulate(config, Top) db_path = os.path.join(config['sim.workspace'], config['sim.db.file']) assert os.path.exists(db_path) db = sqlite3.connect(db_path) assert db.execute('SELECT COUNT() FROM trace').fetchone()[0] == 15
def demo_12_vcd_persist(config, factors=None): config['sim.result.file'] = 'result_12_vcd_persist.yaml' config['sim.vcd.dump_file'] = 'sim_12_vcd_persist.vcd' config['sim.vcd.enable'] = True config['sim.vcd.persist'] = False if factors: simulate_factors(config, factors, Top) else: simulate(config, Top) dump_path = os.path.join(config['sim.workspace'], config['sim.vcd.dump_file']) assert not os.path.exists(dump_path)
def test_workspace_is_curdir(config): config['sim.workspace'] = '.' config['sim.workspace.overwrite'] = True config['sim.result.file'] = 'first-result.yaml' simulate(config, TopTest) assert os.path.exists('first-result.yaml') config['sim.workspace.overwrite'] = True config['sim.result.file'] = 'second-result.yaml' simulate(config, TopTest) # '.' is not supposed to be overwritten assert os.path.exists('first-result.yaml') assert os.path.exists('second-result.yaml')
def demo_03_log(config, factors=None): config['sim.result.file'] = 'result_03_log.yaml' config['sim.log.file'] = 'sim_03_log.log' config['test.raise'] = False config['sim.log.enable'] = True if factors: simulate_factors(config, factors, Top) else: simulate(config, Top) log_path = os.path.join(config['sim.workspace'], config['sim.log.file']) assert os.path.exists(log_path) last_line = open(log_path).readlines()[-1] assert last_line == 'INFO 9.000 us: top.container: 1\n'
def demo_05_log_persist(config, factors=None): config['sim.result.file'] = 'result_05_log_persist.yaml' config['sim.log.file'] = 'sim_05_log_persist.log' config['sim.log.enable'] = True config['sim.log.persist'] = False if factors: simulate_factors(config, factors, Top) else: simulate(config, Top) log_path = os.path.join(config['sim.workspace'], config['sim.log.file']) assert not os.path.exists(log_path) config['sim.log.file'] = '' simulate(config, Top)
def test_sim_until(config, progress_enable): class TestEnvironment(SimEnvironment): def __init__(self, config): super().__init__(config) self.until = SimStopEvent(self) config['sim.progress.enable'] = progress_enable config['test.until_delay'] = 0 result = simulate(config, TopTest, TestEnvironment) assert result['sim.now'] == 0.50 config['test.until_delay'] = 0.25 result = simulate(config, TopTest, TestEnvironment) assert result['sim.now'] == 0.75
def demo_11_vcd_timescale(config, factors=None): config['sim.result.file'] = 'result_11_vcd_timescale.yaml' config['sim.vcd.dump_file'] = 'sim_11_vcd_timescale.vcd' config['sim.vcd.enable'] = True config['sim.vcd.timescale'] = '10 s' if factors: simulate_factors(config, factors, Top) else: simulate(config, Top) dump_path = os.path.join(config['sim.workspace'], config['sim.vcd.dump_file']) with open(dump_path) as dump: vcd_str = dump.read() assert '$timescale 10 s' in vcd_str
def demo_01_defaults(config, factors=None): config['sim.result.file'] = 'result_01_defaults.yaml' if factors: simulate_factors(config, factors, Top) else: simulate(config, Top) workspace = config['sim.workspace'] assert os.path.isdir(workspace) assert os.path.exists(os.path.join(workspace, config['sim.result.file'])) for filename_key in [ 'sim.log.file', 'sim.vcd.dump_file', 'sim.vcd.gtkw_file', 'sim.db.file' ]: assert not os.path.exists(os.path.join(workspace, config[filename_key]))
def demo_06_vcd(config, factors=None): config['sim.result.file'] = 'result_06_vcd.yaml' config['sim.vcd.dump_file'] = 'sim_06_vcd.vcd' config['sim.vcd.enable'] = True if factors: simulate_factors(config, factors, Top) else: simulate(config, Top) dump_path = os.path.join(config['sim.workspace'], config['sim.vcd.dump_file']) assert os.path.exists(dump_path) with open(dump_path) as dump: vcd_str = dump.read() for t in range(1, 11): assert '#{}\n'.format(t) in vcd_str
def demo_08_vcd_stop(config, factors=None): config['sim.result.file'] = 'result_08_vcd_stop.yaml' config['sim.vcd.dump_file'] = 'sim_08_vcd_stop.vcd' config['sim.vcd.enable'] = True config['sim.vcd.stop_time'] = '5 us' if factors: simulate_factors(config, factors, Top) else: simulate(config, Top) dump_path = os.path.join(config['sim.workspace'], config['sim.vcd.dump_file']) with open(dump_path) as dump: vcd_str = dump.read() assert 'dumpoff' in vcd_str assert '#6' not in vcd_str
def test_sim_time(config): config['sim.timescale'] = '10 ms' config['sim.duration'] = '995 ms' result = simulate(config, TopTest) assert result['sim.time'] == 0.995 assert result['sim.now'] == 99.5 assert result['time_100ps'] == 9950000000
def demo_04_log_stderr(config, factors=None): config['sim.result.file'] = 'result_04_log_stderr.yaml' config['sim.log.enable'] = True config['sim.log.file'] = '' old_stdout = sys.stdout old_stderr = sys.stderr redirected_output = sys.stdout = StringIO() redirected_error = sys.stderr = StringIO() ns_globals = {} ns_locals = {} out, err, exc = None, None, None try: if factors: exec(simulate_factors(config, factors, Top), ns_globals, ns_locals) else: exec(simulate(config, Top), ns_globals, ns_locals) except: import traceback exc = traceback.format_exc() out = redirected_output.getvalue() err = redirected_error.getvalue() assert out == '' assert err.endswith('INFO 9.000 us: top.container: 1\n') # reset outputs to the original values sys.stdout = old_stdout sys.stderr = old_stderr
def test_sim_result_format(config, ext, parser): config['sim.result.file'] = 'result.' + ext config['sim.config.file'] = 'config.' + ext result = simulate(config, TopTest) workspace = config['sim.workspace'] with open(os.path.join(workspace, config['sim.result.file'])) as f: assert parser(f) == result with open(os.path.join(workspace, config['sim.config.file'])) as f: assert parser(f) == config
def test_progress_enabled(config): config['sim.progress.enable'] = True result = simulate(config, TopTest) assert result['sim.exception'] is None assert result['sim.now'] == 1 assert result['sim.time'] == 1e-6 assert result['sim.runtime'] > 0 assert os.path.exists( os.path.join(config['sim.workspace'], config['sim.result.file']))
def demo_10_vcd_stop_then_start(config, factors=None): config['sim.result.file'] = 'result_10_vcd_stop_then_start.yaml' config['sim.vcd.dump_file'] = 'sim_10_vcd_stop_then_start.vcd' config['sim.vcd.enable'] = True config['sim.vcd.start_time'] = '6 us' config['sim.vcd.stop_time'] = '4 us' if factors: simulate_factors(config, factors, Top) else: simulate(config, Top) dump_path = os.path.join(config['sim.workspace'], config['sim.vcd.dump_file']) with open(dump_path) as dump: vcd_str = dump.read() assert 'dumpon' in vcd_str assert 'dumpoff' in vcd_str assert '#1\n' in vcd_str assert '#5' not in vcd_str assert '#9' in vcd_str
def test_pre_init_failure(config): config['test.fail_pre_init'] = True result = simulate(config, TopTest, reraise=False) assert result['sim.exception'] == repr(Exception('fail_pre_init')) assert result['sim.now'] == 0 assert result['sim.time'] == 0 assert result['sim.runtime'] > 0 assert result['config']['test.fail_pre_init'] assert os.path.exists( os.path.join(config['sim.workspace'], config['sim.result.file']))
def test_db_persist(config): config['sim.db.enable'] = True config['sim.db.persist'] = False simulate(config, TopTest) db_path = os.path.join(config['sim.workspace'], config['sim.db.file']) assert not os.path.exists(db_path)
# The various 'sim.xxx' keys are reserved for desmod while the remainder are # application-specific. config = { 'car.capacity': 50, 'car.level': [5, 25], 'gas_station.capacity': 200, 'gas_station.count': 3, 'gas_station.pump_rate': 2, 'gas_station.pumps': 2, 'gas_station.arrival_interval': 60, 'sim.duration': '500 s', 'sim.log.enable': True, 'sim.log.file': 'sim.log', 'sim.log.format': '{level:7} {ts:.3f} {ts_unit}: {scope:<16}:', 'sim.log.level': 'INFO', 'sim.result.file': 'results.yaml', 'sim.seed': 42, 'sim.timescale': 's', 'sim.workspace': '.', 'tanker.capacity': 200, 'tanker.count': 2, 'tanker.pump_rate': 10, 'tanker.travel_time': 100, } if __name__ == '__main__': # Desmod takes responsibility for instantiating and elaborating the model, # thus we only need to pass the configuration dict and the top-level # Component class (Top) to simulate(). simulate(config, Top)
def main(argv=None): """Command line interface for running grocery simulations. This function handles command line parsing, configuration setup, and launching simulations. """ parser = argparse.ArgumentParser() version = get_version() parser.add_argument( '--version', '-V', action='version', version=version, help='Show version and exit.') parser.add_argument( '--named', '-n', metavar='GROUP', dest='named_configs', action='append', default=[], help='Use named configuration %(metavar)s.') parser.add_argument( '--set', '-s', nargs=2, metavar=('KEY', 'VALUE'), action='append', default=[], dest='config_overrides', help='Override configuration KEY with VALUE expression.') parser.add_argument( '--factor', '-f', nargs=2, metavar=('KEYS', 'VALUES'), action='append', default=[], dest='factors', help='Add factorial KEYS with VALUES list of value expressions.') parser.add_argument( '--config', '-c', metavar='YAML', type=argparse.FileType('r'), action='append', default=[], dest='config_files', help='Read configuration from YAML file.') parser.add_argument( '--print-config', action='store_true', help='Print configuration and exit.') parser.add_argument( '--print-named', action='store_true', help='Print named configuration groups and exit.') extra_argv = shlex.split(os.environ.get('SB_EXTRA', '')) if argv is None: argv = sys.argv[1:] args = parser.parse_args(extra_argv + argv) if len(args.config_files) > 1 and args.factors: parser.error('argument --factor/-f: not allowed with multiple ' '--config/-c arguments') if args.print_named: print_named(named, sys.stdout) parser.exit() configs = [] try: if args.config_files: named_overrides = named.resolve(*args.named_configs) for config_file in args.config_files: config = named.resolve('default') apply_user_config(config, parse_config_file(config_file)) config.update(named_overrides) apply_user_overrides(config, args.config_overrides) configs.append(config) else: config = named.resolve('default', *args.named_configs) apply_user_overrides(config, args.config_overrides) configs.append(config) factors = parse_user_factors(configs[0], args.factors) except ConfigError as e: parser.error(str(e)) if args.print_config: yaml.safe_dump_all(configs, stream=sys.stdout) parser.exit() try: if len(configs) == 1: config = configs[0] if factors: results = simulate_factors(config, factors, Top, Environment) return check_errors(results) else: simulate(config, Top, Environment) else: results = simulate_many(configs, Top, Environment) return check_errors(results) except KeyboardInterrupt: print("\nInterrupted by user", file=sys.stderr) return 1
def test_db_in_memory(config): config['sim.db.enable'] = True config['sim.db.file'] = ':memory:' simulate(config, TopTest) db_path = os.path.join(config['sim.workspace'], config['sim.db.file']) assert not os.path.exists(db_path)