diff options
author | Eddie Hung <eddie@fpgeh.com> | 2019-06-12 08:50:39 -0700 |
---|---|---|
committer | Eddie Hung <eddie@fpgeh.com> | 2019-06-12 08:50:39 -0700 |
commit | f7a9769c140f6a56e51d7384dfd8e76bf2aef66d (patch) | |
tree | 4be49b8b30a03ac7d4deafaa7318de275d5c3a7f /backends | |
parent | ac2aff9e28a087a9a2697cd6ccf754af738903a7 (diff) | |
parent | a91ea6612a73568782c80bd12ce2875353e2b5c5 (diff) | |
download | yosys-f7a9769c140f6a56e51d7384dfd8e76bf2aef66d.tar.gz yosys-f7a9769c140f6a56e51d7384dfd8e76bf2aef66d.tar.bz2 yosys-f7a9769c140f6a56e51d7384dfd8e76bf2aef66d.zip |
Merge remote-tracking branch 'origin/master' into xaig
Diffstat (limited to 'backends')
-rw-r--r-- | backends/blif/blif.cc | 26 | ||||
-rw-r--r-- | backends/btor/btor.cc | 8 | ||||
-rw-r--r-- | backends/firrtl/firrtl.cc | 100 | ||||
-rw-r--r-- | backends/ilang/ilang_backend.cc | 5 | ||||
-rw-r--r-- | backends/verilog/verilog_backend.cc | 132 |
5 files changed, 225 insertions, 46 deletions
diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc index b6dbd84cb..a1761b662 100644 --- a/backends/blif/blif.cc +++ b/backends/blif/blif.cc @@ -409,12 +409,26 @@ struct BlifDumper f << stringf(".%s %s", subckt_or_gate(cell->type.str()), cstr(cell->type)); for (auto &conn : cell->connections()) - for (int i = 0; i < conn.second.size(); i++) { - if (conn.second.size() == 1) - f << stringf(" %s", cstr(conn.first)); - else - f << stringf(" %s[%d]", cstr(conn.first), i); - f << stringf("=%s", cstr(conn.second.extract(i, 1))); + { + if (conn.second.size() == 1) { + f << stringf(" %s=%s", cstr(conn.first), cstr(conn.second[0])); + continue; + } + + Module *m = design->module(cell->type); + Wire *w = m ? m->wire(conn.first) : nullptr; + + if (w == nullptr) { + for (int i = 0; i < GetSize(conn.second); i++) + f << stringf(" %s[%d]=%s", cstr(conn.first), i, cstr(conn.second[i])); + } else { + for (int i = 0; i < std::min(GetSize(conn.second), GetSize(w)); i++) { + SigBit sig(w, i); + f << stringf(" %s[%d]=%s", cstr(conn.first), sig.wire->upto ? + sig.wire->start_offset+sig.wire->width-sig.offset-1 : + sig.wire->start_offset+sig.offset, cstr(conn.second[i])); + } + } } f << stringf("\n"); diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 91f238fa5..511a11942 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -129,7 +129,13 @@ struct BtorWorker void export_cell(Cell *cell) { - log_assert(cell_recursion_guard.count(cell) == 0); + if (cell_recursion_guard.count(cell)) { + string cell_list; + for (auto c : cell_recursion_guard) + cell_list += stringf("\n %s", log_id(c)); + log_error("Found topological loop while processing cell %s. Active cells:%s\n", log_id(cell), cell_list.c_str()); + } + cell_recursion_guard.insert(cell); btorf_push(log_id(cell)); diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index ed6e9f8ee..1c7a7351f 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -146,7 +146,7 @@ struct FirrtlWorker if (!mask.is_fully_def()) this->ena = SigSpec(RTLIL::Const(1)); } - string gen_read(const char * /* indent */) { + string gen_read(const char * /* indent */) { log_error("gen_read called on write_port: %s\n", name.c_str()); return stringf("gen_read called on write_port: %s\n", name.c_str()); } @@ -163,31 +163,61 @@ struct FirrtlWorker } }; /* Memories defined within this module. */ - struct memory { - string name; // memory name - int abits; // number of address bits - int size; // size (in units) of the memory - int width; // size (in bits) of each element - int read_latency; - int write_latency; - vector<read_port> read_ports; - vector<write_port> write_ports; - std::string init_file; - std::string init_file_srcFileSpec; - memory(string name, int abits, int size, int width) : name(name), abits(abits), size(size), width(width), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec("") {} - memory() : read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec(""){} - void add_memory_read_port(read_port &rp) { - read_ports.push_back(rp); - } - void add_memory_write_port(write_port &wp) { - write_ports.push_back(wp); - } - void add_memory_file(std::string init_file, std::string init_file_srcFileSpec) { - this->init_file = init_file; - this->init_file_srcFileSpec = init_file_srcFileSpec; + struct memory { + Cell *pCell; // for error reporting + string name; // memory name + int abits; // number of address bits + int size; // size (in units) of the memory + int width; // size (in bits) of each element + int read_latency; + int write_latency; + vector<read_port> read_ports; + vector<write_port> write_ports; + std::string init_file; + std::string init_file_srcFileSpec; + string srcLine; + memory(Cell *pCell, string name, int abits, int size, int width) : pCell(pCell), name(name), abits(abits), size(size), width(width), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec("") { + // Provide defaults for abits or size if one (but not the other) is specified. + if (this->abits == 0 && this->size != 0) { + this->abits = ceil_log2(this->size); + } else if (this->abits != 0 && this->size == 0) { + this->size = 1 << this->abits; + } + // Sanity-check this construction. + if (this->name == "") { + log_error("Nameless memory%s\n", this->atLine()); + } + if (this->abits == 0 && this->size == 0) { + log_error("Memory %s has zero address bits and size%s\n", this->name.c_str(), this->atLine()); + } + if (this->width == 0) { + log_error("Memory %s has zero width%s\n", this->name.c_str(), this->atLine()); + } } + // We need a default constructor for the dict insert. + memory() : pCell(0), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec(""){} + + const char *atLine() { + if (srcLine == "") { + if (pCell) { + auto p = pCell->attributes.find("\\src"); + srcLine = " at " + p->second.decode_string(); + } + } + return srcLine.c_str(); + } + void add_memory_read_port(read_port &rp) { + read_ports.push_back(rp); + } + void add_memory_write_port(write_port &wp) { + write_ports.push_back(wp); + } + void add_memory_file(std::string init_file, std::string init_file_srcFileSpec) { + this->init_file = init_file; + this->init_file_srcFileSpec = init_file_srcFileSpec; + } - }; + }; dict<string, memory> memories; void register_memory(memory &m) @@ -314,6 +344,7 @@ struct FirrtlWorker switch (dir) { case FD_INOUT: log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", cell_type.c_str(), log_signal(it->second)); + /* FALLTHRU */ case FD_OUT: sourceExpr = firstName; sinkExpr = secondExpr; @@ -321,7 +352,7 @@ struct FirrtlWorker break; case FD_NODIRECTION: log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", cell_type.c_str(), log_signal(it->second)); - /* FALL_THROUGH */ + /* FALLTHRU */ case FD_IN: sourceExpr = secondExpr; sinkExpr = firstName; @@ -418,8 +449,10 @@ struct FirrtlWorker string primop; bool always_uint = false; if (cell->type == "$not") primop = "not"; - else if (cell->type == "$neg") primop = "neg"; - else if (cell->type == "$logic_not") { + else if (cell->type == "$neg") { + primop = "neg"; + is_signed = true; // Result of "neg" is signed (an SInt). + } else if (cell->type == "$logic_not") { primop = "eq"; a_expr = stringf("%s, UInt(0)", a_expr.c_str()); } @@ -531,6 +564,7 @@ struct FirrtlWorker auto b_sig = cell->getPort("\\B"); if (b_sig.is_fully_const()) { primop = "shl"; + b_expr = std::to_string(b_sig.as_int()); } else { primop = "dshl"; // Convert from FIRRTL left shift semantics. @@ -544,6 +578,7 @@ struct FirrtlWorker auto b_sig = cell->getPort("\\B"); if (b_sig.is_fully_const()) { primop = "shr"; + b_expr = std::to_string(b_sig.as_int()); } else { primop = "dshr"; } @@ -604,7 +639,7 @@ struct FirrtlWorker int abits = cell->parameters.at("\\ABITS").as_int(); int width = cell->parameters.at("\\WIDTH").as_int(); int size = cell->parameters.at("\\SIZE").as_int(); - memory m(mem_id, abits, size, width); + memory m(cell, mem_id, abits, size, width); int rd_ports = cell->parameters.at("\\RD_PORTS").as_int(); int wr_ports = cell->parameters.at("\\WR_PORTS").as_int(); @@ -681,6 +716,8 @@ struct FirrtlWorker { std::string cell_type = fid(cell->type); std::string mem_id = make_id(cell->parameters["\\MEMID"].decode_string()); + int abits = cell->parameters.at("\\ABITS").as_int(); + int width = cell->parameters.at("\\WIDTH").as_int(); memory *mp = nullptr; if (cell->type == "$meminit" ) { log_error("$meminit (%s.%s.%s) currently unsupported\n", log_id(module), log_id(cell), mem_id.c_str()); @@ -693,6 +730,11 @@ struct FirrtlWorker Const clk_enable = cell->parameters.at("\\CLK_ENABLE"); Const clk_polarity = cell->parameters.at("\\CLK_POLARITY"); + // Do we already have an entry for this memory? + if (memories.count(mem_id) == 0) { + memory m(cell, mem_id, abits, 0, width); + register_memory(m); + } mp = &memories.at(mem_id); int portNum = 0; bool transparency = false; @@ -890,7 +932,7 @@ struct FirrtlWorker // If we have any memory definitions, output them. for (auto kv : memories) { - memory m = kv.second; + memory &m = kv.second; f << stringf(" mem %s:\n", m.name.c_str()); f << stringf(" data-type => UInt<%d>\n", m.width); f << stringf(" depth => %d\n", m.size); diff --git a/backends/ilang/ilang_backend.cc b/backends/ilang/ilang_backend.cc index dc39e5e08..04d1ee311 100644 --- a/backends/ilang/ilang_backend.cc +++ b/backends/ilang/ilang_backend.cc @@ -160,7 +160,10 @@ void ILANG_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL:: } f << stringf("%s" "cell %s %s\n", indent.c_str(), cell->type.c_str(), cell->name.c_str()); for (auto &it : cell->parameters) { - f << stringf("%s parameter%s %s ", indent.c_str(), (it.second.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "", it.first.c_str()); + f << stringf("%s parameter%s%s %s ", indent.c_str(), + (it.second.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "", + (it.second.flags & RTLIL::CONST_FLAG_REAL) != 0 ? " real" : "", + it.first.c_str()); dump_const(f, it.second); f << stringf("\n"); } diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 9967482d6..827af5d85 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -183,8 +183,9 @@ bool is_reg_wire(RTLIL::SigSpec sig, std::string ®_name) return true; } -void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int offset = 0, bool no_decimal = false, bool set_signed = false, bool escape_comment = false) +void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int offset = 0, bool no_decimal = false, bool escape_comment = false) { + bool set_signed = (data.flags & RTLIL::CONST_FLAG_SIGNED) != 0; if (width < 0) width = data.bits.size() - offset; if (width == 0) { @@ -275,7 +276,8 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o } } } else { - f << stringf("\""); + if ((data.flags & RTLIL::CONST_FLAG_REAL) == 0) + f << stringf("\""); std::string str = data.decode_string(); for (size_t i = 0; i < str.size(); i++) { if (str[i] == '\n') @@ -293,7 +295,8 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o else f << str[i]; } - f << stringf("\""); + if ((data.flags & RTLIL::CONST_FLAG_REAL) == 0) + f << stringf("\""); } } @@ -373,7 +376,7 @@ void dump_attributes(std::ostream &f, std::string indent, dict<RTLIL::IdString, else if (modattr && (it->second == Const(1, 1) || it->second == Const(1))) f << stringf(" 1 "); else - dump_const(f, it->second, -1, 0, false, false, attr2comment); + dump_const(f, it->second, -1, 0, false, attr2comment); f << stringf(" %s%c", attr2comment ? "*/" : "*)", term); } } @@ -1242,6 +1245,118 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) return true; } + if (cell->type.in("$assert", "$assume", "$cover")) + { + f << stringf("%s" "always @* if (", indent.c_str()); + dump_sigspec(f, cell->getPort("\\EN")); + f << stringf(") %s(", cell->type.c_str()+1); + dump_sigspec(f, cell->getPort("\\A")); + f << stringf(");\n"); + return true; + } + + if (cell->type.in("$specify2", "$specify3")) + { + f << stringf("%s" "specify\n%s ", indent.c_str(), indent.c_str()); + + SigSpec en = cell->getPort("\\EN"); + if (en != State::S1) { + f << stringf("if ("); + dump_sigspec(f, cell->getPort("\\EN")); + f << stringf(") "); + } + + f << "("; + if (cell->type == "$specify3" && cell->getParam("\\EDGE_EN").as_bool()) + f << (cell->getParam("\\EDGE_POL").as_bool() ? "posedge ": "negedge "); + + dump_sigspec(f, cell->getPort("\\SRC")); + + f << " "; + if (cell->getParam("\\SRC_DST_PEN").as_bool()) + f << (cell->getParam("\\SRC_DST_POL").as_bool() ? "+": "-"); + f << (cell->getParam("\\FULL").as_bool() ? "*> ": "=> "); + + if (cell->type == "$specify3") { + f << "("; + dump_sigspec(f, cell->getPort("\\DST")); + f << " "; + if (cell->getParam("\\DAT_DST_PEN").as_bool()) + f << (cell->getParam("\\DAT_DST_POL").as_bool() ? "+": "-"); + f << ": "; + dump_sigspec(f, cell->getPort("\\DAT")); + f << ")"; + } else { + dump_sigspec(f, cell->getPort("\\DST")); + } + + bool bak_decimal = decimal; + decimal = 1; + + f << ") = ("; + dump_const(f, cell->getParam("\\T_RISE_MIN")); + f << ":"; + dump_const(f, cell->getParam("\\T_RISE_TYP")); + f << ":"; + dump_const(f, cell->getParam("\\T_RISE_MAX")); + f << ", "; + dump_const(f, cell->getParam("\\T_FALL_MIN")); + f << ":"; + dump_const(f, cell->getParam("\\T_FALL_TYP")); + f << ":"; + dump_const(f, cell->getParam("\\T_FALL_MAX")); + f << ");\n"; + + decimal = bak_decimal; + + f << stringf("%s" "endspecify\n", indent.c_str()); + return true; + } + + if (cell->type == "$specrule") + { + f << stringf("%s" "specify\n%s ", indent.c_str(), indent.c_str()); + + string spec_type = cell->getParam("\\TYPE").decode_string(); + f << stringf("%s(", spec_type.c_str()); + + if (cell->getParam("\\SRC_PEN").as_bool()) + f << (cell->getParam("\\SRC_POL").as_bool() ? "posedge ": "negedge "); + dump_sigspec(f, cell->getPort("\\SRC")); + + if (cell->getPort("\\SRC_EN") != State::S1) { + f << " &&& "; + dump_sigspec(f, cell->getPort("\\SRC_EN")); + } + + f << ", "; + if (cell->getParam("\\DST_PEN").as_bool()) + f << (cell->getParam("\\DST_POL").as_bool() ? "posedge ": "negedge "); + dump_sigspec(f, cell->getPort("\\DST")); + + if (cell->getPort("\\DST_EN") != State::S1) { + f << " &&& "; + dump_sigspec(f, cell->getPort("\\DST_EN")); + } + + bool bak_decimal = decimal; + decimal = 1; + + f << ", "; + dump_const(f, cell->getParam("\\T_LIMIT")); + + if (spec_type == "$setuphold" || spec_type == "$recrem" || spec_type == "$fullskew") { + f << ", "; + dump_const(f, cell->getParam("\\T_LIMIT2")); + } + + f << ");\n"; + decimal = bak_decimal; + + f << stringf("%s" "endspecify\n", indent.c_str()); + return true; + } + // FIXME: $_SR_[PN][PN]_, $_DLATCH_[PN]_, $_DLATCHSR_[PN][PN][PN]_ // FIXME: $sr, $dlatch, $memrd, $memwr, $fsm @@ -1264,8 +1379,7 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) if (it != cell->parameters.begin()) f << stringf(","); f << stringf("\n%s .%s(", indent.c_str(), id(it->first).c_str()); - bool is_signed = (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0; - dump_const(f, it->second, -1, 0, false, is_signed); + dump_const(f, it->second); f << stringf(")"); } f << stringf("\n%s" ")", indent.c_str()); @@ -1312,8 +1426,7 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) if (defparam && cell->parameters.size() > 0) { for (auto it = cell->parameters.begin(); it != cell->parameters.end(); ++it) { f << stringf("%sdefparam %s.%s = ", indent.c_str(), cell_name.c_str(), id(it->first).c_str()); - bool is_signed = (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0; - dump_const(f, it->second, -1, 0, false, is_signed); + dump_const(f, it->second); f << stringf(";\n"); } } @@ -1505,7 +1618,8 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) SigSpec sig = active_sigmap(wire); Const val = wire->attributes.at("\\init"); for (int i = 0; i < GetSize(sig) && i < GetSize(val); i++) - active_initdata[sig[i]] = val.bits.at(i); + if (val[i] == State::S0 || val[i] == State::S1) + active_initdata[sig[i]] = val[i]; } if (!module->processes.empty()) |