Engee documentation

Debugging a target

The general mechanism for downloading the support package is described in the article Custom Engee support packages.Integrations. This article discusses the features that are important when developing a target.

Loading a custom target

The user target is implemented as a support package. This means that he added to Engee.Integration and syncing with Engee. After that, all the necessary components should be available through the support package, library .nglib, the EDM-Target block settings and clear instructions for installing external dependencies. The user does not have to independently search or modify files in the support package repository.

The Julia support package code is the interface layer. It makes the classes and methods of the support package accessible from blocks and scripts. Engee. Python code is an implementation: it contains the class BaseTarget, project generation, build, download, launch, work with XCP, drivers, and external utilities.

Practical rules follow from this.:

  • if the body of a Python method has changed, but the method name, arguments, and return types have not changed, it is usually enough to restart the Engee client program.Integrations;

  • if a new public method has been added, the signature has been changed, the class has been renamed, or the package structure has changed, you must run again syncExtensions() as described in the section Synchronization and use of the support package in Engee;

  • if the user library has changed .nglib, you need to update the library in the session Engee according to the mechanism for user libraries;

  • if the model itself or the parameters of the EDM-Target block have changed, the target project must be generated anew from the model.

Logs and errors

For user messages, use the built-in logging system, as described in the section Debugging support packages. The messages should explain the user’s actions: checking the port, installing the tulchain, selecting the correct execution mode, specifying the path to the compiler, and connecting the device.

It is recommended to present target errors as exceptions with a short message that should contain the cause and a recommendation for elimination. You should not rely on the user to have access to the call report or the source code of the support package, so the message should be self-contained and not require additional analysis.

Example of an error message

if model_settings.is_ext_mode:
    raise RuntimeError(
        "This target supports only independent execution. "
        "Disable interactive execution in Target Hardware settings."
    )

Debugging without re-generating the model

During target development, it is often necessary to debug multiple times. generate_executable_code. Generating the C code from the interface Engee it can take time, so it’s convenient to save the input data of the method to JSON files once, and then run Python code locally on this data.

This mechanism is intended solely for target development and debugging; it should not be part of a user’s work scenario and should not be a mandatory component of the supplied support package.

Example of saving input data generate_executable_code

import json
from pathlib import Path
from typing import Any


def _to_jsonable(value: Any) -> Any:
    if hasattr(value, "model_dump"):
        return value.model_dump(mode="json", by_alias=True)
    if isinstance(value, dict):
        return {str(k): _to_jsonable(v) for k, v in value.items()}
    if isinstance(value, list):
        return [_to_jsonable(v) for v in value]
    return value


def dump_codegen_inputs(model, model_settings, model_code) -> None:
    dump_dir = Path("/tmp/mytarget-codegen-dump")
    dump_dir.mkdir(parents=True, exist_ok=True)

    payload = {
        "model": _to_jsonable(model),
        "model_settings": _to_jsonable(model_settings),
        "model_code": _to_jsonable(model_code),
    }

    for name, data in payload.items():
        path = dump_dir / f"{name}.json"
        path.write_text(
            json.dumps(data, ensure_ascii=False, indent=2),
            encoding="utf-8",
        )

Such a call can be temporarily placed at the beginning generate_executable_code:

def generate_executable_code(self, model, model_settings, model_code):
    dump_codegen_inputs(model, model_settings, model_code)
    ...

After that, you can reproduce the project generation without restarting code generation from the interface. Engee.

Example of a local launch using saved JSON

from pathlib import Path

from targets.base_models import EngeeModel, ModelCode
from targets.contract_compat import ModelSettings

from targets.my_target.my_target import MyTarget


dump_dir = Path("/tmp/mytarget-codegen-dump")

model = EngeeModel.model_validate_json(
    (dump_dir / "model.json").read_text(encoding="utf-8")
)
model_settings = ModelSettings.model_validate_json(
    (dump_dir / "model_settings.json").read_text(encoding="utf-8")
)
model_code = ModelCode.model_validate_json(
    (dump_dir / "model_code.json").read_text(encoding="utf-8")
)

target = MyTarget()
target.generate_executable_code(model, model_settings, model_code)
target.compile_model(model)

If you only need to debug templates and copy files, it is enough to run generate_executable_code. If you need to check the integration with the tulchain, add compile_model. upload_model and start_model it is better to run them separately, because they already depend on the connected hardware.

Checking before sending the target

The target is checked according to the following scenario:

  1. Support Package uploaded via Engee.Integration.

  2. After syncExtensions() the target is available in scripts and blocks Engee.

  3. Block EDM-Target is displayed in the user library and saves the mask parameters.

  4. generate_executable_code creates a project without manual edits.

  5. compile_model builds a project from scratch.

  6. upload_model uploads the artifact to the device or to the runtime environment.

  7. start_model launches the model and returns an understandable status.

  8. An unsupported execution mode ends with an understandable error.

  9. The demo model goes through a full user scenario.

For interactive mode additionally check:

  1. Launch commands for changing the data flow.

  2. Accomplishment commands to change at least one parameter.

  3. Correct resource release in stop_model.

Information in the target’s README

The README of the target should be user-oriented and should not contain an internal description of the repository. We recommend that you specify:

  • supported platform and execution modes;

  • how to install external dependencies: toolchain, programmer, OS drivers;

  • how to download the support package and when to synchronize syncExtensions();

  • where is .nglib-the library of blocks;

  • what parameters does the EDM-Target block have?;

  • how to launch a demo model;

  • typical connection, build, and download errors.