boardforge 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- boardforge-0.1.0/LICENSE +21 -0
- boardforge-0.1.0/PKG-INFO +258 -0
- boardforge-0.1.0/README.md +229 -0
- boardforge-0.1.0/pyproject.toml +60 -0
- boardforge-0.1.0/setup.cfg +4 -0
- boardforge-0.1.0/src/boardforge/__init__.py +7 -0
- boardforge-0.1.0/src/boardforge/analysis/__init__.py +259 -0
- boardforge-0.1.0/src/boardforge/cli.py +280 -0
- boardforge-0.1.0/src/boardforge/config.py +218 -0
- boardforge-0.1.0/src/boardforge/datasheets.py +604 -0
- boardforge-0.1.0/src/boardforge/drc.py +71 -0
- boardforge-0.1.0/src/boardforge/fabs/__init__.py +18 -0
- boardforge-0.1.0/src/boardforge/fabs/base.py +108 -0
- boardforge-0.1.0/src/boardforge/fabs/jlcpcb/__init__.py +60 -0
- boardforge-0.1.0/src/boardforge/fabs/jlcpcb/profile.toml +56 -0
- boardforge-0.1.0/src/boardforge/kicad.py +189 -0
- boardforge-0.1.0/src/boardforge/netlist.py +118 -0
- boardforge-0.1.0/src/boardforge/pcb/__init__.py +8 -0
- boardforge-0.1.0/src/boardforge/pcb/astar.py +543 -0
- boardforge-0.1.0/src/boardforge/pcb/build.py +158 -0
- boardforge-0.1.0/src/boardforge/pcb/common.py +112 -0
- boardforge-0.1.0/src/boardforge/pcb/congestion.py +116 -0
- boardforge-0.1.0/src/boardforge/pcb/fanout.py +278 -0
- boardforge-0.1.0/src/boardforge/pcb/fiducials.py +104 -0
- boardforge-0.1.0/src/boardforge/pcb/finish.py +215 -0
- boardforge-0.1.0/src/boardforge/pcb/measure.py +76 -0
- boardforge-0.1.0/src/boardforge/pcb/pinswap.py +143 -0
- boardforge-0.1.0/src/boardforge/pcb/place.py +556 -0
- boardforge-0.1.0/src/boardforge/pcb/specctra.py +24 -0
- boardforge-0.1.0/src/boardforge/pcbfile.py +41 -0
- boardforge-0.1.0/src/boardforge/physical.py +811 -0
- boardforge-0.1.0/src/boardforge/project.py +116 -0
- boardforge-0.1.0/src/boardforge/render.py +66 -0
- boardforge-0.1.0/src/boardforge/review/__init__.py +0 -0
- boardforge-0.1.0/src/boardforge/review/bom_check.py +280 -0
- boardforge-0.1.0/src/boardforge/review/budget.py +92 -0
- boardforge-0.1.0/src/boardforge/review/constraints.py +61 -0
- boardforge-0.1.0/src/boardforge/review/datasheet_check.py +172 -0
- boardforge-0.1.0/src/boardforge/review/gate.py +80 -0
- boardforge-0.1.0/src/boardforge/review/package_check.py +246 -0
- boardforge-0.1.0/src/boardforge/review/spice_path.py +351 -0
- boardforge-0.1.0/src/boardforge/routers/__init__.py +17 -0
- boardforge-0.1.0/src/boardforge/routers/astar.py +87 -0
- boardforge-0.1.0/src/boardforge/routers/base.py +77 -0
- boardforge-0.1.0/src/boardforge/routers/freerouting.py +58 -0
- boardforge-0.1.0/src/boardforge/routers/specctra.py +84 -0
- boardforge-0.1.0/src/boardforge/skidl_runner.py +144 -0
- boardforge-0.1.0/src/boardforge/state.py +54 -0
- boardforge-0.1.0/src/boardforge/units.py +33 -0
- boardforge-0.1.0/src/boardforge/vendor/README.md +5 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/LICENSE +21 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/VENDORED.md +25 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/how-it-works.md +254 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/bom/SKILL.md +378 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/bom/references/kicad-fields.md +68 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/bom/references/ordering-and-fabrication.md +150 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/bom/references/part-number-conventions.md +409 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/bom/scripts/bom_manager.py +1298 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/bom/scripts/edit_properties.py +438 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/bom/scripts/kicad_sexp.py +85 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/bom/scripts/sync_datasheet_urls.py +393 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/bom/scripts/translate_bom_pnp.py +731 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/SKILL.md +119 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/datasheet_types/__init__.py +80 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/datasheet_types/__pycache__/__init__.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/datasheet_types/__pycache__/base_block.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/datasheet_types/__pycache__/codec.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/datasheet_types/__pycache__/extraction.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/datasheet_types/__pycache__/pinout.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/datasheet_types/__pycache__/regulator.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/datasheet_types/__pycache__/spec_value.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/datasheet_types/__pycache__/trust_gating.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/datasheet_types/base_block.py +132 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/datasheet_types/codec.py +174 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/datasheet_types/extraction.py +177 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/datasheet_types/pinout.py +117 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/datasheet_types/regulator.py +95 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/datasheet_types/spec_value.py +51 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/datasheet_types/trust_gating.py +125 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/examples/abm8g-106-12.000mhz-t.json +372 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/examples/irlml6344.json +616 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/examples/lm2596-adj.json +507 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/examples/lm358.json +598 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/examples/mbrs540t3g.json +498 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/examples/stm32f103c8t6.json +2090 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/prompts/base.md +56 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/prompts/crystal.md +127 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/prompts/diode.md +89 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/prompts/mcu.md +163 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/prompts/opamp.md +164 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/prompts/pinout.md +54 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/prompts/regulator.md +56 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/prompts/scout.md +68 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/prompts/transistor.md +145 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/references/cache-layout.md +183 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/references/consumer-api.md +240 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/references/dispatch-claude-code.md +179 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/references/dispatcher-contract.md +112 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/references/extraction-pipeline.md +24 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/references/extraction-schema.md +387 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/references/field-extraction-guide.md +262 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/references/quality-scoring.md +205 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/schemas/CHANGELOG.md +180 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/schemas/base.schema.json +181 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/schemas/crystal.schema.json +106 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/schemas/diode.schema.json +148 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/schemas/extraction.schema.json +91 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/schemas/fixtures/lm2596-adj.example.json +507 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/schemas/fixtures/manifest.example.json +31 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/schemas/fixtures/minimal.example.json +95 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/schemas/manifest.schema.json +69 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/schemas/mcu.schema.json +252 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/schemas/opamp.schema.json +167 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/schemas/pinout.schema.json +130 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/schemas/plan.schema.json +100 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/schemas/regulator.schema.json +156 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/schemas/scout.schema.json +68 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/schemas/spec_value.schema.json +62 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/schemas/transistor.schema.json +221 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/scripts/__pycache__/datasheet_extract_cache.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/scripts/__pycache__/datasheet_features.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/scripts/__pycache__/datasheet_lookup.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/scripts/__pycache__/datasheet_score.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/scripts/__pycache__/datasheet_verify.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/scripts/_smoke_v14_roundtrip.py +211 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/scripts/datasheet_extract_cache.py +541 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/scripts/datasheet_features.py +423 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/scripts/datasheet_lookup.py +243 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/scripts/datasheet_page_selector.py +500 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/scripts/datasheet_score.py +459 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/scripts/datasheet_verify.py +1070 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/scripts/merge_results.py +318 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/scripts/plan_extraction.py +198 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/scripts/validate_extraction_result.py +142 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/datasheets/scripts/validate_sanity_vector.py +157 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/digikey/SKILL.md +377 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/digikey/scripts/fetch_datasheet_digikey.py +547 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/digikey/scripts/sync_datasheets_digikey.py +908 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/element14/SKILL.md +273 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/element14/scripts/fetch_datasheet_element14.py +516 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/element14/scripts/sync_datasheets_element14.py +775 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/emc/SKILL.md +206 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/emc/references/emc-methodology.md +142 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/emc/references/emc-standards.md +110 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/emc/references/pcb-emc-rules.md +381 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/emc/scripts/__pycache__/emc_envelope.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/emc/scripts/__pycache__/emc_formulas.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/emc/scripts/__pycache__/emc_rules.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/emc/scripts/analyze_emc.py +682 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/emc/scripts/emc_envelope.py +291 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/emc/scripts/emc_formulas.py +1392 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/emc/scripts/emc_rules.py +4552 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/emc/scripts/emc_spice.py +708 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/jlcpcb/SKILL.md +233 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/SKILL.md +850 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/references/config-reference.md +356 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/references/datasheet-verification.md +322 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/references/deep-review.md +162 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/references/design-intent.md +123 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/references/diff-analysis.md +355 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/references/file-formats.md +379 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/references/gerber-parsing.md +729 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/references/manual-gerber-parsing.md +621 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/references/manual-pcb-parsing.md +467 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/references/manual-schematic-parsing.md +289 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/references/net-tracing.md +169 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/references/oshwa-certification.md +89 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/references/output-schema.md +317 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/references/pcb-layout-analysis.md +447 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/references/pdf-schematic-extraction.md +315 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/references/report-generation.md +696 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/references/schematic-analysis.md +1165 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/references/standards-compliance.md +638 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/references/supplementary-data-sources.md +288 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/references/what-if.md +500 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/review/README.md +46 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/review/fixtures/deep_review.example.json +39 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/review/fixtures/design_context.example.json +9 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/review/fixtures/review_annotations.example.json +22 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/review/prompts/design_context.md +100 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/review/schemas/deep_review.schema.json +72 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/review/schemas/design_context.schema.json +59 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/review/schemas/review_annotations.schema.json +49 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/review/scripts/_mini_jsonschema.py +173 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/review/scripts/build_review_plan.py +65 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/review/scripts/deep_review_gate.py +347 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/review/scripts/merge_annotations.py +175 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/review/scripts/run_phase4_exercise.py +281 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/review/scripts/validate_review.py +72 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/README.md +389 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/__pycache__/analyzer_envelope.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/__pycache__/bus_resolver.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/__pycache__/capability_mode.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/__pycache__/detection_schema.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/__pycache__/detector_helpers.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/__pycache__/domain_detectors.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/__pycache__/finding_schema.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/__pycache__/inputs_builder.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/__pycache__/kicad_types.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/__pycache__/kicad_utils.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/__pycache__/lookup_detectors.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/__pycache__/lookup_helpers.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/__pycache__/netlist_queries.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/__pycache__/output_filters.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/__pycache__/pcb_connectivity.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/__pycache__/project_config.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/__pycache__/run_id.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/__pycache__/schema_codec.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/__pycache__/sexp_parser.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/__pycache__/signal_detectors.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/__pycache__/validation_detectors.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/analysis_cache.py +604 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/analyze_gerbers.py +1670 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/analyze_pcb.py +7544 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/analyze_schematic.py +10421 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/analyze_thermal.py +1222 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/analyzer_envelope.py +295 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/bus_resolver.py +289 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/capability_mode.py +218 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/check_report_sections.py +201 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/cross_analysis.py +1201 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/cross_verify.py +657 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/detection_schema.py +654 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/detector_helpers.py +76 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/diff_analysis.py +1596 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/domain_detectors.py +6161 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/envelopes/__init__.py +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/envelopes/__pycache__/__init__.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/envelopes/__pycache__/gerber.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/envelopes/__pycache__/pcb.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/envelopes/__pycache__/schematic.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/envelopes/__pycache__/thermal.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/envelopes/cross_analysis.py +132 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/envelopes/gerber.py +355 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/envelopes/pcb.py +395 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/envelopes/schematic.py +450 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/envelopes/thermal.py +144 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/export_issues.py +547 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/fab_release_gate.py +604 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/finding_schema.py +715 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/gen_output_schema_md.py +230 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/inputs_builder.py +107 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/kicad_types.py +117 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/kicad_utils.py +2278 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/lifecycle_audit.py +1137 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/lookup_detectors.py +701 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/lookup_helpers.py +60 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/methodology_gerbers.md +447 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/methodology_pcb.md +473 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/methodology_schematic.md +892 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/netlist_queries.py +360 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/output_filters.py +468 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/pcb_connectivity.py +516 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/project_config.py +956 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/run_id.py +47 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/schema_codec.py +145 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/sexp_parser.py +233 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/signal_detectors.py +4699 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/summarize_findings.py +421 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/validation_detectors.py +1440 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/kicad/scripts/what_if.py +1554 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/lcsc/SKILL.md +241 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/lcsc/scripts/fetch_datasheet_lcsc.py +591 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/lcsc/scripts/search_lcsc.py +360 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/lcsc/scripts/sync_datasheets_lcsc.py +755 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/lcsc/scripts/test_search_lcsc.py +358 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/mouser/SKILL.md +265 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/mouser/scripts/fetch_datasheet_mouser.py +600 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/mouser/scripts/sync_datasheets_mouser.py +805 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/pcbway/SKILL.md +179 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/spice/SKILL.md +333 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/spice/references/simulation-models.md +427 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/spice/scripts/__pycache__/spice_model_generator.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/spice/scripts/__pycache__/spice_models.cpython-314.pyc +0 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/spice/scripts/extract_parasitics.py +319 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/spice/scripts/simulate_subcircuits.py +689 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/spice/scripts/spice_model_cache.py +293 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/spice/scripts/spice_model_generator.py +231 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/spice/scripts/spice_models.py +196 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/spice/scripts/spice_part_library.py +447 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/spice/scripts/spice_results.py +1260 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/spice/scripts/spice_simulator.py +475 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/spice/scripts/spice_spec_fetcher.py +650 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/spice/scripts/spice_templates.py +1740 -0
- boardforge-0.1.0/src/boardforge/vendor/kicad_happy/skills/spice/scripts/spice_tolerance.py +311 -0
- boardforge-0.1.0/src/boardforge.egg-info/PKG-INFO +258 -0
- boardforge-0.1.0/src/boardforge.egg-info/SOURCES.txt +299 -0
- boardforge-0.1.0/src/boardforge.egg-info/dependency_links.txt +1 -0
- boardforge-0.1.0/src/boardforge.egg-info/entry_points.txt +2 -0
- boardforge-0.1.0/src/boardforge.egg-info/requires.txt +9 -0
- boardforge-0.1.0/src/boardforge.egg-info/top_level.txt +1 -0
- boardforge-0.1.0/test/test_bom_check.py +71 -0
- boardforge-0.1.0/test/test_budget.py +65 -0
- boardforge-0.1.0/test/test_datasheet_check.py +105 -0
- boardforge-0.1.0/test/test_datasheets.py +178 -0
- boardforge-0.1.0/test/test_fab_outputs.py +40 -0
- boardforge-0.1.0/test/test_package_check.py +120 -0
- boardforge-0.1.0/test/test_pipeline.py +164 -0
- boardforge-0.1.0/test/test_review.py +148 -0
- boardforge-0.1.0/test/test_runner_order.py +29 -0
- boardforge-0.1.0/test/test_units.py +426 -0
boardforge-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dave Vandenbout
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: boardforge
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Turn a SKiDL circuit into a routed, manufacturable KiCad board, headless.
|
|
5
|
+
Author-email: Dave Vandenbout <dave@vdb.name>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/devbisme/boardforge
|
|
8
|
+
Project-URL: Repository, https://github.com/devbisme/boardforge
|
|
9
|
+
Project-URL: Issues, https://github.com/devbisme/boardforge/issues
|
|
10
|
+
Keywords: KiCad,PCB,SKiDL,EDA,routing
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)
|
|
18
|
+
Requires-Python: >=3.11
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: skidl>=3.0.0
|
|
22
|
+
Requires-Dist: schematizer>=0.2.0
|
|
23
|
+
Provides-Extra: test
|
|
24
|
+
Requires-Dist: pytest; extra == "test"
|
|
25
|
+
Provides-Extra: analysis
|
|
26
|
+
Requires-Dist: jsonschema; extra == "analysis"
|
|
27
|
+
Requires-Dist: referencing; extra == "analysis"
|
|
28
|
+
Dynamic: license-file
|
|
29
|
+
|
|
30
|
+
# boardforge
|
|
31
|
+
|
|
32
|
+
Generate and analyze KiCad designs from a requirements prompt: explore many candidate
|
|
33
|
+
architectures, then turn the selected one into a routed, manufacturable board. SKiDL code is
|
|
34
|
+
the source of truth; runs headless (KiCad only for viewing/editing results).
|
|
35
|
+
|
|
36
|
+
This project was called **boardsmith** until 2026-10-16; the name is taken on PyPI by an
|
|
37
|
+
unrelated tool. An old `boardsmith.toml` is still read (with a warning), and old
|
|
38
|
+
`constraints.json` files keep working.
|
|
39
|
+
|
|
40
|
+
**Status:** the physical pipeline (C1–C6: SKiDL → schematic → board → placement → routing →
|
|
41
|
+
checks → fab outputs) and the review gate (B4) work. The detail stage's agents are a Claude
|
|
42
|
+
Code plugin ([`plugin/`](plugin/README.md)), run end to end twice on the dual-ADC design. The explore stage is not
|
|
43
|
+
started. Design: [`docsrc/design.md`](docsrc/design.md).
|
|
44
|
+
|
|
45
|
+
## Install
|
|
46
|
+
boardforge needs Python 3.11 or later and these released tools:
|
|
47
|
+
|
|
48
|
+
| Tool | Version | Needed for |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| [KiCad](https://www.kicad.org/download/) | 10.0 (tested with 10.0.4) | everything: `kicad-cli` and KiCad's Python (`pcbnew`) |
|
|
51
|
+
| [Freerouting](https://github.com/freerouting/freerouting/releases) | 2.4 or later (tested with 2.4.1) | routing (optional: the built-in A* router handles small boards alone) |
|
|
52
|
+
| [ngspice](https://ngspice.sourceforge.io/download.html) | 44 or later (tested with 44.2) | the review gate's simulation checks (optional) |
|
|
53
|
+
| pdftotext ([Poppler](https://poppler.freedesktop.org/) utilities) | any | checking that a downloaded datasheet is the right part (optional) |
|
|
54
|
+
|
|
55
|
+
Install boardforge from PyPI. This also installs [SKiDL](https://pypi.org/project/skidl/)
|
|
56
|
+
3.0.0 or later and [schematizer](https://pypi.org/project/schematizer/) 0.2.0 or later:
|
|
57
|
+
```bash
|
|
58
|
+
uv tool install "boardforge[analysis]" # or: pip install "boardforge[analysis]"
|
|
59
|
+
boardforge doctor # checks KiCad 10, its Python, Freerouting, ngspice
|
|
60
|
+
```
|
|
61
|
+
The `analysis` extra adds `jsonschema`, which validates datasheet extractions.
|
|
62
|
+
|
|
63
|
+
`boardforge doctor` finds KiCad and Freerouting in their usual install locations and on
|
|
64
|
+
`PATH`. Otherwise, set their paths in `~/.config/boardforge/config.toml`, using the same
|
|
65
|
+
`[kicad]` and `[routing.freerouting]` keys as a project file:
|
|
66
|
+
```toml
|
|
67
|
+
[kicad]
|
|
68
|
+
cli = "/opt/kicad/bin/kicad-cli"
|
|
69
|
+
python = "/opt/kicad/bin/python3"
|
|
70
|
+
|
|
71
|
+
[routing.freerouting]
|
|
72
|
+
path = "/opt/freerouting/bin/freerouting"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
To design with Claude Code agents, also install the boardforge plugin
|
|
76
|
+
([`plugin/README.md`](plugin/README.md)).
|
|
77
|
+
|
|
78
|
+
## Use
|
|
79
|
+
A project is a directory with a SKiDL file and a `boardforge.toml`:
|
|
80
|
+
```bash
|
|
81
|
+
cd test/examples/tiny
|
|
82
|
+
boardforge run # C1..C6 -> build/
|
|
83
|
+
boardforge run --from c4 # rerun from routing
|
|
84
|
+
boardforge route # one stage: sch | board | place | route | check | fab
|
|
85
|
+
boardforge status
|
|
86
|
+
boardforge render --side both # build/renders/*.svg/png of the current board
|
|
87
|
+
boardforge review # B4: constraints.json against the design (after C1)
|
|
88
|
+
boardforge datasheets sync # part-fact cache: datasheet PDFs and extractions
|
|
89
|
+
```
|
|
90
|
+
C3 places multi-pin parts next to what they connect to (through up to three series
|
|
91
|
+
passives), and warns when a connector's signal reaches its first IC from more than
|
|
92
|
+
`[placement] connector_path_mm` (25) away, such as an unbuffered input crossing the board.
|
|
93
|
+
C3 also reports a routability estimate (`reports/congestion.json`: routing demand per 2.5 mm
|
|
94
|
+
cell, ratsnest crossings) and, with compaction, the sizes it tried (`reports/compaction.json`). Each stage prints a short summary; details go to `build/reports/`, and
|
|
95
|
+
`build/pipeline_state.json` records every stage. Outputs:
|
|
96
|
+
- `build/kicad/`: KiCad project (labels-only schematic, board, net classes, lib tables)
|
|
97
|
+
- `build/fab/`: Gerber zip, JLCPCB BOM and CPL
|
|
98
|
+
- `build/docs/`: schematic PDF, 3D renders
|
|
99
|
+
- `build/reports/`: parity, ERC, DRC, geometry checks, kicad-happy analyses
|
|
100
|
+
|
|
101
|
+
### SKiDL conventions
|
|
102
|
+
- Use `part.fields["MPN"] = ...` (and `LCSC`, `Manufacturer`, `Tolerance`, ...). Keyword
|
|
103
|
+
arguments to `Part()` and plain attributes (`part.MPN = ...`) don't become fields.
|
|
104
|
+
- Net classes: `NetClass("Power", track_width=0.3, clearance=0.15, priority=2)` and
|
|
105
|
+
`net.netclasses = power` (not `net.netclass`, which does nothing). Keys are KiCad's
|
|
106
|
+
`.kicad_pro` names; in SKiDL the larger `priority` wins.
|
|
107
|
+
- Don't set `lib_search_paths`; boardforge points SKiDL at KiCad 10's libraries.
|
|
108
|
+
- Expose a function that builds the circuit and name it in `[design] top`, or build it at
|
|
109
|
+
import time. `[design] file` may also be a package directory (`circuits/<name>/` with
|
|
110
|
+
`__main__.py`); it runs as a module, so relative imports work. The project directory and
|
|
111
|
+
its `symbols/` are on SKiDL's library path.
|
|
112
|
+
|
|
113
|
+
### boardforge.toml
|
|
114
|
+
See `src/boardforge/config.py` for every key and its default. The main ones:
|
|
115
|
+
```toml
|
|
116
|
+
[design]
|
|
117
|
+
file = "tiny.py"
|
|
118
|
+
top = "build" # function that builds the circuit
|
|
119
|
+
|
|
120
|
+
[fab]
|
|
121
|
+
name = "jlcpcb"
|
|
122
|
+
tier = "standard" # profile tier: standard (1-2 layers) | multilayer
|
|
123
|
+
|
|
124
|
+
[board]
|
|
125
|
+
size = [130, 90] # mm; omit to estimate from courtyard area (fill)
|
|
126
|
+
layers = 4
|
|
127
|
+
planes = { "In1.Cu" = "GND", "In2.Cu" = "+3V3" }
|
|
128
|
+
pours = ["GND"] # outer-layer pours, stitched with vias
|
|
129
|
+
|
|
130
|
+
[rules] # default net class; lowered to the pad gap of a finer-pitch
|
|
131
|
+
track_width = 0.15 # footprint (0.4 mm QFN: 0.10), down to the fab tier minimum
|
|
132
|
+
clearance = 0.15
|
|
133
|
+
|
|
134
|
+
[[placement.anchor]] # floorplan: fixed positions (mm from top-left)
|
|
135
|
+
value = "^LTC2291" # regex on value (or ref = "U3"), optional sheet regex
|
|
136
|
+
at = [55.0, 44.0]
|
|
137
|
+
rot = 0
|
|
138
|
+
edge = "left" # optional: keep the offset from this edge when compacting
|
|
139
|
+
|
|
140
|
+
[[placement.anchor]] # a connector: rotation from the footprint, mating side out
|
|
141
|
+
ref = "J2"
|
|
142
|
+
at = [12.5, 22.0]
|
|
143
|
+
facing = "left"
|
|
144
|
+
edge = "left"
|
|
145
|
+
|
|
146
|
+
[placement.compact] # shrink the board while everything still fits, then
|
|
147
|
+
enabled = true # confirm by routing (stepping back up if it fails)
|
|
148
|
+
min_scale = 0.6
|
|
149
|
+
max_stretched = 5 # stop when 5 more passives than at full size end up
|
|
150
|
+
stretch_mm = 8.0 # over 8 mm from their spot (C3 summary: stretch)
|
|
151
|
+
|
|
152
|
+
[[placement.region]] # floorplan: unanchored ICs of a sheet go in this area, near
|
|
153
|
+
sheet = "front_end" # the parts they connect to; regex on sheet (and/or value);
|
|
154
|
+
area = [0.0, 0.0, 0.4, 1.0] # fractions of the board (or rect = [x0, y0, x1, y1] mm)
|
|
155
|
+
|
|
156
|
+
[[placement.pin_swap]] # FPGA/MCU pin swap; C3 writes the map, the design reads it
|
|
157
|
+
part = "^ICE40"
|
|
158
|
+
map = "fpga_pinmap.json" # {SKiDL net: pin}; C1-C3 rerun when it changes
|
|
159
|
+
[[placement.pin_swap.group]]
|
|
160
|
+
pins = [1, 2, 3, 4, 7, 8] # swappable pins
|
|
161
|
+
partner = "^LTC2291" # the part these signals go to
|
|
162
|
+
|
|
163
|
+
[routing]
|
|
164
|
+
chain = ["freerouting", "astar"]
|
|
165
|
+
preroute = ["USB_DP", "USB_DM"]
|
|
166
|
+
|
|
167
|
+
[checks.rail_currents] # regulator loads (A) for the thermal check, overriding
|
|
168
|
+
"+1V2" = 0.05 # constraints.json rail_current; else kicad-happy guesses
|
|
169
|
+
```
|
|
170
|
+
Net names in the config are SKiDL names; boardforge maps them to KiCad's.
|
|
171
|
+
|
|
172
|
+
### Review gate (B4)
|
|
173
|
+
`boardforge review` checks `constraints.json` (project root) against the design after C1 and
|
|
174
|
+
writes `build/reports/review.json`: PASS / FAIL / NOT CHECKED per constraint. A HARD failure
|
|
175
|
+
fails the gate; SOFT and ASSUMED failures, and anything not checked, warn.
|
|
176
|
+
```json
|
|
177
|
+
{"schema": "boardforge-constraints", "version": 1, "constraints": [
|
|
178
|
+
{"id": "ALIAS-A", "kind": "ac_gain", "tag": "ASSUMED", "why": "content at Nyquist 40 dB down",
|
|
179
|
+
"in": "VIN_A", "out": ["AIN_AP", "AIN_AN"], "at_hz": 5e6, "ref_hz": 1e3, "max_db": -40}]}
|
|
180
|
+
```
|
|
181
|
+
`ac_gain` runs an ngspice testbench of the whole path, built from the SKiDL netlist. Op-amps
|
|
182
|
+
and fully-differential amplifiers need a model (unmodelled ICs are open circuits):
|
|
183
|
+
```toml
|
|
184
|
+
[review]
|
|
185
|
+
dc = { VCM = 0.9 } # DC volts for nets the netlist can't give
|
|
186
|
+
[review.models."^THS4521"] # regex on value / MPN / symbol
|
|
187
|
+
type = "fda" # or "opamp"
|
|
188
|
+
gbw_hz = 93e6 # overridden by a part-fact cache extraction
|
|
189
|
+
pins = { outp = 4, outn = 5 } # roles the symbol's pin names don't give
|
|
190
|
+
```
|
|
191
|
+
`rail_current` (`net`, `max_a`: the load on the rail) is checked against the rated output
|
|
192
|
+
current (`regulator.iout_max`) of the part that makes the rail, found by its power-output pin
|
|
193
|
+
on the net or behind one series inductor or ferrite bead. The same loads feed the C5 thermal
|
|
194
|
+
check.
|
|
195
|
+
`review` also checks each part that has a datasheet extraction (see Part-fact cache), as
|
|
196
|
+
`DS:<MPN>`: the voltage across its supply pins against the absolute maximum (error) and
|
|
197
|
+
recommended range (warning), and its datasheet power pins connected. `DS:coverage` lists the
|
|
198
|
+
parts without an extraction. `PKG:pins` checks that every symbol pin on a net has a footprint
|
|
199
|
+
pad (and every numbered pad has a pin), and `PKG:<MPN>` compares the footprint with the
|
|
200
|
+
datasheet package: pad count, pitch, thermal pad, pin numbers and body size. `BOM` diffs the
|
|
201
|
+
sourced BOM (`[review] bom`, default `sourcing/sourced_bom.csv`) against the design: MPN,
|
|
202
|
+
LCSC number, value (numerically), footprint, symbol, and the `package` column against the
|
|
203
|
+
footprint's body variant.
|
|
204
|
+
|
|
205
|
+
### Part-fact cache
|
|
206
|
+
Datasheet PDFs and their structured extractions, in kicad-happy's layout
|
|
207
|
+
(`datasheets/manifest.json`, `<MPN>.pdf`, `extracted/<MPN>.json`), kept twice: in the project
|
|
208
|
+
(`datasheets/`, what the analyzers and `review` read) and in a cache shared by all projects
|
|
209
|
+
(`~/.cache/boardforge/datasheets/`). Parts are the netlist's `MPN` fields; ICs, diodes and
|
|
210
|
+
crystals by default (`prefixes`).
|
|
211
|
+
```bash
|
|
212
|
+
boardforge datasheets status # per part: PDF, extraction, quality, staleness, in the cache
|
|
213
|
+
boardforge datasheets sync # copy from the shared cache, then find missing PDFs
|
|
214
|
+
boardforge datasheets add MPN FILE_OR_URL # one PDF, after checking it names the part
|
|
215
|
+
boardforge datasheets check MPN... # validate extractions, fill derived fields, score
|
|
216
|
+
boardforge datasheets show MPN... # markdown summary of extractions
|
|
217
|
+
boardforge datasheets paths # kicad-happy's extraction prompts, schemas, examples
|
|
218
|
+
boardforge datasheets publish # copy the project's extractions to the shared cache
|
|
219
|
+
```
|
|
220
|
+
Before there is a netlist, the parts come from the sourced BOM CSV.
|
|
221
|
+
A PDF is kept only if its text names the part; a scanned one needs `add --force` after a
|
|
222
|
+
look by eye. `sync` looks for a missing PDF in the `search` directories (a file named after the part,
|
|
223
|
+
`OPA810.pdf` for `OPA810IDR`), then downloads it from the symbol's datasheet URL, then
|
|
224
|
+
LCSC. A download whose text doesn't name the part is discarded (needs `pdftotext`). `--fresh`
|
|
225
|
+
skips the shared cache, `--offline` the downloads. Extraction itself is LLM work: an agent
|
|
226
|
+
writes `extracted/<MPN>.json` following kicad-happy's prompts and schemas (`paths`), then
|
|
227
|
+
`check` validates it and fills in the PDF hash, page count and quality score. `publish` takes
|
|
228
|
+
only extractions that match their PDF and pass kicad-happy's schema (needs `jsonschema`), and
|
|
229
|
+
keeps a shared entry unless the project's is newer and scores no lower (`--force`).
|
|
230
|
+
`review` takes op-amp GBW and slew rate from the extractions.
|
|
231
|
+
```toml
|
|
232
|
+
[datasheets]
|
|
233
|
+
search = ["~/datasheets"]
|
|
234
|
+
cache = "~/.cache/boardforge/datasheets" # "" = no shared cache
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Layout
|
|
238
|
+
```
|
|
239
|
+
src/boardforge/ package
|
|
240
|
+
physical.py C1-C6 orchestration
|
|
241
|
+
pcb/ board scripts run under KiCad's Python (all pcbnew code is here)
|
|
242
|
+
routers/ router interface: Freerouting (Specctra), A*
|
|
243
|
+
fabs/<fab>/ fab adapters: profile.toml + adapter
|
|
244
|
+
analysis/ analysis-step registry (kicad-happy analyzers by default)
|
|
245
|
+
review/ B4 gate: constraints.json, SPICE path testbenches, datasheet, package and BOM checks
|
|
246
|
+
datasheets.py part-fact cache: status, sync, add, check, show, publish
|
|
247
|
+
plugin/ Claude Code plugin: the detail-stage agents and skills (from skidl-skills)
|
|
248
|
+
vendor/kicad_happy/ vendored kicad-happy (MIT)
|
|
249
|
+
test/ pytest; test/examples/ has the tiny and dual-ADC projects
|
|
250
|
+
docsrc/ documentation source (design doc)
|
|
251
|
+
```
|
|
252
|
+
Tests: `pytest -m "not kicad"` for the fast ones; `pytest` also runs the tiny design
|
|
253
|
+
end to end (about a minute).
|
|
254
|
+
|
|
255
|
+
## Third-party code
|
|
256
|
+
`src/boardforge/vendor/` contains code from other projects, each under its own license.
|
|
257
|
+
See [`src/boardforge/vendor/README.md`](src/boardforge/vendor/README.md). The plugin is
|
|
258
|
+
adapted from skidl-skills (MIT): [`plugin/ATTRIBUTION.md`](plugin/ATTRIBUTION.md).
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# boardforge
|
|
2
|
+
|
|
3
|
+
Generate and analyze KiCad designs from a requirements prompt: explore many candidate
|
|
4
|
+
architectures, then turn the selected one into a routed, manufacturable board. SKiDL code is
|
|
5
|
+
the source of truth; runs headless (KiCad only for viewing/editing results).
|
|
6
|
+
|
|
7
|
+
This project was called **boardsmith** until 2026-10-16; the name is taken on PyPI by an
|
|
8
|
+
unrelated tool. An old `boardsmith.toml` is still read (with a warning), and old
|
|
9
|
+
`constraints.json` files keep working.
|
|
10
|
+
|
|
11
|
+
**Status:** the physical pipeline (C1–C6: SKiDL → schematic → board → placement → routing →
|
|
12
|
+
checks → fab outputs) and the review gate (B4) work. The detail stage's agents are a Claude
|
|
13
|
+
Code plugin ([`plugin/`](plugin/README.md)), run end to end twice on the dual-ADC design. The explore stage is not
|
|
14
|
+
started. Design: [`docsrc/design.md`](docsrc/design.md).
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
boardforge needs Python 3.11 or later and these released tools:
|
|
18
|
+
|
|
19
|
+
| Tool | Version | Needed for |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| [KiCad](https://www.kicad.org/download/) | 10.0 (tested with 10.0.4) | everything: `kicad-cli` and KiCad's Python (`pcbnew`) |
|
|
22
|
+
| [Freerouting](https://github.com/freerouting/freerouting/releases) | 2.4 or later (tested with 2.4.1) | routing (optional: the built-in A* router handles small boards alone) |
|
|
23
|
+
| [ngspice](https://ngspice.sourceforge.io/download.html) | 44 or later (tested with 44.2) | the review gate's simulation checks (optional) |
|
|
24
|
+
| pdftotext ([Poppler](https://poppler.freedesktop.org/) utilities) | any | checking that a downloaded datasheet is the right part (optional) |
|
|
25
|
+
|
|
26
|
+
Install boardforge from PyPI. This also installs [SKiDL](https://pypi.org/project/skidl/)
|
|
27
|
+
3.0.0 or later and [schematizer](https://pypi.org/project/schematizer/) 0.2.0 or later:
|
|
28
|
+
```bash
|
|
29
|
+
uv tool install "boardforge[analysis]" # or: pip install "boardforge[analysis]"
|
|
30
|
+
boardforge doctor # checks KiCad 10, its Python, Freerouting, ngspice
|
|
31
|
+
```
|
|
32
|
+
The `analysis` extra adds `jsonschema`, which validates datasheet extractions.
|
|
33
|
+
|
|
34
|
+
`boardforge doctor` finds KiCad and Freerouting in their usual install locations and on
|
|
35
|
+
`PATH`. Otherwise, set their paths in `~/.config/boardforge/config.toml`, using the same
|
|
36
|
+
`[kicad]` and `[routing.freerouting]` keys as a project file:
|
|
37
|
+
```toml
|
|
38
|
+
[kicad]
|
|
39
|
+
cli = "/opt/kicad/bin/kicad-cli"
|
|
40
|
+
python = "/opt/kicad/bin/python3"
|
|
41
|
+
|
|
42
|
+
[routing.freerouting]
|
|
43
|
+
path = "/opt/freerouting/bin/freerouting"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
To design with Claude Code agents, also install the boardforge plugin
|
|
47
|
+
([`plugin/README.md`](plugin/README.md)).
|
|
48
|
+
|
|
49
|
+
## Use
|
|
50
|
+
A project is a directory with a SKiDL file and a `boardforge.toml`:
|
|
51
|
+
```bash
|
|
52
|
+
cd test/examples/tiny
|
|
53
|
+
boardforge run # C1..C6 -> build/
|
|
54
|
+
boardforge run --from c4 # rerun from routing
|
|
55
|
+
boardforge route # one stage: sch | board | place | route | check | fab
|
|
56
|
+
boardforge status
|
|
57
|
+
boardforge render --side both # build/renders/*.svg/png of the current board
|
|
58
|
+
boardforge review # B4: constraints.json against the design (after C1)
|
|
59
|
+
boardforge datasheets sync # part-fact cache: datasheet PDFs and extractions
|
|
60
|
+
```
|
|
61
|
+
C3 places multi-pin parts next to what they connect to (through up to three series
|
|
62
|
+
passives), and warns when a connector's signal reaches its first IC from more than
|
|
63
|
+
`[placement] connector_path_mm` (25) away, such as an unbuffered input crossing the board.
|
|
64
|
+
C3 also reports a routability estimate (`reports/congestion.json`: routing demand per 2.5 mm
|
|
65
|
+
cell, ratsnest crossings) and, with compaction, the sizes it tried (`reports/compaction.json`). Each stage prints a short summary; details go to `build/reports/`, and
|
|
66
|
+
`build/pipeline_state.json` records every stage. Outputs:
|
|
67
|
+
- `build/kicad/`: KiCad project (labels-only schematic, board, net classes, lib tables)
|
|
68
|
+
- `build/fab/`: Gerber zip, JLCPCB BOM and CPL
|
|
69
|
+
- `build/docs/`: schematic PDF, 3D renders
|
|
70
|
+
- `build/reports/`: parity, ERC, DRC, geometry checks, kicad-happy analyses
|
|
71
|
+
|
|
72
|
+
### SKiDL conventions
|
|
73
|
+
- Use `part.fields["MPN"] = ...` (and `LCSC`, `Manufacturer`, `Tolerance`, ...). Keyword
|
|
74
|
+
arguments to `Part()` and plain attributes (`part.MPN = ...`) don't become fields.
|
|
75
|
+
- Net classes: `NetClass("Power", track_width=0.3, clearance=0.15, priority=2)` and
|
|
76
|
+
`net.netclasses = power` (not `net.netclass`, which does nothing). Keys are KiCad's
|
|
77
|
+
`.kicad_pro` names; in SKiDL the larger `priority` wins.
|
|
78
|
+
- Don't set `lib_search_paths`; boardforge points SKiDL at KiCad 10's libraries.
|
|
79
|
+
- Expose a function that builds the circuit and name it in `[design] top`, or build it at
|
|
80
|
+
import time. `[design] file` may also be a package directory (`circuits/<name>/` with
|
|
81
|
+
`__main__.py`); it runs as a module, so relative imports work. The project directory and
|
|
82
|
+
its `symbols/` are on SKiDL's library path.
|
|
83
|
+
|
|
84
|
+
### boardforge.toml
|
|
85
|
+
See `src/boardforge/config.py` for every key and its default. The main ones:
|
|
86
|
+
```toml
|
|
87
|
+
[design]
|
|
88
|
+
file = "tiny.py"
|
|
89
|
+
top = "build" # function that builds the circuit
|
|
90
|
+
|
|
91
|
+
[fab]
|
|
92
|
+
name = "jlcpcb"
|
|
93
|
+
tier = "standard" # profile tier: standard (1-2 layers) | multilayer
|
|
94
|
+
|
|
95
|
+
[board]
|
|
96
|
+
size = [130, 90] # mm; omit to estimate from courtyard area (fill)
|
|
97
|
+
layers = 4
|
|
98
|
+
planes = { "In1.Cu" = "GND", "In2.Cu" = "+3V3" }
|
|
99
|
+
pours = ["GND"] # outer-layer pours, stitched with vias
|
|
100
|
+
|
|
101
|
+
[rules] # default net class; lowered to the pad gap of a finer-pitch
|
|
102
|
+
track_width = 0.15 # footprint (0.4 mm QFN: 0.10), down to the fab tier minimum
|
|
103
|
+
clearance = 0.15
|
|
104
|
+
|
|
105
|
+
[[placement.anchor]] # floorplan: fixed positions (mm from top-left)
|
|
106
|
+
value = "^LTC2291" # regex on value (or ref = "U3"), optional sheet regex
|
|
107
|
+
at = [55.0, 44.0]
|
|
108
|
+
rot = 0
|
|
109
|
+
edge = "left" # optional: keep the offset from this edge when compacting
|
|
110
|
+
|
|
111
|
+
[[placement.anchor]] # a connector: rotation from the footprint, mating side out
|
|
112
|
+
ref = "J2"
|
|
113
|
+
at = [12.5, 22.0]
|
|
114
|
+
facing = "left"
|
|
115
|
+
edge = "left"
|
|
116
|
+
|
|
117
|
+
[placement.compact] # shrink the board while everything still fits, then
|
|
118
|
+
enabled = true # confirm by routing (stepping back up if it fails)
|
|
119
|
+
min_scale = 0.6
|
|
120
|
+
max_stretched = 5 # stop when 5 more passives than at full size end up
|
|
121
|
+
stretch_mm = 8.0 # over 8 mm from their spot (C3 summary: stretch)
|
|
122
|
+
|
|
123
|
+
[[placement.region]] # floorplan: unanchored ICs of a sheet go in this area, near
|
|
124
|
+
sheet = "front_end" # the parts they connect to; regex on sheet (and/or value);
|
|
125
|
+
area = [0.0, 0.0, 0.4, 1.0] # fractions of the board (or rect = [x0, y0, x1, y1] mm)
|
|
126
|
+
|
|
127
|
+
[[placement.pin_swap]] # FPGA/MCU pin swap; C3 writes the map, the design reads it
|
|
128
|
+
part = "^ICE40"
|
|
129
|
+
map = "fpga_pinmap.json" # {SKiDL net: pin}; C1-C3 rerun when it changes
|
|
130
|
+
[[placement.pin_swap.group]]
|
|
131
|
+
pins = [1, 2, 3, 4, 7, 8] # swappable pins
|
|
132
|
+
partner = "^LTC2291" # the part these signals go to
|
|
133
|
+
|
|
134
|
+
[routing]
|
|
135
|
+
chain = ["freerouting", "astar"]
|
|
136
|
+
preroute = ["USB_DP", "USB_DM"]
|
|
137
|
+
|
|
138
|
+
[checks.rail_currents] # regulator loads (A) for the thermal check, overriding
|
|
139
|
+
"+1V2" = 0.05 # constraints.json rail_current; else kicad-happy guesses
|
|
140
|
+
```
|
|
141
|
+
Net names in the config are SKiDL names; boardforge maps them to KiCad's.
|
|
142
|
+
|
|
143
|
+
### Review gate (B4)
|
|
144
|
+
`boardforge review` checks `constraints.json` (project root) against the design after C1 and
|
|
145
|
+
writes `build/reports/review.json`: PASS / FAIL / NOT CHECKED per constraint. A HARD failure
|
|
146
|
+
fails the gate; SOFT and ASSUMED failures, and anything not checked, warn.
|
|
147
|
+
```json
|
|
148
|
+
{"schema": "boardforge-constraints", "version": 1, "constraints": [
|
|
149
|
+
{"id": "ALIAS-A", "kind": "ac_gain", "tag": "ASSUMED", "why": "content at Nyquist 40 dB down",
|
|
150
|
+
"in": "VIN_A", "out": ["AIN_AP", "AIN_AN"], "at_hz": 5e6, "ref_hz": 1e3, "max_db": -40}]}
|
|
151
|
+
```
|
|
152
|
+
`ac_gain` runs an ngspice testbench of the whole path, built from the SKiDL netlist. Op-amps
|
|
153
|
+
and fully-differential amplifiers need a model (unmodelled ICs are open circuits):
|
|
154
|
+
```toml
|
|
155
|
+
[review]
|
|
156
|
+
dc = { VCM = 0.9 } # DC volts for nets the netlist can't give
|
|
157
|
+
[review.models."^THS4521"] # regex on value / MPN / symbol
|
|
158
|
+
type = "fda" # or "opamp"
|
|
159
|
+
gbw_hz = 93e6 # overridden by a part-fact cache extraction
|
|
160
|
+
pins = { outp = 4, outn = 5 } # roles the symbol's pin names don't give
|
|
161
|
+
```
|
|
162
|
+
`rail_current` (`net`, `max_a`: the load on the rail) is checked against the rated output
|
|
163
|
+
current (`regulator.iout_max`) of the part that makes the rail, found by its power-output pin
|
|
164
|
+
on the net or behind one series inductor or ferrite bead. The same loads feed the C5 thermal
|
|
165
|
+
check.
|
|
166
|
+
`review` also checks each part that has a datasheet extraction (see Part-fact cache), as
|
|
167
|
+
`DS:<MPN>`: the voltage across its supply pins against the absolute maximum (error) and
|
|
168
|
+
recommended range (warning), and its datasheet power pins connected. `DS:coverage` lists the
|
|
169
|
+
parts without an extraction. `PKG:pins` checks that every symbol pin on a net has a footprint
|
|
170
|
+
pad (and every numbered pad has a pin), and `PKG:<MPN>` compares the footprint with the
|
|
171
|
+
datasheet package: pad count, pitch, thermal pad, pin numbers and body size. `BOM` diffs the
|
|
172
|
+
sourced BOM (`[review] bom`, default `sourcing/sourced_bom.csv`) against the design: MPN,
|
|
173
|
+
LCSC number, value (numerically), footprint, symbol, and the `package` column against the
|
|
174
|
+
footprint's body variant.
|
|
175
|
+
|
|
176
|
+
### Part-fact cache
|
|
177
|
+
Datasheet PDFs and their structured extractions, in kicad-happy's layout
|
|
178
|
+
(`datasheets/manifest.json`, `<MPN>.pdf`, `extracted/<MPN>.json`), kept twice: in the project
|
|
179
|
+
(`datasheets/`, what the analyzers and `review` read) and in a cache shared by all projects
|
|
180
|
+
(`~/.cache/boardforge/datasheets/`). Parts are the netlist's `MPN` fields; ICs, diodes and
|
|
181
|
+
crystals by default (`prefixes`).
|
|
182
|
+
```bash
|
|
183
|
+
boardforge datasheets status # per part: PDF, extraction, quality, staleness, in the cache
|
|
184
|
+
boardforge datasheets sync # copy from the shared cache, then find missing PDFs
|
|
185
|
+
boardforge datasheets add MPN FILE_OR_URL # one PDF, after checking it names the part
|
|
186
|
+
boardforge datasheets check MPN... # validate extractions, fill derived fields, score
|
|
187
|
+
boardforge datasheets show MPN... # markdown summary of extractions
|
|
188
|
+
boardforge datasheets paths # kicad-happy's extraction prompts, schemas, examples
|
|
189
|
+
boardforge datasheets publish # copy the project's extractions to the shared cache
|
|
190
|
+
```
|
|
191
|
+
Before there is a netlist, the parts come from the sourced BOM CSV.
|
|
192
|
+
A PDF is kept only if its text names the part; a scanned one needs `add --force` after a
|
|
193
|
+
look by eye. `sync` looks for a missing PDF in the `search` directories (a file named after the part,
|
|
194
|
+
`OPA810.pdf` for `OPA810IDR`), then downloads it from the symbol's datasheet URL, then
|
|
195
|
+
LCSC. A download whose text doesn't name the part is discarded (needs `pdftotext`). `--fresh`
|
|
196
|
+
skips the shared cache, `--offline` the downloads. Extraction itself is LLM work: an agent
|
|
197
|
+
writes `extracted/<MPN>.json` following kicad-happy's prompts and schemas (`paths`), then
|
|
198
|
+
`check` validates it and fills in the PDF hash, page count and quality score. `publish` takes
|
|
199
|
+
only extractions that match their PDF and pass kicad-happy's schema (needs `jsonschema`), and
|
|
200
|
+
keeps a shared entry unless the project's is newer and scores no lower (`--force`).
|
|
201
|
+
`review` takes op-amp GBW and slew rate from the extractions.
|
|
202
|
+
```toml
|
|
203
|
+
[datasheets]
|
|
204
|
+
search = ["~/datasheets"]
|
|
205
|
+
cache = "~/.cache/boardforge/datasheets" # "" = no shared cache
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Layout
|
|
209
|
+
```
|
|
210
|
+
src/boardforge/ package
|
|
211
|
+
physical.py C1-C6 orchestration
|
|
212
|
+
pcb/ board scripts run under KiCad's Python (all pcbnew code is here)
|
|
213
|
+
routers/ router interface: Freerouting (Specctra), A*
|
|
214
|
+
fabs/<fab>/ fab adapters: profile.toml + adapter
|
|
215
|
+
analysis/ analysis-step registry (kicad-happy analyzers by default)
|
|
216
|
+
review/ B4 gate: constraints.json, SPICE path testbenches, datasheet, package and BOM checks
|
|
217
|
+
datasheets.py part-fact cache: status, sync, add, check, show, publish
|
|
218
|
+
plugin/ Claude Code plugin: the detail-stage agents and skills (from skidl-skills)
|
|
219
|
+
vendor/kicad_happy/ vendored kicad-happy (MIT)
|
|
220
|
+
test/ pytest; test/examples/ has the tiny and dual-ADC projects
|
|
221
|
+
docsrc/ documentation source (design doc)
|
|
222
|
+
```
|
|
223
|
+
Tests: `pytest -m "not kicad"` for the fast ones; `pytest` also runs the tiny design
|
|
224
|
+
end to end (about a minute).
|
|
225
|
+
|
|
226
|
+
## Third-party code
|
|
227
|
+
`src/boardforge/vendor/` contains code from other projects, each under its own license.
|
|
228
|
+
See [`src/boardforge/vendor/README.md`](src/boardforge/vendor/README.md). The plugin is
|
|
229
|
+
adapted from skidl-skills (MIT): [`plugin/ATTRIBUTION.md`](plugin/ATTRIBUTION.md).
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "boardforge"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Turn a SKiDL circuit into a routed, manufacturable KiCad board, headless."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
# tomllib (stdlib) is used for configuration and fab profiles. KiCad 10 ships Python 3.11,
|
|
11
|
+
# and the board scripts in boardforge.pcb run under it, so 3.11 is the floor for both sides.
|
|
12
|
+
requires-python = ">=3.11"
|
|
13
|
+
license = "MIT"
|
|
14
|
+
license-files = ["LICENSE"]
|
|
15
|
+
authors = [{ name = "Dave Vandenbout", email = "dave@vdb.name" }]
|
|
16
|
+
keywords = ["KiCad", "PCB", "SKiDL", "EDA", "routing"]
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Development Status :: 3 - Alpha",
|
|
19
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
|
+
"Programming Language :: Python :: 3.14",
|
|
24
|
+
"Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)",
|
|
25
|
+
]
|
|
26
|
+
# skidl >= 3.0.0 reads KiCad 10 .kicad_symdir libraries and writes the fields, attributes and
|
|
27
|
+
# net classes into its netlist; schematizer >= 0.2.0 has the labels-only schematic mode.
|
|
28
|
+
dependencies = [
|
|
29
|
+
"skidl>=3.0.0",
|
|
30
|
+
"schematizer>=0.2.0",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[project.urls]
|
|
34
|
+
Homepage = "https://github.com/devbisme/boardforge"
|
|
35
|
+
Repository = "https://github.com/devbisme/boardforge"
|
|
36
|
+
Issues = "https://github.com/devbisme/boardforge/issues"
|
|
37
|
+
|
|
38
|
+
[project.optional-dependencies]
|
|
39
|
+
test = ["pytest"]
|
|
40
|
+
# A few vendored kicad-happy validators use these.
|
|
41
|
+
analysis = ["jsonschema", "referencing"]
|
|
42
|
+
|
|
43
|
+
[project.scripts]
|
|
44
|
+
boardforge = "boardforge.cli:main"
|
|
45
|
+
|
|
46
|
+
[tool.setuptools.packages.find]
|
|
47
|
+
where = ["src"]
|
|
48
|
+
|
|
49
|
+
[tool.setuptools.package-data]
|
|
50
|
+
boardforge = ["fabs/*/*.toml", "vendor/**/*"]
|
|
51
|
+
|
|
52
|
+
[tool.pytest.ini_options]
|
|
53
|
+
testpaths = ["test"]
|
|
54
|
+
markers = [
|
|
55
|
+
"kicad: needs KiCad 10 (kicad-cli and its Python)",
|
|
56
|
+
"slow: runs the full pipeline (minutes)",
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
[tool.black]
|
|
60
|
+
line-length = 100
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"""boardforge: SKiDL circuit -> routed, manufacturable KiCad board.
|
|
2
|
+
|
|
3
|
+
Keep this module free of imports: the scripts in boardforge.pcb run under KiCad's own
|
|
4
|
+
Python, which imports this package but has none of boardforge's dependencies.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
__version__ = "0.1.0"
|