[Lib] Add a library of parser/writer for pin constraint file (PCF)
This commit is contained in:
parent
ab25e1af5f
commit
52ac7826eb
|
@ -0,0 +1,35 @@
|
|||
cmake_minimum_required(VERSION 3.9)
|
||||
|
||||
project("libpcf")
|
||||
|
||||
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(libpcf STATIC
|
||||
${LIB_HEADERS}
|
||||
${LIB_SOURCES})
|
||||
target_include_directories(libpcf PUBLIC ${LIB_INCLUDE_DIRS})
|
||||
set_target_properties(libpcf PROPERTIES PREFIX "") #Avoid extra 'lib' prefix
|
||||
|
||||
#Specify link-time dependancies
|
||||
target_link_libraries(libpcf
|
||||
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} libpcf)
|
||||
endforeach(testsourcefile ${EXEC_SOURCES})
|
|
@ -0,0 +1,9 @@
|
|||
<pin_constraints>
|
||||
<!-- For a given .blif file, we want to assign
|
||||
- the clk0 signal to the clk[0] port of the FPGA fabric
|
||||
- the clk1 signal to the clk[1] port of the FPGA fabric
|
||||
-->
|
||||
<set_io pin="clk[0]" net="clk0"/>
|
||||
<set_io pin="clk[1]" net="clk1"/>
|
||||
</pin_constraints>
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
#include <algorithm>
|
||||
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
|
||||
#include "pin_constraints.h"
|
||||
|
||||
/************************************************************************
|
||||
* Member functions for class PinConstraints
|
||||
***********************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
* Constructors
|
||||
***********************************************************************/
|
||||
PinConstraints::PinConstraints() {
|
||||
return;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors : aggregates
|
||||
***********************************************************************/
|
||||
PinConstraints::pin_constraint_range PinConstraints::pin_constraints() const {
|
||||
return vtr::make_range(pin_constraint_ids_.begin(), pin_constraint_ids_.end());
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors : Basic data query
|
||||
***********************************************************************/
|
||||
openfpga::BasicPort PinConstraints::pin(const PinConstraintId& pin_constraint_id) const {
|
||||
/* validate the pin_constraint_id */
|
||||
VTR_ASSERT(valid_pin_constraint_id(pin_constraint_id));
|
||||
return pin_constraint_pins_[pin_constraint_id];
|
||||
}
|
||||
|
||||
std::string PinConstraints::net(const PinConstraintId& pin_constraint_id) const {
|
||||
/* validate the pin_constraint_id */
|
||||
VTR_ASSERT(valid_pin_constraint_id(pin_constraint_id));
|
||||
return pin_constraint_nets_[pin_constraint_id];
|
||||
}
|
||||
|
||||
bool PinConstraints::empty() const {
|
||||
return 0 == pin_constraint_ids_.size();
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public Mutators
|
||||
***********************************************************************/
|
||||
void PinConstraints::reserve_pin_constraints(const size_t& num_pin_constraints) {
|
||||
pin_constraint_ids_.reserve(num_pin_constraints);
|
||||
pin_constraint_pins_.reserve(num_pin_constraints);
|
||||
pin_constraint_nets_.reserve(num_pin_constraints);
|
||||
}
|
||||
|
||||
PinConstraintId PinConstraints::create_pin_constraint(const openfpga::BasicPort& pin,
|
||||
const std::string& net) {
|
||||
/* Create a new id */
|
||||
PinConstraintId pin_constraint_id = PinConstraintId(pin_constraint_ids_.size());
|
||||
|
||||
pin_constraint_ids_.push_back(pin_constraint_id);
|
||||
pin_constraint_pins_.push_back(pin);
|
||||
pin_constraint_nets_.push_back(net);
|
||||
|
||||
return pin_constraint_id;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Internal invalidators/validators
|
||||
***********************************************************************/
|
||||
/* Validators */
|
||||
bool PinConstraints::valid_pin_constraint_id(const PinConstraintId& pin_constraint_id) const {
|
||||
return ( size_t(pin_constraint_id) < pin_constraint_ids_.size() ) && ( pin_constraint_id == pin_constraint_ids_[pin_constraint_id] );
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
#ifndef PIN_CONSTRAINTS_H
|
||||
#define PIN_CONSTRAINTS_H
|
||||
|
||||
/********************************************************************
|
||||
* This file include the declaration of pin 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 "pin_constraints_fwd.h"
|
||||
|
||||
/********************************************************************
|
||||
* A data structure to describe the pin constraints for FPGA fabrics
|
||||
* This data structure may include a number of pin 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 pin constraints
|
||||
* PinConstraints pin_constraints;
|
||||
* // Add a pin assignment
|
||||
* openfpga::BasicPort pin_info(clk, 1);
|
||||
* std::string net_info("top_clock");
|
||||
* PinConstraintId pin_constraint_id = pin_constraints.create_pin_constraint(pin_info, net_info);
|
||||
*
|
||||
*******************************************************************/
|
||||
class PinConstraints {
|
||||
public: /* Types */
|
||||
typedef vtr::vector<PinConstraintId, PinConstraintId>::const_iterator pin_constraint_iterator;
|
||||
/* Create range */
|
||||
typedef vtr::Range<pin_constraint_iterator> pin_constraint_range;
|
||||
public: /* Constructors */
|
||||
PinConstraints();
|
||||
public: /* Accessors: aggregates */
|
||||
pin_constraint_range pin_constraints() const;
|
||||
public: /* Public Accessors: Basic data query */
|
||||
/* Get the pin to be constrained */
|
||||
openfpga::BasicPort pin(const PinConstraintId& pin_constraint_id) const;
|
||||
|
||||
/* Get the net to be constrained */
|
||||
std::string net(const PinConstraintId& pin_constraint_id) const;
|
||||
|
||||
/* Check if there are any pin constraints */
|
||||
bool empty() const;
|
||||
|
||||
public: /* Public Mutators */
|
||||
|
||||
/* Reserve a number of design constraints to be memory efficent */
|
||||
void reserve_pin_constraints(const size_t& num_pin_constraints);
|
||||
|
||||
/* Add a pin constraint to storage */
|
||||
PinConstraintId create_pin_constraint(const openfpga::BasicPort& pin,
|
||||
const std::string& net);
|
||||
|
||||
public: /* Public invalidators/validators */
|
||||
bool valid_pin_constraint_id(const PinConstraintId& pin_constraint_id) const;
|
||||
private: /* Internal data */
|
||||
/* Unique ids for each design constraint */
|
||||
vtr::vector<PinConstraintId, PinConstraintId> pin_constraint_ids_;
|
||||
|
||||
/* Pins to constraint */
|
||||
vtr::vector<PinConstraintId, openfpga::BasicPort> pin_constraint_pins_;
|
||||
|
||||
/* Nets to constraint */
|
||||
vtr::vector<PinConstraintId, std::string> pin_constraint_nets_;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,22 @@
|
|||
/************************************************************************
|
||||
* A header file for PinConstraints class, including critical data declaration
|
||||
* Please include this file only for using any PinConstraints data structure
|
||||
* Refer to pin_constraints.h for more details
|
||||
***********************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
* Create strong id for PinConstraints to avoid illegal type casting
|
||||
***********************************************************************/
|
||||
#ifndef PIN_CONSTRAINTS_FWD_H
|
||||
#define PIN_CONSTRAINTS_FWD_H
|
||||
|
||||
#include "vtr_strong_id.h"
|
||||
|
||||
struct pin_constraint_id_tag;
|
||||
|
||||
typedef vtr::StrongId<pin_constraint_id_tag> PinConstraintId;
|
||||
|
||||
/* Short declaration of class */
|
||||
class PinConstraints;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,82 @@
|
|||
/********************************************************************
|
||||
* This file includes the top-level function of this library
|
||||
* which reads an XML of pin constraints 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_pin_constraints.h"
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes of a <set_io> to an object of PinConstraint
|
||||
*******************************************************************/
|
||||
static
|
||||
void read_xml_pin_constraint(pugi::xml_node& xml_pin_constraint,
|
||||
const pugiutil::loc_data& loc_data,
|
||||
PinConstraints& pin_constraints) {
|
||||
|
||||
openfpga::PortParser port_parser(get_attribute(xml_pin_constraint, "pin", loc_data).as_string());
|
||||
|
||||
std::string net_name = get_attribute(xml_pin_constraint, "net", loc_data).as_string();
|
||||
|
||||
/* Create a new pin constraint in the storage */
|
||||
PinConstraintId pin_constraint_id = pin_constraints.create_pin_constraint(port_parser.port(), net_name);
|
||||
|
||||
if (false == pin_constraints.valid_pin_constraint_id(pin_constraint_id)) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_pin_constraint),
|
||||
"Fail to create pin constraint!\n");
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Parse XML codes about <pin_constraints> to an object of PinConstraints
|
||||
*******************************************************************/
|
||||
PinConstraints read_xml_pin_constraints(const char* pin_constraint_fname) {
|
||||
|
||||
vtr::ScopedStartFinishTimer timer("Read Pin Constraints");
|
||||
|
||||
PinConstraints pin_constraints;
|
||||
|
||||
/* Parse the file */
|
||||
pugi::xml_document doc;
|
||||
pugiutil::loc_data loc_data;
|
||||
|
||||
try {
|
||||
loc_data = pugiutil::load_xml(doc, pin_constraint_fname);
|
||||
|
||||
pugi::xml_node xml_root = get_single_child(doc, "pin_constraints", loc_data);
|
||||
|
||||
size_t num_pin_constraints = std::distance(xml_root.children().begin(), xml_root.children().end());
|
||||
/* Reserve memory space for the region */
|
||||
pin_constraints.reserve_pin_constraints(num_pin_constraints);
|
||||
|
||||
for (pugi::xml_node xml_pin_constraint : xml_root.children()) {
|
||||
/* Error out if the XML child has an invalid name! */
|
||||
if (xml_pin_constraint.name() != std::string("set_io")) {
|
||||
bad_tag(xml_pin_constraint, loc_data, xml_root, {"set_io"});
|
||||
}
|
||||
read_xml_pin_constraint(xml_pin_constraint, loc_data, pin_constraints);
|
||||
}
|
||||
} catch (pugiutil::XmlError& e) {
|
||||
archfpga_throw(pin_constraint_fname, e.line(),
|
||||
"%s", e.what());
|
||||
}
|
||||
|
||||
return pin_constraints;
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef READ_XML_PIN_CONSTRAINTS_H
|
||||
#define READ_XML_PIN_CONSTRAINTS_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include "pugixml_util.hpp"
|
||||
#include "pugixml.hpp"
|
||||
#include "pin_constraints.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
PinConstraints read_xml_pin_constraints(const char* pin_constraint_fname);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,94 @@
|
|||
/********************************************************************
|
||||
* This file includes functions that outputs a pin 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 pin constraint library */
|
||||
#include "write_xml_pin_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_io_constraint(std::fstream& fp,
|
||||
const PinConstraints& pin_constraints,
|
||||
const PinConstraintId& pin_constraint) {
|
||||
/* Validate the file stream */
|
||||
if (false == openfpga::valid_file_stream(fp)) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
openfpga::write_tab_to_file(fp, 1);
|
||||
fp << "<set_io";
|
||||
|
||||
if (false == pin_constraints.valid_pin_constraint_id(pin_constraint)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
write_xml_attribute(fp, "pin", generate_xml_port_name(pin_constraints.pin(pin_constraint)).c_str());
|
||||
write_xml_attribute(fp, "net", pin_constraints.net(pin_constraint).c_str());
|
||||
|
||||
fp << "/>" << "\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a repack pin 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_pin_constraints(const char* fname,
|
||||
const PinConstraints& pin_constraints) {
|
||||
|
||||
vtr::ScopedStartFinishTimer timer("Write Pin 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 << "<pin_constraints>" << "\n";
|
||||
|
||||
int err_code = 0;
|
||||
|
||||
/* Write region by region */
|
||||
for (const PinConstraintId& pin_constraint : pin_constraints.pin_constraints()) {
|
||||
/* Write constraint by constraint */
|
||||
err_code = write_xml_pin_constraint(fp, pin_constraints, pin_constraint);
|
||||
if (0 != err_code) {
|
||||
return err_code;
|
||||
}
|
||||
}
|
||||
|
||||
/* Finish writing the root node */
|
||||
fp << "</pin_constraints>" << "\n";
|
||||
|
||||
/* Close the file stream */
|
||||
fp.close();
|
||||
|
||||
return err_code;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef WRITE_XML_PIN_CONSTRAINTS_H
|
||||
#define WRITE_XML_PIN_CONSTRAINTS_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <fstream>
|
||||
#include "pin_constraints.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
int write_xml_pin_constraints(const char* fname,
|
||||
const PinConstraints& pin_constraints);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,33 @@
|
|||
/********************************************************************
|
||||
* 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_pin_constraints.h"
|
||||
#include "write_xml_pin_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 */
|
||||
PinConstraints pin_constraints = read_xml_pin_constraints(argv[1]);
|
||||
VTR_LOG("Read the pin constraints from an XML file: %s.\n",
|
||||
argv[1]);
|
||||
|
||||
/* Output pin constraints to an XML file
|
||||
* This is optional only used when there is a second argument
|
||||
*/
|
||||
if (3 <= argc) {
|
||||
write_xml_pin_constraints(argv[2], pin_constraints);
|
||||
VTR_LOG("Echo the pin constraints to an XML file: %s.\n",
|
||||
argv[2]);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue