From 0073712b71ea642edc2b67ad64a09cc0f54a137f Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Thu, 12 Oct 2017 22:04:02 +0200 Subject: o Support for reading hierarchical schematics. --- src/ee/kicad/__init__.py | 3 +- src/ee/kicad/model.py | 80 ++++++++++++++++++------- src/ee/kicad/read_schematic.py | 35 +++++++++-- test/parser/hierarchical/child.sch | 35 +++++++++++ test/parser/hierarchical/grand-child.sch | 29 +++++++++ test/parser/hierarchical/hierarchical-cache.lib | 63 +++++++++++++++++++ test/parser/hierarchical/hierarchical.pro | 35 +++++++++++ test/parser/hierarchical/hierarchical.sch | 35 +++++++++++ test/test_read_schematic.py | 13 +++- 9 files changed, 301 insertions(+), 27 deletions(-) create mode 100644 test/parser/hierarchical/child.sch create mode 100644 test/parser/hierarchical/grand-child.sch create mode 100644 test/parser/hierarchical/hierarchical-cache.lib create mode 100644 test/parser/hierarchical/hierarchical.pro create mode 100644 test/parser/hierarchical/hierarchical.sch diff --git a/src/ee/kicad/__init__.py b/src/ee/kicad/__init__.py index f431e13..1aac33d 100644 --- a/src/ee/kicad/__init__.py +++ b/src/ee/kicad/__init__.py @@ -1,7 +1,7 @@ from typing import Any from ee import EeException -from ee.kicad.read_schematic import read_schematic +from ee.kicad.read_schematic import read_schematic, read_schematics from ee.kicad.to_bom import to_bom, to_bom_xml from .model import * @@ -11,6 +11,7 @@ __all__ = [ "Component", "Schematic", "read_schematic", + "read_schematics", "to_bom", "to_bom_xml", "to_pandas", diff --git a/src/ee/kicad/model.py b/src/ee/kicad/model.py index 7d9a437..eacf8e2 100644 --- a/src/ee/kicad/model.py +++ b/src/ee/kicad/model.py @@ -133,16 +133,17 @@ class Component(object): class Sheet(object): - def __init__(self): - self._components = [] - pass + def __init__(self, name, path): + self._name = name + self._path = path @property - def components(self): - return frozenset(self._components) + def path(self): + return self._path - def add_component(self, component): - self._components.append(component) + @property + def name(self): + return self._name class Library(object): @@ -153,12 +154,8 @@ class Library(object): class Schematic(object): def __init__(self): self._libraries = set() - self._sheets = [Sheet()] - pass - - @property - def first_sheet(self): - return self._sheets[0] + self._sheets = [] + self._components = [] @property def libraries(self): @@ -167,18 +164,61 @@ class Schematic(object): def add_library(self, library): self._libraries.add(Library(library)) - # Getters @property - def components(self) -> List[Component]: - a = [] - for s in self._sheets: - for c in s.components: - a.append(c) - return a + def sheets(self): + return frozenset(self._sheets) + + def add_sheet(self, sheet): + self._sheets.append(sheet) + + @property + def components(self): + return frozenset(self._components) + + def add_component(self, component): + self._components.append(component) def get_component(self, ref, unit=1): + c = find_component(self, ref, unit) + + if c: + return c + + raise KeyError("No such component: {}".format(ref)) + + def find_component(self, ref, unit=1): for c in self.components: if c.ref == ref and unit == unit: return c +class Schematics(object): + def __init__(self, schematics): + self._schematics = schematics + + @property + def schematics(self) -> List[Schematic]: + return list(self._schematics) + + @property + def components(self) -> List[Component]: + cs = [] + for s in self._schematics: + for c in s.components: + cs.append(c) + return cs + + def get_component(self, ref, unit=1): + for s in self._schematics: + c = s.find_component(ref, unit) + if c: + return c + raise KeyError("No such component: {}".format(ref)) + + @property + def libraries(self) -> List[Library]: + ls = [] + for s in self._schematics: + for l in s.libraries: + ls.append(l) + return ls diff --git a/src/ee/kicad/read_schematic.py b/src/ee/kicad/read_schematic.py index e70d1a7..ed5ce21 100644 --- a/src/ee/kicad/read_schematic.py +++ b/src/ee/kicad/read_schematic.py @@ -1,16 +1,42 @@ import shlex from ee import EeException from ee.kicad.model import * +import os.path +def read_schematics(path): + def read(path): + schematic = read_schematic(path) + schematics = [schematic] + for sheet in schematic.sheets: + p = os.path.join(os.path.dirname(path), sheet.path) + print("Loading {} from {}, path: {}".format(sheet.name, sheet.path, p)) + children = read(p) + schematics.extend(children) + return schematics + + return Schematics(read(path)) + def read_schematic(path): schematic = Schematic() - sheet = None def descr_section(lines): # print("descr_section: len={}".format(len(lines))) pass + def sheet_section(lines): + + for line in lines: + parts = shlex.split(line) + if len(parts) < 2: + continue + if parts[0] == "F0": + name = parts[1] + elif parts[0] == "F1": + path = parts[1] + + schematic.add_sheet(Sheet(name, path)) + def comp_section(lines): # print("comp_section: len={}".format(len(lines))) timestamp = None @@ -65,16 +91,13 @@ def read_schematic(path): else: raise EeException("Bad component field: '{}'".format(line)) - sheet.add_component(Component(position, timestamp, library, name, unit, ref, fields)) + schematic.add_component(Component(position, timestamp, library, name, unit, ref, fields)) def load(f): header = f.readline() if "EESchema Schematic File Version" not in header: raise EeException("Not a KiCAD schematic file.") - nonlocal sheet - sheet = schematic.first_sheet - section_name = None section = [] @@ -93,6 +116,8 @@ def read_schematic(path): comp_section(section) elif section_name == "$Descr": descr_section(section) + elif section_name == "$Sheet": + sheet_section(section) else: if line == "$EndSCHEMATIC": seen_end = True diff --git a/test/parser/hierarchical/child.sch b/test/parser/hierarchical/child.sch new file mode 100644 index 0000000..b80f666 --- /dev/null +++ b/test/parser/hierarchical/child.sch @@ -0,0 +1,35 @@ +EESchema Schematic File Version 2 +LIBS:device +LIBS:hierarchical-cache +EELAYER 25 0 +EELAYER END +$Descr A4 11693 8268 +encoding utf-8 +Sheet 2 3 +Title "" +Date "" +Rev "" +Comp "" +Comment1 "" +Comment2 "" +Comment3 "" +Comment4 "" +$EndDescr +$Comp +L C C201 +U 1 1 59DF3621 +P 5200 3000 +F 0 "C201" H 5225 3100 50 0000 L CNN +F 1 "1u" H 5225 2900 50 0000 L CNN +F 2 "" H 5238 2850 50 0001 C CNN +F 3 "" H 5200 3000 50 0001 C CNN + 1 5200 3000 + 1 0 0 -1 +$EndComp +$Sheet +S 2800 3200 1300 600 +U 59DF3A64 +F0 "Grand Child" 60 +F1 "grand-child.sch" 60 +$EndSheet +$EndSCHEMATC diff --git a/test/parser/hierarchical/grand-child.sch b/test/parser/hierarchical/grand-child.sch new file mode 100644 index 0000000..f4bc921 --- /dev/null +++ b/test/parser/hierarchical/grand-child.sch @@ -0,0 +1,29 @@ +EESchema Schematic File Version 2 +LIBS:device +LIBS:hierarchical-cache +EELAYER 25 0 +EELAYER END +$Descr A4 11693 8268 +encoding utf-8 +Sheet 3 3 +Title "" +Date "" +Rev "" +Comp "" +Comment1 "" +Comment2 "" +Comment3 "" +Comment4 "" +$EndDescr +$Comp +L L L301 +U 1 1 59DF3A6F +P 4700 2100 +F 0 "L301" V 4650 2100 50 0000 C CNN +F 1 "10u" V 4775 2100 50 0000 C CNN +F 2 "" H 4700 2100 50 0001 C CNN +F 3 "" H 4700 2100 50 0001 C CNN + 1 4700 2100 + 1 0 0 -1 +$EndComp +$EndSCHEMATC diff --git a/test/parser/hierarchical/hierarchical-cache.lib b/test/parser/hierarchical/hierarchical-cache.lib new file mode 100644 index 0000000..22e755f --- /dev/null +++ b/test/parser/hierarchical/hierarchical-cache.lib @@ -0,0 +1,63 @@ +EESchema-LIBRARY Version 2.3 +#encoding utf-8 +# +# C +# +DEF C C 0 10 N Y 1 F N +F0 "C" 25 100 50 H V L CNN +F1 "C" 25 -100 50 H V L CNN +F2 "" 38 -150 50 H I C CNN +F3 "" 0 0 50 H I C CNN +$FPLIST + C_* +$ENDFPLIST +DRAW +P 2 0 1 20 -80 -30 80 -30 N +P 2 0 1 20 -80 30 80 30 N +X ~ 1 0 150 110 D 50 50 1 1 P +X ~ 2 0 -150 110 U 50 50 1 1 P +ENDDRAW +ENDDEF +# +# L +# +DEF L L 0 40 N N 1 F N +F0 "L" -50 0 50 V V C CNN +F1 "L" 75 0 50 V V C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +$FPLIST + Choke_* + *Coil* + Inductor_* + L_* +$ENDFPLIST +DRAW +A 0 -75 25 -899 899 0 1 0 N 0 -100 0 -50 +A 0 -25 25 -899 899 0 1 0 N 0 -50 0 0 +A 0 25 25 -899 899 0 1 0 N 0 0 0 50 +A 0 75 25 -899 899 0 1 0 N 0 50 0 100 +X 1 1 0 150 50 D 50 50 1 1 P +X 2 2 0 -150 50 U 50 50 1 1 P +ENDDRAW +ENDDEF +# +# R +# +DEF R R 0 0 N Y 1 F N +F0 "R" 80 0 50 V V C CNN +F1 "R" 0 0 50 V V C CNN +F2 "" -70 0 50 V I C CNN +F3 "" 0 0 50 H I C CNN +$FPLIST + R_* + R_* +$ENDFPLIST +DRAW +S -40 -100 40 100 0 1 10 N +X ~ 1 0 150 50 D 50 50 1 1 P +X ~ 2 0 -150 50 U 50 50 1 1 P +ENDDRAW +ENDDEF +# +#End Library diff --git a/test/parser/hierarchical/hierarchical.pro b/test/parser/hierarchical/hierarchical.pro new file mode 100644 index 0000000..8543101 --- /dev/null +++ b/test/parser/hierarchical/hierarchical.pro @@ -0,0 +1,35 @@ +update=Mon 31 Jul 2017 10:04:56 AM MDT +version=1 +last_client=kicad +[general] +version=1 +RootSch= +BoardNm= +[pcbnew] +version=1 +LastNetListRead= +UseCmpFile=1 +PadDrill=0.600000000000 +PadDrillOvalY=0.600000000000 +PadSizeH=1.500000000000 +PadSizeV=1.500000000000 +PcbTextSizeV=1.500000000000 +PcbTextSizeH=1.500000000000 +PcbTextThickness=0.300000000000 +ModuleTextSizeV=1.000000000000 +ModuleTextSizeH=1.000000000000 +ModuleTextSizeThickness=0.150000000000 +SolderMaskClearance=0.000000000000 +SolderMaskMinWidth=0.000000000000 +DrawSegmentWidth=0.200000000000 +BoardOutlineThickness=0.100000000000 +ModuleOutlineThickness=0.150000000000 +[cvpcb] +version=1 +NetIExt=net +[eeschema] +version=1 +LibDir= +[eeschema/libraries] +LibName1=device +LibName2=hierarchical-cache diff --git a/test/parser/hierarchical/hierarchical.sch b/test/parser/hierarchical/hierarchical.sch new file mode 100644 index 0000000..daf7b88 --- /dev/null +++ b/test/parser/hierarchical/hierarchical.sch @@ -0,0 +1,35 @@ +EESchema Schematic File Version 2 +LIBS:device +LIBS:hierarchical-cache +EELAYER 25 0 +EELAYER END +$Descr A4 11693 8268 +encoding utf-8 +Sheet 1 3 +Title "" +Date "" +Rev "" +Comp "" +Comment1 "" +Comment2 "" +Comment3 "" +Comment4 "" +$EndDescr +$Comp +L R R101 +U 1 1 59DF35E4 +P 5100 2600 +F 0 "R101" V 5180 2600 50 0000 C CNN +F 1 "1k" V 5100 2600 50 0000 C CNN +F 2 "" V 5030 2600 50 0001 C CNN +F 3 "" H 5100 2600 50 0001 C CNN + 1 5100 2600 + 1 0 0 -1 +$EndComp +$Sheet +S 2600 3300 1300 600 +U 59DF3614 +F0 "Child" 60 +F1 "child.sch" 60 +$EndSheet +$EndSCHEMATC diff --git a/test/test_read_schematic.py b/test/test_read_schematic.py index 1af7002..2b269a6 100644 --- a/test/test_read_schematic.py +++ b/test/test_read_schematic.py @@ -35,7 +35,7 @@ def dump_bom(sch): def load(path): p = basedir + "/parser/" + path print("p={}".format(p)) - sch = kicad.read_schematic(p) + sch = kicad.read_schematics(p) return sch @@ -51,3 +51,14 @@ def test_sch(): sch = load("foo.sch") dump_schema(sch) dump_bom(sch) + + +def test_hierarchical(): + sch = load("hierarchical/hierarchical.sch") + dump_schema(sch) + dump_bom(sch) + assert 3 == len(sch.components) + assert 3 == len(sch.schematics) + assert sch.get_component("R101") + assert sch.get_component("C201") + assert sch.get_component("L301") -- cgit v1.2.3