FeatMgr

FeatMgr is a configuration dataclass for Riescue. It contains all configuration needed for RiescueD to generate a test. It specifies the enabled features, environment, and generation options.

Note

Generally, users will not need to construct a FeatMgr directly. Instead, they will use the FeatMgrBuilder to construct a FeatMgr.

from riescue import FeatMgr

featmgr = FeatMgr() # build default FeatMgr
class riescue.FeatMgr

Configuration manager; aata structure containing configuration for test generation.

FeatMgrBuilder class provides interface for constructing FeatMgr objects. Users can choose to override any fields after construction.

eot_print_htif_console: bool = False

When True, Riescue-D injects RVCP FAIL lines (with banners) via HTIF tohost putchar before ;#test_failed().

print_rvcp_passes: bool = False

When True, Riescue-D injects RVCP PASSED lines via HTIF tohost putchar before ;#test_passed() and at final ALL PASSED.

duplicate() FeatMgr

Duplicate / deepcopy a FeatMgr instance.

get_summary() dict[str, bool | int]

Returns an array representation of feature presence.

is_feature_supported(feature: str) bool

Check if a feature is supported - delegate to FeatureDiscovery

is_feature_enabled(feature: str) bool

Check if a feature is enabled - delegate to FeatureDiscovery

get_feature_randomize(feature: str) int

Get the randomization probability for a feature - delegate to FeatureDiscovery

get_misa_bits() int

Get MISA bits based on enabled features

get_compiler_march_string() str

Generate a compiler march string from enabled features

register_default_handler(vec: int, label: str, assembly: Callable[[FeatMgr], str]) None

Override the default interrupt handler for a vector.

Replaces the framework’s built-in handler for vec with a user-supplied label and assembly body for the entire test. The handler is active for all discrete_tests that do not install a per-segment handler via add_custom_intr_handler().

Called from riescue.dtest_framework.config.conf.Conf.add_hooks().

Parameters:
  • vec – Interrupt vector number (e.g. 1 for SSI, 3 for MSI, 25 for ZKR).

  • label – Assembly label for the handler (must be unique in the test).

  • assembly – Callable (featmgr: FeatMgr) -> str returning the handler body. The body should end with the appropriate xret (mret for M-mode vectors).

from riescue import Conf, FeatMgr

def my_msi_handler(featmgr: FeatMgr) -> str:
    return """
        csrci mip, 8   # clear MSIP
        mret
    """

class MyConf(Conf):
    def add_hooks(self, featmgr: FeatMgr) -> None:
        featmgr.register_default_handler(3, "my_msi_handler", my_msi_handler)

def setup() -> Conf:
    return MyConf()
register_hook(hook_point: HookPoint, hook: Callable[[FeatMgr], str])

Register a hook for a given hook point Multiple hooks can be registered for the same hook point. The order of hooks registered is preserved.

Parameters:
  • hook_point – The riescue.lib.enums.HookPoint enum value to register the hook.

  • hook – Callable hook function to register; returns a string of assembly code

def hook(featmgr: FeatMgr) -> str:
    return "nop"
featmgr.register_hook(RV.HookPoint.PRE_PASS, hook)
call_hook(hook_point: HookPoint) str

Get a hook for a given hook point

Hooks

Hooks are available for inserting additional code at different points in the code. Hooks take an instance of the riescue.FeatMgr class as an argument and return a string of assembly code. This can be used to add additional code at different points in the Runtime.

E.g.

def hook(featmgr: FeatMgr) -> str:
    return "nop"
featmgr.register_hook(RV.HookPoint.PRE_PASS, hook)

The available hooks are defined in the riescue.lib.enums.HookPoint enum.

class riescue.lib.enums.HookPoint(value)

Bases: MyEnum

Enumerated hooks for runtime code.

These are all the available hooks, they allow for inserting code at specific points in the Runtime. They append or replace code at the hook point.

This describes the name of the hook; behavior of the hook is defined where the hook is used.

PRE_LOADER = 'pre_loader'

Insert code before the loader. Can be used to insert code for custom CSRs, platform intialization code. GPRs, and changes to tvec, status, and satp will be overwritten by loader.

M_LOADER = 'm_loader'

Insert additional M-level configuration needed before the runtime may jump to a less privileged or virtualized mode. Code should avoid modifying trap handling or paging registers, e.g. tvec, satp, or vsatp.

POST_LOADER = 'post_loader'

Insert code after the loader but before the test jumps to the scheduler, inside loader__done label.

PRE_DISPATCH = 'pre_dispatch'

Insert code before the scheduler loads the next test into a0.

POST_DISPATCH = 'post_dispatch'

Insert code after the scheduler loads the next test into a0. Should not modify a0

POST_TRAP = 'post_trap'

Insert code after a trap is taken. Useful for logging/bookkeeping traps. Code should resume to return code after to continue execution. tp is initialized here - push and pop any registers used by post-trap code.

PRE_FAIL = 'pre_fail'

Insert code before the test is marked as failed.

POST_FAIL = 'post_fail'

Insert code after the test is marked as failed.

PRE_PASS = 'pre_pass'

Insert code before the test is marked as passed.

POST_PASS = 'post_pass'

Insert code after the test is marked as passed.

PRE_HALT = 'pre_halt'

Insert code before the test is halted.

Hooks can be added using the riescue.FeatMgr.register_hook() method with a valid enum value.

Multiple hooks can be registered for the same hook point. The order of hooks registered is preserved.

Hooks can also be added using the riescue.dtest_framework.config.Conf class. See the Conf reference for more information on how to use the Conf class.

Default Interrupt Handler Override

The register_default_handler method lets a Conf override the test-wide default handler for a specific interrupt vector. The replacement handler is active for the whole test and does not require the per-segment PROLOGUE/EPILOGUE pointer-swap mechanism.

from riescue import Conf, FeatMgr

def my_ssi_handler(featmgr: FeatMgr) -> str:
    """Custom handler for SSI (vec 1).  Clears SSIP and returns."""
    return """
    csrci mip, 2          # clear SSIP (bit 1)
    mret
"""

class MyConf(Conf):
    def add_hooks(self, featmgr: FeatMgr) -> None:
        featmgr.register_default_handler(
            vec=1,
            label="my_ssi_handler",
            assembly=my_ssi_handler,
        )

def setup() -> Conf:
    return MyConf()

The handler assembly callable receives the FeatMgr instance and returns a raw assembly string. The string must end with the appropriate return instruction (mret for machine-mode vectors, sret for supervisor-mode vectors).

The framework emits the handler body into the .runtime section and wires the vector into the M-mode vector dispatch table. S-mode delegated vector overrides are not yet supported.

See riescue/dtest_framework/tests/non_instr_tests/default_handler_override.s and default_handler_override_conf.py for a complete working example.