From 58b79588998756fa41bf42d7c9f4c6d151a82449 Mon Sep 17 00:00:00 2001 From: "Salvador E. Tropea" Date: Wed, 21 Sep 2022 11:33:26 -0300 Subject: [PATCH] [Update_XML] Now you can check PCB and schematic parity Related to #297 --- CHANGELOG.md | 2 + README.md | 11 +- docs/samples/generic_plot.kibot.yaml | 5 +- kibot/misc.py | 3 + kibot/pre_run_drc.py | 4 +- kibot/pre_update_xml.py | 143 ++++- .../kicad_6/pcb_parity.kicad_pcb | 231 ++++++++ .../kicad_6/pcb_parity.kicad_sch | 515 ++++++++++++++++++ tests/test_plot/test_preflight.py | 25 +- tests/yaml_samples/update_xml_2.kibot.yaml | 9 + 10 files changed, 936 insertions(+), 12 deletions(-) create mode 100644 tests/board_samples/kicad_6/pcb_parity.kicad_pcb create mode 100644 tests/board_samples/kicad_6/pcb_parity.kicad_sch create mode 100644 tests/yaml_samples/update_xml_2.kibot.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index ba725c6a..a98ce12a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Render_3D: Options to disable some technical layers and control the silkscreen clipping. (#282) - Internal BoM: Now you can aggregate components using CSV files. (See #248) +- Now you can check PCB and schematic parity using the `update_xml` preflight + (See #297) ### Fixed - Problems to compress netlists. (#287) diff --git a/README.md b/README.md index 87763426..c985171e 100644 --- a/README.md +++ b/README.md @@ -398,6 +398,8 @@ This section is used to specify tasks that will be executed before generating an - `text`: [string=''] Text to insert instead of the tag. - `run_drc`: [boolean=false] Runs the DRC (Distance Rules Check). To ensure we have a valid PCB. The report file name is controlled by the global output pattern (%i=drc %x=txt). + Note that the KiCad 6 *Test for parity between PCB and schematic* option is not supported. + If you need to check the parity use the `update_xml` preflight. - `run_erc`: [boolean=false] Runs the ERC (Electrical Rules Check). To ensure the schematic is electrically correct. The report file name is controlled by the global output pattern (%i=erc %x=txt). - `sch_replace`: [dict] Replaces tags in the schematic. I.e. to insert the git hash or last revision date. @@ -437,9 +439,16 @@ This section is used to specify tasks that will be executed before generating an - `update_qr`: [boolean=false] Update the QR codes. Complements the `qr_lib` output. The KiCad 6 files and the KiCad 5 PCB needs manual update, generating a new library isn't enough. -- `update_xml`: [boolean=false] Update the XML version of the BoM (Bill of Materials). +- `update_xml`: [boolean=false|dict] Update the XML version of the BoM (Bill of Materials). To ensure our generated BoM is up to date. Note that this isn't needed when using the internal BoM generator (`bom`). + You can compare the PCB and schematic netlists using it. + * Valid keys: + - **`check_pcb_parity`**: [boolean=false] Check if the PCB and Schematic are synchronized. + This is equivalent to the *Test for parity between PCB and schematic* of the DRC dialog. + Only available for KiCad 6. + - `as_warnings`: [boolean=false] Inform the problems as warnings and don't stop. + - `enabled`: [boolean=true] Enable the update. This is the replacement for the boolean value. Here is an example of a *preflight* section: diff --git a/docs/samples/generic_plot.kibot.yaml b/docs/samples/generic_plot.kibot.yaml index 28b6c28a..f9445757 100644 --- a/docs/samples/generic_plot.kibot.yaml +++ b/docs/samples/generic_plot.kibot.yaml @@ -53,6 +53,8 @@ preflight: after: '>' # [boolean=false] Runs the DRC (Distance Rules Check). To ensure we have a valid PCB. # The report file name is controlled by the global output pattern (%i=drc %x=txt). + # Note that the KiCad 6 *Test for parity between PCB and schematic* option is not supported. + # If you need to check the parity use the `update_xml` preflight. run_drc: true # [boolean=false] Runs the ERC (Electrical Rules Check). To ensure the schematic is electrically correct. # The report file name is controlled by the global output pattern (%i=erc %x=txt). @@ -80,9 +82,10 @@ preflight: # Complements the `qr_lib` output. # The KiCad 6 files and the KiCad 5 PCB needs manual update, generating a new library isn't enough. update_qr: true - # [boolean=false] Update the XML version of the BoM (Bill of Materials). + # [boolean=false|dict] Update the XML version of the BoM (Bill of Materials). # To ensure our generated BoM is up to date. # Note that this isn't needed when using the internal BoM generator (`bom`). + # You can compare the PCB and schematic netlists using it. update_xml: true outputs: diff --git a/kibot/misc.py b/kibot/misc.py index 7e8a5ee0..6f82a541 100644 --- a/kibot/misc.py +++ b/kibot/misc.py @@ -40,6 +40,7 @@ KICOST_ERROR = 26 MISSING_WKS = 27 MISSING_FILES = 28 DIFF_TOO_BIG = 29 +NETLIST_DIFF = 30 error_level_to_name = ['NONE', 'INTERNAL_ERROR', 'WRONG_ARGUMENTS', @@ -70,6 +71,7 @@ error_level_to_name = ['NONE', 'MISSING_WKS', 'MISSING_FILES', 'DIFF_TOO_BIG', + 'NETLIST_DIFF', ] KICOST_SUBMODULE = '../submodules/KiCost/src/kicost' EXAMPLE_CFG = 'example_template.kibot.yaml' @@ -233,6 +235,7 @@ W_3DRESVER = '(W097) ' W_DOWN3D = '(W098) ' W_MISSREF = '(W099) ' W_COPYOVER = '(W100) ' +W_PARITY = '(W101) ' # Somehow arbitrary, the colors are real, but can be different PCB_MAT_COLORS = {'fr1': "937042", 'fr2': "949d70", 'fr3': "adacb4", 'fr4': "332B16", 'fr5': "6cc290"} PCB_FINISH_COLORS = {'hal': "8b898c", 'hasl': "8b898c", 'imag': "8b898c", 'enig': "cfb96e", 'enepig': "cfb96e", diff --git a/kibot/pre_run_drc.py b/kibot/pre_run_drc.py index 1a98e665..db2ba33f 100644 --- a/kibot/pre_run_drc.py +++ b/kibot/pre_run_drc.py @@ -25,7 +25,9 @@ logger = get_logger(__name__) @pre_class class Run_DRC(BasePreFlight): # noqa: F821 """ [boolean=false] Runs the DRC (Distance Rules Check). To ensure we have a valid PCB. - The report file name is controlled by the global output pattern (%i=drc %x=txt) """ + The report file name is controlled by the global output pattern (%i=drc %x=txt). + Note that the KiCad 6 *Test for parity between PCB and schematic* option is not supported. + If you need to check the parity use the `update_xml` preflight """ def __init__(self, name, value): super().__init__(name, value) if not isinstance(value, bool): diff --git a/kibot/pre_update_xml.py b/kibot/pre_update_xml.py index 68a88fec..b2d57d71 100644 --- a/kibot/pre_update_xml.py +++ b/kibot/pre_update_xml.py @@ -12,32 +12,157 @@ Dependencies: """ import os from sys import exit -from .macros import macros, pre_class # noqa: F401 +import xml.etree.ElementTree as ET +from .macros import macros, document, pre_class # noqa: F401 from .error import KiPlotConfigurationError from .gs import GS -from .kiplot import exec_with_retry, add_extra_options -from .misc import BOM_ERROR +from .kiplot import exec_with_retry, add_extra_options, load_board +from .misc import BOM_ERROR, NETLIST_DIFF, W_PARITY, MISSING_TOOL from .log import get_logger +from .optionable import Optionable +import pcbnew logger = get_logger(__name__) +class Update_XMLOptions(Optionable): + """ Reference sorting options """ + def __init__(self): + super().__init__() + with document: + self.enabled = True + """ Enable the update. This is the replacement for the boolean value """ + self.check_pcb_parity = False + """ *Check if the PCB and Schematic are synchronized. + This is equivalent to the *Test for parity between PCB and schematic* of the DRC dialog. + Only available for KiCad 6 """ + self.as_warnings = False + """ Inform the problems as warnings and don't stop """ + + @pre_class class Update_XML(BasePreFlight): # noqa: F821 - """ [boolean=false] Update the XML version of the BoM (Bill of Materials). + """ [boolean=false|dict] Update the XML version of the BoM (Bill of Materials). To ensure our generated BoM is up to date. - Note that this isn't needed when using the internal BoM generator (`bom`) """ + Note that this isn't needed when using the internal BoM generator (`bom`). + You can compare the PCB and schematic netlists using it """ def __init__(self, name, value): super().__init__(name, value) - if not isinstance(value, bool): - raise KiPlotConfigurationError('must be boolean') - self._enabled = value + self._check_pcb_parity = False + if isinstance(value, bool): + self._enabled = value + elif isinstance(value, dict): + f = Update_XMLOptions() + f.set_tree(value) + f.config(self) + self._enabled = f.enabled + self._check_pcb_parity = f.check_pcb_parity + self.options = f + self._pcb_related = True self._sch_related = True + @classmethod + def get_doc(cls): + return cls.__doc__, Update_XMLOptions + def get_targets(self): """ Returns a list of targets generated by this preflight """ return [GS.sch_no_ext+'.xml'] + def check_components(self, comps, errors): + found_comps = set() + for m in GS.get_modules(): + ref = m.GetReference() + found_comps.add(ref) + if ref not in comps: + errors.append('{} found in PCB, but not in schematic'.format(ref)) + continue + sch_fp = comps[ref] + pcb_fp = m.GetFPIDAsString() + if sch_fp != pcb_fp: + errors.append('{} footprint mismatch (PCB: {} vs schematic: {})'.format(ref, pcb_fp, sch_fp)) + for ref in set(comps.keys()).difference(found_comps): + errors.append('{} found in schematic, but not in PCB'.format(ref)) + + def check_nets(self, net_names, net_nodes, errors): + # Total count + con = GS.board.GetConnectivity() + pcb_net_count = con.GetNetCount()-1 # Removing the bogus net 0 + sch_net_count = len(net_names) + if pcb_net_count != sch_net_count: + errors.append('Net count mismatch (PCB {} vs schematic {})'.format(pcb_net_count, sch_net_count)) + net_info = GS.board.GetNetInfo() + # Names and connection + for n in net_info.NetsByNetcode(): + if not n: + # Bogus net code 0 + continue + if n not in net_names: + errors.append('PCB net code {} not in schematic'.format(n)) + continue + net = net_info.GetNetItem(n) + net_name = net.GetNetname() + sch_name = net_names[n] + if net_name != sch_name: + errors.append('PCB net code {} name mismatch ({} vs {})'.format(n, net_name, sch_name)) + sch_nodes = net_nodes[n] + pcb_nodes = {pad.GetParent().GetReference()+' pin '+pad.GetNumber() + for pad in con.GetNetItems(n, [pcbnew.PCB_PAD_T])} + dif = pcb_nodes-sch_nodes + if dif: + errors.append('PCB net code {} extra connection/s: {}'.format(n, ','.join(list(dif)))) + dif = sch_nodes-pcb_nodes + if dif: + errors.append('PCB net code {} missing connection/s: {}'.format(n, ','.join(list(dif)))) + + def check_pcb_parity(self): + if GS.ki5: + logger.error('PCB vs schematic parity only available for KiCad 6') + exit(MISSING_TOOL) + fname = GS.sch_no_ext+'.xml' + logger.debug('Loading XML: '+fname) + try: + tree = ET.parse(fname) + except Exception as e: + raise KiPlotConfigurationError('Errors parsing {}\n{}'.format(fname, e)) + root = tree.getroot() + if root.tag != 'export': + raise KiPlotConfigurationError("{} isn't a valid netlist".format(fname)) + # Check version? root.attrib.get('version') + components = root.find('components') + comps = {} + if components is not None: + for c in components.iter('comp'): + ref = c.attrib.get('ref') + fp = c.find('footprint') + fp = fp.text if fp is not None else '' + logger.debugl(2, '- {}: {}'.format(ref, fp)) + comps[ref] = fp + netlist = root.find('nets') + net_names = {} + net_nodes = {} + if netlist is not None: + for n in netlist.iter('net'): + code = int(n.get('code')) + net_names[code] = n.get('name') + net_nodes[code] = {node.get('ref')+' pin '+node.get('pin') for node in n.iter('node')} + # Check with the PCB + errors = [] + load_board() + # Check components + self.check_components(comps, errors) + # Check the nets + self.check_nets(net_names, net_nodes, errors) + # Report errors + if errors: + if self.options.as_warnings: + for e in errors: + logger.warning(W_PARITY+e) + else: + for e in errors: + logger.error(e) + exit(NETLIST_DIFF) + def run(self): command = self.ensure_tool('KiAuto') out_dir = self.expand_dirname(GS.out_dir) @@ -59,3 +184,5 @@ class Update_XML(BasePreFlight): # noqa: F821 video_name = os.path.join(self.expand_dirname(GS.out_dir), 'bom_xml_eeschema_screencast.ogv') if os.path.isfile(video_name): os.remove(video_name) + if self._check_pcb_parity: + self.check_pcb_parity() diff --git a/tests/board_samples/kicad_6/pcb_parity.kicad_pcb b/tests/board_samples/kicad_6/pcb_parity.kicad_pcb new file mode 100644 index 00000000..56b40a15 --- /dev/null +++ b/tests/board_samples/kicad_6/pcb_parity.kicad_pcb @@ -0,0 +1,231 @@ +(kicad_pcb (version 20211014) (generator pcbnew) + + (general + (thickness 1.6) + ) + + (paper "A4") + (layers + (0 "F.Cu" signal) + (31 "B.Cu" signal) + (32 "B.Adhes" user "B.Adhesive") + (33 "F.Adhes" user "F.Adhesive") + (34 "B.Paste" user) + (35 "F.Paste" user) + (36 "B.SilkS" user "B.Silkscreen") + (37 "F.SilkS" user "F.Silkscreen") + (38 "B.Mask" user) + (39 "F.Mask" user) + (40 "Dwgs.User" user "User.Drawings") + (41 "Cmts.User" user "User.Comments") + (42 "Eco1.User" user "User.Eco1") + (43 "Eco2.User" user "User.Eco2") + (44 "Edge.Cuts" user) + (45 "Margin" user) + (46 "B.CrtYd" user "B.Courtyard") + (47 "F.CrtYd" user "F.Courtyard") + (48 "B.Fab" user) + (49 "F.Fab" user) + ) + + (setup + (pad_to_mask_clearance 0) + (aux_axis_origin 148.4 80.2) + (pcbplotparams + (layerselection 0x00010fc_ffffffff) + (disableapertmacros false) + (usegerberextensions false) + (usegerberattributes false) + (usegerberadvancedattributes false) + (creategerberjobfile false) + (svguseinch false) + (svgprecision 6) + (excludeedgelayer true) + (plotframeref false) + (viasonmask false) + (mode 1) + (useauxorigin false) + (hpglpennumber 1) + (hpglpenspeed 20) + (hpglpendiameter 15.000000) + (dxfpolygonmode true) + (dxfimperialunits true) + (dxfusepcbnewfont true) + (psnegative false) + (psa4output false) + (plotreference true) + (plotvalue true) + (plotinvisibletext false) + (sketchpadsonfab false) + (subtractmaskfromsilk false) + (outputformat 1) + (mirror false) + (drillshape 1) + (scaleselection 1) + (outputdirectory "") + ) + ) + + (net 0 "") + (net 1 "GND") + (net 2 "Net-(C1-Pad1)") + (net 3 "VCC") + + (footprint "Capacitor_SMD:C_0805_2012Metric" (layer "F.Cu") + (tedit 5B36C52B) (tstamp 00000000-0000-0000-0000-00005ebea01d) + (at 146.3 78.6) + (descr "Capacitor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") + (tags "capacitor") + (path "/00000000-0000-0000-0000-00005ebe91ac") + (attr smd) + (fp_text reference "C1" (at 0 -1.65) (layer "F.SilkS") + (effects (font (size 1 1) (thickness 0.15))) + (tstamp c974f755-f11c-4e72-9337-9b1b03ad46d6) + ) + (fp_text value "1uF" (at 0 1.65) (layer "F.Fab") + (effects (font (size 1 1) (thickness 0.15))) + (tstamp 2b79ad18-d7d7-43df-ab38-e75b2da12556) + ) + (fp_text user "${REFERENCE}" (at 0 0) (layer "F.Fab") + (effects (font (size 0.5 0.5) (thickness 0.08))) + (tstamp 5db96da7-af8d-43d8-8dc7-a398bfc8659a) + ) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer "F.SilkS") (width 0.12) (tstamp 3076b8ca-409a-4abb-8543-19f45b2d32e7)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer "F.SilkS") (width 0.12) (tstamp a32b7c78-669e-4058-9e8f-159773d391d1)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer "F.CrtYd") (width 0.05) (tstamp 5298dbf1-ff20-463f-b22f-955b234f027b)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer "F.CrtYd") (width 0.05) (tstamp 5ee42af7-ef65-46ec-93e1-21c0e6077de0)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer "F.CrtYd") (width 0.05) (tstamp 9aaa51e5-eb42-4e37-9164-e5b31a4cd652)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer "F.CrtYd") (width 0.05) (tstamp e610961e-a821-4b86-8c7d-d4cb27796910)) + (fp_line (start -1 0.6) (end -1 -0.6) (layer "F.Fab") (width 0.1) (tstamp 1ffd0374-60f5-4975-8863-7ed9f29dac0e)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer "F.Fab") (width 0.1) (tstamp 26a053d6-55aa-4839-adb7-568fd5c066bb)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer "F.Fab") (width 0.1) (tstamp 8367eaee-e0ca-41eb-bc30-e532a8b59fdd)) + (fp_line (start 1 0.6) (end -1 0.6) (layer "F.Fab") (width 0.1) (tstamp e3a76526-d318-4ed9-8120-844abbdc3456)) + (pad "1" smd roundrect locked (at -0.9375 0) (size 0.975 1.4) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25) + (net 2 "Net-(C1-Pad1)") (tstamp 34fb9d00-02b1-48b3-a790-0112e6a08449)) + (pad "2" smd roundrect locked (at 0.9375 0) (size 0.975 1.4) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25) + (net 1 "GND") (tstamp 0336c0d4-c4f4-4020-8380-287f839c852a)) + (model "${KISYS3DMOD}/Capacitor_SMD.3dshapes/C_0805_2012Metric.step" + (offset (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (footprint "Resistor_SMD:R_0805_2012Metric" (layer "F.Cu") + (tedit 5B36C52B) (tstamp 00000000-0000-0000-0000-00005ebea02e) + (at 146.3 81.55 180) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") + (tags "resistor") + (path "/00000000-0000-0000-0000-00005ebe8a2e") + (attr smd) + (fp_text reference "R1" (at 0 -1.65) (layer "F.SilkS") + (effects (font (size 1 1) (thickness 0.15))) + (tstamp 7ef0f81b-f6e6-4f07-b717-38c4b1e50a5e) + ) + (fp_text value "100" (at 0 1.65) (layer "F.Fab") + (effects (font (size 1 1) (thickness 0.15))) + (tstamp 8cd4eec9-ceb5-4b8f-83f2-9a146ee7ddd5) + ) + (fp_text user "${REFERENCE}" (at 0 0) (layer "F.Fab") + (effects (font (size 0.5 0.5) (thickness 0.08))) + (tstamp 93acb41a-3723-4469-9dee-a34acc325774) + ) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer "F.SilkS") (width 0.12) (tstamp 39441d2f-6110-4320-92bb-88f09b0de90b)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer "F.SilkS") (width 0.12) (tstamp ae28541a-0239-4867-9639-a73e46808278)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer "F.CrtYd") (width 0.05) (tstamp 752a50bd-195a-4ad5-acdb-d18c11a301e4)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer "F.CrtYd") (width 0.05) (tstamp 757c5363-13ba-436b-9db8-e5dc02596d27)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer "F.CrtYd") (width 0.05) (tstamp 91e75b42-fb6a-4a6b-be78-4013b6183b9a)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer "F.CrtYd") (width 0.05) (tstamp c76bc75f-8181-4476-9973-7173e45c68ed)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer "F.Fab") (width 0.1) (tstamp 337d7915-43e4-4835-8aab-ff527c0de866)) + (fp_line (start 1 0.6) (end -1 0.6) (layer "F.Fab") (width 0.1) (tstamp 656d7de6-1e65-4eb7-8002-7e680bef80b9)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer "F.Fab") (width 0.1) (tstamp ba9a410d-1c13-461f-b6a8-eeb7c4c46e58)) + (fp_line (start -1 0.6) (end -1 -0.6) (layer "F.Fab") (width 0.1) (tstamp fe5b7a7b-9594-494a-8fe7-df5ac5e9fd07)) + (pad "1" smd roundrect locked (at -0.9375 0 180) (size 0.975 1.4) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25) + (net 3 "VCC") (tstamp ee158b8c-0101-4c4c-b5ce-76e87c497fb9)) + (pad "2" smd roundrect locked (at 0.9375 0 180) (size 0.975 1.4) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25) + (net 2 "Net-(C1-Pad1)") (tstamp b67e7460-96bc-4aa0-8593-880eb3320d89)) + (model "${KISYS3DMOD}/Resistor_SMD.3dshapes/R_0805_2012Metrico.step" + (offset (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (footprint "Resistor_SMD:R_0805_2012Metric" (layer "F.Cu") + (tedit 5B36C52B) (tstamp 00000000-0000-0000-0000-00005ebea03f) + (at 150.71 78.6 180) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") + (tags "resistor") + (path "/00000000-0000-0000-0000-00005ebe8e9e") + (attr smd) + (fp_text reference "R2" (at 0 -1.65) (layer "F.SilkS") + (effects (font (size 1 1) (thickness 0.15))) + (tstamp 9d088aec-c53e-413e-8715-779a6ee7e407) + ) + (fp_text value "200" (at 0 1.65) (layer "F.Fab") + (effects (font (size 1 1) (thickness 0.15))) + (tstamp abf3504c-c638-4bb0-8898-7b38d0241a11) + ) + (fp_text user "${REFERENCE}" (at 0 0) (layer "F.Fab") + (effects (font (size 0.5 0.5) (thickness 0.08))) + (tstamp 730e1bed-bd81-4343-85e9-17d6a47cb046) + ) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer "F.SilkS") (width 0.12) (tstamp 7613df36-4992-4dd5-b97e-1f17e43e73c6)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer "F.SilkS") (width 0.12) (tstamp b6f74bca-cdeb-4109-905d-6a81777da69b)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer "F.CrtYd") (width 0.05) (tstamp 0e6314c1-5679-49cb-898a-296f9477855a)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer "F.CrtYd") (width 0.05) (tstamp 434bf54a-a88a-45dc-a569-a0a5b81a7096)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer "F.CrtYd") (width 0.05) (tstamp ea59c7f6-51a1-4630-b89e-075386e527c9)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer "F.CrtYd") (width 0.05) (tstamp ee5f10ba-08e8-4cb5-8185-dae7f54c20a3)) + (fp_line (start -1 0.6) (end -1 -0.6) (layer "F.Fab") (width 0.1) (tstamp 5c2f40eb-308c-4cc2-9669-44b6645a7910)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer "F.Fab") (width 0.1) (tstamp 608be37a-af03-4e73-9e8e-c1bb3353eaf4)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer "F.Fab") (width 0.1) (tstamp a384a468-0937-4800-9a3b-e63b6186898c)) + (fp_line (start 1 0.6) (end -1 0.6) (layer "F.Fab") (width 0.1) (tstamp dc5732f3-4764-4a19-a8e3-24308ca8b363)) + (pad "1" smd roundrect locked (at -0.9375 0 180) (size 0.975 1.4) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25) + (net 2 "Net-(C1-Pad1)") (tstamp 55440b89-8f8a-483a-9b2b-9ccc95708f75)) + (pad "2" smd roundrect locked (at 0.9375 0 180) (size 0.975 1.4) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25) + (net 1 "GND") (tstamp 3d8a4e48-dfd4-4c64-8dd3-885d6a7ed460)) + (model "${KICAD6_3DMODEL_DIR}/Resistor_SMD.3dshapes/R_0805_2012Metric.step" + (offset (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (footprint "Fiducial:Fiducial_0.5mm_Mask1.5mm" (layer "F.Cu") + (tedit 5C18D139) (tstamp 8f72dcc2-f1da-44e8-b5c2-75c243ce8c64) + (at 151.49 82.61) + (descr "Circular Fiducial, 0.5mm bare copper, 1.5mm soldermask opening") + (tags "fiducial") + (attr smd) + (fp_text reference "F1" (at -2.01 0.02) (layer "F.Fab") + (effects (font (size 1 1) (thickness 0.15))) + (tstamp 0f744c1d-9b8e-4589-a3b9-64c4394aa382) + ) + (fp_text value "Fiducial_0.5mm_Mask1.5mm" (at 0 1.7145) (layer "F.Fab") hide + (effects (font (size 1 1) (thickness 0.15))) + (tstamp d7adc8d6-5699-4906-b02c-51dcbe8f1263) + ) + (fp_text user "${REFERENCE}" (at 0 0) (layer "F.Fab") + (effects (font (size 0.2 0.2) (thickness 0.04))) + (tstamp fee24d08-b944-4719-940b-5f0252b08a7d) + ) + (fp_circle (center 0 0) (end 1 0) (layer "F.CrtYd") (width 0.05) (fill none) (tstamp 1e6365f0-f6d5-4748-b97b-31a779d65060)) + (fp_circle (center 0 0) (end 0.75 0) (layer "F.Fab") (width 0.1) (fill none) (tstamp 80ff894e-6850-45a2-b181-026db3f9fcee)) + (pad "" smd circle (at 0 0) (size 0.5 0.5) (layers "F.Cu" "F.Mask") + (solder_mask_margin 0.5) (clearance 0.5) (tstamp 1dd739b1-51b1-449f-b842-9ba7b75a8664)) + ) + + (gr_line (start 153 84) (end 153 76) (layer "Edge.Cuts") (width 0.05) (tstamp 00000000-0000-0000-0000-00005ebea29b)) + (gr_line (start 144 76) (end 144 84) (layer "Edge.Cuts") (width 0.05) (tstamp bb3326cd-028c-43fb-af47-5975412a67c7)) + (gr_line (start 153 76) (end 144 76) (layer "Edge.Cuts") (width 0.05) (tstamp d534140b-6f16-4b83-8893-ef4b026f6ec9)) + (gr_line (start 144 84) (end 153 84) (layer "Edge.Cuts") (width 0.05) (tstamp ea655683-6135-4d3f-a322-1186e1a703b2)) + + (segment (start 147.2375 78.6) (end 149.7725 78.6) (width 0.25) (layer "F.Cu") (net 1) (tstamp 4ebf58f7-8428-4480-b240-bb7d3c895103)) + (segment (start 150.62249 77.57499) (end 151.161973 78.114473) (width 0.25) (layer "F.Cu") (net 2) (tstamp 4ed009e2-b8f5-47d8-ba45-e73cbf2524c2)) + (segment (start 145.3625 78.6) (end 145.3625 79.3) (width 0.25) (layer "F.Cu") (net 2) (tstamp 5505e502-12b2-42b0-9e88-71997ebbcbde)) + (segment (start 151.161973 78.114473) (end 151.6475 78.6) (width 0.25) (layer "F.Cu") (net 2) (tstamp 5e3899fa-1efc-49c7-bd03-0723e6564f66)) + (segment (start 145.3625 78.6) (end 146.38751 77.57499) (width 0.25) (layer "F.Cu") (net 2) (tstamp 88b2a9f5-ec07-44cc-be7d-6243af8d21a7)) + (segment (start 145.3625 79.3) (end 145.3625 81.55) (width 0.25) (layer "F.Cu") (net 2) (tstamp a49ce2ce-5d29-415b-a41f-07567cbabb0f)) + (segment (start 146.38751 77.57499) (end 150.62249 77.57499) (width 0.25) (layer "F.Cu") (net 2) (tstamp fd90cb38-571b-4f7c-8630-139c123989e3)) + +) diff --git a/tests/board_samples/kicad_6/pcb_parity.kicad_sch b/tests/board_samples/kicad_6/pcb_parity.kicad_sch new file mode 100644 index 00000000..d8a56dc9 --- /dev/null +++ b/tests/board_samples/kicad_6/pcb_parity.kicad_sch @@ -0,0 +1,515 @@ +(kicad_sch (version 20211123) (generator eeschema) + + (uuid e6521bef-4109-48f7-8b88-4121b0468927) + + (paper "A4") + + (title_block + (title "BoM Test") + (date "13/07/2020") + (rev "r1") + (company "INTI-CMNB") + ) + + (lib_symbols + (symbol "Device:C" (pin_numbers hide) (pin_names (offset 0.254)) (in_bom yes) (on_board yes) + (property "Reference" "C" (id 0) (at 0.635 2.54 0) + (effects (font (size 1.27 1.27)) (justify left)) + ) + (property "Value" "C" (id 1) (at 0.635 -2.54 0) + (effects (font (size 1.27 1.27)) (justify left)) + ) + (property "Footprint" "" (id 2) (at 0.9652 -3.81 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "~" (id 3) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_keywords" "cap capacitor" (id 4) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_description" "Unpolarized capacitor" (id 5) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_fp_filters" "C_*" (id 6) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (symbol "C_0_1" + (polyline + (pts + (xy -2.032 -0.762) + (xy 2.032 -0.762) + ) + (stroke (width 0.508) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy -2.032 0.762) + (xy 2.032 0.762) + ) + (stroke (width 0.508) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + ) + (symbol "C_1_1" + (pin passive line (at 0 3.81 270) (length 2.794) + (name "~" (effects (font (size 1.27 1.27)))) + (number "1" (effects (font (size 1.27 1.27)))) + ) + (pin passive line (at 0 -3.81 90) (length 2.794) + (name "~" (effects (font (size 1.27 1.27)))) + (number "2" (effects (font (size 1.27 1.27)))) + ) + ) + ) + (symbol "Device:R" (pin_numbers hide) (pin_names (offset 0)) (in_bom yes) (on_board yes) + (property "Reference" "R" (id 0) (at 2.032 0 90) + (effects (font (size 1.27 1.27))) + ) + (property "Value" "R" (id 1) (at 0 0 90) + (effects (font (size 1.27 1.27))) + ) + (property "Footprint" "" (id 2) (at -1.778 0 90) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "~" (id 3) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_keywords" "R res resistor" (id 4) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_description" "Resistor" (id 5) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_fp_filters" "R_*" (id 6) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (symbol "R_0_1" + (rectangle (start -1.016 -2.54) (end 1.016 2.54) + (stroke (width 0.254) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + ) + (symbol "R_1_1" + (pin passive line (at 0 3.81 270) (length 1.27) + (name "~" (effects (font (size 1.27 1.27)))) + (number "1" (effects (font (size 1.27 1.27)))) + ) + (pin passive line (at 0 -3.81 90) (length 1.27) + (name "~" (effects (font (size 1.27 1.27)))) + (number "2" (effects (font (size 1.27 1.27)))) + ) + ) + ) + (symbol "Mechanical:Fiducial" (in_bom yes) (on_board yes) + (property "Reference" "FID" (id 0) (at 0 5.08 0) + (effects (font (size 1.27 1.27))) + ) + (property "Value" "Fiducial" (id 1) (at 0 3.175 0) + (effects (font (size 1.27 1.27))) + ) + (property "Footprint" "" (id 2) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "~" (id 3) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_keywords" "fiducial marker" (id 4) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_description" "Fiducial Marker" (id 5) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_fp_filters" "Fiducial*" (id 6) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (symbol "Fiducial_0_1" + (circle (center 0 0) (radius 1.27) + (stroke (width 0.508) (type default) (color 0 0 0 0)) + (fill (type background)) + ) + ) + ) + (symbol "power:GND" (power) (pin_names (offset 0)) (in_bom yes) (on_board yes) + (property "Reference" "#PWR" (id 0) (at 0 -6.35 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "GND" (id 1) (at 0 -3.81 0) + (effects (font (size 1.27 1.27))) + ) + (property "Footprint" "" (id 2) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_keywords" "power-flag" (id 4) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_description" "Power symbol creates a global label with name \"GND\" , ground" (id 5) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (symbol "GND_0_1" + (polyline + (pts + (xy 0 0) + (xy 0 -1.27) + (xy 1.27 -1.27) + (xy 0 -2.54) + (xy -1.27 -1.27) + (xy 0 -1.27) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + ) + (symbol "GND_1_1" + (pin power_in line (at 0 0 270) (length 0) hide + (name "GND" (effects (font (size 1.27 1.27)))) + (number "1" (effects (font (size 1.27 1.27)))) + ) + ) + ) + (symbol "power:PWR_FLAG" (power) (pin_numbers hide) (pin_names (offset 0) hide) (in_bom yes) (on_board yes) + (property "Reference" "#FLG" (id 0) (at 0 1.905 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "PWR_FLAG" (id 1) (at 0 3.81 0) + (effects (font (size 1.27 1.27))) + ) + (property "Footprint" "" (id 2) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "~" (id 3) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_keywords" "power-flag" (id 4) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_description" "Special symbol for telling ERC where power comes from" (id 5) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (symbol "PWR_FLAG_0_0" + (pin power_out line (at 0 0 90) (length 0) + (name "pwr" (effects (font (size 1.27 1.27)))) + (number "1" (effects (font (size 1.27 1.27)))) + ) + ) + (symbol "PWR_FLAG_0_1" + (polyline + (pts + (xy 0 0) + (xy 0 1.27) + (xy -1.016 1.905) + (xy 0 2.54) + (xy 1.016 1.905) + (xy 0 1.27) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + ) + ) + (symbol "power:VCC" (power) (pin_names (offset 0)) (in_bom yes) (on_board yes) + (property "Reference" "#PWR" (id 0) (at 0 -3.81 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "VCC" (id 1) (at 0 3.81 0) + (effects (font (size 1.27 1.27))) + ) + (property "Footprint" "" (id 2) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_keywords" "power-flag" (id 4) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "ki_description" "Power symbol creates a global label with name \"VCC\"" (id 5) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (symbol "VCC_0_1" + (polyline + (pts + (xy -0.762 1.27) + (xy 0 2.54) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 0 0) + (xy 0 2.54) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 0 2.54) + (xy 0.762 1.27) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + ) + (symbol "VCC_1_1" + (pin power_in line (at 0 0 90) (length 0) hide + (name "VCC" (effects (font (size 1.27 1.27)))) + (number "1" (effects (font (size 1.27 1.27)))) + ) + ) + ) + ) + + (junction (at 88.9 50.8) (diameter 0) (color 0 0 0 0) + (uuid a9ec539a-d80d-40cc-803c-12b6adefe42a) + ) + + (wire (pts (xy 114.3 74.93) (xy 114.3 77.47)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid 2bf3f24b-fd30-41a7-a274-9b519491916b) + ) + (wire (pts (xy 81.28 49.53) (xy 81.28 50.8)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid 34871042-9d5c-4e29-abdd-a168368c3c22) + ) + (wire (pts (xy 88.9 52.07) (xy 88.9 50.8)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid 4d609e7c-74c9-4ae9-a26d-946ff00c167d) + ) + (wire (pts (xy 88.9 59.69) (xy 88.9 66.04)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid 6199bec7-e7eb-4ae0-b9ec-c563e157d635) + ) + (wire (pts (xy 88.9 76.2) (xy 88.9 73.66)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid 786b6072-5772-4bc1-8eeb-6c4e19f2a91b) + ) + (wire (pts (xy 99.06 76.2) (xy 99.06 73.66)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid 9a9f2d82-f64d-4264-8bec-c182528fc4de) + ) + (wire (pts (xy 88.9 50.8) (xy 88.9 49.53)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid c264c438-a475-4ad4-9915-0f1e6ecf3053) + ) + (wire (pts (xy 81.28 50.8) (xy 88.9 50.8)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid ef1b4b98-541b-4673-a04f-2043250fc40a) + ) + (wire (pts (xy 99.06 66.04) (xy 99.06 62.23)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid f144a97d-c3f0-423f-b0a9-3f7dbc42478b) + ) + + (symbol (lib_id "Device:R") (at 88.9 55.88 0) (unit 1) + (in_bom yes) (on_board yes) + (uuid 00000000-0000-0000-0000-00005ebe8a2e) + (property "Reference" "R1" (id 0) (at 90.678 54.7116 0) + (effects (font (size 1.27 1.27)) (justify left)) + ) + (property "Value" "100" (id 1) (at 90.678 57.023 0) + (effects (font (size 1.27 1.27)) (justify left)) + ) + (property "Footprint" "Resistor_SMD:R_0805_2012Metric" (id 2) (at 87.122 55.88 90) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "~" (id 3) (at 88.9 55.88 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid 9dbd9e26-9782-45c4-9403-4d72b07f29de)) + (pin "2" (uuid 437250d9-eb22-42a7-a0ee-f2e6a9628e2b)) + ) + + (symbol (lib_id "Device:R") (at 88.9 69.85 0) (unit 1) + (in_bom yes) (on_board yes) + (uuid 00000000-0000-0000-0000-00005ebe8e9e) + (property "Reference" "R2" (id 0) (at 90.678 68.6816 0) + (effects (font (size 1.27 1.27)) (justify left)) + ) + (property "Value" "200" (id 1) (at 90.678 70.993 0) + (effects (font (size 1.27 1.27)) (justify left)) + ) + (property "Footprint" "Resistor_SMD:R_0805_2012Metric" (id 2) (at 87.122 69.85 90) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "~" (id 3) (at 88.9 69.85 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid eda12c9f-b24f-4458-a3cc-61f318dc57fe)) + (pin "2" (uuid 004d701c-7e69-4a10-9c95-7de04fa2be20)) + ) + + (symbol (lib_id "Device:C") (at 99.06 69.85 0) (unit 1) + (in_bom yes) (on_board yes) + (uuid 00000000-0000-0000-0000-00005ebe91ac) + (property "Reference" "C1" (id 0) (at 101.981 68.6816 0) + (effects (font (size 1.27 1.27)) (justify left)) + ) + (property "Value" "1uF" (id 1) (at 101.981 70.993 0) + (effects (font (size 1.27 1.27)) (justify left)) + ) + (property "Footprint" "Capacitor_SMD:C_0603_1608Metric" (id 2) (at 100.0252 73.66 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "~" (id 3) (at 99.06 69.85 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid a86ce70c-0b0b-4e00-81fd-fa720b16c5ec)) + (pin "2" (uuid f3fc3ce5-4efa-4006-8983-46e918c0de75)) + ) + + (symbol (lib_id "power:GND") (at 99.06 76.2 0) (unit 1) + (in_bom yes) (on_board yes) + (uuid 00000000-0000-0000-0000-00005ebe965a) + (property "Reference" "#PWR03" (id 0) (at 99.06 82.55 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "GND" (id 1) (at 99.187 80.5942 0)) + (property "Footprint" "" (id 2) (at 99.06 76.2 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 99.06 76.2 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid 607bd1dc-3a6b-4b00-8871-0e4f8cbd31b4)) + ) + + (symbol (lib_id "power:GND") (at 88.9 76.2 0) (unit 1) + (in_bom yes) (on_board yes) + (uuid 00000000-0000-0000-0000-00005ebe9830) + (property "Reference" "#PWR02" (id 0) (at 88.9 82.55 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "GND" (id 1) (at 89.027 80.5942 0)) + (property "Footprint" "" (id 2) (at 88.9 76.2 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 88.9 76.2 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid c02ea828-b111-4d1d-9474-98d811361c61)) + ) + + (symbol (lib_id "power:VCC") (at 88.9 49.53 0) (unit 1) + (in_bom yes) (on_board yes) + (uuid 00000000-0000-0000-0000-00005ebe99a0) + (property "Reference" "#PWR01" (id 0) (at 88.9 53.34 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "VCC" (id 1) (at 89.3318 45.1358 0)) + (property "Footprint" "" (id 2) (at 88.9 49.53 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 88.9 49.53 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid bc94524b-c378-44e8-acce-7c1ac0292375)) + ) + + (symbol (lib_id "power:GND") (at 114.3 77.47 0) (unit 1) + (in_bom yes) (on_board yes) + (uuid 00000000-0000-0000-0000-00005ec534bf) + (property "Reference" "#PWR0101" (id 0) (at 114.3 83.82 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "GND" (id 1) (at 114.427 81.8642 0)) + (property "Footprint" "" (id 2) (at 114.3 77.47 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 114.3 77.47 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid 5d56d28a-c4af-4430-8964-9b60bd37a4ca)) + ) + + (symbol (lib_id "power:PWR_FLAG") (at 114.3 74.93 0) (unit 1) + (in_bom yes) (on_board yes) + (uuid 00000000-0000-0000-0000-00005ec53a6e) + (property "Reference" "#FLG0101" (id 0) (at 114.3 73.025 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "PWR_FLAG" (id 1) (at 114.3 70.5358 0)) + (property "Footprint" "" (id 2) (at 114.3 74.93 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "~" (id 3) (at 114.3 74.93 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid 3081c45f-0a62-4dc8-a706-c2b3c5e194d8)) + ) + + (symbol (lib_id "power:PWR_FLAG") (at 81.28 49.53 0) (unit 1) + (in_bom yes) (on_board yes) + (uuid 00000000-0000-0000-0000-00005ec53e1a) + (property "Reference" "#FLG0102" (id 0) (at 81.28 47.625 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "PWR_FLAG" (id 1) (at 81.28 45.1358 0)) + (property "Footprint" "" (id 2) (at 81.28 49.53 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "~" (id 3) (at 81.28 49.53 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid 0d525ad4-3f7e-4e8e-b572-5aed774da48c)) + ) + + (symbol (lib_id "Mechanical:Fiducial") (at 114.3 58.42 0) (unit 1) + (in_bom yes) (on_board yes) (fields_autoplaced) + (uuid a356d368-eee7-4981-9ff4-135cb700ad3f) + (property "Reference" "FID1" (id 0) (at 116.84 57.1499 0) + (effects (font (size 1.27 1.27)) (justify left)) + ) + (property "Value" "Fiducial" (id 1) (at 116.84 59.6899 0) + (effects (font (size 1.27 1.27)) (justify left)) + ) + (property "Footprint" "" (id 2) (at 114.3 58.42 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "~" (id 3) (at 114.3 58.42 0) + (effects (font (size 1.27 1.27)) hide) + ) + ) + + (sheet_instances + (path "/" (page "1")) + ) + + (symbol_instances + (path "/00000000-0000-0000-0000-00005ec53a6e" + (reference "#FLG0101") (unit 1) (value "PWR_FLAG") (footprint "") + ) + (path "/00000000-0000-0000-0000-00005ec53e1a" + (reference "#FLG0102") (unit 1) (value "PWR_FLAG") (footprint "") + ) + (path "/00000000-0000-0000-0000-00005ebe99a0" + (reference "#PWR01") (unit 1) (value "VCC") (footprint "") + ) + (path "/00000000-0000-0000-0000-00005ebe9830" + (reference "#PWR02") (unit 1) (value "GND") (footprint "") + ) + (path "/00000000-0000-0000-0000-00005ebe965a" + (reference "#PWR03") (unit 1) (value "GND") (footprint "") + ) + (path "/00000000-0000-0000-0000-00005ec534bf" + (reference "#PWR0101") (unit 1) (value "GND") (footprint "") + ) + (path "/00000000-0000-0000-0000-00005ebe91ac" + (reference "C1") (unit 1) (value "1uF") (footprint "Capacitor_SMD:C_0603_1608Metric") + ) + (path "/a356d368-eee7-4981-9ff4-135cb700ad3f" + (reference "FID1") (unit 1) (value "Fiducial") (footprint "") + ) + (path "/00000000-0000-0000-0000-00005ebe8a2e" + (reference "R1") (unit 1) (value "100") (footprint "Resistor_SMD:R_0805_2012Metric") + ) + (path "/00000000-0000-0000-0000-00005ebe8e9e" + (reference "R2") (unit 1) (value "200") (footprint "Resistor_SMD:R_0805_2012Metric") + ) + ) +) diff --git a/tests/test_plot/test_preflight.py b/tests/test_plot/test_preflight.py index edb6ebc9..524054fa 100644 --- a/tests/test_plot/test_preflight.py +++ b/tests/test_plot/test_preflight.py @@ -20,7 +20,7 @@ import os import re from subprocess import run, PIPE from . import context -from kibot.misc import DRC_ERROR, ERC_ERROR, BOM_ERROR, CORRUPTED_PCB, CORRUPTED_SCH, EXIT_BAD_CONFIG +from kibot.misc import DRC_ERROR, ERC_ERROR, BOM_ERROR, CORRUPTED_PCB, CORRUPTED_SCH, EXIT_BAD_CONFIG, NETLIST_DIFF @pytest.mark.slow @@ -173,6 +173,29 @@ def test_update_xml_1(test_dir): ctx.clean_up() +@pytest.mark.slow +@pytest.mark.eeschema +@pytest.mark.skipif(context.ki5(), reason="KiCad 6 implementation") +def test_update_xml_2(test_dir): + prj = 'pcb_parity' + ctx = context.TestContext(test_dir, prj, 'update_xml_2', '') + # The XML should be created where the schematic is located + xml = os.path.abspath(os.path.join(ctx.get_board_dir(), prj+'.xml')) + ctx.run(ret_val=NETLIST_DIFF) + # Check all outputs are there + # ctx.expect_out_file(prj+'.csv') + assert os.path.isfile(xml) + assert os.path.getsize(xml) > 0 + logging.debug(os.path.basename(xml)+' OK') + ctx.search_err(["C1 footprint mismatch", + "F1 found in PCB, but not in schematic", + "FID1 found in schematic, but not in PCB", + "Net count mismatch .PCB 3 vs schematic 4.", + "PCB net code 2 name mismatch", + "PCB net code 2 extra connection/s: C1 pin 1"]) + ctx.clean_up() + + @pytest.mark.slow @pytest.mark.eeschema def test_update_xml_fail(test_dir): diff --git a/tests/yaml_samples/update_xml_2.kibot.yaml b/tests/yaml_samples/update_xml_2.kibot.yaml new file mode 100644 index 00000000..a21a13f9 --- /dev/null +++ b/tests/yaml_samples/update_xml_2.kibot.yaml @@ -0,0 +1,9 @@ +# Example KiBot config file +kibot: + version: 1 + +preflight: + update_xml: + enabled: true + check_pcb_parity: true + as_warnings: false