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
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))
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))
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)]
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 )
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)
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
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)]
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
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()
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 )
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()
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
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) )
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) )