librelane 3.0.0.dev49__tar.gz → 3.0.0.dev51__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.dev49 → librelane-3.0.0.dev51}/PKG-INFO +1 -1
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/__main__.py +2 -2
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/__version__.py +15 -10
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/drc.py +1 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/config/flow.py +1 -1
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/config/removals.py +1 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/flows/cli.py +21 -11
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/klayout/stream_out.py +8 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/def/mag_gds.tcl +4 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/antenna_repair.tcl +9 -5
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/common/grt.tcl +1 -3
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/drt.tcl +10 -7
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/pyosys/synthesize.py +25 -9
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/state/state.py +12 -10
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/common_variables.py +12 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/klayout.py +11 -10
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/magic.py +7 -1
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/odb.py +2 -2
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/openroad.py +12 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/pyosys.py +42 -38
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/yosys.py +0 -11
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/pyproject.toml +1 -1
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/Readme.md +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/__init__.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/__init__.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/cli.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/generic_dict.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/metrics/__init__.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/metrics/__main__.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/metrics/library.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/metrics/metric.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/metrics/util.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/misc.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/ring_buffer.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/tcl.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/toolbox.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/tpe.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/common/types.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/config/__init__.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/config/__main__.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/config/config.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/config/pdk_compat.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/config/preprocessor.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/config/variable.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/container.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/env_info.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/hold_eco_demo/config.yaml +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/hold_eco_demo/demo.v +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm/config.yaml +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm/pin_order.cfg +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm/src/impl.sdc +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm/src/signoff.sdc +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm/src/spm.v +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm/verify/spm_tb.v +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm-user_project_wrapper/SPM_example.v +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm-user_project_wrapper/base_sdc_file.sdc +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm-user_project_wrapper/config-tut.json +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm-user_project_wrapper/config.json +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm-user_project_wrapper/defines.v +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm-user_project_wrapper/template.def +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/examples/spm-user_project_wrapper/user_project_wrapper.v +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/flows/__init__.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/flows/builtins.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/flows/chip.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/flows/classic.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/flows/flow.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/flows/misc.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/flows/optimizing.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/flows/sequential.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/flows/synth_explore.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/help/__main__.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/logging/__init__.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/logging/logger.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/pdk_hashes.yaml +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/plugins.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/py.typed +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/base.sdc +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/klayout/Readme.md +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/klayout/open_design.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/klayout/render.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/klayout/xml_drc_report_to_json.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/klayout/xor.drc +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/Readme.md +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/common/read.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/def/antenna_check.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/def/mag.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/drc.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/extract_spice.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/gds/drc_batch.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/gds/erase_box.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/gds/extras_mag.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/gds/mag_with_pointers.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/get_bbox.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/lef/extras_maglef.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/lef/maglef.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/lef.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/open.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/magic/wrapper.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/netgen/setup.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/apply_def_template.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/cell_frequency.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/check_antenna_properties.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/contextualize.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/defutil.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/diodes.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/disconnected_pins.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/eco_buffer.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/eco_diode.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/filter_unannotated.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/io_place.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/ioplace_parser/__init__.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/ioplace_parser/parse.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/label_macro_pins.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/lefutil.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/placers.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/power_utils.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/random_place.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/reader.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/remove_buffers.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/snap_to_grid.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/odbpy/wire_lengths.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/antenna_check.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/buffer_list.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/common/dpl.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/common/dpl_cell_pad.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/common/io.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/common/pad_cfg.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/common/pdn_cfg.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/common/resizer.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/common/set_global_connections.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/common/set_layer_adjustments.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/common/set_power_nets.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/common/set_rc.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/common/set_routing_layers.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/cts.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/cut_rows.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/dpl.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/dump_rc.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/fill.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/floorplan.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/gpl.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/grt.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/gui.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/insert_buffer.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/ioplacer.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/irdrop.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/pad.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/pdn.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/rcx.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/repair_design.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/repair_design_postgrt.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/rsz_timing_postcts.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/rsz_timing_postgrt.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/sta/check_macro_instances.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/sta/corner.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/tapcell.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/ungpl.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/write_cdl.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/write_views.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/pyosys/construct_abc_script.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/pyosys/json_header.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/pyosys/ys_common.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/tclsh/hello.tcl +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/state/__init__.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/state/__main__.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/state/design_format.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/__init__.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/__main__.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/checker.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/misc.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/netgen.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/openroad_alerts.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/step.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/tclstep.py +0 -0
- {librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/steps/verilator.py +0 -0
|
@@ -122,13 +122,13 @@ def run(
|
|
|
122
122
|
err(f"Invalid initial state element override: '{element}'.")
|
|
123
123
|
ctx.exit(1)
|
|
124
124
|
df_id, path = element_split
|
|
125
|
-
design_format = DesignFormat.
|
|
125
|
+
design_format = DesignFormat.factory.get(df_id)
|
|
126
126
|
if design_format is None:
|
|
127
127
|
err(f"Invalid design format ID: '{df_id}'.")
|
|
128
128
|
ctx.exit(1)
|
|
129
129
|
overrides[design_format] = common.Path(path)
|
|
130
130
|
|
|
131
|
-
with_initial_state = with_initial_state
|
|
131
|
+
with_initial_state = type(with_initial_state)(
|
|
132
132
|
with_initial_state,
|
|
133
133
|
overrides=overrides,
|
|
134
134
|
)
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
# Copyright 2025 LibreLane Contributors
|
|
2
|
+
#
|
|
3
|
+
# Adapted from OpenLane 2
|
|
4
|
+
#
|
|
1
5
|
# Copyright 2023 Efabless Corporation
|
|
2
6
|
#
|
|
3
7
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -11,32 +15,33 @@
|
|
|
11
15
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
16
|
# See the License for the specific language governing permissions and
|
|
13
17
|
# limitations under the License.
|
|
14
|
-
import os
|
|
15
|
-
import importlib.metadata
|
|
16
18
|
import sys
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
import importlib.metadata
|
|
21
|
+
|
|
22
|
+
__file_dir__ = Path(__file__).absolute().parent
|
|
17
23
|
|
|
18
24
|
|
|
19
|
-
def __get_version():
|
|
25
|
+
def __get_version(pkg_name: str):
|
|
20
26
|
try:
|
|
21
27
|
return importlib.metadata.version(__package__ or __name__)
|
|
22
28
|
except importlib.metadata.PackageNotFoundError:
|
|
23
29
|
import re
|
|
24
30
|
|
|
25
31
|
rx = re.compile(r"version\s*=\s*\"([^\"]+)\"")
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
)
|
|
29
|
-
pyproject_path = os.path.join(librelane_directory, "pyproject.toml")
|
|
32
|
+
pyproject_toml_dir = __file_dir__.parent
|
|
33
|
+
pyproject_path = pyproject_toml_dir / "pyproject.toml"
|
|
30
34
|
try:
|
|
31
|
-
|
|
35
|
+
with open(pyproject_path, encoding="utf8") as f:
|
|
36
|
+
match = rx.search(f.read())
|
|
32
37
|
assert match is not None, "pyproject.toml found, but without a version"
|
|
33
38
|
return match[1]
|
|
34
39
|
except FileNotFoundError:
|
|
35
|
-
print("Warning: Failed to extract
|
|
40
|
+
print(f"Warning: Failed to extract {pkg_name} version.", file=sys.stderr)
|
|
36
41
|
return "UNKNOWN"
|
|
37
42
|
|
|
38
43
|
|
|
39
|
-
__version__ = __get_version()
|
|
44
|
+
__version__ = __get_version("librelane")
|
|
40
45
|
|
|
41
46
|
|
|
42
47
|
if __name__ == "__main__":
|
|
@@ -225,6 +225,7 @@ class DRC:
|
|
|
225
225
|
violations: Dict[str, Violation] = {}
|
|
226
226
|
last_bounding_box: Optional[BoundingBox] = None
|
|
227
227
|
lex = shlex.shlex(feedback.read(), posix=True)
|
|
228
|
+
lex.wordchars = lex.wordchars + "-"
|
|
228
229
|
components = list(lex)
|
|
229
230
|
while len(components):
|
|
230
231
|
instruction = components.pop(0)
|
|
@@ -297,7 +297,7 @@ scl_variables = [
|
|
|
297
297
|
Variable(
|
|
298
298
|
"DIODE_CELL",
|
|
299
299
|
Optional[str],
|
|
300
|
-
"Defines a diode cell used to fix antenna violations, in the format {
|
|
300
|
+
"Defines a diode cell used to fix antenna violations, in the format `{cell}/{port}`. If not defined, steps should not attempt to repair the antenna effect by inserting diode cells.",
|
|
301
301
|
pdk=True,
|
|
302
302
|
),
|
|
303
303
|
Variable(
|
|
@@ -44,4 +44,5 @@ removed_variables: Dict[str, str] = {
|
|
|
44
44
|
"FP_CONTEXT_LEF": "To be implemented.",
|
|
45
45
|
"SYNLIG_DEFER": "Synlig replaced with Slang.",
|
|
46
46
|
"VDD_PIN_VOLTAGE": "Information should be obtained from dotlib files.",
|
|
47
|
+
"LIGHTER_DFF_MAP": "Lighter has been replaced with Yosys' built-in clock gate functionality.",
|
|
47
48
|
}
|
|
@@ -17,9 +17,10 @@
|
|
|
17
17
|
# limitations under the License.
|
|
18
18
|
import os
|
|
19
19
|
import sys
|
|
20
|
+
import json
|
|
20
21
|
from functools import partial, wraps
|
|
21
22
|
from concurrent.futures import ThreadPoolExecutor
|
|
22
|
-
from typing import Optional, Union
|
|
23
|
+
from typing import Optional, Union, Tuple
|
|
23
24
|
|
|
24
25
|
from click import (
|
|
25
26
|
Context,
|
|
@@ -146,18 +147,27 @@ def set_worker_count_cb(
|
|
|
146
147
|
def initial_state_cb(
|
|
147
148
|
ctx: Context,
|
|
148
149
|
param: Parameter,
|
|
149
|
-
value:
|
|
150
|
+
value: Tuple[str],
|
|
150
151
|
):
|
|
151
|
-
if value
|
|
152
|
+
if len(value) == 0:
|
|
152
153
|
return None
|
|
153
154
|
|
|
155
|
+
raw = {}
|
|
156
|
+
for state_json in value:
|
|
157
|
+
try:
|
|
158
|
+
with open(state_json, encoding="utf8") as f:
|
|
159
|
+
state_dict = json.load(f)
|
|
160
|
+
if not isinstance(state_dict, dict):
|
|
161
|
+
raise ValueError(f"JSON data {value} is not a dictionary")
|
|
162
|
+
raw.update(state_dict)
|
|
163
|
+
except json.JSONDecodeError as e:
|
|
164
|
+
err(f"Invalid JSON file: {e}")
|
|
165
|
+
ctx.exit(-1)
|
|
166
|
+
except Exception as e:
|
|
167
|
+
err(f"Failed to read initial state: {e}")
|
|
168
|
+
ctx.exit(-1)
|
|
154
169
|
try:
|
|
155
|
-
|
|
156
|
-
except Exception as e:
|
|
157
|
-
err(f"Failed to read initial state: {e}")
|
|
158
|
-
ctx.exit(-1)
|
|
159
|
-
try:
|
|
160
|
-
initial_state = State.loads(initial_state_str, validate_path=True)
|
|
170
|
+
initial_state = State.load(raw, validate_path=True)
|
|
161
171
|
except InvalidState as e:
|
|
162
172
|
err(e)
|
|
163
173
|
ctx.exit(-1)
|
|
@@ -289,9 +299,9 @@ def cloup_flow_opts(
|
|
|
289
299
|
file_okay=True,
|
|
290
300
|
dir_okay=False,
|
|
291
301
|
),
|
|
292
|
-
|
|
302
|
+
multiple=True,
|
|
293
303
|
callback=initial_state_cb,
|
|
294
|
-
help="Use
|
|
304
|
+
help="Use these JSON files as an initial state. If multiple are provided, they are merged with keys in later files overriding keys in prior files. If none are specified, the latest `state_out.json` of the run directory will be used. If none exist, an empty initial state is created.",
|
|
295
305
|
)(f)
|
|
296
306
|
f = o(
|
|
297
307
|
"--design-dir",
|
|
@@ -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");
|
|
@@ -116,6 +120,10 @@ def stream_out(
|
|
|
116
120
|
layout_options.lefdef_config.read_lef_with_def = False
|
|
117
121
|
layout_options.lefdef_config.lef_files = list(input_lefs)
|
|
118
122
|
layout_options.lefdef_config.map_file = lym
|
|
123
|
+
# Don't produce user properties
|
|
124
|
+
layout_options.lefdef_config.net_property_name = None
|
|
125
|
+
layout_options.lefdef_config.instance_property_name = None
|
|
126
|
+
layout_options.lefdef_config.pin_property_name = None
|
|
119
127
|
|
|
120
128
|
cell_conflict_resolution = {
|
|
121
129
|
"AddToCell": pya.LoadLayoutOptions.CellConflictResolution.AddToCell,
|
{librelane-3.0.0.dev49 → librelane-3.0.0.dev51}/librelane/scripts/openroad/antenna_repair.tcl
RENAMED
|
@@ -13,14 +13,18 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
source $::env(SCRIPTS_DIR)/openroad/common/io.tcl
|
|
15
15
|
read_current_odb
|
|
16
|
-
source $::env(SCRIPTS_DIR)/openroad/common/dpl_cell_pad.tcl
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
set diode_cell [lindex [split $::env(DIODE_CELL) "/"] 0]
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
set arg_list [list]
|
|
20
|
+
lappend arg_list $diode_cell
|
|
21
|
+
lappend arg_list -iterations $::env(GRT_ANTENNA_REPAIR_ITERS)
|
|
22
|
+
lappend arg_list -ratio_margin $::env(GRT_ANTENNA_REPAIR_MARGIN)
|
|
23
|
+
append_if_flag arg_list GRT_ALLOW_CONGESTION -allow_congestion
|
|
24
|
+
append_if_flag arg_list GRT_ANTENNA_REPAIR_JUMPER_ONLY -jumper_only
|
|
25
|
+
append_if_flag arg_list GRT_ANTENNA_REPAIR_DIODE_ONLY -diode_only
|
|
21
26
|
|
|
22
|
-
|
|
23
|
-
repair_antennas "[lindex $diode_split 0]" -iterations $::env(GRT_ANTENNA_REPAIR_ITERS) -ratio_margin $::env(GRT_ANTENNA_REPAIR_MARGIN)
|
|
27
|
+
log_cmd repair_antennas {*}$arg_list
|
|
24
28
|
|
|
25
29
|
source $::env(SCRIPTS_DIR)/openroad/common/set_rc.tcl
|
|
26
30
|
estimate_parasitics -global_routing
|
|
@@ -23,9 +23,7 @@ if { ![info exists ::grt_preamble] } {
|
|
|
23
23
|
set arg_list [list]
|
|
24
24
|
lappend arg_list -congestion_iterations $::env(GRT_OVERFLOW_ITERS)
|
|
25
25
|
lappend arg_list -verbose
|
|
26
|
-
|
|
27
|
-
lappend arg_list -allow_congestion
|
|
28
|
-
}
|
|
26
|
+
append_if_flag arg_list GRT_ALLOW_CONGESTION -allow_congestion
|
|
29
27
|
|
|
30
28
|
log_cmd global_route {*}$arg_list
|
|
31
29
|
|
|
@@ -30,11 +30,6 @@ proc drt_run {i args} {
|
|
|
30
30
|
source $::env(SCRIPTS_DIR)/openroad/common/io.tcl
|
|
31
31
|
read_current_odb
|
|
32
32
|
|
|
33
|
-
# We need to call grt once, so that options like allow_congestion can be set for repair_antennas.
|
|
34
|
-
# This needs to be done before drt. If grt is called after drt, repair_antennas only uses the
|
|
35
|
-
# routing information from grt for fixing the antennas = useless.
|
|
36
|
-
source $::env(SCRIPTS_DIR)/openroad/common/grt.tcl
|
|
37
|
-
|
|
38
33
|
set_thread_count $::env(DRT_THREADS)
|
|
39
34
|
|
|
40
35
|
set drc_report_iter_step_arg ""
|
|
@@ -65,10 +60,18 @@ if { ![info exists ::env(DIODE_CELL)] } {
|
|
|
65
60
|
} else {
|
|
66
61
|
set diode_cell [lindex [split $::env(DIODE_CELL) "/"] 0]
|
|
67
62
|
|
|
63
|
+
set arg_list [list]
|
|
64
|
+
lappend arg_list $diode_cell
|
|
65
|
+
lappend arg_list -ratio_margin $::env(GRT_ANTENNA_REPAIR_MARGIN)
|
|
66
|
+
append_if_flag arg_list GRT_ALLOW_CONGESTION -allow_congestion
|
|
67
|
+
append_if_flag arg_list DRT_ANTENNA_REPAIR_JUMPER_ONLY -jumper_only
|
|
68
|
+
append_if_flag arg_list DRT_ANTENNA_REPAIR_DIODE_ONLY -diode_only
|
|
69
|
+
|
|
68
70
|
while {$i <= $::env(DRT_ANTENNA_REPAIR_ITERS) && [log_cmd check_antennas]} {
|
|
69
71
|
puts "\[INFO\] Running antenna repair iteration $i…"
|
|
70
|
-
set diodes_inserted [log_cmd repair_antennas $
|
|
71
|
-
|
|
72
|
+
set diodes_inserted [log_cmd repair_antennas {*}$arg_list]
|
|
73
|
+
|
|
74
|
+
if {$diodes_inserted || $::env(DRT_ANTENNA_REPAIR_JUMPER_ONLY)} {
|
|
72
75
|
drt_run $i {*}$drt_args
|
|
73
76
|
} else {
|
|
74
77
|
puts "\[INFO\] No diodes inserted. Ending antenna repair iterations."
|
|
@@ -240,13 +240,11 @@ def librelane_synth(
|
|
|
240
240
|
@click.option("--output", type=click.Path(exists=False, dir_okay=False), required=True)
|
|
241
241
|
@click.option("--config-in", type=click.Path(exists=True), required=True)
|
|
242
242
|
@click.option("--extra-in", type=click.Path(exists=True), required=True)
|
|
243
|
-
@click.option("--lighter-dff-map", type=click.Path(exists=True), required=False)
|
|
244
243
|
@click.argument("inputs", nargs=-1)
|
|
245
244
|
def synthesize(
|
|
246
245
|
output,
|
|
247
246
|
config_in,
|
|
248
247
|
extra_in,
|
|
249
|
-
lighter_dff_map,
|
|
250
248
|
inputs,
|
|
251
249
|
):
|
|
252
250
|
config = json.load(open(config_in))
|
|
@@ -304,7 +302,8 @@ def synthesize(
|
|
|
304
302
|
)
|
|
305
303
|
elif vhdl_files := config.get("VHDL_FILES"):
|
|
306
304
|
d.run_pass("plugin", "-i", "ghdl")
|
|
307
|
-
|
|
305
|
+
ghdl_arguments = config["GHDL_ARGUMENTS"] or []
|
|
306
|
+
d.run_pass("ghdl", *ghdl_arguments, *vhdl_files, "-e", config["DESIGN_NAME"])
|
|
308
307
|
else:
|
|
309
308
|
ys.log_error(
|
|
310
309
|
"Script called inappropriately: config must include either VERILOG_FILES or VHDL_FILES.",
|
|
@@ -335,7 +334,7 @@ def synthesize(
|
|
|
335
334
|
|
|
336
335
|
if config["SYNTH_ELABORATE_ONLY"]:
|
|
337
336
|
librelane_proc(d, report_dir)
|
|
338
|
-
if config["
|
|
337
|
+
if config["SYNTH_HIERARCHY_MODE"] in ["deferred_flatten", "flatten"]:
|
|
339
338
|
d.run_pass("flatten", "-noscopeinfo")
|
|
340
339
|
d.run_pass("setattr", "-set", "keep", "1")
|
|
341
340
|
d.run_pass("splitnets")
|
|
@@ -368,11 +367,6 @@ def synthesize(
|
|
|
368
367
|
ys.log(f"[INFO] Applying {adder_type} mapping from '{mapping}'…")
|
|
369
368
|
d.run_pass("techmap", "-map", mapping)
|
|
370
369
|
|
|
371
|
-
if mapping := lighter_dff_map:
|
|
372
|
-
ys.log(f"[INFO] Using Lighter with mapping '{mapping}'…")
|
|
373
|
-
d.run_pass("plugin", "-i", "lighter")
|
|
374
|
-
d.run_pass("reg_clock_gating", "-map", mapping)
|
|
375
|
-
|
|
376
370
|
librelane_synth(
|
|
377
371
|
d,
|
|
378
372
|
config["DESIGN_NAME"],
|
|
@@ -422,6 +416,28 @@ def synthesize(
|
|
|
422
416
|
ys.log(f"[INFO] Applying extra mappings from '{extra_mapping}'…")
|
|
423
417
|
d.run_pass("techmap", "-map", extra_mapping)
|
|
424
418
|
|
|
419
|
+
if config["SYNTH_CLOCKGATE_MIN_WIDTH"] is not None: # 0 is a valid value and falsey
|
|
420
|
+
cg_min_width = config["SYNTH_CLOCKGATE_MIN_WIDTH"]
|
|
421
|
+
posedge = ()
|
|
422
|
+
negedge = ()
|
|
423
|
+
if posedge_raw := config["SYNTH_CLOCKGATE_POSEDGE_ICG"]:
|
|
424
|
+
cell, ce, clk, gclk = posedge_raw.rsplit("/", maxsplit=4)
|
|
425
|
+
posedge = ("-pos", cell, f"{ce}:{clk}:{gclk}")
|
|
426
|
+
if negedge_raw := config["SYNTH_CLOCKGATE_NEGEDGE_ICG"]:
|
|
427
|
+
cell, ce, clk, gclk = negedge_raw.rsplit("/", maxsplit=4)
|
|
428
|
+
negedge = ("-neg", cell, f"{ce}:{clk}:{gclk}")
|
|
429
|
+
if len(posedge) == 0 and len(negedge) == 0:
|
|
430
|
+
ys.log(
|
|
431
|
+
"[WARNING] A minimum width for clock gating is set; but no ICGs are configured."
|
|
432
|
+
)
|
|
433
|
+
d.run_pass(
|
|
434
|
+
"clockgate",
|
|
435
|
+
"-min_net_size",
|
|
436
|
+
str(cg_min_width),
|
|
437
|
+
*posedge,
|
|
438
|
+
*negedge,
|
|
439
|
+
)
|
|
440
|
+
|
|
425
441
|
dfflibmap_args = []
|
|
426
442
|
for lib in libs:
|
|
427
443
|
dfflibmap_args.extend(["-liberty", lib])
|
|
@@ -253,7 +253,7 @@ class State(GenericImmutableDict[str, StateElement]):
|
|
|
253
253
|
self._walk(self.to_raw_dict(metrics=False), "", visit=visitor)
|
|
254
254
|
|
|
255
255
|
@classmethod
|
|
256
|
-
def
|
|
256
|
+
def __load_recursive(
|
|
257
257
|
Self,
|
|
258
258
|
views: Dict,
|
|
259
259
|
validate_path: bool = True,
|
|
@@ -267,7 +267,7 @@ class State(GenericImmutableDict[str, StateElement]):
|
|
|
267
267
|
continue
|
|
268
268
|
|
|
269
269
|
if isinstance(value, dict):
|
|
270
|
-
target[key] = Self.
|
|
270
|
+
target[key] = Self.__load_recursive(
|
|
271
271
|
value,
|
|
272
272
|
validate_path,
|
|
273
273
|
key_path=current_key_path,
|
|
@@ -280,6 +280,15 @@ class State(GenericImmutableDict[str, StateElement]):
|
|
|
280
280
|
target[key] = Path(value)
|
|
281
281
|
return target
|
|
282
282
|
|
|
283
|
+
@classmethod
|
|
284
|
+
def load(Self, dict_in: dict, validate_path: bool = True) -> "State":
|
|
285
|
+
metrics = dict_in.get("metrics")
|
|
286
|
+
if metrics is not None:
|
|
287
|
+
del dict_in["metrics"]
|
|
288
|
+
|
|
289
|
+
views = Self.__load_recursive(dict_in, validate_path)
|
|
290
|
+
return Self(views, metrics=metrics)
|
|
291
|
+
|
|
283
292
|
@classmethod
|
|
284
293
|
def loads(Self, json_in: str, validate_path: bool = True) -> "State":
|
|
285
294
|
try:
|
|
@@ -290,14 +299,7 @@ class State(GenericImmutableDict[str, StateElement]):
|
|
|
290
299
|
if not isinstance(raw, dict):
|
|
291
300
|
raise InvalidState("Failed to load state: JSON result is not a dictionary")
|
|
292
301
|
|
|
293
|
-
|
|
294
|
-
if metrics is not None:
|
|
295
|
-
del raw["metrics"]
|
|
296
|
-
|
|
297
|
-
views = Self.__loads_recursive(raw, validate_path)
|
|
298
|
-
state = Self(views, metrics=metrics)
|
|
299
|
-
|
|
300
|
-
return state
|
|
302
|
+
return Self.load(raw, validate_path=validate_path)
|
|
301
303
|
|
|
302
304
|
def __mapping_to_html_rec(
|
|
303
305
|
self,
|
|
@@ -423,6 +423,18 @@ grt_variables = routing_layer_variables + [
|
|
|
423
423
|
units="%",
|
|
424
424
|
deprecated_names=["GRT_ANT_MARGIN", "GRT_ANTENNA_MARGIN"],
|
|
425
425
|
),
|
|
426
|
+
Variable(
|
|
427
|
+
"GRT_ANTENNA_REPAIR_JUMPER_ONLY",
|
|
428
|
+
bool,
|
|
429
|
+
"Only use jumpers to fix antenna violations. Cannot be used in conjunction with GRT_ANTENNA_REPAIR_DIODE_ONLY.",
|
|
430
|
+
default=False,
|
|
431
|
+
),
|
|
432
|
+
Variable(
|
|
433
|
+
"GRT_ANTENNA_REPAIR_DIODE_ONLY",
|
|
434
|
+
bool,
|
|
435
|
+
"Only use antenna diodes to fix antenna violations. Cannot be used in conjunction with GRT_ANTENNA_REPAIR_JUMPER_ONLY.",
|
|
436
|
+
default=False,
|
|
437
|
+
),
|
|
426
438
|
]
|
|
427
439
|
|
|
428
440
|
rsz_variables = dpl_variables + [
|
|
@@ -413,7 +413,7 @@ class DRC(KLayoutStep):
|
|
|
413
413
|
metrics_updates = self.run_sky130(state_in, **kwargs)
|
|
414
414
|
elif self.config["PDK"] in ["gf180mcuA", "gf180mcuB", "gf180mcuC", "gf180mcuD"]:
|
|
415
415
|
metrics_updates = self.run_gf180mcu(state_in, **kwargs)
|
|
416
|
-
elif self.config["PDK"] in ["ihp-sg13g2"]:
|
|
416
|
+
elif self.config["PDK"] in ["ihp-sg13g2", "ihp-sg13cmos5l"]:
|
|
417
417
|
metrics_updates = self.run_ihp_sg13g2(state_in, **kwargs)
|
|
418
418
|
else:
|
|
419
419
|
metrics_updates = self.run_generic(state_in, **kwargs)
|
|
@@ -821,7 +821,7 @@ class LVS(KLayoutStep):
|
|
|
821
821
|
def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
|
|
822
822
|
metrics_updates: MetricsUpdate = {}
|
|
823
823
|
views_updates: ViewsUpdate = {}
|
|
824
|
-
if self.config["PDK"] in ["ihp-sg13g2"]:
|
|
824
|
+
if self.config["PDK"] in ["ihp-sg13g2", "ihp-sg13cmos5l"]:
|
|
825
825
|
views_updates, metrics_updates = self.run_ihp_sg13g2(state_in, **kwargs)
|
|
826
826
|
else:
|
|
827
827
|
self.warn(
|
|
@@ -855,7 +855,7 @@ class SealRing(KLayoutStep):
|
|
|
855
855
|
def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
|
|
856
856
|
metrics_updates: MetricsUpdate = {}
|
|
857
857
|
views_updates: ViewsUpdate = {}
|
|
858
|
-
if self.config["PDK"] in ["ihp-sg13g2"]:
|
|
858
|
+
if self.config["PDK"] in ["ihp-sg13g2", "ihp-sg13cmos5l"]:
|
|
859
859
|
views_updates, metrics_updates = self.run_ihp_sg13g2(state_in, **kwargs)
|
|
860
860
|
else:
|
|
861
861
|
views_updates, metrics_updates = self.run_generic(state_in, **kwargs)
|
|
@@ -983,7 +983,14 @@ class Filler(KLayoutStep):
|
|
|
983
983
|
def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
|
|
984
984
|
metrics_updates: MetricsUpdate = {}
|
|
985
985
|
views_updates: ViewsUpdate = {}
|
|
986
|
-
|
|
986
|
+
|
|
987
|
+
if not self.config["KLAYOUT_FILLER_SCRIPT"]:
|
|
988
|
+
self.warn(
|
|
989
|
+
f"KLAYOUT_FILLER_SCRIPT is unset. KLayout.Filler may not be supported for the {self.config['PDK']} PDK. This step will be skipped."
|
|
990
|
+
)
|
|
991
|
+
return views_updates, metrics_updates
|
|
992
|
+
|
|
993
|
+
if self.config["PDK"] in ["ihp-sg13g2", "ihp-sg13cmos5l"]:
|
|
987
994
|
views_updates, metrics_updates = self.run_ihp_sg13g2(state_in, **kwargs)
|
|
988
995
|
else:
|
|
989
996
|
views_updates, metrics_updates = self.run_generic(state_in, **kwargs)
|
|
@@ -996,12 +1003,6 @@ class Filler(KLayoutStep):
|
|
|
996
1003
|
views_updates: ViewsUpdate = {}
|
|
997
1004
|
kwargs, env = self.extract_env(kwargs)
|
|
998
1005
|
|
|
999
|
-
if not self.config["KLAYOUT_FILLER_SCRIPT"]:
|
|
1000
|
-
self.warn(
|
|
1001
|
-
f"KLAYOUT_FILLER_SCRIPT is unset. KLayout.Filler may not be supported for the {self.config['PDK']} PDK. This step will be skipped."
|
|
1002
|
-
)
|
|
1003
|
-
return views_updates, {}
|
|
1004
|
-
|
|
1005
1006
|
input_gds = state_in[DesignFormat.GDS]
|
|
1006
1007
|
assert isinstance(input_gds, Path)
|
|
1007
1008
|
output_gds = os.path.join(
|
|
@@ -98,7 +98,7 @@ class MagicStep(TclStep):
|
|
|
98
98
|
"MAGIC_DEF_LABELS",
|
|
99
99
|
bool,
|
|
100
100
|
"A flag to choose whether labels are read with DEF files or not. From magic docs: \"The '-labels' option to the 'def read' command causes each net in the NETS and SPECIALNETS sections of the DEF file to be annotated with a label having the net name as the label text.\" If LVS fails, try disabling this option.",
|
|
101
|
-
default=
|
|
101
|
+
default=False,
|
|
102
102
|
),
|
|
103
103
|
Variable(
|
|
104
104
|
"MAGIC_GDS_POLYGON_SUBCELLS",
|
|
@@ -106,6 +106,12 @@ class MagicStep(TclStep):
|
|
|
106
106
|
'A flag to enable polygon subcells in magic for gds read potentially speeding up magic. From magic docs: "Put non-Manhattan polygons. This prevents interations with other polygons on the same plane and so reduces tile splitting."',
|
|
107
107
|
default=False,
|
|
108
108
|
),
|
|
109
|
+
Variable(
|
|
110
|
+
"MAGIC_GDS_MERGE",
|
|
111
|
+
bool,
|
|
112
|
+
'A flag to enable merging of connected tiles into polygons during gds write. From magic docs: "Depending on the tile geometry, this may make the output file up to four times smaller, at the cost of speed in generating the output file."',
|
|
113
|
+
default=True,
|
|
114
|
+
),
|
|
109
115
|
Variable(
|
|
110
116
|
"MAGIC_DEF_NO_BLOCKAGES",
|
|
111
117
|
bool,
|
|
@@ -93,8 +93,8 @@ class OdbpyStep(Step):
|
|
|
93
93
|
str(state_in[DesignFormat.ODB]),
|
|
94
94
|
]
|
|
95
95
|
|
|
96
|
-
env["PYTHONPATH"] = (
|
|
97
|
-
|
|
96
|
+
env["PYTHONPATH"] = ":".join(
|
|
97
|
+
(env.get("PYTHONPATH", ""), os.path.join(get_script_dir(), "odbpy"))
|
|
98
98
|
)
|
|
99
99
|
check = False
|
|
100
100
|
if "check" in kwargs:
|
|
@@ -1934,6 +1934,18 @@ class DetailedRouting(OpenROADStep):
|
|
|
1934
1934
|
units="%",
|
|
1935
1935
|
deprecated_names=["DRT_ANTENNA_MARGIN"],
|
|
1936
1936
|
),
|
|
1937
|
+
Variable(
|
|
1938
|
+
"DRT_ANTENNA_REPAIR_JUMPER_ONLY",
|
|
1939
|
+
bool,
|
|
1940
|
+
"Only use jumpers to fix antenna violations. Cannot be used in conjunction with DRT_ANTENNA_REPAIR_DIODE_ONLY.",
|
|
1941
|
+
default=False,
|
|
1942
|
+
),
|
|
1943
|
+
Variable(
|
|
1944
|
+
"DRT_ANTENNA_REPAIR_DIODE_ONLY",
|
|
1945
|
+
bool,
|
|
1946
|
+
"Only use antenna diodes to fix antenna violations. Cannot be used in conjunction with DRT_ANTENNA_REPAIR_JUMPER_ONLY.",
|
|
1947
|
+
default=False,
|
|
1948
|
+
),
|
|
1937
1949
|
Variable(
|
|
1938
1950
|
"DRT_SAVE_DRC_REPORT_ITERS",
|
|
1939
1951
|
Optional[int],
|
|
@@ -22,7 +22,6 @@ import sys
|
|
|
22
22
|
import json
|
|
23
23
|
import fnmatch
|
|
24
24
|
import shutil
|
|
25
|
-
import subprocess
|
|
26
25
|
from decimal import Decimal
|
|
27
26
|
from abc import abstractmethod
|
|
28
27
|
from typing import List, Literal, Optional, Set, Tuple
|
|
@@ -147,6 +146,18 @@ DesignFormat(
|
|
|
147
146
|
).register()
|
|
148
147
|
|
|
149
148
|
|
|
149
|
+
def _validate_icg(
|
|
150
|
+
variable: Variable, input: Optional[str], warning_list_ref: List[str]
|
|
151
|
+
):
|
|
152
|
+
if input is not None:
|
|
153
|
+
components = input.split("/")
|
|
154
|
+
if len(components) != 4:
|
|
155
|
+
raise ValueError(
|
|
156
|
+
f"{variable.name} must be in the form '<cell>/<ce>/<clk>/<gclk>'"
|
|
157
|
+
)
|
|
158
|
+
return input
|
|
159
|
+
|
|
160
|
+
|
|
150
161
|
class PyosysStep(Step):
|
|
151
162
|
config_vars = [
|
|
152
163
|
Variable(
|
|
@@ -196,15 +207,24 @@ class PyosysStep(Step):
|
|
|
196
207
|
pdk=True,
|
|
197
208
|
),
|
|
198
209
|
Variable(
|
|
199
|
-
"
|
|
200
|
-
|
|
201
|
-
"
|
|
202
|
-
|
|
210
|
+
"SYNTH_CLOCKGATE_MIN_WIDTH",
|
|
211
|
+
Optional[int],
|
|
212
|
+
"If set to a value, a group of flip-flops with size >= SYNTH_CLOCKGATE_MIN_WIDTH and an enable signal are clock-gated instead.",
|
|
213
|
+
deprecated_names=[("USE_LIGHTER", lambda x: 1 if x else None)],
|
|
203
214
|
),
|
|
204
215
|
Variable(
|
|
205
|
-
"
|
|
206
|
-
Optional[
|
|
207
|
-
"
|
|
216
|
+
"SYNTH_CLOCKGATE_POSEDGE_ICG",
|
|
217
|
+
Optional[str],
|
|
218
|
+
"The integrated clock gate cell used for positive-edge flip-flops, in the format `<cell>/<active-high clock enable port>/<clk port>/<gated clk port>`.",
|
|
219
|
+
pdk=True,
|
|
220
|
+
validator=_validate_icg,
|
|
221
|
+
),
|
|
222
|
+
Variable(
|
|
223
|
+
"SYNTH_CLOCKGATE_NEGEDGE_ICG",
|
|
224
|
+
Optional[str],
|
|
225
|
+
"The integrated clock gate cell used for positive-edge flip-flops, in the format `<cell>/<active-high clock enable port>/<clk port>/<gated clk port>`.",
|
|
226
|
+
pdk=True,
|
|
227
|
+
validator=_validate_icg,
|
|
208
228
|
),
|
|
209
229
|
Variable(
|
|
210
230
|
"YOSYS_LOG_LEVEL",
|
|
@@ -253,12 +273,14 @@ class PyosysStep(Step):
|
|
|
253
273
|
|
|
254
274
|
def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
|
|
255
275
|
cmd = self.get_command(state_in)
|
|
276
|
+
kwargs, env = self.extract_env(kwargs)
|
|
256
277
|
# HACK: Get Colab working
|
|
257
278
|
if "google.colab" in sys.modules:
|
|
258
|
-
kwargs, env = self.extract_env(kwargs)
|
|
259
279
|
env.pop("PATH", "")
|
|
260
|
-
|
|
261
|
-
|
|
280
|
+
env["PYTHONPATH"] = ":".join(
|
|
281
|
+
(env.get("PYTHONPATH", ""), os.path.join(get_script_dir(), "pyosys"))
|
|
282
|
+
)
|
|
283
|
+
subprocess_result = super().run_subprocess(cmd, env=env, **kwargs)
|
|
262
284
|
return {}, subprocess_result["generated_metrics"]
|
|
263
285
|
|
|
264
286
|
|
|
@@ -477,7 +499,9 @@ class SynthesisCommon(VerilogStep):
|
|
|
477
499
|
(
|
|
478
500
|
"SYNTH_NO_FLAT",
|
|
479
501
|
lambda x: "deferred_flatten" if x else "flatten",
|
|
480
|
-
)
|
|
502
|
+
),
|
|
503
|
+
("SYNTH_ELABORATE_FLATTEN", lambda x: "flatten" if x else "keep"),
|
|
504
|
+
("SYNTH_FLAT_TOP", lambda x: "flatten" if x else "keep"),
|
|
481
505
|
],
|
|
482
506
|
),
|
|
483
507
|
Variable(
|
|
@@ -518,13 +542,6 @@ class SynthesisCommon(VerilogStep):
|
|
|
518
542
|
'"Elaborate" the design only without attempting any logic mapping. Useful when dealing with structural Verilog netlists.',
|
|
519
543
|
default=False,
|
|
520
544
|
),
|
|
521
|
-
Variable(
|
|
522
|
-
"SYNTH_ELABORATE_FLATTEN",
|
|
523
|
-
bool,
|
|
524
|
-
"If `SYNTH_ELABORATE_ONLY` is specified, this variable controls whether or not the top level should be flattened.",
|
|
525
|
-
default=True,
|
|
526
|
-
deprecated_names=["SYNTH_FLAT_TOP"],
|
|
527
|
-
),
|
|
528
545
|
Variable(
|
|
529
546
|
"SYNTH_MUL_BOOTH",
|
|
530
547
|
bool,
|
|
@@ -564,25 +581,7 @@ class SynthesisCommon(VerilogStep):
|
|
|
564
581
|
self.step_dir,
|
|
565
582
|
f"{self.config['DESIGN_NAME']}.{DesignFormat.NETLIST.extension}",
|
|
566
583
|
)
|
|
567
|
-
|
|
568
|
-
if self.config["USE_LIGHTER"]:
|
|
569
|
-
lighter_dff_map = self.config["LIGHTER_DFF_MAP"]
|
|
570
|
-
if lighter_dff_map is None:
|
|
571
|
-
scl = self.config["STD_CELL_LIBRARY"]
|
|
572
|
-
try:
|
|
573
|
-
raw = subprocess.check_output(
|
|
574
|
-
["lighter_files", scl], encoding="utf8"
|
|
575
|
-
)
|
|
576
|
-
files = raw.strip().splitlines()
|
|
577
|
-
lighter_dff_map = Path(files[0])
|
|
578
|
-
except FileNotFoundError:
|
|
579
|
-
self.warn(
|
|
580
|
-
"Lighter not found or not set up with LibreLane: If you're using a manual Lighter install, try setting LIGHTER_DFF_MAP explicitly."
|
|
581
|
-
)
|
|
582
|
-
except subprocess.CalledProcessError:
|
|
583
|
-
self.warn(f"{scl} not supported by Lighter.")
|
|
584
|
-
cmd.extend(["--lighter-dff-map", lighter_dff_map])
|
|
585
|
-
return cmd + ["--output", out_file]
|
|
584
|
+
return super().get_command(state_in) + ["--output", out_file]
|
|
586
585
|
|
|
587
586
|
def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
|
|
588
587
|
out_file = os.path.join(
|
|
@@ -704,4 +703,9 @@ class VHDLSynthesis(SynthesisCommon):
|
|
|
704
703
|
List[Path],
|
|
705
704
|
"The paths of the design's VHDL files.",
|
|
706
705
|
),
|
|
706
|
+
Variable(
|
|
707
|
+
"GHDL_ARGUMENTS",
|
|
708
|
+
Optional[List[str]],
|
|
709
|
+
"Pass arguments to the ghdl frontend.",
|
|
710
|
+
),
|
|
707
711
|
]
|