[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