#!/usr/bin/env python3 # -*- coding: utf-8 -*- # # AWL simulator - Commandline interface # # Copyright 2012-2013 Michael Buesch # # 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. # import sys import getopt import traceback from awlsim import * opt_onecycle = False opt_quiet = False def usage(): printInfo("awlsim version %d.%d" % (VERSION_MAJOR, VERSION_MINOR)) printInfo("") printInfo("%s [OPTIONS] AWL-source" % sys.argv[0]) printInfo("") printInfo("Options:") printInfo(" -1|--onecycle Only run one cycle") printInfo(" -4|--fouraccu Enable 4-accu mode") printInfo(" -D|--no-cpu-dump Do not show CPU status while running") printInfo(" -q|--quiet Do not show any status messages") printInfo(" -x|--extended-insns Enable extended instructions") printInfo(" -t|--obtemp 1/0 Enable/disable writing of OB-temp variables (Default: off)") printInfo(" -r|--rng 1/0 Enable/disable the RNG (Default: off)") printInfo(" -m|--mnemonics auto Mnemonics type: en, de, auto (default)") printInfo(" -P|--profile 0 Set profiling level (Default: 0)") printInfo("") printInfo("Loading hardware modules:") printInfo(" -H|--hardware NAME:PARAM=VAL:PARAM=VAL...") printInfo("Print module information:") printInfo(" -I|--hardware-info NAME") printInfo("") printInfo(" Where NAME is the name of the hardware module.") printInfo(" PARAM=VAL are optional hardware specific parameters.") def writeStdout(message): if not opt_quiet: sys.stdout.write(message) sys.stdout.flush() nextScreenUpdate = 0.0 lastDump = "" def cpuDumpCallback(cpu): global nextScreenUpdate if cpu.now < nextScreenUpdate and\ not opt_onecycle: return nextScreenUpdate = cpu.now + 0.1 # Dump CPU and pad lines dump = '\n'.join(line + (79 - len(line)) * ' ' + '|' for line in str(cpu).splitlines()) global lastDump lastDump = dump writeStdout("\x1B[H" + dump) def main(): global opt_onecycle global opt_quiet opt_noCpuDump = False opt_fouraccu = False opt_extInsns = False opt_obtemp = False opt_rng = False opt_mnemonics = "auto" opt_hwmods = [] opt_hwinfos = [] opt_profile = 0 try: (opts, args) = getopt.getopt(sys.argv[1:], "h1qDxt:r:m:H:I:P:", [ "help", "onecycle", "quiet", "no-cpu-dump", "extended-insns", "obtemp=", "rng=", "mnemonics=", "hardware=", "hardware-info=", "profile=", ]) except getopt.GetoptError as e: printError(str(e)) usage() return 1 for (o, v) in opts: if o in ("-h", "--help"): usage() return 0 if o in ("-1", "--onecycle"): opt_onecycle = True if o in ("-4", "--fouraccu"): opt_fouraccu = True if o in ("-q", "--quiet"): opt_quiet = True if o in ("-D", "--no-cpu-dump"): opt_noCpuDump = True if o in ("-x", "--extended-insns"): opt_extInsns = True if o in ("-t", "--obtemp"): opt_obtemp = str2bool(v) if o in ("-r", "--rng"): opt_rng = str2bool(v) if o in ("-m", "--mnemonics"): opt_mnemonics = v.lower() if opt_mnemonics not in ("en", "de", "auto"): printError("-m|--mnemonics: Invalid mnemonics type") sys.exit(1) 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) if o in ("-I", "--hardware-info"): opt_hwinfos.append(v.split(':')[0]) if o in ("-P", "--profile"): try: opt_profile = int(v) except ValueError: printError("-P|--profile: Invalid profile level") if len(args) != 1 and not opt_hwinfos: usage() return 1 if args: awlSource = args[0] opt_mnemonics = { "en" : S7CPUSpecs.MNEMONICS_EN, "de" : S7CPUSpecs.MNEMONICS_DE, "auto" : S7CPUSpecs.MNEMONICS_AUTO, }[opt_mnemonics] s = None try: if opt_hwinfos: # Just print the hardware-infos and exit. for name in opt_hwinfos: cls = AwlSim.loadHardwareModule(name) printInfo(cls.getModuleInfo()) return 0 if awlsim_useCython: writeStdout("*** Using accelerated CYTHON core " "(AWLSIMCYTHON environment variable is set)\n") writeStdout("Parsing code...\n") p = AwlParser() p.parseFile(awlSource) writeStdout("Initializing simulator...\n") s = AwlSim(profileLevel = opt_profile) # Load hardware modules for name, parameters in opt_hwmods: writeStdout("Loading hardware module '%s'...\n" % name) hwClass = s.loadHardwareModule(name) s.registerHardwareClass(hwClass = hwClass, parameters = parameters) cpu = s.getCPU() specs = cpu.getSpecs() specs.setConfiguredMnemonics(opt_mnemonics) specs.setNrAccus(4 if opt_fouraccu else 2) cpu.enableObTempPresets(opt_obtemp) cpu.enableRNG(opt_rng) cpu.enableExtendedInsns(opt_extInsns) if not opt_noCpuDump and not opt_quiet: cpu.setBlockExitCallback(cpuDumpCallback, cpu) writeStdout("Initializing CPU...\n") s.load(p.getParseTree()) writeStdout("[Initialization finished - CPU is executing user code]\n") try: if not opt_noCpuDump: writeStdout("\x1B[?25l\x1B[2J") while 1: s.runCycle() if opt_onecycle: break finally: if not opt_noCpuDump and not opt_quiet: writeStdout("\x1B[?25h\x1B[2J\x1B[H") writeStdout(lastDump + '\n') except (AwlParserError, AwlSimError) as e: printError(e.getReport()) return 1 except KeyboardInterrupt as e: pass finally: if s: ps = s.getProfileStats() if ps: writeStdout("\n\nProfile stats (level %d) follow:\n" %\ opt_profile) writeStdout(ps) writeStdout("\n") s.shutdown() return 0 if __name__ == "__main__": sys.exit(main())