--- a/PLCGenerator.py Tue Nov 27 12:58:34 2007 +0100
+++ b/PLCGenerator.py Thu Dec 06 18:05:29 2007 +0100
@@ -34,6 +34,7 @@
currentProject = None
currentProgram = ""
+datatypeComputed = {}
pouComputed = {}
def ReIndentText(text, nb_spaces):
@@ -53,6 +54,49 @@
compute += "\n"
return compute
+def GenerateDataType(datatype_name):
+ if not datatypeComputed.get(datatype_name, True):
+ datatypeComputed[datatype_name] = True
+ global currentProject, currentProgram
+ datatype = currentProject.getDataType(datatype_name)
+ datatype_def = " %s :"%datatype.getName()
+ basetype_content = datatype.baseType.getContent()
+ if basetype_content["value"] is None:
+ datatype_def += " %s"%basetype_content["name"]
+ elif basetype_content["name"] == "derived":
+ basetype_name = basetype_content["value"].getName()
+ GenerateDataType(basetype_name)
+ datatype_def += " %s"%basetype_name
+ elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned"]:
+ base_type = basetype_content["value"].baseType.getContent()
+ if base_type["value"] is None:
+ basetype_name = base_type["name"]
+ else:
+ basetype_name = base_type["value"].getName()
+ GenerateDataType(basetype_name)
+ min_value = basetype_content["value"].range.getLower()
+ max_value = basetype_content["value"].range.getUpper()
+ datatype_def += " %s (%d..%d)"%(basetype_name, min_value, max_value)
+ elif basetype_content["name"] == "enum":
+ values = []
+ for value in basetype_content["value"].values.getValue():
+ values.append(value.getName())
+ datatype_def += " (%s)"%", ".join(values)
+ elif basetype_content["name"] == "array":
+ base_type = basetype_content["value"].baseType.getContent()
+ if base_type["value"] is None:
+ basetype_name = base_type["name"]
+ else:
+ basetype_name = base_type["value"].getName()
+ GenerateDataType(basetype_name)
+ dimensions = []
+ for dimension in basetype_content["value"].getDimension():
+ dimensions.append("0..%d"%(dimension.getUpper() - 1))
+ datatype_def += " ARRAY [%s] OF %s"%(",".join(dimensions), basetype_name)
+ if datatype.initialValue is not None:
+ datatype_def += " := %s"%str(datatype.initialValue.getValue())
+ currentProgram += "%s;\n"%datatype_def
+
def GeneratePouProgram(pou_name):
if not pouComputed.get(pou_name, True):
pouComputed[pou_name] = True
@@ -64,6 +108,8 @@
else:
raise ValueError, "Undefined pou type"
pou_program.GenerateInterface(pou.getInterface())
+ pou_program.GenerateConnectionTypes(pou)
+ #print pou.getName(), pou_program.ConnectionTypes, pou_program.RelatedConnections
pou_program.GenerateProgram(pou)
currentProgram += pou_program.GenerateSTProgram()
@@ -77,7 +123,11 @@
config += " CONSTANT"
config += "\n"
for var in varlist.getVariable():
- var_type = var.getType().getValue()
+ vartype_content = var.getType().getContent()
+ if vartype_content["value"] is None:
+ var_type = vartype_content["name"]
+ else:
+ var_type = vartype_content["value"].getName()
config += " %s "%var.getName()
address = var.getAddress()
if address:
@@ -110,12 +160,16 @@
resrce += " CONSTANT"
resrce += "\n"
for var in varlist.getVariable():
- var_type = var.getType().getValue()
+ vartype_content = var.getType().getContent()
+ if vartype_content["value"] is None:
+ var_type = vartype_content["name"]
+ else:
+ var_type = vartype_content["value"].getName()
resrce += " %s "%var.getName()
address = var.getAddress()
if address:
resrce += "AT %s "%address
- resrce += ": %s"%var.getType().getValue()
+ resrce += ": %s"%var_type
initial = var.getInitialValue()
if initial:
value = str(initial.getValue())
@@ -171,6 +225,8 @@
self.InitialSteps = []
self.ComputedBlocks = {}
self.ComputedConnectors = {}
+ self.ConnectionTypes = {}
+ self.RelatedConnections = []
self.SFCNetworks = {"Steps":{}, "Transitions":{}, "Actions":{}}
self.SFCComputedBlocks = ""
self.ActionNumber = 0
@@ -187,22 +243,71 @@
return True
return False
+ def GetVariableType(self, name):
+ for list_type, retain, constant, located, vars in self.Interface:
+ for var_type, var_name, var_address, var_initial in vars:
+ if name == var_name:
+ return var_type
+ return None
+
+ def GetConnectedConnection(self, connection, body):
+ links = connection.getConnections()
+ if links and len(links) == 1:
+ return self.GetLinkedConnection(links[0], body)
+ return None
+
+ def GetLinkedConnection(self, link, body):
+ parameter = link.getFormalParameter()
+ instance = body.getContentInstance(link.getRefLocalId())
+ if isinstance(instance, (plcopen.inVariable, plcopen.inOutVariable, plcopen.continuation, plcopen.contact, plcopen.coil)):
+ return instance.connectionPointOut
+ elif isinstance(instance, plcopen.block):
+ outputvariables = instance.outputVariables.getVariable()
+ if len(outputvariables) == 1:
+ return outputvariables[0].connectionPointOut
+ elif parameter:
+ for variable in outputvariables:
+ if variable.getFormalParameter() == parameter:
+ return variable.connectionPointOut
+ else:
+ point = link.getPosition()[-1]
+ for variable in outputvariables:
+ relposition = variable.connectionPointOut.getRelPosition()
+ blockposition = instance.getPosition()
+ if point.x == blockposition.x + relposition[0] and point.y == blockposition.y + relposition[1]:
+ return variable.connectionPointOut
+ elif isinstance(instance, plcopen.leftPowerRail):
+ outputconnections = instance.getConnectionPointOut()
+ if len(outputconnections) == 1:
+ return outputconnections[0]
+ else:
+ point = link.getPosition()[-1]
+ for outputconnection in outputconnections:
+ relposition = outputconnection.getRelPosition()
+ powerrailposition = instance.getPosition()
+ if point.x == powerrailposition.x + relposition[0] and point.y == powerrailposition.y + relposition[1]:
+ return outputconnection
+ return None
+
+ def ExtractRelatedConnections(self, connection):
+ for i, related in enumerate(self.RelatedConnections):
+ if connection in related:
+ return self.RelatedConnections.pop(i)
+ return [connection]
+
def GenerateInterface(self, interface):
if self.Type == "FUNCTION":
- self.ReturnType = interface.getReturnType().getValue()
+ returntype_content = interface.getReturnType().getContent()
+ if returntype_content["value"] is None:
+ self.ReturnType = returntype_content["name"]
+ else:
+ self.ReturnType = returntype_content["value"].getName()
for varlist in interface.getContent():
variables = []
located = False
for var in varlist["value"].getVariable():
- type = var.getType().getValue()
- if not isinstance(type, (StringType, UnicodeType)):
- type = type.getName()
- GeneratePouProgram(type)
- blocktype = GetBlockType(type)
- if blocktype:
- variables.extend(blocktype["initialise"](type, var.getName()))
- located = False
- else:
+ vartype_content = var.getType().getContent()
+ if vartype_content["value"] is None:
initial = var.getInitialValue()
if initial:
initial_value = initial.getValue()
@@ -211,11 +316,120 @@
address = var.getAddress()
if address:
located = True
- variables.append((type, var.getName(), address, initial_value))
+ variables.append((vartype_content["name"], var.getName(), address, initial_value))
+ else:
+ var_type = vartype_content["value"].getName()
+ GeneratePouProgram(var_type)
+ blocktype = GetBlockType(var_type)
+ if blocktype is not None:
+ variables.extend(blocktype["initialise"](var_type, var.getName()))
+ located = False
+ else:
+ initial = var.getInitialValue()
+ if initial:
+ initial_value = initial.getValue()
+ else:
+ initial_value = None
+ address = var.getAddress()
+ if address:
+ located = True
+ variables.append((vartype_content["value"].getName(), var.getName(), address, initial_value))
if len(variables) > 0:
self.Interface.append((varTypeNames[varlist["name"]], varlist["value"].getRetain(),
varlist["value"].getConstant(), located, variables))
+ def GenerateConnectionTypes(self, pou):
+ body = pou.getBody()
+ body_content = body.getContent()
+ body_type = body_content["name"]
+ if body_type in ["FBD", "LD", "SFC"]:
+ for instance in body.getContentInstances():
+ if isinstance(instance, (plcopen.inVariable, plcopen.outVariable, plcopen.inOutVariable)):
+ expression = instance.getExpression()
+ var_type = self.GetVariableType(expression)
+ if expression == pou.getName():
+ returntype_content = pou.interface.getReturnType().getContent()
+ if returntype_content["value"] is None:
+ var_type = returntype_content["name"]
+ else:
+ var_type = returntype_content["value"].getName()
+ elif var_type is None:
+ var_type = expression.split("#")[0]
+ if isinstance(instance, (plcopen.inVariable, plcopen.inOutVariable)):
+ self.ConnectionTypes[instance.connectionPointOut] = var_type
+ if isinstance(instance, (plcopen.outVariable, plcopen.inOutVariable)):
+ self.ConnectionTypes[instance.connectionPointIn] = var_type
+ connected = self.GetConnectedConnection(instance.connectionPointIn, body)
+ if connected and connected not in self.ConnectionTypes:
+ for connection in self.ExtractRelatedConnections(connected):
+ self.ConnectionTypes[connection] = var_type
+ elif isinstance(instance, (plcopen.contact, plcopen.coil)):
+ self.ConnectionTypes[instance.connectionPointOut] = "BOOL"
+ self.ConnectionTypes[instance.connectionPointIn] = "BOOL"
+ connected = self.GetConnectedConnection(instance.connectionPointIn, body)
+ if connected and connected not in self.ConnectionTypes:
+ for connection in self.ExtractRelatedConnections(connected):
+ self.ConnectionTypes[connection] = "BOOL"
+ elif isinstance(instance, plcopen.leftPowerRail):
+ for connection in instance.getConnectionPointOut():
+ self.ConnectionTypes[connection] = "BOOL"
+ elif isinstance(instance, plcopen.rightPowerRail):
+ for connection in instance.getConnectionPointIn():
+ self.ConnectionTypes[connection] = "BOOL"
+ connected = self.GetConnectedConnection(connection, body)
+ if connected and connected not in self.ConnectionTypes:
+ for connection in self.ExtractRelatedConnections(connected):
+ self.ConnectionTypes[connection] = "BOOL"
+ elif isinstance(instance, plcopen.transition):
+ content = instance.condition.getContent()
+ if content["name"] == "connection" and len(content["value"]) == 1:
+ connected = self.GetLinkedConnection(content["value"][0], body)
+ if connected and connected not in self.ConnectionTypes:
+ for connection in self.ExtractRelatedConnections(connected):
+ self.ConnectionTypes[connection] = "BOOL"
+ elif isinstance(instance, plcopen.block):
+ block_infos = GetBlockType(instance.getTypeName())
+ undefined = {}
+ for variable in instance.outputVariables.getVariable():
+ output_name = variable.getFormalParameter()
+ for oname, otype, oqualifier in block_infos["outputs"]:
+ if output_name == oname and variable.connectionPointOut not in self.ConnectionTypes:
+ if otype.startswith("ANY"):
+ if otype not in undefined:
+ undefined[otype] = []
+ undefined[otype].append(variable.connectionPointOut)
+ else:
+ for connection in self.ExtractRelatedConnections(variable.connectionPointOut):
+ self.ConnectionTypes[connection] = otype
+ for variable in instance.inputVariables.getVariable():
+ input_name = variable.getFormalParameter()
+ for iname, itype, iqualifier in block_infos["inputs"]:
+ if input_name == iname:
+ connected = self.GetConnectedConnection(variable.connectionPointIn, body)
+ if itype.startswith("ANY"):
+ if itype not in undefined:
+ undefined[itype] = []
+ undefined[itype].append(variable.connectionPointIn)
+ if connected:
+ undefined[itype].append(connected)
+ else:
+ self.ConnectionTypes[variable.connectionPointIn] = itype
+ if connected and connected not in self.ConnectionTypes:
+ for connection in self.ExtractRelatedConnections(connected):
+ self.ConnectionTypes[connection] = itype
+ for var_type, connections in undefined.items():
+ related = []
+ for connection in connections:
+ if connection in self.ConnectionTypes:
+ var_type = self.ConnectionTypes[connection]
+ else:
+ related.extend(self.ExtractRelatedConnections(connection))
+ if var_type.startswith("ANY") and len(related) > 0:
+ self.RelatedConnections.append(related)
+ else:
+ for connection in related:
+ self.ConnectionTypes[connection] = var_type
+
def GenerateProgram(self, pou):
body = pou.getBody()
body_content = body.getContent()
@@ -223,7 +437,20 @@
if body_type in ["IL","ST"]:
self.Program = ReIndentText(body_content["value"].getText(), 2)
elif body_type == "FBD":
+ orderedInstances = []
+ otherInstances = []
for instance in body.getContentInstances():
+ if isinstance(instance, (plcopen.outVariable, plcopen.inOutVariable, plcopen.block)):
+ executionOrderId = instance.getExecutionOrderId()
+ if executionOrderId > 0:
+ orderedInstances.append((executionOrderId, instance))
+ else:
+ otherInstances.append(instance)
+ elif isinstance(instance, plcopen.connector):
+ otherInstances.append(instance)
+ orderedInstances.sort()
+ instances = [instance for (executionOrderId, instance) in orderedInstances] + otherInstances
+ for instance in instances:
if isinstance(instance, (plcopen.outVariable, plcopen.inOutVariable)):
var = instance.getExpression()
connections = instance.connectionPointIn.getConnections()
@@ -231,8 +458,9 @@
expression = self.ComputeFBDExpression(body, connections[0])
self.Program += " %s := %s;\n"%(var, expression)
elif isinstance(instance, plcopen.block):
- type = instance.getTypeName()
- block_infos = GetBlockType(type)
+ block_type = instance.getTypeName()
+ self.GeneratePouProgram(block_type)
+ block_infos = GetBlockType(block_type)
block_infos["generate"](self, instance, body, None)
elif isinstance(instance, plcopen.connector):
connector = instance.getName()
@@ -271,15 +499,16 @@
for initialstep in self.InitialSteps:
self.ComputeSFCStep(initialstep)
- def ComputeFBDExpression(self, body, link):
+ def ComputeFBDExpression(self, body, link, order = False):
localid = link.getRefLocalId()
instance = body.getContentInstance(localid)
if isinstance(instance, (plcopen.inVariable, plcopen.inOutVariable)):
return instance.getExpression()
elif isinstance(instance, plcopen.block):
block_type = instance.getTypeName()
+ self.GeneratePouProgram(block_type)
block_infos = GetBlockType(block_type)
- return block_infos["generate"](self, instance, body, link)
+ return block_infos["generate"](self, instance, body, link, order)
elif isinstance(instance, plcopen.continuation):
name = instance.getName()
computed_value = self.ComputedConnectors.get(name, None)
@@ -290,7 +519,7 @@
if tmp_instance.getName() == name:
connections = tmp_instance.connectionPointIn.getConnections()
if connections and len(connections) == 1:
- expression = self.ComputeFBDExpression(body, connections[0])
+ expression = self.ComputeFBDExpression(body, connections[0], order)
self.ComputedConnectors[name] = expression
return expression
raise ValueError, "No connector found"
@@ -304,6 +533,7 @@
paths.append(None)
elif isinstance(next, plcopen.block):
block_type = next.getTypeName()
+ self.GeneratePouProgram(block_type)
block_infos = GetBlockType(block_type)
paths.append(block_infos["generate"](self, next, body, connection))
else:
@@ -662,8 +892,15 @@
global currentProject, currentProgram
currentProject = project
currentProgram = ""
+ for datatype in project.getDataTypes():
+ datatypeComputed[datatype.getName()] = False
for pou in project.getPous():
pouComputed[pou.getName()] = False
+ if len(datatypeComputed) > 0:
+ currentProgram += "TYPE\n"
+ for datatype_name in datatypeComputed.keys():
+ GenerateDataType(datatype_name)
+ currentProgram += "END_TYPE\n\n"
for pou_name in pouComputed.keys():
GeneratePouProgram(pou_name)
for config in project.getConfigurations():