diff --git a/libopenfpga/libpcf/CMakeLists.txt b/libopenfpga/libpcf/CMakeLists.txt
new file mode 100644
index 000000000..8287bb3bc
--- /dev/null
+++ b/libopenfpga/libpcf/CMakeLists.txt
@@ -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})
diff --git a/libopenfpga/libpcf/example/fpga_io_nets.xml b/libopenfpga/libpcf/example/fpga_io_nets.xml
new file mode 100644
index 000000000..90523a274
--- /dev/null
+++ b/libopenfpga/libpcf/example/fpga_io_nets.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
diff --git a/libopenfpga/libpcf/src/pin_constraints.cpp b/libopenfpga/libpcf/src/pin_constraints.cpp
new file mode 100644
index 000000000..4f7a701a7
--- /dev/null
+++ b/libopenfpga/libpcf/src/pin_constraints.cpp
@@ -0,0 +1,72 @@
+#include
+
+#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] );
+}
diff --git a/libopenfpga/libpcf/src/pin_constraints.h b/libopenfpga/libpcf/src/pin_constraints.h
new file mode 100644
index 000000000..487eec22a
--- /dev/null
+++ b/libopenfpga/libpcf/src/pin_constraints.h
@@ -0,0 +1,77 @@
+#ifndef PIN_CONSTRAINTS_H
+#define PIN_CONSTRAINTS_H
+
+/********************************************************************
+ * This file include the declaration of pin constraints
+ *******************************************************************/
+#include
+#include