docs: def run_simulation(argument_list=None):  # noqa: C901
      """
      This is effectively the main function of a typical simulation run. Arguments passed in are
      parsed and used to construct and run the simulation.
  
      This function only exits when the program has completed or is interrupted.
  
      :param argument_list: Argument list to pass to the argument parser declared in this module.
      """
      try:
          arguments = parser.parse_args(argument_list or sys.argv[1:])
  
          if arguments.version:
              print(__version__)
              return
  
          if arguments.relaxed_versions:
              print('Unknown option --relaxed-versions. Did you mean --ignore-versions?')
              return
  
          loglevel = 'debug' if arguments.verify else arguments.output_level
          if loglevel != 'none':
              logging.basicConfig(
                  level=getattr(logging, loglevel.upper()), format=default_log_format)
  
          if arguments.add_path is not None:
              additional_path = os.path.abspath(arguments.add_path)
              logging.getLogger().debug('Extending path with: %s', additional_path)
              sys.path.append(additional_path)
  
          strict_versions = use_strict_versions(arguments.strict_versions, arguments.ignore_versions)
  
          simulation_factory = SimulationFactory(arguments.device_package, strict_versions)
  
          if not arguments.device:
              devices = ['Please specify a device to simulate. The following devices are available:']
  
              for dev in simulation_factory.devices:
                  devices.append('    ' + dev)
  
              print('\n'.join(devices))
              return
  
          if arguments.list_protocols:
              print('\n'.join(simulation_factory.get_protocols(arguments.device)))
              return
  
          protocols = parse_adapter_options(arguments.adapter_options) \
              if not arguments.no_interface else {}
  
          simulation = simulation_factory.create(
              arguments.device, arguments.setup, protocols, arguments.rpc_host)
  
          if arguments.show_interface:
              print(simulation._adapters.documentation())
              return
  
          if arguments.list_adapter_options:
              configurations = simulation._adapters.configuration()
  
              for protocol, options in configurations.items():
                  print('{}:'.format(protocol))
  
                  for opt, val in options.items():
                      print('    {} = {}'.format(opt, val))
  
              return
  
          simulation.cycle_delay = arguments.cycle_delay
          simulation.speed = arguments.speed
  
          if not arguments.verify:
              try:
                  simulation.start()
              except KeyboardInterrupt:
                  print('\nInterrupt received; shutting down. Goodbye, cruel world!')
                  simulation.log.critical('Simulation aborted by user interaction')
              finally:
                  simulation.stop()
  
      except LewisException as e:
          print('\n'.join(('An error occurred:', str(e))))