librelane 3.1.0.dev1__tar.gz → 3.1.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.
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/PKG-INFO +3 -3
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/__main__.py +1 -1
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/common/metrics/__main__.py +16 -143
- librelane-3.1.0.dev3/librelane/common/metrics/compare.py +156 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/config/config.py +14 -4
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/config/flow.py +6 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/config/pdk_compat.py +2 -2
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/config/preprocessor.py +20 -13
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/config/variable.py +89 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/examples/spm/src/impl.sdc +2 -2
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/examples/spm/src/signoff.sdc +2 -2
- librelane-3.1.0.dev3/librelane/pdk_hashes.yaml +3 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/base.sdc +2 -2
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/magic/def/antenna_check.tcl +3 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/magic/def/mag.tcl +4 -1
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/magic/def/mag_gds.tcl +1 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/magic/drc.tcl +1 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/magic/extract_spice.tcl +3 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/magic/gds/drc_batch.tcl +3 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/magic/gds/erase_box.tcl +4 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/magic/gds/extras_mag.tcl +2 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/magic/gds/mag_with_pointers.tcl +2 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/magic/get_bbox.tcl +4 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/magic/lef/extras_maglef.tcl +2 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/magic/lef/maglef.tcl +2 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/magic/lef.tcl +3 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/magic/spice_rcx.tcl +4 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/odbpy/power_utils.py +19 -11
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/common/io.tcl +7 -3
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/common/pad_cfg.tcl +25 -11
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/drt.tcl +16 -1
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/gpl.tcl +6 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/repair_design.tcl +5 -2
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/pyosys/construct_abc_script.py +5 -5
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/pyosys/json_header.py +5 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/pyosys/synthesize.py +36 -19
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/pyosys/ys_common.py +32 -5
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/steps/common_variables.py +1 -1
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/steps/klayout.py +13 -9
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/steps/openroad.py +52 -8
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/steps/pyosys.py +12 -13
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/steps/tclstep.py +6 -4
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/steps/verilator.py +21 -6
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/steps/yosys.py +0 -12
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/pyproject.toml +3 -3
- librelane-3.1.0.dev1/librelane/pdk_hashes.yaml +0 -3
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/Readme.md +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/__init__.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/__version__.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/common/__init__.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/common/cli.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/common/drc.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/common/generic_dict.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/common/metrics/__init__.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/common/metrics/library.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/common/metrics/metric.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/common/metrics/util.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/common/misc.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/common/ring_buffer.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/common/tcl.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/common/toolbox.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/common/tpe.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/common/types.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/config/__init__.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/config/__main__.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/config/removals.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/container.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/env_info.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/examples/hold_eco_demo/config.yaml +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/examples/hold_eco_demo/demo.v +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/examples/spm/config.yaml +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/examples/spm/pin_order.cfg +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/examples/spm/src/spm.v +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/examples/spm/verify/spm_tb.v +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/examples/spm-user_project_wrapper/SPM_example.v +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/examples/spm-user_project_wrapper/base_sdc_file.sdc +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/examples/spm-user_project_wrapper/config-tut.json +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/examples/spm-user_project_wrapper/config.json +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/examples/spm-user_project_wrapper/defines.v +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/examples/spm-user_project_wrapper/template.def +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/examples/spm-user_project_wrapper/user_project_wrapper.v +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/flows/__init__.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/flows/builtins.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/flows/chip.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/flows/classic.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/flows/cli.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/flows/flow.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/flows/misc.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/flows/optimizing.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/flows/sequential.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/flows/synth_explore.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/help/__main__.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/logging/__init__.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/logging/logger.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/plugins.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/py.typed +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/klayout/Readme.md +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/klayout/insert_cell.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/klayout/open_design.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/klayout/render.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/klayout/stream_out.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/klayout/xml_drc_report_to_json.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/klayout/xor.drc +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/magic/Readme.md +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/magic/common/read.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/magic/open.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/magic/wrapper.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/netgen/setup.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/odbpy/apply_def_template.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/odbpy/cell_frequency.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/odbpy/check_antenna_properties.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/odbpy/contextualize.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/odbpy/defutil.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/odbpy/diodes.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/odbpy/disconnected_pins.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/odbpy/eco_buffer.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/odbpy/eco_diode.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/odbpy/filter_unannotated.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/odbpy/io_place.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/odbpy/ioplace_parser/__init__.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/odbpy/ioplace_parser/parse.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/odbpy/label_macro_pins.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/odbpy/lefutil.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/odbpy/placers.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/odbpy/random_place.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/odbpy/reader.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/odbpy/remove_buffers.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/odbpy/snap_to_grid.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/odbpy/wire_lengths.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/antenna_check.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/antenna_repair.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/buffer_list.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/common/dpl.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/common/dpl_cell_pad.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/common/grt.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/common/pdn_cfg.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/common/resizer.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/common/set_global_connections.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/common/set_layer_adjustments.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/common/set_power_nets.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/common/set_rc.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/common/set_routing_layers.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/cts.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/cut_rows.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/dpl.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/dump_rc.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/fill.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/floorplan.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/grt.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/gui.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/insert_buffer.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/ioplacer.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/irdrop.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/pad.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/pdn.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/rcx.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/repair_design_postgrt.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/rsz_timing_postcts.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/rsz_timing_postgrt.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/sta/check_macro_instances.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/sta/corner.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/tapcell.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/ungpl.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/write_cdl.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/openroad/write_views.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/scripts/tclsh/hello.tcl +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/state/__init__.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/state/__main__.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/state/design_format.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/state/state.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/steps/__init__.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/steps/__main__.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/steps/checker.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/steps/magic.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/steps/misc.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/steps/netgen.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/steps/odb.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/steps/openroad_alerts.py +0 -0
- {librelane-3.1.0.dev1 → librelane-3.1.0.dev3}/librelane/steps/step.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.dev3
|
|
4
4
|
Summary: An infrastructure for implementing chip design flows
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Maintainer: Mohamed Gaber
|
|
@@ -13,7 +13,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.13
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.14
|
|
15
15
|
Requires-Dist: ciel (>=2.3.1,<3)
|
|
16
|
-
Requires-Dist: click (>=8,<8.
|
|
16
|
+
Requires-Dist: click (>=8,<8.4)
|
|
17
17
|
Requires-Dist: cloup (>=3.0.5,<4)
|
|
18
18
|
Requires-Dist: deprecated (>=1.2.10,<2)
|
|
19
19
|
Requires-Dist: httpx (>=0.22.0,<0.29)
|
|
@@ -23,7 +23,7 @@ Requires-Dist: lxml (>=4.9.0)
|
|
|
23
23
|
Requires-Dist: psutil (>=5.9.0)
|
|
24
24
|
Requires-Dist: pyyaml (>=5,<7)
|
|
25
25
|
Requires-Dist: rapidfuzz (>=3.9.0,<4)
|
|
26
|
-
Requires-Dist: rich (>=12,<
|
|
26
|
+
Requires-Dist: rich (>=12,<16)
|
|
27
27
|
Requires-Dist: semver (>=3.0.2,<4)
|
|
28
28
|
Requires-Dist: yamlcore (>=0.0.2,<0.1.0)
|
|
29
29
|
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()
|
|
@@ -495,10 +495,10 @@ class Config(GenericImmutableDict[str, Any]):
|
|
|
495
495
|
:param pdk: A process design kit to use. Required unless specified via the
|
|
496
496
|
"PDK" key in a configuration object.
|
|
497
497
|
|
|
498
|
-
:param pdk_root: Required if
|
|
498
|
+
:param pdk_root: Required if Ciel is not installed.
|
|
499
499
|
|
|
500
|
-
If
|
|
501
|
-
|
|
500
|
+
If Ciel is installed, this value can be used to optionally override
|
|
501
|
+
Ciel's default.
|
|
502
502
|
|
|
503
503
|
:param scl: A standard cell library to use. If not specified, the PDK's
|
|
504
504
|
default standard cell library will be used instead.
|
|
@@ -678,6 +678,7 @@ class Config(GenericImmutableDict[str, Any]):
|
|
|
678
678
|
raw,
|
|
679
679
|
only_extract_process_info=True,
|
|
680
680
|
design_dir=design_dir,
|
|
681
|
+
version=meta.version,
|
|
681
682
|
)
|
|
682
683
|
)
|
|
683
684
|
|
|
@@ -713,8 +714,9 @@ class Config(GenericImmutableDict[str, Any]):
|
|
|
713
714
|
pdk=pdk,
|
|
714
715
|
pdkpath=pdkpath,
|
|
715
716
|
scl=mutable[SpecialKeys.scl],
|
|
716
|
-
pad=mutable.get(SpecialKeys.pad,
|
|
717
|
+
pad=mutable.get(SpecialKeys.pad, pad),
|
|
717
718
|
design_dir=design_dir,
|
|
719
|
+
version=meta.version,
|
|
718
720
|
)
|
|
719
721
|
)
|
|
720
722
|
|
|
@@ -775,6 +777,9 @@ class Config(GenericImmutableDict[str, Any]):
|
|
|
775
777
|
tcl_config,
|
|
776
778
|
only_extract_process_info=True,
|
|
777
779
|
design_dir=design_dir,
|
|
780
|
+
# Tcl is version 1 by default I believe; on par with JSON
|
|
781
|
+
# also this path is deprecated anyways
|
|
782
|
+
version=1,
|
|
778
783
|
)
|
|
779
784
|
|
|
780
785
|
pdk = process_info.get(SpecialKeys.pdk) or pdk
|
|
@@ -833,6 +838,11 @@ class Config(GenericImmutableDict[str, Any]):
|
|
|
833
838
|
if scl is not None:
|
|
834
839
|
pdk_config[SpecialKeys.scl] = scl
|
|
835
840
|
|
|
841
|
+
# HACK: Prevent loading default SCL cfg vars for old openlane PDK
|
|
842
|
+
# configs
|
|
843
|
+
# For more info: https://github.com/librelane/librelane/issues/932
|
|
844
|
+
pdk_config["STD_CELL_LIBRARY_OPT"] = scl
|
|
845
|
+
|
|
836
846
|
if pad is not None:
|
|
837
847
|
pdk_config[SpecialKeys.pad] = pad
|
|
838
848
|
|
|
@@ -39,6 +39,12 @@ pdk_variables = [
|
|
|
39
39
|
"Specifies the default standard cell library to be used under the specified PDK. Must be a valid C identifier, i.e., matches the regular expression `[_a-zA-Z][_a-zA-Z0-9]+`.",
|
|
40
40
|
pdk=True,
|
|
41
41
|
),
|
|
42
|
+
Variable(
|
|
43
|
+
"PAD_CELL_LIBRARY",
|
|
44
|
+
Optional[str],
|
|
45
|
+
"Specifies the default pad cell library to be used under the specified PDK. Must be a valid C identifier, i.e., matches the regular expression `[_a-zA-Z][_a-zA-Z0-9]+`.",
|
|
46
|
+
pdk=True,
|
|
47
|
+
),
|
|
42
48
|
Variable(
|
|
43
49
|
"VDD_PIN",
|
|
44
50
|
str,
|
|
@@ -325,9 +325,9 @@ def migrate_old_config(config: Mapping[str, Any]) -> Dict[str, Any]:
|
|
|
325
325
|
if "CLOCK_TRANSITION_CONSTRAINT" not in config:
|
|
326
326
|
new["CLOCK_TRANSITION_CONSTRAINT"] = 0.15
|
|
327
327
|
if "TIME_DERATING_CONSTRAINT" not in config:
|
|
328
|
-
new["TIME_DERATING_CONSTRAINT"] = 5
|
|
328
|
+
new["TIME_DERATING_CONSTRAINT"] = 5.0
|
|
329
329
|
if "IO_DELAY_CONSTRAINT" not in config:
|
|
330
|
-
new["IO_DELAY_CONSTRAINT"] = 20
|
|
330
|
+
new["IO_DELAY_CONSTRAINT"] = 20.0
|
|
331
331
|
|
|
332
332
|
# Unspecififed is fine
|
|
333
333
|
# if "FP_IO_MIN_DISTANCE" not in config:
|
|
@@ -211,10 +211,7 @@ class Expr(object):
|
|
|
211
211
|
ref_rx = re.compile(r"^\$([A-Za-z_][A-Za-z0-9_\.\[\]]*)")
|
|
212
212
|
|
|
213
213
|
|
|
214
|
-
def process_string(
|
|
215
|
-
value: str,
|
|
216
|
-
symbols: Mapping[str, Any],
|
|
217
|
-
) -> Valid:
|
|
214
|
+
def process_string(value: str, symbols: Mapping[str, Any], version: int = 1) -> Valid:
|
|
218
215
|
global ref_rx
|
|
219
216
|
EXPR_PREFIX = "expr::"
|
|
220
217
|
REF_PREFIX = "ref::"
|
|
@@ -230,6 +227,11 @@ def process_string(
|
|
|
230
227
|
elif value.startswith(PDK_DIR_PREFIX):
|
|
231
228
|
mutable = value.replace(PDK_DIR_PREFIX, f"refg::${Keys.pdkpath}/")
|
|
232
229
|
|
|
230
|
+
# gate this behind meta version 3
|
|
231
|
+
if version >= 3:
|
|
232
|
+
# before we do anything else, apply inline variable substitution
|
|
233
|
+
mutable = mutable.format(**symbols)
|
|
234
|
+
|
|
233
235
|
if mutable.startswith(EXPR_PREFIX):
|
|
234
236
|
try:
|
|
235
237
|
return Expr.evaluate(value[len(EXPR_PREFIX) :], symbols)
|
|
@@ -296,6 +298,7 @@ def process_list_recursive(
|
|
|
296
298
|
input: Sequence[Any],
|
|
297
299
|
ref: List[Any],
|
|
298
300
|
symbols: Dict[str, Any],
|
|
301
|
+
version: int = 1,
|
|
299
302
|
*,
|
|
300
303
|
key_path: str = "",
|
|
301
304
|
):
|
|
@@ -308,6 +311,7 @@ def process_list_recursive(
|
|
|
308
311
|
value,
|
|
309
312
|
processed,
|
|
310
313
|
symbols,
|
|
314
|
+
version,
|
|
311
315
|
key_path=current_key_path,
|
|
312
316
|
)
|
|
313
317
|
elif isinstance(value, Sequence) and not is_string(value):
|
|
@@ -316,10 +320,11 @@ def process_list_recursive(
|
|
|
316
320
|
value,
|
|
317
321
|
processed,
|
|
318
322
|
symbols,
|
|
323
|
+
version,
|
|
319
324
|
key_path=current_key_path,
|
|
320
325
|
)
|
|
321
326
|
elif is_string(value):
|
|
322
|
-
processed = process_string(value, symbols)
|
|
327
|
+
processed = process_string(value, symbols, version)
|
|
323
328
|
else:
|
|
324
329
|
processed = value
|
|
325
330
|
|
|
@@ -332,6 +337,7 @@ def process_dict_recursive(
|
|
|
332
337
|
input: Mapping[str, Any],
|
|
333
338
|
ref: Dict[str, Any],
|
|
334
339
|
symbols: Dict[str, Any],
|
|
340
|
+
version: int = 1,
|
|
335
341
|
*,
|
|
336
342
|
key_path: str = "",
|
|
337
343
|
):
|
|
@@ -348,6 +354,7 @@ def process_dict_recursive(
|
|
|
348
354
|
value,
|
|
349
355
|
ref,
|
|
350
356
|
symbols,
|
|
357
|
+
version,
|
|
351
358
|
key_path=key_path,
|
|
352
359
|
)
|
|
353
360
|
elif key.startswith(SCL_PREFIX):
|
|
@@ -359,6 +366,7 @@ def process_dict_recursive(
|
|
|
359
366
|
value,
|
|
360
367
|
ref,
|
|
361
368
|
symbols,
|
|
369
|
+
version,
|
|
362
370
|
key_path=key_path,
|
|
363
371
|
)
|
|
364
372
|
else:
|
|
@@ -367,6 +375,7 @@ def process_dict_recursive(
|
|
|
367
375
|
value,
|
|
368
376
|
processed,
|
|
369
377
|
symbols,
|
|
378
|
+
version,
|
|
370
379
|
key_path=current_key_path,
|
|
371
380
|
)
|
|
372
381
|
|
|
@@ -376,10 +385,11 @@ def process_dict_recursive(
|
|
|
376
385
|
value,
|
|
377
386
|
processed,
|
|
378
387
|
symbols,
|
|
388
|
+
version,
|
|
379
389
|
key_path=current_key_path,
|
|
380
390
|
)
|
|
381
391
|
elif is_string(value):
|
|
382
|
-
processed = process_string(value, symbols)
|
|
392
|
+
processed = process_string(value, symbols, version)
|
|
383
393
|
else:
|
|
384
394
|
processed = value
|
|
385
395
|
|
|
@@ -389,12 +399,11 @@ def process_dict_recursive(
|
|
|
389
399
|
|
|
390
400
|
|
|
391
401
|
def process_config_dict(
|
|
392
|
-
config_in: Mapping[str, Any],
|
|
393
|
-
exposed_variables: Dict[str, Any],
|
|
402
|
+
config_in: Mapping[str, Any], exposed_variables: Dict[str, Any], version: int = 1
|
|
394
403
|
) -> Dict[str, Any]:
|
|
395
404
|
state = dict(exposed_variables)
|
|
396
405
|
symbols = dict(exposed_variables)
|
|
397
|
-
process_dict_recursive(config_in, state, symbols)
|
|
406
|
+
process_dict_recursive(config_in, state, symbols, version)
|
|
398
407
|
return state
|
|
399
408
|
|
|
400
409
|
|
|
@@ -414,6 +423,7 @@ def preprocess_dict(
|
|
|
414
423
|
pdkpath: Optional[str] = None,
|
|
415
424
|
scl: Optional[str] = None,
|
|
416
425
|
pad: Optional[str] = None,
|
|
426
|
+
version: int = 1,
|
|
417
427
|
) -> Dict[str, Any]:
|
|
418
428
|
if None in (pdk, pdkpath, scl):
|
|
419
429
|
if only_extract_process_info:
|
|
@@ -433,10 +443,7 @@ def preprocess_dict(
|
|
|
433
443
|
Keys.design_dir: design_dir,
|
|
434
444
|
}
|
|
435
445
|
|
|
436
|
-
preprocessed = process_config_dict(
|
|
437
|
-
config_dict,
|
|
438
|
-
base_vars,
|
|
439
|
-
)
|
|
446
|
+
preprocessed = process_config_dict(config_dict, base_vars, version)
|
|
440
447
|
if only_extract_process_info:
|
|
441
448
|
preprocessed = extract_process_vars(preprocessed)
|
|
442
449
|
|