add direct annotation with inter-column/row syntax

This commit is contained in:
tangxifan 2020-02-14 17:40:59 -07:00
parent c855ab24f5
commit 59c13550e0
15 changed files with 372 additions and 65 deletions

View File

@ -266,7 +266,7 @@
<segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment>
<direct_connection>
<direct name="adder" circuit_model_name="direct_interc"/>
<direct name="adder" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/>
</direct_connection>
<pb_type_annotations>
<!-- physical pb_type binding in complex block IO -->

View File

@ -0,0 +1,112 @@
#include "vtr_assert.h"
#include "arch_direct.h"
/************************************************************************
* Member functions for class ArchDirect
***********************************************************************/
/************************************************************************
* Constructors
***********************************************************************/
ArchDirect::ArchDirect() {
return;
}
/************************************************************************
* Public Accessors : aggregates
***********************************************************************/
ArchDirect::arch_direct_range ArchDirect::directs() const {
return vtr::make_range(direct_ids_.begin(), direct_ids_.end());
}
/************************************************************************
* Public Accessors
***********************************************************************/
ArchDirectId ArchDirect::direct(const std::string& name) const {
if (0 < direct_name2ids_.count(name)) {
return direct_name2ids_.at(name);
}
return ArchDirectId::INVALID();
}
std::string ArchDirect::name(const ArchDirectId& direct_id) const {
/* validate the direct_id */
VTR_ASSERT(valid_direct_id(direct_id));
return names_[direct_id];
}
CircuitModelId ArchDirect::circuit_model(const ArchDirectId& direct_id) const {
/* validate the direct_id */
VTR_ASSERT(valid_direct_id(direct_id));
return circuit_models_[direct_id];
}
e_direct_type ArchDirect::type(const ArchDirectId& direct_id) const {
/* validate the direct_id */
VTR_ASSERT(valid_direct_id(direct_id));
return types_[direct_id];
}
e_direct_direction ArchDirect::x_dir(const ArchDirectId& direct_id) const {
/* validate the direct_id */
VTR_ASSERT(valid_direct_id(direct_id));
return directions_[direct_id].x();
}
e_direct_direction ArchDirect::y_dir(const ArchDirectId& direct_id) const {
/* validate the direct_id */
VTR_ASSERT(valid_direct_id(direct_id));
return directions_[direct_id].y();
}
/************************************************************************
* Public Mutators
***********************************************************************/
ArchDirectId ArchDirect::add_direct(const std::string& name) {
if (0 < direct_name2ids_.count(name)) {
return ArchDirectId::INVALID();
}
/* This is a legal name. we can create a new id */
ArchDirectId direct = ArchDirectId(direct_ids_.size());
direct_ids_.push_back(direct);
names_.push_back(name);
circuit_models_.push_back(CircuitModelId::INVALID());
types_.emplace_back(NUM_DIRECT_TYPES);
directions_.emplace_back(vtr::Point<e_direct_direction>(NUM_DIRECT_DIRECTIONS, NUM_DIRECT_DIRECTIONS));
/* Register in the name-to-id map */
direct_name2ids_[name] = direct;
return direct;
}
void ArchDirect::set_circuit_model(const ArchDirectId& direct_id, const CircuitModelId& circuit_model) {
/* validate the direct_id */
VTR_ASSERT(valid_direct_id(direct_id));
circuit_models_[direct_id] = circuit_model;
}
void ArchDirect::set_type(const ArchDirectId& direct_id, const e_direct_type& type) {
/* validate the direct_id */
VTR_ASSERT(valid_direct_id(direct_id));
types_[direct_id] = type;
}
void ArchDirect::set_direction(const ArchDirectId& direct_id,
const e_direct_direction& x_dir,
const e_direct_direction& y_dir) {
/* validate the direct_id */
VTR_ASSERT(valid_direct_id(direct_id));
directions_[direct_id].set_x(x_dir);
directions_[direct_id].set_y(y_dir);
}
/************************************************************************
* Internal invalidators/validators
***********************************************************************/
/* Validators */
bool ArchDirect::valid_direct_id(const ArchDirectId& direct_id) const {
return ( size_t(direct_id) < direct_ids_.size() ) && ( direct_id == direct_ids_[direct_id] );
}

View File

@ -0,0 +1,103 @@
#ifndef ARCH_DIRECT_H
#define ARCH_DIRECT_H
#include <map>
#include "vtr_vector.h"
#include "vtr_geometry.h"
#include "circuit_library_fwd.h"
#include "arch_direct_fwd.h"
/********************************************************************
* Define the types of point to point connection between CLBs
* These types are supplementary to the original VPR direct connections
* Here we extend to the cross-row and cross-column connections
********************************************************************/
enum e_direct_type {
INNER_COLUMN,
INNER_ROW,
INTER_COLUMN,
INTER_ROW,
NUM_DIRECT_TYPES
};
constexpr std::array<const char*, NUM_DIRECT_TYPES> DIRECT_TYPE_STRING = {{"inner_column", "inner_row", "inter_column", "inter_row"}};
enum e_direct_direction {
POSITIVE_DIR,
NEGATIVE_DIR,
NUM_DIRECT_DIRECTIONS
};
constexpr std::array<const char*, NUM_DIRECT_DIRECTIONS> DIRECT_DIRECTION_STRING = {{"positive", "negative"}};
/********************************************************************
* A data base to describe the direct connection in OpenFPGA architecture
* For each direct connection, it will include
* - name: the identifier to annotate the original direct connection in VPR architecture
* - circuit model: the circuit model to used to implement this connection
* - type: if this connection should be cross-column or cross-row
* - x-direction: how this connection is going to be applied to adjacent columns
* a positive x-direction means that column A will be connected
* to the column B on the right side of column A
* - y-direction: how this connection is going to be applied to adjacent rows
* a positive y-direction means that row A will be connected
* to the row B on the bottom side of row A
*
* Note that: this is the data structure to be used when parsing the XML
* this is NOT the data structure to be use in core engine
********************************************************************/
class ArchDirect {
public: /* Types */
typedef vtr::vector<ArchDirectId, ArchDirectId>::const_iterator arch_direct_iterator;
/* Create range */
typedef vtr::Range<arch_direct_iterator> arch_direct_range;
public: /* Constructors */
ArchDirect();
public: /* Accessors: aggregates */
arch_direct_range directs() const;
public: /* Public Accessors: Basic data query on directs */
ArchDirectId direct(const std::string& name) const;
std::string name(const ArchDirectId& direct_id) const;
CircuitModelId circuit_model(const ArchDirectId& direct_id) const;
e_direct_type type(const ArchDirectId& direct_id) const;
e_direct_direction x_dir(const ArchDirectId& direct_id) const;
e_direct_direction y_dir(const ArchDirectId& direct_id) const;
public: /* Public Mutators */
ArchDirectId add_direct(const std::string& name);
void set_circuit_model(const ArchDirectId& direct_id, const CircuitModelId& circuit_model);
void set_type(const ArchDirectId& direct_id, const e_direct_type& type);
void set_direction(const ArchDirectId& direct_id,
const e_direct_direction& x_dir,
const e_direct_direction& y_dir);
public: /* Public invalidators/validators */
bool valid_direct_id(const ArchDirectId& direct_id) const;
private: /* Internal data */
vtr::vector<ArchDirectId, ArchDirectId> direct_ids_;
/* Unique name: the identifier to annotate the original direct connection in VPR architecture */
vtr::vector<ArchDirectId, std::string> names_;
/* circuit model: the circuit model to used to implement this connection */
vtr::vector<ArchDirectId, CircuitModelId> circuit_models_;
/* type: if this connection should be cross-column or cross-row */
vtr::vector<ArchDirectId, e_direct_type> types_;
/*
* x-direction: how this connection is going to be applied to adjacent columns
* a positive x-direction means that column A will be connected
* to the column B on the right side of column A
* y-direction: how this connection is going to be applied to adjacent rows
* a positive y-direction means that row A will be connected
* to the row B on the bottom side of row A
*/
vtr::vector<ArchDirectId, vtr::Point<e_direct_direction>> directions_;
/* Fast look-up */
std::map<std::string, ArchDirectId> direct_name2ids_;
};
#endif

View File

@ -0,0 +1,22 @@
/************************************************************************
* A header file for ArchDirect class, including critical data declaration
* Please include this file only for using any TechnologyLibrary data structure
* Refer to arch_direct.h for more details
***********************************************************************/
/************************************************************************
* Create strong id for ArchDirect to avoid illegal type casting
***********************************************************************/
#ifndef ARCH_DIRECT_FWD_H
#define ARCH_DIRECT_FWD_H
#include "vtr_strong_id.h"
struct arch_direct_id_tag;
typedef vtr::StrongId<arch_direct_id_tag> ArchDirectId;
/* Short declaration of class */
class ArchDirect;
#endif

View File

@ -1,22 +0,0 @@
#ifndef DIRECT_TYPES_H
#define DIRECT_TYPES_H
/********************************************************************
* Define the types of point to point connection between CLBs
* These types are supplementary to the original VPR direct connections
* Here we extend to the cross-row and cross-column connections
********************************************************************/
enum e_point2point_interconnection_type {
NO_P2P,
P2P_DIRECT_COLUMN,
P2P_DIRECT_ROW,
NUM_POINT2POINT_INTERCONNECT_TYPE
};
enum e_point2point_interconnection_dir {
POSITIVE_DIR,
NEGATIVE_DIR,
NUM_POINT2POINT_INTERCONNECT_DIR
};
#endif

View File

@ -8,6 +8,7 @@
#include "technology_library.h"
#include "simulation_setting.h"
#include "config_protocol.h"
#include "arch_direct.h"
#include "pb_type_annotation.h"
/* namespace openfpga begins */
@ -48,7 +49,7 @@ struct Arch {
/* Mapping from the names of direct connection
* to circuit models in circuit library
*/
std::map<std::string, CircuitModelId> direct2circuit;
ArchDirect arch_direct;
/* Pb type annotations
* Bind from operating to physical

View File

@ -94,8 +94,8 @@ openfpga::Arch read_xml_openfpga_arch(const char* arch_file_name) {
openfpga_arch.circuit_lib);
/* Parse the direct circuit definition */
openfpga_arch.direct2circuit = read_xml_direct_circuit(xml_openfpga_arch, loc_data,
openfpga_arch.circuit_lib);
openfpga_arch.arch_direct = read_xml_direct_circuit(xml_openfpga_arch, loc_data,
openfpga_arch.circuit_lib);
/* Parse the pb_type annotation */
openfpga_arch.pb_type_annotations = read_xml_pb_type_annotations(xml_openfpga_arch, loc_data);

View File

@ -185,20 +185,53 @@ std::map<std::string, CircuitModelId> read_xml_routing_segment_circuit(pugi::xml
return seg2circuit;
}
/********************************************************************
* Convert string to the enumerate of direct type
*******************************************************************/
static
e_direct_type string_to_direct_type(const std::string& type_string) {
if (std::string("column") == type_string) {
return INTER_COLUMN;
}
if (std::string("row") == type_string) {
return INTER_ROW;
}
return NUM_DIRECT_TYPES;
}
/********************************************************************
* Convert string to the enumerate of direct direction type
*******************************************************************/
static
e_direct_direction string_to_direct_direction(const std::string& type_string) {
if (std::string("positive") == type_string) {
return POSITIVE_DIR;
}
if (std::string("negative") == type_string) {
return NEGATIVE_DIR;
}
return NUM_DIRECT_DIRECTIONS;
}
/********************************************************************
* Parse XML codes about <direct_connection> to an object of name-to-circuit mapping
* Note: this function should be called AFTER the parsing of circuit library!!!
*******************************************************************/
std::map<std::string, CircuitModelId> read_xml_direct_circuit(pugi::xml_node& Node,
const pugiutil::loc_data& loc_data,
const CircuitLibrary& circuit_lib) {
std::map<std::string, CircuitModelId> direct2circuit;
ArchDirect read_xml_direct_circuit(pugi::xml_node& Node,
const pugiutil::loc_data& loc_data,
const CircuitLibrary& circuit_lib) {
ArchDirect arch_direct;
/* Parse direct list, this is optional. May not be used */
pugi::xml_node xml_directs= get_single_child(Node, "direct_connection", loc_data, pugiutil::ReqOpt::OPTIONAL);
/* Not found, we can return */
if (!xml_directs) {
return direct2circuit;
return arch_direct;
}
/* Iterate over the children under this node,
@ -219,17 +252,46 @@ std::map<std::string, CircuitModelId> read_xml_direct_circuit(pugi::xml_node& No
circuit_lib, direct_model_name,
CIRCUIT_MODEL_WIRE);
/* Ensure that there is no duplicated seg names defined here */
std::map<std::string, CircuitModelId>::const_iterator it = direct2circuit.find(direct_name);
if (it != direct2circuit.end()) {
/* Add to the Arch direct database */
ArchDirectId direct = arch_direct.add_direct(direct_name);
if (false == arch_direct.valid_direct_id(direct)) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_direct),
"Direct name '%s' has been defined more than once!\n",
direct_name.c_str());
}
arch_direct.set_circuit_model(direct, direct_model);
/* Pass all the check, we can add it to the map */
direct2circuit[direct_name] = direct_model;
/* Add more information*/
std::string direct_type_name = get_attribute(xml_direct, "type", loc_data).as_string();
e_direct_type direct_type = string_to_direct_type(direct_type_name);
if (NUM_DIRECT_TYPES == direct_type) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_direct),
"Direct type '%s' is not support! Acceptable values are [column|row]\n",
direct_type_name.c_str());
}
arch_direct.set_type(direct, direct_type);
std::string x_dir_name = get_attribute(xml_direct, "x_dir", loc_data).as_string();
std::string y_dir_name = get_attribute(xml_direct, "y_dir", loc_data).as_string();
e_direct_direction x_dir = string_to_direct_direction(x_dir_name);
e_direct_direction y_dir = string_to_direct_direction(y_dir_name);
if (NUM_DIRECT_DIRECTIONS == x_dir) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_direct),
"Direct x-direction '%s' is not support! Acceptable values are [positive|column]\n",
x_dir_name.c_str());
}
if (NUM_DIRECT_DIRECTIONS == y_dir) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_direct),
"Direct y-direction '%s' is not support! Acceptable values are [positive|column]\n",
y_dir_name.c_str());
}
arch_direct.set_direction(direct, x_dir, y_dir);
}
return direct2circuit;
return arch_direct;
}

View File

@ -10,6 +10,7 @@
#include "pugixml_util.hpp"
#include "pugixml.hpp"
#include "circuit_library.h"
#include "arch_direct.h"
/********************************************************************
* Function declaration
@ -26,8 +27,9 @@ std::map<std::string, CircuitModelId> read_xml_routing_segment_circuit(pugi::xml
const pugiutil::loc_data& loc_data,
const CircuitLibrary& circuit_lib);
std::map<std::string, CircuitModelId> read_xml_direct_circuit(pugi::xml_node& Node,
const pugiutil::loc_data& loc_data,
const CircuitLibrary& circuit_lib);
ArchDirect read_xml_direct_circuit(pugi::xml_node& Node,
const pugiutil::loc_data& loc_data,
const CircuitLibrary& circuit_lib);
#endif

View File

@ -56,8 +56,7 @@ void write_xml_openfpga_arch(const char* fname,
write_xml_routing_segment_circuit(fp, fname, openfpga_arch.circuit_lib, openfpga_arch.routing_seg2circuit);
/* Write the direct connection circuit definition */
write_xml_direct_circuit(fp, fname, openfpga_arch.circuit_lib, openfpga_arch.direct2circuit);
write_xml_direct_circuit(fp, fname, openfpga_arch.circuit_lib, openfpga_arch.arch_direct);
/* Write the pb_type annotations */
openfpga::write_xml_pb_type_annotations(fp, fname, openfpga_arch. pb_type_annotations);

View File

@ -38,6 +38,29 @@ void write_xml_routing_component_circuit(std::fstream& fp,
}
}
/********************************************************************
* Write switch circuit model definition in XML format
*******************************************************************/
static
void write_xml_direct_component_circuit(std::fstream& fp,
const char* fname,
const std::string& direct_tag_name,
const CircuitLibrary& circuit_lib,
const ArchDirect& arch_direct,
const ArchDirectId& direct_id) {
/* Validate the file stream */
openfpga::check_file_stream(fname, fp);
/* Iterate over the mapping */
fp << "\t\t" << "<" << direct_tag_name;
write_xml_attribute(fp, "name", arch_direct.name(direct_id).c_str());
write_xml_attribute(fp, "circuit_model_name", circuit_lib.model_name(arch_direct.circuit_model(direct_id)).c_str());
write_xml_attribute(fp, "type", DIRECT_TYPE_STRING[arch_direct.type(direct_id)]);
write_xml_attribute(fp, "x_dir", DIRECT_DIRECTION_STRING[arch_direct.x_dir(direct_id)]);
write_xml_attribute(fp, "y_dir", DIRECT_DIRECTION_STRING[arch_direct.y_dir(direct_id)]);
fp << "/>" << "\n";
}
/********************************************************************
* Write Connection block circuit models in XML format
*******************************************************************/
@ -104,9 +127,9 @@ void write_xml_routing_segment_circuit(std::fstream& fp,
void write_xml_direct_circuit(std::fstream& fp,
const char* fname,
const CircuitLibrary& circuit_lib,
const std::map<std::string, CircuitModelId>& direct2circuit) {
const ArchDirect& arch_direct) {
/* If the direct2circuit is empty, we do not output XML */
if (direct2circuit.empty()) {
if (0 == arch_direct.directs().size()) {
return;
}
@ -117,7 +140,9 @@ void write_xml_direct_circuit(std::fstream& fp,
fp << "\t" << "<direct_connection>" << "\n";
/* Write each direct connection circuit definition */
write_xml_routing_component_circuit(fp, fname, std::string("direct"), circuit_lib, direct2circuit);
for (const ArchDirectId& direct_id : arch_direct.directs()) {
write_xml_direct_component_circuit(fp, fname, std::string("direct"), circuit_lib, arch_direct, direct_id);
}
/* Finish writing the root node */
fp << "\t" << "</direct_connection>" << "\n";

View File

@ -9,6 +9,7 @@
#include <string>
#include "circuit_library.h"
#include "arch_direct.h"
/********************************************************************
* Function declaration
@ -31,6 +32,6 @@ void write_xml_routing_segment_circuit(std::fstream& fp,
void write_xml_direct_circuit(std::fstream& fp,
const char* fname,
const CircuitLibrary& circuit_lib,
const std::map<std::string, CircuitModelId>& direct2circuit);
const ArchDirect& arch_direct);
#endif

View File

@ -524,13 +524,16 @@ void annotate_direct_circuit_models(const DeviceContext& vpr_device_ctx,
for (int idirect = 0; idirect < vpr_device_ctx.arch->num_directs; ++idirect) {
std::string direct_name = vpr_device_ctx.arch->Directs[idirect].name;
CircuitModelId circuit_model = CircuitModelId::INVALID();
/* The name-to-circuit mapping is stored in either cb_switch-to-circuit or sb_switch-to-circuit,
* Try to find one and update the device annotation
*/
if (0 < openfpga_arch.direct2circuit.count(direct_name)) {
circuit_model = openfpga_arch.direct2circuit.at(direct_name);
ArchDirectId direct_id = openfpga_arch.arch_direct.direct(direct_name);
/* Cannot find a direct, no annotation needed for this direct */
if (ArchDirectId::INVALID() == direct_id) {
continue;
}
CircuitModelId circuit_model = openfpga_arch.arch_direct.circuit_model(direct_id);
/* Cannot find a circuit model, error out! */
if (CircuitModelId::INVALID() == circuit_model) {
VTR_LOG_ERROR("Fail to find a circuit model for a direct connection '%s'!\nPlease check your OpenFPGA architecture XML!\n",
@ -547,7 +550,7 @@ void annotate_direct_circuit_models(const DeviceContext& vpr_device_ctx,
}
/* Now update the device annotation */
vpr_device_annotation.add_direct_circuit_model(idirect, circuit_model);
vpr_device_annotation.add_direct_annotation(idirect, direct_id);
VTR_LOGV(verbose_output,
"Binded a direct connection '%s' to circuit model '%s'\n",
direct_name.c_str(),

View File

@ -233,13 +233,12 @@ CircuitModelId VprDeviceAnnotation::rr_segment_circuit_model(const RRSegmentId&
return rr_segment_circuit_models_.at(rr_segment);
}
CircuitModelId VprDeviceAnnotation::direct_circuit_model(const size_t& direct) const {
ArchDirectId VprDeviceAnnotation::direct_annotation(const size_t& direct) const {
/* Ensure that the rr_switch is in the list */
std::map<size_t, CircuitModelId>::const_iterator it = direct_circuit_models_.find(direct);
if (it == direct_circuit_models_.end()) {
return CircuitModelId::INVALID();
if (0 == direct_annotations_.count(direct)) {
return ArchDirectId::INVALID();
}
return direct_circuit_models_.at(direct);
return direct_annotations_.at(direct);
}
/************************************************************************
@ -461,15 +460,14 @@ void VprDeviceAnnotation::add_rr_segment_circuit_model(const RRSegmentId& rr_seg
rr_segment_circuit_models_[rr_segment] = circuit_model;
}
void VprDeviceAnnotation::add_direct_circuit_model(const size_t& direct, const CircuitModelId& circuit_model) {
void VprDeviceAnnotation::add_direct_annotation(const size_t& direct, const ArchDirectId& arch_direct_id) {
/* Warn any override attempt */
std::map<size_t, CircuitModelId>::const_iterator it = direct_circuit_models_.find(direct);
if (it != direct_circuit_models_.end()) {
VTR_LOG_WARN("Override the annotation between direct '%ld' and its circuit_model '%ld'!\n",
size_t(direct), size_t(circuit_model));
if (0 < direct_annotations_.count(direct)) {
VTR_LOG_WARN("Override the annotation between direct '%ld' and its annotation '%ld'!\n",
size_t(direct), size_t(arch_direct_id));
}
direct_circuit_models_[direct] = circuit_model;
direct_annotations_[direct] = arch_direct_id;
}
} /* End namespace openfpga*/

View File

@ -18,6 +18,7 @@
/* Header from openfpgautil library */
#include "openfpga_port.h"
#include "circuit_library.h"
#include "arch_direct.h"
/* Begin namespace openfpga */
namespace openfpga {
@ -71,7 +72,7 @@ class VprDeviceAnnotation {
t_pb_graph_pin* physical_pb_graph_pin(t_pb_graph_pin* pb_graph_pin) const;
CircuitModelId rr_switch_circuit_model(const RRSwitchId& rr_switch) const;
CircuitModelId rr_segment_circuit_model(const RRSegmentId& rr_segment) const;
CircuitModelId direct_circuit_model(const size_t& direct) const;
ArchDirectId direct_annotation(const size_t& direct) const;
public: /* Public mutators */
void add_pb_type_physical_mode(t_pb_type* pb_type, t_mode* physical_mode);
void add_physical_pb_type(t_pb_type* operating_pb_type, t_pb_type* physical_pb_type);
@ -91,7 +92,7 @@ class VprDeviceAnnotation {
void add_physical_pb_graph_pin(t_pb_graph_pin* operating_pb_graph_pin, t_pb_graph_pin* physical_pb_graph_pin);
void add_rr_switch_circuit_model(const RRSwitchId& rr_switch, const CircuitModelId& circuit_model);
void add_rr_segment_circuit_model(const RRSegmentId& rr_segment, const CircuitModelId& circuit_model);
void add_direct_circuit_model(const size_t& direct, const CircuitModelId& circuit_model);
void add_direct_annotation(const size_t& direct, const ArchDirectId& arch_direct_id);
private: /* Internal data */
/* Pair a regular pb_type to its physical pb_type */
std::map<t_pb_type*, t_pb_type*> physical_pb_types_;
@ -173,8 +174,8 @@ class VprDeviceAnnotation {
/* Pair a Routing Segment (rr_segment) to a circuit model */
std::map<RRSegmentId, CircuitModelId> rr_segment_circuit_models_;
/* Pair a direct connection (direct) to a circuit model */
std::map<size_t, CircuitModelId> direct_circuit_models_;
/* Pair a direct connection (direct) to a annotation which contains circuit model id */
std::map<size_t, ArchDirectId> direct_annotations_;
};
} /* End namespace openfpga*/