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.
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/PKG-INFO +5 -4
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/__main__.py +1 -1
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/__init__.py +1 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/metrics/__main__.py +16 -143
- librelane-3.1.0.dev4/librelane/common/metrics/compare.py +156 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/misc.py +27 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/toolbox.py +5 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/config/__init__.py +4 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/config/__main__.py +4 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/config/config.py +10 -1
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/config/flow.py +1 -1
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/config/pdk_compat.py +22 -2
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/config/preprocessor.py +24 -13
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/config/removals.py +4 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/config/variable.py +93 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm/src/impl.sdc +2 -2
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm/src/signoff.sdc +2 -2
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/flows/cli.py +20 -18
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/flows/synth_explore.py +1 -0
- librelane-3.1.0.dev4/librelane/pdk_hashes.yaml +4 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/base.sdc +2 -2
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/check_antenna_properties.py +1 -1
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/defutil.py +4 -1
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/power_utils.py +10 -9
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/common/io.tcl +25 -7
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/drt.tcl +16 -1
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/gpl.tcl +6 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/repair_design.tcl +3 -3
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/repair_design_postgrt.tcl +1 -4
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/pyosys/construct_abc_script.py +5 -5
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/pyosys/synthesize.py +49 -22
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/pyosys/ys_common.py +39 -5
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/klayout.py +62 -29
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/openroad.py +59 -8
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/pyosys.py +72 -45
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/step.py +1 -1
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/tclstep.py +6 -4
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/verilator.py +7 -6
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/yosys.py +0 -12
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/pyproject.toml +4 -4
- librelane-3.1.0.dev2/librelane/pdk_hashes.yaml +0 -3
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/Readme.md +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/__init__.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/__version__.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/cli.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/drc.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/generic_dict.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/metrics/__init__.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/metrics/library.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/metrics/metric.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/metrics/util.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/ring_buffer.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/tcl.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/tpe.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/common/types.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/container.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/env_info.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/hold_eco_demo/config.yaml +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/hold_eco_demo/demo.v +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm/config.yaml +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm/pin_order.cfg +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm/src/spm.v +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm/verify/spm_tb.v +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm-user_project_wrapper/SPM_example.v +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm-user_project_wrapper/base_sdc_file.sdc +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm-user_project_wrapper/config-tut.json +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm-user_project_wrapper/config.json +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm-user_project_wrapper/defines.v +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm-user_project_wrapper/template.def +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/examples/spm-user_project_wrapper/user_project_wrapper.v +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/flows/__init__.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/flows/builtins.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/flows/chip.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/flows/classic.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/flows/flow.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/flows/misc.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/flows/optimizing.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/flows/sequential.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/help/__main__.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/logging/__init__.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/logging/logger.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/plugins.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/py.typed +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/klayout/Readme.md +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/klayout/insert_cell.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/klayout/open_design.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/klayout/render.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/klayout/stream_out.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/klayout/xml_drc_report_to_json.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/klayout/xor.drc +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/Readme.md +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/common/read.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/def/antenna_check.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/def/mag.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/def/mag_gds.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/drc.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/extract_spice.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/gds/drc_batch.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/gds/erase_box.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/gds/extras_mag.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/gds/mag_with_pointers.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/get_bbox.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/lef/extras_maglef.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/lef/maglef.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/lef.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/open.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/spice_rcx.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/magic/wrapper.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/netgen/setup.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/apply_def_template.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/cell_frequency.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/contextualize.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/diodes.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/disconnected_pins.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/eco_buffer.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/eco_diode.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/filter_unannotated.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/io_place.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/ioplace_parser/__init__.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/ioplace_parser/parse.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/label_macro_pins.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/lefutil.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/placers.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/random_place.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/reader.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/remove_buffers.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/snap_to_grid.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/odbpy/wire_lengths.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/antenna_check.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/antenna_repair.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/buffer_list.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/common/dpl.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/common/dpl_cell_pad.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/common/grt.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/common/pad_cfg.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/common/pdn_cfg.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/common/resizer.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/common/set_global_connections.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/common/set_layer_adjustments.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/common/set_power_nets.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/common/set_rc.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/common/set_routing_layers.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/cts.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/cut_rows.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/dpl.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/dump_rc.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/fill.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/floorplan.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/grt.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/gui.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/insert_buffer.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/ioplacer.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/irdrop.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/pad.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/pdn.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/rcx.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/rsz_timing_postcts.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/rsz_timing_postgrt.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/sta/check_macro_instances.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/sta/corner.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/tapcell.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/ungpl.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/write_cdl.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/openroad/write_views.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/pyosys/json_header.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/scripts/tclsh/hello.tcl +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/state/__init__.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/state/__main__.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/state/design_format.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/state/state.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/__init__.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/__main__.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/checker.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/common_variables.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/magic.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/misc.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/netgen.py +0 -0
- {librelane-3.1.0.dev2 → librelane-3.1.0.dev4}/librelane/steps/odb.py +0 -0
- {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.
|
|
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
|
-
|
|
16
|
-
Requires-Dist:
|
|
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,<
|
|
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.
|
|
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.")
|
|
@@ -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,
|
|
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("
|
|
124
|
+
@cloup.argument("metric_directories", nargs=2)
|
|
252
125
|
def compare_multiple(
|
|
253
126
|
filter_wildcards: Tuple[str, ...],
|
|
254
127
|
table_verbosity: TableVerbosity,
|
|
255
|
-
|
|
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
|
|
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 =
|
|
267
|
-
summary, tables =
|
|
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("
|
|
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
|
-
|
|
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
|
|
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 =
|
|
255
|
+
summary, tables = compare_metric_directories(
|
|
383
256
|
filter_wildcards,
|
|
384
257
|
table_verbosity,
|
|
385
258
|
d,
|
|
386
|
-
|
|
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");
|
|
@@ -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,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
|