Beispiel #1
0
    def gen_vmstate_initializer(self, state_struct):
        # TODO: avoid using TYPE macros
        # https://lists.gnu.org/archive/html/qemu-devel/2018-10/msg02175.html
        type_macro = Type[self.qtn.type_macro]
        code = ("""{
    .name@b=@s%s,
    .version_id@b=@s1,
    .fields@b=@s(VMStateField[])@b{
""" % type_macro.name
        )

        used_macros = set()
        global type2vmstate

        for f in self.state_fields:
            if not f.save:
                continue

            if f.num is not None:
                raise Exception(
                    "VMState field generation for arrays is not supported"
                )

            try:
                vms_macro_name = type2vmstate[f.type.c_name]
            except KeyError:
                raise Exception(
                    "VMState generation for type %s is not implemented" % \
                        f.type.name
                )

            vms_macro = Type[vms_macro_name]
            used_macros.add(vms_macro)

            init = Initializer(
                # code of macro initializer is dict
                {
                    "_f": f.name,
                    "_s": state_struct.name,
                    # Macros may use different argument names
                    "_field": f.name,
                    "_state": state_struct.name
                }
            )
            code += " " * 8 + vms_macro.gen_usage_string(init) + ",\n"

        # Generate VM state list terminator macro.
        code += " " * 8 + Type["VMSTATE_END_OF_LIST"].gen_usage_string()

        code += "\n    }\n}"

        init = Initializer(
            code = code,
            used_types = used_macros.union([
                type_macro,
                Type["VMStateField"],
                state_struct
            ])
        )
        return init
Beispiel #2
0
def machine_register_2_5(mach):
    # machine class definition function
    mach.class_init = Function("machine_%s_class_init" % mach.qtn.for_id_name,
                               static=True,
                               ret_type=Type["void"],
                               args=[
                                   Type["ObjectClass"].gen_var("oc",
                                                               pointer=True),
                                   Type["void"].gen_var("opaque", pointer=True)
                               ],
                               body="""\
    MachineClass *mc = MACHINE_CLASS(oc);

    mc->name = \"{type_name}\";
    mc->desc = \"{desc}\";
    mc->init = {instance_init};
""".format(type_name=mach.qtn.for_id_name,
           desc=mach.desc,
           instance_init=mach.instance_init.name),
                               used_types=[
                                   Type["MachineClass"], Type["MACHINE_CLASS"],
                                   mach.instance_init
                               ])
    mach.source.add_type(mach.class_init)

    # machine type definition structure
    type_machine_macro = Type["TYPE_MACHINE"]
    type_machine_suf_macro = Type["TYPE_MACHINE_SUFFIX"]

    mach.type_info = Type["TypeInfo"].gen_var(
        name="machine_type_%s" % mach.qtn.for_id_name,
        static=True,
        initializer=Initializer(
            {
                "name":
                '"%s" %s' %
                (mach.qtn.for_id_name, type_machine_suf_macro.name),
                "parent":
                type_machine_macro,
                "class_init":
                mach.class_init
            },
            used_types=[type_machine_suf_macro]))
    mach.source.add_global_variable(mach.type_info)

    # machine type registration function
    mach.type_reg_func = Function("machine_init_%s" % mach.qtn.for_id_name,
                                  body="""\
    type_register(&{type_info});
""".format(type_info=mach.type_info.name),
                                  static=True,
                                  used_types=[Type["type_register"]],
                                  used_globals=[mach.type_info])
    mach.source.add_type(mach.type_reg_func)

    # Main machine registration macro
    def_type = get_vp("machine initialization function register type name")
    machine_init_def_args = Initializer(code={"function": mach.type_reg_func})
    mach.source.add_type(
        Type[def_type].gen_usage(initializer=machine_init_def_args))
Beispiel #3
0
def machine_register_2_6(mach):
    # machine class definition function
    mach.class_init = Function(
        name="machine_%s_class_init" % mach.qtn.for_id_name,
        static=True,
        ret_type=Type.lookup("void"),
        args=[
            Type.lookup("ObjectClass").gen_var("oc", pointer=True),
            Type.lookup("void").gen_var("opaque", pointer=True)
        ],
        body="""\
    MachineClass *mc = MACHINE_CLASS(oc);

    mc->desc = \"{desc}\";
    mc->init = {instance_init};
""".format(desc=mach.desc, instance_init=mach.instance_init.name),
        used_types=[
            Type.lookup("MachineClass"),
            Type.lookup("MACHINE_CLASS"), mach.instance_init
        ])
    mach.source.add_type(mach.class_init)

    # machine type definition structure
    type_machine_macro = Type.lookup("TYPE_MACHINE")
    type_machine_type_name_macro = Type.lookup("MACHINE_TYPE_NAME")

    mach.type_info = Type.lookup("TypeInfo").gen_var(
        name="machine_type_%s" % mach.qtn.for_id_name,
        static=True,
        initializer=Initializer(
            {
                "name":
                type_machine_type_name_macro.gen_usage_string(
                    Initializer({"machinename": '"%s"' % mach.qtn.for_id_name
                                 })),
                "parent":
                type_machine_macro,
                "class_init":
                mach.class_init
            },
            used_types=[type_machine_type_name_macro]))
    mach.source.add_global_variable(mach.type_info)

    # machine type registration function
    mach.type_reg_func = mach.gen_register_types_fn(mach.type_info)
    mach.source.add_type(mach.type_reg_func)

    # Main machine registration macro
    machine_init_def = Type.lookup("type_init").gen_var()
    machine_init_def_args = Initializer({"function": mach.type_reg_func})
    mach.source.add_usage(machine_init_def.gen_usage(machine_init_def_args))
Beispiel #4
0
    def setUp(self):
        super(TestMacroType, self).setUp()
        name = type(self).__name__

        hdr = Header(name.lower() + ".h")
        hdr.add_type(Macro("QTAIL_ENTRY", args=["type"]))

        struct = Structure("StructA")
        struct.append_fields([
            Type["QTAIL_ENTRY"]("entry",
                                macro_initializer=Initializer({"type":
                                                               struct})),
            Pointer(struct)("next")
        ])
        hdr.add_type(struct)

        hdr_content = """\
/* {path} */
#ifndef INCLUDE_{fname_upper}_H
#define INCLUDE_{fname_upper}_H

#define QTAIL_ENTRY(type)

typedef struct StructA StructA;

struct StructA {{
    QTAIL_ENTRY(StructA) entry;
    StructA *next;
}};

#endif /* INCLUDE_{fname_upper}_H */
""".format(path=hdr.path, fname_upper=name.upper())

        self.files = [(hdr, hdr_content)]
Beispiel #5
0
    def gen_net_client_info(self, index):
        helpers = []
        code = {}
        for helper_name, cbtn in [
            ("link_status_changed", "LinkStatusChanged"),
            ("can_receive", "NetCanReceive"),
            ("receive", "NetReceive"),
            ("cleanup", "NetCleanup")
        ]:
            helper = self.gen_nic_helper(helper_name, cbtn, index)
            self.source.add_type(helper)
            helpers.append(helper)
            code[helper_name] = helper

        # Define relative order of helpers: link, can recv, recv, cleanup
        line_origins(helpers)

        code["type"] = Type["NET_CLIENT_DRIVER_NIC"]
        types = set([Type["NICState"]] + list(code.values()))
        code["size"] = "sizeof(NICState)"

        return Type["NetClientInfo"](
            self.net_client_info_name(index),
            initializer = Initializer(code, used_types = types),
            static = True
        )
Beispiel #6
0
def gen_prop_declaration(field,
                         decl_macro_name,
                         state_struct,
                         default_default=None):
    decl_macro = Type.lookup(decl_macro_name)
    used_types = set([decl_macro])
    bool_true = Type.lookup("true")
    bool_false = Type.lookup("false")

    init_code = {
        "_f": field.name,
        "_s": state_struct,
    }

    if field.prop_macro_name is not None:
        init_code["_n"] = Type.lookup(field.prop_macro_name)
        init_code["_name"] = init_code["_n"]

    init_code["_state"] = init_code["_s"]
    init_code["_field"] = init_code["_f"]

    # _conf is name of argument of macro DEFINE_NIC_PROPERTIES that
    # corresponds to structure filed name
    init_code["_conf"] = init_code["_f"]

    if default_default is not None:
        if field.default is None:
            val = default_default
        else:
            val = field.default

        if isinstance(val, str):
            try:
                val_macro = Type.lookup(val)
            except TypeNotRegistered:
                val = '"%s"' % val
            else:
                val = val_macro
        elif isinstance(val, bool):
            if val:
                val = bool_true
            else:
                val = bool_false
        elif isinstance(val, integer_types):
            if field.type.name[0] == "u":
                val = "0x%X" % val
            else:
                val = str(val)
        else:
            val = str(val)

        init_code["_d"] = val
        init_code["_defval"] = val

    initializer = Initializer(code=init_code)
    usage_str = decl_macro.gen_usage_string(initializer)
    return (usage_str, used_types)
Beispiel #7
0
    def gen_properties_initializer(self, state_struct):
        used_types = set()
        global type2prop

        code = "{"

        first = True
        for f in self.state_fields:
            if not f.prop:
                continue

            try:
                helper = type2prop[f.type.c_name]
            except KeyError:
                raise Exception(
                    "Property generation for type %s is not implemented" % \
                        f.type.name
                )

            decl_code, decl_types = helper(f, state_struct)

            used_types |= decl_types

            if first:
                first = False
                code += "\n"
            else:
                code += ",\n"
            code += "    " + decl_code

        # generate property list terminator
        terminator_macro = Type["DEFINE_PROP_END_OF_LIST"]
        if first:
            code += "\n"
        else:
            code += ",\n"
        code += "    " + terminator_macro.gen_usage_string() + "\n}"

        init = Initializer(
            code = code,
            used_types = used_types.union([
                terminator_macro,
                state_struct
            ])
        )
        return init
Beispiel #8
0
    def setUp(self):
        super(TestMacroType, self).setUp()
        name = type(self).__name__

        Header("entry_macro.h").add_type(Macro("QTAIL_ENTRY", args=["type"]))
        Header("struct_end.h").add_type(Macro("END_STRUCT"))
        Header("header_init.h").add_type(Macro("INIT_HEADER"))

        hdr = Header(name.lower() + ".h")
        struct = Structure("StructA")
        struct.append_fields([
            Type["QTAIL_ENTRY"]("entry",
                                macro_initializer=Initializer({"type":
                                                               struct})),
            Pointer(struct)("next"), Type["END_STRUCT"].gen_type()
        ])
        hdr.add_type(struct)

        hdr.add_type(Type["INIT_HEADER"].gen_type())

        hdr_content = """\
/* {path} */
#ifndef INCLUDE_{fname_upper}_H
#define INCLUDE_{fname_upper}_H

#include "entry_macro.h"
#include "header_init.h"
#include "struct_end.h"

typedef struct StructA StructA;

struct StructA {{
    QTAIL_ENTRY(StructA) entry;
    StructA *next;
    END_STRUCT
}};

INIT_HEADER
#endif /* INCLUDE_{fname_upper}_H */
""".format(path=hdr.path, fname_upper=name.upper())

        self.files = [(hdr, hdr_content)]
Beispiel #9
0
    def gen_type_info_var(self,
                          state_struct,
                          instance_init_fn,
                          class_init_fn,
                          parent_tn="TYPE_OBJECT"):
        used_types = [state_struct, instance_init_fn, class_init_fn]

        try:
            parent_macro = Type.lookup(parent_tn)
        except TypeNotRegistered:
            parent_macro = None
        else:
            used_types.append(parent_macro)

        # Type info initializer
        tii = Initializer(
            code = """{{
    .name@b@b@b@b@b@b@b@b@b@b=@sTYPE_{UPPER},
    .parent@b@b@b@b@b@b@b@b=@s{parent_tn},
    .instance_size@b=@ssizeof({Struct}),
    .instance_init@b=@s{instance_init},
    .class_init@b@b@b@b=@s{class_init}
}}""".format(
        UPPER = self.qtn.for_macros,
        parent_tn = ('"%s"' % parent_tn) if parent_macro is None \
                else parent_macro.name,
        Struct = state_struct.name,
        instance_init = instance_init_fn.name,
        class_init = class_init_fn.name
            ),
            used_types = used_types
        )
        # TypeInfo variable
        tiv = Type.lookup("TypeInfo").gen_var(name=self.gen_type_info_name(),
                                              static=True,
                                              initializer=tii)

        return tiv
Beispiel #10
0
    def generate_source(self):
        self.device_reset = Function(
            "%s_reset" % self.qtn.for_id_name,
            body="""\
    __attribute__((unused))@b{Struct}@b*s@b=@s{UPPER}(dev);
""".format(
                Struct=self.state_struct.name,
                UPPER=self.type_cast_macro.name,
            ),
            args=[Type.lookup("DeviceState").gen_var("dev", True)],
            static=True,
            used_types=[self.state_struct])
        self.source.add_type(self.device_reset)

        realize_code = ''
        realize_used_types = set()
        realize_used_globals = []
        s_is_used = False

        if self.mem_bar_num > 0:
            s_is_used = True
            realize_used_types.update([
                Type.lookup("sysbus_init_mmio"),
                Type.lookup("memory_region_init_io"),
                Type.lookup("Object")
            ])

        for barN in range(0, self.mem_bar_num):
            size_macro = self.mem_bar_size_macros[barN]
            realize_used_types.add(size_macro)

            component = self.get_Ith_mem_bar_id_component(barN)

            read_func = QOMType.gen_mmio_read(
                name=self.qtn.for_id_name + "_" + component + "_read",
                struct_name=self.state_struct.name,
                type_cast_macro=self.type_cast_macro.name,
                regs=self.bars.get(barN, None))

            write_func = QOMType.gen_mmio_write(
                name=self.qtn.for_id_name + "_" + component + "_write",
                struct_name=self.state_struct.name,
                type_cast_macro=self.type_cast_macro.name,
                regs=self.bars.get(barN, None))

            write_func.extra_references = {read_func}

            self.source.add_types([read_func, write_func])

            ops_init = Initializer(used_types=[read_func, write_func],
                                   code="""{{
    .read = {read},
    .write = {write}
}}""".format(read=read_func.name, write=write_func.name))

            ops = Type.lookup("MemoryRegionOps").gen_var(
                name=self.gen_Ith_mem_bar_ops_name(barN),
                pointer=False,
                initializer=ops_init,
                static=True)

            self.source.add_global_variable(ops)
            realize_used_globals.append(ops)

            realize_code += """
    memory_region_init_io(@a&s->{bar},@sOBJECT(dev),@s&{ops},@ss,@s{TYPE_MACRO},@s{size});
    pci_register_bar(@a&s->parent_obj,@s{barN},@sPCI_BASE_ADDRESS_SPACE_MEMORY,@s&s->{bar});
""".format(barN=barN,
            bar=self.get_Ith_mem_bar_name(barN),
            ops=self.gen_Ith_mem_bar_ops_name(barN),
            TYPE_MACRO=self.qtn.type_macro,
            size=size_macro.name)

        if self.msi_messages_num > 0:
            msi_init_type = Type.lookup("msi_init")
            s_is_used = True

            realize_code += """
    msi_init(dev,@s%s,@s%s,@s%s,@s%s%s);
""" % (self.msi_cap_offset.gen_usage_string(),
            self.msi_vectors.gen_usage_string(),
            self.msi_64bit.gen_usage_string(),
            self.msi_masking.gen_usage_string(),
            ",@serrp" if msi_init_type.args[-1].type \
                   == Pointer(Pointer(Type.lookup("Error"))) else ""
            )

            realize_used_types.update(self.msi_types)
            realize_used_types.add(msi_init_type)

        self.device_realize = self.gen_realize(
            "PCIDevice",
            code=realize_code,
            s_is_used=s_is_used,
            used_types=realize_used_types,
            used_globals=realize_used_globals)
        self.source.add_type(self.device_realize)

        code = ""
        used_types = set([self.state_struct])
        used_s = False

        if self.msi_messages_num > 0:
            code += """
    msi_uninit(dev);
"""
            used_types.add(Type.lookup("msi_uninit"))

        if self.nic_num > 0:
            code += "\n"
            used_s = True

            del_nic = Type.lookup("qemu_del_nic")
            used_types.add(del_nic)

            for nicN in xrange(self.nic_num):
                nic_name = self.nic_name(nicN)
                code += "    %s(s->%s);\n" % (del_nic.name, nic_name)

        if self.timer_num > 0:
            used_s = True
            code += "\n"
            used_types.update(
                [Type.lookup("timer_del"),
                 Type.lookup("timer_free")])

            for timerN in range(self.timer_num):
                code += """    timer_del(s->{timerN});
    timer_free(s->{timerN});
""".format(timerN=self.timer_name(timerN))

        self.device_exit = Function(
            name="%s_exit" % self.qtn.for_id_name,
            args=[Type.lookup("PCIDevice").gen_var("dev", pointer=True)],
            static=True,
            used_types=used_types,
            body="""\
    {unused}{Struct}@b*s@b=@s{UPPER}(dev);
{extra_code}\
""".format(unused="" if used_s else "__attribute__((unused))@b",
           Struct=self.state_struct.name,
           UPPER=self.type_cast_macro.name,
           extra_code=code))
        self.source.add_type(self.device_exit)

        self.vmstate = self.gen_vmstate_var(self.state_struct)

        self.source.add_global_variable(self.vmstate)

        self.properties = self.gen_properties_global(self.state_struct)

        self.source.add_global_variable(self.properties)

        self.vmstate.extra_references = {self.properties}

        self.class_init = Function(
            name="%s_class_init" % self.qtn.for_id_name,
            body="""\
    DeviceClass@b*dc@b=@sDEVICE_CLASS(oc);
    PCIDeviceClass@b*pc@b=@sPCI_DEVICE_CLASS(oc);

    pc->realize@b@b@b{pad}=@s{dev}_realize;
    dc->reset@b@b@b@b@b{pad}=@s{dev}_reset;
    pc->exit@b@b@b@b@b@b{pad}=@s{dev}_exit;
    pc->vendor_id@b{pad}=@s{vendor_macro};
    pc->device_id@b{pad}=@s{device_macro};
    pc->class_id@b@b{pad}=@s{pci_class_macro};{subsys_id}{subsys_vid}
    pc->revision@b@b{pad}=@s{revision};
    dc->vmsd@b@b@b@b@b@b{pad}=@s&vmstate_{dev};
    dc->props@b@b@b@b@b{pad}=@s{dev}_properties;
""".format(dev=self.qtn.for_id_name,
           revision=self.revision,
           vendor_macro=self.vendor_macro.name,
           device_macro=self.device_macro.name,
           pci_class_macro=self.pci_class_macro.name,
           subsys_id='' if self.subsystem_macro is None else ("""
    pc->subsystem_id@b@b@b@b@b@b@b@b=@s%s;""" % self.subsystem_macro.name),
           subsys_vid='' if self.subsystem_vendor_macro is None else ("""
    pc->subsystem_vendor_id@b=@s%s;""" % self.subsystem_vendor_macro.name),
           pad='@b@b@b@b@b@b@b@b@b@b' if self.subsystem_vendor_macro else ''),
            args=[
                Type.lookup("ObjectClass").gen_var("oc", True),
                Type.lookup("void").gen_var("opaque", True),
            ],
            static=True,
            used_types=[
                Type.lookup("DeviceClass"),
                Type.lookup("PCIDeviceClass"), self.device_realize,
                self.device_reset, self.device_exit, self.vendor_macro,
                self.device_macro, self.pci_class_macro
            ],
            used_globals=[self.vmstate, self.properties])
        self.source.add_type(self.class_init)

        instance_init_used_types = set()
        instance_init_code = ""
        s_is_used = False

        self.instance_init = self.gen_instance_init_fn(
            self.state_struct,
            code=instance_init_code,
            s_is_used=s_is_used,
            used_types=instance_init_used_types)
        self.source.add_type(self.instance_init)

        self.type_info = self.gen_type_info_var(self.state_struct,
                                                self.instance_init,
                                                self.class_init,
                                                parent_tn="TYPE_PCI_DEVICE")

        self.source.add_global_variable(self.type_info)

        self.register_types = self.gen_register_types_fn(self.type_info)

        self.source.add_type(self.register_types)

        type_init_usage_init = Initializer(
            code={"function": self.register_types})
        self.source.add_type(
            Type.lookup("type_init").gen_usage(type_init_usage_init))

        # order life cycle functions
        self.device_reset.extra_references = {self.device_realize}
        self.device_exit.extra_references = {self.device_reset}

        return self.source.generate()
Beispiel #11
0
    def gen_type_info_var(self, state_struct, instance_init_fn, class_init_fn,
        parent_tn = "TYPE_OBJECT"
    ):
        used_types = [
            state_struct,
            instance_init_fn,
            class_init_fn
        ]

        try:
            parent_macro = Type[parent_tn]
        except TypeNotRegistered:
            parent_macro = None
        else:
            used_types.append(parent_macro)

        if self.interfaces:
            used_types.append(Type["InterfaceInfo"])
            interfaces = []
            for i in self.interfaces:
                if not isinstance(i, Macro):
                    try:
                        i = Type[i]
                    except TypeNotRegistered:
                        pass

                if isinstance(i, Macro):
                    interfaces.append(i.name)
                    used_types.append(i)
                else:
                    interfaces.append('"%s"' % i)
        else:
            interfaces = False

        # Type info initializer
        tii = Initializer(
            code = """{{
    .name@b@b@b@b@b@b@b@b@b@b=@s{TYPE_MACRO},
    .parent@b@b@b@b@b@b@b@b=@s{parent_tn},
    .instance_size@b=@ssizeof({Struct}),
    .instance_init@b=@s{instance_init},
    .class_init@b@b@b@b=@s{class_init}{interfaces}
}}""".format(
    TYPE_MACRO = self.qtn.type_macro,
    parent_tn = ('"%s"' % parent_tn) if parent_macro is None \
                else parent_macro.name,
    Struct = state_struct.name,
    instance_init = instance_init_fn.name,
    class_init = class_init_fn.name,
    interfaces = (
        ",\n"
        "    .interfaces@b@b@b@b=@s(InterfaceInfo[])@b{\n        "
        +
        ",\n        ".join("{@b%s@s}" % i for i in interfaces)
        +
        ",\n        {@b}\n"
        "    }"
    ) if interfaces else ""
            ),
            used_types = used_types
        )
        # TypeInfo variable
        return Type["TypeInfo"](
            name = self.gen_type_info_name(),
            static = True,
            initializer = tii
        )
Beispiel #12
0
    def generate_source(self):
        s_is_used = False

        all_regs = []
        for idx, regs in self.mmio.items():
            if idx >= self.mmio_num:
                continue
            all_regs.extend(regs)
        for idx, regs in self.pio.items():
            if idx >= self.pio_num:
                continue
            all_regs.extend(regs)

        reg_resets = []

        used_types = set([self.state_struct])

        for reg in all_regs:
            name = reg.name
            if name is None or name == "gap":
                continue
            qtn = QemuTypeName(name)

            s_is_used = True

            reg_resets.append("s->%s@b=@s%s;" %
                              (qtn.for_id_name, reg.reset.gen_c_code()))

            warb = reg.warbits
            if warb.v:
                # forbid writing to WAR bits just after reset
                wm = reg.wmask
                if wm.v == (1 << (8 * reg.size)) - 1:
                    if reg.size < 4:
                        # Avoid gcc "overflow" warning: large integer
                        # implicitly truncated to unsigned type
                        cast_type = "uint%u_t" % (8 * reg.size)
                        used_types.add(Type[cast_type])
                        cast = "(%s)" % cast_type
                    else:
                        cast = ""

                    reg_resets.append(
                        "s->%s_war@b=@s%s~%s;" %
                        (qtn.for_id_name, cast, warb.gen_c_code()))
                elif wm.v:
                    reg_resets.append(
                        "s->%s_war@b=@s%s@s&@b~%s;" %
                        (qtn.for_id_name, wm.gen_c_code(), warb.gen_c_code()))

        self.device_reset = Function(
            "%s_reset" % self.qtn.for_id_name,
            body="""\
    {unused}{Struct}@b*s@b=@s{UPPER}(dev);{reset}
""".format(unused="" if s_is_used else "__attribute__((unused))@b",
           Struct=self.state_struct.name,
           UPPER=self.type_cast_macro.name,
           reset="\n\n    " + "\n    ".join(reg_resets) if reg_resets else ""),
            args=[Type.lookup("DeviceState").gen_var("dev", True)],
            static=True,
            used_types=used_types)

        self.source.add_type(self.device_reset)

        self.device_realize = self.gen_realize("DeviceState")
        self.source.add_type(self.device_realize)

        s_is_used = False
        instance_init_code = ''
        instance_init_used_types = set()
        instance_init_used_globals = []

        if self.mmio_num > 0:
            instance_init_used_types.update([
                Type.lookup("sysbus_init_mmio"),
                Type.lookup("memory_region_init_io"),
                Type.lookup("Object")
            ])

        for mmioN in range(0, self.mmio_num):
            size_macro = self.mmio_size_macros[mmioN]
            instance_init_used_types.add(size_macro)

            component = self.get_Ith_mmio_id_component(mmioN)

            regs = self.mmio.get(mmioN, None)

            read_func = QOMType.gen_mmio_read(
                name=self.qtn.for_id_name + "_" + component + "_read",
                struct_name=self.state_struct.name,
                type_cast_macro=self.type_cast_macro.name,
                regs=regs)

            write_func = QOMType.gen_mmio_write(
                name=self.qtn.for_id_name + "_" + component + "_write",
                struct_name=self.state_struct.name,
                type_cast_macro=self.type_cast_macro.name,
                regs=regs)

            impl = ""

            if regs:
                reg_sizes = set(reg.size for reg in regs)

                size = regs[0].size  # note that all sizes are equal

                if len(reg_sizes) == 1 and size < 8:  # 8 is max size by impl.
                    impl = """,
    .impl = {{
        .max_access_size = {size}
    }}""".format(size=size)

            write_func.extra_references = {read_func}

            self.source.add_types([read_func, write_func])

            ops_init = Initializer(used_types=[read_func, write_func],
                                   code="""{{
    .read@b=@s{read},
    .write@b=@s{write}{impl}
}}""".format(read=read_func.name, write=write_func.name, impl=impl))

            ops = Type.lookup("MemoryRegionOps").gen_var(
                name=self.gen_Ith_mmio_ops_name(mmioN),
                pointer=False,
                initializer=ops_init,
                static=True)

            self.source.add_global_variable(ops)
            instance_init_used_globals.append(ops)

            instance_init_code += """
    memory_region_init_io(@a&s->{mmio},@sobj,@s&{ops},@ss,@s{TYPE_MACRO},\
@s{size});
    sysbus_init_mmio(@aSYS_BUS_DEVICE(obj),@s&s->{mmio});
""".format(mmio=self.get_Ith_mmio_name(mmioN),
            ops=self.gen_Ith_mmio_ops_name(mmioN),
            TYPE_MACRO=self.qtn.type_macro,
            size=size_macro.name)
            s_is_used = True

        if self.pio_num > 0:
            instance_init_used_types.update([
                Type.lookup("sysbus_add_io"),
                Type.lookup("memory_region_init_io"),
                Type.lookup("Object"),
                Type.lookup("sysbus_init_ioports")
            ])

        for pioN in range(0, self.pio_num):
            size_macro = self.pio_size_macros[pioN]
            address_macro = self.pio_address_macros[pioN]
            instance_init_used_types.update([size_macro, address_macro])

            component = self.get_Ith_pio_id_component(pioN)

            read_func = QOMType.gen_mmio_read(
                name=self.qtn.for_id_name + "_" + component + "_read",
                struct_name=self.state_struct.name,
                type_cast_macro=self.type_cast_macro.name,
                regs=self.pio.get(pioN, None))

            write_func = QOMType.gen_mmio_write(
                name=self.qtn.for_id_name + "_" + component + "_write",
                struct_name=self.state_struct.name,
                type_cast_macro=self.type_cast_macro.name,
                regs=self.pio.get(pioN, None))

            write_func.extra_references = {read_func}

            self.source.add_types([read_func, write_func])

            ops_init = Initializer(used_types=[read_func, write_func],
                                   code="""{{
    .read@b=@s{read},
    .write@b=@s{write}
}}""".format(read=read_func.name, write=write_func.name))

            ops = Type.lookup("MemoryRegionOps").gen_var(
                name=self.gen_Ith_pio_ops_name(pioN),
                pointer=False,
                initializer=ops_init,
                static=True)

            self.source.add_global_variable(ops)
            instance_init_used_globals.append(ops)

            instance_init_code += """
    memory_region_init_io(@a&s->{pio},@sobj,@s&{ops},@ss,@s{TYPE_MACRO},\
@s{size});
    sysbus_add_io(@aSYS_BUS_DEVICE(obj),@s{addr},@s&s->{pio});
    sysbus_init_ioports(@aSYS_BUS_DEVICE(obj),@s{addr},@s{size});
""".format(pio=self.get_Ith_io_name(pioN),
            ops=self.gen_Ith_pio_ops_name(pioN),
            TYPE_MACRO=self.qtn.type_macro,
            size=size_macro.name,
            addr=address_macro.name)
            s_is_used = True

        if self.out_irq_num > 0:
            instance_init_used_types.update(
                [Type.lookup("qemu_irq"),
                 Type.lookup("sysbus_init_irq")])

            instance_init_code += "\n"

            for irqN in range(0, self.out_irq_num):
                instance_init_code += """\
    sysbus_init_irq(@aSYS_BUS_DEVICE(obj),@s&s->%s);
""" % self.get_Ith_irq_name(irqN)

        if self.in_irq_num > 0:
            self.irq_handler = Type["qemu_irq_handler"].use_as_prototype(
                name=self.qtn.for_id_name + "_irq_handler",
                static=True,
                used_types=[self.state_struct, self.type_cast_macro],
                body="""\
    __attribute__((unused))@b{Struct}@b*s@b=@s{UPPER}(opaque);
""".format(
                    Struct=self.state_struct.name,
                    UPPER=self.type_cast_macro.name,
                ))

            self.source.add_type(self.irq_handler)

            instance_init_code += """
    qdev_init_gpio_in(@aDEVICE(obj),@s{handler},@s{irqs});
""".format(handler=self.irq_handler.name, irqs=self.in_irq_macro.name)

            instance_init_used_types.update([
                self.irq_handler, self.in_irq_macro,
                Type.lookup("qdev_init_gpio_in"),
                Type.lookup("DEVICE")
            ])

        self.instance_init = self.gen_instance_init_fn(
            self.state_struct,
            code=instance_init_code,
            s_is_used=s_is_used,
            used_types=instance_init_used_types,
            used_globals=instance_init_used_globals)

        self.source.add_type(self.instance_init)

        # `unrealized` method code generation
        code = ""
        used_s = False
        used_types = set([self.state_struct, self.type_cast_macro])

        if self.timer_num > 0:
            used_s = True
            code += "\n"
            used_types.update(
                [Type.lookup("timer_del"),
                 Type.lookup("timer_free")])

            for timerN in range(self.timer_num):
                code += """    timer_del(s->{timerN});
    timer_free(s->{timerN});
""".format(timerN=self.timer_name(timerN))

        self.device_unrealize = Function(
            self.qtn.for_id_name + "_unrealize",
            args=[
                Pointer(Type.lookup("DeviceState")).gen_var("dev"),
                Pointer(Pointer(Type.lookup("Error"))).gen_var("errp")
            ],
            static=True,
            used_types=used_types,
            body="""    {unused}{Struct}@b*s@b=@s{CAST}(dev);
{extra_code}""".format(unused="" if used_s else "__attribute__((unused))@b",
                       Struct=self.state_struct.name,
                       CAST=self.type_cast_macro.name,
                       extra_code=code))
        self.source.add_type(self.device_unrealize)

        self.vmstate = self.gen_vmstate_var(self.state_struct)

        self.source.add_global_variable(self.vmstate)

        self.properties = self.gen_properties_global(self.state_struct)

        self.source.add_global_variable(self.properties)

        self.vmstate.extra_references = {self.properties}

        self.class_init = Function(
            name="%s_class_init" % self.qtn.for_id_name,
            body="""\
    DeviceClass@b*dc@b=@sDEVICE_CLASS(oc);

    dc->realize@b@b@b=@s{dev}_realize;
    dc->reset@b@b@b@b@b=@s{dev}_reset;
    dc->unrealize@b=@s{dev}_unrealize;
    dc->vmsd@b@b@b@b@b@b=@s&vmstate_{dev};
    dc->props@b@b@b@b@b=@s{dev}_properties;
""".format(dev=self.qtn.for_id_name),
            args=[
                Type.lookup("ObjectClass").gen_var("oc", True),
                Type.lookup("void").gen_var("opaque", True),
            ],
            static=True,
            used_types=[
                Type.lookup("DeviceClass"), self.device_realize,
                self.device_reset, self.device_unrealize
            ],
            used_globals=[self.vmstate, self.properties])

        self.source.add_type(self.class_init)

        self.type_info = self.gen_type_info_var(
            self.state_struct,
            self.instance_init,
            self.class_init,
            parent_tn="TYPE_SYS_BUS_DEVICE")

        self.source.add_global_variable(self.type_info)

        self.register_types = self.gen_register_types_fn(self.type_info)

        self.source.add_type(self.register_types)

        type_init_usage_init = Initializer(
            code={"function": self.register_types})
        self.source.add_type(
            Type.lookup("type_init").gen_usage(type_init_usage_init))

        # order life cycle functions
        self.device_realize.extra_references = {self.instance_init}
        self.device_reset.extra_references = {self.device_realize}
        self.device_unrealize.extra_references = {self.device_reset}

        return self.source.generate()
Beispiel #13
0
    def gen_vmstate_initializer(self, state_struct):
        type_macro = Type.lookup("TYPE_" + self.qtn.for_macros)
        code = ("""{
    .name@b=@s%s,
    .version_id@b=@s1,
    .fields@b=@s(VMStateField[])@b{""" % type_macro.name)

        used_macros = set()
        global type2vmstate

        first = True
        for f in self.state_fields:
            if not f.save:
                continue

            if f.num is not None:
                raise Exception(
                    "VMState field generation for arrays is not supported")

            try:
                vms_macro_name = type2vmstate[f.type.name]
            except KeyError:
                raise Exception(
                    "VMState generation for type %s is not implemented" % \
                        f.type.name
                )

            vms_macro = Type.lookup(vms_macro_name)
            used_macros.add(vms_macro)

            init = Initializer(
                # code of macro initializer is dict
                {
                    "_f": f.name,
                    "_s": state_struct.name,
                    # Macros may use different argument names
                    "_field": f.name,
                    "_state": state_struct.name
                })

            if first:
                first = False
                code += "\n"
            else:
                code += ",\n"

            code += " " * 8 + vms_macro.gen_usage_string(init)

        # Generate VM state list terminator macro.
        if first:
            code += "\n"
        else:
            code += ",\n"
        code += " " * 8 + Type.lookup("VMSTATE_END_OF_LIST").gen_usage_string()

        code += "\n    }\n}"

        init = Initializer(code=code,
                           used_types=used_macros.union([
                               type_macro,
                               Type.lookup("VMStateField"), state_struct
                           ]))
        return init
Beispiel #14
0
def machine_register_2_6(mach):
    # machine class definition function
    class_init = Function(
        name = "machine_%s_class_init" % mach.qtn.for_id_name,
        static = True,
        ret_type = Type["void"],
        args = [
            Pointer(Type["ObjectClass"])("oc"),
            Pointer(Type["void"])("opaque")
        ]
    )
    mc = Pointer(Type["MachineClass"])("mc")
    class_init.body = BodyTree()(
        Declare(
            OpDeclareAssign(
                mc,
                MCall(
                   "MACHINE_CLASS",
                    class_init.args[0]
                )
            )
        ),
        NewLine(),
        OpAssign(
            OpSDeref(mc, "desc"),
            mach.desc
        ),
        OpAssign(
            OpSDeref(mc, "init"),
            mach.instance_init
        )
    )
    mach.class_init = class_init
    mach.source.add_type(class_init)

    # machine type definition structure
    type_machine_macro = Type["TYPE_MACHINE"]
    type_machine_type_name_macro = Type["MACHINE_TYPE_NAME"]

    mach.type_info = Type["TypeInfo"](
        name = "machine_type_%s" % mach.qtn.for_id_name,
        static = True,
        initializer = Initializer({
                "name" : type_machine_type_name_macro.gen_usage_string(
                    Initializer({
                        "machinename" : '"%s"' % mach.qtn.for_id_name
                    })
                ),
                "parent" : type_machine_macro,
                "class_init" : mach.class_init
            },
            used_types = [ type_machine_type_name_macro ]
        )
    )
    mach.source.add_global_variable(mach.type_info)

    # machine type registration function
    mach.type_reg_func = mach.gen_register_types_fn(mach.type_info)
    mach.source.add_type(mach.type_reg_func)

    # Main machine registration macro
    machine_init_def_args = Initializer({ "function": mach.type_reg_func })
    mach.source.add_type(
        Type["type_init"].gen_type(initializer = machine_init_def_args)
    )
Beispiel #15
0
def machine_register_2_5(mach):
    # machine class definition function
    class_init = Function(
        name = "machine_%s_class_init" % mach.qtn.for_id_name,
        static = True,
        ret_type = Type["void"],
        args = [
            Pointer(Type["ObjectClass"])("oc"),
            Pointer(Type["void"])("opaque")
        ]
    )
    mc = Pointer(Type["MachineClass"])("mc")
    class_init.body = BodyTree()(
        Declare(
            OpDeclareAssign(
                mc,
                MCall(
                   "MACHINE_CLASS",
                    class_init.args[0]
                )
            )
        ),
        NewLine(),
        OpAssign(
            OpSDeref(mc, "name"),
            mach.qtn.for_id_name
        ),
        OpAssign(
            OpSDeref(mc, "desc"),
            mach.desc
        ),
        OpAssign(
            OpSDeref(mc, "init"),
            mach.instance_init
        )
    )
    mach.class_init = class_init
    mach.source.add_type(class_init)

    # machine type definition structure
    type_machine_macro = Type["TYPE_MACHINE"]
    type_machine_suf_macro = Type["TYPE_MACHINE_SUFFIX"]

    mach.type_info = Type["TypeInfo"](
        name = "machine_type_%s" % mach.qtn.for_id_name,
        static = True,
        initializer = Initializer({
                "name" : '"%s" %s' % (mach.qtn.for_id_name,
                    type_machine_suf_macro.name
                ),
                "parent" : type_machine_macro,
                "class_init" : mach.class_init
            },
            used_types = [ type_machine_suf_macro ]
        )
    )
    mach.source.add_global_variable(mach.type_info)

    # machine type registration function
    mach.type_reg_func = Function(
        name = "machine_init_%s" % mach.qtn.for_id_name,
        body = BodyTree()(
            Call(
                "type_register",
                OpAddr(mach.type_info)
            )
        ),
        static = True
    )
    mach.source.add_type(mach.type_reg_func)

    # Main machine registration macro
    def_type = get_vp("machine initialization function register type name")
    machine_init_def_args = Initializer(
        code = { "function": mach.type_reg_func }
    )
    mach.source.add_type(
        Type[def_type].gen_type(initializer = machine_init_def_args)
    )