add graph-based mux decoding function

This commit is contained in:
tangxifan 2019-08-18 00:06:38 -06:00
parent dcca9f4f0f
commit 153d506abb
3 changed files with 135 additions and 17 deletions

View File

@ -60,7 +60,8 @@ size_t MuxGraph::num_inputs() const {
/* Find the number of levels in the MUX graph */
size_t MuxGraph::num_levels() const {
/* FIXME: need to check if the graph is valid or not */
return node_lookup_.size();
/* The num_levels by definition excludes the level for outputs, so a deduection is applied */
return node_lookup_.size() - 1;
}
/* Find the number of configuration memories in the MUX graph */
@ -101,6 +102,57 @@ std::vector<size_t> MuxGraph::branch_sizes() const {
return branch;
}
/* Get the node id of a given input */
MuxNodeId MuxGraph::node_id(const MuxInputId& input_id) const {
/* Use the node_lookup to accelerate the search */
for (const auto& lvl : node_lookup_) {
for (const auto& cand_node : lvl[MUX_INPUT_NODE]) {
if (input_id == node_input_ids_[cand_node]) {
return cand_node;
}
}
}
return MuxNodeId::INVALID();
}
/* Decode memory bits based on an input id */
std::vector<size_t> MuxGraph::decode_memory_bits(const MuxInputId& input_id) const {
/* initialize the memory bits: TODO: support default value */
std::vector<size_t> mem_bits(mem_ids_.size(), 0);
/* valid the input */
VTR_ASSERT_SAFE(valid_input_id(input_id));
/* Route the input to the output and update mem */
MuxNodeId next_node = node_id(input_id);
while ( 0 < node_out_edges_[next_node].size() ) {
VTR_ASSERT_SAFE (1 == node_out_edges_[next_node].size());
MuxEdgeId edge = node_out_edges_[next_node][0];
/* Configure the mem bits:
* if inv_mem is enabled, it means 0 to enable this edge
* otherwise, it is 1 to enable this edge
*/
MuxMemId mem = edge_mem_ids_[edge];
VTR_ASSERT_SAFE (valid_mem_id(mem));
if (true == edge_inv_mem_[edge]) {
mem_bits[size_t(mem)] = 0;
} else {
mem_bits[size_t(mem)] = 1;
}
/* each edge must have 1 fan-out */
VTR_ASSERT_SAFE (1 == edge_sink_nodes_[edge].size());
/* Visit the next node */
next_node = edge_sink_nodes_[edge][0];
}
VTR_ASSERT_SAFE(MUX_OUTPUT_NODE == node_types_[next_node]);
return mem_bits;
}
/**************************************************
* Private mutators: basic operations
*************************************************/
@ -111,7 +163,7 @@ MuxNodeId MuxGraph::add_node(const enum e_mux_graph_node_type& node_type) {
node_ids_.push_back(node);
/* Resize the other node-related vectors */
node_types_.push_back(node_type);
node_input_ids_.push_back(-1);
node_input_ids_.push_back(MuxInputId::INVALID());
node_levels_.push_back(-1);
node_in_edges_.emplace_back();
node_out_edges_.emplace_back();
@ -129,12 +181,14 @@ MuxEdgeId MuxGraph::add_edge(const MuxNodeId& from_node, const MuxNodeId& to_nod
edge_mem_ids_.push_back(MuxMemId::INVALID());
edge_inv_mem_.push_back(false);
/* update the node_in_edges and node_out_edges */
/* update the edge-node connections */
VTR_ASSERT(valid_node_id(from_node));
edge_src_nodes_[edge].push_back(from_node);
node_out_edges_[from_node].push_back(edge);
VTR_ASSERT(valid_node_id(to_node));
node_in_edges_[to_node].push_back(edge);
edge_sink_nodes_[edge].push_back(to_node);
return edge;
}
@ -302,7 +356,7 @@ void MuxGraph::build_multilevel_mux_graph(const size_t& mux_size,
continue;
}
/* Update the input node ids */
node_input_ids_[cand_node] = input_cnt;
node_input_ids_[cand_node] = MuxInputId(input_cnt);
/* Update the counter */
input_cnt++;
}
@ -339,7 +393,7 @@ void MuxGraph::build_onelevel_mux_graph(const size_t& mux_size,
for (size_t i = 0; i < mux_size; ++i) {
MuxNodeId input_node = add_node(MUX_INPUT_NODE);
/* All the node belong to level 0 (we have only 1 level) */
node_input_ids_[input_node] = i;
node_input_ids_[input_node] = MuxInputId(i);
node_levels_[input_node] = 0;
/* We definitely know how many edges we need,
@ -434,15 +488,6 @@ void MuxGraph::build_node_lookup() {
}
}
bool MuxGraph::valid_node_lookup() const {
return node_lookup_.empty();
}
/* Invalidate (empty) the node fast lookup*/
void MuxGraph::invalidate_node_lookup() {
node_lookup_.clear();
}
/**************************************************
* Private validators
*************************************************/
@ -460,6 +505,66 @@ bool MuxGraph::valid_mem_id(const MuxMemId& mem) const {
return size_t(mem) < mem_ids_.size() && mem_ids_[mem] == mem;
}
/* validate an input id (from which data path signal will be progagated to the output */
bool MuxGraph::valid_input_id(const MuxInputId& input_id) const {
for (const auto& lvl : node_lookup_) {
for (const auto& node : lvl[MUX_INPUT_NODE]) {
if (size_t(input_id) > size_t(node_input_ids_[node])) {
return false;
}
}
}
return true;
}
bool MuxGraph::valid_node_lookup() const {
return node_lookup_.empty();
}
/* Invalidate (empty) the node fast lookup*/
void MuxGraph::invalidate_node_lookup() {
node_lookup_.clear();
}
/* validate a mux graph and see if it is valid */
bool MuxGraph::valid_mux_graph() const {
/* A valid MUX graph should be
* 1. every node has 1 fan-out except output node
* 2. every input can be routed to the output node
*/
for (const auto& node : nodes()) {
/* output node has 0 fan-out*/
if (MUX_OUTPUT_NODE == node_types_[node]) {
continue;
}
/* other nodes should have 1 fan-out */
if (1 != node_out_edges_[node].size()) {
return false;
}
}
/* Try to route to output */
for (const auto& node : nodes()) {
if (MUX_INPUT_NODE == node_types_[node]) {
MuxNodeId next_node = node;
while ( 0 < node_out_edges_[next_node].size() ) {
MuxEdgeId edge = node_out_edges_[next_node][0];
/* each edge must have 1 fan-out */
if (1 != edge_sink_nodes_[edge].size()) {
return false;
}
next_node = edge_sink_nodes_[edge][0];
}
if (MUX_OUTPUT_NODE != node_types_[next_node]) {
return false;
}
}
}
return true;
}
/**************************************************
* End of Member functions for the class MuxGraph
*************************************************/

View File

@ -67,6 +67,10 @@ class MuxGraph {
size_t num_memory_bits() const;
/* Find the sizes of each branch of a MUX */
std::vector<size_t> branch_sizes() const;
/* Get the node id of a given input */
MuxNodeId node_id(const MuxInputId& input_id) const;
/* Decode memory bits based on an input id */
std::vector<size_t> decode_memory_bits(const MuxInputId& input_id) const;
private: /* Private mutators : basic operations */
/* Add a unconfigured node to the MuxGraph */
MuxNodeId add_node(const enum e_mux_graph_node_type& node_type);
@ -94,18 +98,23 @@ class MuxGraph {
bool valid_node_id(const MuxNodeId& node) const;
bool valid_edge_id(const MuxEdgeId& edge) const;
bool valid_mem_id(const MuxMemId& mem) const;
bool valid_input_id(const MuxInputId& input_id) const;
/* validate/invalidate node lookup */
bool valid_node_lookup() const;
void invalidate_node_lookup();
/* validate graph */
bool valid_mux_graph() const;
private: /* Internal data */
vtr::vector<MuxNodeId, MuxNodeId> node_ids_; /* Unique ids for each node */
vtr::vector<MuxNodeId, enum e_mux_graph_node_type> node_types_; /* type of each node, input/output/internal */
vtr::vector<MuxNodeId, size_t> node_input_ids_; /* Unique ids for each node as an input of the MUX */
vtr::vector<MuxNodeId, MuxInputId> node_input_ids_; /* Unique ids for each node as an input of the MUX */
vtr::vector<MuxNodeId, size_t> node_levels_; /* at which level, each node belongs to */
vtr::vector<MuxNodeId, std::vector<MuxEdgeId>> node_in_edges_; /* ids of incoming edges to each node */
vtr::vector<MuxNodeId, std::vector<MuxEdgeId>> node_out_edges_; /* ids of outgoing edges from each node */
vtr::vector<MuxEdgeId, MuxEdgeId> edge_ids_; /* Unique ids for each edge */
vtr::vector<MuxEdgeId, std::vector<MuxNodeId>> edge_src_nodes_; /* source nodes drive this edge */
vtr::vector<MuxEdgeId, std::vector<MuxNodeId>> edge_sink_nodes_; /* sink nodes this edge drives */
vtr::vector<MuxEdgeId, enum e_spice_model_pass_gate_logic_type> edge_types_; /* type of each edge: tgate/pass-gate */
vtr::vector<MuxEdgeId, MuxMemId> edge_mem_ids_; /* ids of memory bit that control the edge */
vtr::vector<MuxEdgeId, bool> edge_inv_mem_; /* if the edge is controlled by an inverted output of a memory bit */
@ -119,8 +128,10 @@ class MuxGraph {
class MuxLibrary {
private: /* Internal data */
/* MUX graph-based desription */
vtr::vector<MuxId, MuxGraph> mux_graphs_; /* Graphs describing MUX internal structures */
vtr::vector<MuxId, CircuitModelId> circuit_model_ids_; /* ids in the circuit library, each MUX graph belongs to*/
/* Local encoder description */
};
#endif

View File

@ -13,11 +13,13 @@ struct mux_id_tag;
struct mux_node_id_tag;
struct mux_edge_id_tag;
struct mux_mem_id_tag;
struct mux_input_id_tag;
typedef vtr::StrongId<mux_id_tag> MuxId;
typedef vtr::StrongId<mux_node_id_tag> MuxNodeId;
typedef vtr::StrongId<mux_edge_id_tag> MuxEdgeId;
typedef vtr::StrongId<mux_mem_id_tag> MuxMemId;
typedef vtr::StrongId<mux_input_id_tag> MuxInputId;
class MuxGraph;
class MuxLibrary;