diff --git a/openfpga/src/annotation/device_rr_gsb.h b/openfpga/src/annotation/device_rr_gsb.h new file mode 100644 index 000000000..e801417bc --- /dev/null +++ b/openfpga/src/annotation/device_rr_gsb.h @@ -0,0 +1,106 @@ +#ifndef DEVICE_RR_GSB_H +#define DEVICE_RR_GSB_H + +/******************************************************************** + * Include header files required by the data structure definition + *******************************************************************/ +#include "rr_gsb.h" + +/******************************************************************** + * Object Device Routing Resource Switch Block + * This includes: + * 1. a collection of RRSwitch blocks, each of which can be used to instance Switch blocks in the top-level netlists + * 2. a collection of unique mirrors of RRGSBs, which can be used to output Verilog / SPICE modules + * 3. a colleciton of unique rotatable of RRGSBs, which can be used to output Verilog / SPICE modules + * The rotatable RRGSBs are more generic mirrors, which allow SwitchBlocks to be wired by rotating the pins, + * further reduce the number of Verilog/SPICE modules outputted. This will lead to rapid layout generation + *******************************************************************/ +class DeviceRRGSB { + public: /* Contructors */ + public: /* Accessors */ + DeviceCoordinator get_gsb_range() const; /* get the max coordinator of the switch block array */ + const RRGSB get_gsb(const DeviceCoordinator& coordinator) const; /* Get a rr switch block in the array with a coordinator */ + const RRGSB get_gsb(size_t x, size_t y) const; /* Get a rr switch block in the array with a coordinator */ + size_t get_num_gsb_unique_module() const; /* get the number of unique mirrors of GSB */ + size_t get_num_sb_unique_submodule(enum e_side side, size_t seg_index) const; /* get the number of unique mirrors of switch blocks */ + size_t get_num_sb_unique_module() const; /* get the number of unique mirrors of switch blocks */ + size_t get_num_cb_unique_module(t_rr_type cb_type) const; /* get the number of unique mirrors of CBs */ + size_t get_sb_unique_submodule_id(DeviceCoordinator& coordinator, enum e_side side, size_t seg_id) const; + const RRGSB get_sb_unique_submodule(size_t index, enum e_side side, size_t seg_id) const; /* Get a rr switch block which a unique mirror */ + const RRGSB get_sb_unique_submodule(DeviceCoordinator& coordinator, enum e_side side, size_t seg_id) const; /* Get a rr switch block which a unique mirror */ + const RRGSB get_sb_unique_module(size_t index) const; /* Get a rr switch block which a unique mirror */ + const RRGSB get_sb_unique_module(const DeviceCoordinator& coordinator) const; /* Get a rr switch block which a unique mirror */ + const RRGSB& get_cb_unique_module(t_rr_type cb_type, size_t index) const; /* Get a rr switch block which a unique mirror */ + const RRGSB& get_cb_unique_module(t_rr_type cb_type, const DeviceCoordinator& coordinator) const; + size_t get_max_num_sides() const; /* Get the maximum number of sides across the switch blocks */ + size_t get_num_segments() const; /* Get the size of segment_ids */ + size_t get_segment_id(size_t index) const; /* Get a segment id */ + bool is_two_sb_share_same_submodules(DeviceCoordinator& src, DeviceCoordinator& des) const; + public: /* Mutators */ + void set_sb_num_reserved_conf_bits(DeviceCoordinator& coordinator, size_t num_reserved_conf_bits); /* TODO: TOBE DEPRECATED!!! conf_bits should be initialized when creating a switch block!!! */ + void set_sb_conf_bits_lsb(DeviceCoordinator& coordinator, size_t conf_bits_lsb); /* TODO: TOBE DEPRECATED!!! conf_bits should be initialized when creating a switch block!!! */ + void set_sb_conf_bits_msb(DeviceCoordinator& coordinator, size_t conf_bits_msb); /* TODO: TOBE DEPRECATED!!! conf_bits should be initialized when creating a switch block!!! */ + void set_cb_num_reserved_conf_bits(DeviceCoordinator& coordinator, t_rr_type cb_type, size_t num_reserved_conf_bits); /* TODO: TOBE DEPRECATED!!! conf_bits should be initialized when creating a switch block!!! */ + void set_cb_conf_bits_lsb(DeviceCoordinator& coordinator, t_rr_type cb_type, size_t conf_bits_lsb); /* TODO: TOBE DEPRECATED!!! conf_bits should be initialized when creating a switch block!!! */ + void set_cb_conf_bits_msb(DeviceCoordinator& coordinator, t_rr_type cb_type, size_t conf_bits_msb); /* TODO: TOBE DEPRECATED!!! conf_bits should be initialized when creating a switch block!!! */ + void reserve(DeviceCoordinator& coordinator); /* Pre-allocate the rr_switch_block array that the device requires */ + void reserve_sb_unique_submodule_id(DeviceCoordinator& coordinator); /* Pre-allocate the rr_sb_unique_module_id matrix that the device requires */ + void resize_upon_need(const DeviceCoordinator& coordinator); /* Resize the rr_switch_block array if needed */ + void add_rr_gsb(const DeviceCoordinator& coordinator, const RRGSB& rr_gsb); /* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */ + void build_unique_module(); /* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */ + void clear(); /* clean the content */ + private: /* Internal cleaners */ + void clear_gsb(); /* clean the content */ + void clear_cb_unique_module(t_rr_type cb_type); /* clean the content */ + void clear_cb_unique_module_id(t_rr_type cb_type); /* clean the content */ + void clear_sb_unique_module(); /* clean the content */ + void clear_sb_unique_module_id(); /* clean the content */ + void clear_sb_unique_submodule(); /* clean the content */ + void clear_sb_unique_submodule_id(); /* clean the content */ + void clear_gsb_unique_module(); /* clean the content */ + void clear_gsb_unique_module_id(); /* clean the content */ + void clear_segment_ids(); + private: /* Validators */ + bool validate_coordinator(const DeviceCoordinator& coordinator) const; /* Validate if the (x,y) is the range of this device */ + bool validate_coordinator_edge(DeviceCoordinator& coordinator) const; /* Validate if the (x,y) is the range of this device but takes into consideration the fact that edges are 1 off */ + bool validate_side(enum e_side side) const; /* validate if side is in the range of unique_side_module_ */ + bool validate_sb_unique_module_index(size_t index) const; /* Validate if the index in the range of unique_mirror vector*/ + bool validate_cb_unique_module_index(t_rr_type cb_type, size_t index) const; /* Validate if the index in the range of unique_mirror vector*/ + bool validate_sb_unique_submodule_index(size_t index, enum e_side side, size_t seg_index) const; /* Validate if the index in the range of unique_module vector */ + bool validate_segment_index(size_t index) const; + bool validate_cb_type(t_rr_type cb_type) const; + private: /* Internal builders */ + void build_segment_ids(); /* build a map of segment_ids */ + void add_gsb_unique_module(const DeviceCoordinator& coordinator); + void add_sb_unique_side_submodule(DeviceCoordinator& coordinator, const RRGSB& rr_sb, enum e_side side); + void add_sb_unique_side_segment_submodule(DeviceCoordinator& coordinator, const RRGSB& rr_sb, enum e_side side, size_t seg_id); + void add_cb_unique_module(t_rr_type cb_type, const DeviceCoordinator& coordinator); + void set_cb_unique_module_id(t_rr_type, const DeviceCoordinator& coordinator, size_t id); + void build_sb_unique_submodule(); /* Add a switch block to the array, which will automatically identify and update the lists of unique side module */ + void build_sb_unique_module(); /* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */ + void build_cb_unique_module(t_rr_type cb_type); /* Add a switch block to the array, which will automatically identify and update the lists of unique side module */ + void build_gsb_unique_module(); /* Add a switch block to the array, which will automatically identify and update the lists of unique mirrors and rotatable mirrors */ + private: /* Internal Data */ + std::vector< std::vector > rr_gsb_; + + std::vector< std::vector > gsb_unique_module_id_; /* A map from rr_gsb to its unique mirror */ + std::vector gsb_unique_module_; + + std::vector< std::vector > sb_unique_module_id_; /* A map from rr_gsb to its unique mirror */ + std::vector sb_unique_module_; + + std::vector< std::vector< std::vector< std::vector > > > sb_unique_submodule_id_; /* A map from rr_switch_block to its unique_side_module [0..x][0..y][0..num_sides][num_seg-1]*/ + std::vector< std::vector > > sb_unique_submodule_; /* For each side of switch block, we identify a list of unique modules based on its connection. This is a matrix [0..num_sides-1][0..num_seg-1][0..num_module], num_sides will the max number of sides of all the rr_switch_blocks */ + + std::vector< std::vector > cbx_unique_module_id_; /* A map from rr_gsb to its unique mirror */ + std::vector cbx_unique_module_; /* For each side of connection block, we identify a list of unique modules based on its connection. This is a matrix [0..num_module] */ + + std::vector< std::vector > cby_unique_module_id_; /* A map from rr_gsb to its unique mirror */ + std::vector cby_unique_module_; /* For each side of connection block, we identify a list of unique modules based on its connection. This is a matrix [0..num_module] */ + + std::vector segment_ids_; +}; + +} /* End namespace openfpga*/ + +#endif diff --git a/openfpga/src/annotation/rr_chan.cpp b/openfpga/src/annotation/rr_chan.cpp new file mode 100644 index 000000000..84540758e --- /dev/null +++ b/openfpga/src/annotation/rr_chan.cpp @@ -0,0 +1,221 @@ +/************************************************************************ + * Member functions for class RRChan + ***********************************************************************/ +#include "vtr_log.h" +#include "vtr_assert.h" +#include "rr_chan.h" + +/* namespace openfpga begins */ +namespace openfpga { + +/************************************************************************ + * Constructors + ***********************************************************************/ +/* Copy Constructor */ +RRChan::RRChan(const RRChan& rr_chan) { + this->set(rr_chan); + return; +} + +/* default constructor */ +RRChan::RRChan() { + type_ = NUM_RR_TYPES; + nodes_.resize(0); + node_segments_.resize(0); +} + +/* Accessors */ +t_rr_type RRChan::get_type() const { + return type_; +} + +/* get the number of tracks in this channel */ +size_t RRChan::get_chan_width() const { + return nodes_.size(); +} + +/* get the track_id of a node */ +int RRChan::get_node_track_id(const RRNodeId& node) const { + /* if the given node is NULL, we return an invalid id */ + if (RRNodeId::INVALID() == node) { + return -1; + } + /* check each member and return if we find a match in content */ + std::vector::const_iterator it = std::find(nodes_.begin(), nodes_.end(), node); + if (nodes_.end() == it) { + return -1; + } + return it - nodes_.begin(); +} + +/* get the rr_node with the track_id */ +RRNodeId RRChan::get_node(const size_t& track_num) const { + if ( false == valid_node_id(track_num) ) { + return RRNodeId::INVALID(); + } + return nodes_[track_num]; +} + +/* get the segment id of a node */ +RRSegmentId RRChan::get_node_segment(const RRNodeId& node) const { + int node_id = get_node_track_id(node); + if ( false == valid_node_id(node_id)) { + return RRSegmentId::INVALID(); + } + return get_node_segment(node_id); +} + +/* get the segment id of a node */ +RRSegmentId RRChan::get_node_segment(const size_t& track_num) const { + if ( false == valid_node_id(track_num)) { + return RRSegmentId::INVALID(); + } + return node_segments_[track_num]; +} + +/* evaluate if two RRChan is mirror to each other */ +bool RRChan::is_mirror(const RRGraph& rr_graph, const RRChan& cand) const { + /* If any following element does not match, it is not mirror */ + /* 1. type */ + if (this->get_type() != cand.get_type()) { + return false; + } + /* 2. track_width */ + if (this->get_chan_width() != cand.get_chan_width()) { + return false; + } + /* 3. for each node */ + for (size_t inode = 0; inode < this->get_chan_width(); ++inode) { + /* 3.1 check node type */ + if (rr_graph.node_type(this->get_node(inode)) != rr_graph.node_type(cand.get_node(inode))) { + return false; + } + /* 3.2 check node directionality */ + if (rr_graph.node_direction(this->get_node(inode)) != rr_graph.node_direction(cand.get_node(inode))) { + return false; + } + /* 3.3 check node segment */ + if (this->get_node_segment(inode) != cand.get_node_segment(inode)) { + return false; + } + } + + return true; +} + +/* Get a list of segments used in this routing channel */ +std::vector RRChan::get_segment_ids() const { + std::vector seg_list; + + /* make sure a clean start */ + seg_list.clear(); + + /* Traverse node_segments */ + for (size_t inode = 0; inode < get_chan_width(); ++inode) { + std::vector::iterator it; + /* Try to find the node_segment id in the list */ + it = find(seg_list.begin(), seg_list.end(), node_segments_[inode]); + if ( it == seg_list.end() ) { + /* Not found, add it to the list */ + seg_list.push_back(node_segments_[inode]); + } + } + + return seg_list; +} + +/* Get a list of nodes whose segment_id is specified */ +std::vector RRChan::get_node_ids_by_segment_ids(const RRSegmentId& seg_id) const { + std::vector node_list; + + /* make sure a clean start */ + node_list.clear(); + + /* Traverse node_segments */ + for (size_t inode = 0; inode < get_chan_width(); ++inode) { + /* Try to find the node_segment id in the list */ + if ( seg_id == node_segments_[inode] ) { + node_list.push_back(nodes_[inode]); + } + } + + return node_list; +} + +/* Mutators */ +void RRChan::set(const RRChan& rr_chan) { + /* Ensure a clean start */ + this->clear(); + /* Assign type of this routing channel */ + this->type_ = rr_chan.get_type(); + /* Copy node and node_segments */ + this->nodes_.resize(rr_chan.get_chan_width()); + this->node_segments_.resize(rr_chan.get_chan_width()); + for (size_t inode = 0; inode < rr_chan.get_chan_width(); ++inode) { + this->nodes_[inode] = rr_chan.get_node(inode); + this->node_segments_[inode] = rr_chan.get_node_segment(inode); + } + return; +} + +/* modify type */ +void RRChan::set_type(const t_rr_type& type) { + VTR_ASSERT(valid_type(type)); + type_ = type; +} + +/* Reserve node list */ +void RRChan::reserve_node(const size_t& node_size) { + nodes_.reserve(node_size); /* reserve to the maximum */ + node_segments_.reserve(node_size); /* reserve to the maximum */ +} + +/* add a node to the array */ +void RRChan::add_node(const RRGraph& rr_graph, const RRNodeId& node, const RRSegmentId& node_segment) { + /* fill the dedicated element in the vector */ + nodes_.push_back(node); + node_segments_.push_back(node_segment); + + VTR_ASSERT(valid_node_type(rr_graph, node)); +} + +/* Clear content */ +void RRChan::clear() { + nodes_.clear(); + node_segments_.clear(); +} + +/************************************************************************ + * Internal functions + ***********************************************************************/ +/* for type, only valid type is CHANX and CHANY */ +bool RRChan::valid_type(const t_rr_type& type) const { + if ((CHANX == type) || (CHANY == type)) { + return true; + } + return false; +} + +/* Check each node, see if the node type is consistent with the type */ +bool RRChan::valid_node_type(const RRGraph& rr_graph, const RRNodeId& node) const { + valid_type(rr_graph.node_type(node)); + if (NUM_RR_TYPES == type_) { + return true; + } + valid_type(type_); + if (type_ != rr_graph.node_type(node)) { + return false; + } + return true; +} + +/* check if the node id is valid */ +bool RRChan::valid_node_id(const size_t& node_id) const { + if (node_id < nodes_.size()) { + return true; + } + + return false; +} + +} /* End namespace openfpga*/ diff --git a/openfpga/src/annotation/rr_chan.h b/openfpga/src/annotation/rr_chan.h new file mode 100644 index 000000000..ab8bb6617 --- /dev/null +++ b/openfpga/src/annotation/rr_chan.h @@ -0,0 +1,95 @@ +#ifndef RR_CHAN_H +#define RR_CHAN_H + +/******************************************************************** + * Include header files required by the data structure definition + *******************************************************************/ +#include + +/* Headers from vtrutil library */ +#include "vtr_geometry.h" + +/* Headers from openfpgautil library */ +#include "openfpga_port.h" + +/* Headers from vpr library */ +#include "rr_graph_obj.h" + +/* Begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * RRChan object aim to describe a routing channel in a routing resource graph + * - What are the nodes in the RRGraph object, for each routing track + * - What are routing segments used by each node in the channel + * - What are the directions of each routing channel + * being either X-direction or Y-direction + * + * Note : + * - This is a collection of rr_nodes from the RRGraph Object + * It does not rebuild or contruct any connects between rr_nodes + * It is just an annotation on an existing RRGraph + * ------------- ------ + * | | | | + * | | | Y | + * | CLB | | Chan | + * | | | | + * | | | | + * ------------- ------ + * ------------- + * | X | + * | Channel | + * ------------- + *******************************************************************/ +class RRChan { + public: /* Constructors */ + RRChan(const RRChan&); /* Copy Constructor */ + RRChan(); + public: /* Accessors */ + t_rr_type get_type() const; + size_t get_chan_width() const; /* get the number of tracks in this channel */ + int get_node_track_id(const RRNodeId& node) const; /* get the track_id of a node */ + RRNodeId get_node(const size_t& track_num) const; /* get the rr_node with the track_id */ + RRSegmentId get_node_segment(const RRNodeId& node) const; + RRSegmentId get_node_segment(const size_t& track_num) const; + bool is_mirror(const RRGraph& rr_graph, const RRChan& cand) const; /* evaluate if two RR_chan is mirror to each other */ + std::vector get_segment_ids() const; /* Get a list of segments used in this routing channel */ + std::vector get_node_ids_by_segment_ids(const RRSegmentId& seg_id) const; /* Get a list of segments used in this routing channel */ + public: /* Mutators */ + /* copy */ + void set(const RRChan&); + + /* modify the type of routing channel */ + void set_type(const t_rr_type& type); + + /* reseve a number of nodes to the array */ + void reserve_node(const size_t& node_size); + + /* add a node to the routing channel */ + void add_node(const RRGraph& rr_graph, const RRNodeId& node, const RRSegmentId& node_segment); + + /* clear the content */ + void clear(); + + private: /* internal functions */ + + /* For the type of a routing channel, only valid type is CHANX and CHANY */ + bool valid_type(const t_rr_type& type) const; + + /* Check each node, see if the node type is consistent with the type of routing channel */ + bool valid_node_type(const RRGraph& rr_graph, const RRNodeId& node) const; + + /* Validate if the track number in the range */ + bool valid_node_id(const size_t& node_id) const; + + private: /* Internal Data */ + t_rr_type type_; /* channel type: CHANX or CHANY */ + std::vector nodes_; /* rr nodes of each track in the channel */ + std::vector node_segments_; /* segment of each track */ +}; + + + +} /* End namespace openfpga*/ + +#endif diff --git a/openfpga/src/annotation/rr_gsb.h b/openfpga/src/annotation/rr_gsb.h new file mode 100644 index 000000000..7febeffc7 --- /dev/null +++ b/openfpga/src/annotation/rr_gsb.h @@ -0,0 +1,193 @@ +#ifndef RR_GSB_H +#define RR_GSB_H + +/******************************************************************** + * Include header files required by the data structure definition + *******************************************************************/ +#include "rr_chan.h" + +/* Begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * Object Generic Switch Block + * This block contains + * 1. A switch block + * 2. A X-direction Connection block locates at the left side of the switch block + * 2. A Y-direction Connection block locates at the top side of the switch block + * This is a collection of rr_nodes, which may be replaced with RRNodeId in new RRGraph + * + * +---------------------------------+ + * | Y-direction CB | + * | [x][y + 1] | + * +---------------------------------+ + * + * TOP SIDE + * +-------------+ +---------------------------------+ + * | | | OPIN_NODE CHAN_NODES OPIN_NODES | + * | | | | + * | | | OPIN_NODES OPIN_NODES | + * | X-direction | | | + * | CB | LEFT SIDE | Switch Block | RIGHT SIDE + * | [x][y] | | [x][y] | + * | | | | + * | | | CHAN_NODES CHAN_NODES | + * | | | | + * | | | OPIN_NODES OPIN_NODES | + * | | | | + * | | | OPIN_NODE CHAN_NODES OPIN_NODES | + * +-------------+ +---------------------------------+ + * BOTTOM SIDE + * num_sides: number of sides of this switch block + * chan_rr_node: a collection of rr_nodes as routing tracks locating at each side of the Switch block <0..num_sides-1><0..chan_width-1> + * chan_rr_node_direction: Indicate if this rr_node is an input or an output of the Switch block <0..num_sides-1><0..chan_width-1> + * ipin_rr_node: a collection of rr_nodes as IPIN of a GRID locating at each side of the Switch block <0..num_sides-1><0..num_ipin_rr_nodes-1> + * ipin_rr_node_grid_side: specify the side of the input pins on which side of a GRID <0..num_sides-1><0..num_ipin_rr_nodes-1> + * opin_rr_node: a collection of rr_nodes as OPIN of a GRID locating at each side of the Switch block <0..num_sides-1><0..num_opin_rr_nodes-1> + * opin_rr_node_grid_side: specify the side of the output pins on which side of a GRID <0..num_sides-1><0..num_opin_rr_nodes-1> + * num_reserved_conf_bits: number of reserved configuration bits this switch block requires (mainly due to RRAM-based multiplexers) + * num_conf_bits: number of configuration bits this switch block requires + *******************************************************************/ +class RRGSB { + public: /* Contructors */ + RRGSB(const RRGSB&);/* Copy constructor */ + RRGSB();/* Default constructor */ + public: /* Accessors */ + size_t get_num_sides() const; /* Get the number of sides of this SB */ + size_t get_chan_width(enum e_side side) const; /* Get the number of routing tracks on a side */ + size_t get_cb_chan_width(t_rr_type cb_type) const; /* Get the number of routing tracks of a X/Y-direction CB */ + std::vector get_cb_ipin_sides(t_rr_type cb_type) const; /* Get the sides of CB ipins in the array */ + size_t get_max_chan_width() const; /* Get the maximum number of routing tracks on all sides */ + enum PORTS get_chan_node_direction(enum e_side side, size_t track_id) const; /* Get the direction of a rr_node at a given side and track_id */ + RRChan get_chan(enum e_side side) const; /* get a rr_node at a given side and track_id */ + std::vector get_chan_segment_ids(enum e_side side) const; /* Get a list of segments used in this routing channel */ + std::vector get_chan_node_ids_by_segment_ids(enum e_side side, size_t seg_id) const; /* Get a list of segments used in this routing channel */ + t_rr_node* get_chan_node(enum e_side side, size_t track_id) const; /* get a rr_node at a given side and track_id */ + size_t get_chan_node_segment(enum e_side side, size_t track_id) const; /* get the segment id of a channel rr_node */ + size_t get_num_ipin_nodes(enum e_side side) const; /* Get the number of IPIN rr_nodes on a side */ + t_rr_node* get_ipin_node(enum e_side side, size_t node_id) const; /* get a rr_node at a given side and track_id */ + enum e_side get_ipin_node_grid_side(enum e_side side, size_t node_id) const; /* get a rr_node at a given side and track_id */ + enum e_side get_ipin_node_grid_side(t_rr_node* ipin_node) const; /* get a rr_node at a given side and track_id */ + size_t get_num_opin_nodes(enum e_side side) const; /* Get the number of OPIN rr_nodes on a side */ + t_rr_node* get_opin_node(enum e_side side, size_t node_id) const; /* get a rr_node at a given side and track_id */ + enum e_side get_opin_node_grid_side(enum e_side side, size_t node_id) const; /* get a rr_node at a given side and track_id */ + enum e_side get_opin_node_grid_side(t_rr_node* opin_node) const; /* get a rr_node at a given side and track_id */ + int get_cb_chan_node_index(t_rr_type cb_type, t_rr_node* node) const; + int get_chan_node_index(enum e_side node_side, t_rr_node* node) const; + int get_node_index(t_rr_node* node, enum e_side node_side, enum PORTS node_direction) const; /* Get the node index in the array, return -1 if not found */ + void get_node_side_and_index(t_rr_node* node, enum PORTS node_direction, enum e_side* node_side, int* node_index) const; /* Given a rr_node, try to find its side and index in the Switch block */ + bool is_sb_node_exist_opposite_side(t_rr_node* node, enum e_side node_side) const; /* Check if the node exist in the opposite side of this Switch Block */ + public: /* Accessors: get information about configuration ports */ + size_t get_sb_num_reserved_conf_bits() const; + size_t get_sb_reserved_conf_bits_lsb() const; + size_t get_sb_reserved_conf_bits_msb() const; + size_t get_sb_num_conf_bits() const; + size_t get_sb_conf_bits_lsb() const; + size_t get_sb_conf_bits_msb() const; + size_t get_cb_num_reserved_conf_bits(t_rr_type cb_type) const; + size_t get_cb_reserved_conf_bits_lsb(t_rr_type cb_type) const; + size_t get_cb_reserved_conf_bits_msb(t_rr_type cb_type) const; + size_t get_cb_num_conf_bits(t_rr_type cb_type) const; + size_t get_cb_conf_bits_lsb(t_rr_type cb_type) const; + size_t get_cb_conf_bits_msb(t_rr_type cb_type) const; + bool is_sb_node_passing_wire(const enum e_side node_side, const size_t track_id) const; /* Check if the node imply a short connection inside the SB, which happens to long wires across a FPGA fabric */ + bool is_sb_side_mirror(const RRGSB& cand, enum e_side side) const; /* check if a side of candidate SB is a mirror of the current one */ + bool is_sb_side_segment_mirror(const RRGSB& cand, enum e_side side, size_t seg_id) const; /* check if all the routing segments of a side of candidate SB is a mirror of the current one */ + bool is_sb_mirror(const RRGSB& cand) const; /* check if the candidate SB is a mirror of the current one */ + bool is_sb_mirrorable(const RRGSB& cand) const; /* check if the candidate SB satisfy the basic requirements on being a mirror of the current one */ + bool is_cb_mirror(const RRGSB& cand, t_rr_type cb_type) const; /* check if the candidate SB is a mirror of the current one */ + bool is_cb_exist(t_rr_type cb_type) const; /* check if the candidate SB is a mirror of the current one */ + size_t get_hint_rotate_offset(const RRGSB& cand) const; /* Determine an initial offset in rotating the candidate Switch Block to find a mirror matching*/ + public: /* Cooridinator conversion and output */ + size_t get_x() const; /* get the x coordinator of this switch block */ + size_t get_y() const; /* get the y coordinator of this switch block */ + size_t get_sb_x() const; /* get the x coordinator of this switch block */ + size_t get_sb_y() const; /* get the y coordinator of this switch block */ + DeviceCoordinator get_sb_coordinator() const; /* Get the coordinator of the SB */ + size_t get_cb_x(t_rr_type cb_type) const; /* get the x coordinator of this X/Y-direction block */ + size_t get_cb_y(t_rr_type cb_type) const; /* get the y coordinator of this X/Y-direction block */ + DeviceCoordinator get_cb_coordinator(t_rr_type cb_type) const; /* Get the coordinator of the X/Y-direction CB */ + enum e_side get_cb_chan_side(t_rr_type cb_type) const; /* get the side of a Connection block */ + enum e_side get_cb_chan_side(enum e_side ipin_side) const; /* get the side of a Connection block */ + DeviceCoordinator get_side_block_coordinator(enum e_side side) const; + DeviceCoordinator get_grid_coordinator() const; + public: /* Verilog writer */ + const char* gen_gsb_verilog_module_name() const; + const char* gen_gsb_verilog_instance_name() const; + const char* gen_sb_verilog_module_name() const; + const char* gen_sb_verilog_instance_name() const; + const char* gen_sb_verilog_side_module_name(enum e_side side, size_t seg_id) const; + const char* gen_sb_verilog_side_instance_name(enum e_side side, size_t seg_id) const; + const char* gen_cb_verilog_module_name(t_rr_type cb_type) const; + const char* gen_cb_verilog_instance_name(t_rr_type cb_type) const; + const char* gen_cb_verilog_routing_track_name(t_rr_type cb_type, size_t track_id) const; + public: /* Mutators */ + void set(const RRGSB& src); /* get a copy from a source */ + void set_coordinator(size_t x, size_t y); + void init_num_sides(size_t num_sides); /* Allocate the vectors with the given number of sides */ + void add_chan_node(enum e_side node_side, RRChan& rr_chan, std::vector rr_chan_dir); /* Add a node to the chan_rr_node_ list and also assign its direction in chan_rr_node_direction_ */ + void add_ipin_node(t_rr_node* node, const enum e_side node_side, const enum e_side grid_side); /* Add a node to the chan_rr_node_ list and also assign its direction in chan_rr_node_direction_ */ + void add_opin_node(t_rr_node* node, const enum e_side node_side, const enum e_side grid_side); /* Add a node to the chan_rr_node_ list and also assign its direction in chan_rr_node_direction_ */ + void set_sb_num_reserved_conf_bits(size_t num_reserved_conf_bits); + void set_sb_conf_bits_lsb(size_t conf_bits_lsb); + void set_sb_conf_bits_msb(size_t conf_bits_msb); + void set_cb_num_reserved_conf_bits(t_rr_type cb_type, size_t num_reserved_conf_bits); + void set_cb_conf_bits_lsb(t_rr_type cb_type, size_t conf_bits_lsb); + void set_cb_conf_bits_msb(t_rr_type cb_type, size_t conf_bits_msb); + void rotate_side_chan_node_by_direction(enum e_side side, enum e_direction chan_dir, size_t offset); /* rotate all the channel nodes by a given offset */ + void counter_rotate_side_chan_node_by_direction(enum e_side side, enum e_direction chan_dir, size_t offset); /* rotate all the channel nodes by a given offset */ + void rotate_side_chan_node(enum e_side side, size_t offset); /* rotate all the channel nodes by a given offset */ + void rotate_chan_node(size_t offset); /* rotate all the channel nodes by a given offset */ + void rotate_chan_node_in_group(size_t offset); /* rotate all the channel nodes by a given offset */ + void rotate_side_opin_node_in_group(enum e_side side, size_t offset); /* rotate all the opin nodes by a given offset */ + void rotate_opin_node_in_group(size_t offset); /* rotate all the opin nodes by a given offset */ + void rotate_side(enum e_side side, size_t offset); /* rotate all the channel and opin nodes by a given offset */ + void rotate(size_t offset); /* rotate all the channel and opin nodes by a given offset */ + void swap_chan_node(enum e_side src_side, enum e_side des_side); /* swap the chan rr_nodes on two sides */ + void swap_opin_node(enum e_side src_side, enum e_side des_side); /* swap the OPIN rr_nodes on two sides */ + void swap_ipin_node(enum e_side src_side, enum e_side des_side); /* swap the IPIN rr_nodes on two sides */ + void reverse_opin_node(enum e_side side); /* reverse the OPIN rr_nodes on two sides */ + void reverse_ipin_node(enum e_side side); /* reverse the IPIN rr_nodes on two sides */ + public: /* Mutators: cleaners */ + void clear(); + void clear_chan_nodes(enum e_side node_side); /* Clean the chan_width of a side */ + void clear_ipin_nodes(enum e_side node_side); /* Clean the number of IPINs of a side */ + void clear_opin_nodes(enum e_side node_side); /* Clean the number of OPINs of a side */ + void clear_one_side(enum e_side node_side); /* Clean chan/opin/ipin nodes at one side */ + private: /* Internal Mutators */ + void mirror_side_chan_node_direction(enum e_side side); /* Mirror the node direction and port direction of routing track nodes on a side */ + private: /* internal functions */ + bool is_sb_node_mirror (const RRGSB& cand, enum e_side node_side, size_t track_id) const; + bool is_cb_node_mirror (const RRGSB& cand, t_rr_type cb_type, enum e_side node_side, size_t node_id) const; + size_t get_track_id_first_short_connection(enum e_side node_side) const; + bool validate_num_sides() const; + bool validate_side(enum e_side side) const; + bool validate_track_id(enum e_side side, size_t track_id) const; + bool validate_opin_node_id(enum e_side side, size_t node_id) const; + bool validate_ipin_node_id(enum e_side side, size_t node_id) const; + bool validate_cb_type(t_rr_type cb_type) const; + private: /* Internal Data */ + /* Coordinator */ + DeviceCoordinator coordinator_; + /* Routing channel data */ + std::vector chan_node_; + std::vector< std::vector > chan_node_direction_; + + /* Logic Block Inputs data */ + std::vector< std::vector > ipin_node_; + std::vector< std::vector > ipin_node_grid_side_; + + /* Logic Block Outputs data */ + std::vector< std::vector > opin_node_; + std::vector< std::vector > opin_node_grid_side_; + + /* Configuration bits */ + ConfPorts sb_conf_port_; + ConfPorts cbx_conf_port_; + ConfPorts cby_conf_port_; +}; + + +} /* End namespace openfpga*/ + +#endif