aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rtlil.cc
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/rtlil.cc')
-rw-r--r--kernel/rtlil.cc200
1 files changed, 196 insertions, 4 deletions
diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc
index a05023c52..72dcb89af 100644
--- a/kernel/rtlil.cc
+++ b/kernel/rtlil.cc
@@ -58,6 +58,8 @@ const pool<IdString> &RTLIL::builtin_ff_cell_types() {
ID($dffsre),
ID($adff),
ID($adffe),
+ ID($aldff),
+ ID($aldffe),
ID($sdff),
ID($sdffe),
ID($sdffce),
@@ -118,6 +120,18 @@ const pool<IdString> &RTLIL::builtin_ff_cell_types() {
ID($_DFFE_PP0P_),
ID($_DFFE_PP1N_),
ID($_DFFE_PP1P_),
+ ID($_ALDFF_NN_),
+ ID($_ALDFF_NP_),
+ ID($_ALDFF_PN_),
+ ID($_ALDFF_PP_),
+ ID($_ALDFFE_NNN_),
+ ID($_ALDFFE_NNP_),
+ ID($_ALDFFE_NPN_),
+ ID($_ALDFFE_NPP_),
+ ID($_ALDFFE_PNN_),
+ ID($_ALDFFE_PNP_),
+ ID($_ALDFFE_PPN_),
+ ID($_ALDFFE_PPP_),
ID($_SDFF_NN0_),
ID($_SDFF_NN1_),
ID($_SDFF_NP0_),
@@ -193,6 +207,7 @@ RTLIL::Const::Const()
RTLIL::Const::Const(std::string str)
{
flags = RTLIL::CONST_FLAG_STRING;
+ bits.reserve(str.size() * 8);
for (int i = str.size()-1; i >= 0; i--) {
unsigned char ch = str[i];
for (int j = 0; j < 8; j++) {
@@ -205,6 +220,7 @@ RTLIL::Const::Const(std::string str)
RTLIL::Const::Const(int val, int width)
{
flags = RTLIL::CONST_FLAG_NONE;
+ bits.reserve(width);
for (int i = 0; i < width; i++) {
bits.push_back((val & 1) != 0 ? State::S1 : State::S0);
val = val >> 1;
@@ -214,6 +230,7 @@ RTLIL::Const::Const(int val, int width)
RTLIL::Const::Const(RTLIL::State bit, int width)
{
flags = RTLIL::CONST_FLAG_NONE;
+ bits.reserve(width);
for (int i = 0; i < width; i++)
bits.push_back(bit);
}
@@ -221,6 +238,7 @@ RTLIL::Const::Const(RTLIL::State bit, int width)
RTLIL::Const::Const(const std::vector<bool> &bits)
{
flags = RTLIL::CONST_FLAG_NONE;
+ this->bits.reserve(bits.size());
for (const auto &b : bits)
this->bits.emplace_back(b ? State::S1 : State::S0);
}
@@ -228,6 +246,7 @@ RTLIL::Const::Const(const std::vector<bool> &bits)
RTLIL::Const::Const(const RTLIL::Const &c)
{
flags = c.flags;
+ this->bits.reserve(c.size());
for (const auto &b : c.bits)
this->bits.push_back(b);
}
@@ -466,6 +485,35 @@ vector<string> RTLIL::AttrObject::get_hdlname_attribute() const
return split_tokens(get_string_attribute(ID::hdlname), " ");
}
+void RTLIL::AttrObject::set_intvec_attribute(RTLIL::IdString id, const vector<int> &data)
+{
+ std::stringstream attrval;
+ for (auto &i : data) {
+ if (attrval.tellp() > 0)
+ attrval << " ";
+ attrval << i;
+ }
+ attributes[id] = RTLIL::Const(attrval.str());
+}
+
+vector<int> RTLIL::AttrObject::get_intvec_attribute(RTLIL::IdString id) const
+{
+ vector<int> data;
+ auto it = attributes.find(id);
+ if (it != attributes.end())
+ for (const auto &s : split_tokens(attributes.at(id).decode_string())) {
+ char *end = nullptr;
+ errno = 0;
+ long value = strtol(s.c_str(), &end, 10);
+ if (end != s.c_str() + s.size())
+ log_cmd_error("Literal for intvec attribute has invalid format");
+ if (errno == ERANGE || value < INT_MIN || value > INT_MAX)
+ log_cmd_error("Literal for intvec attribute is out of range");
+ data.push_back(value);
+ }
+ return data;
+}
+
bool RTLIL::Selection::selected_module(RTLIL::IdString mod_name) const
{
if (full_selection)
@@ -922,9 +970,14 @@ void RTLIL::Module::makeblackbox()
set_bool_attribute(ID::blackbox);
}
-void RTLIL::Module::reprocess_module(RTLIL::Design *, const dict<RTLIL::IdString, RTLIL::Module *> &)
+void RTLIL::Module::expand_interfaces(RTLIL::Design *, const dict<RTLIL::IdString, RTLIL::Module *> &)
+{
+ log_error("Class doesn't support expand_interfaces (module: `%s')!\n", id2cstr(name));
+}
+
+bool RTLIL::Module::reprocess_if_necessary(RTLIL::Design *)
{
- log_error("Cannot reprocess_module module `%s' !\n", id2cstr(name));
+ return false;
}
RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, const dict<RTLIL::IdString, RTLIL::Const> &, bool mayfail)
@@ -1203,6 +1256,22 @@ namespace {
return;
}
+ if (cell->type == ID($bmux)) {
+ port(ID::A, param(ID::WIDTH) << param(ID::S_WIDTH));
+ port(ID::S, param(ID::S_WIDTH));
+ port(ID::Y, param(ID::WIDTH));
+ check_expected();
+ return;
+ }
+
+ if (cell->type == ID($demux)) {
+ port(ID::A, param(ID::WIDTH));
+ port(ID::S, param(ID::S_WIDTH));
+ port(ID::Y, param(ID::WIDTH) << param(ID::S_WIDTH));
+ check_expected();
+ return;
+ }
+
if (cell->type == ID($lut)) {
param(ID::LUT);
port(ID::A, param(ID::WIDTH));
@@ -1337,6 +1406,32 @@ namespace {
return;
}
+ if (cell->type == ID($aldff)) {
+ param_bool(ID::CLK_POLARITY);
+ param_bool(ID::ALOAD_POLARITY);
+ port(ID::CLK, 1);
+ port(ID::ALOAD, 1);
+ port(ID::D, param(ID::WIDTH));
+ port(ID::AD, param(ID::WIDTH));
+ port(ID::Q, param(ID::WIDTH));
+ check_expected();
+ return;
+ }
+
+ if (cell->type == ID($aldffe)) {
+ param_bool(ID::CLK_POLARITY);
+ param_bool(ID::EN_POLARITY);
+ param_bool(ID::ALOAD_POLARITY);
+ port(ID::CLK, 1);
+ port(ID::EN, 1);
+ port(ID::ALOAD, 1);
+ port(ID::D, param(ID::WIDTH));
+ port(ID::AD, param(ID::WIDTH));
+ port(ID::Q, param(ID::WIDTH));
+ check_expected();
+ return;
+ }
+
if (cell->type == ID($dlatch)) {
param_bool(ID::EN_POLARITY);
port(ID::EN, 1);
@@ -1649,6 +1744,15 @@ namespace {
{ port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::R,1); port(ID::E,1); check_expected(); return; }
if (cell->type.in(
+ ID($_ALDFF_NN_), ID($_ALDFF_NP_), ID($_ALDFF_PN_), ID($_ALDFF_PP_)))
+ { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::L,1); port(ID::AD,1); check_expected(); return; }
+
+ if (cell->type.in(
+ ID($_ALDFFE_NNN_), ID($_ALDFFE_NNP_), ID($_ALDFFE_NPN_), ID($_ALDFFE_NPP_),
+ ID($_ALDFFE_PNN_), ID($_ALDFFE_PNP_), ID($_ALDFFE_PPN_), ID($_ALDFFE_PPP_)))
+ { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::L,1); port(ID::AD,1); port(ID::E,1); check_expected(); return; }
+
+ if (cell->type.in(
ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_)))
{ port(ID::C,1); port(ID::S,1); port(ID::R,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; }
@@ -2361,6 +2465,26 @@ DEF_METHOD(Mux, ID($mux), 0)
DEF_METHOD(Pmux, ID($pmux), 1)
#undef DEF_METHOD
+#define DEF_METHOD(_func, _type, _demux) \
+ RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const std::string &src) { \
+ RTLIL::Cell *cell = addCell(name, _type); \
+ cell->parameters[ID::WIDTH] = _demux ? sig_a.size() : sig_y.size(); \
+ cell->parameters[ID::S_WIDTH] = sig_s.size(); \
+ cell->setPort(ID::A, sig_a); \
+ cell->setPort(ID::S, sig_s); \
+ cell->setPort(ID::Y, sig_y); \
+ cell->set_src_attribute(src); \
+ return cell; \
+ } \
+ RTLIL::SigSpec RTLIL::Module::_func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const std::string &src) { \
+ RTLIL::SigSpec sig_y = addWire(NEW_ID, _demux ? sig_a.size() << sig_s.size() : sig_a.size() >> sig_s.size()); \
+ add ## _func(name, sig_a, sig_s, sig_y, src); \
+ return sig_y; \
+ }
+DEF_METHOD(Bmux, ID($bmux), 0)
+DEF_METHOD(Demux, ID($demux), 1)
+#undef DEF_METHOD
+
#define DEF_METHOD_2(_func, _type, _P1, _P2) \
RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const RTLIL::SigBit &sig2, const std::string &src) { \
RTLIL::Cell *cell = addCell(name, _type); \
@@ -2675,6 +2799,40 @@ RTLIL::Cell* RTLIL::Module::addAdffe(RTLIL::IdString name, const RTLIL::SigSpec
return cell;
}
+RTLIL::Cell* RTLIL::Module::addAldff(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
+ const RTLIL::SigSpec &sig_ad, bool clk_polarity, bool aload_polarity, const std::string &src)
+{
+ RTLIL::Cell *cell = addCell(name, ID($aldff));
+ cell->parameters[ID::CLK_POLARITY] = clk_polarity;
+ cell->parameters[ID::ALOAD_POLARITY] = aload_polarity;
+ cell->parameters[ID::WIDTH] = sig_q.size();
+ cell->setPort(ID::CLK, sig_clk);
+ cell->setPort(ID::ALOAD, sig_aload);
+ cell->setPort(ID::D, sig_d);
+ cell->setPort(ID::AD, sig_ad);
+ cell->setPort(ID::Q, sig_q);
+ cell->set_src_attribute(src);
+ return cell;
+}
+
+RTLIL::Cell* RTLIL::Module::addAldffe(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
+ const RTLIL::SigSpec &sig_ad, bool clk_polarity, bool en_polarity, bool aload_polarity, const std::string &src)
+{
+ RTLIL::Cell *cell = addCell(name, ID($aldffe));
+ cell->parameters[ID::CLK_POLARITY] = clk_polarity;
+ cell->parameters[ID::EN_POLARITY] = en_polarity;
+ cell->parameters[ID::ALOAD_POLARITY] = aload_polarity;
+ cell->parameters[ID::WIDTH] = sig_q.size();
+ cell->setPort(ID::CLK, sig_clk);
+ cell->setPort(ID::EN, sig_en);
+ cell->setPort(ID::ALOAD, sig_aload);
+ cell->setPort(ID::D, sig_d);
+ cell->setPort(ID::AD, sig_ad);
+ cell->setPort(ID::Q, sig_q);
+ cell->set_src_attribute(src);
+ return cell;
+}
+
RTLIL::Cell* RTLIL::Module::addSdff(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
RTLIL::Const srst_value, bool clk_polarity, bool srst_polarity, const std::string &src)
{
@@ -2865,6 +3023,33 @@ RTLIL::Cell* RTLIL::Module::addAdffeGate(RTLIL::IdString name, const RTLIL::SigS
return cell;
}
+RTLIL::Cell* RTLIL::Module::addAldffGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
+ const RTLIL::SigSpec &sig_ad, bool clk_polarity, bool aload_polarity, const std::string &src)
+{
+ RTLIL::Cell *cell = addCell(name, stringf("$_ALDFF_%c%c_", clk_polarity ? 'P' : 'N', aload_polarity ? 'P' : 'N'));
+ cell->setPort(ID::C, sig_clk);
+ cell->setPort(ID::L, sig_aload);
+ cell->setPort(ID::D, sig_d);
+ cell->setPort(ID::AD, sig_ad);
+ cell->setPort(ID::Q, sig_q);
+ cell->set_src_attribute(src);
+ return cell;
+}
+
+RTLIL::Cell* RTLIL::Module::addAldffeGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
+ const RTLIL::SigSpec &sig_ad, bool clk_polarity, bool en_polarity, bool aload_polarity, const std::string &src)
+{
+ RTLIL::Cell *cell = addCell(name, stringf("$_ALDFFE_%c%c%c_", clk_polarity ? 'P' : 'N', aload_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N'));
+ cell->setPort(ID::C, sig_clk);
+ cell->setPort(ID::L, sig_aload);
+ cell->setPort(ID::E, sig_en);
+ cell->setPort(ID::D, sig_d);
+ cell->setPort(ID::AD, sig_ad);
+ cell->setPort(ID::Q, sig_q);
+ cell->set_src_attribute(src);
+ return cell;
+}
+
RTLIL::Cell* RTLIL::Module::addSdffGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
bool srst_value, bool clk_polarity, bool srst_polarity, const std::string &src)
{
@@ -3214,14 +3399,21 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed)
type.begins_with("$verific$") || type.begins_with("$array:") || type.begins_with("$extern:"))
return;
- if (type == ID($mux) || type == ID($pmux)) {
+ if (type == ID($mux) || type == ID($pmux) || type == ID($bmux)) {
parameters[ID::WIDTH] = GetSize(connections_[ID::Y]);
- if (type == ID($pmux))
+ if (type != ID($mux))
parameters[ID::S_WIDTH] = GetSize(connections_[ID::S]);
check();
return;
}
+ if (type == ID($demux)) {
+ parameters[ID::WIDTH] = GetSize(connections_[ID::A]);
+ parameters[ID::S_WIDTH] = GetSize(connections_[ID::S]);
+ check();
+ return;
+ }
+
if (type == ID($lut) || type == ID($sop)) {
parameters[ID::WIDTH] = GetSize(connections_[ID::A]);
return;