diff --git a/libopenfpga/CMakeLists.txt b/libopenfpga/CMakeLists.txt
index 36bce10b6..f6f812f89 100644
--- a/libopenfpga/CMakeLists.txt
+++ b/libopenfpga/CMakeLists.txt
@@ -8,3 +8,4 @@ add_subdirectory(librepackdc)
add_subdirectory(libfpgabitstream)
add_subdirectory(libpcf)
add_subdirectory(libbusgroup)
+add_subdirectory(libpinconstrain)
diff --git a/libopenfpga/libpinconstrain/CMakeLists.txt b/libopenfpga/libpinconstrain/CMakeLists.txt
new file mode 100644
index 000000000..9ee340d87
--- /dev/null
+++ b/libopenfpga/libpinconstrain/CMakeLists.txt
@@ -0,0 +1,40 @@
+cmake_minimum_required(VERSION 3.9)
+
+project("libpinconstrain")
+
+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)
+
+file(GLOB_RECURSE BLIF_READ_HEADERS ../../vpr/src/base/*.h)
+files_to_dirs(BLIF_READ_HEADERS BLIF_READ_INCLUDE_DIRS)
+
+file(GLOB_RECURSE VTR_UTIL_HEADERS ../../libs/libvtrutil/src/*.h)
+files_to_dirs(VTR_UTIL_HEADERS VTR_UTIL_INCLUDE_DIRS)
+
+#Remove test executable from library
+list(REMOVE_ITEM LIB_SOURCES ${EXEC_SOURCES})
+
+#Create the library
+add_library(libpinconstrain STATIC
+ ${LIB_HEADERS}
+ ${LIB_SOURCES})
+target_include_directories(libpinconstrain PUBLIC ${LIB_INCLUDE_DIRS} ${BLIF_READ_INCLUDE_DIRS} ${VTR_UTIL_INCLUDE_DIRS})
+set_target_properties(libpinconstrain PROPERTIES PREFIX "") #Avoid extra 'lib' prefix
+
+#Specify link-time dependancies
+target_link_libraries(libpinconstrain
+ libvpr
+ libvtrutil
+ libpugixml)
+
+#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})
+ target_include_directories(${testname} PUBLIC ${LIB_INCLUDE_DIRS} ${BLIF_READ_INCLUDE_DIRS} ${VTR_UTIL_INCLUDE_DIRS})
+ # Make sure the library is linked to each test executable
+ target_link_libraries(${testname} libpinconstrain)
+endforeach(testsourcefile ${EXEC_SOURCES})
diff --git a/libopenfpga/libpinconstrain/data/pinmap_qlf_k6n10_tsmc22.csv b/libopenfpga/libpinconstrain/data/pinmap_qlf_k6n10_tsmc22.csv
new file mode 100755
index 000000000..ce9e78890
--- /dev/null
+++ b/libopenfpga/libpinconstrain/data/pinmap_qlf_k6n10_tsmc22.csv
@@ -0,0 +1,161 @@
+orientation,row,col,pin_num_in_cell,port_name,mapped_pin,GPIO_type,Associated Clock,Clock Edge
+TOP,,,,gfpga_pad_IO_A2F[0],pad_fpga_io[18],,,
+TOP,,,,gfpga_pad_IO_F2A[0],pad_fpga_io[18],,,
+TOP,,,,gfpga_pad_IO_A2F[6],pad_fpga_io[19],,,
+TOP,,,,gfpga_pad_IO_F2A[6],pad_fpga_io[19],,,
+TOP,,,,gfpga_pad_IO_A2F[8],pad_fpga_io[20],,,
+TOP,,,,gfpga_pad_IO_F2A[8],pad_fpga_io[20],,,
+TOP,,,,gfpga_pad_IO_A2F[12],pad_fpga_io[21],,,
+TOP,,,,gfpga_pad_IO_F2A[12],pad_fpga_io[21],,,
+TOP,,,,gfpga_pad_IO_A2F[16],pad_fpga_io[22],,,
+TOP,,,,gfpga_pad_IO_F2A[16],pad_fpga_io[22],,,
+TOP,,,,gfpga_pad_IO_A2F[20],pad_fpga_io[23],,,
+TOP,,,,gfpga_pad_IO_F2A[20],pad_fpga_io[23],,,
+TOP,,,,gfpga_pad_IO_A2F[24],pad_fpga_io[24],,,
+TOP,,,,gfpga_pad_IO_F2A[24],pad_fpga_io[24],,,
+TOP,,,,gfpga_pad_IO_F2A[28],pad_fpga_io[25],,,
+TOP,,,,gfpga_pad_IO_A2F[28],pad_fpga_io[25],,,
+TOP,,,,gfpga_pad_IO_F2A[32],pad_fpga_io[26],,,
+TOP,,,,gfpga_pad_IO_A2F[32],pad_fpga_io[26],,,
+TOP,,,,gfpga_pad_IO_F2A[36],pad_fpga_io[27],,,
+TOP,,,,gfpga_pad_IO_A2F[36],pad_fpga_io[27],,,
+TOP,,,,gfpga_pad_IO_F2A[40],pad_fpga_io[28],,,
+TOP,,,,gfpga_pad_IO_A2F[40],pad_fpga_io[28],,,
+TOP,,,,gfpga_pad_IO_F2A[44],pad_fpga_io[29],,,
+TOP,,,,gfpga_pad_IO_A2F[44],pad_fpga_io[29],,,
+TOP,,,,gfpga_pad_IO_F2A[48],pad_fpga_io[30],,,
+TOP,,,,gfpga_pad_IO_A2F[48],pad_fpga_io[30],,,
+TOP,,,,gfpga_pad_IO_A2F[52],pad_fpga_io[31],,,
+TOP,,,,gfpga_pad_IO_F2A[52],pad_fpga_io[31],,,
+TOP,,,,gfpga_pad_IO_A2F[56],pad_fpga_io[32],,,
+TOP,,,,gfpga_pad_IO_F2A[56],pad_fpga_io[32],,,
+TOP,,,,gfpga_pad_IO_A2F[60],pad_fpga_io[33],,,
+TOP,,,,gfpga_pad_IO_F2A[60],pad_fpga_io[33],,,
+TOP,,,,gfpga_pad_IO_A2F[64],pad_fpga_io[34],,,
+TOP,,,,gfpga_pad_IO_F2A[64],pad_fpga_io[34],,,
+TOP,,,,gfpga_pad_IO_A2F[68],pad_fpga_io[35],,,
+TOP,,,,gfpga_pad_IO_F2A[68],pad_fpga_io[35],,,
+TOP,,,,gfpga_pad_IO_A2F[72],pad_fpga_io[36],,,
+TOP,,,,gfpga_pad_IO_F2A[72],pad_fpga_io[36],,,
+TOP,,,,gfpga_pad_IO_A2F[76],pad_fpga_io[37],,,
+TOP,,,,gfpga_pad_IO_F2A[76],pad_fpga_io[37],,,
+RIGHT,,,,gfpga_pad_IO_A2F[80],pad_fpga_io[38],,,
+RIGHT,,,,gfpga_pad_IO_F2A[80],pad_fpga_io[38],,,
+RIGHT,,,,gfpga_pad_IO_A2F[84],pad_fpga_io[39],,,
+RIGHT,,,,gfpga_pad_IO_F2A[84],pad_fpga_io[39],,,
+RIGHT,,,,gfpga_pad_IO_A2F[88],pad_fpga_io[40],,,
+RIGHT,,,,gfpga_pad_IO_F2A[88],pad_fpga_io[40],,,
+RIGHT,,,,gfpga_pad_IO_A2F[92],pad_fpga_io[41],,,
+RIGHT,,,,gfpga_pad_IO_F2A[92],pad_fpga_io[41],,,
+RIGHT,,,,gfpga_pad_IO_A2F[96],pad_fpga_io[42],,,
+RIGHT,,,,gfpga_pad_IO_F2A[96],pad_fpga_io[42],,,
+RIGHT,,,,gfpga_pad_IO_A2F[100],pad_fpga_io[43],,,
+RIGHT,,,,gfpga_pad_IO_F2A[100],pad_fpga_io[43],,,
+RIGHT,,,,gfpga_pad_IO_A2F[104],pad_fpga_io[44],,,
+RIGHT,,,,gfpga_pad_IO_F2A[104],pad_fpga_io[44],,,
+RIGHT,,,,gfpga_pad_IO_F2A[108],pad_fpga_io[45],,,
+RIGHT,,,,gfpga_pad_IO_A2F[108],pad_fpga_io[45],,,
+RIGHT,,,,gfpga_pad_IO_F2A[112],pad_fpga_io[46],,,
+RIGHT,,,,gfpga_pad_IO_A2F[112],pad_fpga_io[46],,,
+RIGHT,,,,gfpga_pad_IO_F2A[116],pad_fpga_io[47],,,
+RIGHT,,,,gfpga_pad_IO_A2F[116],pad_fpga_io[47],,,
+RIGHT,,,,gfpga_pad_IO_F2A[120],pad_fpga_io[48],,,
+RIGHT,,,,gfpga_pad_IO_A2F[120],pad_fpga_io[48],,,
+RIGHT,,,,gfpga_pad_IO_F2A[124],pad_fpga_io[49],,,
+RIGHT,,,,gfpga_pad_IO_A2F[124],pad_fpga_io[49],,,
+RIGHT,,,,gfpga_pad_IO_F2A[128],pad_fpga_io[50],,,
+RIGHT,,,,gfpga_pad_IO_A2F[128],pad_fpga_io[50],,,
+RIGHT,,,,gfpga_pad_IO_F2A[132],pad_fpga_io[51],,,
+RIGHT,,,,gfpga_pad_IO_A2F[132],pad_fpga_io[51],,,
+RIGHT,,,,gfpga_pad_IO_F2A[136],pad_fpga_io[52],,,
+RIGHT,,,,gfpga_pad_IO_A2F[136],pad_fpga_io[52],,,
+RIGHT,,,,gfpga_pad_IO_F2A[140],pad_fpga_io[53],,,
+RIGHT,,,,gfpga_pad_IO_A2F[140],pad_fpga_io[53],,,
+RIGHT,,,,gfpga_pad_IO_F2A[144],pad_fpga_io[54],,,
+RIGHT,,,,gfpga_pad_IO_A2F[144],pad_fpga_io[54],,,
+RIGHT,,,,gfpga_pad_IO_F2A[148],pad_fpga_io[55],,,
+RIGHT,,,,gfpga_pad_IO_A2F[148],pad_fpga_io[55],,,
+RIGHT,,,,gfpga_pad_IO_F2A[152],pad_fpga_io[56],,,
+RIGHT,,,,gfpga_pad_IO_A2F[152],pad_fpga_io[56],,,
+RIGHT,,,,gfpga_pad_IO_A2F[156],pad_fpga_io[57],,,
+RIGHT,,,,gfpga_pad_IO_F2A[156],pad_fpga_io[57],,,
+BOTTOM,,,,gfpga_pad_IO_A2F[160],pad_fpga_io[58],,,
+BOTTOM,,,,gfpga_pad_IO_F2A[160],pad_fpga_io[58],,,
+BOTTOM,,,,gfpga_pad_IO_A2F[164],pad_fpga_io[59],,,
+BOTTOM,,,,gfpga_pad_IO_F2A[164],pad_fpga_io[59],,,
+BOTTOM,,,,gfpga_pad_IO_A2F[168],pad_fpga_io[60],,,
+BOTTOM,,,,gfpga_pad_IO_F2A[168],pad_fpga_io[60],,,
+BOTTOM,,,,gfpga_pad_IO_A2F[172],pad_fpga_io[61],,,
+BOTTOM,,,,gfpga_pad_IO_F2A[172],pad_fpga_io[61],,,
+BOTTOM,,,,gfpga_pad_IO_A2F[176],pad_fpga_io[62],,,
+BOTTOM,,,,gfpga_pad_IO_F2A[176],pad_fpga_io[62],,,
+BOTTOM,,,,gfpga_pad_IO_A2F[180],pad_fpga_io[63],,,
+BOTTOM,,,,gfpga_pad_IO_F2A[180],pad_fpga_io[63],,,
+BOTTOM,,,,gfpga_pad_IO_A2F[184],pad_fpga_io[64],,,
+BOTTOM,,,,gfpga_pad_IO_F2A[184],pad_fpga_io[64],,,
+BOTTOM,,,,gfpga_pad_IO_A2F[188],pad_fpga_io[65],,,
+BOTTOM,,,,gfpga_pad_IO_F2A[188],pad_fpga_io[65],,,
+BOTTOM,,,,gfpga_pad_IO_A2F[192],pad_fpga_io[66],,,
+BOTTOM,,,,gfpga_pad_IO_F2A[192],pad_fpga_io[66],,,
+BOTTOM,,,,gfpga_pad_IO_A2F[196],pad_fpga_io[67],,,
+BOTTOM,,,,gfpga_pad_IO_F2A[196],pad_fpga_io[67],,,
+BOTTOM,,,,gfpga_pad_IO_A2F[200],pad_fpga_io[68],,,
+BOTTOM,,,,gfpga_pad_IO_F2A[200],pad_fpga_io[68],,,
+BOTTOM,,,,gfpga_pad_IO_A2F[204],pad_fpga_io[69],,,
+BOTTOM,,,,gfpga_pad_IO_F2A[204],pad_fpga_io[69],,,
+BOTTOM,,,,gfpga_pad_IO_F2A[208],pad_fpga_io[70],,,
+BOTTOM,,,,gfpga_pad_IO_A2F[208],pad_fpga_io[70],,,
+BOTTOM,,,,gfpga_pad_IO_F2A[212],pad_fpga_io[71],,,
+BOTTOM,,,,gfpga_pad_IO_A2F[212],pad_fpga_io[71],,,
+BOTTOM,,,,gfpga_pad_IO_F2A[216],pad_fpga_io[72],,,
+BOTTOM,,,,gfpga_pad_IO_A2F[216],pad_fpga_io[72],,,
+BOTTOM,,,,gfpga_pad_IO_F2A[220],pad_fpga_io[73],,,
+BOTTOM,,,,gfpga_pad_IO_A2F[220],pad_fpga_io[73],,,
+BOTTOM,,,,gfpga_pad_IO_F2A[224],pad_fpga_io[74],,,
+BOTTOM,,,,gfpga_pad_IO_A2F[224],pad_fpga_io[74],,,
+BOTTOM,,,,gfpga_pad_IO_F2A[228],pad_fpga_io[75],,,
+BOTTOM,,,,gfpga_pad_IO_A2F[228],pad_fpga_io[75],,,
+BOTTOM,,,,gfpga_pad_IO_F2A[232],pad_fpga_io[76],,,
+BOTTOM,,,,gfpga_pad_IO_A2F[232],pad_fpga_io[76],,,
+BOTTOM,,,,gfpga_pad_IO_F2A[236],pad_fpga_io[77],,,
+BOTTOM,,,,gfpga_pad_IO_A2F[236],pad_fpga_io[77],,,
+LEFT,,,,gfpga_pad_IO_F2A[240],pad_fpga_io[78],,,
+LEFT,,,,gfpga_pad_IO_A2F[240],pad_fpga_io[78],,,
+LEFT,,,,gfpga_pad_IO_F2A[244],pad_fpga_io[79],,,
+LEFT,,,,gfpga_pad_IO_A2F[244],pad_fpga_io[79],,,
+LEFT,,,,gfpga_pad_IO_F2A[248],pad_fpga_io[0],,,
+LEFT,,,,gfpga_pad_IO_A2F[248],pad_fpga_io[0],,,
+LEFT,,,,gfpga_pad_IO_A2F[252],pad_fpga_io[1],,,
+LEFT,,,,gfpga_pad_IO_F2A[252],pad_fpga_io[1],,,
+LEFT,,,,gfpga_pad_IO_A2F[256],pad_fpga_io[2],,,
+LEFT,,,,gfpga_pad_IO_F2A[256],pad_fpga_io[2],,,
+LEFT,,,,gfpga_pad_IO_A2F[260],pad_fpga_io[3],,,
+LEFT,,,,gfpga_pad_IO_F2A[260],pad_fpga_io[3],,,
+LEFT,,,,gfpga_pad_IO_A2F[264],pad_fpga_io[4],,,
+LEFT,,,,gfpga_pad_IO_F2A[264],pad_fpga_io[4],,,
+LEFT,,,,gfpga_pad_IO_A2F[268],pad_fpga_io[5],,,
+LEFT,,,,gfpga_pad_IO_F2A[268],pad_fpga_io[5],,,
+LEFT,,,,gfpga_pad_IO_A2F[272],pad_fpga_io[6],,,
+LEFT,,,,gfpga_pad_IO_F2A[272],pad_fpga_io[6],,,
+LEFT,,,,gfpga_pad_IO_A2F[276],pad_fpga_io[7],,,
+LEFT,,,,gfpga_pad_IO_F2A[276],pad_fpga_io[7],,,
+LEFT,,,,gfpga_pad_IO_A2F[280],pad_fpga_io[8],,,
+LEFT,,,,gfpga_pad_IO_F2A[280],pad_fpga_io[8],,,
+LEFT,,,,gfpga_pad_IO_A2F[284],pad_fpga_io[9],,,
+LEFT,,,,gfpga_pad_IO_F2A[284],pad_fpga_io[9],,,
+LEFT,,,,gfpga_pad_IO_A2F[288],pad_fpga_io[10],,,
+LEFT,,,,gfpga_pad_IO_F2A[288],pad_fpga_io[10],,,
+LEFT,,,,gfpga_pad_IO_A2F[292],pad_fpga_io[11],,,
+LEFT,,,,gfpga_pad_IO_F2A[292],pad_fpga_io[11],,,
+LEFT,,,,gfpga_pad_IO_A2F[296],pad_fpga_io[12],,,
+LEFT,,,,gfpga_pad_IO_F2A[296],pad_fpga_io[12],,,
+LEFT,,,,gfpga_pad_IO_A2F[300],pad_fpga_io[13],,,
+LEFT,,,,gfpga_pad_IO_F2A[300],pad_fpga_io[13],,,
+LEFT,,,,gfpga_pad_IO_A2F[304],pad_fpga_io[14],,,
+LEFT,,,,gfpga_pad_IO_F2A[304],pad_fpga_io[14],,,
+LEFT,,,,gfpga_pad_IO_F2A[308],pad_fpga_io[15],,,
+LEFT,,,,gfpga_pad_IO_A2F[308],pad_fpga_io[15],,,
+LEFT,,,,gfpga_pad_IO_F2A[312],pad_fpga_io[16],,,
+LEFT,,,,gfpga_pad_IO_A2F[312],pad_fpga_io[16],,,
+LEFT,,,,gfpga_pad_IO_F2A[316],pad_fpga_io[17],,,
+LEFT,,,,gfpga_pad_IO_A2F[316],pad_fpga_io[17],,,
diff --git a/libopenfpga/libpinconstrain/data/pinmap_qlf_k6n10_tsmc22.xml b/libopenfpga/libpinconstrain/data/pinmap_qlf_k6n10_tsmc22.xml
new file mode 100755
index 000000000..b919edfa8
--- /dev/null
+++ b/libopenfpga/libpinconstrain/data/pinmap_qlf_k6n10_tsmc22.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+ |
+ |
+
+
+ |
+ |
+
+
+ |
+ |
+
+
+ |
+ |
+
+
+
diff --git a/libopenfpga/libpinconstrain/data/simple_pic.blif b/libopenfpga/libpinconstrain/data/simple_pic.blif
new file mode 100644
index 000000000..cc29c34f6
--- /dev/null
+++ b/libopenfpga/libpinconstrain/data/simple_pic.blif
@@ -0,0 +1,580 @@
+# Generated by Yosys 0.10.0 (git sha1 dca8fb54a, gcc 7.5.0-3ubuntu1~18.04 -fPIC -Os)
+
+.model simple_pic
+.inputs clk_i rst_i cyc_i stb_i adr_i[1] adr_i[2] we_i dat_i[0] dat_i[1] dat_i[2] dat_i[3] dat_i[4] dat_i[5] dat_i[6] dat_i[7] irq[1] irq[2] irq[3] irq[4] irq[5] irq[6] irq[7] irq[8]
+.outputs dat_o[0] dat_o[1] dat_o[2] dat_o[3] dat_o[4] dat_o[5] dat_o[6] dat_o[7] ack_o int_o
+.names $false
+.names $true
+1
+.names $undef
+.names stb_i cyc_i ack_o ack_o_dffsre_Q_D
+110 1
+.subckt dffsre C=clk_i D=ack_o_dffsre_Q_D E=$true Q=ack_o R=$true S=$true
+.subckt dffsre C=clk_i D=dat_o_dffsre_Q_D[7] E=$true Q=dat_o[7] R=$true S=$true
+.subckt dffsre C=clk_i D=dat_o_dffsre_Q_D[6] E=$true Q=dat_o[6] R=$true S=$true
+.subckt dffsre C=clk_i D=dat_o_dffsre_Q_D[5] E=$true Q=dat_o[5] R=$true S=$true
+.subckt dffsre C=clk_i D=dat_o_dffsre_Q_D[4] E=$true Q=dat_o[4] R=$true S=$true
+.subckt dffsre C=clk_i D=dat_o_dffsre_Q_D[3] E=$true Q=dat_o[3] R=$true S=$true
+.subckt dffsre C=clk_i D=dat_o_dffsre_Q_D[2] E=$true Q=dat_o[2] R=$true S=$true
+.subckt dffsre C=clk_i D=dat_o_dffsre_Q_D[1] E=$true Q=dat_o[1] R=$true S=$true
+.subckt dffsre C=clk_i D=dat_o_dffsre_Q_D[0] E=$true Q=dat_o[0] R=$true S=$true
+.names adr_i[1] adr_i[2] pending[8] mask[8] pol[8] edgen[8] dat_o_dffsre_Q_D[7]
+000001 1
+000011 1
+000101 1
+000111 1
+001001 1
+001011 1
+001101 1
+001111 1
+010100 1
+010101 1
+010110 1
+010111 1
+011100 1
+011101 1
+011110 1
+011111 1
+100010 1
+100011 1
+100110 1
+100111 1
+101010 1
+101011 1
+101110 1
+101111 1
+111000 1
+111001 1
+111010 1
+111011 1
+111100 1
+111101 1
+111110 1
+111111 1
+.names adr_i[1] adr_i[2] pending[7] mask[7] pol[7] edgen[7] dat_o_dffsre_Q_D[6]
+000001 1
+000011 1
+000101 1
+000111 1
+001001 1
+001011 1
+001101 1
+001111 1
+010100 1
+010101 1
+010110 1
+010111 1
+011100 1
+011101 1
+011110 1
+011111 1
+100010 1
+100011 1
+100110 1
+100111 1
+101010 1
+101011 1
+101110 1
+101111 1
+111000 1
+111001 1
+111010 1
+111011 1
+111100 1
+111101 1
+111110 1
+111111 1
+.names adr_i[1] adr_i[2] pending[6] mask[6] pol[6] edgen[6] dat_o_dffsre_Q_D[5]
+000001 1
+000011 1
+000101 1
+000111 1
+001001 1
+001011 1
+001101 1
+001111 1
+010100 1
+010101 1
+010110 1
+010111 1
+011100 1
+011101 1
+011110 1
+011111 1
+100010 1
+100011 1
+100110 1
+100111 1
+101010 1
+101011 1
+101110 1
+101111 1
+111000 1
+111001 1
+111010 1
+111011 1
+111100 1
+111101 1
+111110 1
+111111 1
+.names adr_i[1] adr_i[2] pending[5] mask[5] pol[5] edgen[5] dat_o_dffsre_Q_D[4]
+000001 1
+000011 1
+000101 1
+000111 1
+001001 1
+001011 1
+001101 1
+001111 1
+010100 1
+010101 1
+010110 1
+010111 1
+011100 1
+011101 1
+011110 1
+011111 1
+100010 1
+100011 1
+100110 1
+100111 1
+101010 1
+101011 1
+101110 1
+101111 1
+111000 1
+111001 1
+111010 1
+111011 1
+111100 1
+111101 1
+111110 1
+111111 1
+.names adr_i[1] adr_i[2] pending[4] mask[4] pol[4] edgen[4] dat_o_dffsre_Q_D[3]
+000001 1
+000011 1
+000101 1
+000111 1
+001001 1
+001011 1
+001101 1
+001111 1
+010100 1
+010101 1
+010110 1
+010111 1
+011100 1
+011101 1
+011110 1
+011111 1
+100010 1
+100011 1
+100110 1
+100111 1
+101010 1
+101011 1
+101110 1
+101111 1
+111000 1
+111001 1
+111010 1
+111011 1
+111100 1
+111101 1
+111110 1
+111111 1
+.names adr_i[1] adr_i[2] pending[3] mask[3] pol[3] edgen[3] dat_o_dffsre_Q_D[2]
+000001 1
+000011 1
+000101 1
+000111 1
+001001 1
+001011 1
+001101 1
+001111 1
+010100 1
+010101 1
+010110 1
+010111 1
+011100 1
+011101 1
+011110 1
+011111 1
+100010 1
+100011 1
+100110 1
+100111 1
+101010 1
+101011 1
+101110 1
+101111 1
+111000 1
+111001 1
+111010 1
+111011 1
+111100 1
+111101 1
+111110 1
+111111 1
+.names adr_i[1] adr_i[2] pending[2] mask[2] pol[2] edgen[2] dat_o_dffsre_Q_D[1]
+000001 1
+000011 1
+000101 1
+000111 1
+001001 1
+001011 1
+001101 1
+001111 1
+010100 1
+010101 1
+010110 1
+010111 1
+011100 1
+011101 1
+011110 1
+011111 1
+100010 1
+100011 1
+100110 1
+100111 1
+101010 1
+101011 1
+101110 1
+101111 1
+111000 1
+111001 1
+111010 1
+111011 1
+111100 1
+111101 1
+111110 1
+111111 1
+.names adr_i[1] adr_i[2] pending[1] mask[1] pol[1] edgen[1] dat_o_dffsre_Q_D[0]
+000001 1
+000011 1
+000101 1
+000111 1
+001001 1
+001011 1
+001101 1
+001111 1
+010100 1
+010101 1
+010110 1
+010111 1
+011100 1
+011101 1
+011110 1
+011111 1
+100010 1
+100011 1
+100110 1
+100111 1
+101010 1
+101011 1
+101110 1
+101111 1
+111000 1
+111001 1
+111010 1
+111011 1
+111100 1
+111101 1
+111110 1
+111111 1
+.names lirq[8] pol[8] dirq[8] edgen[8] irq_event_dffsre_Q_D[7]
+0000 1
+0010 1
+0011 1
+1100 1
+1101 1
+1110 1
+.names lirq[7] pol[7] dirq[7] edgen[7] irq_event_dffsre_Q_D[6]
+0000 1
+0010 1
+0011 1
+1100 1
+1101 1
+1110 1
+.names lirq[6] pol[6] dirq[6] edgen[6] irq_event_dffsre_Q_D[5]
+0000 1
+0010 1
+0011 1
+1100 1
+1101 1
+1110 1
+.names lirq[5] pol[5] dirq[5] edgen[5] irq_event_dffsre_Q_D[4]
+0000 1
+0010 1
+0011 1
+1100 1
+1101 1
+1110 1
+.names lirq[4] pol[4] dirq[4] edgen[4] irq_event_dffsre_Q_D[3]
+0000 1
+0010 1
+0011 1
+1100 1
+1101 1
+1110 1
+.names lirq[3] pol[3] dirq[3] edgen[3] irq_event_dffsre_Q_D[2]
+0000 1
+0010 1
+0011 1
+1100 1
+1101 1
+1110 1
+.names lirq[2] pol[2] dirq[2] edgen[2] irq_event_dffsre_Q_D[1]
+0000 1
+0010 1
+0011 1
+1100 1
+1101 1
+1110 1
+.names lirq[1] pol[1] dirq[1] edgen[1] irq_event_dffsre_Q_D[0]
+0000 1
+0010 1
+0011 1
+1100 1
+1101 1
+1110 1
+.subckt dffsre C=clk_i D=lirq[8] E=$true Q=dirq[8] R=$true S=$true
+.subckt dffsre C=clk_i D=lirq[7] E=$true Q=dirq[7] R=$true S=$true
+.subckt dffsre C=clk_i D=lirq[6] E=$true Q=dirq[6] R=$true S=$true
+.subckt dffsre C=clk_i D=lirq[5] E=$true Q=dirq[5] R=$true S=$true
+.subckt dffsre C=clk_i D=lirq[4] E=$true Q=dirq[4] R=$true S=$true
+.subckt dffsre C=clk_i D=lirq[3] E=$true Q=dirq[3] R=$true S=$true
+.subckt dffsre C=clk_i D=lirq[2] E=$true Q=dirq[2] R=$true S=$true
+.subckt dffsre C=clk_i D=lirq[1] E=$true Q=dirq[1] R=$true S=$true
+.subckt dffsre C=clk_i D=dat_i[7] E=we_i_$lut_A_2_Y Q=edgen[8] R=rst_i S=$true
+.subckt dffsre C=clk_i D=dat_i[6] E=we_i_$lut_A_2_Y Q=edgen[7] R=rst_i S=$true
+.subckt dffsre C=clk_i D=dat_i[5] E=we_i_$lut_A_2_Y Q=edgen[6] R=rst_i S=$true
+.subckt dffsre C=clk_i D=dat_i[4] E=we_i_$lut_A_2_Y Q=edgen[5] R=rst_i S=$true
+.subckt dffsre C=clk_i D=dat_i[3] E=we_i_$lut_A_2_Y Q=edgen[4] R=rst_i S=$true
+.subckt dffsre C=clk_i D=dat_i[2] E=we_i_$lut_A_2_Y Q=edgen[3] R=rst_i S=$true
+.subckt dffsre C=clk_i D=dat_i[1] E=we_i_$lut_A_2_Y Q=edgen[2] R=rst_i S=$true
+.subckt dffsre C=clk_i D=dat_i[0] E=we_i_$lut_A_2_Y Q=edgen[1] R=rst_i S=$true
+.subckt dffsre C=clk_i D=int_o_dffsre_Q_D E=$true Q=int_o R=$true S=$true
+.names int_o_dffsre_Q_D_$lut_Y_A int_o_dffsre_Q_D_$lut_Y_A_1 int_o_dffsre_Q_D_$lut_Y_A_2 pending[6] mask[6] int_o_dffsre_Q_D
+00000 1
+00001 1
+00010 1
+00011 1
+00100 1
+00101 1
+00110 1
+00111 1
+01000 1
+01001 1
+01010 1
+01011 1
+01100 1
+01101 1
+01110 1
+01111 1
+10000 1
+10001 1
+10010 1
+10011 1
+10100 1
+10101 1
+10110 1
+10111 1
+11000 1
+11001 1
+11010 1
+11011 1
+11110 1
+.names pending[7] mask[7] pending[8] mask[8] int_o_dffsre_Q_D_$lut_Y_A
+0000 1
+0001 1
+0011 1
+0100 1
+0101 1
+0111 1
+1100 1
+1101 1
+1111 1
+.names pending[2] mask[2] pending[3] mask[3] int_o_dffsre_Q_D_$lut_Y_A_1
+0000 1
+0001 1
+0011 1
+0100 1
+0101 1
+0111 1
+1100 1
+1101 1
+1111 1
+.names pending[1] mask[1] pending[4] mask[4] pending[5] mask[5] int_o_dffsre_Q_D_$lut_Y_A_2
+000000 1
+000001 1
+000011 1
+000100 1
+000101 1
+000111 1
+001100 1
+001101 1
+001111 1
+010000 1
+010001 1
+010011 1
+010100 1
+010101 1
+010111 1
+011100 1
+011101 1
+011111 1
+110000 1
+110001 1
+110011 1
+110100 1
+110101 1
+110111 1
+111100 1
+111101 1
+111111 1
+.subckt dffsre C=clk_i D=irq_event_dffsre_Q_D[7] E=$true Q=irq_event[8] R=$true S=$true
+.subckt dffsre C=clk_i D=irq_event_dffsre_Q_D[6] E=$true Q=irq_event[7] R=$true S=$true
+.subckt dffsre C=clk_i D=irq_event_dffsre_Q_D[5] E=$true Q=irq_event[6] R=$true S=$true
+.subckt dffsre C=clk_i D=irq_event_dffsre_Q_D[4] E=$true Q=irq_event[5] R=$true S=$true
+.subckt dffsre C=clk_i D=irq_event_dffsre_Q_D[3] E=$true Q=irq_event[4] R=$true S=$true
+.subckt dffsre C=clk_i D=irq_event_dffsre_Q_D[2] E=$true Q=irq_event[3] R=$true S=$true
+.subckt dffsre C=clk_i D=irq_event_dffsre_Q_D[1] E=$true Q=irq_event[2] R=$true S=$true
+.subckt dffsre C=clk_i D=irq_event_dffsre_Q_D[0] E=$true Q=irq_event[1] R=$true S=$true
+.subckt dffsre C=clk_i D=irq[8] E=$true Q=lirq[8] R=$true S=$true
+.subckt dffsre C=clk_i D=irq[7] E=$true Q=lirq[7] R=$true S=$true
+.subckt dffsre C=clk_i D=irq[6] E=$true Q=lirq[6] R=$true S=$true
+.subckt dffsre C=clk_i D=irq[5] E=$true Q=lirq[5] R=$true S=$true
+.subckt dffsre C=clk_i D=irq[4] E=$true Q=lirq[4] R=$true S=$true
+.subckt dffsre C=clk_i D=irq[3] E=$true Q=lirq[3] R=$true S=$true
+.subckt dffsre C=clk_i D=irq[2] E=$true Q=lirq[2] R=$true S=$true
+.subckt dffsre C=clk_i D=irq[1] E=$true Q=lirq[1] R=$true S=$true
+.subckt dffsre C=clk_i D=dat_i[7] E=we_i_$lut_A_3_Y Q=mask[8] R=$true S=rst_i
+.subckt dffsre C=clk_i D=dat_i[6] E=we_i_$lut_A_3_Y Q=mask[7] R=$true S=rst_i
+.subckt dffsre C=clk_i D=dat_i[5] E=we_i_$lut_A_3_Y Q=mask[6] R=$true S=rst_i
+.subckt dffsre C=clk_i D=dat_i[4] E=we_i_$lut_A_3_Y Q=mask[5] R=$true S=rst_i
+.subckt dffsre C=clk_i D=dat_i[3] E=we_i_$lut_A_3_Y Q=mask[4] R=$true S=rst_i
+.subckt dffsre C=clk_i D=dat_i[2] E=we_i_$lut_A_3_Y Q=mask[3] R=$true S=rst_i
+.subckt dffsre C=clk_i D=dat_i[1] E=we_i_$lut_A_3_Y Q=mask[2] R=$true S=rst_i
+.subckt dffsre C=clk_i D=dat_i[0] E=we_i_$lut_A_3_Y Q=mask[1] R=$true S=rst_i
+.subckt dffsre C=clk_i D=pending_dffsre_Q_D[7] E=$true Q=pending[8] R=rst_i S=$true
+.subckt dffsre C=clk_i D=pending_dffsre_Q_D[6] E=$true Q=pending[7] R=rst_i S=$true
+.subckt dffsre C=clk_i D=pending_dffsre_Q_D[5] E=$true Q=pending[6] R=rst_i S=$true
+.subckt dffsre C=clk_i D=pending_dffsre_Q_D[4] E=$true Q=pending[5] R=rst_i S=$true
+.subckt dffsre C=clk_i D=pending_dffsre_Q_D[3] E=$true Q=pending[4] R=rst_i S=$true
+.subckt dffsre C=clk_i D=pending_dffsre_Q_D[2] E=$true Q=pending[3] R=rst_i S=$true
+.subckt dffsre C=clk_i D=pending_dffsre_Q_D[1] E=$true Q=pending[2] R=rst_i S=$true
+.subckt dffsre C=clk_i D=pending_dffsre_Q_D[0] E=$true Q=pending[1] R=rst_i S=$true
+.subckt dffsre C=clk_i D=dat_i[7] E=we_i_$lut_A_Y Q=pol[8] R=rst_i S=$true
+.subckt dffsre C=clk_i D=dat_i[6] E=we_i_$lut_A_Y Q=pol[7] R=rst_i S=$true
+.subckt dffsre C=clk_i D=dat_i[5] E=we_i_$lut_A_Y Q=pol[6] R=rst_i S=$true
+.subckt dffsre C=clk_i D=dat_i[4] E=we_i_$lut_A_Y Q=pol[5] R=rst_i S=$true
+.subckt dffsre C=clk_i D=dat_i[3] E=we_i_$lut_A_Y Q=pol[4] R=rst_i S=$true
+.subckt dffsre C=clk_i D=dat_i[2] E=we_i_$lut_A_Y Q=pol[3] R=rst_i S=$true
+.subckt dffsre C=clk_i D=dat_i[1] E=we_i_$lut_A_Y Q=pol[2] R=rst_i S=$true
+.subckt dffsre C=clk_i D=dat_i[0] E=we_i_$lut_A_Y Q=pol[1] R=rst_i S=$true
+.names we_i stb_i cyc_i adr_i[1] adr_i[2] we_i_$lut_A_Y
+11110 1
+.names we_i stb_i cyc_i adr_i[1] adr_i[2] we_i_$lut_A_1_Y
+11111 1
+.names irq_event[8] pending[8] dat_i[7] we_i_$lut_A_1_Y pending_dffsre_Q_D[7]
+0100 1
+0101 1
+0110 1
+1000 1
+1001 1
+1010 1
+1011 1
+1100 1
+1101 1
+1110 1
+1111 1
+.names irq_event[7] pending[7] dat_i[6] we_i_$lut_A_1_Y pending_dffsre_Q_D[6]
+0100 1
+0101 1
+0110 1
+1000 1
+1001 1
+1010 1
+1011 1
+1100 1
+1101 1
+1110 1
+1111 1
+.names irq_event[6] pending[6] dat_i[5] we_i_$lut_A_1_Y pending_dffsre_Q_D[5]
+0100 1
+0101 1
+0110 1
+1000 1
+1001 1
+1010 1
+1011 1
+1100 1
+1101 1
+1110 1
+1111 1
+.names irq_event[5] pending[5] dat_i[4] we_i_$lut_A_1_Y pending_dffsre_Q_D[4]
+0100 1
+0101 1
+0110 1
+1000 1
+1001 1
+1010 1
+1011 1
+1100 1
+1101 1
+1110 1
+1111 1
+.names irq_event[4] pending[4] dat_i[3] we_i_$lut_A_1_Y pending_dffsre_Q_D[3]
+0100 1
+0101 1
+0110 1
+1000 1
+1001 1
+1010 1
+1011 1
+1100 1
+1101 1
+1110 1
+1111 1
+.names irq_event[3] pending[3] dat_i[2] we_i_$lut_A_1_Y pending_dffsre_Q_D[2]
+0100 1
+0101 1
+0110 1
+1000 1
+1001 1
+1010 1
+1011 1
+1100 1
+1101 1
+1110 1
+1111 1
+.names irq_event[2] pending[2] dat_i[1] we_i_$lut_A_1_Y pending_dffsre_Q_D[1]
+0100 1
+0101 1
+0110 1
+1000 1
+1001 1
+1010 1
+1011 1
+1100 1
+1101 1
+1110 1
+1111 1
+.names irq_event[1] pending[1] dat_i[0] we_i_$lut_A_1_Y pending_dffsre_Q_D[0]
+0100 1
+0101 1
+0110 1
+1000 1
+1001 1
+1010 1
+1011 1
+1100 1
+1101 1
+1110 1
+1111 1
+.names we_i stb_i cyc_i adr_i[1] adr_i[2] we_i_$lut_A_2_Y
+11100 1
+.names we_i stb_i cyc_i adr_i[2] adr_i[1] we_i_$lut_A_3_Y
+11110 1
+.end
diff --git a/libopenfpga/libpinconstrain/data/simple_pic_cstr_pin.pcf b/libopenfpga/libpinconstrain/data/simple_pic_cstr_pin.pcf
new file mode 100644
index 000000000..a875201c8
--- /dev/null
+++ b/libopenfpga/libpinconstrain/data/simple_pic_cstr_pin.pcf
@@ -0,0 +1,20 @@
+set_io dat_o[0] pad_fpga_io[18]
+set_io dat_o[1] pad_fpga_io[19]
+set_io dat_o[2] pad_fpga_io[20]
+set_io dat_o[3] pad_fpga_io[21]
+set_io dat_o[4] pad_fpga_io[22]
+set_io dat_o[5] pad_fpga_io[23]
+set_io dat_o[6] pad_fpga_io[24]
+set_io dat_o[7] pad_fpga_io[25]
+set_io ack_o pad_fpga_io[26]
+set_io int_o pad_fpga_io[27]
+set_io clk_i pad_fpga_io[28]
+set_io rst_i pad_fpga_io[29]
+set_io cyc_i pad_fpga_io[30]
+set_io stb_i pad_fpga_io[31]
+set_io adr_i[1] pad_fpga_io[32]
+set_io adr_i[2] pad_fpga_io[33]
+set_io we_i pad_fpga_io[60]
+set_io dat_i[0] pad_fpga_io[35]
+set_io dat_i[1] pad_fpga_io[36]
+set_io dat_i[2] pad_fpga_io[37]
diff --git a/libopenfpga/libpinconstrain/src/file_readers/blif_reader.cpp b/libopenfpga/libpinconstrain/src/file_readers/blif_reader.cpp
new file mode 100644
index 000000000..46f6bf68f
--- /dev/null
+++ b/libopenfpga/libpinconstrain/src/file_readers/blif_reader.cpp
@@ -0,0 +1,70 @@
+#include "vtr_path.h"
+#include "read_blif.h"
+#include "blifparse.hpp"
+#include "blif_reader.h"
+
+// blif parser callback
+ using namespace blifparse;
+ class BlifParserCallback : public Callback {
+ public:
+ void start_parse() override {}
+
+ void filename(std::string /*fname*/) override {}
+ void lineno(int /*line_num*/) override {}
+
+ void begin_model(std::string /*model_name*/) override {}
+ void inputs(std::vector input_ports) override {
+ for (auto input_port : input_ports) {
+ inputs_.push_back(input_port);
+ }
+ }
+ void outputs(std::vector output_ports) override {
+ for (auto output_port : output_ports) {
+ outputs_.push_back(output_port);
+ }
+ }
+
+ void names(std::vector /*nets*/, std::vector> /*so_cover*/) override {}
+ void latch(std::string /*input*/, std::string /*output*/, LatchType /* type*/, std::string /*control*/, LogicValue /*init*/) override {}
+ void subckt(std::string /*model*/, std::vector /*ports*/, std:: vector /*nets*/) override {}
+ void blackbox() override {}
+
+ void end_model() override {}
+
+ void finish_parse() override {}
+
+ void parse_error(const int curr_lineno, const std::string& near_text, const std::string& msg) override {
+ fprintf(stderr, "Custom Error at line %d near '%s': %s\n", curr_lineno, near_text.c_str(), msg.c_str());
+ had_error_ = true;
+ }
+
+ bool had_error() { return had_error_ == true; }
+ std::vector get_inputs() { return inputs_;}
+ std::vector get_outputs() { return outputs_;}
+ private:
+ bool had_error_ = false;
+ std::vector inputs_;
+ std::vector outputs_;
+};
+
+// read port info from blif file
+bool BlifReader::read_blif(const std::string &blif_file_name)
+{
+ e_circuit_format circuit_format;
+ auto name_ext = vtr::split_ext(blif_file_name);
+ if (name_ext[1] == ".blif") {
+ circuit_format = e_circuit_format::BLIF;
+ } else if (name_ext[1] == ".eblif") {
+ circuit_format = e_circuit_format::EBLIF;
+ } else {
+ return false;
+ }
+ BlifParserCallback callback;
+ blif_parse_filename(blif_file_name, callback);
+ if (callback.had_error()) {
+ return false;
+ }
+ inputs = callback.get_inputs();
+ outputs = callback.get_outputs();
+ return true;
+}
diff --git a/libopenfpga/libpinconstrain/src/file_readers/blif_reader.h b/libopenfpga/libpinconstrain/src/file_readers/blif_reader.h
new file mode 100644
index 000000000..ab5829a4f
--- /dev/null
+++ b/libopenfpga/libpinconstrain/src/file_readers/blif_reader.h
@@ -0,0 +1,37 @@
+#ifndef BLIF_READER_H
+#define BLIF_READER_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include