Skip to main content

PdkTarget

Struct PdkTarget 

Source
pub struct PdkTarget {
Show 13 fields pub name: &'static str, pub node_nm: u32, pub std_cell_library: &'static str, pub metal_stack: &'static [&'static str], pub local_interconnect: Option<&'static str>, pub top_routing_layer: &'static str, pub clk_driving_cell: Option<(&'static str, &'static str)>, pub golden_drc_deck: &'static str, pub user_area: Option<UserArea>, pub sram_macros: &'static [SramMacro], pub precheck_checks: u32, pub estimator_layer_rc: Option<&'static [LayerRc]>, pub provenance: &'static str,
}
Expand description

One process, as data.

Fields§

§name: &'static str

The PDK variant exactly as ciel/open_pdks names it — this is the string that must appear in a run’s config.tcl and therefore in the signoff ledger.

§node_nm: u32

Drawn feature size in nanometres. Useful for first-order area scaling and nothing else.

§std_cell_library: &'static str§metal_stack: &'static [&'static str]

Routing layers bottom-to-top, in the names the tools use. sky130 says li1,met1..met5; GF180 says Metal1..Metal5 and has no li1. A six-column layer-adjustment vector written for one is silently wrong on the other, which is exactly the bug this field removes.

§local_interconnect: Option<&'static str>

The LOCAL-INTERCONNECT layer, when the process has one. sky130 has li1 below met1; GF180 does not. This is a ROLE, not a name, and conflating the two is a live bug: a layer vector that hard-penalises “the lowest layer” is right on sky130 (li1 is not for routing) and wrong on GF180, where the lowest layer IS the first real metal and hard-penalising it strangles the router. Caught by emitting for both processes and reading the result.

§top_routing_layer: &'static str

Highest layer signal routing may use on this vehicle.

§clk_driving_cell: Option<(&'static str, &'static str)>

This process’s clock-root buffer and its output pin — the cell that should be declared as the CLOCK input port’s driver, when the process has been characterized here.

OpenLane models the clock port’s drive with SYNTH_CLK_DRIVING_CELL, which DEFAULTS TO SYNTH_DRIVING_CELL — the minimum data-input inverter (sky130_fd_sc_hd__inv_2). A clock port is not driven by a minimum logic inverter on any real die; it arrives from a pad, a PLL, or (on Caravel) the management SoC’s clock distribution. The pessimism lands on the ONE net a design cannot repair, because an input port’s transition is an ASSUMPTION rather than something a resizer can buffer. Measured: systolic_os_pipe8_realbist closed every other gate and signed off with exactly three max-slew violations, and all three were that single net — clk, clkbuf_0_clk/A, and a diode sitting on it, each 0.97 against a 0.75 limit. systolic_pipe16_realbist shows the identical triple at 1.25.

The value is not invented: it is the process’s OWN ROOT_CLK_BUFFER, read from its libs.tech/openlane/<scl>/config.tcl. None means this process has not been installed and read here, and the flow then emits nothing rather than guessing a cell name that may not exist in the library — a wrong name fails the flow, and a plausible wrong one is worse.

(This cannot be expressed as ref::$ROOT_CLK_BUFFER in config.json: design-config references resolve BEFORE the PDK config is sourced, so the variable is not yet defined and OpenLane exits with Referenced variable 'ROOT_CLK_BUFFER' not found.)

§golden_drc_deck: &'static str

The efabless/foundry maximal-rule deck mpw_precheck accepts a submission against.

§user_area: Option<UserArea>

The shuttle vehicle’s fixed user area, when there is one.

§sram_macros: &'static [SramMacro]

SRAM macros the PDK ships, widest-capacity first.

§precheck_checks: u32

How many of mpw_precheck’s checks are scheduled for this PDK. It is NOT the same number for every process — gf180 drops six that sky130 runs (magic_drc, zeroarea, consistency, illegal_cellname, pin_label, metalcheck) and adds pdnmulti. “19/19” and “13/13” are not the same assurance, and a claim built on one must not be read as the other.

§estimator_layer_rc: Option<&'static [LayerRc]>

Per-layer wire RC for the PRE-ROUTE parasitic estimate (LAYERS_RC), calibrated against this project’s own extraction — or None where no process measurement exists, in which case nothing is emitted rather than another process’s numbers borrowed.

Every resizer and pre-route STA step sizes drivers against this estimate, so its error becomes the gap signoff later finds. See SKY130A_LAYER_RC for the measurement.

§provenance: &'static str

Where these numbers come from, so a reader can check them rather than trust them.

Implementations§

Source§

impl PdkTarget

Source

pub fn all() -> &'static [PdkTarget]

Every process this project can currently build against.

Source

pub fn by_name(name: &str) -> Option<&'static PdkTarget>

Look a process up by the name a run’s config.tcl records.

Source

pub fn first_signal_layer(&self) -> &'static str

The first layer signal routing should actually use: the one above local interconnect where the process has it, otherwise the bottom of the stack.

Source

pub fn layer_adjustments( &self, local_penalty: f64, first_metal_penalty: f64, ) -> String

The GRT_LAYER_ADJUSTMENTS vector — one column per routing layer, so the string can never have the wrong count for the process, and assigned by ROLE so it can never have the right count with the wrong meaning.

local_penalty applies to local interconnect (which is not for routing at all), and first_metal_penalty to the lowest real signal layer (the antenna lever). On a process with no local interconnect only the second applies — the bug this replaced put the local-interconnect penalty on GF180’s Metal1 and silently dropped the antenna one.

Source

pub fn plan_memory( &self, req: MemoryRequest, ) -> Result<MemoryPlan, PdkUnsupported>

Plan a memory onto this process’s macros, or refuse with a reason.

Refusing is the point. A design that silently “fits” because nobody checked the port count or the corner set is a design that fails at signoff, or worse, on silicon.

Trait Implementations§

Source§

impl Clone for PdkTarget

Source§

fn clone(&self) -> PdkTarget

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for PdkTarget

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl PartialEq for PdkTarget

Source§

fn eq(&self, other: &PdkTarget) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl StructuralPartialEq for PdkTarget

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
§

impl<T> Downcast for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,