Commit 3cf83594 authored by Michael Büsch's avatar Michael Büsch

corserver: Add messages to fetch sources

Signed-off-by: Michael Büsch's avatarMichael Buesch <m@bues.ch>
parent e2e8c2d9
......@@ -302,11 +302,11 @@ def runWithServerBackend(inputFile):
# Fire up the core
writeStdout("Initializing CPU...\n")
for symTabSrc in project.getSymTabSources():
client.loadSymbolTable(symTabSrc)
client.loadSymTabSource(symTabSrc)
for libSel in project.getLibSelections():
client.loadLibraryBlock(libSel)
for awlSrc in project.getAwlSources():
client.loadCode(awlSrc)
client.loadAwlSource(awlSrc)
client.setRunState(True)
# Run the client-side event loop
......
......@@ -2,7 +2,7 @@
#
# AWL simulator - PLC core server client
#
# Copyright 2013-2014 Michael Buesch <m@bues.ch>
# Copyright 2013-2015 Michael Buesch <m@bues.ch>
#
# 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
......@@ -208,6 +208,18 @@ class AwlSimClient(object):
def __rx_PONG(self, msg):
self.handle_PONG()
def handle_AWLSRC(self, awlSource):
pass # Don't do anything by default
def __rx_AWLSRC(self, msg):
self.handle_AWLSRC(msg.source)
def handle_SYMTABSRC(self, symTabSource):
pass # Don't do anything by default
def __rx_SYMTABSRC(self, msg):
self.handle_SYMTABSRC(msg.source)
def handle_CPUDUMP(self, dumpText):
pass # Don't do anything by default
......@@ -242,15 +254,17 @@ class AwlSimClient(object):
__msgRxHandlers = {
AwlSimMessage.MSG_ID_REPLY : __rx_NOP,
AwlSimMessage.MSG_ID_EXCEPTION : __rx_EXCEPTION,
AwlSimMessage.MSG_ID_MAINTREQ : __rx_MAINTREQ,
AwlSimMessage.MSG_ID_PING : __rx_PING,
AwlSimMessage.MSG_ID_PONG : __rx_PONG,
AwlSimMessage.MSG_ID_CPUDUMP : __rx_CPUDUMP,
AwlSimMessage.MSG_ID_MAINTREQ : __rx_MAINTREQ,
AwlSimMessage.MSG_ID_AWLSRC : __rx_AWLSRC,
AwlSimMessage.MSG_ID_SYMTABSRC : __rx_SYMTABSRC,
AwlSimMessage.MSG_ID_IDENTS : __rx_IDENTS,
AwlSimMessage.MSG_ID_CPUSPECS : __rx_NOP,
AwlSimMessage.MSG_ID_RUNSTATE : __rx_NOP,
AwlSimMessage.MSG_ID_CPUDUMP : __rx_CPUDUMP,
AwlSimMessage.MSG_ID_MEMORY : __rx_MEMORY,
AwlSimMessage.MSG_ID_INSNSTATE : __rx_INSNSTATE,
AwlSimMessage.MSG_ID_RUNSTATE : __rx_NOP,
AwlSimMessage.MSG_ID_IDENTS : __rx_IDENTS,
}
# Main message processing
......@@ -360,16 +374,40 @@ class AwlSimClient(object):
return True
return False
def loadCode(self, codeSource):
def getAwlSource(self, identHash, sync=True):
if not self.__transceiver:
return False
msg = AwlSimMessage_AWLSRC(codeSource)
msg = AwlSimMessage_GET_AWLSRC(identHash)
if sync:
rxMsg = self.__sendAndWait(msg,
lambda rxMsg: rxMsg.msgId == AwlSimMessage.MSG_ID_AWLSRC)
return rxMsg.source
else:
self.__send(msg)
return True
def loadAwlSource(self, awlSource):
if not self.__transceiver:
return False
msg = AwlSimMessage_AWLSRC(awlSource)
status = self.__sendAndWaitFor_REPLY(msg, 10.0)
if status != AwlSimMessage_REPLY.STAT_OK:
raise AwlSimError("AwlSimClient: Failed to AWL source")
return True
def loadSymbolTable(self, symTabSource):
def getSymTabSource(self, identHash, sync=True):
if not self.__transceiver:
return False
msg = AwlSimMessage_GET_SYMTABSRC(identHash)
if sync:
rxMsg = self.__sendAndWait(msg,
lambda rxMsg: rxMsg.msgId == AwlSimMessage.MSG_ID_SYMTABSRC)
return rxMsg.source
else:
self.__send(msg)
return True
def loadSymTabSource(self, symTabSource):
if not self.__transceiver:
return False
msg = AwlSimMessage_SYMTABSRC(symTabSource)
......
......@@ -93,16 +93,16 @@ class AwlSimMessage(object):
MSG_ID_RESET = EnumGen.item
MSG_ID_SHUTDOWN = EnumGen.item
# Program sources and blocks
MSG_ID_GET_AWLSRC = EnumGen.itemAt(0x0100) #TODO not implemented, yet
MSG_ID_GET_AWLSRC = EnumGen.itemAt(0x0100)
MSG_ID_AWLSRC = EnumGen.item
MSG_ID_GET_SYMTABSRC = EnumGen.item #TODO not implemented, yet
MSG_ID_GET_SYMTABSRC = EnumGen.item
MSG_ID_SYMTABSRC = EnumGen.item
MSG_ID_HWMOD = EnumGen.item
MSG_ID_LIBSEL = EnumGen.item
MSG_ID_GET_IDENTS = EnumGen.itemAt(0x0190)
MSG_ID_IDENTS = EnumGen.item
#TODO: add messages to get compiled block info
#TODO: add messages to delete compiled blocks
#TODO: add messages to delete compiled blocks and sources
# Configuration
MSG_ID_GET_OPT = EnumGen.itemAt(0x0200) #TODO not implemented, yet
MSG_ID_OPT = EnumGen.item
......@@ -273,10 +273,30 @@ class AwlSimMessage_EXCEPTION(AwlSimMessage):
raise TransferError("EXCEPTION: Encoding error")
return cls(AwlSimErrorText(text, verboseText))
class _AwlSimMessage_GET_source(AwlSimMessage):
msgId = None
def __init__(self, identHash):
self.identHash = identHash
def toBytes(self):
payload = self.packBytes(self.identHash)
return AwlSimMessage.toBytes(self, len(payload)) + payload
@classmethod
def fromBytes(cls, payload):
try:
identHash = cls.unpackBytes(payload, 0)
except (ValueError, struct.error, AwlSimError) as e:
raise TransferError("GET_source: Invalid data format")
return cls(identHash = identHash)
class _AwlSimMessage_source(AwlSimMessage):
sourceClass = None
def __init__(self, source):
if not source:
source = self.sourceClass()
self.source = source
def toBytes(self):
......@@ -301,10 +321,16 @@ class _AwlSimMessage_source(AwlSimMessage):
raise TransferError("SOURCE: Data format error")
return cls(cls.sourceClass(name, filepath, sourceBytes))
class AwlSimMessage_GET_SYMTABSRC(_AwlSimMessage_GET_source):
msgId = AwlSimMessage.MSG_ID_GET_SYMTABSRC
class AwlSimMessage_SYMTABSRC(_AwlSimMessage_source):
msgId = AwlSimMessage.MSG_ID_SYMTABSRC
sourceClass = SymTabSource
class AwlSimMessage_GET_AWLSRC(_AwlSimMessage_GET_source):
msgId = AwlSimMessage.MSG_ID_GET_AWLSRC
class AwlSimMessage_AWLSRC(_AwlSimMessage_source):
msgId = AwlSimMessage.MSG_ID_AWLSRC
sourceClass = AwlSource
......@@ -881,9 +907,9 @@ class AwlSimMessageTransceiver(object):
AwlSimMessage.MSG_ID_PONG : AwlSimMessage_PONG,
AwlSimMessage.MSG_ID_RESET : AwlSimMessage_RESET,
AwlSimMessage.MSG_ID_SHUTDOWN : AwlSimMessage_SHUTDOWN,
#TODO AwlSimMessage.MSG_ID_GET_AWLSRC : AwlSimMessage_GET_AWLSRC,
AwlSimMessage.MSG_ID_GET_AWLSRC : AwlSimMessage_GET_AWLSRC,
AwlSimMessage.MSG_ID_AWLSRC : AwlSimMessage_AWLSRC,
#TODO AwlSimMessage.MSG_ID_GET_SYMTABSRC : AwlSimMessage_GET_SYMTABSRC,
AwlSimMessage.MSG_ID_GET_SYMTABSRC : AwlSimMessage_GET_SYMTABSRC,
AwlSimMessage.MSG_ID_SYMTABSRC : AwlSimMessage_SYMTABSRC,
AwlSimMessage.MSG_ID_HWMOD : AwlSimMessage_HWMOD,
AwlSimMessage.MSG_ID_LIBSEL : AwlSimMessage_LIBSEL,
......
......@@ -212,10 +212,10 @@ class AwlSimServer(object):
self.__sim = AwlSim()
self.setCycleExitHook(None)
# List of loaded AwlSource()s
# Container of loaded and managed AwlSource()s
self.awlSourceContainer = SourceContainer()
# List of loaded SymTabSource()s
self.loadedSymTabSources = []
# Container of loaded and managed SymTabSource()s
self.symTabSourceContainer = SourceContainer()
# List of tuples of loaded hardware modules:
# (hwModName, parameterDict)
self.loadedHwModules = []
......@@ -413,7 +413,7 @@ class AwlSimServer(object):
def __resetSources(self):
self.awlSourceContainer.clear()
self.loadedSymTabSources = []
self.symTabSourceContainer.clear()
self.loadedHwModules = []
self.loadedLibSelections = []
# Schedule a CPU restart/rebuild.
......@@ -423,8 +423,7 @@ class AwlSimServer(object):
parser = AwlParser()
parser.parseSource(awlSource)
srcManager = SourceManager(awlSource,
self.awlSourceContainer)
srcManager = SourceManager(awlSource)
needRebuild = False
if self.__state == self.STATE_RUN or\
......@@ -439,9 +438,13 @@ class AwlSimServer(object):
symbolTable = SymTabParser.parseSource(symTabSource,
autodetectFormat = True,
mnemonics = self.__sim.cpu.getSpecs().getMnemonics())
srcManager = SourceManager(symTabSource)
self.setRunState(self.STATE_STOP)
self.__sim.loadSymbolTable(symbolTable)
self.loadedSymTabSources.append(symTabSource)
self.symTabSourceContainer.addManager(srcManager)
def loadHardwareModule(self, moduleName, paramDict):
printInfo("Loading hardware module '%s'..." % moduleName)
......@@ -527,12 +530,24 @@ class AwlSimServer(object):
#TODO add a call that can remove sources from the CPU.
def __rx_GET_AWLSRC(self, client, msg):
printDebug("Received message: GET_AWLSRC")
awlSource = self.awlSourceContainer.getSourceByIdent(msg.identHash)
reply = AwlSimMessage_AWLSRC(awlSource)
client.transceiver.send(reply)
def __rx_AWLSRC(self, client, msg):
printDebug("Received message: AWLSRC")
status = AwlSimMessage_REPLY.STAT_OK
self.loadAwlSource(msg.source)
client.transceiver.send(AwlSimMessage_REPLY.make(msg, status))
def __rx_GET_SYMTABSRC(self, client, msg):
printDebug("Received message: GET_SYMTABSRC")
symTabSource = self.symTabSourceContainer.getSourceByIdent(msg.identHash)
reply = AwlSimMessage_SYMTABSRC(symTabSource)
client.transceiver.send(reply)
def __rx_SYMTABSRC(self, client, msg):
printDebug("Received message: SYMTABSRC")
status = AwlSimMessage_REPLY.STAT_OK
......@@ -635,7 +650,7 @@ class AwlSimServer(object):
if msg.getFlags & msg.GET_AWLSRCS:
awlSrcs = self.awlSourceContainer.getSources()
if msg.getFlags & msg.GET_SYMTABSRCS:
symSrcs = self.loadedSymTabSources
symSrcs = self.symTabSourceContainer.getSources()
if msg.getFlags & msg.GET_HWMODS:
hwMods = self.loadedHwModules
if msg.getFlags & msg.GET_LIBSELS:
......@@ -651,7 +666,9 @@ class AwlSimServer(object):
AwlSimMessage.MSG_ID_SHUTDOWN : __rx_SHUTDOWN,
AwlSimMessage.MSG_ID_RUNSTATE : __rx_RUNSTATE,
AwlSimMessage.MSG_ID_GET_RUNSTATE : __rx_GET_RUNSTATE,
AwlSimMessage.MSG_ID_GET_AWLSRC : __rx_GET_AWLSRC,
AwlSimMessage.MSG_ID_AWLSRC : __rx_AWLSRC,
AwlSimMessage.MSG_ID_GET_SYMTABSRC : __rx_GET_SYMTABSRC,
AwlSimMessage.MSG_ID_SYMTABSRC : __rx_SYMTABSRC,
AwlSimMessage.MSG_ID_HWMOD : __rx_HWMOD,
AwlSimMessage.MSG_ID_LIBSEL : __rx_LIBSEL,
......
......@@ -64,51 +64,6 @@ class RunState(QObject):
self.port = port
self.__emitStateChanged()
class ToolButton(QPushButton):
ICONSIZE = (32, 32)
BTNFACT = 1.2
def __init__(self, iconName, description, parent=None):
QPushButton.__init__(self, parent)
iconSize = QSize(self.ICONSIZE[0], self.ICONSIZE[1])
btnSize = QSize(int(round(iconSize.width() * self.BTNFACT)),
int(round(iconSize.height() * self.BTNFACT)))
self.setMinimumSize(btnSize)
self.setMaximumSize(btnSize)
self.setIcon(getIcon(iconName))
self.setIconSize(iconSize)
self.setToolTip(description)
class CheckableToolButton(ToolButton):
def __init__(self,
checkedIconName, uncheckedIconName="",
checkedToolTip="", uncheckedToolTip="",
parent=None):
ToolButton.__init__(self, uncheckedIconName, "", parent)
self.__checkedIconName = checkedIconName
self.__uncheckedIconName = uncheckedIconName
if not self.__uncheckedIconName:
self.__uncheckedIconName = self.__checkedIconName
self.__checkedToolTip = checkedToolTip
self.__uncheckedToolTip = uncheckedToolTip
if not self.__uncheckedToolTip:
self.__uncheckedToolTip = self.__checkedToolTip
self.setCheckable(True)
self.setChecked(False)
self.__handleToggle(False)
self.toggled.connect(self.__handleToggle)
def __handleToggle(self, checked):
self.setToolTip(self.__checkedToolTip if checked else\
self.__uncheckedToolTip)
self.setIcon(getIcon(self.__checkedIconName if checked else\
self.__uncheckedIconName))
class OnlineSelectAction(QAction):
def __init__(self, parent):
QAction.__init__(self, getIcon("network"), "", parent)
......@@ -631,11 +586,11 @@ class CpuWidget(QWidget):
client.loadHardwareModule(modDesc.getModuleName(),
modDesc.getParameters())
for symTabSource in symTabSources:
client.loadSymbolTable(symTabSource)
client.loadSymTabSource(symTabSource)
for libSel in libSelections:
client.loadLibraryBlock(libSel)
for awlSource in awlSources:
client.loadCode(awlSource)
client.loadAwlSource(awlSource)
self.state.setState(RunState.STATE_ONLINE)
except AwlParserError as e:
......@@ -685,14 +640,14 @@ class CpuWidget(QWidget):
printVerbose("Single AWL download: %s/%s" %\
(awlSource.name,
awlSource.identHashStr))
client.loadCode(awlSource)
client.loadAwlSource(awlSource)
elif selectedResource == projectWidget.RES_SYMTABS:
symTabSource = projectWidget.getCurrentSymTabSource()
if symTabSource:
printVerbose("Single sym download: %s/%s" %\
(symTabSource.name,
symTabSource.identHashStr))
client.loadSymbolTable(symTabSource)
client.loadSymTabSource(symTabSource)
elif selectedResource == projectWidget.RES_LIBSELS:
libSelections = projectWidget.getLibSelections()
printVerbose("Single libSelections download.")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment