librelane 3.0.0.dev52__tar.gz → 3.0.0rc1__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.0.0.dev52 → librelane-3.0.0rc1}/PKG-INFO +13 -1
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/Readme.md +12 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/common/toolbox.py +3 -1
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/config/config.py +0 -7
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/config/preprocessor.py +3 -28
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/examples/spm/config.yaml +1 -1
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/flows/classic.py +1 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/pdk_hashes.yaml +1 -1
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/klayout/render.py +74 -8
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/magic/common/read.tcl +8 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/magic/def/mag_gds.tcl +3 -2
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/magic/extract_spice.tcl +5 -1
- librelane-3.0.0rc1/librelane/scripts/magic/spice_rcx.tcl +72 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/netgen/setup.tcl +11 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/common/io.tcl +46 -10
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/common/set_rc.tcl +12 -14
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/cts.tcl +1 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/drt.tcl +41 -1
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/dump_rc.tcl +6 -2
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/grt.tcl +0 -5
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/sta/corner.tcl +61 -50
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/state/design_format.py +18 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/steps/__main__.py +2 -1
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/steps/klayout.py +63 -3
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/steps/magic.py +71 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/steps/netgen.py +5 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/steps/openroad.py +44 -2
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/steps/step.py +2 -4
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/pyproject.toml +1 -1
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/__init__.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/__main__.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/__version__.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/common/__init__.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/common/cli.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/common/drc.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/common/generic_dict.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/common/metrics/__init__.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/common/metrics/__main__.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/common/metrics/library.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/common/metrics/metric.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/common/metrics/util.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/common/misc.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/common/ring_buffer.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/common/tcl.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/common/tpe.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/common/types.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/config/__init__.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/config/__main__.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/config/flow.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/config/pdk_compat.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/config/removals.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/config/variable.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/container.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/env_info.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/examples/hold_eco_demo/config.yaml +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/examples/hold_eco_demo/demo.v +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/examples/spm/pin_order.cfg +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/examples/spm/src/impl.sdc +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/examples/spm/src/signoff.sdc +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/examples/spm/src/spm.v +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/examples/spm/verify/spm_tb.v +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/examples/spm-user_project_wrapper/SPM_example.v +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/examples/spm-user_project_wrapper/base_sdc_file.sdc +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/examples/spm-user_project_wrapper/config-tut.json +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/examples/spm-user_project_wrapper/config.json +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/examples/spm-user_project_wrapper/defines.v +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/examples/spm-user_project_wrapper/template.def +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/examples/spm-user_project_wrapper/user_project_wrapper.v +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/flows/__init__.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/flows/builtins.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/flows/chip.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/flows/cli.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/flows/flow.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/flows/misc.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/flows/optimizing.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/flows/sequential.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/flows/synth_explore.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/help/__main__.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/logging/__init__.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/logging/logger.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/plugins.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/py.typed +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/base.sdc +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/klayout/Readme.md +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/klayout/open_design.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/klayout/stream_out.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/klayout/xml_drc_report_to_json.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/klayout/xor.drc +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/magic/Readme.md +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/magic/def/antenna_check.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/magic/def/mag.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/magic/drc.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/magic/gds/drc_batch.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/magic/gds/erase_box.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/magic/gds/extras_mag.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/magic/gds/mag_with_pointers.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/magic/get_bbox.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/magic/lef/extras_maglef.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/magic/lef/maglef.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/magic/lef.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/magic/open.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/magic/wrapper.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/odbpy/apply_def_template.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/odbpy/cell_frequency.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/odbpy/check_antenna_properties.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/odbpy/contextualize.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/odbpy/defutil.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/odbpy/diodes.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/odbpy/disconnected_pins.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/odbpy/eco_buffer.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/odbpy/eco_diode.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/odbpy/filter_unannotated.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/odbpy/io_place.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/odbpy/ioplace_parser/__init__.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/odbpy/ioplace_parser/parse.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/odbpy/label_macro_pins.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/odbpy/lefutil.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/odbpy/placers.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/odbpy/power_utils.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/odbpy/random_place.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/odbpy/reader.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/odbpy/remove_buffers.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/odbpy/snap_to_grid.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/odbpy/wire_lengths.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/antenna_check.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/antenna_repair.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/buffer_list.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/common/dpl.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/common/dpl_cell_pad.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/common/grt.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/common/pad_cfg.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/common/pdn_cfg.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/common/resizer.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/common/set_global_connections.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/common/set_layer_adjustments.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/common/set_power_nets.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/common/set_routing_layers.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/cut_rows.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/dpl.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/fill.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/floorplan.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/gpl.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/gui.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/insert_buffer.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/ioplacer.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/irdrop.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/pad.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/pdn.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/rcx.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/repair_design.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/repair_design_postgrt.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/rsz_timing_postcts.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/rsz_timing_postgrt.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/sta/check_macro_instances.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/tapcell.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/ungpl.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/write_cdl.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/openroad/write_views.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/pyosys/construct_abc_script.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/pyosys/json_header.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/pyosys/synthesize.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/pyosys/ys_common.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/scripts/tclsh/hello.tcl +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/state/__init__.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/state/__main__.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/state/state.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/steps/__init__.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/steps/checker.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/steps/common_variables.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/steps/misc.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/steps/odb.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/steps/openroad_alerts.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/steps/pyosys.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/steps/tclstep.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/steps/verilator.py +0 -0
- {librelane-3.0.0.dev52 → librelane-3.0.0rc1}/librelane/steps/yosys.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: librelane
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.0rc1
|
|
4
4
|
Summary: An infrastructure for implementing chip design flows
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Maintainer: Mohamed Gaber
|
|
@@ -139,6 +139,18 @@ If you use LibreLane in your research, please cite the following paper.
|
|
|
139
139
|
doi={}}
|
|
140
140
|
```
|
|
141
141
|
|
|
142
|
+
## Contributing
|
|
143
|
+
Thank you in advance for considering a contribution to LibreLane!
|
|
144
|
+
|
|
145
|
+
Please be sure to read our [contributor's guide](https://librelane.readthedocs.io/en/stable/contributors/index.html).
|
|
146
|
+
|
|
147
|
+
> [!TIP]
|
|
148
|
+
>
|
|
149
|
+
> The `main` branch is the stable branch for LibreLane, i.e., this branch is
|
|
150
|
+
> updated less frequently and only accepts bugfixes.
|
|
151
|
+
>
|
|
152
|
+
> Feature contributions should be directed towards the `dev` branch.
|
|
153
|
+
|
|
142
154
|
## License and Legal Info
|
|
143
155
|
|
|
144
156
|
LibreLane is a trademark of the [FOSSi Foundation](https://fossi-foundation.org).
|
|
@@ -105,6 +105,18 @@ If you use LibreLane in your research, please cite the following paper.
|
|
|
105
105
|
doi={}}
|
|
106
106
|
```
|
|
107
107
|
|
|
108
|
+
## Contributing
|
|
109
|
+
Thank you in advance for considering a contribution to LibreLane!
|
|
110
|
+
|
|
111
|
+
Please be sure to read our [contributor's guide](https://librelane.readthedocs.io/en/stable/contributors/index.html).
|
|
112
|
+
|
|
113
|
+
> [!TIP]
|
|
114
|
+
>
|
|
115
|
+
> The `main` branch is the stable branch for LibreLane, i.e., this branch is
|
|
116
|
+
> updated less frequently and only accepts bugfixes.
|
|
117
|
+
>
|
|
118
|
+
> Feature contributions should be directed towards the `dev` branch.
|
|
119
|
+
|
|
108
120
|
## License and Legal Info
|
|
109
121
|
|
|
110
122
|
LibreLane is a trademark of the [FOSSi Foundation](https://fossi-foundation.org).
|
|
@@ -351,7 +351,9 @@ class Toolbox(object):
|
|
|
351
351
|
with tempfile.TemporaryDirectory(prefix="librelane_klayout_tmp_") as d:
|
|
352
352
|
render_step = KLayout.Render(config, state_in, _config_quiet=True)
|
|
353
353
|
render_step.start(self, d)
|
|
354
|
-
return open(
|
|
354
|
+
return open(
|
|
355
|
+
os.path.join(d, f"{config['DESIGN_NAME']}.png"), "rb"
|
|
356
|
+
).read()
|
|
355
357
|
except InvalidConfig:
|
|
356
358
|
warn("PDK is incompatible with KLayout. Unable to generate preview.")
|
|
357
359
|
return None
|
|
@@ -707,12 +707,6 @@ class Config(GenericImmutableDict[str, Any]):
|
|
|
707
707
|
if pdk_root is not None:
|
|
708
708
|
pdkpath = os.path.join(pdk_root, mutable["PDK"])
|
|
709
709
|
|
|
710
|
-
readable_paths = [
|
|
711
|
-
os.path.abspath(design_dir),
|
|
712
|
-
]
|
|
713
|
-
if pdkpath != "":
|
|
714
|
-
readable_paths.append(os.path.abspath(pdkpath))
|
|
715
|
-
|
|
716
710
|
mutable.update(
|
|
717
711
|
preprocess_dict(
|
|
718
712
|
raw,
|
|
@@ -721,7 +715,6 @@ class Config(GenericImmutableDict[str, Any]):
|
|
|
721
715
|
scl=mutable[SpecialKeys.scl],
|
|
722
716
|
pad=mutable.get(SpecialKeys.pad, None),
|
|
723
717
|
design_dir=design_dir,
|
|
724
|
-
readable_paths=readable_paths,
|
|
725
718
|
)
|
|
726
719
|
)
|
|
727
720
|
|
|
@@ -214,7 +214,6 @@ ref_rx = re.compile(r"^\$([A-Za-z_][A-Za-z0-9_\.\[\]]*)")
|
|
|
214
214
|
def process_string(
|
|
215
215
|
value: str,
|
|
216
216
|
symbols: Mapping[str, Any],
|
|
217
|
-
readable_paths: Optional[List[str]] = None,
|
|
218
217
|
) -> Valid:
|
|
219
218
|
global ref_rx
|
|
220
219
|
EXPR_PREFIX = "expr::"
|
|
@@ -271,22 +270,12 @@ def process_string(
|
|
|
271
270
|
|
|
272
271
|
## If we're refg, all returns beyond this point must be of type
|
|
273
272
|
## List[str]
|
|
274
|
-
|
|
275
|
-
# Glob only if readable_paths isn't null
|
|
276
|
-
if readable_paths is None:
|
|
277
|
-
return [target]
|
|
278
|
-
|
|
279
273
|
final_abspath = os.path.abspath(concatenated)
|
|
280
274
|
|
|
281
275
|
# Glob only if it doesn't already resolve to a valid file
|
|
282
276
|
if os.path.exists(final_abspath):
|
|
283
277
|
return [final_abspath]
|
|
284
278
|
|
|
285
|
-
in_exposed = [final_abspath.startswith(p) for p in readable_paths]
|
|
286
|
-
if True not in in_exposed:
|
|
287
|
-
raise PermissionError(
|
|
288
|
-
f"'{concatenated}' is not located any path readable to LibreLane"
|
|
289
|
-
)
|
|
290
279
|
files = sorted(glob.glob(final_abspath))
|
|
291
280
|
files_escaped = [file.replace("$", r"\$") for file in files]
|
|
292
281
|
files_escaped.sort()
|
|
@@ -307,7 +296,6 @@ def process_list_recursive(
|
|
|
307
296
|
input: Sequence[Any],
|
|
308
297
|
ref: List[Any],
|
|
309
298
|
symbols: Dict[str, Any],
|
|
310
|
-
readable_paths: Optional[List[str]],
|
|
311
299
|
*,
|
|
312
300
|
key_path: str = "",
|
|
313
301
|
):
|
|
@@ -320,7 +308,6 @@ def process_list_recursive(
|
|
|
320
308
|
value,
|
|
321
309
|
processed,
|
|
322
310
|
symbols,
|
|
323
|
-
readable_paths,
|
|
324
311
|
key_path=current_key_path,
|
|
325
312
|
)
|
|
326
313
|
elif isinstance(value, Sequence) and not is_string(value):
|
|
@@ -329,11 +316,10 @@ def process_list_recursive(
|
|
|
329
316
|
value,
|
|
330
317
|
processed,
|
|
331
318
|
symbols,
|
|
332
|
-
readable_paths,
|
|
333
319
|
key_path=current_key_path,
|
|
334
320
|
)
|
|
335
321
|
elif is_string(value):
|
|
336
|
-
processed = process_string(value, symbols
|
|
322
|
+
processed = process_string(value, symbols)
|
|
337
323
|
else:
|
|
338
324
|
processed = value
|
|
339
325
|
|
|
@@ -346,7 +332,6 @@ def process_dict_recursive(
|
|
|
346
332
|
input: Mapping[str, Any],
|
|
347
333
|
ref: Dict[str, Any],
|
|
348
334
|
symbols: Dict[str, Any],
|
|
349
|
-
readable_paths: Optional[List[str]],
|
|
350
335
|
*,
|
|
351
336
|
key_path: str = "",
|
|
352
337
|
):
|
|
@@ -363,7 +348,6 @@ def process_dict_recursive(
|
|
|
363
348
|
value,
|
|
364
349
|
ref,
|
|
365
350
|
symbols,
|
|
366
|
-
readable_paths,
|
|
367
351
|
key_path=key_path,
|
|
368
352
|
)
|
|
369
353
|
elif key.startswith(SCL_PREFIX):
|
|
@@ -375,7 +359,6 @@ def process_dict_recursive(
|
|
|
375
359
|
value,
|
|
376
360
|
ref,
|
|
377
361
|
symbols,
|
|
378
|
-
readable_paths,
|
|
379
362
|
key_path=key_path,
|
|
380
363
|
)
|
|
381
364
|
else:
|
|
@@ -384,7 +367,6 @@ def process_dict_recursive(
|
|
|
384
367
|
value,
|
|
385
368
|
processed,
|
|
386
369
|
symbols,
|
|
387
|
-
readable_paths,
|
|
388
370
|
key_path=current_key_path,
|
|
389
371
|
)
|
|
390
372
|
|
|
@@ -394,11 +376,10 @@ def process_dict_recursive(
|
|
|
394
376
|
value,
|
|
395
377
|
processed,
|
|
396
378
|
symbols,
|
|
397
|
-
readable_paths,
|
|
398
379
|
key_path=current_key_path,
|
|
399
380
|
)
|
|
400
381
|
elif is_string(value):
|
|
401
|
-
processed = process_string(value, symbols
|
|
382
|
+
processed = process_string(value, symbols)
|
|
402
383
|
else:
|
|
403
384
|
processed = value
|
|
404
385
|
|
|
@@ -410,11 +391,10 @@ def process_dict_recursive(
|
|
|
410
391
|
def process_config_dict(
|
|
411
392
|
config_in: Mapping[str, Any],
|
|
412
393
|
exposed_variables: Dict[str, Any],
|
|
413
|
-
readable_paths: Optional[List[str]],
|
|
414
394
|
) -> Dict[str, Any]:
|
|
415
395
|
state = dict(exposed_variables)
|
|
416
396
|
symbols = dict(exposed_variables)
|
|
417
|
-
process_dict_recursive(config_in, state, symbols
|
|
397
|
+
process_dict_recursive(config_in, state, symbols)
|
|
418
398
|
return state
|
|
419
399
|
|
|
420
400
|
|
|
@@ -434,11 +414,7 @@ def preprocess_dict(
|
|
|
434
414
|
pdkpath: Optional[str] = None,
|
|
435
415
|
scl: Optional[str] = None,
|
|
436
416
|
pad: Optional[str] = None,
|
|
437
|
-
readable_paths: Optional[List[str]] = None,
|
|
438
417
|
) -> Dict[str, Any]:
|
|
439
|
-
"""
|
|
440
|
-
If readable_paths are set to None, refg:: will not work
|
|
441
|
-
"""
|
|
442
418
|
if None in (pdk, pdkpath, scl):
|
|
443
419
|
if only_extract_process_info:
|
|
444
420
|
pdkpath = ""
|
|
@@ -460,7 +436,6 @@ def preprocess_dict(
|
|
|
460
436
|
preprocessed = process_config_dict(
|
|
461
437
|
config_dict,
|
|
462
438
|
base_vars,
|
|
463
|
-
readable_paths,
|
|
464
439
|
)
|
|
465
440
|
if only_extract_process_info:
|
|
466
441
|
preprocessed = extract_process_vars(preprocessed)
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
# Copyright 2025 LibreLane Contributors
|
|
3
|
+
#
|
|
4
|
+
# Adapted from OpenLane
|
|
5
|
+
#
|
|
2
6
|
# Copyright (c) 2021-2022 Efabless Corporation
|
|
3
7
|
#
|
|
4
8
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -76,6 +80,42 @@ import click
|
|
|
76
80
|
required=True,
|
|
77
81
|
help="KLayout .map (LEF/DEF layer map) file",
|
|
78
82
|
)
|
|
83
|
+
@click.option(
|
|
84
|
+
"--grid-visible",
|
|
85
|
+
required=False,
|
|
86
|
+
default=False,
|
|
87
|
+
type=bool,
|
|
88
|
+
)
|
|
89
|
+
@click.option(
|
|
90
|
+
"--grid-show-ruler",
|
|
91
|
+
required=False,
|
|
92
|
+
default=False,
|
|
93
|
+
type=bool,
|
|
94
|
+
)
|
|
95
|
+
@click.option(
|
|
96
|
+
"--text-visible",
|
|
97
|
+
required=False,
|
|
98
|
+
default=False,
|
|
99
|
+
type=bool,
|
|
100
|
+
)
|
|
101
|
+
@click.option(
|
|
102
|
+
"--background-color",
|
|
103
|
+
required=False,
|
|
104
|
+
default=False,
|
|
105
|
+
type=str,
|
|
106
|
+
)
|
|
107
|
+
@click.option(
|
|
108
|
+
"--resolution",
|
|
109
|
+
required=False,
|
|
110
|
+
default=1000,
|
|
111
|
+
type=int,
|
|
112
|
+
)
|
|
113
|
+
@click.option(
|
|
114
|
+
"--oversampling",
|
|
115
|
+
required=False,
|
|
116
|
+
default=0,
|
|
117
|
+
type=int,
|
|
118
|
+
)
|
|
79
119
|
@click.argument("input")
|
|
80
120
|
def render(
|
|
81
121
|
input_lefs: Tuple[str, ...],
|
|
@@ -84,6 +124,12 @@ def render(
|
|
|
84
124
|
lyp: str,
|
|
85
125
|
lym: str,
|
|
86
126
|
input: str,
|
|
127
|
+
grid_visible: bool,
|
|
128
|
+
grid_show_ruler: bool,
|
|
129
|
+
text_visible: bool,
|
|
130
|
+
background_color: str,
|
|
131
|
+
resolution: int,
|
|
132
|
+
oversampling: int,
|
|
87
133
|
):
|
|
88
134
|
try:
|
|
89
135
|
gds = input.endswith(".gds")
|
|
@@ -100,18 +146,38 @@ def render(
|
|
|
100
146
|
layout_options.lefdef_config.read_lef_with_def = False
|
|
101
147
|
layout_options.lefdef_config.lef_files = list(input_lefs)
|
|
102
148
|
|
|
103
|
-
|
|
104
|
-
|
|
149
|
+
lv = pya.LayoutView()
|
|
150
|
+
|
|
151
|
+
lv.set_config("grid-visible", str(grid_visible).lower())
|
|
152
|
+
lv.set_config("grid-show-ruler", str(grid_show_ruler).lower())
|
|
153
|
+
lv.set_config("text-visible", str(text_visible).lower())
|
|
154
|
+
background_color = "#FFFFFF" if background_color == "white" else "#000000"
|
|
155
|
+
lv.set_config("background-color", background_color)
|
|
105
156
|
|
|
106
157
|
if gds:
|
|
107
|
-
|
|
158
|
+
lv.load_layout(input)
|
|
108
159
|
else:
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
160
|
+
lv.load_layout(input, layout_options, lyt)
|
|
161
|
+
|
|
162
|
+
lv.max_hier()
|
|
163
|
+
|
|
164
|
+
# Get aspect ratio
|
|
165
|
+
top_cell = lv.active_cellview().layout().top_cell()
|
|
166
|
+
top_bbox = top_cell.dbbox()
|
|
167
|
+
aspect_ratio = top_bbox.width() / top_bbox.height()
|
|
168
|
+
|
|
169
|
+
width = resolution
|
|
170
|
+
height = int(width / aspect_ratio)
|
|
171
|
+
|
|
172
|
+
lv.load_layer_props(lyp)
|
|
173
|
+
|
|
174
|
+
lv.save_image_with_options(
|
|
175
|
+
output,
|
|
176
|
+
width,
|
|
177
|
+
height,
|
|
178
|
+
oversampling=oversampling,
|
|
179
|
+
)
|
|
112
180
|
|
|
113
|
-
with open(output, "wb") as f:
|
|
114
|
-
f.write(pixels.to_png_data())
|
|
115
181
|
except Exception as e:
|
|
116
182
|
print(e)
|
|
117
183
|
exit(1)
|
|
@@ -147,3 +147,11 @@ proc read_def {} {
|
|
|
147
147
|
puts "> def read $def_read_args"
|
|
148
148
|
def read {*}$def_read_args
|
|
149
149
|
}
|
|
150
|
+
|
|
151
|
+
proc read_pdk_spice {} {
|
|
152
|
+
set spice_files_in $::env(CELL_SPICE_MODELS)
|
|
153
|
+
foreach spice_file $spice_files_in {
|
|
154
|
+
puts "> spice read $spice_file"
|
|
155
|
+
readspice $spice_file
|
|
156
|
+
}
|
|
157
|
+
}
|
|
@@ -56,6 +56,8 @@ read_def
|
|
|
56
56
|
load $::env(DESIGN_NAME)
|
|
57
57
|
select top cell
|
|
58
58
|
|
|
59
|
+
units microns
|
|
60
|
+
|
|
59
61
|
if { $::env(MAGIC_ZEROIZE_ORIGIN) } {
|
|
60
62
|
# assuming scalegrid 1 2
|
|
61
63
|
# makes origin zero based on the minimum enclosing box
|
|
@@ -73,8 +75,7 @@ if { $::env(MAGIC_ZEROIZE_ORIGIN) } {
|
|
|
73
75
|
# file. Shapes can extend outside the block boundary.
|
|
74
76
|
# magic "lef write -hide" doesn't produce nice results in this
|
|
75
77
|
# case for shapes outside the boundary.
|
|
76
|
-
|
|
77
|
-
property FIXED_BBOX [box values]
|
|
78
|
+
property FIXED_BBOX [lindex $::env(DIE_AREA) 0]um [lindex $::env(DIE_AREA) 1]um [lindex $::env(DIE_AREA) 2]um [lindex $::env(DIE_AREA) 3]um
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
select top cell
|
|
@@ -19,10 +19,11 @@ set f [open $::env(STEP_DIR)/cif_scale.txt "w"]
|
|
|
19
19
|
puts $f [expr {((round([magic::cif scale output] * 10000)) / 10000.0) * 1}]
|
|
20
20
|
close $f
|
|
21
21
|
|
|
22
|
+
source $::env(SCRIPTS_DIR)/magic/common/read.tcl
|
|
23
|
+
|
|
22
24
|
if { $::env(MAGIC_EXT_USE_GDS) } {
|
|
23
25
|
gds read $::env(CURRENT_GDS)
|
|
24
26
|
} else {
|
|
25
|
-
source $::env(SCRIPTS_DIR)/magic/common/read.tcl
|
|
26
27
|
read_tech_lef
|
|
27
28
|
read_pdk_lef
|
|
28
29
|
read_macro_lef
|
|
@@ -31,6 +32,9 @@ if { $::env(MAGIC_EXT_USE_GDS) } {
|
|
|
31
32
|
read_def
|
|
32
33
|
}
|
|
33
34
|
|
|
35
|
+
# annotate stdcell port order
|
|
36
|
+
read_pdk_spice
|
|
37
|
+
|
|
34
38
|
if { [info exists ::env(MAGIC_EXT_ABSTRACT_CELLS)] } {
|
|
35
39
|
set cells [cellname list allcells]
|
|
36
40
|
set matching_cells ""
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Copyright 2025 LibreLane Contributors
|
|
2
|
+
#
|
|
3
|
+
# Adapted from OpenLane
|
|
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
|
+
|
|
19
|
+
# we do always want to read the GDS for this
|
|
20
|
+
gds read $::env(CURRENT_GDS)
|
|
21
|
+
|
|
22
|
+
load $::env(DESIGN_NAME)
|
|
23
|
+
|
|
24
|
+
set backup $::env(PWD)
|
|
25
|
+
set extdir $::env(STEP_DIR)/extraction_full
|
|
26
|
+
set netlist $::env(STEP_DIR)/$::env(DESIGN_NAME).rcx.spice
|
|
27
|
+
|
|
28
|
+
file mkdir $extdir
|
|
29
|
+
cd $extdir
|
|
30
|
+
|
|
31
|
+
# flatten
|
|
32
|
+
select top cell
|
|
33
|
+
flatten flat
|
|
34
|
+
load flat
|
|
35
|
+
cellname delete $::env(DESIGN_NAME)
|
|
36
|
+
cellname rename flat $::env(DESIGN_NAME)
|
|
37
|
+
select top cell
|
|
38
|
+
|
|
39
|
+
# configure parasitics extraction
|
|
40
|
+
puts "capacitance extraction corner: $::env(MAGIC_RCX_EXTRACT_STYLE)"
|
|
41
|
+
extract style $::env(MAGIC_RCX_EXTRACT_STYLE)
|
|
42
|
+
|
|
43
|
+
extract do local
|
|
44
|
+
if { $::env(MAGIC_RCX_DO_CAPACITANCE) } {
|
|
45
|
+
puts "enabling capacitance"
|
|
46
|
+
extract do capacitance
|
|
47
|
+
}
|
|
48
|
+
if { $::env(MAGIC_RCX_DO_RESISTANCE) } {
|
|
49
|
+
puts "enabling resistance"
|
|
50
|
+
extract do resistance
|
|
51
|
+
}
|
|
52
|
+
extract do coupling
|
|
53
|
+
extract do adjust
|
|
54
|
+
extract do unique
|
|
55
|
+
extract warn all
|
|
56
|
+
|
|
57
|
+
# perform the SPICE extraction itself
|
|
58
|
+
extract all
|
|
59
|
+
|
|
60
|
+
# merge the extracted data into a single SPICE netlist
|
|
61
|
+
puts "capacitance threshold: $::env(MAGIC_RCX_CTHRESH)"
|
|
62
|
+
# "ext2spice lvs here" is used to configure default parameters, via Tim Edwards on fossi-chat.org matrix in
|
|
63
|
+
# #ngspice:
|
|
64
|
+
# > "I use ext2spice lvs as a shorthand for "set ext2spice parameters to something sane", after which I
|
|
65
|
+
# > re-establish the options that I want."
|
|
66
|
+
ext2spice lvs
|
|
67
|
+
ext2spice cthresh $::env(MAGIC_RCX_CTHRESH)
|
|
68
|
+
ext2spice extresist on
|
|
69
|
+
ext2spice -f ngspice -o $netlist $::env(DESIGN_NAME).ext
|
|
70
|
+
|
|
71
|
+
cd $backup
|
|
72
|
+
feedback save $::env(STEP_DIR)/feedback.txt
|
|
@@ -26,3 +26,14 @@ if { [info exists ::env(LVS_FLATTEN_CELLS)] } {
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
+
|
|
30
|
+
if { [info exists ::env(LVS_IGNORE_CELLS)] } {
|
|
31
|
+
foreach cell $::env(LVS_IGNORE_CELLS) {
|
|
32
|
+
if { [lsearch $cells1 "$cell"] >= 0 } {
|
|
33
|
+
ignore class "-circuit1 $cell"
|
|
34
|
+
}
|
|
35
|
+
if { [lsearch $cells2 "$cell"] >= 0 } {
|
|
36
|
+
ignore class "-circuit2 $cell"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -18,6 +18,49 @@
|
|
|
18
18
|
source $::env(_TCL_ENV_IN)
|
|
19
19
|
source $::env(SCRIPTS_DIR)/openroad/common/set_global_connections.tcl
|
|
20
20
|
|
|
21
|
+
namespace eval lln {
|
|
22
|
+
proc get_corner_names {} {
|
|
23
|
+
# returns: names as a Tcl list, compatible with both OpenSTA 2 and 3
|
|
24
|
+
if {[string length [namespace which sta::scenes]] != 0} {
|
|
25
|
+
# scenes are bridged as a list of strings
|
|
26
|
+
return [sta::scenes]
|
|
27
|
+
} else {
|
|
28
|
+
# corners are not bridged as strings
|
|
29
|
+
set result [list]
|
|
30
|
+
foreach corner [sta::corners] {
|
|
31
|
+
lappend result [$corner name]
|
|
32
|
+
}
|
|
33
|
+
return $result
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
proc get_corner_dict {} {
|
|
37
|
+
# returns: Tcl dictionary from corner names to whatever object is
|
|
38
|
+
# interpreted as a corner for internal commands that expect corners:
|
|
39
|
+
# - in OpenSTA 3, that's the scene's name again
|
|
40
|
+
# - in OpenSTA 2, that's an opaque Tcl pointer
|
|
41
|
+
set result [dict create]
|
|
42
|
+
if {[string length [namespace which sta::scenes]] != 0} {
|
|
43
|
+
foreach scene [sta::scenes] {
|
|
44
|
+
dict set result $scene $scene
|
|
45
|
+
}
|
|
46
|
+
} else {
|
|
47
|
+
foreach corner [sta::corners] {
|
|
48
|
+
dict set result [$corner name] $corner
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return $result
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
proc set_sta_cmd_corner {corner_name} {
|
|
55
|
+
if {[string length [namespace which sta::set_cmd_scene]] != 0} {
|
|
56
|
+
sta::set_cmd_scene $corner_name
|
|
57
|
+
} else {
|
|
58
|
+
set corner_object [sta::find_corner $corner_name]
|
|
59
|
+
sta::set_cmd_corner $corner_object
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
21
64
|
proc string_in_file {file_path substring} {
|
|
22
65
|
set f [open $file_path r]
|
|
23
66
|
set data [read $f]
|
|
@@ -532,9 +575,7 @@ proc write_views {args} {
|
|
|
532
575
|
}
|
|
533
576
|
|
|
534
577
|
if { [info exists ::env(SAVE_SDF)] } {
|
|
535
|
-
|
|
536
|
-
if { [llength $corners] > 1 } {
|
|
537
|
-
} else {
|
|
578
|
+
if { [llength [lln::get_corner_names]] <= 1 } {
|
|
538
579
|
puts "Writing SDF to '$::env(SAVE_SDF)'…"
|
|
539
580
|
write_sdf -include_typ -divider . $::env(SAVE_SDF)
|
|
540
581
|
}
|
|
@@ -543,11 +584,8 @@ proc write_views {args} {
|
|
|
543
584
|
|
|
544
585
|
proc write_sdfs {} {
|
|
545
586
|
if { [info exists ::env(_SDF_SAVE_DIR)] } {
|
|
546
|
-
set corners [sta::corners]
|
|
547
|
-
|
|
548
587
|
puts "Writing SDF files for all corners…"
|
|
549
|
-
foreach
|
|
550
|
-
set corner_name [$corner name]
|
|
588
|
+
foreach corner_name [lln::get_corner_names] {
|
|
551
589
|
set target $::env(_SDF_SAVE_DIR)/$::env(DESIGN_NAME)__$corner_name.sdf
|
|
552
590
|
write_sdf -include_typ -divider . -corner $corner_name $target
|
|
553
591
|
}
|
|
@@ -560,10 +598,8 @@ proc write_libs {} {
|
|
|
560
598
|
# This is to avoid OpenSTA writing a context-dependent timing model
|
|
561
599
|
set_clock_latency -source -max 0 [all_clocks]
|
|
562
600
|
set_clock_latency -source -min 0 [all_clocks]
|
|
563
|
-
set corners [sta::corners]
|
|
564
601
|
puts "Writing timing models for all corners…"
|
|
565
|
-
foreach
|
|
566
|
-
set corner_name [$corner name]
|
|
602
|
+
foreach corner_name [lln::get_corner_names] {
|
|
567
603
|
set target $::env(_LIB_SAVE_DIR)/$::env(DESIGN_NAME)__$corner_name.lib
|
|
568
604
|
puts "Writing timing models for the $corner_name corner to $target…"
|
|
569
605
|
write_timing_model -corner $corner_name $target
|
|
@@ -24,7 +24,7 @@ proc log_cmd_rc {cmd args} {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
proc set_layers_custom_rc {args} {
|
|
27
|
-
# Returns: All
|
|
27
|
+
# Returns: All corner names for which RC values were found
|
|
28
28
|
set i "0"
|
|
29
29
|
set tc_key "_LAYER_RC_$i"
|
|
30
30
|
set custom_corner_rc [list]
|
|
@@ -41,9 +41,8 @@ proc set_layers_custom_rc {args} {
|
|
|
41
41
|
-resistance $res_value
|
|
42
42
|
incr i
|
|
43
43
|
set tc_key "_LAYER_RC_$i"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
lappend custom_corner_rc $corner
|
|
44
|
+
if { [lsearch $custom_corner_rc $corner_name] == -1 } {
|
|
45
|
+
lappend custom_corner_rc $corner_name
|
|
47
46
|
}
|
|
48
47
|
}
|
|
49
48
|
return $custom_corner_rc
|
|
@@ -63,9 +62,8 @@ proc set_via_custom_r {args} {
|
|
|
63
62
|
-corner $corner_name
|
|
64
63
|
incr i
|
|
65
64
|
set tc_key "_VIA_R_$i"
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
lappend custom_corner_r $corner
|
|
65
|
+
if { [lsearch $custom_corner_r $corner_name] == -1 } {
|
|
66
|
+
lappend custom_corner_r $corner_name
|
|
69
67
|
}
|
|
70
68
|
}
|
|
71
69
|
return $custom_corner_r
|
|
@@ -77,7 +75,7 @@ proc set_layers_default_rc {corners} {
|
|
|
77
75
|
lassign [est::dblayer_wire_rc $layer] layer_wire_res_ohm_m layer_wire_cap_farad_m
|
|
78
76
|
set layer_wire_res_per_unit_distance [expr $layer_wire_res_ohm_m * [sta::unit_scale distance] / [sta::unit_scale resistance]]
|
|
79
77
|
set layer_wire_cap_per_unit_distance [expr $layer_wire_cap_farad_m * [sta::unit_scale distance] / [sta::unit_scale capacitance]]
|
|
80
|
-
foreach corner
|
|
78
|
+
foreach corner $corners {
|
|
81
79
|
log_cmd_rc set_layer_rc \
|
|
82
80
|
-layer $layer_name\
|
|
83
81
|
-corner $corner\
|
|
@@ -132,9 +130,9 @@ proc set_wire_rc_wrapper {args} {
|
|
|
132
130
|
}
|
|
133
131
|
|
|
134
132
|
if { [info exists flags(-use_corners)] } {
|
|
135
|
-
foreach corner [
|
|
136
|
-
log_cmd_rc set_wire_rc {*}$clock_args -corner
|
|
137
|
-
log_cmd_rc set_wire_rc {*}$signal_args -corner
|
|
133
|
+
foreach corner [lln::get_corner_names] {
|
|
134
|
+
log_cmd_rc set_wire_rc {*}$clock_args -corner $corner
|
|
135
|
+
log_cmd_rc set_wire_rc {*}$signal_args -corner $corner
|
|
138
136
|
}
|
|
139
137
|
} else {
|
|
140
138
|
log_cmd_rc set_wire_rc {*}$clock_args
|
|
@@ -163,8 +161,8 @@ proc set_diff {setA setB} {
|
|
|
163
161
|
|
|
164
162
|
set corners_with_custom_layer_rc [set_layers_custom_rc]
|
|
165
163
|
set corners_with_custom_via_r [set_via_custom_r]
|
|
166
|
-
set corners_without_custom_layer_rc [set_diff [
|
|
167
|
-
set corners_without_custom_via_r [set_diff [
|
|
164
|
+
set corners_without_custom_layer_rc [set_diff [lln::get_corner_names] $corners_with_custom_layer_rc]
|
|
165
|
+
set corners_without_custom_via_r [set_diff [lln::get_corner_names] $corners_with_custom_via_r]
|
|
168
166
|
|
|
169
167
|
# If ANY CORNERS have custom RC values set, set the tech LEF values for the
|
|
170
168
|
# remaining corners.
|
|
@@ -175,7 +173,7 @@ set corners_without_custom_via_r [set_diff [sta::corners] $corners_with_custom_v
|
|
|
175
173
|
# This is because, technically, while both behaviors SHOULD be identical, they
|
|
176
174
|
# aren't because of roundoff errors emblematic of IEEE 754.
|
|
177
175
|
if { [llength $corners_with_custom_layer_rc] } {
|
|
178
|
-
log_cmd_rc set_layers_default_rc
|
|
176
|
+
log_cmd_rc set_layers_default_rc $corners_without_custom_layer_rc
|
|
179
177
|
}
|
|
180
178
|
if { [llength $corners_with_custom_via_r] } {
|
|
181
179
|
log_cmd_rc set_vias_default_r $corners_without_custom_via_r
|
|
@@ -72,6 +72,7 @@ append_if_exists_argument arg_list CTS_MACRO_CLUSTERING_MAX_DIAMETER -macro_clus
|
|
|
72
72
|
append_if_flag arg_list CTS_DISABLE_POST_PROCESSING -post_cts_disable
|
|
73
73
|
append_if_flag arg_list CTS_OBSTRUCTION_AWARE -obstruction_aware
|
|
74
74
|
append_if_flag arg_list CTS_BALANCE_LEVELS -balance_levels
|
|
75
|
+
append_if_exists_argument arg_list CTS_APPLY_NDR -apply_ndr
|
|
75
76
|
|
|
76
77
|
if { $::env(CTS_DISTANCE_BETWEEN_BUFFERS) != 0 } {
|
|
77
78
|
lappend arg_list -distance_between_buffers $::env(CTS_DISTANCE_BETWEEN_BUFFERS)
|