librelane 3.1.0.dev2__tar.gz → 3.1.0.dev4__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.
Files changed (179) hide show
  1. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/PKG-INFO +5 -4
  2. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/__main__.py +1 -1
  3. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/__init__.py +1 -0
  4. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/metrics/__main__.py +16 -143
  5. librelane-3.1.0.dev4/librelane/common/metrics/compare.py +156 -0
  6. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/misc.py +27 -0
  7. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/toolbox.py +5 -0
  8. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/config/__init__.py +4 -0
  9. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/config/__main__.py +4 -0
  10. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/config/config.py +10 -1
  11. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/config/flow.py +1 -1
  12. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/config/pdk_compat.py +22 -2
  13. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/config/preprocessor.py +24 -13
  14. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/config/removals.py +4 -0
  15. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/config/variable.py +93 -0
  16. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm/src/impl.sdc +2 -2
  17. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm/src/signoff.sdc +2 -2
  18. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/flows/cli.py +20 -18
  19. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/flows/synth_explore.py +1 -0
  20. librelane-3.1.0.dev4/librelane/pdk_hashes.yaml +4 -0
  21. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/base.sdc +2 -2
  22. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/check_antenna_properties.py +1 -1
  23. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/defutil.py +4 -1
  24. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/power_utils.py +10 -9
  25. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/common/io.tcl +25 -7
  26. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/drt.tcl +16 -1
  27. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/gpl.tcl +6 -0
  28. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/repair_design.tcl +3 -3
  29. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/repair_design_postgrt.tcl +1 -4
  30. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/pyosys/construct_abc_script.py +5 -5
  31. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/pyosys/synthesize.py +49 -22
  32. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/pyosys/ys_common.py +39 -5
  33. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/klayout.py +62 -29
  34. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/openroad.py +59 -8
  35. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/pyosys.py +72 -45
  36. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/step.py +1 -1
  37. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/tclstep.py +6 -4
  38. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/verilator.py +7 -6
  39. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/yosys.py +0 -12
  40. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/pyproject.toml +4 -4
  41. librelane-3.1.0.dev2/librelane/pdk_hashes.yaml +0 -3
  42. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/Readme.md +0 -0
  43. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/__init__.py +0 -0
  44. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/__version__.py +0 -0
  45. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/cli.py +0 -0
  46. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/drc.py +0 -0
  47. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/generic_dict.py +0 -0
  48. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/metrics/__init__.py +0 -0
  49. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/metrics/library.py +0 -0
  50. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/metrics/metric.py +0 -0
  51. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/metrics/util.py +0 -0
  52. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/ring_buffer.py +0 -0
  53. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/tcl.py +0 -0
  54. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/tpe.py +0 -0
  55. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/types.py +0 -0
  56. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/container.py +0 -0
  57. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/env_info.py +0 -0
  58. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/hold_eco_demo/config.yaml +0 -0
  59. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/hold_eco_demo/demo.v +0 -0
  60. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm/config.yaml +0 -0
  61. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm/pin_order.cfg +0 -0
  62. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm/src/spm.v +0 -0
  63. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm/verify/spm_tb.v +0 -0
  64. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm-user_project_wrapper/SPM_example.v +0 -0
  65. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm-user_project_wrapper/base_sdc_file.sdc +0 -0
  66. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm-user_project_wrapper/config-tut.json +0 -0
  67. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm-user_project_wrapper/config.json +0 -0
  68. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm-user_project_wrapper/defines.v +0 -0
  69. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm-user_project_wrapper/template.def +0 -0
  70. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm-user_project_wrapper/user_project_wrapper.v +0 -0
  71. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/flows/__init__.py +0 -0
  72. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/flows/builtins.py +0 -0
  73. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/flows/chip.py +0 -0
  74. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/flows/classic.py +0 -0
  75. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/flows/flow.py +0 -0
  76. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/flows/misc.py +0 -0
  77. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/flows/optimizing.py +0 -0
  78. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/flows/sequential.py +0 -0
  79. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/help/__main__.py +0 -0
  80. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/logging/__init__.py +0 -0
  81. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/logging/logger.py +0 -0
  82. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/plugins.py +0 -0
  83. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/py.typed +0 -0
  84. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/klayout/Readme.md +0 -0
  85. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/klayout/insert_cell.py +0 -0
  86. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/klayout/open_design.py +0 -0
  87. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/klayout/render.py +0 -0
  88. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/klayout/stream_out.py +0 -0
  89. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/klayout/xml_drc_report_to_json.py +0 -0
  90. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/klayout/xor.drc +0 -0
  91. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/Readme.md +0 -0
  92. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/common/read.tcl +0 -0
  93. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/def/antenna_check.tcl +0 -0
  94. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/def/mag.tcl +0 -0
  95. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/def/mag_gds.tcl +0 -0
  96. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/drc.tcl +0 -0
  97. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/extract_spice.tcl +0 -0
  98. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/gds/drc_batch.tcl +0 -0
  99. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/gds/erase_box.tcl +0 -0
  100. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/gds/extras_mag.tcl +0 -0
  101. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/gds/mag_with_pointers.tcl +0 -0
  102. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/get_bbox.tcl +0 -0
  103. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/lef/extras_maglef.tcl +0 -0
  104. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/lef/maglef.tcl +0 -0
  105. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/lef.tcl +0 -0
  106. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/open.tcl +0 -0
  107. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/spice_rcx.tcl +0 -0
  108. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/wrapper.tcl +0 -0
  109. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/netgen/setup.tcl +0 -0
  110. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/apply_def_template.py +0 -0
  111. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/cell_frequency.py +0 -0
  112. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/contextualize.py +0 -0
  113. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/diodes.py +0 -0
  114. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/disconnected_pins.py +0 -0
  115. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/eco_buffer.py +0 -0
  116. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/eco_diode.py +0 -0
  117. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/filter_unannotated.py +0 -0
  118. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/io_place.py +0 -0
  119. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/ioplace_parser/__init__.py +0 -0
  120. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/ioplace_parser/parse.py +0 -0
  121. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/label_macro_pins.py +0 -0
  122. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/lefutil.py +0 -0
  123. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/placers.py +0 -0
  124. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/random_place.py +0 -0
  125. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/reader.py +0 -0
  126. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/remove_buffers.py +0 -0
  127. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/snap_to_grid.py +0 -0
  128. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/wire_lengths.py +0 -0
  129. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/antenna_check.tcl +0 -0
  130. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/antenna_repair.tcl +0 -0
  131. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/buffer_list.tcl +0 -0
  132. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/common/dpl.tcl +0 -0
  133. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/common/dpl_cell_pad.tcl +0 -0
  134. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/common/grt.tcl +0 -0
  135. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/common/pad_cfg.tcl +0 -0
  136. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/common/pdn_cfg.tcl +0 -0
  137. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/common/resizer.tcl +0 -0
  138. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/common/set_global_connections.tcl +0 -0
  139. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/common/set_layer_adjustments.tcl +0 -0
  140. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/common/set_power_nets.tcl +0 -0
  141. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/common/set_rc.tcl +0 -0
  142. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/common/set_routing_layers.tcl +0 -0
  143. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/cts.tcl +0 -0
  144. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/cut_rows.tcl +0 -0
  145. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/dpl.tcl +0 -0
  146. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/dump_rc.tcl +0 -0
  147. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/fill.tcl +0 -0
  148. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/floorplan.tcl +0 -0
  149. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/grt.tcl +0 -0
  150. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/gui.tcl +0 -0
  151. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/insert_buffer.tcl +0 -0
  152. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/ioplacer.tcl +0 -0
  153. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/irdrop.tcl +0 -0
  154. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/pad.tcl +0 -0
  155. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/pdn.tcl +0 -0
  156. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/rcx.tcl +0 -0
  157. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/rsz_timing_postcts.tcl +0 -0
  158. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/rsz_timing_postgrt.tcl +0 -0
  159. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/sta/check_macro_instances.tcl +0 -0
  160. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/sta/corner.tcl +0 -0
  161. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/tapcell.tcl +0 -0
  162. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/ungpl.tcl +0 -0
  163. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/write_cdl.tcl +0 -0
  164. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/write_views.tcl +0 -0
  165. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/pyosys/json_header.py +0 -0
  166. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/tclsh/hello.tcl +0 -0
  167. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/state/__init__.py +0 -0
  168. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/state/__main__.py +0 -0
  169. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/state/design_format.py +0 -0
  170. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/state/state.py +0 -0
  171. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/__init__.py +0 -0
  172. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/__main__.py +0 -0
  173. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/checker.py +0 -0
  174. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/common_variables.py +0 -0
  175. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/magic.py +0 -0
  176. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/misc.py +0 -0
  177. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/netgen.py +0 -0
  178. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/odb.py +0 -0
  179. {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/openroad_alerts.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: librelane
3
- Version: 3.1.0.dev2
3
+ Version: 3.1.0.dev4
4
4
  Summary: An infrastructure for implementing chip design flows
5
5
  License-Expression: Apache-2.0
6
6
  Maintainer: Mohamed Gaber
@@ -12,8 +12,9 @@ Classifier: Programming Language :: Python :: 3.11
12
12
  Classifier: Programming Language :: Python :: 3.12
13
13
  Classifier: Programming Language :: Python :: 3.13
14
14
  Classifier: Programming Language :: Python :: 3.14
15
- Requires-Dist: ciel (>=2.3.1,<3)
16
- Requires-Dist: click (>=8,<8.3)
15
+ Classifier: Programming Language :: Python :: 3.15
16
+ Requires-Dist: ciel (>=3.2.0,<4)
17
+ Requires-Dist: click (>=8,<8.4)
17
18
  Requires-Dist: cloup (>=3.0.5,<4)
18
19
  Requires-Dist: deprecated (>=1.2.10,<2)
19
20
  Requires-Dist: httpx (>=0.22.0,<0.29)
@@ -23,7 +24,7 @@ Requires-Dist: lxml (>=4.9.0)
23
24
  Requires-Dist: psutil (>=5.9.0)
24
25
  Requires-Dist: pyyaml (>=5,<7)
25
26
  Requires-Dist: rapidfuzz (>=3.9.0,<4)
26
- Requires-Dist: rich (>=12,<15)
27
+ Requires-Dist: rich (>=12,<16)
27
28
  Requires-Dist: semver (>=3.0.2,<4)
28
29
  Requires-Dist: yamlcore (>=0.0.2,<0.1.0)
29
30
  Project-URL: Bug Tracker, https://github.com/librelane/librelane/issues
@@ -94,7 +94,7 @@ def run(
94
94
  )
95
95
  ctx.exit(1)
96
96
  elif isinstance(meta.flow, list):
97
- TargetFlow = SequentialFlow.make(meta.flow)
97
+ TargetFlow = SequentialFlow.Make(meta.flow)
98
98
  if meta.substituting_steps is not None:
99
99
  if meta.flow is None:
100
100
  err("config_file has substituting_steps set with no flow.")
@@ -33,6 +33,7 @@ from .misc import (
33
33
  get_librelane_root,
34
34
  get_script_dir,
35
35
  get_pdk_hash,
36
+ get_ciel_pdk_hash,
36
37
  slugify,
37
38
  protected,
38
39
  final,
@@ -1,3 +1,7 @@
1
+ # Copyright 2026 LibreLane Contributors
2
+ #
3
+ # Adapted from OpenLane 2
4
+ #
1
5
  # Copyright 2023 Efabless Corporation
2
6
  #
3
7
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,42 +24,16 @@ import tarfile
20
24
  import tempfile
21
25
  from io import BytesIO
22
26
  from decimal import Decimal
23
- from typing import Optional, Set, Tuple
27
+ from typing import Optional, Tuple
24
28
 
25
29
  import cloup
26
30
  import httpx
27
31
 
28
32
  from .util import MetricDiff, TableVerbosity
33
+ from .compare import compare_metric_directories, default_filter_set
29
34
  from ..misc import Filter, get_httpx_session, mkdirp
30
35
  from ..cli import formatter_settings, IntEnumChoice
31
36
 
32
- default_filter_set = [
33
- "design__*__area",
34
- "design__max_*",
35
- "design__lvs_error__count",
36
- "antenna__violating*",
37
- "clock__*",
38
- "ir__*",
39
- "power__*",
40
- "timing__*_vio__*",
41
- "timing*wns*",
42
- "timing*tns*",
43
- "*error*",
44
- "!*__iter:*",
45
- ]
46
-
47
- # passing_filter_set = [
48
- # "design__*__area",
49
- # "route__wirelength__max",
50
- # "design__instance__utilization",
51
- # "antenna__violating*",
52
- # "timing__*__ws",
53
- # "clock__skew__*",
54
- # "ir__*",
55
- # "power__*",
56
- # "!*__iter:*",
57
- # ]
58
-
59
37
 
60
38
  @cloup.group(
61
39
  no_args_is_help=True,
@@ -141,130 +119,25 @@ def compare(
141
119
  cli.add_command(compare)
142
120
 
143
121
 
144
- def _compare_metric_folders(
145
- filter_wildcards: Tuple[str, ...],
146
- table_verbosity: TableVerbosity,
147
- path_a: str,
148
- path_b: str,
149
- significant_figures: int,
150
- ) -> Tuple[str, str]: # (summary, table)
151
- a: Set[Tuple[str, str, str]] = set()
152
- b: Set[Tuple[str, str, str]] = set()
153
-
154
- def add_designs(in_dir: str, to_set: Set[Tuple[str, str, str]]):
155
- for file in os.listdir(in_dir):
156
- basename = os.path.basename(file)
157
- if not basename.endswith(".metrics.json"):
158
- continue
159
- basename = basename[: -len(".metrics.json")]
160
-
161
- # We have to rsplit, since ihp-sg13g2 contains a "-"
162
- parts = basename.rsplit("-", maxsplit=2)
163
- if len(parts) != 3:
164
- raise ValueError(
165
- f"Invalid filename {basename}: not in the format {{pdk}}-{{scl}}-{{design_name}}"
166
- )
167
- pdk, scl, design = parts
168
- to_set.add((pdk, scl, design))
169
-
170
- add_designs(path_a, a)
171
- add_designs(path_b, b)
172
-
173
- not_in_a = b - a
174
- not_in_b = a - b
175
- common = a.intersection(b)
176
- difference_report = ""
177
- for tup in not_in_a:
178
- pdk, scl, design = tup
179
- difference_report += f"* Results for a new test, `{'/'.join(tup)}`, detected.\n"
180
- for tup in not_in_b:
181
- pdk, scl, design = tup
182
- difference_report += (
183
- f"* ‼️ Results for `{'/'.join(tup)}` appear to be missing!\n"
184
- )
185
-
186
- final_filters = []
187
- for wildcard in filter_wildcards:
188
- if wildcard == "DEFAULT":
189
- final_filters += default_filter_set
190
- else:
191
- final_filters.append(wildcard)
192
-
193
- filter = Filter(final_filters)
194
- critical_change_report = ""
195
- tables = ""
196
- total_critical = 0
197
- for pdk, scl, design in sorted(common):
198
- metrics_a = json.load(
199
- open(
200
- os.path.join(path_a, f"{pdk}-{scl}-{design}.metrics.json"),
201
- encoding="utf8",
202
- ),
203
- parse_float=Decimal,
204
- )
205
-
206
- metrics_b = json.load(
207
- open(
208
- os.path.join(path_b, f"{pdk}-{scl}-{design}.metrics.json"),
209
- encoding="utf8",
210
- ),
211
- parse_float=Decimal,
212
- )
213
-
214
- diff = MetricDiff.from_metrics(
215
- metrics_a,
216
- metrics_b,
217
- significant_figures,
218
- filter=filter,
219
- )
220
-
221
- stats = diff.stats()
222
-
223
- total_critical += stats.critical
224
- if stats.critical > 0:
225
- critical_change_report += f" * `{pdk}/{scl}/{design}` \n"
226
- if table_verbosity != "NONE":
227
- rendered = diff.render_md(("corner", ""), table_verbosity)
228
- if rendered.strip() != "":
229
- tables += f"<details><summary><code>{pdk}/{scl}/{design}</code></summary>\n{rendered}\n</details>\n\n"
230
-
231
- if total_critical == 0:
232
- critical_change_report = (
233
- "* No changes to critical metrics were detected in analyzed designs.\n"
234
- + critical_change_report
235
- )
236
- else:
237
- critical_change_report = (
238
- "* **Changes to critical metrics were detected in the following designs:**\n"
239
- + critical_change_report
240
- )
241
-
242
- report = ""
243
- report += difference_report
244
- report += critical_change_report
245
-
246
- return report, tables.strip()
247
-
248
-
249
122
  @cloup.command(no_args_is_help=True)
250
123
  @common_opts
251
- @cloup.argument("metric_folders", nargs=2)
124
+ @cloup.argument("metric_directories", nargs=2)
252
125
  def compare_multiple(
253
126
  filter_wildcards: Tuple[str, ...],
254
127
  table_verbosity: TableVerbosity,
255
- metric_folders: Tuple[str, str],
128
+ metric_directories: Tuple[str, str],
256
129
  table_out: Optional[str],
257
130
  significant_figures: int,
258
131
  ):
259
132
  """
260
- Creates a small summary/report of the differences between two folders with
133
+ Creates a small summary/report of the differences between two directories with
261
134
  metrics files.
262
135
 
263
136
  The metrics files must be named in the format ``{pdk}-{scl}-{design}.metrics.json``.
264
137
  All other files are ignored.
265
138
  """
266
- path_a, path_b = metric_folders
267
- summary, tables = _compare_metric_folders(
139
+ path_a, path_b = metric_directories
140
+ summary, tables = compare_metric_directories(
268
141
  filter_wildcards, table_verbosity, path_a, path_b, significant_figures
269
142
  )
270
143
  print(summary)
@@ -309,7 +182,7 @@ cli.add_command(compare_multiple)
309
182
  help="A GitHub token to use to query the API and fetch the metrics. Not strictly required, but helps avoid rate-limiting.",
310
183
  )
311
184
  @common_opts
312
- @cloup.argument("metric_folder", nargs=1)
185
+ @cloup.argument("metric_directory", nargs=1)
313
186
  def compare_remote(
314
187
  filter_wildcards: Tuple[str, ...],
315
188
  table_verbosity: TableVerbosity,
@@ -317,13 +190,13 @@ def compare_remote(
317
190
  metric_repo: str,
318
191
  commit: Optional[str],
319
192
  token: str,
320
- metric_folder: str,
193
+ metric_directory: str,
321
194
  table_out: Optional[str],
322
195
  significant_figures: int,
323
196
  branch: str,
324
197
  ):
325
198
  """
326
- Creates a small summary/report of the differences between a folder and
199
+ Creates a small summary/report of the differences between a directory and
327
200
  a set of metrics stored in --metric-repo. Requires Internet access and
328
201
  access to GitHub.
329
202
 
@@ -379,11 +252,11 @@ def compare_remote(
379
252
  with open(final_path, "wb") as f:
380
253
  f.write(io.read())
381
254
 
382
- summary, tables = _compare_metric_folders(
255
+ summary, tables = compare_metric_directories(
383
256
  filter_wildcards,
384
257
  table_verbosity,
385
258
  d,
386
- metric_folder,
259
+ metric_directory,
387
260
  significant_figures,
388
261
  )
389
262
  print(summary)
@@ -0,0 +1,156 @@
1
+ # Copyright 2026 LibreLane Contributors
2
+ #
3
+ # Adapted from OpenLane 2
4
+ #
5
+ # Copyright 2023 Efabless Corporation
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ import os
19
+ import json
20
+ from decimal import Decimal
21
+ from typing import Set, Tuple
22
+
23
+ from .util import MetricDiff, TableVerbosity
24
+ from ..misc import Filter
25
+
26
+ default_filter_set = [
27
+ "design__*__area",
28
+ "design__max_*",
29
+ "design__lvs_error__count",
30
+ "antenna__violating*",
31
+ "clock__*",
32
+ "ir__*",
33
+ "power__*",
34
+ "timing__*_vio__*",
35
+ "timing*wns*",
36
+ "timing*tns*",
37
+ "*error*",
38
+ "!*__iter:*",
39
+ ]
40
+
41
+ # passing_filter_set = [
42
+ # "design__*__area",
43
+ # "route__wirelength__max",
44
+ # "design__instance__utilization",
45
+ # "antenna__violating*",
46
+ # "timing__*__ws",
47
+ # "clock__skew__*",
48
+ # "ir__*",
49
+ # "power__*",
50
+ # "!*__iter:*",
51
+ # ]
52
+
53
+
54
+ def compare_metric_directories(
55
+ filter_wildcards: Tuple[str, ...],
56
+ table_verbosity: TableVerbosity,
57
+ path_a: str,
58
+ path_b: str,
59
+ significant_figures: int,
60
+ ) -> Tuple[str, str]: # (summary, table)
61
+ a: Set[Tuple[str, str, str]] = set()
62
+ b: Set[Tuple[str, str, str]] = set()
63
+
64
+ def add_designs(in_dir: str, to_set: Set[Tuple[str, str, str]]):
65
+ for file in os.listdir(in_dir):
66
+ basename = os.path.basename(file)
67
+ if not basename.endswith(".metrics.json"):
68
+ continue
69
+ basename = basename[: -len(".metrics.json")]
70
+
71
+ # We have to rsplit, since ihp-sg13g2 contains a "-"
72
+ parts = basename.rsplit("-", maxsplit=2)
73
+ if len(parts) != 3:
74
+ raise ValueError(
75
+ f"Invalid filename {basename}: not in the format {{pdk}}-{{scl}}-{{design_name}}"
76
+ )
77
+ pdk, scl, design = parts
78
+ to_set.add((pdk, scl, design))
79
+
80
+ add_designs(path_a, a)
81
+ add_designs(path_b, b)
82
+
83
+ not_in_a = b - a
84
+ not_in_b = a - b
85
+ common = a.intersection(b)
86
+ difference_report = ""
87
+ for tup in not_in_a:
88
+ pdk, scl, design = tup
89
+ difference_report += f"* Results for a new test, `{'/'.join(tup)}`, detected.\n"
90
+ for tup in not_in_b:
91
+ pdk, scl, design = tup
92
+ difference_report += (
93
+ f"* ‼️ Results for `{'/'.join(tup)}` appear to be missing!\n"
94
+ )
95
+
96
+ final_filters = []
97
+ for wildcard in filter_wildcards:
98
+ if wildcard == "DEFAULT":
99
+ final_filters += default_filter_set
100
+ else:
101
+ final_filters.append(wildcard)
102
+
103
+ filter = Filter(final_filters)
104
+ critical_change_report = ""
105
+ tables = ""
106
+ total_critical = 0
107
+ for pdk, scl, design in sorted(common):
108
+ metrics_a = json.load(
109
+ open(
110
+ os.path.join(path_a, f"{pdk}-{scl}-{design}.metrics.json"),
111
+ encoding="utf8",
112
+ ),
113
+ parse_float=Decimal,
114
+ )
115
+
116
+ metrics_b = json.load(
117
+ open(
118
+ os.path.join(path_b, f"{pdk}-{scl}-{design}.metrics.json"),
119
+ encoding="utf8",
120
+ ),
121
+ parse_float=Decimal,
122
+ )
123
+
124
+ diff = MetricDiff.from_metrics(
125
+ metrics_a,
126
+ metrics_b,
127
+ significant_figures,
128
+ filter=filter,
129
+ )
130
+
131
+ stats = diff.stats()
132
+
133
+ total_critical += stats.critical
134
+ if stats.critical > 0:
135
+ critical_change_report += f" * `{pdk}/{scl}/{design}` \n"
136
+ if table_verbosity != "NONE":
137
+ rendered = diff.render_md(("corner", ""), table_verbosity)
138
+ if rendered.strip() != "":
139
+ tables += f"<details><summary><code>{pdk}/{scl}/{design}</code></summary>\n{rendered}\n</details>\n\n"
140
+
141
+ if total_critical == 0:
142
+ critical_change_report = (
143
+ "* No changes to critical metrics were detected in analyzed designs.\n"
144
+ + critical_change_report
145
+ )
146
+ else:
147
+ critical_change_report = (
148
+ "* **Changes to critical metrics were detected in the following designs:**\n"
149
+ + critical_change_report
150
+ )
151
+
152
+ report = ""
153
+ report += difference_report
154
+ report += critical_change_report
155
+
156
+ return report, tables.strip()
@@ -40,6 +40,7 @@ from typing import (
40
40
  )
41
41
 
42
42
  import httpx
43
+ from deprecated.sphinx import deprecated
43
44
 
44
45
  from ..__version__ import __version__
45
46
  from .types import AnyPath, Path
@@ -75,6 +76,11 @@ def get_script_dir() -> str:
75
76
  )
76
77
 
77
78
 
79
+ @deprecated(
80
+ version="3.1.0",
81
+ reason="Use get_ciel_pdk_hash, this method can force an exit in some codepaths",
82
+ action="once",
83
+ )
78
84
  def get_pdk_hash(pdk_variant) -> str:
79
85
  """
80
86
  Gets the PDK version hash confirmed compatible with this version of LibreLane.
@@ -92,6 +98,27 @@ def get_pdk_hash(pdk_variant) -> str:
92
98
  exit(1)
93
99
 
94
100
 
101
+ def get_ciel_pdk_hash(pdk_variant: str) -> str:
102
+ """
103
+ Gets the PDK version hash confirmed compatible with this version of LibreLane.
104
+
105
+ Requires ciel
106
+ """
107
+ import ciel
108
+
109
+ with open(os.path.join(get_librelane_root(), "pdk_hashes.yaml"), "r") as file:
110
+ pdk_hashes = yaml.safe_load(file)
111
+
112
+ pdk_family = ciel.resolve_pdk_family(pdk_variant)
113
+
114
+ if pdk_family not in pdk_hashes:
115
+ raise ValueError(
116
+ f"LibreLane does not have a validated version for Ciel PDK family {pdk_family}."
117
+ )
118
+
119
+ return pdk_hashes[pdk_family]
120
+
121
+
95
122
  # The following code snippet has been adapted under the following license:
96
123
  #
97
124
  # Copyright (c) Django Software Foundation and individual contributors.
@@ -367,6 +367,11 @@ class Toolbox(object):
367
367
  warn(f"Failed to generate preview: {e}.")
368
368
  return None
369
369
 
370
+ @deprecated(
371
+ version="3.1.0",
372
+ reason="No longer needed by internal LibreLane steps and will be removed in LibreLane 4.0.",
373
+ action="once",
374
+ )
370
375
  def remove_cells_from_lib(
371
376
  self,
372
377
  input_lib_files: FrozenSet[str],
@@ -1,3 +1,7 @@
1
+ # Copyright 2025 LibreLane Contributors
2
+ #
3
+ # Adapted from OpenLane 2
4
+ #
1
5
  # Copyright 2023 Efabless Corporation
2
6
  #
3
7
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,3 +1,7 @@
1
+ # Copyright 2025 LibreLane Contributors
2
+ #
3
+ # Adapted from OpenLane 2
4
+ #
1
5
  # Copyright 2023 Efabless Corporation
2
6
  #
3
7
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,3 +1,7 @@
1
+ # Copyright 2025 LibreLane Contributors
2
+ #
3
+ # Adapted from OpenLane 2
4
+ #
1
5
  # Copyright 2023 Efabless Corporation
2
6
  #
3
7
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -678,6 +682,7 @@ class Config(GenericImmutableDict[str, Any]):
678
682
  raw,
679
683
  only_extract_process_info=True,
680
684
  design_dir=design_dir,
685
+ version=meta.version,
681
686
  )
682
687
  )
683
688
 
@@ -715,6 +720,7 @@ class Config(GenericImmutableDict[str, Any]):
715
720
  scl=mutable[SpecialKeys.scl],
716
721
  pad=mutable.get(SpecialKeys.pad, pad),
717
722
  design_dir=design_dir,
723
+ version=meta.version,
718
724
  )
719
725
  )
720
726
 
@@ -775,6 +781,9 @@ class Config(GenericImmutableDict[str, Any]):
775
781
  tcl_config,
776
782
  only_extract_process_info=True,
777
783
  design_dir=design_dir,
784
+ # Tcl is version 1 by default I believe; on par with JSON
785
+ # also this path is deprecated anyways
786
+ version=1,
778
787
  )
779
788
 
780
789
  pdk = process_info.get(SpecialKeys.pdk) or pdk
@@ -810,7 +819,7 @@ class Config(GenericImmutableDict[str, Any]):
810
819
  try:
811
820
  import ciel
812
821
 
813
- pdk_root = ciel.get_ciel_home(pdk_root)
822
+ pdk_root = str(ciel.get_ciel_home(pdk_root))
814
823
  except ImportError:
815
824
  raise ValueError(
816
825
  "The pdk_root argument is required as Ciel is not installed."
@@ -1,6 +1,6 @@
1
1
  # Copyright 2025 LibreLane Contributors
2
2
  #
3
- # Adapted from OpenLane
3
+ # Adapted from OpenLane 2
4
4
  #
5
5
  # Copyright 2023 Efabless Corporation
6
6
  #
@@ -1,3 +1,7 @@
1
+ # Copyright 2025 LibreLane Contributors
2
+ #
3
+ # Adapted from OpenLane 2
4
+ #
1
5
  # Copyright 2023-2025 Efabless Corporation
2
6
  #
3
7
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -325,9 +329,9 @@ def migrate_old_config(config: Mapping[str, Any]) -> Dict[str, Any]:
325
329
  if "CLOCK_TRANSITION_CONSTRAINT" not in config:
326
330
  new["CLOCK_TRANSITION_CONSTRAINT"] = 0.15
327
331
  if "TIME_DERATING_CONSTRAINT" not in config:
328
- new["TIME_DERATING_CONSTRAINT"] = 5
332
+ new["TIME_DERATING_CONSTRAINT"] = 5.0
329
333
  if "IO_DELAY_CONSTRAINT" not in config:
330
- new["IO_DELAY_CONSTRAINT"] = 20
334
+ new["IO_DELAY_CONSTRAINT"] = 20.0
331
335
 
332
336
  # Unspecififed is fine
333
337
  # if "FP_IO_MIN_DISTANCE" not in config:
@@ -350,4 +354,20 @@ def migrate_old_config(config: Mapping[str, Any]) -> Dict[str, Any]:
350
354
  if "HEURISTIC_ANTENNA_THRESHOLD" not in config:
351
355
  new["HEURISTIC_ANTENNA_THRESHOLD"] = 130
352
356
 
357
+ # x7. KLAYOUT_DRC_OPTIONS to defines
358
+ if new["PDK"].startswith("sky130") and "KLAYOUT_DRC_OPTIONS" in new:
359
+ tcl_dict = new["KLAYOUT_DRC_OPTIONS"]
360
+ ws_rx = re.compile(r"\s+")
361
+ del new["KLAYOUT_DRC_OPTIONS"]
362
+ new["KLAYOUT_DRC_DEFINES"] = {}
363
+ # deliberately not checking for bad dicts or dicts that require quoting
364
+ # it's already overkill to assume people modified the PDK files here
365
+ #
366
+ # if someone complains we can parse a Tcl dict later
367
+ tcl_dict_entries = ws_rx.split(tcl_dict)
368
+ while len(tcl_dict_entries):
369
+ key = tcl_dict_entries.pop(0)
370
+ value = tcl_dict_entries.pop(0)
371
+ new["KLAYOUT_DRC_DEFINES"][key] = value
372
+
353
373
  return new