252 lines
7.1 KiB
C++
252 lines
7.1 KiB
C++
// OpenSTA, Static Timing Analyzer
|
|
// Copyright (c) 2020, Parallax Software, Inc.
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
#include "TimingRole.hh"
|
|
|
|
namespace sta {
|
|
|
|
TimingRole *TimingRole::wire_;
|
|
TimingRole *TimingRole::combinational_;
|
|
TimingRole *TimingRole::tristate_enable_;
|
|
TimingRole *TimingRole::tristate_disable_;
|
|
TimingRole *TimingRole::reg_clk_q_;
|
|
TimingRole *TimingRole::reg_set_clr_;
|
|
TimingRole *TimingRole::latch_en_q_;
|
|
TimingRole *TimingRole::latch_d_q_;
|
|
TimingRole *TimingRole::sdf_iopath_;
|
|
TimingRole *TimingRole::setup_;
|
|
TimingRole *TimingRole::hold_;
|
|
TimingRole *TimingRole::recovery_;
|
|
TimingRole *TimingRole::removal_;
|
|
TimingRole *TimingRole::width_;
|
|
TimingRole *TimingRole::period_;
|
|
TimingRole *TimingRole::skew_;
|
|
TimingRole *TimingRole::nochange_;
|
|
TimingRole *TimingRole::output_setup_;
|
|
TimingRole *TimingRole::output_hold_;
|
|
TimingRole *TimingRole::gated_clk_setup_;
|
|
TimingRole *TimingRole::gated_clk_hold_;
|
|
TimingRole *TimingRole::latch_setup_;
|
|
TimingRole *TimingRole::latch_hold_;
|
|
TimingRole *TimingRole::data_check_setup_;
|
|
TimingRole *TimingRole::data_check_hold_;
|
|
TimingRole *TimingRole::non_seq_setup_;
|
|
TimingRole *TimingRole::non_seq_hold_;
|
|
|
|
TimingRoleMap TimingRole::timing_roles_;
|
|
|
|
void
|
|
TimingRole::init()
|
|
{
|
|
wire_ = new TimingRole("wire", false, false, false, nullptr, nullptr, 0);
|
|
combinational_ = new TimingRole("combinational", true, false, false,
|
|
nullptr, nullptr, 1);
|
|
tristate_enable_ = new TimingRole("tristate enable",
|
|
true, false, false,
|
|
nullptr, nullptr, 2);
|
|
tristate_disable_ = new TimingRole("tristate disable",
|
|
true, false, false,
|
|
nullptr, nullptr, 3);
|
|
reg_clk_q_ = new TimingRole("Reg Clk to Q", true, false, false,
|
|
nullptr, nullptr, 4);
|
|
reg_set_clr_ = new TimingRole("Reg Set/Clr", true, false, false,
|
|
nullptr, nullptr, 5);
|
|
latch_en_q_ = new TimingRole("Latch En to Q", true, false, false,
|
|
nullptr, TimingRole::regClkToQ(), 6);
|
|
latch_d_q_ = new TimingRole("Latch D to Q", true, false, false,
|
|
nullptr, nullptr, 7);
|
|
|
|
sdf_iopath_ = new TimingRole("sdf IOPATH", true, false, false,
|
|
nullptr, nullptr, 8);
|
|
|
|
setup_ = new TimingRole("setup", false, true, false,
|
|
MinMax::max(), nullptr, 9);
|
|
hold_ = new TimingRole("hold", false, true, false,
|
|
MinMax::min(), nullptr, 10);
|
|
recovery_ = new TimingRole("recovery", false, true, false,
|
|
MinMax::max(), TimingRole::setup(), 11);
|
|
removal_ = new TimingRole("removal", false, true, false,
|
|
MinMax::min(), TimingRole::hold(), 12);
|
|
width_ = new TimingRole("width", false, true, false,
|
|
nullptr, nullptr, 13);
|
|
period_ = new TimingRole("period", false, true, false,
|
|
nullptr, nullptr, 14);
|
|
skew_ = new TimingRole("skew", false, true, false,
|
|
nullptr, nullptr, 15);
|
|
nochange_ = new TimingRole("nochange", true, false, false,
|
|
nullptr, nullptr, 16);
|
|
|
|
output_setup_ = new TimingRole("output setup", false, true, false,
|
|
MinMax::max(), TimingRole::setup(), 17);
|
|
output_hold_ = new TimingRole("output hold", false, true, false,
|
|
MinMax::min(), TimingRole::hold(), 18);
|
|
gated_clk_setup_ = new TimingRole("clock gating setup",
|
|
false, true, false,
|
|
MinMax::max(), TimingRole::setup(),19);
|
|
gated_clk_hold_ = new TimingRole("clock gating hold", false, true, false,
|
|
MinMax::min(), TimingRole::hold(),20);
|
|
latch_setup_ = new TimingRole("latch setup", false, true, false,
|
|
MinMax::max(), TimingRole::setup(),21);
|
|
latch_hold_ = new TimingRole("latch hold", false, true, false,
|
|
MinMax::min(), TimingRole::hold(),22);
|
|
data_check_setup_ = new TimingRole("data check setup",
|
|
false, true, false,
|
|
MinMax::max(),TimingRole::setup(),23);
|
|
data_check_hold_ = new TimingRole("data check hold", false, true, false,
|
|
MinMax::min(), TimingRole::hold(), 24);
|
|
non_seq_setup_ = new TimingRole("setup", false, true, true,
|
|
MinMax::max(), TimingRole::setup(), 25);
|
|
non_seq_hold_ = new TimingRole("hold", false, true, true,
|
|
MinMax::min(), TimingRole::hold(), 26);
|
|
}
|
|
|
|
void
|
|
TimingRole::destroy()
|
|
{
|
|
delete wire_;
|
|
wire_ = nullptr;
|
|
delete combinational_;
|
|
combinational_ = nullptr;
|
|
delete tristate_enable_;
|
|
tristate_enable_ = nullptr;
|
|
delete tristate_disable_;
|
|
tristate_disable_ = nullptr;
|
|
delete reg_clk_q_;
|
|
reg_clk_q_ = nullptr;
|
|
delete reg_set_clr_;
|
|
reg_set_clr_ = nullptr;
|
|
delete latch_en_q_;
|
|
latch_en_q_ = nullptr;
|
|
delete latch_d_q_;
|
|
latch_d_q_ = nullptr;
|
|
delete sdf_iopath_;
|
|
sdf_iopath_ = nullptr;
|
|
delete setup_;
|
|
setup_ = nullptr;
|
|
delete hold_;
|
|
hold_ = nullptr;
|
|
delete recovery_;
|
|
recovery_ = nullptr;
|
|
delete removal_;
|
|
removal_ = nullptr;
|
|
delete width_;
|
|
width_ = nullptr;
|
|
delete period_;
|
|
period_ = nullptr;
|
|
delete skew_;
|
|
skew_ = nullptr;
|
|
delete nochange_;
|
|
nochange_ = nullptr;
|
|
delete output_setup_;
|
|
output_setup_ = nullptr;
|
|
delete output_hold_;
|
|
output_hold_ = nullptr;
|
|
delete gated_clk_setup_;
|
|
gated_clk_setup_ = nullptr;
|
|
delete gated_clk_hold_;
|
|
gated_clk_hold_ = nullptr;
|
|
delete latch_setup_;
|
|
latch_setup_ = nullptr;
|
|
delete latch_hold_;
|
|
latch_hold_ = nullptr;
|
|
delete data_check_setup_;
|
|
data_check_setup_ = nullptr;
|
|
delete data_check_hold_;
|
|
data_check_hold_ = nullptr;
|
|
delete non_seq_setup_;
|
|
non_seq_setup_ = nullptr;
|
|
delete non_seq_hold_;
|
|
non_seq_hold_ = nullptr;
|
|
timing_roles_.clear();
|
|
}
|
|
|
|
TimingRole::TimingRole(const char *name,
|
|
bool is_sdf_iopath,
|
|
bool is_timing_check,
|
|
bool is_non_seq_check,
|
|
MinMax *path_min_max,
|
|
TimingRole *generic_role,
|
|
int index) :
|
|
name_(name),
|
|
is_timing_check_(is_timing_check),
|
|
is_sdf_iopath_(is_sdf_iopath),
|
|
is_non_seq_check_(is_non_seq_check),
|
|
generic_role_(generic_role),
|
|
index_(index),
|
|
path_min_max_(path_min_max)
|
|
{
|
|
timing_roles_[name] = this;
|
|
}
|
|
|
|
TimingRole *
|
|
TimingRole::find(const char *name)
|
|
{
|
|
return timing_roles_[name];
|
|
}
|
|
|
|
const TimingRole *
|
|
TimingRole::sdfRole() const
|
|
{
|
|
if (is_sdf_iopath_)
|
|
return sdf_iopath_;
|
|
else
|
|
return this;
|
|
}
|
|
|
|
const TimingRole *
|
|
TimingRole::genericRole() const
|
|
{
|
|
if (generic_role_ == nullptr)
|
|
return this;
|
|
else
|
|
return generic_role_;
|
|
}
|
|
|
|
const EarlyLate *
|
|
TimingRole::tgtClkEarlyLate() const
|
|
{
|
|
return path_min_max_->opposite();
|
|
}
|
|
|
|
bool
|
|
TimingRole::isWire() const
|
|
{
|
|
return this == wire_;
|
|
}
|
|
|
|
bool
|
|
TimingRole::isAsyncTimingCheck() const
|
|
{
|
|
return this == recovery_
|
|
|| this == removal_;
|
|
}
|
|
|
|
bool
|
|
TimingRole::isDataCheck() const
|
|
{
|
|
return this == data_check_setup_
|
|
|| this == data_check_hold_;
|
|
}
|
|
|
|
bool
|
|
TimingRole::less(const TimingRole *role1,
|
|
const TimingRole *role2)
|
|
{
|
|
return role1->index() < role2->index();
|
|
}
|
|
|
|
} // namespace
|