mirror of
https://github.com/YosysHQ/yosys
synced 2025-08-04 10:20:24 +00:00
ff: split out type-only information
This commit is contained in:
parent
c768d5e8d2
commit
95ed267960
2 changed files with 323 additions and 244 deletions
495
kernel/ff.cc
495
kernel/ff.cc
|
@ -21,247 +21,318 @@
|
||||||
|
|
||||||
USING_YOSYS_NAMESPACE
|
USING_YOSYS_NAMESPACE
|
||||||
|
|
||||||
FfData::FfData(FfInitVals *initvals, Cell *cell_) : FfData(cell_->module, initvals, cell_->name)
|
// sorry
|
||||||
{
|
template<typename InputType, typename OutputType, typename = std::enable_if_t<std::is_base_of_v<FfTypeData, OutputType>>>
|
||||||
cell = cell_;
|
void manufacture_info(InputType flop, OutputType& info, FfInitVals *initvals) {
|
||||||
sig_q = cell->getPort(ID::Q);
|
Cell* cell = nullptr;
|
||||||
width = GetSize(sig_q);
|
IdString type;
|
||||||
attributes = cell->attributes;
|
constexpr bool have_cell = std::is_same_v<InputType, Cell*>;
|
||||||
|
if constexpr (std::is_same_v<InputType, IdString>) {
|
||||||
if (initvals)
|
type = flop;
|
||||||
val_init = (*initvals)(sig_q);
|
|
||||||
|
|
||||||
std::string type_str = cell->type.str();
|
|
||||||
|
|
||||||
if (cell->type.in(ID($anyinit), ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($dffsre), ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($sdff), ID($sdffe), ID($sdffce), ID($dlatch), ID($adlatch), ID($dlatchsr), ID($sr))) {
|
|
||||||
if (cell->type.in(ID($anyinit), ID($ff))) {
|
|
||||||
has_gclk = true;
|
|
||||||
sig_d = cell->getPort(ID::D);
|
|
||||||
if (cell->type == ID($anyinit)) {
|
|
||||||
is_anyinit = true;
|
|
||||||
log_assert(val_init.is_fully_undef());
|
|
||||||
}
|
|
||||||
} else if (cell->type == ID($sr)) {
|
|
||||||
// No data input at all.
|
|
||||||
} else if (cell->type.in(ID($dlatch), ID($adlatch), ID($dlatchsr))) {
|
|
||||||
has_aload = true;
|
|
||||||
sig_aload = cell->getPort(ID::EN);
|
|
||||||
pol_aload = cell->getParam(ID::EN_POLARITY).as_bool();
|
|
||||||
sig_ad = cell->getPort(ID::D);
|
|
||||||
} else {
|
} else {
|
||||||
has_clk = true;
|
static_assert(std::is_same_v<InputType, Cell*>);
|
||||||
sig_clk = cell->getPort(ID::CLK);
|
cell = flop;
|
||||||
pol_clk = cell->getParam(ID::CLK_POLARITY).as_bool();
|
type = flop->type;
|
||||||
sig_d = cell->getPort(ID::D);
|
|
||||||
}
|
}
|
||||||
if (cell->type.in(ID($dffe), ID($dffsre), ID($adffe), ID($aldffe), ID($sdffe), ID($sdffce))) {
|
if constexpr (have_cell) {
|
||||||
has_ce = true;
|
info.sig_q = cell->getPort(ID::Q);
|
||||||
sig_ce = cell->getPort(ID::EN);
|
info.width = GetSize(info.sig_q);
|
||||||
pol_ce = cell->getParam(ID::EN_POLARITY).as_bool();
|
info.attributes = cell->attributes;
|
||||||
|
if (initvals)
|
||||||
|
info.val_init = (*initvals)(info.sig_q);
|
||||||
}
|
}
|
||||||
if (cell->type.in(ID($dffsr), ID($dffsre), ID($dlatchsr), ID($sr))) {
|
|
||||||
has_sr = true;
|
|
||||||
sig_clr = cell->getPort(ID::CLR);
|
std::string type_str = type.str();
|
||||||
sig_set = cell->getPort(ID::SET);
|
|
||||||
pol_clr = cell->getParam(ID::CLR_POLARITY).as_bool();
|
if (type.in(ID($anyinit), ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($dffsre), ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($sdff), ID($sdffe), ID($sdffce), ID($dlatch), ID($adlatch), ID($dlatchsr), ID($sr))) {
|
||||||
pol_set = cell->getParam(ID::SET_POLARITY).as_bool();
|
if (type.in(ID($anyinit), ID($ff))) {
|
||||||
|
info.has_gclk = true;
|
||||||
|
if constexpr (have_cell)
|
||||||
|
info.sig_d = cell->getPort(ID::D);
|
||||||
|
if (type == ID($anyinit)) {
|
||||||
|
info.is_anyinit = true;
|
||||||
|
if constexpr (have_cell)
|
||||||
|
log_assert(info.val_init.is_fully_undef());
|
||||||
}
|
}
|
||||||
if (cell->type.in(ID($aldff), ID($aldffe))) {
|
} else if (type == ID($sr)) {
|
||||||
has_aload = true;
|
// No data input at all.
|
||||||
sig_aload = cell->getPort(ID::ALOAD);
|
} else if (type.in(ID($dlatch), ID($adlatch), ID($dlatchsr))) {
|
||||||
pol_aload = cell->getParam(ID::ALOAD_POLARITY).as_bool();
|
info.has_aload = true;
|
||||||
sig_ad = cell->getPort(ID::AD);
|
if constexpr (have_cell) {
|
||||||
|
info.sig_aload = cell->getPort(ID::EN);
|
||||||
|
info.pol_aload = cell->getParam(ID::EN_POLARITY).as_bool();
|
||||||
|
info.sig_ad = cell->getPort(ID::D);
|
||||||
}
|
}
|
||||||
if (cell->type.in(ID($adff), ID($adffe), ID($adlatch))) {
|
} else {
|
||||||
has_arst = true;
|
info.has_clk = true;
|
||||||
sig_arst = cell->getPort(ID::ARST);
|
if constexpr (have_cell) {
|
||||||
pol_arst = cell->getParam(ID::ARST_POLARITY).as_bool();
|
info.sig_clk = cell->getPort(ID::CLK);
|
||||||
val_arst = cell->getParam(ID::ARST_VALUE);
|
info.pol_clk = cell->getParam(ID::CLK_POLARITY).as_bool();
|
||||||
|
info.sig_d = cell->getPort(ID::D);
|
||||||
}
|
}
|
||||||
if (cell->type.in(ID($sdff), ID($sdffe), ID($sdffce))) {
|
|
||||||
has_srst = true;
|
|
||||||
sig_srst = cell->getPort(ID::SRST);
|
|
||||||
pol_srst = cell->getParam(ID::SRST_POLARITY).as_bool();
|
|
||||||
val_srst = cell->getParam(ID::SRST_VALUE);
|
|
||||||
ce_over_srst = cell->type == ID($sdffce);
|
|
||||||
}
|
}
|
||||||
} else if (cell->type == ID($_FF_)) {
|
if (type.in(ID($dffe), ID($dffsre), ID($adffe), ID($aldffe), ID($sdffe), ID($sdffce))) {
|
||||||
is_fine = true;
|
info.has_ce = true;
|
||||||
has_gclk = true;
|
if constexpr (have_cell) {
|
||||||
sig_d = cell->getPort(ID::D);
|
info.sig_ce = cell->getPort(ID::EN);
|
||||||
|
info.pol_ce = cell->getParam(ID::EN_POLARITY).as_bool();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type.in(ID($dffsr), ID($dffsre), ID($dlatchsr), ID($sr))) {
|
||||||
|
info.has_sr = true;
|
||||||
|
if constexpr (have_cell) {
|
||||||
|
info.sig_clr = cell->getPort(ID::CLR);
|
||||||
|
info.sig_set = cell->getPort(ID::SET);
|
||||||
|
info.pol_clr = cell->getParam(ID::CLR_POLARITY).as_bool();
|
||||||
|
info.pol_set = cell->getParam(ID::SET_POLARITY).as_bool();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type.in(ID($aldff), ID($aldffe))) {
|
||||||
|
info.has_aload = true;
|
||||||
|
if constexpr (have_cell) {
|
||||||
|
info.sig_aload = cell->getPort(ID::ALOAD);
|
||||||
|
info.pol_aload = cell->getParam(ID::ALOAD_POLARITY).as_bool();
|
||||||
|
info.sig_ad = cell->getPort(ID::AD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type.in(ID($adff), ID($adffe), ID($adlatch))) {
|
||||||
|
info.has_arst = true;
|
||||||
|
if constexpr (have_cell) {
|
||||||
|
info.sig_arst = cell->getPort(ID::ARST);
|
||||||
|
info.pol_arst = cell->getParam(ID::ARST_POLARITY).as_bool();
|
||||||
|
info.val_arst = cell->getParam(ID::ARST_VALUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type.in(ID($sdff), ID($sdffe), ID($sdffce))) {
|
||||||
|
info.has_srst = true;
|
||||||
|
if constexpr (have_cell) {
|
||||||
|
info.sig_srst = cell->getPort(ID::SRST);
|
||||||
|
info.pol_srst = cell->getParam(ID::SRST_POLARITY).as_bool();
|
||||||
|
info.val_srst = cell->getParam(ID::SRST_VALUE);
|
||||||
|
}
|
||||||
|
info.ce_over_srst = type == ID($sdffce);
|
||||||
|
}
|
||||||
|
} else if (type == ID($_FF_)) {
|
||||||
|
info.is_fine = true;
|
||||||
|
info.has_gclk = true;
|
||||||
|
if constexpr (have_cell)
|
||||||
|
info.sig_d = cell->getPort(ID::D);
|
||||||
} else if (type_str.substr(0, 5) == "$_SR_") {
|
} else if (type_str.substr(0, 5) == "$_SR_") {
|
||||||
is_fine = true;
|
info.is_fine = true;
|
||||||
has_sr = true;
|
info.has_sr = true;
|
||||||
pol_set = type_str[5] == 'P';
|
info.pol_set = type_str[5] == 'P';
|
||||||
pol_clr = type_str[6] == 'P';
|
info.pol_clr = type_str[6] == 'P';
|
||||||
sig_set = cell->getPort(ID::S);
|
if constexpr (have_cell) {
|
||||||
sig_clr = cell->getPort(ID::R);
|
info.sig_set = cell->getPort(ID::S);
|
||||||
|
info.sig_clr = cell->getPort(ID::R);
|
||||||
|
}
|
||||||
} else if (type_str.substr(0, 6) == "$_DFF_" && type_str.size() == 8) {
|
} else if (type_str.substr(0, 6) == "$_DFF_" && type_str.size() == 8) {
|
||||||
is_fine = true;
|
info.is_fine = true;
|
||||||
sig_d = cell->getPort(ID::D);
|
info.has_clk = true;
|
||||||
has_clk = true;
|
info.pol_clk = type_str[6] == 'P';
|
||||||
pol_clk = type_str[6] == 'P';
|
if constexpr (have_cell) {
|
||||||
sig_clk = cell->getPort(ID::C);
|
info.sig_d = cell->getPort(ID::D);
|
||||||
|
info.sig_clk = cell->getPort(ID::C);
|
||||||
|
}
|
||||||
} else if (type_str.substr(0, 7) == "$_DFFE_" && type_str.size() == 10) {
|
} else if (type_str.substr(0, 7) == "$_DFFE_" && type_str.size() == 10) {
|
||||||
is_fine = true;
|
info.is_fine = true;
|
||||||
sig_d = cell->getPort(ID::D);
|
info.has_clk = true;
|
||||||
has_clk = true;
|
info.pol_clk = type_str[7] == 'P';
|
||||||
pol_clk = type_str[7] == 'P';
|
info.has_ce = true;
|
||||||
sig_clk = cell->getPort(ID::C);
|
info.pol_ce = type_str[8] == 'P';
|
||||||
has_ce = true;
|
if constexpr (have_cell) {
|
||||||
pol_ce = type_str[8] == 'P';
|
info.sig_d = cell->getPort(ID::D);
|
||||||
sig_ce = cell->getPort(ID::E);
|
info.sig_clk = cell->getPort(ID::C);
|
||||||
|
info.sig_ce = cell->getPort(ID::E);
|
||||||
|
}
|
||||||
} else if (type_str.substr(0, 6) == "$_DFF_" && type_str.size() == 10) {
|
} else if (type_str.substr(0, 6) == "$_DFF_" && type_str.size() == 10) {
|
||||||
is_fine = true;
|
info.is_fine = true;
|
||||||
sig_d = cell->getPort(ID::D);
|
info.has_clk = true;
|
||||||
has_clk = true;
|
info.pol_clk = type_str[6] == 'P';
|
||||||
pol_clk = type_str[6] == 'P';
|
info.has_arst = true;
|
||||||
sig_clk = cell->getPort(ID::C);
|
info.pol_arst = type_str[7] == 'P';
|
||||||
has_arst = true;
|
info.val_arst = type_str[8] == '1' ? State::S1 : State::S0;
|
||||||
pol_arst = type_str[7] == 'P';
|
if constexpr (have_cell) {
|
||||||
sig_arst = cell->getPort(ID::R);
|
info.sig_d = cell->getPort(ID::D);
|
||||||
val_arst = type_str[8] == '1' ? State::S1 : State::S0;
|
info.sig_clk = cell->getPort(ID::C);
|
||||||
|
info.sig_arst = cell->getPort(ID::R);
|
||||||
|
}
|
||||||
} else if (type_str.substr(0, 7) == "$_DFFE_" && type_str.size() == 12) {
|
} else if (type_str.substr(0, 7) == "$_DFFE_" && type_str.size() == 12) {
|
||||||
is_fine = true;
|
info.is_fine = true;
|
||||||
sig_d = cell->getPort(ID::D);
|
info.has_clk = true;
|
||||||
has_clk = true;
|
info.pol_clk = type_str[7] == 'P';
|
||||||
pol_clk = type_str[7] == 'P';
|
info.has_arst = true;
|
||||||
sig_clk = cell->getPort(ID::C);
|
info.pol_arst = type_str[8] == 'P';
|
||||||
has_arst = true;
|
info.val_arst = type_str[9] == '1' ? State::S1 : State::S0;
|
||||||
pol_arst = type_str[8] == 'P';
|
info.has_ce = true;
|
||||||
sig_arst = cell->getPort(ID::R);
|
info.pol_ce = type_str[10] == 'P';
|
||||||
val_arst = type_str[9] == '1' ? State::S1 : State::S0;
|
if constexpr (have_cell) {
|
||||||
has_ce = true;
|
info.sig_d = cell->getPort(ID::D);
|
||||||
pol_ce = type_str[10] == 'P';
|
info.sig_clk = cell->getPort(ID::C);
|
||||||
sig_ce = cell->getPort(ID::E);
|
info.sig_arst = cell->getPort(ID::R);
|
||||||
|
info.sig_ce = cell->getPort(ID::E);
|
||||||
|
}
|
||||||
} else if (type_str.substr(0, 8) == "$_ALDFF_" && type_str.size() == 11) {
|
} else if (type_str.substr(0, 8) == "$_ALDFF_" && type_str.size() == 11) {
|
||||||
is_fine = true;
|
info.is_fine = true;
|
||||||
sig_d = cell->getPort(ID::D);
|
info.has_clk = true;
|
||||||
has_clk = true;
|
info.pol_clk = type_str[8] == 'P';
|
||||||
pol_clk = type_str[8] == 'P';
|
info.has_aload = true;
|
||||||
sig_clk = cell->getPort(ID::C);
|
info.pol_aload = type_str[9] == 'P';
|
||||||
has_aload = true;
|
if constexpr (have_cell) {
|
||||||
pol_aload = type_str[9] == 'P';
|
info.sig_d = cell->getPort(ID::D);
|
||||||
sig_aload = cell->getPort(ID::L);
|
info.sig_clk = cell->getPort(ID::C);
|
||||||
sig_ad = cell->getPort(ID::AD);
|
info.sig_aload = cell->getPort(ID::L);
|
||||||
|
info.sig_ad = cell->getPort(ID::AD);
|
||||||
|
}
|
||||||
} else if (type_str.substr(0, 9) == "$_ALDFFE_" && type_str.size() == 13) {
|
} else if (type_str.substr(0, 9) == "$_ALDFFE_" && type_str.size() == 13) {
|
||||||
is_fine = true;
|
info.is_fine = true;
|
||||||
sig_d = cell->getPort(ID::D);
|
info.has_clk = true;
|
||||||
has_clk = true;
|
info.pol_clk = type_str[9] == 'P';
|
||||||
pol_clk = type_str[9] == 'P';
|
info.has_aload = true;
|
||||||
sig_clk = cell->getPort(ID::C);
|
info.pol_aload = type_str[10] == 'P';
|
||||||
has_aload = true;
|
info.has_ce = true;
|
||||||
pol_aload = type_str[10] == 'P';
|
info.pol_ce = type_str[11] == 'P';
|
||||||
sig_aload = cell->getPort(ID::L);
|
if constexpr (have_cell) {
|
||||||
sig_ad = cell->getPort(ID::AD);
|
info.sig_d = cell->getPort(ID::D);
|
||||||
has_ce = true;
|
info.sig_clk = cell->getPort(ID::C);
|
||||||
pol_ce = type_str[11] == 'P';
|
info.sig_aload = cell->getPort(ID::L);
|
||||||
sig_ce = cell->getPort(ID::E);
|
info.sig_ad = cell->getPort(ID::AD);
|
||||||
|
info.sig_ce = cell->getPort(ID::E);
|
||||||
|
}
|
||||||
} else if (type_str.substr(0, 8) == "$_DFFSR_" && type_str.size() == 12) {
|
} else if (type_str.substr(0, 8) == "$_DFFSR_" && type_str.size() == 12) {
|
||||||
is_fine = true;
|
info.is_fine = true;
|
||||||
sig_d = cell->getPort(ID::D);
|
info.has_clk = true;
|
||||||
has_clk = true;
|
info.pol_clk = type_str[8] == 'P';
|
||||||
pol_clk = type_str[8] == 'P';
|
info.has_sr = true;
|
||||||
sig_clk = cell->getPort(ID::C);
|
info.pol_set = type_str[9] == 'P';
|
||||||
has_sr = true;
|
info.pol_clr = type_str[10] == 'P';
|
||||||
pol_set = type_str[9] == 'P';
|
if constexpr (have_cell) {
|
||||||
pol_clr = type_str[10] == 'P';
|
info.sig_d = cell->getPort(ID::D);
|
||||||
sig_set = cell->getPort(ID::S);
|
info.sig_clk = cell->getPort(ID::C);
|
||||||
sig_clr = cell->getPort(ID::R);
|
info.sig_set = cell->getPort(ID::S);
|
||||||
|
info.sig_clr = cell->getPort(ID::R);
|
||||||
|
}
|
||||||
} else if (type_str.substr(0, 9) == "$_DFFSRE_" && type_str.size() == 14) {
|
} else if (type_str.substr(0, 9) == "$_DFFSRE_" && type_str.size() == 14) {
|
||||||
is_fine = true;
|
info.is_fine = true;
|
||||||
sig_d = cell->getPort(ID::D);
|
info.has_clk = true;
|
||||||
has_clk = true;
|
info.pol_clk = type_str[9] == 'P';
|
||||||
pol_clk = type_str[9] == 'P';
|
info.has_sr = true;
|
||||||
sig_clk = cell->getPort(ID::C);
|
info.pol_set = type_str[10] == 'P';
|
||||||
has_sr = true;
|
info.pol_clr = type_str[11] == 'P';
|
||||||
pol_set = type_str[10] == 'P';
|
info.has_ce = true;
|
||||||
pol_clr = type_str[11] == 'P';
|
info.pol_ce = type_str[12] == 'P';
|
||||||
sig_set = cell->getPort(ID::S);
|
if constexpr (have_cell) {
|
||||||
sig_clr = cell->getPort(ID::R);
|
info.sig_d = cell->getPort(ID::D);
|
||||||
has_ce = true;
|
info.sig_clk = cell->getPort(ID::C);
|
||||||
pol_ce = type_str[12] == 'P';
|
info.sig_set = cell->getPort(ID::S);
|
||||||
sig_ce = cell->getPort(ID::E);
|
info.sig_clr = cell->getPort(ID::R);
|
||||||
|
info.sig_ce = cell->getPort(ID::E);
|
||||||
|
}
|
||||||
} else if (type_str.substr(0, 7) == "$_SDFF_" && type_str.size() == 11) {
|
} else if (type_str.substr(0, 7) == "$_SDFF_" && type_str.size() == 11) {
|
||||||
is_fine = true;
|
info.is_fine = true;
|
||||||
sig_d = cell->getPort(ID::D);
|
info.has_clk = true;
|
||||||
has_clk = true;
|
info.pol_clk = type_str[7] == 'P';
|
||||||
pol_clk = type_str[7] == 'P';
|
info.has_srst = true;
|
||||||
sig_clk = cell->getPort(ID::C);
|
info.pol_srst = type_str[8] == 'P';
|
||||||
has_srst = true;
|
info.val_srst = type_str[9] == '1' ? State::S1 : State::S0;
|
||||||
pol_srst = type_str[8] == 'P';
|
if constexpr (have_cell) {
|
||||||
sig_srst = cell->getPort(ID::R);
|
info.sig_d = cell->getPort(ID::D);
|
||||||
val_srst = type_str[9] == '1' ? State::S1 : State::S0;
|
info.sig_clk = cell->getPort(ID::C);
|
||||||
|
info.sig_srst = cell->getPort(ID::R);
|
||||||
|
}
|
||||||
} else if (type_str.substr(0, 8) == "$_SDFFE_" && type_str.size() == 13) {
|
} else if (type_str.substr(0, 8) == "$_SDFFE_" && type_str.size() == 13) {
|
||||||
is_fine = true;
|
info.is_fine = true;
|
||||||
sig_d = cell->getPort(ID::D);
|
info.has_clk = true;
|
||||||
has_clk = true;
|
info.pol_clk = type_str[8] == 'P';
|
||||||
pol_clk = type_str[8] == 'P';
|
info.has_srst = true;
|
||||||
sig_clk = cell->getPort(ID::C);
|
info.pol_srst = type_str[9] == 'P';
|
||||||
has_srst = true;
|
info.val_srst = type_str[10] == '1' ? State::S1 : State::S0;
|
||||||
pol_srst = type_str[9] == 'P';
|
info.has_ce = true;
|
||||||
sig_srst = cell->getPort(ID::R);
|
info.pol_ce = type_str[11] == 'P';
|
||||||
val_srst = type_str[10] == '1' ? State::S1 : State::S0;
|
if constexpr (have_cell) {
|
||||||
has_ce = true;
|
info.sig_d = cell->getPort(ID::D);
|
||||||
pol_ce = type_str[11] == 'P';
|
info.sig_clk = cell->getPort(ID::C);
|
||||||
sig_ce = cell->getPort(ID::E);
|
info.sig_srst = cell->getPort(ID::R);
|
||||||
|
info.sig_ce = cell->getPort(ID::E);
|
||||||
|
}
|
||||||
} else if (type_str.substr(0, 9) == "$_SDFFCE_" && type_str.size() == 14) {
|
} else if (type_str.substr(0, 9) == "$_SDFFCE_" && type_str.size() == 14) {
|
||||||
is_fine = true;
|
info.is_fine = true;
|
||||||
sig_d = cell->getPort(ID::D);
|
info.has_clk = true;
|
||||||
has_clk = true;
|
info.pol_clk = type_str[9] == 'P';
|
||||||
pol_clk = type_str[9] == 'P';
|
info.has_srst = true;
|
||||||
sig_clk = cell->getPort(ID::C);
|
info.pol_srst = type_str[10] == 'P';
|
||||||
has_srst = true;
|
info.val_srst = type_str[11] == '1' ? State::S1 : State::S0;
|
||||||
pol_srst = type_str[10] == 'P';
|
info.has_ce = true;
|
||||||
sig_srst = cell->getPort(ID::R);
|
info.pol_ce = type_str[12] == 'P';
|
||||||
val_srst = type_str[11] == '1' ? State::S1 : State::S0;
|
info.ce_over_srst = true;
|
||||||
has_ce = true;
|
if constexpr (have_cell) {
|
||||||
pol_ce = type_str[12] == 'P';
|
info.sig_d = cell->getPort(ID::D);
|
||||||
sig_ce = cell->getPort(ID::E);
|
info.sig_clk = cell->getPort(ID::C);
|
||||||
ce_over_srst = true;
|
info.sig_srst = cell->getPort(ID::R);
|
||||||
|
info.sig_ce = cell->getPort(ID::E);
|
||||||
|
}
|
||||||
} else if (type_str.substr(0, 9) == "$_DLATCH_" && type_str.size() == 11) {
|
} else if (type_str.substr(0, 9) == "$_DLATCH_" && type_str.size() == 11) {
|
||||||
is_fine = true;
|
info.is_fine = true;
|
||||||
has_aload = true;
|
info.has_aload = true;
|
||||||
sig_ad = cell->getPort(ID::D);
|
info.has_aload = true;
|
||||||
has_aload = true;
|
info.pol_aload = type_str[9] == 'P';
|
||||||
pol_aload = type_str[9] == 'P';
|
if constexpr (have_cell) {
|
||||||
sig_aload = cell->getPort(ID::E);
|
info.sig_ad = cell->getPort(ID::D);
|
||||||
|
info.sig_aload = cell->getPort(ID::E);
|
||||||
|
}
|
||||||
} else if (type_str.substr(0, 9) == "$_DLATCH_" && type_str.size() == 13) {
|
} else if (type_str.substr(0, 9) == "$_DLATCH_" && type_str.size() == 13) {
|
||||||
is_fine = true;
|
info.is_fine = true;
|
||||||
has_aload = true;
|
info.has_aload = true;
|
||||||
sig_ad = cell->getPort(ID::D);
|
info.has_aload = true;
|
||||||
has_aload = true;
|
info.pol_aload = type_str[9] == 'P';
|
||||||
pol_aload = type_str[9] == 'P';
|
info.has_arst = true;
|
||||||
sig_aload = cell->getPort(ID::E);
|
info.pol_arst = type_str[10] == 'P';
|
||||||
has_arst = true;
|
info.val_arst = type_str[11] == '1' ? State::S1 : State::S0;
|
||||||
pol_arst = type_str[10] == 'P';
|
if constexpr (have_cell) {
|
||||||
sig_arst = cell->getPort(ID::R);
|
info.sig_ad = cell->getPort(ID::D);
|
||||||
val_arst = type_str[11] == '1' ? State::S1 : State::S0;
|
info.sig_aload = cell->getPort(ID::E);
|
||||||
|
info.sig_arst = cell->getPort(ID::R);
|
||||||
|
}
|
||||||
} else if (type_str.substr(0, 11) == "$_DLATCHSR_" && type_str.size() == 15) {
|
} else if (type_str.substr(0, 11) == "$_DLATCHSR_" && type_str.size() == 15) {
|
||||||
is_fine = true;
|
info.is_fine = true;
|
||||||
has_aload = true;
|
info.has_aload = true;
|
||||||
sig_ad = cell->getPort(ID::D);
|
info.has_aload = true;
|
||||||
has_aload = true;
|
info.pol_aload = type_str[11] == 'P';
|
||||||
pol_aload = type_str[11] == 'P';
|
info.has_sr = true;
|
||||||
sig_aload = cell->getPort(ID::E);
|
info.pol_set = type_str[12] == 'P';
|
||||||
has_sr = true;
|
info.pol_clr = type_str[13] == 'P';
|
||||||
pol_set = type_str[12] == 'P';
|
if constexpr (have_cell) {
|
||||||
pol_clr = type_str[13] == 'P';
|
info.sig_ad = cell->getPort(ID::D);
|
||||||
sig_set = cell->getPort(ID::S);
|
info.sig_aload = cell->getPort(ID::E);
|
||||||
sig_clr = cell->getPort(ID::R);
|
info.sig_set = cell->getPort(ID::S);
|
||||||
|
info.sig_clr = cell->getPort(ID::R);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
log_assert(0);
|
log_assert(0);
|
||||||
}
|
}
|
||||||
if (has_aload && !has_clk && !has_sr && !has_arst && sig_ad.is_fully_const()) {
|
if constexpr (have_cell)
|
||||||
|
if (info.has_aload && !info.has_clk && !info.has_sr && !info.has_arst && info.sig_ad.is_fully_const()) {
|
||||||
// Plain D latches with const D treated specially.
|
// Plain D latches with const D treated specially.
|
||||||
has_aload = false;
|
info.has_aload = false;
|
||||||
has_arst = true;
|
info.has_arst = true;
|
||||||
sig_arst = sig_aload;
|
info.sig_arst = info.sig_aload;
|
||||||
pol_arst = pol_aload;
|
info.pol_arst = info.pol_aload;
|
||||||
val_arst = sig_ad.as_const();
|
info.val_arst = info.sig_ad.as_const();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FfTypeData::FfTypeData(IdString type) : FfTypeData()
|
||||||
|
{
|
||||||
|
manufacture_info(type, *this, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
FfData::FfData(FfInitVals *initvals, Cell *cell_) : FfData(cell_->module, initvals, cell_->name)
|
||||||
|
{
|
||||||
|
cell = cell_;
|
||||||
|
manufacture_info(cell, *this, initvals);
|
||||||
|
}
|
||||||
|
|
||||||
FfData FfData::slice(const std::vector<int> &bits) {
|
FfData FfData::slice(const std::vector<int> &bits) {
|
||||||
FfData res(module, initvals, NEW_ID);
|
FfData res(module, initvals, NEW_ID);
|
||||||
res.sig_clk = sig_clk;
|
res.sig_clk = sig_clk;
|
||||||
|
|
78
kernel/ff.h
78
kernel/ff.h
|
@ -78,31 +78,20 @@ YOSYS_NAMESPACE_BEGIN
|
||||||
// - has_arst [does not correspond to a native cell, represented as dlatch with const D input]
|
// - has_arst [does not correspond to a native cell, represented as dlatch with const D input]
|
||||||
// - empty set [not a cell — will be emitted as a simple direct connection]
|
// - empty set [not a cell — will be emitted as a simple direct connection]
|
||||||
|
|
||||||
struct FfData {
|
struct FfTypeData {
|
||||||
Module *module;
|
FfTypeData(IdString type);
|
||||||
FfInitVals *initvals;
|
FfTypeData() {
|
||||||
Cell *cell;
|
has_clk = false;
|
||||||
IdString name;
|
has_gclk = false;
|
||||||
// The FF output.
|
has_ce = false;
|
||||||
SigSpec sig_q;
|
has_aload = false;
|
||||||
// The sync data input, present if has_clk or has_gclk.
|
has_srst = false;
|
||||||
SigSpec sig_d;
|
has_arst = false;
|
||||||
// The async data input, present if has_aload.
|
has_sr = false;
|
||||||
SigSpec sig_ad;
|
ce_over_srst = false;
|
||||||
// The sync clock, present if has_clk.
|
is_fine = false;
|
||||||
SigSpec sig_clk;
|
is_anyinit = false;
|
||||||
// The clock enable, present if has_ce.
|
}
|
||||||
SigSpec sig_ce;
|
|
||||||
// The async load enable, present if has_aload.
|
|
||||||
SigSpec sig_aload;
|
|
||||||
// The async reset, preset if has_arst.
|
|
||||||
SigSpec sig_arst;
|
|
||||||
// The sync reset, preset if has_srst.
|
|
||||||
SigSpec sig_srst;
|
|
||||||
// The async clear (per-lane), present if has_sr.
|
|
||||||
SigSpec sig_clr;
|
|
||||||
// The async set (per-lane), present if has_sr.
|
|
||||||
SigSpec sig_set;
|
|
||||||
// True if this is a clocked (edge-sensitive) flip-flop.
|
// True if this is a clocked (edge-sensitive) flip-flop.
|
||||||
bool has_clk;
|
bool has_clk;
|
||||||
// True if this is a $ff, exclusive with every other has_*.
|
// True if this is a $ff, exclusive with every other has_*.
|
||||||
|
@ -143,9 +132,38 @@ struct FfData {
|
||||||
bool pol_clr;
|
bool pol_clr;
|
||||||
bool pol_set;
|
bool pol_set;
|
||||||
// The value loaded by sig_arst.
|
// The value loaded by sig_arst.
|
||||||
|
// Zero length if unknowable from just type
|
||||||
Const val_arst;
|
Const val_arst;
|
||||||
// The value loaded by sig_srst.
|
// The value loaded by sig_srst.
|
||||||
|
// Zero length if unknowable from just type
|
||||||
Const val_srst;
|
Const val_srst;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FfData : FfTypeData {
|
||||||
|
Module *module;
|
||||||
|
FfInitVals *initvals;
|
||||||
|
Cell *cell;
|
||||||
|
IdString name;
|
||||||
|
// The FF output.
|
||||||
|
SigSpec sig_q;
|
||||||
|
// The sync data input, present if has_clk or has_gclk.
|
||||||
|
SigSpec sig_d;
|
||||||
|
// The async data input, present if has_aload.
|
||||||
|
SigSpec sig_ad;
|
||||||
|
// The sync clock, present if has_clk.
|
||||||
|
SigSpec sig_clk;
|
||||||
|
// The clock enable, present if has_ce.
|
||||||
|
SigSpec sig_ce;
|
||||||
|
// The async load enable, present if has_aload.
|
||||||
|
SigSpec sig_aload;
|
||||||
|
// The async reset, preset if has_arst.
|
||||||
|
SigSpec sig_arst;
|
||||||
|
// The sync reset, preset if has_srst.
|
||||||
|
SigSpec sig_srst;
|
||||||
|
// The async clear (per-lane), present if has_sr.
|
||||||
|
SigSpec sig_clr;
|
||||||
|
// The async set (per-lane), present if has_sr.
|
||||||
|
SigSpec sig_set;
|
||||||
// The initial value at power-up.
|
// The initial value at power-up.
|
||||||
Const val_init;
|
Const val_init;
|
||||||
// The FF data width in bits.
|
// The FF data width in bits.
|
||||||
|
@ -154,16 +172,6 @@ struct FfData {
|
||||||
|
|
||||||
FfData(Module *module = nullptr, FfInitVals *initvals = nullptr, IdString name = IdString()) : module(module), initvals(initvals), cell(nullptr), name(name) {
|
FfData(Module *module = nullptr, FfInitVals *initvals = nullptr, IdString name = IdString()) : module(module), initvals(initvals), cell(nullptr), name(name) {
|
||||||
width = 0;
|
width = 0;
|
||||||
has_clk = false;
|
|
||||||
has_gclk = false;
|
|
||||||
has_ce = false;
|
|
||||||
has_aload = false;
|
|
||||||
has_srst = false;
|
|
||||||
has_arst = false;
|
|
||||||
has_sr = false;
|
|
||||||
ce_over_srst = false;
|
|
||||||
is_fine = false;
|
|
||||||
is_anyinit = false;
|
|
||||||
pol_clk = false;
|
pol_clk = false;
|
||||||
pol_aload = false;
|
pol_aload = false;
|
||||||
pol_ce = false;
|
pol_ce = false;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue