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 setUp(self): super(TestOpaqueCode, self).setUp() name = type(self).__name__ hdr = Header(name.lower() + ".h", protection=False) test_var = Type["int"]("test_var") test_func = Function(name="test_func") opaque_top = OpaqueCode("""\ /* Generic comment above macros */ """, weight=0) opaque_bottom = OpaqueCode(""" /* A comment at bottom of file */ """, weight=10) opaque_middle = OpaqueCode(""" /* How to use test_var and test_func. */ """, used_variables=[test_var], used_types=[test_func] # Default weight (5) ) hdr.add_types([ # Yields #define statement with weight 1 Macro("TEST_MACRO"), # Yields function declaration with weight 6 Function(name="another_test_func"), opaque_middle, opaque_bottom, opaque_top ]) hdr_content = """\ /* {path} */ /* Generic comment above macros */ #define TEST_MACRO extern int test_var; void test_func(void); /* How to use test_var and test_func. */ void another_test_func(void); /* A comment at bottom of file */ """.format(path=hdr.path) self.files = [(hdr, hdr_content)]
def setUp(self): super(TestSeparateCases, self).setUp() src = Source(type(self).__name__.lower() + ".c") i = Type["int"]("i") src.add_type( Function(name="func_a", body=BodyTree()(Declare(OpDeclareAssign(i, 0)), BranchSwitch(i, separate_cases=True)( SwitchCase(1), SwitchCase(2))))) src_content = """\ /* {} */ void func_a(void) {{ int i = 0; switch (i) {{ case 1: break; case 2: break; default: break; }} }} """.format(src.path) self.files = [(src, src_content)]
def setUp(self): super(TestRedirectionToDeclaration, self).setUp() name = type(self).__name__ private_h = Header("private.h") private_h.add_type(Structure("Private")) public_h = Header("public.h") public_h.add_types([ Type["Private"].gen_forward_declaration(), Function("public_func") ]) private_c = Source("private.c") public_func_impl = Type["public_func"].gen_definition() private_c.add_type(public_func_impl) src = Source(name.lower() + ".c").add_global_variable( # It must internally re-direct pointer from type "Private" # to "Private.declaration", its forward declaration. Pointer(Type["Private"])("handler")) src.add_type(Pointer(public_func_impl, name="cb_ptr")) src_content = """\ /* %s */ #include "public.h" typedef void (*cb_ptr)(void); Private *handler __attribute__((unused)); """ % (name.lower() + ".c") self.files = [(src, src_content)]
def setUp(self): super(TestLabelAndGotoGeneration, self).setUp() name = type(self).__name__ src = Source(name.lower() + ".c") lbl = Label("begin") i = Type["int"]("i") src.add_type( Function(name="main", body=BodyTree()(Declare(i), lbl, OpAssign(i, OpAdd(i, 1)), Goto(lbl)))) src_content = """\ /* {} */ void main(void) {{ int i; begin: i = i + 1; goto begin; }} """.format(src.path) self.files = [(src, src_content)]
def setUp(self): super(TestHeaderInclusion, self).setUp() name = type(self).__name__ f = Function(name="test_f") f_def = f.gen_definition() hdr = Header(name.lower() + ".h").add_type(f) hdr_content = """\ /* {path} */ #ifndef INCLUDE_{fname_upper}_H #define INCLUDE_{fname_upper}_H void test_f(void); #endif /* INCLUDE_{fname_upper}_H */ """.format(path=hdr.path, fname_upper=name.upper()) src1 = Source(name.lower() + ".c").add_type(f_def) src1_content = """\ /* {} */ void test_f(void) {{}} """.format(src1.path) src2 = Source(name.lower() + "2.c").add_type( Function( name="func_a", body=BodyTree()( Call(f_def) # use function definition to Call ))) src2_content = """\ /* {} */ #include "{}" void func_a(void) {{ test_f(); }} """.format(src2.path, hdr.path) self.files = [(hdr, hdr_content), (src1, src1_content), (src2, src2_content)]
def define_qemu_2_6_5_types(): add_base_types() define_only_qemu_2_6_0_types() if get_vp("char backend hotswap handler"): Header["chardev/char-fe.h"].add_type( Function("BackendChangeHandler", ret_type=Type["int"], args=[Type["void"].gen_var("opaque", pointer=True)]))
def gen_register_types_fn(self, *infos): fn = Function(name=self.gen_register_types_name(), body=BodyTree()(*[ Call(Type["type_register_static"], OpAddr(info)) for info in infos ]), static=True) return fn
def timer_gen_cb(self, index, source, state_struct, type_cast_macro): timer_cb = Function(name=self.timer_cb_name(index), body="""\ __attribute__((unused))@b%s@b*s@b=@s%s(opaque); """ % (state_struct.name, self.type_cast_macro.name), args=[Pointer(Type["void"])("opaque")], static=True, used_types=set([state_struct, type_cast_macro])) source.add_type(timer_cb) return timer_cb
def define_msi_init_2_6_0(): Header["hw/pci/msi.h"].add_type( Function("msi_init", ret_type=Type["int"], args=[ Type["PCIDevice"].gen_var("dev", pointer=True), Type["uint8_t"].gen_var("offset"), Type["unsigned int"].gen_var("nr_vectors"), Type["bool"].gen_var("msi64bit"), Type["bool"].gen_var("msi_per_vector_mask") ]))
def define_msi_init_2_6_0(): Header.lookup("hw/pci/msi.h").add_type( Function(name="msi_init", ret_type=Type.lookup("int"), args=[ Type.lookup("PCIDevice").gen_var("dev", pointer=True), Type.lookup("uint8_t").gen_var("offset"), Type.lookup("unsigned int").gen_var("nr_vectors"), Type.lookup("bool").gen_var("msi64bit"), Type.lookup("bool").gen_var("msi_per_vector_mask") ]))
def gen_register_types_fn(self, *infos): body = "" for info in infos: body += " type_register_static(&%s);\n" % info.name fn = Function(name=self.gen_register_types_name(), body=body, static=True, used_types=[Type.lookup("type_register_static")], used_globals=list(infos)) return fn
def define_msi_init_2_6_5(): Header["hw/pci/msi.h"].add_type( Function(name="msi_init", ret_type=Type["int"], args=[ Pointer(Type["PCIDevice"])("dev"), Type["uint8_t"]("offset"), Type["unsigned int"]("nr_vectors"), Type["bool"]("msi64bit"), Type["bool"]("msi_per_vector_mask"), Pointer(Pointer(Type["Error"]))("errp") ]))
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 gen_instance_init_fn(self, state_struct, code = "", s_is_used = False, used_types = [], used_globals = [] ): type_cast_macro = Type.lookup(self.qtn.for_macros) total_used_types = set([state_struct, type_cast_macro]) total_used_types.update(used_types) if self.timer_num > 0: total_used_types.update([ Type.lookup("QEMU_CLOCK_VIRTUAL"), Type.lookup("timer_new_ns") ]) s_is_used = True code += "\n" for timerN in range(self.timer_num): cb = self.timer_gen_cb(timerN, self.source, state_struct, self.type_cast_macro ) total_used_types.add(cb) code += """\ s->%s@b=@stimer_new_ns(@aQEMU_CLOCK_VIRTUAL,@s%s,@ss); """ % (self.timer_name(timerN), cb.name, ) fn = Function( name = self.gen_instance_init_name(), body = """\ {used}{Struct}@b*s@b=@s{UPPER}(obj); {extra_code}\ """.format( Struct = state_struct.name, UPPER = type_cast_macro.name, extra_code = code, used = "" if s_is_used else "__attribute__((unused))@b" ), static = True, args = [ Type.lookup("Object").gen_var("obj", pointer = True) ], used_types = total_used_types, used_globals = used_globals ) return fn
def _parse(self): funclines = {} source = None with open(self.filename) as f: for line in f: line = line.strip() if line == 'end_of_record': if source is not None: directory, filename = os.path.split(source.filename) self.sources[directory][filename] = source source = None else: key, argstr = tuple(line.split(':')) args = argstr.split(',') if key == 'SF': fname = args[0] if fname.startswith(self.basepath): source = Source(args[0]) else: source = None elif source is not None: if key == 'FN': name = args[1] funclines[name] = int(args[0]) elif key == 'FNDA': hits = int(args[0]) name = args[1] func = Function(funclines[name], name, hits) source.add_function(func) elif key == 'BRDA': line = int(args[0]) path = int(args[2]) hits = 0 if args[3] == '-' else int(args[3]) source.add_branch(Branch(line, path, hits)) elif key == 'DA': line = int(args[0]) hits = int(args[1]) source.add_line(Line(line, hits))
def setUp(self): super(TestEnumerations, self).setUp() name = type(self).__name__ try: h = Header["enums.h"] except: h = Header("enums.h") h.add_type(Enumeration("A", [("one", 1), ("two", 2)])) a = Type["int"]("a") b = Type["int"]("b") c = Type["int"]("c") src = Source(name.lower() + ".c").add_types([ Enumeration("B", [("three", 3), ("four", 4)], "B"), Function(name="main", body=BodyTree()(Declare(a, b, c), OpAssign(a, Type["A"].one), OpAssign(b, Type["B"].three), OpAssign(c, Type["four"]))) ]) src_content = """\ /* {} */ #include "enums.h" enum B {{ three = 3, four = 4 }}; void main(void) {{ int a, b, c; a = one; b = three; c = four; }} """.format(src.path) self.files = [(src, src_content)]
def fill_source(self): """ Adds a hook callback in MMIO read handler. """ super(CustomSBDType, self).fill_source() # Now, code of device's module is generated. It's time to patch it! # Assuming, your code uses functions and types from your header. custom_h = Header("custom-api.h", is_global=True) # If your header is inside Qemu source tree and under Git, then you # likely should write above statement as follows: # # custom_h = Header["custom/custom-api.h"] # # Because the header is already registered. # To use custom functions (and other things) you must declare them. # Note that, macros are added automatically if header is inside Qemu # source tree. # Only name is sufficient because no code will be generated for them. custom_h.add_types([Function("custom_callback")]) read_func = self.find_mmio_read_helper(0) # We are going to pass second and following argument values of the # read helper to the custom callback. # Of course, you can made different choice in your code. args2callback = read_func.args[1:] # Insert function call statement before 3-nd statement. # Note, first statements are likely variable declarations. # This is for prettiness only. read_func.body.children.insert(2, Call("custom_callback", *args2callback))
def gen_realize(self, dev_type_name, code = "", s_is_used = False, used_types = [], used_globals = [] ): total_used_types = set([self.state_struct, self.type_cast_macro]) total_used_types.update(used_types) total_used_globals = list(used_globals) if self.char_num > 0: if get_vp()["v2.8 chardev"]: helper_name = "qemu_chr_fe_set_handlers" char_name_fmt = "&s->%s" extra_args = ",@sNULL,@strue" else: helper_name = "qemu_chr_add_handlers" char_name_fmt = "s->%s" extra_args = "" total_used_types.add(Type[helper_name]) code += "\n" s_is_used = True for chrN in range(self.char_num): chr_name = self.char_name(chrN) har_handlers = self.char_gen_handlers(chrN, self.source, self.state_struct, self.type_cast_macro ) code += """\ if@b({chr_name})@b{{ {helper_name}(@a{chr_name},@s{helpers},@ss{extra_args}); }} """.format( helper_name = helper_name, chr_name = char_name_fmt % chr_name, helpers = ",@s".join([h.name for h in har_handlers]), extra_args = extra_args ) total_used_types.update(har_handlers) if self.block_num > 0: code += "\n" s_is_used = True # actually not, but user probably needed functions from same header total_used_types.add(Type["BlockDevOps"]) for blkN in range(self.block_num): blk_name = self.block_name(blkN) code += """\ if@b(s->%s)@b{ /*@sTODO:@sImplement@sinteraction@swith@sblock@sdriver.@c@s*/ } """ % (blk_name ) if self.nic_num > 0: code += "\n" s_is_used = True def_mac = Type["qemu_macaddr_default_if_unset"] fmt_info = Type["qemu_format_nic_info_str"] obj_tn = Type["object_get_typename"] obj_cast = Type["OBJECT"] def_cast = Type["DEVICE"] new_nic = Type["qemu_new_nic"] get_queue = Type["qemu_get_queue"] total_used_types.update([def_mac, fmt_info, obj_tn, obj_cast, def_cast, new_nic, get_queue ]) for nicN in range(self.nic_num): conf_name = self.nic_conf_name(nicN) nic_name = self.nic_name(nicN) info = self.gen_net_client_info(nicN) self.source.add_global_variable(info) total_used_globals.append(info) code += """\ {def_mac}(&s->{conf_name}.macaddr); s->{nic_name}@b=@s{new_nic}(@a&{info},@s&s->{conf_name},@s{obj_tn}\ ({obj_cast}(s)),@s{def_cast}(s)->id,@ss); {fmt_info}(@a{get_queue}(s->{nic_name}),@ss->{conf_name}.macaddr.a); """.format( def_mac = def_mac.name, conf_name = conf_name, nic_name = nic_name, new_nic = new_nic.name, info = info.name, obj_tn = obj_tn.name, obj_cast = obj_cast.name, def_cast = def_cast.name, fmt_info = fmt_info.name, get_queue = get_queue.name ) fn = Function( name = "%s_realize" % self.qtn.for_id_name, body = """\ {unused}{Struct}@b*s@b=@s{UPPER}(dev); {extra_code}\ """.format( unused = "" if s_is_used else "__attribute__((unused))@b", Struct = self.state_struct.name, UPPER = self.type_cast_macro.name, extra_code = code ), args = [ Pointer(Type[dev_type_name])("dev"), Pointer(Pointer(Type["Error"]))("errp") ], static = True, used_types = total_used_types, used_globals = total_used_globals ) return fn
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) )
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 define_only_qemu_2_6_0_types(): # According to Qemu inclusion policy, each source file must include # qemu/osdep.h. This could be met using different ways. For now add a # reference to a fake type inside osdep.h. # TODO: the tweak must be handled using version API. osdep_fake_type = Type("FAKE_TYPE_IN_QEMU_OSDEP") if not get_vp("tcg_enabled is macro"): Header.lookup("qemu-common.h").add_types( [Function("tcg_enabled", ret_type=Type.lookup("bool"))]) Header.lookup("tcg.h").add_types([ Type("TCGv_i32"), Type("TCGv_i64"), Type("TCGv_ptr"), Type("TCGv_env"), Type("TCGv"), Function("tcg_global_mem_new_i32"), Function("tcg_global_mem_new_i64"), Function("tcg_op_buf_full") ]) Header.lookup("tcg-op.h").add_types([ Function("tcg_gen_insn_start"), Function("tcg_gen_goto_tb"), Function("tcg_gen_exit_tb") ]) Header.lookup("tcg-op.h").add_types([ # HLTTemp is a fake type intended to mark # variables which are to be replaced by this tool # preprocessor (still in progress) # HLTTemp is then converted to some existing QEMU types Type("HLTTemp") ]) Header.lookup("qemu/osdep.h").add_types([osdep_fake_type]) Header.lookup("exec/hwaddr.h").add_types([Type("hwaddr", False) ]).add_reference(osdep_fake_type) Header.lookup("exec/cpu-defs.h").add_types([ Type("target_ulong", False), ]) Header.lookup("exec/cpu_ldst.h").add_types([ Function("cpu_ldub_code", ret_type=Type.lookup("uint8_t")), Function("cpu_lduw_code", ret_type=Type.lookup("uint16_t")), Function("cpu_ldl_code", ret_type=Type.lookup("uint32_t")), Function("cpu_ldq_code", ret_type=Type.lookup("uint64_t")), ]) Header.lookup("qom/object.h").add_types([ Type("ObjectClass", False), Type("Object", False), Structure( "TypeInfo", fields=[ # These are required fields only Pointer(Type.lookup("const char")).gen_var("name"), Pointer(Type.lookup("const char")).gen_var("parent"), Pointer(Type.lookup("void")).gen_var("class_init") ]), Type("Type", False), Type("TypeImpl", False), Function(name="type_register_static", ret_type=Type.lookup("TypeImpl"), args=[Type.lookup("TypeInfo").gen_var("info", pointer=True)]), Function(name="type_register", ret_type=Type.lookup("TypeImpl"), args=[Type.lookup("TypeInfo").gen_var("info", pointer=True)]), Function("object_get_typename"), Function("object_property_set_str"), Function("object_property_set_link"), Function("object_property_set_bool"), Function("object_property_set_int"), Function("object_class_by_name"), Function("object_class_dynamic_cast"), Function("object_class_is_abstract") ]).add_reference(osdep_fake_type) Header.lookup("qom/cpu.h").add_types([ Type("CPUState", False), Type("CPUClass", False), Type("vaddr", False), Type("MMUAccessType", False), Type("CPUBreakpoint", False), Function("qemu_init_vcpu", args=[Type.lookup("CPUState").gen_var("cpu", pointer=True)]), Function("cpu_exec_realizefn"), Function("cpu_reset"), Function("cpu_generic_init") ]).add_reference(osdep_fake_type) Header.lookup("qapi/error.h").add_types([Type("Error") ]).add_reference(osdep_fake_type) Header.lookup("disas/bfd.h").add_types([Type("disassemble_info", False) ]).add_reference(osdep_fake_type) Header.lookup("qemu/fprintf-fn.h").add_types( [Type("fprintf_function", False)]).add_reference(osdep_fake_type) Header.lookup("exec/exec-all.h").add_types([ Type("TranslationBlock", False), Function("tlb_fill", args=[ Type.lookup("CPUState").gen_var("cs", pointer=True), Type.lookup("target_ulong").gen_var("addr"), Type.lookup("MMUAccessType").gen_var("access_type"), Type.lookup("int").gen_var("mmu_idx"), Type.lookup("uintptr_t").gen_var("retaddr") ], used_types=[]), Function("cpu_exec_init", args=[ Type.lookup("CPUState").gen_var("cs", pointer=True), Pointer(Pointer(Type.lookup("Error"))).gen_var("errp") ]), Function("gen_intermediate_code"), Function("cpu_restore_state"), Function("cpu_loop_exit"), Function("cpu_loop_exit_restore"), Function("tlb_set_page") ]).add_reference(osdep_fake_type) Header.lookup("exec/gen-icount.h").add_types( [Function("gen_tb_start"), Function("gen_tb_end")]) Header.lookup("exec/address-spaces.h").add_types( [Function("get_system_memory")]).add_reference(osdep_fake_type) Header.lookup("exec/memory.h").add_types([ Type("MemoryRegion", False), Function(name="MemoryRegionOps_read", ret_type=Type.lookup("uint64_t"), args=[ Type.lookup("void").gen_var("opaque", pointer=True), Type.lookup("hwaddr").gen_var("offset"), Type.lookup("unsigned").gen_var("size") ]), Function(name="MemoryRegionOps_write", ret_type=Type.lookup("void"), args=[ Type.lookup("void").gen_var("opaque", pointer=True), Type.lookup("hwaddr").gen_var("offset"), Type.lookup("uint64_t").gen_var("value"), Type.lookup("unsigned").gen_var("size") ]), Structure("MemoryRegionOps", [ Type.lookup("MemoryRegionOps_read").gen_var("read"), Type.lookup("MemoryRegionOps_write").gen_var("write"), ]), Function( name="memory_region_init_io", args=[ Type.lookup("MemoryRegion").gen_var("mr", pointer=True), # struct Type.lookup("Object").gen_var("owner", pointer=True), # const Type.lookup("MemoryRegionOps").gen_var("ops", pointer=True), Type.lookup("void").gen_var("opaque", pointer=True), Type.lookup("const char").gen_var("name", pointer=True), Type.lookup("uint64_t").gen_var("size") ]), Function("memory_region_init"), Function("memory_region_init_alias"), Function("memory_region_init_ram"), Function("memory_region_add_subregion_overlap"), Function("memory_region_add_subregion") ]).add_reference(osdep_fake_type) Header.lookup("exec/gdbstub.h").add_types([ Function(name="gdb_get_reg8"), Function(name="gdb_get_reg16"), Function(name="gdb_get_reg32"), Function(name="gdb_get_reg64") ]).add_reference(osdep_fake_type) Header.lookup("exec/ioport.h").add_types( [Type("pio_addr_t", incomplete=False)]).add_reference(osdep_fake_type) Header.lookup("hw/boards.h").add_types( [Structure("MachineClass"), Structure("MachineState")]).add_reference(osdep_fake_type) Header.lookup("hw/sysbus.h").add_types([ Type("SysBusDevice", False), Type("qemu_irq", False), Function(name="sysbus_init_mmio", ret_type=Type.lookup("void"), args=[ Type.lookup("SysBusDevice").gen_var("dev", pointer=True), Type.lookup("MemoryRegion").gen_var("memory", pointer=True) ]), Function(name="sysbus_init_irq", ret_type=Type.lookup("void"), args=[ Type.lookup("SysBusDevice").gen_var("dev", pointer=True), Type.lookup("qemu_irq").gen_var("p", pointer=True) ]), Function(name="sysbus_add_io", ret_type=Type.lookup("void"), args=[ Type.lookup("SysBusDevice").gen_var("dev", pointer=True), Type.lookup("hwaddr").gen_var("addr"), Type.lookup("MemoryRegion").gen_var("mem", pointer=True) ]), Function(name="sysbus_init_ioports", ret_type=Type.lookup("void"), args=[ Type.lookup("SysBusDevice").gen_var("dev", pointer=True), Type.lookup("pio_addr_t").gen_var("dev"), Type.lookup("pio_addr_t").gen_var("dev") ]), Function("sysbus_mmio_map"), Function("sysbus_connect_irq") ]).add_reference(osdep_fake_type) Header.lookup("hw/irq.h").add_types([ Function(name="qemu_irq_handler", ret_type=Type.lookup("void"), args=[ Type.lookup("void").gen_var("opaque", pointer=True), Type.lookup("int").gen_var("n"), Type.lookup("int").gen_var("level") ]), Function("qemu_irq_split") ]).add_reference(osdep_fake_type) Header.lookup("hw/qdev-core.h").add_types([ Type("DeviceClass", False), Type("DeviceState", False), Type("Property", False), Function(name="qdev_init_gpio_in", ret_type=Type.lookup("void"), args=[ Type.lookup("DeviceState").gen_var("dev", pointer=True), Type.lookup("qemu_irq_handler").gen_var("handler"), Type.lookup("int").gen_var("n") ]), Pointer( Function(name="device_realize pointee", args=[ Type.lookup("DeviceState").gen_var("dev", pointer=True), Pointer(Type.lookup("Error")).gen_var("errp", pointer=True) ]), name="DeviceRealize", ), Function(name="qdev_create"), Function(name="qdev_init_nofail"), Function(name="qdev_get_child_bus"), Structure(name="BusState"), Function(name="qdev_get_gpio_in"), Function(name="qdev_get_gpio_in_named"), Function(name="qdev_connect_gpio_out"), Function(name="qdev_connect_gpio_out_named") ]).add_reference(osdep_fake_type) Header.lookup("migration/vmstate.h").add_types([ Type("VMStateDescription", False), Type("VMStateField", False), Function("vmstate_register_ram_global") ]).add_reference(osdep_fake_type) Header.lookup("qemu/module.h").add_reference(osdep_fake_type) Header.lookup("hw/pci/pci.h").add_types([ Type("PCIDevice", False), Type("PCIDeviceClass", False), Function("pci_create_multifunction"), Type("PCIIOMMUFunc"), ]).add_reference(osdep_fake_type) Header.lookup("hw/pci/msi.h").add_types([ Function(name="msi_uninit", ret_type=Type.lookup("void"), args=[Type.lookup("PCIDevice").gen_var("dev", pointer=True)]) ]).add_reference(osdep_fake_type) Header.lookup("hw/pci/pci_bus.h").add_types([ Type("PCIBus", incomplete=True) ]).add_references([Type.lookup("PCIIOMMUFunc"), osdep_fake_type]) Header.lookup("hw/pci/pci_host.h").add_reference(osdep_fake_type) Header.lookup("qemu/typedefs.h").add_types([ # BlockBackend is defined in internal block_int.h. Its fields may not # be accessed outside internal code. Methods from block-backend.h must # be used instead. Structure("BlockBackend"), Structure("I2CBus") # the structure is defined in .c file ]).add_reference(osdep_fake_type) Header.lookup("qemu/bswap.h").add_types( [Function("bswap64"), Function("bswap32"), Function("bswap16")]).add_reference(osdep_fake_type) Header.lookup("hw/ide/internal.h").add_types( [Structure("IDEDMA")]).add_reference(osdep_fake_type) Header.lookup("hw/ide/ahci.h").add_references( [Type.lookup("IDEDMA"), osdep_fake_type]) Header.lookup("hw/block/flash.h").add_references( [Type.lookup("VMStateDescription"), osdep_fake_type]) Header.lookup("qemu/timer.h").add_types([ Structure("QEMUTimer"), Function("timer_new_ns"), Function("timer_del"), Function("timer_free"), Type("QEMU_CLOCK_VIRTUAL") # It is enumeration entry... ]).add_references([osdep_fake_type]) Header.lookup("qemu/main-loop.h").add_types([ Function("IOCanReadHandler", ret_type=Type.lookup("int"), args=[Pointer(Type.lookup("void")).gen_var("opaque")]), Function("IOReadHandler", args=[ Pointer(Type.lookup("void")).gen_var("opaque"), Pointer(Type.lookup("uint8_t"), const=True).gen_var("buf"), Type.lookup("int").gen_var("size") ]) ]).add_references([osdep_fake_type]) if get_vp()["v2.8 chardev"]: chardev_types = [ Function("qemu_chr_fe_set_handlers"), Structure("CharBackend") ] else: chardev_types = [ Function("qemu_chr_add_handlers"), Structure("CharDriverState") ] Header.lookup(get_vp("header with IOEventHandler")).add_types([ Function("IOEventHandler", args=[ Pointer(Type.lookup("void")).gen_var("opaque"), Type.lookup("int").gen_var("event") ]) ] + chardev_types).add_references([osdep_fake_type]) Header.lookup("sysemu/block-backend.h").add_types([ Structure("BlockDevOps"), ]).add_references([osdep_fake_type]) Header.lookup("hw/isa/isa.h").add_types([Type("IsaDmaTransferHandler")]) if get_vp()["include/hw/isa/i8257.h have IsaDmaTransferHandler reference"]: Header.lookup(get_vp()["i8257.h path"]).add_references([ Type.lookup("IsaDmaTransferHandler"), Type.lookup("MemoryRegion") ]) Header.lookup("net/net.h").add_types([ Type("qemu_macaddr_default_if_unset"), Type("qemu_format_nic_info_str"), Type("qemu_new_nic"), Type("qemu_del_nic"), Type("qemu_get_queue"), Structure("NICConf"), Type("NICState"), Type("NetClientState"), Function("NetCanReceive", ret_type=Type.lookup("int"), args=[Pointer(Type.lookup("NetClientState")).gen_var("nc")]), Function("NetReceive", ret_type=Type.lookup("ssize_t"), args=[ Pointer(Type.lookup("NetClientState")).gen_var("nc"), Pointer(Type.lookup("const uint8_t")).gen_var("buf"), Type.lookup("size_t").gen_var("size") ]), Function("LinkStatusChanged", args=[Pointer(Type.lookup("NetClientState")).gen_var("nc")]), Function("NetCleanup", args=[Pointer(Type.lookup("NetClientState")).gen_var("nc")]), Structure( "NetClientInfo", fields=[ # "type" field type is enum NetClientDriver, but enum is not # supported by model Type.lookup("int").gen_var("type"), Type.lookup("size_t").gen_var("size"), Type.lookup("NetReceive").gen_var("receive"), Type.lookup("NetCanReceive").gen_var("can_receive"), Type.lookup("NetCleanup").gen_var("cleanup"), Type.lookup("LinkStatusChanged").gen_var("link_status_changed") # There are other fields but they are not needed. ]), Macro("NET_CLIENT_DRIVER_NIC") # This is an enum item actually. It # is defined in auto generated "qapi-types.h" which is not presented in # registry but is included by "net.h" indirectly. ]).add_references([osdep_fake_type]) Header.lookup("exec/helper-proto.h").add_type(Macro("HELPER_PROTO_H")) Header.lookup("disas/bfd.h").add_types([ Type("bfd_vma", False), Type("bfd_byte", False), Type("const bfd_tyte", False), Function("bfd_getl64", ret_type=Type.lookup("bfd_vma"), args=[ Pointer(Type.lookup("const bfd_tyte")).gen_var( "addr", pointer=True) ]), Function("bfd_getl32", ret_type=Type.lookup("bfd_vma"), args=[ Pointer(Type.lookup("const bfd_tyte")).gen_var( "addr", pointer=True) ]), Function("bfd_getb32", ret_type=Type.lookup("bfd_vma"), args=[ Pointer(Type.lookup("const bfd_tyte")).gen_var( "addr", pointer=True) ]), Function("bfd_getl16", ret_type=Type.lookup("bfd_vma"), args=[ Pointer(Type.lookup("const bfd_tyte")).gen_var( "addr", pointer=True) ]), Function("bfd_getb16", ret_type=Type.lookup("bfd_vma"), args=[ Pointer(Type.lookup("const bfd_tyte")).gen_var( "addr", pointer=True) ]) ]) Header.lookup("disas/disas.h").add_types([Function("lookup_symbol")]) Header.lookup("qemu/log.h").add_types([ Function("qemu_loglevel_mask"), Function("qemu_log_in_addr_range"), Function("qemu_log_lock"), Function("qemu_log_unlock"), Function("qemu_log") ]) Header.lookup("exec/log.h").add_types([Function("log_target_disas")])
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 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)
def setUp(self): super(TestEnumerations, self).setUp() name = type(self).__name__ try: h = Header["enums.h"] except: h = Header("enums.h") h.add_type(Enumeration([("EXT", 1)])) src = Source(name.lower() + ".c").add_types([ Enumeration([("ONE", 1)]), Enumeration([("TWO", 2)], enum_name="A"), Enumeration([("THREE", 3)], typedef_name="B"), Enumeration([("FOUR", 4)], enum_name="C", typedef_name="D") ]) a = Type["int"]("a") b = Type["int"]("b") c = Type["A"]("c") d = Type["B"]("d") e = Type["D"]("e") src.add_types([ Function(name="main", body=BodyTree()(Declare(a, b), OpAssign(a, Type["EXT"]), OpAssign(b, Type["ONE"]), Declare(c), OpAssign(c, Type["TWO"]), Declare(d), OpAssign(d, Type["THREE"]), Declare(e), OpAssign(e, Type["FOUR"]))) ]) src_content = """\ /* {} */ #include "enums.h" enum A {{ TWO = 2 }}; typedef enum {{ THREE = 3 }} B; typedef enum C {{ FOUR = 4 }} D; enum {{ ONE = 1 }}; void main(void) {{ int a, b; a = EXT; b = ONE; enum A c; c = TWO; B d; d = THREE; D e; e = FOUR; }} """.format(src.path) self.files = [(src, src_content)]
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()