From bdce9c28c2078077f279999bfa31f5adc5157774 Mon Sep 17 00:00:00 2001 From: Sahand Kashani Date: Wed, 18 Mar 2020 23:38:36 +0100 Subject: [PATCH 01/13] Add fileinfo to firrtl backend for top-level circuit --- backends/firrtl/firrtl.cc | 63 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 22aa686a7..56a464b1e 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -42,6 +42,60 @@ static const FDirection FD_OUT = 0x2; static const FDirection FD_INOUT = 0x3; static const int FIRRTL_MAX_DSH_WIDTH_ERROR = 20; // For historic reasons, this is actually one greater than the maximum allowed shift width +// Shamelessly copied from ilang_backend.cc. Something better is surely possible here. +void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int offset = 0, bool autoint = true) +{ + if (width < 0) + width = data.bits.size() - offset; + if ((data.flags & RTLIL::CONST_FLAG_STRING) == 0 || width != (int)data.bits.size()) { + if (width == 32 && autoint) { + int32_t val = 0; + for (int i = 0; i < width; i++) { + log_assert(offset+i < (int)data.bits.size()); + switch (data.bits[offset+i]) { + case RTLIL::S0: break; + case RTLIL::S1: val |= 1 << i; break; + default: val = -1; break; + } + } + if (val >= 0) { + f << stringf("%d", val); + return; + } + } + f << stringf("%d'", width); + for (int i = offset+width-1; i >= offset; i--) { + log_assert(i < (int)data.bits.size()); + switch (data.bits[i]) { + case RTLIL::S0: f << stringf("0"); break; + case RTLIL::S1: f << stringf("1"); break; + case RTLIL::Sx: f << stringf("x"); break; + case RTLIL::Sz: f << stringf("z"); break; + case RTLIL::Sa: f << stringf("-"); break; + case RTLIL::Sm: f << stringf("m"); break; + } + } + } else { + f << stringf("\""); + std::string str = data.decode_string(); + for (size_t i = 0; i < str.size(); i++) { + if (str[i] == '\n') + f << stringf("\\n"); + else if (str[i] == '\t') + f << stringf("\\t"); + else if (str[i] < 32) + f << stringf("\\%03o", str[i]); + else if (str[i] == '"') + f << stringf("\\\""); + else if (str[i] == '\\') + f << stringf("\\\\"); + else + f << str[i]; + } + f << stringf("\""); + } +} + // Get a port direction with respect to a specific module. FDirection getPortFDirection(IdString id, Module *module) { @@ -1123,7 +1177,14 @@ struct FirrtlBackend : public Backend { if (top == nullptr) top = last; - *f << stringf("circuit %s:\n", make_id(top->name)); + std::ostringstream fileinfo; + for (auto &it : top->attributes) { + if (it.first == "\\src") { + dump_const(fileinfo, it.second); + } + } + + *f << stringf("circuit %s: @[%s]\n", make_id(top->name), fileinfo.str().c_str()); for (auto module : design->modules()) { From 59236314f80b68126ca7ec81cca3ce1bf36a384b Mon Sep 17 00:00:00 2001 From: Sahand Kashani Date: Thu, 19 Mar 2020 14:59:05 +0100 Subject: [PATCH 02/13] Add fileinfo to firrtl backend for modules and wires --- backends/firrtl/firrtl.cc | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 56a464b1e..30b99fd91 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -96,6 +96,17 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o } } +std::string getFileinfo(dict attributes) +{ + std::ostringstream fileinfo; + for (auto &it : attributes) { + if (it.first == "\\src") { + dump_const(fileinfo, it.second); + } + } + return fileinfo.str(); +} + // Get a port direction with respect to a specific module. FDirection getPortFDirection(IdString id, Module *module) { @@ -448,12 +459,15 @@ struct FirrtlWorker void run() { - f << stringf(" module %s:\n", make_id(module->name)); + auto moduleFileinfo = getFileinfo(module->attributes); + f << stringf(" module %s: @[%s]\n", make_id(module->name), moduleFileinfo.c_str()); vector port_decls, wire_decls, cell_exprs, wire_exprs; for (auto wire : module->wires()) { const auto wireName = make_id(wire->name); + auto wireFileinfo = getFileinfo(wire->attributes); + // If a wire has initial data, issue a warning since FIRRTL doesn't currently support it. if (wire->attributes.count("\\init")) { log_warning("Initial value (%s) for (%s.%s) not supported\n", @@ -464,12 +478,12 @@ struct FirrtlWorker { if (wire->port_input && wire->port_output) log_error("Module port %s.%s is inout!\n", log_id(module), log_id(wire)); - port_decls.push_back(stringf(" %s %s: UInt<%d>\n", wire->port_input ? "input" : "output", - wireName, wire->width)); + port_decls.push_back(stringf(" %s %s: UInt<%d> @[%s]\n", wire->port_input ? "input" : "output", + wireName, wire->width, wireFileinfo.c_str())); } else { - wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", wireName, wire->width)); + wire_decls.push_back(stringf(" wire %s: UInt<%d> @[%s]\n", wireName, wire->width, wireFileinfo.c_str())); } } @@ -1177,14 +1191,8 @@ struct FirrtlBackend : public Backend { if (top == nullptr) top = last; - std::ostringstream fileinfo; - for (auto &it : top->attributes) { - if (it.first == "\\src") { - dump_const(fileinfo, it.second); - } - } - - *f << stringf("circuit %s: @[%s]\n", make_id(top->name), fileinfo.str().c_str()); + auto circuitFileinfo = getFileinfo(top->attributes); + *f << stringf("circuit %s: @[%s]\n", make_id(top->name), circuitFileinfo.c_str()); for (auto module : design->modules()) { From ed9f8bfe6ecfbe395a3be9b9d711b8209e0f38cb Mon Sep 17 00:00:00 2001 From: Sahand Kashani Date: Thu, 19 Mar 2020 16:24:18 +0100 Subject: [PATCH 03/13] Add fileinfo to firrtl backend for instances --- backends/firrtl/firrtl.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 30b99fd91..8b361e9ac 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -394,7 +394,8 @@ struct FirrtlWorker log_warning("No instance for %s.%s\n", cell_type.c_str(), cell_name.c_str()); return; } - wire_exprs.push_back(stringf("%s" "inst %s%s of %s", indent.c_str(), cell_name.c_str(), cell_name_comment.c_str(), instanceOf.c_str())); + auto cellFileinfo = getFileinfo(cell->attributes); + wire_exprs.push_back(stringf("%s" "inst %s%s of %s @[%s]", indent.c_str(), cell_name.c_str(), cell_name_comment.c_str(), instanceOf.c_str(), cellFileinfo.c_str())); for (auto it = cell->connections().begin(); it != cell->connections().end(); ++it) { if (it->second.size() > 0) { @@ -435,7 +436,7 @@ struct FirrtlWorker // as part of the coalesced subfield assignments for this wire. register_reverse_wire_map(sourceExpr, *sinkSig); } else { - wire_exprs.push_back(stringf("\n%s%s <= %s", indent.c_str(), sinkExpr.c_str(), sourceExpr.c_str())); + wire_exprs.push_back(stringf("\n%s%s <= %s @[%s]", indent.c_str(), sinkExpr.c_str(), sourceExpr.c_str(), cellFileinfo.c_str())); } } } From 3e04e29dec54cce32ee4c6143747ece0487b564e Mon Sep 17 00:00:00 2001 From: Sahand Kashani Date: Fri, 20 Mar 2020 18:31:12 +0100 Subject: [PATCH 04/13] Refactor fileinfo emission characters to single location --- backends/firrtl/firrtl.cc | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 8b361e9ac..5bb945a94 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -101,7 +101,9 @@ std::string getFileinfo(dict attributes) std::ostringstream fileinfo; for (auto &it : attributes) { if (it.first == "\\src") { + fileinfo << "@["; dump_const(fileinfo, it.second); + fileinfo << "]"; } } return fileinfo.str(); @@ -395,7 +397,7 @@ struct FirrtlWorker return; } auto cellFileinfo = getFileinfo(cell->attributes); - wire_exprs.push_back(stringf("%s" "inst %s%s of %s @[%s]", indent.c_str(), cell_name.c_str(), cell_name_comment.c_str(), instanceOf.c_str(), cellFileinfo.c_str())); + wire_exprs.push_back(stringf("%s" "inst %s%s of %s %s", indent.c_str(), cell_name.c_str(), cell_name_comment.c_str(), instanceOf.c_str(), cellFileinfo.c_str())); for (auto it = cell->connections().begin(); it != cell->connections().end(); ++it) { if (it->second.size() > 0) { @@ -436,7 +438,7 @@ struct FirrtlWorker // as part of the coalesced subfield assignments for this wire. register_reverse_wire_map(sourceExpr, *sinkSig); } else { - wire_exprs.push_back(stringf("\n%s%s <= %s @[%s]", indent.c_str(), sinkExpr.c_str(), sourceExpr.c_str(), cellFileinfo.c_str())); + wire_exprs.push_back(stringf("\n%s%s <= %s %s", indent.c_str(), sinkExpr.c_str(), sourceExpr.c_str(), cellFileinfo.c_str())); } } } @@ -461,7 +463,7 @@ struct FirrtlWorker void run() { auto moduleFileinfo = getFileinfo(module->attributes); - f << stringf(" module %s: @[%s]\n", make_id(module->name), moduleFileinfo.c_str()); + f << stringf(" module %s: %s\n", make_id(module->name), moduleFileinfo.c_str()); vector port_decls, wire_decls, cell_exprs, wire_exprs; for (auto wire : module->wires()) @@ -479,12 +481,12 @@ struct FirrtlWorker { if (wire->port_input && wire->port_output) log_error("Module port %s.%s is inout!\n", log_id(module), log_id(wire)); - port_decls.push_back(stringf(" %s %s: UInt<%d> @[%s]\n", wire->port_input ? "input" : "output", + port_decls.push_back(stringf(" %s %s: UInt<%d> %s\n", wire->port_input ? "input" : "output", wireName, wire->width, wireFileinfo.c_str())); } else { - wire_decls.push_back(stringf(" wire %s: UInt<%d> @[%s]\n", wireName, wire->width, wireFileinfo.c_str())); + wire_decls.push_back(stringf(" wire %s: UInt<%d> %s\n", wireName, wire->width, wireFileinfo.c_str())); } } @@ -1193,7 +1195,7 @@ struct FirrtlBackend : public Backend { top = last; auto circuitFileinfo = getFileinfo(top->attributes); - *f << stringf("circuit %s: @[%s]\n", make_id(top->name), circuitFileinfo.c_str()); + *f << stringf("circuit %s: %s\n", make_id(top->name), circuitFileinfo.c_str()); for (auto module : design->modules()) { From c0b2a9af2efab6eadc63b4152303018366a82aa2 Mon Sep 17 00:00:00 2001 From: Sahand Kashani Date: Sat, 21 Mar 2020 12:54:23 +0100 Subject: [PATCH 05/13] Add fileinfo to firrtl backend for assignments and non-instance cells --- backends/firrtl/firrtl.cc | 51 +++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 5bb945a94..7d2da7b00 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -261,7 +261,7 @@ struct FirrtlWorker } } // We need a default constructor for the dict insert. - memory() : pCell(0), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec(""){} + memory() : pCell(0), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec(""){} const char *atLine() { if (srcLine == "") { @@ -494,7 +494,7 @@ struct FirrtlWorker { static Const ndef(0, 0); - // Is this cell is a module instance? + // Is this cell is a module instance? if (cell->type[0] != '$') { process_instance(cell, wire_exprs); @@ -512,11 +512,12 @@ struct FirrtlWorker string primop; bool always_uint = false; string y_id = make_id(cell->name); + std::string cellFileinfo = getFileinfo(cell->attributes); if (cell->type.in("$not", "$logic_not", "$neg", "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_bool", "$reduce_xnor")) { string a_expr = make_expr(cell->getPort("\\A")); - wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width)); + wire_decls.push_back(stringf(" wire %s: UInt<%d> %s\n", y_id.c_str(), y_width, cellFileinfo.c_str())); if (a_signed) { a_expr = "asSInt(" + a_expr + ")"; @@ -535,16 +536,16 @@ struct FirrtlWorker firrtl_is_signed = true; // Result of "neg" is signed (an SInt). firrtl_width = a_width; } else if (cell->type == "$logic_not") { - primop = "eq"; - a_expr = stringf("%s, UInt(0)", a_expr.c_str()); - } + primop = "eq"; + a_expr = stringf("%s, UInt(0)", a_expr.c_str()); + } else if (cell->type == "$reduce_and") primop = "andr"; else if (cell->type == "$reduce_or") primop = "orr"; else if (cell->type == "$reduce_xor") primop = "xorr"; else if (cell->type == "$reduce_xnor") { - primop = "not"; - a_expr = stringf("xorr(%s)", a_expr.c_str()); - } + primop = "not"; + a_expr = stringf("xorr(%s)", a_expr.c_str()); + } else if (cell->type == "$reduce_bool") { primop = "neq"; // Use the sign of the a_expr and its width as the type (UInt/SInt) and width of the comparand. @@ -556,18 +557,19 @@ struct FirrtlWorker if ((firrtl_is_signed && !always_uint)) expr = stringf("asUInt(%s)", expr.c_str()); - cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str())); + cell_exprs.push_back(stringf(" %s <= %s %s\n", y_id.c_str(), expr.c_str(), cellFileinfo.c_str())); register_reverse_wire_map(y_id, cell->getPort("\\Y")); continue; } if (cell->type.in("$add", "$sub", "$mul", "$div", "$mod", "$xor", "$xnor", "$and", "$or", "$eq", "$eqx", - "$gt", "$ge", "$lt", "$le", "$ne", "$nex", "$shr", "$sshr", "$sshl", "$shl", - "$logic_and", "$logic_or", "$pow")) + "$gt", "$ge", "$lt", "$le", "$ne", "$nex", "$shr", "$sshr", "$sshl", "$shl", + "$logic_and", "$logic_or", "$pow")) { string a_expr = make_expr(cell->getPort("\\A")); string b_expr = make_expr(cell->getPort("\\B")); - wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width)); + std::string cellFileinfo = getFileinfo(cell->attributes); + wire_decls.push_back(stringf(" wire %s: UInt<%d> %s\n", y_id.c_str(), y_width, cellFileinfo.c_str())); if (a_signed) { a_expr = "asSInt(" + a_expr + ")"; @@ -650,7 +652,7 @@ struct FirrtlWorker primop = "eq"; always_uint = true; firrtl_width = 1; - } + } else if ((cell->type == "$ne") | (cell->type == "$nex")) { primop = "neq"; always_uint = true; @@ -783,7 +785,7 @@ struct FirrtlWorker if ((firrtl_is_signed && !always_uint)) expr = stringf("asUInt(%s)", expr.c_str()); - cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str())); + cell_exprs.push_back(stringf(" %s <= %s %s\n", y_id.c_str(), expr.c_str(), cellFileinfo.c_str())); register_reverse_wire_map(y_id, cell->getPort("\\Y")); continue; @@ -795,11 +797,11 @@ struct FirrtlWorker string a_expr = make_expr(cell->getPort("\\A")); string b_expr = make_expr(cell->getPort("\\B")); string s_expr = make_expr(cell->getPort("\\S")); - wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), width)); + wire_decls.push_back(stringf(" wire %s: UInt<%d> %s\n", y_id.c_str(), width, cellFileinfo.c_str())); string expr = stringf("mux(%s, %s, %s)", s_expr.c_str(), b_expr.c_str(), a_expr.c_str()); - cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str())); + cell_exprs.push_back(stringf(" %s <= %s %s\n", y_id.c_str(), expr.c_str(), cellFileinfo.c_str())); register_reverse_wire_map(y_id, cell->getPort("\\Y")); continue; @@ -938,9 +940,9 @@ struct FirrtlWorker string expr = make_expr(cell->getPort("\\D")); string clk_expr = "asClock(" + make_expr(cell->getPort("\\CLK")) + ")"; - wire_decls.push_back(stringf(" reg %s: UInt<%d>, %s\n", y_id.c_str(), width, clk_expr.c_str())); + wire_decls.push_back(stringf(" reg %s: UInt<%d>, %s %s\n", y_id.c_str(), width, clk_expr.c_str(), cellFileinfo.c_str())); - cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str())); + cell_exprs.push_back(stringf(" %s <= %s %s\n", y_id.c_str(), expr.c_str(), cellFileinfo.c_str())); register_reverse_wire_map(y_id, cell->getPort("\\Q")); continue; @@ -1030,6 +1032,7 @@ struct FirrtlWorker for (auto wire : module->wires()) { string expr; + std::string wireFileinfo = getFileinfo(wire->attributes); if (wire->port_input) continue; @@ -1088,14 +1091,20 @@ struct FirrtlWorker if (is_valid) { if (make_unconn_id) { - wire_decls.push_back(stringf(" wire %s: UInt<1>\n", unconn_id.c_str())); + wire_decls.push_back(stringf(" wire %s: UInt<1> %s\n", unconn_id.c_str(), wireFileinfo.c_str())); + // `invalid` is a firrtl construction for simulation so we will not + // tag it with a @[fileinfo] tag as it doesn't directly correspond to + // a specific line of verilog code. wire_decls.push_back(stringf(" %s is invalid\n", unconn_id.c_str())); } - wire_exprs.push_back(stringf(" %s <= %s\n", make_id(wire->name), expr.c_str())); + wire_exprs.push_back(stringf(" %s <= %s %s\n", make_id(wire->name), expr.c_str(), wireFileinfo.c_str())); } else { if (make_unconn_id) { unconn_id.clear(); } + // `invalid` is a firrtl construction for simulation so we will not + // tag it with a @[fileinfo] tag as it doesn't directly correspond to + // a specific line of verilog code. wire_decls.push_back(stringf(" %s is invalid\n", make_id(wire->name))); } } From 21492914a29a8cbd9ccae6ad275c9ee2f1d98957 Mon Sep 17 00:00:00 2001 From: Sahand Kashani Date: Sat, 21 Mar 2020 15:57:53 +0100 Subject: [PATCH 06/13] Strip quotes around fileinfo strings Yosys puts quotes around the string that represents the fileinfo whereas firrtl does not. So when firrtl sees quotes, it escapes them with an extra backslash which makes it hard to read afterwards. --- backends/firrtl/firrtl.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 7d2da7b00..a6cb9cfbe 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -106,7 +106,11 @@ std::string getFileinfo(dict attributes) fileinfo << "]"; } } - return fileinfo.str(); + + std::string fileinfo_str = fileinfo.str(); + fileinfo_str.erase(std::remove(fileinfo_str.begin(), fileinfo_str.end(), '\"'), fileinfo_str.end()); + + return fileinfo_str; } // Get a port direction with respect to a specific module. From 566e08485a93c07d9db2162250a56ab6952a06e3 Mon Sep 17 00:00:00 2001 From: Sahand Kashani-Akhavan Date: Mon, 23 Mar 2020 08:56:28 +0100 Subject: [PATCH 07/13] Const parameter in function (backends/firrtl/firrtl.cc) Co-Authored-By: Alberto Gonzalez <61295559+boqwxp@users.noreply.github.com> --- backends/firrtl/firrtl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index a6cb9cfbe..a4bfe8549 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -96,7 +96,7 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o } } -std::string getFileinfo(dict attributes) +std::string getFileinfo(const dict &attributes) { std::ostringstream fileinfo; for (auto &it : attributes) { From f48fb26c0f87b2310ed1ae0ce2bfeaeb3a1ae4ae Mon Sep 17 00:00:00 2001 From: Sahand Kashani Date: Mon, 23 Mar 2020 09:01:17 +0100 Subject: [PATCH 08/13] Indentation conventions --- backends/firrtl/firrtl.cc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index a4bfe8549..de7d2275b 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -107,10 +107,10 @@ std::string getFileinfo(const dict &attributes) } } - std::string fileinfo_str = fileinfo.str(); - fileinfo_str.erase(std::remove(fileinfo_str.begin(), fileinfo_str.end(), '\"'), fileinfo_str.end()); + std::string fileinfo_str = fileinfo.str(); + fileinfo_str.erase(std::remove(fileinfo_str.begin(), fileinfo_str.end(), '\"'), fileinfo_str.end()); - return fileinfo_str; + return fileinfo_str; } // Get a port direction with respect to a specific module. @@ -263,9 +263,10 @@ struct FirrtlWorker 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(""){} + memory() : pCell(0), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec(""){} const char *atLine() { if (srcLine == "") { From 018116e478259f175a0a239da52bbbca8fa69b22 Mon Sep 17 00:00:00 2001 From: Sahand Kashani Date: Tue, 24 Mar 2020 10:36:14 +0100 Subject: [PATCH 09/13] Refactor to directly call ILANG_BACKEND::dump_const() + directly lookup src attribute --- backends/firrtl/firrtl.cc | 83 +++++++-------------------------------- 1 file changed, 15 insertions(+), 68 deletions(-) diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index de7d2275b..48a4d0465 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -23,6 +23,7 @@ #include "kernel/celltypes.h" #include "kernel/cellaigs.h" #include "kernel/log.h" +#include "backends/ilang/ilang_backend.h" #include #include #include @@ -42,72 +43,18 @@ static const FDirection FD_OUT = 0x2; static const FDirection FD_INOUT = 0x3; static const int FIRRTL_MAX_DSH_WIDTH_ERROR = 20; // For historic reasons, this is actually one greater than the maximum allowed shift width -// Shamelessly copied from ilang_backend.cc. Something better is surely possible here. -void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int offset = 0, bool autoint = true) +std::string getFileinfo(const RTLIL::AttrObject *design_entity) { - if (width < 0) - width = data.bits.size() - offset; - if ((data.flags & RTLIL::CONST_FLAG_STRING) == 0 || width != (int)data.bits.size()) { - if (width == 32 && autoint) { - int32_t val = 0; - for (int i = 0; i < width; i++) { - log_assert(offset+i < (int)data.bits.size()); - switch (data.bits[offset+i]) { - case RTLIL::S0: break; - case RTLIL::S1: val |= 1 << i; break; - default: val = -1; break; - } - } - if (val >= 0) { - f << stringf("%d", val); - return; - } - } - f << stringf("%d'", width); - for (int i = offset+width-1; i >= offset; i--) { - log_assert(i < (int)data.bits.size()); - switch (data.bits[i]) { - case RTLIL::S0: f << stringf("0"); break; - case RTLIL::S1: f << stringf("1"); break; - case RTLIL::Sx: f << stringf("x"); break; - case RTLIL::Sz: f << stringf("z"); break; - case RTLIL::Sa: f << stringf("-"); break; - case RTLIL::Sm: f << stringf("m"); break; - } - } - } else { - f << stringf("\""); - std::string str = data.decode_string(); - for (size_t i = 0; i < str.size(); i++) { - if (str[i] == '\n') - f << stringf("\\n"); - else if (str[i] == '\t') - f << stringf("\\t"); - else if (str[i] < 32) - f << stringf("\\%03o", str[i]); - else if (str[i] == '"') - f << stringf("\\\""); - else if (str[i] == '\\') - f << stringf("\\\\"); - else - f << str[i]; - } - f << stringf("\""); - } -} + std::string src(design_entity->get_src_attribute()); -std::string getFileinfo(const dict &attributes) -{ std::ostringstream fileinfo; - for (auto &it : attributes) { - if (it.first == "\\src") { - fileinfo << "@["; - dump_const(fileinfo, it.second); - fileinfo << "]"; - } + if (!src.empty()) { + fileinfo << "@[" << src << "]"; } - std::string fileinfo_str = fileinfo.str(); + // Remove quotes from src attribute as firrtl automatically escapes and + // double-quotes them. + std::string fileinfo_str(fileinfo.str()); fileinfo_str.erase(std::remove(fileinfo_str.begin(), fileinfo_str.end(), '\"'), fileinfo_str.end()); return fileinfo_str; @@ -401,7 +348,7 @@ struct FirrtlWorker log_warning("No instance for %s.%s\n", cell_type.c_str(), cell_name.c_str()); return; } - auto cellFileinfo = getFileinfo(cell->attributes); + auto cellFileinfo = getFileinfo(cell); wire_exprs.push_back(stringf("%s" "inst %s%s of %s %s", indent.c_str(), cell_name.c_str(), cell_name_comment.c_str(), instanceOf.c_str(), cellFileinfo.c_str())); for (auto it = cell->connections().begin(); it != cell->connections().end(); ++it) { @@ -467,14 +414,14 @@ struct FirrtlWorker void run() { - auto moduleFileinfo = getFileinfo(module->attributes); + auto moduleFileinfo = getFileinfo(module); f << stringf(" module %s: %s\n", make_id(module->name), moduleFileinfo.c_str()); vector port_decls, wire_decls, cell_exprs, wire_exprs; for (auto wire : module->wires()) { const auto wireName = make_id(wire->name); - auto wireFileinfo = getFileinfo(wire->attributes); + auto wireFileinfo = getFileinfo(wire); // If a wire has initial data, issue a warning since FIRRTL doesn't currently support it. if (wire->attributes.count("\\init")) { @@ -517,7 +464,7 @@ struct FirrtlWorker string primop; bool always_uint = false; string y_id = make_id(cell->name); - std::string cellFileinfo = getFileinfo(cell->attributes); + std::string cellFileinfo = getFileinfo(cell); if (cell->type.in("$not", "$logic_not", "$neg", "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_bool", "$reduce_xnor")) { @@ -573,7 +520,7 @@ struct FirrtlWorker { string a_expr = make_expr(cell->getPort("\\A")); string b_expr = make_expr(cell->getPort("\\B")); - std::string cellFileinfo = getFileinfo(cell->attributes); + std::string cellFileinfo = getFileinfo(cell); wire_decls.push_back(stringf(" wire %s: UInt<%d> %s\n", y_id.c_str(), y_width, cellFileinfo.c_str())); if (a_signed) { @@ -1037,7 +984,7 @@ struct FirrtlWorker for (auto wire : module->wires()) { string expr; - std::string wireFileinfo = getFileinfo(wire->attributes); + std::string wireFileinfo = getFileinfo(wire); if (wire->port_input) continue; @@ -1208,7 +1155,7 @@ struct FirrtlBackend : public Backend { if (top == nullptr) top = last; - auto circuitFileinfo = getFileinfo(top->attributes); + auto circuitFileinfo = getFileinfo(top); *f << stringf("circuit %s: %s\n", make_id(top->name), circuitFileinfo.c_str()); for (auto module : design->modules()) From 6c2b220af56ccac5ce343914cab095114656c83a Mon Sep 17 00:00:00 2001 From: Sahand Kashani Date: Tue, 24 Mar 2020 21:07:08 +0100 Subject: [PATCH 10/13] Remove use of auto for simple types + simplify src attribute computation --- backends/firrtl/firrtl.cc | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 48a4d0465..0cac437ac 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -46,15 +46,10 @@ static const int FIRRTL_MAX_DSH_WIDTH_ERROR = 20; // For historic reasons, this std::string getFileinfo(const RTLIL::AttrObject *design_entity) { std::string src(design_entity->get_src_attribute()); - - std::ostringstream fileinfo; - if (!src.empty()) { - fileinfo << "@[" << src << "]"; - } + std::string fileinfo_str = src.empty() ? "" : "@[" + src + "]"; // Remove quotes from src attribute as firrtl automatically escapes and // double-quotes them. - std::string fileinfo_str(fileinfo.str()); fileinfo_str.erase(std::remove(fileinfo_str.begin(), fileinfo_str.end(), '\"'), fileinfo_str.end()); return fileinfo_str; @@ -348,7 +343,7 @@ struct FirrtlWorker log_warning("No instance for %s.%s\n", cell_type.c_str(), cell_name.c_str()); return; } - auto cellFileinfo = getFileinfo(cell); + std::string cellFileinfo = getFileinfo(cell); wire_exprs.push_back(stringf("%s" "inst %s%s of %s %s", indent.c_str(), cell_name.c_str(), cell_name_comment.c_str(), instanceOf.c_str(), cellFileinfo.c_str())); for (auto it = cell->connections().begin(); it != cell->connections().end(); ++it) { @@ -414,14 +409,14 @@ struct FirrtlWorker void run() { - auto moduleFileinfo = getFileinfo(module); + std::string moduleFileinfo = getFileinfo(module); f << stringf(" module %s: %s\n", make_id(module->name), moduleFileinfo.c_str()); vector port_decls, wire_decls, cell_exprs, wire_exprs; for (auto wire : module->wires()) { const auto wireName = make_id(wire->name); - auto wireFileinfo = getFileinfo(wire); + std::string wireFileinfo = getFileinfo(wire); // If a wire has initial data, issue a warning since FIRRTL doesn't currently support it. if (wire->attributes.count("\\init")) { @@ -1155,7 +1150,7 @@ struct FirrtlBackend : public Backend { if (top == nullptr) top = last; - auto circuitFileinfo = getFileinfo(top); + std::string circuitFileinfo = getFileinfo(top); *f << stringf("circuit %s: %s\n", make_id(top->name), circuitFileinfo.c_str()); for (auto module : design->modules()) From 820e3d1dad4f484f9646588f79b73b21b495e3d8 Mon Sep 17 00:00:00 2001 From: Sahand Kashani Date: Wed, 8 Apr 2020 23:20:56 +0200 Subject: [PATCH 11/13] Remove unnecessary pruning of double-quoting In the past I was calling the ILANG_BACKEND::dump_const() to dump values to an output stream. When these values were strings, the function used to add quotes around them. The firrtl compiler, in turn, escaped these quotes and the result was double-quoted strings which were hard to read. However I'm now calling design_entity->get_src_attribute() directly and there is no additional quote being put around it, so we can safely remove the unnecessary call to str.erase() here. --- backends/firrtl/firrtl.cc | 5 ----- 1 file changed, 5 deletions(-) diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 0cac437ac..3ef886664 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -47,11 +47,6 @@ std::string getFileinfo(const RTLIL::AttrObject *design_entity) { std::string src(design_entity->get_src_attribute()); std::string fileinfo_str = src.empty() ? "" : "@[" + src + "]"; - - // Remove quotes from src attribute as firrtl automatically escapes and - // double-quotes them. - fileinfo_str.erase(std::remove(fileinfo_str.begin(), fileinfo_str.end(), '\"'), fileinfo_str.end()); - return fileinfo_str; } From ac388859e3a859ac6f8e1b219295e2ddfac0fd6b Mon Sep 17 00:00:00 2001 From: Sahand Kashani Date: Wed, 8 Apr 2020 23:59:22 +0200 Subject: [PATCH 12/13] Remove dependency on ilang backend since we no longer use it --- backends/firrtl/firrtl.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 94d3e14c1..21eade1fc 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -23,7 +23,6 @@ #include "kernel/celltypes.h" #include "kernel/cellaigs.h" #include "kernel/log.h" -#include "backends/ilang/ilang_backend.h" #include #include #include From 959a00a46ff65ec0cf82b6803cf7dd01f2ec4d39 Mon Sep 17 00:00:00 2001 From: Sahand Kashani Date: Thu, 9 Apr 2020 21:16:02 +0200 Subject: [PATCH 13/13] Fix indentation --- backends/firrtl/firrtl.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 21eade1fc..fd7f20cc6 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -504,8 +504,8 @@ struct FirrtlWorker continue; } if (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($xor), ID($xnor), ID($and), ID($or), ID($eq), ID($eqx), - ID($gt), ID($ge), ID($lt), ID($le), ID($ne), ID($nex), ID($shr), ID($sshr), ID($sshl), ID($shl), - ID($logic_and), ID($logic_or), ID($pow))) + ID($gt), ID($ge), ID($lt), ID($le), ID($ne), ID($nex), ID($shr), ID($sshr), ID($sshl), ID($shl), + ID($logic_and), ID($logic_or), ID($pow))) { string a_expr = make_expr(cell->getPort(ID::A)); string b_expr = make_expr(cell->getPort(ID::B)); @@ -593,7 +593,7 @@ struct FirrtlWorker primop = "eq"; always_uint = true; firrtl_width = 1; - } + } else if ((cell->type == ID($ne)) | (cell->type == ID($nex))) { primop = "neq"; always_uint = true;