SDC: Write waveform from RTLIL attributes

Signed-off-by: Tomasz Michalak <tmichalak@antmicro.com>
diff --git a/sdc-plugin/clocks.cc b/sdc-plugin/clocks.cc
index d1804b7..3727ec6 100644
--- a/sdc-plugin/clocks.cc
+++ b/sdc-plugin/clocks.cc
@@ -33,7 +33,12 @@
 void Clocks::AddClock(const std::string& name, RTLIL::Wire* wire, float period,
                       float rising_edge, float falling_edge) {
     wire->set_string_attribute(RTLIL::escape_id("CLOCK_SIGNAL"), "yes");
+    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"), Clock::ClockWireName(wire));
     wire->set_string_attribute(RTLIL::escape_id("PERIOD"), std::to_string(period));
+    std::string waveform(std::to_string(rising_edge) + " " + std::to_string(falling_edge));
+    wire->set_string_attribute(RTLIL::escape_id("WAVEFORM"), waveform);
 }
 
 void Clocks::AddClock(Clock& clock) {
@@ -169,7 +174,41 @@
 
 Clock::Clock(RTLIL::Wire* wire, float period,
              float rising_edge, float falling_edge)
-    : Clock(RTLIL::id2cstr(wire->name), wire, period, rising_edge, falling_edge) {}
+    : Clock(RTLIL::unescape_id(wire->name), wire, period, rising_edge, falling_edge) {}
+
+float Clock::Period(RTLIL::Wire* clock_wire) {
+    if (!clock_wire->has_attribute(RTLIL::escape_id("PERIOD"))) {
+	log_warning("Period has not been specified\n Default value 0 will be used\n");
+	return 0;
+    }
+    return std::stof(clock_wire->get_string_attribute(RTLIL::escape_id("PERIOD")));
+}
+
+std::pair<float, float> Clock::Waveform(RTLIL::Wire* clock_wire) {
+    if (!clock_wire->has_attribute(RTLIL::escape_id("WAVEFORM"))) {
+	float period(Period(clock_wire));
+	if (!period) {
+	    log_cmd_error("Neither PERIOD nor WAVEFORM has been specified for wire %s\n", ClockWireName(clock_wire).c_str());
+	    return std::make_pair(0,0);
+	}
+	float falling_edge = period / 2;
+	log_warning("Waveform has not been specified\n Default value {0 %f} will be used\n", falling_edge);
+	return std::make_pair(0, falling_edge);
+    }
+    float rising_edge(0);
+    float falling_edge(0);
+    std::string waveform(clock_wire->get_string_attribute(RTLIL::escape_id("WAVEFORM")));
+    std::sscanf(waveform.c_str(), "%f %f", &rising_edge, &falling_edge);
+    return std::make_pair(rising_edge, falling_edge);
+}
+
+float Clock::RisingEdge(RTLIL::Wire* clock_wire) {
+    return Waveform(clock_wire).first;
+}
+
+float Clock::FallingEdge(RTLIL::Wire* clock_wire) {
+    return Waveform(clock_wire).second;
+}
 
 void Clock::UpdateClock(RTLIL::Wire* wire, float period, float rising_edge,
                         float falling_edge) {
diff --git a/sdc-plugin/clocks.h b/sdc-plugin/clocks.h
index c074649..478b9ea 100644
--- a/sdc-plugin/clocks.h
+++ b/sdc-plugin/clocks.h
@@ -40,8 +40,11 @@
     std::vector<RTLIL::Wire*> GetClockWires() { return clock_wires_; }
     const std::string& Name() const { return name_; }
     float Period() { return period_; }
+    static float Period(RTLIL::Wire* clock_wire);
     float RisingEdge() { return rising_edge_; }
+    static float RisingEdge(RTLIL::Wire* clock_wire);
     float FallingEdge() { return falling_edge_; }
+    static float FallingEdge(RTLIL::Wire* clock_wire);
     RTLIL::Wire* ClockWire() { return clock_wire_; }
     void UpdateClock(RTLIL::Wire* wire, float period, float rising_edge,
                      float falling_edge);
@@ -55,6 +58,7 @@
     float rising_edge_;
     float falling_edge_;
 
+    static std::pair<float, float> Waveform(RTLIL::Wire* clock_wire);
     void UpdateWires(RTLIL::Wire* wire);
     void UpdatePeriod(float period);
     void UpdateWaveform(float rising_edge, float falling_edge);
diff --git a/sdc-plugin/sdc_writer.cc b/sdc-plugin/sdc_writer.cc
index 6826d01..41ebfa3 100644
--- a/sdc-plugin/sdc_writer.cc
+++ b/sdc-plugin/sdc_writer.cc
@@ -50,10 +50,10 @@
 	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 << "create_clock -period " << Clock::Period(clock_wire);
+	file << " -waveform {" << Clock::RisingEdge(clock_wire) << " "
+	     << Clock::FallingEdge(clock_wire) << "}";
+	file << " " << Clock::ClockWireName(clock_wire);
 	file << std::endl;
     }
 }