diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/command.cc | 3 | ||||
-rw-r--r-- | common/design_utils.cc | 17 | ||||
-rw-r--r-- | common/design_utils.h | 3 | ||||
-rw-r--r-- | common/nextpnr.cc | 8 | ||||
-rw-r--r-- | common/nextpnr.h | 6 | ||||
-rw-r--r-- | common/pybindings.cc | 44 | ||||
-rw-r--r-- | common/pywrappers.h | 111 | ||||
-rw-r--r-- | common/timing.cc | 5 |
8 files changed, 182 insertions, 15 deletions
diff --git a/common/command.cc b/common/command.cc index 49081e72..3eafdb17 100644 --- a/common/command.cc +++ b/common/command.cc @@ -107,6 +107,7 @@ po::options_description CommandHandler::getGeneralOptions() general.add_options()("force,f", "keep running after errors"); #ifndef NO_GUI general.add_options()("gui", "start gui"); + general.add_options()("gui-no-aa", "disable anti aliasing (use together with --gui option)"); #endif #ifndef NO_PYTHON general.add_options()("run", po::value<std::vector<std::string>>(), @@ -235,7 +236,7 @@ int CommandHandler::executeMain(std::unique_ptr<Context> ctx) #ifndef NO_GUI if (vm.count("gui")) { - Application a(argc, argv); + Application a(argc, argv, (vm.count("gui-no-aa") > 0)); MainWindow w(std::move(ctx), chipArgs); try { if (vm.count("json")) { diff --git a/common/design_utils.cc b/common/design_utils.cc index da170030..bdf5ca5c 100644 --- a/common/design_utils.cc +++ b/common/design_utils.cc @@ -129,4 +129,21 @@ void connect_ports(Context *ctx, CellInfo *cell1, IdString port1_name, CellInfo connect_port(ctx, port1.net, cell2, port2_name); } +void rename_port(Context *ctx, CellInfo *cell, IdString old_name, IdString new_name) +{ + if (!cell->ports.count(old_name)) + return; + PortInfo pi = cell->ports.at(old_name); + if (pi.net != nullptr) { + if (pi.net->driver.cell == cell && pi.net->driver.port == old_name) + pi.net->driver.port = new_name; + for (auto &usr : pi.net->users) + if (usr.cell == cell && usr.port == old_name) + usr.port = new_name; + } + cell->ports.erase(old_name); + pi.name = new_name; + cell->ports[new_name] = pi; +} + NEXTPNR_NAMESPACE_END diff --git a/common/design_utils.h b/common/design_utils.h index 8a42d21f..3eb9024f 100644 --- a/common/design_utils.h +++ b/common/design_utils.h @@ -91,6 +91,9 @@ void disconnect_port(const Context *ctx, CellInfo *cell, IdString port_name); // Connect two ports together void connect_ports(Context *ctx, CellInfo *cell1, IdString port1_name, CellInfo *cell2, IdString port2_name); +// Rename a port if it exists on a cell +void rename_port(Context *ctx, CellInfo *cell, IdString old_name, IdString new_name); + void print_utilisation(const Context *ctx); NEXTPNR_NAMESPACE_END diff --git a/common/nextpnr.cc b/common/nextpnr.cc index 54333b15..daaadf28 100644 --- a/common/nextpnr.cc +++ b/common/nextpnr.cc @@ -444,5 +444,13 @@ void BaseCtx::constrainCellToRegion(IdString cell, IdString region_name) { cells[cell]->region = region[region_name].get(); } +DecalXY BaseCtx::constructDecalXY(DecalId decal, float x, float y) +{ + DecalXY dxy; + dxy.decal = decal; + dxy.x = x; + dxy.y = y; + return dxy; +} NEXTPNR_NAMESPACE_END diff --git a/common/nextpnr.h b/common/nextpnr.h index 5967ecee..fc49300e 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -181,6 +181,9 @@ struct GraphicElement float x1 = 0, y1 = 0, x2 = 0, y2 = 0, z = 0; std::string text; + GraphicElement(){}; + GraphicElement(type_t type, style_t style, float x1, float y1, float x2, float y2, float z) + : type(type), style(style), x1(x1), y1(y1), x2(x2), y2(y2), z(z){}; }; struct Loc @@ -640,6 +643,9 @@ struct BaseCtx void createRectangularRegion(IdString name, int x0, int y0, int x1, int y1); void addBelToRegion(IdString name, BelId bel); void constrainCellToRegion(IdString cell, IdString region_name); + + // Workaround for lack of wrappable constructors + DecalXY constructDecalXY(DecalId decal, float x, float y); }; NEXTPNR_NAMESPACE_END diff --git a/common/pybindings.cc b/common/pybindings.cc index eee78b5e..60f87e27 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -23,8 +23,10 @@ #include "pybindings.h" #include "arch_pybindings.h" #include "jsonparse.h" +#include "log.h" #include "nextpnr.h" +#include <boost/filesystem.hpp> #include <fstream> #include <memory> #include <signal.h> @@ -87,7 +89,26 @@ BOOST_PYTHON_MODULE(MODULE_NAME) using namespace PythonConversion; + enum_<GraphicElement::type_t>("GraphicElementType") + .value("TYPE_NONE", GraphicElement::TYPE_NONE) + .value("TYPE_LINE", GraphicElement::TYPE_LINE) + .value("TYPE_ARROW", GraphicElement::TYPE_ARROW) + .value("TYPE_BOX", GraphicElement::TYPE_BOX) + .value("TYPE_CIRCLE", GraphicElement::TYPE_CIRCLE) + .value("TYPE_LABEL", GraphicElement::TYPE_LABEL) + .export_values(); + + enum_<GraphicElement::style_t>("GraphicElementStyle") + .value("STYLE_GRID", GraphicElement::STYLE_GRID) + .value("STYLE_FRAME", GraphicElement::STYLE_FRAME) + .value("STYLE_HIDDEN", GraphicElement::STYLE_HIDDEN) + .value("STYLE_INACTIVE", GraphicElement::STYLE_INACTIVE) + .value("STYLE_ACTIVE", GraphicElement::STYLE_ACTIVE) + .export_values(); + class_<GraphicElement>("GraphicElement") + .def(init<GraphicElement::type_t, GraphicElement::style_t, float, float, float, float, float>( + (args("type"), "style", "x1", "y1", "x2", "y2", "z"))) .def_readwrite("type", &GraphicElement::type) .def_readwrite("x1", &GraphicElement::x1) .def_readwrite("y1", &GraphicElement::y1) @@ -108,6 +129,12 @@ BOOST_PYTHON_MODULE(MODULE_NAME) class_<BaseCtx, BaseCtx *, boost::noncopyable>("BaseCtx", no_init); + auto loc_cls = class_<Loc>("Loc") + .def(init<int, int, int>()) + .def_readwrite("x", &Loc::x) + .def_readwrite("y", &Loc::y) + .def_readwrite("z", &Loc::z); + auto ci_cls = class_<ContextualWrapper<CellInfo &>>("CellInfo", no_init); readwrite_wrapper<CellInfo &, decltype(&CellInfo::name), &CellInfo::name, conv_to_str<IdString>, conv_from_str<IdString>>::def_wrap(ci_cls, "name"); @@ -208,8 +235,14 @@ void init_python(const char *executable, bool first) PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME); Py_SetProgramName(program); Py_Initialize(); - if (first) - PyImport_ImportModule(TOSTRING(MODULE_NAME)); + + // Add cwd to Python's search path so `import` can be used in user scripts + boost::filesystem::path cwd = boost::filesystem::absolute("./").normalize(); + PyObject *sys_path = PySys_GetObject("path"); + PyList_Insert(sys_path, 0, PyUnicode_FromString(cwd.string().c_str())); + + PyImport_ImportModule(TOSTRING(MODULE_NAME)); + PyRun_SimpleString("from " TOSTRING(MODULE_NAME) " import *"); } catch (boost::python::error_already_set const &) { // Parse and output the exception std::string perror_str = parse_python_exception(); @@ -235,12 +268,15 @@ void execute_python_file(const char *python_file) fprintf(stderr, "Fatal error: file not found %s\n", python_file); exit(1); } - PyRun_SimpleFile(fp, python_file); + int result = PyRun_SimpleFile(fp, python_file); fclose(fp); + if (result == -1) { + log_error("Error occurred while executing Python script %s\n", python_file); + } } 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; + log_error("Error in Python: %s\n", perror_str.c_str()); } } diff --git a/common/pywrappers.h b/common/pywrappers.h index 427c3623..1d970985 100644 --- a/common/pywrappers.h +++ b/common/pywrappers.h @@ -155,11 +155,15 @@ template <typename Class, typename FuncT, FuncT fn, typename rv_conv> struct fn_ using class_type = typename WrapIfNotContext<Class>::maybe_wrapped_t; using conv_result_type = typename rv_conv::ret_type; - static conv_result_type wrapped_fn(class_type &cls) + static object wrapped_fn(class_type &cls) { Context *ctx = get_ctx<Class>(cls); Class &base = get_base<Class>(cls); - return rv_conv()(ctx, (base.*fn)()); + try { + return object(rv_conv()(ctx, (base.*fn)())); + } catch (bad_wrap &) { + return object(); + } } template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } @@ -172,11 +176,15 @@ template <typename Class, typename FuncT, FuncT fn, typename rv_conv, typename a using conv_result_type = typename rv_conv::ret_type; using conv_arg1_type = typename arg1_conv::arg_type; - static conv_result_type wrapped_fn(class_type &cls, conv_arg1_type arg1) + static object wrapped_fn(class_type &cls, conv_arg1_type arg1) { Context *ctx = get_ctx<Class>(cls); Class &base = get_base<Class>(cls); - return rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1))); + try { + return object(rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1)))); + } catch (bad_wrap &) { + return object(); + } } template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } @@ -191,11 +199,15 @@ struct fn_wrapper_2a using conv_arg1_type = typename arg1_conv::arg_type; using conv_arg2_type = typename arg2_conv::arg_type; - static conv_result_type wrapped_fn(class_type &cls, conv_arg1_type arg1, conv_arg2_type arg2) + static object wrapped_fn(class_type &cls, conv_arg1_type arg1, conv_arg2_type arg2) { Context *ctx = get_ctx<Class>(cls); Class &base = get_base<Class>(cls); - return rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2))); + try { + return object(rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2)))); + } catch (bad_wrap &) { + return object(); + } } template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } @@ -212,11 +224,16 @@ struct fn_wrapper_3a using conv_arg2_type = typename arg2_conv::arg_type; using conv_arg3_type = typename arg3_conv::arg_type; - static conv_result_type wrapped_fn(class_type &cls, conv_arg1_type arg1, conv_arg2_type arg2, conv_arg3_type arg3) + static object wrapped_fn(class_type &cls, conv_arg1_type arg1, conv_arg2_type arg2, conv_arg3_type arg3) { Context *ctx = get_ctx<Class>(cls); Class &base = get_base<Class>(cls); - return rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3))); + try { + return object( + rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3)))); + } catch (bad_wrap &) { + return object(); + } } template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } @@ -250,6 +267,11 @@ template <typename Class, typename FuncT, FuncT fn, typename arg1_conv> struct f } template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } + + template <typename WrapCls, typename Ta> static void def_wrap(WrapCls cls_, const char *name, Ta a = arg("arg1")) + { + cls_.def(name, wrapped_fn, a); + } }; // Two parameters, one return @@ -267,6 +289,11 @@ template <typename Class, typename FuncT, FuncT fn, typename arg1_conv, typename } template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } + + template <typename WrapCls, typename Ta> static void def_wrap(WrapCls cls_, const char *name, const Ta &a) + { + cls_.def(name, wrapped_fn, a); + } }; // Three parameters, no return @@ -286,6 +313,39 @@ struct fn_wrapper_3a_v } template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } + + template <typename WrapCls, typename Ta> static void def_wrap(WrapCls cls_, const char *name, const Ta &a) + { + cls_.def(name, wrapped_fn, a); + } +}; + +// Four parameters, no return +template <typename Class, typename FuncT, FuncT fn, typename arg1_conv, typename arg2_conv, typename arg3_conv, + typename arg4_conv> +struct fn_wrapper_4a_v +{ + using class_type = typename WrapIfNotContext<Class>::maybe_wrapped_t; + using conv_arg1_type = typename arg1_conv::arg_type; + using conv_arg2_type = typename arg2_conv::arg_type; + using conv_arg3_type = typename arg3_conv::arg_type; + using conv_arg4_type = typename arg4_conv::arg_type; + + static void wrapped_fn(class_type &cls, conv_arg1_type arg1, conv_arg2_type arg2, conv_arg3_type arg3, + conv_arg4_type arg4) + { + Context *ctx = get_ctx<Class>(cls); + Class &base = get_base<Class>(cls); + return (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3), + arg4_conv()(ctx, arg4)); + } + + template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } + + template <typename WrapCls, typename Ta> static void def_wrap(WrapCls cls_, const char *name, const Ta &a) + { + cls_.def(name, wrapped_fn, a); + } }; // Five parameters, no return @@ -310,6 +370,41 @@ struct fn_wrapper_5a_v } template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } + + template <typename WrapCls, typename Ta> static void def_wrap(WrapCls cls_, const char *name, const Ta &a) + { + cls_.def(name, wrapped_fn, a); + } +}; + +// Six parameters, no return +template <typename Class, typename FuncT, FuncT fn, typename arg1_conv, typename arg2_conv, typename arg3_conv, + typename arg4_conv, typename arg5_conv, typename arg6_conv> +struct fn_wrapper_6a_v +{ + using class_type = typename WrapIfNotContext<Class>::maybe_wrapped_t; + using conv_arg1_type = typename arg1_conv::arg_type; + using conv_arg2_type = typename arg2_conv::arg_type; + using conv_arg3_type = typename arg3_conv::arg_type; + using conv_arg4_type = typename arg4_conv::arg_type; + using conv_arg5_type = typename arg5_conv::arg_type; + using conv_arg6_type = typename arg6_conv::arg_type; + + static void wrapped_fn(class_type &cls, conv_arg1_type arg1, conv_arg2_type arg2, conv_arg3_type arg3, + conv_arg4_type arg4, conv_arg5_type arg5, conv_arg6_type arg6) + { + Context *ctx = get_ctx<Class>(cls); + Class &base = get_base<Class>(cls); + return (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3), + arg4_conv()(ctx, arg4), arg5_conv()(ctx, arg5), arg6_conv()(ctx, arg6)); + } + + template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } + + template <typename WrapCls, typename Ta> static void def_wrap(WrapCls cls_, const char *name, const Ta &a) + { + cls_.def(name, wrapped_fn, a); + } }; // Wrapped getter diff --git a/common/timing.cc b/common/timing.cc index 2ce9eea3..e67ac231 100644 --- a/common/timing.cc +++ b/common/timing.cc @@ -546,7 +546,8 @@ struct Timing for (size_t i = 0; i < sink_net->users.size(); i++) { auto &user = sink_net->users.at(i); if (user.cell == drv.cell && user.port == port.first) { - sink_nd.min_required.at(i) = net_min_required - comb_delay.maxDelay(); + sink_nd.min_required.at(i) = std::min(sink_nd.min_required.at(i), + net_min_required - comb_delay.maxDelay()); break; } } @@ -752,7 +753,7 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p } if (clock_reports.empty()) { - log_warning("No clocks found in design"); + log_warning("No clocks found in design\n"); } std::sort(xclock_paths.begin(), xclock_paths.end(), [ctx](const ClockPair &a, const ClockPair &b) { |