CoolFace
Apppublic

Synaptics/SR100-Model-Compiler

sourceHugging Faceupdated 7mo agoView on Hugging Face
0likes
app.py272 linesDownload Raw Back to root
1import glob2import gradio as gr3import tempfile4import os5import sr_model_compiler6import html7import pathlib8import spaces9 10# ---------- Helpers ----------11 12def _resolve_uploaded_path(uploaded):13    """14    Normalize Gradio File input into a filesystem path.15    Handles: str, dict with {path|name}, file-like objects with .path/.name,16    or a list/tuple of the above.17    """18    if uploaded is None:19        return None20    if isinstance(uploaded, (list, tuple)) and uploaded:21        return _resolve_uploaded_path(uploaded[0])22    if isinstance(uploaded, str):23        return uploaded24    if isinstance(uploaded, dict):25        return uploaded.get("path") or uploaded.get("name")26    for attr in ("path", "name"):27        if hasattr(uploaded, attr):28            return getattr(uploaded, attr)29    return None30 31 32@spaces.GPU33def compile_model(model_name, vmem_value, lpmem_value, uploaded_model):34    # Decide the source model path (uploaded has priority)35    uploaded_path = _resolve_uploaded_path(uploaded_model)36    model_path = uploaded_path or model_name37 38    # Basic validations39    if not model_path or not os.path.exists(model_path):40        return (41            "<div style='color:#d32f2f; font-weight:bold; font-size:1.1em;'>"42            "❌ ERROR: Could not locate the model file you selected or uploaded."43            "</div>"44        )45 46    if pathlib.Path(model_path).suffix.lower() != ".tflite":47        return (48            "<div style='color:#d32f2f; font-weight:bold; font-size:1.1em;'>"49            "❌ ERROR: Please provide a <code>.tflite</code> model file.</div>"50        )51 52    # Create a temporary directory53    with tempfile.TemporaryDirectory() as out_dir:54        print(f"Created temporary directory: {out_dir}")55 56        vmem_size_limit = int(vmem_value * 1000)57        lpmem_size_limit = int(lpmem_value * 1000)58        59        # Run the model fitter with better error handling60        try:61            original_file_name = os.path.basename(model_path)62            root, ext = os.path.splitext(original_file_name)63            safe_root = root.replace('.', '_')  64            model_file_name = f"{safe_root}{ext}"65            temp_model_path = os.path.join(out_dir, model_file_name)66            67            print(f"Copying model to sanitized path: {temp_model_path}")68            with open(model_path, "rb") as src, open(temp_model_path, "wb") as dst:69                dst.write(src.read())70            71            print(f"Starting model optimization for {temp_model_path}")72            print(f"VMEM limit: {vmem_size_limit}, LPMEM limit: {lpmem_size_limit}")73            74            success, results = sr_model_compiler.sr100_model_optimizer(75                model_file=temp_model_path,76                vmem_size_limit=vmem_size_limit,77                lpmem_size_limit=lpmem_size_limit,78                optimize='Performance'79            )80            81            print(f"Optimization complete. Success: {success}")82            print(f"Results: {results}")83            84            # Check if results is None or missing expected keys85            if not results:86                return (87                    "<div style='color:#d32f2f; font-weight:bold; font-size:1.2em;'>"88                    "❌ ERROR: Optimization returned empty results</div>"89                )90                91        except Exception as e:92            error_message = str(e)93            print(f"Exception during model optimization: {error_message}")94            95            return (96                "<div style='color:#d32f2f; font-weight:bold; font-size:1.2em;'>"97                "❌ ERROR: Model optimization failed</div>"98                "<div style='margin-top:0.5em;color:#000;'>Error details:</div>"99                f"<pre style='white-space:pre-wrap; background:#f6f8fa; padding:8px; border-radius:6px; color:#000;'>{html.escape(error_message)}</pre>"100            )101 102    output = []103    104    # Check for specific failure cases from results105    if not success:106        print(f"Optimization reported failure. Reason: {results.get('failure_reason', 'Unknown')}")107    108    # Check if NPU cycles is zero (CPU-only model)109    npu_zero = results.get('cycles_npu', 0) == 0110    111    if npu_zero:112        output.append(113            "<div style='color:#e65100; font-weight:bold; font-size:1.2em;'>"114            "⚠️ CPU-ONLY: Model fits in memory but no operators mapped to the NPU</div>"115        )116        output.append(117            "<div style='color:#000; margin-top:0.25em;'>"118            "This typically means the model contains ops not supported by the SR100 NPU. "119            "Please review/convert unsupported ops or choose an NPU-friendly model.</div>"120        )121        output.append("<div style='margin-top:0.5em;color:#000;'>Compiler log:</div>")122        output.append(123            f"<pre style='white-space:pre-wrap; background:#f6f8fa; padding:8px; border-radius:6px; color:#000;'>"124            f"{html.escape(results.get('vela_log', 'No log available'))}</pre>"125        )126    else:127        if success:128            output.append(129                "<div style='color:#007dc3; font-weight:bold; font-size:1.2em;'>"130                "✅ SUCCESS: Model fits on SR100 and below is the estimates Performance</div>"131            )132        else:133            output.append(134                "<div style='color:#d32f2f; font-weight:bold; font-size:1.2em;'>"135                "❌ FAILURE: Model does not fit on SR100, Please check Memory usage of Model</div>"136            )137 138        # Format metrics in a nice table139        table_rows = []140        141        # Calculate all the metrics142        weights_size = results['weights_size'] / 1000.0143        arena_size = results['arena_cache_size'] / 1000.0144        clock = results['core_clock'] / 1.0e6145        infer_time = results['inference_time'] * 1000.0146        infer_fps = results['inferences_per_sec']147        vmem_size = results['vmem_size'] / 1000.0148        lpmem_size = results['lpmem_size'] / 1000.0149        vmem_size_limit = results['vmem_size_limit'] / 1000.0150        lpmem_size_limit = results['lpmem_size_limit'] / 1000.0151        vmem_perc = results['vmem_size'] * 100.0 / results['vmem_size_limit']152        lpmem_perc = results['lpmem_size'] * 100.0 / results['lpmem_size_limit']153        154        # Add rows to the table155        metrics = [156            ("Clock Frequency", f"{clock:0.1f} MHz"),157            ("Inference Time", f"{infer_time:0.1f} ms"),158            ("Inferences Per Second", f"{infer_fps:0.1f} fps"),159            ("Arena Cache Size", f"{arena_size:0.3f} kB"),160            ("Model Size", f"{weights_size:0.3f} kB"),161            ("Model Location", f"{results['model_loc']}"),162            ("System Configuration", f"{results['system_config']}"),163            ("VMEM Size", f"{vmem_size:0.3f} kB ({vmem_perc:0.1f}% of {vmem_size_limit:0.3f} kB limit)"),164            ("LPMEM Size", f"{lpmem_size:0.3f} kB ({lpmem_perc:0.1f}% of {lpmem_size_limit:0.3f} kB limit)")165        ]166        167        for label, value in metrics:168            table_rows.append(169                "<tr>"170                f"<td style='padding:4px 12px; font-weight:bold; border-bottom:1px solid #eee; color:#000;'>{label}</td>"171                f"<td style='padding:4px 12px; border-bottom:1px solid #eee; color:#000;'>{value}</td>"172                "</tr>"173            )174        175        output.append(176            "<table style='margin-top:1em; border-collapse:collapse; color:#000;'>"177            + "".join(table_rows) + "</table>"178        )179 180    return "".join(output)181 182# Get all available models183model_choices = glob.glob('models/*.tflite')184 185custom_css = """186:root {187    --color-accent: #007dc3;188    --color-primary-500: #007dc3;189    --color-primary-600: #007dc3;190}191body, .gradio-container, #root {192    background: #fff !important;193}194/* Hide Gradio footer and settings */195footer, .gradio-footer, .svelte-1ipelgc, .gradio-logo, .gradio-app__settings {196    display: none !important;197}198/* Style input labels and controls */199.gradio-slider label,200.gradio-radio label,201.gradio-dropdown label,202.gradio-file label {203    color: #007dc3 !important;204    font-weight: bold;205}206.gradio-slider input[type="range"]::-webkit-slider-thumb,207.gradio-slider input[type="range"]::-moz-range-thumb,208.gradio-slider input[type="range"]::-ms-thumb {209    background: #007dc3 !important;210}211.gradio-radio input[type="radio"]:checked + span {212    background: #007dc3 !important;213    border-color: #007dc3 !important;214}215.gradio-dropdown select,216.gradio-file input[type="file"] {217    border-color: #007dc3 !important;218}219.gradio-button {220    background: #007dc3 !important;221    color: #fff !important;222    border: none !important;223}224"""225    226with gr.Blocks(css=custom_css) as demo:227    gr.Markdown("<h1 style='font-size:2.5em; color:#007dc3; margin-bottom:0;'>SR100 Model Compiler</h1>", elem_id="main_title")228    gr.Markdown("<h3 style='margin-top:0; color:#000;'>Bring a TFlite INT8 model and compile it for Synaptics Astra SR100. Learn more at <a href='https://developer.synaptics.com/docs/sr/sr100/quick-start?utm_source=hf' target='_blank' style='color:#007dc3; text-decoration:underline;'>Synaptics AI Developer Zone</a></h3>", elem_id="subtitle")229    gr.Markdown("""230    <p style='margin-top:0; color:#000; font-style:italic;'>231    SR100 includes the following on-chip SRAM memories:<br>232    - 1536 kB of Virtual Memory SRAM (VMEM) for high-speed operations.<br>233    - 1536 kB of Low Power SRAM (LPMEM) for images, audio, and other less-performance-critical data.<br><br>234    The amount of memory allocated to the model is customizable. Any memory not allocated to the model is usable by the application.<br>235    Ensure that the Arena cache size is smaller than the available VMEM to ensure it fits and runs optimally.236    </p>237    """, elem_id="memory_note"238    )239 240    with gr.Row():241        vmem_slider = gr.Slider(minimum=1, maximum=1536, step=1.024, label="Set total VMEM SRAM size available in kB", value=1536.0)242        lpmem_slider = gr.Slider(minimum=1, maximum=1536, step=1.024, label="Set total LPMEM SRAM size in kB", value=1536.0)243    244    model_dropdown = gr.Dropdown(245        label="Select a model",246        value='models/person_classification_256x448.tflite',247        choices=model_choices248    )249    250    # Add file upload component251    model_upload = gr.File(label="Or upload a .tflite INT8 model. Please note, Uploaded models are stored in a temporary directory and will be deleted automatically after processing.", file_types=[".tflite"], file_count="single")252    253    # Run the compile254    compile_btn = gr.Button("Compile Model")255    compile_text = gr.Markdown("<span style='color:#000;'>Waiting for model results</span>")256    257    # Compute options258    compile_btn.click(compile_model, inputs=[model_dropdown, vmem_slider, lpmem_slider, model_upload], outputs=[compile_text])259    260    gr.HTML("""261    <div style="max-width: 900px; margin: 2rem auto; background: white; color: black; border-radius: 12px; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); border: 1px solid #e5e7eb; padding: 1.5rem; text-align: center;">262        For a detailed walkthrough, please see our263        <a href="https://developer.synaptics.com/docs/sr/sr100/evaluate-sr?utm_source=hf" target="_blank" style="color: #1a0dab;">Evaluate Model Guide</a>.<br>264        This Space uses a simulation toolchain to estimate model performance providing results that closely reflect real hardware behavior.265        <br><br>266        Request a 267        <a href="https://synacsm.atlassian.net/servicedesk/customer/portal/543/group/597/create/7208?utm_source=hf" target="_blank" style="color: #1a0dab;">Machina Micro [MCU] Dev Kit</a> with Astra SR100 MCU.268    </div>269    """)270 271if __name__ == "__main__":272    demo.launch()