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);