librelane 2.4.0.dev2__tar.gz → 2.4.0.dev4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of librelane might be problematic. Click here for more details.
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/PKG-INFO +1 -1
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/config/variable.py +12 -7
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/odbpy/defutil.py +6 -7
- librelane-2.4.0.dev4/librelane/scripts/odbpy/eco_buffer.py +181 -0
- librelane-2.4.0.dev4/librelane/scripts/odbpy/eco_diode.py +139 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/odbpy/reader.py +15 -11
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/common/io.tcl +66 -2
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/steps/__init__.py +1 -1
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/steps/odb.py +160 -24
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/steps/openroad.py +7 -2
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/steps/pyosys.py +12 -1
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/pyproject.toml +1 -1
- librelane-2.4.0.dev2/librelane/scripts/odbpy/exception_codes.py +0 -17
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/Readme.md +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/__init__.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/__main__.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/__version__.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/common/__init__.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/common/cli.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/common/drc.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/common/generic_dict.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/common/metrics/__init__.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/common/metrics/__main__.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/common/metrics/library.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/common/metrics/metric.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/common/metrics/util.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/common/misc.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/common/ring_buffer.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/common/tcl.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/common/toolbox.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/common/tpe.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/common/types.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/config/__init__.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/config/__main__.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/config/config.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/config/flow.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/config/pdk_compat.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/config/preprocessor.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/config/removals.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/container.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/env_info.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/examples/spm/config.yaml +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/examples/spm/pin_order.cfg +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/examples/spm/src/impl.sdc +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/examples/spm/src/signoff.sdc +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/examples/spm/src/spm.v +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/examples/spm/verify/spm_tb.v +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/examples/spm-user_project_wrapper/SPM_example.v +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/examples/spm-user_project_wrapper/base_sdc_file.sdc +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/examples/spm-user_project_wrapper/config-tut.json +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/examples/spm-user_project_wrapper/config.json +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/examples/spm-user_project_wrapper/defines.v +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/examples/spm-user_project_wrapper/template.def +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/examples/spm-user_project_wrapper/user_project_wrapper.v +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/flows/__init__.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/flows/builtins.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/flows/classic.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/flows/cli.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/flows/flow.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/flows/misc.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/flows/optimizing.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/flows/sequential.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/flows/synth_explore.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/logging/__init__.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/logging/logger.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/open_pdks_rev +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/plugins.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/py.typed +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/base.sdc +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/klayout/Readme.md +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/klayout/open_design.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/klayout/render.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/klayout/stream_out.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/klayout/xml_drc_report_to_json.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/klayout/xor.drc +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/magic/Readme.md +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/magic/common/read.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/magic/def/antenna_check.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/magic/def/mag.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/magic/def/mag_gds.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/magic/drc.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/magic/extract_spice.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/magic/gds/drc_batch.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/magic/gds/erase_box.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/magic/gds/extras_mag.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/magic/gds/mag_with_pointers.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/magic/get_bbox.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/magic/lef/extras_maglef.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/magic/lef/maglef.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/magic/lef.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/magic/open.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/magic/wrapper.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/netgen/setup.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/odbpy/apply_def_template.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/odbpy/cell_frequency.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/odbpy/check_antenna_properties.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/odbpy/contextualize.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/odbpy/diodes.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/odbpy/disconnected_pins.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/odbpy/filter_unannotated.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/odbpy/io_place.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/odbpy/ioplace_parser/__init__.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/odbpy/ioplace_parser/parse.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/odbpy/label_macro_pins.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/odbpy/lefutil.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/odbpy/placers.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/odbpy/power_utils.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/odbpy/random_place.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/odbpy/remove_buffers.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/odbpy/snap_to_grid.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/odbpy/wire_lengths.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/antenna_check.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/antenna_repair.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/basic_mp.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/buffer_list.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/common/dpl.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/common/dpl_cell_pad.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/common/grt.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/common/pdn_cfg.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/common/resizer.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/common/set_global_connections.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/common/set_layer_adjustments.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/common/set_power_nets.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/common/set_rc.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/common/set_routing_layers.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/cts.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/cut_rows.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/dpl.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/drt.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/fill.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/floorplan.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/gpl.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/grt.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/gui.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/insert_buffer.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/ioplacer.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/irdrop.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/pdn.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/rcx.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/repair_design.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/repair_design_postgrt.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/rsz_timing_postcts.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/rsz_timing_postgrt.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/sta/check_macro_instances.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/sta/corner.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/tapcell.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/openroad/write_views.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/pyosys/construct_abc_script.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/pyosys/json_header.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/pyosys/synthesize.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/pyosys/ys_common.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/scripts/tclsh/hello.tcl +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/state/__init__.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/state/__main__.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/state/design_format.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/state/state.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/steps/__main__.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/steps/checker.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/steps/common_variables.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/steps/cvc_rv.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/steps/klayout.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/steps/magic.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/steps/misc.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/steps/netgen.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/steps/openroad_alerts.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/steps/step.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/steps/tclstep.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/steps/verilator.py +0 -0
- {librelane-2.4.0.dev2 → librelane-2.4.0.dev4}/librelane/steps/yosys.py +0 -0
|
@@ -238,7 +238,7 @@ def some_of(t: Type[Any]) -> Type[Any]:
|
|
|
238
238
|
return new_union # type: ignore
|
|
239
239
|
|
|
240
240
|
|
|
241
|
-
def repr_type(t: Type[Any]) -> str: # pragma: no cover
|
|
241
|
+
def repr_type(t: Type[Any], for_document: bool = False) -> str: # pragma: no cover
|
|
242
242
|
optional = is_optional(t)
|
|
243
243
|
some = some_of(t)
|
|
244
244
|
|
|
@@ -247,18 +247,25 @@ def repr_type(t: Type[Any]) -> str: # pragma: no cover
|
|
|
247
247
|
else:
|
|
248
248
|
type_string = str(some)
|
|
249
249
|
|
|
250
|
+
if is_dataclass(t):
|
|
251
|
+
type_string = (
|
|
252
|
+
f"{{class}}`{some.__qualname__} <{some.__module__}.{some.__qualname__}>`"
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
separator = "|<br />" if for_document else "|"
|
|
256
|
+
|
|
250
257
|
if inspect.isclass(some) and issubclass(some, Enum):
|
|
251
|
-
type_string =
|
|
258
|
+
type_string = separator.join([str(e.name) for e in some])
|
|
252
259
|
type_string = f"`{type_string}`"
|
|
253
260
|
else:
|
|
254
261
|
origin, args = get_origin(some), get_args(some)
|
|
255
262
|
if origin is not None:
|
|
256
263
|
if origin == Union:
|
|
257
264
|
arg_strings = [repr_type(arg) for arg in args]
|
|
258
|
-
type_string =
|
|
265
|
+
type_string = separator.join(arg_strings)
|
|
259
266
|
type_string = f"({type_string})"
|
|
260
267
|
elif origin == Literal:
|
|
261
|
-
return
|
|
268
|
+
return separator.join([repr(arg) for arg in args])
|
|
262
269
|
else:
|
|
263
270
|
arg_strings = [repr_type(arg) for arg in args]
|
|
264
271
|
type_string = f"{type_string}[{', '.join(arg_strings)}]"
|
|
@@ -377,9 +384,7 @@ class Variable:
|
|
|
377
384
|
for easier wrapping by web browsers/PDF renderers/what have you
|
|
378
385
|
:returns: A pretty Markdown string representation of the Variable's type.
|
|
379
386
|
"""
|
|
380
|
-
|
|
381
|
-
return repr_type(self.type).replace("|", "|<br />")
|
|
382
|
-
return repr_type(self.type)
|
|
387
|
+
return repr_type(self.type, for_document=for_document)
|
|
383
388
|
|
|
384
389
|
def desc_repr_md(self) -> str: # pragma: no cover
|
|
385
390
|
"""
|
|
@@ -21,7 +21,6 @@ from decimal import Decimal
|
|
|
21
21
|
|
|
22
22
|
from reader import click_odb, click
|
|
23
23
|
from typing import Tuple, List
|
|
24
|
-
from exception_codes import METAL_LAYER_ERROR, FORMAT_ERROR, NOT_FOUND_ERROR
|
|
25
24
|
|
|
26
25
|
|
|
27
26
|
@click.group()
|
|
@@ -481,7 +480,7 @@ def parse_obstructions(obstructions) -> List[Tuple[str, List[int]]]:
|
|
|
481
480
|
f"[ERROR] Incorrectly formatted input {obs}.\n Format: layer llx lly urx ury, ...",
|
|
482
481
|
file=sys.stderr,
|
|
483
482
|
)
|
|
484
|
-
sys.exit(
|
|
483
|
+
sys.exit(1)
|
|
485
484
|
else:
|
|
486
485
|
layer = m.group("layer")
|
|
487
486
|
bbox = [Decimal(x) for x in m.group("bbox").split()]
|
|
@@ -505,8 +504,8 @@ def add_obstructions(reader, input_lefs, obstructions):
|
|
|
505
504
|
layer = obs[0]
|
|
506
505
|
odb_layer = reader.tech.findLayer(layer)
|
|
507
506
|
if odb_layer is None:
|
|
508
|
-
print(f"[ERROR]
|
|
509
|
-
sys.exit(
|
|
507
|
+
print(f"[ERROR] Layer '{layer}' not found.", file=sys.stderr)
|
|
508
|
+
sys.exit(1)
|
|
510
509
|
bbox = obs[1]
|
|
511
510
|
dbu = reader.tech.getDbUnitsPerMicron()
|
|
512
511
|
bbox = [int(x * dbu) for x in bbox]
|
|
@@ -550,8 +549,8 @@ def remove_obstructions(reader, input_lefs, obstructions):
|
|
|
550
549
|
bbox = [int(x * dbu) for x in bbox] # To dbus
|
|
551
550
|
found = False
|
|
552
551
|
if reader.tech.findLayer(layer) is None:
|
|
553
|
-
print(f"[ERROR]
|
|
554
|
-
sys.exit(
|
|
552
|
+
print(f"[ERROR] Layer '{layer}' not found.", file=sys.stderr)
|
|
553
|
+
sys.exit(1)
|
|
555
554
|
for odb_obstruction in existing_obstructions:
|
|
556
555
|
odb_layer, odb_bbox, odb_obj = odb_obstruction
|
|
557
556
|
if (odb_layer, odb_bbox) == (layer, bbox):
|
|
@@ -565,7 +564,7 @@ def remove_obstructions(reader, input_lefs, obstructions):
|
|
|
565
564
|
f"[ERROR] Obstruction on {layer} at {bbox} (DBU) not found.",
|
|
566
565
|
file=sys.stderr,
|
|
567
566
|
)
|
|
568
|
-
sys.exit(
|
|
567
|
+
sys.exit(1)
|
|
569
568
|
|
|
570
569
|
|
|
571
570
|
cli.add_command(remove_obstructions)
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Copyright 2025 Efabless Corporation
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
import sys
|
|
16
|
+
from reader import click_odb, click, odb
|
|
17
|
+
import grt as GRT
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def average_location(instances):
|
|
21
|
+
locations = [instance.getLocation() for instance in instances]
|
|
22
|
+
x_sum = sum(loc[0] for loc in locations)
|
|
23
|
+
y_sum = sum(loc[1] for loc in locations)
|
|
24
|
+
return (x_sum // len(locations), y_sum // len(locations))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@click.command()
|
|
28
|
+
@click_odb
|
|
29
|
+
def cli(reader):
|
|
30
|
+
grt = reader.design.getGlobalRouter()
|
|
31
|
+
dpl = reader.design.getOpendp()
|
|
32
|
+
|
|
33
|
+
insts_to_temporarily_lock_then_unlock_later = []
|
|
34
|
+
for inst in reader.block.getInsts():
|
|
35
|
+
if inst.getPlacementStatus() != "LOCKED":
|
|
36
|
+
insts_to_temporarily_lock_then_unlock_later.append(
|
|
37
|
+
(inst, inst.getPlacementStatus())
|
|
38
|
+
)
|
|
39
|
+
inst.setPlacementStatus("LOCKED")
|
|
40
|
+
|
|
41
|
+
reader._grt_setup(grt)
|
|
42
|
+
|
|
43
|
+
grt_inc = GRT.IncrementalGRoute(grt, reader.block)
|
|
44
|
+
i = 0
|
|
45
|
+
|
|
46
|
+
for target_info in reader.config["INSERT_ECO_BUFFERS"]:
|
|
47
|
+
target_name, target_pin = target_info["target"].split("/")
|
|
48
|
+
name_escaped = reader.escape_verilog_name(target_name)
|
|
49
|
+
buffer_master = target_info["buffer"]
|
|
50
|
+
|
|
51
|
+
master = reader.db.findMaster(buffer_master)
|
|
52
|
+
if master is None:
|
|
53
|
+
print(
|
|
54
|
+
f"[ERROR] Buffer type '{buffer_master}' not found.",
|
|
55
|
+
file=sys.stderr,
|
|
56
|
+
)
|
|
57
|
+
exit(-1)
|
|
58
|
+
|
|
59
|
+
target = reader.block.findInst(name_escaped)
|
|
60
|
+
if target is None:
|
|
61
|
+
print(f"[ERROR] Instance '{target_name}' not found.", file=sys.stderr)
|
|
62
|
+
exit(-1)
|
|
63
|
+
|
|
64
|
+
target_iterm = target.findITerm(target_pin)
|
|
65
|
+
if target_iterm is None:
|
|
66
|
+
print(
|
|
67
|
+
f"[ERROR] Pin '{target_pin}' not found for instance '{target_name}'.",
|
|
68
|
+
file=sys.stderr,
|
|
69
|
+
)
|
|
70
|
+
exit(-1)
|
|
71
|
+
|
|
72
|
+
net = target_iterm.getNet()
|
|
73
|
+
if net is None:
|
|
74
|
+
print(
|
|
75
|
+
f"[ERROR] Net not found on pin '{target_pin}' of instance '{target_name}'.",
|
|
76
|
+
file=sys.stderr,
|
|
77
|
+
)
|
|
78
|
+
exit(-1)
|
|
79
|
+
|
|
80
|
+
new_buf_name = f"eco_buffer_{i}"
|
|
81
|
+
new_net_name = f"eco_buffer_{i}_net"
|
|
82
|
+
while (
|
|
83
|
+
reader.block.findInst(new_buf_name) is not None
|
|
84
|
+
or reader.block.findNet(new_net_name) is not None
|
|
85
|
+
):
|
|
86
|
+
i += 1
|
|
87
|
+
new_buf_name = f"eco_buffer_{i}"
|
|
88
|
+
new_net_name = f"eco_buffer_{i}_net"
|
|
89
|
+
|
|
90
|
+
# Prepare buffer cell, net
|
|
91
|
+
eco_buffer = odb.dbInst.create(reader.block, master, new_buf_name)
|
|
92
|
+
eco_net = odb.dbNet.create(reader.block, new_net_name)
|
|
93
|
+
buffer_iterms = eco_buffer.getITerms()
|
|
94
|
+
buffer_a = None
|
|
95
|
+
for iterm in buffer_iterms:
|
|
96
|
+
if iterm.isInputSignal():
|
|
97
|
+
buffer_a = iterm
|
|
98
|
+
break # Exit loop once input is found
|
|
99
|
+
if buffer_a is None:
|
|
100
|
+
print(
|
|
101
|
+
f"[ERROR] Buffer {buffer_master} has no input signals.",
|
|
102
|
+
file=sys.stderr,
|
|
103
|
+
)
|
|
104
|
+
exit(-1)
|
|
105
|
+
|
|
106
|
+
buffer_x = None
|
|
107
|
+
for iterm in buffer_iterms:
|
|
108
|
+
if iterm.isOutputSignal():
|
|
109
|
+
buffer_x = iterm
|
|
110
|
+
break # Exit loop once output is found
|
|
111
|
+
if buffer_x is None:
|
|
112
|
+
print(
|
|
113
|
+
f"[ERROR] Buffer {buffer_master} has no output signals.",
|
|
114
|
+
file=sys.stderr,
|
|
115
|
+
)
|
|
116
|
+
exit(-1)
|
|
117
|
+
|
|
118
|
+
location_instances = [target]
|
|
119
|
+
net_iterms = net.getITerms()
|
|
120
|
+
if target_iterm.getIoType() == "INPUT":
|
|
121
|
+
driver_iterms = [
|
|
122
|
+
iterm for iterm in net_iterms if iterm.getIoType() in ["OUTPUT"]
|
|
123
|
+
]
|
|
124
|
+
drivers = [iterm.getInst() for iterm in driver_iterms]
|
|
125
|
+
location_instances.extend(drivers)
|
|
126
|
+
|
|
127
|
+
target_iterm.disconnect()
|
|
128
|
+
buffer_a.connect(net)
|
|
129
|
+
buffer_x.connect(eco_net)
|
|
130
|
+
target_iterm.connect(eco_net)
|
|
131
|
+
elif target_iterm.getIoType() == "OUTPUT":
|
|
132
|
+
sink_iterms = [
|
|
133
|
+
iterm for iterm in net_iterms if iterm.getIoType() in ["INPUT", "INOUT"]
|
|
134
|
+
]
|
|
135
|
+
sinks = [iterm.getInst() for iterm in sink_iterms]
|
|
136
|
+
location_instances.extend(sinks)
|
|
137
|
+
|
|
138
|
+
target_iterm.disconnect()
|
|
139
|
+
target_iterm.connect(eco_net)
|
|
140
|
+
buffer_a.connect(eco_net)
|
|
141
|
+
buffer_x.connect(net)
|
|
142
|
+
else:
|
|
143
|
+
print(
|
|
144
|
+
f"[ERROR] {target_name}/{target_pin} is neither an INPUT or an OUTPUT and is unsupported by this script. To buffer an INOUT port, buffer its drivers instead.",
|
|
145
|
+
file=sys.stderr,
|
|
146
|
+
)
|
|
147
|
+
exit(-1)
|
|
148
|
+
|
|
149
|
+
if target_info.get("placement") is not None:
|
|
150
|
+
eco_x, eco_y = target_info["placement"]
|
|
151
|
+
eco_x = reader.block.micronsToDbu(float(eco_x))
|
|
152
|
+
eco_y = reader.block.micronsToDbu(float(eco_y))
|
|
153
|
+
eco_loc = (eco_x, eco_y)
|
|
154
|
+
else:
|
|
155
|
+
eco_loc = average_location(location_instances)
|
|
156
|
+
|
|
157
|
+
eco_buffer.setOrient("R0")
|
|
158
|
+
eco_buffer.setLocation(*eco_loc)
|
|
159
|
+
eco_buffer.setPlacementStatus("PLACED")
|
|
160
|
+
grt.addDirtyNet(net)
|
|
161
|
+
grt.addDirtyNet(eco_net)
|
|
162
|
+
|
|
163
|
+
site = reader.rows[0].getSite()
|
|
164
|
+
max_disp_x = int(
|
|
165
|
+
reader.design.micronToDBU(reader.config["PL_MAX_DISPLACEMENT_X"])
|
|
166
|
+
/ site.getWidth()
|
|
167
|
+
)
|
|
168
|
+
max_disp_y = int(
|
|
169
|
+
reader.design.micronToDBU(reader.config["PL_MAX_DISPLACEMENT_Y"])
|
|
170
|
+
/ site.getHeight()
|
|
171
|
+
)
|
|
172
|
+
dpl.detailedPlacement(max_disp_x, max_disp_y)
|
|
173
|
+
|
|
174
|
+
grt_inc.updateRoutes(True)
|
|
175
|
+
|
|
176
|
+
for inst, previous_status in insts_to_temporarily_lock_then_unlock_later:
|
|
177
|
+
inst.setPlacementStatus(previous_status)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
if __name__ == "__main__":
|
|
181
|
+
cli()
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Copyright 2025 Efabless Corporation
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
import sys
|
|
16
|
+
from reader import click_odb, click, odb
|
|
17
|
+
import grt as GRT
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@click.command()
|
|
21
|
+
@click_odb
|
|
22
|
+
def cli(reader):
|
|
23
|
+
grt = reader.design.getGlobalRouter()
|
|
24
|
+
dpl = reader.design.getOpendp()
|
|
25
|
+
|
|
26
|
+
insts_to_temporarily_lock_then_unlock_later = []
|
|
27
|
+
for inst in reader.block.getInsts():
|
|
28
|
+
if inst.getPlacementStatus() != "LOCKED":
|
|
29
|
+
insts_to_temporarily_lock_then_unlock_later.append(
|
|
30
|
+
(inst, inst.getPlacementStatus())
|
|
31
|
+
)
|
|
32
|
+
inst.setPlacementStatus("LOCKED")
|
|
33
|
+
|
|
34
|
+
reader._grt_setup(grt)
|
|
35
|
+
|
|
36
|
+
diode_master, diode_pin = reader.config["DIODE_CELL"].split("/")
|
|
37
|
+
|
|
38
|
+
# print(grt)
|
|
39
|
+
grt_inc = GRT.IncrementalGRoute(grt, reader.block)
|
|
40
|
+
i = 0
|
|
41
|
+
for target_info in reader.config["INSERT_ECO_DIODES"]:
|
|
42
|
+
target_name, target_pin = target_info["target"].split("/")
|
|
43
|
+
name_escaped = reader.escape_verilog_name(target_name)
|
|
44
|
+
|
|
45
|
+
target = reader.block.findInst(name_escaped)
|
|
46
|
+
if target is None:
|
|
47
|
+
print(
|
|
48
|
+
f"[ERROR] Instance '{target_name}' not found.",
|
|
49
|
+
file=sys.stderr,
|
|
50
|
+
)
|
|
51
|
+
exit(-1)
|
|
52
|
+
|
|
53
|
+
master = reader.db.findMaster(diode_master)
|
|
54
|
+
if master is None:
|
|
55
|
+
print(
|
|
56
|
+
f"[ERROR] Cell kind '{diode_master}' not found.",
|
|
57
|
+
file=sys.stderr,
|
|
58
|
+
)
|
|
59
|
+
exit(-1)
|
|
60
|
+
|
|
61
|
+
target_iterm = target.findITerm(target_pin)
|
|
62
|
+
if target_iterm is None:
|
|
63
|
+
print(
|
|
64
|
+
f"[ERROR] Pin '{target_pin}' not found for instance {target_name}.",
|
|
65
|
+
file=sys.stderr,
|
|
66
|
+
)
|
|
67
|
+
exit(-1)
|
|
68
|
+
|
|
69
|
+
if target_iterm.getIoType() not in ["INPUT", "INOUT"]:
|
|
70
|
+
print(
|
|
71
|
+
f"[ERROR] Pin {target_info['target']} is an OUTPUT pin.",
|
|
72
|
+
file=sys.stderr,
|
|
73
|
+
)
|
|
74
|
+
exit(-1)
|
|
75
|
+
|
|
76
|
+
net = target_iterm.getNet()
|
|
77
|
+
if net is None:
|
|
78
|
+
print(
|
|
79
|
+
f"[ERROR] Pin {target_info['target']} has no nets connected.",
|
|
80
|
+
file=sys.stderr,
|
|
81
|
+
)
|
|
82
|
+
exit(-1)
|
|
83
|
+
|
|
84
|
+
eco_diode_name = f"eco_diode_{i}"
|
|
85
|
+
while reader.block.findInst(eco_diode_name) is not None:
|
|
86
|
+
i += 1
|
|
87
|
+
eco_diode_name = f"eco_diode_{i}"
|
|
88
|
+
|
|
89
|
+
eco_diode = odb.dbInst.create(
|
|
90
|
+
reader.block,
|
|
91
|
+
master,
|
|
92
|
+
eco_diode_name,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
diode_iterm = eco_diode.findITerm(diode_pin)
|
|
96
|
+
if diode_iterm is None:
|
|
97
|
+
print(
|
|
98
|
+
f"[ERROR] Pin '{diode_pin}' on ECO diode not found- invalid DIODE_CELL definition.",
|
|
99
|
+
file=sys.stderr,
|
|
100
|
+
)
|
|
101
|
+
exit(-1)
|
|
102
|
+
|
|
103
|
+
sys.stdout.flush()
|
|
104
|
+
|
|
105
|
+
if target_info["placement"] is not None:
|
|
106
|
+
x, y = target_info["placement"]
|
|
107
|
+
x = reader.block.micronsToDbu(float(x))
|
|
108
|
+
y = reader.block.micronsToDbu(float(y))
|
|
109
|
+
else:
|
|
110
|
+
x, y = target.getLocation()
|
|
111
|
+
|
|
112
|
+
eco_diode.setOrient("R0")
|
|
113
|
+
eco_diode.setLocation(x, y)
|
|
114
|
+
eco_diode.setPlacementStatus("PLACED")
|
|
115
|
+
|
|
116
|
+
diode_iterm.connect(net)
|
|
117
|
+
grt.addDirtyNet(net)
|
|
118
|
+
|
|
119
|
+
site = reader.rows[0].getSite()
|
|
120
|
+
max_disp_x = int(
|
|
121
|
+
reader.design.micronToDBU(reader.config["PL_MAX_DISPLACEMENT_X"])
|
|
122
|
+
/ site.getWidth()
|
|
123
|
+
)
|
|
124
|
+
max_disp_y = int(
|
|
125
|
+
reader.design.micronToDBU(reader.config["PL_MAX_DISPLACEMENT_Y"])
|
|
126
|
+
/ site.getHeight()
|
|
127
|
+
)
|
|
128
|
+
dpl.detailedPlacement(max_disp_x, max_disp_y)
|
|
129
|
+
|
|
130
|
+
grt_inc.updateRoutes(True)
|
|
131
|
+
|
|
132
|
+
for inst, previous_status in insts_to_temporarily_lock_then_unlock_later:
|
|
133
|
+
inst.setPlacementStatus(previous_status)
|
|
134
|
+
|
|
135
|
+
reader.design.writeDef("out.def")
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
if __name__ == "__main__":
|
|
139
|
+
cli()
|
|
@@ -131,16 +131,9 @@ class OdbReader(object):
|
|
|
131
131
|
dpl.reportLegalizationStats()
|
|
132
132
|
dpl.optimizeMirroring()
|
|
133
133
|
|
|
134
|
-
def
|
|
135
|
-
""
|
|
136
|
-
The ``._grt()`` method is EXPERIMENTAL and SHOULD NOT BE USED YET.
|
|
137
|
-
|
|
138
|
-
Use a composite step with ``OpenROAD.GlobalRouting``.
|
|
139
|
-
"""
|
|
140
|
-
if self.config is None:
|
|
141
|
-
raise RuntimeError("Attempted to call grt without config file")
|
|
134
|
+
def _grt_setup(self, grt):
|
|
135
|
+
grt.setAdjustment(float(self.config["GRT_ADJUSTMENT"]))
|
|
142
136
|
|
|
143
|
-
grt = self.design.getGlobalRouter()
|
|
144
137
|
routing_layers = [l for l in self.layers.values() if l.getRoutingLevel() >= 1]
|
|
145
138
|
for layer, adj in zip(routing_layers, self.config["GRT_LAYER_ADJUSTMENTS"]):
|
|
146
139
|
grt.addLayerAdjustment(
|
|
@@ -170,14 +163,25 @@ class OdbReader(object):
|
|
|
170
163
|
raise RuntimeError(f"Unknown layer name '{max_clk_name}'")
|
|
171
164
|
max_clk_idx = self.layers[max_clk_name].getRoutingLevel()
|
|
172
165
|
|
|
173
|
-
grt.setMinRoutingLayer(min_layer_idx)
|
|
174
|
-
grt.setMaxRoutingLayer(max_layer_idx)
|
|
175
166
|
grt.setMinLayerForClock(min_clk_idx)
|
|
176
167
|
grt.setMaxLayerForClock(max_clk_idx)
|
|
177
168
|
grt.setMacroExtension(self.config["GRT_MACRO_EXTENSION"])
|
|
178
169
|
grt.setOverflowIterations(self.config["GRT_OVERFLOW_ITERS"])
|
|
179
170
|
grt.setAllowCongestion(self.config["GRT_ALLOW_CONGESTION"])
|
|
180
171
|
grt.setVerbose(True)
|
|
172
|
+
grt.initFastRoute(min_layer_idx, max_layer_idx)
|
|
173
|
+
|
|
174
|
+
def _grt(self):
|
|
175
|
+
"""
|
|
176
|
+
The ``._grt()`` method is EXPERIMENTAL and SHOULD NOT BE USED YET.
|
|
177
|
+
|
|
178
|
+
Use a composite step with ``OpenROAD.GlobalRouting``.
|
|
179
|
+
"""
|
|
180
|
+
if self.config is None:
|
|
181
|
+
raise RuntimeError("Attempted to call grt without config file")
|
|
182
|
+
|
|
183
|
+
grt = self.design.getGlobalRouter()
|
|
184
|
+
self._grt_setup(grt)
|
|
181
185
|
grt.globalRoute(
|
|
182
186
|
True
|
|
183
187
|
) # The first variable updates guides- not sure why the default is False
|
|
@@ -316,6 +316,70 @@ proc read_current_odb {args} {
|
|
|
316
316
|
set_dont_use_cells
|
|
317
317
|
}
|
|
318
318
|
|
|
319
|
+
proc _populate_cells_by_class {} {
|
|
320
|
+
if { [info exists ::_cells_by_class(physical)] } {
|
|
321
|
+
return
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
set ::_cells_by_class(physical) [list]
|
|
325
|
+
set ::_cells_by_class(non_timing) [list]
|
|
326
|
+
set _comment_ {
|
|
327
|
+
We naïvely assume anything not in these classes is not a cell with a
|
|
328
|
+
logical function. This may not be comprehensive, but is good enough.
|
|
329
|
+
|
|
330
|
+
CORE just means a macro used in the core area (i.e. a standard cell.)
|
|
331
|
+
|
|
332
|
+
Thing is, it has a lot of subclasses for physical cells:
|
|
333
|
+
|
|
334
|
+
`FEEDTHRU`,`SPACER`,`ANTENNACELL`,`WELLTAP`
|
|
335
|
+
|
|
336
|
+
Only `TIEHIGH`, `TIELOW` are for logical cells. Thus, the inclusion
|
|
337
|
+
list allows them as well. `BLOCKS` are macros, which we cannot discern
|
|
338
|
+
whether they have a logical function or not, so we include them
|
|
339
|
+
regardless.
|
|
340
|
+
|
|
341
|
+
We do make one exception for `ANTENNACELL`s. These are not counted as
|
|
342
|
+
logical cells but they are not exempt from the so-called SDF-friendly
|
|
343
|
+
netlist as they do affect timing ever so slightly.
|
|
344
|
+
}
|
|
345
|
+
set logical_classes {
|
|
346
|
+
BLOCK
|
|
347
|
+
BUMP
|
|
348
|
+
CORE
|
|
349
|
+
CORE_TIEHIGH
|
|
350
|
+
CORE_TIELOW
|
|
351
|
+
COVER
|
|
352
|
+
PAD
|
|
353
|
+
PAD_AREAIO
|
|
354
|
+
PAD_INOUT
|
|
355
|
+
PAD_INPUT
|
|
356
|
+
PAD_OUTPUT
|
|
357
|
+
PAD_POWER
|
|
358
|
+
PAD_SPACER
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
foreach lib $::libs {
|
|
362
|
+
foreach master [$lib getMasters] {
|
|
363
|
+
if { [lsearch -exact $logical_classes [$master getType]] == -1 } {
|
|
364
|
+
lappend ::_cells_by_class(physical) [$master getName]
|
|
365
|
+
if { "[$master getType]" != "CORE_ANTENNACELL" } {
|
|
366
|
+
lappend ::_cells_by_class(non_timing) [$master getName]
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
proc get_timing_excluded_cells {args} {
|
|
374
|
+
_populate_cells_by_class
|
|
375
|
+
return $::_cells_by_class(non_timing)
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
proc get_physical_cells {args} {
|
|
379
|
+
_populate_cells_by_class
|
|
380
|
+
return $::_cells_by_class(physical)
|
|
381
|
+
}
|
|
382
|
+
|
|
319
383
|
proc write_views {args} {
|
|
320
384
|
# This script will attempt to write views based on existing "SAVE_"
|
|
321
385
|
# environment variables. If the SAVE_ variable exists, the script will
|
|
@@ -349,7 +413,7 @@ proc write_views {args} {
|
|
|
349
413
|
}
|
|
350
414
|
|
|
351
415
|
if { [info exists ::env(SAVE_POWERED_NETLIST_SDF_FRIENDLY)] } {
|
|
352
|
-
set exclude_cells "[
|
|
416
|
+
set exclude_cells "[get_timing_excluded_cells]"
|
|
353
417
|
puts "Writing nofill powered netlist to '$::env(SAVE_POWERED_NETLIST_SDF_FRIENDLY)'…"
|
|
354
418
|
puts "Excluding $exclude_cells"
|
|
355
419
|
write_verilog -include_pwr_gnd \
|
|
@@ -358,7 +422,7 @@ proc write_views {args} {
|
|
|
358
422
|
}
|
|
359
423
|
|
|
360
424
|
if { [info exists ::env(SAVE_POWERED_NETLIST_NO_PHYSICAL_CELLS)] } {
|
|
361
|
-
set exclude_cells "[
|
|
425
|
+
set exclude_cells "[get_physical_cells]"
|
|
362
426
|
puts "Writing nofilldiode powered netlist to '$::env(SAVE_POWERED_NETLIST_NO_PHYSICAL_CELLS)'…"
|
|
363
427
|
puts "Excluding $exclude_cells"
|
|
364
428
|
write_verilog -include_pwr_gnd \
|