context module#
Contexts#
This module provides context management classes for maintaining state during design processing and instantiation. Contexts can be set to provide a value for a particular subtree of the design. If a context object is created in the class body, it will be set first, before any of the other fields are initialized, which means that subcircuits or components will see the new context value, even if they are declared before the context is set.
If a context is needed as part of the function, it does not need to be assigned
to a member field, and indeed doing so does not set the context value, instead
it is activated using a with block. Note that this means that setting the
context object on self as part of the __init__ method will have no
effect, if you need to construct a context inside the initializer, it must be
done using a with block.
Some context objects are predefined and set by the infrastructure, such as the current design, but user code can create their own contexts as needed, which can be particularly useful when building reusable librareis where there are optional settings that should be apply to entire designs (or a significant subset). For an example of this, see the jitx standard library’s use of contexts to control things like preferred silkscreen line widths in the landpattern generators.
Note
Context objects should be immutable and hashable, because if it’s used in a memoized object, the context object will be part of the memoization key, which means a new object will be generated if the identity of the context object changes, but should it be mutated instead, the memoization may not recognize that the value has changed.
Below is an example of both mechanisms for registering a context value. Note
that when using a with block, the context is only active within that block
(and within any calls made inside that block, such as creating components)
which can be useful if only a part of your circuit needs a different context
value.
>>> @dataclass(frozen=True)
... class MyCustomContext:
... some_relevant_value: int
>>> class MyCircuit(Circuit):
... circuit_context = MyCustomContext(42)
...
... def __init__(self):
... assert MyCustomContext.require().some_relevant_value == 42
... with MyCustomContext(7):
... self.needs_context_7()
...
... def needs_context_7(self):
... assert MyCustomContext.require().some_relevant_value == 7
- class Context[source]#
Bases:
objectBase class for context objects that maintain state during processing.
Context objects can be used as context managers to automatically push and pop context state, ensuring proper cleanup.
- classmethod require()[source]#
Get the current active context of this type, raising an error if not set. This method can be used in a declarative / class context, and will be populated at instantiation.
- Return type:
- Returns:
The current context instance.
- Raises:
ValueError – If no context of this type is currently active.
- exception ContextMissingException(name)[source]#
Bases:
UserCodeExceptionRaised if
Context.require()is called when the context has not been activated.
- class ContextProperty(context, field=<function ContextProperty.<lambda>>)[source]#
Bases:
GenericProperty descriptor for accessing context objects.
Creates a property that automatically retrieves the current context and optionally applies a field accessor function.
>>> class DesignContext: ... def __init__(self): ... self.substrate = ContextProperty(SubstrateContext) >>> design = DesignContext() >>> # Accessing design.substrate will get the current substrate context