Module yal.core

yal.core

Core components of the YAL parser.

Expand source code
"""
yal.core

Core components of the YAL parser.
"""

from dataclasses import dataclass, asdict
import re
import yaml
from pyparsing import Word, alphanums, nums, Group, Literal, OneOrMore, \
                        Suppress, Optional, Regex, ParseResults

_comment        = Regex(r'\/\/[^\n]*').suppress() \
                | Regex(r'\/\*(.*?)\*\/', flags=re.DOTALL).suppress()
_module_name    = Word(alphanums + "_")
_module_type    = Literal('STANDARD') | Literal('PAD') | Literal('GENERAL') \
                | Literal('PARENT') | Literal('FEEDTHROUGH')
_width          = Word(nums)
_height         = Word(nums)
_signal_name    = Word(alphanums + '_')
_terminal_type  = Literal('I') | Literal('O') | Literal('B') | Literal('PI') \
                | Literal('PO') | Literal('PB') | Literal('F') | Literal('PWR') \
                | Literal('GND')
_side           = Literal('BOTTOM') | Literal('RIGHT') \
                | Literal('TOP') | Literal('LEFT')
_layer          = Literal('PDIFF') | Literal('NDIFF') | Literal('POLY') \
                | Literal('METAL1') | Literal('METAL2')
_x_position     = Word(nums + '-')
_y_position     = Word(nums + '-')
_position       = Word(nums + '-')
_instance_name  = Word(alphanums + '_')
_x_location     = Word(nums + '-')
_y_location     = Word(nums + '-')
_current        = Word(nums + '.-')
_voltage        = Word(nums + '.-')
_maximum_length = Word(nums)
_reflection     = Literal('RFLNONE') | Literal('RFLY')
_rotation       = Literal('ROT0') | Literal('ROT90') \
                | Literal('ROT180') | Literal('ROT270')
_x              = Word(nums + '-')
_y              = Word(nums + '-')
_io             = Group( ( _signal_name('name') + _terminal_type('type')
                         + ( Group( _x_position('x') + _y_position('y')
                                  + Optional(_width('width') + _layer('layer')) )
                           | Group( _side('side') + _position('pos')
                                  + Optional(_width('width') + _layer('layer')) )))
                       + Optional('CURRENT' + _current('current'))
                       + Optional('VOLTAGE' + _voltage('voltage')) )
_ios            = OneOrMore(_io + Suppress(';'))
_dimension      = Group(_x + _y)
_dimensions     = OneOrMore(_dimension)
_network        = Group( _instance_name('name') + _module_name('module')
                       + OneOrMore(_signal_name)('signals') )
_networks       = OneOrMore(_network + Suppress(';'))
_placement      = _instance_name('name') \
                + Group( _x_location + _y_location('y')
                       + Optional(_reflection) + Optional(_rotation)
                       )('placement')
_placements     = OneOrMore(_placement + Suppress(';'))
_critnet        = _signal_name('name') + _maximum_length('len')
_critnets       = OneOrMore(_critnet + Suppress(';'))
_module         = Group( Literal('MODULE') + _module_name('name') + Suppress(';')
                       +     Literal('TYPE') + _module_type('type') + Suppress(';')
                       +     Literal('DIMENSIONS') + _dimensions('dims') + Suppress(';')
                       +     Suppress('IOLIST;')
                       +         _ios('terms')
                       +     Suppress('ENDIOLIST;')
                       +     Optional( Suppress('NETWORK;')
                                     + _networks('nets')
                                     + Suppress('ENDNETWORK;'))
                       +     Optional( Suppress('PLACEMENT;')
                                     + _placements('placements')
                                     + Suppress('ENDPLACEMENT;'))
                       +     Optional( Suppress('CRITICALNETS;')
                                     + _critnets('crits')
                                     + Suppress('ENDCRITICALNETS;'))
                       + Suppress('ENDMODULE;'))
grammar         = OneOrMore(_module).ignore(_comment)

@dataclass
class Network:
    '''
    The NETWORK section defines the internal connectivity for the module.
    '''
    instance_name: str
    module_name:   str
    signal_names:  list[str]

def make_network(parse_result: ParseResults) -> Network:
    '''
    Constructor for the `Network` data class.
    '''
    return Network( parse_result.get('name', 'NO NAME')
                  , parse_result.get('module', 'NO MODULE')
                  , list(parse_result.get('signals', [])) )

@dataclass
class Terminal:
    '''
    This is describes one element of the IOLIST.
    '''
    signal_name:   str
    terminal_type: str
    x_position:    int
    y_position:    int
    width:         int
    layer:         str
    position:      int
    size:          int
    side:          str

def make_terminal(parse_result: ParseResults) -> Terminal:
    '''
    Constructor for the `Terminal` data class.
    '''
    return Terminal( parse_result.get('name', 'NO NAME')
                   , parse_result.get('type', 'NO TYPE')
                   , parse_result.get('x', None)
                   , parse_result.get('y', None)
                   , parse_result.get('width', None)
                   , parse_result.get('layer', None)
                   , parse_result.get('position', None)
                   , parse_result.get('size', None)
                   , parse_result.get('side', None) )

@dataclass
class Module:
    '''
    A MODULE as defined by YAL.
    '''
    module_name:   str
    module_type:   str
    dimensions:    list[(int,int)]
    terminals:     list[Terminal]
    network:       dict[tuple[str,str],list[str]]
    placement:     dict[str,tuple[int,int,str,str]]
    critical_nets: dict[str,int]

def make_module(parse_result: ParseResults) -> Module:
    '''
    Constructor for the `Module` data class.
    '''
    return Module( parse_result.get('name', 'NO NAME')
                 , parse_result.get('type', 'NO TYPE')
                 , [tuple(map(int,d)) for d in parse_result.get('dims', [])]
                 , [make_terminal(t) for t in parse_result.get('terms', [])]
                 , [make_network(n) for n in parse_result.get('nets', [])]
                 , { p.get('name', 'NO NAME'): tuple(p.get('placement', []))
                     for p in parse_result.get('placements', []) }
                 , { c.get('name', 'NO NAME'): c.get('len')
                    for c in parse_result.get('crits', []) })

def parse(file_contents: str) -> list[Module]:
    '''
    Parse a YAL string.
    '''
    return [ make_module(pr) for pr in grammar.parseString(file_contents) ]

def read(file_name: str) -> list[Module]:
    '''
    Read .yal file and parse its content.
    '''
    with open(file_name, 'r') as yal_file:
        yal_input = yal_file.read()
    return parse(yal_input)

def as_dict(module: Module) -> dict:
    '''
    Convert a Module to a dictionary.
    '''
    mod_dict = asdict(module)
    mod_dict['dimensions'] = [{'x': x, 'y': y} for x,y in mod_dict['dimensions']]
    return mod_dict

def as_dicts(modules: list[Module]) -> dict:
    '''
    Convert a list of Modules to a list of dictionaries.
    '''
    return [ as_dict(m) for m in modules ]

def as_yaml(modules: list[Module]) -> str:
    '''
    Convert a list of modules to YAML.
    '''
    return yaml.dump([{'module' : m} for m in as_dicts(modules)])

Functions

def as_dict(module: Module) ‑> dict

Convert a Module to a dictionary.

Expand source code
def as_dict(module: Module) -> dict:
    '''
    Convert a Module to a dictionary.
    '''
    mod_dict = asdict(module)
    mod_dict['dimensions'] = [{'x': x, 'y': y} for x,y in mod_dict['dimensions']]
    return mod_dict
def as_dicts(modules: list[Module]) ‑> dict

Convert a list of Modules to a list of dictionaries.

Expand source code
def as_dicts(modules: list[Module]) -> dict:
    '''
    Convert a list of Modules to a list of dictionaries.
    '''
    return [ as_dict(m) for m in modules ]
def as_yaml(modules: list[Module]) ‑> str

Convert a list of modules to YAML.

Expand source code
def as_yaml(modules: list[Module]) -> str:
    '''
    Convert a list of modules to YAML.
    '''
    return yaml.dump([{'module' : m} for m in as_dicts(modules)])
def make_module(parse_result: pyparsing.results.ParseResults) ‑> Module

Constructor for the Module data class.

Expand source code
def make_module(parse_result: ParseResults) -> Module:
    '''
    Constructor for the `Module` data class.
    '''
    return Module( parse_result.get('name', 'NO NAME')
                 , parse_result.get('type', 'NO TYPE')
                 , [tuple(map(int,d)) for d in parse_result.get('dims', [])]
                 , [make_terminal(t) for t in parse_result.get('terms', [])]
                 , [make_network(n) for n in parse_result.get('nets', [])]
                 , { p.get('name', 'NO NAME'): tuple(p.get('placement', []))
                     for p in parse_result.get('placements', []) }
                 , { c.get('name', 'NO NAME'): c.get('len')
                    for c in parse_result.get('crits', []) })
def make_network(parse_result: pyparsing.results.ParseResults) ‑> Network

Constructor for the Network data class.

Expand source code
def make_network(parse_result: ParseResults) -> Network:
    '''
    Constructor for the `Network` data class.
    '''
    return Network( parse_result.get('name', 'NO NAME')
                  , parse_result.get('module', 'NO MODULE')
                  , list(parse_result.get('signals', [])) )
def make_terminal(parse_result: pyparsing.results.ParseResults) ‑> Terminal

Constructor for the Terminal data class.

Expand source code
def make_terminal(parse_result: ParseResults) -> Terminal:
    '''
    Constructor for the `Terminal` data class.
    '''
    return Terminal( parse_result.get('name', 'NO NAME')
                   , parse_result.get('type', 'NO TYPE')
                   , parse_result.get('x', None)
                   , parse_result.get('y', None)
                   , parse_result.get('width', None)
                   , parse_result.get('layer', None)
                   , parse_result.get('position', None)
                   , parse_result.get('size', None)
                   , parse_result.get('side', None) )
def parse(file_contents: str) ‑> list[Module]

Parse a YAL string.

Expand source code
def parse(file_contents: str) -> list[Module]:
    '''
    Parse a YAL string.
    '''
    return [ make_module(pr) for pr in grammar.parseString(file_contents) ]
def read(file_name: str) ‑> list[Module]

Read .yal file and parse its content.

Expand source code
def read(file_name: str) -> list[Module]:
    '''
    Read .yal file and parse its content.
    '''
    with open(file_name, 'r') as yal_file:
        yal_input = yal_file.read()
    return parse(yal_input)

Classes

class Module (module_name: str, module_type: str, dimensions: list[int, int], terminals: list[Terminal], network: dict[tuple[str, str], list[str]], placement: dict[str, tuple[int, int, str, str]], critical_nets: dict[str, int])

A MODULE as defined by YAL.

Expand source code
@dataclass
class Module:
    '''
    A MODULE as defined by YAL.
    '''
    module_name:   str
    module_type:   str
    dimensions:    list[(int,int)]
    terminals:     list[Terminal]
    network:       dict[tuple[str,str],list[str]]
    placement:     dict[str,tuple[int,int,str,str]]
    critical_nets: dict[str,int]

Class variables

var critical_nets : dict[str, int]
var dimensions : list[int, int]
var module_name : str
var module_type : str
var network : dict[tuple[str, str], list[str]]
var placement : dict[str, tuple[int, int, str, str]]
var terminals : list[Terminal]
class Network (instance_name: str, module_name: str, signal_names: list[str])

The NETWORK section defines the internal connectivity for the module.

Expand source code
@dataclass
class Network:
    '''
    The NETWORK section defines the internal connectivity for the module.
    '''
    instance_name: str
    module_name:   str
    signal_names:  list[str]

Class variables

var instance_name : str
var module_name : str
var signal_names : list[str]
class Terminal (signal_name: str, terminal_type: str, x_position: int, y_position: int, width: int, layer: str, position: int, size: int, side: str)

This is describes one element of the IOLIST.

Expand source code
@dataclass
class Terminal:
    '''
    This is describes one element of the IOLIST.
    '''
    signal_name:   str
    terminal_type: str
    x_position:    int
    y_position:    int
    width:         int
    layer:         str
    position:      int
    size:          int
    side:          str

Class variables

var layer : str
var position : int
var side : str
var signal_name : str
var size : int
var terminal_type : str
var width : int
var x_position : int
var y_position : int