SDC: Attach CLOCK_SIGNAL and PERIOD attributes to wires

Signed-off-by: Tomasz Michalak <tmichalak@antmicro.com>
diff --git a/sdc-plugin/clocks.cc b/sdc-plugin/clocks.cc
index c177f6a..bbad62c 100644
--- a/sdc-plugin/clocks.cc
+++ b/sdc-plugin/clocks.cc
@@ -32,19 +32,8 @@
 
 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());
-	clock->UpdateClock(wire, period, rising_edge, falling_edge);
-    } else {
-	rising_edge = fmod(rising_edge, period);
-	falling_edge = fmod(falling_edge, period);
-	clocks_.emplace_back(name, wire, period, rising_edge, falling_edge);
-	log("Added clock %s with period %f, rising_edge:%f, falling_edge:%f\n", name.c_str(),
-	    period, rising_edge, falling_edge);
-    }
+    wire->set_string_attribute(RTLIL::escape_id("CLOCK_SIGNAL"), "yes");
+    wire->set_string_attribute(RTLIL::escape_id("PERIOD"), std::to_string(period));
 }
 
 void Clocks::AddClock(Clock& clock) {
@@ -52,6 +41,20 @@
              clock.RisingEdge(), clock.FallingEdge());
 }
 
+const std::vector<RTLIL::Wire*> Clocks::GetClocks(RTLIL::Design* design) {
+    std::vector<RTLIL::Wire*> clock_wires;
+    RTLIL::Module* top_module = design->top_module();
+    for (auto& wire_obj : top_module->wires_) {
+	auto& wire = wire_obj.second;
+	if (wire->has_attribute(RTLIL::escape_id("CLOCK_SIGNAL"))) {
+		if (wire->get_string_attribute(RTLIL::escape_id("CLOCK_SIGNAL")) == "yes") {
+			clock_wires.push_back(wire);
+		}
+	}
+    }
+    return clock_wires;
+}
+
 std::vector<std::string> Clocks::GetClockNames() {
     std::vector<std::string> res;
     for (auto clock : clocks_) {
@@ -69,61 +72,62 @@
     return res;
 }
 
-void Clocks::Propagate(NaturalPropagation* pass) {
+void Clocks::Propagate(RTLIL::Design* design, NaturalPropagation* pass) {
 #ifdef SDC_DEBUG
     log("Start natural clock propagation\n");
 #endif
-    for (auto clock : clocks_) {
+    for (auto& clock_wire : Clocks::GetClocks(design)) {
 #ifdef SDC_DEBUG
-	log("Processing clock %s\n", clock.Name().c_str());
+	log("Processing clock %s\n", RTLIL::id2cstr(clock_wire->name));
 #endif
-	auto clock_wires = clock.GetClockWires();
-	for (auto clock_wire : clock_wires) {
-	    auto aliases = pass->FindAliasWires(clock_wire);
-	    AddClock(clock.Name(), aliases, clock.Period(),
-	                  clock.RisingEdge(), clock.FallingEdge());
-	}
+	auto aliases = pass->FindAliasWires(clock_wire);
+	/* AddClock(clock.Name(), aliases, clock.Period(), */
+	/* 	clock.RisingEdge(), clock.FallingEdge()); */
     }
 #ifdef SDC_DEBUG
     log("Finish natural clock propagation\n\n");
 #endif
 }
 
-void Clocks::Propagate(BufferPropagation* pass) {
+void Clocks::Propagate(RTLIL::Design* design, BufferPropagation* pass) {
 #ifdef SDC_DEBUG
     log("Start buffer clock propagation\n");
     log("IBUF pass\n");
 #endif
-    std::vector<Clock> clocks(clocks_);
-    for (auto clock : clocks) {
+    for (auto& clock_wire : Clocks::GetClocks(design)) {
 #ifdef SDC_DEBUG
-	log("Processing clock %s\n", clock.Name().c_str());
+	log("Processing clock %s\n", RTLIL::id2cstr(clock_wire->name));
 #endif
-	PropagateThroughBuffer(pass, clock, IBuf());
+	auto period = std::stof(clock_wire->get_string_attribute(RTLIL::escape_id("PERIOD")));
+	auto clock = Clock(clock_wire, period, 0, period/2);
+	PropagateThroughBuffer(pass, design, clock, IBuf());
     }
 #ifdef SDC_DEBUG
     log("BUFG pass\n");
 #endif
-    clocks = clocks_;
-    for (auto clock : clocks) {
+    for (auto& clock_wire : Clocks::GetClocks(design)) {
 #ifdef SDC_DEBUG
-	log("Processing clock %s\n", clock.Name().c_str());
+	log("Processing clock %s\n", RTLIL::id2cstr(clock_wire->name));
 #endif
-	PropagateThroughBuffer(pass, clock, Bufg());
+	auto period = std::stof(clock_wire->get_string_attribute(RTLIL::escape_id("PERIOD")));
+	auto clock = Clock(clock_wire, period, 0, period/2);
+	PropagateThroughBuffer(pass, design, clock, Bufg());
     }
 #ifdef SDC_DEBUG
     log("Finish buffer clock propagation\n\n");
 #endif
 }
 
-void Clocks::Propagate(ClockDividerPropagation* pass) {
+void Clocks::Propagate(RTLIL::Design* design, ClockDividerPropagation* pass) {
 #ifdef SDC_DEBUG
     log("Start clock divider clock propagation\n");
 #endif
-    for (auto clock : clocks_) {
+    for (auto& clock_wire : Clocks::GetClocks(design)) {
 #ifdef SDC_DEBUG
-	log("Processing clock %s\n", clock.Name().c_str());
+	log("Processing clock %s\n", RTLIL::id2cstr(clock_wire->name));
 #endif
+	auto period = std::stof(clock_wire->get_string_attribute(RTLIL::escape_id("PERIOD")));
+	auto clock = Clock(clock_wire, period, 0, period/2);
 	auto pll_clocks =
 	    pass->FindSinkClocksForCellType(clock, "PLLE2_ADV");
 	for (auto pll_clock : pll_clocks) {
@@ -131,7 +135,7 @@
 	    log("PLL clock: %s\n", pll_clock.Name().c_str());
 #endif
 	    AddClock(pll_clock);
-	    PropagateThroughBuffer(pass, pll_clock, Bufg());
+	    PropagateThroughBuffer(pass, design, pll_clock, Bufg());
 	}
     }
 #ifdef SDC_DEBUG
@@ -139,12 +143,11 @@
 #endif
 }
 
-void Clocks::PropagateThroughBuffer(Propagation* pass, Clock& clock,
+void Clocks::PropagateThroughBuffer(Propagation* pass, RTLIL::Design* design, Clock& clock,
                                     Buffer buffer) {
-    auto clock_wires = clock.GetClockWires();
-    for (auto clock_wire : clock_wires) {
+    for (auto& clock_wire : Clocks::GetClocks(design)) {
 #ifdef SDC_DEBUG
-	log("Clock wire %s\n", RTLIL::unescape_id(clock_wire->name).c_str());
+	log("Clock wire %s\n", RTLIL::id2cstr(clock_wire->name));
 #endif
 	auto buf_wires = pass->FindSinkWiresForCellType(clock_wire, buffer.name,
 	                                                buffer.output);
@@ -152,7 +155,7 @@
 	for (auto wire : buf_wires) {
 #ifdef SDC_DEBUG
 	    log("%s wire: %s\n", buffer.name.c_str(),
-	        RTLIL::unescape_id(wire->name).c_str());
+	        RTLIL::id2cstr(wire->name));
 #endif
 	    path_delay += buffer.delay;
 	    AddClock(RTLIL::unescape_id(wire->name), wire, clock.Period(),
@@ -162,27 +165,6 @@
     }
 }
 
-void Clocks::WriteSdc(std::ostream& file) {
-    for (auto& clock : clocks_) {
-	auto clock_wires = clock.GetClockWires();
-	// FIXME: Input port nets are not found in VPR
-	if (std::all_of(clock_wires.begin(), clock_wires.end(),
-	                [&](RTLIL::Wire* wire) { return wire->port_input; })) {
-	    continue;
-	}
-	file << "create_clock -period " << clock.Period();
-	file << " -waveform {" << clock.RisingEdge() << " "
-	     << clock.FallingEdge() << "}";
-	for (auto clock_wire : clock_wires) {
-	    if (clock_wire->port_input) {
-		continue;
-	    }
-	    file << " " << Clock::ClockWireName(clock_wire);
-	}
-	file << std::endl;
-    }
-}
-
 Clock::Clock(const std::string& name, RTLIL::Wire* wire, float period,
              float rising_edge, float falling_edge)
     : name_(name),
diff --git a/sdc-plugin/clocks.h b/sdc-plugin/clocks.h
index 67ca272..114cee3 100644
--- a/sdc-plugin/clocks.h
+++ b/sdc-plugin/clocks.h
@@ -42,6 +42,7 @@
     float Period() { return period_; }
     float RisingEdge() { return rising_edge_; }
     float FallingEdge() { return falling_edge_; }
+    RTLIL::Wire* ClockWire() { return clock_wire_; }
     void UpdateClock(RTLIL::Wire* wire, float period, float rising_edge,
                      float falling_edge);
     static std::string ClockWireName(RTLIL::Wire* wire);
@@ -49,6 +50,7 @@
    private:
     std::string name_;
     std::vector<RTLIL::Wire*> clock_wires_;
+    RTLIL::Wire* clock_wire_;
     float period_;
     float rising_edge_;
     float falling_edge_;
@@ -66,17 +68,17 @@
                   float rising_edge, float falling_edge);
     void AddClock(Clock& clock);
     std::vector<std::string> GetClockNames();
-    void Propagate(NaturalPropagation* pass);
-    void Propagate(BufferPropagation* pass);
-    void Propagate(ClockDividerPropagation* pass);
-    void WriteSdc(std::ostream& file);
+    void Propagate(RTLIL::Design* design, NaturalPropagation* pass);
+    void Propagate(RTLIL::Design* design, BufferPropagation* pass);
+    void Propagate(RTLIL::Design* design, ClockDividerPropagation* pass);
     const std::vector<Clock> GetClocks() {
-	return clocks_;
+	return std::vector<Clock>();
     }
+    static const std::vector<RTLIL::Wire*> GetClocks(RTLIL::Design* design);
 
    private:
     std::vector<Clock> clocks_;
-    void PropagateThroughBuffer(Propagation* pass, Clock& clock,
+    void PropagateThroughBuffer(Propagation* pass, RTLIL::Design* design, Clock& clock,
                                 Buffer buffer);
 };
 
diff --git a/sdc-plugin/propagation.cc b/sdc-plugin/propagation.cc
index e741e1a..3ea35ad 100644
--- a/sdc-plugin/propagation.cc
+++ b/sdc-plugin/propagation.cc
@@ -40,29 +40,27 @@
 std::vector<Clock> ClockDividerPropagation::FindSinkClocksForCellType(
     Clock driving_clock, const std::string& cell_type) {
     std::vector<Clock> clocks;
-    auto clock_wires = driving_clock.GetClockWires();
-    for (auto clock_wire : clock_wires) {
-	if (cell_type == "PLLE2_ADV") {
-	    RTLIL::Cell* cell = NULL;
-	    for (auto input : Pll::inputs) {
-		cell = FindSinkCellOnPort(clock_wire, input);
-		if (cell and RTLIL::unescape_id(cell->type) == cell_type) {
-		    break;
-		}
+    auto clock_wire = driving_clock.ClockWire();
+    if (cell_type == "PLLE2_ADV") {
+	RTLIL::Cell* cell = NULL;
+	for (auto input : Pll::inputs) {
+	    cell = FindSinkCellOnPort(clock_wire, input);
+	    if (cell and RTLIL::unescape_id(cell->type) == cell_type) {
+		break;
 	    }
-	    if (!cell) {
-		return clocks;
-	    }
-	    Pll pll(cell, driving_clock.Period(), driving_clock.RisingEdge());
-	    for (auto output : Pll::outputs) {
-		RTLIL::Wire* wire = FindSinkWireOnPort(cell, output);
-		if (wire) {
-		    float clkout_period(pll.clkout_period.at(output));
-		    float clkout_rising_edge(pll.clkout_rising_edge.at(output));
-		    float clkout_falling_edge(pll.clkout_falling_edge.at(output));
-		    Clock clock(wire, clkout_period, clkout_rising_edge, clkout_falling_edge);
-		    clocks.push_back(clock);
-		}
+	}
+	if (!cell) {
+	    return clocks;
+	}
+	Pll pll(cell, driving_clock.Period(), driving_clock.RisingEdge());
+	for (auto output : Pll::outputs) {
+	    RTLIL::Wire* wire = FindSinkWireOnPort(cell, output);
+	    if (wire) {
+		float clkout_period(pll.clkout_period.at(output));
+		float clkout_rising_edge(pll.clkout_rising_edge.at(output));
+		float clkout_falling_edge(pll.clkout_falling_edge.at(output));
+		Clock clock(wire, clkout_period, clkout_rising_edge, clkout_falling_edge);
+		clocks.push_back(clock);
 	    }
 	}
     }
diff --git a/sdc-plugin/propagation.h b/sdc-plugin/propagation.h
index 6774062..0e45211 100644
--- a/sdc-plugin/propagation.h
+++ b/sdc-plugin/propagation.h
@@ -48,7 +48,7 @@
     NaturalPropagation(RTLIL::Design* design, Pass* pass)
         : Propagation(design, pass) {}
 
-    void Run(Clocks& clocks) override { clocks.Propagate(this); }
+    void Run(Clocks& clocks) override { clocks.Propagate(design_, this); }
     std::vector<RTLIL::Wire*> FindAliasWires(RTLIL::Wire* wire);
 };
 
@@ -57,7 +57,7 @@
     BufferPropagation(RTLIL::Design* design, Pass* pass)
         : Propagation(design, pass) {}
 
-    void Run(Clocks& clocks) override { clocks.Propagate(this); }
+    void Run(Clocks& clocks) override { clocks.Propagate(design_, this); }
 };
 
 class ClockDividerPropagation : public Propagation {
@@ -65,7 +65,7 @@
     ClockDividerPropagation(RTLIL::Design* design, Pass* pass)
         : Propagation(design, pass) {}
 
-    void Run(Clocks& clocks) override { clocks.Propagate(this); }
+    void Run(Clocks& clocks) override { clocks.Propagate(design_, this); }
     std::vector<Clock> FindSinkClocksForCellType(Clock driver_wire,
                                                  const std::string& cell_type);
 };
diff --git a/sdc-plugin/sdc.cc b/sdc-plugin/sdc.cc
index c138b04..00692be 100644
--- a/sdc-plugin/sdc.cc
+++ b/sdc-plugin/sdc.cc
@@ -73,13 +73,13 @@
     }
 
     void execute(std::ostream*& f, std::string filename,
-                 std::vector<std::string> args, RTLIL::Design*) override {
+                 std::vector<std::string> args, RTLIL::Design* design) override {
 	if (args.size() < 2) {
 	    log_cmd_error("Missing output file.\n");
 	}
 	log("\nWriting out clock constraints file(SDC)\n");
 	extra_args(f, filename, args, 1);
-	sdc_writer_.WriteSdc(clocks_, *f);
+	sdc_writer_.WriteSdc(design, *f);
     }
 
     Clocks& clocks_;
diff --git a/sdc-plugin/sdc_writer.cc b/sdc-plugin/sdc_writer.cc
index 4c7ae57..6998097 100644
--- a/sdc-plugin/sdc_writer.cc
+++ b/sdc-plugin/sdc_writer.cc
@@ -37,13 +37,27 @@
     clock_groups_.Add(clock_group, relation);
 }
 
-void SdcWriter::WriteSdc(Clocks& clocks, std::ostream& file) {
-    WriteClocks(clocks, file);
+void SdcWriter::WriteSdc(RTLIL::Design* design, std::ostream& file) {
+    WriteClocks(design, file);
     WriteFalsePaths(file);
     WriteMaxDelay(file);
     WriteClockGroups(file);
 }
 
+void SdcWriter::WriteClocks(RTLIL::Design* design, std::ostream& file) {
+    for (auto& clock_wire : Clocks::GetClocks(design)) {
+	// FIXME: Input port nets are not found in VPR
+	if (clock_wire->port_input) {
+	    continue;
+	}
+	file << "create_clock -period " << clock_wire->get_string_attribute(RTLIL::escape_id("PERIOD"));
+	/* file << " -waveform {" << clock.RisingEdge() << " " */
+	/*      << clock.FallingEdge() << "}"; */
+	file << " " << RTLIL::unescape_id(clock_wire->name);
+	file << std::endl;
+    }
+}
+
 void SdcWriter::WriteClocks(Clocks& clocks, std::ostream& file) {
     for (auto clock : clocks.GetClocks()) {
 	auto clock_wires = clock.GetClockWires();
diff --git a/sdc-plugin/sdc_writer.h b/sdc-plugin/sdc_writer.h
index 9bcbcf1..c6ea149 100644
--- a/sdc-plugin/sdc_writer.h
+++ b/sdc-plugin/sdc_writer.h
@@ -61,10 +61,11 @@
     void AddFalsePath(FalsePath false_path);
     void SetMaxDelay(TimingPath timing_path);
     void AddClockGroup(ClockGroups::ClockGroup clock_group, ClockGroups::ClockGroupRelation relation);
-    void WriteSdc(Clocks& clocks, std::ostream& file);
+    void WriteSdc(RTLIL::Design* design, std::ostream& file);
 
    private:
     void WriteClocks(Clocks& clocks, std::ostream& file);
+    void WriteClocks(RTLIL::Design* design, std::ostream& file);
     void WriteFalsePaths(std::ostream& file);
     void WriteMaxDelay(std::ostream& file);
     void WriteClockGroups(std::ostream& file);