Initial GUI work
This commit is contained in:
parent
bd08f9e698
commit
7cb42f4368
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
|
/generated/
|
||||||
/objs/
|
/objs/
|
||||||
/nextpnr-dummy
|
/nextpnr-dummy
|
||||||
/nextpnr-ice40
|
/nextpnr-ice40
|
||||||
@ -13,6 +14,7 @@ CMakeCache.txt
|
|||||||
*.dll
|
*.dll
|
||||||
*.a
|
*.a
|
||||||
*.cbp
|
*.cbp
|
||||||
|
*.depends
|
||||||
.*.swp
|
.*.swp
|
||||||
a.out
|
a.out
|
||||||
*.json
|
*.json
|
||||||
|
@ -7,13 +7,26 @@ set(CMAKE_CXX_STANDARD 11)
|
|||||||
# set(CMAKE_CXX_FLAGS "-Wall -pedantic -Wextra -Werror")
|
# set(CMAKE_CXX_FLAGS "-Wall -pedantic -Wextra -Werror")
|
||||||
set(CMAKE_DEFIN)
|
set(CMAKE_DEFIN)
|
||||||
# List of Boost libraries to include
|
# List of Boost libraries to include
|
||||||
set(boost_libs filesystem thread)
|
set(boost_libs filesystem thread program_options)
|
||||||
# TODO: sensible minimum Python version
|
# TODO: sensible minimum Python version
|
||||||
find_package(PythonInterp 3.5 REQUIRED)
|
find_package(PythonInterp 3.5 REQUIRED)
|
||||||
find_package(PythonLibs 3.5 REQUIRED)
|
find_package(PythonLibs 3.5 REQUIRED)
|
||||||
|
|
||||||
find_package(Boost REQUIRED COMPONENTS ${boost_libs})
|
find_package(Boost REQUIRED COMPONENTS ${boost_libs})
|
||||||
|
|
||||||
|
# Get the latest abbreviated commit hash of the working branch
|
||||||
|
execute_process(
|
||||||
|
COMMAND git log -1 --format=%h
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
|
OUTPUT_VARIABLE GIT_COMMIT_HASH
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
|
||||||
|
add_definitions("-DGIT_COMMIT_HASH=${GIT_COMMIT_HASH}")
|
||||||
|
configure_file(
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/common/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/generated/version.h
|
||||||
|
)
|
||||||
|
|
||||||
# Find Boost::Python of a suitable version in a cross-platform way
|
# Find Boost::Python of a suitable version in a cross-platform way
|
||||||
# Some distributions (Arch) call it libboost_python3, others such as Ubuntu
|
# Some distributions (Arch) call it libboost_python3, others such as Ubuntu
|
||||||
# call it libboost_python35. In the latter case we must consider all minor versions
|
# call it libboost_python35. In the latter case we must consider all minor versions
|
||||||
@ -41,16 +54,16 @@ if (NOT Boost_PYTHON_FOUND)
|
|||||||
find_package(Boost COMPONENTS python3 ${boost_libs})
|
find_package(Boost COMPONENTS python3 ${boost_libs})
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
# TODO: Find and include Qt
|
include(gui/gui.cmake)
|
||||||
|
|
||||||
include_directories(common/ ${Boost_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS})
|
include_directories(common/ gui/ ${Boost_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS})
|
||||||
aux_source_directory(common/ COMMON_FILES)
|
aux_source_directory(common/ COMMON_FILES)
|
||||||
|
|
||||||
foreach (family ${FAMILIES})
|
foreach (family ${FAMILIES})
|
||||||
string(TOUPPER ${family} ufamily)
|
string(TOUPPER ${family} ufamily)
|
||||||
aux_source_directory(${family}/ ${ufamily}_FILES)
|
aux_source_directory(${family}/ ${ufamily}_FILES)
|
||||||
# Add the CLI binary target
|
# Add the CLI binary target
|
||||||
add_executable(nextpnr-${family} ${COMMON_FILES} ${${ufamily}_FILES})
|
add_executable(nextpnr-${family} ${COMMON_FILES} ${${ufamily}_FILES} ${GUI_SOURCE_FILES})
|
||||||
# Add the importable Python module target
|
# Add the importable Python module target
|
||||||
PYTHON_ADD_MODULE(nextpnrpy_${family} ${COMMON_FILES} ${${ufamily}_FILES})
|
PYTHON_ADD_MODULE(nextpnrpy_${family} ${COMMON_FILES} ${${ufamily}_FILES})
|
||||||
# Add any new per-architecture targets here
|
# Add any new per-architecture targets here
|
||||||
@ -63,7 +76,7 @@ foreach (family ${FAMILIES})
|
|||||||
# Include family-specific source files to all family targets and set defines appropriately
|
# Include family-specific source files to all family targets and set defines appropriately
|
||||||
target_include_directories(${target} PRIVATE ${family}/)
|
target_include_directories(${target} PRIVATE ${family}/)
|
||||||
target_compile_definitions(${target} PRIVATE ARCH_${ufamily} ARCHNAME=${family})
|
target_compile_definitions(${target} PRIVATE ARCH_${ufamily} ARCHNAME=${family})
|
||||||
target_link_libraries(${target} LINK_PUBLIC ${Boost_LIBRARIES} ${PYTHON_LIBRARIES})
|
target_link_libraries(${target} LINK_PUBLIC ${Boost_LIBRARIES} ${PYTHON_LIBRARIES} ${GUI_LIBRARY_FILES})
|
||||||
endforeach (target)
|
endforeach (target)
|
||||||
endforeach (family)
|
endforeach (family)
|
||||||
|
|
||||||
|
56
common/handle_error.cc
Normal file
56
common/handle_error.cc
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#include <boost/python.hpp>
|
||||||
|
#include <Python.h>
|
||||||
|
|
||||||
|
namespace py = boost::python;
|
||||||
|
|
||||||
|
// Parses the value of the active python exception
|
||||||
|
// NOTE SHOULD NOT BE CALLED IF NO EXCEPTION
|
||||||
|
std::string parse_python_exception(){
|
||||||
|
PyObject *type_ptr = NULL, *value_ptr = NULL, *traceback_ptr = NULL;
|
||||||
|
// Fetch the exception info from the Python C API
|
||||||
|
PyErr_Fetch(&type_ptr, &value_ptr, &traceback_ptr);
|
||||||
|
|
||||||
|
// Fallback error
|
||||||
|
std::string ret("Unfetchable Python error");
|
||||||
|
// If the fetch got a type pointer, parse the type into the exception string
|
||||||
|
if(type_ptr != NULL){
|
||||||
|
py::handle<> h_type(type_ptr);
|
||||||
|
py::str type_pstr(h_type);
|
||||||
|
// Extract the string from the boost::python object
|
||||||
|
py::extract<std::string> e_type_pstr(type_pstr);
|
||||||
|
// If a valid string extraction is available, use it
|
||||||
|
// otherwise use fallback
|
||||||
|
if(e_type_pstr.check())
|
||||||
|
ret = e_type_pstr();
|
||||||
|
else
|
||||||
|
ret = "Unknown exception type";
|
||||||
|
}
|
||||||
|
// Do the same for the exception value (the stringification of the exception)
|
||||||
|
if(value_ptr != NULL){
|
||||||
|
py::handle<> h_val(value_ptr);
|
||||||
|
py::str a(h_val);
|
||||||
|
py::extract<std::string> returned(a);
|
||||||
|
if(returned.check())
|
||||||
|
ret += ": " + returned();
|
||||||
|
else
|
||||||
|
ret += std::string(": Unparseable Python error: ");
|
||||||
|
}
|
||||||
|
// Parse lines from the traceback using the Python traceback module
|
||||||
|
if(traceback_ptr != NULL){
|
||||||
|
py::handle<> h_tb(traceback_ptr);
|
||||||
|
// Load the traceback module and the format_tb function
|
||||||
|
py::object tb(py::import("traceback"));
|
||||||
|
py::object fmt_tb(tb.attr("format_tb"));
|
||||||
|
// Call format_tb to get a list of traceback strings
|
||||||
|
py::object tb_list(fmt_tb(h_tb));
|
||||||
|
// Join the traceback strings into a single string
|
||||||
|
py::object tb_str(py::str("\n").join(tb_list));
|
||||||
|
// Extract the string, check the extraction, and fallback in necessary
|
||||||
|
py::extract<std::string> returned(tb_str);
|
||||||
|
if(returned.check())
|
||||||
|
ret += ": " + returned();
|
||||||
|
else
|
||||||
|
ret += std::string(": Unparseable Python traceback");
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
@ -18,6 +18,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "design.h"
|
#include "design.h"
|
||||||
#include "chip.h"
|
#include "chip.h"
|
||||||
#include "pybindings.h"
|
#include "pybindings.h"
|
||||||
@ -26,6 +27,9 @@
|
|||||||
#define PASTER(x, y) x ## _ ## y
|
#define PASTER(x, y) x ## _ ## y
|
||||||
#define EVALUATOR(x, y) PASTER(x,y)
|
#define EVALUATOR(x, y) PASTER(x,y)
|
||||||
#define MODULE_NAME EVALUATOR(nextpnrpy, ARCHNAME)
|
#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
|
// Architecture-specific bindings should be created in the below function, which must be implemented in all
|
||||||
// architectures
|
// architectures
|
||||||
@ -39,3 +43,41 @@ BOOST_PYTHON_MODULE (MODULE_NAME) {
|
|||||||
|
|
||||||
arch_wrap_python();
|
arch_wrap_python();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -79,5 +79,8 @@ struct range_wrapper {
|
|||||||
|
|
||||||
#define WRAP_RANGE(t) range_wrapper<t##Range>().wrap(#t "Range", #t "Iterator")
|
#define WRAP_RANGE(t) range_wrapper<t##Range>().wrap(#t "Range", #t "Iterator")
|
||||||
|
|
||||||
|
void execute_python_file(const char *executable, const char* python_file);
|
||||||
|
std::string parse_python_exception();
|
||||||
|
void arch_appendinittab();
|
||||||
|
|
||||||
#endif /* end of include guard: COMMON_PYBINDINGS_HH */
|
#endif /* end of include guard: COMMON_PYBINDINGS_HH */
|
||||||
|
6
common/version.h.in
Normal file
6
common/version.h.in
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef VERSION_H
|
||||||
|
#define VERSION_H
|
||||||
|
|
||||||
|
#define GIT_COMMIT_HASH_STR "@GIT_COMMIT_HASH@"
|
||||||
|
|
||||||
|
#endif
|
@ -18,13 +18,19 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "design.h"
|
#include "design.h"
|
||||||
|
#include "mainwindow.h"
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
int main()
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
Design design(ChipArgs{});
|
Design design(ChipArgs{});
|
||||||
|
|
||||||
for (auto bel : design.chip.getBels())
|
for (auto bel : design.chip.getBels())
|
||||||
printf("%s\n", design.chip.getBelName(bel).c_str());
|
printf("%s\n", design.chip.getBelName(bel).c_str());
|
||||||
|
|
||||||
return 0;
|
QApplication a(argc, argv);
|
||||||
|
MainWindow w;
|
||||||
|
w.show();
|
||||||
|
|
||||||
|
return a.exec();
|
||||||
}
|
}
|
||||||
|
60
gui/Qt5Customizations.cmake
Normal file
60
gui/Qt5Customizations.cmake
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
include(CMakeParseArguments)
|
||||||
|
|
||||||
|
# qt5_wrap_ui_custom(outfiles inputfile ... )
|
||||||
|
|
||||||
|
function(QT5_WRAP_UI_CUSTOM outfiles )
|
||||||
|
set(options)
|
||||||
|
set(oneValueArgs)
|
||||||
|
set(multiValueArgs OPTIONS)
|
||||||
|
|
||||||
|
cmake_parse_arguments(_WRAP_UI "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||||
|
|
||||||
|
set(ui_files ${_WRAP_UI_UNPARSED_ARGUMENTS})
|
||||||
|
set(ui_options ${_WRAP_UI_OPTIONS})
|
||||||
|
|
||||||
|
foreach(it ${ui_files})
|
||||||
|
get_filename_component(outfile ${it} NAME_WE)
|
||||||
|
get_filename_component(infile ${it} ABSOLUTE)
|
||||||
|
set(outfile ${CMAKE_CURRENT_BINARY_DIR}/generated/ui_${outfile}.h)
|
||||||
|
add_custom_command(OUTPUT ${outfile}
|
||||||
|
COMMAND ${Qt5Widgets_UIC_EXECUTABLE}
|
||||||
|
ARGS ${ui_options} -o ${outfile} ${infile}
|
||||||
|
MAIN_DEPENDENCY ${infile} VERBATIM)
|
||||||
|
list(APPEND ${outfiles} ${outfile})
|
||||||
|
endforeach()
|
||||||
|
set(${outfiles} ${${outfiles}} PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# qt5_add_resources_custom(outfiles inputfile ... )
|
||||||
|
|
||||||
|
function(QT5_ADD_RESOURCES_CUSTOM outfiles )
|
||||||
|
|
||||||
|
set(options)
|
||||||
|
set(oneValueArgs)
|
||||||
|
set(multiValueArgs OPTIONS)
|
||||||
|
|
||||||
|
cmake_parse_arguments(_RCC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||||
|
|
||||||
|
set(rcc_files ${_RCC_UNPARSED_ARGUMENTS})
|
||||||
|
set(rcc_options ${_RCC_OPTIONS})
|
||||||
|
|
||||||
|
if("${rcc_options}" MATCHES "-binary")
|
||||||
|
message(WARNING "Use qt5_add_binary_resources for binary option")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
foreach(it ${rcc_files})
|
||||||
|
get_filename_component(outfilename ${it} NAME_WE)
|
||||||
|
get_filename_component(infile ${it} ABSOLUTE)
|
||||||
|
set(outfile ${CMAKE_CURRENT_BINARY_DIR}/generated/qrc_${outfilename}.cc)
|
||||||
|
|
||||||
|
_QT5_PARSE_QRC_FILE(${infile} _out_depends _rc_depends)
|
||||||
|
|
||||||
|
add_custom_command(OUTPUT ${outfile}
|
||||||
|
COMMAND ${Qt5Core_RCC_EXECUTABLE}
|
||||||
|
ARGS ${rcc_options} --name ${outfilename} --output ${outfile} ${infile}
|
||||||
|
MAIN_DEPENDENCY ${infile}
|
||||||
|
DEPENDS ${_rc_depends} "${out_depends}" VERBATIM)
|
||||||
|
list(APPEND ${outfiles} ${outfile})
|
||||||
|
endforeach()
|
||||||
|
set(${outfiles} ${${outfiles}} PARENT_SCOPE)
|
||||||
|
endfunction()
|
150
gui/emb.cc
Normal file
150
gui/emb.cc
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2011 Mateusz Loskot <mateusz@loskot.net>
|
||||||
|
// Distributed under the Boost Software License, Version 1.0.
|
||||||
|
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
// Blog article: http://mateusz.loskot.net/?p=2819
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <Python.h>
|
||||||
|
#include "emb.h"
|
||||||
|
|
||||||
|
namespace emb
|
||||||
|
{
|
||||||
|
struct Stdout
|
||||||
|
{
|
||||||
|
PyObject_HEAD
|
||||||
|
stdout_write_type write;
|
||||||
|
};
|
||||||
|
|
||||||
|
PyObject* Stdout_write(PyObject* self, PyObject* args)
|
||||||
|
{
|
||||||
|
std::size_t written(0);
|
||||||
|
Stdout* selfimpl = reinterpret_cast<Stdout*>(self);
|
||||||
|
if (selfimpl->write)
|
||||||
|
{
|
||||||
|
char* data;
|
||||||
|
if (!PyArg_ParseTuple(args, "s", &data))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
std::string str(data);
|
||||||
|
selfimpl->write(str);
|
||||||
|
written = str.size();
|
||||||
|
}
|
||||||
|
return PyLong_FromSize_t(written);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* Stdout_flush(PyObject* self, PyObject* args)
|
||||||
|
{
|
||||||
|
// no-op
|
||||||
|
return Py_BuildValue("");
|
||||||
|
}
|
||||||
|
|
||||||
|
PyMethodDef Stdout_methods[] =
|
||||||
|
{
|
||||||
|
{"write", Stdout_write, METH_VARARGS, "sys.stdout.write"},
|
||||||
|
{"flush", Stdout_flush, METH_VARARGS, "sys.stdout.write"},
|
||||||
|
{0, 0, 0, 0} // sentinel
|
||||||
|
};
|
||||||
|
|
||||||
|
PyTypeObject StdoutType =
|
||||||
|
{
|
||||||
|
PyVarObject_HEAD_INIT(0, 0)
|
||||||
|
"emb.StdoutType", /* tp_name */
|
||||||
|
sizeof(Stdout), /* tp_basicsize */
|
||||||
|
0, /* tp_itemsize */
|
||||||
|
0, /* tp_dealloc */
|
||||||
|
0, /* tp_print */
|
||||||
|
0, /* tp_getattr */
|
||||||
|
0, /* tp_setattr */
|
||||||
|
0, /* tp_reserved */
|
||||||
|
0, /* tp_repr */
|
||||||
|
0, /* tp_as_number */
|
||||||
|
0, /* tp_as_sequence */
|
||||||
|
0, /* tp_as_mapping */
|
||||||
|
0, /* tp_hash */
|
||||||
|
0, /* tp_call */
|
||||||
|
0, /* tp_str */
|
||||||
|
0, /* tp_getattro */
|
||||||
|
0, /* tp_setattro */
|
||||||
|
0, /* tp_as_buffer */
|
||||||
|
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
||||||
|
"emb.Stdout objects", /* tp_doc */
|
||||||
|
0, /* tp_traverse */
|
||||||
|
0, /* tp_clear */
|
||||||
|
0, /* tp_richcompare */
|
||||||
|
0, /* tp_weaklistoffset */
|
||||||
|
0, /* tp_iter */
|
||||||
|
0, /* tp_iternext */
|
||||||
|
Stdout_methods, /* tp_methods */
|
||||||
|
0, /* tp_members */
|
||||||
|
0, /* tp_getset */
|
||||||
|
0, /* tp_base */
|
||||||
|
0, /* tp_dict */
|
||||||
|
0, /* tp_descr_get */
|
||||||
|
0, /* tp_descr_set */
|
||||||
|
0, /* tp_dictoffset */
|
||||||
|
0, /* tp_init */
|
||||||
|
0, /* tp_alloc */
|
||||||
|
0, /* tp_new */
|
||||||
|
};
|
||||||
|
|
||||||
|
PyModuleDef embmodule =
|
||||||
|
{
|
||||||
|
PyModuleDef_HEAD_INIT,
|
||||||
|
"emb", 0, -1, 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Internal state
|
||||||
|
PyObject* g_stdout;
|
||||||
|
PyObject* g_stdout_saved;
|
||||||
|
|
||||||
|
PyMODINIT_FUNC PyInit_emb(void)
|
||||||
|
{
|
||||||
|
g_stdout = 0;
|
||||||
|
g_stdout_saved = 0;
|
||||||
|
|
||||||
|
StdoutType.tp_new = PyType_GenericNew;
|
||||||
|
if (PyType_Ready(&StdoutType) < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
PyObject* m = PyModule_Create(&embmodule);
|
||||||
|
if (m)
|
||||||
|
{
|
||||||
|
Py_INCREF(&StdoutType);
|
||||||
|
PyModule_AddObject(m, "Stdout", reinterpret_cast<PyObject*>(&StdoutType));
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_stdout(stdout_write_type write)
|
||||||
|
{
|
||||||
|
if (!g_stdout)
|
||||||
|
{
|
||||||
|
g_stdout_saved = PySys_GetObject("stdout"); // borrowed
|
||||||
|
g_stdout = StdoutType.tp_new(&StdoutType, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stdout* impl = reinterpret_cast<Stdout*>(g_stdout);
|
||||||
|
impl->write = write;
|
||||||
|
PySys_SetObject("stdout", g_stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset_stdout()
|
||||||
|
{
|
||||||
|
if (g_stdout_saved)
|
||||||
|
PySys_SetObject("stdout", g_stdout_saved);
|
||||||
|
|
||||||
|
Py_XDECREF(g_stdout);
|
||||||
|
g_stdout = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void append_inittab()
|
||||||
|
{
|
||||||
|
PyImport_AppendInittab("emb", emb::PyInit_emb);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace emb
|
21
gui/emb.h
Normal file
21
gui/emb.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2011 Mateusz Loskot <mateusz@loskot.net>
|
||||||
|
// Distributed under the Boost Software License, Version 1.0.
|
||||||
|
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
// Blog article: http://mateusz.loskot.net/?p=2819
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace emb
|
||||||
|
{
|
||||||
|
typedef std::function<void(std::string)> stdout_write_type;
|
||||||
|
|
||||||
|
void set_stdout(stdout_write_type write);
|
||||||
|
void reset_stdout();
|
||||||
|
|
||||||
|
void append_inittab();
|
||||||
|
} // namespace emb
|
153
gui/fpgaviewwidget.cc
Normal file
153
gui/fpgaviewwidget.cc
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <math.h>
|
||||||
|
#include "fpgaviewwidget.h"
|
||||||
|
|
||||||
|
FPGAViewWidget::FPGAViewWidget(QWidget *parent)
|
||||||
|
: QOpenGLWidget(parent),
|
||||||
|
m_xMove(0),m_yMove(0),m_zDistance(1.0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
FPGAViewWidget::~FPGAViewWidget()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize FPGAViewWidget::minimumSizeHint() const
|
||||||
|
{
|
||||||
|
return QSize(640, 480);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize FPGAViewWidget::sizeHint() const
|
||||||
|
{
|
||||||
|
return QSize(640, 480);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FPGAViewWidget::setXTranslation(float t_x)
|
||||||
|
{
|
||||||
|
if(t_x != m_xMove)
|
||||||
|
{
|
||||||
|
m_xMove = t_x;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FPGAViewWidget::setYTranslation(float t_y)
|
||||||
|
{
|
||||||
|
if(t_y != m_yMove)
|
||||||
|
{
|
||||||
|
m_yMove = t_y;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FPGAViewWidget::setZoom(float t_z)
|
||||||
|
{
|
||||||
|
if(t_z != m_zDistance)
|
||||||
|
{
|
||||||
|
m_zDistance -= t_z;
|
||||||
|
if(m_zDistance < 0.1f)
|
||||||
|
m_zDistance = 0.1f;
|
||||||
|
if(m_zDistance > 10.0f)
|
||||||
|
m_zDistance = 10.0f;
|
||||||
|
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FPGAViewWidget::initializeGL()
|
||||||
|
{
|
||||||
|
initializeOpenGLFunctions();
|
||||||
|
glClearColor(1.0, 1.0, 1.0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FPGAViewWidget::paintGL()
|
||||||
|
{
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
glTranslatef(m_xMove, m_yMove, -10.0);
|
||||||
|
glScalef(m_zDistance,m_zDistance, 0.0f);
|
||||||
|
|
||||||
|
// Example grid
|
||||||
|
glColor3f(0.8, 0.8, 0.8);
|
||||||
|
glBegin(GL_LINES);
|
||||||
|
for(float i = -100; i <= 100; i += 0.1)
|
||||||
|
{
|
||||||
|
glVertex3f((float)i, -100.0f, 0.0f);
|
||||||
|
glVertex3f((float)i, 100.0f, 0.0f);
|
||||||
|
glVertex3f(-100.0f, (float)i, 0.0f);
|
||||||
|
glVertex3f(100.0f, (float)i, 0.0f);
|
||||||
|
}
|
||||||
|
glColor3f(0.5, 0.5, 0.5);
|
||||||
|
for(int i = -100; i <= 100; i += 1)
|
||||||
|
{
|
||||||
|
glVertex3f((float)i, -100.0f, 0.0f);
|
||||||
|
glVertex3f((float)i, 100.0f, 0.0f);
|
||||||
|
glVertex3f(-100.0f, (float)i, 0.0f);
|
||||||
|
glVertex3f(100.0f, (float)i, 0.0f);
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
// Example triangle
|
||||||
|
glBegin(GL_TRIANGLES);
|
||||||
|
glColor3f(1.0, 0.0, 0.0);
|
||||||
|
glVertex3f(-0.5, -0.5, 0);
|
||||||
|
glColor3f(0.0, 1.0, 0.0);
|
||||||
|
glVertex3f(0.5, -0.5, 0);
|
||||||
|
glColor3f(0.0, 0.0, 1.0);
|
||||||
|
glVertex3f(0, 0.5, 0);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void FPGAViewWidget::resizeGL(int width, int height)
|
||||||
|
{
|
||||||
|
m_windowWidth = width;
|
||||||
|
m_windowHeight = height;
|
||||||
|
glViewport(0, 0, m_windowWidth, m_windowHeight);
|
||||||
|
|
||||||
|
float aspect = width * 1.0 / height;
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
glOrtho(-1.0* aspect, +1.0* aspect, -1.0, +1.0, 1.0, 15.0);
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FPGAViewWidget::mousePressEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
m_lastPos = event->pos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FPGAViewWidget::mouseMoveEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
int dx = event->x() - m_lastPos.x();
|
||||||
|
int dy = event->y() - m_lastPos.y();
|
||||||
|
float dx_scale = dx * (1 / (float)640);
|
||||||
|
float dy_scale = -dy * (1 / (float)480);
|
||||||
|
|
||||||
|
if (event->buttons() & Qt::LeftButton)
|
||||||
|
{
|
||||||
|
float xpos = m_xMove + dx_scale;
|
||||||
|
float ypos = m_yMove + dy_scale;
|
||||||
|
if (m_xMove/m_zDistance <= 100.0 && m_xMove/m_zDistance>= -100.0) setXTranslation(xpos);
|
||||||
|
if (m_yMove/m_zDistance <= 100.0 && m_yMove/m_zDistance>= -100.0) setYTranslation(ypos);
|
||||||
|
|
||||||
|
}
|
||||||
|
m_lastPos = event->pos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FPGAViewWidget::wheelEvent(QWheelEvent *event)
|
||||||
|
{
|
||||||
|
QPoint degree = event->angleDelta() / 8;
|
||||||
|
|
||||||
|
if(!degree.isNull())
|
||||||
|
{
|
||||||
|
QPoint step = degree / 15;
|
||||||
|
setZoom(step.y() * -0.1f);
|
||||||
|
}
|
||||||
|
}
|
43
gui/fpgaviewwidget.h
Normal file
43
gui/fpgaviewwidget.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#ifndef MAPGLWIDGET_H
|
||||||
|
#define MAPGLWIDGET_H
|
||||||
|
|
||||||
|
#include <QOpenGLWidget>
|
||||||
|
#include <QOpenGLFunctions>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
FPGAViewWidget(QWidget *parent = 0);
|
||||||
|
~FPGAViewWidget();
|
||||||
|
|
||||||
|
QSize minimumSizeHint() const override;
|
||||||
|
QSize sizeHint() const override;
|
||||||
|
|
||||||
|
void setXTranslation(float t_x);
|
||||||
|
void setYTranslation(float t_y);
|
||||||
|
void setZoom(float t_z);
|
||||||
|
|
||||||
|
void xRotationChanged(int angle);
|
||||||
|
void yRotationChanged(int angle);
|
||||||
|
void zRotationChanged(int angle);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void initializeGL() Q_DECL_OVERRIDE;
|
||||||
|
void paintGL() Q_DECL_OVERRIDE;
|
||||||
|
void resizeGL(int width, int height) Q_DECL_OVERRIDE;
|
||||||
|
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
|
||||||
|
void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
|
||||||
|
void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_windowWidth;
|
||||||
|
int m_windowHeight;
|
||||||
|
float m_xMove;
|
||||||
|
float m_yMove;
|
||||||
|
float m_zDistance;
|
||||||
|
QPoint m_lastPos;
|
||||||
|
};
|
||||||
|
#endif
|
26
gui/gui.cmake
Normal file
26
gui/gui.cmake
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# Find the Qt5 libraries
|
||||||
|
find_package(Qt5 COMPONENTS Core Widgets OpenGL REQUIRED)
|
||||||
|
|
||||||
|
ADD_DEFINITIONS(-DQT_NO_KEYWORDS)
|
||||||
|
|
||||||
|
include( gui/Qt5Customizations.cmake )
|
||||||
|
|
||||||
|
# Find includes in corresponding build directories
|
||||||
|
include_directories(${CMAKE_CURRENT_BINARY_DIR}/generated)
|
||||||
|
|
||||||
|
qt5_generate_moc(gui/mainwindow.h ${CMAKE_CURRENT_BINARY_DIR}/generated/moc_mainwindow.cc)
|
||||||
|
qt5_generate_moc(gui/fpgaviewwidget.h ${CMAKE_CURRENT_BINARY_DIR}/generated/moc_fpgaviewwidget.cc)
|
||||||
|
|
||||||
|
set(GENERATED_MOC_FILES
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/generated/moc_mainwindow.cc
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/generated/moc_fpgaviewwidget.cc
|
||||||
|
)
|
||||||
|
|
||||||
|
set(UI_SOURCES
|
||||||
|
gui/mainwindow.ui
|
||||||
|
)
|
||||||
|
qt5_wrap_ui_custom(GENERATED_UI_HEADERS ${UI_SOURCES})
|
||||||
|
qt5_add_resources_custom(GUI_RESOURCE_FILES gui/nextpnr.qrc)
|
||||||
|
|
||||||
|
set(GUI_SOURCE_FILES gui/mainwindow.cc gui/fpgaviewwidget.cc gui/emb.cc ${GENERATED_MOC_FILES} ${GENERATED_UI_HEADERS} ${GUI_RESOURCE_FILES})
|
||||||
|
set(GUI_LIBRARY_FILES Qt5::Widgets Qt5::OpenGL GL)
|
87
gui/mainwindow.cc
Normal file
87
gui/mainwindow.cc
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
#include "mainwindow.h"
|
||||||
|
#include "ui_mainwindow.h"
|
||||||
|
#include <functional>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include "pybindings.h"
|
||||||
|
#include "emb.h"
|
||||||
|
|
||||||
|
MainWindow::MainWindow(QWidget *parent) :
|
||||||
|
QMainWindow(parent),
|
||||||
|
ui(new Ui::MainWindow)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
emb::append_inittab();
|
||||||
|
arch_appendinittab();
|
||||||
|
Py_Initialize();
|
||||||
|
PyImport_ImportModule("emb");
|
||||||
|
|
||||||
|
write = [this] (std::string s) {
|
||||||
|
//ui->plainTextEdit->moveCursor(QTextCursor::End);
|
||||||
|
//ui->plainTextEdit->insertPlainText(s.c_str());
|
||||||
|
//ui->plainTextEdit->moveCursor(QTextCursor::End);
|
||||||
|
ui->plainTextEdit->appendPlainText(s.c_str());
|
||||||
|
};
|
||||||
|
emb::set_stdout(write);
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindow::~MainWindow()
|
||||||
|
{
|
||||||
|
Py_Finalize();
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_system_exit()
|
||||||
|
{
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int MainWindow::executePython(std::string command)
|
||||||
|
{
|
||||||
|
PyObject *m, *d, *v;
|
||||||
|
m = PyImport_AddModule("__main__");
|
||||||
|
if (m == NULL)
|
||||||
|
return -1;
|
||||||
|
d = PyModule_GetDict(m);
|
||||||
|
v = PyRun_StringFlags(command.c_str(), (command.empty() ? Py_file_input : Py_single_input), d, d, NULL);
|
||||||
|
if (v == NULL)
|
||||||
|
{
|
||||||
|
PyObject *exception, *v, *tb;
|
||||||
|
|
||||||
|
if (PyErr_ExceptionMatches(PyExc_SystemExit)) {
|
||||||
|
handle_system_exit();
|
||||||
|
}
|
||||||
|
PyErr_Fetch(&exception, &v, &tb);
|
||||||
|
if (exception == NULL)
|
||||||
|
return 0;
|
||||||
|
PyErr_NormalizeException(&exception, &v, &tb);
|
||||||
|
if (tb == NULL) {
|
||||||
|
tb = Py_None;
|
||||||
|
Py_INCREF(tb);
|
||||||
|
}
|
||||||
|
PyException_SetTraceback(v, tb);
|
||||||
|
if (exception == NULL)
|
||||||
|
return 0;
|
||||||
|
PyErr_Clear();
|
||||||
|
|
||||||
|
PyObject* objectsRepresentation = PyObject_Str(v);
|
||||||
|
const char* errorStr = PyUnicode_AsUTF8(objectsRepresentation);
|
||||||
|
ui->plainTextEdit->appendPlainText(errorStr);
|
||||||
|
Py_DECREF(objectsRepresentation);
|
||||||
|
Py_XDECREF(exception);
|
||||||
|
Py_XDECREF(v);
|
||||||
|
Py_XDECREF(tb);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
Py_DECREF(v);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_lineEdit_returnPressed()
|
||||||
|
{
|
||||||
|
std::string input = ui->lineEdit->text().toStdString();
|
||||||
|
ui->plainTextEdit->appendPlainText(std::string(">>> " + input).c_str());
|
||||||
|
ui->plainTextEdit->update();
|
||||||
|
ui->lineEdit->clear();
|
||||||
|
int error = executePython(input);
|
||||||
|
}
|
30
gui/mainwindow.h
Normal file
30
gui/mainwindow.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef MAINWINDOW_H
|
||||||
|
#define MAINWINDOW_H
|
||||||
|
#include "emb.h"
|
||||||
|
|
||||||
|
#include <QMainWindow>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class MainWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MainWindow : public QMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MainWindow(QWidget *parent = 0);
|
||||||
|
~MainWindow();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int executePython(std::string command);
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void on_lineEdit_returnPressed();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::MainWindow *ui;
|
||||||
|
emb::stdout_write_type write;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MAINWINDOW_H
|
210
gui/mainwindow.ui
Normal file
210
gui/mainwindow.ui
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>MainWindow</class>
|
||||||
|
<widget class="QMainWindow" name="MainWindow">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>969</width>
|
||||||
|
<height>629</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>nextpnr</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="centralWidget">
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QSplitter" name="splitter_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<widget class="QSplitter" name="splitter">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<widget class="FPGAViewWidget" name="openGLWidget" native="true"/>
|
||||||
|
<widget class="QPlainTextEdit" name="plainTextEdit">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>50</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>16777215</width>
|
||||||
|
<height>200</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLineEdit" name="lineEdit">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>30</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>16777215</width>
|
||||||
|
<height>30</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QSplitter" name="splitter_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<widget class="QTreeView" name="treeView">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>200</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>200</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QTableView" name="tableView"/>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenuBar" name="menuBar">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>969</width>
|
||||||
|
<height>27</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<widget class="QMenu" name="menu_File">
|
||||||
|
<property name="title">
|
||||||
|
<string>&File</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="actionNew"/>
|
||||||
|
<addaction name="actionOpen"/>
|
||||||
|
<addaction name="actionSave"/>
|
||||||
|
<addaction name="actionSave_as"/>
|
||||||
|
<addaction name="actionClose"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="actionExit"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenu" name="menu_Help">
|
||||||
|
<property name="title">
|
||||||
|
<string>&Help</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="actionAbout"/>
|
||||||
|
</widget>
|
||||||
|
<addaction name="menu_File"/>
|
||||||
|
<addaction name="menu_Help"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QToolBar" name="mainToolBar">
|
||||||
|
<attribute name="toolBarArea">
|
||||||
|
<enum>TopToolBarArea</enum>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="toolBarBreak">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
<addaction name="actionNew"/>
|
||||||
|
<addaction name="actionOpen"/>
|
||||||
|
<addaction name="actionSave"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QStatusBar" name="statusBar"/>
|
||||||
|
<action name="actionNew">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="nextpnr.qrc">
|
||||||
|
<normaloff>:/icons/resources/new.png</normaloff>:/icons/resources/new.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>New</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionOpen">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="nextpnr.qrc">
|
||||||
|
<normaloff>:/icons/resources/open.png</normaloff>:/icons/resources/open.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Open</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionSave">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="nextpnr.qrc">
|
||||||
|
<normaloff>:/icons/resources/save.png</normaloff>:/icons/resources/save.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Save</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionSave_as">
|
||||||
|
<property name="text">
|
||||||
|
<string>Save as ...</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionClose">
|
||||||
|
<property name="text">
|
||||||
|
<string>Close</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionExit">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="nextpnr.qrc">
|
||||||
|
<normaloff>:/icons/resources/exit.png</normaloff>:/icons/resources/exit.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Exit</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionAbout">
|
||||||
|
<property name="text">
|
||||||
|
<string>About</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
</widget>
|
||||||
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>FPGAViewWidget</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>fpgaviewwidget.h</header>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources>
|
||||||
|
<include location="nextpnr.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>actionExit</sender>
|
||||||
|
<signal>triggered()</signal>
|
||||||
|
<receiver>MainWindow</receiver>
|
||||||
|
<slot>close()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>-1</x>
|
||||||
|
<y>-1</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>484</x>
|
||||||
|
<y>314</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
8
gui/nextpnr.qrc
Normal file
8
gui/nextpnr.qrc
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<RCC>
|
||||||
|
<qresource prefix="/icons">
|
||||||
|
<file>resources/new.png</file>
|
||||||
|
<file>resources/open.png</file>
|
||||||
|
<file>resources/save.png</file>
|
||||||
|
<file>resources/exit.png</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
BIN
gui/resources/exit.png
Normal file
BIN
gui/resources/exit.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
BIN
gui/resources/new.png
Normal file
BIN
gui/resources/new.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
BIN
gui/resources/open.png
Normal file
BIN
gui/resources/open.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
BIN
gui/resources/save.png
Normal file
BIN
gui/resources/save.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
@ -16,18 +16,86 @@
|
|||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "design.h"
|
#include "design.h"
|
||||||
|
#include "mainwindow.h"
|
||||||
|
#include <QApplication>
|
||||||
|
#include <iostream>
|
||||||
|
#include "version.h"
|
||||||
|
#include <boost/program_options.hpp>
|
||||||
|
#include "pybindings.h"
|
||||||
|
|
||||||
int main()
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
ChipArgs chipArgs;
|
namespace po = boost::program_options;
|
||||||
chipArgs.type = ChipArgs::LP384;
|
|
||||||
|
|
||||||
Design design(chipArgs);
|
std::string str;
|
||||||
|
|
||||||
for (auto bel : design.chip.getBels())
|
po::options_description options("Allowed options");
|
||||||
printf("%s\n", design.chip.getBelName(bel).c_str());
|
options.add_options()("help,h","show help");
|
||||||
|
options.add_options()("debug","just a check");
|
||||||
|
options.add_options()("gui","start gui");
|
||||||
|
options.add_options()("file", po::value<std::string>(), "python file to execute");
|
||||||
|
options.add_options()("version,v","show version");
|
||||||
|
|
||||||
|
po::positional_options_description pos;
|
||||||
|
pos.add("file", -1);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
catch(std::exception& e)
|
||||||
|
{
|
||||||
|
std::cout << e.what() << "\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vm.count("help") || argc == 1)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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("gui"))
|
||||||
|
{
|
||||||
|
QApplication a(argc, argv);
|
||||||
|
MainWindow w;
|
||||||
|
w.show();
|
||||||
|
|
||||||
|
return a.exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vm.count("debug"))
|
||||||
|
{
|
||||||
|
ChipArgs chipArgs;
|
||||||
|
chipArgs.type = ChipArgs::LP384;
|
||||||
|
|
||||||
|
Design design(chipArgs);
|
||||||
|
for (auto bel : design.chip.getBels())
|
||||||
|
printf("%s\n", design.chip.getBelName(bel).c_str());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vm.count("file"))
|
||||||
|
{
|
||||||
|
std::string filename = vm["file"].as<std::string>();
|
||||||
|
execute_python_file(argv[0],filename.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user