liberty_db/library/mod.rs
1//! <script>
2//! IFRAME('https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html');
3//! </script>
4
5mod items;
6mod test;
7use crate::{
8 Ctx,
9 ast::{
10 Attributes, BuilderScope, DefaultIndentation, GroupAttri, GroupComments, GroupFn,
11 LibertySet, ParseLoc, ParseScope, ParserError, ParsingBuilder, parser,
12 },
13 cell::{Cell, Model, ScaledCell},
14 common::char_config::CharConfig,
15 pin::BusType,
16 table::{CompactLutTemplate, DriverWaveform, PolyTemplate, TableTemple},
17 units,
18};
19use alloc::borrow::Cow;
20use core::fmt::{self, Write as _};
21pub use items::*;
22use std::path::Path;
23
24/// The first line of the library group statement names the library.
25///
26/// It is the first executable line in your library.
27/// <a name ="reference_link" href="
28/// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=20.24&end=20.26
29/// ">Reference</a>
30/// <script>
31/// IFRAME('https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html');
32/// </script>
33#[derive(Debug, Clone)]
34#[derive(liberty_macros::Group)]
35#[mut_set::derive::item]
36#[derive(serde::Serialize, serde::Deserialize)]
37#[serde(bound = "C::Library: serde::Serialize + serde::de::DeserializeOwned")]
38pub struct Library<C: 'static + Ctx> {
39 /// library name
40 #[id(borrow = [String])]
41 #[liberty(name)]
42 #[liberty(default = vec![String::from("undefined")])]
43 pub name: Vec<String>,
44 /// group comments
45 #[liberty(comments)]
46 comments: GroupComments,
47 #[liberty(extra_ctx)]
48 pub extra_ctx: C::Library,
49 /// group undefined attributes
50 #[liberty(attributes)]
51 pub attributes: Attributes,
52 /// Use this attribute to define new, temporary, or user-defined attributes
53 /// for use in symbol and technology libraries.
54 /// You can use either a space or a comma to separate the arguments.
55 /// The following example shows how to define a new string attribute called `bork`,
56 /// which is valid in a `pin` group:
57 ///
58 /// ### Example
59 /// ``` liberty
60 /// define ("bork", "pin", "string") ;
61 /// ```
62 /// You give the new library attribute a value by using the simple attribute syntax:
63 /// ``` liberty
64 /// bork : "nimo" ;
65 /// ```
66 /// <a name ="reference_link" href="
67 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=36.5&end=36.21
68 /// ">Reference</a>
69 #[liberty(complex)]
70 pub define: LibertySet<Define>,
71 /// The `technology` attribute statement specifies the technology
72 /// family being used in the library.
73 /// When you define the technology attribute,
74 /// it must be the first attribute you use and it must be placed at the top of the listing.
75 /// <a name ="reference_link" href="
76 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=39.3&end=39.5
77 /// ">Reference</a>
78 #[liberty(complex)]
79 pub technology: Option<Technology>,
80 /// Use the `delay_model` attribute to specify which delay model
81 /// to use in the delay calculations.
82 /// The `delay_model` attribute must be the first attribute in the library
83 /// if a technology attribute is not present.
84 /// Otherwise, it should follow the technology attribute.
85 /// <a name ="reference_link" href="
86 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=24.3&end=24.6
87 /// ">Reference</a>
88 #[liberty(simple)]
89 pub delay_model: DelayModel,
90 #[liberty(simple)]
91 pub power_model: DelayModel,
92 /// You can use any format within the quotation marks to report the date
93 /// <a name ="reference_link" href="
94 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=23.5&end=23.5
95 /// ">Reference</a>
96 #[liberty(simple)]
97 pub date: String,
98 /// You use the `comment` attribute to include copyright
99 /// or other product information in the library report. You can include only one comment line in a library
100 /// <a name ="reference_link" href="
101 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=22.10&end=22.11
102 /// ">Reference</a>
103 #[liberty(simple)]
104 pub comment: Option<String>,
105 /// The optional `revision` attribute defines a revision number for your library.
106 /// <a name ="reference_link" href="
107 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=30.17&end=30.18
108 /// ">Reference</a>
109 #[liberty(simple)]
110 pub revision: Option<String>,
111 /// Used in TSMC PDK
112 #[liberty(simple)]
113 pub simulation: Option<bool>,
114 /// The `bus_naming_style` attribute defines the naming convention for buses in the library.
115 ///
116 /// *Syntax*
117 /// ```text
118 /// bus_naming_style : "string";
119 /// ```
120 /// Contains alphanumeric characters, braces, underscores, dashes, or
121 /// parentheses. Must contain one `%s` symbol and one `%d` symbol. The `%s` and `%d`
122 /// symbols can appear in any order with at least one nonnumeric character in
123 /// between.
124 ///
125 /// The colon character is not allowed in a `bus_naming_style` attribute value
126 /// because the colon is used to denote a range of bus members. You construct a
127 /// complete bused-pin name by using the name of the owning bus and the member
128 /// number. The owning bus name is substituted for the `%s`, and the member
129 /// number replaces the `%d`.
130 ///
131 /// If you do not define the `bus_naming_style` attribute, the default naming convention is
132 /// applied, as shown.
133 ///
134 /// *Example*
135 /// ```text
136 /// bus_naming_style : "%s[%d]" ;
137 /// ```
138 /// <a name ="reference_link" href="
139 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=21.14&end=21.30
140 /// ">Reference</a>
141 #[liberty(simple)]
142 pub bus_naming_style: Option<String>,
143 /// The `nom_process` attribute defines process scaling,
144 /// one of the nominal operating conditions for a library.
145 ///
146 /// A floating-point number that represents the degree of process scaling in the cells of the library.
147 /// <a name ="reference_link" href="
148 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=28.3+28.10&end=28.4+28.11
149 /// ">Reference</a>
150 #[liberty(simple)]
151 pub nom_process: Option<f64>,
152 /// The `nom_temperature` attribute defines the temperature (in centigrade),
153 /// one of the nominal operating conditions for a library.
154 ///
155 /// A floating-point number that represents the temperature of the cells in the library
156 /// <a name ="reference_link" href="
157 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=28.15&end=28.22
158 /// ">Reference</a>
159 #[liberty(simple)]
160 pub nom_temperature: Option<f64>,
161 /// The `nom_voltage` attribute defines voltage, one of the nominal operating conditions for a library.
162 /// <a name ="reference_link" href="
163 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=28.26&end=28.27
164 /// ">Reference</a>
165 #[liberty(simple)]
166 pub nom_voltage: Option<f64>,
167 /// The `receiver_capacitance_rise_threshold_pct` attribute specifies the points that
168 /// separate the voltage rise segments in the multi-segment receiver capacitance model.
169 ///
170 /// Specify the points as percentage of the rail voltage between 0.0 and 100.0.
171 ///
172 /// Specify monotonically increasing values with the
173 /// `receiver_capacitance_rise_threshold_pct` attribute.
174 ///
175 /// ### Syntax
176 /// ``` text
177 /// receiver_capacitance_rise_threshold_pct ("float, float,...");
178 /// ```
179 /// ### Example
180 /// ``` text
181 /// receiver_capacitance_rise_threshold_pct ("0, 30, 50, 60, 70, 80, 100");
182 /// ```
183 /// In this example, six segments are defined and the first segment is from zero percent to 30
184 /// percent of the rail voltage.
185 /// <a name ="reference_link" href="
186 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=38.18&end=38.28
187 /// ">Reference</a>
188 #[liberty(complex)]
189 pub receiver_capacitance_rise_threshold_pct: Vec<f64>,
190 /// The `receiver_capacitance_fall_threshold_pct` attribute specifies the points that
191 /// separate the voltage fall segments in the multi-segment receiver capacitance model.
192 ///
193 /// Specify each point as a percentage of the rail voltage between 0.0 and 100.0.
194 ///
195 /// Specify monotonically decreasing values with the
196 /// `receiver_capacitance_fall_threshold_pct` attribute.
197 ///
198 /// ### Syntax
199 /// ``` text
200 /// receiver_capacitance_fall_threshold_pct ("float, float,...");
201 /// ```
202 /// ### Example
203 /// ``` text
204 /// receiver_capacitance_fall_threshold_pct ("100, 80, 70, 60, 50, 30, 0");
205 /// ```
206 /// In this example, six segments are defined and the first segment is from 100 percent to 80
207 /// percent of the rail voltage.
208 /// <a name ="reference_link" href="
209 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=38.6&end=38.16
210 /// ">Reference</a>
211 #[liberty(complex)]
212 pub receiver_capacitance_fall_threshold_pct: Vec<f64>,
213 /// If your library contains bused pins, you must define type groups and define the structural
214 /// constraints of each bus type in the library. The type group is defined at the library group
215 /// level, as shown here:
216 /// <a name ="reference_link" href="
217 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=91.7+136.10&end=91.9+136.25
218 /// ">Reference</a>
219 /// <script>
220 /// IFRAME('https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html');
221 /// </script>
222 /// ``` text
223 /// Example 17 Bused Pins
224 /// library (ExamBus) {
225 /// type (bus4) { /* bus name */
226 /// bit_width : 4 ; /* number of bused pins */
227 /// ...
228 /// ...
229 /// }
230 /// cell (bused cell) {
231 /// ...
232 /// bus (A) {
233 /// ...
234 /// bus_type : bus4 ; /* bus name */
235 /// ...
236 /// }
237 /// }
238 /// }
239 /// ```
240 #[liberty(group)]
241 pub r#type: LibertySet<BusType<C>>,
242 /// The `power_supply` group captures all nominal information about voltage variation.
243 /// It is defined before the `operating_conditions` group and before the `cell` groups.
244 /// All the power supply names defined in the `power_supply` group exist in the
245 /// `operating_conditions` group. Define the `power_supply` group at the library level.
246 ///
247 /// Syntax
248 /// ```text
249 /// power_supply () {
250 /// default_power_rail : string ;
251 /// power_rail (string, float) ;
252 /// power_rail (string, float) ;
253 /// ...
254 /// }
255 /// ```
256 /// Example
257 /// ```text
258 /// power_supply () {
259 /// default_power_rail : VDD0;
260 /// power_rail (VDD1, 5.0) ;
261 /// power_rail (VDD2, 3.3) ;
262 /// }
263 /// ```
264 /// <a name ="reference_link" href="
265 /// https://zao111222333.github.io/liberty-db/2020.09/user_guide.html?field=null&bgn=51.33+52.2&end=51.34+52.16
266 /// ">Reference</a>
267 #[liberty(group)]
268 pub power_supply: Option<PowerSupply<C>>,
269 /// Use this group to define operating conditions;
270 /// that is, `process`, `voltage`, and `temperature`.
271 /// You define an `operating_conditions` group at the library-level, as shown here:
272 /// <a name ="reference_link" href="
273 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=72.3&end=72.4
274 /// ">Reference</a>
275 #[liberty(group)]
276 pub operating_conditions: LibertySet<OperatingConditions<C>>,
277 /// Default operating conditions for the library
278 /// <a name ="reference_link" href="
279 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=34.29+34.32&end=34.31+34.33
280 /// ">Reference</a>
281 #[liberty(simple)]
282 pub default_operating_conditions: Option<String>,
283 /// The optional `default_threshold_voltage_group` attribute specifies a cell’s category based on its threshold voltage characteristics
284 /// <a name ="reference_link" href="
285 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=23.20&end=23.21
286 /// ">Reference</a>
287 #[liberty(simple)]
288 pub default_threshold_voltage_group: Option<String>,
289 /// Use this special attribute to define new, temporary, or user-defined groups
290 /// for use in technology libraries.
291 /// <a name ="reference_link" href="
292 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=37.24&end=37.25
293 /// ">Reference</a>
294 #[liberty(complex)]
295 pub define_group: LibertySet<DefineGroup>,
296 /// The `define_cell_area` attribute defines the area resources a `cell` uses,
297 /// such as the number of pad slots.
298 /// <a name ="reference_link" href="
299 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=36.23&end=36.24
300 /// ">Reference</a>
301 #[liberty(complex)]
302 pub define_cell_area: LibertySet<DefineCellArea>,
303 /// ``` liberty
304 /// library_features (value_1, value_2, ..., value_n) ;
305 /// ```
306 /// <a name ="reference_link" href="
307 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=18.40&end=18.41
308 /// ">Reference</a>
309 #[liberty(complex)]
310 pub library_features: Vec<String>,
311 /// Used in TSMC library
312 #[liberty(simple)]
313 pub default_leakage_power_density: Option<f64>,
314 /// Default leakage power
315 /// <a name ="reference_link" href="
316 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=34.4&end=34.5
317 /// ">Reference</a>
318 #[liberty(simple)]
319 pub default_cell_leakage_power: Option<f64>,
320 /// Default connection class
321 /// <a name ="reference_link" href="
322 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=34.7&end=34.8
323 /// ">Reference</a>
324 #[liberty(simple)]
325 pub default_connection_class: Option<String>,
326 /// Fanout load of input pins
327 /// <a name ="reference_link" href="
328 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=34.10&end=34.11
329 /// ">Reference</a>
330 #[liberty(simple)]
331 pub default_fanout_load: Option<f64>,
332 /// Capacitance of inout pins
333 /// <a name ="reference_link" href="
334 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=34.13&end=34.14
335 /// ">Reference</a>
336 #[liberty(simple)]
337 pub default_inout_pin_cap: Option<f64>,
338 /// Capacitance of input pins
339 /// <a name ="reference_link" href="
340 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=34.16&end=34.17
341 /// ">Reference</a>
342 #[liberty(simple)]
343 pub default_input_pin_cap: Option<f64>,
344 /// Maximum capacitance of output pins
345 /// <a name ="reference_link" href="
346 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=34.19&end=34.21
347 /// ">Reference</a>
348 #[liberty(simple)]
349 pub default_max_capacitance: Option<f64>,
350 /// Maximum fanout of all output pins
351 /// <a name ="reference_link" href="
352 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=34.23&end=34.24
353 /// ">Reference</a>
354 #[liberty(simple)]
355 pub default_max_fanout: Option<f64>,
356 /// Maximum transition of output pins
357 /// <a name ="reference_link" href="
358 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=34.26&end=34.27
359 /// ">Reference</a>
360 #[liberty(simple)]
361 pub default_max_transition: Option<f64>,
362 /// Capacitance of output pins
363 /// <a name ="reference_link" href="
364 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=34.33&end=34.34
365 /// ">Reference</a>
366 #[liberty(simple)]
367 pub default_output_pin_cap: Option<f64>,
368 /// Wire load area
369 /// <a name ="reference_link" href="
370 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=34.37&end=34.37
371 /// ">Reference</a>
372 #[liberty(simple)]
373 pub default_wire_load_area: Option<f64>,
374 /// Wire load capacitance
375 /// <a name ="reference_link" href="
376 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=34.38&end=34.39
377 /// ">Reference</a>
378 #[liberty(simple)]
379 pub default_wire_load_capacitance: Option<f64>,
380 /// Wire load mode
381 /// <a name ="reference_link" href="
382 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=34.41&end=34.41
383 /// ">Reference</a>
384 #[liberty(simple)]
385 pub default_wire_load_mode: Option<String>,
386 /// Wire load resistance
387 /// <a name ="reference_link" href="
388 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=34.42&end=34.43
389 /// ">Reference</a>
390 #[liberty(simple)]
391 pub default_wire_load_resistance: Option<f64>,
392 /// Wire load selection
393 /// <a name ="reference_link" href="
394 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=34.45&end=34.45
395 /// ">Reference</a>
396 #[liberty(simple)]
397 pub default_wire_load_selection: Option<String>,
398 /// The `em_temp_degradation_factor` attribute specifies the electromigration exponential
399 /// degradation factor.
400 ///
401 /// ### Syntax:
402 /// `em_temp_degradation_factor : valuefloat ;`
403 ///
404 /// value:
405 /// A floating-point number in centigrade units consistent with other temperature specifications throughout the library.
406 ///
407 /// ### Example
408 /// `em_temp_degradation_factor : 40.0 ;`
409 /// <a name ="reference_link" href="
410 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=26.3&end=26.13
411 /// ">Reference</a>
412 #[liberty(simple)]
413 pub em_temp_degradation_factor: Option<f64>,
414 /// Valid values are 1ps, 10ps, 100ps, and 1ns. The default is 1ns.
415 /// <a name ="reference_link" href="
416 /// https://zao111222333.github.io/liberty-db/2020.09/user_guide.html?field=null&bgn=42.25&end=42.30
417 /// ">Reference</a>
418 #[liberty(simple)]
419 pub time_unit: units::TimeUnit,
420 /// This attribute specifies the unit for all capacitance
421 /// values within the logic library, including
422 /// default capacitances, `max_fanout` capacitances,
423 /// pin capacitances, and wire capacitances.
424 /// <a name ="reference_link" href="
425 /// https://zao111222333.github.io/liberty-db/2020.09/user_guide.html?field=null&bgn=44.7&end=44.19
426 /// ">Reference</a>
427 #[liberty(complex)]
428 pub capacitive_load_unit: Option<units::CapacitiveLoadUnit>,
429 /// Valid values are 1mV, 10mV, 100mV, and 1V. The default is 1V.
430 /// <a name ="reference_link" href="
431 /// https://zao111222333.github.io/liberty-db/2020.09/user_guide.html?field=null&bgn=43.2&end=43.9
432 /// ">Reference</a>
433 #[liberty(simple)]
434 pub voltage_unit: units::VoltageUnit,
435 /// The valid values are 1uA, 10uA, 100uA, 1mA, 10mA, 100mA, and 1A.
436 /// **No default exists for the `current_unit` attribute if the attribute is omitted.**
437 /// <a name ="reference_link" href="
438 /// https://zao111222333.github.io/liberty-db/2020.09/user_guide.html?field=null&bgn=43.12&end=43.24
439 /// ">Reference</a>
440 #[liberty(simple)]
441 pub current_unit: Option<units::CurrentUnit>,
442 /// Valid unit values are 1ohm, 10ohm, 100ohm, and 1kohm.
443 /// **No default exists for `pulling_resistance_unit` if the attribute is omitted.**
444 /// <a name ="reference_link" href="
445 /// https://zao111222333.github.io/liberty-db/2020.09/user_guide.html?field=null&bgn=43.25&end=44.4
446 /// ">Reference</a>
447 #[liberty(simple)]
448 pub pulling_resistance_unit: Option<units::PullingResistanceUnit>,
449 /// This attribute indicates the units of the power values
450 /// in the library. If this attribute is missing, the
451 /// leakage-power values are expressed without units.
452 ///
453 /// Valid values are 1W, 100mW, 10mW, 1mW, 100nW, 10nW, 1nW, 100pW, 10pW, and 1pW.
454 /// <a name ="reference_link" href="
455 /// https://zao111222333.github.io/liberty-db/2020.09/user_guide.html?field=null&bgn=44.22&end=44.31
456 /// ">Reference</a>
457 #[liberty(simple)]
458 pub leakage_power_unit: Option<units::LeakagePowerUnit>,
459 /// Use the `voltage_map` attribute to associate a voltage name
460 /// with relative voltage values referenced by the cell-level `pg_pin` groups
461 /// <a name ="reference_link" href="
462 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=39.15&end=39.16
463 /// ">Reference</a>
464 #[liberty(complex)]
465 #[liberty(after_build = VoltageMap::add2scope)]
466 pub voltage_map: LibertySet<VoltageMap>,
467 /// An `input_voltage` group is defined in the library group to designate
468 /// a set of input voltage ranges for your cells.
469 /// <a name ="reference_link" href="
470 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=61.32&end=61.33
471 /// ">Reference</a>
472 #[liberty(group)]
473 pub input_voltage: LibertySet<InputVoltage<C>>,
474 /// You define an `output_voltage` group in the `library` group to designate a set of output
475 /// voltage level ranges to drive output cells.
476 /// <a name ="reference_link" href="
477 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=75.22&end=75.23
478 /// ">Reference</a>
479 #[liberty(group)]
480 pub output_voltage: LibertySet<OutputVoltage<C>>,
481 /// Use the `slew_upper_threshold_pct_rise` attribute to set the value of the upper threshold point
482 /// that is used to model the delay of a pin rising from 0 to 1.
483 /// You can specify this attribute at the pin-level to override the default.
484 ///
485 /// A floating-point number between 0.0 and 100.0 that specifies the upper threshold point
486 /// used to model the delay of a pin rising from 0 to 1. The default is 80.0.
487 /// <a name ="reference_link" href="
488 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=32.16+32.24&end=32.18+32.26
489 /// ">Reference</a>
490 #[liberty(simple)]
491 #[liberty(default = 80.0)]
492 pub slew_upper_threshold_pct_rise: f64,
493 /// Use the `slew_lower_threshold_pct_rise` attribute to set the default lower threshold point
494 /// that is used to model the delay of a pin rising from 0 to 1.
495 /// You can specify this attribute at the pin-level to override the default.
496 ///
497 /// A floating-point number between 0.0 and 100.0 that specifies the lower threshold point
498 /// used to model the delay of a pin rising from 0 to 1. The default is 20.0
499 /// <a name ="reference_link" href="
500 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=31.20+31.28&end=31.22+31.29
501 /// ">Reference</a>
502 #[liberty(simple)]
503 #[liberty(default = 20.0)]
504 pub slew_lower_threshold_pct_rise: f64,
505 /// Use the `slew_derate_from_library` attribute to specify how the transition times need to be derated to match the transition times between the characterization trip points
506 ///
507 /// A floating-point number between 0.0 and 1.0. The default is 1.0.
508 /// <a name ="reference_link" href="
509 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=30.25+31.3&end=30.26+31.4
510 /// ">Reference</a>
511 #[liberty(simple)]
512 #[liberty(default = 1.0)]
513 pub slew_derate_from_library: f64,
514 /// Use the `slew_lower_threshold_pct_fall` attribute to set the default lower threshold point
515 /// that is used to model the delay of a pin falling from 1 to 0.
516 /// You can specify this attribute at the pin-level to override the default.
517 ///
518 /// A floating-point number between 0.0 and 100.0 that specifies the lower threshold point
519 /// used to model the delay of a pin falling from 1 to 0. The default is 20.0
520 /// <a name ="reference_link" href="
521 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=31.7+31.15&end=31.9+31.16
522 /// ">Reference</a>
523 #[liberty(simple)]
524 #[liberty(default = 20.0)]
525 pub slew_lower_threshold_pct_fall: f64,
526 /// Use the `slew_upper_threshold_pct_fall` attribute to set the default upper threshold point
527 /// that is used to model the delay of a pin falling from 1 to 0.
528 /// You can specify this attribute at the pin-level to override the default.
529 ///
530 /// A floating-point number between 0.0 and 100.0 that specifies the upper threshold point
531 /// to model the delay of a pin falling from 1 to 0. The default is 80.0
532 /// <a name ="reference_link" href="
533 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=32.3+32.11&end=32.5+32.12
534 /// ">Reference</a>
535 #[liberty(simple)]
536 #[liberty(default = 80.0)]
537 pub slew_upper_threshold_pct_fall: f64,
538 /// Use the `input_threshold_pct_fall` attribute to set the default threshold point
539 /// on an input pin signal falling from 1 to 0.
540 /// You can specify this attribute at the pin-level to override the default.
541 ///
542 /// A floating-point number between 0.0 and 100.0 that specifies the threshold point
543 /// of an input pin signal falling from 1 to 0. The default is 50.0.
544 /// <a name ="reference_link" href="
545 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=26.15+26.23&end=26.17+26.24
546 /// ">Reference</a>
547 #[liberty(simple)]
548 #[liberty(default = 50.0)]
549 pub input_threshold_pct_fall: f64,
550 /// Use the `input_threshold_pct_rise` attribute to set the default threshold point
551 /// on an input pin signal rising from 0 to 1.
552 /// You can specify this attribute at the pin-level to override the default.
553 ///
554 /// A floating-point number between 0.0 and 100.0 that specifies the threshold point
555 /// of an input pin signal rising from 0 to 1. The default is 50.0.
556 /// <a name ="reference_link" href="
557 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=26.28+27.3&end=26.30+27.4
558 /// ">Reference</a>
559 #[liberty(simple)]
560 #[liberty(default = 50.0)]
561 pub input_threshold_pct_rise: f64,
562 /// Use the `output_threshold_pct_rise` attribute to set the value
563 /// of the threshold point on an output pin signal rising from 0 to 1.
564 ///
565 /// A floating-point number between 0.0 and 100.0 that specifies the threshold point
566 /// of an output pin signal rising from 0 to 1.The default is 50.0
567 /// <a name ="reference_link" href="
568 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=29.17+29.24&end=29.18+29.25
569 /// ">Reference</a>
570 #[liberty(simple)]
571 #[liberty(default = 50.0)]
572 pub output_threshold_pct_rise: f64,
573 /// Use the `output_threshold_pct_fall` attribute to set the value of the threshold point
574 /// on an output pin signal falling from 1 to 0.
575 ///
576 /// A floating-point number between 0.0 and 100.0 that specifies the threshold point
577 /// of an output pin signal falling from 1 to 0. The default is 50.0
578 /// <a name ="reference_link" href="
579 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=29.5+29.12&end=29.6+29.13
580 /// ">Reference</a>
581 #[liberty(simple)]
582 #[liberty(default = 50.0)]
583 pub output_threshold_pct_fall: f64,
584 /// You can define power factors only in libraries that use a CMOS technology. Power scaling
585 /// factors scale the power computation according to process, temperature, and voltage.
586 /// The power-scaling factors are listed below. In the following syntax, multiplier is a floatingpoint number:
587 ///
588 /// Specifies process derating factors for the `cell_leakage_power` attribute.
589 #[liberty(simple)]
590 pub k_process_cell_leakage_power: Option<f64>,
591 /// Specifies process derating factors for the `internal_power` attribute.
592 #[liberty(simple)]
593 pub k_process_internal_power: Option<f64>,
594 /// Specifies temperature derating factors for the `cell_leakage_power` attribute.
595 #[liberty(simple)]
596 pub k_temp_cell_leakage_power: Option<f64>,
597 /// Specifies temperature derating factors for the `internal_power` attribute.
598 #[liberty(simple)]
599 pub k_temp_internal_power: Option<f64>,
600 /// Specifies voltage derating factors for the `cell_leakage_power` attribute.
601 #[liberty(simple)]
602 pub k_volt_cell_leakage_power: Option<f64>,
603 /// Specifies voltage derating factors for the `internal_power` attribute.
604 #[liberty(simple)]
605 pub k_volt_internal_power: Option<f64>,
606 /// The `is_soi` attribute specifies that the cell is a
607 /// silicon-on-insulator (SOI) cell.
608 /// The default is false, which means that the cell is a
609 /// bulk-CMOS cell.
610 ///
611 /// If the `is_soi` attribute is specified at both the
612 /// library and cell levels,
613 /// the cell-level value overrides the library-level value
614 /// <a name ="reference_link" href="
615 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=114.25&end=114.28
616 /// ">Reference</a>
617 #[liberty(simple)]
618 pub is_soi: Option<bool>,
619 /// The `soft_error_rate_confidence` attribute specifies the confidence level
620 /// at which the cell soft error rate is sampled in the library. The value range is from 0 to 1.
621 /// <a name ="reference_link" href="
622 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=32.30&end=32.31
623 /// ">Reference</a>
624 #[liberty(simple)]
625 pub soft_error_rate_confidence: Option<f64>,
626 /// The `char_config` group is a group of attributes including simple and complex attributes.
627 /// These attributes represent library characterization configuration, and specify the settings
628 /// to characterize the library. Use the `char_config` group syntax to apply an attribute value
629 /// to a specific characterization model. You can specify multiple complex attributes in the
630 /// `char_config` group. You can also specify a single complex attribute multiple times for
631 /// different characterization models.
632 /// You can also define the `char_config` group within the cell, pin, and timing groups.
633 /// However, when you specify the same attribute in multiple `char_config` groups at different
634 /// levels, such as at the `library`, `cell`, `pin`, and `timing` levels, the attribute specified at the lower
635 /// level gets priority over the ones specified at the higher levels. For example, the pin-level
636 /// `char_config` group attributes have higher priority over the library-level `char_config`
637 /// group attributes.
638 ///
639 /// ### Syntax
640 /// ``` text
641 /// library (library_name) {
642 /// char_config() {
643 /// /* characterization configuration attributes */
644 /// }
645 /// ...
646 /// cell (cell_name) {
647 /// char_config() {
648 /// /* characterization configuration attributes */
649 /// }
650 /// ...
651 /// pin(pin_name) {
652 /// char_config() {
653 /// /* characterization configuration attributes */
654 /// }
655 /// timing() {
656 /// char_config() {
657 /// /* characterization configuration attributes */
658 /// }
659 /// } /* end of timing */
660 /// ...
661 /// } /* end of pin */
662 /// ...
663 /// } /* end of cell */
664 /// ...
665 /// }
666 /// ```
667 /// <a name ="reference_link" href="
668 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=43.30+44.2&end=43.31+44.37
669 /// ">Reference</a>
670 #[liberty(group)]
671 pub char_config: Option<CharConfig<C>>,
672 /// Use the `output_current_template` group to describe a table template
673 /// for composite current source (CCS) modeling.
674 /// <a name ="reference_link" href="
675 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=74.15&end=74.16
676 /// ">Reference</a>
677 #[liberty(group)]
678 pub output_current_template: LibertySet<TableTemple<C>>,
679 /// In the composite current source (CCS) power library format, instantaneous
680 /// power data is specified as 1- to n- dimensional tables of current waveforms in the
681 /// `pg_current_template` group. This library-level group creates templates of common
682 /// information that power and ground current vectors use.
683 /// <a name ="reference_link" href="
684 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=82.22&end=82.25
685 /// ">Reference</a>
686 #[liberty(group)]
687 pub pg_current_template: LibertySet<TableTemple<C>>,
688 /// The `power_lut_template` group is defined within the `library` group, as shown here:
689 /// <a name ="reference_link" href="
690 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=83.34&end=83.35
691 /// ">Reference</a>
692 #[liberty(group)]
693 pub power_lut_template: LibertySet<TableTemple<C>>,
694 /// Use the `lu_table_template` group to define templates of common information
695 /// to use in lookup tables. Define the `lu_table_template` group at the library level
696 /// <a name ="reference_link" href="
697 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=65.5&end=65.6
698 /// ">Reference</a>
699 #[liberty(group)]
700 pub lu_table_template: LibertySet<TableTemple<C>>,
701 #[liberty(group)]
702 pub noise_lut_template: LibertySet<TableTemple<C>>,
703 #[liberty(group)]
704 pub iv_lut_template: LibertySet<TableTemple<C>>,
705 #[liberty(group)]
706 pub propagation_lut_template: LibertySet<TableTemple<C>>,
707 #[liberty(group)]
708 pub poly_template: LibertySet<PolyTemplate<C>>,
709 #[liberty(group)]
710 pub power_poly_template: LibertySet<PolyTemplate<C>>,
711 /// The `base_curves` group is a library-level group that contains
712 /// the detailed description of normalized base curves.
713 ///
714 /// **Syntax**
715 /// ``` text
716 /// library (my_compact_ccs_lib) {
717 /// …
718 /// base_curves (base_curves_name) {
719 /// …
720 /// }
721 /// }
722 /// ```
723 /// **Example**
724 /// ``` text
725 /// library(my_lib) {
726 /// …
727 /// base_curves (ctbct1) {
728 /// …
729 /// }
730 /// }
731 /// ```
732 /// <a name ="reference_link" href="
733 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=39.32+40.2&end=39.33+40.15
734 /// ">Reference</a>
735 #[liberty(group)]
736 pub base_curves: LibertySet<BaseCurves<C>>,
737 /// The `compact_lut_template` group is a lookup table template used for compact CCS timing and power modeling
738 /// <a name ="reference_link" href="
739 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=41.20&end=41.21
740 /// ">Reference</a>
741 #[liberty(group)]
742 pub compact_lut_template: LibertySet<CompactLutTemplate<C>>,
743 /// The library-level `normalized_driver_waveform` group represents a collection
744 /// of driver waveforms under various input slew values.
745 /// The `index_1` specifies the input slew and `index_2` specifies the normalized voltage.
746 /// Note that the slew index in the `normalized_driver_waveform` table is
747 /// based on the slew derate and slew trip points of the library (global values).
748 /// When applied on a pin or cell with different slew or slew derate,
749 /// the new slew should be interpreted from the waveform.
750 /// <a name ="reference_link" href="
751 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=70.28&end=70.33
752 /// ">Reference</a>
753 #[liberty(group)]
754 pub normalized_driver_waveform: LibertySet<DriverWaveform<C>>,
755 /// A `wire_load` group is defined in a `library` group, as follows.
756 /// <a name ="reference_link" href="
757 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=94.16&end=94.17
758 /// ">Reference</a>
759 #[liberty(group)]
760 pub wire_load: LibertySet<WireLoad<C>>,
761 /// A `wire_load_selection` group is defined in a `library` group, as follows.
762 /// <a name ="reference_link" href="
763 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=94.16&end=94.17
764 /// ">Reference</a>
765 #[liberty(group)]
766 pub wire_load_selection: LibertySet<WireLoadSection<C>>,
767 /// Wire load
768 /// <a name ="reference_link" href="
769 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=34.36&end=34.36
770 /// ">Reference</a>
771 #[liberty(simple)]
772 pub default_wire_load: Option<String>,
773 /// Used in TSMC library
774 /// valid: `match_footprint`?
775 #[liberty(simple)]
776 pub in_place_swap_mode: Option<String>,
777 /// You can define one or more `fpga_isd` groups at the library level
778 /// to specify the drive current, I/O voltages, and slew rates for FPGA parts and cells
779 ///
780 /// When you specify more than one `fpga_isd` group, you **must** also define
781 /// the library-level `default_fpga_isd` attribute to specify which `fpga_isd`
782 /// group is the default
783 /// <a name ="reference_link" href="
784 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=63.22+63.25&end=63.23+63.27
785 /// ">Reference</a>
786 #[liberty(group)]
787 pub fpga_isd: LibertySet<FpgaIsd<C>>,
788 /// When you specify more than one `fpga_isd` group, you **must** also define
789 /// the library-level `default_fpga_isd` attribute to specify which `fpga_isd`
790 /// group is the default
791 /// <a name ="reference_link" href="
792 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=63.22+63.25&end=63.23+63.27
793 /// ">Reference</a>
794 #[liberty(simple)]
795 pub default_fpga_isd: Option<String>,
796 /// The `sensitization` group defined at the library level describes
797 /// the complete state patterns for a specific list of pins (defined by the `pin_names` attribute)
798 /// that are referenced and instantiated as stimuli in the timing arc.
799 ///
800 /// Vector attributes in the group define all possible pin states used as stimuli.
801 /// Actual stimulus waveforms can be described by a combination of these vectors.
802 /// Multiple sensitization groups are allowed in a library. Each `sensitization` group
803 /// can be referenced by multiple cells, and each cell can make reference to
804 /// multiple `sensitization` groups.
805 ///
806 /// <a name ="reference_link" href="
807 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=null&bgn=88.10&end=88.16
808 /// ">Reference</a>
809 #[liberty(group)]
810 pub sensitization: LibertySet<Sensitization<C>>,
811 /// A model group can include all the attributes that are valid in a cell group, as well as the
812 /// two additional attributes described in this section. For information about the cell group
813 /// attributes, see Attributes and Values on page 99.
814 /// <a name ="reference_link" href="
815 /// https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html?field=test&bgn=225.23&end=225.29
816 /// ">Reference</a>
817 #[liberty(group)]
818 pub model: LibertySet<Model<C>>,
819 #[liberty(group)]
820 pub cell: LibertySet<Cell<C>>,
821 #[liberty(group)]
822 pub scaled_cell: LibertySet<ScaledCell<C>>,
823}
824
825impl<C: 'static + Ctx> fmt::Display for Library<C> {
826 #[inline]
827 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
828 self.fmt_lib::<DefaultIndentation>(f)
829 }
830}
831impl<C: 'static + Ctx> Library<C> {
832 const KEY: &'static str = "library";
833 #[inline]
834 pub fn write_lib_file<P: AsRef<Path>>(&self, filename: P) -> std::io::Result<()> {
835 use std::io::{BufWriter, Write as _};
836 if let Some(dir) = filename.as_ref().parent() {
837 _ = std::fs::create_dir_all(dir);
838 }
839 let file = std::fs::File::create(filename)?;
840 let mut writer = BufWriter::new(file);
841 write!(&mut writer, "{self}")?;
842 Ok(())
843 }
844 #[inline]
845 pub fn write_lib_file_gz<P: AsRef<Path>>(&self, filename: P) -> std::io::Result<()> {
846 use flate2::{Compression, write::GzEncoder};
847 use std::io::{BufWriter, Write as _};
848 if let Some(dir) = filename.as_ref().parent() {
849 _ = std::fs::create_dir_all(dir);
850 }
851 let file = std::fs::File::create(filename)?;
852 let buf = BufWriter::new(file);
853 let mut writer = GzEncoder::new(buf, Compression::default());
854 write!(&mut writer, "{self}")?;
855 let mut buf_finish = writer.finish()?;
856 buf_finish.flush()?;
857 buf_finish.get_mut().sync_all()?;
858 Ok(())
859 }
860 /// Parse `.lib` file as a [Library] struct.
861 #[inline]
862 pub fn parse_lib_file(filename: &Path) -> Result<Self, ParserError<'_>> {
863 use flate2::read::GzDecoder;
864 use std::io::{self, BufRead as _, BufReader, Read as _};
865
866 fn read_maybe_gz_file(filename: &Path) -> io::Result<Vec<u8>> {
867 let file = std::fs::File::open(filename)?;
868 let mut buf = BufReader::new(file);
869
870 // https://www.rfc-editor.org/rfc/rfc1952#page-5
871 let head = buf.fill_buf()?;
872 let is_gz = head.starts_with(&[0x1F, 0x8B]);
873
874 let mut bytes = Vec::new();
875 _ = if is_gz {
876 GzDecoder::new(buf).read_to_end(&mut bytes)?
877 } else {
878 buf.read_to_end(&mut bytes)?
879 };
880
881 Ok(bytes)
882 }
883 let bytes = read_maybe_gz_file(filename)
884 .map_err(|e| ParserError::IO(filename.to_path_buf(), e))?;
885 // UTF-8 or lossy
886 match String::from_utf8(bytes) {
887 Ok(s) => Self::parse_lib(&s, Some(filename)),
888 Err(e) => {
889 let s = String::from_utf8_lossy(e.as_bytes());
890 Self::parse_lib(&s, Some(filename))
891 }
892 }
893 }
894 /// Parse `.lib` string as a [Library] struct.
895 /// Specify `filename` for better error information.
896 #[expect(clippy::arithmetic_side_effects)]
897 #[inline]
898 pub fn parse_lib<'a>(
899 s: &str,
900 filename: Option<&'a Path>,
901 ) -> Result<Self, ParserError<'a>> {
902 let mut scope = ParseScope {
903 loc: ParseLoc { filename: filename.map(Cow::Borrowed), line_num: 0 },
904 ..Default::default()
905 };
906 let input1 = match parser::comment_space_newline(s) {
907 Ok((input1, n)) => {
908 scope.loc.line_num += n;
909 input1
910 }
911 Err(e) => return Err(ParserError::nom(scope.loc, e)),
912 };
913 let (input2, key) = match parser::key(input1) {
914 Ok(res) => res,
915 Err(e) => return Err(ParserError::nom(scope.loc, e)),
916 };
917 if key == Self::KEY {
918 let mut builder = LibraryBuilder::default();
919 match <Self as GroupAttri<C>>::nom_parse::<false>(
920 &mut builder,
921 input2,
922 Self::KEY,
923 &mut scope,
924 ) {
925 Err(e) => Err(ParserError::nom(scope.loc, e)),
926 Ok((_, Err(e))) => Err(ParserError::IdError(scope.loc, e)),
927 Ok((_, Ok(_))) => {
928 let mut builder_scope = BuilderScope::default();
929 Ok(ParsingBuilder::build(builder, &mut builder_scope))
930 }
931 }
932 } else {
933 Err(ParserError::Other(scope.loc, format!("Need key={}, find={key}", Self::KEY)))
934 }
935 }
936 #[inline]
937 pub fn fmt_lib<I: crate::ast::Indentation>(
938 &self,
939 f: &mut fmt::Formatter<'_>,
940 ) -> Result<(), fmt::Error> {
941 let ff = &mut crate::ast::CodeFormatter::<'_, fmt::Formatter<'_>, I>::new(f);
942 crate::ast::fmt_library_beginning(self.comments_this(), ff)?;
943 GroupAttri::fmt_liberty(self, Self::KEY, ff)?;
944 f.write_char('\n')
945 }
946 /// TODO: Parse `.json` file as a [Library] struct.
947 #[inline]
948 pub fn parse_json(_i: &str) -> Result<Self, ParserError<'_>> {
949 todo!()
950 }
951 /// TODO: Format [Library] to .json
952 #[inline]
953 pub fn fmt_json<I: crate::ast::Indentation>(
954 &self,
955 _f: &mut fmt::Formatter<'_>,
956 ) -> Result<(), fmt::Error> {
957 todo!()
958 }
959 /// TODO: Parse `.db` file as a [Library] struct.
960 #[inline]
961 pub fn parse_db(_i: &str) -> Result<Self, ParserError<'_>> {
962 todo!()
963 }
964 /// TODO: Format [Library] to .db
965 #[inline]
966 pub fn fmt_db(&self, _f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
967 todo!()
968 }
969}
970
971impl<C: 'static + Ctx> GroupFn<C> for Library<C> {
972 #[cfg_attr(not(feature = "lut_template"), expect(unused_variables))]
973 fn before_build(builder: &mut Self::Builder, scope: &mut BuilderScope<C>) {
974 #[cfg(feature = "lut_template")]
975 {
976 use alloc::sync::Arc;
977 let mut empty_scope = BuilderScope::<C>::default();
978 scope.lu_table_template = builder
979 .lu_table_template
980 .iter()
981 .map(|_lut| {
982 let lut =
983 <TableTemple<C> as ParsingBuilder<C>>::build(_lut.clone(), &mut empty_scope);
984 (lut.name.clone(), Arc::new(lut))
985 })
986 .collect();
987 scope.power_lut_template = builder
988 .power_lut_template
989 .iter()
990 .map(|_lut| {
991 let lut =
992 <TableTemple<C> as ParsingBuilder<C>>::build(_lut.clone(), &mut empty_scope);
993 (lut.name.clone(), Arc::new(lut))
994 })
995 .collect();
996 scope.current_template = builder
997 .output_current_template
998 .iter()
999 .chain(builder.pg_current_template.iter())
1000 .map(|_lut| {
1001 let lut =
1002 <TableTemple<C> as ParsingBuilder<C>>::build(_lut.clone(), &mut empty_scope);
1003 (lut.name.clone(), Arc::new(lut))
1004 })
1005 .collect();
1006 scope.compact_lut_template = builder
1007 .compact_lut_template
1008 .iter()
1009 .map(|_lut| {
1010 let lut = <CompactLutTemplate<C> as ParsingBuilder<C>>::build(
1011 _lut.clone(),
1012 &mut empty_scope,
1013 );
1014 (lut.name.clone(), Arc::new(lut))
1015 })
1016 .collect();
1017 }
1018 }
1019}