Merge pull request #921 from lnis-uofu/xt_swig
SWIG APIs for Tcl/Python binding with initial practice on Tcl interface
This commit is contained in:
commit
358c3e51ca
|
@ -149,6 +149,7 @@ jobs:
|
|||
build/vtr-verilog-to-routing/vpr/libvpr.a
|
||||
build/vtr-verilog-to-routing/vpr/vpr
|
||||
build/openfpga/libopenfpga.a
|
||||
build/openfpga/openfpga_shell.so
|
||||
build/openfpga/openfpga
|
||||
yosys/install/share
|
||||
yosys/install/bin
|
||||
|
@ -184,6 +185,10 @@ jobs:
|
|||
cc: gcc-9
|
||||
cxx: g++-9
|
||||
cmake_flags: "-DOPENFPGA_WITH_VERSION=OFF"
|
||||
- name: "Build w/o SWIG support (Ubuntu 20.04)"
|
||||
cc: gcc-9
|
||||
cxx: g++-9
|
||||
cmake_flags: "-DOPENFPGA_WITH_SWIG=OFF"
|
||||
# Define the steps to run the build job
|
||||
env:
|
||||
CC: ${{ matrix.config.cc }}
|
||||
|
@ -271,6 +276,7 @@ jobs:
|
|||
- name: quicklogic_reg_test
|
||||
- name: vtr_benchmark_reg_test
|
||||
- name: iwls_benchmark_reg_test
|
||||
- name: tcl_reg_test
|
||||
steps:
|
||||
- name: Cancel previous
|
||||
uses: styfle/cancel-workflow-action@0.9.1
|
||||
|
@ -328,6 +334,7 @@ jobs:
|
|||
- name: quicklogic_reg_test
|
||||
- name: vtr_benchmark_reg_test
|
||||
- name: iwls_benchmark_reg_test
|
||||
- name: tcl_reg_test
|
||||
steps:
|
||||
- name: Cancel previous
|
||||
uses: styfle/cancel-workflow-action@0.9.1
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
apt-get install --no-install-recommends -y \
|
||||
libdatetime-perl libc6 libffi-dev libgcc1 libreadline8 libstdc++6 \
|
||||
libtcl8.6 python3.8 python3-pip zlib1g libbz2-1.0 \
|
||||
libtcl8.6 tcl python3.8 python3-pip zlib1g libbz2-1.0 \
|
||||
iverilog git rsync make curl wget tree python3.8-venv
|
||||
|
|
|
@ -28,6 +28,7 @@ __pycache__/
|
|||
*.d
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
vpr7_x2p/vpr/vpr
|
||||
vpr7_x2p/printhandler/printhandlerdemo
|
||||
vpr7_x2p/libarchfpga/read_arch
|
||||
|
@ -52,4 +53,4 @@ vpr/vpr
|
|||
# Ignore temp directories
|
||||
node_modules
|
||||
package-lock.json
|
||||
/_*/
|
||||
/_*/
|
||||
|
|
|
@ -55,6 +55,7 @@ set(OPENFPGA_VERSION_PRERELEASE "dev")
|
|||
# Include user-defined functions
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
|
||||
include(FilesToDirs)
|
||||
include(SwigLib)
|
||||
|
||||
# Set the assertion level
|
||||
add_definitions("-DVTR_ASSERT_LEVEL=${VTR_ASSERT_LEVEL}")
|
||||
|
@ -68,6 +69,7 @@ option(OPENFPGA_WITH_YOSYS "Enable building Yosys" ON)
|
|||
option(OPENFPGA_WITH_YOSYS_PLUGIN "Enable building Yosys plugin" ON)
|
||||
option(OPENFPGA_WITH_TEST "Enable testing build for codebase. Once enabled, make test can be run" ON)
|
||||
option(OPENFPGA_WITH_VERSION "Enable version always-up-to-date when building codebase. Disable only when you do not care an accurate version number" ON)
|
||||
option(OPENFPGA_WITH_SWIG "Enable SWIG interface when building codebase. Disable when you do not need high-level interfaces, such as Tcl/Python" ON)
|
||||
|
||||
# Options pass on to VTR
|
||||
set(WITH_ABC ON CACHE BOOL "Enable building ABC in Verilog-to-Routing")
|
||||
|
@ -82,6 +84,21 @@ set(ODIN_YOSYS OFF CACHE BOOL "Enable building odin with yosys in Verilog-to-Rou
|
|||
set(YOSYS_SV_UHDM_PLUGIN OFF CACHE BOOL "Enable building and installing Yosys SystemVerilog and UHDM plugins in Verilog-to-Routing")
|
||||
set(VTR_ENABLE_VERSION ${OPENFPGA_WITH_VERSION} CACHE BOOL "Enable version always-up-to-date when building codebase. Disable only when you do not care an accurate version number")
|
||||
|
||||
# TCL file/lib required to link with SWIG generated wrapper
|
||||
if (OPENFPGA_WITH_SWIG)
|
||||
#Find Tcl
|
||||
include(FindTCL)
|
||||
message(STATUS "tcl.h path is : ${TCL_INCLUDE_PATH}")
|
||||
message(STATUS "libtcl.so path is : ${TCL_LIBRARY}")
|
||||
|
||||
#Find SWIG
|
||||
find_package(SWIG 3.0 REQUIRED)
|
||||
if (SWIG_VERSION VERSION_GREATER_EQUAL "4.1.0")
|
||||
message(WARNING "Using SWIG >= ${SWIG_VERSION} -flatstaticmethod flag for python")
|
||||
endif()
|
||||
include(UseSWIG)
|
||||
endif()
|
||||
|
||||
#Compiler flag configuration checks
|
||||
include(CheckCXXCompilerFlag)
|
||||
|
||||
|
@ -219,10 +236,17 @@ if(OPENFPGA_ENABLE_SANITIZE)
|
|||
link_libraries("-static-libasan") #Fixes 'ASan runtime does not come first in initial library list'
|
||||
endif()
|
||||
|
||||
# Extra flags
|
||||
set(SWIG_SHARED_FLAGS "")
|
||||
if (OPENFPGA_WITH_SWIG)
|
||||
set(SWIG_SHARED_FLAGS "-fpic")
|
||||
endif()
|
||||
add_compile_options(${SWIG_SHARED_FLAGS})
|
||||
|
||||
# Set final flags
|
||||
#
|
||||
separate_arguments(
|
||||
ADDITIONAL_FLAGS UNIX_COMMAND "${SANITIZE_FLAGS} ${PROFILING_FLAGS} ${COVERAGE_FLAGS} ${LOGGING_FLAGS} ${COLORED_COMPILE} ${EXTRA_FLAGS}"
|
||||
ADDITIONAL_FLAGS UNIX_COMMAND "${SANITIZE_FLAGS} ${PROFILING_FLAGS} ${COVERAGE_FLAGS} ${LOGGING_FLAGS} ${COLORED_COMPILE} ${EXTRA_FLAGS} ${SWIG_SHARED_FLAGS}"
|
||||
)
|
||||
separate_arguments(
|
||||
WARN_FLAGS UNIX_COMMAND "${WARN_FLAGS}"
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
# This is adapt based on the OpenROAD cmake module:
|
||||
# https://github.com/The-OpenROAD-Project/OpenROAD/tree/master/src/cmake
|
||||
#
|
||||
# Sets up swig for a .i file and encode .tcl files
|
||||
# Arguments
|
||||
# NAME <library>: the generated library name
|
||||
# I_FILE <file>: the .i file input to swig
|
||||
# NAMESPACE <name>: the namespace prefix in TCL
|
||||
# SWIG_INCLUDES <dir>* : optional list of include dirs for swig
|
||||
# SCRIPTS <file>* : tcl files to encode
|
||||
#
|
||||
# The intention is that this will create a library target with the
|
||||
# generated code in it. Additional c++ source will be added to the
|
||||
# target with target_sources() afterwards.
|
||||
|
||||
function(SwigLib)
|
||||
|
||||
# Parse args
|
||||
set(options "")
|
||||
set(oneValueArgs I_FILE NAME NAMESPACE LANGUAGE RUNTIME_HEADER)
|
||||
set(multiValueArgs SWIG_INCLUDES SCRIPTS)
|
||||
|
||||
cmake_parse_arguments(
|
||||
ARG # prefix on the parsed args
|
||||
"${options}"
|
||||
"${oneValueArgs}"
|
||||
"${multiValueArgs}"
|
||||
${ARGN}
|
||||
)
|
||||
|
||||
# Validate args
|
||||
if (DEFINED ARG_UNPARSED_ARGUMENTS)
|
||||
message(FATAL_ERROR "Unknown argument(s) to SwigLib: ${ARG_UNPARSED_ARGUMENTS}")
|
||||
endif()
|
||||
|
||||
if (DEFINED ARG_KEYWORDS_MISSING_VALUES)
|
||||
message(FATAL_ERROR "Missing value for argument(s) to SwigLib: ${ARG_KEYWORDS_MISSING_VALUES}")
|
||||
endif()
|
||||
|
||||
foreach(arg I_FILE NAME NAMESPACE)
|
||||
if (NOT DEFINED ARG_${arg})
|
||||
message(FATAL_ERROR "${arg} argument must be provided to SwigLib")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Default to tcl if unspecified
|
||||
if (NOT DEFINED ARG_LANGUAGE)
|
||||
set(ARG_LANGUAGE tcl)
|
||||
endif()
|
||||
|
||||
set_source_files_properties(${ARG_I_FILE} PROPERTIES CPLUSPLUS ON)
|
||||
|
||||
if (DEFINED ARG_SWIG_INCLUDES)
|
||||
set_property(SOURCE ${ARG_I_FILE}
|
||||
PROPERTY INCLUDE_DIRECTORIES ${ARG_SWIG_INCLUDES})
|
||||
endif()
|
||||
|
||||
if (${ARG_LANGUAGE} STREQUAL "tcl")
|
||||
set(LANGUAGE_OPTIONS -namespace -prefix ${ARG_NAMESPACE})
|
||||
endif()
|
||||
|
||||
# Setup swig of I_FILE.
|
||||
set_property(SOURCE ${ARG_I_FILE}
|
||||
PROPERTY COMPILE_OPTIONS ${LANGUAGE_OPTIONS}
|
||||
-Werror
|
||||
-w317,325,378,401,402,467,472,503,509)
|
||||
|
||||
set_property(SOURCE ${ARG_I_FILE}
|
||||
PROPERTY SWIG_MODULE_NAME ${ARG_NAME})
|
||||
set_property(SOURCE ${ARG_I_FILE}
|
||||
PROPERTY USE_SWIG_DEPENDENCIES TRUE)
|
||||
set_property(SOURCE ${ARG_I_FILE}
|
||||
PROPERTY USE_TARGET_INCLUDE_DIRECTORIES true)
|
||||
|
||||
# Use shared library which can be loaded in tclsh runtime
|
||||
swig_add_library(${ARG_NAME}
|
||||
LANGUAGE ${ARG_LANGUAGE}
|
||||
TYPE SHARED
|
||||
SOURCES ${ARG_I_FILE}
|
||||
)
|
||||
|
||||
# Disable problematic compiler warnings on generated files.
|
||||
# At this point only the swig generated sources are present.
|
||||
get_target_property(GEN_SRCS ${ARG_NAME} SOURCES)
|
||||
|
||||
foreach(GEN_SRC ${GEN_SRCS})
|
||||
set_source_files_properties(${GEN_SRC}
|
||||
PROPERTIES
|
||||
COMPILE_OPTIONS "-Wno-cast-qual;-Wno-missing-braces"
|
||||
)
|
||||
endforeach()
|
||||
|
||||
# These includes are always needed.
|
||||
# FIXME: Should be made as a parameter or set a rule to put all the dependent headers in a directory, i.e., include/
|
||||
target_include_directories(${ARG_NAME}
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/base
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/mux_lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/annotation
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/repack
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/fpga_bitstream
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/fabric
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/tile_direct
|
||||
)
|
||||
|
||||
if (${ARG_LANGUAGE} STREQUAL tcl)
|
||||
target_include_directories(${ARG_NAME}
|
||||
PRIVATE
|
||||
${TCL_INCLUDE_PATH}
|
||||
)
|
||||
elseif (${ARG_LANGUAGE} STREQUAL python)
|
||||
target_include_directories(${ARG_NAME}
|
||||
PRIVATE
|
||||
${Python3_INCLUDE_DIRS}
|
||||
)
|
||||
if (SWIG_VERSION VERSION_GREATER_EQUAL "4.1.0")
|
||||
set_property(TARGET ${ARG_NAME} PROPERTY SWIG_COMPILE_OPTIONS -flatstaticmethod)
|
||||
endif()
|
||||
|
||||
swig_link_libraries(${ARG_NAME}
|
||||
PUBLIC
|
||||
Python3::Python
|
||||
)
|
||||
endif()
|
||||
|
||||
if (DEFINED ARG_RUNTIME_HEADER)
|
||||
add_custom_command(
|
||||
OUTPUT ${ARG_RUNTIME_HEADER}
|
||||
COMMAND ${SWIG_EXECUTABLE} -${ARG_LANGUAGE} -external-runtime ${ARG_RUNTIME_HEADER}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
add_custom_target(${ARG_NAME}_RUNTIME_HEADER
|
||||
DEPENDS ${ARG_RUNTIME_HEADER}
|
||||
)
|
||||
add_dependencies(${ARG_NAME}
|
||||
${ARG_NAME}_RUNTIME_HEADER
|
||||
)
|
||||
target_include_directories(${ARG_NAME}
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
# Generate the encoded of the script files.
|
||||
if (DEFINED ARG_SCRIPTS)
|
||||
set(LANG_INIT ${CMAKE_CURRENT_BINARY_DIR}/${ARG_NAME}-${ARG_LANGUAGE}InitVar.cc)
|
||||
|
||||
add_custom_command(OUTPUT ${LANG_INIT}
|
||||
COMMAND ${OPENSTA_HOME}/etc/TclEncode.tcl ${LANG_INIT} ${ARG_NAME}_${ARG_LANGUAGE}_inits ${ARG_SCRIPTS}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
DEPENDS ${ARG_SCRIPTS}
|
||||
)
|
||||
|
||||
target_sources(${ARG_NAME}
|
||||
PRIVATE
|
||||
${LANG_INIT}
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
|
@ -75,7 +75,7 @@ class Shell {
|
|||
};
|
||||
|
||||
public: /* Constructor */
|
||||
Shell<T>(const char* name);
|
||||
Shell<T>();
|
||||
|
||||
public: /* Public accessors */
|
||||
std::string name() const;
|
||||
|
@ -96,6 +96,7 @@ class Shell {
|
|||
const ShellCommandClassId& cmd_class_id) const;
|
||||
|
||||
public: /* Public mutators */
|
||||
void set_name(const char* name);
|
||||
void add_title(const char* title);
|
||||
ShellCommandId add_command(const Command& cmd, const char* descr);
|
||||
void set_command_class(const ShellCommandId& cmd_id,
|
||||
|
@ -177,8 +178,6 @@ class Shell {
|
|||
int execution_errors() const;
|
||||
/* Quit the shell */
|
||||
void exit(const int& init_err = 0) const;
|
||||
|
||||
private: /* Private executors */
|
||||
/* Execute a command, the command line is the user's input to launch a command
|
||||
* The common_context is the data structure to exchange data between commands
|
||||
*/
|
||||
|
|
|
@ -26,8 +26,8 @@ namespace openfpga {
|
|||
* Public constructors
|
||||
********************************************************************/
|
||||
template<class T>
|
||||
Shell<T>::Shell(const char* name) {
|
||||
name_ = std::string(name);
|
||||
Shell<T>::Shell() {
|
||||
name_ = std::string("shell_no_name");
|
||||
time_start_ = 0;
|
||||
}
|
||||
|
||||
|
@ -104,6 +104,11 @@ std::vector<ShellCommandId> Shell<T>::commands_by_class(const ShellCommandClassI
|
|||
/************************************************************************
|
||||
* Public mutators
|
||||
***********************************************************************/
|
||||
template<class T>
|
||||
void Shell<T>::set_name(const char* name) {
|
||||
name_ = std::string(name);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void Shell<T>::add_title(const char* title) {
|
||||
title_ = std::string(title);
|
||||
|
|
|
@ -63,7 +63,8 @@ int main(int argc, char** argv) {
|
|||
* 1. help
|
||||
* 2. exit
|
||||
*/
|
||||
Shell<ShellContext> shell("test_shell");
|
||||
Shell<ShellContext> shell;
|
||||
shell.set_name("test_shell");
|
||||
std::string shell_title;
|
||||
|
||||
shell_title += std::string("The MIT License\n");
|
||||
|
|
|
@ -10,7 +10,19 @@ files_to_dirs(LIB_HEADERS LIB_INCLUDE_DIRS)
|
|||
#Remove test executable from library
|
||||
list(REMOVE_ITEM LIB_SOURCES ${EXEC_SOURCE})
|
||||
|
||||
if (OPENFPGA_WITH_SWIG)
|
||||
# SWIG library
|
||||
SwigLib(NAME openfpga_shell
|
||||
NAMESPACE std
|
||||
LANGUAGE tcl
|
||||
I_FILE src/openfpga_shell.i)
|
||||
target_include_directories(openfpga_shell PUBLIC ${LIB_INCLUDE_DIRS})
|
||||
target_link_libraries(openfpga_shell
|
||||
libopenfpga)
|
||||
endif()
|
||||
|
||||
#Create the library
|
||||
#Static linked library for other C++ libraries
|
||||
add_library(libopenfpga STATIC
|
||||
${LIB_HEADERS}
|
||||
${LIB_SOURCES})
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
#include "openfpga_shell.h"
|
||||
|
||||
#include "basic_command.h"
|
||||
#include "command_echo.h"
|
||||
#include "command_parser.h"
|
||||
#include "openfpga_bitstream_command.h"
|
||||
#include "openfpga_context.h"
|
||||
#include "openfpga_sdc_command.h"
|
||||
#include "openfpga_setup_command.h"
|
||||
#include "openfpga_spice_command.h"
|
||||
#include "openfpga_title.h"
|
||||
#include "openfpga_verilog_command.h"
|
||||
#include "vpr_command.h"
|
||||
|
||||
OpenfpgaShell::OpenfpgaShell() {
|
||||
shell_.set_name("OpenFPGA");
|
||||
shell_.add_title(create_openfpga_title().c_str());
|
||||
|
||||
/* Add vpr commands */
|
||||
openfpga::add_vpr_commands(shell_);
|
||||
|
||||
/* Add openfpga setup commands */
|
||||
openfpga::add_openfpga_setup_commands(shell_);
|
||||
|
||||
/* Add openfpga verilog commands */
|
||||
openfpga::add_openfpga_verilog_commands(shell_);
|
||||
|
||||
/* Add openfpga bitstream commands */
|
||||
openfpga::add_openfpga_bitstream_commands(shell_);
|
||||
|
||||
/* Add openfpga SPICE commands */
|
||||
openfpga::add_openfpga_spice_commands(shell_);
|
||||
|
||||
/* Add openfpga sdc commands */
|
||||
openfpga::add_openfpga_sdc_commands(shell_);
|
||||
|
||||
/* Add basic commands: exit, help, etc.
|
||||
* Note:
|
||||
* This MUST be the last command group to be added!
|
||||
*/
|
||||
openfpga::add_basic_commands(shell_);
|
||||
}
|
||||
|
||||
int OpenfpgaShell::run_command(const char* cmd_line) {
|
||||
return shell_.execute_command(cmd_line, openfpga_ctx_);
|
||||
}
|
||||
|
||||
void OpenfpgaShell::reset() {
|
||||
/* TODO: reset the shell status */
|
||||
/* TODO: reset the data storage */
|
||||
}
|
||||
|
||||
int OpenfpgaShell::start(int argc, char** argv) {
|
||||
reset();
|
||||
|
||||
/* Create the command to launch shell in different modes */
|
||||
openfpga::Command start_cmd("OpenFPGA");
|
||||
/* Add options to openfpga shell interface */
|
||||
/* '--interactive', -i': launch the interactive mode */
|
||||
openfpga::CommandOptionId opt_interactive = start_cmd.add_option(
|
||||
"interactive", false, "Launch OpenFPGA in interactive mode");
|
||||
start_cmd.set_option_short_name(opt_interactive, "i");
|
||||
|
||||
/* '--file', -f': launch the script mode */
|
||||
openfpga::CommandOptionId opt_script_mode =
|
||||
start_cmd.add_option("file", false, "Launch OpenFPGA in script mode");
|
||||
start_cmd.set_option_require_value(opt_script_mode, openfpga::OPT_STRING);
|
||||
start_cmd.set_option_short_name(opt_script_mode, "f");
|
||||
|
||||
/* '--batch_execution': execute the script in batch mode.
|
||||
* Will exit immediately when fatal errors occurred
|
||||
*/
|
||||
openfpga::CommandOptionId opt_batch_exec =
|
||||
start_cmd.add_option("batch_execution", false,
|
||||
"Launch OpenFPGA in batch mode when running scripts");
|
||||
start_cmd.set_option_short_name(opt_batch_exec, "batch");
|
||||
|
||||
/* '--version', -v': print version information */
|
||||
openfpga::CommandOptionId opt_version =
|
||||
start_cmd.add_option("version", false, "Show OpenFPGA version");
|
||||
start_cmd.set_option_short_name(opt_version, "v");
|
||||
|
||||
/* '--help', -h': print help desk */
|
||||
openfpga::CommandOptionId opt_help =
|
||||
start_cmd.add_option("help", false, "Help desk");
|
||||
start_cmd.set_option_short_name(opt_help, "h");
|
||||
|
||||
/* Parse the option, to avoid issues, we use the command name to replace the
|
||||
* argv[0] */
|
||||
std::vector<std::string> cmd_opts;
|
||||
cmd_opts.push_back(start_cmd.name());
|
||||
for (int iarg = 1; iarg < argc; ++iarg) {
|
||||
cmd_opts.push_back(std::string(argv[iarg]));
|
||||
}
|
||||
|
||||
openfpga::CommandContext start_cmd_context(start_cmd);
|
||||
if (false == parse_command(cmd_opts, start_cmd, start_cmd_context)) {
|
||||
/* Parse fail: Echo the command */
|
||||
openfpga::print_command_options(start_cmd);
|
||||
} else {
|
||||
/* Parse succeed. Branch on options */
|
||||
/* Show version */
|
||||
if (true == start_cmd_context.option_enable(start_cmd, opt_version)) {
|
||||
print_openfpga_version_info();
|
||||
return 0;
|
||||
}
|
||||
/* Start a shell */
|
||||
if (true == start_cmd_context.option_enable(start_cmd, opt_interactive)) {
|
||||
shell_.run_interactive_mode(openfpga_ctx_);
|
||||
return shell_.exit_code();
|
||||
}
|
||||
|
||||
if (true == start_cmd_context.option_enable(start_cmd, opt_script_mode)) {
|
||||
shell_.run_script_mode(
|
||||
start_cmd_context.option_value(start_cmd, opt_script_mode).c_str(),
|
||||
openfpga_ctx_,
|
||||
start_cmd_context.option_enable(start_cmd, opt_batch_exec));
|
||||
return shell_.exit_code();
|
||||
}
|
||||
/* Reach here there is something wrong, show the help desk */
|
||||
openfpga::print_command_options(start_cmd);
|
||||
}
|
||||
|
||||
/* Reach here, it means shell execution has critical errors.
|
||||
* Return a code with fatal errors
|
||||
*/
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
#ifndef OPENFPGA_SHELL_H
|
||||
#define OPENFPGA_SHELL_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "openfpga_context.h"
|
||||
#include "shell.h"
|
||||
|
||||
/********************************************************************
|
||||
* This is a shell class built on top of the general-purpose shell
|
||||
* It is dedicated for the usage of OpenFPGA engines
|
||||
* - It includes the data storage required
|
||||
* - It includes all the commands available in OpenFPGA
|
||||
*******************************************************************/
|
||||
class OpenfpgaShell {
|
||||
public: /* Contructors */
|
||||
OpenfpgaShell();
|
||||
|
||||
public: /* Mutators */
|
||||
/* Execute a specific command with options in a line, which is available in
|
||||
* the shell Note that running a command will be based on the current status
|
||||
* of data storage. The data storage is impacted by previous commands that
|
||||
* have been run. If you want a clear start, please call API reset() before
|
||||
* running a command. Running a command may cause modification to data
|
||||
* storage. */
|
||||
int run_command(const char* cmd_line);
|
||||
|
||||
/* Start the shell with options. For detailed usage, please refer to online
|
||||
* documentation about openfpgashell Depending on the options, a shell may run
|
||||
* in
|
||||
* - an interactive mode, where users can type in commands and get results
|
||||
* or
|
||||
* - an batch mode, where users provide a script contains a set of commands to
|
||||
* execute
|
||||
* TODO: the shell always has a clean start (refreshed data storage).
|
||||
*/
|
||||
int start(int argc, char** argv);
|
||||
|
||||
/* Reset the data storage and shell status, to ensure a clean start */
|
||||
void reset();
|
||||
|
||||
private: /* Internal data */
|
||||
openfpga::Shell<OpenfpgaContext> shell_;
|
||||
OpenfpgaContext openfpga_ctx_;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,136 +1,12 @@
|
|||
/********************************************************************
|
||||
* Build the OpenFPGA shell interface
|
||||
*******************************************************************/
|
||||
/* Header file from vtrutil library */
|
||||
#include "vtr_log.h"
|
||||
#include "vtr_time.h"
|
||||
|
||||
/* Header file from libopenfpgashell library */
|
||||
#include "command_echo.h"
|
||||
#include "command_parser.h"
|
||||
#include "shell.h"
|
||||
|
||||
/* Header file from openfpga */
|
||||
#include "basic_command.h"
|
||||
#include "openfpga_bitstream_command.h"
|
||||
#include "openfpga_context.h"
|
||||
#include "openfpga_sdc_command.h"
|
||||
#include "openfpga_setup_command.h"
|
||||
#include "openfpga_spice_command.h"
|
||||
#include "openfpga_title.h"
|
||||
#include "openfpga_verilog_command.h"
|
||||
#include "vpr_command.h"
|
||||
#include "openfpga_shell.h"
|
||||
|
||||
/********************************************************************
|
||||
* Main function to start OpenFPGA shell interface
|
||||
*******************************************************************/
|
||||
int main(int argc, char** argv) {
|
||||
/* Create the command to launch shell in different modes */
|
||||
openfpga::Command start_cmd("OpenFPGA");
|
||||
/* Add options to openfpga shell interface */
|
||||
/* '--interactive', -i': launch the interactive mode */
|
||||
openfpga::CommandOptionId opt_interactive = start_cmd.add_option(
|
||||
"interactive", false, "Launch OpenFPGA in interactive mode");
|
||||
start_cmd.set_option_short_name(opt_interactive, "i");
|
||||
|
||||
/* '--file', -f': launch the script mode */
|
||||
openfpga::CommandOptionId opt_script_mode =
|
||||
start_cmd.add_option("file", false, "Launch OpenFPGA in script mode");
|
||||
start_cmd.set_option_require_value(opt_script_mode, openfpga::OPT_STRING);
|
||||
start_cmd.set_option_short_name(opt_script_mode, "f");
|
||||
|
||||
/* '--batch_execution': execute the script in batch mode.
|
||||
* Will exit immediately when fatal errors occurred
|
||||
*/
|
||||
openfpga::CommandOptionId opt_batch_exec =
|
||||
start_cmd.add_option("batch_execution", false,
|
||||
"Launch OpenFPGA in batch mode when running scripts");
|
||||
start_cmd.set_option_short_name(opt_batch_exec, "batch");
|
||||
|
||||
/* '--version', -v': print version information */
|
||||
openfpga::CommandOptionId opt_version =
|
||||
start_cmd.add_option("version", false, "Show OpenFPGA version");
|
||||
start_cmd.set_option_short_name(opt_version, "v");
|
||||
|
||||
/* '--help', -h': print help desk */
|
||||
openfpga::CommandOptionId opt_help =
|
||||
start_cmd.add_option("help", false, "Help desk");
|
||||
start_cmd.set_option_short_name(opt_help, "h");
|
||||
|
||||
/* Create a shell object
|
||||
* Add two commands, which are
|
||||
* 1. exit
|
||||
* 2. help. This must the last to add
|
||||
*/
|
||||
openfpga::Shell<OpenfpgaContext> shell("OpenFPGA");
|
||||
|
||||
shell.add_title(create_openfpga_title().c_str());
|
||||
|
||||
/* Add vpr commands */
|
||||
openfpga::add_vpr_commands(shell);
|
||||
|
||||
/* Add openfpga setup commands */
|
||||
openfpga::add_openfpga_setup_commands(shell);
|
||||
|
||||
/* Add openfpga verilog commands */
|
||||
openfpga::add_openfpga_verilog_commands(shell);
|
||||
|
||||
/* Add openfpga bitstream commands */
|
||||
openfpga::add_openfpga_bitstream_commands(shell);
|
||||
|
||||
/* Add openfpga SPICE commands */
|
||||
openfpga::add_openfpga_spice_commands(shell);
|
||||
|
||||
/* Add openfpga sdc commands */
|
||||
openfpga::add_openfpga_sdc_commands(shell);
|
||||
|
||||
/* Add basic commands: exit, help, etc.
|
||||
* Note:
|
||||
* This MUST be the last command group to be added!
|
||||
*/
|
||||
openfpga::add_basic_commands(shell);
|
||||
|
||||
/* Create the data base for the shell */
|
||||
OpenfpgaContext openfpga_context;
|
||||
|
||||
/* Parse the option, to avoid issues, we use the command name to replace the
|
||||
* argv[0] */
|
||||
std::vector<std::string> cmd_opts;
|
||||
cmd_opts.push_back(start_cmd.name());
|
||||
for (int iarg = 1; iarg < argc; ++iarg) {
|
||||
cmd_opts.push_back(std::string(argv[iarg]));
|
||||
}
|
||||
|
||||
openfpga::CommandContext start_cmd_context(start_cmd);
|
||||
if (false == parse_command(cmd_opts, start_cmd, start_cmd_context)) {
|
||||
/* Parse fail: Echo the command */
|
||||
openfpga::print_command_options(start_cmd);
|
||||
} else {
|
||||
/* Parse succeed. Branch on options */
|
||||
/* Show version */
|
||||
if (true == start_cmd_context.option_enable(start_cmd, opt_version)) {
|
||||
print_openfpga_version_info();
|
||||
return 0;
|
||||
}
|
||||
/* Start a shell */
|
||||
if (true == start_cmd_context.option_enable(start_cmd, opt_interactive)) {
|
||||
shell.run_interactive_mode(openfpga_context);
|
||||
return shell.exit_code();
|
||||
}
|
||||
|
||||
if (true == start_cmd_context.option_enable(start_cmd, opt_script_mode)) {
|
||||
shell.run_script_mode(
|
||||
start_cmd_context.option_value(start_cmd, opt_script_mode).c_str(),
|
||||
openfpga_context,
|
||||
start_cmd_context.option_enable(start_cmd, opt_batch_exec));
|
||||
return shell.exit_code();
|
||||
}
|
||||
/* Reach here there is something wrong, show the help desk */
|
||||
openfpga::print_command_options(start_cmd);
|
||||
}
|
||||
|
||||
/* Reach here, it means shell execution has critical errors.
|
||||
* Return a code with fatal errors
|
||||
*/
|
||||
return 1;
|
||||
OpenfpgaShell openfpga_shell;
|
||||
return openfpga_shell.start(argc, argv);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
/* SWIG interface file for OpenFPGA shell APIs */
|
||||
%module openfpga_shell
|
||||
|
||||
%{
|
||||
#include "openfpga_shell.h"
|
||||
%}
|
||||
|
||||
%include "openfpga_shell.h"
|
|
@ -0,0 +1,12 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
###############################################
|
||||
# OpenFPGA Shell in Tcl
|
||||
##############################################
|
||||
source openfpga.sh
|
||||
echo -e "Regression tests for OpenFPGA in Tcl Shell";
|
||||
|
||||
cd build/openfpga
|
||||
${OPENFPGA_PATH}/openfpga_flow/scripts/swig_tcl_example.tcl
|
||||
cd -
|
|
@ -0,0 +1,2 @@
|
|||
pkg_mkIndex . openfpga_shell.so
|
||||
exit
|
|
@ -0,0 +1,10 @@
|
|||
#! /bin/env tclsh
|
||||
# Load dynamic linked library
|
||||
load "openfpga_shell.so" openfpga_shell
|
||||
# Create a new Openfpga shell
|
||||
std::OpenfpgaShell openfpga_shell
|
||||
# Run an command
|
||||
openfpga_shell run_command "help"
|
||||
# Finish the quit
|
||||
#openfpga_shell run_command "exit"
|
||||
#exit
|
Loading…
Reference in New Issue