blob: 07288ed08ba5c59bbd8600e123d10b68500c1598 [file]
#pragma once
#include <map>
#include <vector>
#include <unordered_set>
#include "tatum/util/tatum_linear_map.hpp"
#include "tatum/util/tatum_range.hpp"
#include "tatum/base/ArrivalType.hpp"
#include "tatum/base/DelayType.hpp"
#include "tatum/TimingConstraintsFwd.hpp"
#include "tatum/TimingGraphFwd.hpp"
#include "tatum/Time.hpp"
namespace tatum {
/**
* The TimingConstraints class stores all the timing constraints applied during timing analysis.
*/
class TimingConstraints {
public: //Types
typedef tatum::util::linear_map<DomainId,DomainId>::const_iterator domain_iterator;
typedef std::map<NodeDomainPair,Time>::const_iterator clock_constraint_iterator;
typedef std::map<DomainPair,Time>::const_iterator clock_uncertainty_iterator;
typedef std::multimap<NodeId,IoConstraint>::const_iterator io_constraint_iterator;
typedef std::map<DomainId,Time>::const_iterator source_latency_iterator;
typedef std::unordered_set<NodeId>::const_iterator constant_generator_iterator;
typedef tatum::util::Range<domain_iterator> domain_range;
typedef tatum::util::Range<clock_constraint_iterator> clock_constraint_range;
typedef tatum::util::Range<clock_uncertainty_iterator> clock_uncertainty_range;
typedef tatum::util::Range<io_constraint_iterator> io_constraint_range;
typedef tatum::util::Range<source_latency_iterator> source_latency_range;
typedef tatum::util::Range<constant_generator_iterator> constant_generator_range;
public: //Accessors
///\returns A range containing all defined clock domains
domain_range clock_domains() const;
///\returns The name of a clock domain
std::string clock_domain_name(const DomainId id) const;
///\returns The source NodeId of the specified domain
NodeId clock_domain_source_node(const DomainId id) const;
//\returns whether the specified domain id corresponds to a virtual lcock
bool is_virtual_clock(const DomainId id) const;
///\returns The domain of the specified node id if it is a clock source
DomainId node_clock_domain(const NodeId id) const;
///\returns True if the node id is a clock source
bool node_is_clock_source(const NodeId id) const;
///\returns True if the node id is a constant generator
bool node_is_constant_generator(const NodeId id) const;
///\returns A valid DomainId if a clock domain with the specified name exists, DomainId::INVALID() otherwise
DomainId find_clock_domain(const std::string& name) const;
///Indicates whether the paths between src_domain and sink_domain should be analyzed
///\param src_domain The ID of the source (launch) clock domain
///\param sink_domain The ID of the sink (capture) clock domain
bool should_analyze(const DomainId src_domain, const DomainId sink_domain, const NodeId capture_node=NodeId::INVALID()) const;
///\returns The setup (max) constraint between src_domain and sink_domain at the specified capture_node_id
Time setup_constraint(const DomainId src_domain, const DomainId sink_domain, const NodeId capture_node=NodeId::INVALID()) const;
///\returns The hold (min) constraint between src_domain and sink_domain at the specified capture_node_id
Time hold_constraint(const DomainId src_domain, const DomainId sink_domain, const NodeId capture_node=NodeId::INVALID()) const;
///\returns The setup clock uncertainty between src_domain and sink_domain (defaults to zero if unspecified)
Time setup_clock_uncertainty(const DomainId src_domain, const DomainId sink_domain) const;
///\returns The hold clock uncertainty between src_domain and sink_domain (defaults to zero if unspecified)
Time hold_clock_uncertainty(const DomainId src_domain, const DomainId sink_domain) const;
///\returns The input delay constraint on node_id
Time input_constraint(const NodeId node_id, const DomainId domain_id, const DelayType delay_type) const;
///\returns The output delay constraint on node_id
Time output_constraint(const NodeId node_id, const DomainId domain_id, const DelayType delay_type) const;
///\returns The external (e.g. off-chip) source latency of a particular clock domain
//
//Corresponds to the delay from the clock's true source to it's definition point on-chip
Time source_latency(const DomainId domain_id, ArrivalType arrival_type) const;
///\returns A range of all constant generator nodes
constant_generator_range constant_generators() const;
///\returns A range of all setup constraints
clock_constraint_range setup_constraints() const;
///\returns A range of all setup constraints
clock_constraint_range hold_constraints() const;
///\returns A range of all setup clock uncertainties
clock_uncertainty_range setup_clock_uncertainties() const;
///\returns A range of all hold clock uncertainties
clock_uncertainty_range hold_clock_uncertainties() const;
///\returns A range of all input constraints
io_constraint_range input_constraints(const DelayType delay_type) const;
///\returns A range of all output constraints
io_constraint_range output_constraints(const DelayType delay_type) const;
///\returns A range of output constraints for the node id
io_constraint_range input_constraints(const NodeId id, const DelayType delay_type) const;
///\returns A range of input constraints for the node id
io_constraint_range output_constraints(const NodeId id, const DelayType delay_type) const;
///\returns A range of all clock source latencies
source_latency_range source_latencies(ArrivalType arrival_type) const;
///Prints out the timing constraints for debug purposes
void print_constraints() const;
public: //Mutators
///\returns The DomainId of the clock with the specified name (will be created if it doesn not exist)
DomainId create_clock_domain(const std::string name);
///Sets the setup constraint between src_domain and sink_domain with value constraint
void set_setup_constraint(const DomainId src_domain, const DomainId sink_domain, const Time constraint);
void set_setup_constraint(const DomainId src_domain, const DomainId sink_domain, const NodeId capture_node, const Time constraint);
///Sets the hold constraint between src_domain and sink_domain with value constraint
void set_hold_constraint(const DomainId src_domain, const DomainId sink_domain, const Time constraint);
void set_hold_constraint(const DomainId src_domain, const DomainId sink_domain, const NodeId capture_node, const Time constraint);
///Sets the setup clock uncertainty between src_domain and sink_domain with value uncertainty
void set_setup_clock_uncertainty(const DomainId src_domain, const DomainId sink_domain, const Time uncertainty);
///Sets the hold clock uncertainty between src_domain and sink_domain with value uncertainty
void set_hold_clock_uncertainty(const DomainId src_domain, const DomainId sink_domain, const Time uncertainty);
///Sets the input delay constraint on node_id with value constraint
void set_input_constraint(const NodeId node_id, const DomainId domain_id, const DelayType delay_type, const Time constraint);
///Sets the output delay constraint on node_id with value constraint
void set_output_constraint(const NodeId node_id, const DomainId domain_id, const DelayType delay_type, const Time constraint);
///Sets the source latency of the specified clock domain
void set_source_latency(const DomainId domain_id, const ArrivalType arrival_type, const Time latency);
///Sets the source node for the specified clock domain
void set_clock_domain_source(const NodeId node_id, const DomainId domain_id);
///Sets whether the specified node is a constant generator
void set_constant_generator(const NodeId node_id, bool is_constant_generator=true);
///Update node IDs if they have changed
///\param node_map A vector mapping from old to new node ids
void remap_nodes(const tatum::util::linear_map<NodeId,NodeId>& node_map);
private:
typedef std::multimap<NodeId,IoConstraint>::iterator mutable_io_constraint_iterator;
private:
///\returns A valid domain id if the node is a clock source
DomainId find_node_source_clock_domain(const NodeId node_id) const;
io_constraint_iterator find_io_constraint(const NodeId node_id, const DomainId domain_id, const std::multimap<NodeId,IoConstraint>& io_constraints) const;
mutable_io_constraint_iterator find_io_constraint(const NodeId node_id, const DomainId domain_id, std::multimap<NodeId,IoConstraint>& io_constraints);
private: //Data
tatum::util::linear_map<DomainId,DomainId> domain_ids_;
tatum::util::linear_map<DomainId,std::string> domain_names_;
tatum::util::linear_map<DomainId,NodeId> domain_sources_;
std::unordered_set<NodeId> constant_generators_;
//The setup/hold constraints between clock domains and sink nodes
//If the key's capture_node is INVALID() it is treated as a wildcard (i.e. default)
//constraint
std::map<NodeDomainPair,Time> setup_constraints_;
std::map<NodeDomainPair,Time> hold_constraints_;
std::map<DomainPair,Time> setup_clock_uncertainties_;
std::map<DomainPair,Time> hold_clock_uncertainties_;
std::multimap<NodeId,IoConstraint> max_input_constraints_;
std::multimap<NodeId,IoConstraint> min_input_constraints_;
std::multimap<NodeId,IoConstraint> max_output_constraints_;
std::multimap<NodeId,IoConstraint> min_output_constraints_;
std::map<DomainId,Time> source_latencies_early_;
std::map<DomainId,Time> source_latencies_late_;
};
/*
* Utility classes
*/
struct DomainPair {
DomainPair(DomainId src, DomainId sink): src_domain_id(src), sink_domain_id(sink) {}
friend bool operator<(const DomainPair& lhs, const DomainPair& rhs) {
return std::tie(lhs.src_domain_id, lhs.sink_domain_id) < std::tie(rhs.src_domain_id, rhs.sink_domain_id);
}
DomainId src_domain_id;
DomainId sink_domain_id;
};
struct NodeDomainPair {
NodeDomainPair(DomainId src, DomainId sink, NodeId to_node)
: domain_pair(src, sink), capture_node(to_node) {}
friend bool operator<(const NodeDomainPair& lhs, const NodeDomainPair& rhs) {
return std::tie(lhs.capture_node, lhs.domain_pair) < std::tie(rhs.capture_node, rhs.domain_pair);
}
DomainPair domain_pair;
NodeId capture_node; //Should be treated as a wild-card if capture_node is NodeId::INVALID()
};
struct IoConstraint {
IoConstraint(DomainId domain_id, Time constraint_val): domain(domain_id), constraint(constraint_val) {}
DomainId domain;
Time constraint;
};
} //namepsace