mirror of
https://github.com/YosysHQ/yosys
synced 2025-11-12 09:02:05 +00:00
WIP dump_meminit
Developed for synth_analogdevices, but there's no reason it couldn't be used for others.
This commit is contained in:
parent
1ceb5b2930
commit
7f8334e781
2 changed files with 122 additions and 0 deletions
|
|
@ -13,3 +13,5 @@ OBJS += passes/memory/memory_libmap.o
|
|||
OBJS += passes/memory/memory_bmux2rom.o
|
||||
|
||||
OBJS += passes/memory/memlib.o
|
||||
|
||||
OBJS += passes/memory/dump_meminit.o
|
||||
|
|
|
|||
120
passes/memory/dump_meminit.cc
Normal file
120
passes/memory/dump_meminit.cc
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
|
||||
#include "kernel/yosys.h"
|
||||
#include "kernel/log_help.h"
|
||||
#include "libs/sha1/sha1.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
struct DumpMemInitPass : public Pass
|
||||
{
|
||||
DumpMemInitPass() : Pass("dump_meminit", "convert memory INIT parameters and dump to file") { }
|
||||
|
||||
bool formatted_help() override
|
||||
{
|
||||
auto *help = PrettyHelp::get_current();
|
||||
auto content_root = help->get_root();
|
||||
|
||||
content_root->usage("dump_meminit [options] [selection]");
|
||||
content_root->paragraph(
|
||||
"Write INIT parameters of selected memories to file. The INIT parameter is removed, "
|
||||
"and the name of the written file is assigned to the INIT_FILE parameter."
|
||||
);
|
||||
|
||||
content_root->paragraph(
|
||||
"Currently requires memories to have the WIDTH parameter assigned, and will rewrite "
|
||||
"undefined bits as 0."
|
||||
);
|
||||
|
||||
content_root->option("-max_name_length <length>",
|
||||
"the written file normally uses the hierarchical name of the memory being written. "
|
||||
"If the length of the hierarchical name exceeds <length>, replace it with a SHA1 "
|
||||
"message digest instead. Note that this message digest is always 40 characters "
|
||||
"long. Has a default value of 60."
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||
{
|
||||
const int DIGEST_LENGTH = 40;
|
||||
int max_name_length = 60;
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++)
|
||||
{
|
||||
std::string arg = args[argidx];
|
||||
if (arg == "-max_name_length" && argidx+1 < args.size()) {
|
||||
max_name_length = stoi(args[++argidx]);
|
||||
if (max_name_length < DIGEST_LENGTH)
|
||||
log_warning("memories with name length in range (%d, %d) will be extended to %d characters\n",
|
||||
max_name_length, DIGEST_LENGTH, DIGEST_LENGTH);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design, true);
|
||||
|
||||
log_header(design, "Dumping memory INIT values\n");
|
||||
|
||||
for (auto *mod : design->selected_unboxed_modules())
|
||||
for (auto *cell : mod->selected_cells())
|
||||
{
|
||||
// construct full hierarchical name
|
||||
auto full_name = stringf("%s.%s", RTLIL::unescape_id(mod->name), RTLIL::unescape_id(cell->name));
|
||||
|
||||
// read INIT
|
||||
auto init = cell->getParam(ID::INIT);
|
||||
cell->unsetParam(ID::INIT);
|
||||
|
||||
// check for shorthand values
|
||||
if (init.is_fully_undef()) {
|
||||
log_debug("%s -> fully undef\n", full_name);
|
||||
cell->setParam(ID::INIT_FILE, Const("X"));
|
||||
continue;
|
||||
}
|
||||
if (init.is_fully_zero()) {
|
||||
log_debug("%s -> fully zero\n", full_name);
|
||||
cell->setParam(ID::INIT_FILE, Const("0"));
|
||||
continue;
|
||||
}
|
||||
|
||||
// construct output file name
|
||||
string filename;
|
||||
if (GetSize(full_name) > max_name_length)
|
||||
filename += sha1(full_name);
|
||||
else
|
||||
filename += full_name;
|
||||
filename += ".mem";
|
||||
log_debug("%s -> `%s'\n", full_name, filename);
|
||||
|
||||
// open output file
|
||||
cell->setParam(ID::INIT_FILE, Const(filename));
|
||||
auto *f = fopen(filename.c_str(), "w");
|
||||
if (f == nullptr)
|
||||
log_error("Can't open `%s' for writing.\n", filename);
|
||||
|
||||
// write memory to file
|
||||
int word_size = cell->getParam(ID::WIDTH).as_int();
|
||||
for (auto idx = 0; idx < GetSize(init); idx += word_size) {
|
||||
auto val = init.extract(idx, word_size, RTLIL::Sx);
|
||||
// split into single hex digits
|
||||
// effectively fprintf(f, "%x\n", val.as_int()) but with
|
||||
// potentially oversized ints and dynamically sized zero padding
|
||||
std::string hex_str;
|
||||
hex_str.reserve(word_size / 4);
|
||||
for (auto x_idx = 0; x_idx < word_size; x_idx += 4) {
|
||||
auto hex = val.extract(x_idx, 4, RTLIL::Sx).as_int();
|
||||
hex_str.push_back((hex < 10 ? '0' : 'a' - 10) + hex);
|
||||
}
|
||||
reverse(hex_str.begin(), hex_str.end());
|
||||
fprintf(f, "%s\n", hex_str.c_str());
|
||||
}
|
||||
|
||||
// close output file
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
} DumpMemInitPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
||||
Loading…
Add table
Add a link
Reference in a new issue