aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/command.cc3
-rw-r--r--common/design_utils.cc17
-rw-r--r--common/design_utils.h3
-rw-r--r--common/nextpnr.cc8
-rw-r--r--common/nextpnr.h6
-rw-r--r--common/pybindings.cc44
-rw-r--r--common/pywrappers.h111
-rw-r--r--common/timing.cc5
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) {