# HG changeset patch # User Laurent Bessard # Date 1353016853 -3600 # Node ID 235a9ec83b955459ad15304c3725a277c57d5549 # Parent 3c6ce0a5ab2cef6630875e347474c7f8809d29ff Adding support for defining specific global variables for ConfTreeNodes Fix bug when defining function block instances as global variables diff -r 3c6ce0a5ab2c -r 235a9ec83b95 ConfigTreeNode.py --- a/ConfigTreeNode.py Thu Nov 15 22:57:55 2012 +0100 +++ b/ConfigTreeNode.py Thu Nov 15 23:00:53 2012 +0100 @@ -195,6 +195,18 @@ shutil.copytree(src_CTNPath, self.CTNPath) return True + def CTNGlobalInstances(self): + """ + @return: [(instance_name, instance_type),...] + """ + return [] + + def _GlobalInstances(self): + instances = self.CTNGlobalInstances() + for CTNChild in self.IECSortedChildren(): + instances.extend(CTNChild._GlobalInstances()) + return instances + def CTNGenerate_C(self, buildpath, locations): """ Generate C code diff -r 3c6ce0a5ab2c -r 235a9ec83b95 PLCControler.py --- a/PLCControler.py Thu Nov 15 22:57:55 2012 +0100 +++ b/PLCControler.py Thu Nov 15 23:00:53 2012 +0100 @@ -1476,6 +1476,32 @@ def GetVariableLocationTree(self): return [] + def GetConfNodeGlobalInstances(self): + return [] + + def GetConfigurationExtraVariables(self): + global_vars = [] + for var_name, var_type in self.GetConfNodeGlobalInstances(): + tempvar = plcopen.varListPlain_variable() + tempvar.setname(var_name) + + tempvartype = plcopen.dataType() + if var_type in self.GetBaseTypes(): + if var_type == "STRING": + var_type.setcontent({"name" : "string", "value" : plcopen.elementaryTypes_string()}) + elif var_type == "WSTRING": + var_type.setcontent({"name" : "wstring", "value" : plcopen.elementaryTypes_wstring()}) + else: + var_type.setcontent({"name" : var_type, "value" : None}) + else: + tempderivedtype = plcopen.derivedTypes_derived() + tempderivedtype.setname(var_type) + tempvartype.setcontent({"name" : "derived", "value" : tempderivedtype}) + tempvar.settype(tempvartype) + + global_vars.append(tempvar) + return global_vars + # Function that returns the block definition associated to the block type given def GetBlockType(self, type, inputs = None, debug = False): result_blocktype = None @@ -1723,6 +1749,8 @@ if words[0] == "D": infos = {} datatype = project.getdataType(words[1]) + if datatype is None: + return None basetype_content = datatype.baseType.getcontent() if basetype_content["value"] is None or basetype_content["name"] in ["string", "wstring"]: infos["type"] = "Directly" diff -r 3c6ce0a5ab2c -r 235a9ec83b95 PLCGenerator.py --- a/PLCGenerator.py Thu Nov 15 22:57:55 2012 +0100 +++ b/PLCGenerator.py Thu Nov 15 23:00:53 2012 +0100 @@ -268,8 +268,17 @@ (configuration.getname(), (tagname, "name")), ("\n", ())] var_number = 0 + + varlists = [(varlist, varlist.getvariable()[:]) for varlist in configuration.getglobalVars()] + + extra_variables = self.Controler.GetConfigurationExtraVariables() + if len(extra_variables) > 0: + if len(varlists) == 0: + varlists = [(plcopen.interface_globalVars(), [])] + varlists[-1][1].extend(extra_variables) + # Generate any global variable in configuration - for varlist in configuration.getglobalVars(): + for varlist, varlist_variables in varlists: variable_type = errorVarTypes.get("VAR_GLOBAL", "var_local") # Generate variable block with modifier config += [(" VAR_GLOBAL", ())] @@ -281,7 +290,7 @@ config += [(" NON_RETAIN", (tagname, variable_type, (var_number, var_number + len(varlist.getvariable())), "non_retain"))] config += [("\n", ())] # Generate any variable of this block - for var in varlist.getvariable(): + for var in varlist_variables: vartype_content = var.gettype().getcontent() if vartype_content["name"] == "derived": var_type = vartype_content["value"].getname() @@ -512,15 +521,24 @@ current_type = var_type break while current_type is not None and len(parts) > 0: - tagname = self.ParentGenerator.Controler.ComputeDataTypeName(current_type) - infos = self.ParentGenerator.Controler.GetDataTypeInfos(tagname) - name = parts.pop(0) - current_type = None - if infos is not None and infos["type"] == "Structure": - for element in infos["elements"]: - if element["Name"] == name: - current_type = element["Type"] + blocktype = self.ParentGenerator.Controler.GetBlockType(current_type) + if blocktype is not None: + name = parts.pop(0) + current_type = None + for var_name, var_type, var_modifier in blocktype["inputs"] + blocktype["outputs"]: + if var_name == name: + current_type = var_type break + else: + tagname = self.ParentGenerator.Controler.ComputeDataTypeName(current_type) + infos = self.ParentGenerator.Controler.GetDataTypeInfos(tagname) + if infos is not None and infos["type"] == "Structure": + name = parts.pop(0) + current_type = None + for element in infos["elements"]: + if element["Name"] == name: + current_type = element["Type"] + break return current_type # Return connectors linked by a connection to the given connector diff -r 3c6ce0a5ab2c -r 235a9ec83b95 ProjectController.py --- a/ProjectController.py Thu Nov 15 22:57:55 2012 +0100 +++ b/ProjectController.py Thu Nov 15 23:00:53 2012 +0100 @@ -503,7 +503,10 @@ # finally store into located variable list locations.append(resdict) return locations - + + def GetConfNodeGlobalInstances(self): + return self._GlobalInstances() + def _Generate_SoftPLC(self): """ Generate SoftPLC ST/IL/SFC code out of PLCOpenEditor controller, and compile it with IEC2C @@ -697,15 +700,23 @@ self._ProgramList.append(attrs) # second section contains all variables + config_FBs = {} for line in ListGroup[1]: # Split and Maps each field to dictionnary entries attrs = dict(zip(VariablesListAttributeName,line.strip().split(';'))) # Truncate "C_path" to remove conf an ressources names parts = attrs["C_path"].split(".",2) if len(parts) > 2: - attrs["C_path"] = '__'.join(parts[1:]) + config_FB = config_FBs.get(tuple(parts[:2])) + if config_FB: + parts = [config_FB] + parts[2:] + attrs["C_path"] = '.'.join(parts) + else: + attrs["C_path"] = '__'.join(parts[1:]) else: attrs["C_path"] = '__'.join(parts) + if attrs["vartype"] == "FB": + config_FBs[tuple(parts)] = attrs["C_path"] # Push this dictionnary into result. self._VariablesList.append(attrs) # Fill in IEC<->C translation dicts @@ -741,18 +752,19 @@ "IN":"extern __IEC_%(type)s_p %(C_path)s;", "MEM":"extern __IEC_%(type)s_p %(C_path)s;", "OUT":"extern __IEC_%(type)s_p %(C_path)s;", - "VAR":"extern __IEC_%(type)s_t %(C_path)s;"}[v["vartype"]]%v - for v in self._VariablesList if v["vartype"] != "FB" and v["C_path"].find('.')<0]), + "VAR":"extern __IEC_%(type)s_t %(C_path)s;", + "FB":"extern %(type)s %(C_path)s;"}[v["vartype"]]%v + for v in self._VariablesList if v["C_path"].find('.')<0]), "for_each_variable_do_code":"\n".join([ - {"EXT":" (*fp)((void*)&%(C_path)s,%(type)s_P_ENUM);\n", - "IN":" (*fp)((void*)&%(C_path)s,%(type)s_P_ENUM);\n", - "MEM":" (*fp)((void*)&%(C_path)s,%(type)s_O_ENUM);\n", - "OUT":" (*fp)((void*)&%(C_path)s,%(type)s_O_ENUM);\n", - "VAR":" (*fp)((void*)&%(C_path)s,%(type)s_ENUM);\n"}[v["vartype"]]%v + {"EXT":" (*fp)((void*)&(%(C_path)s),%(type)s_P_ENUM);\n", + "IN":" (*fp)((void*)&(%(C_path)s),%(type)s_P_ENUM);\n", + "MEM":" (*fp)((void*)&(%(C_path)s),%(type)s_O_ENUM);\n", + "OUT":" (*fp)((void*)&(%(C_path)s),%(type)s_O_ENUM);\n", + "VAR":" (*fp)((void*)&(%(C_path)s),%(type)s_ENUM);\n"}[v["vartype"]]%v for v in self._VariablesList if v["vartype"] != "FB" and v["type"] in DebugTypesSize ]), "find_variable_case_code":"\n".join([ " case %(num)s:\n"%v+ - " *varp = (void*)&%(C_path)s;\n"%v+ + " *varp = (void*)&(%(C_path)s);\n"%v+ {"EXT":" return %(type)s_P_ENUM;\n", "IN":" return %(type)s_P_ENUM;\n", "MEM":" return %(type)s_O_ENUM;\n",