Source code for skidl.netlist_to_skidl

# -*- coding: utf-8 -*-

# The MIT License (MIT) - Copyright (c) 2016-2021 Dave Vandenbout.

"""
Convert a netlist into an equivalent SKiDL program.
"""

from __future__ import (  # isort:skip
    absolute_import,
    division,
    print_function,
    unicode_literals,
)

import re
from builtins import int
from collections import defaultdict

from future import standard_library
from kinparse import parse_netlist

from .part import TEMPLATE

standard_library.install_aliases()


[docs]def netlist_to_skidl(netlist_src): tab = " " * 4 def legalize(name): """Make a string into a legal python variable name.""" return re.sub("[^a-zA-Z0-9_]", "_", name) def comp_key(comp): """Create an ID key from component's major characteristics.""" chars = [c for c in [comp.lib, comp.name, comp.footprint] if len(c)] return legalize("_".join(chars)) def template_comp_to_skidl(template_comp): """Instantiate a component that will be used as a template.""" ltab = tab # Instantiate component template. name = comp_key(template_comp) # python variable name for template. lib = template_comp.lib part = template_comp.name tmpl = "{ltab}{name} = Part('{lib}', '{part}', dest=TEMPLATE".format(**locals()) footprint = template_comp.footprint if len(footprint): tmpl += ", footprint='{footprint}'".format(**locals()) tmpl += ")\n" # Set attributes of template using the component fields. for fld in template_comp.fields: tmpl += "{ltab}setattr({name}, '{fld.name}', '{fld.value}')\n".format( **locals() ) return tmpl def comp_to_skidl(comp, template_comps): """Instantiate components using the component templates.""" ltab = tab # Use the component key to get the template that matches this component. template_comp_name = comp_key(comp) template_comp = template_comps[template_comp_name] # Get the fields for the template. template_comp_fields = {fld.name: fld.value for fld in template_comp.fields} # Create a legal python variable for storing the instantiated component. ref = comp.ref legal_ref = legalize(ref) # Instantiate the component and its value (if any). inst = "{ltab}{legal_ref} = {template_comp_name}(ref='{ref}'".format(**locals()) if len(comp.value): inst += ", value='{comp.value}'".format(**locals()) inst += ")\n" # Set the fields of the instantiated component if they differ from the values in the template. for fld in comp.fields: if fld.value != template_comp_fields.get(fld.name, ""): inst += ( "{ltab}setattr({legal_ref}, '{fld.name}', '{fld.value}')\n".format( **locals() ) ) return inst def net_to_skidl(net): """Instantiate the nets between components.""" # Build a list of component pins attached to the net. pins = [] for pin in net.pins: comp = legalize(pin.ref) # Name of Python variable storing component. pin_num = pin.num # Pin number of component attached to net. pins.append("{comp}['{pin_num}']".format(**locals())) pins = ", ".join(pins) # String the pins into an argument list. ltab = tab # Instantiate the net, connect the pins to it, and return it. return "{ltab}Net('{net.name}').connect({pins})\n".format(**locals()) def _netlist_to_skidl(ntlst): """Convert a netlist into a skidl script.""" # Sequence of operations: # 1. Create a template for each component having a given library, part name and footprint. # 2. Instantiate each component using its matching template. Also, set any attributes # for the component that don't match those in the template. # 3. Instantiate the nets connecting the component pins. # 4. Call the script to instantiate the complete circuit. # 5. Generate the netlist for the circuit. ltab = tab section_div = "#" + "=" * 79 section_comment = ( "\n\n{ltab}{section_div}\n{ltab}# {section_desc}\n{ltab}{section_div}\n\n" ) skidl = "" skidl += "# -*- coding: utf-8 -*-\n\n" skidl += "from skidl import *\n\n\n" circuit_name = legalize(ntlst.source) skidl += "def {circuit_name}():".format(**locals()) section_desc = "Component templates." skidl += section_comment.format(**locals()) comp_templates = {comp_key(comp): comp for comp in ntlst.parts} template_statements = sorted( [template_comp_to_skidl(c) for c in list(comp_templates.values())] ) skidl += "\n".join(template_statements) section_desc = "Component instantiations." skidl += section_comment.format(**locals()) comp_inst_statements = sorted( [comp_to_skidl(c, comp_templates) for c in ntlst.parts] ) skidl += "\n".join(comp_inst_statements) section_desc = "Net interconnections between instantiated components." skidl += section_comment.format(**locals()) net_statements = sorted([net_to_skidl(n) for n in ntlst.nets]) skidl += "\n".join(net_statements) ltab = "" section_desc = "Instantiate the circuit and generate the netlist." skidl += section_comment.format(**locals()) ltab = tab skidl += 'if __name__ == "__main__":\n' skidl += "{ltab}{circuit_name}()\n".format(**locals()) skidl += "{ltab}generate_netlist()\n".format(**locals()) return skidl return _netlist_to_skidl(parse_netlist(netlist_src))