--- a/PLCGenerator.py Wed Jan 31 16:31:39 2007 +0100
+++ b/PLCGenerator.py Thu Feb 01 18:09:34 2007 +0100
@@ -29,6 +29,21 @@
varTypeNames = {"localVars" : "VAR", "tempVars" : "VAR_TEMP", "inputVars" : "VAR_INPUT",
"outputVars" : "VAR_OUTPUT", "inOutVars" : "VAR_IN_OUT", "externalVars" : "VAR_EXTERNAL",
"globalVars" : "VAR_GLOBAL", "accessVars" : "VAR_ACCESS"}
+
+def ReIndentText(text, nb_spaces):
+ compute = ""
+ lines = text.splitlines()
+ if len(lines) > 0:
+ spaces = 0
+ while lines[0][spaces] == " ":
+ spaces += 1
+ indent = ""
+ for i in xrange(spaces, nb_spaces):
+ indent += " "
+ for line in lines:
+ compute += "%s%s\n"%(indent, line)
+ return compute
+
"""
Module implementing methods for generating PLC programs in ST or IL
"""
@@ -38,31 +53,36 @@
def __init__(self, name, type):
self.Name = name
self.Type = type
- self.Interface = {}
- self.Steps = {}
- self.Transitions = {}
- self.Order = []
+ self.ReturnType = None
+ self.Interface = []
+ self.InitialSteps = []
+ self.SFCNetworks = {"Steps":{}, "Transitions":{}, "Actions":{}}
self.Program = ""
+ def IsAlreadyDefined(self, name):
+ for list_type, retain, constant, vars in self.Interface:
+ for var_type, var_name in vars:
+ if name == var_name:
+ return True
+ return False
+
def GenerateInterface(self, interface):
if self.Type == "FUNCTION":
- self.Interface["returnType"] = interface.getReturnType().getValue()
+ self.ReturnType = interface.getReturnType().getValue()
for varlist in interface.getContent():
- variables = {}
+ variables = []
for var in varlist["value"].getVariable():
type = var.getType().getValue()
- if type not in variables:
- variables[type] = []
- variables[type].append(var.getName())
- self.Interface[(varTypeNames[varlist["name"]], varlist["value"].getRetain(),
- varlist["value"].getConstant())] = variables
+ variables.append((type, var.getName()))
+ self.Interface.append((varTypeNames[varlist["name"]], varlist["value"].getRetain(),
+ varlist["value"].getConstant(), variables))
def GenerateProgram(self, pou):
body = pou.getBody()
body_content = body.getContent()
body_type = body_content["name"]
if body_type in ["IL","ST"]:
- self.Program = "%s\n"%body_content["value"].getText()
+ self.Program = ReIndentText(body_content["value"].getText(), 2)
elif body_type == "FBD":
for instance in body.getContentInstances():
if isinstance(instance, plcopen.outVariable):
@@ -81,48 +101,15 @@
elif body_type == "SFC":
for instance in body.getContentInstances():
if isinstance(instance, plcopen.step):
- self.GenerateSFCSteps(instance, pou)
+ self.GenerateSFCStep(instance, pou)
elif isinstance(instance, plcopen.actionBlock):
- self.GenerateSFCActions(instance, pou)
+ self.GenerateSFCStepActions(instance, pou)
elif isinstance(instance, plcopen.transition):
- self.GenerateSFCTransitions(instance, pou)
+ self.GenerateSFCTransition(instance, pou)
elif isinstance(instance, plcopen.jumpStep):
self.GenerateSFCJump(instance, pou)
- for name, values in self.Steps.items():
- if values['initial']:
- self.GenerateSFCStepOrder(name, [])
- steps_type = "ARRAY [1..%d] OF BOOL"%len(self.Order)
- if ("VAR", False, False) not in self.Interface:
- self.Interface[("VAR", False, False)] = {}
- if steps_type not in self.Interface[("VAR", False, False)]:
- self.Interface[("VAR", False, False)][steps_type] = ["Steps"]
- else:
- self.Interface[("VAR", False, False)][steps_type].append("Steps")
- for index, name in enumerate(self.Order):
- values = self.Steps[name]
- self.Program += " IF Steps[%d] THEN\n"%index
- for action in values["actions"]:
- if action["qualifier"] == "N":
- for line in action["content"].splitlines():
- self.Program += " %s\n"%line
- elif action["qualifier"] == "S":
- if "R_TRIG" not in self.Interface[("VAR", False, False)]:
- self.Interface[("VAR", False, False)]["R_TRIG"] = []
- i = 1
- name = "R_TRIG%d"%i
- while name in self.Interface[("VAR", False, False)]["R_TRIG"]:
- i += 1
- name = "R_TRIG%d"%i
- self.Interface[("VAR", False, False)]["R_TRIG"].append(name)
- self.Program += " IF %s(CLK := Steps[%d]) THEN\n"%(name, index)
- self.Program += " %s := TRUE;\n"%action["content"]
- for transition in values["transitions"]:
- if transition["compute"] != '':
- self.Program += " %s %s"%(transition["condition"], transition["compute"])
- self.Program += " IF %s THEN\n"%transition["condition"]
- for target in transition["targets"]:
- self.Program += " Steps[%d] := TRUE;\n"%self.Order.index(target)
- self.Program += " Steps[%d] := FALSE;\n"%index
+ for initialstep in self.InitialSteps:
+ self.ComputeSFCStep(initialstep)
def ComputeFBDExpression(self, body, link):
localid = link.getRefLocalId()
@@ -143,12 +130,10 @@
variable = instance.outputVariables.getVariable()[0]
return self.ExtractModifier(variable, "%s(%s)"%(type, ", ".join(vars)))
elif block_infos["type"] == "functionBlock":
- if ("VAR", False, False) not in self.Interface:
- self.Interface[("VAR", False, False)] = {}
- if type not in self.Interface[("VAR", False, False)]:
- self.Interface[("VAR", False, False)][type] = []
- if name not in self.Interface[("VAR", False, False)][type]:
- self.Interface[("VAR", False, False)][type].append(name)
+ if self.Interface[-1][0] != "VAR" or self.Interface[-1][1] or self.Interface[-1][2]:
+ self.Interface.append(("VAR", False, False, []))
+ if not self.IsAlreadyDefined(name):
+ self.Interface[-1][3].append((type, name))
vars = []
for variable in instance.inputVariables.getVariable():
connections = variable.connectionPointIn.getConnections()
@@ -190,11 +175,12 @@
else:
return variable
- def GenerateSFCSteps(self, step, pou):
+ def GenerateSFCStep(self, step, pou):
step_name = step.getName()
- if step_name not in self.Steps:
+ if step_name not in self.SFCNetworks["Steps"].keys():
+ if step.getInitialStep():
+ self.InitialSteps.append(step_name)
step_infos = {"initial" : step.getInitialStep(), "transitions" : [], "actions" : []}
- self.Steps[step_name] = step_infos
if step.connectionPointIn:
instances = []
connections = step.connectionPointIn.getConnections()
@@ -202,7 +188,7 @@
instanceLocalId = connections[0].getRefLocalId()
instance = pou.body.getContentInstance(instanceLocalId)
if isinstance(instance, plcopen.transition):
- self.GenerateSFCTransitions(instance, pou)
+ self.GenerateSFCTransition(instance, pou)
instances.append(instance)
elif isinstance(instance, plcopen.selectionConvergence):
for connectionPointIn in instance.getConnectionPointIn():
@@ -210,10 +196,21 @@
if len(divergence_connections) == 1:
transitionLocalId = connections[0].getRefLocalId()
transition = pou.body.getContentInstance(transitionLocalId)
- self.GenerateSFCTransitions(transition, pou)
+ self.GenerateSFCTransition(transition, pou)
+ instances.append(transition)
+ elif isinstance(instance, plcopen.simultaneousDivergence):
+ connectionPointIn = instance.getConnectionPointIn()
+ if connectionPointIn:
+ divergence_connections = connectionPointIn.getConnections()
+ if len(divergence_connections) == 1:
+ transitionLocalId = connections[0].getRefLocalId()
+ transition = pou.body.getContentInstance(transitionLocalId)
+ self.GenerateSFCTransition(transition, pou)
instances.append(transition)
for instance in instances:
- self.Transitions[instance]["targets"].append(step_name)
+ if instance in self.SFCNetworks["Transitions"].keys():
+ self.SFCNetworks["Transitions"][instance]["to"].append(step_name)
+ self.SFCNetworks["Steps"][step_name] = step_infos
def GenerateSFCJump(self, jump, pou):
jump_target = jump.getTargetName()
@@ -224,7 +221,7 @@
instanceLocalId = connections[0].getRefLocalId()
instance = pou.body.getContentInstance(instanceLocalId)
if isinstance(instance, plcopen.transition):
- self.GenerateSFCTransitions(instance, pou)
+ self.GenerateSFCTransition(instance, pou)
instances.append(instance)
elif isinstance(instance, plcopen.selectionConvergence):
for connectionPointIn in instance.getConnectionPointIn():
@@ -232,113 +229,160 @@
if len(divergence_connections) == 1:
transitionLocalId = divergence_connections[0].getRefLocalId()
transition = pou.body.getContentInstance(transitionLocalId)
- self.GenerateSFCTransitions(transition, pou)
+ self.GenerateSFCTransition(transition, pou)
+ instances.append(transition)
+ elif isinstance(instance, plcopen.simultaneousDivergence):
+ connectionPointIn = instance.getConnectionPointIn()
+ if connectionPointIn:
+ divergence_connections = connectionPointIn.getConnections()
+ if len(divergence_connections) == 1:
+ transitionLocalId = connections[0].getRefLocalId()
+ transition = pou.body.getContentInstance(transitionLocalId)
+ self.GenerateSFCTransition(transition, pou)
instances.append(transition)
for instance in instances:
- self.Transitions[instance]["targets"].append(jump_target)
-
- def GenerateSFCActions(self, actionBlock, pou):
+ if instance in self.SFCNetworks["Transitions"].keys():
+ self.SFCNetworks["Transitions"][instance]["to"].append(jump_target)
+
+ def GenerateSFCStepActions(self, actionBlock, pou):
connections = actionBlock.connectionPointIn.getConnections()
if len(connections) == 1:
stepLocalId = connections[0].getRefLocalId()
step = pou.body.getContentInstance(stepLocalId)
+ self.GenerateSFCStep(step, pou)
step_name = step.getName()
- if step_name not in self.Steps:
- self.GenerateSFCSteps(step, pou)
- if step_name in self.Steps:
+ if step_name in self.SFCNetworks["Steps"].keys():
actions = actionBlock.getActions()
for action in actions:
- action_infos = {"qualifier" : action["qualifier"], "content" : ""}
- if action["type"] == "inline":
- action_infos["content"] = action["value"]
- elif action["type"] == "reference":
- actionContent = pou.getAction(action["value"])
- if actionContent:
- actionType = actionContent.getBodyType()
- actionBody = actionContent.getBody()
- if actionType in ["ST", "IL"]:
- action_infos["content"] = actionContent.getText()
- elif actionType == "FBD":
- for instance in actionBody.getContentInstances():
- if isinstance(instance, plcopen.outVariable):
- var = instance.getExpression()
- connections = instance.connectionPointIn.getConnections()
- if connections and len(connections) == 1:
- expression = self.ComputeFBDExpression(actionBody, connections[0])
- action_infos["content"] = self.Program + " %s := %s;"%(var, expression)
- self.Program = ""
- elif actionType == "LD":
- for instance in actionbody.getContentInstances():
- if isinstance(instance, plcopen.coil):
- paths = self.GenerateLDPaths(instance, actionBody)
- variable = self.ExtractModifier(instance, instance.getVariable())
- expression = self.ComputeLDExpression(paths, True)
- action_infos["content"] = self.Program + " %s := %s;"%(variable, expression)
- self.Program = ""
- else:
- action_infos["content"] = action["value"]
- self.Steps[step_name]["actions"].append(action_infos)
-
- def GenerateSFCTransitions(self, transition, pou):
- if transition not in self.Transitions:
+ action_infos = {"qualifier" : action["qualifier"], "content" : action["value"]}
+ if "duration" in action:
+ action_infos["duration"] = action["duration"]
+ if "indicator" in action:
+ action_infos["indicator"] = action["indicator"]
+ if action["type"] == "reference":
+ self.GenerateSFCAction(action["value"], pou)
+ self.SFCNetworks["Steps"][step_name]["actions"].append(action_infos)
+
+ def GenerateSFCAction(self, action_name, pou):
+ if action_name not in self.SFCNetworks["Actions"].keys():
+ actionContent = pou.getAction(action_name)
+ if actionContent:
+ actionType = actionContent.getBodyType()
+ actionBody = actionContent.getBody()
+ if actionType in ["ST", "IL"]:
+ self.SFCNetworks["Actions"][action_name] = ReIndentText(actionContent.getText(), 4)
+ elif actionType == "FBD":
+ for instance in actionBody.getContentInstances():
+ if isinstance(instance, plcopen.outVariable):
+ var = instance.getExpression()
+ connections = instance.connectionPointIn.getConnections()
+ if connections and len(connections) == 1:
+ expression = self.ComputeFBDExpression(actionBody, connections[0])
+ self.SFCNetworks["Actions"][action_name] = self.Program + " %s := %s;\n"%(var, expression)
+ self.Program = ""
+ elif actionType == "LD":
+ for instance in actionbody.getContentInstances():
+ if isinstance(instance, plcopen.coil):
+ paths = self.GenerateLDPaths(instance, actionBody)
+ variable = self.ExtractModifier(instance, instance.getVariable())
+ expression = self.ComputeLDExpression(paths, True)
+ self.SFCNetworks["Actions"][action_name] = self.Program + " %s := %s;\n"%(variable, expression)
+ self.Program = ""
+
+ def GenerateSFCTransition(self, transition, pou):
+ if transition not in self.SFCNetworks["Transitions"].keys():
+ steps = []
connections = transition.connectionPointIn.getConnections()
if len(connections) == 1:
instanceLocalId = connections[0].getRefLocalId()
instance = pou.body.getContentInstance(instanceLocalId)
if isinstance(instance, plcopen.step):
- step_name = instance.getName()
- if step_name not in self.Steps:
- self.GenerateSFCSteps(instance, pou)
+ self.GenerateSFCStep(instance, pou)
+ steps.append(instance.getName())
elif isinstance(instance, plcopen.selectionDivergence):
divergence_connections = instance.connectionPointIn.getConnections()
if len(divergence_connections) == 1:
stepLocalId = divergence_connections[0].getRefLocalId()
divergence_instance = pou.body.getContentInstance(stepLocalId)
if isinstance(divergence_instance, plcopen.step):
- step_name = divergence_instance.getName()
- if step_name not in self.Steps:
- self.GenerateSFCSteps(divergence_instance, pou)
- if step_name in self.Steps:
- transition_infos = {"targets" : []}
- transitionValues = transition.getConditionContent()
- transition_infos["condition"] = transitionValues["value"]
- if transitionValues["type"] == "inline":
- transition_infos["compute"] = ""
- else:
- transitionContent = pou.getTransition(transitionValues["value"])
- transitionType = transitionContent.getBodyType()
- transitionBody = transitionContent.getBody()
- if transitionType in ["ST", "IL"]:
- transition_infos["compute"] = "%s\n"%transitionContent.getText()
- elif conditionType == "FBD":
- for instance in conditionBody.getContentInstances():
- if isinstance(instance, plcopen.outVariable):
- var = instance.getExpression()
- connections = instance.connectionPointIn.getConnections()
- if connections and len(connections) == 1:
- expression = self.ComputeFBDExpression(actionBody, connections[0])
- transition_infos["compute"] = self.Program + ":= %s;\n"%(var, expression)
- self.Program = ""
- elif actionType == "LD":
- for instance in conditionbody.getContentInstances():
- if isinstance(instance, plcopen.coil):
- paths = self.GenerateLDPaths(instance, conditionBody)
- variable = self.ExtractModifier(instance, instance.getVariable())
- expression = self.ComputeLDExpression(paths, True)
- transition_infos["compute"] = self.Program + ":= %s;\n"%(variable, expression)
- self.Program = ""
- self.Steps[step_name]["transitions"].append(transition_infos)
- self.Transitions[transition] = transition_infos
-
- def GenerateSFCStepOrder(self, name, path):
- self.Order.append(name)
- for transition in self.Steps[name]["transitions"]:
- for target in transition["targets"]:
- if target not in self.Order or target not in path:
- if target in self.Order:
- self.Order.remove(target)
- self.GenerateSFCStepOrder(target, path + [name])
-
+ self.GenerateSFCStep(divergence_instance, pou)
+ steps.append(divergence_instance.getName())
+ transition_infos = {"from": [], "to" : []}
+ transitionValues = transition.getConditionContent()
+ if transitionValues["type"] == "inline":
+ transition_infos["content"] = "\n := %s;\n"%transitionValues["value"]
+ else:
+ transitionContent = pou.getTransition(transitionValues["value"])
+ transitionType = transitionContent.getBodyType()
+ transitionBody = transitionContent.getBody()
+ if transitionType == "IL":
+ transition_infos["content"] = ":\n%s\n"%ReIndentText(transitionBody.getText(), 4)
+ elif transitionType == "ST":
+ transition_infos["content"] = "\n%s\n"%ReIndentText(transitionBody.getText(), 4)
+ elif conditionType == "FBD":
+ for instance in transitionBody.getContentInstances():
+ if isinstance(instance, plcopen.outVariable):
+ connections = instance.connectionPointIn.getConnections()
+ if connections and len(connections) == 1:
+ expression = self.ComputeFBDExpression(actionBody, connections[0])
+ transition_infos["content"] = "\n := %s;\n"%(var, expression)
+ elif actionType == "LD":
+ for instance in transitionbody.getContentInstances():
+ if isinstance(instance, plcopen.coil):
+ paths = self.GenerateLDPaths(instance, conditionBody)
+ expression = self.ComputeLDExpression(paths, True)
+ transition_infos["content"] = "\n := %s;\n"%expression
+ for step_name in steps:
+ if step_name in self.SFCNetworks["Steps"].keys():
+ transition_infos["from"].append(step_name)
+ self.SFCNetworks["Steps"][step_name]["transitions"].append(transition)
+ self.SFCNetworks["Transitions"][transition] = transition_infos
+
+ def ComputeSFCStep(self, step_name):
+ if step_name in self.SFCNetworks["Steps"].keys():
+ step_infos = self.SFCNetworks["Steps"].pop(step_name)
+ if step_infos["initial"]:
+ self.Program += " INITIAL_STEP %s:\n"%step_name
+ else:
+ self.Program += " STEP %s:\n"%step_name
+ actions = []
+ for action_infos in step_infos["actions"]:
+ actions.append(action_infos["content"])
+ self.Program += " %(content)s(%(qualifier)s"%action_infos
+ if "duration" in action_infos:
+ self.Program += ", %(duration)s"%action_infos
+ if "indicator" in action_infos:
+ self.Program += ", %(indicator)s"%action_infos
+ self.Program += ");\n"
+ self.Program += " END_STEP\n\n"
+ for action in actions:
+ self.ComputeSFCAction(action)
+ for transition in step_infos["transitions"]:
+ self.ComputeSFCTransition(transition)
+
+ def ComputeSFCAction(self, action_name):
+ if action_name in self.SFCNetworks["Actions"].keys():
+ action_content = self.SFCNetworks["Actions"].pop(action_name)
+ self.Program += " ACTION %s:\n%s END_ACTION\n\n"%(action_name, action_content)
+
+ def ComputeSFCTransition(self, transition):
+ if transition in self.SFCNetworks["Transitions"].keys():
+ transition_infos = self.SFCNetworks["Transitions"].pop(transition)
+ self.Program += " TRANSITION FROM "
+ if len(transition_infos["from"]) > 1:
+ self.Program += "(%s)"%", ".join(transition_infos["from"])
+ else:
+ self.Program += "%s"%transition_infos["from"][0]
+ self.Program += " TO "
+ if len(transition_infos["to"]) > 1:
+ self.Program += "(%s)"%", ".join(transition_infos["to"])
+ else:
+ self.Program += "%s"%transition_infos["to"][0]
+ self.Program += transition_infos["content"]
+ self.Program += " END_TRANSITION\n\n"
+ for step_name in transition_infos["to"]:
+ self.ComputeSFCStep(step_name)
+
def ComputeLDExpression(self, paths, first = False):
if type(paths) == TupleType:
if None in paths:
@@ -368,36 +412,33 @@
return text
def AddTrigger(self, edge, text):
- if ("VAR", False, False) not in self.Interface:
- self.Interface[("VAR", False, False)] = {}
- if type not in self.Interface[("VAR", False, False)]:
- self.Interface[("VAR", False, False)][edge] = []
+ if self.Interface[-1][0] != "VAR" or self.Interface[-1][1] or self.Interface[-1][2]:
+ self.Interface.append(("VAR", False, False, []))
i = 1
name = "%s%d"%(edge, i)
- while name in self.Interface[("VAR", False, False)][edge]:
+ while self.IsAlreadyDefined(name):
i += 1
name = "%s%d"%(edge, i)
- self.Interface[("VAR", False, False)][edge].append(name)
+ self.Interface[-1][3].append((edge, name))
self.Program += " %s(CLK := %s);\n"%(name, text)
return "%s.Q"%name
def GenerateSTProgram(self):
program = ""
- if "returnType" in self.Interface:
- program += "%s %s : %s\n"%(self.Type, self.Name, self.Interface["returnType"])
+ if self.ReturnType:
+ program += "%s %s : %s\n"%(self.Type, self.Name, self.ReturnType)
else:
program += "%s %s\n"%(self.Type, self.Name)
- for values, variables in self.Interface.items():
- if values != "returnType":
- program += " %s"%values[0]
- if values[1]:
- program += " RETAIN"
- if values[2]:
- program += " CONSTANT"
- program += "\n"
- for vartype, list in variables.items():
- program += " %s : %s;\n"%(", ".join(list), vartype)
- program += " END_%s\n"%values[0]
+ for list_type, retain, constant, variables in self.Interface:
+ program += " %s"%list_type
+ if retain:
+ program += " RETAIN"
+ if constant:
+ program += " CONSTANT"
+ program += "\n"
+ for var_type, var_name in variables:
+ program += " %s : %s;\n"%(var_name, var_type)
+ program += " END_%s\n"%list_type
program += "\n"
program += self.Program
program += "END_%s\n\n"%self.Type