diff --git a/openlane/config/variable.py b/openlane/config/variable.py index 42f3dd0e3..83f23d17c 100644 --- a/openlane/config/variable.py +++ b/openlane/config/variable.py @@ -77,10 +77,12 @@ class Instance: :param location: The physical co-ordinates of the Macro's origin. :param orientation: Whether the Macro is facing North or South. + :param placed: Whether the Macro is already placed or not. Useful with macros inside macros. """ - location: Tuple[Decimal, Decimal] - orientation: Orientation + location: Optional[Tuple[Decimal, Decimal]] + orientation: Optional[Orientation] + placed: Optional[bool] @dataclass @@ -196,9 +198,12 @@ def instantiate( instance_name: str, location: Tuple[Number, Number], orientation: Orientation = Orientation.N, + placed: bool = False, ): location = (Decimal(location[0]), Decimal(location[1])) - self.instances[instance_name] = Instance(location, Orientation[orientation]) + self.instances[instance_name] = Instance( + location, Orientation[orientation], placed + ) def is_optional(t: Type[Any]) -> bool: diff --git a/openlane/steps/odb.py b/openlane/steps/odb.py index 3fc739b57..83059ac98 100644 --- a/openlane/steps/odb.py +++ b/openlane/steps/odb.py @@ -238,9 +238,22 @@ def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]: f"Misconstructed configuration: macro definition for key {module} is not of type 'Macro'." ) for name, data in macro.instances.items(): - f.write( - f"{name} {data.location[0]} {data.location[1]} {data.orientation}\n" - ) + if data.placed: + info( + f"Not placing already placed marco instance: {name}." + ) + else: + if not data.location: + raise StepException( + f"Unspecified key: location for non-placed macro instance: {name}." + ) + if not data.orientation: + raise StepException( + f"Unspecified key: orientation> for non-placed macro instance: {name}" + ) + f.write( + f"{name} {data.location[0]} {data.location[1]} {data.orientation}\n" + ) if not cfg_file.exists(): info(f"No instances found, skipping '{self.id}'…")