From 5908f2af0697c2be0467b4a83e783d5155992f05 Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 6 Jun 2018 20:54:42 +0200 Subject: [PATCH 01/18] json: Fixing the build Signed-off-by: David Shah --- frontend/json/jsonparse.cc | 4 ++-- frontend/json/jsonparse.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/json/jsonparse.cc b/frontend/json/jsonparse.cc index 45edabad..0f8fb48c 100644 --- a/frontend/json/jsonparse.cc +++ b/frontend/json/jsonparse.cc @@ -377,7 +377,7 @@ void json_import_cell_ports(Design *design, string &modname, CellInfo *cell, log_error("JSON no connection match " "for port_direction \'%s\' of node \'%s\' " "in module \'%s\'\n", - port_name, cell->name.c_str(), modname.c_str()); + port_name.c_str(), cell->name.c_str(), modname.c_str()); assert(wire_group_node); @@ -546,7 +546,7 @@ void json_import_cell(Design *design, string modname, JsonNode *cell_node, param_node = cell_node->data_dict.at("parameters"); if (param_node->type != 'D') - log_error("JSON parameter list of \'%s\' is not a data dictionary\n", cell->name); + log_error("JSON parameter list of \'%s\' is not a data dictionary\n", cell->name.c_str()); // // Loop through all parameters, adding them into the diff --git a/frontend/json/jsonparse.h b/frontend/json/jsonparse.h index 12bf6dcd..6b444be9 100644 --- a/frontend/json/jsonparse.h +++ b/frontend/json/jsonparse.h @@ -24,6 +24,6 @@ #include #include "design.h" -extern void parse_json_file(std::istream *&, std::string &, Design *); +extern void parse_json_file(std::istream *&, std::string , Design *); #endif From ff5a719d8bacf57617f89cc9ac43a25b981455e4 Mon Sep 17 00:00:00 2001 From: ZipCPU Date: Wed, 6 Jun 2018 15:02:20 -0400 Subject: [PATCH 02/18] Fixed run-time bug in json parser --- frontend/json/jsonparse.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/json/jsonparse.h b/frontend/json/jsonparse.h index 6b444be9..12bf6dcd 100644 --- a/frontend/json/jsonparse.h +++ b/frontend/json/jsonparse.h @@ -24,6 +24,6 @@ #include #include "design.h" -extern void parse_json_file(std::istream *&, std::string , Design *); +extern void parse_json_file(std::istream *&, std::string &, Design *); #endif From 3a6e400f4478161c72bbabb1bcbc71ece7318877 Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 6 Jun 2018 21:14:42 +0200 Subject: [PATCH 03/18] rulecheck.cc: Add missing return Signed-off-by: David Shah --- common/rulecheck.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/common/rulecheck.cc b/common/rulecheck.cc index b81695b9..28d4b6b7 100644 --- a/common/rulecheck.cc +++ b/common/rulecheck.cc @@ -57,5 +57,6 @@ bool check_all_nets_driven(Design *design) { } if (debug) log_info(" Verified!\n"); + return true; } From c18f0b1c2286d737f3ace47d4f843ef523ba4b97 Mon Sep 17 00:00:00 2001 From: ZipCPU Date: Wed, 6 Jun 2018 15:45:53 -0400 Subject: [PATCH 04/18] Added the build directory to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index a36bdfc5..77f1871d 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ CMakeCache.txt .*.swp a.out *.json +build/ From bdd93135823ae1ef293d4be3eb50d0ca6bdeee9e Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 7 Jun 2018 08:56:54 +0200 Subject: [PATCH 05/18] Allow loading and running Python files before GUI starts Signed-off-by: David Shah --- common/pybindings.cc | 76 +++++++++++++++++++++++++------------------- common/pybindings.h | 6 ++-- gui/mainwindow.cc | 4 --- ice40/main.cc | 29 +++++++++-------- python/functions.py | 2 ++ 5 files changed, 64 insertions(+), 53 deletions(-) create mode 100644 python/functions.py diff --git a/common/pybindings.cc b/common/pybindings.cc index 556e838e..7a542dc1 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -22,6 +22,7 @@ #include "design.h" #include "chip.h" #include "pybindings.h" +#include "emb.h" // Required to determine concatenated module name (which differs for different archs) #define PASTER(x, y) x ## _ ## y @@ -36,43 +37,52 @@ void arch_wrap_python(); BOOST_PYTHON_MODULE (MODULE_NAME) { - arch_wrap_python(); + arch_wrap_python(); } -void arch_appendinittab() -{ - PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME); +void arch_appendinittab() { + PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME); } -void execute_python_file(const char *executable, const char* python_file) -{ - wchar_t *program = Py_DecodeLocale(executable, NULL); - if (program == NULL) { - fprintf(stderr, "Fatal error: cannot decode executable filename\n"); - exit(1); - } - try - { - PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME); - Py_SetProgramName(program); - Py_Initialize(); +static wchar_t *program; - FILE* fp = fopen(python_file, "r"); - if (fp == NULL) { - fprintf(stderr, "Fatal error: file not found %s\n",python_file); - exit(1); - } - PyRun_SimpleFile(fp , python_file); - fclose(fp); - - Py_Finalize(); - PyMem_RawFree(program); - } - catch(boost::python::error_already_set const &) - { - // Parse and output the exception - std::string perror_str = parse_python_exception(); - std::cout << "Error in Python: " << perror_str << std::endl; - } +void init_python(const char *executable) { + program = Py_DecodeLocale(executable, NULL); + if (program == NULL) { + fprintf(stderr, "Fatal error: cannot decode executable filename\n"); + exit(1); + } + try { + PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME); + emb::append_inittab(); + Py_SetProgramName(program); + Py_Initialize(); + } catch (boost::python::error_already_set const &) { + // Parse and output the exception + std::string perror_str = parse_python_exception(); + std::cout << "Error in Python: " << perror_str << std::endl; + } +} + +void deinit_python() { + Py_Finalize(); + PyMem_RawFree(program); +} + +void execute_python_file(const char *python_file) { + try { + FILE *fp = fopen(python_file, "r"); + if (fp == NULL) { + fprintf(stderr, "Fatal error: file not found %s\n", python_file); + exit(1); + } + PyRun_SimpleFile(fp, python_file); + fclose(fp); + } + catch (boost::python::error_already_set const &) { + // Parse and output the exception + std::string perror_str = parse_python_exception(); + std::cout << "Error in Python: " << perror_str << std::endl; + } } diff --git a/common/pybindings.h b/common/pybindings.h index f594784c..84280908 100644 --- a/common/pybindings.h +++ b/common/pybindings.h @@ -26,7 +26,6 @@ #include #include #include - using namespace boost::python; /* A wrapper for a Pythonised nextpnr Iterator. The actual class wrapped is a @@ -79,7 +78,10 @@ struct range_wrapper { #define WRAP_RANGE(t) range_wrapper().wrap(#t "Range", #t "Iterator") -void execute_python_file(const char *executable, const char* python_file); +void init_python(const char *executable); +void deinit_python(); + +void execute_python_file(const char* python_file); std::string parse_python_exception(); void arch_appendinittab(); diff --git a/gui/mainwindow.cc b/gui/mainwindow.cc index 4404fc5a..b72a0851 100644 --- a/gui/mainwindow.cc +++ b/gui/mainwindow.cc @@ -11,9 +11,6 @@ MainWindow::MainWindow(QWidget *parent) : ui(new Ui::MainWindow) { ui->setupUi(this); - emb::append_inittab(); - arch_appendinittab(); - Py_Initialize(); PyImport_ImportModule("emb"); write = [this] (std::string s) { @@ -27,7 +24,6 @@ MainWindow::MainWindow(QWidget *parent) : MainWindow::~MainWindow() { - Py_Finalize(); delete ui; } diff --git a/ice40/main.cc b/ice40/main.cc index 9295bde4..3d3312c4 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -45,7 +45,7 @@ void svg_dump_el(const GraphicElement &el) int main(int argc, char *argv[]) { namespace po = boost::program_options; - + int rc = 0; std::string str; po::options_description options("Allowed options"); @@ -122,15 +122,7 @@ int main(int argc, char *argv[]) chipArgs.type = ChipArgs::UP5K; Design design(chipArgs); - - if (vm.count("gui")) - { - QApplication a(argc, argv); - MainWindow w; - w.show(); - - return a.exec(); - } + init_python(argv[0]); if (vm.count("test")) { @@ -216,8 +208,17 @@ int main(int argc, char *argv[]) if (vm.count("file")) { std::string filename = vm["file"].as(); - execute_python_file(argv[0],filename.c_str()); - } - - return 0; + execute_python_file(filename.c_str()); + } + + if (vm.count("gui")) + { + QApplication a(argc, argv); + MainWindow w; + w.show(); + + rc = a.exec(); + } + deinit_python(); + return rc; } diff --git a/python/functions.py b/python/functions.py new file mode 100644 index 00000000..4f005456 --- /dev/null +++ b/python/functions.py @@ -0,0 +1,2 @@ +def test_function(): + print("Hello World!") From 0f6ebd638402ca1ac2a202621e9db63c2cb5eb5f Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 7 Jun 2018 09:01:30 +0200 Subject: [PATCH 06/18] Allow specifying multiple Python files on the command line Signed-off-by: David Shah --- ice40/main.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ice40/main.cc b/ice40/main.cc index 3d3312c4..5d00fcc8 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -53,7 +53,7 @@ int main(int argc, char *argv[]) options.add_options()("test","just a check"); options.add_options()("gui","start gui"); options.add_options()("svg","dump SVG file"); - options.add_options()("file", po::value(), "python file to execute"); + options.add_options()("file", po::value>(), "python file to execute"); options.add_options()("json", po::value(), "JSON design file to ingest"); options.add_options()("version,v","show version"); options.add_options()("lp384","set device type to iCE40LP384"); @@ -207,8 +207,9 @@ int main(int argc, char *argv[]) if (vm.count("file")) { - std::string filename = vm["file"].as(); - execute_python_file(filename.c_str()); + std::vector files = vm["file"].as>(); + for(auto filename : files) + execute_python_file(filename.c_str()); } if (vm.count("gui")) From 3769b2058019ce7c6be824085e1047e1beec07dc Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 7 Jun 2018 09:47:00 +0200 Subject: [PATCH 07/18] Adding Python to/from string wrappers for internal IDs --- common/pybindings.h | 48 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/common/pybindings.h b/common/pybindings.h index 84280908..5b2adc6a 100644 --- a/common/pybindings.h +++ b/common/pybindings.h @@ -76,6 +76,54 @@ struct range_wrapper { } }; +/* +A wrapper to enable custom type/ID to/from string conversions + */ +template struct string_wrapper { + template + struct from_pystring_converter { + from_pystring_converter() { + converter::registry::push_back( + &convertible, + &construct, + boost::python::type_id()); + }; + + static void* convertible(PyObject* object) { + return PyUnicode_Check(object) ? object : 0; + } + + static void construct( + PyObject* object, + converter::rvalue_from_python_stage1_data* data) { + const wchar_t* value = PyUnicode_AsUnicode(object); + const std::wstring value_ws(value); + if (value == 0) throw_error_already_set(); + void* storage = ( + (boost::python::converter::rvalue_from_python_storage*) + data)->storage.bytes; + new (storage) T(fn(std::string(value_ws.begin(), value_ws.end()))); + data->convertible = storage; + } + + static F fn; + }; + + template struct to_str_wrapper { + static F fn; + std::string str(T& x) { + return fn(x); + } + }; + + template static void wrap(const char *type_name, F1 to_str_fn, F2 from_str_fn) { + from_pystring_converter::fn = from_str_fn; + from_pystring_converter(); + to_str_wrapper::fn = to_str_fn; + class_(type_name, no_init).def("__str__", to_str_wrapper::str); + }; +}; + #define WRAP_RANGE(t) range_wrapper().wrap(#t "Range", #t "Iterator") void init_python(const char *executable); From e576f71838290ff12b98145fb02af84563fc03c1 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 7 Jun 2018 11:41:54 +0200 Subject: [PATCH 08/18] Developing Python bindings for Design and related types --- common/pybindings.cc | 47 +++++++++++++++ common/pybindings.h | 52 +---------------- common/pycontainers.h | 129 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 179 insertions(+), 49 deletions(-) create mode 100644 common/pycontainers.h diff --git a/common/pybindings.cc b/common/pybindings.cc index 7a542dc1..04b2fa27 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -36,7 +36,54 @@ // architectures void arch_wrap_python(); +bool operator==(const PortRef &a, const PortRef &b) { + return (a.cell == b.cell) && (a.port == b.port); +} + BOOST_PYTHON_MODULE (MODULE_NAME) { + class_("GraphicElement") + .def_readwrite("style", &GraphicElement::style) + .def_readwrite("type", &GraphicElement::type) + .def_readwrite("x1", &GraphicElement::x1) + .def_readwrite("y1", &GraphicElement::y1) + .def_readwrite("x2", &GraphicElement::x2) + .def_readwrite("y2", &GraphicElement::y2) + .def_readwrite("text", &GraphicElement::text); + + class_("PortRef") + .def_readwrite("cell", &PortRef::cell) + .def_readwrite("port", &PortRef::port); + + class_("NetInfo") + .def_readwrite("name", &NetInfo::name) + .def_readwrite("driver", &NetInfo::driver) + .def_readwrite("users", &NetInfo::users) + .def_readwrite("attrs", &NetInfo::attrs) + .def_readwrite("wires", &NetInfo::wires); + + WRAP_MAP(decltype(NetInfo::attrs), "IdStrMap"); + + class_>("PortRefVector") + .def(vector_indexing_suite>()); + + class_("PortInfo") + .def_readwrite("name", &PortInfo::name) + .def_readwrite("net", &PortInfo::net) + .def_readwrite("type", &PortInfo::type); + + class_("CellInfo") + .def_readwrite("name", &CellInfo::name) + .def_readwrite("type", &CellInfo::type) + .def_readwrite("ports", &CellInfo::ports) + .def_readwrite("attrs", &CellInfo::attrs) + .def_readwrite("params", &CellInfo::params) + .def_readwrite("bel", &CellInfo::bel) + .def_readwrite("pins", &CellInfo::pins); + + class_("Design", no_init) + .def_readwrite("chip", &Design::chip) + .def_readwrite("nets", &Design::nets) + .def_readwrite("cells", &Design::cells); arch_wrap_python(); } diff --git a/common/pybindings.h b/common/pybindings.h index 5b2adc6a..3dfadeee 100644 --- a/common/pybindings.h +++ b/common/pybindings.h @@ -20,6 +20,9 @@ #ifndef COMMON_PYBINDINGS_H #define COMMON_PYBINDINGS_H + +#include "pycontainers.h" + #include #include #include @@ -27,54 +30,6 @@ #include #include using namespace boost::python; -/* -A wrapper for a Pythonised nextpnr Iterator. The actual class wrapped is a -pair containing (current, end) -*/ - -template -struct iterator_wrapper { - typedef decltype(*(std::declval())) value_t; - - static value_t next(std::pair &iter) { - if (iter.first != iter.second) { - value_t val = *iter.first; - ++iter.first; - return val; - } else { - PyErr_SetString(PyExc_StopIteration, "End of range reached"); - boost::python::throw_error_already_set(); - // Should be unreachable, but prevent control may reach end of non-void - throw std::runtime_error("unreachable"); - } - } - - static void wrap(const char *python_name) { - class_>(python_name, no_init) - .def("__next__", next); - } -}; - -/* -A wrapper for a nextpnr Range. Ranges should have two functions, begin() -and end() which return iterator-like objects supporting ++, * and != -Full STL iterator semantics are not required, unlike the standard Boost wrappers -*/ - -template -struct range_wrapper { - typedef decltype(std::declval().begin()) iterator_t; - - static std::pair iter(T &range) { - return std::make_pair(range.begin(), range.end()); - } - - static void wrap(const char *range_name, const char *iter_name) { - class_(range_name, no_init) - .def("__iter__", iter); - iterator_wrapper().wrap(iter_name); - } -}; /* A wrapper to enable custom type/ID to/from string conversions @@ -124,7 +79,6 @@ template struct string_wrapper { }; }; -#define WRAP_RANGE(t) range_wrapper().wrap(#t "Range", #t "Iterator") void init_python(const char *executable); void deinit_python(); diff --git a/common/pycontainers.h b/common/pycontainers.h new file mode 100644 index 00000000..64fb265b --- /dev/null +++ b/common/pycontainers.h @@ -0,0 +1,129 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Clifford Wolf + * Copyright (C) 2018 David Shah + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifndef COMMON_PYCONTAINERS_H +#define COMMON_PYCONTAINERS_H + +#include +#include +#include +#include +#include +#include +#include + +using namespace boost::python; + +/* +A wrapper for a Pythonised nextpnr Iterator. The actual class wrapped is a +pair containing (current, end) +*/ + +template +struct iterator_wrapper { + typedef decltype(*(std::declval())) value_t; + + static value_t next(std::pair &iter) { + if (iter.first != iter.second) { + value_t val = *iter.first; + ++iter.first; + return val; + } else { + PyErr_SetString(PyExc_StopIteration, "End of range reached"); + boost::python::throw_error_already_set(); + // Should be unreachable, but prevent control may reach end of non-void + throw std::runtime_error("unreachable"); + } + } + + static void wrap(const char *python_name) { + class_ < std::pair < T, T >> (python_name, no_init) + .def("__next__", next, P()); + } +}; + +/* +A wrapper for a nextpnr Range. Ranges should have two functions, begin() +and end() which return iterator-like objects supporting ++, * and != +Full STL iterator semantics are not required, unlike the standard Boost wrappers +*/ + +template> +struct range_wrapper { + typedef decltype(std::declval().begin()) iterator_t; + + static std::pair iter(T &range) { + return std::make_pair(range.begin(), range.end()); + } + + static void wrap(const char *range_name, const char *iter_name) { + class_(range_name, no_init) + .def("__iter__", iter); + iterator_wrapper().wrap(iter_name); + } + typedef iterator_wrapper iter_wrap; +}; + +#define WRAP_RANGE(t) range_wrapper().wrap(#t "Range", #t "Iterator") + +/* +Wrapper for a map, either an unordered_map, regular map or dict + */ +inline void KeyError() { PyErr_SetString(PyExc_KeyError, "Key not found"); } + +template +struct map_wrapper { + typedef boost::remove_cv_t> K; + typedef typename T::mapped_type V; + typedef typename T::value_type KV; + + static V &get(T &x, K const &i) { + if (x.find(i) != x.end()) return x.at(i); + KeyError(); + std::terminate(); + } + + static void set(T &x, K const &i, V const &v) { + x[i] = v; + } + + static void del(T const &x, K const &i) { + if (x.find(i) != x.end()) x.erase(i); + else KeyError(); + std::terminate(); + } + + static void wrap(const char *map_name, const char *kv_name, const char *iter_name) { + class_(kv_name) + .def_readonly("first", &KV::first) + .def_readwrite("second", &KV::second); + typedef range_wrapper> rw; + typename rw::iter_wrap().wrap(iter_name); + class_(map_name, no_init) + .def("__iter__", rw::iter) + .def("__len__", &T::size) + .def("__getitem__", get, return_internal_reference<>()) + .def("__setitem__", set, with_custodian_and_ward<1,2>()); + } +}; + +#define WRAP_MAP(t, name) map_wrapper().wrap(#name, #name "KeyValue", #name "Iterator") + +#endif From 9eeecf0e62d44c59f5f0a5243a47793369dd71c0 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 7 Jun 2018 12:19:48 +0200 Subject: [PATCH 09/18] Rename --file to --run Signed-off-by: Clifford Wolf --- ice40/main.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ice40/main.cc b/ice40/main.cc index 5d00fcc8..da39c1e5 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -53,7 +53,7 @@ int main(int argc, char *argv[]) options.add_options()("test","just a check"); options.add_options()("gui","start gui"); options.add_options()("svg","dump SVG file"); - options.add_options()("file", po::value>(), "python file to execute"); + options.add_options()("run", po::value>(), "python file to execute"); options.add_options()("json", po::value(), "JSON design file to ingest"); options.add_options()("version,v","show version"); options.add_options()("lp384","set device type to iCE40LP384"); @@ -64,7 +64,7 @@ int main(int argc, char *argv[]) options.add_options()("up5k","set device type to iCE40UP5K"); po::positional_options_description pos; - pos.add("file", -1); + pos.add("run", -1); po::variables_map vm; try { @@ -205,7 +205,7 @@ int main(int argc, char *argv[]) parse_json_file(f, filename, &design); } - if (vm.count("file")) + if (vm.count("run")) { std::vector files = vm["file"].as>(); for(auto filename : files) From 8bfeaeacedeb09133b8fb157c876fb90f41f5676 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 7 Jun 2018 12:26:02 +0200 Subject: [PATCH 10/18] Add ICE40_HX1K_ONLY config macro Signed-off-by: Clifford Wolf --- ice40/chip.cc | 7 +++++++ ice40/main.cc | 50 +++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/ice40/chip.cc b/ice40/chip.cc index d1226b3a..d3388bc9 100644 --- a/ice40/chip.cc +++ b/ice40/chip.cc @@ -277,6 +277,12 @@ PortPin PortPinFromId(IdString id) Chip::Chip(ChipArgs args) { +#ifdef ICE40_HX1K_ONLY + if (args.type == ChipArgs::HX1K) { + chip_info = chip_info_1k; + return; + } +#else if (args.type == ChipArgs::LP384) { chip_info = chip_info_384; return; @@ -293,6 +299,7 @@ Chip::Chip(ChipArgs args) fprintf(stderr, "Unsupported chip type\n"); exit(EXIT_FAILURE); } +#endif abort(); } diff --git a/ice40/main.cc b/ice40/main.cc index da39c1e5..ae5c59b2 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -86,10 +86,11 @@ int main(int argc, char *argv[]) if (vm.count("help") || argc == 1) { + help: std::cout << basename(argv[0]) << " -- Next Generation Place and Route (git sha1 " GIT_COMMIT_HASH_STR ")\n"; std::cout << "\n"; std::cout << options << "\n"; - return 1; + return argc != 1; } if (vm.count("version")) @@ -101,25 +102,52 @@ int main(int argc, char *argv[]) } ChipArgs chipArgs; - chipArgs.type = ChipArgs::HX1K; - if (vm.count("lp384")) + if (vm.count("lp384")) { + if (chipArgs.type != ChipArgs::NONE) + goto help; chipArgs.type = ChipArgs::LP384; + } - if (vm.count("lp1k")) + if (vm.count("lp1k")) { + if (chipArgs.type != ChipArgs::NONE) + goto help; chipArgs.type = ChipArgs::LP1K; + } - if (vm.count("lp8k")) + if (vm.count("lp8k")) { + if (chipArgs.type != ChipArgs::NONE) + goto help; chipArgs.type = ChipArgs::LP8K; + } - if (vm.count("hx1k")) + if (vm.count("hx1k")) { + if (chipArgs.type != ChipArgs::NONE) + goto help; + chipArgs.type = ChipArgs::HX1K; + } + + if (vm.count("hx8k")) { + if (chipArgs.type != ChipArgs::NONE) + goto help; + chipArgs.type = ChipArgs::HX8K; + } + + if (vm.count("up5k")) { + if (chipArgs.type != ChipArgs::NONE) + goto help; + chipArgs.type = ChipArgs::UP5K; + } + + if (chipArgs.type == ChipArgs::NONE) chipArgs.type = ChipArgs::HX1K; - if (vm.count("hx8k")) - chipArgs.type = ChipArgs::HX8K; - - if (vm.count("up5k")) - chipArgs.type = ChipArgs::UP5K; +#ifdef ICE40_HX1K_ONLY + if (chipArgs.type != ChipArgs::HX1K) { + std::cout << "This version of nextpnr-ice40 is built with HX1K-support only.\n"; + return 1; + } +#endif Design design(chipArgs); init_python(argv[0]); From a5249da02d2a55d4b838dd8c29e159513dd71418 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 7 Jun 2018 12:40:31 +0200 Subject: [PATCH 11/18] Working on global Python design object Signed-off-by: David Shah --- common/pybindings.cc | 10 +++++++- common/pybindings.h | 53 ++++++++++++++++++++++++++++++++----------- ice40/main.cc | 1 + python/dump_design.py | 2 ++ 4 files changed, 52 insertions(+), 14 deletions(-) create mode 100644 python/dump_design.py diff --git a/common/pybindings.cc b/common/pybindings.cc index 04b2fa27..4ae83cb0 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -80,10 +80,17 @@ BOOST_PYTHON_MODULE (MODULE_NAME) { .def_readwrite("bel", &CellInfo::bel) .def_readwrite("pins", &CellInfo::pins); - class_("Design", no_init) + WRAP_MAP(decltype(CellInfo::ports), "IdPortMap"); + //WRAP_MAP(decltype(CellInfo::pins), "IdIdMap"); + + class_("Design", no_init) .def_readwrite("chip", &Design::chip) .def_readwrite("nets", &Design::nets) .def_readwrite("cells", &Design::cells); + + WRAP_MAP(decltype(Design::nets), "IdNetMap"); + WRAP_MAP(decltype(Design::cells), "IdCellMap"); + arch_wrap_python(); } @@ -104,6 +111,7 @@ void init_python(const char *executable) { emb::append_inittab(); Py_SetProgramName(program); Py_Initialize(); + PyImport_ImportModule(TOSTRING(MODULE_NAME)); } catch (boost::python::error_already_set const &) { // Parse and output the exception std::string perror_str = parse_python_exception(); diff --git a/common/pybindings.h b/common/pybindings.h index 3dfadeee..44898198 100644 --- a/common/pybindings.h +++ b/common/pybindings.h @@ -29,12 +29,14 @@ #include #include #include +#include using namespace boost::python; /* A wrapper to enable custom type/ID to/from string conversions */ -template struct string_wrapper { +template +struct string_wrapper { template struct from_pystring_converter { from_pystring_converter() { @@ -44,34 +46,37 @@ template struct string_wrapper { boost::python::type_id()); }; - static void* convertible(PyObject* object) { + static void *convertible(PyObject *object) { return PyUnicode_Check(object) ? object : 0; } static void construct( - PyObject* object, - converter::rvalue_from_python_stage1_data* data) { - const wchar_t* value = PyUnicode_AsUnicode(object); + PyObject *object, + converter::rvalue_from_python_stage1_data *data) { + const wchar_t *value = PyUnicode_AsUnicode(object); const std::wstring value_ws(value); if (value == 0) throw_error_already_set(); - void* storage = ( - (boost::python::converter::rvalue_from_python_storage*) + void *storage = ( + (boost::python::converter::rvalue_from_python_storage *) data)->storage.bytes; - new (storage) T(fn(std::string(value_ws.begin(), value_ws.end()))); + new(storage) T(fn(std::string(value_ws.begin(), value_ws.end()))); data->convertible = storage; } - static F fn; + static F fn; }; - template struct to_str_wrapper { + template + struct to_str_wrapper { static F fn; - std::string str(T& x) { + + std::string str(T &x) { return fn(x); } }; - template static void wrap(const char *type_name, F1 to_str_fn, F2 from_str_fn) { + template + static void wrap(const char *type_name, F1 to_str_fn, F2 from_str_fn) { from_pystring_converter::fn = from_str_fn; from_pystring_converter(); to_str_wrapper::fn = to_str_fn; @@ -79,12 +84,34 @@ template struct string_wrapper { }; }; +std::string parse_python_exception(); + +template +void python_export_global(const char *name, Tn &x) { + PyObject * m, *d; + m = PyImport_AddModule("__main__"); + if (m == NULL) + return; + d = PyModule_GetDict(m); + try { + PyObject * p = object(boost::ref(x)).ptr(); + PyDict_SetItemString(d, name, p); + } catch (boost::python::error_already_set const &) { + // Parse and output the exception + std::string perror_str = parse_python_exception(); + std::cout << "Error in Python: " << perror_str << std::endl; + std::terminate(); + } +}; void init_python(const char *executable); + void deinit_python(); -void execute_python_file(const char* python_file); +void execute_python_file(const char *python_file); + std::string parse_python_exception(); + void arch_appendinittab(); #endif /* end of include guard: COMMON_PYBINDINGS_HH */ diff --git a/ice40/main.cc b/ice40/main.cc index 5d00fcc8..12c6b86c 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -123,6 +123,7 @@ int main(int argc, char *argv[]) Design design(chipArgs); init_python(argv[0]); + python_export_global("design", design); if (vm.count("test")) { diff --git a/python/dump_design.py b/python/dump_design.py new file mode 100644 index 00000000..9d8ade3e --- /dev/null +++ b/python/dump_design.py @@ -0,0 +1,2 @@ +for cell in design.cells: + print(cell.first) From 2edde06c07cc3cd58ab156d9598d75e1cff1e7de Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 7 Jun 2018 12:48:53 +0200 Subject: [PATCH 12/18] Fix clang-format include order issues Signed-off-by: Clifford Wolf --- .clang-format | 8 +++----- common/pybindings.cc | 4 +++- dummy/pybindings.cc | 2 ++ ice40/pybindings.cc | 2 ++ 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.clang-format b/.clang-format index d825df6f..8b3158bb 100644 --- a/.clang-format +++ b/.clang-format @@ -47,12 +47,10 @@ DisableFormat: false ExperimentalAutoDetectBinPacking: false ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] IncludeCategories: - - Regex: '^"(llvm|llvm-c|clang|clang-c)/' - Priority: 2 - - Regex: '^(<|"(gtest|isl|json)/)' - Priority: 3 - - Regex: '.*' + - Regex: '<.*>' Priority: 1 + - Regex: '.*' + Priority: 2 IndentCaseLabels: false IndentWidth: 4 IndentWrappedFunctionNames: false diff --git a/common/pybindings.cc b/common/pybindings.cc index 7a542dc1..10c8fd44 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -21,9 +21,11 @@ #include "design.h" #include "chip.h" -#include "pybindings.h" #include "emb.h" +// include after design.h/chip.h +#include "pybindings.h" + // Required to determine concatenated module name (which differs for different archs) #define PASTER(x, y) x ## _ ## y #define EVALUATOR(x, y) PASTER(x,y) diff --git a/dummy/pybindings.cc b/dummy/pybindings.cc index a19479a0..3a586234 100644 --- a/dummy/pybindings.cc +++ b/dummy/pybindings.cc @@ -20,6 +20,8 @@ #include "design.h" #include "chip.h" + +// include after design.h/chip.h #include "pybindings.h" void arch_wrap_python() { diff --git a/ice40/pybindings.cc b/ice40/pybindings.cc index dc13f849..3760e319 100644 --- a/ice40/pybindings.cc +++ b/ice40/pybindings.cc @@ -20,6 +20,8 @@ #include "design.h" #include "chip.h" + +// include after design.h/chip.h #include "pybindings.h" void arch_wrap_python() { From 1ea8fa488127c63e119b07b05ec1c468e820db9c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 7 Jun 2018 12:56:49 +0200 Subject: [PATCH 13/18] clang-format for design and chip codebase Signed-off-by: Clifford Wolf --- common/design.cc | 1 - common/design.h | 115 +++---- dummy/chip.cc | 4 +- dummy/chip.h | 84 ++--- ice40/chip.cc | 701 +++++++++++++++++++++--------------------- ice40/chip.h | 785 ++++++++++++++++++++++++----------------------- 6 files changed, 847 insertions(+), 843 deletions(-) diff --git a/common/design.cc b/common/design.cc index 7ba6a9b1..6ab122df 100644 --- a/common/design.cc +++ b/common/design.cc @@ -18,4 +18,3 @@ */ #include "design.h" - diff --git a/common/design.h b/common/design.h index 314c2fd7..f4c24f15 100644 --- a/common/design.h +++ b/common/design.h @@ -20,50 +20,52 @@ #ifndef DESIGN_H #define DESIGN_H -#include #include -#include +#include #include -#include #include +#include +#include // replace with proper IdString later typedef std::string IdString; // replace with haslib later -template using pool = std::unordered_set; -template using dict = std::unordered_map; +template using pool = std::unordered_set; +template using dict = std::unordered_map; using std::vector; struct GraphicElement { - // This will control colour, and there should be separate - // visibility controls in some cases also - enum { - // Wires entirely inside tiles, e.g. between switchbox and bels - G_LOCAL_WIRES, - // Standard inter-tile routing - G_GENERAL_WIRES, - // Special inter-tile wires, e.g. carry chains - G_DEDICATED_WIRES, - G_BEL_OUTLINE, - G_SWITCHBOX_OUTLINE, - G_TILE_OUTLINE, - G_BEL_PINS, - G_SWITCHBOX_PINS, - G_BEL_MISC, - G_TILE_MISC, - } style; + // This will control colour, and there should be separate + // visibility controls in some cases also + enum + { + // Wires entirely inside tiles, e.g. between switchbox and bels + G_LOCAL_WIRES, + // Standard inter-tile routing + G_GENERAL_WIRES, + // Special inter-tile wires, e.g. carry chains + G_DEDICATED_WIRES, + G_BEL_OUTLINE, + G_SWITCHBOX_OUTLINE, + G_TILE_OUTLINE, + G_BEL_PINS, + G_SWITCHBOX_PINS, + G_BEL_MISC, + G_TILE_MISC, + } style; - enum { - G_LINE, - G_BOX, - G_CIRCLE, - G_LABEL - } type; + enum + { + G_LINE, + G_BOX, + G_CIRCLE, + G_LABEL + } type; - float x1, y1, x2, y2, z; - std::string text; + float x1, y1, x2, y2, z; + std::string text; }; #include "chip.h" @@ -72,56 +74,57 @@ struct CellInfo; struct PortRef { - CellInfo *cell; - IdString port; + CellInfo *cell; + IdString port; }; struct NetInfo { - IdString name; - PortRef driver; - vector users; - dict attrs; + IdString name; + PortRef driver; + vector users; + dict attrs; - // wire -> (uphill_wire, delay) - dict> wires; + // wire -> (uphill_wire, delay) + dict> wires; }; enum PortType { - PORT_IN = 0, - PORT_OUT = 1, - PORT_INOUT = 2 + PORT_IN = 0, + PORT_OUT = 1, + PORT_INOUT = 2 }; struct PortInfo { - IdString name; - NetInfo *net; - PortType type; + IdString name; + NetInfo *net; + PortType type; }; struct CellInfo { - IdString name, type; - dict ports; - dict attrs, params; + IdString name, type; + dict ports; + dict attrs, params; - BelId bel; - // cell_port -> bel_pin - dict pins; + BelId bel; + // cell_port -> bel_pin + dict pins; }; struct Design { - struct Chip chip; + struct Chip chip; - Design(ChipArgs args) : chip(args) { - // ... - } + Design(ChipArgs args) : chip(args) + { + // ... + } - dict nets; - dict cells; + dict nets; + dict cells; }; #endif diff --git a/dummy/chip.cc b/dummy/chip.cc index 51a6a840..642984ca 100644 --- a/dummy/chip.cc +++ b/dummy/chip.cc @@ -19,6 +19,4 @@ #include "chip.h" -Chip::Chip(ChipArgs) -{ -} +Chip::Chip(ChipArgs) {} diff --git a/dummy/chip.h b/dummy/chip.h index 054e822b..8c66fb96 100644 --- a/dummy/chip.h +++ b/dummy/chip.h @@ -24,10 +24,10 @@ struct DelayInfo { - float delay = 0; + float delay = 0; - float raiseDelay() { return delay; } - float fallDelay() { return delay; } + float raiseDelay() { return delay; } + float fallDelay() { return delay; } }; typedef IdString BelType; @@ -45,8 +45,8 @@ typedef IdString PipId; struct BelPin { - BelId bel; - PortPin pin; + BelId bel; + PortPin pin; }; struct ChipArgs @@ -55,48 +55,48 @@ struct ChipArgs struct Chip { - Chip(ChipArgs args); + Chip(ChipArgs args); - BelId getBelByName(IdString name) const; + BelId getBelByName(IdString name) const; - IdString getBelName(BelId bel) const; - void bindBel(BelId bel, IdString cell); - void unbindBel(BelId bel); - bool checkBelAvail(BelId bel) const; - const vector &getBels() const; - const vector &getBelsByType(BelType type) const; - BelType getBelType(BelId bel) const; - WireId getWireBelPin(BelId bel, PortPin pin) const; - BelPin getBelPinUphill(WireId wire) const; - const vector &getBelPinsDownhill(WireId wire) const; + IdString getBelName(BelId bel) const; + void bindBel(BelId bel, IdString cell); + void unbindBel(BelId bel); + bool checkBelAvail(BelId bel) const; + const vector &getBels() const; + const vector &getBelsByType(BelType type) const; + BelType getBelType(BelId bel) const; + WireId getWireBelPin(BelId bel, PortPin pin) const; + BelPin getBelPinUphill(WireId wire) const; + const vector &getBelPinsDownhill(WireId wire) const; - WireId getWireByName(IdString name) const; - IdString getWireName(WireId wire) const; - void bindWire(WireId bel, IdString net); - void unbindWire(WireId bel); - bool checkWireAvail(WireId bel) const; - const vector &getWires() const; + WireId getWireByName(IdString name) const; + IdString getWireName(WireId wire) const; + void bindWire(WireId bel, IdString net); + void unbindWire(WireId bel); + bool checkWireAvail(WireId bel) const; + const vector &getWires() const; - PipId getPipByName(IdString name) const; - IdString getPipName(PipId pip) const; - void bindPip(PipId bel, IdString net); - void unbindPip(PipId bel); - bool checkPipAvail(PipId bel) const; - const vector &getPips() const; - WireId getPipSrcWire(PipId pip) const; - WireId getPipDstWire(PipId pip) const; - DelayInfo getPipDelay(PipId pip) const; - const vector &getPipsDownhill(WireId wire) const; - const vector &getPipsUphill(WireId wire) const; - const vector &getWireAliases(WireId wire) const; + PipId getPipByName(IdString name) const; + IdString getPipName(PipId pip) const; + void bindPip(PipId bel, IdString net); + void unbindPip(PipId bel); + bool checkPipAvail(PipId bel) const; + const vector &getPips() const; + WireId getPipSrcWire(PipId pip) const; + WireId getPipDstWire(PipId pip) const; + DelayInfo getPipDelay(PipId pip) const; + const vector &getPipsDownhill(WireId wire) const; + const vector &getPipsUphill(WireId wire) const; + const vector &getWireAliases(WireId wire) const; - void getBelPosition(BelId bel, float &x, float &y) const; - void getWirePosition(WireId wire, float &x, float &y) const; - void getPipPosition(PipId pip, float &x, float &y) const; - vector getBelGraphics(BelId bel) const; - vector getWireGraphics(WireId wire) const; - vector getPipGraphics(PipId pip) const; - vector getFrameGraphics() const; + void getBelPosition(BelId bel, float &x, float &y) const; + void getWirePosition(WireId wire, float &x, float &y) const; + void getPipPosition(PipId pip, float &x, float &y) const; + vector getBelGraphics(BelId bel) const; + vector getWireGraphics(WireId wire) const; + vector getPipGraphics(PipId pip) const; + vector getFrameGraphics() const; }; #endif diff --git a/ice40/chip.cc b/ice40/chip.cc index d3388bc9..4ba7697d 100644 --- a/ice40/chip.cc +++ b/ice40/chip.cc @@ -23,254 +23,258 @@ IdString belTypeToId(BelType type) { - if (type == TYPE_ICESTORM_LC) - return "ICESTORM_LC"; - if (type == TYPE_ICESTORM_RAM) - return "ICESTORM_RAM"; - if (type == TYPE_SB_IO) - return "SB_IO"; - return IdString(); + if (type == TYPE_ICESTORM_LC) + return "ICESTORM_LC"; + if (type == TYPE_ICESTORM_RAM) + return "ICESTORM_RAM"; + if (type == TYPE_SB_IO) + return "SB_IO"; + return IdString(); } BelType belTypeFromId(IdString id) { - if (id == "ICESTORM_LC") - return TYPE_ICESTORM_LC; - if (id == "ICESTORM_RAM") - return TYPE_ICESTORM_RAM; - if (id == "SB_IO") - return TYPE_SB_IO; - return TYPE_NIL; + if (id == "ICESTORM_LC") + return TYPE_ICESTORM_LC; + if (id == "ICESTORM_RAM") + return TYPE_ICESTORM_RAM; + if (id == "SB_IO") + return TYPE_SB_IO; + return TYPE_NIL; } // ----------------------------------------------------------------------- IdString PortPinToId(PortPin type) { -#define X(t) if (type == PIN_##t) return #t; +#define X(t) \ + if (type == PIN_##t) \ + return #t; - X(IN_0) - X(IN_1) - X(IN_2) - X(IN_3) - X(O) - X(LO) - X(CIN) - X(COUT) - X(CEN) - X(CLK) - X(SR) + X(IN_0) + X(IN_1) + X(IN_2) + X(IN_3) + X(O) + X(LO) + X(CIN) + X(COUT) + X(CEN) + X(CLK) + X(SR) - X(MASK_0) - X(MASK_1) - X(MASK_2) - X(MASK_3) - X(MASK_4) - X(MASK_5) - X(MASK_6) - X(MASK_7) - X(MASK_8) - X(MASK_9) - X(MASK_10) - X(MASK_11) - X(MASK_12) - X(MASK_13) - X(MASK_14) - X(MASK_15) + X(MASK_0) + X(MASK_1) + X(MASK_2) + X(MASK_3) + X(MASK_4) + X(MASK_5) + X(MASK_6) + X(MASK_7) + X(MASK_8) + X(MASK_9) + X(MASK_10) + X(MASK_11) + X(MASK_12) + X(MASK_13) + X(MASK_14) + X(MASK_15) - X(RDATA_0) - X(RDATA_1) - X(RDATA_2) - X(RDATA_3) - X(RDATA_4) - X(RDATA_5) - X(RDATA_6) - X(RDATA_7) - X(RDATA_8) - X(RDATA_9) - X(RDATA_10) - X(RDATA_11) - X(RDATA_12) - X(RDATA_13) - X(RDATA_14) - X(RDATA_15) + X(RDATA_0) + X(RDATA_1) + X(RDATA_2) + X(RDATA_3) + X(RDATA_4) + X(RDATA_5) + X(RDATA_6) + X(RDATA_7) + X(RDATA_8) + X(RDATA_9) + X(RDATA_10) + X(RDATA_11) + X(RDATA_12) + X(RDATA_13) + X(RDATA_14) + X(RDATA_15) - X(WDATA_0) - X(WDATA_1) - X(WDATA_2) - X(WDATA_3) - X(WDATA_4) - X(WDATA_5) - X(WDATA_6) - X(WDATA_7) - X(WDATA_8) - X(WDATA_9) - X(WDATA_10) - X(WDATA_11) - X(WDATA_12) - X(WDATA_13) - X(WDATA_14) - X(WDATA_15) + X(WDATA_0) + X(WDATA_1) + X(WDATA_2) + X(WDATA_3) + X(WDATA_4) + X(WDATA_5) + X(WDATA_6) + X(WDATA_7) + X(WDATA_8) + X(WDATA_9) + X(WDATA_10) + X(WDATA_11) + X(WDATA_12) + X(WDATA_13) + X(WDATA_14) + X(WDATA_15) - X(WADDR_0) - X(WADDR_1) - X(WADDR_2) - X(WADDR_3) - X(WADDR_4) - X(WADDR_5) - X(WADDR_6) - X(WADDR_7) - X(WADDR_8) - X(WADDR_9) - X(WADDR_10) + X(WADDR_0) + X(WADDR_1) + X(WADDR_2) + X(WADDR_3) + X(WADDR_4) + X(WADDR_5) + X(WADDR_6) + X(WADDR_7) + X(WADDR_8) + X(WADDR_9) + X(WADDR_10) - X(RADDR_0) - X(RADDR_1) - X(RADDR_2) - X(RADDR_3) - X(RADDR_4) - X(RADDR_5) - X(RADDR_6) - X(RADDR_7) - X(RADDR_8) - X(RADDR_9) - X(RADDR_10) + X(RADDR_0) + X(RADDR_1) + X(RADDR_2) + X(RADDR_3) + X(RADDR_4) + X(RADDR_5) + X(RADDR_6) + X(RADDR_7) + X(RADDR_8) + X(RADDR_9) + X(RADDR_10) - X(WCLK) - X(WCLKE) - X(WE) + X(WCLK) + X(WCLKE) + X(WE) - X(RCLK) - X(RCLKE) - X(RE) + X(RCLK) + X(RCLKE) + X(RE) - X(PACKAGE_PIN) - X(LATCH_INPUT_VALUE) - X(CLOCK_ENABLE) - X(INPUT_CLK) - X(OUTPUT_CLK) - X(OUTPUT_ENABLE) - X(D_OUT_0) - X(D_OUT_1) - X(D_IN_0) - X(D_IN_1) + X(PACKAGE_PIN) + X(LATCH_INPUT_VALUE) + X(CLOCK_ENABLE) + X(INPUT_CLK) + X(OUTPUT_CLK) + X(OUTPUT_ENABLE) + X(D_OUT_0) + X(D_OUT_1) + X(D_IN_0) + X(D_IN_1) #undef X - return IdString(); + return IdString(); } PortPin PortPinFromId(IdString id) { -#define X(t) if (id == #t) return PIN_##t; +#define X(t) \ + if (id == #t) \ + return PIN_##t; - X(IN_0) - X(IN_1) - X(IN_2) - X(IN_3) - X(O) - X(LO) - X(CIN) - X(COUT) - X(CEN) - X(CLK) - X(SR) + X(IN_0) + X(IN_1) + X(IN_2) + X(IN_3) + X(O) + X(LO) + X(CIN) + X(COUT) + X(CEN) + X(CLK) + X(SR) - X(MASK_0) - X(MASK_1) - X(MASK_2) - X(MASK_3) - X(MASK_4) - X(MASK_5) - X(MASK_6) - X(MASK_7) - X(MASK_8) - X(MASK_9) - X(MASK_10) - X(MASK_11) - X(MASK_12) - X(MASK_13) - X(MASK_14) - X(MASK_15) + X(MASK_0) + X(MASK_1) + X(MASK_2) + X(MASK_3) + X(MASK_4) + X(MASK_5) + X(MASK_6) + X(MASK_7) + X(MASK_8) + X(MASK_9) + X(MASK_10) + X(MASK_11) + X(MASK_12) + X(MASK_13) + X(MASK_14) + X(MASK_15) - X(RDATA_0) - X(RDATA_1) - X(RDATA_2) - X(RDATA_3) - X(RDATA_4) - X(RDATA_5) - X(RDATA_6) - X(RDATA_7) - X(RDATA_8) - X(RDATA_9) - X(RDATA_10) - X(RDATA_11) - X(RDATA_12) - X(RDATA_13) - X(RDATA_14) - X(RDATA_15) + X(RDATA_0) + X(RDATA_1) + X(RDATA_2) + X(RDATA_3) + X(RDATA_4) + X(RDATA_5) + X(RDATA_6) + X(RDATA_7) + X(RDATA_8) + X(RDATA_9) + X(RDATA_10) + X(RDATA_11) + X(RDATA_12) + X(RDATA_13) + X(RDATA_14) + X(RDATA_15) - X(WDATA_0) - X(WDATA_1) - X(WDATA_2) - X(WDATA_3) - X(WDATA_4) - X(WDATA_5) - X(WDATA_6) - X(WDATA_7) - X(WDATA_8) - X(WDATA_9) - X(WDATA_10) - X(WDATA_11) - X(WDATA_12) - X(WDATA_13) - X(WDATA_14) - X(WDATA_15) + X(WDATA_0) + X(WDATA_1) + X(WDATA_2) + X(WDATA_3) + X(WDATA_4) + X(WDATA_5) + X(WDATA_6) + X(WDATA_7) + X(WDATA_8) + X(WDATA_9) + X(WDATA_10) + X(WDATA_11) + X(WDATA_12) + X(WDATA_13) + X(WDATA_14) + X(WDATA_15) - X(WADDR_0) - X(WADDR_1) - X(WADDR_2) - X(WADDR_3) - X(WADDR_4) - X(WADDR_5) - X(WADDR_6) - X(WADDR_7) - X(WADDR_8) - X(WADDR_9) - X(WADDR_10) + X(WADDR_0) + X(WADDR_1) + X(WADDR_2) + X(WADDR_3) + X(WADDR_4) + X(WADDR_5) + X(WADDR_6) + X(WADDR_7) + X(WADDR_8) + X(WADDR_9) + X(WADDR_10) - X(RADDR_0) - X(RADDR_1) - X(RADDR_2) - X(RADDR_3) - X(RADDR_4) - X(RADDR_5) - X(RADDR_6) - X(RADDR_7) - X(RADDR_8) - X(RADDR_9) - X(RADDR_10) + X(RADDR_0) + X(RADDR_1) + X(RADDR_2) + X(RADDR_3) + X(RADDR_4) + X(RADDR_5) + X(RADDR_6) + X(RADDR_7) + X(RADDR_8) + X(RADDR_9) + X(RADDR_10) - X(WCLK) - X(WCLKE) - X(WE) + X(WCLK) + X(WCLKE) + X(WE) - X(RCLK) - X(RCLKE) - X(RE) + X(RCLK) + X(RCLKE) + X(RE) - X(PACKAGE_PIN) - X(LATCH_INPUT_VALUE) - X(CLOCK_ENABLE) - X(INPUT_CLK) - X(OUTPUT_CLK) - X(OUTPUT_ENABLE) - X(D_OUT_0) - X(D_OUT_1) - X(D_IN_0) - X(D_IN_1) + X(PACKAGE_PIN) + X(LATCH_INPUT_VALUE) + X(CLOCK_ENABLE) + X(INPUT_CLK) + X(OUTPUT_CLK) + X(OUTPUT_ENABLE) + X(D_OUT_0) + X(D_OUT_1) + X(D_IN_0) + X(D_IN_1) #undef X - return PIN_NIL; + return PIN_NIL; } // ----------------------------------------------------------------------- @@ -278,212 +282,211 @@ PortPin PortPinFromId(IdString id) Chip::Chip(ChipArgs args) { #ifdef ICE40_HX1K_ONLY - if (args.type == ChipArgs::HX1K) { - chip_info = chip_info_1k; - return; - } + if (args.type == ChipArgs::HX1K) { + chip_info = chip_info_1k; + return; + } #else - if (args.type == ChipArgs::LP384) { - chip_info = chip_info_384; - return; - } else if (args.type == ChipArgs::LP1K || args.type == ChipArgs::HX1K) { - chip_info = chip_info_1k; - return; - } else if (args.type == ChipArgs::UP5K) { - chip_info = chip_info_5k; - return; - } else if (args.type == ChipArgs::LP8K || args.type == ChipArgs::HX8K) { - chip_info = chip_info_8k; - return; - } else { - fprintf(stderr, "Unsupported chip type\n"); - exit(EXIT_FAILURE); - } + if (args.type == ChipArgs::LP384) { + chip_info = chip_info_384; + return; + } else if (args.type == ChipArgs::LP1K || args.type == ChipArgs::HX1K) { + chip_info = chip_info_1k; + return; + } else if (args.type == ChipArgs::UP5K) { + chip_info = chip_info_5k; + return; + } else if (args.type == ChipArgs::LP8K || args.type == ChipArgs::HX8K) { + chip_info = chip_info_8k; + return; + } else { + fprintf(stderr, "Unsupported chip type\n"); + exit(EXIT_FAILURE); + } #endif - abort(); + abort(); } // ----------------------------------------------------------------------- BelId Chip::getBelByName(IdString name) const { - BelId ret; + BelId ret; - if (bel_by_name.empty()) { - for (int i = 0; i < chip_info.num_bels; i++) - bel_by_name[chip_info.bel_data[i].name] = i; - } + if (bel_by_name.empty()) { + for (int i = 0; i < chip_info.num_bels; i++) + bel_by_name[chip_info.bel_data[i].name] = i; + } - auto it = bel_by_name.find(name); - if (it != bel_by_name.end()) - ret.index = it->second; + auto it = bel_by_name.find(name); + if (it != bel_by_name.end()) + ret.index = it->second; - return ret; + return ret; } WireId Chip::getWireBelPin(BelId bel, PortPin pin) const { - // FIXME - return WireId(); + // FIXME + return WireId(); } // ----------------------------------------------------------------------- WireId Chip::getWireByName(IdString name) const { - WireId ret; + WireId ret; - if (wire_by_name.empty()) { - for (int i = 0; i < chip_info.num_wires; i++) - wire_by_name[chip_info.wire_data[i].name] = i; - } + if (wire_by_name.empty()) { + for (int i = 0; i < chip_info.num_wires; i++) + wire_by_name[chip_info.wire_data[i].name] = i; + } - auto it = wire_by_name.find(name); - if (it != wire_by_name.end()) - ret.index = it->second; + auto it = wire_by_name.find(name); + if (it != wire_by_name.end()) + ret.index = it->second; - return ret; + return ret; } // ----------------------------------------------------------------------- PipId Chip::getPipByName(IdString name) const { - PipId ret; + PipId ret; - if (pip_by_name.empty()) { - for (int i = 0; i < chip_info.num_pips; i++) { - PipId pip; - pip.index = i; - pip_by_name[getPipName(pip)] = i; - } - } + if (pip_by_name.empty()) { + for (int i = 0; i < chip_info.num_pips; i++) { + PipId pip; + pip.index = i; + pip_by_name[getPipName(pip)] = i; + } + } - auto it = pip_by_name.find(name); - if (it != pip_by_name.end()) - ret.index = it->second; + auto it = pip_by_name.find(name); + if (it != pip_by_name.end()) + ret.index = it->second; - return ret; + return ret; } // ----------------------------------------------------------------------- void Chip::getBelPosition(BelId bel, float &x, float &y) const { - assert(!bel.nil()); - x = chip_info.bel_data[bel.index].x; - y = chip_info.bel_data[bel.index].y; + assert(!bel.nil()); + x = chip_info.bel_data[bel.index].x; + y = chip_info.bel_data[bel.index].y; } void Chip::getWirePosition(WireId wire, float &x, float &y) const { - assert(!wire.nil()); - x = chip_info.wire_data[wire.index].x; - y = chip_info.wire_data[wire.index].y; + assert(!wire.nil()); + x = chip_info.wire_data[wire.index].x; + y = chip_info.wire_data[wire.index].y; } void Chip::getPipPosition(PipId pip, float &x, float &y) const { - assert(!pip.nil()); - x = chip_info.pip_data[pip.index].x; - y = chip_info.pip_data[pip.index].y; + assert(!pip.nil()); + x = chip_info.pip_data[pip.index].x; + y = chip_info.pip_data[pip.index].y; } vector Chip::getBelGraphics(BelId bel) const { - vector ret; + vector ret; - auto bel_type = getBelType(bel); + auto bel_type = getBelType(bel); - if (bel_type == TYPE_ICESTORM_LC) { - GraphicElement el; - el.type = GraphicElement::G_BOX; - el.x1 = chip_info.bel_data[bel.index].x + 0.1; - el.x2 = chip_info.bel_data[bel.index].x + 0.9; - el.y1 = chip_info.bel_data[bel.index].y + 0.10 + (chip_info.bel_data[bel.index].z) * (0.8/8); - el.y2 = chip_info.bel_data[bel.index].y + 0.18 + (chip_info.bel_data[bel.index].z) * (0.8/8); - el.z = 0; - ret.push_back(el); - } + if (bel_type == TYPE_ICESTORM_LC) { + GraphicElement el; + el.type = GraphicElement::G_BOX; + el.x1 = chip_info.bel_data[bel.index].x + 0.1; + el.x2 = chip_info.bel_data[bel.index].x + 0.9; + el.y1 = chip_info.bel_data[bel.index].y + 0.10 + + (chip_info.bel_data[bel.index].z) * (0.8 / 8); + el.y2 = chip_info.bel_data[bel.index].y + 0.18 + + (chip_info.bel_data[bel.index].z) * (0.8 / 8); + el.z = 0; + ret.push_back(el); + } - if (bel_type == TYPE_SB_IO) { - if (chip_info.bel_data[bel.index].x == 0 || chip_info.bel_data[bel.index].x == chip_info.width-1) - { - GraphicElement el; - el.type = GraphicElement::G_BOX; - el.x1 = chip_info.bel_data[bel.index].x + 0.1; - el.x2 = chip_info.bel_data[bel.index].x + 0.9; - if (chip_info.bel_data[bel.index].z == 0) { - el.y1 = chip_info.bel_data[bel.index].y + 0.10; - el.y2 = chip_info.bel_data[bel.index].y + 0.45; - } else { - el.y1 = chip_info.bel_data[bel.index].y + 0.55; - el.y2 = chip_info.bel_data[bel.index].y + 0.90; - } - el.z = 0; - ret.push_back(el); - } - else - { - GraphicElement el; - el.type = GraphicElement::G_BOX; - if (chip_info.bel_data[bel.index].z == 0) { - el.x1 = chip_info.bel_data[bel.index].x + 0.10; - el.x2 = chip_info.bel_data[bel.index].x + 0.45; - } else { - el.x1 = chip_info.bel_data[bel.index].x + 0.55; - el.x2 = chip_info.bel_data[bel.index].x + 0.90; - } - el.y1 = chip_info.bel_data[bel.index].y + 0.1; - el.y2 = chip_info.bel_data[bel.index].y + 0.9; - el.z = 0; - ret.push_back(el); - } - } + if (bel_type == TYPE_SB_IO) { + if (chip_info.bel_data[bel.index].x == 0 || + chip_info.bel_data[bel.index].x == chip_info.width - 1) { + GraphicElement el; + el.type = GraphicElement::G_BOX; + el.x1 = chip_info.bel_data[bel.index].x + 0.1; + el.x2 = chip_info.bel_data[bel.index].x + 0.9; + if (chip_info.bel_data[bel.index].z == 0) { + el.y1 = chip_info.bel_data[bel.index].y + 0.10; + el.y2 = chip_info.bel_data[bel.index].y + 0.45; + } else { + el.y1 = chip_info.bel_data[bel.index].y + 0.55; + el.y2 = chip_info.bel_data[bel.index].y + 0.90; + } + el.z = 0; + ret.push_back(el); + } else { + GraphicElement el; + el.type = GraphicElement::G_BOX; + if (chip_info.bel_data[bel.index].z == 0) { + el.x1 = chip_info.bel_data[bel.index].x + 0.10; + el.x2 = chip_info.bel_data[bel.index].x + 0.45; + } else { + el.x1 = chip_info.bel_data[bel.index].x + 0.55; + el.x2 = chip_info.bel_data[bel.index].x + 0.90; + } + el.y1 = chip_info.bel_data[bel.index].y + 0.1; + el.y2 = chip_info.bel_data[bel.index].y + 0.9; + el.z = 0; + ret.push_back(el); + } + } - if (bel_type == TYPE_ICESTORM_RAM) { - GraphicElement el; - el.type = GraphicElement::G_BOX; - el.x1 = chip_info.bel_data[bel.index].x + 0.1; - el.x2 = chip_info.bel_data[bel.index].x + 0.9; - el.y1 = chip_info.bel_data[bel.index].y + 0.1; - el.y2 = chip_info.bel_data[bel.index].y + 1.9; - el.z = 0; - ret.push_back(el); - } + if (bel_type == TYPE_ICESTORM_RAM) { + GraphicElement el; + el.type = GraphicElement::G_BOX; + el.x1 = chip_info.bel_data[bel.index].x + 0.1; + el.x2 = chip_info.bel_data[bel.index].x + 0.9; + el.y1 = chip_info.bel_data[bel.index].y + 0.1; + el.y2 = chip_info.bel_data[bel.index].y + 1.9; + el.z = 0; + ret.push_back(el); + } - return ret; + return ret; } vector Chip::getWireGraphics(WireId wire) const { - vector ret; - // FIXME - return ret; + vector ret; + // FIXME + return ret; } vector Chip::getPipGraphics(PipId pip) const { - vector ret; - // FIXME - return ret; + vector ret; + // FIXME + return ret; } vector Chip::getFrameGraphics() const { - vector ret; + vector ret; - for (int x = 0; x <= chip_info.width; x++) - for (int y = 0; y <= chip_info.height; y++) - { - GraphicElement el; - el.type = GraphicElement::G_LINE; - el.x1 = x - 0.05, el.x2 = x + 0.05, el.y1 = y, el.y2 = y, el.z = 0; - ret.push_back(el); - el.x1 = x, el.x2 = x, el.y1 = y - 0.05, el.y2 = y + 0.05, el.z = 0; - ret.push_back(el); - } + for (int x = 0; x <= chip_info.width; x++) + for (int y = 0; y <= chip_info.height; y++) { + GraphicElement el; + el.type = GraphicElement::G_LINE; + el.x1 = x - 0.05, el.x2 = x + 0.05, el.y1 = y, el.y2 = y, el.z = 0; + ret.push_back(el); + el.x1 = x, el.x2 = x, el.y1 = y - 0.05, el.y2 = y + 0.05, el.z = 0; + ret.push_back(el); + } - return ret; + return ret; } diff --git a/ice40/chip.h b/ice40/chip.h index 2f0a1284..695eea48 100644 --- a/ice40/chip.h +++ b/ice40/chip.h @@ -24,20 +24,20 @@ struct DelayInfo { - float delay = 0; + float delay = 0; - float raiseDelay() { return delay; } - float fallDelay() { return delay; } + float raiseDelay() { return delay; } + float fallDelay() { return delay; } }; // ----------------------------------------------------------------------- enum BelType { - TYPE_NIL, - TYPE_ICESTORM_LC, - TYPE_ICESTORM_RAM, - TYPE_SB_IO + TYPE_NIL, + TYPE_ICESTORM_LC, + TYPE_ICESTORM_RAM, + TYPE_SB_IO }; IdString belTypeToId(BelType type); @@ -45,113 +45,113 @@ BelType belTypeFromId(IdString id); enum PortPin { - PIN_NIL, + PIN_NIL, - PIN_IN_0, - PIN_IN_1, - PIN_IN_2, - PIN_IN_3, - PIN_O, - PIN_LO, - PIN_CIN, - PIN_COUT, - PIN_CEN, - PIN_CLK, - PIN_SR, + PIN_IN_0, + PIN_IN_1, + PIN_IN_2, + PIN_IN_3, + PIN_O, + PIN_LO, + PIN_CIN, + PIN_COUT, + PIN_CEN, + PIN_CLK, + PIN_SR, - PIN_MASK_0, - PIN_MASK_1, - PIN_MASK_2, - PIN_MASK_3, - PIN_MASK_4, - PIN_MASK_5, - PIN_MASK_6, - PIN_MASK_7, - PIN_MASK_8, - PIN_MASK_9, - PIN_MASK_10, - PIN_MASK_11, - PIN_MASK_12, - PIN_MASK_13, - PIN_MASK_14, - PIN_MASK_15, + PIN_MASK_0, + PIN_MASK_1, + PIN_MASK_2, + PIN_MASK_3, + PIN_MASK_4, + PIN_MASK_5, + PIN_MASK_6, + PIN_MASK_7, + PIN_MASK_8, + PIN_MASK_9, + PIN_MASK_10, + PIN_MASK_11, + PIN_MASK_12, + PIN_MASK_13, + PIN_MASK_14, + PIN_MASK_15, - PIN_RDATA_0, - PIN_RDATA_1, - PIN_RDATA_2, - PIN_RDATA_3, - PIN_RDATA_4, - PIN_RDATA_5, - PIN_RDATA_6, - PIN_RDATA_7, - PIN_RDATA_8, - PIN_RDATA_9, - PIN_RDATA_10, - PIN_RDATA_11, - PIN_RDATA_12, - PIN_RDATA_13, - PIN_RDATA_14, - PIN_RDATA_15, + PIN_RDATA_0, + PIN_RDATA_1, + PIN_RDATA_2, + PIN_RDATA_3, + PIN_RDATA_4, + PIN_RDATA_5, + PIN_RDATA_6, + PIN_RDATA_7, + PIN_RDATA_8, + PIN_RDATA_9, + PIN_RDATA_10, + PIN_RDATA_11, + PIN_RDATA_12, + PIN_RDATA_13, + PIN_RDATA_14, + PIN_RDATA_15, - PIN_WDATA_0, - PIN_WDATA_1, - PIN_WDATA_2, - PIN_WDATA_3, - PIN_WDATA_4, - PIN_WDATA_5, - PIN_WDATA_6, - PIN_WDATA_7, - PIN_WDATA_8, - PIN_WDATA_9, - PIN_WDATA_10, - PIN_WDATA_11, - PIN_WDATA_12, - PIN_WDATA_13, - PIN_WDATA_14, - PIN_WDATA_15, + PIN_WDATA_0, + PIN_WDATA_1, + PIN_WDATA_2, + PIN_WDATA_3, + PIN_WDATA_4, + PIN_WDATA_5, + PIN_WDATA_6, + PIN_WDATA_7, + PIN_WDATA_8, + PIN_WDATA_9, + PIN_WDATA_10, + PIN_WDATA_11, + PIN_WDATA_12, + PIN_WDATA_13, + PIN_WDATA_14, + PIN_WDATA_15, - PIN_WADDR_0, - PIN_WADDR_1, - PIN_WADDR_2, - PIN_WADDR_3, - PIN_WADDR_4, - PIN_WADDR_5, - PIN_WADDR_6, - PIN_WADDR_7, - PIN_WADDR_8, - PIN_WADDR_9, - PIN_WADDR_10, + PIN_WADDR_0, + PIN_WADDR_1, + PIN_WADDR_2, + PIN_WADDR_3, + PIN_WADDR_4, + PIN_WADDR_5, + PIN_WADDR_6, + PIN_WADDR_7, + PIN_WADDR_8, + PIN_WADDR_9, + PIN_WADDR_10, - PIN_RADDR_0, - PIN_RADDR_1, - PIN_RADDR_2, - PIN_RADDR_3, - PIN_RADDR_4, - PIN_RADDR_5, - PIN_RADDR_6, - PIN_RADDR_7, - PIN_RADDR_8, - PIN_RADDR_9, - PIN_RADDR_10, + PIN_RADDR_0, + PIN_RADDR_1, + PIN_RADDR_2, + PIN_RADDR_3, + PIN_RADDR_4, + PIN_RADDR_5, + PIN_RADDR_6, + PIN_RADDR_7, + PIN_RADDR_8, + PIN_RADDR_9, + PIN_RADDR_10, - PIN_WCLK, - PIN_WCLKE, - PIN_WE, + PIN_WCLK, + PIN_WCLKE, + PIN_WE, - PIN_RCLK, - PIN_RCLKE, - PIN_RE, + PIN_RCLK, + PIN_RCLKE, + PIN_RE, - PIN_PACKAGE_PIN, - PIN_LATCH_INPUT_VALUE, - PIN_CLOCK_ENABLE, - PIN_INPUT_CLK, - PIN_OUTPUT_CLK, - PIN_OUTPUT_ENABLE, - PIN_D_OUT_0, - PIN_D_OUT_1, - PIN_D_IN_0, - PIN_D_IN_1 + PIN_PACKAGE_PIN, + PIN_LATCH_INPUT_VALUE, + PIN_CLOCK_ENABLE, + PIN_INPUT_CLK, + PIN_OUTPUT_CLK, + PIN_OUTPUT_ENABLE, + PIN_D_OUT_0, + PIN_D_OUT_1, + PIN_D_IN_0, + PIN_D_IN_1 }; IdString PortPinToId(PortPin type); @@ -159,47 +159,46 @@ PortPin PortPinFromId(IdString id); // ----------------------------------------------------------------------- - struct BelInfoPOD { - const char *name; - BelType type; - int8_t x, y, z; + const char *name; + BelType type; + int8_t x, y, z; }; struct BelPortPOD { - int32_t bel_index; - PortPin port; + int32_t bel_index; + PortPin port; }; struct PipInfoPOD { - int32_t src, dst; - float delay; - int8_t x, y; + int32_t src, dst; + float delay; + int8_t x, y; }; struct WireInfoPOD { - const char *name; - int num_uphill, num_downhill; - int *pips_uphill, *pips_downhill; + const char *name; + int num_uphill, num_downhill; + int *pips_uphill, *pips_downhill; - int num_bels_downhill; - BelPortPOD bel_uphill; - BelPortPOD *bels_downhill; + int num_bels_downhill; + BelPortPOD bel_uphill; + BelPortPOD *bels_downhill; - float x, y; + float x, y; }; struct ChipInfoPOD { - int width, height; - int num_bels, num_wires, num_pips; - BelInfoPOD *bel_data; - WireInfoPOD *wire_data; - PipInfoPOD *pip_data; + int width, height; + int num_bels, num_wires, num_pips; + BelInfoPOD *bel_data; + WireInfoPOD *wire_data; + PipInfoPOD *pip_data; }; extern ChipInfoPOD chip_info_384; @@ -211,248 +210,256 @@ extern ChipInfoPOD chip_info_8k; struct BelId { - int32_t index = -1; + int32_t index = -1; - bool nil() const { - return index < 0; - } + bool nil() const { return index < 0; } - bool operator==(const BelId &other) const { return index == other.index; } - bool operator!=(const BelId &other) const { return index != other.index; } + bool operator==(const BelId &other) const { return index == other.index; } + bool operator!=(const BelId &other) const { return index != other.index; } }; struct WireId { - int32_t index = -1; + int32_t index = -1; - bool nil() const { - return index < 0; - } + bool nil() const { return index < 0; } - bool operator==(const WireId &other) const { return index == other.index; } - bool operator!=(const WireId &other) const { return index != other.index; } + bool operator==(const WireId &other) const { return index == other.index; } + bool operator!=(const WireId &other) const { return index != other.index; } }; struct PipId { - int32_t index = -1; + int32_t index = -1; - bool nil() const { - return index < 0; - } + bool nil() const { return index < 0; } - bool operator==(const PipId &other) const { return index == other.index; } - bool operator!=(const PipId &other) const { return index != other.index; } + bool operator==(const PipId &other) const { return index == other.index; } + bool operator!=(const PipId &other) const { return index != other.index; } }; struct BelPin { - BelId bel; - PortPin pin; + BelId bel; + PortPin pin; }; -namespace std +namespace std { +template <> struct hash { - template<> struct hash - { - std::size_t operator()(const BelId &bel) const noexcept - { - return bel.index; - } - }; + std::size_t operator()(const BelId &bel) const noexcept + { + return bel.index; + } +}; - template<> struct hash - { - std::size_t operator()(const WireId &wire) const noexcept - { - return wire.index; - } - }; +template <> struct hash +{ + std::size_t operator()(const WireId &wire) const noexcept + { + return wire.index; + } +}; - template<> struct hash - { - std::size_t operator()(const PipId &wire) const noexcept - { - return wire.index; - } - }; +template <> struct hash +{ + std::size_t operator()(const PipId &wire) const noexcept + { + return wire.index; + } +}; } // ----------------------------------------------------------------------- struct BelIterator { - int cursor; + int cursor; - void operator++() { cursor++; } - bool operator!=(const BelIterator &other) const { return cursor != other.cursor; } + void operator++() { cursor++; } + bool operator!=(const BelIterator &other) const + { + return cursor != other.cursor; + } - BelId operator*() const { - BelId ret; - ret.index = cursor; - return ret; - } + BelId operator*() const + { + BelId ret; + ret.index = cursor; + return ret; + } }; struct BelRange { - BelIterator b, e; - BelIterator begin() const { return b; } - BelIterator end() const { return e; } + BelIterator b, e; + BelIterator begin() const { return b; } + BelIterator end() const { return e; } }; // ----------------------------------------------------------------------- struct BelPinIterator { - BelPortPOD *ptr = nullptr; + BelPortPOD *ptr = nullptr; - void operator++() { ptr++; } - bool operator!=(const BelPinIterator &other) const { return ptr != other.ptr; } + void operator++() { ptr++; } + bool operator!=(const BelPinIterator &other) const + { + return ptr != other.ptr; + } - BelPin operator*() const { - BelPin ret; - ret.bel.index = ptr->bel_index; - ret.pin = ptr->port; - return ret; - } + BelPin operator*() const + { + BelPin ret; + ret.bel.index = ptr->bel_index; + ret.pin = ptr->port; + return ret; + } }; struct BelPinRange { - BelPinIterator b, e; - BelPinIterator begin() const { return b; } - BelPinIterator end() const { return e; } + BelPinIterator b, e; + BelPinIterator begin() const { return b; } + BelPinIterator end() const { return e; } }; // ----------------------------------------------------------------------- struct WireIterator { - int cursor = -1; + int cursor = -1; - void operator++() { cursor++; } - bool operator!=(const WireIterator &other) const { return cursor != other.cursor; } + void operator++() { cursor++; } + bool operator!=(const WireIterator &other) const + { + return cursor != other.cursor; + } - WireId operator*() const { - WireId ret; - ret.index = cursor; - return ret; - } + WireId operator*() const + { + WireId ret; + ret.index = cursor; + return ret; + } }; struct WireRange { - WireIterator b, e; - WireIterator begin() const { return b; } - WireIterator end() const { return e; } + WireIterator b, e; + WireIterator begin() const { return b; } + WireIterator end() const { return e; } }; // ----------------------------------------------------------------------- struct AllPipIterator { - int cursor = -1; + int cursor = -1; - void operator++() { cursor++; } - bool operator!=(const AllPipIterator &other) const { return cursor != other.cursor; } + void operator++() { cursor++; } + bool operator!=(const AllPipIterator &other) const + { + return cursor != other.cursor; + } - PipId operator*() const { - PipId ret; - ret.index = cursor; - return ret; - } + PipId operator*() const + { + PipId ret; + ret.index = cursor; + return ret; + } }; struct AllPipRange { - AllPipIterator b, e; - AllPipIterator begin() const { return b; } - AllPipIterator end() const { return e; } + AllPipIterator b, e; + AllPipIterator begin() const { return b; } + AllPipIterator end() const { return e; } }; // ----------------------------------------------------------------------- struct PipIterator { - int *cursor = nullptr; + int *cursor = nullptr; - void operator++() { cursor++; } - bool operator!=(const PipIterator &other) const { return cursor != other.cursor; } + void operator++() { cursor++; } + bool operator!=(const PipIterator &other) const + { + return cursor != other.cursor; + } - PipId operator*() const { - PipId ret; - ret.index = *cursor; - return ret; - } + PipId operator*() const + { + PipId ret; + ret.index = *cursor; + return ret; + } }; struct PipRange { - PipIterator b, e; - PipIterator begin() const { return b; } - PipIterator end() const { return e; } + PipIterator b, e; + PipIterator begin() const { return b; } + PipIterator end() const { return e; } }; // ----------------------------------------------------------------------- struct ChipArgs { - enum { - NONE, - LP384, - LP1K, - LP8K, - HX1K, - HX8K, - UP5K - } type = NONE; + enum + { + NONE, + LP384, + LP1K, + LP8K, + HX1K, + HX8K, + UP5K + } type = NONE; }; struct Chip { - ChipInfoPOD chip_info; + ChipInfoPOD chip_info; - mutable dict bel_by_name; - mutable dict wire_by_name; - mutable dict pip_by_name; + mutable dict bel_by_name; + mutable dict wire_by_name; + mutable dict pip_by_name; - Chip(ChipArgs args); + Chip(ChipArgs args); - // ------------------------------------------------- + // ------------------------------------------------- - BelId getBelByName(IdString name) const; + BelId getBelByName(IdString name) const; - IdString getBelName(BelId bel) const - { - assert(!bel.nil()); - return chip_info.bel_data[bel.index].name; - } + IdString getBelName(BelId bel) const + { + assert(!bel.nil()); + return chip_info.bel_data[bel.index].name; + } - void bindBel(BelId bel, IdString cell) - { - } + void bindBel(BelId bel, IdString cell) {} - void unbindBel(BelId bel) - { - } + void unbindBel(BelId bel) {} - bool checkBelAvail(BelId bel) const - { - } + bool checkBelAvail(BelId bel) const {} - BelRange getBels() const - { - BelRange range; - range.b.cursor = 0; - range.e.cursor = chip_info.num_bels; - return range; - } + BelRange getBels() const + { + BelRange range; + range.b.cursor = 0; + range.e.cursor = chip_info.num_bels; + return range; + } - BelRange getBelsByType(BelType type) const - { - BelRange range; - // FIXME + BelRange getBelsByType(BelType type) const + { + BelRange range; +// FIXME #if 0 if (type == "TYPE_A") { range.b.cursor = bels_type_a_begin; @@ -460,161 +467,155 @@ struct Chip } ... #endif - return range; - } + return range; + } - BelType getBelType(BelId bel) const - { - assert(!bel.nil()); - return chip_info.bel_data[bel.index].type; - } + BelType getBelType(BelId bel) const + { + assert(!bel.nil()); + return chip_info.bel_data[bel.index].type; + } - WireId getWireBelPin(BelId bel, PortPin pin) const; + WireId getWireBelPin(BelId bel, PortPin pin) const; - BelPin getBelPinUphill(WireId wire) const - { - BelPin ret; - assert(!wire.nil()); + BelPin getBelPinUphill(WireId wire) const + { + BelPin ret; + assert(!wire.nil()); - if (chip_info.wire_data[wire.index].bel_uphill.bel_index >= 0) { - ret.bel.index = chip_info.wire_data[wire.index].bel_uphill.bel_index; - ret.pin = chip_info.wire_data[wire.index].bel_uphill.port; - } + if (chip_info.wire_data[wire.index].bel_uphill.bel_index >= 0) { + ret.bel.index = + chip_info.wire_data[wire.index].bel_uphill.bel_index; + ret.pin = chip_info.wire_data[wire.index].bel_uphill.port; + } - return ret; - } + return ret; + } - BelPinRange getBelPinsDownhill(WireId wire) const - { - BelPinRange range; - assert(!wire.nil()); - range.b.ptr = chip_info.wire_data[wire.index].bels_downhill; - range.e.ptr = range.b.ptr + chip_info.wire_data[wire.index].num_bels_downhill; - return range; - } + BelPinRange getBelPinsDownhill(WireId wire) const + { + BelPinRange range; + assert(!wire.nil()); + range.b.ptr = chip_info.wire_data[wire.index].bels_downhill; + range.e.ptr = + range.b.ptr + chip_info.wire_data[wire.index].num_bels_downhill; + return range; + } - // ------------------------------------------------- + // ------------------------------------------------- - WireId getWireByName(IdString name) const; + WireId getWireByName(IdString name) const; - IdString getWireName(WireId wire) const - { - assert(!wire.nil()); - return chip_info.wire_data[wire.index].name; - } + IdString getWireName(WireId wire) const + { + assert(!wire.nil()); + return chip_info.wire_data[wire.index].name; + } - void bindWire(WireId bel, IdString net) - { - } + void bindWire(WireId bel, IdString net) {} - void unbindWire(WireId bel) - { - } + void unbindWire(WireId bel) {} - bool checkWireAvail(WireId bel) const - { - } + bool checkWireAvail(WireId bel) const {} - WireRange getWires() const - { - WireRange range; - range.b.cursor = 0; - range.e.cursor = chip_info.num_wires; - return range; - } + WireRange getWires() const + { + WireRange range; + range.b.cursor = 0; + range.e.cursor = chip_info.num_wires; + return range; + } - // ------------------------------------------------- + // ------------------------------------------------- - PipId getPipByName(IdString name) const; + PipId getPipByName(IdString name) const; - IdString getPipName(PipId pip) const - { - assert(!pip.nil()); - std::string src_name = chip_info.wire_data[chip_info.pip_data[pip.index].src].name; - std::string dst_name = chip_info.wire_data[chip_info.pip_data[pip.index].dst].name; - return src_name + "->" + dst_name; - } + IdString getPipName(PipId pip) const + { + assert(!pip.nil()); + std::string src_name = + chip_info.wire_data[chip_info.pip_data[pip.index].src].name; + std::string dst_name = + chip_info.wire_data[chip_info.pip_data[pip.index].dst].name; + return src_name + "->" + dst_name; + } - void bindPip(PipId bel, IdString net) - { - } + void bindPip(PipId bel, IdString net) {} - void unbindPip(PipId bel) - { - } + void unbindPip(PipId bel) {} - bool checkPipAvail(PipId bel) const - { - } + bool checkPipAvail(PipId bel) const {} - AllPipRange getPips() const - { - AllPipRange range; - range.b.cursor = 0; - range.e.cursor = chip_info.num_pips; - return range; - } + AllPipRange getPips() const + { + AllPipRange range; + range.b.cursor = 0; + range.e.cursor = chip_info.num_pips; + return range; + } - WireId getPipSrcWire(PipId pip) const - { - WireId wire; - assert(!pip.nil()); - wire.index = chip_info.pip_data[pip.index].src; - return wire; - } + WireId getPipSrcWire(PipId pip) const + { + WireId wire; + assert(!pip.nil()); + wire.index = chip_info.pip_data[pip.index].src; + return wire; + } - WireId getPipDstWire(PipId pip) const - { - WireId wire; - assert(!pip.nil()); - wire.index = chip_info.pip_data[pip.index].dst; - return wire; - } + WireId getPipDstWire(PipId pip) const + { + WireId wire; + assert(!pip.nil()); + wire.index = chip_info.pip_data[pip.index].dst; + return wire; + } - DelayInfo getPipDelay(PipId pip) const - { - DelayInfo delay; - assert(!pip.nil()); - delay.delay = chip_info.pip_data[pip.index].delay; - return delay; - } + DelayInfo getPipDelay(PipId pip) const + { + DelayInfo delay; + assert(!pip.nil()); + delay.delay = chip_info.pip_data[pip.index].delay; + return delay; + } - PipRange getPipsDownhill(WireId wire) const - { - PipRange range; - assert(!wire.nil()); - range.b.cursor = chip_info.wire_data[wire.index].pips_downhill; - range.e.cursor = range.b.cursor + chip_info.wire_data[wire.index].num_downhill; - return range; - } + PipRange getPipsDownhill(WireId wire) const + { + PipRange range; + assert(!wire.nil()); + range.b.cursor = chip_info.wire_data[wire.index].pips_downhill; + range.e.cursor = + range.b.cursor + chip_info.wire_data[wire.index].num_downhill; + return range; + } - PipRange getPipsUphill(WireId wire) const - { - PipRange range; - assert(!wire.nil()); - range.b.cursor = chip_info.wire_data[wire.index].pips_uphill; - range.e.cursor = range.b.cursor + chip_info.wire_data[wire.index].num_uphill; - return range; - } + PipRange getPipsUphill(WireId wire) const + { + PipRange range; + assert(!wire.nil()); + range.b.cursor = chip_info.wire_data[wire.index].pips_uphill; + range.e.cursor = + range.b.cursor + chip_info.wire_data[wire.index].num_uphill; + return range; + } - PipRange getWireAliases(WireId wire) const - { - PipRange range; - assert(!wire.nil()); - range.b.cursor = nullptr; - range.e.cursor = nullptr; - return range; - } + PipRange getWireAliases(WireId wire) const + { + PipRange range; + assert(!wire.nil()); + range.b.cursor = nullptr; + range.e.cursor = nullptr; + return range; + } - // ------------------------------------------------- + // ------------------------------------------------- - void getBelPosition(BelId bel, float &x, float &y) const; - void getWirePosition(WireId wire, float &x, float &y) const; - void getPipPosition(PipId pip, float &x, float &y) const; - vector getBelGraphics(BelId bel) const; - vector getWireGraphics(WireId wire) const; - vector getPipGraphics(PipId pip) const; - vector getFrameGraphics() const; + void getBelPosition(BelId bel, float &x, float &y) const; + void getWirePosition(WireId wire, float &x, float &y) const; + void getPipPosition(PipId pip, float &x, float &y) const; + vector getBelGraphics(BelId bel) const; + vector getWireGraphics(WireId wire) const; + vector getPipGraphics(PipId pip) const; + vector getFrameGraphics() const; }; #endif From b0e66d441cf584e7e48049d4f07afcc8e743309a Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 7 Jun 2018 12:57:52 +0200 Subject: [PATCH 14/18] Global design object working Signed-off-by: David Shah --- common/pybindings.cc | 6 ++++++ common/pybindings.h | 2 +- ice40/main.cc | 2 +- python/dump_design.py | 8 ++++++-- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/common/pybindings.cc b/common/pybindings.cc index 4ae83cb0..a051eea6 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -66,6 +66,12 @@ BOOST_PYTHON_MODULE (MODULE_NAME) { class_>("PortRefVector") .def(vector_indexing_suite>()); + enum_("PortType") + .value("PORT_IN", PORT_IN) + .value("PORT_OUT", PORT_OUT) + .value("PORT_INOUT", PORT_INOUT) + .export_values(); + class_("PortInfo") .def_readwrite("name", &PortInfo::name) .def_readwrite("net", &PortInfo::net) diff --git a/common/pybindings.h b/common/pybindings.h index 44898198..a99ad51b 100644 --- a/common/pybindings.h +++ b/common/pybindings.h @@ -94,7 +94,7 @@ void python_export_global(const char *name, Tn &x) { return; d = PyModule_GetDict(m); try { - PyObject * p = object(boost::ref(x)).ptr(); + PyObject * p = incref(object(boost::ref(x)).ptr()); PyDict_SetItemString(d, name, p); } catch (boost::python::error_already_set const &) { // Parse and output the exception diff --git a/ice40/main.cc b/ice40/main.cc index 12c6b86c..88ef4155 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -205,7 +205,7 @@ int main(int argc, char *argv[]) parse_json_file(f, filename, &design); } - + if (vm.count("file")) { std::vector files = vm["file"].as>(); diff --git a/python/dump_design.py b/python/dump_design.py index 9d8ade3e..b8436288 100644 --- a/python/dump_design.py +++ b/python/dump_design.py @@ -1,2 +1,6 @@ -for cell in design.cells: - print(cell.first) +# Run ./nextpnr-ice40 --json ice40/blinky.json --file python/dump_design.py +for cell in sorted(design.cells, key=lambda x: x.first): + print("Cell {} : {}".format(cell.first, cell.second.type)) + for port in sorted(cell.second.ports, key=lambda x: x.first): + dir = (" <-- ", " --> ", " <-> ")[int(port.second.type)] + print(" {} {} {}".format(port.first, dir, port.second.net.name)) From 6236a1042797be90224461adf23243e0bb16f2fe Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 7 Jun 2018 13:08:18 +0200 Subject: [PATCH 15/18] Fixing file->run renaming Signed-off-by: David Shah --- ice40/main.cc | 2 +- python/dump_design.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ice40/main.cc b/ice40/main.cc index 445e81ba..18896142 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -236,7 +236,7 @@ int main(int argc, char *argv[]) if (vm.count("run")) { - std::vector files = vm["file"].as>(); + std::vector files = vm["run"].as>(); for(auto filename : files) execute_python_file(filename.c_str()); } diff --git a/python/dump_design.py b/python/dump_design.py index b8436288..22d4ab17 100644 --- a/python/dump_design.py +++ b/python/dump_design.py @@ -1,4 +1,4 @@ -# Run ./nextpnr-ice40 --json ice40/blinky.json --file python/dump_design.py +# Run ./nextpnr-ice40 --json ice40/blinky.json --run python/dump_design.py for cell in sorted(design.cells, key=lambda x: x.first): print("Cell {} : {}".format(cell.first, cell.second.type)) for port in sorted(cell.second.ports, key=lambda x: x.first): From c3e02527030c11f0177e3bf8d8c5d9a5c9925dc4 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 7 Jun 2018 13:10:53 +0200 Subject: [PATCH 16/18] Reformat Python bindings and ice40 main Signed-off-by: David Shah --- common/pybindings.cc | 192 ++++++++++----------- common/pybindings.h | 126 +++++++------- dummy/main.cc | 6 +- dummy/pybindings.cc | 6 +- ice40/main.cc | 391 ++++++++++++++++++++++--------------------- ice40/pybindings.cc | 8 +- 6 files changed, 368 insertions(+), 361 deletions(-) diff --git a/common/pybindings.cc b/common/pybindings.cc index c3818cad..5c86720e 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -18,134 +18,138 @@ * */ - -#include "design.h" #include "chip.h" +#include "design.h" #include "emb.h" // include after design.h/chip.h #include "pybindings.h" -// Required to determine concatenated module name (which differs for different archs) -#define PASTER(x, y) x ## _ ## y -#define EVALUATOR(x, y) PASTER(x,y) +// Required to determine concatenated module name (which differs for different +// archs) +#define PASTER(x, y) x##_##y +#define EVALUATOR(x, y) PASTER(x, y) #define MODULE_NAME EVALUATOR(nextpnrpy, ARCHNAME) #define PYINIT_MODULE_NAME EVALUATOR(&PyInit_nextpnrpy, ARCHNAME) #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) -// Architecture-specific bindings should be created in the below function, which must be implemented in all -// architectures +// Architecture-specific bindings should be created in the below function, which +// must be implemented in all architectures void arch_wrap_python(); -bool operator==(const PortRef &a, const PortRef &b) { - return (a.cell == b.cell) && (a.port == b.port); +bool operator==(const PortRef &a, const PortRef &b) +{ + return (a.cell == b.cell) && (a.port == b.port); } -BOOST_PYTHON_MODULE (MODULE_NAME) { - class_("GraphicElement") - .def_readwrite("style", &GraphicElement::style) - .def_readwrite("type", &GraphicElement::type) - .def_readwrite("x1", &GraphicElement::x1) - .def_readwrite("y1", &GraphicElement::y1) - .def_readwrite("x2", &GraphicElement::x2) - .def_readwrite("y2", &GraphicElement::y2) - .def_readwrite("text", &GraphicElement::text); +BOOST_PYTHON_MODULE(MODULE_NAME) +{ + class_("GraphicElement") + .def_readwrite("style", &GraphicElement::style) + .def_readwrite("type", &GraphicElement::type) + .def_readwrite("x1", &GraphicElement::x1) + .def_readwrite("y1", &GraphicElement::y1) + .def_readwrite("x2", &GraphicElement::x2) + .def_readwrite("y2", &GraphicElement::y2) + .def_readwrite("text", &GraphicElement::text); - class_("PortRef") - .def_readwrite("cell", &PortRef::cell) - .def_readwrite("port", &PortRef::port); + class_("PortRef") + .def_readwrite("cell", &PortRef::cell) + .def_readwrite("port", &PortRef::port); - class_("NetInfo") - .def_readwrite("name", &NetInfo::name) - .def_readwrite("driver", &NetInfo::driver) - .def_readwrite("users", &NetInfo::users) - .def_readwrite("attrs", &NetInfo::attrs) - .def_readwrite("wires", &NetInfo::wires); + class_("NetInfo") + .def_readwrite("name", &NetInfo::name) + .def_readwrite("driver", &NetInfo::driver) + .def_readwrite("users", &NetInfo::users) + .def_readwrite("attrs", &NetInfo::attrs) + .def_readwrite("wires", &NetInfo::wires); - WRAP_MAP(decltype(NetInfo::attrs), "IdStrMap"); + WRAP_MAP(decltype(NetInfo::attrs), "IdStrMap"); - class_>("PortRefVector") - .def(vector_indexing_suite>()); + class_>("PortRefVector") + .def(vector_indexing_suite>()); - enum_("PortType") - .value("PORT_IN", PORT_IN) - .value("PORT_OUT", PORT_OUT) - .value("PORT_INOUT", PORT_INOUT) - .export_values(); + enum_("PortType") + .value("PORT_IN", PORT_IN) + .value("PORT_OUT", PORT_OUT) + .value("PORT_INOUT", PORT_INOUT) + .export_values(); - class_("PortInfo") - .def_readwrite("name", &PortInfo::name) - .def_readwrite("net", &PortInfo::net) - .def_readwrite("type", &PortInfo::type); + class_("PortInfo") + .def_readwrite("name", &PortInfo::name) + .def_readwrite("net", &PortInfo::net) + .def_readwrite("type", &PortInfo::type); - class_("CellInfo") - .def_readwrite("name", &CellInfo::name) - .def_readwrite("type", &CellInfo::type) - .def_readwrite("ports", &CellInfo::ports) - .def_readwrite("attrs", &CellInfo::attrs) - .def_readwrite("params", &CellInfo::params) - .def_readwrite("bel", &CellInfo::bel) - .def_readwrite("pins", &CellInfo::pins); + class_("CellInfo") + .def_readwrite("name", &CellInfo::name) + .def_readwrite("type", &CellInfo::type) + .def_readwrite("ports", &CellInfo::ports) + .def_readwrite("attrs", &CellInfo::attrs) + .def_readwrite("params", &CellInfo::params) + .def_readwrite("bel", &CellInfo::bel) + .def_readwrite("pins", &CellInfo::pins); - WRAP_MAP(decltype(CellInfo::ports), "IdPortMap"); - //WRAP_MAP(decltype(CellInfo::pins), "IdIdMap"); + WRAP_MAP(decltype(CellInfo::ports), "IdPortMap"); + // WRAP_MAP(decltype(CellInfo::pins), "IdIdMap"); - class_("Design", no_init) - .def_readwrite("chip", &Design::chip) - .def_readwrite("nets", &Design::nets) - .def_readwrite("cells", &Design::cells); + class_("Design", no_init) + .def_readwrite("chip", &Design::chip) + .def_readwrite("nets", &Design::nets) + .def_readwrite("cells", &Design::cells); - WRAP_MAP(decltype(Design::nets), "IdNetMap"); - WRAP_MAP(decltype(Design::cells), "IdCellMap"); + WRAP_MAP(decltype(Design::nets), "IdNetMap"); + WRAP_MAP(decltype(Design::cells), "IdCellMap"); - arch_wrap_python(); + arch_wrap_python(); } -void arch_appendinittab() { - PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME); +void arch_appendinittab() +{ + PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME); } static wchar_t *program; -void init_python(const char *executable) { - program = Py_DecodeLocale(executable, NULL); - if (program == NULL) { - fprintf(stderr, "Fatal error: cannot decode executable filename\n"); - exit(1); - } - try { - PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME); - emb::append_inittab(); - Py_SetProgramName(program); - Py_Initialize(); - PyImport_ImportModule(TOSTRING(MODULE_NAME)); - } catch (boost::python::error_already_set const &) { - // Parse and output the exception - std::string perror_str = parse_python_exception(); - std::cout << "Error in Python: " << perror_str << std::endl; - } +void init_python(const char *executable) +{ + program = Py_DecodeLocale(executable, NULL); + if (program == NULL) { + fprintf(stderr, "Fatal error: cannot decode executable filename\n"); + exit(1); + } + try { + PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME); + emb::append_inittab(); + Py_SetProgramName(program); + Py_Initialize(); + PyImport_ImportModule(TOSTRING(MODULE_NAME)); + } catch (boost::python::error_already_set const &) { + // Parse and output the exception + std::string perror_str = parse_python_exception(); + std::cout << "Error in Python: " << perror_str << std::endl; + } } -void deinit_python() { - Py_Finalize(); - PyMem_RawFree(program); +void deinit_python() +{ + Py_Finalize(); + PyMem_RawFree(program); } -void execute_python_file(const char *python_file) { - try { - FILE *fp = fopen(python_file, "r"); - if (fp == NULL) { - fprintf(stderr, "Fatal error: file not found %s\n", python_file); - exit(1); - } - PyRun_SimpleFile(fp, python_file); - fclose(fp); - } - catch (boost::python::error_already_set const &) { - // Parse and output the exception - std::string perror_str = parse_python_exception(); - std::cout << "Error in Python: " << perror_str << std::endl; - } +void execute_python_file(const char *python_file) +{ + try { + FILE *fp = fopen(python_file, "r"); + if (fp == NULL) { + fprintf(stderr, "Fatal error: file not found %s\n", python_file); + exit(1); + } + PyRun_SimpleFile(fp, python_file); + fclose(fp); + } catch (boost::python::error_already_set const &) { + // Parse and output the exception + std::string perror_str = parse_python_exception(); + std::cout << "Error in Python: " << perror_str << std::endl; + } } - diff --git a/common/pybindings.h b/common/pybindings.h index a99ad51b..bb060718 100644 --- a/common/pybindings.h +++ b/common/pybindings.h @@ -23,85 +23,85 @@ #include "pycontainers.h" -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include using namespace boost::python; /* A wrapper to enable custom type/ID to/from string conversions */ -template -struct string_wrapper { - template - struct from_pystring_converter { - from_pystring_converter() { - converter::registry::push_back( - &convertible, - &construct, - boost::python::type_id()); - }; +template struct string_wrapper +{ + template struct from_pystring_converter + { + from_pystring_converter() + { + converter::registry::push_back(&convertible, &construct, + boost::python::type_id()); + }; - static void *convertible(PyObject *object) { - return PyUnicode_Check(object) ? object : 0; - } + static void *convertible(PyObject *object) + { + return PyUnicode_Check(object) ? object : 0; + } - static void construct( - PyObject *object, - converter::rvalue_from_python_stage1_data *data) { - const wchar_t *value = PyUnicode_AsUnicode(object); - const std::wstring value_ws(value); - if (value == 0) throw_error_already_set(); - void *storage = ( - (boost::python::converter::rvalue_from_python_storage *) - data)->storage.bytes; - new(storage) T(fn(std::string(value_ws.begin(), value_ws.end()))); - data->convertible = storage; - } + static void construct(PyObject *object, + converter::rvalue_from_python_stage1_data *data) + { + const wchar_t *value = PyUnicode_AsUnicode(object); + const std::wstring value_ws(value); + if (value == 0) + throw_error_already_set(); + void *storage = + ((boost::python::converter::rvalue_from_python_storage *) + data) + ->storage.bytes; + new (storage) T(fn(std::string(value_ws.begin(), value_ws.end()))); + data->convertible = storage; + } - static F fn; - }; + static F fn; + }; - template - struct to_str_wrapper { - static F fn; + template struct to_str_wrapper + { + static F fn; - std::string str(T &x) { - return fn(x); - } - }; + std::string str(T &x) { return fn(x); } + }; - template - static void wrap(const char *type_name, F1 to_str_fn, F2 from_str_fn) { - from_pystring_converter::fn = from_str_fn; - from_pystring_converter(); - to_str_wrapper::fn = to_str_fn; - class_(type_name, no_init).def("__str__", to_str_wrapper::str); - }; + template + static void wrap(const char *type_name, F1 to_str_fn, F2 from_str_fn) + { + from_pystring_converter::fn = from_str_fn; + from_pystring_converter(); + to_str_wrapper::fn = to_str_fn; + class_(type_name, no_init).def("__str__", to_str_wrapper::str); + }; }; std::string parse_python_exception(); -template -void python_export_global(const char *name, Tn &x) { - PyObject * m, *d; - m = PyImport_AddModule("__main__"); - if (m == NULL) - return; - d = PyModule_GetDict(m); - try { - PyObject * p = incref(object(boost::ref(x)).ptr()); - PyDict_SetItemString(d, name, p); - } catch (boost::python::error_already_set const &) { - // Parse and output the exception - std::string perror_str = parse_python_exception(); - std::cout << "Error in Python: " << perror_str << std::endl; - std::terminate(); - } +template void python_export_global(const char *name, Tn &x) +{ + PyObject *m, *d; + m = PyImport_AddModule("__main__"); + if (m == NULL) + return; + d = PyModule_GetDict(m); + try { + PyObject *p = incref(object(boost::ref(x)).ptr()); + PyDict_SetItemString(d, name, p); + } catch (boost::python::error_already_set const &) { + // Parse and output the exception + std::string perror_str = parse_python_exception(); + std::cout << "Error in Python: " << perror_str << std::endl; + std::terminate(); + } }; void init_python(const char *executable); diff --git a/dummy/main.cc b/dummy/main.cc index 5c36a961..cc6addb5 100644 --- a/dummy/main.cc +++ b/dummy/main.cc @@ -17,15 +17,15 @@ * */ +#include #include "design.h" #include "mainwindow.h" -#include int main(int argc, char *argv[]) { - Design design(ChipArgs{}); + Design design(ChipArgs{}); - QApplication a(argc, argv); + QApplication a(argc, argv); MainWindow w; w.show(); diff --git a/dummy/pybindings.cc b/dummy/pybindings.cc index 3a586234..12e0ca13 100644 --- a/dummy/pybindings.cc +++ b/dummy/pybindings.cc @@ -18,12 +18,10 @@ * */ -#include "design.h" #include "chip.h" +#include "design.h" // include after design.h/chip.h #include "pybindings.h" -void arch_wrap_python() { - class_("ChipArgs"); -} +void arch_wrap_python() { class_("ChipArgs"); } diff --git a/ice40/main.cc b/ice40/main.cc index 18896142..d47076fd 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -16,239 +16,244 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ -#include "design.h" -#include "mainwindow.h" #include -#include -#include -#include "version.h" #include -#include "pybindings.h" +#include +#include +#include "design.h" #include "jsonparse.h" +#include "mainwindow.h" +#include "pybindings.h" +#include "version.h" void svg_dump_el(const GraphicElement &el) { - float scale = 10.0, offset = 10.0; - std::string style = "stroke=\"black\" stroke-width=\"0.1\" fill=\"none\""; + float scale = 10.0, offset = 10.0; + std::string style = "stroke=\"black\" stroke-width=\"0.1\" fill=\"none\""; - if (el.type == GraphicElement::G_BOX) { - std::cout << "\n"; - } + if (el.type == GraphicElement::G_BOX) { + std::cout << "\n"; + } - if (el.type == GraphicElement::G_LINE) { - std::cout << "\n"; - } + if (el.type == GraphicElement::G_LINE) { + std::cout << "\n"; + } } int main(int argc, char *argv[]) { - namespace po = boost::program_options; - int rc = 0; - std::string str; + namespace po = boost::program_options; + int rc = 0; + std::string str; - po::options_description options("Allowed options"); - options.add_options()("help,h","show help"); - options.add_options()("test","just a check"); - options.add_options()("gui","start gui"); - options.add_options()("svg","dump SVG file"); - options.add_options()("run", po::value>(), "python file to execute"); - options.add_options()("json", po::value(), "JSON design file to ingest"); - options.add_options()("version,v","show version"); - options.add_options()("lp384","set device type to iCE40LP384"); - options.add_options()("lp1k","set device type to iCE40LP1K"); - options.add_options()("lp8k","set device type to iCE40LP8K"); - options.add_options()("hx1k","set device type to iCE40HX1K"); - options.add_options()("hx8k","set device type to iCE40HX8K"); - options.add_options()("up5k","set device type to iCE40UP5K"); + po::options_description options("Allowed options"); + options.add_options()("help,h", "show help"); + options.add_options()("test", "just a check"); + options.add_options()("gui", "start gui"); + options.add_options()("svg", "dump SVG file"); + options.add_options()("run", po::value>(), + "python file to execute"); + options.add_options()("json", po::value(), + "JSON design file to ingest"); + options.add_options()("version,v", "show version"); + options.add_options()("lp384", "set device type to iCE40LP384"); + options.add_options()("lp1k", "set device type to iCE40LP1K"); + options.add_options()("lp8k", "set device type to iCE40LP8K"); + options.add_options()("hx1k", "set device type to iCE40HX1K"); + options.add_options()("hx8k", "set device type to iCE40HX8K"); + options.add_options()("up5k", "set device type to iCE40UP5K"); - po::positional_options_description pos; - pos.add("run", -1); + po::positional_options_description pos; + pos.add("run", -1); - po::variables_map vm; - try { - po::parsed_options parsed = po::command_line_parser(argc, argv). - options(options). - positional(pos). - run(); + po::variables_map vm; + try { + po::parsed_options parsed = po::command_line_parser(argc, argv) + .options(options) + .positional(pos) + .run(); - po::store(parsed, vm); - - po::notify(vm); - } + po::store(parsed, vm); - catch(std::exception& e) - { - std::cout << e.what() << "\n"; - return 1; - } + po::notify(vm); + } - if (vm.count("help") || argc == 1) - { - help: - std::cout << basename(argv[0]) << " -- Next Generation Place and Route (git sha1 " GIT_COMMIT_HASH_STR ")\n"; - std::cout << "\n"; - std::cout << options << "\n"; - return argc != 1; - } - - if (vm.count("version")) - { - std::cout << basename(argv[0]) - << " -- Next Generation Place and Route (git sha1 " - GIT_COMMIT_HASH_STR ")\n"; - return 1; - } + catch (std::exception &e) { + std::cout << e.what() << "\n"; + return 1; + } - ChipArgs chipArgs; + if (vm.count("help") || argc == 1) { + help: + std::cout << basename(argv[0]) + << " -- Next Generation Place and Route (git " + "sha1 " GIT_COMMIT_HASH_STR ")\n"; + std::cout << "\n"; + std::cout << options << "\n"; + return argc != 1; + } - if (vm.count("lp384")) { - if (chipArgs.type != ChipArgs::NONE) - goto help; - chipArgs.type = ChipArgs::LP384; - } + if (vm.count("version")) { + std::cout << basename(argv[0]) + << " -- Next Generation Place and Route (git " + "sha1 " GIT_COMMIT_HASH_STR ")\n"; + return 1; + } - if (vm.count("lp1k")) { - if (chipArgs.type != ChipArgs::NONE) - goto help; - chipArgs.type = ChipArgs::LP1K; - } + ChipArgs chipArgs; - if (vm.count("lp8k")) { - if (chipArgs.type != ChipArgs::NONE) - goto help; - chipArgs.type = ChipArgs::LP8K; - } + if (vm.count("lp384")) { + if (chipArgs.type != ChipArgs::NONE) + goto help; + chipArgs.type = ChipArgs::LP384; + } - if (vm.count("hx1k")) { - if (chipArgs.type != ChipArgs::NONE) - goto help; - chipArgs.type = ChipArgs::HX1K; - } + if (vm.count("lp1k")) { + if (chipArgs.type != ChipArgs::NONE) + goto help; + chipArgs.type = ChipArgs::LP1K; + } - if (vm.count("hx8k")) { - if (chipArgs.type != ChipArgs::NONE) - goto help; - chipArgs.type = ChipArgs::HX8K; - } + if (vm.count("lp8k")) { + if (chipArgs.type != ChipArgs::NONE) + goto help; + chipArgs.type = ChipArgs::LP8K; + } - if (vm.count("up5k")) { - if (chipArgs.type != ChipArgs::NONE) - goto help; - chipArgs.type = ChipArgs::UP5K; - } + if (vm.count("hx1k")) { + if (chipArgs.type != ChipArgs::NONE) + goto help; + chipArgs.type = ChipArgs::HX1K; + } - if (chipArgs.type == ChipArgs::NONE) - chipArgs.type = ChipArgs::HX1K; + if (vm.count("hx8k")) { + if (chipArgs.type != ChipArgs::NONE) + goto help; + chipArgs.type = ChipArgs::HX8K; + } + + if (vm.count("up5k")) { + if (chipArgs.type != ChipArgs::NONE) + goto help; + chipArgs.type = ChipArgs::UP5K; + } + + if (chipArgs.type == ChipArgs::NONE) + chipArgs.type = ChipArgs::HX1K; #ifdef ICE40_HX1K_ONLY - if (chipArgs.type != ChipArgs::HX1K) { - std::cout << "This version of nextpnr-ice40 is built with HX1K-support only.\n"; - return 1; - } + if (chipArgs.type != ChipArgs::HX1K) { + std::cout << "This version of nextpnr-ice40 is built with HX1K-support " + "only.\n"; + return 1; + } #endif - Design design(chipArgs); - init_python(argv[0]); - python_export_global("design", design); + Design design(chipArgs); + init_python(argv[0]); + python_export_global("design", design); - if (vm.count("test")) - { - int bel_count = 0, wire_count = 0, pip_count = 0; + if (vm.count("test")) { + int bel_count = 0, wire_count = 0, pip_count = 0; - std::cout << "Checking bel names.\n"; - for (auto bel : design.chip.getBels()) { - auto name = design.chip.getBelName(bel); - assert(bel == design.chip.getBelByName(name)); - bel_count++; - } - std::cout << " checked " << bel_count << " bels.\n"; + std::cout << "Checking bel names.\n"; + for (auto bel : design.chip.getBels()) { + auto name = design.chip.getBelName(bel); + assert(bel == design.chip.getBelByName(name)); + bel_count++; + } + std::cout << " checked " << bel_count << " bels.\n"; - std::cout << "Checking wire names.\n"; - for (auto wire : design.chip.getWires()) { - auto name = design.chip.getWireName(wire); - assert(wire == design.chip.getWireByName(name)); - wire_count++; - } - std::cout << " checked " << wire_count << " wires.\n"; + std::cout << "Checking wire names.\n"; + for (auto wire : design.chip.getWires()) { + auto name = design.chip.getWireName(wire); + assert(wire == design.chip.getWireByName(name)); + wire_count++; + } + std::cout << " checked " << wire_count << " wires.\n"; - std::cout << "Checking pip names.\n"; - for (auto pip : design.chip.getPips()) { - auto name = design.chip.getPipName(pip); - assert(pip == design.chip.getPipByName(name)); - pip_count++; - } - std::cout << " checked " << pip_count << " pips.\n"; + std::cout << "Checking pip names.\n"; + for (auto pip : design.chip.getPips()) { + auto name = design.chip.getPipName(pip); + assert(pip == design.chip.getPipByName(name)); + pip_count++; + } + std::cout << " checked " << pip_count << " pips.\n"; - std::cout << "Checking uphill -> downhill consistency.\n"; - for (auto dst : design.chip.getWires()) { - for (auto uphill_pip : design.chip.getPipsUphill(dst)) { - bool found_downhill = false; - for (auto downhill_pip : design.chip.getPipsDownhill(design.chip.getPipSrcWire(uphill_pip))) { - if (uphill_pip == downhill_pip) { - assert(!found_downhill); - found_downhill = true; - } - } - assert(found_downhill); - } - } + std::cout << "Checking uphill -> downhill consistency.\n"; + for (auto dst : design.chip.getWires()) { + for (auto uphill_pip : design.chip.getPipsUphill(dst)) { + bool found_downhill = false; + for (auto downhill_pip : design.chip.getPipsDownhill( + design.chip.getPipSrcWire(uphill_pip))) { + if (uphill_pip == downhill_pip) { + assert(!found_downhill); + found_downhill = true; + } + } + assert(found_downhill); + } + } - std::cout << "Checking downhill -> uphill consistency.\n"; - for (auto dst : design.chip.getWires()) { - for (auto downhill_pip : design.chip.getPipsDownhill(dst)) { - bool found_uphill = false; - for (auto uphill_pip : design.chip.getPipsUphill(design.chip.getPipDstWire(downhill_pip))) { - if (uphill_pip == downhill_pip) { - assert(!found_uphill); - found_uphill = true; - } - } - assert(found_uphill); - } - } + std::cout << "Checking downhill -> uphill consistency.\n"; + for (auto dst : design.chip.getWires()) { + for (auto downhill_pip : design.chip.getPipsDownhill(dst)) { + bool found_uphill = false; + for (auto uphill_pip : design.chip.getPipsUphill( + design.chip.getPipDstWire(downhill_pip))) { + if (uphill_pip == downhill_pip) { + assert(!found_uphill); + found_uphill = true; + } + } + assert(found_uphill); + } + } - return 0; - } + return 0; + } - if (vm.count("svg")) - { - std::cout << "\n"; - for (auto bel : design.chip.getBels()) { - std::cout << "\n"; - for (auto &el : design.chip.getBelGraphics(bel)) - svg_dump_el(el); - } - std::cout << "\n"; - for (auto &el : design.chip.getFrameGraphics()) - svg_dump_el(el); - std::cout << "\n"; - } + if (vm.count("svg")) { + std::cout << "\n"; + for (auto bel : design.chip.getBels()) { + std::cout << "\n"; + for (auto &el : design.chip.getBelGraphics(bel)) + svg_dump_el(el); + } + std::cout << "\n"; + for (auto &el : design.chip.getFrameGraphics()) + svg_dump_el(el); + std::cout << "\n"; + } - if (vm.count("json")) - { - std::string filename = vm["json"].as(); - std::istream *f = new std::ifstream(filename); - - parse_json_file(f, filename, &design); - } + if (vm.count("json")) { + std::string filename = vm["json"].as(); + std::istream *f = new std::ifstream(filename); - if (vm.count("run")) - { - std::vector files = vm["run"].as>(); - for(auto filename : files) - execute_python_file(filename.c_str()); - } + parse_json_file(f, filename, &design); + } - if (vm.count("gui")) - { - QApplication a(argc, argv); - MainWindow w; - w.show(); + if (vm.count("run")) { + std::vector files = + vm["run"].as>(); + for (auto filename : files) + execute_python_file(filename.c_str()); + } - rc = a.exec(); - } - deinit_python(); - return rc; + if (vm.count("gui")) { + QApplication a(argc, argv); + MainWindow w; + w.show(); + + rc = a.exec(); + } + deinit_python(); + return rc; } diff --git a/ice40/pybindings.cc b/ice40/pybindings.cc index 3760e319..daf0be84 100644 --- a/ice40/pybindings.cc +++ b/ice40/pybindings.cc @@ -18,15 +18,15 @@ * */ -#include "design.h" #include "chip.h" +#include "design.h" // include after design.h/chip.h #include "pybindings.h" -void arch_wrap_python() { - class_("ChipArgs") - .def_readwrite("type", &ChipArgs::type); +void arch_wrap_python() +{ + class_("ChipArgs").def_readwrite("type", &ChipArgs::type); enum_().type)>("iCE40Type") .value("NONE", ChipArgs::NONE) From 024ff8fa7d1aa7c9ae81afcac6f7c2499f44b624 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 7 Jun 2018 13:20:16 +0200 Subject: [PATCH 17/18] cmake: Add HX1K-only builds support Signed-off-by: David Shah --- README.md | 1 + ice40/family.cmake | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 92d055f1..688f3632 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ Building - Use CMake to generate the Makefiles (only needs to be done when `CMakeLists.txt` changes) - For a debug build, run `cmake -DCMAKE_BUILD_TYPE=Debug .` + - For a debug build with HX1K support only, run ` cmake -DCMAKE_BUILD_TYPE=Debug -DICE40_HX1K_ONLY=1 .` - For a release build, run `cmake .` - Use Make to run the build itself - For all targets, just run `make` diff --git a/ice40/family.cmake b/ice40/family.cmake index 870b69b9..05709388 100644 --- a/ice40/family.cmake +++ b/ice40/family.cmake @@ -1,4 +1,12 @@ -set(devices 384 1k 5k 8k) +if(ICE40_HX1K_ONLY) + set(devices 1k) + foreach (target ${family_targets}) + target_compile_definitions(${target} PRIVATE ICE40_HX1K_ONLY=1) + endforeach (target) +else() + set(devices 384 1k 5k 8k) +endif() + set(DB_PY ${CMAKE_CURRENT_SOURCE_DIR}/ice40/chipdb.py) file(MAKE_DIRECTORY ice40/chipdbs/) add_library(ice40_chipdb OBJECT ice40/chipdbs/) From ed0c44891fb510c8181c2ae9332d7a030f0aaaff Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 7 Jun 2018 13:36:42 +0200 Subject: [PATCH 18/18] Replacing Boost type_traits with std Signed-off-by: David Shah --- common/pycontainers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/pycontainers.h b/common/pycontainers.h index 64fb265b..6e2cdea9 100644 --- a/common/pycontainers.h +++ b/common/pycontainers.h @@ -90,7 +90,7 @@ inline void KeyError() { PyErr_SetString(PyExc_KeyError, "Key not found"); } template struct map_wrapper { - typedef boost::remove_cv_t> K; + typedef typename std::remove_cv::type>::type K; typedef typename T::mapped_type V; typedef typename T::value_type KV;