<commit_before>#include <set>
#include <vector>
#include <map>
#include <cmath>

#include "util.hpp"

#include "tatum_error.hpp"
#include "TimingGraph.hpp"
#include "TimingConstraints.hpp"

using tatum::TimingGraph;
using tatum::TimingConstraints;
using tatum::NodeId;
using tatum::EdgeId;
using tatum::NodeType;

template<typename Range>
size_t num_valid(Range range) {
    size_t count = 0;
    for(auto val : range) {
        if(val) ++count;
    }
    return count;
}

template<typename Range>
typename Range::iterator ith_valid(Range range, size_t i) {
    size_t j = 0;
    for(auto iter = range.begin(); iter != range.end(); ++iter) {
        if(*iter && ++j == i) return iter;
    }
    throw tatum::Error("No valid ith value");
}

void rebuild_timing_graph(TimingGraph& tg, TimingConstraints& tc, const VprFfInfo& ff_info, std::vector<float>& edge_delays, VprArrReqTimes& arr_req_times) {
    TimingConstraints new_tc;

    //Rebuild the graph to elminate redundant nodes (e.g. IPIN/OPINs in front of SOURCES/SINKS)

    std::map<NodeId,NodeId> arr_req_remap;

    for(NodeId node : tg.nodes()) {
        if(tg.node_type(node) == NodeType::SOURCE) {
            for(EdgeId out_edge : tg.node_out_edges(node)) {
                NodeId sink_node = tg.edge_sink_node(out_edge);

                TATUM_ASSERT(tg.node_type(sink_node) == NodeType::OPIN);

                if(tg.node_in_edges(node).size() == 0) {
                    //Primary Input source node
                    NodeId opin_src_node = node;
                    NodeId opin_node = sink_node;
                    TATUM_ASSERT(tg.node_out_edges(opin_node).size() == 1);
                    EdgeId opin_out_edge = *tg.node_out_edges(opin_node).begin();
                    NodeId opin_sink_node = tg.edge_sink_node(opin_out_edge);

                    float constraint = edge_delays[size_t(out_edge)];
                    float opin_out_delay = edge_delays[size_t(opin_out_edge)];

                    //Remove the node (and it's connected edges)
                    tg.remove_node(opin_node);

                    //Add the new edge
                    EdgeId new_edge = tg.add_edge(opin_src_node, opin_sink_node);

                    //Set the edge delay
                    edge_delays.resize(size_t(new_edge) + 1); //Make space
                    edge_delays[size_t(new_edge)] = opin_out_delay;

                    tc.set_input_constraint(opin_src_node, tc.node_clock_domain(opin_src_node), constraint);<commit_msg>Handle multiple outputs of a SOURCE OPIN<commit_after>#include <set>
#include <vector>
#include <map>
#include <cmath>

#include "util.hpp"

#include "tatum_error.hpp"
#include "TimingGraph.hpp"
#include "TimingConstraints.hpp"

using tatum::TimingGraph;
using tatum::TimingConstraints;
using tatum::NodeId;
using tatum::EdgeId;
using tatum::NodeType;

template<typename Range>
size_t num_valid(Range range) {
    size_t count = 0;
    for(auto val : range) {
        if(val) ++count;
    }
    return count;
}

template<typename Range>
typename Range::iterator ith_valid(Range range, size_t i) {
    size_t j = 0;
    for(auto iter = range.begin(); iter != range.end(); ++iter) {
        if(*iter && ++j == i) return iter;
    }
    throw tatum::Error("No valid ith value");
}

void rebuild_timing_graph(TimingGraph& tg, TimingConstraints& tc, const VprFfInfo& ff_info, std::vector<float>& edge_delays, VprArrReqTimes& arr_req_times) {
    TimingConstraints new_tc;

    //Rebuild the graph to elminate redundant nodes (e.g. IPIN/OPINs in front of SOURCES/SINKS)

    std::map<NodeId,NodeId> arr_req_remap;

    for(NodeId node : tg.nodes()) {
        if(tg.node_type(node) == NodeType::SOURCE) {
            for(EdgeId out_edge : tg.node_out_edges(node)) {
                NodeId sink_node = tg.edge_sink_node(out_edge);

                TATUM_ASSERT(tg.node_type(sink_node) == NodeType::OPIN);

                if(tg.node_in_edges(node).size() == 0) {
                    //Primary Input source node
                    NodeId opin_src_node = node;
                    NodeId opin_node = sink_node;
                    float constraint = edge_delays[size_t(out_edge)];

                    std::map<NodeId,float> new_edges;
                    for(EdgeId opin_out_edge : tg.node_out_edges(opin_node)) {
                        NodeId opin_sink_node = tg.edge_sink_node(opin_out_edge);

                        float opin_out_delay = edge_delays[size_t(opin_out_edge)];

                        new_edges[opin_sink_node] = opin_out_delay;
                    }

                    //Remove the node (and it's connected edges)
                    tg.remove_node(opin_node);

                    //Add the new edges
                    for(auto kv : new_edges) {
                        NodeId opin_sink_node = kv.first;
                        float delay = kv.second;

                        EdgeId new_edge = tg.add_edge(opin_src_node, opin_sink_node);

                        //Set the edge delay
                        edge_delays.resize(size_t(new_edge) + 1); //Make space
                        edge_delays[size_t(new_edge)] = delay;
                    }

                    //Set the constraint
                    tc.set_input_constraint(opin_src_node, tc.node_clock_domain(opin_src_node), constraint);
{'fraction_non_alphanumeric': 0.10644310474755087, 'fraction_numerical': 0.0016955538809344385, 'mean_word_length': 2.273119605425401, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4849239', 'n_tokens_mistral': 1787, 'n_tokens_neox': 1665, 'n_words': 349}