awlsim-test 17.3 KB
Newer Older
Michael Büsch's avatar
Michael Büsch committed
1 2 3
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
4
# AWL simulator - Commandline testing interface
5
#
6
# Copyright 2012-2016 Michael Buesch <m@bues.ch>
Michael Büsch's avatar
Michael Büsch committed
7
#
8 9 10 11 12 13 14 15 16 17 18 19 20
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Michael Büsch's avatar
Michael Büsch committed
21 22
#

23 24
from __future__ import division, absolute_import, print_function, unicode_literals

25
import sys
26
import os
Michael Büsch's avatar
Michael Büsch committed
27
import getopt
28
import traceback
29
import signal
Michael Büsch's avatar
Michael Büsch committed
30

31 32 33
from awlsim_loader.common import *
from awlsim_loader.core import *
from awlsim_loader.coreclient import *
34
from awlsim_loader.awlcompiler import *
Michael Büsch's avatar
Michael Büsch committed
35
from awlsim_loader.fupcompiler import *
36
import awlsim_loader.cython_helper as cython_helper
Michael Büsch's avatar
Michael Büsch committed
37

Michael Büsch's avatar
Michael Büsch committed
38

39
class TestAwlSimClient(AwlSimClient):
40 41
	def handle_CPUDUMP(self, dumpText):
		emitCpuDump(dumpText)
Michael Büsch's avatar
Michael Büsch committed
42

43 44 45 46 47 48
class ConsoleSSHTunnel(SSHTunnel):
	def sshMessage(self, message, isDebug):
		if opt_loglevel > Logging.LOG_INFO:
			isDebug = False
		super(ConsoleSSHTunnel, self).sshMessage(message, isDebug)

Michael Büsch's avatar
Michael Büsch committed
49
def usage():
50 51
	print("awlsim version %s" % VERSION_STRING)
	print("")
52
	print("Usage: awlsim-test [OPTIONS] <AWL-source or awlsim-project file>")
53 54
	print("")
	print("Options:")
55
	print(" -Y|--cycle-limit SEC  Cycle time limit, in seconds (default 5.0)")
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
	print(" -M|--max-runtime SEC  CPU will be stopped after SEC seconds (default: off)")
	print(" -2|--twoaccu          Force 2-accu mode")
	print(" -4|--fouraccu         Force 4-accu mode")
	print(" -D|--no-cpu-dump      Do not show CPU status while running")
	print(" -x|--extended-insns   Enable extended instructions")
	print(" -t|--obtemp 1/0       Enable/disable writing of OB-temp variables (Default: off)")
	print(" -T|--clock-mem ADDR   Force clock memory address (Default: off)")
	print(" -m|--mnemonics auto   Force mnemonics type: en, de, auto")
	print(" -P|--profile 0        Set profiling level (Default: 0)")
	print(" -L|--loglevel LVL     Set the log level:")
	print("                       0: Log nothing")
	print("                       1: Log errors")
	print("                       2: Log errors and warnings")
	print("                       3: Log errors, warnings and info messages (default)")
	print("                       4: Verbose logging")
	print("                       5: Extremely verbose logging")
	print("")
	print("Server backend related options:")
74 75
	print(" -c|--connect          Connect to server backend")
	print(" -C|--connect-to IP:PORT  Connect to server backend")
76
	print(" -b|--spawn-backend    Spawn a new backend server and connect to it")
77
	if not isWinStandalone:
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
		print(" -i|--interpreter EXE  Set the backend interpreter executable")
	print("")
	print("Loading hardware modules:")
	print(" -H|--hardware NAME:PARAM=VAL:PARAM=VAL...")
	print("Print module information:")
	print(" -I|--hardware-info NAME")
	print("")
	print(" Where NAME is the name of the hardware module.")
	print(" PARAM=VAL are optional hardware specific parameters.")
	print("")
	print("Other options:")
	print(" --list-sfc            Print a list of all supported SFCs")
	print(" --list-sfc-verbose    Verbose SFC list")
	print(" --list-sfb            Print a list of all supported SFBs")
	print(" --list-sfb-verbose    Verbose SFB list")
93

94
def printSysblockInfo(blockTable, prefix, withExtended, withInterface):
95
	for block in sorted(dictValues(blockTable),
96
			    key = lambda b: b.name[0]):
97 98
		if block.broken:
			continue
99 100 101 102 103 104 105
		number, name, desc = block.name
		if number < 0 and not withExtended:
			continue
		if desc:
			desc = "  (%s)" % desc
		else:
			desc = ""
106
		print("  %s %d  \"%s\"%s" % (prefix, number, name, desc))
107 108 109 110 111 112 113 114 115 116
		if withInterface:
			for ftype in (BlockInterfaceField.FTYPE_IN,
				      BlockInterfaceField.FTYPE_OUT,
				      BlockInterfaceField.FTYPE_INOUT):
				try:
					fields = block.interfaceFields[ftype]
				except KeyError:
					continue
				for field in fields:
					field.fieldType = ftype
117
					print("        %s" % str(field))
Michael Büsch's avatar
Michael Büsch committed
118 119

def writeStdout(message):
120
	if Logging.loglevel >= Logging.LOG_INFO:
Michael Büsch's avatar
Michael Büsch committed
121 122 123
		sys.stdout.write(message)
		sys.stdout.flush()

124 125 126
nextScreenUpdate = 0.0
lastDump = ""

127 128 129
def clearConsole():
	# Make cursor visible, clear console and
	# move cursor to homeposition.
130 131 132 133
	if osIsPosix:
		writeStdout("\x1B[?25h\x1B[2J\x1B[H")
	elif osIsWindows:
		os.system("cls")
134 135 136

def emitCpuDump(dump):
	# Pad lines
137
	dump = '\n'.join(line + (78 - len(line)) * ' ' + '|'
138 139 140
			 for line in dump.splitlines())
	global lastDump
	lastDump = dump
141 142 143 144 145
	if osIsPosix:
		writeStdout("\x1B[H" + dump)
	else:
		clearConsole()
		writeStdout(dump)
146

147
def cpuDumpCallback(cpu):
148
	global nextScreenUpdate
149 150 151
	if cpu.now >= nextScreenUpdate:
		nextScreenUpdate = cpu.now + 0.1
		emitCpuDump(str(cpu))
152

153 154 155 156 157 158
def assignCpuSpecs(cpuSpecs, projectCpuSpecs):
	cpuSpecs.assignFrom(projectCpuSpecs)
	if opt_mnemonics is not None:
		cpuSpecs.setConfiguredMnemonics(opt_mnemonics)
	if opt_nrAccus is not None:
		cpuSpecs.setNrAccus(opt_nrAccus)
159 160
	if opt_clockMem is not None:
		cpuSpecs.setClockMemByte(opt_clockMem)
161

162
def run(inputFile):
163 164
	s = None
	try:
165
		if cython_helper.shouldUseCython():
166
			writeStdout("*** Using accelerated CYTHON core "
167
				    "(AWLSIM_CYTHON environment variable is set)\n")
168

169
		project = Project.fromProjectOrRawAwlFile(inputFile)
170

171
		writeStdout("Parsing code...\n")
172 173
		generatedAwlSrcs = []

174 175 176 177 178
		# Get mnemonics type
		mnemonics = project.getCpuSpecs().getConfiguredMnemonics()
		if opt_mnemonics is not None:
			mnemonics = opt_mnemonics

179
		# Parse FUP sources
Michael Büsch's avatar
Michael Büsch committed
180
		for fupSrc in project.getFupSources():
181 182
			generatedAwlSrcs.append(FupCompiler().compile(
				fupSource=fupSrc, mnemonics=mnemonics))
183 184

		# Parse KOP sources
Michael Büsch's avatar
Michael Büsch committed
185 186
		for kopSrc in project.getKopSources():
			pass#TODO
187 188

		# Parse AWL sources
189
		parseTrees = []
190 191
		for awlSrc in itertools.chain(project.getAwlSources(),
					      generatedAwlSrcs):
192
			p = AwlParser()
193
			p.parseSource(awlSrc)
194
			parseTrees.append(p.getParseTree())
195 196

		# Parse symbol tables
Michael Büsch's avatar
Michael Büsch committed
197
		symTables = []
198
		for symTabSrc in project.getSymTabSources():
199 200 201
			tab = SymTabParser.parseSource(symTabSrc,
						       autodetectFormat = True,
						       mnemonics = mnemonics)
Michael Büsch's avatar
Michael Büsch committed
202
			symTables.append(tab)
203

Michael Büsch's avatar
Michael Büsch committed
204
		writeStdout("Initializing core...\n")
205
		s = AwlSim(profileLevel = opt_profile)
Michael Büsch's avatar
Michael Büsch committed
206
		s.reset()
207 208

		# Load hardware modules
209
		def loadMod(name, parameters):
210 211 212 213
			writeStdout("Loading hardware module '%s'...\n" % name)
			hwClass = s.loadHardwareModule(name)
			s.registerHardwareClass(hwClass = hwClass,
						parameters = parameters)
214 215 216 217 218
		for modDesc in project.getHwmodSettings().getLoadedModules():
			loadMod(modDesc.getModuleName(),
				modDesc.getParameters())
		for name, parameters in opt_hwmods:
			loadMod(name, parameters)
219

220
		# Configure the CPU
221
		cpu = s.getCPU()
222
		assignCpuSpecs(cpu.getSpecs(), project.getCpuSpecs())
223 224
		cpu.enableObTempPresets(project.getObTempPresetsEn() or opt_obtemp)
		cpu.enableExtendedInsns(project.getExtInsnsEn() or opt_extInsns)
225
		if not opt_noCpuDump and opt_loglevel >= Logging.LOG_INFO:
226
			cpu.setBlockExitCallback(cpuDumpCallback, cpu)
227
		cpu.setCycleTimeLimit(opt_cycletime)
228
		cpu.setRunTimeLimit(opt_maxRuntime)
229 230

		# Download the program
231
		writeStdout("Initializing CPU...\n")
Michael Büsch's avatar
Michael Büsch committed
232 233
		for symTable in symTables:
			s.loadSymbolTable(symTable)
234 235
		for libSel in project.getLibSelections():
			s.loadLibraryBlock(libSel)
236 237
		for parseTree in parseTrees:
			s.load(parseTree)
238 239

		# Run the program
240
		s.startup()
241 242 243 244 245 246 247
		writeStdout("[Initialization finished - CPU is executing user code]\n")
		try:
			if not opt_noCpuDump:
				clearConsole()
			while 1:
				s.runCycle()
		finally:
248
			if not opt_noCpuDump and opt_loglevel >= Logging.LOG_INFO:
249 250 251 252
				clearConsole()
				writeStdout(lastDump + '\n')
	except (AwlParserError, AwlSimError) as e:
		printError(e.getReport())
Michael Büsch's avatar
Michael Büsch committed
253
		return ExitCodes.EXIT_ERR_SIM
254 255
	except KeyboardInterrupt as e:
		pass
Michael Büsch's avatar
Michael Büsch committed
256
	except MaintenanceRequest as e:
257
		if e.requestType in (MaintenanceRequest.TYPE_SHUTDOWN,
258 259 260
				     MaintenanceRequest.TYPE_STOP,
				     MaintenanceRequest.TYPE_RTTIMEOUT):
			writeStdout("Shutting down, as requested (%s)...\n" % str(e))
Michael Büsch's avatar
Michael Büsch committed
261
		else:
262 263
			writeStdout("Received unknown maintenance request "
				    "(%d: %s)...\n" % (e.requestType, str(e)))
264 265
	finally:
		if s:
266
			s.unregisterAllHardware()
267 268 269 270 271 272
			ps = s.getProfileStats()
			if ps:
				writeStdout("\n\nProfile stats (level %d) follow:\n" %\
					    opt_profile)
				writeStdout(ps)
				writeStdout("\n")
Michael Büsch's avatar
Michael Büsch committed
273
	return ExitCodes.EXIT_OK
274

275
def runWithServerBackend(inputFile):
276
	client = None
277
	tunnel = None
278
	try:
279
		if cython_helper.shouldUseCython():
280 281
			printError("The accelerated CYTHON core currently is incompatible "
				   "with the backend server. Please remove the "
282
				   "AWLSIM_CYTHON environment variable.")
Michael Büsch's avatar
Michael Büsch committed
283
			return ExitCodes.EXIT_ERR_INTERP
284

285
		project = Project.fromProjectOrRawAwlFile(inputFile)
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
		linkSettings = project.getCoreLinkSettings()

		if opt_spawnBackend:
			host = AwlSimServer.DEFAULT_HOST
			port = AwlSimServer.DEFAULT_PORT
		else:
			host = linkSettings.getConnectHost()
			port = linkSettings.getConnectPort()
		if opt_connectTo:
			host, port = opt_connectTo

		# Establish SSH tunnel, if requested.
		if linkSettings.getTunnel() == linkSettings.TUNNEL_SSH:
			writeStdout("Establishing SSH tunnel...\n")
			localPort = linkSettings.getTunnelLocalPort()
			if localPort == linkSettings.TUNNEL_LOCPORT_AUTO:
				localPort = None
			tunnel = ConsoleSSHTunnel(
				remoteHost = host,
				remotePort = port,
				localPort = localPort,
				sshUser = linkSettings.getSSHUser(),
				sshPort = linkSettings.getSSHPort(),
				sshExecutable = linkSettings.getSSHExecutable(),
			)
			host, port = tunnel.connect()
312

313
		# Connect to the server
314
		client = TestAwlSimClient()
315
		if opt_spawnBackend:
316 317 318
			client.spawnServer(interpreter = opt_interpreter,
					   listenHost = host,
					   listenPort = port)
319
		writeStdout("Connecting to core server...\n")
320
		client.connectToServer(host = host, port = port)
321

Michael Büsch's avatar
Michael Büsch committed
322
		writeStdout("Initializing core...\n")
323
		client.setLoglevel(opt_loglevel)
324
		client.setRunState(False)
325
		client.reset()
326 327

		# Load hardware modules
328
		client.loadHardwareModules(project.getHwmodSettings().getLoadedModules())
329
		for name, parameters in opt_hwmods:
330
			client.loadHardwareModule(HwmodDescriptor(name, parameters))
331 332 333 334 335 336

		# Configure the core
		if opt_noCpuDump:
			client.setPeriodicDumpInterval(0)
		else:
			client.setPeriodicDumpInterval(300)
337 338
		client.enableOBTempPresets(project.getObTempPresetsEn() or opt_obtemp)
		client.enableExtendedInsns(project.getExtInsnsEn() or opt_extInsns)
339
		client.setCycleTimeLimit(opt_cycletime)
340
		client.setRunTimeLimit(opt_maxRuntime)
341
		specs = client.getCpuSpecs()
342
		assignCpuSpecs(specs, project.getCpuSpecs())
343
		client.setCpuSpecs(specs)
344 345 346

		# Fire up the core
		writeStdout("Initializing CPU...\n")
347 348 349 350
		client.loadProject(project, loadCpuSpecs=False,
				   loadTempPresets=False,
				   loadExtInsns=False,
				   loadHwMods=False)
351
		client.setRunState(True)
352 353 354 355 356 357 358

		# Run the client-side event loop
		writeStdout("[Initialization finished - Remote-CPU is executing user code]\n")
		try:
			if not opt_noCpuDump:
				clearConsole()
			while True:
359
				client.processMessages(None)
360
		finally:
361
			if not opt_noCpuDump and opt_loglevel >= Logging.LOG_INFO:
362 363 364 365
				clearConsole()
				writeStdout(lastDump + '\n')
	except AwlSimError as e:
		printError(e.getReport())
Michael Büsch's avatar
Michael Büsch committed
366
		return ExitCodes.EXIT_ERR_SIM
Michael Büsch's avatar
Michael Büsch committed
367
	except MaintenanceRequest as e:
368
		if e.requestType in (MaintenanceRequest.TYPE_SHUTDOWN,
369 370 371
				     MaintenanceRequest.TYPE_STOP,
				     MaintenanceRequest.TYPE_RTTIMEOUT):
			writeStdout("Shutting down, as requested (%s)...\n" % str(e))
Michael Büsch's avatar
Michael Büsch committed
372
		else:
373 374
			writeStdout("Received unknown maintenance request "
				    "(%d: %s)...\n" % (e.requestType, str(e)))
375 376 377
	except KeyboardInterrupt as e:
		pass
	finally:
378 379
		if tunnel:
			tunnel.shutdown()
380 381
		if client:
			client.shutdown()
Michael Büsch's avatar
Michael Büsch committed
382
	return ExitCodes.EXIT_OK
383

384 385 386 387 388 389
def __signalHandler(sig, frame):
	printInfo("Received signal %d" % sig)
	if sig == signal.SIGTERM:
		# Raise SIGINT. It will shut down everything.
		os.kill(os.getpid(), signal.SIGINT)

Michael Büsch's avatar
Michael Büsch committed
390
def main():
391
	global opt_cycletime
392
	global opt_maxRuntime
393
	global opt_noCpuDump
394
	global opt_nrAccus
395 396
	global opt_extInsns
	global opt_obtemp
397
	global opt_clockMem
398 399 400 401
	global opt_mnemonics
	global opt_hwmods
	global opt_hwinfos
	global opt_profile
402
	global opt_loglevel
403
	global opt_connect
404
	global opt_connectTo
405 406
	global opt_spawnBackend
	global opt_interpreter
407

408
	opt_cycletime = 5.0
409
	opt_maxRuntime = -1.0
410
	opt_noCpuDump = False
411
	opt_nrAccus = None
412
	opt_extInsns = False
413
	opt_obtemp = False
414
	opt_clockMem = None
415
	opt_mnemonics = None
416
	opt_hwmods = []
417
	opt_hwinfos = []
Michael Büsch's avatar
Michael Büsch committed
418
	opt_profile = 0
419
	opt_loglevel = Logging.LOG_INFO
420
	opt_connect = None
421
	opt_connectTo = False
422 423
	opt_spawnBackend = False
	opt_interpreter = None
Michael Büsch's avatar
Michael Büsch committed
424 425 426

	try:
		(opts, args) = getopt.getopt(sys.argv[1:],
427
			"hY:M:24qDxt:T:m:H:I:P:L:cC:bi:",
428
			[ "help", "cycle-limit=", "max-runtime=", "twoaccu", "fouraccu",
429
			  "quiet", "no-cpu-dump", "extended-insns",
430
			  "obtemp=", "clock-mem=", "mnemonics=",
431
			  "hardware=", "hardware-info=", "profile=",
432
			  "loglevel=",
433
			  "connect", "connect-to=", "spawn-backend", "interpreter=",
434 435
			  "list-sfc", "list-sfc-verbose",
			  "list-sfb", "list-sfb-verbose", ])
Michael Büsch's avatar
Michael Büsch committed
436
	except getopt.GetoptError as e:
437
		printError(str(e))
Michael Büsch's avatar
Michael Büsch committed
438
		usage()
Michael Büsch's avatar
Michael Büsch committed
439
		return ExitCodes.EXIT_ERR_CMDLINE
Michael Büsch's avatar
Michael Büsch committed
440 441 442
	for (o, v) in opts:
		if o in ("-h", "--help"):
			usage()
Michael Büsch's avatar
Michael Büsch committed
443
			return ExitCodes.EXIT_OK
444
		if o in ("-Y", "--cycle-limit"):
445 446 447
			try:
				opt_cycletime = float(v)
			except ValueError:
448
				printError("-Y|--cycle-limit: Invalid time format")
449
				sys.exit(1)
450 451 452 453 454 455
		if o in ("-M", "--max-runtime"):
			try:
				opt_maxRuntime = float(v)
			except ValueError:
				printError("-M|--max-runtime: Invalid time format")
				sys.exit(1)
456 457
		if o in ("-2", "--twoaccu"):
			opt_nrAccus = 2
Michael Büsch's avatar
Michael Büsch committed
458
		if o in ("-4", "--fouraccu"):
459
			opt_nrAccus = 4
460 461
		if o in ("-D", "--no-cpu-dump"):
			opt_noCpuDump = True
462 463
		if o in ("-x", "--extended-insns"):
			opt_extInsns = True
464 465
		if o in ("-t", "--obtemp"):
			opt_obtemp = str2bool(v)
466 467 468 469 470 471 472
		if o in ("-T", "--clock-mem"):
			try:
				opt_clockMem = int(v)
				if opt_clockMem < -1 or opt_clockMem > 0xFFFF:
					raise ValueError
			except ValueError:
				printError("-T|--clock-mem: Invalid byte address")
473
		if o in ("-m", "--mnemonics"):
474 475
			opt_mnemonics = v.lower()
			if opt_mnemonics not in ("en", "de", "auto"):
476 477
				printError("-m|--mnemonics: Invalid mnemonics type")
				sys.exit(1)
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
		if o in ("-H", "--hardware"):
			try:
				v = v.split(':')
				if not v:
					raise ValueError
				name = v[0]
				params = {}
				for pstr in v[1:]:
					if not pstr:
						continue
					i = pstr.find('=')
					if i < 0:
						raise ValueError
					pname = pstr[:i]
					pval = pstr[i+1:]
					if not pname or not pval:
						raise ValueError
					params[pname] = pval
				opt_hwmods.append( (name, params) )
			except (ValueError, IndexError) as e:
				printError("-H|--hardware: Invalid module name or parameters")
				sys.exit(1)
500
		if o in ("-I", "--hardware-info"):
501
			opt_hwinfos.append(v.split(':')[0])
Michael Büsch's avatar
Michael Büsch committed
502 503 504 505 506
		if o in ("-P", "--profile"):
			try:
				opt_profile = int(v)
			except ValueError:
				printError("-P|--profile: Invalid profile level")
507 508 509 510 511 512
		if o in ("-L", "--loglevel"):
			try:
				opt_loglevel = int(v)
			except ValueError:
				printError("-L|--loglevel: Invalid log level")
				sys.exit(1)
513
		if o in ("-c", "--connect"):
514 515
			opt_connect = True
		if o in ("-C", "--connect-to"):
516 517 518 519
			try:
				idx = v.rfind(":")
				if idx <= 0:
					raise ValueError
520
				opt_connectTo = (v[:idx], int(v[idx+1:]))
521 522 523 524 525 526
			except ValueError:
				printError("-c|--connect: Invalid host/port")
				sys.exit(1)
		if o in ("-b", "--spawn-backend"):
			opt_spawnBackend = True
		if o in ("-i", "--interpreter"):
527 528 529
			if isWinStandalone:
				printError("-i|--interpreter not supported on win-standalone")
				sys.exit(1)
530
			opt_interpreter = v
531
		if o in ("--list-sfc", "--list-sfc-verbose"):
532
			print("The supported system functions (SFCs) are:")
533 534
			printSysblockInfo(SFC_table, "SFC", opt_extInsns,
					  o.endswith("verbose"))
Michael Büsch's avatar
Michael Büsch committed
535
			return ExitCodes.EXIT_OK
536
		if o in ("--list-sfb", "--list-sfb-verbose"):
537
			print("The supported system function blocks (SFBs) are:")
538 539
			printSysblockInfo(SFB_table, "SFB", opt_extInsns,
					  o.endswith("verbose"))
Michael Büsch's avatar
Michael Büsch committed
540
			return ExitCodes.EXIT_OK
541
	if len(args) != 1 and not opt_hwinfos:
Michael Büsch's avatar
Michael Büsch committed
542
		usage()
Michael Büsch's avatar
Michael Büsch committed
543
		return ExitCodes.EXIT_ERR_CMDLINE
544
	if args:
545
		inputFile = args[0]
Michael Büsch's avatar
Michael Büsch committed
546

547
	Logging.setLoglevel(opt_loglevel)
Michael Büsch's avatar
Michael Büsch committed
548

549
	opt_mnemonics = {
550
		None	: None,
551 552 553 554 555
		"en"	: S7CPUSpecs.MNEMONICS_EN,
		"de"	: S7CPUSpecs.MNEMONICS_DE,
		"auto"	: S7CPUSpecs.MNEMONICS_AUTO,
	}[opt_mnemonics]

Michael Büsch's avatar
Michael Büsch committed
556
	try:
557 558 559
		if opt_hwinfos:
			# Just print the hardware-infos and exit.
			for name in opt_hwinfos:
560
				cls = AwlSim.loadHardwareModule(name)
561
				print(cls.getModuleInfo())
Michael Büsch's avatar
Michael Büsch committed
562
			return ExitCodes.EXIT_OK
563 564
	except (AwlParserError, AwlSimError) as e:
		printError(e.getReport())
Michael Büsch's avatar
Michael Büsch committed
565
		return ExitCodes.EXIT_ERR_SIM
566

567 568
	signal.signal(signal.SIGTERM, __signalHandler)

569 570 571
	if opt_interpreter and not opt_spawnBackend:
		printError("Selected an --interpreter, but no "
			   "--spawn-backend was requested.")
Michael Büsch's avatar
Michael Büsch committed
572
		return ExitCodes.EXIT_ERR_CMDLINE
573

574
	if opt_spawnBackend or opt_connect or opt_connectTo:
575 576
		return runWithServerBackend(inputFile)
	return run(inputFile)
Michael Büsch's avatar
Michael Büsch committed
577 578 579

if __name__ == "__main__":
	sys.exit(main())