Files
oapy/labs/src/lab13_4_occproducer.py
opencad-abu 1e26b0dff7 Add labs: 59 Python lab scripts + tools + run_lab.sh
- labs/src/: 59 lab scripts covering OA API (Ch2-Ch25 + extras)
  - All C++ references removed, oapy-only documentation
- labs/tools/: debug and test utilities
- labs/run_lab.sh: lab runner with LD_PRELOAD and env setup
2026-06-02 16:59:08 +08:00

137 lines
5.0 KiB
Python

#!/usr/bin/env python3
"""
Lab 13-4: OccProducer — Occurrence Producer
Demonstrates the oaOccProducer class for producing occurrence-domain objects.
The producer generates occurrence objects for a given root occurrence.
Key concepts:
- Constructing oaOccProducer with a root occurrence
- Calling produce() to generate occurrence objects
- Setting a new occurrence with setOccurrence() and producing again
Note: The oapy bindings do not have Python director support for process*()
virtuals, so we demonstrate the base API pattern.
"""
import os
import sys
__dir__ = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, os.path.join(__dir__, "..", "..", "build"))
sys.path.insert(0, __dir__)
from oapy._oa import _base, _dm, _design
from utils import init_oa, make_oa_name, make_oa_string, get_namespace, create_lib
def main():
print("=" * 60)
print("Lab 13-4: OccProducer — Occurrence Producer")
print("=" * 60)
init_oa()
ns = get_namespace("native")
import shutil
LIB_DIR = os.path.join(__dir__, "..", "data", "lab13_4_dir")
if os.path.exists(LIB_DIR):
shutil.rmtree(LIB_DIR)
sn_lib, lib = create_lib("lab13_4_lib", LIB_DIR)
vt = _dm.oaViewType.find(make_oa_string("schematic"))
sv_name = make_oa_name(ns, "schematic")
bv_enum = _design.oaBlockDomainVisibilityEnum
ps_enum = _design.oaPlacementStatusEnum
xform = _base.oaTransform(0, 0, _base.oaOrient(_base.oaOrientEnum.oacR0))
# ── Build hierarchy: top → sub (2 inst) → leaf (2 inst each) ──
print("\n─── Building Hierarchy ───")
leaf_view = _design.oaDesign.open(sn_lib, make_oa_name(ns, "leaf"), sv_name, vt, 'w')
_design.oaBlock.create(leaf_view, True)
leaf_view.save()
leaf_view.close()
leaf_master = _design.oaDesign.open(sn_lib, make_oa_name(ns, "leaf"), sv_name, vt, 'r')
sub_view = _design.oaDesign.open(sn_lib, make_oa_name(ns, "sub"), sv_name, vt, 'w')
sub_blk = _design.oaBlock.create(sub_view, True)
_design.oaScalarInst.create(sub_blk, leaf_master, make_oa_name(ns, "subLeaf1"),
xform, _base.oaParamArray(0),
_design.oaBlockDomainVisibility(bv_enum.oacInheritFromTopBlock),
_design.oaPlacementStatus(ps_enum.oacUnplacedPlacementStatus))
_design.oaScalarInst.create(sub_blk, leaf_master, make_oa_name(ns, "subLeaf2"),
xform, _base.oaParamArray(0),
_design.oaBlockDomainVisibility(bv_enum.oacInheritFromTopBlock),
_design.oaPlacementStatus(ps_enum.oacUnplacedPlacementStatus))
sub_view.save()
leaf_master.close()
sub_master = _design.oaDesign.open(sn_lib, make_oa_name(ns, "sub"), sv_name, vt, 'r')
top_view = _design.oaDesign.open(sn_lib, make_oa_name(ns, "top"), sv_name, vt, 'w')
top_blk = _design.oaBlock.create(top_view, True)
_design.oaScalarInst.create(top_blk, sub_master, make_oa_name(ns, "topSub1"),
xform, _base.oaParamArray(0),
_design.oaBlockDomainVisibility(bv_enum.oacInheritFromTopBlock),
_design.oaPlacementStatus(ps_enum.oacUnplacedPlacementStatus))
_design.oaScalarInst.create(top_blk, sub_master, make_oa_name(ns, "topSub2"),
xform, _base.oaParamArray(0),
_design.oaBlockDomainVisibility(bv_enum.oacInheritFromTopBlock),
_design.oaPlacementStatus(ps_enum.oacUnplacedPlacementStatus))
top_view.save()
print(" [PASS] 3-level hierarchy created")
# ── oaOccProducer: construct and produce ──
print("\n─── oaOccProducer ───")
top_occ = top_view.getTopOccurrence()
assert top_occ is not None
prod = _design.oaOccProducer(top_occ)
assert prod is not None
print(f" [PASS] oaOccProducer constructed with root occ")
prod.produce()
print(" [PASS] produce() called on top occurrence")
# ── setOccurrence: produce from a different occurrence ──
print("\n─── setOccurrence to sub-level ──")
sTopSub1 = _base.oaSimpleName(ns, "topSub1")
oi_topSub1 = _design.oaOccInst.find(top_occ, sTopSub1)
assert oi_topSub1 is not None
sub1_master = oi_topSub1.getMasterOccurrence(True)
assert sub1_master is not None
# Set the producer to sub1's master occurrence
prod.setOccurrence(sub1_master)
prod.produce()
print(" [PASS] produce() called on topSub1's master occurrence")
# Verify we can access the inner instances
sSubLeaf = _base.oaSimpleName(ns, "subLeaf1")
oi_subLeaf = _design.oaOccInst.find(sub1_master, sSubLeaf)
assert oi_subLeaf is not None
print(" [PASS] Found subLeaf1 inside topSub1's master")
# ── CalcVM ──
print("\n─── Design size ──")
vm = top_view.calcVMSize()
assert vm > 0
print(f" [PASS] VM size: {vm}")
# ── Cleanup ──
print("\n─── Cleanup ───")
top_view.close()
sub_master.close()
lib.close()
shutil.rmtree(LIB_DIR, ignore_errors=True)
print("\n" + "=" * 60)
print("✅ Lab 13-4 (OccProducer) PASSED!")
print("=" * 60)
if __name__ == "__main__":
main()
os._exit(0)