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