Beispiel #1
0
    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)
Beispiel #2
0
    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)