| 
20 | 20 |     QuantDtype,  | 
21 | 21 |     TestQNN,  | 
22 | 22 |     to_backend,  | 
 | 23 | +    validate_context_binary,  | 
 | 24 | +    validate_qcir,  | 
23 | 25 | )  | 
24 | 26 | from executorch.backends.qualcomm.utils.constants import (  | 
25 | 27 |     QCOM_ANNOTATION,  | 
 | 
30 | 32 | 
 
  | 
31 | 33 | from executorch.backends.qualcomm.utils.utils import (  | 
32 | 34 |     capture_program,  | 
 | 35 | +    dump_context_from_pte,  | 
33 | 36 |     from_context_binary,  | 
34 | 37 |     generate_htp_compiler_spec,  | 
35 | 38 |     generate_multi_graph_program,  | 
36 | 39 |     generate_qnn_executorch_compiler_spec,  | 
 | 40 | +    PyQnnManagerAdaptor,  | 
37 | 41 |     skip_annotation,  | 
38 | 42 |     update_spill_fill_size,  | 
39 | 43 | )  | 
@@ -2041,6 +2045,81 @@ def test_qnn_backend_context_direct(self):  | 
2041 | 2045 |                 bundle_program["edge_program_manager"].to_executorch(),  | 
2042 | 2046 |             )  | 
2043 | 2047 | 
 
  | 
 | 2048 | +    def test_qnn_backend_context_extraction(self):  | 
 | 2049 | +        from executorch.exir import EdgeCompileConfig, EdgeProgramManager  | 
 | 2050 | + | 
 | 2051 | +        module = SimpleModel()  # noqa: F405  | 
 | 2052 | +        sample_input = (torch.ones(1, 32, 28, 28), torch.ones(1, 32, 28, 28))  | 
 | 2053 | +        backend_options = generate_htp_compiler_spec(use_fp16=True)  | 
 | 2054 | +        compiler_specs = [  | 
 | 2055 | +            self.compiler_specs,  | 
 | 2056 | +            generate_qnn_executorch_compiler_spec(  | 
 | 2057 | +                soc_model=self.chipset_table[TestQNN.model],  | 
 | 2058 | +                backend_options=backend_options,  | 
 | 2059 | +                online_prepare=True,  | 
 | 2060 | +            ),  | 
 | 2061 | +        ]  | 
 | 2062 | +        validators = [validate_context_binary, validate_qcir]  | 
 | 2063 | + | 
 | 2064 | +        for compiler_spec, validate in zip(compiler_specs, validators):  | 
 | 2065 | +            edge_prog_mgr = EdgeProgramManager(  | 
 | 2066 | +                edge_programs={  | 
 | 2067 | +                    "forward": capture_program(module, sample_input).exported_program  | 
 | 2068 | +                },  | 
 | 2069 | +                compile_config=EdgeCompileConfig(_use_edge_ops=False),  | 
 | 2070 | +            ).to_backend(QnnPartitioner(compiler_spec))  | 
 | 2071 | +            lowered_module = edge_prog_mgr.exported_program().graph_module._modules[  | 
 | 2072 | +                "lowered_module_0"  | 
 | 2073 | +            ]  | 
 | 2074 | +            qnn_mgr = PyQnnManagerAdaptor.QnnManager(  | 
 | 2075 | +                lowered_module.compile_specs[0].value  | 
 | 2076 | +            )  | 
 | 2077 | +            qnn_mgr.Init()  | 
 | 2078 | +            binary = qnn_mgr.StripProtocol(lowered_module.processed_bytes)  | 
 | 2079 | +            validate(binary)  | 
 | 2080 | + | 
 | 2081 | +    def test_qnn_backend_dump_context_from_pte(self):  | 
 | 2082 | +        from executorch.exir import EdgeCompileConfig, EdgeProgramManager  | 
 | 2083 | + | 
 | 2084 | +        module = SimpleModel()  # noqa: F405  | 
 | 2085 | +        sample_input = (torch.ones(1, 32, 28, 28), torch.ones(1, 32, 28, 28))  | 
 | 2086 | +        backend_options = generate_htp_compiler_spec(use_fp16=True)  | 
 | 2087 | +        compiler_specs = [  | 
 | 2088 | +            self.compiler_specs,  | 
 | 2089 | +            generate_qnn_executorch_compiler_spec(  | 
 | 2090 | +                soc_model=self.chipset_table[TestQNN.model],  | 
 | 2091 | +                backend_options=backend_options,  | 
 | 2092 | +                online_prepare=True,  | 
 | 2093 | +            ),  | 
 | 2094 | +        ]  | 
 | 2095 | +        validators = [validate_context_binary, validate_qcir]  | 
 | 2096 | + | 
 | 2097 | +        for compiler_spec, validate in zip(compiler_specs, validators):  | 
 | 2098 | +            edge_prog_mgr = (  | 
 | 2099 | +                EdgeProgramManager(  | 
 | 2100 | +                    edge_programs={  | 
 | 2101 | +                        "forward": capture_program(  | 
 | 2102 | +                            module, sample_input  | 
 | 2103 | +                        ).exported_program  | 
 | 2104 | +                    },  | 
 | 2105 | +                    compile_config=EdgeCompileConfig(_use_edge_ops=False),  | 
 | 2106 | +                )  | 
 | 2107 | +                .to_backend(QnnPartitioner(compiler_spec))  | 
 | 2108 | +                .to_executorch()  | 
 | 2109 | +            )  | 
 | 2110 | + | 
 | 2111 | +            with tempfile.TemporaryDirectory() as tmp_dir:  | 
 | 2112 | +                pte_path = f"{tmp_dir}/model.pte"  | 
 | 2113 | +                with open(pte_path, "wb") as f:  | 
 | 2114 | +                    edge_prog_mgr.write_to_file(f)  | 
 | 2115 | + | 
 | 2116 | +                dump_context_from_pte(pte_path)  | 
 | 2117 | +                binary_name = f"{tmp_dir}/forward_0.bin"  | 
 | 2118 | +                self.assertTrue(os.path.isfile(binary_name))  | 
 | 2119 | +                with open(binary_name, "rb") as f:  | 
 | 2120 | +                    stripped_binary = f.read()  | 
 | 2121 | +                    validate(stripped_binary)  | 
 | 2122 | + | 
2044 | 2123 |     def test_qnn_backend_draw_graph(self):  | 
2045 | 2124 |         golden_data = """digraph test {  | 
2046 | 2125 |             rankdir=TB  | 
@@ -2433,7 +2512,7 @@ def test_qnn_backend_multi_graphs(self):  | 
2433 | 2512 |             for module, sample_input in zip(modules, sample_inputs)  | 
2434 | 2513 |         ]  | 
2435 | 2514 |         backend_options = generate_htp_compiler_spec(  | 
2436 |  | -            use_fp16=True,  | 
 | 2515 | +            use_fp16=False,  | 
2437 | 2516 |         )  | 
2438 | 2517 |         compiler_specs = [  | 
2439 | 2518 |             generate_qnn_executorch_compiler_spec(  | 
@@ -2532,6 +2611,83 @@ def test_qnn_backend_context_direct(self):  | 
2532 | 2611 |                 bundle_program["edge_program_manager"].to_executorch(),  | 
2533 | 2612 |             )  | 
2534 | 2613 | 
 
  | 
 | 2614 | +    def test_qnn_backend_context_extraction(self):  | 
 | 2615 | +        from executorch.exir import EdgeCompileConfig, EdgeProgramManager  | 
 | 2616 | + | 
 | 2617 | +        module = SimpleModel()  # noqa: F405  | 
 | 2618 | +        sample_input = (torch.ones(1, 32, 28, 28), torch.ones(1, 32, 28, 28))  | 
 | 2619 | +        module = self.get_qdq_module(module, sample_input)  | 
 | 2620 | +        backend_options = generate_htp_compiler_spec(use_fp16=False)  | 
 | 2621 | +        compiler_specs = [  | 
 | 2622 | +            self.compiler_specs,  | 
 | 2623 | +            generate_qnn_executorch_compiler_spec(  | 
 | 2624 | +                soc_model=self.chipset_table[TestQNN.model],  | 
 | 2625 | +                backend_options=backend_options,  | 
 | 2626 | +                online_prepare=True,  | 
 | 2627 | +            ),  | 
 | 2628 | +        ]  | 
 | 2629 | +        validators = [validate_context_binary, validate_qcir]  | 
 | 2630 | + | 
 | 2631 | +        for compiler_spec, validate in zip(compiler_specs, validators):  | 
 | 2632 | +            edge_prog_mgr = EdgeProgramManager(  | 
 | 2633 | +                edge_programs={  | 
 | 2634 | +                    "forward": capture_program(module, sample_input).exported_program  | 
 | 2635 | +                },  | 
 | 2636 | +                compile_config=EdgeCompileConfig(_use_edge_ops=False),  | 
 | 2637 | +            ).to_backend(QnnPartitioner(compiler_spec))  | 
 | 2638 | +            lowered_module = edge_prog_mgr.exported_program().graph_module._modules[  | 
 | 2639 | +                "lowered_module_0"  | 
 | 2640 | +            ]  | 
 | 2641 | +            qnn_mgr = PyQnnManagerAdaptor.QnnManager(  | 
 | 2642 | +                lowered_module.compile_specs[0].value  | 
 | 2643 | +            )  | 
 | 2644 | +            qnn_mgr.Init()  | 
 | 2645 | +            binary = qnn_mgr.StripProtocol(lowered_module.processed_bytes)  | 
 | 2646 | +            validate(binary)  | 
 | 2647 | + | 
 | 2648 | +    def test_qnn_backend_dump_context_from_pte(self):  | 
 | 2649 | +        from executorch.exir import EdgeCompileConfig, EdgeProgramManager  | 
 | 2650 | + | 
 | 2651 | +        module = SimpleModel()  # noqa: F405  | 
 | 2652 | +        sample_input = (torch.ones(1, 32, 28, 28), torch.ones(1, 32, 28, 28))  | 
 | 2653 | +        module = self.get_qdq_module(module, sample_input)  | 
 | 2654 | +        backend_options = generate_htp_compiler_spec(use_fp16=True)  | 
 | 2655 | +        compiler_specs = [  | 
 | 2656 | +            self.compiler_specs,  | 
 | 2657 | +            generate_qnn_executorch_compiler_spec(  | 
 | 2658 | +                soc_model=self.chipset_table[TestQNN.model],  | 
 | 2659 | +                backend_options=backend_options,  | 
 | 2660 | +                online_prepare=True,  | 
 | 2661 | +            ),  | 
 | 2662 | +        ]  | 
 | 2663 | +        validators = [validate_context_binary, validate_qcir]  | 
 | 2664 | + | 
 | 2665 | +        for compiler_spec, validate in zip(compiler_specs, validators):  | 
 | 2666 | +            edge_prog_mgr = (  | 
 | 2667 | +                EdgeProgramManager(  | 
 | 2668 | +                    edge_programs={  | 
 | 2669 | +                        "forward": capture_program(  | 
 | 2670 | +                            module, sample_input  | 
 | 2671 | +                        ).exported_program  | 
 | 2672 | +                    },  | 
 | 2673 | +                    compile_config=EdgeCompileConfig(_use_edge_ops=False),  | 
 | 2674 | +                )  | 
 | 2675 | +                .to_backend(QnnPartitioner(compiler_spec))  | 
 | 2676 | +                .to_executorch()  | 
 | 2677 | +            )  | 
 | 2678 | + | 
 | 2679 | +            with tempfile.TemporaryDirectory() as tmp_dir:  | 
 | 2680 | +                pte_path = f"{tmp_dir}/model.pte"  | 
 | 2681 | +                with open(pte_path, "wb") as f:  | 
 | 2682 | +                    edge_prog_mgr.write_to_file(f)  | 
 | 2683 | + | 
 | 2684 | +                dump_context_from_pte(pte_path)  | 
 | 2685 | +                binary_name = f"{tmp_dir}/forward_0.bin"  | 
 | 2686 | +                self.assertTrue(os.path.isfile(binary_name))  | 
 | 2687 | +                with open(binary_name, "rb") as f:  | 
 | 2688 | +                    stripped_binary = f.read()  | 
 | 2689 | +                    validate(stripped_binary)  | 
 | 2690 | + | 
2535 | 2691 |     def test_qnn_backend_draw_graph(self):  | 
2536 | 2692 |         golden_data = """digraph test {  | 
2537 | 2693 |             rankdir=TB  | 
 | 
0 commit comments