Commit bc48349a authored by Michael Büsch's avatar Michael Büsch

Add ID number to source object

Signed-off-by: Michael Büsch's avatarMichael Buesch <m@bues.ch>
parent 921963cf
...@@ -158,7 +158,6 @@ class S7CPU(object): ...@@ -158,7 +158,6 @@ class S7CPU(object):
try: try:
insn = AwlInsnTranslator.fromRawInsn(self, rawInsn) insn = AwlInsnTranslator.fromRawInsn(self, rawInsn)
insn.setIP(ip) insn.setIP(ip)
insn.setFileNr(self.__currentAwlFileNr)
except AwlSimError as e: except AwlSimError as e:
if e.getRawInsn() is None: if e.getRawInsn() is None:
e.setRawInsn(rawInsn) e.setRawInsn(rawInsn)
...@@ -541,8 +540,6 @@ class S7CPU(object): ...@@ -541,8 +540,6 @@ class S7CPU(object):
db = self.__translateDB(rawDB) db = self.__translateDB(rawDB)
self.dbs[dbNumber] = db self.dbs[dbNumber] = db
self.__currentAwlFileNr += 1
def loadSymbolTable(self, symbolTable): def loadSymbolTable(self, symbolTable):
self.symbolTable.merge(symbolTable) self.symbolTable.merge(symbolTable)
...@@ -566,7 +563,6 @@ class S7CPU(object): ...@@ -566,7 +563,6 @@ class S7CPU(object):
CallStackElem.resetCache() CallStackElem.resetCache()
def reset(self): def reset(self):
self.__currentAwlFileNr = 0
self.dbs = { self.dbs = {
# DBs # DBs
0 : DB(0, permissions = 0), # read/write-protected system-DB 0 : DB(0, permissions = 0), # read/write-protected system-DB
......
...@@ -28,13 +28,14 @@ from awlsim.core.enumeration import * ...@@ -28,13 +28,14 @@ from awlsim.core.enumeration import *
class AwlSimError(Exception): class AwlSimError(Exception):
def __init__(self, message, cpu=None, def __init__(self, message, cpu=None,
rawInsn=None, insn=None, lineNr=None, rawInsn=None, insn=None, lineNr=None,
fileId=None): sourceId=None, sourceName=None):
Exception.__init__(self, message) Exception.__init__(self, message)
self.cpu = cpu self.cpu = cpu
self.rawInsn = rawInsn self.rawInsn = rawInsn
self.insn = insn self.insn = insn
self.lineNr = lineNr self.lineNr = lineNr
self.fileId = fileId self.sourceId = sourceId
self.sourceName = sourceName
def setCpu(self, cpu): def setCpu(self, cpu):
self.cpu = cpu self.cpu = cpu
...@@ -54,11 +55,17 @@ class AwlSimError(Exception): ...@@ -54,11 +55,17 @@ class AwlSimError(Exception):
def getInsn(self): def getInsn(self):
return self.insn return self.insn
def setFileId(self, fileId): def setSourceId(self, sourceId):
self.fileId = fileId self.sourceId = sourceId
def getFileId(self): def getSourceId(self):
return self.fileId return self.sourceId
def setSourceName(self, sourceName):
self.sourceName = sourceName
def getSourceName(self):
return self.sourceName
def setLineNr(self, lineNr): def setLineNr(self, lineNr):
self.lineNr = lineNr self.lineNr = lineNr
...@@ -96,14 +103,14 @@ class AwlSimError(Exception): ...@@ -96,14 +103,14 @@ class AwlSimError(Exception):
return errorStr return errorStr
def doGetReport(self, title): def doGetReport(self, title):
fileId = self.getFileId() sourceName = self.getSourceName()
if fileId: if sourceName:
fileId += " " sourceName += " "
else: else:
fileId = "" sourceName = ""
ret = [ "-- %s --\n" % title ] ret = [ "-- %s --\n" % title ]
ret.append("ERROR at %sline %s:\n" %\ ret.append("ERROR at %sline %s:\n" %\
(fileId, self.getLineNrStr())) (sourceName, self.getLineNrStr()))
ret.append(" \n%s\n" % str(self)) ret.append(" \n%s\n" % str(self))
cpu = self.getCpu() cpu = self.getCpu()
if cpu: if cpu:
......
...@@ -433,7 +433,6 @@ class AwlInsn(object): ...@@ -433,7 +433,6 @@ class AwlInsn(object):
self.cpu = cpu self.cpu = cpu
self.type = type self.type = type
self.rawInsn = rawInsn self.rawInsn = rawInsn
self.fileNr = -1 # AWL file number
self.ip = None # Instruction pointer (IP) self.ip = None # Instruction pointer (IP)
self.ops = [] # Operators self.ops = [] # Operators
self.params = [] # Parameter assignments (for CALL) self.params = [] # Parameter assignments (for CALL)
...@@ -462,12 +461,14 @@ class AwlInsn(object): ...@@ -462,12 +461,14 @@ class AwlInsn(object):
def setIP(self, newIp): def setIP(self, newIp):
self.ip = newIp self.ip = newIp
def setFileNr(self, newFileNr):
self.fileNr = newFileNr
def getCpu(self): def getCpu(self):
return self.cpu return self.cpu
def getSourceId(self):
if not self.rawInsn:
return None
return self.rawInsn.getSourceId()
def getLineNr(self): def getLineNr(self):
if not self.rawInsn: if not self.rawInsn:
return -1 return -1
......
...@@ -33,6 +33,7 @@ from awlsim.core.project import * ...@@ -33,6 +33,7 @@ from awlsim.core.project import *
class RawAwlInsn(object): class RawAwlInsn(object):
def __init__(self, block): def __init__(self, block):
self.block = block self.block = block
self.sourceId = None
self.lineNr = 0 self.lineNr = 0
self.label = None self.label = None
self.name = None self.name = None
...@@ -54,6 +55,12 @@ class RawAwlInsn(object): ...@@ -54,6 +55,12 @@ class RawAwlInsn(object):
ret.extend(self.getOperators()) ret.extend(self.getOperators())
return " ".join(ret) return " ".join(ret)
def setSourceId(self, sourceId):
self.sourceId = sourceId
def getSourceId(self):
return self.sourceId
def setLineNr(self, newLineNr): def setLineNr(self, newLineNr):
self.lineNr = newLineNr self.lineNr = newLineNr
...@@ -266,7 +273,8 @@ class AwlParseTree(object): ...@@ -266,7 +273,8 @@ class AwlParseTree(object):
self.curBlock = None self.curBlock = None
self.fileId = "" self.sourceId = None
self.sourceName = None
class AwlParser(object): class AwlParser(object):
EnumGen.start EnumGen.start
...@@ -352,9 +360,10 @@ class AwlParser(object): ...@@ -352,9 +360,10 @@ class AwlParser(object):
return self.__inAnyHeader() or\ return self.__inAnyHeader() or\
self.state == self.STATE_GLOBAL self.state == self.STATE_GLOBAL
def __tokenize(self, data, fileId): def __tokenize(self, data, sourceId, sourceName):
self.reset() self.reset()
self.tree.fileId = fileId self.tree.sourceId = sourceId
self.tree.sourceName = sourceName
self.lineNr = 1 self.lineNr = 1
t = self.TokenizerState(self) t = self.TokenizerState(self)
...@@ -607,6 +616,7 @@ class AwlParser(object): ...@@ -607,6 +616,7 @@ class AwlParser(object):
def __parseInstruction(self, t): def __parseInstruction(self, t):
insn = RawAwlInsn(self.tree.curBlock) insn = RawAwlInsn(self.tree.curBlock)
insn.setLineNr(t.tokensLineNr) insn.setLineNr(t.tokensLineNr)
insn.setSourceId(self.tree.sourceId)
if t.tokens[0].endswith(":"): if t.tokens[0].endswith(":"):
# First token is a label # First token is a label
if len(t.tokens) <= 1: if len(t.tokens) <= 1:
...@@ -975,9 +985,11 @@ class AwlParser(object): ...@@ -975,9 +985,11 @@ class AwlParser(object):
def parseSource(self, awlSource): def parseSource(self, awlSource):
"""Parse an AWL source. """Parse an AWL source.
awlSource is an AwlSource instance.""" awlSource is an AwlSource instance."""
self.parseData(awlSource.sourceBytes, str(awlSource)) self.parseData(awlSource.sourceBytes,
sourceId = awlSource.identNr,
sourceName = awlSource.name)
def parseData(self, dataBytes, fileId=""): def parseData(self, dataBytes, sourceId=None, sourceName=None):
try: try:
data = dataBytes.decode(self.TEXT_ENCODING) data = dataBytes.decode(self.TEXT_ENCODING)
except UnicodeError as e: except UnicodeError as e:
...@@ -987,10 +999,11 @@ class AwlParser(object): ...@@ -987,10 +999,11 @@ class AwlParser(object):
self.flatLayout = not re.match(r'.*^\s*ORGANIZATION_BLOCK\s+.*', self.flatLayout = not re.match(r'.*^\s*ORGANIZATION_BLOCK\s+.*',
data, re.DOTALL | re.MULTILINE) data, re.DOTALL | re.MULTILINE)
try: try:
self.__tokenize(data, fileId) self.__tokenize(data, sourceId, sourceName)
except AwlParserError as e: except AwlParserError as e:
e.setLineNr(self.lineNr) e.setLineNr(self.lineNr)
e.setFileId(fileId) e.setSourceId(sourceId)
e.setSourceName(sourceName)
raise e raise e
def getParseTree(self): def getParseTree(self):
......
...@@ -40,12 +40,20 @@ else: ...@@ -40,12 +40,20 @@ else:
class GenericSource(object): class GenericSource(object):
SRCTYPE = "<generic>" SRCTYPE = "<generic>"
def __init__(self, identifier, filepath="", sourceBytes=b""): __nextIdentNr = 0
assert(identifier)
self.identifier = identifier def __init__(self, identNr, name="", filepath="", sourceBytes=b""):
self.identNr = identNr
self.name = name
self.filepath = filepath self.filepath = filepath
self.sourceBytes = sourceBytes self.sourceBytes = sourceBytes
@staticmethod
def newIdentNr():
identNr = GenericSource.__nextIdentNr
GenericSource.__nextIdentNr = (GenericSource.__nextIdentNr + 1) & 0x7FFFFFFF
return identNr
def dup(self): def dup(self):
raise NotImplementedError raise NotImplementedError
...@@ -58,51 +66,51 @@ class GenericSource(object): ...@@ -58,51 +66,51 @@ class GenericSource(object):
return return
awlFileWrite(self.filepath, self.sourceBytes, encoding="binary") awlFileWrite(self.filepath, self.sourceBytes, encoding="binary")
def forceNonFileBacked(self, newIdentifier): def forceNonFileBacked(self, newName):
"Convert this source to a non-file-backed source." "Convert this source to a non-file-backed source."
if self.isFileBacked(): if self.isFileBacked():
self.filepath = "" self.filepath = ""
self.identifier = newIdentifier self.name = newName
def toBase64(self): def toBase64(self):
return base64.b64encode(self.sourceBytes).decode("ascii") return base64.b64encode(self.sourceBytes).decode("ascii")
@classmethod @classmethod
def fromFile(cls, identifier, filepath): def fromFile(cls, identNr, name, filepath):
try: try:
data = awlFileRead(filepath, encoding="binary") data = awlFileRead(filepath, encoding="binary")
except AwlSimError as e: except AwlSimError as e:
raise AwlSimError("Project: Could not read %s " raise AwlSimError("Project: Could not read %s "
"source file '%s':\n%s" %\ "source file '%s':\n%s" %\
(cls.SRCTYPE, filepath, str(e))) (cls.SRCTYPE, filepath, str(e)))
return cls(identifier, filepath, data) return cls(identNr, name, filepath, data)
@classmethod @classmethod
def fromBase64(cls, identifier, b64): def fromBase64(cls, identNr, name, b64):
try: try:
data = base64.b64decode(b64, validate=True) data = base64.b64decode(b64, validate=True)
except (TypeError, binascii.Error) as e: except (TypeError, binascii.Error) as e:
raise AwlSimError("Project: %s source '%s' " raise AwlSimError("Project: %s source '%s' "
"has invalid base64 encoding." %\ "has invalid base64 encoding." %\
(cls.SRCTYPE, identifier)) (cls.SRCTYPE, identNr))
return cls(identifier, None, data) return cls(identNr, name, None, data)
def __repr__(self): def __repr__(self):
return "%s%s %s" % ("" if self.isFileBacked() else "project ", return "%s%s %d %s" % ("" if self.isFileBacked() else "project ",
self.SRCTYPE, self.identifier) self.SRCTYPE, self.identNr, self.name)
class AwlSource(GenericSource): class AwlSource(GenericSource):
SRCTYPE = "AWL/STL" SRCTYPE = "AWL/STL"
def dup(self): def dup(self):
return AwlSource(self.identifier, self.filepath, return AwlSource(self.identNr, self.name, self.filepath,
self.sourceBytes[:]) self.sourceBytes[:])
class SymTabSource(GenericSource): class SymTabSource(GenericSource):
SRCTYPE = "symbol table" SRCTYPE = "symbol table"
def dup(self): def dup(self):
return SymTabSource(self.identifier, self.filepath, return SymTabSource(self.identNr, self.name, self.filepath,
self.sourceBytes[:]) self.sourceBytes[:])
class Project(object): class Project(object):
...@@ -196,14 +204,16 @@ class Project(object): ...@@ -196,14 +204,16 @@ class Project(object):
if not p.has_option("CPU", option): if not p.has_option("CPU", option):
break break
path = p.get("CPU", option) path = p.get("CPU", option)
src = AwlSource.fromFile(path, cls.__generic2path(path, projectDir)) sourceId = AwlSource.newIdentNr()
src = AwlSource.fromFile(sourceId, path, cls.__generic2path(path, projectDir))
awlSources.append(src) awlSources.append(src)
for i in range(0xFFFF): for i in range(0xFFFF):
option = "awl_%d" % i option = "awl_%d" % i
if not p.has_option("CPU", option): if not p.has_option("CPU", option):
break break
awlBase64 = p.get("CPU", option) awlBase64 = p.get("CPU", option)
src = AwlSource.fromBase64("#%d" % i, awlBase64) sourceId = AwlSource.newIdentNr()
src = AwlSource.fromBase64(sourceId, "#%d" % sourceId, awlBase64)
awlSources.append(src) awlSources.append(src)
if p.has_option("CPU", "mnemonics"): if p.has_option("CPU", "mnemonics"):
mnemonics = p.getint("CPU", "mnemonics") mnemonics = p.getint("CPU", "mnemonics")
...@@ -222,14 +232,16 @@ class Project(object): ...@@ -222,14 +232,16 @@ class Project(object):
if not p.has_option("SYMBOLS", option): if not p.has_option("SYMBOLS", option):
break break
path = p.get("SYMBOLS", option) path = p.get("SYMBOLS", option)
src = SymTabSource.fromFile(path, cls.__generic2path(path, projectDir)) sourceId = SymTabSource.newIdentNr()
src = SymTabSource.fromFile(sourceId, path, cls.__generic2path(path, projectDir))
symTabSources.append(src) symTabSources.append(src)
for i in range(0xFFFF): for i in range(0xFFFF):
option = "sym_tab_%d" % i option = "sym_tab_%d" % i
if not p.has_option("SYMBOLS", option): if not p.has_option("SYMBOLS", option):
break break
symTabBase64 = p.get("SYMBOLS", option) symTabBase64 = p.get("SYMBOLS", option)
src = SymTabSource.fromBase64("#%d" % i, symTabBase64) sourceId = SymTabSource.newIdentNr()
src = SymTabSource.fromBase64(sourceId, "#%d" % sourceId, symTabBase64)
symTabSources.append(src) symTabSources.append(src)
except _ConfigParserError as e: except _ConfigParserError as e:
......
...@@ -356,13 +356,13 @@ class AwlSimClient(object): ...@@ -356,13 +356,13 @@ class AwlSimClient(object):
# fromLine, toLine is the range of AWL line numbers for which # fromLine, toLine is the range of AWL line numbers for which
# dumping is enabled. # dumping is enabled.
def setInsnStateDump(self, enable=True, def setInsnStateDump(self, enable=True,
fileNr=0, fromLine=1, toLine=0x7FFFFFFF, sourceId=0, fromLine=1, toLine=0x7FFFFFFF,
sync=True): sync=True):
if not self.transceiver: if not self.transceiver:
return None return None
msg = AwlSimMessage_INSNSTATE_CONFIG( msg = AwlSimMessage_INSNSTATE_CONFIG(
flags = 0, flags = 0,
fileNr = fileNr, sourceId = sourceId,
fromLine = fromLine, fromLine = fromLine,
toLine = toLine) toLine = toLine)
if enable: if enable:
......
...@@ -224,13 +224,18 @@ class AwlSimMessage_EXCEPTION(AwlSimMessage): ...@@ -224,13 +224,18 @@ class AwlSimMessage_EXCEPTION(AwlSimMessage):
class _AwlSimMessage_source(AwlSimMessage): class _AwlSimMessage_source(AwlSimMessage):
sourceClass = None sourceClass = None
# Payload header struct:
# Source identifier (32 bit)
plStruct = struct.Struct(str(">I"))
def __init__(self, msgId, source): def __init__(self, msgId, source):
AwlSimMessage.__init__(self, msgId) AwlSimMessage.__init__(self, msgId)
self.source = source self.source = source
def toBytes(self): def toBytes(self):
try: try:
pl = self.packString(self.source.identifier) +\ pl = self.plStruct.pack(self.source.identNr) +\
self.packString(self.source.name) +\
self.packString(self.source.filepath) +\ self.packString(self.source.filepath) +\
self.packBytes(self.source.sourceBytes) self.packBytes(self.source.sourceBytes)
return AwlSimMessage.toBytes(self, len(pl)) + pl return AwlSimMessage.toBytes(self, len(pl)) + pl
...@@ -240,13 +245,16 @@ class _AwlSimMessage_source(AwlSimMessage): ...@@ -240,13 +245,16 @@ class _AwlSimMessage_source(AwlSimMessage):
@classmethod @classmethod
def fromBytes(cls, payload): def fromBytes(cls, payload):
try: try:
identifier, count = cls.unpackString(payload) (identNr, ) = cls.plStruct.unpack_from(payload, 0)
count = cls.plStruct.size
name, cnt = cls.unpackString(payload, count)
count += cnt
filepath, cnt = cls.unpackString(payload, count) filepath, cnt = cls.unpackString(payload, count)
count += cnt count += cnt
sourceBytes, cnt = cls.unpackBytes(payload, count) sourceBytes, cnt = cls.unpackBytes(payload, count)
except ValueError: except (ValueError, struct.error) as e:
raise TransferError("SOURCE: Data format error") raise TransferError("SOURCE: Data format error")
return cls(cls.sourceClass(identifier, filepath, sourceBytes)) return cls(cls.sourceClass(identNr, name, filepath, sourceBytes))
class AwlSimMessage_LOAD_SYMTAB(_AwlSimMessage_source): class AwlSimMessage_LOAD_SYMTAB(_AwlSimMessage_source):
sourceClass = SymTabSource sourceClass = SymTabSource
...@@ -537,7 +545,7 @@ class AwlSimMessage_MEMORY(AwlSimMessage): ...@@ -537,7 +545,7 @@ class AwlSimMessage_MEMORY(AwlSimMessage):
class AwlSimMessage_INSNSTATE(AwlSimMessage): class AwlSimMessage_INSNSTATE(AwlSimMessage):
# Payload data struct: # Payload data struct:
# AWL file ident number (32 bit) # AWL source ident number (32 bit)
# AWL line number (32 bit) # AWL line number (32 bit)
# Serial number. Reset to 0 on cycle exit. (32 bit) # Serial number. Reset to 0 on cycle exit. (32 bit)
# Flags (16 bit) (currently unused. Set to 0) # Flags (16 bit) (currently unused. Set to 0)
...@@ -552,9 +560,9 @@ class AwlSimMessage_INSNSTATE(AwlSimMessage): ...@@ -552,9 +560,9 @@ class AwlSimMessage_INSNSTATE(AwlSimMessage):
# CPU DI register (16 bit) # CPU DI register (16 bit)
plDataStruct = struct.Struct(str(">IIIHHIIIIIIHH")) plDataStruct = struct.Struct(str(">IIIHHIIIIIIHH"))
def __init__(self, fileNr, lineNr, serial, flags, stw, accu1, accu2, accu3, accu4, ar1, ar2, db, di): def __init__(self, sourceId, lineNr, serial, flags, stw, accu1, accu2, accu3, accu4, ar1, ar2, db, di):
AwlSimMessage.__init__(self, AwlSimMessage.MSG_ID_INSNSTATE) AwlSimMessage.__init__(self, AwlSimMessage.MSG_ID_INSNSTATE)
self.fileNr = fileNr self.sourceId = sourceId
self.lineNr = lineNr self.lineNr = lineNr
self.serial = serial self.serial = serial
self.flags = flags self.flags = flags
...@@ -570,7 +578,7 @@ class AwlSimMessage_INSNSTATE(AwlSimMessage): ...@@ -570,7 +578,7 @@ class AwlSimMessage_INSNSTATE(AwlSimMessage):
def toBytes(self): def toBytes(self):
pl = self.plDataStruct.pack( pl = self.plDataStruct.pack(
self.fileNr, self.lineNr, self.serial, self.sourceId, self.lineNr, self.serial,
self.flags, self.stw, self.accu1, self.accu2, self.flags, self.stw, self.accu1, self.accu2,
self.accu3, self.accu4, self.ar1, self.ar2, self.accu3, self.accu4, self.ar1, self.ar2,
self.db, self.di) self.db, self.di)
...@@ -579,16 +587,16 @@ class AwlSimMessage_INSNSTATE(AwlSimMessage): ...@@ -579,16 +587,16 @@ class AwlSimMessage_INSNSTATE(AwlSimMessage):
@classmethod @classmethod
def fromBytes(cls, payload): def fromBytes(cls, payload):
try: try:
fileNr, lineNr, serial, flags, stw, accu1, accu2, accu3, accu4, ar1, ar2, db, di =\ sourceId, lineNr, serial, flags, stw, accu1, accu2, accu3, accu4, ar1, ar2, db, di =\
cls.plDataStruct.unpack_from(payload, 0) cls.plDataStruct.unpack_from(payload, 0)
except (struct.error, IndexError) as e: except (struct.error, IndexError) as e:
raise TransferError("INSNSTATE: Invalid data format") raise TransferError("INSNSTATE: Invalid data format")
return cls(fileNr, lineNr, serial, flags, stw, accu1, accu2, accu3, accu4, ar1, ar2, db, di) return cls(sourceId, lineNr, serial, flags, stw, accu1, accu2, accu3, accu4, ar1, ar2, db, di)
class AwlSimMessage_INSNSTATE_CONFIG(AwlSimMessage): class AwlSimMessage_INSNSTATE_CONFIG(AwlSimMessage):
# Payload data struct: # Payload data struct:
# Flags (32 bit) # Flags (32 bit)
# AWL file ident number (32 bit) # AWL source ident number (32 bit)
# From AWL line (32 bit) # From AWL line (32 bit)
# To AWL line (32 bit) # To AWL line (32 bit)
plDataStruct = struct.Struct(str(">IIII")) plDataStruct = struct.Struct(str(">IIII"))
...@@ -598,27 +606,27 @@ class AwlSimMessage_INSNSTATE_CONFIG(AwlSimMessage): ...@@ -598,27 +606,27 @@ class AwlSimMessage_INSNSTATE_CONFIG(AwlSimMessage):
FLG_CLEAR_ONLY = 1 << 1 # Just clear current settings. FLG_CLEAR_ONLY = 1 << 1 # Just clear current settings.
FLG_CLEAR = 1 << 2 # Clear, then apply settings. FLG_CLEAR = 1 << 2 # Clear, then apply settings.
def __init__(self, flags, fileNr, fromLine, toLine): def __init__(self, flags, sourceId, fromLine, toLine):
AwlSimMessage.__init__(self, AwlSimMessage.MSG_ID_INSNSTATE_CONFIG) AwlSimMessage.__init__(self, AwlSimMessage.MSG_ID_INSNSTATE_CONFIG)
self.flags = flags self.flags = flags
self.fileNr = fileNr self.sourceId = sourceId
self.fromLine = fromLine self.fromLine = fromLine
self.toLine = toLine self.toLine = toLine
def toBytes(self): def toBytes(self):
pl = self.plDataStruct.pack( pl = self.plDataStruct.pack(
self.flags, self.fileNr, self.flags, self.sourceId,
self.fromLine, self.toLine) self.fromLine, self.toLine)
return AwlSimMessage.toBytes(self, len(pl)) + pl return AwlSimMessage.toBytes(self, len(pl)) + pl
@classmethod @classmethod
def fromBytes(cls, payload): def fromBytes(cls, payload):
try: try:
flags, fileNr, fromLine, toLine =\ flags, sourceId, fromLine, toLine =\
cls.plDataStruct.unpack_from(payload, 0) cls.plDataStruct.unpack_from(payload, 0)
except (struct.error, IndexError) as e: except (struct.error, IndexError) as e:
raise TransferError("INSNSTATE_CONFIG: Invalid data format") raise TransferError("INSNSTATE_CONFIG: Invalid data format")
return cls(flags, fileNr, fromLine, toLine) return cls(flags, sourceId, fromLine, toLine)
class AwlSimMessageTransceiver(object): class AwlSimMessageTransceiver(object):
class RemoteEndDied(Exception): pass class RemoteEndDied(Exception): pass
......
...@@ -72,7 +72,7 @@ class AwlSimServer(object): ...@@ -72,7 +72,7 @@ class AwlSimServer(object):
self.nextDump = 0 self.nextDump = 0
# Instruction state dump: Enabled lines. # Instruction state dump: Enabled lines.
# dict key: AWL file number. # dict key: AWL source ID number.
# dict values: range() of AWL line numbers. # dict values: range() of AWL line numbers.
self.insnStateDump_enabledLines = {} self.insnStateDump_enabledLines = {}
...@@ -264,16 +264,16 @@ class AwlSimServer(object): ...@@ -264,16 +264,16 @@ class AwlSimServer(object):
insn = cpu.getCurrentInsn() insn = cpu.getCurrentInsn()
if not insn: if not insn:
return return
fileNr, lineNr, msg = insn.fileNr, insn.getLineNr(), None sourceId, lineNr, msg = insn.getSourceId(), insn.getLineNr(), None
for client in self.clients: for client in self.clients:
try: try:
if lineNr not in client.insnStateDump_enabledLines[fileNr]: if lineNr not in client.insnStateDump_enabledLines[sourceId]:
continue continue
except KeyError: except KeyError:
continue continue
if not msg: if not msg:
msg = AwlSimMessage_INSNSTATE( msg = AwlSimMessage_INSNSTATE(
fileNr & 0xFFFFFFFF, sourceId & 0xFFFFFFFF,
lineNr & 0xFFFFFFFF, lineNr & 0xFFFFFFFF,
self.__insnSerial, self.__insnSerial,
0, 0,
...@@ -431,7 +431,7 @@ class AwlSimServer(object): ...@@ -431,7 +431,7 @@ class AwlSimServer(object):
client.insnStateDump_enabledLines = {} client.insnStateDump_enabledLines = {}
if not (msg.flags & msg.FLG_CLEAR_ONLY): if not (msg.flags & msg.FLG_CLEAR_ONLY):
rnge = range(msg.fromLine, msg.toLine + 1) rnge = range(msg.fromLine, msg.toLine + 1)
client.insnStateDump_enabledLines[msg.fileNr] = rnge client.insnStateDump_enabledLines[msg.sourceId] = rnge
self.__updateCpuPostInsnCallback() self.__updateCpuPostInsnCallback()
self.__updateCpuCycleExitCallback() self.__updateCpuCycleExitCallback()
if msg.flags & msg.FLG_SYNC: if msg.flags & msg.FLG_SYNC:
......
...@@ -311,7 +311,7 @@ class CpuWidget(QWidget): ...@@ -311,7 +311,7 @@ class CpuWidget(QWidget):
client = self.mainWidget.getSimClient() client = self.mainWidget.getSimClient()
if onlineDiagEn and source: if onlineDiagEn and source:
client.setInsnStateDump(enable=True,