From 068fca46f862ff11eba1c3823cbce06728d3ec81 Mon Sep 17 00:00:00 2001 From: Ben Bowers Date: Tue, 16 Jul 2024 07:11:44 -0400 Subject: [PATCH] fixing schema bug with PROPERTYDEFINITION --- lef21/resources/lef21.schema.json | 316 +++++++++++++++++++++++++----- lef21/src/data.rs | 48 +++-- lef21/src/read.rs | 2 +- lef21/src/write.rs | 2 +- 4 files changed, 299 insertions(+), 69 deletions(-) diff --git a/lef21/resources/lef21.schema.json b/lef21/resources/lef21.schema.json index 6f5d3bf..99b6b2a 100644 --- a/lef21/resources/lef21.schema.json +++ b/lef21/resources/lef21.schema.json @@ -3,6 +3,9 @@ "title": "Lef Library", "description": "LEF's primary design-content container, including a set of macro/cell definitions and associated metadata.", "type": "object", + "required": [ + "fixed_mask" + ], "properties": { "bus_bit_chars": { "description": "Bus-Bit Separator Characters", @@ -27,10 +30,9 @@ }, "clearance_measure": { "description": "Clearance Measure", - "writeOnly": true, "anyOf": [ { - "$ref": "#/definitions/Unsupported" + "$ref": "#/definitions/LefClearanceStyle" }, { "type": "null" @@ -47,16 +49,15 @@ "minLength": 1 }, "extensions": { - "description": "Syntax Extensions (Unsupported)", + "description": "Syntax Extensions", + "type": "array", + "items": { + "$ref": "#/definitions/LefExtension" + } + }, + "fixed_mask": { "writeOnly": true, - "anyOf": [ - { - "$ref": "#/definitions/Unsupported" - }, - { - "type": "null" - } - ] + "type": "boolean" }, "layers": { "description": "Layer Definitions", @@ -79,15 +80,11 @@ }, "manufacturing_grid": { "description": "Manufacturing Grid", - "writeOnly": true, - "anyOf": [ - { - "$ref": "#/definitions/Unsupported" - }, - { - "type": "null" - } - ] + "type": [ + "string", + "null" + ], + "pattern": "^-?[0-9]+(\\.[0-9]+)?$" }, "max_via_stack": { "description": "Max Via Stack", @@ -137,15 +134,10 @@ }, "property_definitions": { "description": "Property Definitions", - "writeOnly": true, - "anyOf": [ - { - "$ref": "#/definitions/Unsupported" - }, - { - "type": "null" - } - ] + "type": "array", + "items": { + "$ref": "#/definitions/LefPropertyDefinition" + } }, "sites": { "description": "Site Definitions", @@ -167,7 +159,6 @@ }, "use_min_spacing": { "description": "\"Use Min Spacing\" Option", - "writeOnly": true, "anyOf": [ { "$ref": "#/definitions/LefOnOff" @@ -275,6 +266,25 @@ } ] }, + "LefClearanceStyle": { + "description": "Clearance Measure Spacing Styles", + "oneOf": [ + { + "description": "MAXXY", + "type": "string", + "enum": [ + "MaxXY" + ] + }, + { + "description": "EUCLIDEAN", + "type": "string", + "enum": [ + "Euclidean" + ] + } + ] + }, "LefCoreClassType": { "description": "Sub-Types for Macros of Class [LefMacroClass::Core]", "oneOf": [ @@ -410,6 +420,23 @@ } ] }, + "LefExtension": { + "type": "object", + "required": [ + "data", + "name" + ], + "properties": { + "data": { + "description": "Stringified data contained in the extension", + "type": "string" + }, + "name": { + "description": "Name of the extension", + "type": "string" + } + } + }, "LefForeign": { "title": "Lef Foreign Cell Declaration", "description": "Declares the linkage to another cell, commonly in DEF or GDSII format. Foreign-cell references are stored exacty as in the LEF format: as a string cell-name.", @@ -663,16 +690,11 @@ } }, "properties": { - "description": "Properties (Unsupported)", - "writeOnly": true, - "anyOf": [ - { - "$ref": "#/definitions/Unsupported" - }, - { - "type": "null" - } - ] + "description": "Properties", + "type": "array", + "items": { + "$ref": "#/definitions/LefProperty" + } }, "site": { "description": "Site Name Note the optional `SITEPATTERN` is not supported", @@ -1058,16 +1080,11 @@ } }, "properties": { - "description": "Properties (Unsupported)", - "writeOnly": true, - "anyOf": [ - { - "$ref": "#/definitions/Unsupported" - }, - { - "type": "null" - } - ] + "description": "Properties", + "type": "array", + "items": { + "$ref": "#/definitions/LefProperty" + } }, "shape": { "description": "Shape", @@ -1301,6 +1318,205 @@ } ] }, + "LefProperty": { + "title": "User Defined Property Instantiation", + "type": "object", + "required": [ + "name", + "value" + ], + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "string" + } + } + }, + "LefPropertyDefinition": { + "title": "User Defined Property Definition", + "oneOf": [ + { + "type": "object", + "required": [ + "LefString" + ], + "properties": { + "LefString": { + "type": "array", + "items": [ + { + "$ref": "#/definitions/LefPropertyDefinitionObjectType" + }, + { + "type": "string" + }, + { + "type": [ + "string", + "null" + ] + } + ], + "maxItems": 3, + "minItems": 3 + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "LefReal" + ], + "properties": { + "LefReal": { + "type": "array", + "items": [ + { + "$ref": "#/definitions/LefPropertyDefinitionObjectType" + }, + { + "type": "string" + }, + { + "type": [ + "string", + "null" + ], + "pattern": "^-?[0-9]+(\\.[0-9]+)?$" + }, + { + "anyOf": [ + { + "$ref": "#/definitions/LefPropertyRange" + }, + { + "type": "null" + } + ] + } + ], + "maxItems": 4, + "minItems": 4 + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "LefInteger" + ], + "properties": { + "LefInteger": { + "type": "array", + "items": [ + { + "$ref": "#/definitions/LefPropertyDefinitionObjectType" + }, + { + "type": "string" + }, + { + "type": [ + "string", + "null" + ], + "pattern": "^-?[0-9]+(\\.[0-9]+)?$" + }, + { + "anyOf": [ + { + "$ref": "#/definitions/LefPropertyRange" + }, + { + "type": "null" + } + ] + } + ], + "maxItems": 4, + "minItems": 4 + } + }, + "additionalProperties": false + } + ] + }, + "LefPropertyDefinitionObjectType": { + "description": "Valid object types for [LefPropertyDefinition]", + "oneOf": [ + { + "description": "LAYER", + "type": "string", + "enum": [ + "Layer" + ] + }, + { + "description": "LIBRARY", + "type": "string", + "enum": [ + "Library" + ] + }, + { + "description": "MACRO", + "type": "string", + "enum": [ + "Macro" + ] + }, + { + "description": "NONDEFAULTRULE", + "type": "string", + "enum": [ + "NonDefaultRule" + ] + }, + { + "description": "PIN", + "type": "string", + "enum": [ + "Pin" + ] + }, + { + "description": "VIA", + "type": "string", + "enum": [ + "Via" + ] + }, + { + "description": "VIARULE", + "type": "string", + "enum": [ + "ViaRule" + ] + } + ] + }, + "LefPropertyRange": { + "title": "Numeric Range for [LefPropertyDefinition]", + "type": "object", + "required": [ + "begin", + "end" + ], + "properties": { + "begin": { + "type": "string", + "pattern": "^-?[0-9]+(\\.[0-9]+)?$" + }, + "end": { + "type": "string", + "pattern": "^-?[0-9]+(\\.[0-9]+)?$" + } + } + }, "LefShape": { "title": "Lef Shape Enumeration", "description": "Includes each of LEF's individual geometric primitives: rectangles, polygons, and paths.", diff --git a/lef21/src/data.rs b/lef21/src/data.rs index 7cf9c01..ffb59ac 100644 --- a/lef21/src/data.rs +++ b/lef21/src/data.rs @@ -83,26 +83,26 @@ pub struct LefLibrary { pub fixed_mask: bool, /// Clearance Measure - #[serde(default, skip_serializing)] + #[serde(default, skip_serializing_if = "Option::is_none")] #[builder(default)] pub clearance_measure: Option, - + // Unsupported fields recommended for *either* LEF "cell libraries" or "technologies" /// Via Definitions (Unsupported) #[serde(default, skip_serializing)] #[builder(default)] pub vias: Option, /// Syntax Extensions - #[serde(default, skip_serializing)] + #[serde(default, skip_serializing_if = "Vec::is_empty")] #[builder(default)] pub extensions: Vec, // Fields recommended for LEF technology descriptions, AKA "tech-lefs" /// Manufacturing Grid - #[serde(default, skip_serializing)] + #[serde(default, skip_serializing_if = "Option::is_none")] #[builder(default)] pub manufacturing_grid: Option, /// "Use Min Spacing" Option - #[serde(default, skip_serializing)] + #[serde(default, skip_serializing_if = "Option::is_none")] #[builder(default)] pub use_min_spacing: Option, /// Property Definitions @@ -426,23 +426,26 @@ pub enum LefLayerSpacing { DesignRuleWidth(LefDecimal), } +/// # User Defined Property Instantiation #[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, PartialEq, Eq)] pub struct LefProperty { pub name: String, pub value: String, } +/// # Numeric Range for [LefPropertyDefinition] #[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, PartialEq, Eq)] pub struct LefPropertyRange { pub begin: LefDecimal, pub end: LefDecimal, } +/// # User Defined Property Definition #[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, PartialEq, Eq)] pub enum LefPropertyDefinition { - LefString(LefKey, String, Option), - LefReal(LefKey, String, Option, Option), - LefInteger(LefKey, String, Option, Option), + LefString(LefPropertyDefinitionObjectType, String, Option), + LefReal(LefPropertyDefinitionObjectType, String, Option, Option), + LefInteger(LefPropertyDefinitionObjectType, String, Option, Option), } /// # Lef Geometric Object Enumeration /// Includes [LefShape]s and Iterators thereof @@ -682,6 +685,14 @@ enumstr!( FixedMask: "FIXEDMASK", Mask: "MASK", UseMinSpacing: "USEMINSPACING", + TaperRule: "TAPERRULE", + NetExpr: "NETEXPR", + SupplySensitivity: "SUPPLYSENSITIVITY", + GroundSensitivity: "GROUNDSENSITIVITY", + MustJoin: "MUSTJOIN", + Property: "PROPERTY", + ManufacturingGrid: "MANUFACTURINGGRID", + ClearanceMeasure: "CLEARANCEMEASURE", // UNITS Fields Units: "UNITS", @@ -722,14 +733,6 @@ enumstr!( Integer: "INTEGER", // Unsupported - TaperRule: "TAPERRULE", - NetExpr: "NETEXPR", - SupplySensitivity: "SUPPLYSENSITIVITY", - GroundSensitivity: "GROUNDSENSITIVITY", - MustJoin: "MUSTJOIN", - Property: "PROPERTY", - ManufacturingGrid: "MANUFACTURINGGRID", - ClearanceMeasure: "CLEARANCEMEASURE", MaxViaStack: "MAXVIASTACK", ViaRule: "VIARULE", Generate: "GENERATE", @@ -888,7 +891,18 @@ enumstr!( Oxide4: "OXIDE4", } ); - +enumstr!( + /// Valid object types for [LefPropertyDefinition] + LefPropertyDefinitionObjectType { + Layer: "LAYER", + Library: "LIBRARY", + Macro: "MACRO", + NonDefaultRule: "NONDEFAULTRULE", + Pin: "PIN", + Via: "VIA", + ViaRule: "VIARULE", + } +); use super::read::{LefParseErrorType, ParserState}; /// # Lef Error Enumeration diff --git a/lef21/src/read.rs b/lef21/src/read.rs index 9693794..3db0db5 100644 --- a/lef21/src/read.rs +++ b/lef21/src/read.rs @@ -1045,7 +1045,7 @@ impl<'src> LefParser<'src> { loop { match self.peek_key()? { Layer | Library | Macro | NonDefaultRule | Pin | Via | ViaRule => { - let objtype = self.get_key()?; + let objtype = self.parse_enum::()?; let propname = String::from(self.get_name()?); match self.get_key()? { LefKey::String => { diff --git a/lef21/src/write.rs b/lef21/src/write.rs index a60f507..dfb5a9a 100644 --- a/lef21/src/write.rs +++ b/lef21/src/write.rs @@ -160,7 +160,7 @@ impl<'wr> LefWriter<'wr> { // helper function to format numeric PROPERTYDEFINITION entries // for "objType propName [RANGE begin end] [value]" - fn format_numeric_prop_def(&mut self, objtype: &LefKey, name: &String, key: LefKey, value: &Option, range: &Option) -> LefResult { + fn format_numeric_prop_def(&mut self, objtype: &LefPropertyDefinitionObjectType, name: &String, key: LefKey, value: &Option, range: &Option) -> LefResult { use LefKey::Range; let mut string_list: Vec = Vec::new(); string_list.push(objtype.to_string());