/* * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf * * 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 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ #include "kernel/yosys.h" #include "kernel/sigtools.h" #include #include #include USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN static void run_ice40_braminit(Module *module) { for (auto cell : module->selected_cells()) { uint16_t mem[256]; /* Only consider cells we're interested in */ if (cell->type != "\\SB_RAM40_4K" && cell->type != "\\SB_RAM40_4KNR" && cell->type != "\\SB_RAM40_4KNW" && cell->type != "\\SB_RAM40_4KNRNW") continue; if (!cell->hasParam("\\INIT_FILE")) continue; std::string init_file = cell->getParam("\\INIT_FILE").decode_string(); cell->unsetParam("\\INIT_FILE"); if (init_file == "") continue; /* Open file */ log("Processing %s : %s\n", RTLIL::id2cstr(cell->name), init_file.c_str()); std::ifstream f; f.open(init_file.c_str()); if (f.fail()) { log("Can not open file `%s`.\n", init_file.c_str()); continue; } /* Defaults to 0 */ memset(mem, 0x00, sizeof(mem)); /* Process each line */ bool in_comment = false; int cursor = 0; while (!f.eof()) { std::string line, token; std::getline(f, line); for (int i = 0; i < GetSize(line); i++) { if (in_comment && line.substr(i, 2) == "*/") { line[i] = ' '; line[i+1] = ' '; in_comment = false; continue; } if (!in_comment && line.substr(i, 2) == "/*") in_comment = true; if (in_comment) line[i] = ' '; } while (1) { bool set_cursor = false; long value; token = next_token(line, " \t\r\n"); if (token.empty() || token.substr(0, 2) == "//") break; if (token[0] == '@') { token = token.substr(1); set_cursor = true; } const char *nptr = token.c_str(); char *endptr; value = strtol(nptr, &endptr, 16); if (!*nptr || *endptr) { log("Can not parse %s `%s` for %s.\n", set_cursor ? "address" : "value", nptr, token.c_str() ); continue; } if (set_cursor) cursor = value; else if (cursor >= 0 && cursor < 256) mem[cursor++] = value; else log("Attempt to initialize non existent address %d\n", cursor); } } /* Set attributes */ const char *hex = "0123456789ABCDEF"; for (int i=0; i<16; i++) { std::string val = ""; for (int j=15; j>=0; j--) val += std::bitset<16>(mem[i*16+j]).to_string(); cell->setParam("\\INIT_" + std::string(1, hex[i]), RTLIL::Const::from_string(val)); } } } struct Ice40BRAMInitPass : public Pass { Ice40BRAMInitPass() : Pass("ice40_braminit", "iCE40: perform SB_RAM40_4K initialization from file") { } void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); log(" ice40_braminit\n"); log("\n"); log("This command processes all SB_RAM40_4K blocks with a non-empty INIT_FILE\n"); log("parameter and converts it into the required INIT_x attributes\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing ICE40_BRAMINIT pass.\n"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { // if (args[argidx] == "-???") { // continue; // } break; } extra_args(args, argidx, design); for (auto module : design->selected_modules()) run_ice40_braminit(module); } } Ice40BRAMInitPass; PRIVATE_NAMESPACE_END