Merge pull request #174 from lnis-uofu/dev

Support Design Constraints for Repack
This commit is contained in:
tangxifan 2021-01-17 17:41:53 -07:00 committed by GitHub
commit 17c49711d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 786 additions and 19 deletions

View File

@ -12,3 +12,5 @@ FPGA-Bitstream can generate two types of bitstreams:
generic_bitstream
fabric_dependent_bitstream
repack_design_constraints

View File

@ -0,0 +1,29 @@
.. _fpga_bitstream_repack_design_constraints:
Repack Design Constraints
-------------------------
An example of design constraints is shown as follows.
.. code-block:: xml
<repack_design_constraints>
<pin_constraint pb_type="clb" pin="clk[0]" net="clk0"/>
<pin_constraint pb_type="clb" pin="clk[1]" net="clk1"/>
<pin_constraint pb_type="clb" pin="clk[2]" net="OPEN"/>
<pin_constraint pb_type="clb" pin="clk[3]" net="OPEN"/>
</repack_design_constraints>
.. option:: pb_type="<string>"
The pb_type name to be constrained, which should be consistent with VPR's architecture description.
.. option:: pin="<string>"
The pin name of the ``pb_type`` to be constrained, which should be consistent with VPR's architecture description.
.. option:: net="<string>"
The net name of the pin to be mapped, which should be consistent with net definition in your ``.blif`` file. The reserved word ``OPEN`` means that no net should be mapped to a given pin. Please ensure that it is not conflicted with any net names in your ``.blif`` file.
.. warning:: Design constraints is a feature for power-users. It may cause repack to fail. It is users's responsibility to ensure proper design constraints

View File

@ -6,11 +6,28 @@ FPGA-Bitstream
repack
~~~~~~
Repack the netlist to physical pbs
Repack the netlist to physical pbs
Repack is an essential procedure before building a bitstream, which aims to packing each programmable blocks by considering **only** the physical modes.
Repack's functionality are in the following aspects:
.. note:: This must be done before bitstream generator and testbench generation. Strongly recommend it is done after all the fix-up have been applied
- It annotates the net mapping results from operating modes (considered by VPR) to the physical modes (considered by OpenFPGA)
- It re-routes all the nets by considering the programmable interconnects in physical modes **only**.
.. note:: This must be done before bitstream generator and testbench generation. Strongly recommend it is done after all the fix-up have been applied
.. option:: --design_constraints
Apply design constraints from an external file.
Normally, repack takes the net mapping from VPR packing and routing results.
Alternatively, repack can accept the design constraints, in particular, net remapping, from an XML-based design constraint description.
See details in :ref:`fpga_bitstream_repack_design_constraints`.
.. warning:: Design constraints are designed to help repacker to identify which clock net to be mapped to which pin, so that multi-clock benchmarks can be correctly implemented, in the case that VPR may not have sufficient vision on clock net mapping. **Try not to use design constraints to remap any other types of nets!!!**
- ``--verbose`` Show verbose log
.. option:: --verbose
Show verbose log
build_architecture_bitstream
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -4,4 +4,5 @@ add_subdirectory(libopenfpgashell)
add_subdirectory(libarchopenfpga)
add_subdirectory(libopenfpgautil)
add_subdirectory(libfabrickey)
add_subdirectory(librepackdc)
add_subdirectory(libfpgabitstream)

View File

@ -0,0 +1,35 @@
cmake_minimum_required(VERSION 3.9)
project("librepackdc")
file(GLOB_RECURSE EXEC_SOURCES test/*.cpp)
file(GLOB_RECURSE LIB_SOURCES src/*.cpp)
file(GLOB_RECURSE LIB_HEADERS src/*.h)
files_to_dirs(LIB_HEADERS LIB_INCLUDE_DIRS)
#Remove test executable from library
list(REMOVE_ITEM LIB_SOURCES ${EXEC_SOURCES})
#Create the library
add_library(librepackdc STATIC
${LIB_HEADERS}
${LIB_SOURCES})
target_include_directories(librepackdc PUBLIC ${LIB_INCLUDE_DIRS})
set_target_properties(librepackdc PROPERTIES PREFIX "") #Avoid extra 'lib' prefix
#Specify link-time dependancies
target_link_libraries(librepackdc
libopenfpgautil
libarchopenfpga
libvtrutil
libpugixml
libpugiutil)
#Create the test executable
foreach(testsourcefile ${EXEC_SOURCES})
# Use a simple string replace, to cut off .cpp.
get_filename_component(testname ${testsourcefile} NAME_WE)
add_executable(${testname} ${testsourcefile})
# Make sure the library is linked to each test executable
target_link_libraries(${testname} librepackdc)
endforeach(testsourcefile ${EXEC_SOURCES})

View File

@ -0,0 +1,7 @@
<repack_design_constraints>
<pin_constraint pb_type="clb" pin="clk[0]" net="clk0"/>
<pin_constraint pb_type="clb" pin="clk[1]" net="clk1"/>
<pin_constraint pb_type="clb" pin="clk[2]" net="OPEN"/>
<pin_constraint pb_type="clb" pin="clk[3]" net="OPEN"/>
</repack_design_constraints>

View File

@ -0,0 +1,89 @@
/********************************************************************
* This file includes the top-level function of this library
* which reads an XML of a fabric key to the associated
* data structures
*******************************************************************/
#include <string>
/* Headers from pugi XML library */
#include "pugixml.hpp"
#include "pugixml_util.hpp"
/* Headers from vtr util library */
#include "vtr_assert.h"
#include "vtr_time.h"
/* Headers from libopenfpga util library */
#include "openfpga_port_parser.h"
/* Headers from libarchfpga */
#include "arch_error.h"
#include "read_xml_util.h"
#include "read_xml_repack_design_constraints.h"
/********************************************************************
* Parse XML codes of a <key> to an object of FabricKey
*******************************************************************/
static
void read_xml_pin_constraint(pugi::xml_node& xml_pin_constraint,
const pugiutil::loc_data& loc_data,
RepackDesignConstraints& repack_design_constraints) {
/* Create a new design constraint in the storage */
RepackDesignConstraintId design_constraint_id = repack_design_constraints.create_design_constraint(RepackDesignConstraints::PIN_ASSIGNMENT);
if (false == repack_design_constraints.valid_design_constraint_id(design_constraint_id)) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_pin_constraint),
"Fail to create design constraint!\n");
}
repack_design_constraints.set_pb_type(design_constraint_id,
get_attribute(xml_pin_constraint, "pb_type", loc_data).as_string());
openfpga::PortParser port_parser(get_attribute(xml_pin_constraint, "pin", loc_data).as_string());
repack_design_constraints.set_pin(design_constraint_id,
port_parser.port());
repack_design_constraints.set_net(design_constraint_id,
get_attribute(xml_pin_constraint, "net", loc_data).as_string());
}
/********************************************************************
* Parse XML codes about <repack_design_constraints> to an object of RepackDesignConstraints
*******************************************************************/
RepackDesignConstraints read_xml_repack_design_constraints(const char* design_constraint_fname) {
vtr::ScopedStartFinishTimer timer("Read Repack Design Constraints");
RepackDesignConstraints repack_design_constraints;
/* Parse the file */
pugi::xml_document doc;
pugiutil::loc_data loc_data;
try {
loc_data = pugiutil::load_xml(doc, design_constraint_fname);
pugi::xml_node xml_root = get_single_child(doc, "repack_design_constraints", loc_data);
size_t num_design_constraints = std::distance(xml_root.children().begin(), xml_root.children().end());
/* Reserve memory space for the region */
repack_design_constraints.reserve_design_constraints(num_design_constraints);
for (pugi::xml_node xml_design_constraint : xml_root.children()) {
/* Error out if the XML child has an invalid name! */
if (xml_design_constraint.name() != std::string("pin_constraint")) {
bad_tag(xml_design_constraint, loc_data, xml_root, {"pin_constraint"});
}
read_xml_pin_constraint(xml_design_constraint, loc_data, repack_design_constraints);
}
} catch (pugiutil::XmlError& e) {
archfpga_throw(design_constraint_fname, e.line(),
"%s", e.what());
}
return repack_design_constraints;
}

View File

@ -0,0 +1,16 @@
#ifndef READ_XML_REPACK_DESIGN_CONSTRAINTS_H
#define READ_XML_REPACK_DESIGN_CONSTRAINTS_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include "pugixml_util.hpp"
#include "pugixml.hpp"
#include "repack_design_constraints.h"
/********************************************************************
* Function declaration
*******************************************************************/
RepackDesignConstraints read_xml_repack_design_constraints(const char* design_constraint_fname);
#endif

View File

@ -0,0 +1,108 @@
#include <algorithm>
#include "vtr_assert.h"
#include "vtr_log.h"
#include "repack_design_constraints.h"
/************************************************************************
* Member functions for class RepackDesignConstraints
***********************************************************************/
/************************************************************************
* Constructors
***********************************************************************/
RepackDesignConstraints::RepackDesignConstraints() {
return;
}
/************************************************************************
* Public Accessors : aggregates
***********************************************************************/
RepackDesignConstraints::repack_design_constraint_range RepackDesignConstraints::design_constraints() const {
return vtr::make_range(repack_design_constraint_ids_.begin(), repack_design_constraint_ids_.end());
}
/************************************************************************
* Public Accessors : Basic data query
***********************************************************************/
RepackDesignConstraints::e_design_constraint_type RepackDesignConstraints::type(const RepackDesignConstraintId& repack_design_constraint_id) const {
/* validate the design_constraint_id */
VTR_ASSERT(valid_design_constraint_id(repack_design_constraint_id));
return repack_design_constraint_types_[repack_design_constraint_id];
}
std::string RepackDesignConstraints::pb_type(const RepackDesignConstraintId& repack_design_constraint_id) const {
/* validate the design_constraint_id */
VTR_ASSERT(valid_design_constraint_id(repack_design_constraint_id));
return repack_design_constraint_pb_types_[repack_design_constraint_id];
}
openfpga::BasicPort RepackDesignConstraints::pin(const RepackDesignConstraintId& repack_design_constraint_id) const {
/* validate the design_constraint_id */
VTR_ASSERT(valid_design_constraint_id(repack_design_constraint_id));
return repack_design_constraint_pins_[repack_design_constraint_id];
}
std::string RepackDesignConstraints::net(const RepackDesignConstraintId& repack_design_constraint_id) const {
/* validate the design_constraint_id */
VTR_ASSERT(valid_design_constraint_id(repack_design_constraint_id));
return repack_design_constraint_nets_[repack_design_constraint_id];
}
bool RepackDesignConstraints::empty() const {
return 0 == repack_design_constraint_ids_.size();
}
/************************************************************************
* Public Mutators
***********************************************************************/
void RepackDesignConstraints::reserve_design_constraints(const size_t& num_design_constraints) {
repack_design_constraint_ids_.reserve(num_design_constraints);
repack_design_constraint_types_.reserve(num_design_constraints);
repack_design_constraint_pb_types_.reserve(num_design_constraints);
repack_design_constraint_pins_.reserve(num_design_constraints);
repack_design_constraint_nets_.reserve(num_design_constraints);
}
RepackDesignConstraintId RepackDesignConstraints::create_design_constraint(const RepackDesignConstraints::e_design_constraint_type& repack_design_constraint_type) {
/* Create a new id */
RepackDesignConstraintId repack_design_constraint_id = RepackDesignConstraintId(repack_design_constraint_ids_.size());
repack_design_constraint_ids_.push_back(repack_design_constraint_id);
repack_design_constraint_types_.push_back(repack_design_constraint_type);
repack_design_constraint_pb_types_.emplace_back();
repack_design_constraint_pins_.emplace_back();
repack_design_constraint_nets_.emplace_back();
return repack_design_constraint_id;
}
void RepackDesignConstraints::set_pb_type(const RepackDesignConstraintId& repack_design_constraint_id,
const std::string& pb_type) {
/* validate the design_constraint_id */
VTR_ASSERT(valid_design_constraint_id(repack_design_constraint_id));
repack_design_constraint_pb_types_[repack_design_constraint_id] = pb_type;
}
void RepackDesignConstraints::set_pin(const RepackDesignConstraintId& repack_design_constraint_id,
const openfpga::BasicPort& pin) {
/* validate the design_constraint_id */
VTR_ASSERT(valid_design_constraint_id(repack_design_constraint_id));
repack_design_constraint_pins_[repack_design_constraint_id] = pin;
}
void RepackDesignConstraints::set_net(const RepackDesignConstraintId& repack_design_constraint_id,
const std::string& net) {
/* validate the design_constraint_id */
VTR_ASSERT(valid_design_constraint_id(repack_design_constraint_id));
repack_design_constraint_nets_[repack_design_constraint_id] = net;
}
/************************************************************************
* Internal invalidators/validators
***********************************************************************/
/* Validators */
bool RepackDesignConstraints::valid_design_constraint_id(const RepackDesignConstraintId& design_constraint_id) const {
return ( size_t(design_constraint_id) < repack_design_constraint_ids_.size() ) && ( design_constraint_id == repack_design_constraint_ids_[design_constraint_id] );
}

View File

@ -0,0 +1,106 @@
#ifndef REPACK_DESIGN_CONSTRAINTS_H
#define REPACK_DESIGN_CONSTRAINTS_H
/********************************************************************
* This file include the declaration of repack design constraints
*******************************************************************/
#include <string>
#include <map>
#include <array>
/* Headers from vtrutil library */
#include "vtr_vector.h"
#include "vtr_geometry.h"
/* Headers from openfpgautil library */
#include "openfpga_port.h"
#include "repack_design_constraints_fwd.h"
/* Constants */
constexpr char* REPACK_DESIGN_CONSTRAINT_OPEN_NET = "OPEN";
/********************************************************************
* A data structure to describe the design constraints for repacking tools
* This data structure may include a number of design constraints
* each of which may constrain:
* - pin assignment, for instance, force a net to be mapped to specific pin
*
* Typical usage:
* --------------
* // Create an object of design constraints
* RepackDesignConstraints repack_design_constraints;
* // Add a pin assignment
* RepackDesignConstraintId repack_dc_id = fabric_key.create_design_constraint(RepackDesignConstraints::PIN_ASSIGNMENT);
*
*******************************************************************/
class RepackDesignConstraints {
public: /* Type of design constraints */
enum e_design_constraint_type {
PIN_ASSIGNMENT,
NUM_DESIGN_CONSTRAINT_TYPES
};
public: /* Types */
typedef vtr::vector<RepackDesignConstraintId, RepackDesignConstraintId>::const_iterator repack_design_constraint_iterator;
/* Create range */
typedef vtr::Range<repack_design_constraint_iterator> repack_design_constraint_range;
public: /* Constructors */
RepackDesignConstraints();
public: /* Accessors: aggregates */
repack_design_constraint_range design_constraints() const;
public: /* Public Accessors: Basic data query */
/* Get the type of constraint */
e_design_constraint_type type(const RepackDesignConstraintId& repack_design_constraint_id) const;
/* Get the pb_type name to be constrained */
std::string pb_type(const RepackDesignConstraintId& repack_design_constraint_id) const;
/* Get the pin to be constrained */
openfpga::BasicPort pin(const RepackDesignConstraintId& repack_design_constraint_id) const;
/* Get the net to be constrained */
std::string net(const RepackDesignConstraintId& repack_design_constraint_id) const;
/* Check if there are any design constraints */
bool empty() const;
public: /* Public Mutators */
/* Reserve a number of design constraints to be memory efficent */
void reserve_design_constraints(const size_t& num_design_constraints);
/* Add a design constraint to storage */
RepackDesignConstraintId create_design_constraint(const e_design_constraint_type& repack_design_constraint_type);
/* Set the pb_type name to be constrained */
void set_pb_type(const RepackDesignConstraintId& repack_design_constraint_id,
const std::string& pb_type);
/* Set the pin to be constrained */
void set_pin(const RepackDesignConstraintId& repack_design_constraint_id,
const openfpga::BasicPort& pin);
/* Set the net to be constrained */
void set_net(const RepackDesignConstraintId& repack_design_constraint_id,
const std::string& net);
public: /* Public invalidators/validators */
bool valid_design_constraint_id(const RepackDesignConstraintId& repack_design_constraint_id) const;
private: /* Internal data */
/* Unique ids for each design constraint */
vtr::vector<RepackDesignConstraintId, RepackDesignConstraintId> repack_design_constraint_ids_;
/* Type for each design constraint */
vtr::vector<RepackDesignConstraintId, e_design_constraint_type> repack_design_constraint_types_;
/* Tiles to constraint */
vtr::vector<RepackDesignConstraintId, std::string> repack_design_constraint_pb_types_;
/* Pins to constraint */
vtr::vector<RepackDesignConstraintId, openfpga::BasicPort> repack_design_constraint_pins_;
/* Nets to constraint */
vtr::vector<RepackDesignConstraintId, std::string> repack_design_constraint_nets_;
};
#endif

View File

@ -0,0 +1,22 @@
/************************************************************************
* A header file for RepackDesignConstraints class, including critical data declaration
* Please include this file only for using any TechnologyLibrary data structure
* Refer to repack_design_constraints.h for more details
***********************************************************************/
/************************************************************************
* Create strong id for RepackDesignConstraints to avoid illegal type casting
***********************************************************************/
#ifndef REPACK_DESIGN_CONSTRAINTS_FWD_H
#define REPACK_DESIGN_CONSTRAINTS_FWD_H
#include "vtr_strong_id.h"
struct repack_design_constraint_id_tag;
typedef vtr::StrongId<repack_design_constraint_id_tag> RepackDesignConstraintId;
/* Short declaration of class */
class RepackDesignConstraints;
#endif

View File

@ -0,0 +1,97 @@
/********************************************************************
* This file includes functions that outputs a repack design constraint object to XML format
*******************************************************************/
/* Headers from system goes first */
#include <string>
#include <algorithm>
/* Headers from vtr util library */
#include "vtr_assert.h"
#include "vtr_log.h"
#include "vtr_time.h"
/* Headers from openfpga util library */
#include "openfpga_digest.h"
/* Headers from arch openfpga library */
#include "write_xml_utils.h"
/* Headers from fabrickey library */
#include "write_xml_repack_design_constraints.h"
/********************************************************************
* A writer to output a pin constraint to XML format
*
* Return 0 if successful
* Return 1 if there are more serious bugs in the architecture
* Return 2 if fail when creating files
*******************************************************************/
static
int write_xml_pin_constraint(std::fstream& fp,
const RepackDesignConstraints& repack_design_constraints,
const RepackDesignConstraintId& design_constraint) {
/* Validate the file stream */
if (false == openfpga::valid_file_stream(fp)) {
return 2;
}
openfpga::write_tab_to_file(fp, 1);
fp << "<pin_constraint";
if (false == repack_design_constraints.valid_design_constraint_id(design_constraint)) {
return 1;
}
write_xml_attribute(fp, "pb_type", repack_design_constraints.pb_type(design_constraint).c_str());
write_xml_attribute(fp, "pin", generate_xml_port_name(repack_design_constraints.pin(design_constraint)).c_str());
write_xml_attribute(fp, "net", repack_design_constraints.net(design_constraint).c_str());
fp << "/>" << "\n";
return 0;
}
/********************************************************************
* A writer to output a repack design constraint object to XML format
*
* Return 0 if successful
* Return 1 if there are more serious bugs in the architecture
* Return 2 if fail when creating files
*******************************************************************/
int write_xml_repack_design_constraints(const char* fname,
const RepackDesignConstraints& repack_design_constraints) {
vtr::ScopedStartFinishTimer timer("Write Repack Design Constraints");
/* Create a file handler */
std::fstream fp;
/* Open the file stream */
fp.open(std::string(fname), std::fstream::out | std::fstream::trunc);
/* Validate the file stream */
openfpga::check_file_stream(fname, fp);
/* Write the root node */
fp << "<repack_design_constraints>" << "\n";
int err_code = 0;
/* Write region by region */
for (const RepackDesignConstraintId& design_constraint : repack_design_constraints.design_constraints()) {
/* Write constraint by constraint */
if (RepackDesignConstraints::PIN_ASSIGNMENT == repack_design_constraints.type(design_constraint)) {
err_code = write_xml_pin_constraint(fp, repack_design_constraints, design_constraint);
if (0 != err_code) {
return err_code;
}
}
}
/* Finish writing the root node */
fp << "</repack_design_constraints>" << "\n";
/* Close the file stream */
fp.close();
return err_code;
}

View File

@ -0,0 +1,16 @@
#ifndef WRITE_XML_REPACK_DESIGN_CONSTRAINTS_H
#define WRITE_XML_REPACK_DESIGN_CONSTRAINTS_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <fstream>
#include "repack_design_constraints.h"
/********************************************************************
* Function declaration
*******************************************************************/
int write_xml_repack_design_constraints(const char* fname,
const RepackDesignConstraints& repack_design_constraints);
#endif

View File

@ -0,0 +1,34 @@
/********************************************************************
* Unit test functions to validate the correctness of
* 1. parser of data structures
* 2. writer of data structures
*******************************************************************/
/* Headers from vtrutils */
#include "vtr_assert.h"
#include "vtr_log.h"
/* Headers from fabric key */
#include "read_xml_repack_design_constraints.h"
#include "write_xml_repack_design_constraints.h"
int main(int argc, const char** argv) {
/* Ensure we have only one or two argument */
VTR_ASSERT((2 == argc) || (3 == argc));
/* Parse the fabric key from an XML file */
RepackDesignConstraints design_constraints = read_xml_repack_design_constraints(argv[1]);
VTR_LOG("Read the repack design constraints from an XML file: %s.\n",
argv[1]);
/* Output the circuit library to an XML file
* This is optional only used when there is a second argument
*/
if (3 <= argc) {
write_xml_repack_design_constraints(argv[2], design_constraints);
VTR_LOG("Echo the repack design constraints to an XML file: %s.\n",
argv[2]);
}
}

View File

@ -23,6 +23,7 @@ target_link_libraries(libopenfpga
libopenfpgashell
libopenfpgautil
libfabrickey
librepackdc
libfpgabitstream
libini
libvtrutil

View File

@ -21,6 +21,9 @@ ShellCommandId add_openfpga_repack_command(openfpga::Shell<OpenfpgaContext>& she
const ShellCommandClassId& cmd_class_id,
const std::vector<ShellCommandId>& dependent_cmds) {
Command shell_cmd("repack");
/* Add an option '--design_constraints' */
CommandOptionId opt_design_constraints = shell_cmd.add_option("design_constraints", false, "file path to the design constraints");
shell_cmd.set_option_require_value(opt_design_constraints, openfpga::OPT_STRING);
/* Add an option '--verbose' */
shell_cmd.add_option("verbose", false, "Enable verbose output");

View File

@ -8,10 +8,15 @@
/* Headers from openfpgashell library */
#include "command_exit_codes.h"
/* Headers from librepackdc library */
#include "repack_design_constraints.h"
#include "read_xml_repack_design_constraints.h"
#include "build_physical_truth_table.h"
#include "repack.h"
#include "openfpga_repack.h"
/* Include global variables of VPR */
#include "globals.h"
@ -24,13 +29,23 @@ namespace openfpga {
int repack(OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context) {
CommandOptionId opt_design_constraints = cmd.option("design_constraints");
CommandOptionId opt_verbose = cmd.option("verbose");
/* Load design constraints from file */
RepackDesignConstraints repack_design_constraints;
if (true == cmd_context.option_enable(cmd, opt_design_constraints)) {
std::string dc_fname = cmd_context.option_value(cmd, opt_design_constraints);
VTR_ASSERT(false == dc_fname.empty());
repack_design_constraints = read_xml_repack_design_constraints(dc_fname.c_str());
}
pack_physical_pbs(g_vpr_ctx.device(),
g_vpr_ctx.atom(),
g_vpr_ctx.clustering(),
openfpga_ctx.mutable_vpr_device_annotation(),
openfpga_ctx.mutable_vpr_clustering_annotation(),
repack_design_constraints,
cmd_context.option_enable(cmd, opt_verbose));
build_physical_lut_truth_tables(openfpga_ctx.mutable_vpr_clustering_annotation(),

View File

@ -240,9 +240,9 @@ std::vector<t_pb_graph_pin*> find_routed_pb_graph_pins_atom_net(const t_pb* pb,
* Note: this is ONLY applicable to the pb_pin of top-level pb_graph_node
***************************************************************************************/
static
int find_pb_route_remapped_source_pb_pin(const t_pb* pb,
const t_pb_graph_pin* source_pb_pin,
const AtomNetId& atom_net_id) {
std::vector<int> find_pb_route_remapped_source_pb_pin(const t_pb* pb,
const t_pb_graph_pin* source_pb_pin,
const AtomNetId& atom_net_id) {
VTR_ASSERT(true == source_pb_pin->parent_node->is_root());
std::vector<int> pb_route_indices;
@ -268,9 +268,7 @@ int find_pb_route_remapped_source_pb_pin(const t_pb* pb,
}
}
VTR_ASSERT(1 == pb_route_indices.size());
return pb_route_indices[0];
return pb_route_indices;
}
/***************************************************************************************
@ -339,6 +337,7 @@ void add_lb_router_nets(LbRouter& lb_router,
const VprDeviceAnnotation& device_annotation,
const ClusteringContext& clustering_ctx,
const VprClusteringAnnotation& clustering_annotation,
const RepackDesignConstraints& design_constraints,
const ClusterBlockId& block_id,
const bool& verbose) {
size_t net_counter = 0;
@ -409,31 +408,101 @@ void add_lb_router_nets(LbRouter& lb_router,
/* Find the net mapped to this pin in clustering results*/
AtomNetId atom_net_id = pb_pin_mapped_nets[source_pb_pin];
/* Bypass unmapped pins */
if (AtomNetId::INVALID() == atom_net_id) {
/* Check if the net information is constrained or not */
std::string constrained_net_name;
for (const RepackDesignConstraintId& design_constraint : design_constraints.design_constraints()) {
/* All the pin must have only 1 bit */
VTR_ASSERT_SAFE(1 == design_constraints.pin(design_constraint).get_width());
/* If found a constraint, record the net name */
if ( (std::string(lb_type->pb_type->name) == design_constraints.pb_type(design_constraint))
&& (std::string(source_pb_pin->port->name) == design_constraints.pin(design_constraint).get_name())
&& (size_t(source_pb_pin->pin_number) == design_constraints.pin(design_constraint).get_lsb())) {
constrained_net_name = design_constraints.net(design_constraint);
break;
}
}
/* Find the constrained net mapped to this pin in clustering results */
AtomNetId constrained_atom_net_id = AtomNetId::INVALID();
/* If the pin is constrained, we need to
* - if this is an open net, for invalid net then
* - if this is valid net name, find the net id from atom_netlist
* and overwrite the atom net id to mapped
*/
if (!constrained_net_name.empty()) {
if (std::string(REPACK_DESIGN_CONSTRAINT_OPEN_NET) != constrained_net_name) {
constrained_atom_net_id = atom_ctx.nlist.find_net(constrained_net_name);
if (false == atom_ctx.nlist.valid_net_id(constrained_atom_net_id)) {
VTR_LOG_WARN("Invalid net '%s' to be constrained! Will drop the constraint in repacking\n",
constrained_net_name.c_str());
}
}
} else {
VTR_ASSERT_SAFE(constrained_net_name.empty());
constrained_atom_net_id = atom_net_id;
}
/* Bypass unmapped pins. There are 4 conditions to consider
* +======+=================+=============+================================+
* | Case | Packing results | Constraints | Decision to route |
* +======+=================+=============+================================+
* | 0 | Unmapped | Unmapped | No routing needed |
* +======+=================+=============+================================+
* | 1 | Unmapped | Mapped | Find the pb source pin that |
* | | | | drives the constrained net and |
* | | | | use it to find sink nodes |
* +======+=================+=============+================================+
* | 2 | Mapped | Unmapped | No routing needed |
* +======+=================+=============+================================+
* | 3 | Mapped | Mapped | Route with the constrained net |
* | | | | but use the packing net id to |
* | | | | find the sink nodes to route |
* +======+=================+=============+================================+
*/
if (AtomNetId::INVALID() == constrained_atom_net_id) {
continue;
}
/* If we have a net to route, it must be the constrained net */
AtomNetId atom_net_id_to_route = constrained_atom_net_id;
/* The outputs of pb_graph_node is INTERMEDIATE node in the routing resource graph,
* they are all connected to a common source node
*/
LbRRNodeId source_lb_rr_node = lb_rr_graph.find_node(LB_INTERMEDIATE, source_pb_pin);
VTR_ASSERT(true == lb_rr_graph.valid_node_id(source_lb_rr_node));
int pb_route_index = find_pb_route_remapped_source_pb_pin(pb, source_pb_pin, atom_net_id);
/* As the pin remapping is allowed during routing, we should
* - Find the routing traces from packing results which is mapped to the net
* from the same port (as remapping is allowed for pins in the same port only)
* - Find the source pb_graph_pin that drives the routing traces during packing
* - Then we can find the sink nodes
*/
std::vector<int> pb_route_indices = find_pb_route_remapped_source_pb_pin(pb, source_pb_pin, atom_net_id_to_route);
/* It could happen that the constrained net is NOT used in this clb, we just skip it for routing
* For example, a clkB net is never mapped to any ports in the pb that is clocked by clkA net
* */
int pb_route_index;
if (0 == pb_route_indices.size()) {
continue;
} else {
VTR_ASSERT(1 == pb_route_indices.size());
pb_route_index = pb_route_indices[0];
}
t_pb_graph_pin* packing_source_pb_pin = get_pb_graph_node_pin_from_block_pin(block_id, pb_route_index);
VTR_ASSERT(nullptr != packing_source_pb_pin);
/* Find all the sink pins in the pb_route, we walk through the input pins and find the pin */
std::vector<t_pb_graph_pin*> sink_pb_graph_pins = find_routed_pb_graph_pins_atom_net(pb, source_pb_pin, packing_source_pb_pin, atom_net_id, device_annotation, pb_pin_mapped_nets, pb_graph_pin_lookup_from_index);
std::vector<t_pb_graph_pin*> sink_pb_graph_pins = find_routed_pb_graph_pins_atom_net(pb, source_pb_pin, packing_source_pb_pin, atom_net_id_to_route, device_annotation, pb_pin_mapped_nets, pb_graph_pin_lookup_from_index);
std::vector<LbRRNodeId> sink_lb_rr_nodes = find_lb_net_physical_sink_lb_rr_nodes(lb_rr_graph, sink_pb_graph_pins, device_annotation);
VTR_ASSERT(sink_lb_rr_nodes.size() == sink_pb_graph_pins.size());
/* Printf for debugging only, may be enabled if verbose is enabled
*/
/* Output verbose messages for debugging only */
VTR_LOGV(verbose,
"Pb route for Net %s:\n",
atom_ctx.nlist.net_name(atom_net_id).c_str());
atom_ctx.nlist.net_name(atom_net_id_to_route).c_str());
VTR_LOGV(verbose,
"Source node:\n\t%s -> %s\n",
source_pb_pin->to_string().c_str(),
@ -449,7 +518,7 @@ void add_lb_router_nets(LbRouter& lb_router,
add_lb_router_net_to_route(lb_router, lb_rr_graph,
std::vector<LbRRNodeId>(1, source_lb_rr_node),
sink_lb_rr_nodes,
atom_ctx, atom_net_id);
atom_ctx, atom_net_id_to_route);
net_counter++;
}
@ -542,6 +611,7 @@ void repack_cluster(const AtomContext& atom_ctx,
const ClusteringContext& clustering_ctx,
const VprDeviceAnnotation& device_annotation,
VprClusteringAnnotation& clustering_annotation,
const RepackDesignConstraints& design_constraints,
const ClusterBlockId& block_id,
const bool& verbose) {
/* Get the pb graph that current clustered block is mapped to */
@ -563,6 +633,7 @@ void repack_cluster(const AtomContext& atom_ctx,
/* Add nets to be routed with source and terminals */
add_lb_router_nets(lb_router, lb_type, lb_rr_graph, atom_ctx, device_annotation,
clustering_ctx, const_cast<const VprClusteringAnnotation&>(clustering_annotation),
design_constraints,
block_id, verbose);
/* Initialize the modes to expand routing trees with the physical modes in device annotation
@ -607,12 +678,15 @@ void repack_clusters(const AtomContext& atom_ctx,
const ClusteringContext& clustering_ctx,
const VprDeviceAnnotation& device_annotation,
VprClusteringAnnotation& clustering_annotation,
const RepackDesignConstraints& design_constraints,
const bool& verbose) {
vtr::ScopedStartFinishTimer timer("Repack clustered blocks to physical implementation of logical tile");
for (auto blk_id : clustering_ctx.clb_nlist.blocks()) {
repack_cluster(atom_ctx, clustering_ctx,
device_annotation, clustering_annotation,
device_annotation,
clustering_annotation,
design_constraints,
blk_id, verbose);
}
}
@ -632,6 +706,7 @@ void pack_physical_pbs(const DeviceContext& device_ctx,
const ClusteringContext& clustering_ctx,
VprDeviceAnnotation& device_annotation,
VprClusteringAnnotation& clustering_annotation,
const RepackDesignConstraints& design_constraints,
const bool& verbose) {
/* build the routing resource graph for each logical tile */
@ -642,6 +717,7 @@ void pack_physical_pbs(const DeviceContext& device_ctx,
/* Call the LbRouter to re-pack each clustered block to physical implementation */
repack_clusters(atom_ctx, clustering_ctx,
const_cast<const VprDeviceAnnotation&>(device_annotation), clustering_annotation,
design_constraints,
verbose);
}

View File

@ -8,6 +8,7 @@
#include "vpr_device_annotation.h"
#include "vpr_clustering_annotation.h"
#include "vpr_routing_annotation.h"
#include "repack_design_constraints.h"
/********************************************************************
* Function declaration
@ -21,6 +22,7 @@ void pack_physical_pbs(const DeviceContext& device_ctx,
const ClusteringContext& clustering_ctx,
VprDeviceAnnotation& device_annotation,
VprClusteringAnnotation& clustering_annotation,
const RepackDesignConstraints& design_constraints,
const bool& verbose);
} /* end namespace openfpga */

View File

@ -0,0 +1,76 @@
# Run VPR for the 'and' design
# When the global clock is defined as a port of a tile, clock routing in VPR should be skipped
# This is due to the Fc_in of clock port is set to 0 for global wiring
#--write_rr_graph example_rr_graph.xml
vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF}
# Read OpenFPGA architecture definition
read_openfpga_arch -f ${OPENFPGA_ARCH_FILE}
# Read OpenFPGA simulation settings
read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE}
# Annotate the OpenFPGA architecture to VPR data base
# to debug use --verbose options
link_openfpga_arch --activity_file ${ACTIVITY_FILE} --sort_gsb_chan_node_in_edges
# Check and correct any naming conflicts in the BLIF netlist
check_netlist_naming_conflict --fix --report ./netlist_renaming.xml
# Apply fix-up to clustering nets based on routing results
pb_pin_fixup --verbose
# Apply fix-up to Look-Up Table truth tables based on packing results
lut_truth_table_fixup
# Build the module graph
# - Enabled compression on routing architecture modules
# - Enable pin duplication on grid modules
build_fabric --compress_routing #--verbose
# Write the fabric hierarchy of module graph to a file
# This is used by hierarchical PnR flows
write_fabric_hierarchy --file ./fabric_hierarchy.txt
# Repack the netlist to physical pbs
# This must be done before bitstream generator and testbench generation
# Strongly recommend it is done after all the fix-up have been applied
repack --design_constraints ${OPENFPGA_REPACK_DESIGN_CONSTRAINTS_FILE} #--verbose
# Build the bitstream
# - Output the fabric-independent bitstream to a file
build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml
# Build fabric-dependent bitstream
build_fabric_bitstream --verbose
# Write fabric-dependent bitstream
write_fabric_bitstream --file fabric_bitstream.xml --format xml
# Write the Verilog netlist for FPGA fabric
# - Enable the use of explicit port mapping in Verilog netlist
write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose
# Write the Verilog testbench for FPGA fabric
# - We suggest the use of same output directory as fabric Verilog netlists
# - Must specify the reference benchmark file if you want to output any testbenches
# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA
# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase
# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts
write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --include_signal_init --support_icarus_simulator #--explicit_port_mapping
# Write the SDC files for PnR backend
# - Turn on every options here
write_pnr_sdc --file ./SDC
# Write SDC to disable timing for configure ports
write_sdc_disable_timing_configure_ports --file ./SDC/disable_configure_ports.sdc
# Write the SDC to run timing analysis for a mapped FPGA fabric
write_analysis_sdc --file ./SDC_analysis
# Finish and exit OpenFPGA
exit
# Note :
# To run verification at the end of the flow maintain source in ./SRC directory

View File

@ -0,0 +1,14 @@
<repack_design_constraints>
<!-- For a given .blif file, we want to assign
- the clk0 signal to the clk[0] port of all the clb tiles available in the FPGA fabric
- the clk1 signal to the clk[1] port of all the clb tiles available in the FPGA fabric
and ensure no signals could be mapped to
- the clk[2] port of all the clb tiles available in the FPGA fabric
- the clk[3] port of all the clb tiles available in the FPGA fabric
-->
<pin_constraint pb_type="clb" pin="clk[0]" net="clk0"/>
<pin_constraint pb_type="clb" pin="clk[1]" net="clk1"/>
<pin_constraint pb_type="clb" pin="clk[2]" net="OPEN"/>
<pin_constraint pb_type="clb" pin="clk[3]" net="OPEN"/>
</repack_design_constraints>

View File

@ -22,9 +22,10 @@ fpga_flow=vpr_blif
#fpga_flow=yosys_vpr
[OpenFPGA_SHELL]
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/global_tile_clock_example_script.openfpga
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/global_tile_multiclock_example_script.openfpga
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_GlobalTile4Clk_cc_openfpga.xml
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_4clock_sim_openfpga.xml
openfpga_repack_design_constraints_file=${PATH:OPENFPGA_PATH}/openfpga_flow/tasks/basic_tests/global_tile_ports/global_tile_4clock/config/repack_pin_constraints.xml
[ARCHITECTURES]
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_GlobalTile4Clk_40nm.xml