diff options
Diffstat (limited to 'kernel/rtlil.cc')
-rw-r--r-- | kernel/rtlil.cc | 372 |
1 files changed, 304 insertions, 68 deletions
diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 776625b9c..9da6d2816 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -2,11 +2,11 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at> - * + * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. - * + * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR @@ -147,7 +147,7 @@ RTLIL::Const RTLIL::Const::from_string(std::string str) std::string RTLIL::Const::decode_string() const { std::string string; - std::vector <char> string_chars; + std::vector<char> string_chars; for (int i = 0; i < int (bits.size()); i += 8) { char ch = 0; for (int j = 0; j < 8 && i + j < int (bits.size()); j++) @@ -161,6 +161,46 @@ std::string RTLIL::Const::decode_string() const return string; } +void RTLIL::AttrObject::set_bool_attribute(RTLIL::IdString id) +{ + attributes[id] = RTLIL::Const(1); +} + +bool RTLIL::AttrObject::get_bool_attribute(RTLIL::IdString id) const +{ + if (attributes.count(id) == 0) + return false; + return attributes.at(id).as_bool(); +} + +void RTLIL::AttrObject::set_strpool_attribute(RTLIL::IdString id, const pool<string> &data) +{ + string attrval; + for (auto &s : data) { + if (!attrval.empty()) + attrval += "|"; + attrval += s; + } + attributes[id] = RTLIL::Const(attrval); +} + +void RTLIL::AttrObject::add_strpool_attribute(RTLIL::IdString id, const pool<string> &data) +{ + pool<string> union_data = get_strpool_attribute(id); + union_data.insert(data.begin(), data.end()); + if (!union_data.empty()) + set_strpool_attribute(id, union_data); +} + +pool<string> RTLIL::AttrObject::get_strpool_attribute(RTLIL::IdString id) const +{ + pool<string> data; + if (attributes.count(id) != 0) + for (auto s : split_tokens(attributes.at(id).decode_string(), "|")) + data.insert(s); + return data; +} + bool RTLIL::Selection::selected_module(RTLIL::IdString mod_name) const { if (full_selection) @@ -264,6 +304,8 @@ RTLIL::Design::~Design() { for (auto it = modules_.begin(); it != modules_.end(); ++it) delete it->second; + for (auto n : verilog_packages) + delete n; } RTLIL::ObjRange<RTLIL::Module*> RTLIL::Design::modules() @@ -276,6 +318,21 @@ RTLIL::Module *RTLIL::Design::module(RTLIL::IdString name) return modules_.count(name) ? modules_.at(name) : NULL; } +RTLIL::Module *RTLIL::Design::top_module() +{ + RTLIL::Module *module = nullptr; + int module_count = 0; + + for (auto mod : selected_modules()) { + if (mod->get_bool_attribute("\\top")) + return mod; + module_count++; + module = mod; + } + + return module_count == 1 ? module : nullptr; +} + void RTLIL::Design::add(RTLIL::Module *module) { log_assert(modules_.count(module->name) == 0); @@ -389,6 +446,13 @@ void RTLIL::Design::remove(RTLIL::Module *module) delete module; } +void RTLIL::Design::rename(RTLIL::Module *module, RTLIL::IdString new_name) +{ + modules_.erase(module->name); + module->name = new_name; + add(module); +} + void RTLIL::Design::sort() { scratchpad.sort(); @@ -783,6 +847,15 @@ namespace { return; } + if (cell->type == "$sop") { + param("\\DEPTH"); + param("\\TABLE"); + port("\\A", param("\\WIDTH")); + port("\\Y", 1); + check_expected(); + return; + } + if (cell->type == "$sr") { param_bool("\\SET_POLARITY"); param_bool("\\CLR_POLARITY"); @@ -885,6 +958,7 @@ namespace { param_bool("\\CLK_POLARITY"); param_bool("\\TRANSPARENT"); port("\\CLK", 1); + port("\\EN", 1); port("\\ADDR", param("\\ABITS")); port("\\DATA", param("\\WIDTH")); check_expected(); @@ -904,16 +978,27 @@ namespace { return; } + if (cell->type == "$meminit") { + param("\\MEMID"); + param("\\PRIORITY"); + port("\\ADDR", param("\\ABITS")); + port("\\DATA", param("\\WIDTH") * param("\\WORDS")); + check_expected(); + return; + } + if (cell->type == "$mem") { param("\\MEMID"); param("\\SIZE"); param("\\OFFSET"); - param_bits("\\RD_CLK_ENABLE", param("\\RD_PORTS")); - param_bits("\\RD_CLK_POLARITY", param("\\RD_PORTS")); - param_bits("\\RD_TRANSPARENT", param("\\RD_PORTS")); - param_bits("\\WR_CLK_ENABLE", param("\\WR_PORTS")); - param_bits("\\WR_CLK_POLARITY", param("\\WR_PORTS")); + param("\\INIT"); + param_bits("\\RD_CLK_ENABLE", max(1, param("\\RD_PORTS"))); + param_bits("\\RD_CLK_POLARITY", max(1, param("\\RD_PORTS"))); + param_bits("\\RD_TRANSPARENT", max(1, param("\\RD_PORTS"))); + param_bits("\\WR_CLK_ENABLE", max(1, param("\\WR_PORTS"))); + param_bits("\\WR_CLK_POLARITY", max(1, param("\\WR_PORTS"))); port("\\RD_CLK", param("\\RD_PORTS")); + port("\\RD_EN", param("\\RD_PORTS")); port("\\RD_ADDR", param("\\RD_PORTS") * param("\\ABITS")); port("\\RD_DATA", param("\\RD_PORTS") * param("\\WIDTH")); port("\\WR_CLK", param("\\WR_PORTS")); @@ -924,6 +1009,14 @@ namespace { return; } + if (cell->type == "$tribuf") { + port("\\A", param("\\WIDTH")); + port("\\Y", param("\\WIDTH")); + port("\\EN", 1); + check_expected(); + return; + } + if (cell->type == "$assert") { port("\\A", 1); port("\\EN", 1); @@ -931,6 +1024,13 @@ namespace { return; } + if (cell->type == "$assume") { + port("\\A", 1); + port("\\EN", 1); + check_expected(); + return; + } + if (cell->type == "$equiv") { port("\\A", 1); port("\\B", 1); @@ -953,6 +1053,12 @@ namespace { if (cell->type == "$_AOI4_") { check_gate("ABCDY"); return; } if (cell->type == "$_OAI4_") { check_gate("ABCDY"); return; } + if (cell->type == "$_TBUF_") { check_gate("AYE"); return; } + + if (cell->type == "$_MUX4_") { check_gate("ABCDSTY"); return; } + if (cell->type == "$_MUX8_") { check_gate("ABCDEFGHSTUY"); return; } + if (cell->type == "$_MUX16_") { check_gate("ABCDEFGHIJKLMNOPSTUVY"); return; } + if (cell->type == "$_SR_NN_") { check_gate("SRQ"); return; } if (cell->type == "$_SR_NP_") { check_gate("SRQ"); return; } if (cell->type == "$_SR_PN_") { check_gate("SRQ"); return; } @@ -1097,6 +1203,8 @@ void RTLIL::Module::cloneInto(RTLIL::Module *new_mod) const log_assert(new_mod->refcount_wires_ == 0); log_assert(new_mod->refcount_cells_ == 0); + new_mod->avail_parameters = avail_parameters; + for (auto &conn : connections_) new_mod->connect(conn); @@ -1351,6 +1459,19 @@ void RTLIL::Module::connect(const RTLIL::SigSig &conn) for (auto mon : design->monitors) mon->notify_connect(this, conn); + // ignore all attempts to assign constants to other constants + if (conn.first.has_const()) { + RTLIL::SigSig new_conn; + for (int i = 0; i < GetSize(conn.first); i++) + if (conn.first[i].wire) { + new_conn.first.append(conn.first[i]); + new_conn.second.append(conn.second[i]); + } + if (GetSize(new_conn.first)) + connect(new_conn); + return; + } + if (yosys_xtrace) { log("#X# Connect (SigSig) in %s: %s = %s (%d bits)\n", log_id(this), log_signal(conn.first), log_signal(conn.second), GetSize(conn.first)); log_backtrace("-X- ", yosys_xtrace-1); @@ -1491,10 +1612,10 @@ DEF_METHOD(LogicNot, 1, "$logic_not") add ## _func(name, sig_a, sig_b, sig_y, is_signed); \ return sig_y; \ } -DEF_METHOD(And, std::max(sig_a.size(), sig_b.size()), "$and") -DEF_METHOD(Or, std::max(sig_a.size(), sig_b.size()), "$or") -DEF_METHOD(Xor, std::max(sig_a.size(), sig_b.size()), "$xor") -DEF_METHOD(Xnor, std::max(sig_a.size(), sig_b.size()), "$xnor") +DEF_METHOD(And, max(sig_a.size(), sig_b.size()), "$and") +DEF_METHOD(Or, max(sig_a.size(), sig_b.size()), "$or") +DEF_METHOD(Xor, max(sig_a.size(), sig_b.size()), "$xor") +DEF_METHOD(Xnor, max(sig_a.size(), sig_b.size()), "$xnor") DEF_METHOD(Shl, sig_a.size(), "$shl") DEF_METHOD(Shr, sig_a.size(), "$shr") DEF_METHOD(Sshl, sig_a.size(), "$sshl") @@ -1509,11 +1630,11 @@ DEF_METHOD(Eqx, 1, "$eqx") DEF_METHOD(Nex, 1, "$nex") DEF_METHOD(Ge, 1, "$ge") DEF_METHOD(Gt, 1, "$gt") -DEF_METHOD(Add, std::max(sig_a.size(), sig_b.size()), "$add") -DEF_METHOD(Sub, std::max(sig_a.size(), sig_b.size()), "$sub") -DEF_METHOD(Mul, std::max(sig_a.size(), sig_b.size()), "$mul") -DEF_METHOD(Div, std::max(sig_a.size(), sig_b.size()), "$div") -DEF_METHOD(Mod, std::max(sig_a.size(), sig_b.size()), "$mod") +DEF_METHOD(Add, max(sig_a.size(), sig_b.size()), "$add") +DEF_METHOD(Sub, max(sig_a.size(), sig_b.size()), "$sub") +DEF_METHOD(Mul, max(sig_a.size(), sig_b.size()), "$mul") +DEF_METHOD(Div, max(sig_a.size(), sig_b.size()), "$div") +DEF_METHOD(Mod, max(sig_a.size(), sig_b.size()), "$mod") DEF_METHOD(LogicAnd, 1, "$logic_and") DEF_METHOD(LogicOr, 1, "$logic_or") #undef DEF_METHOD @@ -1592,6 +1713,7 @@ DEF_METHOD(Pmux, "$pmux", 1) add ## _func(name, sig1, sig2, sig3, sig4, sig5); \ return sig5; \ } +DEF_METHOD_2(BufGate, "$_BUF_", A, Y) DEF_METHOD_2(NotGate, "$_NOT_", A, Y) DEF_METHOD_3(AndGate, "$_AND_", A, B, Y) DEF_METHOD_3(NandGate, "$_NAND_", A, B, Y) @@ -1645,13 +1767,23 @@ RTLIL::Cell* RTLIL::Module::addConcat(RTLIL::IdString name, RTLIL::SigSpec sig_a return cell; } -RTLIL::Cell* RTLIL::Module::addLut(RTLIL::IdString name, RTLIL::SigSpec sig_i, RTLIL::SigSpec sig_o, RTLIL::Const lut) +RTLIL::Cell* RTLIL::Module::addLut(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, RTLIL::Const lut) { RTLIL::Cell *cell = addCell(name, "$lut"); cell->parameters["\\LUT"] = lut; - cell->parameters["\\WIDTH"] = sig_i.size(); - cell->setPort("\\A", sig_i); - cell->setPort("\\Y", sig_o); + cell->parameters["\\WIDTH"] = sig_a.size(); + cell->setPort("\\A", sig_a); + cell->setPort("\\Y", sig_y); + return cell; +} + +RTLIL::Cell* RTLIL::Module::addTribuf(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_y) +{ + RTLIL::Cell *cell = addCell(name, "$tribuf"); + cell->parameters["\\WIDTH"] = sig_a.size(); + cell->setPort("\\A", sig_a); + cell->setPort("\\EN", sig_en); + cell->setPort("\\Y", sig_y); return cell; } @@ -2012,7 +2144,7 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed) return; } - if (type == "$lut") { + if (type == "$lut" || type == "$sop") { parameters["\\WIDTH"] = GetSize(connections_["\\A"]); return; } @@ -2453,8 +2585,18 @@ void RTLIL::SigSpec::sort() void RTLIL::SigSpec::sort_and_unify() { + unpack(); cover("kernel.rtlil.sigspec.sort_and_unify"); - *this = this->to_sigbit_set(); + + // A copy of the bits vector is used to prevent duplicating the logic from + // SigSpec::SigSpec(std::vector<SigBit>). This incurrs an extra copy but + // that isn't showing up as significant in profiles. + std::vector<SigBit> unique_bits = bits_; + std::sort(unique_bits.begin(), unique_bits.end()); + auto last = std::unique(unique_bits.begin(), unique_bits.end()); + unique_bits.erase(last, unique_bits.end()); + + *this = unique_bits; } void RTLIL::SigSpec::replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with) @@ -2464,18 +2606,26 @@ void RTLIL::SigSpec::replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec void RTLIL::SigSpec::replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with, RTLIL::SigSpec *other) const { + log_assert(other != NULL); + log_assert(width_ == other->width_); log_assert(pattern.width_ == with.width_); pattern.unpack(); with.unpack(); + unpack(); + other->unpack(); - dict<RTLIL::SigBit, RTLIL::SigBit> rules; - - for (int i = 0; i < GetSize(pattern.bits_); i++) - if (pattern.bits_[i].wire != NULL) - rules[pattern.bits_[i]] = with.bits_[i]; + for (int i = 0; i < GetSize(pattern.bits_); i++) { + if (pattern.bits_[i].wire != NULL) { + for (int j = 0; j < GetSize(bits_); j++) { + if (bits_[j] == pattern.bits_[i]) { + other->bits_[j] = with.bits_[i]; + } + } + } + } - replace(rules, other); + other->check(); } void RTLIL::SigSpec::replace(const dict<RTLIL::SigBit, RTLIL::SigBit> &rules) @@ -2539,8 +2689,35 @@ void RTLIL::SigSpec::remove(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other void RTLIL::SigSpec::remove2(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other) { - pool<RTLIL::SigBit> pattern_bits = pattern.to_sigbit_pool(); - remove2(pattern_bits, other); + if (other) + cover("kernel.rtlil.sigspec.remove_other"); + else + cover("kernel.rtlil.sigspec.remove"); + + unpack(); + if (other != NULL) { + log_assert(width_ == other->width_); + other->unpack(); + } + + for (int i = GetSize(bits_) - 1; i >= 0; i--) { + if (bits_[i].wire == NULL) continue; + + for (auto &pattern_chunk : pattern.chunks()) { + if (bits_[i].wire == pattern_chunk.wire && + bits_[i].offset >= pattern_chunk.offset && + bits_[i].offset < pattern_chunk.offset + pattern_chunk.width) { + bits_.erase(bits_.begin() + i); + width_--; + if (other != NULL) { + other->bits_.erase(other->bits_.begin() + i); + other->width_--; + } + } + } + } + + check(); } void RTLIL::SigSpec::remove(const pool<RTLIL::SigBit> &pattern) @@ -2568,31 +2745,43 @@ void RTLIL::SigSpec::remove2(const pool<RTLIL::SigBit> &pattern, RTLIL::SigSpec other->unpack(); } - std::vector<RTLIL::SigBit> new_bits, new_other_bits; - - new_bits.resize(GetSize(bits_)); - if (other != NULL) - new_other_bits.resize(GetSize(bits_)); - - int k = 0; - for (int i = 0; i < GetSize(bits_); i++) { - if (bits_[i].wire != NULL && pattern.count(bits_[i])) - continue; - if (other != NULL) - new_other_bits[k] = other->bits_[i]; - new_bits[k++] = bits_[i]; + for (int i = GetSize(bits_) - 1; i >= 0; i--) { + if (bits_[i].wire != NULL && pattern.count(bits_[i])) { + bits_.erase(bits_.begin() + i); + width_--; + if (other != NULL) { + other->bits_.erase(other->bits_.begin() + i); + other->width_--; + } + } } - new_bits.resize(k); - if (other != NULL) - new_other_bits.resize(k); + check(); +} - bits_.swap(new_bits); - width_ = GetSize(bits_); +void RTLIL::SigSpec::remove2(const std::set<RTLIL::SigBit> &pattern, RTLIL::SigSpec *other) +{ + if (other) + cover("kernel.rtlil.sigspec.remove_other"); + else + cover("kernel.rtlil.sigspec.remove"); + + unpack(); if (other != NULL) { - other->bits_.swap(new_other_bits); - other->width_ = GetSize(other->bits_); + log_assert(width_ == other->width_); + other->unpack(); + } + + for (int i = GetSize(bits_) - 1; i >= 0; i--) { + if (bits_[i].wire != NULL && pattern.count(bits_[i])) { + bits_.erase(bits_.begin() + i); + width_--; + if (other != NULL) { + other->bits_.erase(other->bits_.begin() + i); + other->width_--; + } + } } check(); @@ -2600,8 +2789,37 @@ void RTLIL::SigSpec::remove2(const pool<RTLIL::SigBit> &pattern, RTLIL::SigSpec RTLIL::SigSpec RTLIL::SigSpec::extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other) const { - pool<RTLIL::SigBit> pattern_bits = pattern.to_sigbit_pool(); - return extract(pattern_bits, other); + if (other) + cover("kernel.rtlil.sigspec.extract_other"); + else + cover("kernel.rtlil.sigspec.extract"); + + log_assert(other == NULL || width_ == other->width_); + + RTLIL::SigSpec ret; + std::vector<RTLIL::SigBit> bits_match = to_sigbit_vector(); + + for (auto& pattern_chunk : pattern.chunks()) { + if (other) { + std::vector<RTLIL::SigBit> bits_other = other->to_sigbit_vector(); + for (int i = 0; i < width_; i++) + if (bits_match[i].wire && + bits_match[i].wire == pattern_chunk.wire && + bits_match[i].offset >= pattern_chunk.offset && + bits_match[i].offset < pattern_chunk.offset + pattern_chunk.width) + ret.append_bit(bits_other[i]); + } else { + for (int i = 0; i < width_; i++) + if (bits_match[i].wire && + bits_match[i].wire == pattern_chunk.wire && + bits_match[i].offset >= pattern_chunk.offset && + bits_match[i].offset < pattern_chunk.offset + pattern_chunk.width) + ret.append_bit(bits_match[i]); + } + } + + ret.check(); + return ret; } RTLIL::SigSpec RTLIL::SigSpec::extract(const pool<RTLIL::SigBit> &pattern, const RTLIL::SigSpec *other) const @@ -2785,7 +3003,7 @@ void RTLIL::SigSpec::extend_u0(int width, bool is_signed) if (width_ > width) remove(width, width_ - width); - + if (width_ < width) { RTLIL::SigBit padding = width_ > 0 ? (*this)[width_ - 1] : RTLIL::State::S0; if (!is_signed) @@ -2939,6 +3157,21 @@ bool RTLIL::SigSpec::is_fully_const() const return true; } +bool RTLIL::SigSpec::is_fully_zero() const +{ + cover("kernel.rtlil.sigspec.is_fully_zero"); + + pack(); + for (auto it = chunks_.begin(); it != chunks_.end(); it++) { + if (it->width > 0 && it->wire != NULL) + return false; + for (size_t i = 0; i < it->data.size(); i++) + if (it->data[i] != RTLIL::State::S0) + return false; + } + return true; +} + bool RTLIL::SigSpec::is_fully_def() const { cover("kernel.rtlil.sigspec.is_fully_def"); @@ -3062,6 +3295,17 @@ RTLIL::SigChunk RTLIL::SigSpec::as_chunk() const return chunks_[0]; } +RTLIL::SigBit RTLIL::SigSpec::as_bit() const +{ + cover("kernel.rtlil.sigspec.as_bit"); + + log_assert(width_ == 1); + if (packed()) + return RTLIL::SigBit(*chunks_.begin()); + else + return bits_[0]; +} + bool RTLIL::SigSpec::match(std::string pattern) const { cover("kernel.rtlil.sigspec.match"); @@ -3149,18 +3393,6 @@ dict<RTLIL::SigBit, RTLIL::SigBit> RTLIL::SigSpec::to_sigbit_dict(const RTLIL::S return new_map; } -RTLIL::SigBit RTLIL::SigSpec::to_single_sigbit() const -{ - cover("kernel.rtlil.sigspec.to_single_sigbit"); - - pack(); - log_assert(width_ == 1); - for (auto &c : chunks_) - if (c.width) - return RTLIL::SigBit(c); - log_abort(); -} - static void sigspec_parse_split(std::vector<std::string> &tokens, const std::string &text, char sep) { size_t start = 0, end = 0; @@ -3180,6 +3412,10 @@ bool RTLIL::SigSpec::parse(RTLIL::SigSpec &sig, RTLIL::Module *module, std::stri { cover("kernel.rtlil.sigspec.parse"); + AST::current_filename = "input"; + AST::use_internal_line_num(); + AST::set_line_num(0); + std::vector<std::string> tokens; sigspec_parse_split(tokens, str, ','); @@ -3339,7 +3575,7 @@ RTLIL::SwitchRule *RTLIL::SwitchRule::clone() const for (auto &it : cases) new_switchrule->cases.push_back(it->clone()); return new_switchrule; - + } RTLIL::SyncRule *RTLIL::SyncRule::clone() const @@ -3371,7 +3607,7 @@ RTLIL::Process *RTLIL::Process::clone() const for (auto &it : syncs) new_proc->syncs.push_back(it->clone()); - + return new_proc; } |