Skip to content

XDC physical constraints with TCL interpreter. #15

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 20 commits into
base: acom/fpga-interchange-rr-graph+constants
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/scripts/install_dependencies.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ sudo apt install -y \
libxml++2.6-dev \
libreadline-dev \
tcl-dev \
tk-dev \
libffi-dev \
perl \
texinfo \
Expand Down
22 changes: 11 additions & 11 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,26 @@ jobs:

Run-tests:
# Prevents from running on forks where no custom runners are available
if: ${{ github.repository_owner == 'verilog-to-routing' }}
#if: ${{ github.repository_owner == 'verilog-to-routing' }}

container: ubuntu:bionic

runs-on: [self-hosted, Linux, X64]
runs-on: ubuntu-18.04

strategy:
fail-fast: false
matrix:
include:
- {test: "vtr_reg_nightly_test1", cores: "8", options: "", cmake: "" }
- {test: "vtr_reg_nightly_test2", cores: "16", options: "", cmake: "" }
- {test: "vtr_reg_nightly_test3", cores: "16", options: "", cmake: "" }
- {test: "vtr_reg_nightly_test4", cores: "16", options: "", cmake: "" }
#- {test: "vtr_reg_nightly_test1", cores: "8", options: "", cmake: "" }
#- {test: "vtr_reg_nightly_test2", cores: "16", options: "", cmake: "" }
#- {test: "vtr_reg_nightly_test3", cores: "16", options: "", cmake: "" }
#- {test: "vtr_reg_nightly_test4", cores: "16", options: "", cmake: "" }
- {test: "vtr_reg_strong", cores: "16", options: "", cmake: "-DVTR_ASSERT_LEVEL=3" }
- {test: "vtr_reg_strong", cores: "16", options: "-skip_qor", cmake: "-DVTR_ASSERT_LEVEL=3 -DVTR_ENABLE_SANITIZE=ON"}
- {test: "vtr_reg_yosys", cores: "16", options: "", cmake: "-DWITH_YOSYS=ON" }
- {test: "vtr_reg_yosys_odin", cores: "16", options: "", cmake: "-DODIN_USE_YOSYS=ON" }
- {test: "odin_tech_strong", cores: "16", options: "", cmake: "-DODIN_USE_YOSYS=ON" }
- {test: "odin_reg_strong", cores: "16", options: "", cmake: "" }
#- {test: "vtr_reg_strong", cores: "16", options: "-skip_qor", cmake: "-DVTR_ASSERT_LEVEL=3 -DVTR_ENABLE_SANITIZE=ON"}
#- {test: "vtr_reg_yosys", cores: "16", options: "", cmake: "-DWITH_YOSYS=ON" }
#- {test: "vtr_reg_yosys_odin", cores: "16", options: "", cmake: "-DODIN_USE_YOSYS=ON" }
#- {test: "odin_tech_strong", cores: "16", options: "", cmake: "-DODIN_USE_YOSYS=ON" }
#- {test: "odin_reg_strong", cores: "16", options: "", cmake: "" }

env:
DEBIAN_FRONTEND: "noninteractive"
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ list(APPEND DIRS_TO_FORMAT_CPP "${CMAKE_CURRENT_SOURCE_DIR}/libs/libvtrutil")
list(APPEND DIRS_TO_FORMAT_CPP "${CMAKE_CURRENT_SOURCE_DIR}/libs/libpugiutil")
list(APPEND DIRS_TO_FORMAT_CPP "${CMAKE_CURRENT_SOURCE_DIR}/libs/liblog")
list(APPEND DIRS_TO_FORMAT_CPP "${CMAKE_CURRENT_SOURCE_DIR}/libs/librtlnumber")
list(APPEND DIRS_TO_FORMAT_CPP "${CMAKE_CURRENT_SOURCE_DIR}/libs/libtclcpp")
list(APPEND DIRS_TO_FORMAT_CPP "${CMAKE_CURRENT_SOURCE_DIR}/ODIN_II")

include(AutoClangFormat)
Expand Down
1 change: 1 addition & 0 deletions install_apt_packages.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ sudo apt-get install -y \
sudo apt-get install -y \
clang \
tcl-dev \
tk-dev \
libreadline-dev

# Required to build the documentation
Expand Down
1 change: 1 addition & 0 deletions libs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ if(${VTR_ENABLE_CAPNPROTO})
add_subdirectory(libvtrcapnproto)
endif()
add_subdirectory(librrgraph)
add_subdirectory(libtclcpp)
11 changes: 10 additions & 1 deletion libs/libarchfpga/src/physical_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -976,7 +976,7 @@ struct t_mode {
* input_string: input string verbatim to parse later
* output_string: input string output to parse later
* annotations: Annotations for delay, power, etc
* num_annotations: Total number of annotations
* num_annotations: Total number opb_typef annotations
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably a typo

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo still needs fix

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not my typo, will fix in another commit.

* infer_annotations: This interconnect is autogenerated, if true, infer pack_patterns
* such as carry-chains and forced packs based on interconnect linked to it
* parent_mode_index: Mode of parent as int
Expand Down Expand Up @@ -1773,6 +1773,14 @@ struct t_lut_element {
}
};

struct t_phys_map_region {
int x, y, w, h;
int subtile;
};

/* Maps Physical PIN name to a name of PAD BEL */
typedef std::unordered_map<std::string, t_phys_map_region> t_phys_grid_mapping;

/* Detailed routing architecture */
struct t_arch {
mutable vtr::string_internment strings;
Expand Down Expand Up @@ -1831,6 +1839,7 @@ struct t_arch {
std::string ipin_cblock_switch_name;

std::vector<t_grid_def> grid_layouts; //Set of potential device layouts
t_phys_grid_mapping phys_grid_mapping; //Mapping from physical pins to grid locations

t_clock_arch_spec clock_arch; // Clock related data types
};
Expand Down
32 changes: 32 additions & 0 deletions libs/libarchfpga/src/read_fpga_interchange_arch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -806,10 +806,13 @@ struct ArchReader {
}

void process_package_pins() {
std::unordered_map<std::string, std::string> site_to_pin_map;

for (auto package : ar_.getPackages()) {
for (auto pin : package.getPackagePins()) {
t_package_pin pckg_pin;
pckg_pin.name = str(pin.getPackagePin());


if (pin.getBel().isBel()) {
pckg_pin.bel_name = str(pin.getBel().getBel());
Expand All @@ -820,6 +823,35 @@ struct ArchReader {
pckg_pin.site_name = str(pin.getSite().getSite());

package_pins_.push_back(pckg_pin);

site_to_pin_map[pckg_pin.site_name] = pckg_pin.name;
}
}

/* Populate phys_grid_mapping - associate pin names with grid locations */
for (const auto& tile : ar_.getTileList()) {
int site_idx = 0;
for (const auto& site : tile.getSites()) {
int subtile = site_idx++;

std::string site_name = str(site.getName());
auto it = site_to_pin_map.find(site_name);
if (it == site_to_pin_map.end())
continue;
std::string& pin_name = it->second;

auto tile_type = ar_.getTileTypeList()[tile.getType()];

/* TODO: All tiles are currently set to 1x1 size, but this is done in process_tiles method which gets
* called later. We should split this logic in a way that's more suitable for constraining pins,
* because currently the line below makes an assumption about tile size which happens to be true only
* due to process_tiles implementation.
*
* A similar thing could be said about subtile indexing.
*/
t_phys_map_region pin_region { tile.getCol() + 1, tile.getRow() + 1, 1, 1, subtile };

arch_->phys_grid_mapping[pin_name] = std::move(pin_region);
}
}
}
Expand Down
21 changes: 21 additions & 0 deletions libs/libtclcpp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
cmake_minimum_required(VERSION 3.9)

project("libtclcpp")

file(GLOB_RECURSE LIB_SOURCES src/*.cpp)
file(GLOB_RECURSE LIB_HEADERS src/*.h)
files_to_dirs(LIB_HEADERS LIB_INCLUDE_DIRS)

add_library(libtclcpp STATIC
${LIB_HEADERS}
${LIB_SOURCES}
)

target_include_directories(libtclcpp PUBLIC ${LIB_INCLUDE_DIRS})

set_target_properties(libtclcpp PROPERTIES PREFIX "")

find_package(TCL REQUIRED)
target_link_libraries(libtclcpp tcl)

install(TARGETS libtclcpp DESTINATION bin)
157 changes: 157 additions & 0 deletions libs/libtclcpp/src/tclcpp.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
#include "tclcpp.h"

#include <functional>
#include <vector>
#include <list>
#include <tcl/tcl.h>
#include <cstring>
#include <sstream>

/* TCL ERRORS */
#define OV_TOSTRING(c, e) \
c::operator std::string() const { return (e); }

OV_TOSTRING(TCL_eException, "Unknown error")

TCL_eCustomException::TCL_eCustomException(std::string&& message_)
: message(std::move(message_)) {}
TCL_eCustomException::operator std::string() const { return (this->message); }

TCL_eFailedToInitTcl::TCL_eFailedToInitTcl(int error_code_)
: error_code(error_code_) {}
OV_TOSTRING(TCL_eFailedToInitTcl, "Can't initialize TCL (code " + std::to_string(error_code) + ")")

TCL_eErroneousTCL::TCL_eErroneousTCL(
std::string&& filename_,
int line_,
int column_,
std::string&& message_)
: filename(std::move(filename_))
, line(line_)
, column(column_)
, message(message_) {}
OV_TOSTRING(TCL_eErroneousTCL, this->filename + ":" + std::to_string(this->line) + "," + std::to_string(this->column) + ": " + this->message)

void Tcl_SetStringResult(Tcl_Interp* interp, const std::string& s) {
char* copy = Tcl_Alloc(s.length() + 1);
std::strcpy(copy, s.c_str());
Tcl_SetResult(interp, copy, TCL_DYNAMIC);
}

TclClient::TclClient()
: cmd_status(e_TclCommandStatus::TCL_CMD_SUCCESS)
, string("No errors") {}

void tcl_obj_dup(Tcl_Obj* src, Tcl_Obj* dst) {
dst->internalRep.twoPtrValue = src->internalRep.twoPtrValue;
dst->typePtr = src->typePtr;
dst->bytes = nullptr;
dst->length = 0;
}

void tcl_set_obj_string(Tcl_Obj* obj, const std::string& str) {
if (obj->bytes != nullptr)
Tcl_Free(obj->bytes);
obj->bytes = Tcl_Alloc(str.length() + 1);
obj->length = str.length();
std::strcpy(obj->bytes, str.c_str());
}

int tcl_set_from_none(Tcl_Interp* tcl_interp, Tcl_Obj* obj) {
(void)(obj); /* Surpress "unused parameter" macro */
/* TODO: Better error message */
Tcl_SetStringResult(tcl_interp, "Attempted an invalid conversion.");
return TCL_ERROR;
}

TclCtx::TclCtx() {
this->_tcl_interp = Tcl_CreateInterp();
#ifdef DEBUG
this->_init = false;
#endif
}

TclCtx::~TclCtx() {
Tcl_DeleteInterp(this->_tcl_interp);
}

void TclCtx::_init() {
int error;

if ((error = Tcl_Init(this->_tcl_interp)) != TCL_OK)
throw TCL_eFailedToInitTcl(error);

#ifdef DEBUG
this->_init = true;
#endif
}

void TclCtx::read_tcl(std::istream& tcl_stream) {
int error;

this->_debug_init();

std::ostringstream os;
tcl_stream >> os.rdbuf();
std::string tcl = os.str();

error = Tcl_Eval(this->_tcl_interp, tcl.c_str());
/* TODO: More precise error */
if (error != TCL_OK) {
int error_line = Tcl_GetErrorLine(this->_tcl_interp);
const char* msg = Tcl_GetStringResult(this->_tcl_interp);
throw TCL_eErroneousTCL("<unknown file>", error_line, 0, std::string(msg));
}
}

int TclCtx::_tcl_do_method(
ClientData cd,
Tcl_Interp* tcl_interp,
int objc,
Tcl_Obj* const objvp[]) {
TclMethodDispatchBase* d = static_cast<TclMethodDispatchBase*>(cd);
d->do_method(objc, objvp);

switch (d->client.cmd_status) {
case e_TclCommandStatus::TCL_CMD_FAIL:
Tcl_SetStringResult(tcl_interp, d->client.string);
return TCL_ERROR;
case e_TclCommandStatus::TCL_CMD_SUCCESS_STRING:
Tcl_SetStringResult(tcl_interp, d->client.string);
return TCL_OK;
case e_TclCommandStatus::TCL_CMD_SUCCESS_OBJECT:
case e_TclCommandStatus::TCL_CMD_SUCCESS_LIST:
Tcl_SetObjResult(tcl_interp, d->client.object);
default:
break;
}
return TCL_OK;
}

TclDynList::TclDynList(Tcl_Interp* interp, Tcl_Obj* obj)
: _interp(interp) {
const Tcl_ObjType* obj_type = obj->typePtr;
if (obj_type == nullptr)
return;

if (obj_type == nullptr || std::strcmp(obj_type->name, "list"))
this->_obj = Tcl_NewListObj(1, &obj);
else
this->_obj = obj;
}

TclDynList tcl_obj_getdynlist (TclClient* client, Tcl_Obj* obj) {
return TclDynList(client->_interp, obj);
}

Tcl_Obj* TclDynList::operator[](size_t idx) {
int count;
Tcl_Obj* objp;

Tcl_ListObjLength(this->_interp, this->_obj, &count);
if (idx >= size_t(count))
return nullptr;
Tcl_ListObjIndex(this->_interp, this->_obj, idx, &objp);

return objp;
}
Loading