Merge branch 'refactoring' into dev
This commit is contained in:
commit
b6b46c5563
|
@ -46,6 +46,10 @@ project("OPENFPGA" C CXX)
|
||||||
option(ENABLE_VPR_GRAPHICS "Enables VPR graphics" ON)
|
option(ENABLE_VPR_GRAPHICS "Enables VPR graphics" ON)
|
||||||
option(ENABLE_VPR_GRAPHICS "Enables build with librtlnumber" OFF)
|
option(ENABLE_VPR_GRAPHICS "Enables build with librtlnumber" OFF)
|
||||||
|
|
||||||
|
#Allow the user to decide weather to compile the graphics library
|
||||||
|
set(VPR_USE_EZGL "auto" CACHE STRING "Specify whether vpr uses the graphics library")
|
||||||
|
set_property(CACHE VPR_USE_EZGL PROPERTY STRINGS auto off on)
|
||||||
|
|
||||||
# Version number
|
# Version number
|
||||||
set(OPENFPGA_VERSION_MAJOR 1)
|
set(OPENFPGA_VERSION_MAJOR 1)
|
||||||
set(OPENFPGA_VERSION_MINOR 0)
|
set(OPENFPGA_VERSION_MINOR 0)
|
||||||
|
@ -154,6 +158,27 @@ message(STATUS "CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")
|
||||||
#
|
#
|
||||||
enable_testing()
|
enable_testing()
|
||||||
|
|
||||||
|
# set VPR_USE_EZGL in the root of VTR to decide whether to add
|
||||||
|
# subdirectory of graphics library, which prevents users
|
||||||
|
# without gtk/x11 libraries installed to build. VPR_USE_EZGL is
|
||||||
|
# being used in both the vpr CMakeLists and libs/EXTERNAL CMakeLists.
|
||||||
|
#
|
||||||
|
# check if GTK and X11 are installed and turn on/off graphics
|
||||||
|
if (VPR_USE_EZGL STREQUAL "auto")
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
pkg_check_modules(GTK3 QUIET gtk+-3.0)
|
||||||
|
pkg_check_modules(X11 QUIET x11)
|
||||||
|
|
||||||
|
if(GTK3_FOUND AND X11_FOUND)
|
||||||
|
set(VPR_USE_EZGL "on")
|
||||||
|
message(STATUS "VPR Graphics: Enabled")
|
||||||
|
else()
|
||||||
|
set(VPR_USE_EZGL "off")
|
||||||
|
message(STATUS "VPR Graphics: Disabled (required libraries missing, on debia/ubuntu try: sudo apt install libgtk-3 libx11-dev")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Sub-projects
|
# Sub-projects
|
||||||
#
|
#
|
||||||
|
|
|
@ -115,7 +115,7 @@ class Shell {
|
||||||
bool valid_command_class_id(const ShellCommandClassId& cmd_class_id) const;
|
bool valid_command_class_id(const ShellCommandClassId& cmd_class_id) const;
|
||||||
public: /* Public executors */
|
public: /* Public executors */
|
||||||
/* Start the interactive mode, where users will type-in command by command */
|
/* Start the interactive mode, where users will type-in command by command */
|
||||||
void run_interactive_mode(T& context);
|
void run_interactive_mode(T& context, const bool& quiet_mode = false);
|
||||||
/* Start the script mode, where users provide a file which includes all the commands to run */
|
/* Start the script mode, where users provide a file which includes all the commands to run */
|
||||||
void run_script_mode(const char* script_file_name, T& context);
|
void run_script_mode(const char* script_file_name, T& context);
|
||||||
/* Print all the commands by their classes. This is actually the help desk */
|
/* Print all the commands by their classes. This is actually the help desk */
|
||||||
|
|
|
@ -239,13 +239,15 @@ ShellCommandClassId Shell<T>::add_command_class(const char* name) {
|
||||||
* Public executors
|
* Public executors
|
||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
template <class T>
|
template <class T>
|
||||||
void Shell<T>::run_interactive_mode(T& context) {
|
void Shell<T>::run_interactive_mode(T& context, const bool& quiet_mode) {
|
||||||
VTR_LOG("Start interactive mode of %s...\n",
|
if (false == quiet_mode) {
|
||||||
name().c_str());
|
VTR_LOG("Start interactive mode of %s...\n",
|
||||||
|
name().c_str());
|
||||||
|
|
||||||
/* Print the title of the shell */
|
/* Print the title of the shell */
|
||||||
if (!title().empty()) {
|
if (!title().empty()) {
|
||||||
VTR_LOG("%s\n", title().c_str());
|
VTR_LOG("%s\n", title().c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for users input and execute the command */
|
/* Wait for users input and execute the command */
|
||||||
|
@ -306,6 +308,9 @@ void Shell<T>::run_script_mode(const char* script_file_name, T& context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fp.close();
|
fp.close();
|
||||||
|
|
||||||
|
/* Return to interactive mode, stay tuned */
|
||||||
|
run_interactive_mode(context, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@ -390,6 +395,10 @@ void Shell<T>::execute_command(const char* cmd_line,
|
||||||
free(argv[itok]);
|
free(argv[itok]);
|
||||||
}
|
}
|
||||||
free(argv);
|
free(argv);
|
||||||
|
|
||||||
|
/* Change the status of the command */
|
||||||
|
command_status_[cmd_id] = true;
|
||||||
|
|
||||||
/* Finish for macro command, return */
|
/* Finish for macro command, return */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "vpr_context.h"
|
#include "vpr_context.h"
|
||||||
#include "openfpga_arch.h"
|
#include "openfpga_arch.h"
|
||||||
|
#include "vpr_pb_type_annotation.h"
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* This file includes the declaration of the date structure
|
* This file includes the declaration of the date structure
|
||||||
|
@ -34,11 +35,15 @@
|
||||||
class OpenfpgaContext : public Context {
|
class OpenfpgaContext : public Context {
|
||||||
public: /* Public accessors */
|
public: /* Public accessors */
|
||||||
const openfpga::Arch& arch() const { return arch_; }
|
const openfpga::Arch& arch() const { return arch_; }
|
||||||
|
const openfpga::VprPbTypeAnnotation& vpr_pb_type_annotation() const { return vpr_pb_type_annotation_; }
|
||||||
public: /* Public mutators */
|
public: /* Public mutators */
|
||||||
openfpga::Arch& mutable_arch() { return arch_; }
|
openfpga::Arch& mutable_arch() { return arch_; }
|
||||||
|
openfpga::VprPbTypeAnnotation& mutable_vpr_pb_type_annotation() { return vpr_pb_type_annotation_; }
|
||||||
private: /* Internal data */
|
private: /* Internal data */
|
||||||
/* Data structure to store information from read_openfpga_arch library */
|
/* Data structure to store information from read_openfpga_arch library */
|
||||||
openfpga::Arch arch_;
|
openfpga::Arch arch_;
|
||||||
|
/* Annotation to pb_type of VPR */
|
||||||
|
openfpga::VprPbTypeAnnotation vpr_pb_type_annotation_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,342 @@
|
||||||
|
/********************************************************************
|
||||||
|
* This file includes functions to read an OpenFPGA architecture file
|
||||||
|
* which are built on the libarchopenfpga library
|
||||||
|
*******************************************************************/
|
||||||
|
/* Headers from vtrutil library */
|
||||||
|
#include "vtr_time.h"
|
||||||
|
#include "vtr_assert.h"
|
||||||
|
#include "vtr_log.h"
|
||||||
|
|
||||||
|
#include "vpr_pb_type_annotation.h"
|
||||||
|
#include "pb_type_utils.h"
|
||||||
|
#include "openfpga_link_arch.h"
|
||||||
|
|
||||||
|
/* Include global variables of VPR */
|
||||||
|
#include "globals.h"
|
||||||
|
|
||||||
|
/* begin namespace openfpga */
|
||||||
|
namespace openfpga {
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* This function will traverse pb_type graph from its top to find
|
||||||
|
* a pb_type with a given name as well as its hierarchy
|
||||||
|
*******************************************************************/
|
||||||
|
static
|
||||||
|
t_pb_type* try_find_pb_type_with_given_path(t_pb_type* top_pb_type,
|
||||||
|
const std::vector<std::string>& target_pb_type_names,
|
||||||
|
const std::vector<std::string>& target_pb_mode_names) {
|
||||||
|
/* Ensure that number of parent names and modes matches */
|
||||||
|
VTR_ASSERT_SAFE(target_pb_type_names.size() == target_pb_mode_names.size() + 1);
|
||||||
|
|
||||||
|
t_pb_type* cur_pb_type = top_pb_type;
|
||||||
|
|
||||||
|
/* If the top pb_type is what we want, we can return here */
|
||||||
|
if (1 == target_pb_type_names.size()) {
|
||||||
|
if (target_pb_type_names[0] == std::string(top_pb_type->name)) {
|
||||||
|
return top_pb_type;
|
||||||
|
}
|
||||||
|
/* Not match, return null pointer */
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We start from the first element of the parent names and parent modes.
|
||||||
|
* If the pb_type does not match in name, we fail
|
||||||
|
* If we cannot find a mode match the name, we fail
|
||||||
|
*/
|
||||||
|
for (size_t i = 0; i < target_pb_type_names.size() - 1; ++i) {
|
||||||
|
/* If this level does not match, search fail */
|
||||||
|
if (target_pb_type_names[i] != std::string(cur_pb_type->name)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
/* Find if the mode matches */
|
||||||
|
t_mode* cur_mode = find_pb_type_mode(cur_pb_type, target_pb_mode_names[i].c_str());
|
||||||
|
if (nullptr == cur_mode) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
/* Go to the next level of pb_type */
|
||||||
|
cur_pb_type = find_mode_child_pb_type(cur_mode, target_pb_type_names[i + 1].c_str());
|
||||||
|
if (nullptr == cur_pb_type) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
/* If this is already the last pb_type in the list, this is what we want */
|
||||||
|
if (i == target_pb_type_names.size() - 1) {
|
||||||
|
return cur_pb_type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reach here, it means we find nothing */
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* This function will identify the physical pb_type for each multi-mode
|
||||||
|
* pb_type in VPR pb_type graph by following the explicit definition
|
||||||
|
* in OpenFPGA architecture XML
|
||||||
|
*******************************************************************/
|
||||||
|
static
|
||||||
|
void build_vpr_physical_pb_mode_explicit_annotation(const DeviceContext& vpr_device_ctx,
|
||||||
|
const Arch& openfpga_arch,
|
||||||
|
VprPbTypeAnnotation& vpr_pb_type_annotation) {
|
||||||
|
/* Walk through the pb_type annotation stored in the openfpga arch */
|
||||||
|
for (const PbTypeAnnotation& pb_type_annotation : openfpga_arch.pb_type_annotations) {
|
||||||
|
/* Since our target is to annotate the physical mode name,
|
||||||
|
* we can skip those has not physical mode defined
|
||||||
|
*/
|
||||||
|
if (true == pb_type_annotation.physical_mode_name().empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Identify if the pb_type is operating or physical,
|
||||||
|
* For operating pb_type, get the full name of operating pb_type
|
||||||
|
* For physical pb_type, get the full name of physical pb_type
|
||||||
|
*/
|
||||||
|
std::vector<std::string> target_pb_type_names;
|
||||||
|
std::vector<std::string> target_pb_mode_names;
|
||||||
|
|
||||||
|
if (true == pb_type_annotation.is_operating_pb_type()) {
|
||||||
|
target_pb_type_names = pb_type_annotation.operating_parent_pb_type_names();
|
||||||
|
target_pb_type_names.push_back(pb_type_annotation.operating_pb_type_name());
|
||||||
|
target_pb_mode_names = pb_type_annotation.operating_parent_mode_names();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (true == pb_type_annotation.is_physical_pb_type()) {
|
||||||
|
target_pb_type_names = pb_type_annotation.physical_parent_pb_type_names();
|
||||||
|
target_pb_type_names.push_back(pb_type_annotation.physical_pb_type_name());
|
||||||
|
target_pb_mode_names = pb_type_annotation.physical_parent_mode_names();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We must have at least one pb_type in the list */
|
||||||
|
VTR_ASSERT_SAFE(0 < target_pb_type_names.size());
|
||||||
|
|
||||||
|
/* Pb type information are located at the logic_block_types in the device context of VPR
|
||||||
|
* We iterate over the vectors and find the pb_type matches the parent_pb_type_name
|
||||||
|
*/
|
||||||
|
bool link_success = false;
|
||||||
|
|
||||||
|
for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) {
|
||||||
|
/* By pass nullptr for pb_type head */
|
||||||
|
if (nullptr == lb_type.pb_type) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Check the name of the top-level pb_type, if it does not match, we can bypass */
|
||||||
|
if (target_pb_type_names[0] != std::string(lb_type.pb_type->name)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Match the name in the top-level, we go further to search the pb_type in the graph */
|
||||||
|
t_pb_type* target_pb_type = try_find_pb_type_with_given_path(lb_type.pb_type, target_pb_type_names,
|
||||||
|
target_pb_mode_names);
|
||||||
|
if (nullptr == target_pb_type) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Found, we update the annotation by assigning the physical mode */
|
||||||
|
t_mode* physical_mode = find_pb_type_mode(target_pb_type, pb_type_annotation.physical_mode_name().c_str());
|
||||||
|
vpr_pb_type_annotation.add_pb_type_physical_mode(target_pb_type, physical_mode);
|
||||||
|
|
||||||
|
/* Give a message */
|
||||||
|
VTR_LOG("Annotate pb_type '%s' with physical mode '%s'\n",
|
||||||
|
target_pb_type->name, physical_mode->name);
|
||||||
|
|
||||||
|
link_success = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false == link_success) {
|
||||||
|
/* Not found, error out! */
|
||||||
|
VTR_LOG_ERROR("Unable to find the pb_type '%s' in VPR architecture definition!\n",
|
||||||
|
target_pb_type_names.back().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* This function will recursively visit all the pb_type from the top
|
||||||
|
* pb_type in the graph and
|
||||||
|
* infer the physical pb_type for each multi-mode
|
||||||
|
* pb_type in VPR pb_type graph without OpenFPGA architecture XML
|
||||||
|
*
|
||||||
|
* The following rule is applied:
|
||||||
|
* if there is only 1 mode under a pb_type, it will be the default
|
||||||
|
* physical mode for this pb_type
|
||||||
|
*******************************************************************/
|
||||||
|
static
|
||||||
|
void rec_infer_vpr_physical_pb_mode_annotation(t_pb_type* cur_pb_type,
|
||||||
|
VprPbTypeAnnotation& vpr_pb_type_annotation) {
|
||||||
|
/* We do not check any primitive pb_type */
|
||||||
|
if (true == is_primitive_pb_type(cur_pb_type)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For non-primitive pb_type:
|
||||||
|
* - if there is only one mode, it will be the physical mode
|
||||||
|
* we just need to make sure that we do not repeatedly annotate this
|
||||||
|
* - if there are multiple modes, we should be able to find a physical mode
|
||||||
|
* and then go recursively
|
||||||
|
*/
|
||||||
|
t_mode* physical_mode = nullptr;
|
||||||
|
|
||||||
|
if (1 == cur_pb_type->num_modes) {
|
||||||
|
if (nullptr == vpr_pb_type_annotation.physical_mode(cur_pb_type)) {
|
||||||
|
/* Not assigned by explicit annotation, we should infer here */
|
||||||
|
vpr_pb_type_annotation.add_pb_type_physical_mode(cur_pb_type, &(cur_pb_type->modes[0]));
|
||||||
|
VTR_LOG("Implicitly infer physical mode '%s' for pb_type '%s'\n",
|
||||||
|
cur_pb_type->modes[0].name, cur_pb_type->name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
VTR_ASSERT(1 < cur_pb_type->num_modes);
|
||||||
|
if (nullptr == vpr_pb_type_annotation.physical_mode(cur_pb_type)) {
|
||||||
|
/* Not assigned by explicit annotation, we should infer here */
|
||||||
|
vpr_pb_type_annotation.add_pb_type_physical_mode(cur_pb_type, &(cur_pb_type->modes[0]));
|
||||||
|
VTR_LOG_ERROR("Unable to find a physical mode for a multi-mode pb_type '%s'!\n",
|
||||||
|
cur_pb_type->name);
|
||||||
|
VTR_LOG_ERROR("Please specify in the OpenFPGA architecture\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the physical mode from annotation */
|
||||||
|
physical_mode = vpr_pb_type_annotation.physical_mode(cur_pb_type);
|
||||||
|
|
||||||
|
VTR_ASSERT(nullptr != physical_mode);
|
||||||
|
|
||||||
|
/* Traverse the pb_type children under the physical mode */
|
||||||
|
for (int ichild = 0; ichild < physical_mode->num_pb_type_children; ++ichild) {
|
||||||
|
rec_infer_vpr_physical_pb_mode_annotation(&(physical_mode->pb_type_children[ichild]),
|
||||||
|
vpr_pb_type_annotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* This function will infer the physical pb_type for each multi-mode
|
||||||
|
* pb_type in VPR pb_type graph without OpenFPGA architecture XML
|
||||||
|
*
|
||||||
|
* The following rule is applied:
|
||||||
|
* if there is only 1 mode under a pb_type, it will be the default
|
||||||
|
* physical mode for this pb_type
|
||||||
|
*
|
||||||
|
* Note:
|
||||||
|
* This function must be executed AFTER the function
|
||||||
|
* build_vpr_physical_pb_mode_explicit_annotation()
|
||||||
|
*******************************************************************/
|
||||||
|
static
|
||||||
|
void build_vpr_physical_pb_mode_implicit_annotation(const DeviceContext& vpr_device_ctx,
|
||||||
|
VprPbTypeAnnotation& vpr_pb_type_annotation) {
|
||||||
|
for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) {
|
||||||
|
/* By pass nullptr for pb_type head */
|
||||||
|
if (nullptr == lb_type.pb_type) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
rec_infer_vpr_physical_pb_mode_annotation(lb_type.pb_type, vpr_pb_type_annotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* This function will recursively traverse pb_type graph to ensure
|
||||||
|
* 1. there is only a physical mode under each pb_type
|
||||||
|
* 2. physical mode appears only when its parent is a physical mode.
|
||||||
|
*******************************************************************/
|
||||||
|
static
|
||||||
|
void rec_check_vpr_physical_pb_mode_annotation(t_pb_type* cur_pb_type,
|
||||||
|
const bool& expect_physical_mode,
|
||||||
|
const VprPbTypeAnnotation& vpr_pb_type_annotation,
|
||||||
|
size_t& num_err) {
|
||||||
|
/* We do not check any primitive pb_type */
|
||||||
|
if (true == is_primitive_pb_type(cur_pb_type)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For non-primitive pb_type:
|
||||||
|
* - If we expect a physical mode to exist under this pb_type
|
||||||
|
* we should be able to find one in the annoation
|
||||||
|
* - If we do NOT expect a physical mode, make sure we find
|
||||||
|
* nothing in the annotation
|
||||||
|
*/
|
||||||
|
if (true == expect_physical_mode) {
|
||||||
|
if (nullptr == vpr_pb_type_annotation.physical_mode(cur_pb_type)) {
|
||||||
|
VTR_LOG_ERROR("Unable to find a physical mode for a multi-mode pb_type '%s'!\n",
|
||||||
|
cur_pb_type->name);
|
||||||
|
VTR_LOG_ERROR("Please specify in the OpenFPGA architecture\n");
|
||||||
|
num_err++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
VTR_ASSERT_SAFE(false == expect_physical_mode);
|
||||||
|
if (nullptr != vpr_pb_type_annotation.physical_mode(cur_pb_type)) {
|
||||||
|
VTR_LOG_ERROR("Find a physical mode '%s' for pb_type '%s' which is not under any physical mode!\n",
|
||||||
|
vpr_pb_type_annotation.physical_mode(cur_pb_type)->name,
|
||||||
|
cur_pb_type->name);
|
||||||
|
num_err++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Traverse all the modes
|
||||||
|
* - for pb_type children under a physical mode, we expect an physical mode
|
||||||
|
* - for pb_type children under non-physical mode, we expect no physical mode
|
||||||
|
*/
|
||||||
|
for (int imode = 0; imode < cur_pb_type->num_modes; ++imode) {
|
||||||
|
bool expect_child_physical_mode = false;
|
||||||
|
if (&(cur_pb_type->modes[imode]) == vpr_pb_type_annotation.physical_mode(cur_pb_type)) {
|
||||||
|
expect_child_physical_mode = true && expect_physical_mode;
|
||||||
|
}
|
||||||
|
for (int ichild = 0; ichild < cur_pb_type->modes[imode].num_pb_type_children; ++ichild) {
|
||||||
|
rec_check_vpr_physical_pb_mode_annotation(&(cur_pb_type->modes[imode].pb_type_children[ichild]),
|
||||||
|
expect_child_physical_mode, vpr_pb_type_annotation,
|
||||||
|
num_err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* This function will check the physical mode annotation for
|
||||||
|
* each pb_type in the device
|
||||||
|
*******************************************************************/
|
||||||
|
static
|
||||||
|
void check_vpr_physical_pb_mode_annotation(const DeviceContext& vpr_device_ctx,
|
||||||
|
const VprPbTypeAnnotation& vpr_pb_type_annotation) {
|
||||||
|
size_t num_err = 0;
|
||||||
|
|
||||||
|
for (const t_logical_block_type& lb_type : vpr_device_ctx.logical_block_types) {
|
||||||
|
/* By pass nullptr for pb_type head */
|
||||||
|
if (nullptr == lb_type.pb_type) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Top pb_type should always has a physical mode! */
|
||||||
|
rec_check_vpr_physical_pb_mode_annotation(lb_type.pb_type, true, vpr_pb_type_annotation, num_err);
|
||||||
|
}
|
||||||
|
if (0 == num_err) {
|
||||||
|
VTR_LOG("Check physical mode annotation for pb_types passed.\n");
|
||||||
|
} else {
|
||||||
|
VTR_LOG("Check physical mode annotation for pb_types failed with %ld errors!\n",
|
||||||
|
num_err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Top-level function to link openfpga architecture to VPR, including:
|
||||||
|
* - physical pb_type
|
||||||
|
* - idle pb_type
|
||||||
|
* - circuit models for pb_type, pb interconnect and routing architecture
|
||||||
|
*******************************************************************/
|
||||||
|
void link_arch(OpenfpgaContext& openfpga_context) {
|
||||||
|
|
||||||
|
vtr::ScopedStartFinishTimer timer("Link OpenFPGA architecture to VPR architecture");
|
||||||
|
|
||||||
|
/* Annotate physical pb_type in the VPR pb_type graph */
|
||||||
|
build_vpr_physical_pb_mode_explicit_annotation(g_vpr_ctx.device(), openfpga_context.arch(),
|
||||||
|
openfpga_context.mutable_vpr_pb_type_annotation());
|
||||||
|
build_vpr_physical_pb_mode_implicit_annotation(g_vpr_ctx.device(),
|
||||||
|
openfpga_context.mutable_vpr_pb_type_annotation());
|
||||||
|
|
||||||
|
check_vpr_physical_pb_mode_annotation(g_vpr_ctx.device(),
|
||||||
|
openfpga_context.vpr_pb_type_annotation());
|
||||||
|
|
||||||
|
/* Annotate idle pb_type in the VPR pb_type graph */
|
||||||
|
|
||||||
|
/* Link physical pb_type to circuit model */
|
||||||
|
|
||||||
|
/* Link routing architecture to circuit model */
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* end namespace openfpga */
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef OPENFPGA_LINK_ARCH_COMMAND_H
|
||||||
|
#define OPENFPGA_LINK_ARCH_COMMAND_H
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Include header files that are required by function declaration
|
||||||
|
*******************************************************************/
|
||||||
|
#include "openfpga_context.h"
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Function declaration
|
||||||
|
*******************************************************************/
|
||||||
|
|
||||||
|
/* begin namespace openfpga */
|
||||||
|
namespace openfpga {
|
||||||
|
|
||||||
|
void link_arch(OpenfpgaContext& openfpga_context);
|
||||||
|
|
||||||
|
} /* end namespace openfpga */
|
||||||
|
|
||||||
|
#endif
|
|
@ -4,6 +4,7 @@
|
||||||
* - read_openfpga_arch : read OpenFPGA architecture file
|
* - read_openfpga_arch : read OpenFPGA architecture file
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
#include "openfpga_read_arch.h"
|
#include "openfpga_read_arch.h"
|
||||||
|
#include "openfpga_link_arch.h"
|
||||||
#include "openfpga_setup_command.h"
|
#include "openfpga_setup_command.h"
|
||||||
|
|
||||||
/* begin namespace openfpga */
|
/* begin namespace openfpga */
|
||||||
|
@ -36,8 +37,23 @@ void add_openfpga_setup_commands(openfpga::Shell<OpenfpgaContext>& shell) {
|
||||||
ShellCommandId shell_cmd_write_arch_id = shell.add_command(shell_cmd_write_arch, "write OpenFPGA architecture file");
|
ShellCommandId shell_cmd_write_arch_id = shell.add_command(shell_cmd_write_arch, "write OpenFPGA architecture file");
|
||||||
shell.set_command_class(shell_cmd_write_arch_id, openfpga_setup_cmd_class);
|
shell.set_command_class(shell_cmd_write_arch_id, openfpga_setup_cmd_class);
|
||||||
shell.set_command_const_execute_function(shell_cmd_write_arch_id, write_arch);
|
shell.set_command_const_execute_function(shell_cmd_write_arch_id, write_arch);
|
||||||
/* The 'write_openfpga_arch' command should be executed before 'read_openfpga_arch' */
|
/* The 'write_openfpga_arch' command should NOT be executed before 'read_openfpga_arch' */
|
||||||
shell.set_command_dependency(shell_cmd_write_arch_id, std::vector<ShellCommandId>(1, shell_cmd_read_arch_id));
|
shell.set_command_dependency(shell_cmd_write_arch_id, std::vector<ShellCommandId>(1, shell_cmd_read_arch_id));
|
||||||
|
|
||||||
|
/* Command 'link_openfpga_arch' */
|
||||||
|
Command shell_cmd_link_openfpga_arch("link_openfpga_arch");
|
||||||
|
|
||||||
|
/* Add command 'link_openfpga_arch' to the Shell */
|
||||||
|
ShellCommandId shell_cmd_link_openfpga_arch_id = shell.add_command(shell_cmd_link_openfpga_arch, "Bind OpenFPGA architecture to VPR");
|
||||||
|
shell.set_command_class(shell_cmd_link_openfpga_arch_id, openfpga_setup_cmd_class);
|
||||||
|
shell.set_command_execute_function(shell_cmd_link_openfpga_arch_id, link_arch);
|
||||||
|
/* The 'link_openfpga_arch' command should NOT be executed before 'read_openfpga_arch' and 'vpr' */
|
||||||
|
const ShellCommandId& shell_cmd_vpr_id = shell.command(std::string("vpr"));
|
||||||
|
std::vector<ShellCommandId> cmd_dependency_link_openfpga_arch;
|
||||||
|
cmd_dependency_link_openfpga_arch.push_back(shell_cmd_read_arch_id);
|
||||||
|
cmd_dependency_link_openfpga_arch.push_back(shell_cmd_vpr_id);
|
||||||
|
shell.set_command_dependency(shell_cmd_link_openfpga_arch_id, cmd_dependency_link_openfpga_arch);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* end namespace openfpga */
|
} /* end namespace openfpga */
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
/********************************************************************
|
||||||
|
* This file includes most utilized functions for the pb_type
|
||||||
|
* and pb_graph_node data structure in the OpenFPGA context
|
||||||
|
*******************************************************************/
|
||||||
|
/* Headers from vtrutil library */
|
||||||
|
#include "vtr_assert.h"
|
||||||
|
#include "vtr_log.h"
|
||||||
|
|
||||||
|
#include "pb_type_utils.h"
|
||||||
|
|
||||||
|
/* begin namespace openfpga */
|
||||||
|
namespace openfpga {
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* A pb_type is considered to be primitive when it has zero modes
|
||||||
|
* However, this not always true. An exception is the LUT_CLASS
|
||||||
|
* VPR added two modes by default to a LUT pb_type. Therefore,
|
||||||
|
* for LUT_CLASS, it is a primitive when it is binded to a blif model
|
||||||
|
*
|
||||||
|
* Note:
|
||||||
|
* - if VPR changes its mode organization for LUT pb_type
|
||||||
|
* this code should be adapted as well!
|
||||||
|
************************************************************************/
|
||||||
|
bool is_primitive_pb_type(t_pb_type* pb_type) {
|
||||||
|
if (LUT_CLASS == pb_type->class_type) {
|
||||||
|
/* The first mode of LUT is wire, the second is the regular LUT */
|
||||||
|
VTR_ASSERT(std::string("wire") == std::string(pb_type->modes[0].name));
|
||||||
|
VTR_ASSERT(std::string(pb_type->name) == std::string(pb_type->modes[1].name));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return 0 == pb_type->num_modes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* A pb_type is the root pb_type when it has no parent mode
|
||||||
|
************************************************************************/
|
||||||
|
bool is_root_pb_type(t_pb_type* pb_type) {
|
||||||
|
return pb_type->parent_mode == nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* With a given mode name, find the mode pointer
|
||||||
|
************************************************************************/
|
||||||
|
t_mode* find_pb_type_mode(t_pb_type* pb_type, const char* mode_name) {
|
||||||
|
for (int i = 0; i < pb_type->num_modes; ++i) {
|
||||||
|
if (std::string(mode_name) == std::string(pb_type->modes[i].name)) {
|
||||||
|
return &(pb_type->modes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Note found, return a nullptr */
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* With a given pb_type name, find the pb_type pointer
|
||||||
|
************************************************************************/
|
||||||
|
t_pb_type* find_mode_child_pb_type(t_mode* mode, const char* child_name) {
|
||||||
|
for (int i = 0; i < mode->num_pb_type_children; ++i) {
|
||||||
|
if (std::string(child_name) == std::string(mode->pb_type_children[i].name)) {
|
||||||
|
return &(mode->pb_type_children[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Note found, return a nullptr */
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* end namespace openfpga */
|
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef PB_TYPE_UTILS_H
|
||||||
|
#define PB_TYPE_UTILS_H
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Include header files that are required by function declaration
|
||||||
|
*******************************************************************/
|
||||||
|
#include "physical_types.h"
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Function declaration
|
||||||
|
*******************************************************************/
|
||||||
|
|
||||||
|
/* begin namespace openfpga */
|
||||||
|
namespace openfpga {
|
||||||
|
|
||||||
|
bool is_primitive_pb_type(t_pb_type* pb_type);
|
||||||
|
|
||||||
|
bool is_root_pb_type(t_pb_type* pb_type);
|
||||||
|
|
||||||
|
t_mode* find_pb_type_mode(t_pb_type* pb_type, const char* mode_name);
|
||||||
|
|
||||||
|
t_pb_type* find_mode_child_pb_type(t_mode* mode, const char* child_name);
|
||||||
|
|
||||||
|
} /* end namespace openfpga */
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,44 @@
|
||||||
|
/************************************************************************
|
||||||
|
* Member functions for class VprPbTypeAnnotation
|
||||||
|
***********************************************************************/
|
||||||
|
#include "vtr_log.h"
|
||||||
|
#include "vtr_assert.h"
|
||||||
|
#include "vpr_pb_type_annotation.h"
|
||||||
|
|
||||||
|
/* namespace openfpga begins */
|
||||||
|
namespace openfpga {
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* Constructors
|
||||||
|
***********************************************************************/
|
||||||
|
VprPbTypeAnnotation::VprPbTypeAnnotation() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* Public mutators
|
||||||
|
***********************************************************************/
|
||||||
|
t_mode* VprPbTypeAnnotation::physical_mode(t_pb_type* pb_type) const {
|
||||||
|
/* Ensure that the pb_type is in the list */
|
||||||
|
std::map<t_pb_type*, t_mode*>::const_iterator it = physical_pb_modes_.find(pb_type);
|
||||||
|
if (it == physical_pb_modes_.end()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return physical_pb_modes_.at(pb_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* Public mutators
|
||||||
|
***********************************************************************/
|
||||||
|
void VprPbTypeAnnotation::add_pb_type_physical_mode(t_pb_type* pb_type, t_mode* physical_mode) {
|
||||||
|
/* Warn any override attempt */
|
||||||
|
std::map<t_pb_type*, t_mode*>::const_iterator it = physical_pb_modes_.find(pb_type);
|
||||||
|
if (it != physical_pb_modes_.end()) {
|
||||||
|
VTR_LOG_WARN("Override the annotation between pb_type '%s' and it physical mode '%s'!\n",
|
||||||
|
pb_type->name, physical_mode->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
physical_pb_modes_[pb_type] = physical_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* End namespace openfpga*/
|
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef VPR_PB_TYPE_ANNOTATION_H
|
||||||
|
#define VPR_PB_TYPE_ANNOTATION_H
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Include header files required by the data structure definition
|
||||||
|
*******************************************************************/
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
/* Header from archfpga library */
|
||||||
|
#include "physical_types.h"
|
||||||
|
|
||||||
|
/* Header from openfpgautil library */
|
||||||
|
#include "circuit_library.h"
|
||||||
|
|
||||||
|
/* Begin namespace openfpga */
|
||||||
|
namespace openfpga {
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* This is the critical data structure to link the pb_type in VPR
|
||||||
|
* to openfpga annotations
|
||||||
|
* With a given pb_type pointer, it aims to identify:
|
||||||
|
* 1. if the pb_type is a physical pb_type or a operating pb_type
|
||||||
|
* 2. what is the circuit model id linked to a physical pb_type
|
||||||
|
* 3. what is the physical pb_type for an operating pb_type
|
||||||
|
* 4. what is the mode pointer that represents the physical mode for a pb_type
|
||||||
|
*******************************************************************/
|
||||||
|
class VprPbTypeAnnotation {
|
||||||
|
public: /* Constructor */
|
||||||
|
VprPbTypeAnnotation();
|
||||||
|
public: /* Public accessors */
|
||||||
|
t_mode* physical_mode(t_pb_type* pb_type) const;
|
||||||
|
public: /* Public mutators */
|
||||||
|
void add_pb_type_physical_mode(t_pb_type* pb_type, t_mode* physical_mode);
|
||||||
|
private: /* Internal data */
|
||||||
|
std::map<t_pb_type*, bool> is_physical_pb_types_;
|
||||||
|
std::map<t_pb_type*, t_pb_type*> physical_pb_types_;
|
||||||
|
std::map<t_pb_type*, t_mode*> physical_pb_modes_;
|
||||||
|
std::map<t_pb_type*, CircuitModelId> pb_type_circuit_models_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* End namespace openfpga*/
|
||||||
|
|
||||||
|
#endif
|
|
@ -10,13 +10,13 @@ namespace openfpga {
|
||||||
|
|
||||||
void add_vpr_commands(openfpga::Shell<OpenfpgaContext>& shell) {
|
void add_vpr_commands(openfpga::Shell<OpenfpgaContext>& shell) {
|
||||||
/* Add a new class of commands */
|
/* Add a new class of commands */
|
||||||
ShellCommandClassId arith_cmd_class = shell.add_command_class("VPR");
|
ShellCommandClassId vpr_cmd_class = shell.add_command_class("VPR");
|
||||||
|
|
||||||
/* Create a macro command of 'vpr' which will call the main engine of vpr
|
/* Create a macro command of 'vpr' which will call the main engine of vpr
|
||||||
*/
|
*/
|
||||||
Command shell_cmd_vpr("vpr");
|
Command shell_cmd_vpr("vpr");
|
||||||
ShellCommandId shell_cmd_vpr_id = shell.add_command(shell_cmd_vpr, "Start VPR core engine to pack, place and route a BLIF design on a FPGA architecture");
|
ShellCommandId shell_cmd_vpr_id = shell.add_command(shell_cmd_vpr, "Start VPR core engine to pack, place and route a BLIF design on a FPGA architecture");
|
||||||
shell.set_command_class(shell_cmd_vpr_id, arith_cmd_class);
|
shell.set_command_class(shell_cmd_vpr_id, vpr_cmd_class);
|
||||||
shell.set_command_execute_function(shell_cmd_vpr_id, vpr::vpr);
|
shell.set_command_execute_function(shell_cmd_vpr_id, vpr::vpr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ int vpr(int argc, char** argv) {
|
||||||
vpr_install_signal_handler();
|
vpr_install_signal_handler();
|
||||||
|
|
||||||
/* Read options, architecture, and circuit netlist */
|
/* Read options, architecture, and circuit netlist */
|
||||||
vpr_init(argc, (const char**)argv, &Options, &vpr_setup, &Arch);
|
vpr_init(argc, const_cast<const char**>(argv), &Options, &vpr_setup, &Arch);
|
||||||
|
|
||||||
if (Options.show_version) {
|
if (Options.show_version) {
|
||||||
return SUCCESS_EXIT_CODE;
|
return SUCCESS_EXIT_CODE;
|
||||||
|
@ -70,8 +70,10 @@ int vpr(int argc, char** argv) {
|
||||||
timing_ctx.stats.num_full_hold_updates,
|
timing_ctx.stats.num_full_hold_updates,
|
||||||
timing_ctx.stats.num_full_setup_hold_updates);
|
timing_ctx.stats.num_full_setup_hold_updates);
|
||||||
|
|
||||||
/* free data structures */
|
/* TODO: move this to the end of flow
|
||||||
vpr_free_all(Arch, vpr_setup);
|
* free data structures
|
||||||
|
*/
|
||||||
|
/* vpr_free_all(Arch, vpr_setup); */
|
||||||
|
|
||||||
VTR_LOG("VPR suceeded\n");
|
VTR_LOG("VPR suceeded\n");
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
# Benchmark "s298" written by ABC on Tue Mar 12 09:40:31 2019
|
||||||
|
.model s298
|
||||||
|
.inputs clock G0 G1 G2
|
||||||
|
.outputs G117 G132 G66 G118 G133 G67
|
||||||
|
|
||||||
|
.latch n21 G10 re clock 0
|
||||||
|
.latch n26 G11 re clock 0
|
||||||
|
.latch n31 G12 re clock 0
|
||||||
|
.latch n36 G13 re clock 0
|
||||||
|
.latch n41 G14 re clock 0
|
||||||
|
.latch n46 G15 re clock 0
|
||||||
|
.latch n51 G66 re clock 0
|
||||||
|
.latch n55 G67 re clock 0
|
||||||
|
.latch n59 G117 re clock 0
|
||||||
|
.latch n63 G118 re clock 0
|
||||||
|
.latch n67 G132 re clock 0
|
||||||
|
.latch n71 G133 re clock 0
|
||||||
|
.latch n75 G22 re clock 0
|
||||||
|
.latch n80 G23 re clock 0
|
||||||
|
|
||||||
|
.names n56 n57 G10 n63
|
||||||
|
0-0 1
|
||||||
|
11- 1
|
||||||
|
.names G15 G11 G13 G22 G14 G12 n56
|
||||||
|
01---- 1
|
||||||
|
0-0--- 1
|
||||||
|
0--0-- 1
|
||||||
|
0---1- 1
|
||||||
|
0----1 1
|
||||||
|
-11000 1
|
||||||
|
.names G14 G13 G12 G118 G11 n57
|
||||||
|
01--- 1
|
||||||
|
100-0 1
|
||||||
|
1-11- 1
|
||||||
|
-1-1- 1
|
||||||
|
.names n56 n59_1 G10 n67
|
||||||
|
0-0 1
|
||||||
|
11- 1
|
||||||
|
.names G14 G13 G12 G132 G11 n59_1
|
||||||
|
100-0 1
|
||||||
|
11-1- 1
|
||||||
|
1-11- 1
|
||||||
|
.names G0 G10 n21
|
||||||
|
00 1
|
||||||
|
.names G10 G11 G0 G12 G13 n26
|
||||||
|
010-- 1
|
||||||
|
1001- 1
|
||||||
|
100-0 1
|
||||||
|
.names G12 G0 G11 G10 n31
|
||||||
|
0011 1
|
||||||
|
100- 1
|
||||||
|
10-0 1
|
||||||
|
.names G13 G0 G11 G12 G10 n36
|
||||||
|
00111 1
|
||||||
|
1001- 1
|
||||||
|
1010- 1
|
||||||
|
10--0 1
|
||||||
|
.names n65 G14 G0 n41
|
||||||
|
000 1
|
||||||
|
110 1
|
||||||
|
.names G23 G10 G13 G11 G12 n65
|
||||||
|
1---- 0
|
||||||
|
-1100 0
|
||||||
|
.names G0 n56 n46
|
||||||
|
00 1
|
||||||
|
.names n56 G66 G14 G13 G12 n51
|
||||||
|
111-1 1
|
||||||
|
11-1- 1
|
||||||
|
1-01- 1
|
||||||
|
.names n56 G13 G14 G11 G67 G12 n55
|
||||||
|
1000-- 1
|
||||||
|
10-1-0 1
|
||||||
|
111-1- 1
|
||||||
|
1-1-11 1
|
||||||
|
.names n56 G13 G117 G14 G12 G11 n59
|
||||||
|
10-0-- 1
|
||||||
|
10--01 1
|
||||||
|
1111-- 1
|
||||||
|
1-111- 1
|
||||||
|
.names n56 G14 G12 G13 G133 G11 n71
|
||||||
|
1010-1 1
|
||||||
|
111-1- 1
|
||||||
|
11-11- 1
|
||||||
|
.names G2 G22 G0 n75
|
||||||
|
010 1
|
||||||
|
100 1
|
||||||
|
.names G1 G23 G0 n80
|
||||||
|
010 1
|
||||||
|
100 1
|
||||||
|
.end
|
|
@ -0,0 +1,234 @@
|
||||||
|
<!-- Architecture annotation for OpenFPGA framework
|
||||||
|
This annotation supports the k6_N10_40nm.xml
|
||||||
|
- General purpose logic block
|
||||||
|
- K = 6, N = 10, I = 40
|
||||||
|
- Single mode
|
||||||
|
- Routing architecture
|
||||||
|
- L = 4, fc_in = 0.15, fc_out = 0.1
|
||||||
|
-->
|
||||||
|
<openfpga_architecture>
|
||||||
|
<technology_library>
|
||||||
|
<device_library>
|
||||||
|
<device_model name="logic" type="transistor">
|
||||||
|
<lib type="industry" corner="TOP_TT" ref="M" path="${OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.pm"/>
|
||||||
|
<design vdd="0.9" pn_ratio="2"/>
|
||||||
|
<pmos name="pch" chan_length="40e-9" min_width="140e-9" variation="logic_transistor_var"/>
|
||||||
|
<nmos name="nch" chan_length="40e-9" min_width="140e-9" variation="logic_transistor_var"/>
|
||||||
|
</device_model>
|
||||||
|
<device_model name="io" type="transistor">
|
||||||
|
<lib type="academia" ref="M" path="${OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.pm"/>
|
||||||
|
<design vdd="2.5" pn_ratio="3"/>
|
||||||
|
<pmos name="pch_25" chan_length="270e-9" min_width="320e-9" variation="io_transistor_var"/>
|
||||||
|
<nmos name="nch_25" chan_length="270e-9" min_width="320e-9" variation="io_transistor_var"/>
|
||||||
|
</device_model>
|
||||||
|
</device_library>
|
||||||
|
<variation_library>
|
||||||
|
<variation name="logic_transistor_var" abs_deviation="0.1" num_sigma="3"/>
|
||||||
|
<variation name="io_transistor_var" abs_deviation="0.1" num_sigma="3"/>
|
||||||
|
</variation_library>
|
||||||
|
</technology_library>
|
||||||
|
<circuit_library>
|
||||||
|
<circuit_model type="inv_buf" name="INVTX1" prefix="INVTX1" is_default="true">
|
||||||
|
<design_technology type="cmos" topology="inverter" size="1"/>
|
||||||
|
<port type="input" prefix="in" size="1"/>
|
||||||
|
<port type="output" prefix="out" size="1"/>
|
||||||
|
<delay_matrix type="rise" in_port="in" out_port="out">
|
||||||
|
10e-12
|
||||||
|
</delay_matrix>
|
||||||
|
<delay_matrix type="fall" in_port="in" out_port="out">
|
||||||
|
10e-12
|
||||||
|
</delay_matrix>
|
||||||
|
</circuit_model>
|
||||||
|
<circuit_model type="inv_buf" name="buf4" prefix="buf4" is_default="false">
|
||||||
|
<design_technology type="cmos" topology="buffer" size="1" num_level="2" f_per_stage="4"/>
|
||||||
|
<port type="input" prefix="in" size="1"/>
|
||||||
|
<port type="output" prefix="out" size="1"/>
|
||||||
|
<delay_matrix type="rise" in_port="in" out_port="out">
|
||||||
|
10e-12
|
||||||
|
</delay_matrix>
|
||||||
|
<delay_matrix type="fall" in_port="in" out_port="out">
|
||||||
|
10e-12
|
||||||
|
</delay_matrix>
|
||||||
|
</circuit_model>
|
||||||
|
<circuit_model type="inv_buf" name="tap_buf4" prefix="tap_buf4" is_default="false">
|
||||||
|
<design_technology type="cmos" topology="buffer" size="1" num_level="3" f_per_stage="4"/>
|
||||||
|
<port type="input" prefix="in" size="1"/>
|
||||||
|
<port type="output" prefix="out" size="1"/>
|
||||||
|
<delay_matrix type="rise" in_port="in" out_port="out">
|
||||||
|
10e-12
|
||||||
|
</delay_matrix>
|
||||||
|
<delay_matrix type="fall" in_port="in" out_port="out">
|
||||||
|
10e-12
|
||||||
|
</delay_matrix>
|
||||||
|
</circuit_model>
|
||||||
|
<circuit_model type="pass_gate" name="TGATE" prefix="TGATE" is_default="true">
|
||||||
|
<design_technology type="cmos" topology="transmission_gate" nmos_size="1" pmos_size="2"/>
|
||||||
|
<input_buffer exist="false"/>
|
||||||
|
<output_buffer exist="false"/>
|
||||||
|
<port type="input" prefix="in" size="1"/>
|
||||||
|
<port type="input" prefix="sel" size="1"/>
|
||||||
|
<port type="input" prefix="selb" size="1"/>
|
||||||
|
<port type="output" prefix="out" size="1"/>
|
||||||
|
<delay_matrix type="rise" in_port="in sel selb" out_port="out">
|
||||||
|
10e-12 5e-12 5e-12
|
||||||
|
</delay_matrix>
|
||||||
|
<delay_matrix type="fall" in_port="in sel selb" out_port="out">
|
||||||
|
10e-12 5e-12 5e-12
|
||||||
|
</delay_matrix>
|
||||||
|
</circuit_model>
|
||||||
|
<circuit_model type="chan_wire" name="chan_segment" prefix="track_seg" is_default="true">
|
||||||
|
<design_technology type="cmos"/>
|
||||||
|
<input_buffer exist="false"/>
|
||||||
|
<output_buffer exist="false"/>
|
||||||
|
<port type="input" prefix="in" size="1"/>
|
||||||
|
<port type="output" prefix="out" size="1"/>
|
||||||
|
<wire_param model_type="pi" R="101" C="22.5e-15" num_level="1"/> <!-- model_type could be T, res_val and cap_val DON'T CARE -->
|
||||||
|
</circuit_model>
|
||||||
|
<circuit_model type="wire" name="direct_interc" prefix="direct_interc" is_default="true">
|
||||||
|
<design_technology type="cmos"/>
|
||||||
|
<input_buffer exist="false"/>
|
||||||
|
<output_buffer exist="false"/>
|
||||||
|
<port type="input" prefix="in" size="1"/>
|
||||||
|
<port type="output" prefix="out" size="1"/>
|
||||||
|
<wire_param model_type="pi" R="0" C="0" num_level="1"/> <!-- model_type could be T, res_val cap_val should be defined -->
|
||||||
|
</circuit_model>
|
||||||
|
<circuit_model type="mux" name="mux_2level" prefix="mux_2level" dump_structural_verilog="true">
|
||||||
|
<design_technology type="cmos" structure="multi_level" num_level="2" add_const_input="true" const_input_val="1"/>
|
||||||
|
<input_buffer exist="true" circuit_model_name="INVTX1"/>
|
||||||
|
<output_buffer exist="true" circuit_model_name="INVTX1"/>
|
||||||
|
<!--mux2to1 subckt_name="mux2to1"/-->
|
||||||
|
<pass_gate_logic circuit_model_name="TGATE"/>
|
||||||
|
<port type="input" prefix="in" size="1"/>
|
||||||
|
<port type="output" prefix="out" size="1"/>
|
||||||
|
<port type="sram" prefix="sram" size="1"/>
|
||||||
|
</circuit_model>
|
||||||
|
<circuit_model type="mux" name="mux_2level_tapbuf" prefix="mux_2level_tapbuf" dump_structural_verilog="true">
|
||||||
|
<design_technology type="cmos" structure="multi_level" num_level="2" add_const_input="true" const_input_val="1"/>
|
||||||
|
<input_buffer exist="true" circuit_model_name="INVTX1"/>
|
||||||
|
<output_buffer exist="true" circuit_model_name="tap_buf4"/>
|
||||||
|
<!--mux2to1 subckt_name="mux2to1"/-->
|
||||||
|
<pass_gate_logic circuit_model_name="TGATE"/>
|
||||||
|
<port type="input" prefix="in" size="1"/>
|
||||||
|
<port type="output" prefix="out" size="1"/>
|
||||||
|
<port type="sram" prefix="sram" size="1"/>
|
||||||
|
</circuit_model>
|
||||||
|
<circuit_model type="mux" name="mux_1level_tapbuf" prefix="mux_1level_tapbuf" is_default="true" dump_structural_verilog="true">
|
||||||
|
<design_technology type="cmos" structure="one_level" add_const_input="true" const_input_val="1"/>
|
||||||
|
<input_buffer exist="true" circuit_model_name="INVTX1"/>
|
||||||
|
<output_buffer exist="true" circuit_model_name="tap_buf4"/>
|
||||||
|
<!--mux2to1 subckt_name="mux2to1"/-->
|
||||||
|
<pass_gate_logic circuit_model_name="TGATE"/>
|
||||||
|
<port type="input" prefix="in" size="1"/>
|
||||||
|
<port type="output" prefix="out" size="1"/>
|
||||||
|
<port type="sram" prefix="sram" size="1"/>
|
||||||
|
</circuit_model>
|
||||||
|
<!--DFF subckt ports should be defined as <D> <Q> <CLK> <RESET> <SET> -->
|
||||||
|
<circuit_model type="ff" name="static_dff" prefix="dff" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/SpiceNetlists/ff.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/VerilogNetlists/ff.v">
|
||||||
|
<design_technology type="cmos"/>
|
||||||
|
<input_buffer exist="true" circuit_model_name="INVTX1"/>
|
||||||
|
<output_buffer exist="true" circuit_model_name="INVTX1"/>
|
||||||
|
<pass_gate_logic circuit_model_name="TGATE"/>
|
||||||
|
<port type="input" prefix="D" size="1"/>
|
||||||
|
<port type="input" prefix="set" size="1" is_global="true" default_val="0" is_set="true"/>
|
||||||
|
<port type="input" prefix="reset" size="1" is_global="true" default_val="0" is_reset="true"/>
|
||||||
|
<port type="output" prefix="Q" size="1"/>
|
||||||
|
<port type="clock" prefix="clk" size="1" is_global="true" default_val="0" />
|
||||||
|
</circuit_model>
|
||||||
|
<circuit_model type="lut" name="lut5" prefix="lut5" dump_structural_verilog="true">
|
||||||
|
<design_technology type="cmos"/>
|
||||||
|
<input_buffer exist="true" circuit_model_name="INVTX1"/>
|
||||||
|
<output_buffer exist="true" circuit_model_name="INVTX1"/>
|
||||||
|
<lut_input_inverter exist="true" circuit_model_name="INVTX1"/>
|
||||||
|
<lut_input_buffer exist="true" circuit_model_name="buf4"/>
|
||||||
|
<pass_gate_logic circuit_model_name="TGATE"/>
|
||||||
|
<port type="input" prefix="in" size="5"/>
|
||||||
|
<port type="output" prefix="out" size="1"/>
|
||||||
|
<port type="sram" prefix="sram" size="32"/>
|
||||||
|
</circuit_model>
|
||||||
|
<!--Scan-chain DFF subckt ports should be defined as <D> <Q> <Qb> <CLK> <RESET> <SET> -->
|
||||||
|
<circuit_model type="ccff" name="sc_dff_compact" prefix="scff" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/SpiceNetlists/ff.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/VerilogNetlists/ff.v">
|
||||||
|
<design_technology type="cmos"/>
|
||||||
|
<input_buffer exist="true" circuit_model_name="INVTX1"/>
|
||||||
|
<output_buffer exist="true" circuit_model_name="INVTX1"/>
|
||||||
|
<pass_gate_logic circuit_model_name="TGATE"/>
|
||||||
|
<port type="input" prefix="pReset" size="1" is_global="true" default_val="0" is_reset="true" is_prog="true"/>
|
||||||
|
<port type="input" prefix="D" size="1"/>
|
||||||
|
<port type="output" prefix="Q" size="1"/>
|
||||||
|
<port type="output" prefix="Qb" size="1"/>
|
||||||
|
<port type="clock" prefix="prog_clk" size="1" is_global="true" default_val="0" is_prog="true"/>
|
||||||
|
</circuit_model>
|
||||||
|
<circuit_model type="iopad" name="iopad" prefix="iopad" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/SpiceNetlists/io.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/VerilogNetlists/io.v">
|
||||||
|
<design_technology type="cmos"/>
|
||||||
|
<input_buffer exist="true" circuit_model_name="INVTX1"/>
|
||||||
|
<output_buffer exist="true" circuit_model_name="INVTX1"/>
|
||||||
|
<pass_gate_logic circuit_model_name="TGATE"/>
|
||||||
|
<port type="inout" prefix="pad" size="1"/>
|
||||||
|
<port type="sram" prefix="en" size="1" mode_select="true" circuit_model_name="sc_dff_compact" default_val="1"/>
|
||||||
|
<port type="input" prefix="outpad" size="1"/>
|
||||||
|
<port type="output" prefix="inpad" size="1"/>
|
||||||
|
</circuit_model>
|
||||||
|
</circuit_library>
|
||||||
|
<configuration_protocol>
|
||||||
|
<organization type="scan_chain" circuit_model_name="sc_dff_compact"/>
|
||||||
|
</configuration_protocol>
|
||||||
|
<connection_block>
|
||||||
|
<switch name="ipin_cblock" circuit_model_name="mux_2level_tapbuf"/>
|
||||||
|
</connection_block>
|
||||||
|
<switch_block>
|
||||||
|
<switch name="0" circuit_model_name="mux_2level_tapbuf"/>
|
||||||
|
</switch_block>
|
||||||
|
<routing_segment>
|
||||||
|
<segment name="L4" circuit_model_name="chan_segment"/>
|
||||||
|
</routing_segment>
|
||||||
|
<pb_type_annotations>
|
||||||
|
<!-- physical pb_type binding in complex block IO -->
|
||||||
|
<pb_type name="io" physical_mode_name="physical" idle_mode_name="inpad"/>
|
||||||
|
<pb_type name="io[physical].iopad" circuit_model_name="iopad" mode_bits="1"/>
|
||||||
|
<pb_type name="io[inpad].inpad" physical_pb_type_name="io[physical].iopad" mode_bits="1"/>
|
||||||
|
<pb_type name="io[outpad].outpad" physical_pb_type_name="io[physical].iopad" mode_bits="0"/>
|
||||||
|
<!-- End physical pb_type binding in complex block IO -->
|
||||||
|
|
||||||
|
<!-- physical pb_type binding in complex block CLB -->
|
||||||
|
<!-- physical mode will be the default mode if not specified -->
|
||||||
|
<pb_type name="clb">
|
||||||
|
<!-- Binding interconnect to circuit models as their physical implementation, if not defined, we use the default model -->
|
||||||
|
<interconnect name="crossbar" circuit_model_name="mux_2level"/>
|
||||||
|
</pb_type>
|
||||||
|
<pb_type name="clb.fle[n1_lut6].ble6.lut6" circuit_model_name="lut6"/>
|
||||||
|
<pb_type name="clb.fle[n1_lut6].ble6.ff" circuit_model_name="static_dff"/>
|
||||||
|
<!-- End physical pb_type binding in complex block IO -->
|
||||||
|
</pb_type_annotations>
|
||||||
|
</openfpga_architecture>
|
||||||
|
<openfpga_simulation_setting>
|
||||||
|
<clock_setting>
|
||||||
|
<operating frequency="200e6" num_cycles="auto" slack="0.2"/>
|
||||||
|
<programming frequency="10e6"/>
|
||||||
|
</clock_setting>
|
||||||
|
<simulator_option>
|
||||||
|
<operating_condition temperature="25"/>
|
||||||
|
<output_log verbose="false" captab="false"/>
|
||||||
|
<accuracy type="abs" value="1e-13"/>
|
||||||
|
<runtime fast_simulation="true"/>
|
||||||
|
</simulator_option>
|
||||||
|
<monte_carlo num_simulation_points="2"/>
|
||||||
|
<measurement_setting>
|
||||||
|
<slew>
|
||||||
|
<rise upper_thres_pct="0.95" lower_thres_pct="0.05"/>
|
||||||
|
<fall upper_thres_pct="0.05" lower_thres_pct="0.95"/>
|
||||||
|
</slew>
|
||||||
|
<delay>
|
||||||
|
<rise input_thres_pct="0.5" output_thres_pct="0.5"/>
|
||||||
|
<fall input_thres_pct="0.5" output_thres_pct="0.5"/>
|
||||||
|
</delay>
|
||||||
|
</measurement_setting>
|
||||||
|
<stimulus>
|
||||||
|
<clock>
|
||||||
|
<rise slew_type="abs" slew_time="20e-12" />
|
||||||
|
<fall slew_type="abs" slew_time="20e-12" />
|
||||||
|
</clock>
|
||||||
|
<input>
|
||||||
|
<rise slew_type="abs" slew_time="25e-12" />
|
||||||
|
<fall slew_type="abs" slew_time="25e-12" />
|
||||||
|
</input>
|
||||||
|
</stimulus>
|
||||||
|
</openfpga_simulation_setting>
|
|
@ -0,0 +1,8 @@
|
||||||
|
# Run VPR for the s298 design
|
||||||
|
vpr ./test_vpr_arch/k6_N10_40nm.xml ./test_blif/s298.blif
|
||||||
|
|
||||||
|
# Read OpenFPGA architecture definition
|
||||||
|
read_openfpga_arch -f ./test_openfpga_arch/k6_N10_40nm_openfpga.xml
|
||||||
|
|
||||||
|
# Annotate the OpenFPGA architecture to VPR data base
|
||||||
|
link_openfpga_arch
|
|
@ -0,0 +1,308 @@
|
||||||
|
<!--
|
||||||
|
Architecture with no fracturable LUTs
|
||||||
|
|
||||||
|
- 40 nm technology
|
||||||
|
- General purpose logic block:
|
||||||
|
K = 6, N = 10
|
||||||
|
- Routing architecture: L = 4, fc_in = 0.15, Fc_out = 0.1
|
||||||
|
|
||||||
|
Details on Modelling:
|
||||||
|
|
||||||
|
Based on flagship k6_frac_N10_mem32K_40nm.xml architecture. This architecture has no fracturable LUTs nor any heterogeneous blocks.
|
||||||
|
|
||||||
|
|
||||||
|
Authors: Jason Luu, Jeff Goeders, Vaughn Betz
|
||||||
|
-->
|
||||||
|
<architecture>
|
||||||
|
<!--
|
||||||
|
ODIN II specific config begins
|
||||||
|
Describes the types of user-specified netlist blocks (in blif, this corresponds to
|
||||||
|
".model [type_of_block]") that this architecture supports.
|
||||||
|
|
||||||
|
Note: Basic LUTs, I/Os, and flip-flops are not included here as there are
|
||||||
|
already special structures in blif (.names, .input, .output, and .latch)
|
||||||
|
that describe them.
|
||||||
|
-->
|
||||||
|
<models>
|
||||||
|
<!-- A virtual model for I/O to be used in the physical mode of io block -->
|
||||||
|
<model name="io">
|
||||||
|
<input_ports>
|
||||||
|
<port name="outpad"/>
|
||||||
|
</input_ports>
|
||||||
|
<output_ports>
|
||||||
|
<port name="inpad"/>
|
||||||
|
</output_ports>
|
||||||
|
</model>
|
||||||
|
</models>
|
||||||
|
<tiles>
|
||||||
|
<tile name="io" capacity="8" area="0">
|
||||||
|
<equivalent_sites>
|
||||||
|
<site pb_type="io"/>
|
||||||
|
</equivalent_sites>
|
||||||
|
<input name="outpad" num_pins="1"/>
|
||||||
|
<output name="inpad" num_pins="1"/>
|
||||||
|
<clock name="clock" num_pins="1"/>
|
||||||
|
<fc in_type="frac" in_val="0.15" out_type="frac" out_val="0.10"/>
|
||||||
|
<pinlocations pattern="custom">
|
||||||
|
<loc side="left">io.outpad io.inpad io.clock</loc>
|
||||||
|
<loc side="top">io.outpad io.inpad io.clock</loc>
|
||||||
|
<loc side="right">io.outpad io.inpad io.clock</loc>
|
||||||
|
<loc side="bottom">io.outpad io.inpad io.clock</loc>
|
||||||
|
</pinlocations>
|
||||||
|
</tile>
|
||||||
|
<tile name="clb" area="53894">
|
||||||
|
<equivalent_sites>
|
||||||
|
<site pb_type="clb"/>
|
||||||
|
</equivalent_sites>
|
||||||
|
<input name="I" num_pins="40" equivalent="full"/>
|
||||||
|
<output name="O" num_pins="10" equivalent="instance"/>
|
||||||
|
<clock name="clk" num_pins="1"/>
|
||||||
|
<fc in_type="frac" in_val="0.15" out_type="frac" out_val="0.10"/>
|
||||||
|
<pinlocations pattern="spread"/>
|
||||||
|
</tile>
|
||||||
|
</tiles>
|
||||||
|
<!-- ODIN II specific config ends -->
|
||||||
|
<!-- Physical descriptions begin -->
|
||||||
|
<layout>
|
||||||
|
<auto_layout aspect_ratio="1.0">
|
||||||
|
<!--Perimeter of 'io' blocks with 'EMPTY' blocks at corners-->
|
||||||
|
<perimeter type="io" priority="100"/>
|
||||||
|
<corners type="EMPTY" priority="101"/>
|
||||||
|
<!--Fill with 'clb'-->
|
||||||
|
<fill type="clb" priority="10"/>
|
||||||
|
</auto_layout>
|
||||||
|
</layout>
|
||||||
|
<device>
|
||||||
|
<!-- VB & JL: Using Ian Kuon's transistor sizing and drive strength data for routing, at 40 nm. Ian used BPTM
|
||||||
|
models. We are modifying the delay values however, to include metal C and R, which allows more architecture
|
||||||
|
experimentation. We are also modifying the relative resistance of PMOS to be 1.8x that of NMOS
|
||||||
|
(vs. Ian's 3x) as 1.8x lines up with Jeff G's data from a 45 nm process (and is more typical of
|
||||||
|
45 nm in general). I'm upping the Rmin_nmos from Ian's just over 6k to nearly 9k, and dropping
|
||||||
|
RminW_pmos from 18k to 16k to hit this 1.8x ratio, while keeping the delays of buffers approximately
|
||||||
|
lined up with Stratix IV.
|
||||||
|
We are using Jeff G.'s capacitance data for 45 nm (in tech/ptm_45nm).
|
||||||
|
Jeff's tables list C in for transistors with widths in multiples of the minimum feature size (45 nm).
|
||||||
|
The minimum contactable transistor is 2.5 * 45 nm, so I need to multiply drive strength sizes in this file
|
||||||
|
by 2.5x when looking up in Jeff's tables.
|
||||||
|
The delay values are lined up with Stratix IV, which has an architecture similar to this
|
||||||
|
proposed FPGA, and which is also 40 nm
|
||||||
|
C_ipin_cblock: input capacitance of a track buffer, which VPR assumes is a single-stage
|
||||||
|
4x minimum drive strength buffer. -->
|
||||||
|
<sizing R_minW_nmos="8926" R_minW_pmos="16067"/>
|
||||||
|
<!-- The grid_logic_tile_area below will be used for all blocks that do not explicitly set their own (non-routing)
|
||||||
|
area; set to 0 since we explicitly set the area of all blocks currently in this architecture file.
|
||||||
|
-->
|
||||||
|
<area grid_logic_tile_area="0"/>
|
||||||
|
<chan_width_distr>
|
||||||
|
<x distr="uniform" peak="1.000000"/>
|
||||||
|
<y distr="uniform" peak="1.000000"/>
|
||||||
|
</chan_width_distr>
|
||||||
|
<switch_block type="wilton" fs="3"/>
|
||||||
|
<connection_block input_switch_name="ipin_cblock"/>
|
||||||
|
</device>
|
||||||
|
<switchlist>
|
||||||
|
<!-- VB: the mux_trans_size and buf_size data below is in minimum width transistor *areas*, assuming the purple
|
||||||
|
book area formula. This means the mux transistors are about 5x minimum drive strength.
|
||||||
|
We assume the first stage of the buffer is 3x min drive strength to be reasonable given the large
|
||||||
|
mux transistors, and this gives a reasonable stage ratio of a bit over 5x to the second stage. We assume
|
||||||
|
the n and p transistors in the first stage are equal-sized to lower the buffer trip point, since it's fed
|
||||||
|
by a pass transistor mux. We can then reverse engineer the buffer second stage to hit the specified
|
||||||
|
buf_size (really buffer area) - 16.2x minimum drive nmos and 1.8*16.2 = 29.2x minimum drive.
|
||||||
|
I then took the data from Jeff G.'s PTM modeling of 45 nm to get the Cin (gate of first stage) and Cout
|
||||||
|
(diff of second stage) listed below. Jeff's models are in tech/ptm_45nm, and are in min feature multiples.
|
||||||
|
The minimum contactable transistor is 2.5 * 45 nm, so I need to multiply the drive strength sizes above by
|
||||||
|
2.5x when looking up in Jeff's tables.
|
||||||
|
Finally, we choose a switch delay (58 ps) that leads to length 4 wires having a delay equal to that of SIV of 126 ps.
|
||||||
|
This also leads to the switch being 46% of the total wire delay, which is reasonable. -->
|
||||||
|
<switch type="mux" name="0" R="551" Cin=".77e-15" Cout="4e-15" Tdel="58e-12" mux_trans_size="2.630740" buf_size="27.645901"/>
|
||||||
|
<!--switch ipin_cblock resistance set to yeild for 4x minimum drive strength buffer-->
|
||||||
|
<switch type="mux" name="ipin_cblock" R="2231.5" Cout="0." Cin="1.47e-15" Tdel="7.247000e-11" mux_trans_size="1.222260" buf_size="auto"/>
|
||||||
|
</switchlist>
|
||||||
|
<segmentlist>
|
||||||
|
<!--- VB & JL: using ITRS metal stack data, 96 nm half pitch wires, which are intermediate metal width/space.
|
||||||
|
With the 96 nm half pitch, such wires would take 60 um of height, vs. a 90 nm high (approximated as square) Stratix IV tile so this seems
|
||||||
|
reasonable. Using a tile length of 90 nm, corresponding to the length of a Stratix IV tile if it were square. -->
|
||||||
|
<segment name="L4" freq="1.000000" length="4" type="unidir" Rmetal="101" Cmetal="22.5e-15">
|
||||||
|
<mux name="0"/>
|
||||||
|
<sb type="pattern">1 1 1 1 1</sb>
|
||||||
|
<cb type="pattern">1 1 1 1</cb>
|
||||||
|
</segment>
|
||||||
|
</segmentlist>
|
||||||
|
<complexblocklist>
|
||||||
|
<!-- Define I/O pads begin -->
|
||||||
|
<!-- Capacity is a unique property of I/Os, it is the maximum number of I/Os that can be placed at the same (X,Y) location on the FPGA -->
|
||||||
|
<!-- Not sure of the area of an I/O (varies widely), and it's not relevant to the design of the FPGA core, so we're setting it to 0. -->
|
||||||
|
<pb_type name="io">
|
||||||
|
<input name="outpad" num_pins="1"/>
|
||||||
|
<output name="inpad" num_pins="1"/>
|
||||||
|
<clock name="clock" num_pins="1"/>
|
||||||
|
<!-- A mode denotes the physical implementation of an I/O
|
||||||
|
This mode will be not packable but is mainly used for fabric verilog generation
|
||||||
|
-->
|
||||||
|
<mode name="physical" disabled_in_pack="true">
|
||||||
|
<pb_type name="iopad" blif_model=".subckt io" num_pb="1">
|
||||||
|
<input name="outpad" num_pins="1"/>
|
||||||
|
<output name="inpad" num_pins="1"/>
|
||||||
|
</pb_type>
|
||||||
|
<interconnect>
|
||||||
|
<direct name="outpad" input="io.outpad" output="iopad.outpad">
|
||||||
|
<delay_constant max="1.394e-11" in_port="io.outpad" out_port="iopad.outpad"/>
|
||||||
|
</direct>
|
||||||
|
<direct name="inpad" input="iopad.inpad" output="io.inpad">
|
||||||
|
<delay_constant max="4.243e-11" in_port="iopad.inpad" out_port="io.inpad"/>
|
||||||
|
</direct>
|
||||||
|
</interconnect>
|
||||||
|
</mode>
|
||||||
|
<!-- IOs can operate as either inputs or outputs.
|
||||||
|
Delays below come from Ian Kuon. They are small, so they should be interpreted as
|
||||||
|
the delays to and from registers in the I/O (and generally I/Os are registered
|
||||||
|
today and that is when you timing analyze them.
|
||||||
|
-->
|
||||||
|
<mode name="inpad">
|
||||||
|
<pb_type name="inpad" blif_model=".input" num_pb="1">
|
||||||
|
<output name="inpad" num_pins="1"/>
|
||||||
|
</pb_type>
|
||||||
|
<interconnect>
|
||||||
|
<direct name="inpad" input="inpad.inpad" output="io.inpad">
|
||||||
|
<delay_constant max="4.243e-11" in_port="inpad.inpad" out_port="io.inpad"/>
|
||||||
|
</direct>
|
||||||
|
</interconnect>
|
||||||
|
</mode>
|
||||||
|
<mode name="outpad">
|
||||||
|
<pb_type name="outpad" blif_model=".output" num_pb="1">
|
||||||
|
<input name="outpad" num_pins="1"/>
|
||||||
|
</pb_type>
|
||||||
|
<interconnect>
|
||||||
|
<direct name="outpad" input="io.outpad" output="outpad.outpad">
|
||||||
|
<delay_constant max="1.394e-11" in_port="io.outpad" out_port="outpad.outpad"/>
|
||||||
|
</direct>
|
||||||
|
</interconnect>
|
||||||
|
</mode>
|
||||||
|
<!-- Every input pin is driven by 15% of the tracks in a channel, every output pin is driven by 10% of the tracks in a channel -->
|
||||||
|
<!-- IOs go on the periphery of the FPGA, for consistency,
|
||||||
|
make it physically equivalent on all sides so that only one definition of I/Os is needed.
|
||||||
|
If I do not make a physically equivalent definition, then I need to define 4 different I/Os, one for each side of the FPGA
|
||||||
|
-->
|
||||||
|
<!-- Place I/Os on the sides of the FPGA -->
|
||||||
|
<power method="ignore"/>
|
||||||
|
</pb_type>
|
||||||
|
<!-- Define I/O pads ends -->
|
||||||
|
<!-- Define general purpose logic block (CLB) begin -->
|
||||||
|
<!--- Area calculation: Total Stratix IV tile area is about 8100 um^2, and a minimum width transistor
|
||||||
|
area is 60 L^2 yields a tile area of 84375 MWTAs.
|
||||||
|
Routing at W=300 is 30481 MWTAs, leaving us with a total of 53000 MWTAs for logic block area
|
||||||
|
This means that only 37% of our area is in the general routing, and 63% is inside the logic
|
||||||
|
block. Note that the crossbar / local interconnect is considered part of the logic block
|
||||||
|
area in this analysis. That is a lower proportion of of routing area than most academics
|
||||||
|
assume, but note that the total routing area really includes the crossbar, which would push
|
||||||
|
routing area up significantly, we estimate into the ~70% range.
|
||||||
|
-->
|
||||||
|
<pb_type name="clb">
|
||||||
|
<input name="I" num_pins="40" equivalent="full"/>
|
||||||
|
<output name="O" num_pins="10" equivalent="instance"/>
|
||||||
|
<clock name="clk" num_pins="1"/>
|
||||||
|
<!-- Describe basic logic element.
|
||||||
|
Each basic logic element has a 6-LUT that can be optionally registered
|
||||||
|
-->
|
||||||
|
<pb_type name="fle" num_pb="10">
|
||||||
|
<input name="in" num_pins="6"/>
|
||||||
|
<output name="out" num_pins="1"/>
|
||||||
|
<clock name="clk" num_pins="1"/>
|
||||||
|
<!-- 6-LUT mode definition begin -->
|
||||||
|
<mode name="n1_lut6">
|
||||||
|
<!-- Define 6-LUT mode -->
|
||||||
|
<pb_type name="ble6" num_pb="1">
|
||||||
|
<input name="in" num_pins="6"/>
|
||||||
|
<output name="out" num_pins="1"/>
|
||||||
|
<clock name="clk" num_pins="1"/>
|
||||||
|
<!-- Define LUT -->
|
||||||
|
<pb_type name="lut6" blif_model=".names" num_pb="1" class="lut">
|
||||||
|
<input name="in" num_pins="6" port_class="lut_in"/>
|
||||||
|
<output name="out" num_pins="1" port_class="lut_out"/>
|
||||||
|
<!-- LUT timing using delay matrix -->
|
||||||
|
<!-- These are the physical delay inputs on a Stratix IV LUT but because VPR cannot do LUT rebalancing,
|
||||||
|
we instead take the average of these numbers to get more stable results
|
||||||
|
82e-12
|
||||||
|
173e-12
|
||||||
|
261e-12
|
||||||
|
263e-12
|
||||||
|
398e-12
|
||||||
|
397e-12
|
||||||
|
-->
|
||||||
|
<delay_matrix type="max" in_port="lut6.in" out_port="lut6.out">
|
||||||
|
261e-12
|
||||||
|
261e-12
|
||||||
|
261e-12
|
||||||
|
261e-12
|
||||||
|
261e-12
|
||||||
|
261e-12
|
||||||
|
</delay_matrix>
|
||||||
|
</pb_type>
|
||||||
|
<!-- Define flip-flop -->
|
||||||
|
<pb_type name="ff" blif_model=".latch" num_pb="1" class="flipflop">
|
||||||
|
<input name="D" num_pins="1" port_class="D"/>
|
||||||
|
<output name="Q" num_pins="1" port_class="Q"/>
|
||||||
|
<clock name="clk" num_pins="1" port_class="clock"/>
|
||||||
|
<T_setup value="66e-12" port="ff.D" clock="clk"/>
|
||||||
|
<T_clock_to_Q max="124e-12" port="ff.Q" clock="clk"/>
|
||||||
|
</pb_type>
|
||||||
|
<interconnect>
|
||||||
|
<direct name="direct1" input="ble6.in" output="lut6[0:0].in"/>
|
||||||
|
<direct name="direct2" input="lut6.out" output="ff.D">
|
||||||
|
<!-- Advanced user option that tells CAD tool to find LUT+FF pairs in netlist -->
|
||||||
|
<pack_pattern name="ble6" in_port="lut6.out" out_port="ff.D"/>
|
||||||
|
</direct>
|
||||||
|
<direct name="direct3" input="ble6.clk" output="ff.clk"/>
|
||||||
|
<mux name="mux1" input="ff.Q lut6.out" output="ble6.out">
|
||||||
|
<!-- LUT to output is faster than FF to output on a Stratix IV -->
|
||||||
|
<delay_constant max="25e-12" in_port="lut6.out" out_port="ble6.out"/>
|
||||||
|
<delay_constant max="45e-12" in_port="ff.Q" out_port="ble6.out"/>
|
||||||
|
</mux>
|
||||||
|
</interconnect>
|
||||||
|
</pb_type>
|
||||||
|
<interconnect>
|
||||||
|
<direct name="direct1" input="fle.in" output="ble6.in"/>
|
||||||
|
<direct name="direct2" input="ble6.out" output="fle.out[0:0]"/>
|
||||||
|
<direct name="direct3" input="fle.clk" output="ble6.clk"/>
|
||||||
|
</interconnect>
|
||||||
|
</mode>
|
||||||
|
<!-- 6-LUT mode definition end -->
|
||||||
|
</pb_type>
|
||||||
|
<interconnect>
|
||||||
|
<!-- We use a full crossbar to get logical equivalence at inputs of CLB
|
||||||
|
The delays below come from Stratix IV. the delay through a connection block
|
||||||
|
input mux + the crossbar in Stratix IV is 167 ps. We already have a 72 ps
|
||||||
|
delay on the connection block input mux (modeled by Ian Kuon), so the remaining
|
||||||
|
delay within the crossbar is 95 ps.
|
||||||
|
The delays of cluster feedbacks in Stratix IV is 100 ps, when driven by a LUT.
|
||||||
|
Since all our outputs LUT outputs go to a BLE output, and have a delay of
|
||||||
|
25 ps to do so, we subtract 25 ps from the 100 ps delay of a feedback
|
||||||
|
to get the part that should be marked on the crossbar. -->
|
||||||
|
<complete name="crossbar" input="clb.I fle[9:0].out" output="fle[9:0].in">
|
||||||
|
<delay_constant max="95e-12" in_port="clb.I" out_port="fle[9:0].in"/>
|
||||||
|
<delay_constant max="75e-12" in_port="fle[9:0].out" out_port="fle[9:0].in"/>
|
||||||
|
</complete>
|
||||||
|
<complete name="clks" input="clb.clk" output="fle[9:0].clk">
|
||||||
|
</complete>
|
||||||
|
<!-- This way of specifying direct connection to clb outputs is important because this architecture uses automatic spreading of opins.
|
||||||
|
By grouping to output pins in this fashion, if a logic block is completely filled by 6-LUTs,
|
||||||
|
then the outputs those 6-LUTs take get evenly distributed across all four sides of the CLB instead of clumped on two sides (which is what happens with a more
|
||||||
|
naive specification).
|
||||||
|
-->
|
||||||
|
<direct name="clbouts1" input="fle[9:0].out" output="clb.O"/>
|
||||||
|
</interconnect>
|
||||||
|
<!-- Every input pin is driven by 15% of the tracks in a channel, every output pin is driven by 10% of the tracks in a channel -->
|
||||||
|
<!-- Place this general purpose logic block in any unspecified column -->
|
||||||
|
</pb_type>
|
||||||
|
<!-- Define general purpose logic block (CLB) ends -->
|
||||||
|
</complexblocklist>
|
||||||
|
<power>
|
||||||
|
<local_interconnect C_wire="2.5e-10"/>
|
||||||
|
<mux_transistor_size mux_transistor_size="3"/>
|
||||||
|
<FF_size FF_size="4"/>
|
||||||
|
<LUT_transistor_size LUT_transistor_size="4"/>
|
||||||
|
</power>
|
||||||
|
<clocks>
|
||||||
|
<clock buffer_size="auto" C_wire="2.5e-10"/>
|
||||||
|
</clocks>
|
||||||
|
</architecture>
|
|
@ -0,0 +1,351 @@
|
||||||
|
<!--
|
||||||
|
Flagship Heterogeneous Architecture (No Carry Chains) for VTR 7.0.
|
||||||
|
|
||||||
|
- 40 nm technology
|
||||||
|
- General purpose logic block:
|
||||||
|
K = 6, N = 10, fracturable 6 LUTs (can operate as one 6-LUT or two 5-LUTs with all 5 inputs shared)
|
||||||
|
with optionally registered outputs
|
||||||
|
- Routing architecture: L = 4, fc_in = 0.15, Fc_out = 0.1
|
||||||
|
|
||||||
|
Details on Modelling:
|
||||||
|
|
||||||
|
Based on flagship k6_frac_N10_mem32K_40nm.xml architecture.
|
||||||
|
|
||||||
|
Authors: Jason Luu, Jeff Goeders, Vaughn Betz
|
||||||
|
-->
|
||||||
|
<architecture>
|
||||||
|
<!--
|
||||||
|
ODIN II specific config begins
|
||||||
|
Describes the types of user-specified netlist blocks (in blif, this corresponds to
|
||||||
|
".model [type_of_block]") that this architecture supports.
|
||||||
|
|
||||||
|
Note: Basic LUTs, I/Os, and flip-flops are not included here as there are
|
||||||
|
already special structures in blif (.names, .input, .output, and .latch)
|
||||||
|
that describe them.
|
||||||
|
-->
|
||||||
|
<models>
|
||||||
|
</models>
|
||||||
|
<tiles>
|
||||||
|
<tile name="io" capacity="8" area="0">
|
||||||
|
<equivalent_sites>
|
||||||
|
<site pb_type="io"/>
|
||||||
|
</equivalent_sites>
|
||||||
|
<input name="outpad" num_pins="1"/>
|
||||||
|
<output name="inpad" num_pins="1"/>
|
||||||
|
<clock name="clock" num_pins="1"/>
|
||||||
|
<fc in_type="frac" in_val="0.15" out_type="frac" out_val="0.10"/>
|
||||||
|
<pinlocations pattern="custom">
|
||||||
|
<loc side="left">io.outpad io.inpad io.clock</loc>
|
||||||
|
<loc side="top">io.outpad io.inpad io.clock</loc>
|
||||||
|
<loc side="right">io.outpad io.inpad io.clock</loc>
|
||||||
|
<loc side="bottom">io.outpad io.inpad io.clock</loc>
|
||||||
|
</pinlocations>
|
||||||
|
</tile>
|
||||||
|
<tile name="clb" area="53894">
|
||||||
|
<equivalent_sites>
|
||||||
|
<site pb_type="clb"/>
|
||||||
|
</equivalent_sites>
|
||||||
|
<input name="I" num_pins="40" equivalent="full"/>
|
||||||
|
<output name="O" num_pins="20" equivalent="none"/>
|
||||||
|
<clock name="clk" num_pins="1"/>
|
||||||
|
<fc in_type="frac" in_val="0.15" out_type="frac" out_val="0.10"/>
|
||||||
|
<pinlocations pattern="spread"/>
|
||||||
|
</tile>
|
||||||
|
</tiles>
|
||||||
|
<!-- ODIN II specific config ends -->
|
||||||
|
<!-- Physical descriptions begin -->
|
||||||
|
<layout>
|
||||||
|
<auto_layout aspect_ratio="1.0">
|
||||||
|
<!--Perimeter of 'io' blocks with 'EMPTY' blocks at corners-->
|
||||||
|
<perimeter type="io" priority="100"/>
|
||||||
|
<corners type="EMPTY" priority="101"/>
|
||||||
|
<!--Fill with 'clb'-->
|
||||||
|
<fill type="clb" priority="10"/>
|
||||||
|
</auto_layout>
|
||||||
|
</layout>
|
||||||
|
<device>
|
||||||
|
<!-- VB & JL: Using Ian Kuon's transistor sizing and drive strength data for routing, at 40 nm. Ian used BPTM
|
||||||
|
models. We are modifying the delay values however, to include metal C and R, which allows more architecture
|
||||||
|
experimentation. We are also modifying the relative resistance of PMOS to be 1.8x that of NMOS
|
||||||
|
(vs. Ian's 3x) as 1.8x lines up with Jeff G's data from a 45 nm process (and is more typical of
|
||||||
|
45 nm in general). I'm upping the Rmin_nmos from Ian's just over 6k to nearly 9k, and dropping
|
||||||
|
RminW_pmos from 18k to 16k to hit this 1.8x ratio, while keeping the delays of buffers approximately
|
||||||
|
lined up with Stratix IV.
|
||||||
|
We are using Jeff G.'s capacitance data for 45 nm (in tech/ptm_45nm).
|
||||||
|
Jeff's tables list C in for transistors with widths in multiples of the minimum feature size (45 nm).
|
||||||
|
The minimum contactable transistor is 2.5 * 45 nm, so I need to multiply drive strength sizes in this file
|
||||||
|
by 2.5x when looking up in Jeff's tables.
|
||||||
|
The delay values are lined up with Stratix IV, which has an architecture similar to this
|
||||||
|
proposed FPGA, and which is also 40 nm
|
||||||
|
C_ipin_cblock: input capacitance of a track buffer, which VPR assumes is a single-stage
|
||||||
|
4x minimum drive strength buffer. -->
|
||||||
|
<sizing R_minW_nmos="8926" R_minW_pmos="16067"/>
|
||||||
|
<!-- The grid_logic_tile_area below will be used for all blocks that do not explicitly set their own (non-routing)
|
||||||
|
area; set to 0 since we explicitly set the area of all blocks currently in this architecture file.
|
||||||
|
-->
|
||||||
|
<area grid_logic_tile_area="0"/>
|
||||||
|
<chan_width_distr>
|
||||||
|
<x distr="uniform" peak="1.000000"/>
|
||||||
|
<y distr="uniform" peak="1.000000"/>
|
||||||
|
</chan_width_distr>
|
||||||
|
<switch_block type="wilton" fs="3"/>
|
||||||
|
<connection_block input_switch_name="ipin_cblock"/>
|
||||||
|
</device>
|
||||||
|
<switchlist>
|
||||||
|
<!-- VB: the mux_trans_size and buf_size data below is in minimum width transistor *areas*, assuming the purple
|
||||||
|
book area formula. This means the mux transistors are about 5x minimum drive strength.
|
||||||
|
We assume the first stage of the buffer is 3x min drive strength to be reasonable given the large
|
||||||
|
mux transistors, and this gives a reasonable stage ratio of a bit over 5x to the second stage. We assume
|
||||||
|
the n and p transistors in the first stage are equal-sized to lower the buffer trip point, since it's fed
|
||||||
|
by a pass transistor mux. We can then reverse engineer the buffer second stage to hit the specified
|
||||||
|
buf_size (really buffer area) - 16.2x minimum drive nmos and 1.8*16.2 = 29.2x minimum drive.
|
||||||
|
I then took the data from Jeff G.'s PTM modeling of 45 nm to get the Cin (gate of first stage) and Cout
|
||||||
|
(diff of second stage) listed below. Jeff's models are in tech/ptm_45nm, and are in min feature multiples.
|
||||||
|
The minimum contactable transistor is 2.5 * 45 nm, so I need to multiply the drive strength sizes above by
|
||||||
|
2.5x when looking up in Jeff's tables.
|
||||||
|
Finally, we choose a switch delay (58 ps) that leads to length 4 wires having a delay equal to that of SIV of 126 ps.
|
||||||
|
This also leads to the switch being 46% of the total wire delay, which is reasonable. -->
|
||||||
|
<switch type="mux" name="0" R="551" Cin=".77e-15" Cout="4e-15" Tdel="58e-12" mux_trans_size="2.630740" buf_size="27.645901"/>
|
||||||
|
<!--switch ipin_cblock resistance set to yeild for 4x minimum drive strength buffer-->
|
||||||
|
<switch type="mux" name="ipin_cblock" R="2231.5" Cout="0." Cin="1.47e-15" Tdel="7.247000e-11" mux_trans_size="1.222260" buf_size="auto"/>
|
||||||
|
</switchlist>
|
||||||
|
<segmentlist>
|
||||||
|
<!--- VB & JL: using ITRS metal stack data, 96 nm half pitch wires, which are intermediate metal width/space.
|
||||||
|
With the 96 nm half pitch, such wires would take 60 um of height, vs. a 90 nm high (approximated as square) Stratix IV tile so this seems
|
||||||
|
reasonable. Using a tile length of 90 nm, corresponding to the length of a Stratix IV tile if it were square. -->
|
||||||
|
<segment freq="1.000000" length="4" type="unidir" Rmetal="101" Cmetal="22.5e-15">
|
||||||
|
<mux name="0"/>
|
||||||
|
<sb type="pattern">1 1 1 1 1</sb>
|
||||||
|
<cb type="pattern">1 1 1 1</cb>
|
||||||
|
</segment>
|
||||||
|
</segmentlist>
|
||||||
|
<complexblocklist>
|
||||||
|
<!-- Define I/O pads begin -->
|
||||||
|
<!-- Capacity is a unique property of I/Os, it is the maximum number of I/Os that can be placed at the same (X,Y) location on the FPGA -->
|
||||||
|
<!-- Not sure of the area of an I/O (varies widely), and it's not relevant to the design of the FPGA core, so we're setting it to 0. -->
|
||||||
|
<pb_type name="io">
|
||||||
|
<input name="outpad" num_pins="1"/>
|
||||||
|
<output name="inpad" num_pins="1"/>
|
||||||
|
<clock name="clock" num_pins="1"/>
|
||||||
|
<!-- IOs can operate as either inputs or outputs.
|
||||||
|
Delays below come from Ian Kuon. They are small, so they should be interpreted as
|
||||||
|
the delays to and from registers in the I/O (and generally I/Os are registered
|
||||||
|
today and that is when you timing analyze them.
|
||||||
|
-->
|
||||||
|
<mode name="inpad">
|
||||||
|
<pb_type name="inpad" blif_model=".input" num_pb="1">
|
||||||
|
<output name="inpad" num_pins="1"/>
|
||||||
|
</pb_type>
|
||||||
|
<interconnect>
|
||||||
|
<direct name="inpad" input="inpad.inpad" output="io.inpad">
|
||||||
|
<delay_constant max="4.243e-11" in_port="inpad.inpad" out_port="io.inpad"/>
|
||||||
|
</direct>
|
||||||
|
</interconnect>
|
||||||
|
</mode>
|
||||||
|
<mode name="outpad">
|
||||||
|
<pb_type name="outpad" blif_model=".output" num_pb="1">
|
||||||
|
<input name="outpad" num_pins="1"/>
|
||||||
|
</pb_type>
|
||||||
|
<interconnect>
|
||||||
|
<direct name="outpad" input="io.outpad" output="outpad.outpad">
|
||||||
|
<delay_constant max="1.394e-11" in_port="io.outpad" out_port="outpad.outpad"/>
|
||||||
|
</direct>
|
||||||
|
</interconnect>
|
||||||
|
</mode>
|
||||||
|
<!-- Every input pin is driven by 15% of the tracks in a channel, every output pin is driven by 10% of the tracks in a channel -->
|
||||||
|
<!-- IOs go on the periphery of the FPGA, for consistency,
|
||||||
|
make it physically equivalent on all sides so that only one definition of I/Os is needed.
|
||||||
|
If I do not make a physically equivalent definition, then I need to define 4 different I/Os, one for each side of the FPGA
|
||||||
|
-->
|
||||||
|
<!-- Place I/Os on the sides of the FPGA -->
|
||||||
|
<power method="ignore"/>
|
||||||
|
</pb_type>
|
||||||
|
<!-- Define I/O pads ends -->
|
||||||
|
<!-- Define general purpose logic block (CLB) begin -->
|
||||||
|
<!--- Area calculation: Total Stratix IV tile area is about 8100 um^2, and a minimum width transistor
|
||||||
|
area is 60 L^2 yields a tile area of 84375 MWTAs.
|
||||||
|
Routing at W=300 is 30481 MWTAs, leaving us with a total of 53000 MWTAs for logic block area
|
||||||
|
This means that only 37% of our area is in the general routing, and 63% is inside the logic
|
||||||
|
block. Note that the crossbar / local interconnect is considered part of the logic block
|
||||||
|
area in this analysis. That is a lower proportion of of routing area than most academics
|
||||||
|
assume, but note that the total routing area really includes the crossbar, which would push
|
||||||
|
routing area up significantly, we estimate into the ~70% range.
|
||||||
|
-->
|
||||||
|
<pb_type name="clb">
|
||||||
|
<input name="I" num_pins="40" equivalent="full"/>
|
||||||
|
<output name="O" num_pins="20" equivalent="none"/>
|
||||||
|
<clock name="clk" num_pins="1"/>
|
||||||
|
<!-- Describe fracturable logic element.
|
||||||
|
Each fracturable logic element has a 6-LUT that can alternatively operate as two 5-LUTs with shared inputs.
|
||||||
|
The outputs of the fracturable logic element can be optionally registered
|
||||||
|
-->
|
||||||
|
<pb_type name="fle" num_pb="10">
|
||||||
|
<input name="in" num_pins="6"/>
|
||||||
|
<output name="out" num_pins="2"/>
|
||||||
|
<clock name="clk" num_pins="1"/>
|
||||||
|
<!-- Dual 5-LUT mode definition begin -->
|
||||||
|
<mode name="n2_lut5">
|
||||||
|
<pb_type name="lut5inter" num_pb="1">
|
||||||
|
<input name="in" num_pins="5"/>
|
||||||
|
<output name="out" num_pins="2"/>
|
||||||
|
<clock name="clk" num_pins="1"/>
|
||||||
|
<pb_type name="ble5" num_pb="2">
|
||||||
|
<input name="in" num_pins="5"/>
|
||||||
|
<output name="out" num_pins="1"/>
|
||||||
|
<clock name="clk" num_pins="1"/>
|
||||||
|
<!-- Define the LUT -->
|
||||||
|
<pb_type name="lut5" blif_model=".names" num_pb="1" class="lut">
|
||||||
|
<input name="in" num_pins="5" port_class="lut_in"/>
|
||||||
|
<output name="out" num_pins="1" port_class="lut_out"/>
|
||||||
|
<!-- LUT timing using delay matrix -->
|
||||||
|
<!-- These are the physical delay inputs on a Stratix IV LUT but because VPR cannot do LUT rebalancing,
|
||||||
|
we instead take the average of these numbers to get more stable results
|
||||||
|
82e-12
|
||||||
|
173e-12
|
||||||
|
261e-12
|
||||||
|
263e-12
|
||||||
|
398e-12
|
||||||
|
-->
|
||||||
|
<delay_matrix type="max" in_port="lut5.in" out_port="lut5.out">
|
||||||
|
235e-12
|
||||||
|
235e-12
|
||||||
|
235e-12
|
||||||
|
235e-12
|
||||||
|
235e-12
|
||||||
|
</delay_matrix>
|
||||||
|
</pb_type>
|
||||||
|
<!-- Define the flip-flop -->
|
||||||
|
<pb_type name="ff" blif_model=".latch" num_pb="1" class="flipflop">
|
||||||
|
<input name="D" num_pins="1" port_class="D"/>
|
||||||
|
<output name="Q" num_pins="1" port_class="Q"/>
|
||||||
|
<clock name="clk" num_pins="1" port_class="clock"/>
|
||||||
|
<T_setup value="66e-12" port="ff.D" clock="clk"/>
|
||||||
|
<T_clock_to_Q max="124e-12" port="ff.Q" clock="clk"/>
|
||||||
|
</pb_type>
|
||||||
|
<interconnect>
|
||||||
|
<direct name="direct1" input="ble5.in[4:0]" output="lut5[0:0].in[4:0]"/>
|
||||||
|
<direct name="direct2" input="lut5[0:0].out" output="ff[0:0].D">
|
||||||
|
<!-- Advanced user option that tells CAD tool to find LUT+FF pairs in netlist -->
|
||||||
|
<pack_pattern name="ble5" in_port="lut5[0:0].out" out_port="ff[0:0].D"/>
|
||||||
|
</direct>
|
||||||
|
<direct name="direct3" input="ble5.clk" output="ff[0:0].clk"/>
|
||||||
|
<mux name="mux1" input="ff[0:0].Q lut5.out[0:0]" output="ble5.out[0:0]">
|
||||||
|
<!-- LUT to output is faster than FF to output on a Stratix IV -->
|
||||||
|
<delay_constant max="25e-12" in_port="lut5.out[0:0]" out_port="ble5.out[0:0]"/>
|
||||||
|
<delay_constant max="45e-12" in_port="ff[0:0].Q" out_port="ble5.out[0:0]"/>
|
||||||
|
</mux>
|
||||||
|
</interconnect>
|
||||||
|
</pb_type>
|
||||||
|
<interconnect>
|
||||||
|
<direct name="direct1" input="lut5inter.in" output="ble5[0:0].in"/>
|
||||||
|
<direct name="direct2" input="lut5inter.in" output="ble5[1:1].in"/>
|
||||||
|
<direct name="direct3" input="ble5[1:0].out" output="lut5inter.out"/>
|
||||||
|
<complete name="complete1" input="lut5inter.clk" output="ble5[1:0].clk"/>
|
||||||
|
</interconnect>
|
||||||
|
</pb_type>
|
||||||
|
<interconnect>
|
||||||
|
<direct name="direct1" input="fle.in[4:0]" output="lut5inter.in"/>
|
||||||
|
<direct name="direct2" input="lut5inter.out" output="fle.out"/>
|
||||||
|
<direct name="direct3" input="fle.clk" output="lut5inter.clk"/>
|
||||||
|
</interconnect>
|
||||||
|
</mode>
|
||||||
|
<!-- Dual 5-LUT mode definition end -->
|
||||||
|
<!-- 6-LUT mode definition begin -->
|
||||||
|
<mode name="n1_lut6">
|
||||||
|
<!-- Define 6-LUT mode -->
|
||||||
|
<pb_type name="ble6" num_pb="1">
|
||||||
|
<input name="in" num_pins="6"/>
|
||||||
|
<output name="out" num_pins="1"/>
|
||||||
|
<clock name="clk" num_pins="1"/>
|
||||||
|
<!-- Define LUT -->
|
||||||
|
<pb_type name="lut6" blif_model=".names" num_pb="1" class="lut">
|
||||||
|
<input name="in" num_pins="6" port_class="lut_in"/>
|
||||||
|
<output name="out" num_pins="1" port_class="lut_out"/>
|
||||||
|
<!-- LUT timing using delay matrix -->
|
||||||
|
<!-- These are the physical delay inputs on a Stratix IV LUT but because VPR cannot do LUT rebalancing,
|
||||||
|
we instead take the average of these numbers to get more stable results
|
||||||
|
82e-12
|
||||||
|
173e-12
|
||||||
|
261e-12
|
||||||
|
263e-12
|
||||||
|
398e-12
|
||||||
|
397e-12
|
||||||
|
-->
|
||||||
|
<delay_matrix type="max" in_port="lut6.in" out_port="lut6.out">
|
||||||
|
261e-12
|
||||||
|
261e-12
|
||||||
|
261e-12
|
||||||
|
261e-12
|
||||||
|
261e-12
|
||||||
|
261e-12
|
||||||
|
</delay_matrix>
|
||||||
|
</pb_type>
|
||||||
|
<!-- Define flip-flop -->
|
||||||
|
<pb_type name="ff" blif_model=".latch" num_pb="1" class="flipflop">
|
||||||
|
<input name="D" num_pins="1" port_class="D"/>
|
||||||
|
<output name="Q" num_pins="1" port_class="Q"/>
|
||||||
|
<clock name="clk" num_pins="1" port_class="clock"/>
|
||||||
|
<T_setup value="66e-12" port="ff.D" clock="clk"/>
|
||||||
|
<T_clock_to_Q max="124e-12" port="ff.Q" clock="clk"/>
|
||||||
|
</pb_type>
|
||||||
|
<interconnect>
|
||||||
|
<direct name="direct1" input="ble6.in" output="lut6[0:0].in"/>
|
||||||
|
<direct name="direct2" input="lut6.out" output="ff.D">
|
||||||
|
<!-- Advanced user option that tells CAD tool to find LUT+FF pairs in netlist -->
|
||||||
|
<pack_pattern name="ble6" in_port="lut6.out" out_port="ff.D"/>
|
||||||
|
</direct>
|
||||||
|
<direct name="direct3" input="ble6.clk" output="ff.clk"/>
|
||||||
|
<mux name="mux1" input="ff.Q lut6.out" output="ble6.out">
|
||||||
|
<!-- LUT to output is faster than FF to output on a Stratix IV -->
|
||||||
|
<delay_constant max="25e-12" in_port="lut6.out" out_port="ble6.out"/>
|
||||||
|
<delay_constant max="45e-12" in_port="ff.Q" out_port="ble6.out"/>
|
||||||
|
</mux>
|
||||||
|
</interconnect>
|
||||||
|
</pb_type>
|
||||||
|
<interconnect>
|
||||||
|
<direct name="direct1" input="fle.in" output="ble6.in"/>
|
||||||
|
<direct name="direct2" input="ble6.out" output="fle.out[0:0]"/>
|
||||||
|
<direct name="direct3" input="fle.clk" output="ble6.clk"/>
|
||||||
|
</interconnect>
|
||||||
|
</mode>
|
||||||
|
<!-- 6-LUT mode definition end -->
|
||||||
|
</pb_type>
|
||||||
|
<interconnect>
|
||||||
|
<!-- We use a full crossbar to get logical equivalence at inputs of CLB
|
||||||
|
The delays below come from Stratix IV. the delay through a connection block
|
||||||
|
input mux + the crossbar in Stratix IV is 167 ps. We already have a 72 ps
|
||||||
|
delay on the connection block input mux (modeled by Ian Kuon), so the remaining
|
||||||
|
delay within the crossbar is 95 ps.
|
||||||
|
The delays of cluster feedbacks in Stratix IV is 100 ps, when driven by a LUT.
|
||||||
|
Since all our outputs LUT outputs go to a BLE output, and have a delay of
|
||||||
|
25 ps to do so, we subtract 25 ps from the 100 ps delay of a feedback
|
||||||
|
to get the part that should be marked on the crossbar. -->
|
||||||
|
<complete name="crossbar" input="clb.I fle[9:0].out" output="fle[9:0].in">
|
||||||
|
<delay_constant max="95e-12" in_port="clb.I" out_port="fle[9:0].in"/>
|
||||||
|
<delay_constant max="75e-12" in_port="fle[9:0].out" out_port="fle[9:0].in"/>
|
||||||
|
</complete>
|
||||||
|
<complete name="clks" input="clb.clk" output="fle[9:0].clk">
|
||||||
|
</complete>
|
||||||
|
<!-- This way of specifying direct connection to clb outputs is important because this architecture uses automatic spreading of opins.
|
||||||
|
By grouping to output pins in this fashion, if a logic block is completely filled by 6-LUTs,
|
||||||
|
then the outputs those 6-LUTs take get evenly distributed across all four sides of the CLB instead of clumped on two sides (which is what happens with a more
|
||||||
|
naive specification).
|
||||||
|
-->
|
||||||
|
<direct name="clbouts1" input="fle[9:0].out[0:0]" output="clb.O[9:0]"/>
|
||||||
|
<direct name="clbouts2" input="fle[9:0].out[1:1]" output="clb.O[19:10]"/>
|
||||||
|
</interconnect>
|
||||||
|
<!-- Every input pin is driven by 15% of the tracks in a channel, every output pin is driven by 10% of the tracks in a channel -->
|
||||||
|
<!-- Place this general purpose logic block in any unspecified column -->
|
||||||
|
</pb_type>
|
||||||
|
<!-- Define general purpose logic block (CLB) ends -->
|
||||||
|
</complexblocklist>
|
||||||
|
<power>
|
||||||
|
<local_interconnect C_wire="2.5e-10"/>
|
||||||
|
<mux_transistor_size mux_transistor_size="3"/>
|
||||||
|
<FF_size FF_size="4"/>
|
||||||
|
<LUT_transistor_size LUT_transistor_size="4"/>
|
||||||
|
</power>
|
||||||
|
<clocks>
|
||||||
|
<clock buffer_size="auto" C_wire="2.5e-10"/>
|
||||||
|
</clocks>
|
||||||
|
</architecture>
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue