librelane 2.4.0.dev0__tar.gz → 2.4.0.dev3__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 (169) hide show
  1. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/PKG-INFO +28 -9
  2. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/Readme.md +24 -5
  3. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/__main__.py +6 -1
  4. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/config/config.py +2 -2
  5. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/config/variable.py +12 -7
  6. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/container.py +1 -1
  7. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/env_info.py +1 -1
  8. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/flows/classic.py +1 -4
  9. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/flows/optimizing.py +1 -1
  10. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/odbpy/defutil.py +6 -7
  11. librelane-2.4.0.dev3/librelane/scripts/odbpy/eco_buffer.py +181 -0
  12. librelane-2.4.0.dev3/librelane/scripts/odbpy/eco_diode.py +139 -0
  13. librelane-2.4.0.dev3/librelane/scripts/odbpy/ioplace_parser/__init__.py +23 -0
  14. librelane-2.4.0.dev3/librelane/scripts/odbpy/ioplace_parser/parse.py +147 -0
  15. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/odbpy/reader.py +15 -11
  16. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/common/io.tcl +66 -2
  17. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/steps/__init__.py +1 -1
  18. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/steps/__main__.py +1 -1
  19. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/steps/odb.py +160 -24
  20. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/steps/openroad.py +7 -2
  21. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/pyproject.toml +2 -3
  22. librelane-2.4.0.dev0/librelane/scripts/odbpy/exception_codes.py +0 -17
  23. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/__init__.py +0 -0
  24. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/__version__.py +0 -0
  25. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/common/__init__.py +0 -0
  26. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/common/cli.py +0 -0
  27. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/common/drc.py +0 -0
  28. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/common/generic_dict.py +0 -0
  29. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/common/metrics/__init__.py +0 -0
  30. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/common/metrics/__main__.py +0 -0
  31. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/common/metrics/library.py +0 -0
  32. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/common/metrics/metric.py +0 -0
  33. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/common/metrics/util.py +0 -0
  34. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/common/misc.py +0 -0
  35. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/common/ring_buffer.py +0 -0
  36. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/common/tcl.py +0 -0
  37. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/common/toolbox.py +0 -0
  38. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/common/tpe.py +0 -0
  39. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/common/types.py +0 -0
  40. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/config/__init__.py +0 -0
  41. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/config/__main__.py +0 -0
  42. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/config/flow.py +0 -0
  43. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/config/pdk_compat.py +0 -0
  44. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/config/preprocessor.py +0 -0
  45. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/config/removals.py +0 -0
  46. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/examples/spm/config.yaml +0 -0
  47. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/examples/spm/pin_order.cfg +0 -0
  48. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/examples/spm/src/impl.sdc +0 -0
  49. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/examples/spm/src/signoff.sdc +0 -0
  50. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/examples/spm/src/spm.v +0 -0
  51. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/examples/spm/verify/spm_tb.v +0 -0
  52. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/examples/spm-user_project_wrapper/SPM_example.v +0 -0
  53. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/examples/spm-user_project_wrapper/base_sdc_file.sdc +0 -0
  54. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/examples/spm-user_project_wrapper/config-tut.json +0 -0
  55. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/examples/spm-user_project_wrapper/config.json +0 -0
  56. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/examples/spm-user_project_wrapper/defines.v +0 -0
  57. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/examples/spm-user_project_wrapper/template.def +0 -0
  58. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/examples/spm-user_project_wrapper/user_project_wrapper.v +0 -0
  59. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/flows/__init__.py +0 -0
  60. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/flows/builtins.py +0 -0
  61. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/flows/cli.py +0 -0
  62. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/flows/flow.py +0 -0
  63. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/flows/misc.py +0 -0
  64. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/flows/sequential.py +0 -0
  65. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/flows/synth_explore.py +0 -0
  66. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/logging/__init__.py +0 -0
  67. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/logging/logger.py +0 -0
  68. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/open_pdks_rev +0 -0
  69. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/plugins.py +0 -0
  70. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/py.typed +0 -0
  71. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/base.sdc +0 -0
  72. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/klayout/Readme.md +0 -0
  73. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/klayout/open_design.py +0 -0
  74. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/klayout/render.py +0 -0
  75. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/klayout/stream_out.py +0 -0
  76. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/klayout/xml_drc_report_to_json.py +0 -0
  77. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/klayout/xor.drc +0 -0
  78. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/magic/Readme.md +0 -0
  79. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/magic/common/read.tcl +0 -0
  80. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/magic/def/antenna_check.tcl +0 -0
  81. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/magic/def/mag.tcl +0 -0
  82. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/magic/def/mag_gds.tcl +0 -0
  83. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/magic/drc.tcl +0 -0
  84. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/magic/extract_spice.tcl +0 -0
  85. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/magic/gds/drc_batch.tcl +0 -0
  86. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/magic/gds/erase_box.tcl +0 -0
  87. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/magic/gds/extras_mag.tcl +0 -0
  88. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/magic/gds/mag_with_pointers.tcl +0 -0
  89. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/magic/get_bbox.tcl +0 -0
  90. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/magic/lef/extras_maglef.tcl +0 -0
  91. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/magic/lef/maglef.tcl +0 -0
  92. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/magic/lef.tcl +0 -0
  93. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/magic/open.tcl +0 -0
  94. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/magic/wrapper.tcl +0 -0
  95. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/netgen/setup.tcl +0 -0
  96. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/odbpy/apply_def_template.py +0 -0
  97. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/odbpy/cell_frequency.py +0 -0
  98. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/odbpy/check_antenna_properties.py +0 -0
  99. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/odbpy/contextualize.py +0 -0
  100. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/odbpy/diodes.py +0 -0
  101. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/odbpy/disconnected_pins.py +0 -0
  102. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/odbpy/filter_unannotated.py +0 -0
  103. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/odbpy/io_place.py +0 -0
  104. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/odbpy/label_macro_pins.py +0 -0
  105. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/odbpy/lefutil.py +0 -0
  106. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/odbpy/placers.py +0 -0
  107. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/odbpy/power_utils.py +0 -0
  108. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/odbpy/random_place.py +0 -0
  109. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/odbpy/remove_buffers.py +0 -0
  110. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/odbpy/snap_to_grid.py +0 -0
  111. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/odbpy/wire_lengths.py +0 -0
  112. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/antenna_check.tcl +0 -0
  113. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/antenna_repair.tcl +0 -0
  114. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/basic_mp.tcl +0 -0
  115. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/buffer_list.tcl +0 -0
  116. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/common/dpl.tcl +0 -0
  117. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/common/dpl_cell_pad.tcl +0 -0
  118. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/common/grt.tcl +0 -0
  119. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/common/pdn_cfg.tcl +0 -0
  120. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/common/resizer.tcl +0 -0
  121. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/common/set_global_connections.tcl +0 -0
  122. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/common/set_layer_adjustments.tcl +0 -0
  123. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/common/set_power_nets.tcl +0 -0
  124. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/common/set_rc.tcl +0 -0
  125. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/common/set_routing_layers.tcl +0 -0
  126. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/cts.tcl +0 -0
  127. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/cut_rows.tcl +0 -0
  128. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/dpl.tcl +0 -0
  129. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/drt.tcl +0 -0
  130. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/fill.tcl +0 -0
  131. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/floorplan.tcl +0 -0
  132. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/gpl.tcl +0 -0
  133. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/grt.tcl +0 -0
  134. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/gui.tcl +0 -0
  135. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/insert_buffer.tcl +0 -0
  136. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/ioplacer.tcl +0 -0
  137. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/irdrop.tcl +0 -0
  138. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/pdn.tcl +0 -0
  139. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/rcx.tcl +0 -0
  140. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/repair_design.tcl +0 -0
  141. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/repair_design_postgrt.tcl +0 -0
  142. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/rsz_timing_postcts.tcl +0 -0
  143. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/rsz_timing_postgrt.tcl +0 -0
  144. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/sta/check_macro_instances.tcl +0 -0
  145. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/sta/corner.tcl +0 -0
  146. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/tapcell.tcl +0 -0
  147. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/openroad/write_views.tcl +0 -0
  148. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/pyosys/construct_abc_script.py +0 -0
  149. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/pyosys/json_header.py +0 -0
  150. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/pyosys/synthesize.py +0 -0
  151. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/pyosys/ys_common.py +0 -0
  152. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/scripts/tclsh/hello.tcl +0 -0
  153. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/state/__init__.py +0 -0
  154. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/state/__main__.py +0 -0
  155. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/state/design_format.py +0 -0
  156. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/state/state.py +0 -0
  157. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/steps/checker.py +0 -0
  158. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/steps/common_variables.py +0 -0
  159. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/steps/cvc_rv.py +0 -0
  160. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/steps/klayout.py +0 -0
  161. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/steps/magic.py +0 -0
  162. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/steps/misc.py +0 -0
  163. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/steps/netgen.py +0 -0
  164. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/steps/openroad_alerts.py +0 -0
  165. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/steps/pyosys.py +0 -0
  166. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/steps/step.py +0 -0
  167. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/steps/tclstep.py +0 -0
  168. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/steps/verilator.py +0 -0
  169. {librelane-2.4.0.dev0 → librelane-2.4.0.dev3}/librelane/steps/yosys.py +0 -0
@@ -1,7 +1,8 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.1
2
2
  Name: librelane
3
- Version: 2.4.0.dev0
3
+ Version: 2.4.0.dev3
4
4
  Summary: An infrastructure for implementing chip design flows
5
+ Home-page: https://github.com/librelane/librelane
5
6
  License: Apache-2.0
6
7
  Author: Mohamed Gaber
7
8
  Author-email: me@donn.website
@@ -19,8 +20,7 @@ Requires-Dist: click (>=8,<9)
19
20
  Requires-Dist: cloup (>=3.0.5,<4)
20
21
  Requires-Dist: deprecated (>=1.2.10,<2)
21
22
  Requires-Dist: httpx (>=0.22.0,<0.29)
22
- Requires-Dist: ioplace-parser (>=0.3.0,<0.5.0)
23
- Requires-Dist: klayout (>=0.29.0,<0.30.0)
23
+ Requires-Dist: klayout (>=0.29.0,<0.31.0)
24
24
  Requires-Dist: libparse (>=0.3.1,<1)
25
25
  Requires-Dist: lxml (>=4.9.0)
26
26
  Requires-Dist: psutil (>=5.9.0)
@@ -49,8 +49,10 @@ Description-Content-Type: text/markdown
49
49
 
50
50
  LibreLane is an ASIC infrastructure library based on several components including
51
51
  OpenROAD, Yosys, Magic, Netgen, CVC, KLayout and a number of custom scripts for
52
- design exploration and optimization, currently developed and maintained by the
53
- American University in Cairo Open Hardware Lab (AUCOHL.)
52
+ design exploration and optimization, currently developed and maintained by
53
+ members and affiliates of the
54
+ [American University in Cairo Open Hardware Lab](https://github.com/aucohl)
55
+ under the stewardship of the [FOSSi Foundation](https://fossi-foundation.org).
54
56
 
55
57
  A reference flow, "Classic", performs all ASIC implementation steps from RTL all
56
58
  the way down to GDSII.
@@ -142,10 +144,27 @@ If you use LibreLane in your research, please cite the following paper.
142
144
 
143
145
  ## License and Legal Info
144
146
 
145
- LibreLane is a trademark of the FOSSi Foundation.
147
+ LibreLane is a trademark of the [FOSSi Foundation](https://fossi-foundation.org).
146
148
 
149
+ LibreLane code and binaries are available under
147
150
  [The Apache License, version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt).
148
151
 
149
- LibreLane is based on OpenLane 2.0 by Efabless Corporation
150
- (https://github.com/efabless/openlane2) under the same license.
152
+ LibreLane is based on [OpenLane 2](https://github.com/efabless/openlane2)
153
+ by Efabless Corporation:
154
+
155
+ ```
156
+ Copyright 2022-2025 Efabless Corporation
157
+
158
+ Licensed under the Apache License, Version 2.0 (the "License");
159
+ you may not use this file except in compliance with the License.
160
+ You may obtain a copy of the License at
161
+
162
+ http://www.apache.org/licenses/LICENSE-2.0
163
+
164
+ Unless required by applicable law or agreed to in writing, software
165
+ distributed under the License is distributed on an "AS IS" BASIS,
166
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
167
+ See the License for the specific language governing permissions and
168
+ limitations under the License.
169
+ ```
151
170
 
@@ -14,8 +14,10 @@
14
14
 
15
15
  LibreLane is an ASIC infrastructure library based on several components including
16
16
  OpenROAD, Yosys, Magic, Netgen, CVC, KLayout and a number of custom scripts for
17
- design exploration and optimization, currently developed and maintained by the
18
- American University in Cairo Open Hardware Lab (AUCOHL.)
17
+ design exploration and optimization, currently developed and maintained by
18
+ members and affiliates of the
19
+ [American University in Cairo Open Hardware Lab](https://github.com/aucohl)
20
+ under the stewardship of the [FOSSi Foundation](https://fossi-foundation.org).
19
21
 
20
22
  A reference flow, "Classic", performs all ASIC implementation steps from RTL all
21
23
  the way down to GDSII.
@@ -107,9 +109,26 @@ If you use LibreLane in your research, please cite the following paper.
107
109
 
108
110
  ## License and Legal Info
109
111
 
110
- LibreLane is a trademark of the FOSSi Foundation.
112
+ LibreLane is a trademark of the [FOSSi Foundation](https://fossi-foundation.org).
111
113
 
114
+ LibreLane code and binaries are available under
112
115
  [The Apache License, version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt).
113
116
 
114
- LibreLane is based on OpenLane 2.0 by Efabless Corporation
115
- (https://github.com/efabless/openlane2) under the same license.
117
+ LibreLane is based on [OpenLane 2](https://github.com/efabless/openlane2)
118
+ by Efabless Corporation:
119
+
120
+ ```
121
+ Copyright 2022-2025 Efabless Corporation
122
+
123
+ Licensed under the Apache License, Version 2.0 (the "License");
124
+ you may not use this file except in compliance with the License.
125
+ You may obtain a copy of the License at
126
+
127
+ http://www.apache.org/licenses/LICENSE-2.0
128
+
129
+ Unless required by applicable law or agreed to in writing, software
130
+ distributed under the License is distributed on an "AS IS" BASIS,
131
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132
+ See the License for the specific language governing permissions and
133
+ limitations under the License.
134
+ ```
@@ -1,3 +1,7 @@
1
+ # Copyright 2025 The American University in Cairo
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");
@@ -202,7 +206,8 @@ def print_version(ctx: click.Context, param: click.Parameter, value: bool):
202
206
  f"""
203
207
  LibreLane v{__version__}
204
208
 
205
- Copyright ©2020-2023 Efabless Corporation and other contributors.
209
+ Copyright ©2020-2025 Efabless Corporation, The American University in
210
+ Cairo, and other contributors.
206
211
 
207
212
  Available under the Apache License, version 2. Included with the source code,
208
213
  but you can also get a copy at https://www.apache.org/licenses/LICENSE-2.0
@@ -102,7 +102,7 @@ class PassedDirectoryError(ValueError):
102
102
  def __init__(self, config: AnyPath) -> None:
103
103
  self.config = str(config)
104
104
  super().__init__(
105
- "Passing design directories as arguments is unsupported in LibreLane 2 or higher: please pass the configuration file(s) directly."
105
+ "Passing design directories as arguments is unsupported in LibreLane: please pass the configuration file(s) directly."
106
106
  )
107
107
 
108
108
 
@@ -960,7 +960,7 @@ class Config(GenericImmutableDict[str, Any]):
960
960
  pass
961
961
  if not isinstance(dis, int) or dis in [1, 2, 5] or dis > 6:
962
962
  errors.append(
963
- f"DIODE_INSERTION_STRATEGY '{dis}' is not available in LibreLane 2 or higher. See 'Migrating DIODE_INSERTION_STRATEGY' in the docs for more info."
963
+ f"DIODE_INSERTION_STRATEGY '{dis}' is not available in LibreLane 2.0 or higher. See 'Migrating DIODE_INSERTION_STRATEGY' in the docs for more info."
964
964
  )
965
965
  else:
966
966
  warnings.append(
@@ -238,7 +238,7 @@ def some_of(t: Type[Any]) -> Type[Any]:
238
238
  return new_union # type: ignore
239
239
 
240
240
 
241
- def repr_type(t: Type[Any]) -> str: # pragma: no cover
241
+ def repr_type(t: Type[Any], for_document: bool = False) -> str: # pragma: no cover
242
242
  optional = is_optional(t)
243
243
  some = some_of(t)
244
244
 
@@ -247,18 +247,25 @@ def repr_type(t: Type[Any]) -> str: # pragma: no cover
247
247
  else:
248
248
  type_string = str(some)
249
249
 
250
+ if is_dataclass(t):
251
+ type_string = (
252
+ f"{{class}}`{some.__qualname__} <{some.__module__}.{some.__qualname__}>`"
253
+ )
254
+
255
+ separator = "|<br />" if for_document else "|"
256
+
250
257
  if inspect.isclass(some) and issubclass(some, Enum):
251
- type_string = "|".join([str(e.name) for e in some])
258
+ type_string = separator.join([str(e.name) for e in some])
252
259
  type_string = f"`{type_string}`"
253
260
  else:
254
261
  origin, args = get_origin(some), get_args(some)
255
262
  if origin is not None:
256
263
  if origin == Union:
257
264
  arg_strings = [repr_type(arg) for arg in args]
258
- type_string = "|".join(arg_strings)
265
+ type_string = separator.join(arg_strings)
259
266
  type_string = f"({type_string})"
260
267
  elif origin == Literal:
261
- return "|".join([repr(arg) for arg in args])
268
+ return separator.join([repr(arg) for arg in args])
262
269
  else:
263
270
  arg_strings = [repr_type(arg) for arg in args]
264
271
  type_string = f"{type_string}[{', '.join(arg_strings)}]"
@@ -377,9 +384,7 @@ class Variable:
377
384
  for easier wrapping by web browsers/PDF renderers/what have you
378
385
  :returns: A pretty Markdown string representation of the Variable's type.
379
386
  """
380
- if for_document:
381
- return repr_type(self.type).replace("|", "|<br />")
382
- return repr_type(self.type)
387
+ return repr_type(self.type, for_document=for_document)
383
388
 
384
389
  def desc_repr_md(self) -> str: # pragma: no cover
385
390
  """
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- ## This file is internal to LibreLane 2 and is not part of the API.
15
+ ## This file is internal to LibreLane and is not part of the API.
16
16
  import os
17
17
  import re
18
18
  import uuid
@@ -18,7 +18,7 @@
18
18
  # environment surveys. Please ensure all code as compatible as possible
19
19
  # with ancient versions of Python.
20
20
 
21
- ## This file is internal to LibreLane 2 and is not part of the API.
21
+ ## This file is internal to LibreLane and is not part of the API.
22
22
  import os
23
23
  import re
24
24
  import sys
@@ -30,11 +30,8 @@ from ..steps import (
30
30
  @Flow.factory.register()
31
31
  class Classic(SequentialFlow):
32
32
  """
33
- **Note: While LibreLane 2 has a stable release, the default flow is in beta
34
- pending silicon validation. Use at your own risk.**
35
-
36
33
  A flow of type :class:`librelane.flows.SequentialFlow` that is the most
37
- similar to the original LibreLane 1.0 flow, running the Verilog RTL through
34
+ similar to the original OpenLane flow, running the Verilog RTL through
38
35
  Yosys, OpenROAD, KLayout and Magic to produce a valid GDSII for simpler designs.
39
36
 
40
37
  This is the default when using LibreLane via the command-line.
@@ -23,7 +23,7 @@ from ..steps import Step, Yosys, OpenROAD, StepError
23
23
  from ..logging import get_log_level, set_log_level, LogLevels, success, info
24
24
 
25
25
 
26
- # "Optimizing" is a custom demo flow to show what's possible with non-sequential Flows in LibreLane 2+.
26
+ # "Optimizing" is a custom demo flow to show what's possible with non-sequential Flows in LibreLan
27
27
  # It works across two steps:
28
28
  # * The Synthesis Exploration - tries multiple synthesis strategies in *parallel*.
29
29
  # The best-performing strategy in terms of minimizing the area makes it to the next stage.
@@ -21,7 +21,6 @@ from decimal import Decimal
21
21
 
22
22
  from reader import click_odb, click
23
23
  from typing import Tuple, List
24
- from exception_codes import METAL_LAYER_ERROR, FORMAT_ERROR, NOT_FOUND_ERROR
25
24
 
26
25
 
27
26
  @click.group()
@@ -481,7 +480,7 @@ def parse_obstructions(obstructions) -> List[Tuple[str, List[int]]]:
481
480
  f"[ERROR] Incorrectly formatted input {obs}.\n Format: layer llx lly urx ury, ...",
482
481
  file=sys.stderr,
483
482
  )
484
- sys.exit(FORMAT_ERROR)
483
+ sys.exit(1)
485
484
  else:
486
485
  layer = m.group("layer")
487
486
  bbox = [Decimal(x) for x in m.group("bbox").split()]
@@ -505,8 +504,8 @@ def add_obstructions(reader, input_lefs, obstructions):
505
504
  layer = obs[0]
506
505
  odb_layer = reader.tech.findLayer(layer)
507
506
  if odb_layer is None:
508
- print(f"[ERROR] layer {layer} doesn't exist.", file=sys.stderr)
509
- sys.exit(METAL_LAYER_ERROR)
507
+ print(f"[ERROR] Layer '{layer}' not found.", file=sys.stderr)
508
+ sys.exit(1)
510
509
  bbox = obs[1]
511
510
  dbu = reader.tech.getDbUnitsPerMicron()
512
511
  bbox = [int(x * dbu) for x in bbox]
@@ -550,8 +549,8 @@ def remove_obstructions(reader, input_lefs, obstructions):
550
549
  bbox = [int(x * dbu) for x in bbox] # To dbus
551
550
  found = False
552
551
  if reader.tech.findLayer(layer) is None:
553
- print(f"[ERROR] layer {layer} doesn't exist.", file=sys.stderr)
554
- sys.exit(METAL_LAYER_ERROR)
552
+ print(f"[ERROR] Layer '{layer}' not found.", file=sys.stderr)
553
+ sys.exit(1)
555
554
  for odb_obstruction in existing_obstructions:
556
555
  odb_layer, odb_bbox, odb_obj = odb_obstruction
557
556
  if (odb_layer, odb_bbox) == (layer, bbox):
@@ -565,7 +564,7 @@ def remove_obstructions(reader, input_lefs, obstructions):
565
564
  f"[ERROR] Obstruction on {layer} at {bbox} (DBU) not found.",
566
565
  file=sys.stderr,
567
566
  )
568
- sys.exit(NOT_FOUND_ERROR)
567
+ sys.exit(1)
569
568
 
570
569
 
571
570
  cli.add_command(remove_obstructions)
@@ -0,0 +1,181 @@
1
+ #!/usr/bin/env python3
2
+ # Copyright 2025 Efabless Corporation
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ import sys
16
+ from reader import click_odb, click, odb
17
+ import grt as GRT
18
+
19
+
20
+ def average_location(instances):
21
+ locations = [instance.getLocation() for instance in instances]
22
+ x_sum = sum(loc[0] for loc in locations)
23
+ y_sum = sum(loc[1] for loc in locations)
24
+ return (x_sum // len(locations), y_sum // len(locations))
25
+
26
+
27
+ @click.command()
28
+ @click_odb
29
+ def cli(reader):
30
+ grt = reader.design.getGlobalRouter()
31
+ dpl = reader.design.getOpendp()
32
+
33
+ insts_to_temporarily_lock_then_unlock_later = []
34
+ for inst in reader.block.getInsts():
35
+ if inst.getPlacementStatus() != "LOCKED":
36
+ insts_to_temporarily_lock_then_unlock_later.append(
37
+ (inst, inst.getPlacementStatus())
38
+ )
39
+ inst.setPlacementStatus("LOCKED")
40
+
41
+ reader._grt_setup(grt)
42
+
43
+ grt_inc = GRT.IncrementalGRoute(grt, reader.block)
44
+ i = 0
45
+
46
+ for target_info in reader.config["INSERT_ECO_BUFFERS"]:
47
+ target_name, target_pin = target_info["target"].split("/")
48
+ name_escaped = reader.escape_verilog_name(target_name)
49
+ buffer_master = target_info["buffer"]
50
+
51
+ master = reader.db.findMaster(buffer_master)
52
+ if master is None:
53
+ print(
54
+ f"[ERROR] Buffer type '{buffer_master}' not found.",
55
+ file=sys.stderr,
56
+ )
57
+ exit(-1)
58
+
59
+ target = reader.block.findInst(name_escaped)
60
+ if target is None:
61
+ print(f"[ERROR] Instance '{target_name}' not found.", file=sys.stderr)
62
+ exit(-1)
63
+
64
+ target_iterm = target.findITerm(target_pin)
65
+ if target_iterm is None:
66
+ print(
67
+ f"[ERROR] Pin '{target_pin}' not found for instance '{target_name}'.",
68
+ file=sys.stderr,
69
+ )
70
+ exit(-1)
71
+
72
+ net = target_iterm.getNet()
73
+ if net is None:
74
+ print(
75
+ f"[ERROR] Net not found on pin '{target_pin}' of instance '{target_name}'.",
76
+ file=sys.stderr,
77
+ )
78
+ exit(-1)
79
+
80
+ new_buf_name = f"eco_buffer_{i}"
81
+ new_net_name = f"eco_buffer_{i}_net"
82
+ while (
83
+ reader.block.findInst(new_buf_name) is not None
84
+ or reader.block.findNet(new_net_name) is not None
85
+ ):
86
+ i += 1
87
+ new_buf_name = f"eco_buffer_{i}"
88
+ new_net_name = f"eco_buffer_{i}_net"
89
+
90
+ # Prepare buffer cell, net
91
+ eco_buffer = odb.dbInst.create(reader.block, master, new_buf_name)
92
+ eco_net = odb.dbNet.create(reader.block, new_net_name)
93
+ buffer_iterms = eco_buffer.getITerms()
94
+ buffer_a = None
95
+ for iterm in buffer_iterms:
96
+ if iterm.isInputSignal():
97
+ buffer_a = iterm
98
+ break # Exit loop once input is found
99
+ if buffer_a is None:
100
+ print(
101
+ f"[ERROR] Buffer {buffer_master} has no input signals.",
102
+ file=sys.stderr,
103
+ )
104
+ exit(-1)
105
+
106
+ buffer_x = None
107
+ for iterm in buffer_iterms:
108
+ if iterm.isOutputSignal():
109
+ buffer_x = iterm
110
+ break # Exit loop once output is found
111
+ if buffer_x is None:
112
+ print(
113
+ f"[ERROR] Buffer {buffer_master} has no output signals.",
114
+ file=sys.stderr,
115
+ )
116
+ exit(-1)
117
+
118
+ location_instances = [target]
119
+ net_iterms = net.getITerms()
120
+ if target_iterm.getIoType() == "INPUT":
121
+ driver_iterms = [
122
+ iterm for iterm in net_iterms if iterm.getIoType() in ["OUTPUT"]
123
+ ]
124
+ drivers = [iterm.getInst() for iterm in driver_iterms]
125
+ location_instances.extend(drivers)
126
+
127
+ target_iterm.disconnect()
128
+ buffer_a.connect(net)
129
+ buffer_x.connect(eco_net)
130
+ target_iterm.connect(eco_net)
131
+ elif target_iterm.getIoType() == "OUTPUT":
132
+ sink_iterms = [
133
+ iterm for iterm in net_iterms if iterm.getIoType() in ["INPUT", "INOUT"]
134
+ ]
135
+ sinks = [iterm.getInst() for iterm in sink_iterms]
136
+ location_instances.extend(sinks)
137
+
138
+ target_iterm.disconnect()
139
+ target_iterm.connect(eco_net)
140
+ buffer_a.connect(eco_net)
141
+ buffer_x.connect(net)
142
+ else:
143
+ print(
144
+ f"[ERROR] {target_name}/{target_pin} is neither an INPUT or an OUTPUT and is unsupported by this script. To buffer an INOUT port, buffer its drivers instead.",
145
+ file=sys.stderr,
146
+ )
147
+ exit(-1)
148
+
149
+ if target_info.get("placement") is not None:
150
+ eco_x, eco_y = target_info["placement"]
151
+ eco_x = reader.block.micronsToDbu(float(eco_x))
152
+ eco_y = reader.block.micronsToDbu(float(eco_y))
153
+ eco_loc = (eco_x, eco_y)
154
+ else:
155
+ eco_loc = average_location(location_instances)
156
+
157
+ eco_buffer.setOrient("R0")
158
+ eco_buffer.setLocation(*eco_loc)
159
+ eco_buffer.setPlacementStatus("PLACED")
160
+ grt.addDirtyNet(net)
161
+ grt.addDirtyNet(eco_net)
162
+
163
+ site = reader.rows[0].getSite()
164
+ max_disp_x = int(
165
+ reader.design.micronToDBU(reader.config["PL_MAX_DISPLACEMENT_X"])
166
+ / site.getWidth()
167
+ )
168
+ max_disp_y = int(
169
+ reader.design.micronToDBU(reader.config["PL_MAX_DISPLACEMENT_Y"])
170
+ / site.getHeight()
171
+ )
172
+ dpl.detailedPlacement(max_disp_x, max_disp_y)
173
+
174
+ grt_inc.updateRoutes(True)
175
+
176
+ for inst, previous_status in insts_to_temporarily_lock_then_unlock_later:
177
+ inst.setPlacementStatus(previous_status)
178
+
179
+
180
+ if __name__ == "__main__":
181
+ cli()
@@ -0,0 +1,139 @@
1
+ #!/usr/bin/env python3
2
+ # Copyright 2025 Efabless Corporation
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ import sys
16
+ from reader import click_odb, click, odb
17
+ import grt as GRT
18
+
19
+
20
+ @click.command()
21
+ @click_odb
22
+ def cli(reader):
23
+ grt = reader.design.getGlobalRouter()
24
+ dpl = reader.design.getOpendp()
25
+
26
+ insts_to_temporarily_lock_then_unlock_later = []
27
+ for inst in reader.block.getInsts():
28
+ if inst.getPlacementStatus() != "LOCKED":
29
+ insts_to_temporarily_lock_then_unlock_later.append(
30
+ (inst, inst.getPlacementStatus())
31
+ )
32
+ inst.setPlacementStatus("LOCKED")
33
+
34
+ reader._grt_setup(grt)
35
+
36
+ diode_master, diode_pin = reader.config["DIODE_CELL"].split("/")
37
+
38
+ # print(grt)
39
+ grt_inc = GRT.IncrementalGRoute(grt, reader.block)
40
+ i = 0
41
+ for target_info in reader.config["INSERT_ECO_DIODES"]:
42
+ target_name, target_pin = target_info["target"].split("/")
43
+ name_escaped = reader.escape_verilog_name(target_name)
44
+
45
+ target = reader.block.findInst(name_escaped)
46
+ if target is None:
47
+ print(
48
+ f"[ERROR] Instance '{target_name}' not found.",
49
+ file=sys.stderr,
50
+ )
51
+ exit(-1)
52
+
53
+ master = reader.db.findMaster(diode_master)
54
+ if master is None:
55
+ print(
56
+ f"[ERROR] Cell kind '{diode_master}' not found.",
57
+ file=sys.stderr,
58
+ )
59
+ exit(-1)
60
+
61
+ target_iterm = target.findITerm(target_pin)
62
+ if target_iterm is None:
63
+ print(
64
+ f"[ERROR] Pin '{target_pin}' not found for instance {target_name}.",
65
+ file=sys.stderr,
66
+ )
67
+ exit(-1)
68
+
69
+ if target_iterm.getIoType() not in ["INPUT", "INOUT"]:
70
+ print(
71
+ f"[ERROR] Pin {target_info['target']} is an OUTPUT pin.",
72
+ file=sys.stderr,
73
+ )
74
+ exit(-1)
75
+
76
+ net = target_iterm.getNet()
77
+ if net is None:
78
+ print(
79
+ f"[ERROR] Pin {target_info['target']} has no nets connected.",
80
+ file=sys.stderr,
81
+ )
82
+ exit(-1)
83
+
84
+ eco_diode_name = f"eco_diode_{i}"
85
+ while reader.block.findInst(eco_diode_name) is not None:
86
+ i += 1
87
+ eco_diode_name = f"eco_diode_{i}"
88
+
89
+ eco_diode = odb.dbInst.create(
90
+ reader.block,
91
+ master,
92
+ eco_diode_name,
93
+ )
94
+
95
+ diode_iterm = eco_diode.findITerm(diode_pin)
96
+ if diode_iterm is None:
97
+ print(
98
+ f"[ERROR] Pin '{diode_pin}' on ECO diode not found- invalid DIODE_CELL definition.",
99
+ file=sys.stderr,
100
+ )
101
+ exit(-1)
102
+
103
+ sys.stdout.flush()
104
+
105
+ if target_info["placement"] is not None:
106
+ x, y = target_info["placement"]
107
+ x = reader.block.micronsToDbu(float(x))
108
+ y = reader.block.micronsToDbu(float(y))
109
+ else:
110
+ x, y = target.getLocation()
111
+
112
+ eco_diode.setOrient("R0")
113
+ eco_diode.setLocation(x, y)
114
+ eco_diode.setPlacementStatus("PLACED")
115
+
116
+ diode_iterm.connect(net)
117
+ grt.addDirtyNet(net)
118
+
119
+ site = reader.rows[0].getSite()
120
+ max_disp_x = int(
121
+ reader.design.micronToDBU(reader.config["PL_MAX_DISPLACEMENT_X"])
122
+ / site.getWidth()
123
+ )
124
+ max_disp_y = int(
125
+ reader.design.micronToDBU(reader.config["PL_MAX_DISPLACEMENT_Y"])
126
+ / site.getHeight()
127
+ )
128
+ dpl.detailedPlacement(max_disp_x, max_disp_y)
129
+
130
+ grt_inc.updateRoutes(True)
131
+
132
+ for inst, previous_status in insts_to_temporarily_lock_then_unlock_later:
133
+ inst.setPlacementStatus(previous_status)
134
+
135
+ reader.design.writeDef("out.def")
136
+
137
+
138
+ if __name__ == "__main__":
139
+ cli()
@@ -0,0 +1,23 @@
1
+ # Copyright 2025 The American University in Cairo
2
+ #
3
+ # Adapted from ioplace_parser
4
+ #
5
+ # Copyright 2020-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
+ """
19
+ This is a modified version of https://github.com/efabless/ioplace_parser that
20
+ does NOT use Antlr4 and instead uses a custom parser that is faster and
21
+ dependency-free.
22
+ """
23
+ from .parse import Side, Order, parse