SDC: Distinguish GENERATED, PROPAGATED and EXPLICIT clocks

Signed-off-by: Tomasz Michalak <tmichalak@antmicro.com>
diff --git a/sdc-plugin/clocks.cc b/sdc-plugin/clocks.cc
index adcb6b1..4147174 100644
--- a/sdc-plugin/clocks.cc
+++ b/sdc-plugin/clocks.cc
@@ -23,8 +23,11 @@
 #include "propagation.h"
 
 void Clock::Add(const std::string& name, RTLIL::Wire* wire, float period,
-                float rising_edge, float falling_edge) {
+                float rising_edge, float falling_edge, ClockType type) {
     wire->set_string_attribute(RTLIL::escape_id("CLOCK_SIGNAL"), "yes");
+    wire->set_bool_attribute(RTLIL::escape_id("IS_GENERATED"), type == GENERATED);
+    wire->set_bool_attribute(RTLIL::escape_id("IS_EXPLICIT"), type == EXPLICIT);
+    wire->set_bool_attribute(RTLIL::escape_id("IS_PROPAGATED"), type == PROPAGATED);
     wire->set_string_attribute(RTLIL::escape_id("CLASS"), "clock");
     wire->set_string_attribute(RTLIL::escape_id("NAME"), name);
     wire->set_string_attribute(RTLIL::escape_id("SOURCE_PINS"),
@@ -37,15 +40,15 @@
 }
 
 void Clock::Add(const std::string& name, std::vector<RTLIL::Wire*> wires,
-                float period, float rising_edge, float falling_edge) {
+                float period, float rising_edge, float falling_edge, ClockType type) {
     std::for_each(wires.begin(), wires.end(), [&](RTLIL::Wire* wire) {
-	Add(name, wire, period, rising_edge, falling_edge);
+	Add(name, wire, period, rising_edge, falling_edge, type);
     });
 }
 
 void Clock::Add(RTLIL::Wire* wire, float period, float rising_edge,
-                float falling_edge) {
-    Add(Clock::WireName(wire), wire, period, rising_edge, falling_edge);
+                float falling_edge, ClockType type) {
+    Add(Clock::WireName(wire), wire, period, rising_edge, falling_edge, type);
 }
 
 float Clock::Period(RTLIL::Wire* clock_wire) {
@@ -128,6 +131,13 @@
     return Name(clock_wire);
 }
 
+bool Clock::GetClockWireBoolAttribute(RTLIL::Wire* wire, const std::string& attribute_name) {
+    if (wire->has_attribute(RTLIL::escape_id(attribute_name))) {
+	return wire->get_bool_attribute(RTLIL::escape_id(attribute_name));
+    }
+    return false;
+}
+
 const std::map<std::string, RTLIL::Wire*> Clocks::GetClocks(
     RTLIL::Design* design) {
     std::map<std::string, RTLIL::Wire*> clock_wires;
diff --git a/sdc-plugin/clocks.h b/sdc-plugin/clocks.h
index 846a2af..d9208e0 100644
--- a/sdc-plugin/clocks.h
+++ b/sdc-plugin/clocks.h
@@ -32,12 +32,13 @@
 
 class Clock {
    public:
+    enum ClockType { EXPLICIT, GENERATED, PROPAGATED };
     static void Add(const std::string& name, RTLIL::Wire* wire, float period,
-                    float rising_edge, float falling_edge);
+                    float rising_edge, float falling_edge, ClockType type);
     static void Add(const std::string& name, std::vector<RTLIL::Wire*> wires,
-                    float period, float rising_edge, float falling_edge);
+                    float period, float rising_edge, float falling_edge, ClockType type);
     static void Add(RTLIL::Wire* wire, float period, float rising_edge,
-                    float falling_edge);
+                    float falling_edge, ClockType type);
     static float Period(RTLIL::Wire* clock_wire);
     static float RisingEdge(RTLIL::Wire* clock_wire);
     static float FallingEdge(RTLIL::Wire* clock_wire);
@@ -47,9 +48,22 @@
 	return std::regex_replace(name, std::regex{"\\$"}, "\\$");
     }
     static std::string SourcePinName(RTLIL::Wire* clock_wire);
+    static bool IsPropagated(RTLIL::Wire* wire) {
+	return GetClockWireBoolAttribute(wire, "IS_PROPAGATED");
+    }
+
+    static bool IsGenerated(RTLIL::Wire* wire) {
+	return GetClockWireBoolAttribute(wire, "IS_GENERATED");
+    }
+
+    static bool IsExplicit(RTLIL::Wire* wire) {
+	return GetClockWireBoolAttribute(wire, "IS_EXPLICIT");
+    }
 
    private:
     static std::pair<float, float> Waveform(RTLIL::Wire* clock_wire);
+
+    static bool GetClockWireBoolAttribute(RTLIL::Wire* wire, const std::string& attribute_name);
 };
 
 class Clocks {
diff --git a/sdc-plugin/propagation.cc b/sdc-plugin/propagation.cc
index f7e59d8..1982aef 100644
--- a/sdc-plugin/propagation.cc
+++ b/sdc-plugin/propagation.cc
@@ -37,7 +37,7 @@
 	    path_delay += buffer.delay;
 	    Clock::Add(wire, Clock::Period(clock_wire),
 	               Clock::RisingEdge(clock_wire) + path_delay,
-	               Clock::FallingEdge(clock_wire) + path_delay);
+	               Clock::FallingEdge(clock_wire) + path_delay, Clock::PROPAGATED);
 	}
     }
 }
@@ -169,7 +169,7 @@
 	auto aliases = FindAliasWires(clock_wire);
 	Clock::Add(Clock::WireName(clock_wire), aliases,
 	           Clock::Period(clock_wire), Clock::RisingEdge(clock_wire),
-	           Clock::FallingEdge(clock_wire));
+	           Clock::FallingEdge(clock_wire), Clock::PROPAGATED);
     }
 #ifdef SDC_DEBUG
     log("Finish natural clock propagation\n\n");
@@ -253,7 +253,7 @@
 		float clkout_rising_edge(pll.clkout_rising_edge.at(output));
 		float clkout_falling_edge(pll.clkout_falling_edge.at(output));
 		Clock::Add(wire, clkout_period, clkout_rising_edge,
-		           clkout_falling_edge);
+		           clkout_falling_edge, Clock::GENERATED);
 	    }
 	}
     }
diff --git a/sdc-plugin/propagation.h b/sdc-plugin/propagation.h
index 29ee07f..3efd984 100644
--- a/sdc-plugin/propagation.h
+++ b/sdc-plugin/propagation.h
@@ -34,6 +34,8 @@
     RTLIL::Design* design_;
     Pass* pass_;
 
+    // This propagation doesn't change the clock so the sink wire is only marked
+    // as propagated clock signal, but has the properties of the driving clock
     void PropagateThroughBuffers(Buffer buffer);
     std::vector<RTLIL::Wire*> FindSinkWiresForCellType(
         RTLIL::Wire* driver_wire, const std::string& cell_type,
diff --git a/sdc-plugin/sdc.cc b/sdc-plugin/sdc.cc
index a9b7f6a..83fb61b 100644
--- a/sdc-plugin/sdc.cc
+++ b/sdc-plugin/sdc.cc
@@ -169,7 +169,7 @@
 	    rising_edge = 0;
 	    falling_edge = period / 2;
 	}
-	Clock::Add(name, selected_wires, period, rising_edge, falling_edge);
+	Clock::Add(name, selected_wires, period, rising_edge, falling_edge, Clock::EXPLICIT);
     }
 
     void AddWirePrefix(std::vector<std::string>& args, size_t argidx) {
diff --git a/sdc-plugin/sdc_writer.cc b/sdc-plugin/sdc_writer.cc
index 6f7a760..4c3e093 100644
--- a/sdc-plugin/sdc_writer.cc
+++ b/sdc-plugin/sdc_writer.cc
@@ -46,11 +46,15 @@
 
 void SdcWriter::WriteClocks(RTLIL::Design* design, std::ostream& file) {
     for (auto& clock : Clocks::GetClocks(design)) {
-	// FIXME: Input port nets are not found in VPR
 	auto& clock_wire = clock.second;
+	// FIXME: Input port nets are not found in VPR
 	if (clock_wire->port_input) {
 	    continue;
 	}
+	// Write out only GENERATED and EXPLICIT clocks
+	if (Clock::IsPropagated(clock_wire)) {
+	    continue;
+	}
 	file << "create_clock -period " << Clock::Period(clock_wire);
 	file << " -waveform {" << Clock::RisingEdge(clock_wire) << " "
 	     << Clock::FallingEdge(clock_wire) << "}";