librelane 3.0.0.dev26__tar.gz → 3.0.0.dev27__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of librelane might be problematic. Click here for more details.

Files changed (171) hide show
  1. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/PKG-INFO +1 -1
  2. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/common/tcl.py +42 -0
  3. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/config/flow.py +12 -0
  4. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/magic/extract_spice.tcl +1 -1
  5. librelane-3.0.0.dev27/librelane/scripts/openroad/write_cdl.tcl +23 -0
  6. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/state/design_format.py +7 -0
  7. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/steps/cvc_rv.py +1 -8
  8. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/steps/klayout.py +193 -1
  9. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/steps/openroad.py +14 -0
  10. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/pyproject.toml +1 -1
  11. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/Readme.md +0 -0
  12. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/__init__.py +0 -0
  13. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/__main__.py +0 -0
  14. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/__version__.py +0 -0
  15. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/common/__init__.py +0 -0
  16. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/common/cli.py +0 -0
  17. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/common/drc.py +0 -0
  18. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/common/generic_dict.py +0 -0
  19. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/common/metrics/__init__.py +0 -0
  20. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/common/metrics/__main__.py +0 -0
  21. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/common/metrics/library.py +0 -0
  22. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/common/metrics/metric.py +0 -0
  23. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/common/metrics/util.py +0 -0
  24. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/common/misc.py +0 -0
  25. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/common/ring_buffer.py +0 -0
  26. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/common/toolbox.py +0 -0
  27. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/common/tpe.py +0 -0
  28. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/common/types.py +0 -0
  29. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/config/__init__.py +0 -0
  30. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/config/__main__.py +0 -0
  31. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/config/config.py +0 -0
  32. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/config/pdk_compat.py +0 -0
  33. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/config/preprocessor.py +0 -0
  34. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/config/removals.py +0 -0
  35. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/config/variable.py +0 -0
  36. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/container.py +0 -0
  37. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/env_info.py +0 -0
  38. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/examples/spm/config.yaml +0 -0
  39. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/examples/spm/pin_order.cfg +0 -0
  40. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/examples/spm/src/impl.sdc +0 -0
  41. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/examples/spm/src/signoff.sdc +0 -0
  42. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/examples/spm/src/spm.v +0 -0
  43. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/examples/spm/verify/spm_tb.v +0 -0
  44. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/examples/spm-user_project_wrapper/SPM_example.v +0 -0
  45. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/examples/spm-user_project_wrapper/base_sdc_file.sdc +0 -0
  46. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/examples/spm-user_project_wrapper/config-tut.json +0 -0
  47. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/examples/spm-user_project_wrapper/config.json +0 -0
  48. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/examples/spm-user_project_wrapper/defines.v +0 -0
  49. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/examples/spm-user_project_wrapper/template.def +0 -0
  50. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/examples/spm-user_project_wrapper/user_project_wrapper.v +0 -0
  51. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/flows/__init__.py +0 -0
  52. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/flows/builtins.py +0 -0
  53. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/flows/classic.py +0 -0
  54. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/flows/cli.py +0 -0
  55. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/flows/flow.py +0 -0
  56. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/flows/misc.py +0 -0
  57. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/flows/optimizing.py +0 -0
  58. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/flows/sequential.py +0 -0
  59. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/flows/synth_explore.py +0 -0
  60. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/logging/__init__.py +0 -0
  61. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/logging/logger.py +0 -0
  62. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/open_pdks_rev +0 -0
  63. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/plugins.py +0 -0
  64. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/py.typed +0 -0
  65. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/base.sdc +0 -0
  66. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/klayout/Readme.md +0 -0
  67. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/klayout/open_design.py +0 -0
  68. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/klayout/render.py +0 -0
  69. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/klayout/stream_out.py +0 -0
  70. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/klayout/xml_drc_report_to_json.py +0 -0
  71. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/klayout/xor.drc +0 -0
  72. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/magic/Readme.md +0 -0
  73. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/magic/common/read.tcl +0 -0
  74. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/magic/def/antenna_check.tcl +0 -0
  75. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/magic/def/mag.tcl +0 -0
  76. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/magic/def/mag_gds.tcl +0 -0
  77. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/magic/drc.tcl +0 -0
  78. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/magic/gds/drc_batch.tcl +0 -0
  79. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/magic/gds/erase_box.tcl +0 -0
  80. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/magic/gds/extras_mag.tcl +0 -0
  81. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/magic/gds/mag_with_pointers.tcl +0 -0
  82. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/magic/get_bbox.tcl +0 -0
  83. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/magic/lef/extras_maglef.tcl +0 -0
  84. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/magic/lef/maglef.tcl +0 -0
  85. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/magic/lef.tcl +0 -0
  86. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/magic/open.tcl +0 -0
  87. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/magic/wrapper.tcl +0 -0
  88. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/netgen/setup.tcl +0 -0
  89. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/odbpy/apply_def_template.py +0 -0
  90. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/odbpy/cell_frequency.py +0 -0
  91. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/odbpy/check_antenna_properties.py +0 -0
  92. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/odbpy/contextualize.py +0 -0
  93. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/odbpy/defutil.py +0 -0
  94. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/odbpy/diodes.py +0 -0
  95. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/odbpy/disconnected_pins.py +0 -0
  96. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/odbpy/eco_buffer.py +0 -0
  97. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/odbpy/eco_diode.py +0 -0
  98. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/odbpy/filter_unannotated.py +0 -0
  99. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/odbpy/io_place.py +0 -0
  100. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/odbpy/ioplace_parser/__init__.py +0 -0
  101. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/odbpy/ioplace_parser/parse.py +0 -0
  102. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/odbpy/label_macro_pins.py +0 -0
  103. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/odbpy/lefutil.py +0 -0
  104. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/odbpy/placers.py +0 -0
  105. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/odbpy/power_utils.py +0 -0
  106. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/odbpy/random_place.py +0 -0
  107. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/odbpy/reader.py +0 -0
  108. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/odbpy/remove_buffers.py +0 -0
  109. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/odbpy/snap_to_grid.py +0 -0
  110. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/odbpy/wire_lengths.py +0 -0
  111. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/antenna_check.tcl +0 -0
  112. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/antenna_repair.tcl +0 -0
  113. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/basic_mp.tcl +0 -0
  114. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/buffer_list.tcl +0 -0
  115. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/common/dpl.tcl +0 -0
  116. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/common/dpl_cell_pad.tcl +0 -0
  117. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/common/grt.tcl +0 -0
  118. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/common/io.tcl +0 -0
  119. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/common/pdn_cfg.tcl +0 -0
  120. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/common/resizer.tcl +0 -0
  121. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/common/set_global_connections.tcl +0 -0
  122. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/common/set_layer_adjustments.tcl +0 -0
  123. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/common/set_power_nets.tcl +0 -0
  124. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/common/set_rc.tcl +0 -0
  125. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/common/set_routing_layers.tcl +0 -0
  126. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/cts.tcl +0 -0
  127. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/cut_rows.tcl +0 -0
  128. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/dpl.tcl +0 -0
  129. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/drt.tcl +0 -0
  130. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/dump_rc.tcl +0 -0
  131. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/fill.tcl +0 -0
  132. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/floorplan.tcl +0 -0
  133. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/gpl.tcl +0 -0
  134. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/grt.tcl +0 -0
  135. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/gui.tcl +0 -0
  136. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/insert_buffer.tcl +0 -0
  137. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/ioplacer.tcl +0 -0
  138. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/irdrop.tcl +0 -0
  139. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/pdn.tcl +0 -0
  140. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/rcx.tcl +0 -0
  141. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/repair_design.tcl +0 -0
  142. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/repair_design_postgrt.tcl +0 -0
  143. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/rsz_timing_postcts.tcl +0 -0
  144. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/rsz_timing_postgrt.tcl +0 -0
  145. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/sta/check_macro_instances.tcl +0 -0
  146. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/sta/corner.tcl +0 -0
  147. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/tapcell.tcl +0 -0
  148. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/ungpl.tcl +0 -0
  149. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/openroad/write_views.tcl +0 -0
  150. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/pyosys/construct_abc_script.py +0 -0
  151. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/pyosys/json_header.py +0 -0
  152. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/pyosys/synthesize.py +0 -0
  153. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/pyosys/ys_common.py +0 -0
  154. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/scripts/tclsh/hello.tcl +0 -0
  155. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/state/__init__.py +0 -0
  156. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/state/__main__.py +0 -0
  157. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/state/state.py +0 -0
  158. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/steps/__init__.py +0 -0
  159. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/steps/__main__.py +0 -0
  160. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/steps/checker.py +0 -0
  161. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/steps/common_variables.py +0 -0
  162. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/steps/magic.py +0 -0
  163. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/steps/misc.py +0 -0
  164. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/steps/netgen.py +0 -0
  165. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/steps/odb.py +0 -0
  166. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/steps/openroad_alerts.py +0 -0
  167. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/steps/pyosys.py +0 -0
  168. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/steps/step.py +0 -0
  169. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/steps/tclstep.py +0 -0
  170. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/steps/verilator.py +0 -0
  171. {librelane-3.0.0.dev26 → librelane-3.0.0.dev27}/librelane/steps/yosys.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: librelane
3
- Version: 3.0.0.dev26
3
+ Version: 3.0.0.dev27
4
4
  Summary: An infrastructure for implementing chip design flows
5
5
  Home-page: https://github.com/librelane/librelane
6
6
  License: Apache-2.0
@@ -1,3 +1,7 @@
1
+ # Copyright 2025 LibreLane Contributors
2
+ #
3
+ # Adapted from OpenLane
4
+ #
1
5
  # Copyright 2023 Efabless Corporation
2
6
  #
3
7
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -68,12 +72,50 @@ class TclUtils(object):
68
72
  if value is not None:
69
73
  env_out[match.group(1)] = value
70
74
 
75
+ def py_dict(command, target=None, *args):
76
+ if command == "set":
77
+ if match := _env_rx.fullmatch(target):
78
+
79
+ if len(args) > 1:
80
+ value = args[-1]
81
+ keys = args[:-1]
82
+
83
+ # Create new dict if it does not exist
84
+ if not match.group(1) in env_out:
85
+ env_out[match.group(1)] = {}
86
+
87
+ # set ::env(...) [dict create]
88
+ # will create an empty string ""
89
+ # convert into an empty dictionary
90
+ if env_out[match.group(1)] == "":
91
+ env_out[match.group(1)] = {}
92
+
93
+ # Set key value pair
94
+ cur_dict = env_out[match.group(1)]
95
+
96
+ # Create all nested dicts
97
+ for key in keys[:-1]:
98
+ if key in cur_dict:
99
+ cur_dict = cur_dict[key]
100
+ else:
101
+ cur_dict[key] = {}
102
+ cur_dict = cur_dict[key]
103
+
104
+ # Finally set the value
105
+ cur_dict[keys[-1]] = value
106
+
71
107
  py_set_name = interpreter.register(py_set)
108
+ py_dict_name = interpreter.register(py_dict)
72
109
  interpreter.call("rename", py_set_name, "_py_set")
73
110
  interpreter.call("rename", "set", "_orig_set")
111
+ interpreter.call("rename", py_dict_name, "_py_dict")
112
+ interpreter.call("rename", "dict", "_orig_dict")
74
113
  interpreter.eval(
75
114
  "proc set args { _py_set {*}$args; tailcall _orig_set {*}$args; }"
76
115
  )
116
+ interpreter.eval(
117
+ "proc dict args { _py_dict {*}$args; tailcall _orig_dict {*}$args; }"
118
+ )
77
119
 
78
120
  interpreter.eval(tcl_in)
79
121
 
@@ -195,6 +195,13 @@ scl_variables = [
195
195
  "Path(s) to cells' SPICE model(s)",
196
196
  pdk=True,
197
197
  ),
198
+ Variable(
199
+ "CELL_CDLS",
200
+ Optional[List[Path]],
201
+ description="A circuit-design language view of the standard cell library.",
202
+ pdk=True,
203
+ deprecated_names=["STD_CELL_LIBRARY_CDL"],
204
+ ),
198
205
  Variable(
199
206
  "SYNTH_EXCLUDED_CELL_FILE",
200
207
  Path,
@@ -424,6 +431,11 @@ option_variables = [
424
431
  Optional[List[Path]],
425
432
  "Specifies miscellaneous SPICE models to be loaded indiscriminately whenever SPICE models are loaded.",
426
433
  ),
434
+ Variable(
435
+ "EXTRA_CDLS",
436
+ Optional[List[Path]],
437
+ "Specifies miscellaneous CDL netlists to be loaded indiscriminately whenever CDL netlists are loaded.",
438
+ ),
427
439
  Variable(
428
440
  "EXTRA_LIBS",
429
441
  Optional[List[Path]],
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
  set f [open $::env(STEP_DIR)/cif_scale.txt "w"]
15
- puts $f "[magic::i2u 1]"
15
+ puts $f [expr {((round([magic::cif scale output] * 10000)) / 10000.0) * 1}]
16
16
  close $f
17
17
 
18
18
  if { $::env(MAGIC_EXT_USE_GDS) } {
@@ -0,0 +1,23 @@
1
+ #
2
+ # Write CDL netlist of the current design
3
+ #
4
+
5
+ # Load design database
6
+ source $::env(SCRIPTS_DIR)/openroad/common/io.tcl
7
+ read_current_odb
8
+
9
+ # Collect masters CDL
10
+ set masters {}
11
+
12
+ foreach cdl $::env(CELL_CDLS) {
13
+ lappend masters $cdl
14
+ }
15
+
16
+ if { [info exist ::env(EXTRA_CDLS)] } {
17
+ foreach cdl $::env(EXTRA_CDLS) {
18
+ lappend masters $cdl
19
+ }
20
+ }
21
+
22
+ # Write only the CDL
23
+ write_cdl -include_fillers -masters "$masters" $::env(STEP_DIR)/$::env(DESIGN_NAME).cdl
@@ -239,6 +239,13 @@ DesignFormat(
239
239
  alts=["SPICE"],
240
240
  ).register()
241
241
 
242
+ DesignFormat(
243
+ "cdl",
244
+ "cdl",
245
+ "Circuit Design Language",
246
+ alts=["CDL"],
247
+ ).register()
248
+
242
249
  DesignFormat(
243
250
  "gds",
244
251
  "gds",
@@ -16,7 +16,7 @@ import re
16
16
  import json
17
17
  from enum import Enum
18
18
  from io import StringIO, TextIOWrapper
19
- from typing import List, Optional, Tuple
19
+ from typing import Optional, Tuple
20
20
 
21
21
  from .step import StepException, ViewsUpdate, MetricsUpdate, Step
22
22
  from ..common import Path
@@ -124,13 +124,6 @@ class ERC(Step):
124
124
  description="",
125
125
  pdk=True,
126
126
  ),
127
- Variable(
128
- "CELL_CDLS",
129
- List[Path],
130
- description="A circuit-design language view of the standard cell library.",
131
- pdk=True,
132
- deprecated_names=["STD_CELL_LIBRARY_CDL"],
133
- ),
134
127
  ]
135
128
 
136
129
  def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
@@ -1,3 +1,7 @@
1
+ # Copyright 2025 LibreLane Contributors
2
+ #
3
+ # Adapted from OpenLane
4
+ #
1
5
  # Copyright 2023 Efabless Corporation
2
6
  #
3
7
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,6 +23,7 @@ import shutil
19
23
  import subprocess
20
24
  from os.path import abspath
21
25
  from base64 import b64encode
26
+ from tempfile import NamedTemporaryFile
22
27
  from typing import Any, Dict, Optional, List, Sequence, Tuple, Union
23
28
 
24
29
  from .step import ViewsUpdate, MetricsUpdate, Step, StepError, StepException
@@ -431,10 +436,77 @@ class DRC(KLayoutStep):
431
436
  )
432
437
  return subprocess_result["generated_metrics"]
433
438
 
439
+ def run_ihp_sg13g2(self, state_in: State, **kwargs) -> MetricsUpdate:
440
+ kwargs, env = self.extract_env(kwargs)
441
+
442
+ drc_script_path = self.config["KLAYOUT_DRC_RUNSET"]
443
+
444
+ reports_dir = os.path.join(self.step_dir, "reports")
445
+ mkdirp(reports_dir)
446
+ xml_report = os.path.join(reports_dir, "drc_violations.klayout.xml")
447
+ json_report = os.path.join(reports_dir, "drc_violations.klayout.json")
448
+
449
+ input_view = state_in[DesignFormat.GDS]
450
+ assert isinstance(input_view, Path)
451
+
452
+ opts = []
453
+ for k, v in self.config["KLAYOUT_DRC_OPTIONS"].items():
454
+ opts.extend(
455
+ [
456
+ "-rd",
457
+ f"{k}={v}",
458
+ ]
459
+ )
460
+
461
+ threads = self.config["KLAYOUT_DRC_THREADS"] or str(_get_process_limit())
462
+ if threads != "1":
463
+ opts.extend(
464
+ [
465
+ "-rd",
466
+ f"threads={threads}",
467
+ ]
468
+ )
469
+
470
+ info(f"Running KLayout DRC with {threads} threads…")
471
+
472
+ # Not pya script - DRC script is not part of OpenLane
473
+ self.run_subprocess(
474
+ [
475
+ "klayout",
476
+ "-b",
477
+ "-zz",
478
+ "-r",
479
+ drc_script_path,
480
+ "-rd",
481
+ f"in_gds={abspath(input_view)}",
482
+ "-rd",
483
+ f"report_file={abspath(xml_report)}",
484
+ *opts,
485
+ ]
486
+ )
487
+
488
+ subprocess_result = self.run_pya_script(
489
+ [
490
+ "python3",
491
+ os.path.join(
492
+ get_script_dir(),
493
+ "klayout",
494
+ "xml_drc_report_to_json.py",
495
+ ),
496
+ f"--xml-file={abspath(xml_report)}",
497
+ f"--json-file={abspath(json_report)}",
498
+ ],
499
+ env=env,
500
+ log_to=os.path.join(self.step_dir, "xml_drc_report_to_json.log"),
501
+ )
502
+ return subprocess_result["generated_metrics"]
503
+
434
504
  def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
435
505
  metrics_updates: MetricsUpdate = {}
436
506
  if self.config["PDK"] in ["sky130A", "sky130B"]:
437
507
  metrics_updates = self.run_sky130(state_in, **kwargs)
508
+ elif self.config["PDK"] in ["ihp-sg13g2"]:
509
+ metrics_updates = self.run_ihp_sg13g2(state_in, **kwargs)
438
510
  else:
439
511
  self.warn(
440
512
  f"KLayout DRC is not supported for the {self.config['PDK']} PDK. This step will be skipped."
@@ -443,6 +515,126 @@ class DRC(KLayoutStep):
443
515
  return {}, metrics_updates
444
516
 
445
517
 
518
+ @Step.factory.register()
519
+ class LVS(KLayoutStep):
520
+ id = "KLayout.LVS"
521
+ name = "Layout Versus Schematic (KLayout)"
522
+
523
+ inputs = [
524
+ DesignFormat.CDL,
525
+ DesignFormat.GDS,
526
+ ]
527
+ outputs = [DesignFormat.SPICE]
528
+
529
+ config_vars = KLayoutStep.config_vars + [
530
+ Variable(
531
+ "KLAYOUT_LVS_SCRIPT",
532
+ Optional[Path],
533
+ "A path to KLayout LVS script.",
534
+ pdk=True,
535
+ ),
536
+ Variable(
537
+ "KLAYOUT_LVS_OPTIONS",
538
+ Optional[Dict[str, Union[bool, int, str]]],
539
+ "Options passed directly to the KLayout LVS script. They vary from one PDK to another.",
540
+ pdk=True,
541
+ ),
542
+ ]
543
+
544
+ def run_ihp_sg13g2(
545
+ self, state_in: State, **kwargs
546
+ ) -> Tuple[ViewsUpdate, MetricsUpdate]:
547
+ kwargs, env = self.extract_env(kwargs)
548
+
549
+ lvs_script_path = self.config["KLAYOUT_LVS_SCRIPT"]
550
+
551
+ reports_dir = os.path.join(self.step_dir, "reports")
552
+ mkdirp(reports_dir)
553
+ lvsdb_report = os.path.join(reports_dir, "lvs.klayout.lvsdb")
554
+
555
+ input_view_gds = state_in[DesignFormat.GDS]
556
+ input_view_cdl = state_in[DesignFormat.CDL]
557
+ assert isinstance(input_view_gds, Path)
558
+ assert isinstance(input_view_cdl, Path)
559
+
560
+ output_spice = os.path.join(
561
+ self.step_dir,
562
+ f"{self.config['DESIGN_NAME']}.{DesignFormat.SPICE.value.extension}",
563
+ )
564
+
565
+ with NamedTemporaryFile("w") as f:
566
+ # Merge all CDL inputs
567
+ cdl_lst = [input_view_cdl]
568
+ cdl_lst.extend(self.config["CELL_CDLS"] or [])
569
+ cdl_lst.extend(self.config["EXTRA_CDLS"] or [])
570
+
571
+ for fn in cdl_lst:
572
+ with open(fn, "r") as cdl_fh:
573
+ f.write(cdl_fh.read())
574
+
575
+ opts = []
576
+ for k, v in self.config["KLAYOUT_LVS_OPTIONS"].items():
577
+ opts.extend(
578
+ [
579
+ "-rd",
580
+ f"{k}={v}",
581
+ ]
582
+ )
583
+
584
+ # Not pya script - LVS script is not part of LibreLane
585
+ subprocess_result = self.run_subprocess(
586
+ [
587
+ "klayout",
588
+ "-b",
589
+ "-zz",
590
+ "-r",
591
+ lvs_script_path,
592
+ "-rd",
593
+ f"input={abspath(input_view_gds)}",
594
+ "-rd",
595
+ f"schematic={abspath(f.name)}",
596
+ "-rd",
597
+ f"report={abspath(lvsdb_report)}",
598
+ "-rd",
599
+ f"target_netlist={abspath(output_spice)}",
600
+ ]
601
+ + opts,
602
+ env=env,
603
+ )
604
+
605
+ with open(subprocess_result["log_path"]) as fh:
606
+ for line in fh:
607
+ if "INFO : Congratulations! Netlists match" in line:
608
+ ok = True
609
+ break
610
+ elif "ERROR : Netlists don't match" in line:
611
+ ok = False
612
+ break
613
+ else:
614
+ ok = False
615
+
616
+ views_updates: ViewsUpdate = {
617
+ DesignFormat.SPICE: Path(output_spice),
618
+ }
619
+ metrics_updates: MetricsUpdate = {
620
+ "design__lvs_error__count": 0 if ok else 1,
621
+ }
622
+
623
+ return views_updates, metrics_updates
624
+
625
+ def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
626
+ metrics_updates: MetricsUpdate = {}
627
+ views_updates: ViewsUpdate = {}
628
+ if self.config["PDK"] in ["ihp-sg13g2"]:
629
+ views_updates, metrics_updates = self.run_ihp_sg13g2(state_in, **kwargs)
630
+ else:
631
+ self.warn(
632
+ f"KLayout LVS is not supported for the {self.config['PDK']} PDK. This step will be skipped."
633
+ )
634
+
635
+ return views_updates, metrics_updates
636
+
637
+
446
638
  @Step.factory.register()
447
639
  class OpenGUI(KLayoutStep):
448
640
  """
@@ -480,7 +672,7 @@ class OpenGUI(KLayoutStep):
480
672
 
481
673
  layout = state_in[DesignFormat.DEF]
482
674
  if self.config["KLAYOUT_GUI_USE_GDS"]:
483
- if gds := state_in[DesignFormat.GDS]:
675
+ if gds := state_in.get(DesignFormat.GDS):
484
676
  layout = gds
485
677
  assert isinstance(layout, Path)
486
678
 
@@ -2188,6 +2188,20 @@ class WriteViews(OpenROADStep):
2188
2188
  return os.path.join(get_script_dir(), "openroad", "write_views.tcl")
2189
2189
 
2190
2190
 
2191
+ @Step.factory.register()
2192
+ class WriteCDL(OpenROADStep):
2193
+ """
2194
+ Write CDL view of an ODB design
2195
+ """
2196
+
2197
+ id = "OpenROAD.WriteCDL"
2198
+ name = "Write CDL"
2199
+ outputs = [DesignFormat.CDL]
2200
+
2201
+ def get_script_path(self):
2202
+ return os.path.join(get_script_dir(), "openroad", "write_cdl.tcl")
2203
+
2204
+
2191
2205
  # Resizer Steps
2192
2206
 
2193
2207
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "librelane"
3
- version = "3.0.0.dev26"
3
+ version = "3.0.0.dev27"
4
4
  description = "An infrastructure for implementing chip design flows"
5
5
  # Technically, maintainer. We cannot use the maintainers field until
6
6
  # poetry-core>=2.0.0 which requires Python version 3.9+. This field does