aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2016-07-26 00:22:55 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2016-07-26 00:22:55 +0200
commit128e53d220d97225803d61d86f8e43439563181d (patch)
treee0d5da8d666c54d1d17e64ee6f52af424129f90d
downloadkicad-utils-128e53d220d97225803d61d86f8e43439563181d.tar.gz
kicad-utils-128e53d220d97225803d61d86f8e43439563181d.tar.bz2
kicad-utils-128e53d220d97225803d61d86f8e43439563181d.tar.xz
kicad-utils-128e53d220d97225803d61d86f8e43439563181d.zip
WIP: kicad_gen is a util to generate schematic.h files from KiCAD netlist files.
Current code contains a lexer and parser for KiCAD's netlist files and code to build a tree of the netlist which can be used for generation. Contains CMake code for integrating the generation into CMake too.
-rw-r--r--.editorconfig4
-rw-r--r--.gitignore5
-rw-r--r--CMakeLists.txt67
-rw-r--r--KicadNetLexer.g436
-rw-r--r--KicadNetParser.g472
-rw-r--r--examples/.gitignore2
-rw-r--r--examples/CMakeLists.txt1
-rw-r--r--examples/arduino-led/CMakeLists.txt14
-rw-r--r--examples/arduino-led/arduino-led.ino13
-rw-r--r--examples/arduino-led/schematic/arduino-led.net166
-rw-r--r--examples/arduino-led/schematic/arduino-led.pro61
-rw-r--r--examples/arduino-led/schematic/arduino-led.sch101
-rw-r--r--include/trygvis/kicad.h80
-rw-r--r--java/pom.xml87
-rw-r--r--java/src/main/java/io/trygvis/ld/CollectingErrorListener.java17
-rw-r--r--java/src/main/java/io/trygvis/ld/ElfinfoExprVisitor.java318
-rw-r--r--java/src/main/java/io/trygvis/ld/ElfinfoGnuLdListener.java170
-rw-r--r--java/src/main/java/io/trygvis/ld/ElfinfoGnuLdVisitor.java75
-rw-r--r--java/src/main/java/io/trygvis/ld/LdLoader.java121
-rw-r--r--java/src/main/java/io/trygvis/ld/StringGnuLdVisitor.java59
-rw-r--r--kicad.cpp219
-rw-r--r--kicad/.gitignore2
-rw-r--r--kicad/kicad_utils.dcm3
-rw-r--r--kicad/kicad_utils.lib46
-rw-r--r--main.cpp89
-rw-r--r--test-input/lcd3310.net163
26 files changed, 1991 insertions, 0 deletions
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..b661808
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,4 @@
+[*]
+indent_style = space
+indent_size = 4
+trim_trailing_whitespace = true
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3b4f096
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+.idea
+*.iml
+build
+target
+*.tokens
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..914bfb9
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,67 @@
+cmake_minimum_required(VERSION 3.5)
+project(kicad_utils)
+
+find_package(Antlr4)
+antlr4_add_target(TARGET KicadNet LEXER KicadNetLexer.g4 PARSER KicadNetParser.g4 STATIC)
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+
+set(SOURCE_FILES main.cpp kicad.cpp include/trygvis/kicad.h)
+add_executable(kicad_utils ${SOURCE_FILES})
+target_include_directories(kicad_utils PUBLIC include)
+target_link_libraries(kicad_utils KicadNet Antlr4::antlr4_shared)
+target_compile_options(kicad_utils PUBLIC --std=c++14)
+target_compile_options(kicad_utils PUBLIC -Wall -Wextra)
+
+add_custom_target(all_examples)
+
+function(kicad_gen)
+ set(options IN_SOURCE)
+ set(oneValueArgs TARGET NET REF OUTPUT_DIR)
+
+ cmake_parse_arguments(kicad_gen "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ if (NOT kicad_gen_TARGET)
+ message(FATAL_ERROR "TARGET is required")
+ endif ()
+ set(TARGET "${kicad_gen_TARGET}")
+
+ if (NOT kicad_gen_NET)
+ message(FATAL_ERROR "NET is required")
+ endif ()
+ set(NET "${CMAKE_CURRENT_SOURCE_DIR}/${kicad_gen_NET}")
+
+ if (NOT kicad_gen_REF)
+ message(FATAL_ERROR "REF is required")
+ endif ()
+ set(REF "${kicad_gen_REF}")
+
+ if (kicad_gen_OUTPUT_DIR)
+ if (kicad_gen_IN_SOURCE)
+ message(FATAL_ERROR "IN_SOURCE can't be used if OUTPUT_DIR is used")
+ endif ()
+
+ set(OUTPUT_DIR "${kicad_gen_OUTPUT_DIR}")
+ else ()
+ message("IN_SOURCE=${kicad_gen_IN_SOURCE}")
+ if (kicad_gen_IN_SOURCE)
+ set(OUTPUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
+ else ()
+ set(OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}")
+ endif ()
+ endif ()
+
+ set(OUTPUT_FILE "${OUTPUT_DIR}/${TARGET}")
+ message("OUTPUT_FILE=${OUTPUT_FILE}")
+ message("NET=${NET}")
+
+ add_custom_command(OUTPUT ${OUTPUT_FILE}
+ COMMAND kicad_utils -f ${NET} -r ${REF} > kicad-${TARGET}.tmp
+ COMMAND cmake -E make_directory -p ${OUTPUT_DIR}
+ COMMAND cmake -E rename kicad-${TARGET}.tmp ${OUTPUT_FILE}
+ MAIN_DEPENDENCY ${NET}
+ DEPENDS kicad_utils
+ COMMENT "Generating ${TARGET}")
+endfunction()
+
+add_subdirectory(examples)
diff --git a/KicadNetLexer.g4 b/KicadNetLexer.g4
new file mode 100644
index 0000000..55bda85
--- /dev/null
+++ b/KicadNetLexer.g4
@@ -0,0 +1,36 @@
+lexer grammar KicadNetLexer;
+
+LPAREN: '(';
+RPAREN: ')';
+
+QUOTE: '"';
+
+CODE: 'code';
+COMP: 'comp';
+FIELD: 'field';
+NAME: 'name';
+NET: 'net';
+NODE: 'node';
+NUM: 'num';
+PIN: 'pin';
+REF: 'ref';
+TYPE: 'type';
+VALUE: 'value';
+
+
+//STRING: '"' (~[\\"] | '\\' [\\"])* '"';
+STRING: '"' ~["]* '"';
+
+INTEGER: [0-9]+;
+
+ID
+ : [/+~\_\-\.\*/a-zA-Z0-9]+
+ ;
+
+BlockComment
+ : '/*' .*? '*/' -> skip
+ ;
+
+WS
+ : [ \t\r\n]+ -> skip
+ ;
diff --git a/KicadNetParser.g4 b/KicadNetParser.g4
new file mode 100644
index 0000000..dc45c4b
--- /dev/null
+++ b/KicadNetParser.g4
@@ -0,0 +1,72 @@
+parser grammar KicadNetParser;
+
+options {
+ tokenVocab = KicadNetLexer;
+}
+
+file:
+ form+
+ ;
+
+form:
+ name #formName
+ | component #formComponent
+ | field #formField
+ | net #formNet
+ | node #formNode
+ | pinDecl #formDecl
+ | ref #formRef
+ | value #formValue
+ | keyValue #formKeyValue
+ | string #formString
+ ;
+
+code:
+ '(' 'code' INTEGER ')'
+ ;
+
+component:
+ '(' 'comp' ref value keyValue* ')'
+ ;
+
+field:
+ '(' 'field' name string ')'
+ ;
+
+name:
+ '(' 'name' string ')'
+ ;
+
+net:
+ '(' 'net' code name node+ ')'
+ ;
+
+node:
+ '(' 'node' ref pinRef ')'
+ ;
+
+pinRef:
+ '(' 'pin' INTEGER ')'
+ ;
+
+pinDecl:
+ '(' 'pin' '(' 'num' INTEGER ')' '(' 'name' string ')' '(' 'type' string ')' ')'
+ ;
+
+ref:
+ '(' 'ref' string ')'
+ ;
+
+value:
+ '(' 'value' string ')'
+ ;
+
+keyValue:
+ '(' string form* ')'
+ ;
+
+string:
+ ID #stringId
+ | INTEGER #stringInt
+ | STRING #stringText
+ ;
diff --git a/examples/.gitignore b/examples/.gitignore
new file mode 100644
index 0000000..a84bc5f
--- /dev/null
+++ b/examples/.gitignore
@@ -0,0 +1,2 @@
+*.bak
+*-cache.lib
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
new file mode 100644
index 0000000..6f09874
--- /dev/null
+++ b/examples/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(arduino-led)
diff --git a/examples/arduino-led/CMakeLists.txt b/examples/arduino-led/CMakeLists.txt
new file mode 100644
index 0000000..7bd82af
--- /dev/null
+++ b/examples/arduino-led/CMakeLists.txt
@@ -0,0 +1,14 @@
+kicad_gen(
+ TARGET schematic.h
+ NET schematic/arduino-led.net
+ REF U1
+ IN_SOURCE)
+
+if (FALSE)
+ # If you have Arduino support for CMake something like this would work:
+
+ #add_executable(arduino-led arduino-led.ino schematic.h)
+ #target_include_directories(arduino-led PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/kicad-include)
+else ()
+ add_custom_target(arduino-led ALL DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/schematic.h)
+endif ()
diff --git a/examples/arduino-led/arduino-led.ino b/examples/arduino-led/arduino-led.ino
new file mode 100644
index 0000000..01c83ea
--- /dev/null
+++ b/examples/arduino-led/arduino-led.ino
@@ -0,0 +1,13 @@
+#include <stdlib.h>
+#include "Arduino.h"
+#include "schematic.h"
+
+void setup() {
+}
+
+void loop() {
+ digitalWrite(SCHEMATIC_STATUS_LED, HIGH);
+ delay(1000);
+ digitalWrite(SCHEMATIC_STATUS_LED, LOW);
+ delay(1000);
+}
diff --git a/examples/arduino-led/schematic/arduino-led.net b/examples/arduino-led/schematic/arduino-led.net
new file mode 100644
index 0000000..f230aaa
--- /dev/null
+++ b/examples/arduino-led/schematic/arduino-led.net
@@ -0,0 +1,166 @@
+(export (version D)
+ (design
+ (source /home/trygvis/dev/io.trygvis/2016/07/kicad-utils/examples/arduino+led/schematic/arduino+led.sch)
+ (date "Mon 25 Jul 2016 19:16:49 CEST")
+ (tool "Eeschema 4.0.2+dfsg1-stable")
+ (sheet (number 1) (name /) (tstamps /)
+ (title_block
+ (title)
+ (company)
+ (rev)
+ (date)
+ (source arduino+led.sch)
+ (comment (number 1) (value ""))
+ (comment (number 2) (value ""))
+ (comment (number 3) (value ""))
+ (comment (number 4) (value "")))))
+ (components
+ (comp (ref U1)
+ (value ARDUINO_UNO)
+ (libsource (lib kicad_utils) (part ARDUINO_UNO))
+ (sheetpath (names /) (tstamps /))
+ (tstamp 57913050))
+ (comp (ref R1)
+ (value R)
+ (libsource (lib device) (part R))
+ (sheetpath (names /) (tstamps /))
+ (tstamp 579130F0))
+ (comp (ref D1)
+ (value LED)
+ (libsource (lib device) (part LED))
+ (sheetpath (names /) (tstamps /))
+ (tstamp 5791311D)))
+ (libparts
+ (libpart (lib kicad_utils) (part ARDUINO_UNO)
+ (fields
+ (field (name Reference) U)
+ (field (name Value) ARDUINO_UNO))
+ (pins
+ (pin (num 1) (name ~RST) (type input))
+ (pin (num 2) (name 3V3) (type input))
+ (pin (num 3) (name 5V) (type input))
+ (pin (num 4) (name GND) (type input))
+ (pin (num 5) (name GND) (type input))
+ (pin (num 6) (name Vin) (type input))
+ (pin (num 7) (name A0) (type input))
+ (pin (num 8) (name A1) (type input))
+ (pin (num 9) (name A2) (type input))
+ (pin (num 10) (name A3) (type input))
+ (pin (num 11) (name A4) (type power_out))
+ (pin (num 12) (name A5) (type input))
+ (pin (num 13) (name D0) (type input))
+ (pin (num 14) (name D1) (type input))
+ (pin (num 15) (name D2) (type input))
+ (pin (num 16) (name D3) (type input))
+ (pin (num 17) (name D4) (type input))
+ (pin (num 18) (name D5) (type input))
+ (pin (num 19) (name D6) (type input))
+ (pin (num 20) (name D7) (type input))
+ (pin (num 21) (name D8) (type input))
+ (pin (num 22) (name D9) (type input))
+ (pin (num 23) (name D10) (type input))
+ (pin (num 24) (name D11) (type input))
+ (pin (num 25) (name D12) (type input))
+ (pin (num 26) (name D13) (type input))
+ (pin (num 27) (name GND) (type input))
+ (pin (num 28) (name Aref) (type input))
+ (pin (num 29) (name SDA) (type input))
+ (pin (num 30) (name SCL) (type input))))
+ (libpart (lib device) (part LED)
+ (footprints
+ (fp LED-3MM)
+ (fp LED-5MM)
+ (fp LED-10MM)
+ (fp LED-0603)
+ (fp LED-0805)
+ (fp LED-1206)
+ (fp LEDV))
+ (fields
+ (field (name Reference) D)
+ (field (name Value) LED))
+ (pins
+ (pin (num 1) (name K) (type passive))
+ (pin (num 2) (name A) (type passive))))
+ (libpart (lib device) (part R)
+ (description Resistor)
+ (footprints
+ (fp R_*)
+ (fp Resistor_*))
+ (fields
+ (field (name Reference) R)
+ (field (name Value) R))
+ (pins
+ (pin (num 1) (name ~) (type passive))
+ (pin (num 2) (name ~) (type passive)))))
+ (libraries
+ (library (logical device)
+ (uri /usr/share/kicad/library/device.lib))
+ (library (logical kicad_utils)
+ (uri /home/trygvis/dev/io.trygvis/2016/07/kicad-utils/kicad/kicad_utils.lib)))
+ (nets
+ (net (code 1) (name "Net-(U1-Pad25)")
+ (node (ref U1) (pin 25)))
+ (net (code 2) (name "Net-(U1-Pad26)")
+ (node (ref U1) (pin 26)))
+ (net (code 3) (name "Net-(U1-Pad17)")
+ (node (ref U1) (pin 17)))
+ (net (code 4) (name "Net-(U1-Pad27)")
+ (node (ref U1) (pin 27)))
+ (net (code 5) (name "Net-(U1-Pad18)")
+ (node (ref U1) (pin 18)))
+ (net (code 6) (name "Net-(U1-Pad28)")
+ (node (ref U1) (pin 28)))
+ (net (code 7) (name "Net-(U1-Pad19)")
+ (node (ref U1) (pin 19)))
+ (net (code 8) (name "Net-(U1-Pad29)")
+ (node (ref U1) (pin 29)))
+ (net (code 9) (name "Net-(U1-Pad15)")
+ (node (ref U1) (pin 15)))
+ (net (code 10) (name GND)
+ (node (ref D1) (pin 1)))
+ (net (code 11) (name "Net-(D1-Pad2)")
+ (node (ref D1) (pin 2))
+ (node (ref R1) (pin 2)))
+ (net (code 12) (name /STATUS_LED)
+ (node (ref U1) (pin 16))
+ (node (ref R1) (pin 1)))
+ (net (code 13) (name "Net-(U1-Pad20)")
+ (node (ref U1) (pin 20)))
+ (net (code 14) (name "Net-(U1-Pad2)")
+ (node (ref U1) (pin 2)))
+ (net (code 15) (name "Net-(U1-Pad3)")
+ (node (ref U1) (pin 3)))
+ (net (code 16) (name "Net-(U1-Pad4)")
+ (node (ref U1) (pin 4)))
+ (net (code 17) (name "Net-(U1-Pad5)")
+ (node (ref U1) (pin 5)))
+ (net (code 18) (name "Net-(U1-Pad6)")
+ (node (ref U1) (pin 6)))
+ (net (code 19) (name "Net-(U1-Pad7)")
+ (node (ref U1) (pin 7)))
+ (net (code 20) (name "Net-(U1-Pad8)")
+ (node (ref U1) (pin 8)))
+ (net (code 21) (name "Net-(U1-Pad9)")
+ (node (ref U1) (pin 9)))
+ (net (code 22) (name "Net-(U1-Pad10)")
+ (node (ref U1) (pin 10)))
+ (net (code 23) (name "Net-(U1-Pad1)")
+ (node (ref U1) (pin 1)))
+ (net (code 24) (name "Net-(U1-Pad30)")
+ (node (ref U1) (pin 30)))
+ (net (code 25) (name "Net-(U1-Pad11)")
+ (node (ref U1) (pin 11)))
+ (net (code 26) (name "Net-(U1-Pad21)")
+ (node (ref U1) (pin 21)))
+ (net (code 27) (name "Net-(U1-Pad12)")
+ (node (ref U1) (pin 12)))
+ (net (code 28) (name "Net-(U1-Pad22)")
+ (node (ref U1) (pin 22)))
+ (net (code 29) (name "Net-(U1-Pad13)")
+ (node (ref U1) (pin 13)))
+ (net (code 30) (name "Net-(U1-Pad23)")
+ (node (ref U1) (pin 23)))
+ (net (code 31) (name "Net-(U1-Pad14)")
+ (node (ref U1) (pin 14)))
+ (net (code 32) (name "Net-(U1-Pad24)")
+ (node (ref U1) (pin 24))))) \ No newline at end of file
diff --git a/examples/arduino-led/schematic/arduino-led.pro b/examples/arduino-led/schematic/arduino-led.pro
new file mode 100644
index 0000000..e707bbb
--- /dev/null
+++ b/examples/arduino-led/schematic/arduino-led.pro
@@ -0,0 +1,61 @@
+update=Mon 25 Jul 2016 19:13:30 CEST
+version=1
+last_client=kicad
+[pcbnew]
+version=1
+LastNetListRead=
+UseCmpFile=1
+PadDrill=0.600000000000
+PadDrillOvalY=0.600000000000
+PadSizeH=1.500000000000
+PadSizeV=1.500000000000
+PcbTextSizeV=1.500000000000
+PcbTextSizeH=1.500000000000
+PcbTextThickness=0.300000000000
+ModuleTextSizeV=1.000000000000
+ModuleTextSizeH=1.000000000000
+ModuleTextSizeThickness=0.150000000000
+SolderMaskClearance=0.000000000000
+SolderMaskMinWidth=0.000000000000
+DrawSegmentWidth=0.200000000000
+BoardOutlineThickness=0.100000000000
+ModuleOutlineThickness=0.150000000000
+[cvpcb]
+version=1
+NetIExt=net
+[general]
+version=1
+[eeschema]
+version=1
+LibDir=../../../kicad
+[eeschema/libraries]
+LibName1=power
+LibName2=device
+LibName3=transistors
+LibName4=conn
+LibName5=linear
+LibName6=regul
+LibName7=74xx
+LibName8=cmos4000
+LibName9=adc-dac
+LibName10=memory
+LibName11=xilinx
+LibName12=microcontrollers
+LibName13=dsp
+LibName14=microchip
+LibName15=analog_switches
+LibName16=motorola
+LibName17=texas
+LibName18=intel
+LibName19=audio
+LibName20=interface
+LibName21=digital-audio
+LibName22=philips
+LibName23=display
+LibName24=cypress
+LibName25=siliconi
+LibName26=opto
+LibName27=atmel
+LibName28=contrib
+LibName29=valves
+LibName30=kicad_utils
diff --git a/examples/arduino-led/schematic/arduino-led.sch b/examples/arduino-led/schematic/arduino-led.sch
new file mode 100644
index 0000000..642cd4b
--- /dev/null
+++ b/examples/arduino-led/schematic/arduino-led.sch
@@ -0,0 +1,101 @@
+EESchema Schematic File Version 2
+LIBS:power
+LIBS:device
+LIBS:transistors
+LIBS:conn
+LIBS:linear
+LIBS:regul
+LIBS:74xx
+LIBS:cmos4000
+LIBS:adc-dac
+LIBS:memory
+LIBS:xilinx
+LIBS:microcontrollers
+LIBS:dsp
+LIBS:microchip
+LIBS:analog_switches
+LIBS:motorola
+LIBS:texas
+LIBS:intel
+LIBS:audio
+LIBS:interface
+LIBS:digital-audio
+LIBS:philips
+LIBS:display
+LIBS:cypress
+LIBS:siliconi
+LIBS:opto
+LIBS:atmel
+LIBS:contrib
+LIBS:valves
+LIBS:kicad_utils
+LIBS:arduino+mod-lcd3310-cache
+EELAYER 25 0
+EELAYER END
+$Descr A4 11693 8268
+encoding utf-8
+Sheet 1 1
+Title ""
+Date ""
+Rev ""
+Comp ""
+Comment1 ""
+Comment2 ""
+Comment3 ""
+Comment4 ""
+$EndDescr
+$Comp
+L ARDUINO_UNO U1
+U 1 1 57913050
+P 5250 3750
+F 0 "U1" H 5250 3750 60 0000 C CNN
+F 1 "ARDUINO_UNO" H 5250 3850 60 0000 C CNN
+F 2 "" H 5250 3750 60 0000 C CNN
+F 3 "" H 5250 3750 60 0000 C CNN
+ 1 5250 3750
+ 1 0 0 -1
+$EndComp
+$Comp
+L GND #PWR1
+U 1 1 579130D3
+P 7100 5200
+F 0 "#PWR1" H 7100 4950 50 0001 C CNN
+F 1 "GND" H 7100 5050 50 0000 C CNN
+F 2 "" H 7100 5200 50 0000 C CNN
+F 3 "" H 7100 5200 50 0000 C CNN
+ 1 7100 5200
+ 1 0 0 -1
+$EndComp
+Wire Wire Line
+ 6000 4050 7100 4050
+Wire Wire Line
+ 7100 4050 7100 4150
+$Comp
+L R R1
+U 1 1 579130F0
+P 7100 4300
+F 0 "R1" V 7180 4300 50 0000 C CNN
+F 1 "R" V 7100 4300 50 0000 C CNN
+F 2 "" V 7030 4300 50 0000 C CNN
+F 3 "" H 7100 4300 50 0000 C CNN
+ 1 7100 4300
+ 1 0 0 -1
+$EndComp
+$Comp
+L LED D1
+U 1 1 5791311D
+P 7100 4750
+F 0 "D1" H 7100 4850 50 0000 C CNN
+F 1 "LED" H 7100 4650 50 0000 C CNN
+F 2 "" H 7100 4750 50 0000 C CNN
+F 3 "" H 7100 4750 50 0000 C CNN
+ 1 7100 4750
+ 0 -1 -1 0
+$EndComp
+Wire Wire Line
+ 7100 4450 7100 4550
+Wire Wire Line
+ 7100 4950 7100 5200
+Text Label 6400 4050 0 60 ~ 0
+STATUS_LED
+$EndSCHEMATC
diff --git a/include/trygvis/kicad.h b/include/trygvis/kicad.h
new file mode 100644
index 0000000..4cff944
--- /dev/null
+++ b/include/trygvis/kicad.h
@@ -0,0 +1,80 @@
+#pragma once
+
+#include <string>
+#include <vector>
+#include <stdexcept>
+#include <experimental/optional>
+
+namespace trygvis {
+namespace kicad {
+
+template<typename T>
+using opt = std::experimental::optional<T>;
+
+class component {
+public:
+ std::string ref;
+ std::string value;
+
+ component(const std::string &ref, const std::string &value) : ref(ref), value(value) { }
+};
+
+struct pin {
+ int num;
+ std::string name;
+ std::string type;
+};
+
+struct part {
+ std::vector<pin> pins;
+};
+
+class node {
+public:
+ std::string ref;
+ int pin;
+
+ node(const std::string &ref, int pin) : ref(ref), pin(pin) { }
+};
+
+class net {
+public:
+ int code;
+ std::string name;
+ std::vector<node> nodes;
+
+ net(int code, const std::string &name, const std::vector<node> &nodes) : code(code), name(name), nodes(nodes) { }
+};
+
+struct netlist {
+ std::vector<component> components;
+ std::vector<part> parts;
+ std::vector<net> nets;
+
+ opt<const component *> find_component(std::string ref) const;
+};
+
+class kicad_parse_exception : public std::runtime_error {
+public:
+ explicit kicad_parse_exception(const std::vector<std::string> &messages) :
+ runtime_error("Parse error"), messages(messages) { }
+
+ const std::vector<std::string> messages;
+};
+
+class kicad_net_loader {
+public:
+ kicad_net_loader();
+
+ virtual ~kicad_net_loader();
+
+ netlist load(std::string path);
+
+ void setDebug(bool debug);
+
+private:
+ bool debug_;
+};
+
+} // namespace kicad
+} // namespace trygvis
diff --git a/java/pom.xml b/java/pom.xml
new file mode 100644
index 0000000..4821b17
--- /dev/null
+++ b/java/pom.xml
@@ -0,0 +1,87 @@
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>io.trygvis.kicad</groupId>
+ <artifactId>kicad-utils</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <dependencies>
+ <dependency>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4</artifactId>
+ <version>${antlr4-runtime.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4-runtime</artifactId>
+ <version>${antlr4-runtime.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ <version>3.0.1</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <properties>
+ <antlr4-runtime.version>4.5.3</antlr4-runtime.version>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4-maven-plugin</artifactId>
+ <version>${antlr4-runtime.version}</version>
+ <executions>
+ <execution>
+ <id>gnu</id>
+ <goals>
+ <goal>antlr4</goal>
+ </goals>
+ <configuration>
+ <arguments>
+ <argument>-package</argument>
+ <argument>io.trygvis.ld.antlr</argument>
+ </arguments>
+ <includes>
+ <include>GnuLd*.g4</include>
+ </includes>
+ <sourceDirectory>.</sourceDirectory>
+ <outputDirectory>target/generated-sources/antlr4/io/trygvis/ld/antlr</outputDirectory>
+ </configuration>
+ </execution>
+ <execution>
+ <id>test1</id>
+ <goals>
+ <goal>antlr4</goal>
+ </goals>
+ <configuration>
+ <arguments>
+ <argument>-package</argument>
+ <argument>io.trygvis.ld.test1</argument>
+ </arguments>
+ <includes>
+ <include>**/Test1*.g4</include>
+ </includes>
+ <outputDirectory>target/generated-sources/antlr4/io/trygvis/ld/test1</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ <configuration>
+ <visitor>true</visitor>
+ <outputDirectory>target/generated-sources/antlr4</outputDirectory>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/java/src/main/java/io/trygvis/ld/CollectingErrorListener.java b/java/src/main/java/io/trygvis/ld/CollectingErrorListener.java
new file mode 100644
index 0000000..968a02b
--- /dev/null
+++ b/java/src/main/java/io/trygvis/ld/CollectingErrorListener.java
@@ -0,0 +1,17 @@
+package io.trygvis.ld;
+
+import org.antlr.v4.runtime.BaseErrorListener;
+import org.antlr.v4.runtime.RecognitionException;
+import org.antlr.v4.runtime.Recognizer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CollectingErrorListener extends BaseErrorListener {
+ public final List<String> errors = new ArrayList<>();
+
+ public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
+ String s = line + ":" + charPositionInLine + " " + msg;
+ errors.add(s);
+ }
+}
diff --git a/java/src/main/java/io/trygvis/ld/ElfinfoExprVisitor.java b/java/src/main/java/io/trygvis/ld/ElfinfoExprVisitor.java
new file mode 100644
index 0000000..af5bea5
--- /dev/null
+++ b/java/src/main/java/io/trygvis/ld/ElfinfoExprVisitor.java
@@ -0,0 +1,318 @@
+package io.trygvis.ld;
+
+import io.trygvis.ld.antlr.GnuLdParser;
+import io.trygvis.ld.antlr.GnuLdParserBaseVisitor;
+import org.antlr.v4.runtime.tree.ParseTreeProperty;
+
+import java.math.BigInteger;
+
+class ElfinfoExprVisitor extends GnuLdParserBaseVisitor<ElfinfoExprVisitor> {
+ private BigInteger value;
+ private ParseTreeProperty<BigInteger> es = new ParseTreeProperty<>();
+
+ public static BigInteger evaluate(GnuLdParser.Mustbe_expContext ctx) {
+ ElfinfoExprVisitor v = new ElfinfoExprVisitor();
+ v.visitMustbe_exp(ctx);
+ return v.value();
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpLt(GnuLdParser.ExpLtContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpBlock(GnuLdParser.ExpBlockContext ctx) {
+ return visitChildren(ctx);
+
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpAbsolute(GnuLdParser.ExpAbsoluteContext ctx) {
+ return visitChildren(ctx);
+
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpLog2ceil(GnuLdParser.ExpLog2ceilContext ctx) {
+ return visitChildren(ctx);
+
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpAddr(GnuLdParser.ExpAddrContext ctx) {
+ return visitChildren(ctx);
+
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpDataSegmentEnd(GnuLdParser.ExpDataSegmentEndContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpSub(GnuLdParser.ExpSubContext ctx) {
+ System.out.println("ElfinfoExprVisitor.visitExpSub");
+
+ ElfinfoExprVisitor ret = visitChildren(ctx);
+ BigInteger a = es.removeFrom(ctx.exp(0));
+ BigInteger b = es.removeFrom(ctx.exp(1));
+
+ BigInteger x = a.subtract(b);
+
+ es.put(ctx, x);
+ return ret;
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpDefined(GnuLdParser.ExpDefinedContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpMod(GnuLdParser.ExpModContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpInvert(GnuLdParser.ExpInvertContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpAlign(GnuLdParser.ExpAlignContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpMul(GnuLdParser.ExpMulContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpAnd(GnuLdParser.ExpAndContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpXor(GnuLdParser.ExpXorContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpParen(GnuLdParser.ExpParenContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpMinus(GnuLdParser.ExpMinusContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpDiv(GnuLdParser.ExpDivContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpGe(GnuLdParser.ExpGeContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpMin(GnuLdParser.ExpMinContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpAlignK(GnuLdParser.ExpAlignKContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpNegate(GnuLdParser.ExpNegateContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpName(GnuLdParser.ExpNameContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpOr(GnuLdParser.ExpOrContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpTrinary(GnuLdParser.ExpTrinaryContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpOror(GnuLdParser.ExpOrorContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpDataSegmentAlign(GnuLdParser.ExpDataSegmentAlignContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpLengthExp(GnuLdParser.ExpLengthExpContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpAdd(GnuLdParser.ExpAddContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpLoadaddr(GnuLdParser.ExpLoadaddrContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpGt(GnuLdParser.ExpGtContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpOrigin(GnuLdParser.ExpOriginContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpEq(GnuLdParser.ExpEqContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpMax(GnuLdParser.ExpMaxContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpLshift(GnuLdParser.ExpLshiftContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpSizeofHeaders(GnuLdParser.ExpSizeofHeadersContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpLe(GnuLdParser.ExpLeContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpNe(GnuLdParser.ExpNeContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpAndand(GnuLdParser.ExpAndandContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpRshift(GnuLdParser.ExpRshiftContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpNextParen(GnuLdParser.ExpNextParenContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpAlignof(GnuLdParser.ExpAlignofContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpSegmentStart(GnuLdParser.ExpSegmentStartContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpInt(GnuLdParser.ExpIntContext ctx) {
+ System.out.println("ElfinfoExprVisitor.visitExpInt");
+
+ BigInteger i = parseInt(ctx.INT().getText());
+ es.put(ctx, i);
+
+ return this;
+ }
+
+ public static BigInteger parseInt(String str) {
+ str = str.toLowerCase();
+ int base = 10;
+ if (str.startsWith("0x")) {
+ base = 16;
+ str = str.substring(2);
+ }
+
+ int factor = 1;
+ if (str.endsWith("k")) {
+ factor = 1024;
+ str = str.substring(0, str.length() - 1);
+ } else if (str.endsWith("k")) {
+ factor = 1024 * 1024;
+ str = str.substring(0, str.length() - 1);
+ }
+
+ BigInteger i = new BigInteger(str, base);
+ if (factor > 1) {
+ i = i.multiply(BigInteger.valueOf(factor));
+ }
+ return i;
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpConstant(GnuLdParser.ExpConstantContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpPlus(GnuLdParser.ExpPlusContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpSizeof(GnuLdParser.ExpSizeofContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpDataSegmentRelRoEnd(GnuLdParser.ExpDataSegmentRelRoEndContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitExpAssert(GnuLdParser.ExpAssertContext ctx) {
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoExprVisitor visitMustbe_exp(GnuLdParser.Mustbe_expContext ctx) {
+ ElfinfoExprVisitor ret = visitChildren(ctx);
+
+ value = es.removeFrom(ctx.exp());
+ es.put(ctx, value);
+
+ return ret;
+ }
+
+ public BigInteger value() {
+ if (value != null) {
+ return value;
+ }
+
+ throw new RuntimeException("Something bad happened, probably an unevaluated expression part.");
+ }
+}
diff --git a/java/src/main/java/io/trygvis/ld/ElfinfoGnuLdListener.java b/java/src/main/java/io/trygvis/ld/ElfinfoGnuLdListener.java
new file mode 100644
index 0000000..fe40547
--- /dev/null
+++ b/java/src/main/java/io/trygvis/ld/ElfinfoGnuLdListener.java
@@ -0,0 +1,170 @@
+package io.trygvis.ld;
+
+import io.trygvis.ld.antlr.GnuLdParser;
+import io.trygvis.ld.antlr.GnuLdParserBaseListener;
+import org.antlr.v4.runtime.tree.ParseTreeProperty;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+class ElfinfoGnuLdListener extends GnuLdParserBaseListener {
+ public List<LdLoader.MemoryArea> memoryAreas = new ArrayList<>();
+
+ private final ParseTreeProperty<BigInteger> expr = new ParseTreeProperty<>();
+
+ @Override
+ public void exitExpInt(GnuLdParser.ExpIntContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.exitExpInt: ctx.INT().getText() = " + ctx.INT().getText());
+ expr.put(ctx, ElfinfoExprVisitor.parseInt(ctx.INT().getText()));
+ }
+
+ @Override
+ public void exitExpSub(GnuLdParser.ExpSubContext ctx) {
+ BigInteger a = expr.get(ctx.exp(0));
+ BigInteger b = expr.get(ctx.exp(1));
+ BigInteger x = a.subtract(b);
+ expr.put(ctx, x);
+ }
+
+ @Override
+ public void exitExpAdd(GnuLdParser.ExpAddContext ctx) {
+ BigInteger a = expr.get(ctx.exp(0));
+ BigInteger b = expr.get(ctx.exp(1));
+ BigInteger x = a.add(b);
+ expr.put(ctx, x);
+ }
+
+ @Override
+ public void exitExpName(GnuLdParser.ExpNameContext ctx) {
+ expr.put(ctx, BigInteger.ZERO);
+ }
+
+ @Override
+ public void exitExpAddr(GnuLdParser.ExpAddrContext ctx) {
+ expr.put(ctx, BigInteger.ZERO);
+ }
+
+ @Override
+ public void exitExpSizeof(GnuLdParser.ExpSizeofContext ctx) {
+ expr.put(ctx, BigInteger.ZERO);
+ }
+
+ @Override
+ public void exitExpLengthExp(GnuLdParser.ExpLengthExpContext ctx) {
+ LdLoader.MemoryArea ma = getMemoryArea(ctx.NAME().getText());
+// System.out.println("ma.length = " + ma.length);
+ expr.put(ctx, ma.length);
+ }
+
+ @Override
+ public void exitExpOrigin(GnuLdParser.ExpOriginContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.exitExpOrigin: " + ctx.getText());
+ LdLoader.MemoryArea ma = getMemoryArea(ctx.NAME().getText());
+// System.out.println("ma.origin = " + ma.origin);
+ expr.put(ctx, ma.origin);
+ }
+
+ private LdLoader.MemoryArea getMemoryArea(String name) {
+ LdLoader.MemoryArea m = null;
+ for (LdLoader.MemoryArea ma : memoryAreas) {
+ if (ma.name.equals(name)) {
+ m = ma;
+ }
+ }
+ if (m == null) {
+ throw new RuntimeException("No such memory area: " + name);
+ }
+ return m;
+ }
+
+ @Override
+ public void enterMustbe_exp(GnuLdParser.Mustbe_expContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.enterMustbe_exp");
+ }
+
+ @Override
+ public void exitMustbe_exp(GnuLdParser.Mustbe_expContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.exitMustbe_exp");
+
+ expr.put(ctx, expr.get(ctx.exp()));
+ }
+
+
+ @Override
+ public void enterOrigin_spec(GnuLdParser.Origin_specContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.enterOrigin_spec");
+ }
+
+ @Override
+ public void exitOrigin_spec(GnuLdParser.Origin_specContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.exitOrigin_spec");
+ }
+
+ @Override
+ public void enterLength_spec(GnuLdParser.Length_specContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.enterLength_spec");
+ }
+
+ @Override
+ public void exitLength_spec(GnuLdParser.Length_specContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.exitLength_spec");
+ }
+
+ @Override
+ public void enterMemory_spec(GnuLdParser.Memory_specContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.enterMemory_spec");
+ }
+
+ @Override
+ public void exitMemory_spec(GnuLdParser.Memory_specContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.exitMemory_spec");
+ LdLoader.MemoryArea ma = new LdLoader.MemoryArea();
+ ma.name = ctx.NAME().getText();
+ ma.attributes = attributes;
+// System.out.println("ctx.origin_spec() = " + ctx.origin_spec());
+ ma.origin = expr.get(ctx.origin_spec().mustbe_exp());
+ ma.length = expr.get(ctx.length_spec().mustbe_exp());
+ System.out.println(ma);
+ memoryAreas.add(ma);
+ }
+
+ LdLoader.MemoryAttribute attribute;
+ boolean attributesInverted;
+ Set<LdLoader.MemoryAttribute> attributes;
+
+ @Override
+ public void exitAttributes_opt(GnuLdParser.Attributes_optContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.exitAttributes_opt");
+ attributes = new HashSet<>();
+ }
+
+ @Override
+ public void enterAttributeInverted(GnuLdParser.AttributeInvertedContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.enterAttributeInverted");
+
+ if (!attributes.isEmpty()) {
+ throw new RuntimeException("Attributes for memory areas can only be attributesInverted (with '!') as the first character in a specification; foo(!rw), not foo(x!rw).");
+ }
+// String name = ctx.name().getText();
+ String name = ctx.NAME().getText();
+// System.out.println("ctx.ATTRIBUTE().getText() = " + name);
+
+ attributesInverted = true;
+ }
+
+ @Override
+ public void enterAttributeNormal(GnuLdParser.AttributeNormalContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.enterAttributeNormal");
+
+ String name = ctx.NAME().getText();
+// System.out.println("ctx.ATTRIBUTE().getText() = " + name);
+ for (int i = 0; i < name.length(); i++) {
+ attribute = LdLoader.MemoryAttribute.valueOf(String.valueOf(Character.toUpperCase(name.charAt(i))));
+ attributes.add(attribute);
+ }
+ attributesInverted = false;
+ }
+}
diff --git a/java/src/main/java/io/trygvis/ld/ElfinfoGnuLdVisitor.java b/java/src/main/java/io/trygvis/ld/ElfinfoGnuLdVisitor.java
new file mode 100644
index 0000000..3062aad
--- /dev/null
+++ b/java/src/main/java/io/trygvis/ld/ElfinfoGnuLdVisitor.java
@@ -0,0 +1,75 @@
+package io.trygvis.ld;
+
+import io.trygvis.ld.antlr.GnuLdParser;
+import io.trygvis.ld.antlr.GnuLdParserBaseVisitor;
+import org.antlr.v4.runtime.tree.ParseTreeProperty;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class ElfinfoGnuLdVisitor extends GnuLdParserBaseVisitor<ElfinfoGnuLdVisitor> {
+ public List<LdLoader.MemoryArea> memoryAreas = new ArrayList<>();
+
+ ParseTreeProperty<BigInteger> es = new ParseTreeProperty<>();
+
+ @Override
+ public ElfinfoGnuLdVisitor visitMemory_spec(GnuLdParser.Memory_specContext ctx) {
+ System.out.println("ElfinfoGnuLdBaseVisitor.visitMemory_spec");
+ visitChildren(ctx);
+
+ if (attributesInverted) {
+ // not quite sure how this is supposed to work yet
+ throw new RuntimeException("Inverted memory region attributes is not implemented yet.");
+ }
+
+ LdLoader.MemoryArea ma = new LdLoader.MemoryArea();
+ ma.name = ctx.NAME().getText();
+ ma.attributes = attributes;
+ ma.origin = ElfinfoExprVisitor.evaluate(ctx.origin_spec().mustbe_exp());
+ ma.length = ElfinfoExprVisitor.evaluate(ctx.length_spec().mustbe_exp());
+ System.out.println(ma);
+ memoryAreas.add(ma);
+ return this;
+ }
+
+ LdLoader.MemoryAttribute attribute;
+ boolean attributesInverted;
+ Set<LdLoader.MemoryAttribute> attributes;
+
+ @Override
+ public ElfinfoGnuLdVisitor visitAttributes_opt(GnuLdParser.Attributes_optContext ctx) {
+ System.out.println("ElfinfoGnuLdBaseVisitor.visitAttributes_opt");
+ attributes = new HashSet<>();
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoGnuLdVisitor visitAttributeNormal(GnuLdParser.AttributeNormalContext ctx) {
+ System.out.println("ElfinfoGnuLdBaseVisitor.visitAttributeNormal");
+ String name = ctx.NAME().getText();
+ System.out.println("ctx.ATTRIBUTE().getText() = " + name);
+ for (int i = 0; i < name.length(); i++) {
+ attribute = LdLoader.MemoryAttribute.valueOf(String.valueOf(Character.toUpperCase(name.charAt(i))));
+ attributes.add(attribute);
+ }
+ attributesInverted = false;
+ return visitChildren(ctx);
+ }
+
+ @Override
+ public ElfinfoGnuLdVisitor visitAttributeInverted(GnuLdParser.AttributeInvertedContext ctx) {
+ System.out.println("ElfinfoGnuLdBaseVisitor.visitAttributeInverted");
+ if (!attributes.isEmpty()) {
+ throw new RuntimeException("Attributes for memory areas can only be attributesInverted (with '!') as the first character in a specification; foo(!rw), not foo(x!rw).");
+ }
+// String name = ctx.name().getText();
+ String name = ctx.NAME().getText();
+ System.out.println("ctx.ATTRIBUTE().getText() = " + name);
+
+ attributesInverted = true;
+ return visitChildren(ctx);
+ }
+}
diff --git a/java/src/main/java/io/trygvis/ld/LdLoader.java b/java/src/main/java/io/trygvis/ld/LdLoader.java
new file mode 100644
index 0000000..0b71720
--- /dev/null
+++ b/java/src/main/java/io/trygvis/ld/LdLoader.java
@@ -0,0 +1,121 @@
+package io.trygvis.ld;
+
+import io.trygvis.ld.antlr.GnuLdLexer;
+import io.trygvis.ld.antlr.GnuLdParser;
+import org.antlr.v4.runtime.ANTLRFileStream;
+import org.antlr.v4.runtime.BufferedTokenStream;
+import org.antlr.v4.runtime.ConsoleErrorListener;
+
+import java.io.File;
+import java.math.BigInteger;
+import java.util.List;
+import java.util.Set;
+
+public class LdLoader {
+
+ public final List<MemoryArea> memoryAreas;
+
+ public LdLoader(List<MemoryArea> memoryAreas) {
+ this.memoryAreas = memoryAreas;
+ }
+
+ public enum MemoryAttribute {
+ R, W, X, A, I,
+ }
+
+ public static class MemoryArea {
+ private final BigInteger MEGA = BigInteger.valueOf(1024 * 1024);
+ private final BigInteger KILO = BigInteger.valueOf(1024);
+
+ String name;
+ BigInteger origin;
+ BigInteger length;
+ Set<MemoryAttribute> attributes;
+
+ @Override
+ public String toString() {
+ return "MemoryArea{" +
+ "name='" + name + '\'' +
+ ", origin=" + origin +
+ ", length=" + length +
+ ", attributes='" + attributes + '\'' +
+ '}';
+ }
+
+ public String prettyOrigin() {
+ if (origin == null) {
+ return "";
+ }
+ String hex = origin.toString(16);
+
+ return "0x" + ("00000000").substring(0, 8 - hex.length()) + hex;
+ }
+
+ public String prettyLength() {
+ if (length == null) {
+ return "";
+ }
+
+ if (length.compareTo(MEGA) >= 0 && length.mod(MEGA).equals(BigInteger.ZERO)) {
+ return length.divide(MEGA) + "M";
+ }
+
+ if (length.compareTo(KILO) >= 0 && length.mod(KILO).equals(BigInteger.ZERO)) {
+ return length.divide(KILO) + "k";
+ }
+
+ return String.valueOf(length);
+ }
+
+ public String prettyAttributes() {
+ String s = "";
+ for (MemoryAttribute attribute : attributes) {
+ s += attribute.name().toLowerCase();
+ }
+ return s;
+ }
+ }
+
+ public static LdLoader load(File path) throws Exception {
+ GnuLdLexer lexer = new GnuLdLexer(new ANTLRFileStream(path.getAbsolutePath()));
+ BufferedTokenStream tokens = new BufferedTokenStream(lexer);
+ GnuLdParser parser = new GnuLdParser(tokens);
+ parser.setBuildParseTree(true);
+ parser.removeErrorListeners();
+ ConsoleErrorListener errorListener = new ConsoleErrorListener();
+ parser.addErrorListener(errorListener);
+ CollectingErrorListener collectingErrorListener = new CollectingErrorListener();
+ parser.addErrorListener(collectingErrorListener);
+
+ ElfinfoGnuLdListener listener = new ElfinfoGnuLdListener();
+ parser.addParseListener(listener);
+
+ GnuLdParser.FileContext file = parser.file();
+
+ if (parser.getNumberOfSyntaxErrors() > 0) {
+ throw new ParseErrorException(lexer, tokens, parser, collectingErrorListener.errors
+ );
+ }
+
+// ElfinfoGnuLdVisitor visitor = new ElfinfoGnuLdVisitor();
+// visitor.visit(file);
+
+// return new LdLoader(visitor.memoryAreas);
+ return new LdLoader(listener.memoryAreas);
+ }
+
+ public static class ParseErrorException extends Exception {
+ public final GnuLdLexer lexer;
+ public final BufferedTokenStream tokens;
+ public final GnuLdParser parser;
+ public final List<String> errors;
+
+ public ParseErrorException(GnuLdLexer lexer, BufferedTokenStream tokens, GnuLdParser parser, List<String> errors) {
+ this.lexer = lexer;
+ this.tokens = tokens;
+ this.parser = parser;
+ this.errors = errors;
+ }
+ }
+
+}
diff --git a/java/src/main/java/io/trygvis/ld/StringGnuLdVisitor.java b/java/src/main/java/io/trygvis/ld/StringGnuLdVisitor.java
new file mode 100644
index 0000000..a975497
--- /dev/null
+++ b/java/src/main/java/io/trygvis/ld/StringGnuLdVisitor.java
@@ -0,0 +1,59 @@
+package io.trygvis.ld;
+
+import io.trygvis.ld.antlr.GnuLdParserBaseVisitor;
+import io.trygvis.ld.antlr.GnuLdParser;
+import org.antlr.v4.runtime.tree.ParseTree;
+
+import java.util.List;
+
+class StringGnuLdVisitor extends GnuLdParserBaseVisitor<String> {
+
+// public static String parseName(GnuLdParser.NameContext ctx) {
+// return "";
+// }
+
+ /*
+ public static String parseName(GnuLdParser.NameContext ctx) {
+ StringGnuLdVisitor v = new StringGnuLdVisitor();
+ return v.visit(ctx);
+ }
+
+ private StringBuilder string = new StringBuilder();
+
+ @Override
+ public String visitNamePlain(GnuLdParser.NamePlainContext ctx) {
+ System.out.println("NameTest.visitNamePlain");
+ String s = ctx.NAME().getText();
+ string.append(s);
+ return s;
+ }
+
+// @Override
+// public String visitName_or_space(GnuLdParser.Name_or_spaceContext ctx) {
+// System.out.println("StringGnuLdBaseVisitor.visitName_or_space");
+//
+// TerminalNode name = ctx.NAME();
+// String s = name != null ? name.getText() : " ";
+// string.append(s);
+// return s;
+// }
+
+ @Override
+ public String visitNameQuoted(GnuLdParser.NameQuotedContext ctx) {
+ System.out.println("StringGnuLdBaseVisitor.visitNameQuoted");
+ List<ParseTree> children = ctx.children;
+ System.out.println("children.size()) = " + children.size());
+
+ String s = "";
+ for (int i = 1; i < children.size() - 1; i++) {
+ ParseTree part = children.get(i);
+ System.out.println("part.getText() = " + part.getText());
+ s += part.getText();
+ }
+
+ return s;
+//
+// return visitChildren(ctx);
+ }
+ */
+}
diff --git a/kicad.cpp b/kicad.cpp
new file mode 100644
index 0000000..2af9bc6
--- /dev/null
+++ b/kicad.cpp
@@ -0,0 +1,219 @@
+#include "trygvis/kicad.h"
+#include <KicadNetLexer.h>
+#include <KicadNetParser.h>
+#include <KicadNetParserBaseListener.h>
+
+namespace trygvis {
+namespace antlr {
+
+// This namespace is shared copied code
+
+using ParseTree = antlr4::tree::ParseTree;
+
+class MissingParseTreeProperty : public std::out_of_range {
+public:
+ explicit MissingParseTreeProperty(const std::string &what) : out_of_range(what) { }
+};
+
+template<typename V, bool debug = false>
+class ParseTreeProperty {
+public:
+ virtual V get(Ref<ParseTree> node) {
+ return get(node.get());
+ }
+
+ virtual V get(ParseTree *const node) {
+ if (!debug) {
+ return _annotations.at(node);
+ }
+
+ try {
+// cerr << "node = " << node->getText() << endl;
+ return _annotations.at(node);
+ } catch (std::out_of_range &e) {
+ std::cerr << "get(" << node << "), text=" << node->getText() << std::endl;
+ std::stringstream buf;
+ buf << "out of range: " << node << ", text=" << node->getText();
+ auto msg = buf.str();
+ std::cerr << msg << std::endl;
+ throw MissingParseTreeProperty(msg);
+ }
+ }
+
+ virtual void put(ParseTree *const node, V value) {
+ if (debug) {
+ std::cerr << "put(" << node << ", " << value << "), text: " << node->getText() << std::endl;
+ }
+ _annotations[node] = value;
+ }
+
+ virtual V removeFrom(ParseTree *const node) {
+ auto it = _annotations.find(node);
+
+ if (it == _annotations.end()) {
+ throw MissingParseTreeProperty(node->getText());
+ }
+
+ return it->second;
+ }
+
+protected:
+ std::map<ParseTree *, V> _annotations;
+
+private:
+};
+
+} // namespace antlr
+
+}
+
+using namespace std;
+using namespace trygvis::antlr;
+
+namespace trygvis {
+namespace kicad {
+
+opt<const component *> netlist::find_component(string ref) const {
+ for (const component &c :components) {
+ int x = c.ref.compare(ref);
+ if (x == 0) {
+ return &c;
+ }
+ }
+ return std::experimental::nullopt;
+}
+
+static
+int parse(const Ref<antlr4::tree::TerminalNode> &integer) {
+ unsigned long long i = strtoull(integer->getText().c_str(), NULL, 10);
+
+ return static_cast<int>(i);
+}
+
+class KicadErrorListener : public BaseErrorListener {
+public:
+ vector<string> messages;
+
+ void syntaxError(IRecognizer *recognizer, Token *offendingSymbol, size_t line, int charPositionInLine,
+ const string &msg, exception_ptr e) override {
+ static_cast<void>(recognizer);
+ static_cast<void>(offendingSymbol);
+ static_cast<void>(e);
+ messages.push_back("line " + to_string(line) + ":" + to_string(charPositionInLine) + ": " + msg);
+ }
+};
+
+class kicad_main_listener : public KicadNetParserBaseListener {
+
+public:
+ vector<component> components;
+ vector<part> parts;
+ vector<net> nets;
+ vector<node> nodes;
+
+ ParseTreeProperty<string> strings;
+
+ virtual void exitNet(KicadNetParser::NetContext *ctx) override {
+ auto code = parse(ctx->code()->INTEGER());
+ auto name = strings.get(ctx->name()->string());
+
+// cerr << "exitNet: " << "code=" << code << ", name=" << name << ", nodes=" << nodes.size() << endl;
+
+ if (nodes.size() > 1) {
+ cerr << "Net#" << code << ": " << name << endl;
+ for (auto &node: nodes) {
+ cerr << " Node: " << node.ref << "#" << node.pin << endl;
+ }
+ }
+ nets.emplace_back(code, name, nodes);
+ nodes.clear();
+ }
+
+ virtual void exitNode(KicadNetParser::NodeContext *ctx) override {
+ auto ref = strings.get(ctx->ref()->string());
+ auto pin = parse(ctx->pinRef()->INTEGER());
+
+// cerr << "exitNode: " << "ref=" << ref << ", pin=" << pin << endl;
+
+ nodes.emplace_back(ref, pin);
+ }
+
+ virtual void exitComponent(KicadNetParser::ComponentContext *ctx) override {
+ auto ref = strings.get(ctx->ref()->string());
+ auto value = strings.get(ctx->value()->string());
+
+ cerr << "exitComponent, ref=" << ref << ", value=" << value << endl;
+
+ components.emplace_back(ref, value);
+ }
+
+ virtual void exitStringId(KicadNetParser::StringIdContext *ctx) override {
+ strings.put(ctx, ctx->getText());
+ }
+
+ virtual void exitStringInt(KicadNetParser::StringIntContext *ctx) override {
+ strings.put(ctx, ctx->getText());
+ }
+
+ virtual void exitStringText(KicadNetParser::StringTextContext *ctx) override {
+ auto s = ctx->getText();
+ strings.put(ctx, s.substr(1, s.length() - 2));
+ }
+};
+
+netlist kicad_net_loader::load(string path) {
+
+ ANTLRFileStream input(path);
+ KicadNetLexer lexer(&input);
+ CommonTokenStream tokens(&lexer);
+
+ tokens.fill();
+
+ if (debug_) {
+ for (auto token : tokens.getTokens()) {
+ cerr << token->toString() << endl;
+ }
+ }
+
+ KicadNetParser parser(&tokens);
+ parser.removeErrorListeners();
+ KicadErrorListener errorListener;
+ parser.addErrorListener(&errorListener);
+
+ parser.file();
+
+ if (!errorListener.messages.empty()) {
+ throw kicad_parse_exception(errorListener.messages);
+ }
+
+ parser.reset();
+
+ kicad_main_listener mainListener;
+ parser.addParseListener(&mainListener);
+
+ auto file = parser.file();
+
+ if (debug_ && parser.getNumberOfSyntaxErrors() == 0) {
+ cerr << file->toStringTree(&parser) << endl;
+ }
+
+ return netlist {
+ mainListener.components,
+ mainListener.parts,
+ mainListener.nets,
+ };
+}
+
+kicad_net_loader::kicad_net_loader() : debug_(false) {
+}
+
+kicad_net_loader::~kicad_net_loader() {
+}
+
+void kicad_net_loader::setDebug(bool debug) {
+ debug_ = debug;
+}
+
+
+} // namespace trygvis
+} // namespace kicad
diff --git a/kicad/.gitignore b/kicad/.gitignore
new file mode 100644
index 0000000..68c3cd9
--- /dev/null
+++ b/kicad/.gitignore
@@ -0,0 +1,2 @@
+*.bak
+*.bck
diff --git a/kicad/kicad_utils.dcm b/kicad/kicad_utils.dcm
new file mode 100644
index 0000000..5f3ed79
--- /dev/null
+++ b/kicad/kicad_utils.dcm
@@ -0,0 +1,3 @@
+EESchema-DOCLIB Version 2.0
+#
+#End Doc Library
diff --git a/kicad/kicad_utils.lib b/kicad/kicad_utils.lib
new file mode 100644
index 0000000..586f2c9
--- /dev/null
+++ b/kicad/kicad_utils.lib
@@ -0,0 +1,46 @@
+EESchema-LIBRARY Version 2.3
+#encoding utf-8
+#
+# ARDUINO_UNO
+#
+DEF ARDUINO_UNO U 0 40 Y Y 1 F N
+F0 "U" 0 0 60 H V C CNN
+F1 "ARDUINO_UNO" 0 100 60 H V C CNN
+F2 "" 0 0 60 H V C CNN
+F3 "" 0 0 60 H V C CNN
+DRAW
+S -550 -700 550 1300 0 1 0 N
+X ~RST 1 -750 600 200 R 50 50 1 1 I
+X 3V3 2 -750 500 200 R 50 50 1 1 I
+X 5V 3 -750 400 200 R 50 50 1 1 I
+X GND 4 -750 300 200 R 50 50 1 1 I
+X GND 5 -750 200 200 R 50 50 1 1 I
+X Vin 6 -750 100 200 R 50 50 1 1 I
+X A0 7 -750 -100 200 R 50 50 1 1 I
+X A1 8 -750 -200 200 R 50 50 1 1 I
+X A2 9 -750 -300 200 R 50 50 1 1 I
+X A3 10 -750 -400 200 R 50 50 1 1 I
+X D7 20 750 100 200 L 50 50 1 1 I
+X SCL 30 750 1200 200 L 50 50 1 1 I
+X A4 11 -750 -500 200 R 50 50 1 1 w
+X D8 21 750 300 200 L 50 50 1 1 I
+X A5 12 -750 -600 200 R 50 50 1 1 I
+X D9 22 750 400 200 L 50 50 1 1 I
+X D0 13 750 -600 200 L 50 50 1 1 I
+X D10 23 750 500 200 L 50 50 1 1 I
+X D1 14 750 -500 200 L 50 50 1 1 I
+X D11 24 750 600 200 L 50 50 1 1 I
+X D2 15 750 -400 200 L 50 50 1 1 I
+X D12 25 750 700 200 L 50 50 1 1 I
+X D3 16 750 -300 200 L 50 50 1 1 I
+X D13 26 750 800 200 L 50 50 1 1 I
+X D4 17 750 -200 200 L 50 50 1 1 I
+X GND 27 750 900 200 L 50 50 1 1 I
+X D5 18 750 -100 200 L 50 50 1 1 I
+X Aref 28 750 1000 200 L 50 50 1 1 I
+X D6 19 750 0 200 L 50 50 1 1 I
+X SDA 29 750 1100 200 L 50 50 1 1 I
+ENDDRAW
+ENDDEF
+#
+#End Library
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..b5e998d
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,89 @@
+#include <iostream>
+#include <err.h>
+#include <sysexits.h>
+#include <getopt.h>
+#include "trygvis/kicad.h"
+
+using namespace std;
+using namespace trygvis::kicad;
+
+char *program;
+
+__attribute__((noreturn))
+void usage(const char *reason = nullptr) {
+ if (reason) {
+ fprintf(stderr, "%s\n", reason);
+ }
+ fprintf(stderr, "usage: %s -f file -r ref\n", program);
+ exit(EX_USAGE);
+}
+
+void parse_args(int argc, char **argv, bool *debug, char **filename, char **ref) {
+ *debug = false;
+ *filename = *ref = nullptr;
+
+ int c;
+ while ((c = getopt(argc, argv, "Df:r:")) != -1) {
+ switch (c) {
+ case 'D':
+ *debug = true;
+ break;
+ case 'f':
+ *filename = optarg;
+ break;
+ case 'r':
+ *ref = optarg;
+ break;
+ default:
+ abort();
+ }
+ }
+
+ if (!*filename) {
+ usage();
+ }
+}
+
+bool generate(const char *ref, const trygvis::kicad::netlist &netlist) {
+ opt<const component *> componentO = netlist.find_component(ref);
+
+ if (!componentO) {
+ cerr << "Could not find component '" << ref << "'" << endl;
+ return false;
+ }
+
+ const component *c = *componentO;
+
+ cerr << "Generating connections for " << ref << endl;
+
+ cerr << c->value << endl;
+
+ return true;
+}
+
+int main(int argc, char **argv) {
+ program = argv[0];
+
+ bool debug;
+ char *filename;
+ char *ref;
+ parse_args(argc, argv, &debug, &filename, &ref);
+
+ kicad_net_loader loader;
+
+ try {
+ auto netlist = loader.load(filename);
+
+ auto ok = generate(ref, netlist);
+
+ if (ok) {
+ return EXIT_SUCCESS;
+ }
+ return EXIT_FAILURE;
+ } catch (kicad_parse_exception &e) {
+ for (auto &m: e.messages) {
+ fprintf(stderr, "%s\n", m.c_str());
+ }
+ errx(EX_DATAERR, "Could not parse netlist");
+ }
+}
diff --git a/test-input/lcd3310.net b/test-input/lcd3310.net
new file mode 100644
index 0000000..e7f6a79
--- /dev/null
+++ b/test-input/lcd3310.net
@@ -0,0 +1,163 @@
+(export (version D)
+ (design
+ (source /home/trygvis/dev/io.trygvis/2016/06/intel-quark-d2000-playground/apps/lcd3310/schematic/lcd3310.sch)
+ (date "Thu 21 Jul 2016 20:51:53 CEST")
+ (tool "Eeschema 4.0.2+dfsg1-stable")
+ (sheet (number 1) (name /) (tstamps /)
+ (title_block
+ (title)
+ (company)
+ (rev)
+ (date)
+ (source lcd3310.sch)
+ (comment (number 1) (value ""))
+ (comment (number 2) (value ""))
+ (comment (number 3) (value ""))
+ (comment (number 4) (value "")))))
+ (components
+ (comp (ref U1)
+ (value MOD-LCD3310)
+ (libsource (lib olimex) (part MOD-LCD3310))
+ (sheetpath (names /) (tstamps /))
+ (tstamp 578E9EE0))
+ (comp (ref U2)
+ (value D2000_DP)
+ (libsource (lib intel-quark) (part D2000_DP))
+ (sheetpath (names /) (tstamps /))
+ (tstamp 578E9F5B))
+ (comp (ref W1)
+ (value TEST_1P)
+ (libsource (lib conn) (part TEST_1P))
+ (sheetpath (names /) (tstamps /))
+ (tstamp 578F91E5)))
+ (libparts
+ (libpart (lib intel-quark) (part D2000_DP)
+ (fields
+ (field (name Reference) U)
+ (field (name Value) D2000_DP))
+ (pins
+ (pin (num 1) (name NC) (type NotConnected))
+ (pin (num 2) (name ~RESET) (type input))
+ (pin (num 3) (name 3.3V) (type input))
+ (pin (num 4) (name 5V) (type power_out))
+ (pin (num 5) (name GND) (type power_out))
+ (pin (num 6) (name GND) (type power_out))
+ (pin (num 7) (name NC) (type NotConnected))
+ (pin (num 8) (name A0) (type input))
+ (pin (num 9) (name A1) (type input))
+ (pin (num 10) (name A2) (type input))
+ (pin (num 11) (name A3) (type input))
+ (pin (num 12) (name A4) (type input))
+ (pin (num 13) (name A5_SDA) (type input))
+ (pin (num 14) (name A6_SCL) (type input))
+ (pin (num 15) (name D0_UART_A_RX) (type input))
+ (pin (num 16) (name D1_UART_A_TX) (type input))
+ (pin (num 17) (name D2) (type input))
+ (pin (num 18) (name D3) (type input))
+ (pin (num 19) (name D4) (type input))
+ (pin (num 20) (name D5) (type input))
+ (pin (num 21) (name ~~D6) (type input))
+ (pin (num 22) (name D7) (type input))
+ (pin (num 23) (name D8) (type input))
+ (pin (num 24) (name ~~D9) (type input))
+ (pin (num 25) (name D10_SSO) (type input))
+ (pin (num 26) (name D11_MOSI) (type input))
+ (pin (num 27) (name D12_MISO) (type input))
+ (pin (num 28) (name D13_SCK) (type input))
+ (pin (num 29) (name GND) (type power_out))
+ (pin (num 30) (name Aref) (type input))
+ (pin (num 31) (name SDA) (type BiDi))
+ (pin (num 32) (name SCL) (type output))))
+ (libpart (lib olimex) (part MOD-LCD3310)
+ (fields
+ (field (name Reference) U)
+ (field (name Value) MOD-LCD3310))
+ (pins
+ (pin (num 1) (name GND) (type power_in))
+ (pin (num 2) (name 5V) (type power_in))
+ (pin (num 3) (name SDA) (type BiDi))
+ (pin (num 4) (name SCL) (type input))))
+ (libpart (lib conn) (part TEST_1P)
+ (description point)
+ (fields
+ (field (name Reference) W)
+ (field (name Value) TEST_1P))
+ (pins
+ (pin (num 1) (name 1) (type passive)))))
+ (libraries
+ (library (logical intel-quark)
+ (uri /home/trygvis/dev/io.trygvis/2016/06/intel-quark-d2000-playground/apps/lcd3310/schematic/intel-quark.lib))
+ (library (logical olimex)
+ (uri /home/trygvis/dev/io.trygvis/2016/06/intel-quark-d2000-playground/apps/lcd3310/schematic/olimex.lib))
+ (library (logical conn)
+ (uri /usr/share/kicad/library/conn.lib)))
+ (nets
+ (net (code 1) (name "Net-(U2-Pad30)")
+ (node (ref U2) (pin 30)))
+ (net (code 2) (name "Net-(U2-Pad24)")
+ (node (ref U2) (pin 24)))
+ (net (code 3) (name "Net-(U2-Pad14)")
+ (node (ref U2) (pin 14)))
+ (net (code 4) (name "Net-(U2-Pad23)")
+ (node (ref U2) (pin 23)))
+ (net (code 5) (name "Net-(U2-Pad13)")
+ (node (ref U2) (pin 13)))
+ (net (code 6) (name "Net-(U2-Pad22)")
+ (node (ref U2) (pin 22)))
+ (net (code 7) (name "Net-(U2-Pad12)")
+ (node (ref U2) (pin 12)))
+ (net (code 8) (name "Net-(U2-Pad21)")
+ (node (ref U2) (pin 21)))
+ (net (code 9) (name "Net-(U2-Pad11)")
+ (node (ref U2) (pin 11)))
+ (net (code 10) (name "Net-(U2-Pad15)")
+ (node (ref U2) (pin 15)))
+ (net (code 11) (name "Net-(U2-Pad20)")
+ (node (ref U2) (pin 20)))
+ (net (code 12) (name "Net-(U2-Pad10)")
+ (node (ref U2) (pin 10)))
+ (net (code 13) (name "Net-(U2-Pad9)")
+ (node (ref U2) (pin 9)))
+ (net (code 14) (name "Net-(U2-Pad8)")
+ (node (ref U2) (pin 8)))
+ (net (code 15) (name "Net-(U2-Pad7)")
+ (node (ref U2) (pin 7)))
+ (net (code 16) (name "Net-(U2-Pad6)")
+ (node (ref U2) (pin 6)))
+ (net (code 17) (name "Net-(U2-Pad5)")
+ (node (ref U2) (pin 5)))
+ (net (code 18) (name "Net-(U2-Pad3)")
+ (node (ref U2) (pin 3)))
+ (net (code 19) (name "Net-(U2-Pad2)")
+ (node (ref U2) (pin 2)))
+ (net (code 20) (name /LCD_SDA)
+ (node (ref U1) (pin 3))
+ (node (ref U2) (pin 31))
+ (node (ref W1) (pin 1)))
+ (net (code 21) (name "Net-(U2-Pad1)")
+ (node (ref U2) (pin 1)))
+ (net (code 22) (name "Net-(U2-Pad19)")
+ (node (ref U2) (pin 19)))
+ (net (code 23) (name "Net-(U2-Pad28)")
+ (node (ref U2) (pin 28)))
+ (net (code 24) (name "Net-(U2-Pad18)")
+ (node (ref U2) (pin 18)))
+ (net (code 25) (name "Net-(U2-Pad27)")
+ (node (ref U2) (pin 27)))
+ (net (code 26) (name "Net-(U2-Pad17)")
+ (node (ref U2) (pin 17)))
+ (net (code 27) (name "Net-(U2-Pad26)")
+ (node (ref U2) (pin 26)))
+ (net (code 28) (name "Net-(U2-Pad16)")
+ (node (ref U2) (pin 16)))
+ (net (code 29) (name "Net-(U2-Pad25)")
+ (node (ref U2) (pin 25)))
+ (net (code 30) (name +5V)
+ (node (ref U2) (pin 4))
+ (node (ref U1) (pin 2)))
+ (net (code 31) (name "Net-(U1-Pad1)")
+ (node (ref U1) (pin 1))
+ (node (ref U2) (pin 29)))
+ (net (code 32) (name /LCD_SCL)
+ (node (ref U1) (pin 4))
+ (node (ref U2) (pin 32))))) \ No newline at end of file