aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/generate-header.cpp470
-rw-r--r--core/CMakeLists.txt2
-rw-r--r--core/trygvis/antlr.h (renamed from core/include-priv/trygvis/antlr.h)0
-rw-r--r--core/trygvis/string_utils.h (renamed from core/include-priv/trygvis/string_utils.h)2
-rw-r--r--examples/arduino-led/CMakeLists.txt1
-rw-r--r--examples/arduino-led/schematic.h14
-rw-r--r--examples/intel-quark-d2000/schematic.h51
-rw-r--r--examples/intel-quark-d2000/schematic/intel-quark-d2000.sch8
-rw-r--r--template/arduino-uno.py19
9 files changed, 167 insertions, 400 deletions
diff --git a/cli/generate-header.cpp b/cli/generate-header.cpp
index 1033fc3..6fd64c6 100644
--- a/cli/generate-header.cpp
+++ b/cli/generate-header.cpp
@@ -37,39 +37,51 @@ void usage(const char *reason = nullptr) {
if (reason) {
fprintf(stderr, "%s\n", reason);
}
- fprintf(stderr, "usage: %s -n <net file> -r <ref> [-o <out file>] [-t <python template>]\n", program);
+ fprintf(stderr, "usage: %s -n <net file> -r <ref> -t <template> [-l <template lib dir>] [-o <out file>]\n",
+ program);
exit(EX_USAGE);
}
-void parse_args(int argc, char **argv, bool *debug, char **net_filename, char **ref, char **py_template,
- vector<fs::path> &template_libs, char **out_filename) {
- *debug = false;
- *ref = nullptr;
- *out_filename = nullptr;
- *py_template = nullptr;
- *ref = nullptr;
+struct opts {
+ bool debug;
+ string net_filename;
+ string ref;
+ string py_template;
+ opt<string> out_filename;
+ vector<fs::path> template_libs;
+};
+
+struct opts parse_args(int argc, char **argv) {
+ struct opts opts = {
+ .debug = false,
+ .net_filename = "",
+ .ref = "",
+ .py_template = "",
+ .out_filename = nullopt,
+ .template_libs = {},
+ };
int c;
while ((c = getopt(argc, argv, "Dn:r:o:t:l:")) != -1) {
switch (c) {
case 'D':
- *debug = true;
+ opts.debug = true;
break;
case 'n':
- *net_filename = optarg;
+ opts.net_filename = optarg;
break;
case 'r':
- *ref = optarg;
+ opts.ref = optarg;
break;
case 't':
- *py_template = optarg;
+ opts.py_template = optarg;
break;
case 'l':
- template_libs.push_back(fs::path(optarg));
+ opts.template_libs.push_back(fs::path(optarg));
break;
case 'o':
if (strcmp("-", optarg) != 0) {
- *out_filename = optarg;
+ opts.out_filename = string(optarg);
}
break;
default:
@@ -77,182 +89,24 @@ void parse_args(int argc, char **argv, bool *debug, char **net_filename, char **
}
}
- if (!*net_filename || !*ref) {
+ if (opts.net_filename.empty() || opts.ref.empty() || opts.py_template.empty()) {
usage();
}
-}
-
-class part {
-public:
- part(const string &name) : name(name) {
- }
-
- virtual ~part() {
- }
-
- const string name;
-
- virtual bool generate(stringstream &out, const string &ref, const vector<const net *> usages) = 0;
-};
-
-class arduino_uno : public part {
-public:
- arduino_uno() : part("ARDUINO_UNO") {}
- ~arduino_uno() {
- }
-
- virtual bool generate(stringstream &out, const string &ref, const vector<const net *> usages) override {
- out << "namespace schematic {" << endl;
- for (auto &usage: usages) {
- auto node = usage->node_for_ref(ref);
-
- if (node->pin >= 7 && node->pin <= 12) {
- out << "static const int ANALOG_" << usage->name << " = " << (node->pin - 7) << ";" << endl;
- } else if (node->pin >= 13 && node->pin <= 26) {
- out << "static const int " << usage->name << " = " << (node->pin - 13) << ";" << endl;
- }
- }
- out << "} // namespace schematic" << endl;
-
- return true;
- }
-};
-
-class intel_quark_d2000 : public part {
-public:
- intel_quark_d2000() : part("INTEL_QUARK_D2000") {}
-
- ~intel_quark_d2000() {
- }
-
- virtual bool generate(stringstream &out, const string &ref, const vector<const net *> usages) override {
- static map<int, string> gpio_map{
- {2, "10"},
- {3, "11"},
- {4, "12"},
- {5, "13"},
- {6, "14"},
- {7, "15"},
- {8, "16"},
- {9, "17"},
- {10, "18"},
-
- {11, "9"},
- {13, "20"},
- {14, "21"},
- {15, "22"},
- {16, "23"},
- {18, "19"},
-
- {21, "24"},
-
- {31, "0"},
- {32, "1"},
- {33, "2"},
- {34, "3"},
- {35, "4"},
- {36, "5"},
- {37, "6"},
- {38, "7"},
- {39, "8"},
- };
-
- out << "#include <stddef.h>" << endl;
- out << "#include <qm_gpio.h>" << endl;
- out << endl;
- out << "enum schematic_direction {" << endl;
- out << " schematic_direction_out = 1," << endl;
- out << " schematic_direction_in = 2" << endl;
- out << "};" << endl;;
-
- for (auto &usage: usages) {
- auto node = usage->node_for_ref(ref);
-
- auto gpio = gpio_map.find(node->pin);
-
- if (gpio == gpio_map.end()) {
- continue;
- }
-
- out << "static const uint8_t SCHEMATIC_" << usage->name << " = " << gpio->second << ";" << endl;
- out << endl;
- out << "static inline" << endl;
- out << "qm_rc_t schematic_PUSH_BUTTON_direction(enum schematic_direction dir) {" << endl;
- out << " qm_gpio_port_config_t cfg;" << endl;
- out << "" << endl;
- out << " qm_gpio_get_config(QM_GPIO_0, &cfg);" << endl;
- out << "" << endl;
- out << " if (dir == schematic_direction_out) {" << endl;
- out << " cfg.direction |= BIT(SCHEMATIC_PUSH_BUTTON);" << endl;
- out << " } else {" << endl;
- out << " cfg.direction &= ~BIT(SCHEMATIC_PUSH_BUTTON);" << endl;
- out << " }" << endl;
- out << "" << endl;
- out << " return qm_gpio_set_config(QM_GPIO_0, &cfg);" << endl;
- out << "}" << endl;
- out << endl;
- }
+ return opts;
+}
- return true;
- }
-};
+static
+opt<fs::path> find_py_template(const string &py_template, const vector<fs::path> &paths) {
-//class library {
-//public:
-// library(const string &name) : name(name) {}
-//
-// library(library &&l) : name(std::move(l.name)), parts(std::move(l.parts)) { }
-//
-// virtual ~library() { }
-//
-// const string name;
-// vector<unique_ptr<part>> parts;
-//
-// opt<part *> find_part(string name) const {
-// for (auto &part: parts) {
-// if (part->name == name) {
-// return part.get();
-// }
-// }
-//
-// return nullopt;
-// }
-//};
-
-//class kicad_gen {
-//public:
-// vector<library> libraries;
-//
-// kicad_gen() {
-// library kicad_utils("kicad_utils");
-// kicad_utils.parts.push_back(make_unique<arduino_uno>());
-// kicad_utils.parts.push_back(make_unique<intel_quark_d2000>());
-//
-// libraries.push_back(std::move(kicad_utils));
-// }
-//
-// opt<library *> find_library(string name) {
-// for (auto &l : libraries) {
-// if (l.name == name) {
-// return &l;
-// }
-// }
-//
-// return nullopt;
-// }
-//};
-
-opt<fs::path> find_template(const string &py_template, const vector<fs::path> &paths) {
-
- fs::path p(py_template);
+ fs::path p(py_template + ".py");
if (fs::exists(p)) {
return p;
}
for (auto &&prefix : paths) {
- p = prefix / py_template;
+ p = prefix / (py_template + ".py");
if (fs::exists(p)) {
return p;
@@ -262,67 +116,11 @@ opt<fs::path> find_template(const string &py_template, const vector<fs::path> &p
return nullopt;
}
-/*
-bool generate(const char *ref, nl *const netlist, stringstream &out) {
- kicad_gen gen;
- 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 " << c->ref << " (" << c->value << ")" << endl;
-
- auto libraryO = gen.find_library(c->_lib_source.lib);
-
- if (!libraryO) {
- cerr << "Unsupported library '" << c->_lib_source.lib << "'" << endl;
- return false;
- }
-
- const library *library = *libraryO;
-
- auto partName = c->_lib_source.part;
-
- auto partO = library->find_part(partName);
-
- if (!partO) {
- cerr << "The library library " << library->name << " does not have a component named " << partName << endl;
- return false;
- }
-
- part *part = *partO;
-
- out << "#ifndef SCHEMATIC_H" << endl;
- out << "#define SCHEMATIC_H" << endl;
- out << endl;
- out << "*/
-/*" << endl;
- out << "THIS FILE IS GENERATED. DO NOT EDIT." << endl;
- out << endl;
- out << "Generated from schematic for reference " << ref << ", part " << partName << " in library " <<
- library->name << "." << endl;
- out << "*//*
-" << endl;
- out << endl;
-
- auto usages = netlist->find_usage_of(ref);
-
- part->generate(out, ref, usages);
-
- out << "#endif // SCHEMATIC_H" << endl;
-
- return true;
-}
-*/
-
-bool generate_py(const char *ref, nl *const netlist, stringstream &out, const fs::path &py_template) {
+bool generate(const string &ref, nl *const netlist, stringstream &out, const fs::path &py_template) {
py::dict vars;
pybind11::module kicad_utils_py_module = py::module::import("kicad_utils_py");
- vars = kicad_utils_py_module.attr("__dict__");
+ pybind11::module main_module = py::module::import("__main__");
+ vars = main_module.attr("__dict__");
pybind11::object netlist_py = py::cast(netlist);
@@ -343,30 +141,8 @@ bool generate_py(const char *ref, nl *const netlist, stringstream &out, const fs
return true;
}
-int main(int argc, char **argv) {
- bool debug;
- char *net_filename;
- char *ref;
- char *py_template;
- vector<fs::path> template_libs;
- char *out_filename;
-
- fs::path bin(argv[0]);
- fs::path basedir = bin.parent_path().parent_path();
-
- template_libs.push_back(fs::current_path());
- template_libs.push_back(basedir / "share" / "kicad-utils" / "template");
-
- parse_args(argc, argv, &debug, &net_filename, &ref, &py_template, template_libs, &out_filename);
-
- kicad_net_loader loader;
-
- /*
- string python_version = Py_GetVersion();
- cout << "Python version: " << python_version << endl;
- */
-
- /*
+__attribute__((unused)) static
+void show_env() {
map<string, string> env;
for (char **e = environ; *e != NULL; e++) {
string s = *e;
@@ -377,86 +153,122 @@ int main(int argc, char **argv) {
for (auto &&e: env) {
cout << e.first << " = " << e.second << endl;
}
- */
+}
+
+__attribute__((unused)) static
+void show_py_info() {
+ cerr << "Compile-time Python version: " << PY_VERSION << endl;
+ cerr << "Current python version: " << Py_GetVersion() << endl;
+}
+
+class python_init {
+private:
+ wchar_t *program = nullptr;
+
+public:
+ class python_init_error : public std::runtime_error {
+ public:
+ python_init_error(const string &what) : runtime_error(what) {}
+ };
+
+ python_init(const char *argv0, const vector<fs::path> &python_paths) {
+ std::wstring_convert<codecvt_utf8<wchar_t>> converter;
+
+ wstring pythonpath(Py_GetPath());
+ for (auto &path : python_paths) {
+ if (!fs::exists(path)) {
+ continue;
+ }
+ pythonpath = converter.from_bytes(path.string() + PATH_SEPARATOR) + pythonpath;
+ }
+ wcerr << "PYTHONPATH: " << pythonpath << endl;
+ Py_SetPath(pythonpath.c_str());
+
+ program = Py_DecodeLocale(argv0, NULL);
+ if (program == NULL) {
+ throw python_init_error("Fatal error: cannot decode argv[0]\n");
+ }
+ Py_SetProgramName(program);
+
+ show_py_info();
+
+ Py_Initialize();
+ }
+
+ ~python_init() {
+ Py_Finalize();
+ PyMem_RawFree(program);
+ }
+};
+
+int main(int argc, char **argv) {
+ program = argv[0];
+
+ fs::path bin(argv[0]);
+ fs::path basedir = bin.parent_path().parent_path();
+
+ struct opts opts = parse_args(argc, argv);
+
+ opts.template_libs.push_back(fs::current_path());
+ opts.template_libs.push_back(basedir / "share" / "kicad-utils" / "template");
+
+ kicad_net_loader loader;
+
+ if (opts.debug) {
+ show_env();
+ }
try {
- nl netlist = loader.load(net_filename, cerr);
+ nl netlist = loader.load(opts.net_filename, cerr);
stringstream out;
- bool ok = false;
- if (py_template) {
- cerr << "Template path: " << endl;
- for (auto &&p : template_libs) {
+ cerr << "Template search path: " << endl;
+ for (auto &&p : opts.template_libs) {
+ cerr << " " << p.string() << endl;
+ }
+
+ opt<fs::path> py_template = find_py_template(opts.py_template, opts.template_libs);
+
+ if (!py_template) {
+ cerr << "No such file: " << opts.py_template << endl;
+ cerr << "Search path: " << endl;
+ for (auto &&p : opts.template_libs) {
cerr << " " << p.string() << endl;
}
+ cerr << "Current path is " << fs::current_path().string() << endl;
+ return EXIT_FAILURE;
+ }
- opt<fs::path> tmpl = find_template(py_template, template_libs);
+ vector<fs::path> module_paths{
+ basedir / "python",
+ basedir / "lib",
+ };
- if (!tmpl) {
- cerr << "No such file: " << py_template << endl;
- cerr << "Search path: " << endl;
- for (auto &&p : template_libs) {
- cerr << " " << p.string() << endl;
- }
- cerr << "Current path is " << fs::current_path().string() << endl;
- } else {
- wchar_t *program = Py_DecodeLocale(argv[0], NULL);
- if (program == NULL) {
- fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
- exit(1);
- }
- Py_SetProgramName(program);
-
- vector<fs::path> module_paths{
- basedir / "python",
- basedir / "lib",
- };
-
- std::wstring_convert<codecvt_utf8<wchar_t> > converter;
- converter.from_bytes(string("foo"));
-
- wstring pythonpath(Py_GetPath());
- for (auto &path : module_paths) {
- if (!fs::exists(path)) {
- continue;
- }
-// pythonpath += converter.from_bytes(PATH_SEPARATOR + path.string());
- pythonpath = converter.from_bytes(path.string() + PATH_SEPARATOR) + pythonpath;
+ python_init python(argv[0], module_paths);
+ try {
+ auto ok = generate(opts.ref, &netlist, out, py_template.value());
+
+ if (ok) {
+ auto contents = out.str();
+ if (opts.out_filename) {
+ ofstream outstream(opts.out_filename.value());
+ outstream << contents;
+ outstream.close();
+ } else {
+ cout << contents << flush;
}
- wcerr << "pythonpath=" << pythonpath << endl;
- Py_SetPath(pythonpath.c_str());
-
- cerr << "Compile-time Python version: " << PY_VERSION << endl;
- cerr << "Current python version: " << Py_GetVersion() << endl;
-
- Py_Initialize();
- try {
- ok = generate_py(ref, &netlist, out, tmpl.value());
- } catch (py::error_already_set &e) {
- cerr << "Python failure:" << endl << e.what() << endl;
- } catch (std::runtime_error &e) {
- cerr << "Generation failed: " << e.what() << endl;
- }
- Py_Finalize();
- PyMem_RawFree(program);
+ return EXIT_SUCCESS;
}
-// } else {
-// ok = generate(ref, &netlist, out);
+ } catch (py::error_already_set &e) {
+ cerr << "Python failure:" << endl << e.what() << endl;
+ } catch (std::runtime_error &e) {
+ cerr << "Generation failed: " << e.what() << endl;
}
- if (ok) {
- auto contents = out.str();
- if (out_filename != nullptr) {
- ofstream outstream(out_filename);
- outstream << contents;
- outstream.close();
- } else {
- cout << contents << flush;
- }
- return EXIT_SUCCESS;
- }
- return EXIT_FAILURE;
+ return EXIT_SUCCESS;
+ } catch (python_init::python_init_error &e) {
+ errx(EX_IOERR, e.what());
} catch (kicad_parse_exception &e) {
for (auto &m: e.messages) {
fprintf(stderr, "%s\n", m.c_str());
diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
index cbf8e78..75d2383 100644
--- a/core/CMakeLists.txt
+++ b/core/CMakeLists.txt
@@ -16,7 +16,7 @@ get_target_property(KicadNet_includes KicadNet INCLUDE_DIRECTORIES)
target_include_directories(kicad-utils-core
PUBLIC include
- PRIVATE include-priv ${KicadNet_includes})
+ PRIVATE ${KicadNet_includes})
target_link_libraries(kicad-utils-core
Antlr4::antlr4_shared)
diff --git a/core/include-priv/trygvis/antlr.h b/core/trygvis/antlr.h
index f5656ea..f5656ea 100644
--- a/core/include-priv/trygvis/antlr.h
+++ b/core/trygvis/antlr.h
diff --git a/core/include-priv/trygvis/string_utils.h b/core/trygvis/string_utils.h
index 9902a3f..2f2a7a5 100644
--- a/core/include-priv/trygvis/string_utils.h
+++ b/core/trygvis/string_utils.h
@@ -8,6 +8,7 @@ namespace string_utils {
/**
* Check if a starts with b.
*/
+__attribute__((unused))
static bool startsWith(const std::string &a, const std::string &b) {
return b.length() <= a.length() && a.compare(0, b.length(), b) == 0;
}
@@ -15,6 +16,7 @@ static bool startsWith(const std::string &a, const std::string &b) {
/**
* Check if a ends with b.
*/
+__attribute__((unused))
static bool endsWith(const std::string &a, const std::string &b) {
return b.length() <= a.length() && a.compare(a.length() - b.length(), b.length(), b) == 0;
}
diff --git a/examples/arduino-led/CMakeLists.txt b/examples/arduino-led/CMakeLists.txt
index a615fb7..7855dff 100644
--- a/examples/arduino-led/CMakeLists.txt
+++ b/examples/arduino-led/CMakeLists.txt
@@ -4,6 +4,7 @@ kicad_generate_header(
OUTPUT schematic.h
NET schematic/arduino-led.net
REF U1
+ TEMPLATE arduino-uno
IN_SOURCE)
if (FALSE)
diff --git a/examples/arduino-led/schematic.h b/examples/arduino-led/schematic.h
deleted file mode 100644
index c935528..0000000
--- a/examples/arduino-led/schematic.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef SCHEMATIC_H
-#define SCHEMATIC_H
-
-/*
-THIS FILE IS GENERATED. DO NOT EDIT.
-
-Generated from schematic for reference U1, part ARDUINO_UNO in library kicad_utils.
-*/
-
-namespace schematic {
-static const int STATUS_LED = 3;
-static const int ANALOG_LIGHT_1 = 2;
-} // namespace schematic
-#endif // SCHEMATIC_H
diff --git a/examples/intel-quark-d2000/schematic.h b/examples/intel-quark-d2000/schematic.h
deleted file mode 100644
index 8bc46ae..0000000
--- a/examples/intel-quark-d2000/schematic.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef SCHEMATIC_H
-#define SCHEMATIC_H
-
-/*
-THIS FILE IS GENERATED. DO NOT EDIT.
-
-Generated from schematic for reference U1, part INTEL_QUARK_D2000 in library kicad_utils.
-*/
-
-#include <stddef.h>
-#include <qm_gpio.h>
-
-enum schematic_direction {
- schematic_direction_out = 1,
- schematic_direction_in = 2
-};
-static const uint8_t SCHEMATIC_STATUS_LED = 15;
-
-static inline
-qm_rc_t schematic_PUSH_BUTTON_direction(enum schematic_direction dir) {
- qm_gpio_port_config_t cfg;
-
- qm_gpio_get_config(QM_GPIO_0, &cfg);
-
- if (dir == schematic_direction_out) {
- cfg.direction |= BIT(SCHEMATIC_PUSH_BUTTON);
- } else {
- cfg.direction &= ~BIT(SCHEMATIC_PUSH_BUTTON);
- }
-
- return qm_gpio_set_config(QM_GPIO_0, &cfg);
-}
-
-static const uint8_t SCHEMATIC_PUSH_BUTTON = 11;
-
-static inline
-qm_rc_t schematic_PUSH_BUTTON_direction(enum schematic_direction dir) {
- qm_gpio_port_config_t cfg;
-
- qm_gpio_get_config(QM_GPIO_0, &cfg);
-
- if (dir == schematic_direction_out) {
- cfg.direction |= BIT(SCHEMATIC_PUSH_BUTTON);
- } else {
- cfg.direction &= ~BIT(SCHEMATIC_PUSH_BUTTON);
- }
-
- return qm_gpio_set_config(QM_GPIO_0, &cfg);
-}
-
-#endif // SCHEMATIC_H
diff --git a/examples/intel-quark-d2000/schematic/intel-quark-d2000.sch b/examples/intel-quark-d2000/schematic/intel-quark-d2000.sch
index b9fd1bd..a30ecb8 100644
--- a/examples/intel-quark-d2000/schematic/intel-quark-d2000.sch
+++ b/examples/intel-quark-d2000/schematic/intel-quark-d2000.sch
@@ -66,10 +66,10 @@ F 3 "" H 2250 2900 50 0000 C CNN
1 0 0 -1
$EndComp
$Comp
-L GND #PWR1
+L GND #PWR01
U 1 1 579883CB
P 1750 4250
-F 0 "#PWR1" H 1750 4000 50 0001 C CNN
+F 0 "#PWR01" H 1750 4000 50 0001 C CNN
F 1 "GND" H 1750 4100 50 0000 C CNN
F 2 "" H 1750 4250 50 0000 C CNN
F 3 "" H 1750 4250 50 0000 C CNN
@@ -101,9 +101,7 @@ $EndComp
Wire Wire Line
2550 2900 3700 2900
Wire Wire Line
- 1750 4250 1750 3300
-Wire Wire Line
- 1750 3300 1750 2900
+ 1750 2900 1750 4250
Wire Wire Line
1750 2900 1950 2900
Wire Wire Line
diff --git a/template/arduino-uno.py b/template/arduino-uno.py
new file mode 100644
index 0000000..0e0e0e1
--- /dev/null
+++ b/template/arduino-uno.py
@@ -0,0 +1,19 @@
+global generateHeader
+
+generateHeader.println("""
+namespace schematic {
+""")
+
+usages = generateHeader.netlist.find_usages_of(generateHeader.ref)
+
+for usage in usages:
+ node = usage.node_for_ref(generateHeader.ref)
+
+ if 7 <= node.pin <= 12:
+ generateHeader.println("static const int ANALOG_" + usage.name + " = " + (node.pin - 7) + ";")
+ elif 13 <= node.pin <= 26:
+ generateHeader.println("static const int ANALOG_" + usage.name + " = " + (node.pin - 13) + ";")
+
+generateHeader.println("""
+} // namespace schematic
+""")