def loadHooks(self): target = self.target config = self.target.config lib = self.target.library platform = self.target.project.platform # Collect hooks in various locations for fileName in config.get("hooks", []): Log.notice("Parsing hooks from '%s'." % fileName) source = self.readSource(fileName) functions = Parser.parseSource(source).functions.values() if not functions: Log.warn("No hooks found.") for f in functions: Log.debug("%s %s(%s)" % (f.type, f.name, ", ".join(["%s %s" % (t.type, p) for p, t in f.parameters.items()]))) for function in functions: if not function.body: Log.warn("Hook function '%s' has no body." % function.name) continue if function.name.startswith("@"): lib.hooks[function.name] = function.body continue else: try: name, hookName = function.name.split(".", 1) if not name in lib.functions: target.fail("Function '%s' referred by hook function '%s' does not exist." % (name, function.name)) if not hookName.startswith("@") and not hookName in lib.functions[name].parameters: target.fail("Parameter '%s' referred by hook function '%s' does not exist." % (hookName, function.name)) lib.functions[name].hooks[hookName] = function.body except ValueError: target.fail("Hook function name '%s' is not valid." % function.name)
def generate(project, options, args): """Generate a target from a project. [target]""" if not args: fail("Generation target missing. Use one of %s" % ", ".join(project.targets.keys())) if not project.targets: fail("Project file name missing.") config = project.config for targetName in args: if not targetName in project.targets: fail("No such target. Use one of %s" % ", ".join(project.targets.keys())) # Generate the target target = project.targets[targetName] projectName = config.name.lower() + "-" + targetName targetPath = options.output and options.output or projectName Log.notice( heading("Generating '%s' from project '%s'" % (targetName, config.name))) target.generate(projectName, targetPath) Log.notice("Target '%s' created at '%s'." % (projectName, targetPath))
def prepareTarget(targetName): if targetName in project.targets: return if not targetName in Target.targets: fail("Bad target name '%s'." % targetName) return targetClass = Target.targets[targetName] for dep in targetClass.dependencies: if not dep in project.targets: prepareTarget(dep) Log.notice("Preparing target %d of %d: %s." % (len(project.targets) + 1, len(targetNames), targetName)) target = targetClass(project) target.prepare() target.validate() project.targets[targetName] = target
def show(project, options, args): """Show information about a project target. [target]""" commands = [ "all", "config", "functions", "constants", "typedefs" ] if not args: fail("Show what? Use one of %s" % ", ".join(commands)) command, args = args[0], args[1:] if not command in commands: fail("Show what? Use one of %s" % ", ".join(commands)) if not project.targets: fail("Project file name missing.") config = project.config lib = project.library if "code" in project.targets: lib = project.targets["code"].library if args: config = project.targets[args[0]].config lib = project.targets[args[0]].library if command == "config" or command == "all": Log.notice("Configuration:") print config.save() if command == "functions" or command == "all": Log.notice("%d functions:" % len(lib.functions)) for name, function in lib.functions.items(): params = [] for paramName, param in sorted(function.parameters.items()): params.append("%s %s" % (param.type, param.name)) params = ", ".join(params) print "%s %s(%s)" % (function.type, function.name, params) if command == "constants" or command == "all": Log.notice("%d constants:" % len(lib.constants)) for constName, constValue in sorted(lib.constants.items()): print "%-40s %-8s (0x%x)" % (constName, constValue, constValue) if command == "typedefs" or command == "all": Log.notice("%d typedefs:" % len(lib.typeDefs)) for tdName, tdValue in sorted(lib.typeDefs.items()): print "%-40s %s" % (tdName, tdValue)
def loadHooks(self): target = self.target config = self.target.config lib = self.target.library platform = self.target.project.platform # Collect hooks in various locations for fileName in config.get("hooks", []): Log.notice("Parsing hooks from '%s'." % fileName) source = self.readSource(fileName) functions = Parser.parseSource(source).functions.values() if not functions: Log.warn("No hooks found.") for f in functions: Log.debug("%s %s(%s)" % (f.type, f.name, ", ".join( ["%s %s" % (t.type, p) for p, t in f.parameters.items()]))) for function in functions: if not function.body: Log.warn("Hook function '%s' has no body." % function.name) continue if function.name.startswith("@"): lib.hooks[function.name] = function.body continue else: try: name, hookName = function.name.split(".", 1) if not name in lib.functions: target.fail( "Function '%s' referred by hook function '%s' does not exist." % (name, function.name)) if not hookName.startswith( "@" ) and not hookName in lib.functions[name].parameters: target.fail( "Parameter '%s' referred by hook function '%s' does not exist." % (hookName, function.name)) lib.functions[name].hooks[hookName] = function.body except ValueError: target.fail("Hook function name '%s' is not valid." % function.name)
def generate(project, options, args): """Generate a target from a project. [target]""" if not args: fail("Generation target missing. Use one of %s" % ", ".join(project.targets.keys())) if not project.targets: fail("Project file name missing.") config = project.config for targetName in args: if not targetName in project.targets: fail("No such target. Use one of %s" % ", ".join(project.targets.keys())) # Generate the target target = project.targets[targetName] projectName = config.name.lower() + "-" + targetName targetPath = options.output and options.output or projectName Log.notice(heading("Generating '%s' from project '%s'" % (targetName, config.name))) target.generate(projectName, targetPath) Log.notice("Target '%s' created at '%s'." % (projectName, targetPath))
def show(project, options, args): """Show information about a project target. [target]""" commands = ["all", "config", "functions", "constants", "typedefs"] if not args: fail("Show what? Use one of %s" % ", ".join(commands)) command, args = args[0], args[1:] if not command in commands: fail("Show what? Use one of %s" % ", ".join(commands)) if not project.targets: fail("Project file name missing.") config = project.config lib = project.library if "code" in project.targets: lib = project.targets["code"].library if args: config = project.targets[args[0]].config lib = project.targets[args[0]].library if command == "config" or command == "all": Log.notice("Configuration:") print config.save() if command == "functions" or command == "all": Log.notice("%d functions:" % len(lib.functions)) for name, function in lib.functions.items(): params = [] for paramName, param in sorted(function.parameters.items()): params.append("%s %s" % (param.type, param.name)) params = ", ".join(params) print "%s %s(%s)" % (function.type, function.name, params) if command == "constants" or command == "all": Log.notice("%d constants:" % len(lib.constants)) for constName, constValue in sorted(lib.constants.items()): print "%-40s %-8s (0x%x)" % (constName, constValue, constValue) if command == "typedefs" or command == "all": Log.notice("%d typedefs:" % len(lib.typeDefs)) for tdName, tdValue in sorted(lib.typeDefs.items()): print "%-40s %s" % (tdName, tdValue)
def generateReport(project, trace, traceFileName, path, format): if traceFileName: title = "OpenGL ES performance report for %s" % os.path.basename(traceFileName) else: title = "OpenGL ES performance report" Log.notice(title) g = ReportGenerator.ReportGenerator(project, trace, title, path, format) # Calculate GLES specific stats GlesTraceOperations.calculateStatistics(project, trace) # Calculate general stats g.calculateStatistics() # Add some general information first section = g.report.create(Report.Section, "General statistics") table = g.createGeneralStatisticsTable() auxiliaryTable = g.createAuxiliaryStatisticsTable() histogramTable = g.createCallHistogramTable() if traceFileName: table.addRow("File name", traceFileName) section.add(table) section.add(auxiliaryTable) section.add(histogramTable) # Add a section about the used render targets addRenderTargetSection(g) # Add an overall timeline of all events g.report.add(g.createEventPlot("Event distribution", trace.events)) # Add a graph about the event type distribution g.report.add(g.createEventFrequencyPlot("Operation distribution", trace.events)) # Add overview section overviewSection = g.report.create(Report.Section, "Overview") # Frame thumbnails thumbnailSection = overviewSection.create(Report.Section, "Selected frames") thumbnails = g.createEventThumbnails([f.swapEvent for f in g.interestingFrames]) for frame, thumbnail in zip(g.interestingFrames, thumbnails): thumbnailSection.create(Report.Link, "#frame%d" % (frame.number + 1), thumbnail) # Textures textureLoaders = GlesTraceOperations.getTextureLoaders(project, trace) if textureLoaders: textureSection = overviewSection.create(Report.Section, "Loaded textures") task = Task.startTask("load-textures", "Loading textures", len(textureLoaders)) for event, func in textureLoaders: task.step() image = func().convert("RGBA") fn = os.path.join(path, "texture%03d.png" % event.seq) image.save(fn) textureSection.create(Report.Image, fn) # FPS data = [1.0 / f.duration for f in g.frames] plot = g.createPlot("Frames per second", range(len(g.frames)), data) overviewSection.add(plot) # Render calls data = [len(f.events) for f in g.frames] plot = g.createPlot("Number of API calls per frame", range(len(g.frames)), data) overviewSection.add(plot) # Overdraw data = [f.swapEvent.sensorData.get("draw_ratio", 0) for f in g.frames] plot = g.createPlot("Draw ratio", range(len(g.frames)), data) overviewSection.add(plot) # Fragment count data = [f.swapEvent.sensorData.get("rasterizer_pixels", 0) for f in g.frames] plot = g.createPlot("Rasterized fragments per frame", range(len(g.frames)), data) overviewSection.add(plot) # Texture reads data = [f.swapEvent.sensorData.get("rasterizer_texel_fetches", 0) for f in g.frames] plot = g.createPlot("Texel fetches per frame", range(len(g.frames)), data) overviewSection.add(plot) # Texture uploads data = [f.swapEvent.sensorData.get("texel_uploads", 0) for f in g.frames] plot = g.createPlot("Texel uploads per frame", range(len(g.frames)), data) overviewSection.add(plot) # Now go over each interesting frame task = Task.startTask("frame-report", "Generating report", len(g.interestingFrames)) frameDetailSection = g.report.create(Report.Section, "Detailed frame statistics") for frame in g.interestingFrames: task.step() frameSection = g.createFrameSection(frame) # Add some custom plots plot = g.createSensorPlot(frame, "rasterizer_pixels") frameSection.add(plot) plot = g.createSensorPlot(frame, "rasterizer_texel_fetches") frameSection.add(plot) plot = g.createSensorPlot(frame, "texel_uploads") frameSection.add(plot) # Now go over the individual render calls + the swap event for event in frame.renderEvents + [frame.swapEvent]: eventSection = g.createEventSection(event) frameSection.add(eventSection) frameDetailSection.add(frameSection) # Add the checklist result g.report.add(g.createChecklistSection("Performance Checklist", GlesChecklist.checklistItems)) # Finalize the report task.finish() g.generate()
def reportInfo(self, msg): for line in str(msg).rstrip().split("\n"): Log.notice(line)
def create(project, options, args): """Create a new Tracy project. [config file] [targets]""" if not args or len(args) < 1: fail("Configuration file name missing.") configName = args[0] targetNames = args[1:] # Load the configuration file project.config.loadFile(configName) for path in project.config.paths: Resource.paths.append(path) config = project.config try: # Create the platform and read it's configuration if it exists. platform = Platform.platforms[options.platform](config) except KeyError: fail("No such platform. Use one of %s" % ", ".join(Platform.platforms.keys())) projectName = config.name.lower() Log.notice(heading("Creating Tracy project '%s' for %s" % (projectName, platform.name))) # Initialize the project lib = Library.Library(name = config.name) project.library = lib project.platform = platform def prepareTarget(targetName): if targetName in project.targets: return if not targetName in Target.targets: fail("Bad target name '%s'." % targetName) return targetClass = Target.targets[targetName] for dep in targetClass.dependencies: if not dep in project.targets: prepareTarget(dep) Log.notice("Preparing target %d of %d: %s." % (len(project.targets) + 1, len(targetNames), targetName)) target = targetClass(project) target.prepare() target.validate() project.targets[targetName] = target # Prepare the targets if not targetNames: targetNames = Target.targets.keys() for targetName in targetNames: prepareTarget(targetName) # Save the project projectPath = options.output and options.output or ("%s.tcy" % projectName) project.save(projectPath) Log.notice("Tracy project '%s' saved to '%s'." % (projectName, projectPath))
def sync(options, target, args): """Synchronize the makefile""" f = open("Makefile", "w") Generator.generateMakefile(f) f.close() Log.notice("Makefile synchronized")
def prepare(self): # Shorthand for various objects config = self.config lib = self.library # Parse the sources for fileName in config.get("apiheaders", []): Log.notice("Parsing functions from '%s'." % fileName) source = self.parserTool.readSource(fileName) newLib = Parser.parseSource(source) for f in newLib.functions.values(): f.headerName = fileName for f in newLib.functions.values(): Log.debug("%s %s(%s)" % (f.type, f.name, ", ".join(["%s %s" % (t.type, p) for p, t in f.parameters.items()]))) if not newLib.functions: Log.warn("No new functions found.") else: Log.notice("%d functions found." % len(newLib.functions)) lib.merge(newLib) # Load the hooks self.parserTool.loadHooks() def parseBool(s): return bool(int(s)) # Read the typemap for typeDecl, mapping in self.config.types.items(): attrs = self.config.types[typeDecl].attrs name, type = Parser.parseVariableDeclaration(typeDecl + " dummy") assert name == "dummy" # If this is a class mapping, create the class if it doesn't already exist if mapping == "object": if not mapping in self.library.classes: cls = Library.Class(type) if "namespace" in attrs: cls.namespacePath = attrs["namespace"].split(".") self.library.classes[type] = cls # Patch the default decoration hint into all matching types if "decorationhint" in attrs: for function in self.library.functions.values(): for t in [p.type for p in function.parameters.values()] + [function.type]: if t == type: t.decorationHint = attrs["decorationhint"] self.library.typeMap[type] = str(mapping) # Patch in some function-specific attributes for function in config.functions.keys(): if not function in lib.functions: self.fail("Attributes specified for non-existent function '%s'." % function) attrs = config.functions[function].attrs if "terminator" in attrs: lib.functions[function].isTerminator = parseBool(attrs["terminator"]) if "generate" in attrs: lib.functions[function].generate = parseBool(attrs["generate"]) if "runtimestate" in attrs: lib.functions[function].runtimeStateTracking = parseBool(attrs["runtimestate"]) if "framemarker" in attrs: lib.functions[function].isFrameMarker = parseBool(attrs["framemarker"]) if "staticlinkage" in attrs: lib.functions[function].staticLinkage = parseBool(attrs["staticlinkage"]) if "rendercall" in attrs: lib.functions[function].isRenderCall = parseBool(attrs["rendercall"]) if "passthrough" in attrs: lib.functions[function].passthrough = parseBool(attrs["passthrough"]) if not isinstance(config.functions[function], Config.Group): self.fail("Syntax error: State map definition for function '%s' is missing braces." % function) # Argument to state mapping reservedNames = ["@return", "@modify", "@set", "@get", "@copy"] funcAttrs = attrs for arg, parameter in config.functions[function].items(): # Check that this is a valid parameter if not arg in reservedNames and not arg in lib.functions[function].parameters: self.fail("State mapping for nonexistent parameter '%s' of function '%s' specified." % (arg, function)) if arg in ["@copy"] and parseBool(funcAttrs.get("runtimestate", "0")): Log.warn("Function %s state relation %s not implemented for runtime state tracking." % (function, arg)) # Read the parameter-specific attributes attrs = config.functions[function][arg].attrs if "decoration" in attrs: lib.functions[function].parameters[arg].decoration = attrs["decoration"] if "decorationhint" in attrs: lib.functions[function].parameters[arg].decorationHint = attrs["decorationhint"] if "out" in attrs: lib.functions[function].parameters[arg].isOut = parseBool(attrs["out"]) if "object_class" in attrs: # Create a function-local type so that this parameter type is an object only for this function if arg == "@return": type = lib.functions[function].type else: type = lib.functions[function].parameters[arg].type # Override the type's name so that it will refer to the new object class # while still using the original C type under the hood newType = copy.deepcopy(type) newType.isObject = True newType.name = attrs["object_class"] if arg == "@return": lib.functions[function].type = newType else: lib.functions[function].parameters[arg].type = newType # Check that this class exists classType = Library.Type(attrs["object_class"]) if not classType in self.library.classes: self.fail("Undefined object class '%s'." % classType) # Do we have a meta type? if "metatype" in config.functions[function][arg]: metaGroup = config.functions[function][arg].metatype try: metaType = Library.MetaType(metaGroup.attrs["class"]) except KeyError: self.fail("Meta type for parameter '%s' does not define class." % arg) # Is this an array parameter? if metaType.name == "array": metaType.values["size"] = Library.MetaValue("size", metaGroup.attrs.get("size", 1)) if "type" in metaGroup.attrs: metaType.values["type"] = Library.MetaValue("type", metaGroup.attrs["type"]) if metaGroup.attrs["type"] == "object": if not "object_class" in metaGroup.attrs: self.fail("Required metatype attribute object_class missing") metaType.values["object_class"] = Library.MetaValue("object_class", metaGroup.attrs["object_class"]) # How about an image parameter? elif metaType.name == "image": metaType.values["stride"] = Library.MetaValue("stride", metaGroup.attrs.get("stride", "width")) metaType.values["height"] = Library.MetaValue("height", metaGroup.attrs.get("height", "height")) metaType.values["components"] = Library.MetaValue("components", metaGroup.attrs.get("components", "1")) metaType.values["type"] = Library.MetaValue("type", metaGroup.attrs.get("type", "byte")) else: self.fail("Unknown meta type class '%s'." % metaclass) Log.debug("Meta type: %s.%s: %s" % (function, arg, metaType.name)) # Get the conditions for different meta values if isinstance(metaGroup, Config.List): for item in metaGroup: predicate = item.attrs["condition"] predicateValue = item.attrs["value"] result = item.attrs["result"] metaType.values[item].addPredicate(predicate, predicateValue, result) Log.debug("Meta type condition: If %s is %s, then %s = %s" % (predicate, predicateValue, item, result)) elif isinstance(metaGroup, Config.Group): Log.error("Meta type variations for parameter '%s' represented in a group instead of a list." % arg) # Record the meta type lib.functions[function].parameters[arg].metaType = metaType # Is this a short-hand state mapping? try: path = parameter.split(".") except AttributeError: # Try the expanded form of a nested attribute set try: path = (config.functions[function][arg].state).split(".") except AttributeError: path = [] # Check that we even have a state structure if path and not "state" in config: Log.warn("State structure not defined.") continue # Parse special state mapping relations relation = None checkPaths = [] if arg == "@copy": relation = Library.StateRelationCopy(attrs["src"].split("."), attrs["dest"].split(".")) checkPaths = [relation.sourcePath, relation.destPath] elif arg == "@get": relation = Library.StateRelationGet(path) checkPaths = [relation.path] elif arg == "@set": relation = Library.StateRelationSet(path) checkPaths = [relation.path] elif arg == "@modify": relation = Library.StateRelationModify(path) checkPaths = [relation.path] # Empty mapping? elif not "".join(path): continue if relation: for path in checkPaths: if traverseStatePath(config, path) is None: self.fail("Relation state path '%s' for function '%s' does not exist." % (".".join(path), function)) Log.debug("State relation: %s %s" % (function, relation)) lib.functions[function].stateRelations.append(relation) continue Log.debug("State mapping: %s.%s -> %s" % (function, arg, ".".join(path))) # Determine the parameter type type = None if arg == "@return": type = lib.functions[function].type else: type = lib.functions[function].parameters[arg].type # If this is a runtime mapping, check that the parameter is of a supported type if lib.functions[function].runtimeStateTracking and type and \ lib.getNativeType(type) in ["float", "double"]: self.fail("Values of type '%s' can not be saved to the runtime state tree" % type) continue node = traverseStatePath(config, path) if node is None: self.fail("State path '%s' for function '%s' does not exist." % (".".join(path), function)) # Save the mapping if arg == "@return": lib.functions[function].retStateRelation = Library.StateRelationSet(path) else: lib.functions[function].parameters[arg].stateRelation = Library.StateRelationSet(path)
def prepare(self): # Shorthand for various objects config = self.config lib = self.library # Parse the sources for fileName in config.get("apiheaders", []): Log.notice("Parsing functions from '%s'." % fileName) source = self.parserTool.readSource(fileName) newLib = Parser.parseSource(source) for f in newLib.functions.values(): f.headerName = fileName for f in newLib.functions.values(): Log.debug("%s %s(%s)" % (f.type, f.name, ", ".join( ["%s %s" % (t.type, p) for p, t in f.parameters.items()]))) if not newLib.functions: Log.warn("No new functions found.") else: Log.notice("%d functions found." % len(newLib.functions)) lib.merge(newLib) # Load the hooks self.parserTool.loadHooks() def parseBool(s): return bool(int(s)) # Read the typemap for typeDecl, mapping in self.config.types.items(): attrs = self.config.types[typeDecl].attrs name, type = Parser.parseVariableDeclaration(typeDecl + " dummy") assert name == "dummy" # If this is a class mapping, create the class if it doesn't already exist if mapping == "object": if not mapping in self.library.classes: cls = Library.Class(type) if "namespace" in attrs: cls.namespacePath = attrs["namespace"].split(".") self.library.classes[type] = cls # Patch the default decoration hint into all matching types if "decorationhint" in attrs: for function in self.library.functions.values(): for t in [p.type for p in function.parameters.values() ] + [function.type]: if t == type: t.decorationHint = attrs["decorationhint"] self.library.typeMap[type] = str(mapping) # Patch in some function-specific attributes for function in config.functions.keys(): if not function in lib.functions: self.fail( "Attributes specified for non-existent function '%s'." % function) attrs = config.functions[function].attrs if "terminator" in attrs: lib.functions[function].isTerminator = parseBool( attrs["terminator"]) if "generate" in attrs: lib.functions[function].generate = parseBool(attrs["generate"]) if "runtimestate" in attrs: lib.functions[function].runtimeStateTracking = parseBool( attrs["runtimestate"]) if "framemarker" in attrs: lib.functions[function].isFrameMarker = parseBool( attrs["framemarker"]) if "staticlinkage" in attrs: lib.functions[function].staticLinkage = parseBool( attrs["staticlinkage"]) if "rendercall" in attrs: lib.functions[function].isRenderCall = parseBool( attrs["rendercall"]) if "passthrough" in attrs: lib.functions[function].passthrough = parseBool( attrs["passthrough"]) if not isinstance(config.functions[function], Config.Group): self.fail( "Syntax error: State map definition for function '%s' is missing braces." % function) # Argument to state mapping reservedNames = ["@return", "@modify", "@set", "@get", "@copy"] funcAttrs = attrs for arg, parameter in config.functions[function].items(): # Check that this is a valid parameter if not arg in reservedNames and not arg in lib.functions[ function].parameters: self.fail( "State mapping for nonexistent parameter '%s' of function '%s' specified." % (arg, function)) if arg in ["@copy"] and parseBool( funcAttrs.get("runtimestate", "0")): Log.warn( "Function %s state relation %s not implemented for runtime state tracking." % (function, arg)) # Read the parameter-specific attributes attrs = config.functions[function][arg].attrs if "decoration" in attrs: lib.functions[function].parameters[arg].decoration = attrs[ "decoration"] if "decorationhint" in attrs: lib.functions[function].parameters[ arg].decorationHint = attrs["decorationhint"] if "out" in attrs: lib.functions[function].parameters[arg].isOut = parseBool( attrs["out"]) if "object_class" in attrs: # Create a function-local type so that this parameter type is an object only for this function if arg == "@return": type = lib.functions[function].type else: type = lib.functions[function].parameters[arg].type # Override the type's name so that it will refer to the new object class # while still using the original C type under the hood newType = copy.deepcopy(type) newType.isObject = True newType.name = attrs["object_class"] if arg == "@return": lib.functions[function].type = newType else: lib.functions[function].parameters[arg].type = newType # Check that this class exists classType = Library.Type(attrs["object_class"]) if not classType in self.library.classes: self.fail("Undefined object class '%s'." % classType) # Do we have a meta type? if "metatype" in config.functions[function][arg]: metaGroup = config.functions[function][arg].metatype try: metaType = Library.MetaType(metaGroup.attrs["class"]) except KeyError: self.fail( "Meta type for parameter '%s' does not define class." % arg) # Is this an array parameter? if metaType.name == "array": metaType.values["size"] = Library.MetaValue( "size", metaGroup.attrs.get("size", 1)) if "type" in metaGroup.attrs: metaType.values["type"] = Library.MetaValue( "type", metaGroup.attrs["type"]) if metaGroup.attrs["type"] == "object": if not "object_class" in metaGroup.attrs: self.fail( "Required metatype attribute object_class missing" ) metaType.values[ "object_class"] = Library.MetaValue( "object_class", metaGroup.attrs["object_class"]) # How about an image parameter? elif metaType.name == "image": metaType.values["stride"] = Library.MetaValue( "stride", metaGroup.attrs.get("stride", "width")) metaType.values["height"] = Library.MetaValue( "height", metaGroup.attrs.get("height", "height")) metaType.values["components"] = Library.MetaValue( "components", metaGroup.attrs.get("components", "1")) metaType.values["type"] = Library.MetaValue( "type", metaGroup.attrs.get("type", "byte")) else: self.fail("Unknown meta type class '%s'." % metaclass) Log.debug("Meta type: %s.%s: %s" % (function, arg, metaType.name)) # Get the conditions for different meta values if isinstance(metaGroup, Config.List): for item in metaGroup: predicate = item.attrs["condition"] predicateValue = item.attrs["value"] result = item.attrs["result"] metaType.values[item].addPredicate( predicate, predicateValue, result) Log.debug( "Meta type condition: If %s is %s, then %s = %s" % (predicate, predicateValue, item, result)) elif isinstance(metaGroup, Config.Group): Log.error( "Meta type variations for parameter '%s' represented in a group instead of a list." % arg) # Record the meta type lib.functions[function].parameters[arg].metaType = metaType # Is this a short-hand state mapping? try: path = parameter.split(".") except AttributeError: # Try the expanded form of a nested attribute set try: path = ( config.functions[function][arg].state).split(".") except AttributeError: path = [] # Check that we even have a state structure if path and not "state" in config: Log.warn("State structure not defined.") continue # Parse special state mapping relations relation = None checkPaths = [] if arg == "@copy": relation = Library.StateRelationCopy( attrs["src"].split("."), attrs["dest"].split(".")) checkPaths = [relation.sourcePath, relation.destPath] elif arg == "@get": relation = Library.StateRelationGet(path) checkPaths = [relation.path] elif arg == "@set": relation = Library.StateRelationSet(path) checkPaths = [relation.path] elif arg == "@modify": relation = Library.StateRelationModify(path) checkPaths = [relation.path] # Empty mapping? elif not "".join(path): continue if relation: for path in checkPaths: if traverseStatePath(config, path) is None: self.fail( "Relation state path '%s' for function '%s' does not exist." % (".".join(path), function)) Log.debug("State relation: %s %s" % (function, relation)) lib.functions[function].stateRelations.append(relation) continue Log.debug("State mapping: %s.%s -> %s" % (function, arg, ".".join(path))) # Determine the parameter type type = None if arg == "@return": type = lib.functions[function].type else: type = lib.functions[function].parameters[arg].type # If this is a runtime mapping, check that the parameter is of a supported type if lib.functions[function].runtimeStateTracking and type and \ lib.getNativeType(type) in ["float", "double"]: self.fail( "Values of type '%s' can not be saved to the runtime state tree" % type) continue node = traverseStatePath(config, path) if node is None: self.fail( "State path '%s' for function '%s' does not exist." % (".".join(path), function)) # Save the mapping if arg == "@return": lib.functions[ function].retStateRelation = Library.StateRelationSet( path) else: lib.functions[function].parameters[ arg].stateRelation = Library.StateRelationSet(path)
def create(project, options, args): """Create a new Tracy project. [config file] [targets]""" if not args or len(args) < 1: fail("Configuration file name missing.") configName = args[0] targetNames = args[1:] # Load the configuration file project.config.loadFile(configName) for path in project.config.paths: Resource.paths.append(path) config = project.config try: # Create the platform and read it's configuration if it exists. platform = Platform.platforms[options.platform](config) except KeyError: fail("No such platform. Use one of %s" % ", ".join(Platform.platforms.keys())) projectName = config.name.lower() Log.notice( heading("Creating Tracy project '%s' for %s" % (projectName, platform.name))) # Initialize the project lib = Library.Library(name=config.name) project.library = lib project.platform = platform def prepareTarget(targetName): if targetName in project.targets: return if not targetName in Target.targets: fail("Bad target name '%s'." % targetName) return targetClass = Target.targets[targetName] for dep in targetClass.dependencies: if not dep in project.targets: prepareTarget(dep) Log.notice("Preparing target %d of %d: %s." % (len(project.targets) + 1, len(targetNames), targetName)) target = targetClass(project) target.prepare() target.validate() project.targets[targetName] = target # Prepare the targets if not targetNames: targetNames = Target.targets.keys() for targetName in targetNames: prepareTarget(targetName) # Save the project projectPath = options.output and options.output or ("%s.tcy" % projectName) project.save(projectPath) Log.notice("Tracy project '%s' saved to '%s'." % (projectName, projectPath))