librelane 3.0.0.dev26__tar.gz → 3.0.0.dev28__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of librelane might be problematic. Click here for more details.
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/PKG-INFO +1 -1
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/common/__init__.py +1 -1
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/common/metrics/__main__.py +2 -1
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/common/misc.py +18 -6
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/common/tcl.py +42 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/config/flow.py +12 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/flows/cli.py +2 -2
- librelane-3.0.0.dev28/librelane/pdk_hashes.yaml +3 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/klayout/stream_out.py +26 -2
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/magic/extract_spice.tcl +1 -1
- librelane-3.0.0.dev28/librelane/scripts/openroad/write_cdl.tcl +23 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/pyosys/json_header.py +1 -1
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/pyosys/synthesize.py +1 -1
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/state/design_format.py +7 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/steps/cvc_rv.py +1 -8
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/steps/klayout.py +207 -2
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/steps/openroad.py +14 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/steps/yosys.py +1 -1
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/pyproject.toml +1 -1
- librelane-3.0.0.dev26/librelane/open_pdks_rev +0 -1
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/Readme.md +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/__init__.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/__main__.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/__version__.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/common/cli.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/common/drc.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/common/generic_dict.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/common/metrics/__init__.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/common/metrics/library.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/common/metrics/metric.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/common/metrics/util.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/common/ring_buffer.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/common/toolbox.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/common/tpe.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/common/types.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/config/__init__.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/config/__main__.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/config/config.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/config/pdk_compat.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/config/preprocessor.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/config/removals.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/config/variable.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/container.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/env_info.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/examples/spm/config.yaml +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/examples/spm/pin_order.cfg +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/examples/spm/src/impl.sdc +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/examples/spm/src/signoff.sdc +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/examples/spm/src/spm.v +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/examples/spm/verify/spm_tb.v +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/examples/spm-user_project_wrapper/SPM_example.v +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/examples/spm-user_project_wrapper/base_sdc_file.sdc +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/examples/spm-user_project_wrapper/config-tut.json +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/examples/spm-user_project_wrapper/config.json +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/examples/spm-user_project_wrapper/defines.v +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/examples/spm-user_project_wrapper/template.def +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/examples/spm-user_project_wrapper/user_project_wrapper.v +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/flows/__init__.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/flows/builtins.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/flows/classic.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/flows/flow.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/flows/misc.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/flows/optimizing.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/flows/sequential.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/flows/synth_explore.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/logging/__init__.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/logging/logger.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/plugins.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/py.typed +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/base.sdc +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/klayout/Readme.md +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/klayout/open_design.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/klayout/render.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/klayout/xml_drc_report_to_json.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/klayout/xor.drc +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/magic/Readme.md +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/magic/common/read.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/magic/def/antenna_check.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/magic/def/mag.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/magic/def/mag_gds.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/magic/drc.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/magic/gds/drc_batch.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/magic/gds/erase_box.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/magic/gds/extras_mag.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/magic/gds/mag_with_pointers.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/magic/get_bbox.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/magic/lef/extras_maglef.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/magic/lef/maglef.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/magic/lef.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/magic/open.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/magic/wrapper.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/netgen/setup.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/odbpy/apply_def_template.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/odbpy/cell_frequency.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/odbpy/check_antenna_properties.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/odbpy/contextualize.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/odbpy/defutil.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/odbpy/diodes.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/odbpy/disconnected_pins.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/odbpy/eco_buffer.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/odbpy/eco_diode.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/odbpy/filter_unannotated.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/odbpy/io_place.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/odbpy/ioplace_parser/__init__.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/odbpy/ioplace_parser/parse.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/odbpy/label_macro_pins.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/odbpy/lefutil.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/odbpy/placers.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/odbpy/power_utils.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/odbpy/random_place.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/odbpy/reader.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/odbpy/remove_buffers.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/odbpy/snap_to_grid.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/odbpy/wire_lengths.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/antenna_check.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/antenna_repair.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/basic_mp.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/buffer_list.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/common/dpl.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/common/dpl_cell_pad.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/common/grt.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/common/io.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/common/pdn_cfg.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/common/resizer.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/common/set_global_connections.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/common/set_layer_adjustments.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/common/set_power_nets.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/common/set_rc.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/common/set_routing_layers.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/cts.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/cut_rows.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/dpl.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/drt.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/dump_rc.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/fill.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/floorplan.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/gpl.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/grt.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/gui.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/insert_buffer.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/ioplacer.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/irdrop.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/pdn.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/rcx.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/repair_design.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/repair_design_postgrt.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/rsz_timing_postcts.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/rsz_timing_postgrt.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/sta/check_macro_instances.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/sta/corner.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/tapcell.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/ungpl.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/openroad/write_views.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/pyosys/construct_abc_script.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/pyosys/ys_common.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/scripts/tclsh/hello.tcl +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/state/__init__.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/state/__main__.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/state/state.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/steps/__init__.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/steps/__main__.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/steps/checker.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/steps/common_variables.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/steps/magic.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/steps/misc.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/steps/netgen.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/steps/odb.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/steps/openroad_alerts.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/steps/pyosys.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/steps/step.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/steps/tclstep.py +0 -0
- {librelane-3.0.0.dev26 → librelane-3.0.0.dev28}/librelane/steps/verilator.py +0 -0
|
@@ -158,7 +158,8 @@ def _compare_metric_folders(
|
|
|
158
158
|
continue
|
|
159
159
|
basename = basename[: -len(".metrics.json")]
|
|
160
160
|
|
|
161
|
-
|
|
161
|
+
# We have to rsplit, since ihp-sg13g2 contains a "-"
|
|
162
|
+
parts = basename.rsplit("-", maxsplit=2)
|
|
162
163
|
if len(parts) != 3:
|
|
163
164
|
raise ValueError(
|
|
164
165
|
f"Invalid filename {basename}: not in the format {{pdk}}-{{scl}}-{{design_name}}"
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
# Copyright 2025 LibreLane Contributors
|
|
2
|
+
#
|
|
3
|
+
# Adapted from OpenLane
|
|
4
|
+
#
|
|
1
5
|
# Copyright 2023 Efabless Corporation
|
|
2
6
|
#
|
|
3
7
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -16,6 +20,7 @@ import os
|
|
|
16
20
|
import re
|
|
17
21
|
import glob
|
|
18
22
|
import gzip
|
|
23
|
+
import yaml
|
|
19
24
|
import typing
|
|
20
25
|
import pathlib
|
|
21
26
|
import fnmatch
|
|
@@ -37,6 +42,7 @@ import httpx
|
|
|
37
42
|
|
|
38
43
|
from ..__version__ import __version__
|
|
39
44
|
from .types import AnyPath, Path
|
|
45
|
+
from ..logging import err
|
|
40
46
|
|
|
41
47
|
T = TypeVar("T")
|
|
42
48
|
|
|
@@ -68,15 +74,21 @@ def get_script_dir() -> str:
|
|
|
68
74
|
)
|
|
69
75
|
|
|
70
76
|
|
|
71
|
-
def
|
|
77
|
+
def get_pdk_hash(pdk_variant) -> str:
|
|
72
78
|
"""
|
|
73
|
-
Gets the
|
|
79
|
+
Gets the PDK version hash confirmed compatible with this version of LibreLane.
|
|
74
80
|
"""
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
.
|
|
78
|
-
|
|
81
|
+
|
|
82
|
+
with open(os.path.join(get_librelane_root(), "pdk_hashes.yaml"), "r") as file:
|
|
83
|
+
pdk_hashes = yaml.safe_load(file)
|
|
84
|
+
for pdk_family in pdk_hashes:
|
|
85
|
+
if pdk_family in pdk_variant:
|
|
86
|
+
return pdk_hashes[pdk_family]
|
|
87
|
+
|
|
88
|
+
err(
|
|
89
|
+
f"Could not find a PDK family for '{pdk_variant}'. Please specify a PDK manually with '--manual-pdk'."
|
|
79
90
|
)
|
|
91
|
+
exit(1)
|
|
80
92
|
|
|
81
93
|
|
|
82
94
|
# The following code snippet has been adapted under the following license:
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
# Copyright 2025 LibreLane Contributors
|
|
2
|
+
#
|
|
3
|
+
# Adapted from OpenLane
|
|
4
|
+
#
|
|
1
5
|
# Copyright 2023 Efabless Corporation
|
|
2
6
|
#
|
|
3
7
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -68,12 +72,50 @@ class TclUtils(object):
|
|
|
68
72
|
if value is not None:
|
|
69
73
|
env_out[match.group(1)] = value
|
|
70
74
|
|
|
75
|
+
def py_dict(command, target=None, *args):
|
|
76
|
+
if command == "set":
|
|
77
|
+
if match := _env_rx.fullmatch(target):
|
|
78
|
+
|
|
79
|
+
if len(args) > 1:
|
|
80
|
+
value = args[-1]
|
|
81
|
+
keys = args[:-1]
|
|
82
|
+
|
|
83
|
+
# Create new dict if it does not exist
|
|
84
|
+
if not match.group(1) in env_out:
|
|
85
|
+
env_out[match.group(1)] = {}
|
|
86
|
+
|
|
87
|
+
# set ::env(...) [dict create]
|
|
88
|
+
# will create an empty string ""
|
|
89
|
+
# convert into an empty dictionary
|
|
90
|
+
if env_out[match.group(1)] == "":
|
|
91
|
+
env_out[match.group(1)] = {}
|
|
92
|
+
|
|
93
|
+
# Set key value pair
|
|
94
|
+
cur_dict = env_out[match.group(1)]
|
|
95
|
+
|
|
96
|
+
# Create all nested dicts
|
|
97
|
+
for key in keys[:-1]:
|
|
98
|
+
if key in cur_dict:
|
|
99
|
+
cur_dict = cur_dict[key]
|
|
100
|
+
else:
|
|
101
|
+
cur_dict[key] = {}
|
|
102
|
+
cur_dict = cur_dict[key]
|
|
103
|
+
|
|
104
|
+
# Finally set the value
|
|
105
|
+
cur_dict[keys[-1]] = value
|
|
106
|
+
|
|
71
107
|
py_set_name = interpreter.register(py_set)
|
|
108
|
+
py_dict_name = interpreter.register(py_dict)
|
|
72
109
|
interpreter.call("rename", py_set_name, "_py_set")
|
|
73
110
|
interpreter.call("rename", "set", "_orig_set")
|
|
111
|
+
interpreter.call("rename", py_dict_name, "_py_dict")
|
|
112
|
+
interpreter.call("rename", "dict", "_orig_dict")
|
|
74
113
|
interpreter.eval(
|
|
75
114
|
"proc set args { _py_set {*}$args; tailcall _orig_set {*}$args; }"
|
|
76
115
|
)
|
|
116
|
+
interpreter.eval(
|
|
117
|
+
"proc dict args { _py_dict {*}$args; tailcall _orig_dict {*}$args; }"
|
|
118
|
+
)
|
|
77
119
|
|
|
78
120
|
interpreter.eval(tcl_in)
|
|
79
121
|
|
|
@@ -195,6 +195,13 @@ scl_variables = [
|
|
|
195
195
|
"Path(s) to cells' SPICE model(s)",
|
|
196
196
|
pdk=True,
|
|
197
197
|
),
|
|
198
|
+
Variable(
|
|
199
|
+
"CELL_CDLS",
|
|
200
|
+
Optional[List[Path]],
|
|
201
|
+
description="A circuit-design language view of the standard cell library.",
|
|
202
|
+
pdk=True,
|
|
203
|
+
deprecated_names=["STD_CELL_LIBRARY_CDL"],
|
|
204
|
+
),
|
|
198
205
|
Variable(
|
|
199
206
|
"SYNTH_EXCLUDED_CELL_FILE",
|
|
200
207
|
Path,
|
|
@@ -424,6 +431,11 @@ option_variables = [
|
|
|
424
431
|
Optional[List[Path]],
|
|
425
432
|
"Specifies miscellaneous SPICE models to be loaded indiscriminately whenever SPICE models are loaded.",
|
|
426
433
|
),
|
|
434
|
+
Variable(
|
|
435
|
+
"EXTRA_CDLS",
|
|
436
|
+
Optional[List[Path]],
|
|
437
|
+
"Specifies miscellaneous CDL netlists to be loaded indiscriminately whenever CDL netlists are loaded.",
|
|
438
|
+
),
|
|
427
439
|
Variable(
|
|
428
440
|
"EXTRA_LIBS",
|
|
429
441
|
Optional[List[Path]],
|
|
@@ -34,7 +34,7 @@ from cloup.constraints import (
|
|
|
34
34
|
from cloup.typing import Decorator
|
|
35
35
|
|
|
36
36
|
from .flow import Flow
|
|
37
|
-
from ..common import set_tpe, cli,
|
|
37
|
+
from ..common import set_tpe, cli, get_pdk_hash, _get_process_limit
|
|
38
38
|
from ..logging import set_log_level, verbose, err, options, LogLevels
|
|
39
39
|
from ..state import State, InvalidState
|
|
40
40
|
|
|
@@ -421,7 +421,7 @@ def cloup_flow_opts(
|
|
|
421
421
|
import ciel
|
|
422
422
|
from ciel.source import StaticWebDataSource
|
|
423
423
|
|
|
424
|
-
opdks_rev = volare_pdk_override or
|
|
424
|
+
opdks_rev = volare_pdk_override or get_pdk_hash(pdk)
|
|
425
425
|
ciel_home = ciel.get_ciel_home(pdk_root)
|
|
426
426
|
|
|
427
427
|
include_libraries = ["default"]
|
|
@@ -90,6 +90,13 @@ import click
|
|
|
90
90
|
"input",
|
|
91
91
|
type=click.Path(exists=True, file_okay=True, dir_okay=False),
|
|
92
92
|
)
|
|
93
|
+
@click.option(
|
|
94
|
+
"--conflict-resolution",
|
|
95
|
+
"conflict_resolution",
|
|
96
|
+
type=str,
|
|
97
|
+
default="RenameCell",
|
|
98
|
+
help="Cell conflict resolution handling.",
|
|
99
|
+
)
|
|
93
100
|
def stream_out(
|
|
94
101
|
output: str,
|
|
95
102
|
input_lefs: Tuple[str, ...],
|
|
@@ -100,6 +107,7 @@ def stream_out(
|
|
|
100
107
|
seal_gds: Optional[str],
|
|
101
108
|
design_name: str,
|
|
102
109
|
input: str,
|
|
110
|
+
conflict_resolution: str,
|
|
103
111
|
): # Load technology file
|
|
104
112
|
try:
|
|
105
113
|
tech = pya.Technology()
|
|
@@ -109,6 +117,22 @@ def stream_out(
|
|
|
109
117
|
layout_options.lefdef_config.lef_files = list(input_lefs)
|
|
110
118
|
layout_options.lefdef_config.map_file = lym
|
|
111
119
|
|
|
120
|
+
cell_conflict_resolution = {
|
|
121
|
+
"AddToCell": pya.LoadLayoutOptions.CellConflictResolution.AddToCell,
|
|
122
|
+
"OverwriteCell": pya.LoadLayoutOptions.CellConflictResolution.OverwriteCell,
|
|
123
|
+
"RenameCell": pya.LoadLayoutOptions.CellConflictResolution.RenameCell,
|
|
124
|
+
"SkipNewCell": pya.LoadLayoutOptions.CellConflictResolution.SkipNewCell,
|
|
125
|
+
}.get(conflict_resolution)
|
|
126
|
+
|
|
127
|
+
if cell_conflict_resolution is None:
|
|
128
|
+
print(
|
|
129
|
+
f"[ERROR] Unknown conflict resolution: '{conflict_resolution}'.",
|
|
130
|
+
file=sys.stderr,
|
|
131
|
+
)
|
|
132
|
+
exit(1)
|
|
133
|
+
else:
|
|
134
|
+
layout_options.cell_conflict_resolution = cell_conflict_resolution
|
|
135
|
+
|
|
112
136
|
# Load def file
|
|
113
137
|
main_layout = pya.Layout()
|
|
114
138
|
# main_layout.load_layer_props(props_file)
|
|
@@ -126,7 +150,7 @@ def stream_out(
|
|
|
126
150
|
# Load in the gds to merge
|
|
127
151
|
print("[INFO] Merging GDS files…")
|
|
128
152
|
for gds in input_gds_files:
|
|
129
|
-
main_layout.read(gds)
|
|
153
|
+
main_layout.read(gds, layout_options)
|
|
130
154
|
|
|
131
155
|
# Copy the top level only to a new layout
|
|
132
156
|
print(f"[INFO] Copying top level cell '{design_name}'…")
|
|
@@ -138,7 +162,7 @@ def stream_out(
|
|
|
138
162
|
print("[INFO] Checking for missing GDS…")
|
|
139
163
|
missing_gds = False
|
|
140
164
|
for i in top_only_layout.each_cell():
|
|
141
|
-
if i.
|
|
165
|
+
if i.is_ghost_cell():
|
|
142
166
|
missing_gds = True
|
|
143
167
|
print(
|
|
144
168
|
f"[ERROR] LEF Cell '{i.name}' has no matching GDS cell.",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
set f [open $::env(STEP_DIR)/cif_scale.txt "w"]
|
|
15
|
-
puts $f
|
|
15
|
+
puts $f [expr {((round([magic::cif scale output] * 10000)) / 10000.0) * 1}]
|
|
16
16
|
close $f
|
|
17
17
|
|
|
18
18
|
if { $::env(MAGIC_EXT_USE_GDS) } {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Write CDL netlist of the current design
|
|
3
|
+
#
|
|
4
|
+
|
|
5
|
+
# Load design database
|
|
6
|
+
source $::env(SCRIPTS_DIR)/openroad/common/io.tcl
|
|
7
|
+
read_current_odb
|
|
8
|
+
|
|
9
|
+
# Collect masters CDL
|
|
10
|
+
set masters {}
|
|
11
|
+
|
|
12
|
+
foreach cdl $::env(CELL_CDLS) {
|
|
13
|
+
lappend masters $cdl
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if { [info exist ::env(EXTRA_CDLS)] } {
|
|
17
|
+
foreach cdl $::env(EXTRA_CDLS) {
|
|
18
|
+
lappend masters $cdl
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
# Write only the CDL
|
|
23
|
+
write_cdl -include_fillers -masters "$masters" $::env(STEP_DIR)/$::env(DESIGN_NAME).cdl
|
|
@@ -227,7 +227,7 @@ def synthesize(
|
|
|
227
227
|
|
|
228
228
|
includes = config.get("VERILOG_INCLUDE_DIRS") or []
|
|
229
229
|
defines = (config.get("VERILOG_DEFINES") or []) + [
|
|
230
|
-
f"PDK_{config['PDK']}",
|
|
230
|
+
f"PDK_{config['PDK'].replace('-','_')}",
|
|
231
231
|
f"SCL_{config['STD_CELL_LIBRARY']}",
|
|
232
232
|
"__librelane__",
|
|
233
233
|
"__pnr__",
|
|
@@ -16,7 +16,7 @@ import re
|
|
|
16
16
|
import json
|
|
17
17
|
from enum import Enum
|
|
18
18
|
from io import StringIO, TextIOWrapper
|
|
19
|
-
from typing import
|
|
19
|
+
from typing import Optional, Tuple
|
|
20
20
|
|
|
21
21
|
from .step import StepException, ViewsUpdate, MetricsUpdate, Step
|
|
22
22
|
from ..common import Path
|
|
@@ -124,13 +124,6 @@ class ERC(Step):
|
|
|
124
124
|
description="",
|
|
125
125
|
pdk=True,
|
|
126
126
|
),
|
|
127
|
-
Variable(
|
|
128
|
-
"CELL_CDLS",
|
|
129
|
-
List[Path],
|
|
130
|
-
description="A circuit-design language view of the standard cell library.",
|
|
131
|
-
pdk=True,
|
|
132
|
-
deprecated_names=["STD_CELL_LIBRARY_CDL"],
|
|
133
|
-
),
|
|
134
127
|
]
|
|
135
128
|
|
|
136
129
|
def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
# Copyright 2025 LibreLane Contributors
|
|
2
|
+
#
|
|
3
|
+
# Adapted from OpenLane
|
|
4
|
+
#
|
|
1
5
|
# Copyright 2023 Efabless Corporation
|
|
2
6
|
#
|
|
3
7
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -19,7 +23,8 @@ import shutil
|
|
|
19
23
|
import subprocess
|
|
20
24
|
from os.path import abspath
|
|
21
25
|
from base64 import b64encode
|
|
22
|
-
from
|
|
26
|
+
from tempfile import NamedTemporaryFile
|
|
27
|
+
from typing import Any, Dict, Optional, List, Literal, Sequence, Tuple, Union
|
|
23
28
|
|
|
24
29
|
from .step import ViewsUpdate, MetricsUpdate, Step, StepError, StepException
|
|
25
30
|
|
|
@@ -196,6 +201,17 @@ class StreamOut(KLayoutStep):
|
|
|
196
201
|
inputs = [DesignFormat.DEF]
|
|
197
202
|
outputs = [DesignFormat.GDS, DesignFormat.KLAYOUT_GDS]
|
|
198
203
|
|
|
204
|
+
config_vars = KLayoutStep.config_vars + [
|
|
205
|
+
Variable(
|
|
206
|
+
"KLAYOUT_CONFLICT_RESOLUTION",
|
|
207
|
+
Optional[
|
|
208
|
+
Literal["AddToCell", "OverwriteCell", "RenameCell", "SkipNewCell"]
|
|
209
|
+
],
|
|
210
|
+
"Specifies the conflict resolution if a cell name conflict arises.",
|
|
211
|
+
default="RenameCell",
|
|
212
|
+
),
|
|
213
|
+
]
|
|
214
|
+
|
|
199
215
|
def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
|
|
200
216
|
views_updates: ViewsUpdate = {}
|
|
201
217
|
|
|
@@ -218,6 +234,8 @@ class StreamOut(KLayoutStep):
|
|
|
218
234
|
abspath(klayout_gds_out),
|
|
219
235
|
"--top",
|
|
220
236
|
self.config["DESIGN_NAME"],
|
|
237
|
+
"--conflict-resolution",
|
|
238
|
+
self.config["KLAYOUT_CONFLICT_RESOLUTION"],
|
|
221
239
|
]
|
|
222
240
|
+ self.get_cli_args(include_lefs=True, include_gds=True),
|
|
223
241
|
env=env,
|
|
@@ -431,10 +449,77 @@ class DRC(KLayoutStep):
|
|
|
431
449
|
)
|
|
432
450
|
return subprocess_result["generated_metrics"]
|
|
433
451
|
|
|
452
|
+
def run_ihp_sg13g2(self, state_in: State, **kwargs) -> MetricsUpdate:
|
|
453
|
+
kwargs, env = self.extract_env(kwargs)
|
|
454
|
+
|
|
455
|
+
drc_script_path = self.config["KLAYOUT_DRC_RUNSET"]
|
|
456
|
+
|
|
457
|
+
reports_dir = os.path.join(self.step_dir, "reports")
|
|
458
|
+
mkdirp(reports_dir)
|
|
459
|
+
xml_report = os.path.join(reports_dir, "drc_violations.klayout.xml")
|
|
460
|
+
json_report = os.path.join(reports_dir, "drc_violations.klayout.json")
|
|
461
|
+
|
|
462
|
+
input_view = state_in[DesignFormat.GDS]
|
|
463
|
+
assert isinstance(input_view, Path)
|
|
464
|
+
|
|
465
|
+
opts = []
|
|
466
|
+
for k, v in self.config["KLAYOUT_DRC_OPTIONS"].items():
|
|
467
|
+
opts.extend(
|
|
468
|
+
[
|
|
469
|
+
"-rd",
|
|
470
|
+
f"{k}={v}",
|
|
471
|
+
]
|
|
472
|
+
)
|
|
473
|
+
|
|
474
|
+
threads = self.config["KLAYOUT_DRC_THREADS"] or str(_get_process_limit())
|
|
475
|
+
if threads != "1":
|
|
476
|
+
opts.extend(
|
|
477
|
+
[
|
|
478
|
+
"-rd",
|
|
479
|
+
f"threads={threads}",
|
|
480
|
+
]
|
|
481
|
+
)
|
|
482
|
+
|
|
483
|
+
info(f"Running KLayout DRC with {threads} threads…")
|
|
484
|
+
|
|
485
|
+
# Not pya script - DRC script is not part of OpenLane
|
|
486
|
+
self.run_subprocess(
|
|
487
|
+
[
|
|
488
|
+
"klayout",
|
|
489
|
+
"-b",
|
|
490
|
+
"-zz",
|
|
491
|
+
"-r",
|
|
492
|
+
drc_script_path,
|
|
493
|
+
"-rd",
|
|
494
|
+
f"in_gds={abspath(input_view)}",
|
|
495
|
+
"-rd",
|
|
496
|
+
f"report_file={abspath(xml_report)}",
|
|
497
|
+
*opts,
|
|
498
|
+
]
|
|
499
|
+
)
|
|
500
|
+
|
|
501
|
+
subprocess_result = self.run_pya_script(
|
|
502
|
+
[
|
|
503
|
+
"python3",
|
|
504
|
+
os.path.join(
|
|
505
|
+
get_script_dir(),
|
|
506
|
+
"klayout",
|
|
507
|
+
"xml_drc_report_to_json.py",
|
|
508
|
+
),
|
|
509
|
+
f"--xml-file={abspath(xml_report)}",
|
|
510
|
+
f"--json-file={abspath(json_report)}",
|
|
511
|
+
],
|
|
512
|
+
env=env,
|
|
513
|
+
log_to=os.path.join(self.step_dir, "xml_drc_report_to_json.log"),
|
|
514
|
+
)
|
|
515
|
+
return subprocess_result["generated_metrics"]
|
|
516
|
+
|
|
434
517
|
def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
|
|
435
518
|
metrics_updates: MetricsUpdate = {}
|
|
436
519
|
if self.config["PDK"] in ["sky130A", "sky130B"]:
|
|
437
520
|
metrics_updates = self.run_sky130(state_in, **kwargs)
|
|
521
|
+
elif self.config["PDK"] in ["ihp-sg13g2"]:
|
|
522
|
+
metrics_updates = self.run_ihp_sg13g2(state_in, **kwargs)
|
|
438
523
|
else:
|
|
439
524
|
self.warn(
|
|
440
525
|
f"KLayout DRC is not supported for the {self.config['PDK']} PDK. This step will be skipped."
|
|
@@ -443,6 +528,126 @@ class DRC(KLayoutStep):
|
|
|
443
528
|
return {}, metrics_updates
|
|
444
529
|
|
|
445
530
|
|
|
531
|
+
@Step.factory.register()
|
|
532
|
+
class LVS(KLayoutStep):
|
|
533
|
+
id = "KLayout.LVS"
|
|
534
|
+
name = "Layout Versus Schematic (KLayout)"
|
|
535
|
+
|
|
536
|
+
inputs = [
|
|
537
|
+
DesignFormat.CDL,
|
|
538
|
+
DesignFormat.GDS,
|
|
539
|
+
]
|
|
540
|
+
outputs = [DesignFormat.SPICE]
|
|
541
|
+
|
|
542
|
+
config_vars = KLayoutStep.config_vars + [
|
|
543
|
+
Variable(
|
|
544
|
+
"KLAYOUT_LVS_SCRIPT",
|
|
545
|
+
Optional[Path],
|
|
546
|
+
"A path to KLayout LVS script.",
|
|
547
|
+
pdk=True,
|
|
548
|
+
),
|
|
549
|
+
Variable(
|
|
550
|
+
"KLAYOUT_LVS_OPTIONS",
|
|
551
|
+
Optional[Dict[str, Union[bool, int, str]]],
|
|
552
|
+
"Options passed directly to the KLayout LVS script. They vary from one PDK to another.",
|
|
553
|
+
pdk=True,
|
|
554
|
+
),
|
|
555
|
+
]
|
|
556
|
+
|
|
557
|
+
def run_ihp_sg13g2(
|
|
558
|
+
self, state_in: State, **kwargs
|
|
559
|
+
) -> Tuple[ViewsUpdate, MetricsUpdate]:
|
|
560
|
+
kwargs, env = self.extract_env(kwargs)
|
|
561
|
+
|
|
562
|
+
lvs_script_path = self.config["KLAYOUT_LVS_SCRIPT"]
|
|
563
|
+
|
|
564
|
+
reports_dir = os.path.join(self.step_dir, "reports")
|
|
565
|
+
mkdirp(reports_dir)
|
|
566
|
+
lvsdb_report = os.path.join(reports_dir, "lvs.klayout.lvsdb")
|
|
567
|
+
|
|
568
|
+
input_view_gds = state_in[DesignFormat.GDS]
|
|
569
|
+
input_view_cdl = state_in[DesignFormat.CDL]
|
|
570
|
+
assert isinstance(input_view_gds, Path)
|
|
571
|
+
assert isinstance(input_view_cdl, Path)
|
|
572
|
+
|
|
573
|
+
output_spice = os.path.join(
|
|
574
|
+
self.step_dir,
|
|
575
|
+
f"{self.config['DESIGN_NAME']}.{DesignFormat.SPICE.value.extension}",
|
|
576
|
+
)
|
|
577
|
+
|
|
578
|
+
with NamedTemporaryFile("w") as f:
|
|
579
|
+
# Merge all CDL inputs
|
|
580
|
+
cdl_lst = [input_view_cdl]
|
|
581
|
+
cdl_lst.extend(self.config["CELL_CDLS"] or [])
|
|
582
|
+
cdl_lst.extend(self.config["EXTRA_CDLS"] or [])
|
|
583
|
+
|
|
584
|
+
for fn in cdl_lst:
|
|
585
|
+
with open(fn, "r") as cdl_fh:
|
|
586
|
+
f.write(cdl_fh.read())
|
|
587
|
+
|
|
588
|
+
opts = []
|
|
589
|
+
for k, v in self.config["KLAYOUT_LVS_OPTIONS"].items():
|
|
590
|
+
opts.extend(
|
|
591
|
+
[
|
|
592
|
+
"-rd",
|
|
593
|
+
f"{k}={v}",
|
|
594
|
+
]
|
|
595
|
+
)
|
|
596
|
+
|
|
597
|
+
# Not pya script - LVS script is not part of LibreLane
|
|
598
|
+
subprocess_result = self.run_subprocess(
|
|
599
|
+
[
|
|
600
|
+
"klayout",
|
|
601
|
+
"-b",
|
|
602
|
+
"-zz",
|
|
603
|
+
"-r",
|
|
604
|
+
lvs_script_path,
|
|
605
|
+
"-rd",
|
|
606
|
+
f"input={abspath(input_view_gds)}",
|
|
607
|
+
"-rd",
|
|
608
|
+
f"schematic={abspath(f.name)}",
|
|
609
|
+
"-rd",
|
|
610
|
+
f"report={abspath(lvsdb_report)}",
|
|
611
|
+
"-rd",
|
|
612
|
+
f"target_netlist={abspath(output_spice)}",
|
|
613
|
+
]
|
|
614
|
+
+ opts,
|
|
615
|
+
env=env,
|
|
616
|
+
)
|
|
617
|
+
|
|
618
|
+
with open(subprocess_result["log_path"]) as fh:
|
|
619
|
+
for line in fh:
|
|
620
|
+
if "INFO : Congratulations! Netlists match" in line:
|
|
621
|
+
ok = True
|
|
622
|
+
break
|
|
623
|
+
elif "ERROR : Netlists don't match" in line:
|
|
624
|
+
ok = False
|
|
625
|
+
break
|
|
626
|
+
else:
|
|
627
|
+
ok = False
|
|
628
|
+
|
|
629
|
+
views_updates: ViewsUpdate = {
|
|
630
|
+
DesignFormat.SPICE: Path(output_spice),
|
|
631
|
+
}
|
|
632
|
+
metrics_updates: MetricsUpdate = {
|
|
633
|
+
"design__lvs_error__count": 0 if ok else 1,
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
return views_updates, metrics_updates
|
|
637
|
+
|
|
638
|
+
def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
|
|
639
|
+
metrics_updates: MetricsUpdate = {}
|
|
640
|
+
views_updates: ViewsUpdate = {}
|
|
641
|
+
if self.config["PDK"] in ["ihp-sg13g2"]:
|
|
642
|
+
views_updates, metrics_updates = self.run_ihp_sg13g2(state_in, **kwargs)
|
|
643
|
+
else:
|
|
644
|
+
self.warn(
|
|
645
|
+
f"KLayout LVS is not supported for the {self.config['PDK']} PDK. This step will be skipped."
|
|
646
|
+
)
|
|
647
|
+
|
|
648
|
+
return views_updates, metrics_updates
|
|
649
|
+
|
|
650
|
+
|
|
446
651
|
@Step.factory.register()
|
|
447
652
|
class OpenGUI(KLayoutStep):
|
|
448
653
|
"""
|
|
@@ -480,7 +685,7 @@ class OpenGUI(KLayoutStep):
|
|
|
480
685
|
|
|
481
686
|
layout = state_in[DesignFormat.DEF]
|
|
482
687
|
if self.config["KLAYOUT_GUI_USE_GDS"]:
|
|
483
|
-
if gds := state_in
|
|
688
|
+
if gds := state_in.get(DesignFormat.GDS):
|
|
484
689
|
layout = gds
|
|
485
690
|
assert isinstance(layout, Path)
|
|
486
691
|
|
|
@@ -2188,6 +2188,20 @@ class WriteViews(OpenROADStep):
|
|
|
2188
2188
|
return os.path.join(get_script_dir(), "openroad", "write_views.tcl")
|
|
2189
2189
|
|
|
2190
2190
|
|
|
2191
|
+
@Step.factory.register()
|
|
2192
|
+
class WriteCDL(OpenROADStep):
|
|
2193
|
+
"""
|
|
2194
|
+
Write CDL view of an ODB design
|
|
2195
|
+
"""
|
|
2196
|
+
|
|
2197
|
+
id = "OpenROAD.WriteCDL"
|
|
2198
|
+
name = "Write CDL"
|
|
2199
|
+
outputs = [DesignFormat.CDL]
|
|
2200
|
+
|
|
2201
|
+
def get_script_path(self):
|
|
2202
|
+
return os.path.join(get_script_dir(), "openroad", "write_cdl.tcl")
|
|
2203
|
+
|
|
2204
|
+
|
|
2191
2205
|
# Resizer Steps
|
|
2192
2206
|
|
|
2193
2207
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "librelane"
|
|
3
|
-
version = "3.0.0.
|
|
3
|
+
version = "3.0.0.dev28"
|
|
4
4
|
description = "An infrastructure for implementing chip design flows"
|
|
5
5
|
# Technically, maintainer. We cannot use the maintainers field until
|
|
6
6
|
# poetry-core>=2.0.0 which requires Python version 3.9+. This field does
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
0fe599b2afb6708d281543108caf8310912f54af
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|