Merge pull request #174 from lnis-uofu/dev
Support Design Constraints for Repack
This commit is contained in:
commit
17c49711d3
|
@ -12,3 +12,5 @@ FPGA-Bitstream can generate two types of bitstreams:
|
|||
generic_bitstream
|
||||
|
||||
fabric_dependent_bitstream
|
||||
|
||||
repack_design_constraints
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -4,4 +4,5 @@ add_subdirectory(libopenfpgashell)
|
|||
add_subdirectory(libarchopenfpga)
|
||||
add_subdirectory(libopenfpgautil)
|
||||
add_subdirectory(libfabrickey)
|
||||
add_subdirectory(librepackdc)
|
||||
add_subdirectory(libfpgabitstream)
|
||||
|
|
|
@ -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})
|
|
@ -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>
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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] );
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -23,6 +23,7 @@ target_link_libraries(libopenfpga
|
|||
libopenfpgashell
|
||||
libopenfpgautil
|
||||
libfabrickey
|
||||
librepackdc
|
||||
libfpgabitstream
|
||||
libini
|
||||
libvtrutil
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue