def to_file(self, dot_file_name): "Writes QOM tree to Graphviz file." graph = Digraph( name="QOM", graph_attr=dict(rankdir="LR"), node_attr=dict(shape="polygon", fontname="Momospace"), edge_attr=dict(style="filled"), ) for t in sort_topologically(v for v in self.tree.name2type.values() if v.parent is None): n = gv_node(t.name) label = t.name + "\\n0x%x" % t.impl.address if t.instance_casts: label += "\\n*" for cast in t.instance_casts: label += "\\n" + s(cast.name) graph.node(n, label=label) if t.parent: graph.edge(gv_node(t.parent), n) with open(dot_file_name, "w") as f: f.write(graph.source)
def fill_source(self): glob_mem = get_vp("explicit global memory registration") all_nodes = sort_topologically(self.cpus + self.devices + self.buses + self.irqs + self.mems + self.irq_hubs) decl_code = "" def_code = "" self.reset_generator() skip_nl = False for idx, node in enumerate(all_nodes): if not skip_nl: if idx > 0: def_code += "\n" else: skip_nl = False if isinstance(node, DeviceNode): self.use_type_name("qdev_init_nofail") self.use_type_name("BUS") if Type.exists(node.qom_type): self.use_type_name(node.qom_type) dev_name = self.node_map[node] props_code = "" for p in node.properties: self.use_type_name("OBJECT") self.use_type_name(p.prop_type.set_f) if Type.exists(p.prop_name): self.use_type_name(p.prop_name) if isinstance(p.prop_val, str) and Type.exists(p.prop_val): self.use_type_name(p.prop_val) props_code += """ {set_func}(@aOBJECT({dev_name}),@s{value},@s{prop_name},@sNULL);\ """.format(set_func=p.prop_type.set_f, dev_name=dev_name, prop_name=p.prop_name if Type.exists(p.prop_name) else "\"%s\"" % p.prop_name, value=self.gen_prop_val(p)) if isinstance(node, PCIExpressDeviceNode): self.use_type_name("PCIDevice") self.use_type_name("pci_create_multifunction") self.use_type_name("bool") self.use_type_name("DEVICE") decl_code += " PCIDevice *%s;\n" % dev_name def_code += """\ {dev_name} = pci_create_multifunction(@a{bus_name},@sPCI_DEVFN({slot},@s{func}),@s{multifunction},@s{qom_type});{props_code} qdev_init_nofail(DEVICE({dev_name})); """.format(dev_name=dev_name, bus_name=self.node_map[node.parent_bus], qom_type=node.qom_type if Type.exists(node.qom_type) else "\"%s\"" % node.qom_type, props_code=props_code, multifunction="true" if node.multifunction else "false", slot=node.slot, func=node.function) else: self.use_type_name("DeviceState") self.use_type_name("qdev_create") decl_code += " DeviceState *%s;\n" % dev_name if ((node.parent_bus is None) or isinstance(node.parent_bus, SystemBusNode)): bus_name = "NULL" else: bus_name = "BUS(%s)" % self.node_map[node.parent_bus] if Type.exists(node.qom_type): qom_type = node.qom_type else: qom_type = "\"%s\"" % node.qom_type def_code += """\ {dev_name} = qdev_create(@a{bus_name},@s{qom_type});{props_code} qdev_init_nofail({dev_name}); """.format(dev_name=dev_name, bus_name=bus_name, qom_type=qom_type, props_code=props_code) if isinstance(node, SystemBusDeviceNode): for idx, mmio in node.mmio_mappings.items(): if mmio is not None: self.use_type_name("sysbus_mmio_map") self.use_type_name("SYS_BUS_DEVICE") if isinstance(mmio, str) and Type.exists(mmio): self.use_type_name(mmio) mmio_val = str(mmio) else: mmio_val = "0x%x" % mmio def_code += """\ sysbus_mmio_map(@aSYS_BUS_DEVICE({dev_name}),@s{idx},@s{mmio_val}); """.format(dev_name=dev_name, idx=idx, mmio_val=mmio_val) for bus in node.buses: if len(bus.devices) == 0: continue bus_name = self.node_map[bus] try: if isinstance(bus, PCIExpressBusNode): if isinstance(node, SystemBusDeviceNode): bridge_cast = "PCI_HOST_BRIDGE" bus_field = "bus" elif isinstance(node, PCIExpressDeviceNode): bridge_cast = "PCI_BRIDGE" bus_field = "sec_bus" else: raise UnknownBusBridgeType( node.parent_bus, bus) self.use_type_name(bridge_cast) def_code += """\ {bus_name} = {bridge_cast}({bridge_name})->{bus_field}; """.format(bus_name=bus_name, bridge_name=dev_name, bridge_cast=bridge_cast, bus_field=bus_field) else: raise UnknownBusBridgeType(node.parent_bus, bus) except UnknownBusBridgeType: self.use_type_name("qdev_get_child_bus") self.use_type_name("DEVICE") if bus.cast is not None: self.use_type_name(bus.cast) def_code += """\ {bus_name} = {bus_cast}; """.format( bus_name=bus_name, bus_cast=("(%s *) %%s" % bus.c_type) if bus.cast is None else ("%s(%%s)" % bus.cast), ) % """\ qdev_get_child_bus(@aDEVICE({bridge_name}),@s"{bus_child_name}")\ """.format( bridge_name=dev_name, bus_child_name=bus.gen_child_name_for_bus(), ) elif isinstance(node, BusNode): # No definition code will be generated skip_nl = True if isinstance(node, SystemBusNode): continue if len(node.devices) == 0: continue self.use_type_name(node.c_type) bus_name = self.node_map[node] decl_code += " %s *%s;\n" % (node.c_type, bus_name) elif isinstance(node, IRQLine): if node.hub_ended(): # Do not generate a code for IRQ lines that refers an IRQ # hub. The code will be generated during the hub processing. skip_nl = True continue self.use_type_name("qemu_irq") irq_name = self.node_map[node] decl_code += " qemu_irq %s;\n" % irq_name def_code += (self.gen_irq_get(node.dst, irq_name) + self.gen_irq_connect(node.src, irq_name)) elif isinstance(node, MemoryNode): self.use_type_name("MemoryRegion") if isinstance(node.size, str) and Type.exists(node.size): self.use_type_name(node.size) if Type.exists(node.name): self.use_type_name(node.name) mem_name = self.node_map[node] decl_code += " MemoryRegion *%s;\n" % mem_name if isinstance(node, MemorySASNode): self.use_type_name("get_system_memory") def_code += " %s = get_system_memory();\n" % mem_name else: def_code += " %s = g_new(MemoryRegion, 1);\n" % mem_name if isinstance(node, MemoryAliasNode): self.use_type_name("memory_region_init_alias") if Type.exists(node.alias_offset): self.use_type_name(node.alias_offset) def_code += """\ memory_region_init_alias(@a{mem_name},@sNULL,@s{dbg_name},@s{orig},@s{offset},@s{size}); """.format(mem_name=mem_name, dbg_name=node.name if Type.exists(node.name) else "\"%s\"" % node.name, size=node.size, orig=self.node_map[node.alias_to], offset=node.alias_offset) elif (isinstance(node, MemoryRAMNode) or isinstance(node, MemoryROMNode)): self.use_type_name("memory_region_init_ram") if glob_mem: self.use_type_name("vmstate_register_ram_global") def_code += """\ memory_region_init_ram(@a{mem_name},@sNULL,@s{dbg_name},@s{size},@sNULL);{glob} """.format(mem_name=mem_name, dbg_name=node.name if Type.exists(node.name) else "\"%s\"" % node.name, size=node.size, glob=(("\n vmstate_register_ram_global(%s);" % mem_name) if glob_mem else "")) elif not isinstance(node, MemorySASNode): self.use_type_name("memory_region_init") def_code += """\ memory_region_init(@a{mem_name},@sNULL,@s{dbg_name},@s{size}); """.format(mem_name=mem_name, dbg_name=node.name if Type.exists(node.name) else "\"%s\"" % node.name, size=node.size) if node.parent is not None: if (isinstance(node.offset, str) and Type.exists(node.offset)): self.use_type_name(node.offset) if node.may_overlap: self.use_type_name( "memory_region_add_subregion_overlap") if (isinstance(node.priority, str) and Type.exists(node.priority)): self.use_type_name(node.priority) def_code += """\ memory_region_add_subregion_overlap(@a{parent_name},@s{offset},@s{child},@s{priority}); """.format(parent_name=self.node_map[node.parent], offset=node.offset, priority=node.priority, child=mem_name) else: self.use_type_name("memory_region_add_subregion") if (isinstance(node.priority, str) and Type.exists(node.priority)): self.use_type_name(node.priority) def_code += """\ memory_region_add_subregion(@a{parent_name},@s{offset},@s{child}); """.format(parent_name=self.node_map[node.parent], offset=node.offset, child=mem_name) elif isinstance(node, IRQHub): if len(node.irqs) < 1: # Nothing to do for detached IRQ hub skip_nl = True continue self.use_type_name("qemu_irq") hub_in_name = self.node_map[node] decl_code += " qemu_irq %s;\n" % hub_in_name hubl = self.provide_hub_layout(node) code = hubl.gen_irq_get() decl_code += code[0] def_code += code[1] for in_irq in [irq for irq in node.irqs if irq.dst[0] == node]: src = in_irq.src if isinstance(src[0], IRQHub): # A source hub does connects to this hub by itself continue def_code += self.gen_irq_connect(src, hub_in_name) elif isinstance(node, CPUNode): self.use_type_name("CPUState") self.use_type_name("cpu_create") self.use_type_name("qemu_register_reset") cpu_reset = self.cpu_reset self.use_type_name(cpu_reset.name) cpu_name = self.node_map[node] decl_code += " CPUState *%s;\n" % cpu_name if Type.exists(node.qom_type): qom_type = node.qom_type else: qom_type = "\"%s\"" % node.qom_type def_code += """\ {var_name}@b=@scpu_create(@a{qom_type}); qemu_register_reset(@a{reset},@s{var_name}); """.format(var_name=cpu_name, qom_type=qom_type, reset=cpu_reset.name) else: raise UnknownMachineNodeType(str(type(node))) # machine initialization function self.instance_init = Function( name="init_%s" % self.qtn.for_id_name, static=True, args=[Pointer(Type["MachineState"])("machine")], body=decl_code + "\n" + def_code, used_types=self.init_used_types) self.source.add_type(self.instance_init) get_vp("machine type register template generator")(self)