SDC: Refactor Clock classes

Signed-off-by: Tomasz Michalak <tmichalak@antmicro.com>
diff --git a/sdc-plugin/clocks.cc b/sdc-plugin/clocks.cc
index 06c1933..a9b4607 100644
--- a/sdc-plugin/clocks.cc
+++ b/sdc-plugin/clocks.cc
@@ -21,8 +21,29 @@
 #include "kernel/register.h"
 #include "propagation.h"
 
+void Clocks::AddClock(const std::string& name,
+                           std::vector<RTLIL::Wire*> wires, float period,
+                           float rising_edge, float falling_edge) {
+    AddClockWires(name, wires, period, rising_edge, falling_edge);
+}
+
+void Clocks::AddClock(const std::string& name,
+                           RTLIL::Wire* wire, float period,
+                           float rising_edge, float falling_edge) {
+    auto clock = std::find_if(clocks_.begin(), clocks_.end(), [&](Clock& clock) { return clock.Name() == name; });
+    if (clock != clocks_.end()) {
+	log("Clock %s already exists and will be overwritten\n", name.c_str());
+	clocks_.erase(clock);
+    }
+    clocks_.emplace_back(name, wire, period, rising_edge, falling_edge);
+}
+
+void Clocks::AddClock(Clock& clock) {
+    AddClock(clock.Name(), clock.GetClockWires(), clock.Period(), clock.RisingEdge(), clock.FallingEdge());
+}
+
 void Clocks::AddClockWires(const std::string& name,
-                           const std::vector<RTLIL::Wire*>& wires, float period,
+                           std::vector<RTLIL::Wire*> wires, float period,
                            float rising_edge, float falling_edge) {
     std::for_each(wires.begin(), wires.end(), [&, this](RTLIL::Wire* wire) {
 	AddClockWire(name, wire, period, rising_edge, falling_edge);
@@ -31,32 +52,28 @@
 
 void Clocks::AddClockWire(const std::string& name, RTLIL::Wire* wire,
                           float period, float rising_edge, float falling_edge) {
-    auto clock = clocks_.find(name);
+    auto clock = std::find_if(clocks_.begin(), clocks_.end(), [&](Clock& clock) { return clock.Name() == name; });
     if (clock == clocks_.end()) {
-	clocks_.emplace(std::make_pair(name, Clock(name, wire, period, rising_edge, falling_edge)));
+	AddClock(name, wire, period, rising_edge, falling_edge);
     } else {
-    	clock->second.AddClockWire(wire, period, rising_edge, falling_edge);
+    	clock->AddWire(wire);
     }
 }
 
-void Clocks::AddClockWire(const std::string& name, ClockWire& clock_wire) {
-    AddClockWire(name, clock_wire.Wire(), clock_wire.Period(), clock_wire.RisingEdge(), clock_wire.FallingEdge());
-}
-
 std::vector<std::string> Clocks::GetClockNames() {
     std::vector<std::string> res;
     for (auto clock : clocks_) {
-	res.push_back(clock.first);
+	res.push_back(clock.Name());
 #ifdef SDC_DEBUG
-	log("Wires in clock %s:\n", clock.first.c_str());
-	for (auto clock_wire : clock.second.GetClockWires()) {
-	    log("create_clock -period %f -name %s -waveform {%f %f} %s\n",
-	        clock_wire.Period(), clock.first.c_str(),
-	        clock_wire.RisingEdge(), clock_wire.FallingEdge(),
-	        clock_wire.WireName().c_str());
+	std::stringstream ss;
+	for (auto clock_wire : clock.GetClockWires()) {
+	    ss << RTLIL::unescape_id(clock_wire->name) << " ";
 	}
-#endif
+	log("create_clock -period %f -name %s -waveform {%f %f} %s\n",
+	        clock.Period(), clock.Name().c_str(),
+	        clock.RisingEdge(), clock.FallingEdge(), ss.str().c_str());
     }
+#endif
     return res;
 }
 
@@ -66,13 +83,13 @@
 #endif
     for (auto clock : clocks_) {
 #ifdef SDC_DEBUG
-	log("Processing clock %s\n", clock.first.c_str());
+	log("Processing clock %s\n", clock.Name().c_str());
 #endif
-	auto clock_wires = clock.second.GetClockWires();
+	auto clock_wires = clock.GetClockWires();
 	for (auto clock_wire : clock_wires) {
-	    auto aliases = pass->FindAliasWires(clock_wire.Wire());
-	    AddClockWires(clock.first, aliases, clock_wire.Period(),
-	                  clock_wire.RisingEdge(), clock_wire.FallingEdge());
+	    auto aliases = pass->FindAliasWires(clock_wire);
+	    AddClockWires(clock.Name(), aliases, clock.Period(),
+	                  clock.RisingEdge(), clock.FallingEdge());
 	}
     }
 #ifdef SDC_DEBUG
@@ -84,9 +101,9 @@
 #ifdef SDC_DEBUG
     log("Start buffer clock propagation\n");
 #endif
-    for (auto& clock : clocks_) {
+    for (auto clock : clocks_) {
 #ifdef SDC_DEBUG
-	log("Processing clock %s\n", clock.first.c_str());
+	log("Processing clock %s\n", clock.Name().c_str());
 #endif
 	PropagateThroughBuffer(pass, clock, IBuf());
 	PropagateThroughBuffer(pass, clock, Bufg());
@@ -100,19 +117,19 @@
 #ifdef SDC_DEBUG
     log("Start clock divider clock propagation\n");
 #endif
-    for (auto& clock : clocks_) {
+    for (auto clock : clocks_) {
 #ifdef SDC_DEBUG
-	log("Processing clock %s\n", clock.first.c_str());
+	log("Processing clock %s\n", clock.Name().c_str());
 #endif
-	auto clock_wires = clock.second.GetClockWires();
+	auto clock_wires = clock.GetClockWires();
 	for (auto clock_wire : clock_wires) {
-	    auto pll_clock_wires = pass->FindSinkClockWiresForCellType(
+	    auto pll_clocks = pass->FindSinkClocksForCellType(
 		    clock_wire, "PLLE2_ADV");
-	    for (auto pll_clock_wire : pll_clock_wires) {
+	    for (auto pll_clock : pll_clocks) {
 #ifdef SDC_DEBUG
-		log("PLL wire: %s\n", pll_clock_wire.WireName().c_str());
+		log("PLL clock: %s\n", pll_clock.Name().c_str());
 #endif
-		AddClockWire(pll_clock_wire.WireName(), pll_clock_wire);
+		AddClock(pll_clock);
 	    }
 	}
     }
@@ -122,68 +139,76 @@
 }
 
 void Clocks::PropagateThroughBuffer(BufferPropagation* pass,
-                                    decltype(clocks_)::value_type clock,
+                                    Clock& clock,
                                     Buffer buffer) {
-    auto clock_wires = clock.second.GetClockWires();
+    auto clock_wires = clock.GetClockWires();
     for (auto clock_wire : clock_wires) {
+	log("%s\n", clock_wire->name.c_str());
 	auto buf_wires = pass->FindSinkWiresForCellType(
-	    clock_wire.Wire(), buffer.name, buffer.output);
+	    clock_wire, buffer.name, buffer.output);
 	int path_delay(0);
 	for (auto wire : buf_wires) {
 #ifdef SDC_DEBUG
-	    log("%s wire: %s\n", buffer.name.c_str(), wire->name.c_str());
+	    log("%s wire: %s\n", buffer.name.c_str(), RTLIL::unescape_id(wire->name).c_str());
 #endif
 	    path_delay += buffer.delay;
-	    AddClockWire(wire->name.str(), wire, clock_wire.Period(),
-	                 clock_wire.RisingEdge() + path_delay,
-	                 clock_wire.FallingEdge() + path_delay);
+	    AddClock(RTLIL::unescape_id(wire->name), wire, clock.Period(),
+	                 clock.RisingEdge() + path_delay,
+	                 clock.FallingEdge() + path_delay);
 	}
     }
 }
 
 void Clocks::WriteSdc(std::ostream& file) {
     for (auto& clock : clocks_) {
-	auto clock_wires = clock.second.GetClockWires();
-	file << "create_clock";
-	for (auto clock_wire : clock_wires) {
-	   file << " -period " << clock_wire.Period();
-	   if (clock_wires.size() > 1) {
-	       file << " -name " << clock.first;
-	   }
+	auto clock_wires = clock.GetClockWires();
+	file << "create_clock -period " << clock.Period();
+	if (clock_wires.size() > 1) {
+	    file << " -name " << clock.Name();
 	}
-	    /* log("create_clock -period %f -name %s -waveform {%f %f} %s\n", */
-	    /*     clock_wire.Period(), clock.first.c_str(), */
-	    /*     clock_wire.RisingEdge(), clock_wire.FallingEdge(), */
-	    /*     clock_wire.WireName().c_str()); */
+	file << " -waveform {" << clock.RisingEdge() << " " << clock.FallingEdge() << "}";
+	for (auto clock_wire : clock_wires) {
+	   file << " " << RTLIL::unescape_id(clock_wire->name) << std::endl;
+	}
     }
 }
 
 Clock::Clock(const std::string& name, RTLIL::Wire* wire, float period,
              float rising_edge, float falling_edge)
-    : name_(name) {
-    AddClockWire(wire, period, rising_edge, falling_edge);
+    : name_(name),
+      period_(period),
+      rising_edge_(rising_edge),
+      falling_edge_(falling_edge) {
+    AddWire(wire);
 }
 
-void Clock::AddClockWire(RTLIL::Wire* wire, float period, float rising_edge,
-                         float falling_edge) {
-    auto clock_wire = std::find_if(
+Clock::Clock(const std::string& name, std::vector<RTLIL::Wire*> wires,
+             float period, float rising_edge, float falling_edge)
+    : name_(name),
+      period_(period),
+      rising_edge_(rising_edge),
+      falling_edge_(falling_edge) {
+    std::for_each(wires.begin(), wires.end(), [&, this](RTLIL::Wire* wire) {
+	AddWire(wire);
+    });
+}
+
+void Clock::AddWire(RTLIL::Wire* wire) {
+    auto clock_wire = std::find(
         clock_wires_.begin(), clock_wires_.end(),
-        [wire](ClockWire& clock_wire) { return clock_wire.Wire() == wire; });
+        wire);
     if (clock_wire == clock_wires_.end()) {
-	clock_wires_.emplace_back(wire, period, rising_edge, falling_edge);
-    } else {
-	clock_wire->UpdatePeriod(period);
-	clock_wire->UpdateWaveform(rising_edge, falling_edge);
+	clock_wires_.push_back(wire);
     }
 }
 
-void ClockWire::UpdatePeriod(float period) {
+void Clock::UpdatePeriod(float period) {
     period_ = period;
     rising_edge_ = 0;
     falling_edge_ = period / 2;
 }
 
-void ClockWire::UpdateWaveform(float rising_edge, float falling_edge) {
+void Clock::UpdateWaveform(float rising_edge, float falling_edge) {
     rising_edge_ = rising_edge;
     falling_edge_ = falling_edge;
     assert(falling_edge - rising_edge == period_ / 2);
diff --git a/sdc-plugin/clocks.h b/sdc-plugin/clocks.h
index 1fdce01..97fe75c 100644
--- a/sdc-plugin/clocks.h
+++ b/sdc-plugin/clocks.h
@@ -29,16 +29,15 @@
 class BufferPropagation;
 class ClockDividerPropagation;
 
-class ClockWire {
+class Clock {
    public:
-    ClockWire(RTLIL::Wire* wire, float period, float rising_edge,
-              float falling_edge)
-        : wire_(wire),
-          period_(period),
-          rising_edge_(rising_edge),
-          falling_edge_(falling_edge) {}
-    RTLIL::Wire* Wire() { return wire_; }
-    std::string WireName() { return RTLIL::unescape_id(wire_->name); }
+    Clock(const std::string& name, RTLIL::Wire* wire, float period,
+          float rising_edge, float falling_edge);
+    Clock(const std::string& name, std::vector<RTLIL::Wire*> wires, float period,
+          float rising_edge, float falling_edge);
+    void AddWire(RTLIL::Wire* wire);
+    std::vector<RTLIL::Wire*> GetClockWires() { return clock_wires_; }
+    const std::string& Name() const { return name_; }
     float Period() { return period_; }
     float RisingEdge() { return rising_edge_; }
     float FallingEdge() { return falling_edge_; }
@@ -46,34 +45,26 @@
     void UpdateWaveform(float rising_edge, float falling_edge);
 
    private:
-    RTLIL::Wire* wire_;
+    std::string name_;
+    std::vector<RTLIL::Wire*> clock_wires_;
     float period_;
     float rising_edge_;
     float falling_edge_;
 };
 
-class Clock {
-   public:
-    Clock(const std::string& name, RTLIL::Wire* wire, float period,
-          float rising_edge, float falling_edge);
-    void AddClockWire(RTLIL::Wire* wire, float period, float rising_edge,
-                      float falling_edge);
-    std::vector<ClockWire> GetClockWires() { return clock_wires_; }
-
-   private:
-    std::string name_;
-    std::vector<ClockWire> clock_wires_;
-};
-
-
 class Clocks {
    public:
+    void AddClock(const std::string& name,
+                  std::vector<RTLIL::Wire*> wires, float period,
+                  float rising_edge, float falling_edge);
+    void AddClock(const std::string& name, RTLIL::Wire* wire, float period,
+                  float rising_edge, float falling_edge);
+    void AddClock(Clock& clock);
     void AddClockWires(const std::string& name,
-                       const std::vector<RTLIL::Wire*>& wires, float period,
+                       std::vector<RTLIL::Wire*> wires, float period,
                        float rising_edge, float falling_edge);
     void AddClockWire(const std::string& name, RTLIL::Wire* wire, float period,
                       float rising_edge, float falling_edge);
-    void AddClockWire(const std::string& name, ClockWire& clock_wire);
     std::vector<std::string> GetClockNames();
     void Propagate(NaturalPropagation* pass);
     void Propagate(BufferPropagation* pass);
@@ -81,8 +72,8 @@
     void WriteSdc(std::ostream& file);
 
    private:
-    std::unordered_map<std::string, Clock> clocks_;
-    void PropagateThroughBuffer(BufferPropagation* pass, decltype(clocks_)::value_type clock, Buffer buffer);
+    std::vector<Clock> clocks_;
+    void PropagateThroughBuffer(BufferPropagation* pass, Clock& clock, Buffer buffer);
 };
 
 #endif  // _CLOCKS_H_
diff --git a/sdc-plugin/propagation.cc b/sdc-plugin/propagation.cc
index c719dbb..e8a519e 100644
--- a/sdc-plugin/propagation.cc
+++ b/sdc-plugin/propagation.cc
@@ -37,34 +37,34 @@
     return alias_wires;
 }
 
-std::vector<ClockWire> ClockDividerPropagation::FindSinkClockWiresForCellType(ClockWire& driver_wire,
+std::vector<Clock> ClockDividerPropagation::FindSinkClocksForCellType(RTLIL::Wire* driver_wire,
                                              const std::string& cell_type) {
-    std::vector<ClockWire> wires;
+    std::vector<Clock> clocks;
     if (cell_type == "PLLE2_ADV") {
 	RTLIL::Cell* cell = NULL;
 	for (auto input : Pll::inputs) {
-	    cell = FindSinkCellOnPort(driver_wire.Wire(), input);
+	    cell = FindSinkCellOnPort(driver_wire, input);
 	    if (cell and RTLIL::unescape_id(cell->type) == cell_type) {
 		break;
 	    }
 	}
 	if (!cell) {
-	    return wires;
+	    return clocks;
 	}
 	Pll pll(cell);
 	for (auto output : Pll::outputs) {
 	    RTLIL::Wire* wire = FindSinkWireOnPort(cell, output);
 	    if (wire) {
 		float period(pll.CalculatePeriod(output));
-		ClockWire clock_wire(wire, period, 0, period / 2);
-		wires.push_back(clock_wire);
-		auto further_wires = FindSinkClockWiresForCellType(clock_wire, cell_type);
-		std::copy(further_wires.begin(), further_wires.end(),
-			std::back_inserter(wires));
+		Clock clock(RTLIL::unescape_id(wire->name), wire, period, 0, period / 2);
+		clocks.push_back(clock);
+		auto further_clocks = FindSinkClocksForCellType(wire, cell_type);
+		std::copy(further_clocks.begin(), further_clocks.end(),
+			std::back_inserter(clocks));
 	    }
 	}
     }
-    return wires;
+    return clocks;
 }
 
 RTLIL::Cell* Propagation::FindSinkCellOfType(RTLIL::Wire* wire,
@@ -86,7 +86,7 @@
     if (selected_cells.size() > 0) {
 	sink_cell = selected_cells.at(0);
 #ifdef SDC_DEBUG
-	log("Found sink cell: %s\n", sink_cell->name.c_str());
+	log("Found sink cell: %s\n", RTLIL::unescape_id(sink_cell->name).c_str());
 #endif
     }
     return sink_cell;
@@ -128,7 +128,7 @@
     if (selected_cells.size() > 0) {
 	sink_cell = selected_cells.at(0);
 #ifdef SDC_DEBUG
-	log("Found sink cell: %s\n", sink_cell->name.c_str());
+	log("Found sink cell: %s\n", RTLIL::unescape_id(sink_cell->name).c_str());
 #endif
     }
     return sink_cell;
@@ -154,7 +154,7 @@
     if (selected_wires.size() > 0) {
 	sink_wire = selected_wires.at(0);
 #ifdef SDC_DEBUG
-	log("Found sink wire: %s\n", sink_wire->name.c_str());
+	log("Found sink wire: %s\n", RTLIL::unescape_id(sink_wire->name).c_str());
 #endif
     }
     return sink_wire;
diff --git a/sdc-plugin/propagation.h b/sdc-plugin/propagation.h
index 4680ff9..e09fc84 100644
--- a/sdc-plugin/propagation.h
+++ b/sdc-plugin/propagation.h
@@ -65,7 +65,7 @@
         : Propagation(design, pass) {}
 
     void Run(Clocks& clocks) override { clocks.Propagate(this); }
-    std::vector<ClockWire> FindSinkClockWiresForCellType(
-        ClockWire& driver_wire, const std::string& cell_type);
+    std::vector<Clock> FindSinkClocksForCellType(
+        RTLIL::Wire* driver_wire, const std::string& cell_type);
 };
 #endif  // PROPAGATION_H_
diff --git a/sdc-plugin/sdc.cc b/sdc-plugin/sdc.cc
index e344acb..60a1f83 100644
--- a/sdc-plugin/sdc.cc
+++ b/sdc-plugin/sdc.cc
@@ -73,7 +73,7 @@
 	if (args.size() < 2) {
 	    log_cmd_error("Missing output file.\n");
 	}
-	log("\nWriting out clock constraints file(SDC)\n\n");
+	log("\nWriting out clock constraints file(SDC)\n");
 	extra_args(f, filename, args, 1);
 	clocks_.WriteSdc(*f);
     }
@@ -158,7 +158,7 @@
 	if (name.empty()) {
 	    name = RTLIL::unescape_id(selected_wires.at(0)->name);
 	}
-	clocks_.AddClockWires(name, selected_wires, period, rising_edge,
+	clocks_.AddClock(name, selected_wires, period, rising_edge,
 	                      falling_edge);
 	log("Created clock %s with period %f, waveform {%f %f}\n", name.c_str(),
 	    period, rising_edge, falling_edge);