[lib] deprecate libpinconstrain
This commit is contained in:
parent
cde7a130d3
commit
1d0cad9f96
|
@ -1,40 +0,0 @@
|
|||
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})
|
|
@ -1,3 +0,0 @@
|
|||
set_io a pad_fpga_io[0]
|
||||
set_io b pad_fpga_io[4]
|
||||
set_io c pad_fpga_io[6]
|
|
@ -1,17 +0,0 @@
|
|||
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[0],,,
|
||||
TOP,,,,gfpga_pad_IO_F2A[0],pad_fpga_io[0],,,
|
||||
TOP,,,,gfpga_pad_IO_A2F[4],pad_fpga_io[1],,,
|
||||
TOP,,,,gfpga_pad_IO_F2A[4],pad_fpga_io[1],,,
|
||||
TOP,,,,gfpga_pad_IO_A2F[8],pad_fpga_io[2],,,
|
||||
TOP,,,,gfpga_pad_IO_F2A[8],pad_fpga_io[2],,,
|
||||
TOP,,,,gfpga_pad_IO_A2F[31],pad_fpga_io[3],,,
|
||||
TOP,,,,gfpga_pad_IO_F2A[31],pad_fpga_io[3],,,
|
||||
RIGHT,,,,gfpga_pad_IO_A2F[32],pad_fpga_io[4],,,
|
||||
RIGHT,,,,gfpga_pad_IO_F2A[32],pad_fpga_io[4],,,
|
||||
RIGHT,,,,gfpga_pad_IO_A2F[40],pad_fpga_io[5],,,
|
||||
RIGHT,,,,gfpga_pad_IO_F2A[40],pad_fpga_io[5],,,
|
||||
BOTTOM,,,,gfpga_pad_IO_A2F[64],pad_fpga_io[6],,,
|
||||
BOTTOM,,,,gfpga_pad_IO_F2A[64],pad_fpga_io[6],,,
|
||||
LEFT,,,,gfpga_pad_IO_F2A[127],pad_fpga_io[7],,,
|
||||
LEFT,,,,gfpga_pad_IO_A2F[127],pad_fpga_io[7],,,
|
|
|
@ -1,28 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
XML file specification is primarily to define the mapping of the interface cell ports defined
|
||||
in vpr_arch xml, to the EFPGA IO interface port names. This mapping is required by OpenFPGA
|
||||
alongwith architecture definition file i.e. vpr_arch xml file. OpenFPGA will process this
|
||||
file and use this information for IO placement and then later on use this to map it with the
|
||||
user-defined pin-mapping file.
|
||||
-->
|
||||
<DEVICE name= "k4_N4_tileable_40nm" family="k4n4" width="6" height="6" z="8">
|
||||
<IO>
|
||||
<TOP_IO y="5">
|
||||
<CELL port_name="output" mapped_name="gfpga_pad_IO_F2A[0:31]" startx="1" endx="4"/>
|
||||
<CELL port_name="input" mapped_name="gfpga_pad_IO_A2F[0:31]" startx="1" endx="4"/>
|
||||
</TOP_IO>
|
||||
<RIGHT_IO x="5">
|
||||
<CELL port_name="output" mapped_name="gfpga_pad_IO_F2A[32:63]" starty="4" endy="1"/>
|
||||
<CELL port_name="input" mapped_name="gfpga_pad_IO_A2F[32:63]" starty="4" endy="1"/>
|
||||
</RIGHT_IO>
|
||||
<BOTTOM_IO y="0">
|
||||
<CELL port_name="output" mapped_name="gfpga_pad_IO_F2A[64:95]" startx="4" endx="1"/>
|
||||
<CELL port_name="input" mapped_name="gfpga_pad_IO_A2F[64:95]" startx="4" endx="1"/>
|
||||
</BOTTOM_IO>
|
||||
<LEFT_IO x="0">
|
||||
<CELL port_name="output" mapped_name="gfpga_pad_IO_F2A[96:127]" starty="1" endy="4"/>
|
||||
<CELL port_name="input" mapped_name="gfpga_pad_IO_A2F[96:127]" starty="1" endy="4"/>
|
||||
</LEFT_IO>
|
||||
</IO>
|
||||
</DEVICE>
|
|
@ -1,71 +0,0 @@
|
|||
#include "vtr_path.h"
|
||||
#include "read_blif.h"
|
||||
#include "blifparse.hpp"
|
||||
#include "blif_reader.h"
|
||||
#include "vtr_log.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<std::string> input_ports) override {
|
||||
for (auto input_port : input_ports) {
|
||||
inputs_.push_back(input_port);
|
||||
}
|
||||
}
|
||||
void outputs(std::vector<std::string> output_ports) override {
|
||||
for (auto output_port : output_ports) {
|
||||
outputs_.push_back(output_port);
|
||||
}
|
||||
}
|
||||
|
||||
void names(std::vector<std::string> /*nets*/, std::vector<std:: vector<LogicValue>> /*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<std::string> /*ports*/, std:: vector<std::string> /*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 {
|
||||
VTR_LOG_ERROR("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<std::string> get_inputs() { return inputs_;}
|
||||
std::vector<std::string> get_outputs() { return outputs_;}
|
||||
private:
|
||||
bool had_error_ = false;
|
||||
std::vector<std::string> inputs_;
|
||||
std::vector<std::string> 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;
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
#ifndef BLIF_READER_H
|
||||
#define BLIF_READER_H
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
|
||||
/*
|
||||
Supported PCF commands:
|
||||
|
||||
* set_io <net> <pad> - constrain a given <net> to a given physical <pad> in eFPGA pinout.
|
||||
* set_clk <pin> <net> - constrain a given global clock <pin> to a given <net>
|
||||
|
||||
Every tile where <net> is present will be constrained to use a given global clock.
|
||||
*/
|
||||
using namespace std;
|
||||
class BlifReader
|
||||
{
|
||||
vector<string> inputs;
|
||||
vector<string> outputs;
|
||||
|
||||
public:
|
||||
BlifReader() {}
|
||||
BlifReader(const std::string &f)
|
||||
{
|
||||
read_blif(f);
|
||||
}
|
||||
bool read_blif(const std::string &f);
|
||||
const vector<string>& get_inputs()const { return inputs;}
|
||||
const vector<string>& get_outputs()const { return outputs;}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,53 +0,0 @@
|
|||
#include "csv_reader.h"
|
||||
#include <algorithm>
|
||||
#include "vtr_log.h"
|
||||
|
||||
|
||||
bool CvsReader::read_cvs(const std::string &f)
|
||||
{
|
||||
std::ifstream infile(f);
|
||||
if (!infile.is_open())
|
||||
{
|
||||
VTR_LOG_ERROR("ERROR: cound not open the file %s.\n", f.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string line;
|
||||
while (std::getline(infile, line))
|
||||
{
|
||||
// cout << line << " - " << endl;
|
||||
if (!line.size())
|
||||
continue;
|
||||
entries.push_back(vector<string>());
|
||||
entries.back().push_back(string(""));
|
||||
for (auto c : line)
|
||||
{
|
||||
if (isspace(c))
|
||||
continue;
|
||||
if (c == ',')
|
||||
{
|
||||
entries.back().push_back(string(""));
|
||||
}
|
||||
else
|
||||
entries.back().back().push_back(c);
|
||||
}
|
||||
}
|
||||
std::vector<string> first_v = entries[0];
|
||||
auto result1 = std::find(first_v.begin(), first_v.end(), "port_name");
|
||||
vector<string>::iterator result2 = find(first_v.begin(), first_v.end(), "mapped_pin");
|
||||
int port_name_index = distance(first_v.begin(), result1);
|
||||
int mapped_pin_index = distance(first_v.begin(), result2);
|
||||
|
||||
for (auto &v : entries)
|
||||
{
|
||||
string port_name = v[port_name_index];
|
||||
string mapped_pin = v[mapped_pin_index];
|
||||
port_map.insert(std::pair<std::string, string>(mapped_pin, port_name));
|
||||
//for (auto &s : v)
|
||||
//{
|
||||
// cout << s << " - ";
|
||||
//}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
#ifndef CVS_READER_H
|
||||
#define CVS_READER_H
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <ctype.h>
|
||||
#include <map>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class CvsReader
|
||||
{
|
||||
vector<vector<string>> entries;
|
||||
map<string, string> port_map;
|
||||
public:
|
||||
CvsReader() {}
|
||||
bool read_cvs(const std::string &f);
|
||||
const vector<vector<string>>& get_entries()const { return entries;}
|
||||
const map<string, string>& get_port_map()const { return port_map;}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,27 +0,0 @@
|
|||
#include "pcf_reader.h"
|
||||
#include "vtr_log.h"
|
||||
|
||||
bool PcfReader::read_pcf(const std::string &f)
|
||||
{
|
||||
std::ifstream infile(f);
|
||||
if (!infile.is_open())
|
||||
{
|
||||
VTR_LOG_ERROR("ERROR: cound not open the file %s.\n", f.c_str());
|
||||
return false;
|
||||
}
|
||||
std::string line;
|
||||
while (std::getline(infile, line))
|
||||
{
|
||||
std::istringstream iss(line);
|
||||
std::string a, b, c;
|
||||
if (!(iss >> a >> b >> c))
|
||||
{
|
||||
break;
|
||||
} // error
|
||||
commands.push_back(std::vector<std::string>());
|
||||
commands.back().push_back(a);
|
||||
commands.back().push_back(b);
|
||||
commands.back().push_back(c);
|
||||
}
|
||||
return true;
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
#ifndef PCF_READER_H
|
||||
#define PCF_READER_H
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
|
||||
/*
|
||||
Supported PCF commands:
|
||||
|
||||
* set_io <net> <pad> - constrain a given <net> to a given physical <pad> in eFPGA pinout.
|
||||
* set_clk <pin> <net> - constrain a given global clock <pin> to a given <net>
|
||||
|
||||
Every tile where <net> is present will be constrained to use a given global clock.
|
||||
*/
|
||||
class PcfReader
|
||||
{
|
||||
std::vector<std::vector<std::string>> commands;
|
||||
|
||||
public:
|
||||
PcfReader() {}
|
||||
PcfReader(const std::string &f)
|
||||
{
|
||||
read_pcf(f);
|
||||
}
|
||||
bool read_pcf(const std::string &f);
|
||||
const std::vector<std::vector<std::string>>& get_commands()const { return commands;}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,243 +0,0 @@
|
|||
#include "xml_reader.h"
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
|
||||
//======================================================================
|
||||
std::vector<std::string> XmlReader::vec_to_scalar(std::string str)
|
||||
{
|
||||
auto open_bracket_pos = str.find("[");
|
||||
auto close_bracket_pos = str.find("]");
|
||||
auto colon_pos = str.find(":");
|
||||
std::vector<std::string> scalar_ports;
|
||||
|
||||
//Parse checks
|
||||
if (open_bracket_pos == std::string::npos && close_bracket_pos != std::string::npos) {
|
||||
//Close brace only
|
||||
std::string msg = "near '" + str + "', missing '['";
|
||||
std::cerr << " ERROR: " << msg << std::endl;
|
||||
}
|
||||
|
||||
if (open_bracket_pos != std::string::npos && close_bracket_pos == std::string::npos) {
|
||||
//Open brace only
|
||||
std::string msg = "near '" + str + "', missing ']'";
|
||||
std::cerr << " ERROR: " << msg << std::endl;
|
||||
}
|
||||
|
||||
if (open_bracket_pos != std::string::npos && close_bracket_pos != std::string::npos) {
|
||||
//Have open and close braces, close must be after open
|
||||
if (open_bracket_pos > close_bracket_pos) {
|
||||
std::string msg = "near '" + str + "', '[' after ']'";
|
||||
std::cerr << " ERROR: " << msg << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (colon_pos != std::string::npos) {
|
||||
//Have a colon, it must be between open/close braces
|
||||
if (colon_pos > close_bracket_pos || colon_pos < open_bracket_pos) {
|
||||
std::string msg = "near '" + str + "', found ':' but not between '[' and ']'";
|
||||
std::cerr << " ERROR: " << msg << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::string name = str.substr(0, open_bracket_pos);
|
||||
std::string first_idx_str;
|
||||
std::string second_idx_str;
|
||||
|
||||
if (colon_pos == std::string::npos && open_bracket_pos == std::string::npos && close_bracket_pos == std::string::npos) {
|
||||
} else if (colon_pos == std::string::npos) {
|
||||
first_idx_str = str.substr(open_bracket_pos + 1, close_bracket_pos);
|
||||
second_idx_str = first_idx_str;
|
||||
} else {
|
||||
first_idx_str = str.substr(open_bracket_pos + 1, colon_pos);
|
||||
second_idx_str = str.substr(colon_pos + 1, close_bracket_pos);
|
||||
}
|
||||
|
||||
int first_idx = std::stoi(first_idx_str);
|
||||
int second_idx = std::stoi(second_idx_str);
|
||||
|
||||
if (first_idx < second_idx)
|
||||
{
|
||||
for(int i=first_idx; i < second_idx+1; i++)
|
||||
{
|
||||
std::string curr_port_name = name + '[' + std::to_string(i) + ']';
|
||||
scalar_ports.push_back(curr_port_name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i=first_idx; i >= second_idx ; i--)
|
||||
{
|
||||
std::string curr_port_name = name + '[' + std::to_string(i) + ']';
|
||||
scalar_ports.push_back(curr_port_name);
|
||||
}
|
||||
}
|
||||
return scalar_ports;
|
||||
}
|
||||
//======================================================================
|
||||
bool XmlReader::parse_io_cell (const pugi::xml_node xml_orient_io, const int row_or_col, const int io_per_cell, std::map<std::string, PinMappingData> *port_map)
|
||||
{
|
||||
pugi::xpath_node_set cells = xml_orient_io.select_nodes("CELL");
|
||||
for (pugi::xpath_node_set::const_iterator it = cells.begin(); it != cells.end(); ++it)
|
||||
{
|
||||
pugi::xpath_node node = *it;
|
||||
int startx, starty, endx, endy, i, j, x, y;
|
||||
std::string port_name = node.node().attribute("port_name").as_string();
|
||||
std::string mapped_name = node.node().attribute("mapped_name").as_string();
|
||||
std::vector<std::string> scalar_mapped_pins = vec_to_scalar(mapped_name);
|
||||
i = 0;
|
||||
|
||||
if (node.node().attribute("startx") && node.node().attribute("endx"))
|
||||
{
|
||||
startx = node.node().attribute("startx").as_int();
|
||||
endx = node.node().attribute("endx").as_int();
|
||||
y = row_or_col;
|
||||
if (startx < endx)
|
||||
{
|
||||
for (x=startx; x < endx+1; x++)
|
||||
{
|
||||
for (j=0; j < io_per_cell; j++)
|
||||
{
|
||||
std::string mapped_pin = scalar_mapped_pins[i];
|
||||
PinMappingData pinMapData = PinMappingData(port_name, mapped_pin, x, y, j);
|
||||
port_map->insert(std::pair<std::string, PinMappingData>(mapped_pin, pinMapData));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (x=startx; x >= endx; x--)
|
||||
{
|
||||
for (j=0; j < io_per_cell; j++)
|
||||
{
|
||||
std::string mapped_pin = scalar_mapped_pins[i];
|
||||
PinMappingData pinMapData = PinMappingData(port_name, mapped_pin, x, y, j);
|
||||
port_map->insert(std::pair<std::string, PinMappingData>(mapped_pin, pinMapData));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node.node().attribute("starty") && node.node().attribute("endy").value())
|
||||
{
|
||||
starty = node.node().attribute("starty").as_int();
|
||||
endy = node.node().attribute("endy").as_int();
|
||||
x = row_or_col;
|
||||
if (starty < endy)
|
||||
{
|
||||
for (y=starty; y < endy+1; y++)
|
||||
{
|
||||
for (j=0; j < io_per_cell; j++)
|
||||
{
|
||||
std::string mapped_pin = scalar_mapped_pins[i];
|
||||
PinMappingData pinMapData = PinMappingData(port_name, mapped_pin, x, y, j);
|
||||
port_map->insert(std::pair<std::string, PinMappingData>(mapped_pin, pinMapData));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (y=starty; y >= endy; y--)
|
||||
{
|
||||
for (j=0; j < io_per_cell; j++)
|
||||
{
|
||||
std::string mapped_pin = scalar_mapped_pins[i];
|
||||
PinMappingData pinMapData = PinMappingData(port_name, mapped_pin, x, y, j);
|
||||
port_map->insert(std::pair<std::string, PinMappingData>(mapped_pin, pinMapData));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
bool XmlReader::parse_io (const pugi::xml_node xml_io, const int width, const int height, const int io_per_cell, std::map<std::string, PinMappingData> *port_map)
|
||||
{
|
||||
pugi::xml_node xml_top_io = xml_io.child("TOP_IO");
|
||||
if (!xml_top_io)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int io_row_top = height - 1;
|
||||
if (xml_top_io.attribute("y"))
|
||||
io_row_top = xml_top_io.attribute("y").as_int();
|
||||
|
||||
pugi::xml_node xml_bottom_io = xml_io.child("BOTTOM_IO");
|
||||
if (!xml_bottom_io)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int io_row_bottom = 0;
|
||||
if (xml_bottom_io.attribute("y"))
|
||||
io_row_bottom = xml_bottom_io.attribute("y").as_int();
|
||||
|
||||
pugi::xml_node xml_left_io = xml_io.child("LEFT_IO");
|
||||
if (!xml_left_io)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int io_col_left = 0;
|
||||
if (xml_left_io.attribute("x"))
|
||||
io_col_left = xml_left_io.attribute("x").as_int();
|
||||
pugi::xml_node xml_right_io = xml_io.child("RIGHT_IO");
|
||||
if (!xml_right_io)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int io_col_right = width - 1;
|
||||
if (xml_right_io.attribute("x"))
|
||||
io_col_right = xml_right_io.attribute("x").as_int();
|
||||
|
||||
|
||||
if (!parse_io_cell (xml_top_io, io_row_top, io_per_cell, port_map))
|
||||
return false;
|
||||
if (!parse_io_cell (xml_bottom_io, io_row_bottom, io_per_cell, port_map))
|
||||
return false;
|
||||
if (!parse_io_cell (xml_right_io, io_col_right, io_per_cell, port_map))
|
||||
return false;
|
||||
if (!parse_io_cell (xml_left_io, io_col_left, io_per_cell, port_map))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
//======================================================================
|
||||
|
||||
bool XmlReader::read_xml(const std::string &f)
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
std::ifstream infile(f);
|
||||
if (!infile.is_open())
|
||||
{
|
||||
std::cerr << "ERROR: cound not open the file " << f << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
pugi::xml_parse_result result = doc.load_file(f.c_str());
|
||||
|
||||
if (!result)
|
||||
return false;
|
||||
|
||||
pugi::xml_node device = doc.child("DEVICE");
|
||||
if (!device)
|
||||
return false;
|
||||
|
||||
int width = device.attribute("width").as_int();
|
||||
int height = device.attribute("height").as_int();
|
||||
int z = device.attribute("z").as_int();
|
||||
if (z <= 0)
|
||||
return false;
|
||||
|
||||
pugi::xml_node xml_io = device.child("IO");
|
||||
if (!xml_io)
|
||||
return false;
|
||||
|
||||
if (!parse_io (xml_io, width, height, z, &port_map_))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
#ifndef XML_READER_H
|
||||
#define XML_READER_H
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "pugixml.hpp"
|
||||
|
||||
class PinMappingData
|
||||
{
|
||||
public:
|
||||
PinMappingData(std::string p_name, std::string map_pin, int x, int y, int z):port_name_(p_name), mapped_pin_(map_pin), x_(x), y_(y), z_(z){}
|
||||
std::string get_port_name () { return port_name_; }
|
||||
std::string get_mapped_pin () { return mapped_pin_; }
|
||||
int get_x () { return x_; }
|
||||
int get_y () { return y_; }
|
||||
int get_z () { return z_; }
|
||||
private:
|
||||
std::string port_name_;
|
||||
std::string mapped_pin_;
|
||||
int x_;
|
||||
int y_;
|
||||
int z_;
|
||||
|
||||
};
|
||||
|
||||
class XmlReader
|
||||
{
|
||||
std::map<std::string, PinMappingData> port_map_;
|
||||
public:
|
||||
XmlReader() {}
|
||||
bool read_xml(const std::string &f);
|
||||
const std::map<std::string, PinMappingData>& get_port_map()const { return port_map_;}
|
||||
std::vector<std::string> vec_to_scalar(std::string str);
|
||||
bool parse_io_cell (const pugi::xml_node xml_orient_io, const int row_or_col, const int io_per_cell, std::map<std::string, PinMappingData> *port_map);
|
||||
bool parse_io (const pugi::xml_node xml_io, const int width, const int height, const int io_per_cell, std::map<std::string, PinMappingData> *port_map);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,23 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
#include "csv_reader.h"
|
||||
#include "pcf_reader.h"
|
||||
#include "xml_reader.h"
|
||||
#include "cmd_line.h"
|
||||
// #include "pin_location.h"
|
||||
#include "pin_constrain_loc.h"
|
||||
|
||||
// Convert a PCF file into a VPR io.place file.
|
||||
// This requires : XML file where we can get (x, y, z) of internal port
|
||||
// CSV file where we have the maching list (external, internal) ports
|
||||
// PCF file: constraint file. a design pin can be assigned to an external port
|
||||
// BLIF file: user design. We need to check the input and output. Special handling for outputs
|
||||
// The output is a file constraint in VPR format.
|
||||
// Usage options: --xml PINMAP_XML --pcf PCF --blif BLIF --output OUTPUT --xml PINMAP_XML --csv CSV_FILE
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
cmd_line cmd(argc, argv);
|
||||
|
||||
return pin_constrain_location_cmd_line(cmd);
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
#include "pin_location.h"
|
||||
#include "cmd_line.h"
|
||||
#include "pin_constrain_loc.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
// wraper function to do the real job, it is used by openfpga shell as well
|
||||
// this gurantees same behavior
|
||||
int pin_constrain_location (vector<string> args) {
|
||||
if (args.size() != PIN_C_ARGUMENT_NUMBER ) {
|
||||
return 1;
|
||||
}
|
||||
const char* pin_c_args [PIN_C_ARGUMENT_NUMBER];
|
||||
for (int i = 0; i < PIN_C_ARGUMENT_NUMBER; i++) {
|
||||
pin_c_args[i] = const_cast<char*> (args[i].c_str());
|
||||
}
|
||||
cmd_line pin_c_cmd (PIN_C_ARGUMENT_NUMBER, pin_c_args);
|
||||
return pin_constrain_location_cmd_line(pin_c_cmd);
|
||||
}
|
||||
|
||||
// base function for both openfpga wrapper and pin_c executable
|
||||
int pin_constrain_location_cmd_line (cmd_line& cmd) {
|
||||
pin_location pl (cmd);
|
||||
//pl.get_cmd().print_options();
|
||||
if (!pl.reader_and_writer()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
#include "pin_location.h"
|
||||
#include "cmd_line.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
// wraper function to do the real job, it is used by openfpga shell as well
|
||||
// this gurantees same behavior
|
||||
int pin_constrain_location (std::vector<std::string> args);
|
||||
|
||||
// base function for both openfpga wrapper and pin_c executable
|
||||
int pin_constrain_location_cmd_line (cmd_line& cmd);
|
||||
|
|
@ -1,141 +0,0 @@
|
|||
|
||||
#include "csv_reader.h"
|
||||
#include "pcf_reader.h"
|
||||
#include "xml_reader.h"
|
||||
#include "blif_reader.h"
|
||||
#include "cmd_line.h"
|
||||
#include "pin_location.h"
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include "vtr_log.h"
|
||||
|
||||
const string USAGE_MSG = "usage options: --xml PINMAP_XML --pcf PCF --blif BLIF --csv CSV_FILE --output OUTPUT";
|
||||
const cmd_line & pin_location::get_cmd() const
|
||||
{
|
||||
return cl_;
|
||||
}
|
||||
|
||||
bool pin_location::reader_and_writer()
|
||||
{
|
||||
cmd_line cmd = cl_;
|
||||
string xml_name = cmd.get_param("--xml");
|
||||
string csv_name = cmd.get_param("--csv");
|
||||
string pcf_name = cmd.get_param("--pcf");
|
||||
string blif_name = cmd.get_param("--blif");
|
||||
string output_name = cmd.get_param("--output");
|
||||
if ((xml_name == "") || (csv_name == "") || (pcf_name == "") || (blif_name == "")|| (output_name == "") )
|
||||
{
|
||||
VTR_LOG_ERROR("%s\n %s\n", error_messages[MISSING_IN_OUT_FILES].c_str(), USAGE_MSG.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
XmlReader rd_xml;
|
||||
if (!rd_xml.read_xml(xml_name))
|
||||
{
|
||||
VTR_LOG_ERROR("%s.\n", error_messages[PIN_LOC_XML_PARSE_ERROR].c_str());
|
||||
return false;
|
||||
}
|
||||
std::map<std::string, PinMappingData> xml_port_map = rd_xml.get_port_map();
|
||||
|
||||
CvsReader rd_csv;
|
||||
if (!rd_csv.read_cvs(csv_name))
|
||||
{
|
||||
VTR_LOG_ERROR("%s.\n", error_messages[PIN_MAP_CSV_PARSE_ERROR].c_str());
|
||||
return false;
|
||||
}
|
||||
map<string, string> csv_port_map = rd_csv.get_port_map();
|
||||
|
||||
PcfReader rd_pcf;
|
||||
if (!rd_pcf.read_pcf(pcf_name))
|
||||
{
|
||||
VTR_LOG_ERROR("%s.\n", error_messages[PIN_CONSTRAINT_PARSE_ERROR].c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// read port info from blif file
|
||||
BlifReader rd_blif;
|
||||
if (!rd_blif.read_blif(blif_name)) {
|
||||
VTR_LOG_ERROR("%s.\n", error_messages[INPUT_DESIGN_PARSE_ERROR].c_str());
|
||||
return false;
|
||||
}
|
||||
std::vector<std::string> inputs = rd_blif.get_inputs();
|
||||
std::vector<std::string> outputs = rd_blif.get_outputs();
|
||||
|
||||
std::ofstream out_file;
|
||||
out_file.open(output_name);
|
||||
out_file << "#Block Name x y z\n";
|
||||
out_file << "#------------ -- -- -\n";
|
||||
|
||||
vector<vector<string>> pcf_pin_cstr = rd_pcf.get_commands();
|
||||
std::set<std::string> constrained_ports, constrained_pins;
|
||||
for (auto pin_cstr_v : pcf_pin_cstr)
|
||||
{
|
||||
if ((pin_cstr_v[0] != "set_io") && (pin_cstr_v[0] != "set_clk"))
|
||||
continue;
|
||||
|
||||
string pin_name = pin_cstr_v[1];
|
||||
string cstr_name = pin_cstr_v[2];
|
||||
auto found_in = std::find(inputs.begin(), inputs.end(), pin_name);
|
||||
bool valid = false, is_out = false;
|
||||
|
||||
if (found_in != inputs.end())
|
||||
valid = true;
|
||||
else
|
||||
{
|
||||
auto found_out = std::find(outputs.begin(), outputs.end(), pin_name);
|
||||
if (found_out != outputs.end())
|
||||
{
|
||||
valid = true;
|
||||
is_out = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
VTR_LOG_ERROR("%s: <%s>.\n", error_messages[CONSTRAINED_PORT_NOT_FOUND].c_str(), pin_name.c_str());
|
||||
out_file.close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (constrained_ports.find(pin_name) == constrained_ports.end()) {
|
||||
constrained_ports.insert(pin_name);
|
||||
} else {
|
||||
VTR_LOG_ERROR("%s: <%s>.\n", error_messages[RE_CONSTRAINED_PORT].c_str(), pin_name.c_str());
|
||||
out_file.close();
|
||||
return false;
|
||||
}
|
||||
if (!valid)
|
||||
continue;
|
||||
|
||||
std::string content_to_write;
|
||||
|
||||
// Get the the intternal port from the CSV file
|
||||
auto element_cstr = csv_port_map.find(cstr_name);
|
||||
if (element_cstr != csv_port_map.end())
|
||||
{
|
||||
|
||||
if (constrained_pins.find(cstr_name) == constrained_pins.end()) {
|
||||
constrained_pins.insert(cstr_name);
|
||||
} else {
|
||||
VTR_LOG_ERROR("%s: <%s>.\n", error_messages[OVERLAP_PIN_IN_CONSTRAINT].c_str(), cstr_name.c_str());
|
||||
out_file.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the (x, y, z) from the XML reader
|
||||
PinMappingData pinMapData = xml_port_map.at(element_cstr->second);
|
||||
if (is_out)
|
||||
{
|
||||
content_to_write += "out:";
|
||||
}
|
||||
content_to_write += pin_name + " " + std::to_string(pinMapData.get_x()) + " " + std::to_string(pinMapData.get_y()) + " " + std::to_string(pinMapData.get_z()) + "\n";
|
||||
} else {
|
||||
VTR_LOG_ERROR("%s: <%s>.\n", error_messages[CONSTRAINED_PIN_NOT_FOUND].c_str(), cstr_name.c_str());
|
||||
out_file.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
out_file << content_to_write;
|
||||
}
|
||||
out_file.close();
|
||||
|
||||
return true;
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
#ifndef PIN_LOCATION_H
|
||||
#define PIN_LOCATION_H
|
||||
#include "cmd_line.h"
|
||||
|
||||
// number of arguments for "pin_c", inlcuding the "pin_c" command itself
|
||||
#define PIN_C_ARGUMENT_NUMBER 11
|
||||
class pin_location {
|
||||
private:
|
||||
// error messages to be printed out with std::cerr
|
||||
enum {
|
||||
MISSING_IN_OUT_FILES = 0,
|
||||
PIN_LOC_XML_PARSE_ERROR,
|
||||
PIN_MAP_CSV_PARSE_ERROR,
|
||||
PIN_CONSTRAINT_PARSE_ERROR,
|
||||
INPUT_DESIGN_PARSE_ERROR,
|
||||
CONSTRAINED_PORT_NOT_FOUND,
|
||||
CONSTRAINED_PIN_NOT_FOUND,
|
||||
RE_CONSTRAINED_PORT,
|
||||
OVERLAP_PIN_IN_CONSTRAINT,
|
||||
MAX_MESSAGE_ID
|
||||
};
|
||||
std::string error_messages[MAX_MESSAGE_ID] = {
|
||||
"Missing input or output file arguments", // MISSING_IN_OUT_FILES
|
||||
"Pin location file parse error", // PIN_LOC_XML_PARSE_ERROR
|
||||
"Pin map file parse error", // PIN_MAP_CSV_PARSE_ERROR
|
||||
"Pin constraint file parse error", // PIN_CONSTRAINT_PARSE_ERROR
|
||||
"Input design parse error", // INPUT_DESIGN_PARSE_ERROR
|
||||
"Constrained port not found in design", // CONSTRAINED_PORT_NOT_FOUND
|
||||
"Constrained pin not found in device", // CONSTRAINED_PIN_NOT_FOUND
|
||||
"Re-constrained port", // RE_CONSTRAINED_PORT
|
||||
"Overlap pin found in constraint" // OVERLAP_PIN_IN_CONSTRAINT
|
||||
};
|
||||
|
||||
cmd_line cl_;
|
||||
|
||||
public:
|
||||
pin_location(cmd_line& cl): cl_(cl){
|
||||
|
||||
}
|
||||
const cmd_line& get_cmd()const;
|
||||
bool reader_and_writer();
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
|
@ -1,77 +0,0 @@
|
|||
#include "cmd_line.h"
|
||||
|
||||
cmd_line::cmd_line(int argc, const char *argv[])
|
||||
{
|
||||
bool needVal = false;
|
||||
string key;
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
string s(argv[i]);
|
||||
if (s.size() < 2)
|
||||
{
|
||||
cout << "Warning: Not a valid flag \"" << s << "\" discarding" << endl;
|
||||
continue;
|
||||
}
|
||||
if ('-' == s[0])
|
||||
{
|
||||
if ('-' == s[1])
|
||||
{ // param key
|
||||
if (needVal)
|
||||
cout << "Warning: Key " << key << " did not get a value" << endl;
|
||||
needVal = true;
|
||||
key = s;
|
||||
}
|
||||
else
|
||||
{ // flag
|
||||
flags.insert(s);
|
||||
if (needVal)
|
||||
cout << "Warning: Key " << key << " did not get a value" << endl;
|
||||
needVal = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // param value
|
||||
if (needVal)
|
||||
{
|
||||
params[key] = s;
|
||||
needVal = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "Warning: No key for value " << s << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool cmd_line::is_flag_set(string &fl)
|
||||
{
|
||||
return (flags.find(fl) != end(flags));
|
||||
}
|
||||
|
||||
string cmd_line::get_param(const string &key)
|
||||
{
|
||||
if (params.find(key) != end(params))
|
||||
return params[key];
|
||||
return "";
|
||||
}
|
||||
|
||||
void cmd_line::set_flag(string &fl)
|
||||
{
|
||||
flags.insert(fl);
|
||||
}
|
||||
|
||||
void cmd_line::set_param_value(string &key, string &val)
|
||||
{
|
||||
params[key] = val;
|
||||
}
|
||||
|
||||
void cmd_line::print_options() const
|
||||
{
|
||||
cout << "Flags :\n";
|
||||
for (auto &f : flags)
|
||||
cout << "\t" << f << endl;
|
||||
cout << "Params :\n";
|
||||
for (auto &p : params)
|
||||
cout << "\t" << p.first << "\t" << p.second << endl;
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
#ifndef CMD_LINE
|
||||
#define CMD_LINE
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
using namespace std;
|
||||
class cmd_line
|
||||
{
|
||||
unordered_map<string, string> params;
|
||||
unordered_set<string> flags;
|
||||
|
||||
public:
|
||||
cmd_line(int argc, const char *argv[]);
|
||||
const unordered_set<string> &get_flag_set() const { return flags; }
|
||||
const unordered_map<string, string> get_param_map() const { return params; }
|
||||
bool is_flag_set(string &fl);
|
||||
string get_param(const string &key);
|
||||
void set_flag(string &fl);
|
||||
void set_param_value(string &key, string &val);
|
||||
void print_options() const;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,30 +0,0 @@
|
|||
|
||||
/********************************************************************
|
||||
* 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"
|
||||
#include "cmd_line.h"
|
||||
#include "pin_location.h"
|
||||
#include "pin_constrain_loc.h"
|
||||
|
||||
int main(int argc, const char** argv) {
|
||||
VTR_ASSERT(argc == PIN_C_ARGUMENT_NUMBER);
|
||||
string command_line;
|
||||
for (int i = 0; i < argc; i++) {
|
||||
if (i > 0) {
|
||||
command_line += " ";
|
||||
}
|
||||
command_line += argv[i];
|
||||
}
|
||||
VTR_LOG("Created command line <%s> for test.\n", command_line.c_str());
|
||||
cmd_line pin_c_cmd (argc, argv);
|
||||
VTR_LOG("Testing reader and writer.\n");
|
||||
int status = pin_constrain_location_cmd_line(pin_c_cmd);
|
||||
VTR_LOG("Test result: %s.\n", status == 0 ? "PASS" : "FAIL");
|
||||
return status;
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
set_io a pad_fpga_io[0]
|
||||
set_io b pad_fpga_io[4]
|
||||
set_io c pad_fpga_io[6]
|
Loading…
Reference in New Issue