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 strThe 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: u32Drawn 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 strHighest 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 strThe 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: u32How 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 strWhere these numbers come from, so a reader can check them rather than trust them.
Implementations§
Source§impl PdkTarget
impl PdkTarget
Sourcepub fn by_name(name: &str) -> Option<&'static PdkTarget>
pub fn by_name(name: &str) -> Option<&'static PdkTarget>
Look a process up by the name a run’s config.tcl records.
Sourcepub fn first_signal_layer(&self) -> &'static str
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.
Sourcepub fn layer_adjustments(
&self,
local_penalty: f64,
first_metal_penalty: f64,
) -> String
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.
Sourcepub fn plan_memory(
&self,
req: MemoryRequest,
) -> Result<MemoryPlan, PdkUnsupported>
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§
impl StructuralPartialEq for PdkTarget
Auto Trait Implementations§
impl Freeze for PdkTarget
impl RefUnwindSafe for PdkTarget
impl Send for PdkTarget
impl Sync for PdkTarget
impl Unpin for PdkTarget
impl UnsafeUnpin for PdkTarget
impl UnwindSafe for PdkTarget
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
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>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
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)
fn as_any(&self) -> &(dyn Any + 'static)
&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)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.