Source code for fabulous.fabric_generator.gds_generator.steps.magic_streamout
"""FABulous Magic StreamOut - syncs DIE_AREA env with state's design__die__bbox.
Magic.StreamOut tries to honour `state_in.metrics["design__die__bbox"]`
(librelane/steps/magic.py:329-330) but TclStep.run re-calls `prepare_env`,
which iterates `self.config` and overwrites `env["DIE_AREA"]` from config.
When TileOptimisation evolves DIE_AREA across iterations, the new value lands
in state metrics rather than Flow config, so the stock streamout renders the
stale smart-init rectangle on layer 189/4. Rebinding `self.config["DIE_AREA"]`
from the state metric makes `prepare_env` emit the right value.
"""
from decimal import Decimal
from typing import Any
from librelane.state.state import State
from librelane.steps.magic import StreamOut
from librelane.steps.step import MetricsUpdate, Step, ViewsUpdate
@Step.factory.register()
[docs]
class FABulousMagicStreamOut(StreamOut):
"""Magic.StreamOut variant that pulls DIE_AREA from `design__die__bbox`."""
id = "Magic.FABulousStreamOut"
name = "GDSII Stream Out (Magic, FABulous)"
long_name = "Magic GDSII stream-out with DIE_AREA sync from design__die__bbox"
[docs]
def run(
self,
state_in: State,
**kwargs: Any, # noqa: ANN401
) -> tuple[ViewsUpdate, MetricsUpdate]:
"""Rebind DIE_AREA from the state metric, then delegate to `StreamOut`."""
die_bbox = state_in.metrics.get("design__die__bbox")
if die_bbox is not None:
die_area = tuple(Decimal(c) for c in die_bbox.split())
self.config = self.config.copy(DIE_AREA=die_area)
return super().run(state_in, **kwargs)