librelane 3.0.0.dev49__tar.gz → 3.0.0.dev51__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 (175) hide show
  1. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/PKG-INFO +1 -1
  2. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/__main__.py +2 -2
  3. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/__version__.py +15 -10
  4. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/drc.py +1 -0
  5. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/config/flow.py +1 -1
  6. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/config/removals.py +1 -0
  7. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/flows/cli.py +21 -11
  8. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/klayout/stream_out.py +8 -0
  9. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/def/mag_gds.tcl +4 -0
  10. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/antenna_repair.tcl +9 -5
  11. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/common/grt.tcl +1 -3
  12. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/drt.tcl +10 -7
  13. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/pyosys/synthesize.py +25 -9
  14. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/state/state.py +12 -10
  15. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/common_variables.py +12 -0
  16. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/klayout.py +11 -10
  17. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/magic.py +7 -1
  18. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/odb.py +2 -2
  19. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/openroad.py +12 -0
  20. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/pyosys.py +42 -38
  21. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/yosys.py +0 -11
  22. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/pyproject.toml +1 -1
  23. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/Readme.md +0 -0
  24. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/__init__.py +0 -0
  25. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/__init__.py +0 -0
  26. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/cli.py +0 -0
  27. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/generic_dict.py +0 -0
  28. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/metrics/__init__.py +0 -0
  29. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/metrics/__main__.py +0 -0
  30. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/metrics/library.py +0 -0
  31. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/metrics/metric.py +0 -0
  32. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/metrics/util.py +0 -0
  33. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/misc.py +0 -0
  34. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/ring_buffer.py +0 -0
  35. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/tcl.py +0 -0
  36. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/toolbox.py +0 -0
  37. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/tpe.py +0 -0
  38. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/types.py +0 -0
  39. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/config/__init__.py +0 -0
  40. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/config/__main__.py +0 -0
  41. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/config/config.py +0 -0
  42. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/config/pdk_compat.py +0 -0
  43. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/config/preprocessor.py +0 -0
  44. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/config/variable.py +0 -0
  45. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/container.py +0 -0
  46. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/env_info.py +0 -0
  47. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/hold_eco_demo/config.yaml +0 -0
  48. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/hold_eco_demo/demo.v +0 -0
  49. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm/config.yaml +0 -0
  50. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm/pin_order.cfg +0 -0
  51. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm/src/impl.sdc +0 -0
  52. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm/src/signoff.sdc +0 -0
  53. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm/src/spm.v +0 -0
  54. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm/verify/spm_tb.v +0 -0
  55. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm-user_project_wrapper/SPM_example.v +0 -0
  56. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm-user_project_wrapper/base_sdc_file.sdc +0 -0
  57. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm-user_project_wrapper/config-tut.json +0 -0
  58. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm-user_project_wrapper/config.json +0 -0
  59. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm-user_project_wrapper/defines.v +0 -0
  60. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm-user_project_wrapper/template.def +0 -0
  61. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm-user_project_wrapper/user_project_wrapper.v +0 -0
  62. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/flows/__init__.py +0 -0
  63. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/flows/builtins.py +0 -0
  64. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/flows/chip.py +0 -0
  65. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/flows/classic.py +0 -0
  66. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/flows/flow.py +0 -0
  67. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/flows/misc.py +0 -0
  68. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/flows/optimizing.py +0 -0
  69. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/flows/sequential.py +0 -0
  70. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/flows/synth_explore.py +0 -0
  71. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/help/__main__.py +0 -0
  72. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/logging/__init__.py +0 -0
  73. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/logging/logger.py +0 -0
  74. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/pdk_hashes.yaml +0 -0
  75. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/plugins.py +0 -0
  76. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/py.typed +0 -0
  77. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/base.sdc +0 -0
  78. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/klayout/Readme.md +0 -0
  79. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/klayout/open_design.py +0 -0
  80. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/klayout/render.py +0 -0
  81. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/klayout/xml_drc_report_to_json.py +0 -0
  82. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/klayout/xor.drc +0 -0
  83. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/Readme.md +0 -0
  84. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/common/read.tcl +0 -0
  85. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/def/antenna_check.tcl +0 -0
  86. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/def/mag.tcl +0 -0
  87. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/drc.tcl +0 -0
  88. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/extract_spice.tcl +0 -0
  89. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/gds/drc_batch.tcl +0 -0
  90. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/gds/erase_box.tcl +0 -0
  91. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/gds/extras_mag.tcl +0 -0
  92. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/gds/mag_with_pointers.tcl +0 -0
  93. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/get_bbox.tcl +0 -0
  94. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/lef/extras_maglef.tcl +0 -0
  95. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/lef/maglef.tcl +0 -0
  96. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/lef.tcl +0 -0
  97. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/open.tcl +0 -0
  98. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/wrapper.tcl +0 -0
  99. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/netgen/setup.tcl +0 -0
  100. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/apply_def_template.py +0 -0
  101. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/cell_frequency.py +0 -0
  102. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/check_antenna_properties.py +0 -0
  103. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/contextualize.py +0 -0
  104. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/defutil.py +0 -0
  105. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/diodes.py +0 -0
  106. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/disconnected_pins.py +0 -0
  107. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/eco_buffer.py +0 -0
  108. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/eco_diode.py +0 -0
  109. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/filter_unannotated.py +0 -0
  110. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/io_place.py +0 -0
  111. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/ioplace_parser/__init__.py +0 -0
  112. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/ioplace_parser/parse.py +0 -0
  113. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/label_macro_pins.py +0 -0
  114. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/lefutil.py +0 -0
  115. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/placers.py +0 -0
  116. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/power_utils.py +0 -0
  117. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/random_place.py +0 -0
  118. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/reader.py +0 -0
  119. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/remove_buffers.py +0 -0
  120. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/snap_to_grid.py +0 -0
  121. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/wire_lengths.py +0 -0
  122. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/antenna_check.tcl +0 -0
  123. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/buffer_list.tcl +0 -0
  124. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/common/dpl.tcl +0 -0
  125. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/common/dpl_cell_pad.tcl +0 -0
  126. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/common/io.tcl +0 -0
  127. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/common/pad_cfg.tcl +0 -0
  128. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/common/pdn_cfg.tcl +0 -0
  129. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/common/resizer.tcl +0 -0
  130. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/common/set_global_connections.tcl +0 -0
  131. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/common/set_layer_adjustments.tcl +0 -0
  132. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/common/set_power_nets.tcl +0 -0
  133. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/common/set_rc.tcl +0 -0
  134. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/common/set_routing_layers.tcl +0 -0
  135. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/cts.tcl +0 -0
  136. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/cut_rows.tcl +0 -0
  137. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/dpl.tcl +0 -0
  138. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/dump_rc.tcl +0 -0
  139. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/fill.tcl +0 -0
  140. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/floorplan.tcl +0 -0
  141. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/gpl.tcl +0 -0
  142. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/grt.tcl +0 -0
  143. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/gui.tcl +0 -0
  144. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/insert_buffer.tcl +0 -0
  145. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/ioplacer.tcl +0 -0
  146. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/irdrop.tcl +0 -0
  147. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/pad.tcl +0 -0
  148. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/pdn.tcl +0 -0
  149. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/rcx.tcl +0 -0
  150. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/repair_design.tcl +0 -0
  151. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/repair_design_postgrt.tcl +0 -0
  152. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/rsz_timing_postcts.tcl +0 -0
  153. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/rsz_timing_postgrt.tcl +0 -0
  154. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/sta/check_macro_instances.tcl +0 -0
  155. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/sta/corner.tcl +0 -0
  156. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/tapcell.tcl +0 -0
  157. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/ungpl.tcl +0 -0
  158. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/write_cdl.tcl +0 -0
  159. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/write_views.tcl +0 -0
  160. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/pyosys/construct_abc_script.py +0 -0
  161. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/pyosys/json_header.py +0 -0
  162. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/pyosys/ys_common.py +0 -0
  163. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/tclsh/hello.tcl +0 -0
  164. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/state/__init__.py +0 -0
  165. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/state/__main__.py +0 -0
  166. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/state/design_format.py +0 -0
  167. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/__init__.py +0 -0
  168. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/__main__.py +0 -0
  169. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/checker.py +0 -0
  170. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/misc.py +0 -0
  171. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/netgen.py +0 -0
  172. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/openroad_alerts.py +0 -0
  173. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/step.py +0 -0
  174. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/tclstep.py +0 -0
  175. {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/verilator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: librelane
3
- Version: 3.0.0.dev49
3
+ Version: 3.0.0.dev51
4
4
  Summary: An infrastructure for implementing chip design flows
5
5
  License-Expression: Apache-2.0
6
6
  Maintainer: Mohamed Gaber
@@ -122,13 +122,13 @@ def run(
122
122
  err(f"Invalid initial state element override: '{element}'.")
123
123
  ctx.exit(1)
124
124
  df_id, path = element_split
125
- design_format = DesignFormat.by_id(df_id)
125
+ design_format = DesignFormat.factory.get(df_id)
126
126
  if design_format is None:
127
127
  err(f"Invalid design format ID: '{df_id}'.")
128
128
  ctx.exit(1)
129
129
  overrides[design_format] = common.Path(path)
130
130
 
131
- with_initial_state = with_initial_state.__class__(
131
+ with_initial_state = type(with_initial_state)(
132
132
  with_initial_state,
133
133
  overrides=overrides,
134
134
  )
@@ -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");
@@ -11,32 +15,33 @@
11
15
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
16
  # See the License for the specific language governing permissions and
13
17
  # limitations under the License.
14
- import os
15
- import importlib.metadata
16
18
  import sys
19
+ from pathlib import Path
20
+ import importlib.metadata
21
+
22
+ __file_dir__ = Path(__file__).absolute().parent
17
23
 
18
24
 
19
- def __get_version():
25
+ def __get_version(pkg_name: str):
20
26
  try:
21
27
  return importlib.metadata.version(__package__ or __name__)
22
28
  except importlib.metadata.PackageNotFoundError:
23
29
  import re
24
30
 
25
31
  rx = re.compile(r"version\s*=\s*\"([^\"]+)\"")
26
- librelane_directory = os.path.dirname(
27
- os.path.dirname(os.path.abspath(__file__))
28
- )
29
- pyproject_path = os.path.join(librelane_directory, "pyproject.toml")
32
+ pyproject_toml_dir = __file_dir__.parent
33
+ pyproject_path = pyproject_toml_dir / "pyproject.toml"
30
34
  try:
31
- match = rx.search(open(pyproject_path, encoding="utf8").read())
35
+ with open(pyproject_path, encoding="utf8") as f:
36
+ match = rx.search(f.read())
32
37
  assert match is not None, "pyproject.toml found, but without a version"
33
38
  return match[1]
34
39
  except FileNotFoundError:
35
- print("Warning: Failed to extract LibreLane version.", file=sys.stderr)
40
+ print(f"Warning: Failed to extract {pkg_name} version.", file=sys.stderr)
36
41
  return "UNKNOWN"
37
42
 
38
43
 
39
- __version__ = __get_version()
44
+ __version__ = __get_version("librelane")
40
45
 
41
46
 
42
47
  if __name__ == "__main__":
@@ -225,6 +225,7 @@ class DRC:
225
225
  violations: Dict[str, Violation] = {}
226
226
  last_bounding_box: Optional[BoundingBox] = None
227
227
  lex = shlex.shlex(feedback.read(), posix=True)
228
+ lex.wordchars = lex.wordchars + "-"
228
229
  components = list(lex)
229
230
  while len(components):
230
231
  instruction = components.pop(0)
@@ -297,7 +297,7 @@ scl_variables = [
297
297
  Variable(
298
298
  "DIODE_CELL",
299
299
  Optional[str],
300
- "Defines a diode cell used to fix antenna violations, in the format {name}/{port}. If not defined, steps should not attempt to repair the antenna effect by inserting diode cells.",
300
+ "Defines a diode cell used to fix antenna violations, in the format `{cell}/{port}`. If not defined, steps should not attempt to repair the antenna effect by inserting diode cells.",
301
301
  pdk=True,
302
302
  ),
303
303
  Variable(
@@ -44,4 +44,5 @@ removed_variables: Dict[str, str] = {
44
44
  "FP_CONTEXT_LEF": "To be implemented.",
45
45
  "SYNLIG_DEFER": "Synlig replaced with Slang.",
46
46
  "VDD_PIN_VOLTAGE": "Information should be obtained from dotlib files.",
47
+ "LIGHTER_DFF_MAP": "Lighter has been replaced with Yosys' built-in clock gate functionality.",
47
48
  }
@@ -17,9 +17,10 @@
17
17
  # limitations under the License.
18
18
  import os
19
19
  import sys
20
+ import json
20
21
  from functools import partial, wraps
21
22
  from concurrent.futures import ThreadPoolExecutor
22
- from typing import Optional, Union
23
+ from typing import Optional, Union, Tuple
23
24
 
24
25
  from click import (
25
26
  Context,
@@ -146,18 +147,27 @@ def set_worker_count_cb(
146
147
  def initial_state_cb(
147
148
  ctx: Context,
148
149
  param: Parameter,
149
- value: Optional[str],
150
+ value: Tuple[str],
150
151
  ):
151
- if value is None:
152
+ if len(value) == 0:
152
153
  return None
153
154
 
155
+ raw = {}
156
+ for state_json in value:
157
+ try:
158
+ with open(state_json, encoding="utf8") as f:
159
+ state_dict = json.load(f)
160
+ if not isinstance(state_dict, dict):
161
+ raise ValueError(f"JSON data {value} is not a dictionary")
162
+ raw.update(state_dict)
163
+ except json.JSONDecodeError as e:
164
+ err(f"Invalid JSON file: {e}")
165
+ ctx.exit(-1)
166
+ except Exception as e:
167
+ err(f"Failed to read initial state: {e}")
168
+ ctx.exit(-1)
154
169
  try:
155
- initial_state_str = open(value, encoding="utf8").read()
156
- except Exception as e:
157
- err(f"Failed to read initial state: {e}")
158
- ctx.exit(-1)
159
- try:
160
- initial_state = State.loads(initial_state_str, validate_path=True)
170
+ initial_state = State.load(raw, validate_path=True)
161
171
  except InvalidState as e:
162
172
  err(e)
163
173
  ctx.exit(-1)
@@ -289,9 +299,9 @@ def cloup_flow_opts(
289
299
  file_okay=True,
290
300
  dir_okay=False,
291
301
  ),
292
- default=None,
302
+ multiple=True,
293
303
  callback=initial_state_cb,
294
- help="Use this JSON file as an initial state. If this is not specified, the latest `state_out.json` of the run directory will be used. If none exist, an empty initial state is created.",
304
+ help="Use these JSON files as an initial state. If multiple are provided, they are merged with keys in later files overriding keys in prior files. If none are specified, the latest `state_out.json` of the run directory will be used. If none exist, an empty initial state is created.",
295
305
  )(f)
296
306
  f = o(
297
307
  "--design-dir",
@@ -1,4 +1,8 @@
1
1
  #!/usr/bin/env python3
2
+ # Copyright 2025 LibreLane Contributors
3
+ #
4
+ # Adapted from OpenLane
5
+ #
2
6
  # Copyright (c) 2021-2022 Efabless Corporation
3
7
  #
4
8
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -116,6 +120,10 @@ def stream_out(
116
120
  layout_options.lefdef_config.read_lef_with_def = False
117
121
  layout_options.lefdef_config.lef_files = list(input_lefs)
118
122
  layout_options.lefdef_config.map_file = lym
123
+ # Don't produce user properties
124
+ layout_options.lefdef_config.net_property_name = None
125
+ layout_options.lefdef_config.instance_property_name = None
126
+ layout_options.lefdef_config.pin_property_name = None
119
127
 
120
128
  cell_conflict_resolution = {
121
129
  "AddToCell": pya.LoadLayoutOptions.CellConflictResolution.AddToCell,
@@ -98,5 +98,9 @@ if { $::env(MAGIC_GDS_POLYGON_SUBCELLS) } {
98
98
  gds polygon subcells true
99
99
  }
100
100
 
101
+ if { $::env(MAGIC_GDS_MERGE) } {
102
+ gds merge yes
103
+ }
104
+
101
105
  gds write $::env(SAVE_MAG_GDS)
102
106
  puts "\[INFO\] GDS Write Complete"
@@ -13,14 +13,18 @@
13
13
  # limitations under the License.
14
14
  source $::env(SCRIPTS_DIR)/openroad/common/io.tcl
15
15
  read_current_odb
16
- source $::env(SCRIPTS_DIR)/openroad/common/dpl_cell_pad.tcl
17
16
 
18
- set_propagated_clock [all_clocks]
17
+ set diode_cell [lindex [split $::env(DIODE_CELL) "/"] 0]
19
18
 
20
- source $::env(SCRIPTS_DIR)/openroad/common/grt.tcl
19
+ set arg_list [list]
20
+ lappend arg_list $diode_cell
21
+ lappend arg_list -iterations $::env(GRT_ANTENNA_REPAIR_ITERS)
22
+ lappend arg_list -ratio_margin $::env(GRT_ANTENNA_REPAIR_MARGIN)
23
+ append_if_flag arg_list GRT_ALLOW_CONGESTION -allow_congestion
24
+ append_if_flag arg_list GRT_ANTENNA_REPAIR_JUMPER_ONLY -jumper_only
25
+ append_if_flag arg_list GRT_ANTENNA_REPAIR_DIODE_ONLY -diode_only
21
26
 
22
- set diode_split [split $::env(DIODE_CELL) "/"]
23
- repair_antennas "[lindex $diode_split 0]" -iterations $::env(GRT_ANTENNA_REPAIR_ITERS) -ratio_margin $::env(GRT_ANTENNA_REPAIR_MARGIN)
27
+ log_cmd repair_antennas {*}$arg_list
24
28
 
25
29
  source $::env(SCRIPTS_DIR)/openroad/common/set_rc.tcl
26
30
  estimate_parasitics -global_routing
@@ -23,9 +23,7 @@ if { ![info exists ::grt_preamble] } {
23
23
  set arg_list [list]
24
24
  lappend arg_list -congestion_iterations $::env(GRT_OVERFLOW_ITERS)
25
25
  lappend arg_list -verbose
26
- if { $::env(GRT_ALLOW_CONGESTION) == 1 } {
27
- lappend arg_list -allow_congestion
28
- }
26
+ append_if_flag arg_list GRT_ALLOW_CONGESTION -allow_congestion
29
27
 
30
28
  log_cmd global_route {*}$arg_list
31
29
 
@@ -30,11 +30,6 @@ proc drt_run {i args} {
30
30
  source $::env(SCRIPTS_DIR)/openroad/common/io.tcl
31
31
  read_current_odb
32
32
 
33
- # We need to call grt once, so that options like allow_congestion can be set for repair_antennas.
34
- # This needs to be done before drt. If grt is called after drt, repair_antennas only uses the
35
- # routing information from grt for fixing the antennas = useless.
36
- source $::env(SCRIPTS_DIR)/openroad/common/grt.tcl
37
-
38
33
  set_thread_count $::env(DRT_THREADS)
39
34
 
40
35
  set drc_report_iter_step_arg ""
@@ -65,10 +60,18 @@ if { ![info exists ::env(DIODE_CELL)] } {
65
60
  } else {
66
61
  set diode_cell [lindex [split $::env(DIODE_CELL) "/"] 0]
67
62
 
63
+ set arg_list [list]
64
+ lappend arg_list $diode_cell
65
+ lappend arg_list -ratio_margin $::env(GRT_ANTENNA_REPAIR_MARGIN)
66
+ append_if_flag arg_list GRT_ALLOW_CONGESTION -allow_congestion
67
+ append_if_flag arg_list DRT_ANTENNA_REPAIR_JUMPER_ONLY -jumper_only
68
+ append_if_flag arg_list DRT_ANTENNA_REPAIR_DIODE_ONLY -diode_only
69
+
68
70
  while {$i <= $::env(DRT_ANTENNA_REPAIR_ITERS) && [log_cmd check_antennas]} {
69
71
  puts "\[INFO\] Running antenna repair iteration $i…"
70
- set diodes_inserted [log_cmd repair_antennas $diode_cell -ratio_margin $::env(DRT_ANTENNA_REPAIR_MARGIN)]
71
- if {$diodes_inserted} {
72
+ set diodes_inserted [log_cmd repair_antennas {*}$arg_list]
73
+
74
+ if {$diodes_inserted || $::env(DRT_ANTENNA_REPAIR_JUMPER_ONLY)} {
72
75
  drt_run $i {*}$drt_args
73
76
  } else {
74
77
  puts "\[INFO\] No diodes inserted. Ending antenna repair iterations."
@@ -240,13 +240,11 @@ def librelane_synth(
240
240
  @click.option("--output", type=click.Path(exists=False, dir_okay=False), required=True)
241
241
  @click.option("--config-in", type=click.Path(exists=True), required=True)
242
242
  @click.option("--extra-in", type=click.Path(exists=True), required=True)
243
- @click.option("--lighter-dff-map", type=click.Path(exists=True), required=False)
244
243
  @click.argument("inputs", nargs=-1)
245
244
  def synthesize(
246
245
  output,
247
246
  config_in,
248
247
  extra_in,
249
- lighter_dff_map,
250
248
  inputs,
251
249
  ):
252
250
  config = json.load(open(config_in))
@@ -304,7 +302,8 @@ def synthesize(
304
302
  )
305
303
  elif vhdl_files := config.get("VHDL_FILES"):
306
304
  d.run_pass("plugin", "-i", "ghdl")
307
- d.run_pass("ghdl", *vhdl_files, "-e", config["DESIGN_NAME"])
305
+ ghdl_arguments = config["GHDL_ARGUMENTS"] or []
306
+ d.run_pass("ghdl", *ghdl_arguments, *vhdl_files, "-e", config["DESIGN_NAME"])
308
307
  else:
309
308
  ys.log_error(
310
309
  "Script called inappropriately: config must include either VERILOG_FILES or VHDL_FILES.",
@@ -335,7 +334,7 @@ def synthesize(
335
334
 
336
335
  if config["SYNTH_ELABORATE_ONLY"]:
337
336
  librelane_proc(d, report_dir)
338
- if config["SYNTH_ELABORATE_FLATTEN"]:
337
+ if config["SYNTH_HIERARCHY_MODE"] in ["deferred_flatten", "flatten"]:
339
338
  d.run_pass("flatten", "-noscopeinfo")
340
339
  d.run_pass("setattr", "-set", "keep", "1")
341
340
  d.run_pass("splitnets")
@@ -368,11 +367,6 @@ def synthesize(
368
367
  ys.log(f"[INFO] Applying {adder_type} mapping from '{mapping}'…")
369
368
  d.run_pass("techmap", "-map", mapping)
370
369
 
371
- if mapping := lighter_dff_map:
372
- ys.log(f"[INFO] Using Lighter with mapping '{mapping}'…")
373
- d.run_pass("plugin", "-i", "lighter")
374
- d.run_pass("reg_clock_gating", "-map", mapping)
375
-
376
370
  librelane_synth(
377
371
  d,
378
372
  config["DESIGN_NAME"],
@@ -422,6 +416,28 @@ def synthesize(
422
416
  ys.log(f"[INFO] Applying extra mappings from '{extra_mapping}'…")
423
417
  d.run_pass("techmap", "-map", extra_mapping)
424
418
 
419
+ if config["SYNTH_CLOCKGATE_MIN_WIDTH"] is not None: # 0 is a valid value and falsey
420
+ cg_min_width = config["SYNTH_CLOCKGATE_MIN_WIDTH"]
421
+ posedge = ()
422
+ negedge = ()
423
+ if posedge_raw := config["SYNTH_CLOCKGATE_POSEDGE_ICG"]:
424
+ cell, ce, clk, gclk = posedge_raw.rsplit("/", maxsplit=4)
425
+ posedge = ("-pos", cell, f"{ce}:{clk}:{gclk}")
426
+ if negedge_raw := config["SYNTH_CLOCKGATE_NEGEDGE_ICG"]:
427
+ cell, ce, clk, gclk = negedge_raw.rsplit("/", maxsplit=4)
428
+ negedge = ("-neg", cell, f"{ce}:{clk}:{gclk}")
429
+ if len(posedge) == 0 and len(negedge) == 0:
430
+ ys.log(
431
+ "[WARNING] A minimum width for clock gating is set; but no ICGs are configured."
432
+ )
433
+ d.run_pass(
434
+ "clockgate",
435
+ "-min_net_size",
436
+ str(cg_min_width),
437
+ *posedge,
438
+ *negedge,
439
+ )
440
+
425
441
  dfflibmap_args = []
426
442
  for lib in libs:
427
443
  dfflibmap_args.extend(["-liberty", lib])
@@ -253,7 +253,7 @@ class State(GenericImmutableDict[str, StateElement]):
253
253
  self._walk(self.to_raw_dict(metrics=False), "", visit=visitor)
254
254
 
255
255
  @classmethod
256
- def __loads_recursive(
256
+ def __load_recursive(
257
257
  Self,
258
258
  views: Dict,
259
259
  validate_path: bool = True,
@@ -267,7 +267,7 @@ class State(GenericImmutableDict[str, StateElement]):
267
267
  continue
268
268
 
269
269
  if isinstance(value, dict):
270
- target[key] = Self.__loads_recursive(
270
+ target[key] = Self.__load_recursive(
271
271
  value,
272
272
  validate_path,
273
273
  key_path=current_key_path,
@@ -280,6 +280,15 @@ class State(GenericImmutableDict[str, StateElement]):
280
280
  target[key] = Path(value)
281
281
  return target
282
282
 
283
+ @classmethod
284
+ def load(Self, dict_in: dict, validate_path: bool = True) -> "State":
285
+ metrics = dict_in.get("metrics")
286
+ if metrics is not None:
287
+ del dict_in["metrics"]
288
+
289
+ views = Self.__load_recursive(dict_in, validate_path)
290
+ return Self(views, metrics=metrics)
291
+
283
292
  @classmethod
284
293
  def loads(Self, json_in: str, validate_path: bool = True) -> "State":
285
294
  try:
@@ -290,14 +299,7 @@ class State(GenericImmutableDict[str, StateElement]):
290
299
  if not isinstance(raw, dict):
291
300
  raise InvalidState("Failed to load state: JSON result is not a dictionary")
292
301
 
293
- metrics = raw.get("metrics")
294
- if metrics is not None:
295
- del raw["metrics"]
296
-
297
- views = Self.__loads_recursive(raw, validate_path)
298
- state = Self(views, metrics=metrics)
299
-
300
- return state
302
+ return Self.load(raw, validate_path=validate_path)
301
303
 
302
304
  def __mapping_to_html_rec(
303
305
  self,
@@ -423,6 +423,18 @@ grt_variables = routing_layer_variables + [
423
423
  units="%",
424
424
  deprecated_names=["GRT_ANT_MARGIN", "GRT_ANTENNA_MARGIN"],
425
425
  ),
426
+ Variable(
427
+ "GRT_ANTENNA_REPAIR_JUMPER_ONLY",
428
+ bool,
429
+ "Only use jumpers to fix antenna violations. Cannot be used in conjunction with GRT_ANTENNA_REPAIR_DIODE_ONLY.",
430
+ default=False,
431
+ ),
432
+ Variable(
433
+ "GRT_ANTENNA_REPAIR_DIODE_ONLY",
434
+ bool,
435
+ "Only use antenna diodes to fix antenna violations. Cannot be used in conjunction with GRT_ANTENNA_REPAIR_JUMPER_ONLY.",
436
+ default=False,
437
+ ),
426
438
  ]
427
439
 
428
440
  rsz_variables = dpl_variables + [
@@ -413,7 +413,7 @@ class DRC(KLayoutStep):
413
413
  metrics_updates = self.run_sky130(state_in, **kwargs)
414
414
  elif self.config["PDK"] in ["gf180mcuA", "gf180mcuB", "gf180mcuC", "gf180mcuD"]:
415
415
  metrics_updates = self.run_gf180mcu(state_in, **kwargs)
416
- elif self.config["PDK"] in ["ihp-sg13g2"]:
416
+ elif self.config["PDK"] in ["ihp-sg13g2", "ihp-sg13cmos5l"]:
417
417
  metrics_updates = self.run_ihp_sg13g2(state_in, **kwargs)
418
418
  else:
419
419
  metrics_updates = self.run_generic(state_in, **kwargs)
@@ -821,7 +821,7 @@ class LVS(KLayoutStep):
821
821
  def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
822
822
  metrics_updates: MetricsUpdate = {}
823
823
  views_updates: ViewsUpdate = {}
824
- if self.config["PDK"] in ["ihp-sg13g2"]:
824
+ if self.config["PDK"] in ["ihp-sg13g2", "ihp-sg13cmos5l"]:
825
825
  views_updates, metrics_updates = self.run_ihp_sg13g2(state_in, **kwargs)
826
826
  else:
827
827
  self.warn(
@@ -855,7 +855,7 @@ class SealRing(KLayoutStep):
855
855
  def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
856
856
  metrics_updates: MetricsUpdate = {}
857
857
  views_updates: ViewsUpdate = {}
858
- if self.config["PDK"] in ["ihp-sg13g2"]:
858
+ if self.config["PDK"] in ["ihp-sg13g2", "ihp-sg13cmos5l"]:
859
859
  views_updates, metrics_updates = self.run_ihp_sg13g2(state_in, **kwargs)
860
860
  else:
861
861
  views_updates, metrics_updates = self.run_generic(state_in, **kwargs)
@@ -983,7 +983,14 @@ class Filler(KLayoutStep):
983
983
  def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
984
984
  metrics_updates: MetricsUpdate = {}
985
985
  views_updates: ViewsUpdate = {}
986
- if self.config["PDK"] in ["ihp-sg13g2"]:
986
+
987
+ if not self.config["KLAYOUT_FILLER_SCRIPT"]:
988
+ self.warn(
989
+ f"KLAYOUT_FILLER_SCRIPT is unset. KLayout.Filler may not be supported for the {self.config['PDK']} PDK. This step will be skipped."
990
+ )
991
+ return views_updates, metrics_updates
992
+
993
+ if self.config["PDK"] in ["ihp-sg13g2", "ihp-sg13cmos5l"]:
987
994
  views_updates, metrics_updates = self.run_ihp_sg13g2(state_in, **kwargs)
988
995
  else:
989
996
  views_updates, metrics_updates = self.run_generic(state_in, **kwargs)
@@ -996,12 +1003,6 @@ class Filler(KLayoutStep):
996
1003
  views_updates: ViewsUpdate = {}
997
1004
  kwargs, env = self.extract_env(kwargs)
998
1005
 
999
- if not self.config["KLAYOUT_FILLER_SCRIPT"]:
1000
- self.warn(
1001
- f"KLAYOUT_FILLER_SCRIPT is unset. KLayout.Filler may not be supported for the {self.config['PDK']} PDK. This step will be skipped."
1002
- )
1003
- return views_updates, {}
1004
-
1005
1006
  input_gds = state_in[DesignFormat.GDS]
1006
1007
  assert isinstance(input_gds, Path)
1007
1008
  output_gds = os.path.join(
@@ -98,7 +98,7 @@ class MagicStep(TclStep):
98
98
  "MAGIC_DEF_LABELS",
99
99
  bool,
100
100
  "A flag to choose whether labels are read with DEF files or not. From magic docs: \"The '-labels' option to the 'def read' command causes each net in the NETS and SPECIALNETS sections of the DEF file to be annotated with a label having the net name as the label text.\" If LVS fails, try disabling this option.",
101
- default=True,
101
+ default=False,
102
102
  ),
103
103
  Variable(
104
104
  "MAGIC_GDS_POLYGON_SUBCELLS",
@@ -106,6 +106,12 @@ class MagicStep(TclStep):
106
106
  'A flag to enable polygon subcells in magic for gds read potentially speeding up magic. From magic docs: "Put non-Manhattan polygons. This prevents interations with other polygons on the same plane and so reduces tile splitting."',
107
107
  default=False,
108
108
  ),
109
+ Variable(
110
+ "MAGIC_GDS_MERGE",
111
+ bool,
112
+ 'A flag to enable merging of connected tiles into polygons during gds write. From magic docs: "Depending on the tile geometry, this may make the output file up to four times smaller, at the cost of speed in generating the output file."',
113
+ default=True,
114
+ ),
109
115
  Variable(
110
116
  "MAGIC_DEF_NO_BLOCKAGES",
111
117
  bool,
@@ -93,8 +93,8 @@ class OdbpyStep(Step):
93
93
  str(state_in[DesignFormat.ODB]),
94
94
  ]
95
95
 
96
- env["PYTHONPATH"] = (
97
- f'{os.path.join(get_script_dir(), "odbpy")}:{env.get("PYTHONPATH")}'
96
+ env["PYTHONPATH"] = ":".join(
97
+ (env.get("PYTHONPATH", ""), os.path.join(get_script_dir(), "odbpy"))
98
98
  )
99
99
  check = False
100
100
  if "check" in kwargs:
@@ -1934,6 +1934,18 @@ class DetailedRouting(OpenROADStep):
1934
1934
  units="%",
1935
1935
  deprecated_names=["DRT_ANTENNA_MARGIN"],
1936
1936
  ),
1937
+ Variable(
1938
+ "DRT_ANTENNA_REPAIR_JUMPER_ONLY",
1939
+ bool,
1940
+ "Only use jumpers to fix antenna violations. Cannot be used in conjunction with DRT_ANTENNA_REPAIR_DIODE_ONLY.",
1941
+ default=False,
1942
+ ),
1943
+ Variable(
1944
+ "DRT_ANTENNA_REPAIR_DIODE_ONLY",
1945
+ bool,
1946
+ "Only use antenna diodes to fix antenna violations. Cannot be used in conjunction with DRT_ANTENNA_REPAIR_JUMPER_ONLY.",
1947
+ default=False,
1948
+ ),
1937
1949
  Variable(
1938
1950
  "DRT_SAVE_DRC_REPORT_ITERS",
1939
1951
  Optional[int],
@@ -22,7 +22,6 @@ import sys
22
22
  import json
23
23
  import fnmatch
24
24
  import shutil
25
- import subprocess
26
25
  from decimal import Decimal
27
26
  from abc import abstractmethod
28
27
  from typing import List, Literal, Optional, Set, Tuple
@@ -147,6 +146,18 @@ DesignFormat(
147
146
  ).register()
148
147
 
149
148
 
149
+ def _validate_icg(
150
+ variable: Variable, input: Optional[str], warning_list_ref: List[str]
151
+ ):
152
+ if input is not None:
153
+ components = input.split("/")
154
+ if len(components) != 4:
155
+ raise ValueError(
156
+ f"{variable.name} must be in the form '<cell>/<ce>/<clk>/<gclk>'"
157
+ )
158
+ return input
159
+
160
+
150
161
  class PyosysStep(Step):
151
162
  config_vars = [
152
163
  Variable(
@@ -196,15 +207,24 @@ class PyosysStep(Step):
196
207
  pdk=True,
197
208
  ),
198
209
  Variable(
199
- "USE_LIGHTER",
200
- bool,
201
- "Activates Lighter, an experimental plugin that attempts to optimize clock-gated flip-flops.",
202
- default=False,
210
+ "SYNTH_CLOCKGATE_MIN_WIDTH",
211
+ Optional[int],
212
+ "If set to a value, a group of flip-flops with size >= SYNTH_CLOCKGATE_MIN_WIDTH and an enable signal are clock-gated instead.",
213
+ deprecated_names=[("USE_LIGHTER", lambda x: 1 if x else None)],
203
214
  ),
204
215
  Variable(
205
- "LIGHTER_DFF_MAP",
206
- Optional[Path],
207
- "An override to the custom DFF map file provided for the given SCL by Lighter.",
216
+ "SYNTH_CLOCKGATE_POSEDGE_ICG",
217
+ Optional[str],
218
+ "The integrated clock gate cell used for positive-edge flip-flops, in the format `<cell>/<active-high clock enable port>/<clk port>/<gated clk port>`.",
219
+ pdk=True,
220
+ validator=_validate_icg,
221
+ ),
222
+ Variable(
223
+ "SYNTH_CLOCKGATE_NEGEDGE_ICG",
224
+ Optional[str],
225
+ "The integrated clock gate cell used for positive-edge flip-flops, in the format `<cell>/<active-high clock enable port>/<clk port>/<gated clk port>`.",
226
+ pdk=True,
227
+ validator=_validate_icg,
208
228
  ),
209
229
  Variable(
210
230
  "YOSYS_LOG_LEVEL",
@@ -253,12 +273,14 @@ class PyosysStep(Step):
253
273
 
254
274
  def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
255
275
  cmd = self.get_command(state_in)
276
+ kwargs, env = self.extract_env(kwargs)
256
277
  # HACK: Get Colab working
257
278
  if "google.colab" in sys.modules:
258
- kwargs, env = self.extract_env(kwargs)
259
279
  env.pop("PATH", "")
260
- kwargs["env"] = env
261
- subprocess_result = super().run_subprocess(cmd, **kwargs)
280
+ env["PYTHONPATH"] = ":".join(
281
+ (env.get("PYTHONPATH", ""), os.path.join(get_script_dir(), "pyosys"))
282
+ )
283
+ subprocess_result = super().run_subprocess(cmd, env=env, **kwargs)
262
284
  return {}, subprocess_result["generated_metrics"]
263
285
 
264
286
 
@@ -477,7 +499,9 @@ class SynthesisCommon(VerilogStep):
477
499
  (
478
500
  "SYNTH_NO_FLAT",
479
501
  lambda x: "deferred_flatten" if x else "flatten",
480
- )
502
+ ),
503
+ ("SYNTH_ELABORATE_FLATTEN", lambda x: "flatten" if x else "keep"),
504
+ ("SYNTH_FLAT_TOP", lambda x: "flatten" if x else "keep"),
481
505
  ],
482
506
  ),
483
507
  Variable(
@@ -518,13 +542,6 @@ class SynthesisCommon(VerilogStep):
518
542
  '"Elaborate" the design only without attempting any logic mapping. Useful when dealing with structural Verilog netlists.',
519
543
  default=False,
520
544
  ),
521
- Variable(
522
- "SYNTH_ELABORATE_FLATTEN",
523
- bool,
524
- "If `SYNTH_ELABORATE_ONLY` is specified, this variable controls whether or not the top level should be flattened.",
525
- default=True,
526
- deprecated_names=["SYNTH_FLAT_TOP"],
527
- ),
528
545
  Variable(
529
546
  "SYNTH_MUL_BOOTH",
530
547
  bool,
@@ -564,25 +581,7 @@ class SynthesisCommon(VerilogStep):
564
581
  self.step_dir,
565
582
  f"{self.config['DESIGN_NAME']}.{DesignFormat.NETLIST.extension}",
566
583
  )
567
- cmd = super().get_command(state_in)
568
- if self.config["USE_LIGHTER"]:
569
- lighter_dff_map = self.config["LIGHTER_DFF_MAP"]
570
- if lighter_dff_map is None:
571
- scl = self.config["STD_CELL_LIBRARY"]
572
- try:
573
- raw = subprocess.check_output(
574
- ["lighter_files", scl], encoding="utf8"
575
- )
576
- files = raw.strip().splitlines()
577
- lighter_dff_map = Path(files[0])
578
- except FileNotFoundError:
579
- self.warn(
580
- "Lighter not found or not set up with LibreLane: If you're using a manual Lighter install, try setting LIGHTER_DFF_MAP explicitly."
581
- )
582
- except subprocess.CalledProcessError:
583
- self.warn(f"{scl} not supported by Lighter.")
584
- cmd.extend(["--lighter-dff-map", lighter_dff_map])
585
- return cmd + ["--output", out_file]
584
+ return super().get_command(state_in) + ["--output", out_file]
586
585
 
587
586
  def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
588
587
  out_file = os.path.join(
@@ -704,4 +703,9 @@ class VHDLSynthesis(SynthesisCommon):
704
703
  List[Path],
705
704
  "The paths of the design's VHDL files.",
706
705
  ),
706
+ Variable(
707
+ "GHDL_ARGUMENTS",
708
+ Optional[List[str]],
709
+ "Pass arguments to the ghdl frontend.",
710
+ ),
707
711
  ]