Skip to content

Commit

Permalink
Merge branch 'YosysHQ:main' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
akashlevy authored May 8, 2024
2 parents 2e21078 + 5616180 commit 818fd2e
Show file tree
Hide file tree
Showing 6 changed files with 207 additions and 71 deletions.
16 changes: 15 additions & 1 deletion CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,23 @@
List of major changes and improvements between releases
=======================================================

Yosys 0.40 .. Yosys 0.41-dev
Yosys 0.41 .. Yosys 0.42-dev
--------------------------

Yosys 0.40 .. Yosys 0.41
--------------------------
* New commands and options
- Added "cellmatch" pass for picking out standard cells automatically.

* Various
- Extended the experimental incremental JSON API to allow arbitrary
smtlib subexpressions.
- Added support for using ABCs library merging when providing multiple
liberty files.

* Verific support
- Expose library name as module attribute.

Yosys 0.39 .. Yosys 0.40
--------------------------
* New commands and options
Expand Down
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ LIBS += -lrt
endif
endif

YOSYS_VER := 0.40+68
YOSYS_VER := 0.41+0

# Note: We arrange for .gitcommit to contain the (short) commit hash in
# tarballs generated with git-archive(1) using .gitattributes. The git repo
Expand All @@ -157,15 +157,15 @@ endif
OBJS = kernel/version_$(GIT_REV).o

bumpversion:
sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline a1bb025.. | wc -l`/;" Makefile
sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline c1ad377.. | wc -l`/;" Makefile

# set 'ABCREV = default' to use abc/ as it is
#
# Note: If you do ABC development, make sure that 'abc' in this directory
# is just a symlink to your actual ABC working directory, as 'make mrproper'
# will remove the 'abc' directory and you do not want to accidentally
# delete your work on ABC..
ABCREV = 03da96f
ABCREV = 237d813
ABCPULL = 1
ABCURL ?= https://github.com/YosysHQ/abc
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 ABC_USE_NAMESPACE=abc VERBOSE=$(Q)
Expand Down
189 changes: 125 additions & 64 deletions backends/cxxrtl/cxxrtl_backend.cc
Original file line number Diff line number Diff line change
Expand Up @@ -606,22 +606,30 @@ std::vector<std::string> split_by(const std::string &str, const std::string &sep
return result;
}

std::string escape_cxx_string(const std::string &input)
std::string escape_c_string(const std::string &input)
{
std::string output = "\"";
std::string output;
output.push_back('"');
for (auto c : input) {
if (::isprint(c)) {
if (c == '\\')
output.push_back('\\');
output.push_back(c);
} else {
char l = c & 0xf, h = (c >> 4) & 0xf;
output.append("\\x");
output.push_back((h < 10 ? '0' + h : 'a' + h - 10));
output.push_back((l < 10 ? '0' + l : 'a' + l - 10));
char l = c & 0x3, m = (c >> 3) & 0x3, h = (c >> 6) & 0x3;
output.append("\\");
output.push_back('0' + h);
output.push_back('0' + m);
output.push_back('0' + l);
}
}
output.push_back('"');
return output;
}

std::string escape_cxx_string(const std::string &input)
{
std::string output = escape_c_string(input);
if (output.find('\0') != std::string::npos) {
output.insert(0, "std::string {");
output.append(stringf(", %zu}", input.size()));
Expand Down Expand Up @@ -2275,46 +2283,92 @@ struct CxxrtlWorker {
dec_indent();
}

void dump_metadata_map(const dict<RTLIL::IdString, RTLIL::Const> &metadata_map)
{
void dump_serialized_metadata(const dict<RTLIL::IdString, RTLIL::Const> &metadata_map) {
// Creating thousands metadata_map objects using initializer lists in a single function results in one of:
// 1. Megabytes of stack usage (with __attribute__((optnone))).
// 2. Minutes of compile time (without __attribute__((optnone))).
// So, don't create them.
std::string data;
auto put_u64 = [&](uint64_t value) {
for (size_t count = 0; count < 8; count++) {
data += (char)(value >> 56);
value <<= 8;
}
};
for (auto metadata_item : metadata_map) {
if (!metadata_item.first.isPublic())
continue;
if (metadata_item.second.size() > 64 && (metadata_item.second.flags & RTLIL::CONST_FLAG_STRING) == 0) {
f << indent << "/* attribute " << metadata_item.first.str().substr(1) << " is over 64 bits wide */\n";
continue;
}
data += metadata_item.first.str().substr(1) + '\0';
// In Yosys, a real is a type of string.
if (metadata_item.second.flags & RTLIL::CONST_FLAG_REAL) {
double dvalue = std::stod(metadata_item.second.decode_string());
uint64_t uvalue;
static_assert(sizeof(dvalue) == sizeof(uvalue), "double must be 64 bits in size");
memcpy(&uvalue, &dvalue, sizeof(uvalue));
data += 'd';
put_u64(uvalue);
} else if (metadata_item.second.flags & RTLIL::CONST_FLAG_STRING) {
data += 's';
data += metadata_item.second.decode_string();
data += '\0';
} else if (metadata_item.second.flags & RTLIL::CONST_FLAG_SIGNED) {
data += 'i';
put_u64((uint64_t)metadata_item.second.as_int(/*is_signed=*/true));
} else {
data += 'u';
put_u64(metadata_item.second.as_int(/*is_signed=*/false));
}
}
f << escape_c_string(data);
}

void dump_metadata_map(const dict<RTLIL::IdString, RTLIL::Const> &metadata_map) {
if (metadata_map.empty()) {
f << "metadata_map()";
return;
}
f << "metadata_map({\n";
inc_indent();
for (auto metadata_item : metadata_map) {
if (!metadata_item.first.isPublic())
continue;
if (metadata_item.second.size() > 64 && (metadata_item.second.flags & RTLIL::CONST_FLAG_STRING) == 0) {
f << indent << "/* attribute " << metadata_item.first.str().substr(1) << " is over 64 bits wide */\n";
continue;
}
f << indent << "{ " << escape_cxx_string(metadata_item.first.str().substr(1)) << ", ";
// In Yosys, a real is a type of string.
if (metadata_item.second.flags & RTLIL::CONST_FLAG_REAL) {
f << std::showpoint << std::stod(metadata_item.second.decode_string()) << std::noshowpoint;
} else if (metadata_item.second.flags & RTLIL::CONST_FLAG_STRING) {
f << escape_cxx_string(metadata_item.second.decode_string());
} else if (metadata_item.second.flags & RTLIL::CONST_FLAG_SIGNED) {
f << "INT64_C(" << metadata_item.second.as_int(/*is_signed=*/true) << ")";
} else {
f << "UINT64_C(" << metadata_item.second.as_int(/*is_signed=*/false) << ")";
} else {
f << "metadata_map({\n";
inc_indent();
for (auto metadata_item : metadata_map) {
if (!metadata_item.first.isPublic())
continue;
if (metadata_item.second.size() > 64 && (metadata_item.second.flags & RTLIL::CONST_FLAG_STRING) == 0) {
f << indent << "/* attribute " << metadata_item.first.str().substr(1) << " is over 64 bits wide */\n";
continue;
}
f << indent << "{ " << escape_cxx_string(metadata_item.first.str().substr(1)) << ", ";
// In Yosys, a real is a type of string.
if (metadata_item.second.flags & RTLIL::CONST_FLAG_REAL) {
f << std::showpoint << std::stod(metadata_item.second.decode_string()) << std::noshowpoint;
} else if (metadata_item.second.flags & RTLIL::CONST_FLAG_STRING) {
f << escape_cxx_string(metadata_item.second.decode_string());
} else if (metadata_item.second.flags & RTLIL::CONST_FLAG_SIGNED) {
f << "INT64_C(" << metadata_item.second.as_int(/*is_signed=*/true) << ")";
} else {
f << "UINT64_C(" << metadata_item.second.as_int(/*is_signed=*/false) << ")";
}
f << " },\n";
}
f << " },\n";
}
dec_indent();
f << indent << "})";
dec_indent();
f << indent << "})";
}
}

void dump_debug_attrs(const RTLIL::AttrObject *object)
void dump_debug_attrs(const RTLIL::AttrObject *object, bool serialize = true)
{
dict<RTLIL::IdString, RTLIL::Const> attributes = object->attributes;
// Inherently necessary to get access to the object, so a waste of space to emit.
attributes.erase(ID::hdlname);
// Internal Yosys attribute that should be removed but isn't.
attributes.erase(ID::module_not_derived);
dump_metadata_map(attributes);
if (serialize) {
dump_serialized_metadata(attributes);
} else {
dump_metadata_map(attributes);
}
}

void dump_debug_info_method(RTLIL::Module *module)
Expand All @@ -2337,7 +2391,7 @@ struct CxxrtlWorker {
// The module is responsible for adding its own scope.
f << indent << "scopes->add(path.empty() ? path : path.substr(0, path.size() - 1), ";
f << escape_cxx_string(get_hdl_name(module)) << ", ";
dump_debug_attrs(module);
dump_debug_attrs(module, /*serialize=*/false);
f << ", std::move(cell_attrs));\n";
count_scopes++;
// If there were any submodules that were flattened, the module is also responsible for adding them.
Expand All @@ -2347,11 +2401,11 @@ struct CxxrtlWorker {
auto module_attrs = scopeinfo_attributes(cell, ScopeinfoAttrs::Module);
auto cell_attrs = scopeinfo_attributes(cell, ScopeinfoAttrs::Cell);
cell_attrs.erase(ID::module_not_derived);
f << indent << "scopes->add(path + " << escape_cxx_string(get_hdl_name(cell)) << ", ";
f << indent << "scopes->add(path, " << escape_cxx_string(get_hdl_name(cell)) << ", ";
f << escape_cxx_string(cell->get_string_attribute(ID(module))) << ", ";
dump_metadata_map(module_attrs);
dump_serialized_metadata(module_attrs);
f << ", ";
dump_metadata_map(cell_attrs);
dump_serialized_metadata(cell_attrs);
f << ");\n";
} else log_assert(false && "Unknown $scopeinfo type");
count_scopes++;
Expand Down Expand Up @@ -2419,37 +2473,41 @@ struct CxxrtlWorker {
if (has_driven_sync + has_driven_comb + has_undriven > 1)
count_mixed_driver++;

f << indent << "items->add(path + " << escape_cxx_string(get_hdl_name(wire));
f << ", debug_item(" << mangle(wire) << ", " << wire->start_offset;
bool first = true;
for (auto flag : flags) {
if (first) {
first = false;
f << ", ";
} else {
f << "|";
f << indent << "items->add(path, " << escape_cxx_string(get_hdl_name(wire)) << ", ";
dump_debug_attrs(wire);
f << ", " << mangle(wire);
if (wire->start_offset != 0 || !flags.empty()) {
f << ", " << wire->start_offset;
bool first = true;
for (auto flag : flags) {
if (first) {
first = false;
f << ", ";
} else {
f << "|";
}
f << "debug_item::" << flag;
}
f << "debug_item::" << flag;
}
f << "), ";
dump_debug_attrs(wire);
f << ");\n";
count_member_wires++;
break;
}
case WireType::ALIAS: {
// Alias of a member wire
const RTLIL::Wire *aliasee = debug_wire_type.sig_subst.as_wire();
f << indent << "items->add(path + " << escape_cxx_string(get_hdl_name(wire));
f << ", debug_item(";
f << indent << "items->add(path, " << escape_cxx_string(get_hdl_name(wire)) << ", ";
dump_debug_attrs(aliasee);
f << ", ";
// If the aliasee is an outline, then the alias must be an outline, too; otherwise downstream
// tooling has no way to find out about the outline.
if (debug_wire_types[aliasee].is_outline())
f << "debug_eval_outline";
else
f << "debug_alias()";
f << ", " << mangle(aliasee) << ", " << wire->start_offset << "), ";
dump_debug_attrs(aliasee);
f << ", " << mangle(aliasee);
if (wire->start_offset != 0)
f << ", " << wire->start_offset;
f << ");\n";
count_alias_wires++;
break;
Expand All @@ -2459,18 +2517,22 @@ struct CxxrtlWorker {
f << indent << "static const value<" << wire->width << "> const_" << mangle(wire) << " = ";
dump_const(debug_wire_type.sig_subst.as_const());
f << ";\n";
f << indent << "items->add(path + " << escape_cxx_string(get_hdl_name(wire));
f << ", debug_item(const_" << mangle(wire) << ", " << wire->start_offset << "), ";
f << indent << "items->add(path, " << escape_cxx_string(get_hdl_name(wire)) << ", ";
dump_debug_attrs(wire);
f << ", const_" << mangle(wire);
if (wire->start_offset != 0)
f << ", " << wire->start_offset;
f << ");\n";
count_const_wires++;
break;
}
case WireType::OUTLINE: {
// Localized or inlined, but rematerializable wire
f << indent << "items->add(path + " << escape_cxx_string(get_hdl_name(wire));
f << ", debug_item(debug_eval_outline, " << mangle(wire) << ", " << wire->start_offset << "), ";
f << indent << "items->add(path, " << escape_cxx_string(get_hdl_name(wire)) << ", ";
dump_debug_attrs(wire);
f << ", debug_eval_outline, " << mangle(wire);
if (wire->start_offset != 0)
f << ", " << wire->start_offset;
f << ");\n";
count_inline_wires++;
break;
Expand All @@ -2486,15 +2548,14 @@ struct CxxrtlWorker {
for (auto &mem : mod_memories[module]) {
if (!mem.memid.isPublic())
continue;
f << indent << "items->add(path + " << escape_cxx_string(mem.packed ? get_hdl_name(mem.cell) : get_hdl_name(mem.mem));
f << ", debug_item(" << mangle(&mem) << ", ";
f << mem.start_offset << "), ";
f << indent << "items->add(path, " << escape_cxx_string(mem.packed ? get_hdl_name(mem.cell) : get_hdl_name(mem.mem)) << ", ";
if (mem.packed) {
dump_debug_attrs(mem.cell);
} else {
dump_debug_attrs(mem.mem);
}
f << ");\n";
f << ", " << mangle(&mem) << ", ";
f << mem.start_offset << ");\n";
}
}
dec_indent();
Expand All @@ -2506,7 +2567,7 @@ struct CxxrtlWorker {
const char *access = is_cxxrtl_blackbox_cell(cell) ? "->" : ".";
f << indent << mangle(cell) << access;
f << "debug_info(items, scopes, path + " << escape_cxx_string(get_hdl_name(cell) + ' ') << ", ";
dump_debug_attrs(cell);
dump_debug_attrs(cell, /*serialize=*/false);
f << ");\n";
}
}
Expand Down
Loading

0 comments on commit 818fd2e

Please sign in to comment.