libertyparse 0.3.0

Liberty cell library parser
Documentation

WHITESPACE = _{ " " | "\t" | NEWLINE }
WHITESPACE_NONEWLINE = _{ " " | "\t" }
COMMENT = _{ ("/*" ~ (!"*/" ~ ANY)* ~ "*/") | "\\\n" }

main = {
    SOI ~
    library* ~
    &EOI
}

library = {
    "library" ~ "(" ~ (str | ident) ~ ")" ~ "{" ~
    (((units | properties_library) ~ ";")
    | (cell | lut_template)
    | unparsed_tokenitem)* ~
    "}"
}

unparsed_tokenitem = {
    ident ~ (
      ("(" ~ tokenvalues? ~ ")" ~ (("{" ~ tokentree* ~ "}") | ";"?))
    | (":" ~ tokenvalues ~ ";"?))
}

tokenvalues = _{ tokenvalue ~ ("," ~ tokenvalue)* }
tokenvalue = @{ ((ASCII_ALPHANUMERIC | "_" | "." | "-" | "*" | "+" | "|" | "&" | "!" | "'" | "^" | WHITESPACE_NONEWLINE)+) | str }
tokentree = _{
    ( unparsed_tokenitem
    | ("(" ~ tokentree* ~ ")")
    | ("{" ~ tokentree* ~ "}")
    | ("[" ~ tokentree* ~ "]"))+
}

str = @{ "\"" ~ ((!"\"" ~ !"\\" ~ ANY) | ("\\" ~ ANY))* ~ "\"" }
int = @{ ASCII_DIGIT+ }
ident = @{ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_" | "." | "-")* }
float = @{ "-"? ~ ASCII_DIGIT+ ~ ("." ~ ASCII_DIGIT*)? ~
    ("e" ~ ("+" | "-") ~ ASCII_DIGIT+)?}

ident_group = { "\"" ~ ident+ ~ "\"" }

logic_expr_term_paren = { "(" ~ logic_expr ~ ")" }
logic_expr_term = {
    logic_expr_term_paren | int | ident
}
logic_expr_neg = { ("!" ~ logic_expr_term) | (logic_expr_term ~ "'") }
logic_expr_xor = {
    (logic_expr_neg | logic_expr_term) ~
  ("^" ~ (logic_expr_neg | logic_expr_term))*
}
logic_expr_and = {
    logic_expr_xor ~
  (("&" | "*")? ~ logic_expr_xor)*
}
logic_expr = {
    logic_expr_and ~ (("|" | "+") ~ logic_expr_and)*
}

units = {
    time_unit
  | voltage_unit
  | current_unit
  | leakage_power_unit
  | capacitive_load_unit
  | pulling_resistance_unit
}

time_unit = { "time_unit" ~ ":" ~ unitstr }
voltage_unit = { "voltage_unit" ~ ":" ~ unitstr }
current_unit = { "current_unit" ~ ":" ~ unitstr }
leakage_power_unit = { "leakage_power_unit" ~ ":" ~ unitstr }
capacitive_load_unit = { "capacitive_load_unit" ~ unitcap }
pulling_resistance_unit = { "pulling_resistance_unit" ~ ":" ~ unitstr }

unitstr = _{ (float ~ ident) | ("\"" ~ float ~ ident ~ "\"") }
unitcap = _{ "(" ~ float ~ "," ~ ident ~ ")" }

// property = { ident ~ ":" ~ (float | str | ident) }
properties_library = {
    default_inout_pin_cap
  | default_input_pin_cap
  | default_output_pin_cap
  | slew_derate_from_library
  | input_threshold_pct_fall
  | input_threshold_pct_rise
  | output_threshold_pct_fall
  | output_threshold_pct_rise
  | slew_lower_threshold_pct_fall
  | slew_lower_threshold_pct_rise
  | slew_upper_threshold_pct_fall
  | slew_upper_threshold_pct_rise
}

default_inout_pin_cap = { "default_inout_pin_cap" ~ ":" ~ float }
default_input_pin_cap = { "default_input_pin_cap" ~ ":" ~ float }
default_output_pin_cap = { "default_output_pin_cap" ~ ":" ~ float }

slew_derate_from_library = { "slew_derate_from_library" ~ ":" ~ float }
input_threshold_pct_fall = { "input_threshold_pct_fall" ~ ":" ~ float }
input_threshold_pct_rise = { "input_threshold_pct_rise" ~ ":" ~ float }
output_threshold_pct_fall = { "output_threshold_pct_fall" ~ ":" ~ float }
output_threshold_pct_rise = { "output_threshold_pct_rise" ~ ":" ~ float }
slew_lower_threshold_pct_fall = { "slew_lower_threshold_pct_fall" ~ ":" ~ float }
slew_lower_threshold_pct_rise = { "slew_lower_threshold_pct_rise" ~ ":" ~ float }
slew_upper_threshold_pct_fall = { "slew_upper_threshold_pct_fall" ~ ":" ~ float }
slew_upper_threshold_pct_rise = { "slew_upper_threshold_pct_rise" ~ ":" ~ float }

lut_template = {
    (&"lu_table_template") ~
    ident ~ "(" ~ (str | ident) ~ ")" ~ "{" ~
    ((lut_variable | lut_index) ~ ";")* ~
    "}"
}

lut_variable = { "variable_" ~ int ~ ":" ~ (str | ident) }
lut_index = { "index_" ~ int ~ lut_array }
lut_values = { "values" ~ lut_array }
lut_array = {
    "(" ~ ("," | "\\")* ~
  (("\"" ~ float ~ ("," ~ float)* ~ "\"") ~ ("," | "\\")*)+
  ~ ")"
}

cell = {
    "cell" ~ "(" ~ (str | ident) ~ ")" ~ "{" ~
    (pin | sequential_def | unparsed_tokenitem)* ~
    "}"
}

pin = {
    "pin" ~ "(" ~ (str | ident) ~ ")" ~ "{" ~
    (pin_direction | pin_cap | pin_function | timing | unparsed_tokenitem)* ~
    "}"
}

pin_direction = { "direction" ~ ":" ~ (str | ident) ~ ";" }
pin_cap = { pin_cap_type ~ ":" ~ float ~ ";" }
pin_cap_type = { "capacitance" | "fall_capacitance" | "rise_capacitance" }
pin_function = {
    ("function" | "state_function") ~ ":" ~  // statetable if state function.
    (logic_expr | ("\"" ~ logic_expr ~ "\""))
  ~ ";"
}

timing = {
    "timing" ~ "(" ~ ")" ~ "{" ~
    ((timing_related_pin
      | timing_type
      | timing_sense) ~ ";"
    | nldm_lut
    | unparsed_tokenitem)* ~
    "}"
}

timing_related_pin = { "related_pin" ~ ":" ~ (str | ident) }
timing_sense = { "timing_sense" ~ ":" ~ ident }
timing_type = { "timing_type" ~ ":" ~ ident }

lut_instance = {
    ident ~ "(" ~ (str | ident) ~ ")" ~ "{" ~
    ((lut_index | lut_values) ~ ";")* ~
    "}"
}

nldm_lut = {
    (
      &"cell_fall"
    | &"cell_rise"
    | &"fall_transition"
    | &"rise_transition"
    | &"fall_constraint"
    | &"rise_constraint"
  ) ~ lut_instance
}

sequential_def = {
    ff_def | latch_def | statetable_def
}

ff_def = {
    "ff" ~ "(" ~ (str | ident) ~ "," ~ (str | ident) ~ ")" ~ "{" ~ ((
        seq_def_clocked_on
      | seq_def_next_state
      | seq_def_clear
      | seq_def_preset
      | seq_def_clear_preset_var1
      | seq_def_clear_preset_var2) ~ ";")* ~
  "}"
}

latch_def = {
    "latch" ~ "(" ~ (str | ident) ~ "," ~ (str | ident) ~ ")" ~ "{" ~ ((
        seq_def_enable
      | seq_def_data_in
      | seq_def_clear
      | seq_def_preset
      | seq_def_clear_preset_var1
      | seq_def_clear_preset_var2
    ) ~ ";")* ~
  "}"
}

seq_def_clocked_on = {
    "clocked_on" ~ ":" ~ (logic_expr | ("\"" ~ logic_expr ~ "\""))
}
seq_def_next_state = {
    "next_state" ~ ":" ~ (logic_expr | ("\"" ~ logic_expr ~ "\""))
}
seq_def_enable = {
    "enable" ~ ":" ~ (logic_expr | ("\"" ~ logic_expr ~ "\""))
}
seq_def_data_in = {
    "data_in" ~ ":" ~ (logic_expr | ("\"" ~ logic_expr ~ "\""))
}
seq_def_clear = {
    "clear" ~ ":" ~ (logic_expr | ("\"" ~ logic_expr ~ "\""))
}
seq_def_preset = {
    "preset" ~ ":" ~ (logic_expr | ("\"" ~ logic_expr ~ "\""))
}
seq_def_clear_preset_var1 = {
    "clear_preset_var1" ~ ":" ~ (
      seq_def_clear_preset_var_val
    | ("\"" ~ seq_def_clear_preset_var_val ~ "\""))
}
seq_def_clear_preset_var2 = {
    "clear_preset_var2" ~ ":" ~ (
      seq_def_clear_preset_var_val
    | ("\"" ~ seq_def_clear_preset_var_val ~ "\""))
}
seq_def_clear_preset_var_val = { "L" | "H" | "N" | "T" | "X" }

statetable_def = {
    "statetable" ~ "(" ~ ident_group ~ "," ~ ident_group ~ ")" ~ "{" ~
    "table" ~ ":" ~ "\"" ~
    statetable_line ~ ("," ~ statetable_line)* ~
    "\"" ~ ";" ~
    "}"
}

statetable_line = {
    statetable_val+ ~ ":" ~ statetable_val+ ~ ":" ~ statetable_val+
}

statetable_val = {
    "L" | "H" | "-" | "L/H" | "H/L" | "R" | "F" | "~R" | "~F" | "X" | "N"
}