-
Notifications
You must be signed in to change notification settings - Fork 430
Add support for falling edge clocking #2211
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 24 commits
638a476
00c53c0
b9d570d
af81901
b4af78f
c653664
f1089f7
4253fac
560e5ee
a82d8d4
a1f7c54
725bc6b
9033994
c1004c1
4df34e1
55c6c47
04cb06c
2653d83
76b9203
b63083b
b26fbaa
5e4a8f6
c28d73b
9e566eb
b0adc09
b592f23
5d297ec
b177df7
c1b127c
9a0467f
5b47ceb
2a4f193
079efe0
ab19fee
2353564
e0a3b93
362821a
0ce6545
5c76fcb
7f9c9b0
d859ec3
de3857d
977b9d6
3e4cd85
91369c9
ebfaea8
4649f0f
cb46900
50fe438
9996637
f6e7fea
e947026
4ed6e5a
aa0561b
c59f504
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,6 +20,10 @@ std::string TimingConstraints::clock_domain_name(const DomainId id) const { | |
| return domain_names_[id]; | ||
| } | ||
|
|
||
| bool TimingConstraints::clock_domain_inverted(const DomainId id) const { | ||
| return domain_inverted_[id]; | ||
| } | ||
|
|
||
| NodeId TimingConstraints::clock_domain_source_node(const DomainId id) const { | ||
| return domain_sources_[id]; | ||
| } | ||
|
|
@@ -292,7 +296,8 @@ DomainId TimingConstraints::create_clock_domain(const std::string name) { | |
| //Create it | ||
| id = DomainId(domain_ids_.size()); | ||
| domain_ids_.push_back(id); | ||
|
|
||
|
|
||
| domain_inverted_.push_back(false); | ||
| domain_names_.push_back(name); | ||
| domain_sources_.emplace_back(NodeId::INVALID()); | ||
|
|
||
|
|
@@ -303,6 +308,24 @@ DomainId TimingConstraints::create_clock_domain(const std::string name) { | |
| return id; | ||
| } | ||
|
|
||
| DomainId TimingConstraints::create_clock_domain(const std::string name, bool inverted) { | ||
| DomainId id = find_clock_domain(name); | ||
| if(!id) { | ||
| //Create it | ||
| id = DomainId(domain_ids_.size()); | ||
| domain_ids_.push_back(id); | ||
|
|
||
| domain_inverted_.push_back(inverted); | ||
|
||
| domain_names_.push_back(name); | ||
| domain_sources_.emplace_back(NodeId::INVALID()); | ||
|
|
||
| TATUM_ASSERT(clock_domain_name(id) == name); | ||
| TATUM_ASSERT(find_clock_domain(name) == id); | ||
| } | ||
|
|
||
| return id; | ||
| } | ||
|
|
||
| void TimingConstraints::set_setup_constraint(const DomainId src_domain, const DomainId sink_domain, const Time constraint) { | ||
| set_setup_constraint(src_domain, sink_domain, NodeId::INVALID(), constraint); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -42,6 +42,8 @@ class TimingConstraints { | |
| ///\returns The name of a clock domain | ||
| std::string clock_domain_name(const DomainId id) const; | ||
|
|
||
| bool clock_domain_inverted(const DomainId id) const; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a comment saying what this does (can be short, but should explain what an inverted clock implies). Should be doxygen style, like the rest of the comments in this file.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added |
||
|
|
||
| ///\returns The source NodeId of the specified domain | ||
| NodeId clock_domain_source_node(const DomainId id) const; | ||
|
|
||
|
|
@@ -123,6 +125,7 @@ class TimingConstraints { | |
| 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); | ||
| DomainId create_clock_domain(const std::string name, bool inverted); | ||
|
|
||
| ///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); | ||
|
|
@@ -170,6 +173,7 @@ class TimingConstraints { | |
| private: //Data | ||
| tatum::util::linear_map<DomainId,DomainId> domain_ids_; | ||
| tatum::util::linear_map<DomainId,std::string> domain_names_; | ||
| tatum::util::linear_map<DomainId, bool> domain_inverted_; | ||
| tatum::util::linear_map<DomainId,NodeId> domain_sources_; | ||
|
|
||
| std::unordered_set<NodeId> constant_generators_; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -84,6 +84,24 @@ class TimingGraph { | |
| ///\returns The type of the node | ||
| NodeType node_type(const NodeId id) const { return node_types_[id]; } | ||
|
|
||
| int trigg_edge(const NodeId id) const { return trigg_edges_[id]; } | ||
|
||
| std::string trigg_edge_str(const NodeId id) const { | ||
| switch(trigg_edges_[id]) { | ||
| case 0: | ||
| return "RISING"; | ||
| break; | ||
| case 1: | ||
| return "FALLING"; | ||
| break; | ||
| case 2: | ||
| return "DONT_CARE"; | ||
| break; | ||
| default: | ||
| return "ERROR"; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| ///\param id The node id | ||
| ///\returns A range of all out-going edges the node drives | ||
| edge_range node_out_edges(const NodeId id) const { return tatum::util::make_range(node_out_edges_[id].begin(), node_out_edges_[id].end()); } | ||
|
|
@@ -198,6 +216,7 @@ class TimingGraph { | |
| ///\param type The type of the node to be added | ||
| ///\warning Graph will likely need to be re-levelized after modification | ||
| NodeId add_node(const NodeType type); | ||
| NodeId add_node(const NodeType type, int trigg_edge); | ||
|
|
||
| ///Adds an edge to the timing graph | ||
| ///\param type The edge's type | ||
|
|
@@ -282,6 +301,7 @@ class TimingGraph { | |
| //Node data | ||
| tatum::util::linear_map<NodeId,NodeId> node_ids_; //The node IDs in the graph | ||
| tatum::util::linear_map<NodeId,NodeType> node_types_; //Type of node | ||
| tatum::util::linear_map<NodeId,int> trigg_edges_; //Triggering edge of the clock | ||
| tatum::util::linear_map<NodeId,std::vector<EdgeId>> node_in_edges_; //Incomiing edge IDs for node | ||
| tatum::util::linear_map<NodeId,std::vector<EdgeId>> node_out_edges_; //Out going edge IDs for node | ||
| tatum::util::linear_map<NodeId,LevelId> node_levels_; //Out going edge IDs for node | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -294,6 +294,7 @@ bool CommonAnalysisVisitor<AnalysisOps>::do_arrival_traverse_edge(const TimingGr | |
|
|
||
| //Pulling values from upstream source node | ||
| NodeId src_node_id = tg.edge_src_node(edge_id); | ||
| NodeId sink_node_id = tg.edge_sink_node(edge_id); | ||
|
|
||
| if(should_propagate_clocks(tg, tc, edge_id)) { | ||
| /* | ||
|
|
@@ -311,7 +312,6 @@ bool CommonAnalysisVisitor<AnalysisOps>::do_arrival_traverse_edge(const TimingGr | |
|
|
||
| for(const TimingTag& src_launch_clk_tag : src_launch_clk_tags) { | ||
| //Standard propagation through the clock network | ||
|
|
||
| Time new_arr = src_launch_clk_tag.time() + clk_launch_edge_delay; | ||
| timing_modified |= ops_.merge_arr_tags(node_id, new_arr, src_node_id, src_launch_clk_tag); | ||
|
|
||
|
|
@@ -328,6 +328,15 @@ bool CommonAnalysisVisitor<AnalysisOps>::do_arrival_traverse_edge(const TimingGr | |
|
|
||
| for(const TimingTag& src_capture_clk_tag : src_capture_clk_tags) { | ||
| //Standard propagation through the clock network | ||
|
|
||
| //Skip propagation of timings derived from incompatible constraints | ||
| if ( tg.node_type(sink_node_id) == NodeType::CPIN ) { | ||
| if ((tg.trigg_edge(sink_node_id) == 1 && !tc.clock_domain_inverted(src_capture_clk_tag.launch_clock_domain())) || | ||
|
||
| (tg.trigg_edge(sink_node_id) == 0 && tc.clock_domain_inverted(src_capture_clk_tag.launch_clock_domain()))) { | ||
| continue; | ||
| } | ||
| } | ||
|
|
||
| timing_modified |= ops_.merge_arr_tags(node_id, src_capture_clk_tag.time() + clk_capture_edge_delay, src_node_id, src_capture_clk_tag); | ||
| } | ||
| } | ||
|
|
||

There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding @kmurray so he can take a look.
Is this creating a half cycle clock transfer from -edge to +edge?
Would be good to comment that. Also possibly we should be using launch and capture edge terminology (or active edge) as rise_edge = fall_edge is a bit mysterious looking. So consider some variable renaming. We should at least comment it very thoroughly!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added comments describing the inversion. I'm not sure if renaming
rise_edgeandfall_edgefromsdcparse::CreateClockis necessary because those precisely describe the waveform of the clock.I also slightly modified the 180 degree phase shift.