diff options
Diffstat (limited to 'backends')
-rw-r--r-- | backends/autotest/Makefile.inc | 3 | ||||
-rw-r--r-- | backends/autotest/autotest.cc | 336 | ||||
-rw-r--r-- | backends/blif/blif.cc | 221 | ||||
-rw-r--r-- | backends/btor/btor.cc | 394 | ||||
-rwxr-xr-x | backends/btor/verilog2btor.sh | 4 | ||||
-rw-r--r-- | backends/edif/edif.cc | 216 | ||||
-rw-r--r-- | backends/ilang/ilang_backend.cc | 329 | ||||
-rw-r--r-- | backends/ilang/ilang_backend.h | 32 | ||||
-rw-r--r-- | backends/intersynth/intersynth.cc | 61 | ||||
-rw-r--r-- | backends/spice/spice.cc | 93 | ||||
-rw-r--r-- | backends/verilog/verilog_backend.cc | 729 | ||||
-rw-r--r-- | backends/verilog/verilog_backend.h | 5 |
12 files changed, 1139 insertions, 1284 deletions
diff --git a/backends/autotest/Makefile.inc b/backends/autotest/Makefile.inc deleted file mode 100644 index 9308dcd47..000000000 --- a/backends/autotest/Makefile.inc +++ /dev/null @@ -1,3 +0,0 @@ - -OBJS += backends/autotest/autotest.o - diff --git a/backends/autotest/autotest.cc b/backends/autotest/autotest.cc deleted file mode 100644 index 3e2fab006..000000000 --- a/backends/autotest/autotest.cc +++ /dev/null @@ -1,336 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at> - * - * 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/register.h" -#include "kernel/log.h" -#include <stdlib.h> -#include <stdio.h> - -#define NUM_ITER 1000 - -static std::string id(std::string internal_id) -{ - const char *str = internal_id.c_str(); - bool do_escape = false; - - if (*str == '\\') - str++; - - if ('0' <= *str && *str <= '9') - do_escape = true; - - for (int i = 0; str[i]; i++) { - if ('0' <= str[i] && str[i] <= '9') - continue; - if ('a' <= str[i] && str[i] <= 'z') - continue; - if ('A' <= str[i] && str[i] <= 'Z') - continue; - if (str[i] == '_') - continue; - do_escape = true; - break; - } - - if (do_escape) - return "\\" + std::string(str) + " "; - return std::string(str); -} - -static std::string idx(std::string str) -{ - if (str[0] == '\\') - return str.substr(1); - return str; -} - -static std::string idy(std::string str1, std::string str2 = std::string(), std::string str3 = std::string()) -{ - str1 = idx(str1); - if (!str2.empty()) - str1 += "_" + idx(str2); - if (!str3.empty()) - str1 += "_" + idx(str3); - return id(str1); -} - -static void autotest(FILE *f, RTLIL::Design *design) -{ - fprintf(f, "module testbench;\n\n"); - - fprintf(f, "integer i;\n\n"); - - fprintf(f, "reg [31:0] xorshift128_x = 123456789;\n"); - fprintf(f, "reg [31:0] xorshift128_y = 362436069;\n"); - fprintf(f, "reg [31:0] xorshift128_z = 521288629;\n"); - fprintf(f, "reg [31:0] xorshift128_w = 88675123;\n"); - fprintf(f, "reg [31:0] xorshift128_t;\n\n"); - fprintf(f, "task xorshift128;\n"); - fprintf(f, "begin\n"); - fprintf(f, "\txorshift128_t = xorshift128_x ^ (xorshift128_x << 11);\n"); - fprintf(f, "\txorshift128_x = xorshift128_y;\n"); - fprintf(f, "\txorshift128_y = xorshift128_z;\n"); - fprintf(f, "\txorshift128_z = xorshift128_w;\n"); - fprintf(f, "\txorshift128_w = xorshift128_w ^ (xorshift128_w >> 19) ^ xorshift128_t ^ (xorshift128_t >> 8);\n"); - fprintf(f, "end\n"); - fprintf(f, "endtask\n\n"); - - for (auto it = design->modules.begin(); it != design->modules.end(); it++) - { - std::map<std::string, int> signal_in; - std::map<std::string, std::string> signal_const; - std::map<std::string, int> signal_clk; - std::map<std::string, int> signal_out; - - RTLIL::Module *mod = it->second; - - if (mod->get_bool_attribute("\\gentb_skip")) - continue; - - int count_ports = 0; - log("Generating test bench for module `%s'.\n", it->first.c_str()); - for (auto it2 = mod->wires.begin(); it2 != mod->wires.end(); it2++) { - RTLIL::Wire *wire = it2->second; - if (wire->port_output) { - count_ports++; - signal_out[idy("sig", mod->name, wire->name)] = wire->width; - fprintf(f, "wire [%d:0] %s;\n", wire->width-1, idy("sig", mod->name, wire->name).c_str()); - } else if (wire->port_input) { - count_ports++; - bool is_clksignal = wire->get_bool_attribute("\\gentb_clock"); - for (auto it3 = mod->processes.begin(); it3 != mod->processes.end(); it3++) - for (auto it4 = it3->second->syncs.begin(); it4 != it3->second->syncs.end(); it4++) { - if ((*it4)->type == RTLIL::ST0 || (*it4)->type == RTLIL::ST1) - continue; - RTLIL::SigSpec &signal = (*it4)->signal; - for (size_t i = 0; i < signal.chunks.size(); i++) { - if (signal.chunks[i].wire == wire) - is_clksignal = true; - } - } - if (is_clksignal && wire->attributes.count("\\gentb_constant") == 0) { - signal_clk[idy("sig", mod->name, wire->name)] = wire->width; - } else { - signal_in[idy("sig", mod->name, wire->name)] = wire->width; - if (wire->attributes.count("\\gentb_constant") != 0) - signal_const[idy("sig", mod->name, wire->name)] = wire->attributes["\\gentb_constant"].as_string(); - } - fprintf(f, "reg [%d:0] %s;\n", wire->width-1, idy("sig", mod->name, wire->name).c_str()); - } - } - fprintf(f, "%s %s(\n", id(mod->name).c_str(), idy("uut", mod->name).c_str()); - for (auto it2 = mod->wires.begin(); it2 != mod->wires.end(); it2++) { - RTLIL::Wire *wire = it2->second; - if (wire->port_output || wire->port_input) - fprintf(f, "\t.%s(%s)%s\n", id(wire->name).c_str(), - idy("sig", mod->name, wire->name).c_str(), --count_ports ? "," : ""); - } - fprintf(f, ");\n\n"); - - fprintf(f, "task %s;\n", idy(mod->name, "reset").c_str()); - fprintf(f, "begin\n"); - int delay_counter = 0; - for (auto it = signal_in.begin(); it != signal_in.end(); it++) - fprintf(f, "\t%s <= #%d 0;\n", it->first.c_str(), ++delay_counter*2); - for (auto it = signal_clk.begin(); it != signal_clk.end(); it++) - fprintf(f, "\t%s <= #%d 0;\n", it->first.c_str(), ++delay_counter*2); - for (auto it = signal_clk.begin(); it != signal_clk.end(); it++) { - fprintf(f, "\t#100; %s <= 1;\n", it->first.c_str()); - fprintf(f, "\t#100; %s <= 0;\n", it->first.c_str()); - } - delay_counter = 0; - for (auto it = signal_in.begin(); it != signal_in.end(); it++) - fprintf(f, "\t%s <= #%d ~0;\n", it->first.c_str(), ++delay_counter*2); - for (auto it = signal_clk.begin(); it != signal_clk.end(); it++) { - fprintf(f, "\t#100; %s <= 1;\n", it->first.c_str()); - fprintf(f, "\t#100; %s <= 0;\n", it->first.c_str()); - } - delay_counter = 0; - for (auto it = signal_in.begin(); it != signal_in.end(); it++) { - if (signal_const.count(it->first) == 0) - continue; - fprintf(f, "\t%s <= #%d 'b%s;\n", it->first.c_str(), ++delay_counter*2, signal_const[it->first].c_str()); - } - fprintf(f, "end\n"); - fprintf(f, "endtask\n\n"); - - fprintf(f, "task %s;\n", idy(mod->name, "update_data").c_str()); - fprintf(f, "begin\n"); - delay_counter = 0; - for (auto it = signal_in.begin(); it != signal_in.end(); it++) { - if (signal_const.count(it->first) > 0) - continue; - fprintf(f, "\txorshift128;\n"); - fprintf(f, "\t%s <= #%d { xorshift128_x, xorshift128_y, xorshift128_z, xorshift128_w };\n", it->first.c_str(), ++delay_counter*2); - } - fprintf(f, "end\n"); - fprintf(f, "endtask\n\n"); - - fprintf(f, "task %s;\n", idy(mod->name, "update_clock").c_str()); - fprintf(f, "begin\n"); - if (signal_clk.size()) { - fprintf(f, "\txorshift128;\n"); - fprintf(f, "\t{"); - int total_clock_bits = 0; - for (auto it = signal_clk.begin(); it != signal_clk.end(); it++) { - fprintf(f, "%s %s", it == signal_clk.begin() ? "" : ",", it->first.c_str()); - total_clock_bits += it->second; - } - fprintf(f, " } = {"); - for (auto it = signal_clk.begin(); it != signal_clk.end(); it++) - fprintf(f, "%s %s", it == signal_clk.begin() ? "" : ",", it->first.c_str()); - fprintf(f, " } ^ (%d'b1 << (xorshift128_w %% %d));\n", total_clock_bits, total_clock_bits); - } - fprintf(f, "end\n"); - fprintf(f, "endtask\n\n"); - - char shorthand = 'A'; - std::vector<std::string> header1; - std::string header2 = ""; - - fprintf(f, "task %s;\n", idy(mod->name, "print_status").c_str()); - fprintf(f, "begin\n"); - fprintf(f, "\t$display(\"#OUT# %%b %%b %%b %%t %%d\", {"); - if (signal_in.size()) - for (auto it = signal_in.begin(); it != signal_in.end(); it++) { - fprintf(f, "%s %s", it == signal_in.begin() ? "" : ",", it->first.c_str()); - int len = it->second; - if (len > 1) - header2 += "/", len--; - while (len > 1) - header2 += "-", len--; - if (len > 0) - header2 += shorthand, len--; - header1.push_back(" " + it->first); - header1.back()[0] = shorthand++; - } - else { - fprintf(f, " 1'bx"); - header2 += "#"; - } - fprintf(f, " }, {"); - header2 += " "; - if (signal_clk.size()) { - for (auto it = signal_clk.begin(); it != signal_clk.end(); it++) { - fprintf(f, "%s %s", it == signal_clk.begin() ? "" : ",", it->first.c_str()); - int len = it->second; - if (len > 1) - header2 += "/", len--; - while (len > 1) - header2 += "-", len--; - if (len > 0) - header2 += shorthand, len--; - header1.push_back(" " + it->first); - header1.back()[0] = shorthand++; - } - } else { - fprintf(f, " 1'bx"); - header2 += "#"; - } - fprintf(f, " }, {"); - header2 += " "; - if (signal_out.size()) { - for (auto it = signal_out.begin(); it != signal_out.end(); it++) { - fprintf(f, "%s %s", it == signal_out.begin() ? "" : ",", it->first.c_str()); - int len = it->second; - if (len > 1) - header2 += "/", len--; - while (len > 1) - header2 += "-", len--; - if (len > 0) - header2 += shorthand, len--; - header1.push_back(" " + it->first); - header1.back()[0] = shorthand++; - } - } else { - fprintf(f, " 1'bx"); - header2 += "#"; - } - fprintf(f, " }, $time, i);\n"); - fprintf(f, "end\n"); - fprintf(f, "endtask\n\n"); - - fprintf(f, "task %s;\n", idy(mod->name, "print_header").c_str()); - fprintf(f, "begin\n"); - fprintf(f, "\t$display(\"#OUT#\");\n"); - for (auto &hdr : header1) - fprintf(f, "\t$display(\"#OUT# %s\");\n", hdr.c_str()); - fprintf(f, "\t$display(\"#OUT#\");\n"); - fprintf(f, "\t$display(\"#OUT# %s\");\n", header2.c_str()); - fprintf(f, "end\n"); - fprintf(f, "endtask\n\n"); - - fprintf(f, "task %s;\n", idy(mod->name, "test").c_str()); - fprintf(f, "begin\n"); - fprintf(f, "\t$display(\"#OUT#\\n#OUT# ==== %s ====\");\n", idy(mod->name).c_str()); - fprintf(f, "\t%s;\n", idy(mod->name, "reset").c_str()); - fprintf(f, "\tfor (i=0; i<%d; i=i+1) begin\n", NUM_ITER); - fprintf(f, "\t\tif (i %% 20 == 0) %s;\n", idy(mod->name, "print_header").c_str()); - fprintf(f, "\t\t#100; %s;\n", idy(mod->name, "update_data").c_str()); - fprintf(f, "\t\t#100; %s;\n", idy(mod->name, "update_clock").c_str()); - fprintf(f, "\t\t#100; %s;\n", idy(mod->name, "print_status").c_str()); - fprintf(f, "\tend\n"); - fprintf(f, "end\n"); - fprintf(f, "endtask\n\n"); - } - - fprintf(f, "initial begin\n"); - fprintf(f, "\t// $dumpfile(\"testbench.vcd\");\n"); - fprintf(f, "\t// $dumpvars(0, testbench);\n"); - for (auto it = design->modules.begin(); it != design->modules.end(); it++) - if (!it->second->get_bool_attribute("\\gentb_skip")) - fprintf(f, "\t%s;\n", idy(it->first, "test").c_str()); - fprintf(f, "\t$finish;\n"); - fprintf(f, "end\n\n"); - - fprintf(f, "endmodule\n"); -} - -struct AutotestBackend : public Backend { - AutotestBackend() : Backend("autotest", "generate simple test benches") { } - virtual void help() - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" write_autotest [filename]\n"); - log("\n"); - log("Automatically create primitive verilog test benches for all modules in the\n"); - log("design. The generated testbenches toggle the input pins of the module in\n"); - log("a semi-random manner and dumps the resulting output signals.\n"); - log("\n"); - log("This can be used to check the synthesis results for simple circuits by\n"); - log("comparing the testbench output for the input files and the synthesis results.\n"); - log("\n"); - log("The backend automatically detects clock signals. Additionally a signal can\n"); - log("be forced to be interpreted as clock signal by setting the attribute\n"); - log("'gentb_clock' on the signal.\n"); - log("\n"); - log("The attribute 'gentb_constant' can be used to force a signal to a constant\n"); - log("value after initialization. This can e.g. be used to force a reset signal\n"); - log("low in order to explore more inner states in a state machine.\n"); - log("\n"); - } - virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) - { - log_header("Executing AUTOTEST backend (auto-generate pseudo-random test benches).\n"); - extra_args(f, filename, args, 1); - autotest(f, design); - } -} AutotestBackend; - diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc index f5a982760..ee12546ce 100644 --- a/backends/blif/blif.cc +++ b/backends/blif/blif.cc @@ -27,29 +27,30 @@ #include "kernel/celltypes.h" #include "kernel/log.h" #include <string> -#include <assert.h> struct BlifDumperConfig { - bool subckt_mode; + bool icells_mode; bool conn_mode; bool impltf_mode; + bool gates_mode; + bool param_mode; std::string buf_type, buf_in, buf_out; std::string true_type, true_out, false_type, false_out; - BlifDumperConfig() : subckt_mode(false), conn_mode(false), impltf_mode(false) { } + BlifDumperConfig() : icells_mode(false), conn_mode(false), impltf_mode(false), gates_mode(false), param_mode(false) { } }; struct BlifDumper { - FILE *f; + std::ostream &f; RTLIL::Module *module; RTLIL::Design *design; BlifDumperConfig *config; CellTypes ct; - BlifDumper(FILE *f, RTLIL::Module *module, RTLIL::Design *design, BlifDumperConfig *config) : + BlifDumper(std::ostream &f, RTLIL::Module *module, RTLIL::Design *design, BlifDumperConfig *config) : f(f), module(module), design(design), config(config), ct(design) { } @@ -66,34 +67,42 @@ struct BlifDumper return cstr_buf.back().c_str(); } - const char *cstr(RTLIL::SigSpec sig) + const char *cstr(RTLIL::SigBit sig) { - sig.optimize(); - log_assert(sig.width == 1); + if (sig.wire == NULL) + return sig == RTLIL::State::S1 ? "$true" : "$false"; - if (sig.chunks.at(0).wire == NULL) - return sig.chunks.at(0).data.bits.at(0) == RTLIL::State::S1 ? "$true" : "$false"; - - std::string str = RTLIL::unescape_id(sig.chunks.at(0).wire->name); + std::string str = RTLIL::unescape_id(sig.wire->name); for (size_t i = 0; i < str.size(); i++) if (str[i] == '#' || str[i] == '=') str[i] = '?'; - if (sig.chunks.at(0).wire->width != 1) - str += stringf("[%d]", sig.chunks.at(0).offset); + if (sig.wire->width != 1) + str += stringf("[%d]", sig.offset); cstr_buf.push_back(str); return cstr_buf.back().c_str(); } + const char *subckt_or_gate(std::string cell_type) + { + if (!config->gates_mode) + return "subckt"; + if (!design->modules_.count(RTLIL::escape_id(cell_type))) + return "gate"; + if (design->modules_.at(RTLIL::escape_id(cell_type))->get_bool_attribute("\\blackbox")) + return "gate"; + return "subckt"; + } + void dump() { - fprintf(f, "\n"); - fprintf(f, ".model %s\n", cstr(module->name)); + f << stringf("\n"); + f << stringf(".model %s\n", cstr(module->name)); std::map<int, RTLIL::Wire*> inputs, outputs; - for (auto &wire_it : module->wires) { + for (auto &wire_it : module->wires_) { RTLIL::Wire *wire = wire_it.second; if (wire->port_input) inputs[wire->port_id] = wire; @@ -101,107 +110,150 @@ struct BlifDumper outputs[wire->port_id] = wire; } - fprintf(f, ".inputs"); + f << stringf(".inputs"); for (auto &it : inputs) { RTLIL::Wire *wire = it.second; for (int i = 0; i < wire->width; i++) - fprintf(f, " %s", cstr(RTLIL::SigSpec(wire, 1, i))); + f << stringf(" %s", cstr(RTLIL::SigSpec(wire, i))); } - fprintf(f, "\n"); + f << stringf("\n"); - fprintf(f, ".outputs"); + f << stringf(".outputs"); for (auto &it : outputs) { RTLIL::Wire *wire = it.second; for (int i = 0; i < wire->width; i++) - fprintf(f, " %s", cstr(RTLIL::SigSpec(wire, 1, i))); + f << stringf(" %s", cstr(RTLIL::SigSpec(wire, i))); } - fprintf(f, "\n"); + f << stringf("\n"); if (!config->impltf_mode) { if (!config->false_type.empty()) - fprintf(f, ".subckt %s %s=$false\n", config->false_type.c_str(), config->false_out.c_str()); + f << stringf(".%s %s %s=$false\n", subckt_or_gate(config->false_type), + config->false_type.c_str(), config->false_out.c_str()); else - fprintf(f, ".names $false\n"); + f << stringf(".names $false\n"); if (!config->true_type.empty()) - fprintf(f, ".subckt %s %s=$true\n", config->true_type.c_str(), config->true_out.c_str()); + f << stringf(".%s %s %s=$true\n", subckt_or_gate(config->true_type), + config->true_type.c_str(), config->true_out.c_str()); else - fprintf(f, ".names $true\n1\n"); + f << stringf(".names $true\n1\n"); } - for (auto &cell_it : module->cells) + for (auto &cell_it : module->cells_) { RTLIL::Cell *cell = cell_it.second; - if (!config->subckt_mode && cell->type == "$_INV_") { - fprintf(f, ".names %s %s\n0 1\n", - cstr(cell->connections.at("\\A")), cstr(cell->connections.at("\\Y"))); + if (!config->icells_mode && cell->type == "$_NOT_") { + f << stringf(".names %s %s\n0 1\n", + cstr(cell->getPort("\\A")), cstr(cell->getPort("\\Y"))); + continue; + } + + if (!config->icells_mode && cell->type == "$_AND_") { + f << stringf(".names %s %s %s\n11 1\n", + cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y"))); continue; } - if (!config->subckt_mode && cell->type == "$_AND_") { - fprintf(f, ".names %s %s %s\n11 1\n", - cstr(cell->connections.at("\\A")), cstr(cell->connections.at("\\B")), cstr(cell->connections.at("\\Y"))); + if (!config->icells_mode && cell->type == "$_OR_") { + f << stringf(".names %s %s %s\n1- 1\n-1 1\n", + cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y"))); continue; } - if (!config->subckt_mode && cell->type == "$_OR_") { - fprintf(f, ".names %s %s %s\n1- 1\n-1 1\n", - cstr(cell->connections.at("\\A")), cstr(cell->connections.at("\\B")), cstr(cell->connections.at("\\Y"))); + if (!config->icells_mode && cell->type == "$_XOR_") { + f << stringf(".names %s %s %s\n10 1\n01 1\n", + cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y"))); continue; } - if (!config->subckt_mode && cell->type == "$_XOR_") { - fprintf(f, ".names %s %s %s\n10 1\n01 1\n", - cstr(cell->connections.at("\\A")), cstr(cell->connections.at("\\B")), cstr(cell->connections.at("\\Y"))); + if (!config->icells_mode && cell->type == "$_MUX_") { + f << stringf(".names %s %s %s %s\n1-0 1\n-11 1\n", + cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), + cstr(cell->getPort("\\S")), cstr(cell->getPort("\\Y"))); continue; } - if (!config->subckt_mode && cell->type == "$_MUX_") { - fprintf(f, ".names %s %s %s %s\n1-0 1\n-11 1\n", - cstr(cell->connections.at("\\A")), cstr(cell->connections.at("\\B")), - cstr(cell->connections.at("\\S")), cstr(cell->connections.at("\\Y"))); + if (!config->icells_mode && cell->type == "$_DFF_N_") { + f << stringf(".latch %s %s fe %s\n", + cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")), cstr(cell->getPort("\\C"))); continue; } - if (!config->subckt_mode && cell->type == "$_DFF_N_") { - fprintf(f, ".latch %s %s fe %s\n", - cstr(cell->connections.at("\\D")), cstr(cell->connections.at("\\Q")), cstr(cell->connections.at("\\C"))); + if (!config->icells_mode && cell->type == "$_DFF_P_") { + f << stringf(".latch %s %s re %s\n", + cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")), cstr(cell->getPort("\\C"))); continue; } - if (!config->subckt_mode && cell->type == "$_DFF_P_") { - fprintf(f, ".latch %s %s re %s\n", - cstr(cell->connections.at("\\D")), cstr(cell->connections.at("\\Q")), cstr(cell->connections.at("\\C"))); + if (!config->icells_mode && cell->type == "$lut") { + f << stringf(".names"); + auto &inputs = cell->getPort("\\A"); + auto width = cell->parameters.at("\\WIDTH").as_int(); + log_assert(inputs.size() == width); + for (int i = 0; i < inputs.size(); i++) { + f << stringf(" %s", cstr(inputs.extract(i, 1))); + } + auto &output = cell->getPort("\\Y"); + log_assert(output.size() == 1); + f << stringf(" %s", cstr(output)); + f << stringf("\n"); + auto mask = cell->parameters.at("\\LUT").as_string(); + for (int i = 0; i < (1 << width); i++) { + if (mask[i] == '0') continue; + for (int j = width-1; j >= 0; j--) { + f << ((i>>j)&1 ? '1' : '0'); + } + f << stringf(" %c\n", mask[i]); + } continue; } - fprintf(f, ".subckt %s", cstr(cell->type)); - for (auto &conn : cell->connections) - for (int i = 0; i < conn.second.width; i++) { - if (conn.second.width == 1) - fprintf(f, " %s", cstr(conn.first)); + 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 - fprintf(f, " %s[%d]", cstr(conn.first), i); - fprintf(f, "=%s", cstr(conn.second.extract(i, 1))); + f << stringf(" %s[%d]", cstr(conn.first), i); + f << stringf("=%s", cstr(conn.second.extract(i, 1))); } - fprintf(f, "\n"); + f << stringf("\n"); + + if (config->param_mode) + for (auto ¶m : cell->parameters) { + f << stringf(".param %s ", RTLIL::id2cstr(param.first)); + if (param.second.flags & RTLIL::CONST_FLAG_STRING) { + std::string str = param.second.decode_string(); + f << stringf("\""); + for (char ch : str) + if (ch == '"' || ch == '\\') + f << stringf("\\%c", ch); + else if (ch < 32 || ch >= 127) + f << stringf("\\%03o", ch); + else + f << stringf("%c", ch); + f << stringf("\"\n"); + } else + f << stringf("%s\n", param.second.as_string().c_str()); + } } - for (auto &conn : module->connections) - for (int i = 0; i < conn.first.width; i++) + for (auto &conn : module->connections()) + for (int i = 0; i < conn.first.size(); i++) if (config->conn_mode) - fprintf(f, ".conn %s %s\n", cstr(conn.second.extract(i, 1)), cstr(conn.first.extract(i, 1))); + f << stringf(".conn %s %s\n", cstr(conn.second.extract(i, 1)), cstr(conn.first.extract(i, 1))); else if (!config->buf_type.empty()) - fprintf(f, ".subckt %s %s=%s %s=%s\n", config->buf_type.c_str(), config->buf_in.c_str(), cstr(conn.second.extract(i, 1)), + f << stringf(".%s %s %s=%s %s=%s\n", subckt_or_gate(config->buf_type), config->buf_type.c_str(), config->buf_in.c_str(), cstr(conn.second.extract(i, 1)), config->buf_out.c_str(), cstr(conn.first.extract(i, 1))); else - fprintf(f, ".names %s %s\n1 1\n", cstr(conn.second.extract(i, 1)), cstr(conn.first.extract(i, 1))); + f << stringf(".names %s %s\n1 1\n", cstr(conn.second.extract(i, 1)), cstr(conn.first.extract(i, 1))); - fprintf(f, ".end\n"); + f << stringf(".end\n"); } - static void dump(FILE *f, RTLIL::Module *module, RTLIL::Design *design, BlifDumperConfig &config) + static void dump(std::ostream &f, RTLIL::Module *module, RTLIL::Design *design, BlifDumperConfig &config) { BlifDumper dumper(f, module, design, &config); dumper.dump(); @@ -228,23 +280,30 @@ struct BlifBackend : public Backend { log(" -false <cell-type> <out-port>\n"); log(" use the specified cell types to drive nets that are constant 1 or 0\n"); log("\n"); - log("The following options can be usefull when the generated file is not going to be\n"); + log("The following options can be useful when the generated file is not going to be\n"); log("read by a BLIF parser but a custom tool. It is recommended to not name the output\n"); log("file *.blif when any of this options is used.\n"); log("\n"); - log(" -subckt\n"); + log(" -icells\n"); log(" do not translate Yosys's internal gates to generic BLIF logic\n"); - log(" functions. Instead create .subckt lines for all cells.\n"); + log(" functions. Instead create .subckt or .gate lines for all cells.\n"); + log("\n"); + log(" -gates\n"); + log(" print .gate instead of .subckt lines for all cells that are not\n"); + log(" instantiations of other modules from this design.\n"); log("\n"); log(" -conn\n"); log(" do not generate buffers for connected wires. instead use the\n"); log(" non-standard .conn statement.\n"); log("\n"); + log(" -param\n"); + log(" use the non-standard .param statement to write module parameters\n"); + log("\n"); log(" -impltf\n"); log(" do not write definitions for the $true and $false wires.\n"); log("\n"); } - virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) + virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) { std::string top_module_name; std::string buf_type, buf_in, buf_out; @@ -277,14 +336,22 @@ struct BlifBackend : public Backend { config.false_out = args[++argidx]; continue; } - if (args[argidx] == "-subckt") { - config.subckt_mode = true; + if (args[argidx] == "-icells") { + config.icells_mode = true; + continue; + } + if (args[argidx] == "-gates") { + config.gates_mode = true; continue; } if (args[argidx] == "-conn") { config.conn_mode = true; continue; } + if (args[argidx] == "-param") { + config.param_mode = true; + continue; + } if (args[argidx] == "-impltf") { config.impltf_mode = true; continue; @@ -294,15 +361,15 @@ struct BlifBackend : public Backend { extra_args(f, filename, args, argidx); if (top_module_name.empty()) - for (auto & mod_it:design->modules) + for (auto & mod_it:design->modules_) if (mod_it.second->get_bool_attribute("\\top")) - top_module_name = mod_it.first; + top_module_name = mod_it.first.str(); - fprintf(f, "# Generated by %s\n", yosys_version_str); + *f << stringf("# Generated by %s\n", yosys_version_str); std::vector<RTLIL::Module*> mod_list; - for (auto module_it : design->modules) + for (auto module_it : design->modules_) { RTLIL::Module *module = module_it.second; if (module->get_bool_attribute("\\blackbox")) @@ -314,7 +381,7 @@ struct BlifBackend : public Backend { log_error("Found munmapped emories in module %s: unmapped memories are not supported in BLIF backend!\n", RTLIL::id2cstr(module->name)); if (module->name == RTLIL::escape_id(top_module_name)) { - BlifDumper::dump(f, module, design, config); + BlifDumper::dump(*f, module, design, config); top_module_name.clear(); continue; } @@ -326,7 +393,7 @@ struct BlifBackend : public Backend { log_error("Can't find top module `%s'!\n", top_module_name.c_str()); for (auto module : mod_list) - BlifDumper::dump(f, module, design, config); + BlifDumper::dump(*f, module, design, config); } } BlifBackend; diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index abe09943a..8ce5bb5ed 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -28,7 +28,6 @@ #include "kernel/celltypes.h" #include "kernel/log.h" #include <string> -#include <assert.h> #include <math.h> struct BtorDumperConfig @@ -46,9 +45,9 @@ struct BtorDumperConfig struct WireInfo { RTLIL::IdString cell_name; - RTLIL::SigChunk *chunk; + const RTLIL::SigChunk *chunk; - WireInfo(RTLIL::IdString c, RTLIL::SigChunk* ch) : cell_name(c), chunk(ch) { } + WireInfo(RTLIL::IdString c, const RTLIL::SigChunk* ch) : cell_name(c), chunk(ch) { } }; struct WireInfoOrder @@ -61,7 +60,7 @@ struct WireInfoOrder struct BtorDumper { - FILE *f; + std::ostream &f; RTLIL::Module *module; RTLIL::Design *design; BtorDumperConfig *config; @@ -75,14 +74,14 @@ struct BtorDumper std::string str;//temp string for writing file std::map<RTLIL::IdString, bool> basic_wires;//input wires and registers RTLIL::IdString curr_cell; //current cell being dumped - std::set<int> mem_next; //if memory (line_number) already has next - std::map<std::string, std::string> cell_type_translation, s_cell_type_translation; //RTLIL to BTOR translation - BtorDumper(FILE *f, RTLIL::Module *module, RTLIL::Design *design, BtorDumperConfig *config) : - f(f), module(module), design(design), config(config), ct(design), sigmap(module) + std::map<std::string, std::string> cell_type_translation, s_cell_type_translation; //RTLIL to BTOR translation + std::set<int> mem_next; //if memory (line_number) already has next + BtorDumper(std::ostream &f, RTLIL::Module *module, RTLIL::Design *design, BtorDumperConfig *config) : + f(f), module(module), design(design), config(config), ct(design), sigmap(module) { line_num=0; str.clear(); - for(auto it=module->wires.begin(); it!=module->wires.end(); ++it) + for(auto it=module->wires_.begin(); it!=module->wires_.end(); ++it) { if(it->second->port_input) { @@ -113,6 +112,8 @@ struct BtorDumper cell_type_translation["$shl"] = "sll"; cell_type_translation["$sshr"] = "sra"; cell_type_translation["$sshl"] = "sll"; + cell_type_translation["$shift"] = "srl"; + cell_type_translation["$shiftx"] = "srl"; cell_type_translation["$lt"] = "ult"; cell_type_translation["$le"] = "ulte"; cell_type_translation["$gt"] = "ugt"; @@ -174,7 +175,7 @@ struct BtorDumper ++line_num; line_ref[wire->name]=line_num; str = stringf("%d var %d %s", line_num, wire->width, cstr(wire->name)); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); return line_num; } else return it->second; @@ -194,11 +195,11 @@ struct BtorDumper if(cell_id == curr_cell) break; log(" -- found cell %s\n", cstr(cell_id)); - RTLIL::Cell* cell = module->cells.at(cell_id); - RTLIL::SigSpec* cell_output = get_cell_output(cell); + RTLIL::Cell* cell = module->cells_.at(cell_id); + const RTLIL::SigSpec* cell_output = get_cell_output(cell); int cell_line = dump_cell(cell); - if(dep_set.size()==1 && wire->width == cell_output->width) + if(dep_set.size()==1 && wire->width == cell_output->size()) { wire_line = cell_line; break; @@ -207,22 +208,22 @@ struct BtorDumper { int prev_wire_line=0; //previously dumped wire line int start_bit=0; - for(unsigned j=0; j<cell_output->chunks.size(); ++j) + for(unsigned j=0; j<cell_output->chunks().size(); ++j) { - start_bit+=cell_output->chunks[j].width; - if(cell_output->chunks[j].wire->name == wire->name) + start_bit+=cell_output->chunks().at(j).width; + if(cell_output->chunks().at(j).wire->name == wire->name) { prev_wire_line = wire_line; wire_line = ++line_num; - str = stringf("%d slice %d %d %d %d;1", line_num, cell_output->chunks[j].width, - cell_line, start_bit-1, start_bit-cell_output->chunks[j].width); - fprintf(f, "%s\n", str.c_str()); - wire_width += cell_output->chunks[j].width; + str = stringf("%d slice %d %d %d %d;1", line_num, cell_output->chunks().at(j).width, + cell_line, start_bit-1, start_bit-cell_output->chunks().at(j).width); + f << stringf("%s\n", str.c_str()); + wire_width += cell_output->chunks().at(j).width; if(prev_wire_line!=0) { ++line_num; str = stringf("%d concat %d %d %d", line_num, wire_width, wire_line, prev_wire_line); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); wire_line = line_num; } } @@ -233,7 +234,7 @@ struct BtorDumper { log(" - checking sigmap\n"); RTLIL::SigSpec s = RTLIL::SigSpec(wire); - wire_line = dump_sigspec(&s, s.width); + wire_line = dump_sigspec(&s, s.size()); line_ref[wire->name]=wire_line; } line_ref[wire->name]=wire_line; @@ -245,7 +246,7 @@ struct BtorDumper return it->second; } } - assert(false); + log_abort(); return -1; } @@ -259,7 +260,7 @@ struct BtorDumper int address_bits = ceil(log(memory->size)/log(2)); str = stringf("%d array %d %d", line_num, memory->width, address_bits); line_ref[memory->name]=line_num; - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); return line_num; } else return it->second; @@ -279,12 +280,12 @@ struct BtorDumper ++line_num; str = stringf("%d const %d %s", line_num, width, data_str.c_str()); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); return line_num; } else log("writing const error\n"); - assert(false); + log_abort(); return -1; } @@ -294,7 +295,8 @@ struct BtorDumper int l=-1; if(chunk->wire == NULL) { - l=dump_const(&chunk->data, chunk->width, chunk->offset); + RTLIL::Const data_const(chunk->data); + l=dump_const(&data_const, chunk->width, chunk->offset); } else { @@ -303,11 +305,11 @@ struct BtorDumper else { int wire_line_num = dump_wire(chunk->wire); - assert(wire_line_num>0); + log_assert(wire_line_num>0); ++line_num; str = stringf("%d slice %d %d %d %d;2", line_num, chunk->width, wire_line_num, chunk->width + chunk->offset - 1, chunk->offset); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); l = line_num; } } @@ -322,24 +324,24 @@ struct BtorDumper auto it = sig_ref.find(s); if(it == std::end(sig_ref)) { - if (s.chunks.size() == 1) + if (s.is_chunk()) { - l = dump_sigchunk(&s.chunks[0]); + l = dump_sigchunk(&s.chunks().front()); } else { int l1, l2, w1, w2; - l1 = dump_sigchunk(&s.chunks[0]); - assert(l1>0); - w1 = s.chunks[0].width; - for (unsigned i=1; i < s.chunks.size(); ++i) + l1 = dump_sigchunk(&s.chunks().front()); + log_assert(l1>0); + w1 = s.chunks().front().width; + for (unsigned i=1; i < s.chunks().size(); ++i) { - l2 = dump_sigchunk(&s.chunks[i]); - assert(l2>0); - w2 = s.chunks[i].width; + l2 = dump_sigchunk(&s.chunks().at(i)); + log_assert(l2>0); + w2 = s.chunks().at(i).width; ++line_num; str = stringf("%d concat %d %d %d", line_num, w1+w2, l2, l1); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); l1=line_num; w1+=w2; } @@ -352,30 +354,30 @@ struct BtorDumper l = it->second; } - if (expected_width != s.width) + if (expected_width != s.size()) { log(" - changing width of sigspec\n"); //TODO: this block may not be needed anymore, due to explicit type conversion by "splice" command - if(expected_width > s.width) + if(expected_width > s.size()) { //TODO: case the signal is signed ++line_num; - str = stringf ("%d zero %d", line_num, expected_width - s.width); - fprintf(f, "%s\n", str.c_str()); + str = stringf ("%d zero %d", line_num, expected_width - s.size()); + f << stringf("%s\n", str.c_str()); ++line_num; str = stringf ("%d concat %d %d %d", line_num, expected_width, line_num-1, l); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); l = line_num; } - else if(expected_width < s.width) + else if(expected_width < s.size()) { ++line_num; str = stringf ("%d slice %d %d %d %d;3", line_num, expected_width, l, expected_width-1, 0); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); l = line_num; } } - assert(l>0); + log_assert(l>0); return l; } @@ -389,29 +391,29 @@ struct BtorDumper if(cell->type == "$assert") { log("writing assert cell - %s\n", cstr(cell->type)); - const RTLIL::SigSpec* expr = &cell->connections.at(RTLIL::IdString("\\A")); - const RTLIL::SigSpec* en = &cell->connections.at(RTLIL::IdString("\\EN")); - assert(expr->width == 1); - assert(en->width == 1); + const RTLIL::SigSpec* expr = &cell->getPort(RTLIL::IdString("\\A")); + const RTLIL::SigSpec* en = &cell->getPort(RTLIL::IdString("\\EN")); + log_assert(expr->size() == 1); + log_assert(en->size() == 1); int expr_line = dump_sigspec(expr, 1); int en_line = dump_sigspec(en, 1); int one_line = ++line_num; str = stringf("%d one 1", line_num); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); ++line_num; str = stringf("%d %s %d %d %d", line_num, cell_type_translation.at("$eq").c_str(), 1, en_line, one_line); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); ++line_num; str = stringf("%d %s %d %d %d %d", line_num, cell_type_translation.at("$mux").c_str(), 1, line_num-1, expr_line, one_line); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); int cell_line = ++line_num; str = stringf("%d %s %d %d", line_num, cell_type_translation.at("$assert").c_str(), 1, -1*(line_num-1)); //multiplying the line number with -1, which means logical negation //the reason for negative sign is that the properties in btor are given as "negation of the original property" //bug identified by bobosoft //http://www.reddit.com/r/yosys/comments/1w3xig/btor_backend_bug/ - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); line_ref[cell->name]=cell_line; } //unary cells @@ -422,20 +424,20 @@ struct BtorDumper int w = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int(); int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int(); w = w>output_width ? w:output_width; //padding of w - int l = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\A")), w); + int l = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), w); int cell_line = l; if(cell->type != "$pos") { cell_line = ++line_num; bool reduced = (cell->type == "$not" || cell->type == "$neg") ? false : true; - str = stringf ("%d %s %d %d", cell_line, cell_type_translation.at(cell->type).c_str(), reduced?output_width:w, l); - fprintf(f, "%s\n", str.c_str()); + str = stringf ("%d %s %d %d", cell_line, cell_type_translation.at(cell->type.str()).c_str(), reduced?output_width:w, l); + f << stringf("%s\n", str.c_str()); } if(output_width < w && (cell->type == "$not" || cell->type == "$neg" || cell->type == "$pos")) { ++line_num; str = stringf ("%d slice %d %d %d %d;4", line_num, output_width, cell_line, output_width-1, 0); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); cell_line = line_num; } line_ref[cell->name]=cell_line; @@ -445,25 +447,23 @@ struct BtorDumper log("writing unary cell - %s\n", cstr(cell->type)); int w = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int(); int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int(); - assert(output_width == 1); - int l = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\A")), w); + log_assert(output_width == 1); + int l = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), w); if(cell->type == "$logic_not" && w > 1) { ++line_num; str = stringf ("%d %s %d %d", line_num, cell_type_translation.at("$reduce_or").c_str(), output_width, l); - fprintf(f, "%s\n", str.c_str()); - l = line_num; + f << stringf("%s\n", str.c_str()); } else if(cell->type == "$reduce_xnor") { ++line_num; str = stringf ("%d %s %d %d", line_num, cell_type_translation.at("$reduce_xor").c_str(), output_width, l); - fprintf(f, "%s\n", str.c_str()); - l = line_num; + f << stringf("%s\n", str.c_str()); } ++line_num; str = stringf ("%d %s %d %d", line_num, cell_type_translation.at("$not").c_str(), output_width, l); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); line_ref[cell->name]=line_num; } //binary cells @@ -473,7 +473,7 @@ struct BtorDumper { log("writing binary cell - %s\n", cstr(cell->type)); int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int(); - assert(!(cell->type == "$eq" || cell->type == "$ne" || cell->type == "$eqx" || cell->type == "$nex" || + log_assert(!(cell->type == "$eq" || cell->type == "$ne" || cell->type == "$eqx" || cell->type == "$nex" || cell->type == "$ge" || cell->type == "$gt") || output_width == 1); bool l1_signed = cell->parameters.at(RTLIL::IdString("\\A_SIGNED")).as_bool(); bool l2_signed = cell->parameters.at(RTLIL::IdString("\\B_SIGNED")).as_bool(); @@ -485,21 +485,21 @@ struct BtorDumper l1_width = l1_width > l2_width ? l1_width : l2_width; l2_width = l2_width > l1_width ? l2_width : l1_width; - int l1 = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\A")), l1_width); - int l2 = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\B")), l2_width); + int l1 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), l1_width); + int l2 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), l2_width); ++line_num; - std::string op = cell_type_translation.at(cell->type); + std::string op = cell_type_translation.at(cell->type.str()); if(cell->type == "$lt" || cell->type == "$le" || cell->type == "$eq" || cell->type == "$ne" || cell->type == "$eqx" || cell->type == "$nex" || cell->type == "$ge" || cell->type == "$gt") { if(l1_signed) - op = s_cell_type_translation.at(cell->type); + op = s_cell_type_translation.at(cell->type.str()); } str = stringf ("%d %s %d %d %d", line_num, op.c_str(), output_width, l1, l2); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); line_ref[cell->name]=line_num; } @@ -514,18 +514,18 @@ struct BtorDumper int l1_width = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int(); int l2_width = cell->parameters.at(RTLIL::IdString("\\B_WIDTH")).as_int(); - assert(l1_signed == l2_signed); + log_assert(l1_signed == l2_signed); l1_width = l1_width > output_width ? l1_width : output_width; l1_width = l1_width > l2_width ? l1_width : l2_width; l2_width = l2_width > l1_width ? l2_width : l1_width; - int l1 = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\A")), l1_width); - int l2 = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\B")), l2_width); + int l1 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), l1_width); + int l2 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), l2_width); ++line_num; - std::string op = cell_type_translation.at(cell->type); + std::string op = cell_type_translation.at(cell->type.str()); if(cell->type == "$div" && l1_signed) - op = s_cell_type_translation.at(cell->type); + op = s_cell_type_translation.at(cell->type.str()); else if(cell->type == "$mod") { if(l1_signed) @@ -534,17 +534,17 @@ struct BtorDumper op = s_cell_type_translation.at("$mody"); } str = stringf ("%d %s %d %d %d", line_num, op.c_str(), l1_width, l1, l2); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); if(output_width < l1_width) { ++line_num; str = stringf ("%d slice %d %d %d %d;5", line_num, output_width, line_num-1, output_width-1, 0); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); } line_ref[cell->name]=line_num; } - else if(cell->type == "$shr" || cell->type == "$shl" || cell->type == "$sshr" || cell->type == "$sshl") + else if(cell->type == "$shr" || cell->type == "$shl" || cell->type == "$sshr" || cell->type == "$sshl" || cell->type == "$shift" || cell->type == "$shiftx") { log("writing binary cell - %s\n", cstr(cell->type)); int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int(); @@ -553,32 +553,32 @@ struct BtorDumper int l1_width = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int(); l1_width = pow(2, ceil(log(l1_width)/log(2))); int l2_width = cell->parameters.at(RTLIL::IdString("\\B_WIDTH")).as_int(); - //assert(l2_width <= ceil(log(l1_width)/log(2)) ); - int l1 = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\A")), l1_width); - int l2 = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\B")), ceil(log(l1_width)/log(2))); + //log_assert(l2_width <= ceil(log(l1_width)/log(2)) ); + int l1 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), l1_width); + int l2 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), ceil(log(l1_width)/log(2))); int cell_output = ++line_num; - str = stringf ("%d %s %d %d %d", line_num, cell_type_translation.at(cell->type).c_str(), l1_width, l1, l2); - fprintf(f, "%s\n", str.c_str()); + str = stringf ("%d %s %d %d %d", line_num, cell_type_translation.at(cell->type.str()).c_str(), l1_width, l1, l2); + f << stringf("%s\n", str.c_str()); if(l2_width > ceil(log(l1_width)/log(2))) { int extra_width = l2_width - ceil(log(l1_width)/log(2)); - l2 = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\B")), l2_width); + l2 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), l2_width); ++line_num; str = stringf ("%d slice %d %d %d %d;6", line_num, extra_width, l2, l2_width-1, l2_width-extra_width); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); ++line_num; str = stringf ("%d one %d", line_num, extra_width); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); int mux = ++line_num; str = stringf ("%d %s %d %d %d", line_num, cell_type_translation.at("$gt").c_str(), 1, line_num-2, line_num-1); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); ++line_num; str = stringf("%d %s %d", line_num, l1_signed && cell->type == "$sshr" ? "ones":"zero", l1_width); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); ++line_num; str = stringf ("%d %s %d %d %d %d", line_num, cell_type_translation.at("$mux").c_str(), l1_width, mux, line_num-1, cell_output); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); cell_output = line_num; } @@ -586,7 +586,7 @@ struct BtorDumper { ++line_num; str = stringf ("%d slice %d %d %d %d;5", line_num, output_width, cell_output, output_width-1, 0); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); cell_output = line_num; } line_ref[cell->name] = cell_output; @@ -595,23 +595,23 @@ struct BtorDumper { log("writing binary cell - %s\n", cstr(cell->type)); int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int(); - assert(output_width == 1); - int l1 = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\A")), output_width); - int l2 = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\B")), output_width); + log_assert(output_width == 1); + int l1 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), output_width); + int l2 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), output_width); int l1_width = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int(); int l2_width = cell->parameters.at(RTLIL::IdString("\\B_WIDTH")).as_int(); if(l1_width >1) { ++line_num; str = stringf ("%d %s %d %d", line_num, cell_type_translation.at("$reduce_or").c_str(), output_width, l1); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); l1 = line_num; } if(l2_width > 1) { ++line_num; str = stringf ("%d %s %d %d", line_num, cell_type_translation.at("$reduce_or").c_str(), output_width, l2); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); l2 = line_num; } if(cell->type == "$logic_and") @@ -624,7 +624,7 @@ struct BtorDumper ++line_num; str = stringf ("%d %s %d %d %d", line_num, cell_type_translation.at("$or").c_str(), output_width, l1, l2); } - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); line_ref[cell->name]=line_num; } //multiplexers @@ -632,13 +632,14 @@ struct BtorDumper { log("writing mux cell\n"); int output_width = cell->parameters.at(RTLIL::IdString("\\WIDTH")).as_int(); - int l1 = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\A")), output_width); - int l2 = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\B")), output_width); - int s = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\S")), 1); + int l1 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), output_width); + int l2 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), output_width); + int s = dump_sigspec(&cell->getPort(RTLIL::IdString("\\S")), 1); ++line_num; str = stringf ("%d %s %d %d %d %d", - line_num, cell_type_translation.at(cell->type).c_str(), output_width, s, l2, l1);//if s is 0 then l1, if s is 1 then l2 //according to the implementation of mux cell - fprintf(f, "%s\n", str.c_str()); + line_num, cell_type_translation.at(cell->type.str()).c_str(), output_width, s, l2, l1); + //if s is 0 then l1, if s is 1 then l2 //according to the implementation of mux cell + f << stringf("%s\n", str.c_str()); line_ref[cell->name]=line_num; } else if(cell->type == "$pmux") @@ -646,97 +647,97 @@ struct BtorDumper log("writing pmux cell\n"); int output_width = cell->parameters.at(RTLIL::IdString("\\WIDTH")).as_int(); int select_width = cell->parameters.at(RTLIL::IdString("\\S_WIDTH")).as_int(); - int default_case = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\A")), output_width); - int cases = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\B")), output_width*select_width); - int select = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\S")), select_width); + int default_case = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), output_width); + int cases = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), output_width*select_width); + int select = dump_sigspec(&cell->getPort(RTLIL::IdString("\\S")), select_width); int *c = new int[select_width]; for (int i=0; i<select_width; ++i) { ++line_num; str = stringf ("%d slice 1 %d %d %d", line_num, select, i, i); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); c[i] = line_num; ++line_num; str = stringf ("%d slice %d %d %d %d", line_num, output_width, cases, i*output_width+output_width-1, i*output_width); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); } ++line_num; str = stringf ("%d cond %d %d %d %d", line_num, output_width, c[select_width-1], c[select_width-1]+1, default_case); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); for (int i=select_width-2; i>=0; --i) { ++line_num; str = stringf ("%d cond %d %d %d %d", line_num, output_width, c[i], c[i]+1, line_num-1); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); } line_ref[cell->name]=line_num; } - //registers + //registers else if(cell->type == "$dff" || cell->type == "$adff" || cell->type == "$dffsr") { //TODO: remodelling fo adff cells log("writing cell - %s\n", cstr(cell->type)); int output_width = cell->parameters.at(RTLIL::IdString("\\WIDTH")).as_int(); log(" - width is %d\n", output_width); - int cond = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\CLK")), 1); + int cond = dump_sigspec(&cell->getPort(RTLIL::IdString("\\CLK")), 1); bool polarity = cell->parameters.at(RTLIL::IdString("\\CLK_POLARITY")).as_bool(); - const RTLIL::SigSpec* cell_output = &cell->connections.at(RTLIL::IdString("\\Q")); - int value = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\D")), output_width); + const RTLIL::SigSpec* cell_output = &cell->getPort(RTLIL::IdString("\\Q")); + int value = dump_sigspec(&cell->getPort(RTLIL::IdString("\\D")), output_width); unsigned start_bit = 0; - for(unsigned i=0; i<cell_output->chunks.size(); ++i) + for(unsigned i=0; i<cell_output->chunks().size(); ++i) { - output_width = cell_output->chunks[i].width; - assert( output_width == cell_output->chunks[i].wire->width);//full reg is given the next value - int reg = dump_wire(cell_output->chunks[i].wire);//register + output_width = cell_output->chunks().at(i).width; + log_assert( output_width == cell_output->chunks().at(i).wire->width);//full reg is given the next value + int reg = dump_wire(cell_output->chunks().at(i).wire);//register int slice = value; - if(cell_output->chunks.size()>1) + if(cell_output->chunks().size()>1) { start_bit+=output_width; slice = ++line_num; str = stringf ("%d slice %d %d %d %d;", line_num, output_width, value, start_bit-1, start_bit-output_width); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); } if(cell->type == "$dffsr") { - int sync_reset = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\CLR")), 1); + int sync_reset = dump_sigspec(&cell->getPort(RTLIL::IdString("\\CLR")), 1); bool sync_reset_pol = cell->parameters.at(RTLIL::IdString("\\CLR_POLARITY")).as_bool(); - int sync_reset_value = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\SET")), + int sync_reset_value = dump_sigspec(&cell->getPort(RTLIL::IdString("\\SET")), output_width); bool sync_reset_value_pol = cell->parameters.at(RTLIL::IdString("\\SET_POLARITY")).as_bool(); ++line_num; str = stringf ("%d %s %d %s%d %s%d %d", line_num, cell_type_translation.at("$mux").c_str(), output_width, sync_reset_pol ? "":"-", sync_reset, sync_reset_value_pol? "":"-", sync_reset_value, slice); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); slice = line_num; } ++line_num; str = stringf ("%d %s %d %s%d %d %d", line_num, cell_type_translation.at("$mux").c_str(), output_width, polarity?"":"-", cond, slice, reg); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); int next = line_num; if(cell->type == "$adff") { - int async_reset = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\ARST")), 1); + int async_reset = dump_sigspec(&cell->getPort(RTLIL::IdString("\\ARST")), 1); bool async_reset_pol = cell->parameters.at(RTLIL::IdString("\\ARST_POLARITY")).as_bool(); int async_reset_value = dump_const(&cell->parameters.at(RTLIL::IdString("\\ARST_VALUE")), output_width, 0); ++line_num; str = stringf ("%d %s %d %s%d %d %d", line_num, cell_type_translation.at("$mux").c_str(), output_width, async_reset_pol ? "":"-", async_reset, async_reset_value, next); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); } ++line_num; - str = stringf ("%d %s %d %d %d", line_num, cell_type_translation.at(cell->type).c_str(), + str = stringf ("%d %s %d %d %d", line_num, cell_type_translation.at(cell->type.str()).c_str(), output_width, reg, next); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); } line_ref[cell->name]=line_num; } @@ -749,11 +750,11 @@ struct BtorDumper str = cell->parameters.at(RTLIL::IdString("\\MEMID")).decode_string(); int mem = dump_memory(module->memories.at(RTLIL::IdString(str.c_str()))); int address_width = cell->parameters.at(RTLIL::IdString("\\ABITS")).as_int(); - int address = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\ADDR")), address_width); + int address = dump_sigspec(&cell->getPort(RTLIL::IdString("\\ADDR")), address_width); int data_width = cell->parameters.at(RTLIL::IdString("\\WIDTH")).as_int(); ++line_num; str = stringf("%d read %d %d %d", line_num, data_width, mem, address); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); line_ref[cell->name]=line_num; } else if(cell->type == "$memwr") @@ -761,13 +762,13 @@ struct BtorDumper log("writing memwr cell\n"); if (cell->parameters.at("\\CLK_ENABLE").as_bool() == false) log_error("The btor backen does not support $memwr cells without built-in registers. Run memory_dff (but with -wr_only).\n"); - int clk = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\CLK")), 1); + int clk = dump_sigspec(&cell->getPort(RTLIL::IdString("\\CLK")), 1); bool polarity = cell->parameters.at(RTLIL::IdString("\\CLK_POLARITY")).as_bool(); - int enable = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\EN")), 1); + int enable = dump_sigspec(&cell->getPort(RTLIL::IdString("\\EN")), 1); int address_width = cell->parameters.at(RTLIL::IdString("\\ABITS")).as_int(); - int address = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\ADDR")), address_width); - int data_width = cell->parameters.at(RTLIL::IdString("\\WIDTH")).as_int(); - int data = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\DATA")), data_width); + int address = dump_sigspec(&cell->getPort(RTLIL::IdString("\\ADDR")), address_width); + int data_width = cell->parameters.at(RTLIL::IdString("\\WIDTH")).as_int(); + int data = dump_sigspec(&cell->getPort(RTLIL::IdString("\\DATA")), data_width); str = cell->parameters.at(RTLIL::IdString("\\MEMID")).decode_string(); int mem = dump_memory(module->memories.at(RTLIL::IdString(str.c_str()))); //check if the memory has already next @@ -779,68 +780,67 @@ struct BtorDumper RTLIL::Memory *memory = module->memories.at(RTLIL::IdString(str.c_str())); int address_bits = ceil(log(memory->size)/log(2)); str = stringf("%d array %d %d", line_num, memory->width, address_bits); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); ++line_num; str = stringf("%d eq 1 %d %d", line_num, mem, line_num - 1); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); mem = line_num - 1; } - ++line_num; + ++line_num; if(polarity) str = stringf("%d one 1", line_num); else str = stringf("%d zero 1", line_num); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); ++line_num; str = stringf("%d eq 1 %d %d", line_num, clk, line_num-1); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); ++line_num; str = stringf("%d and 1 %d %d", line_num, line_num-1, enable); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); ++line_num; str = stringf("%d write %d %d %d %d %d", line_num, data_width, address_width, mem, address, data); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); ++line_num; str = stringf("%d acond %d %d %d %d %d", line_num, data_width, address_width, line_num-2/*enable*/, line_num-1, mem); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); ++line_num; str = stringf("%d anext %d %d %d %d", line_num, data_width, address_width, mem, line_num-1); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); mem_next.insert(mem); - line_ref[cell->name]=line_num; + line_ref[cell->name]=line_num; } else if(cell->type == "$slice") { log("writing slice cell\n"); - const RTLIL::SigSpec* input = &cell->connections.at(RTLIL::IdString("\\A")); + const RTLIL::SigSpec* input = &cell->getPort(RTLIL::IdString("\\A")); int input_width = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int(); - assert(input->width == input_width); + log_assert(input->size() == input_width); int input_line = dump_sigspec(input, input_width); - const RTLIL::SigSpec* output = &cell->connections.at(RTLIL::IdString("\\Y")); + const RTLIL::SigSpec* output = &cell->getPort(RTLIL::IdString("\\Y")); int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int(); - assert(output->width == output_width); + log_assert(output->size() == output_width); int offset = cell->parameters.at(RTLIL::IdString("\\OFFSET")).as_int(); ++line_num; - str = stringf("%d %s %d %d %d %d", line_num, cell_type_translation.at(cell->type).c_str(), - output_width, input_line, output_width+offset-1, offset); - fprintf(f, "%s\n", str.c_str()); + str = stringf("%d %s %d %d %d %d", line_num, cell_type_translation.at(cell->type.str()).c_str(), output_width, input_line, output_width+offset-1, offset); + f << stringf("%s\n", str.c_str()); line_ref[cell->name]=line_num; } else if(cell->type == "$concat") { log("writing concat cell\n"); - const RTLIL::SigSpec* input_a = &cell->connections.at(RTLIL::IdString("\\A")); + const RTLIL::SigSpec* input_a = &cell->getPort(RTLIL::IdString("\\A")); int input_a_width = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int(); - assert(input_a->width == input_a_width); + log_assert(input_a->size() == input_a_width); int input_a_line = dump_sigspec(input_a, input_a_width); - const RTLIL::SigSpec* input_b = &cell->connections.at(RTLIL::IdString("\\B")); + const RTLIL::SigSpec* input_b = &cell->getPort(RTLIL::IdString("\\B")); int input_b_width = cell->parameters.at(RTLIL::IdString("\\B_WIDTH")).as_int(); - assert(input_b->width == input_b_width); + log_assert(input_b->size() == input_b_width); int input_b_line = dump_sigspec(input_b, input_b_width); ++line_num; - str = stringf("%d %s %d %d %d", line_num, cell_type_translation.at(cell->type).c_str(), input_a_width+input_b_width, + str = stringf("%d %s %d %d %d", line_num, cell_type_translation.at(cell->type.str()).c_str(), input_a_width+input_b_width, input_a_line, input_b_line); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); line_ref[cell->name]=line_num; } curr_cell.clear(); @@ -852,12 +852,12 @@ struct BtorDumper } } - RTLIL::SigSpec* get_cell_output(RTLIL::Cell* cell) + const RTLIL::SigSpec* get_cell_output(RTLIL::Cell* cell) { - RTLIL::SigSpec *output_sig = nullptr; + const RTLIL::SigSpec *output_sig = nullptr; if (cell->type == "$memrd") { - output_sig = &cell->connections.at(RTLIL::IdString("\\DATA")); + output_sig = &cell->getPort(RTLIL::IdString("\\DATA")); } else if(cell->type == "$memwr" || cell->type == "$assert") { @@ -865,11 +865,11 @@ struct BtorDumper } else if(cell->type == "$dff" || cell->type == "$adff" || cell->type == "$dffsr") { - output_sig = &cell->connections.at(RTLIL::IdString("\\Q")); + output_sig = &cell->getPort(RTLIL::IdString("\\Q")); } else { - output_sig = &cell->connections.at(RTLIL::IdString("\\Y")); + output_sig = &cell->getPort(RTLIL::IdString("\\Y")); } return output_sig; } @@ -879,19 +879,19 @@ struct BtorDumper int l = dump_wire(wire); ++line_num; str = stringf("%d root 1 %d", line_num, l); - fprintf(f, "%s\n", str.c_str()); + f << stringf("%s\n", str.c_str()); } void dump() { - fprintf(f, ";module %s\n", cstr(module->name)); + f << stringf(";module %s\n", cstr(module->name)); log("creating intermediate wires map\n"); //creating map of intermediate wires as output of some cell - for (auto it = module->cells.begin(); it != module->cells.end(); ++it) + for (auto it = module->cells_.begin(); it != module->cells_.end(); ++it) { RTLIL::Cell *cell = it->second; - RTLIL::SigSpec* output_sig = get_cell_output(cell); + const RTLIL::SigSpec* output_sig = get_cell_output(cell); if(output_sig==nullptr) continue; RTLIL::SigSpec s = sigmap(*output_sig); @@ -899,11 +899,11 @@ struct BtorDumper log(" - %s\n", cstr(it->second->type)); if (cell->type == "$memrd") { - for(unsigned i=0; i<output_sig->chunks.size(); ++i) + for(unsigned i=0; i<output_sig->chunks().size(); ++i) { - RTLIL::Wire *w = output_sig->chunks[i].wire; + RTLIL::Wire *w = output_sig->chunks().at(i).wire; RTLIL::IdString wire_id = w->name; - inter_wire_map[wire_id].insert(WireInfo(cell->name,&output_sig->chunks[i])); + inter_wire_map[wire_id].insert(WireInfo(cell->name,&output_sig->chunks().at(i))); } } else if(cell->type == "$memwr") @@ -912,22 +912,22 @@ struct BtorDumper } else if(cell->type == "$dff" || cell->type == "$adff" || cell->type == "$dffsr") { - RTLIL::IdString wire_id = output_sig->chunks[0].wire->name; - for(unsigned i=0; i<output_sig->chunks.size(); ++i) + RTLIL::IdString wire_id = output_sig->chunks().front().wire->name; + for(unsigned i=0; i<output_sig->chunks().size(); ++i) { - RTLIL::Wire *w = output_sig->chunks[i].wire; + RTLIL::Wire *w = output_sig->chunks().at(i).wire; RTLIL::IdString wire_id = w->name; - inter_wire_map[wire_id].insert(WireInfo(cell->name,&output_sig->chunks[i])); + inter_wire_map[wire_id].insert(WireInfo(cell->name,&output_sig->chunks().at(i))); basic_wires[wire_id] = true; } } else { - for(unsigned i=0; i<output_sig->chunks.size(); ++i) + for(unsigned i=0; i<output_sig->chunks().size(); ++i) { - RTLIL::Wire *w = output_sig->chunks[i].wire; + RTLIL::Wire *w = output_sig->chunks().at(i).wire; RTLIL::IdString wire_id = w->name; - inter_wire_map[wire_id].insert(WireInfo(cell->name,&output_sig->chunks[i])); + inter_wire_map[wire_id].insert(WireInfo(cell->name,&output_sig->chunks().at(i))); } } } @@ -936,23 +936,23 @@ struct BtorDumper std::map<int, RTLIL::Wire*> inputs, outputs; std::vector<RTLIL::Wire*> safety; - for (auto &wire_it : module->wires) { + for (auto &wire_it : module->wires_) { RTLIL::Wire *wire = wire_it.second; if (wire->port_input) inputs[wire->port_id] = wire; if (wire->port_output) { outputs[wire->port_id] = wire; - if (wire->name.find("safety") != std::string::npos ) + if (wire->name.str().find("safety") != std::string::npos ) safety.push_back(wire); } } - fprintf(f, ";inputs\n"); + f << stringf(";inputs\n"); for (auto &it : inputs) { RTLIL::Wire *wire = it.second; dump_wire(wire); } - fprintf(f, "\n"); + f << stringf("\n"); log("writing memories\n"); for(auto mem_it = module->memories.begin(); mem_it != module->memories.end(); ++mem_it) @@ -967,7 +967,7 @@ struct BtorDumper } log("writing cells\n"); - for(auto cell_it = module->cells.begin(); cell_it != module->cells.end(); ++cell_it) + for(auto cell_it = module->cells_.begin(); cell_it != module->cells_.end(); ++cell_it) { dump_cell(cell_it->second); } @@ -975,19 +975,19 @@ struct BtorDumper for(auto it: safety) dump_property(it); - fprintf(f, "\n"); + f << stringf("\n"); log("writing outputs info\n"); - fprintf(f, ";outputs\n"); + f << stringf(";outputs\n"); for (auto &it : outputs) { RTLIL::Wire *wire = it.second; int l = dump_wire(wire); - fprintf(f, ";%d %s", l, cstr(wire->name)); + f << stringf(";%d %s", l, cstr(wire->name)); } - fprintf(f, "\n"); + f << stringf("\n"); } - static void dump(FILE *f, RTLIL::Module *module, RTLIL::Design *design, BtorDumperConfig &config) + static void dump(std::ostream &f, RTLIL::Module *module, RTLIL::Design *design, BtorDumperConfig &config) { BtorDumper dumper(f, module, design, &config); dumper.dump(); @@ -1006,7 +1006,7 @@ struct BtorBackend : public Backend { log("Write the current design to an BTOR file.\n"); } - virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) + virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) { std::string top_module_name; std::string buf_type, buf_in, buf_out; @@ -1020,18 +1020,18 @@ struct BtorBackend : public Backend { extra_args(f, filename, args, argidx); if (top_module_name.empty()) - for (auto & mod_it:design->modules) + for (auto & mod_it:design->modules_) if (mod_it.second->get_bool_attribute("\\top")) - top_module_name = mod_it.first; + top_module_name = mod_it.first.str(); - fprintf(f, "; Generated by %s\n", yosys_version_str); - fprintf(f, "; %s developed and maintained by Clifford Wolf <clifford@clifford.at>\n", yosys_version_str); - fprintf(f, "; BTOR Backend developed by Ahmed Irfan <irfan@fbk.eu> - Fondazione Bruno Kessler, Trento, Italy\n"); - fprintf(f, ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n"); + *f << stringf("; Generated by %s\n", yosys_version_str); + *f << stringf("; %s developed and maintained by Clifford Wolf <clifford@clifford.at>\n", yosys_version_str); + *f << stringf("; BTOR Backend developed by Ahmed Irfan <irfan@fbk.eu> - Fondazione Bruno Kessler, Trento, Italy\n"); + *f << stringf(";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n"); std::vector<RTLIL::Module*> mod_list; - for (auto module_it : design->modules) + for (auto module_it : design->modules_) { RTLIL::Module *module = module_it.second; if (module->get_bool_attribute("\\blackbox")) @@ -1041,7 +1041,7 @@ struct BtorBackend : public Backend { log_error("Found unmapped processes in module %s: unmapped processes are not supported in BTOR backend!\n", RTLIL::id2cstr(module->name)); if (module->name == RTLIL::escape_id(top_module_name)) { - BtorDumper::dump(f, module, design, config); + BtorDumper::dump(*f, module, design, config); top_module_name.clear(); continue; } @@ -1053,7 +1053,7 @@ struct BtorBackend : public Backend { log_error("Can't find top module `%s'!\n", top_module_name.c_str()); for (auto module : mod_list) - BtorDumper::dump(f, module, design, config); + BtorDumper::dump(*f, module, design, config); } } BtorBackend; diff --git a/backends/btor/verilog2btor.sh b/backends/btor/verilog2btor.sh index 870f0a28d..ab45b4901 100755 --- a/backends/btor/verilog2btor.sh +++ b/backends/btor/verilog2btor.sh @@ -17,14 +17,14 @@ FULL_PATH=$(readlink -f $1) DIR=$(dirname $FULL_PATH) ./yosys -q -p " -read_verilog $1; +read_verilog -sv $1; hierarchy -top $3; hierarchy -libdir $DIR; hierarchy -check; proc; opt; opt_const -mux_undef; opt; rename -hide;;; -techmap -share_map pmux2mux.v;; +#techmap -share_map pmux2mux.v;; splice; opt; memory_dff -wr_only; memory_collect;; diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc index 1748ed810..ccedd91d2 100644 --- a/backends/edif/edif.cc +++ b/backends/edif/edif.cc @@ -26,9 +26,9 @@ #include "kernel/celltypes.h" #include "kernel/log.h" #include <string> -#include <assert.h> -#define EDIF_NAME(_id) edif_names(RTLIL::unescape_id(_id)).c_str() +#define EDIF_DEF(_id) edif_names(RTLIL::unescape_id(_id), true).c_str() +#define EDIF_REF(_id) edif_names(RTLIL::unescape_id(_id), false).c_str() namespace { @@ -40,8 +40,13 @@ namespace EdifNames() : counter(1) { } - std::string operator()(std::string id) + std::string operator()(std::string id, bool define) { + if (define) { + std::string new_id = operator()(id, false); + return new_id != id ? stringf("(rename %s \"%s\")", new_id.c_str(), id.c_str()) : id; + } + if (name_map.count(id) > 0) return name_map.at(id); if (generated_names.count(id) > 0) @@ -74,7 +79,7 @@ namespace } generated_names.insert(gen_name); name_map[id] = gen_name; - return stringf("(rename %s \"%s\")", gen_name.c_str(), id.c_str()); + return gen_name; } }; } @@ -98,12 +103,12 @@ struct EdifBackend : public Backend { log("is targeted.\n"); log("\n"); } - virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) + virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) { log_header("Executing EDIF backend.\n"); std::string top_module_name; - std::map<std::string, std::set<std::string>> lib_cell_ports; + std::map<RTLIL::IdString, std::set<RTLIL::IdString>> lib_cell_ports; CellTypes ct(design); EdifNames edif_names; @@ -119,31 +124,31 @@ struct EdifBackend : public Backend { extra_args(f, filename, args, argidx); if (top_module_name.empty()) - for (auto & mod_it:design->modules) + for (auto & mod_it:design->modules_) if (mod_it.second->get_bool_attribute("\\top")) - top_module_name = mod_it.first; + top_module_name = mod_it.first.str(); - for (auto module_it : design->modules) + for (auto module_it : design->modules_) { RTLIL::Module *module = module_it.second; if (module->get_bool_attribute("\\blackbox")) continue; if (top_module_name.empty()) - top_module_name = module->name; + top_module_name = module->name.str(); if (module->processes.size() != 0) log_error("Found unmapped processes in module %s: unmapped processes are not supported in EDIF backend!\n", RTLIL::id2cstr(module->name)); if (module->memories.size() != 0) log_error("Found munmapped emories in module %s: unmapped memories are not supported in EDIF backend!\n", RTLIL::id2cstr(module->name)); - for (auto cell_it : module->cells) + for (auto cell_it : module->cells_) { RTLIL::Cell *cell = cell_it.second; - if (!design->modules.count(cell->type) || design->modules.at(cell->type)->get_bool_attribute("\\blackbox")) { + if (!design->modules_.count(cell->type) || design->modules_.at(cell->type)->get_bool_attribute("\\blackbox")) { lib_cell_ports[cell->type]; - for (auto p : cell->connections) { - if (p.second.width > 1) + for (auto p : cell->connections()) { + if (p.second.size() > 1) log_error("Found multi-bit port %s on library cell %s.%s (%s): not supported in EDIF backend!\n", RTLIL::id2cstr(p.first), RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); lib_cell_ports[cell->type].insert(p.first); @@ -155,38 +160,38 @@ struct EdifBackend : public Backend { if (top_module_name.empty()) log_error("No module found in design!\n"); - fprintf(f, "(edif %s\n", EDIF_NAME(top_module_name)); - fprintf(f, " (edifVersion 2 0 0)\n"); - fprintf(f, " (edifLevel 0)\n"); - fprintf(f, " (keywordMap (keywordLevel 0))\n"); - fprintf(f, " (comment \"Generated by %s\")\n", yosys_version_str); - - fprintf(f, " (external LIB\n"); - fprintf(f, " (edifLevel 0)\n"); - fprintf(f, " (technology (numberDefinition))\n"); - - fprintf(f, " (cell GND\n"); - fprintf(f, " (cellType GENERIC)\n"); - fprintf(f, " (view VIEW_NETLIST\n"); - fprintf(f, " (viewType NETLIST)\n"); - fprintf(f, " (interface (port G (direction OUTPUT)))\n"); - fprintf(f, " )\n"); - fprintf(f, " )\n"); - - fprintf(f, " (cell VCC\n"); - fprintf(f, " (cellType GENERIC)\n"); - fprintf(f, " (view VIEW_NETLIST\n"); - fprintf(f, " (viewType NETLIST)\n"); - fprintf(f, " (interface (port P (direction OUTPUT)))\n"); - fprintf(f, " )\n"); - fprintf(f, " )\n"); + *f << stringf("(edif %s\n", EDIF_DEF(top_module_name)); + *f << stringf(" (edifVersion 2 0 0)\n"); + *f << stringf(" (edifLevel 0)\n"); + *f << stringf(" (keywordMap (keywordLevel 0))\n"); + *f << stringf(" (comment \"Generated by %s\")\n", yosys_version_str); + + *f << stringf(" (external LIB\n"); + *f << stringf(" (edifLevel 0)\n"); + *f << stringf(" (technology (numberDefinition))\n"); + + *f << stringf(" (cell GND\n"); + *f << stringf(" (cellType GENERIC)\n"); + *f << stringf(" (view VIEW_NETLIST\n"); + *f << stringf(" (viewType NETLIST)\n"); + *f << stringf(" (interface (port G (direction OUTPUT)))\n"); + *f << stringf(" )\n"); + *f << stringf(" )\n"); + + *f << stringf(" (cell VCC\n"); + *f << stringf(" (cellType GENERIC)\n"); + *f << stringf(" (view VIEW_NETLIST\n"); + *f << stringf(" (viewType NETLIST)\n"); + *f << stringf(" (interface (port P (direction OUTPUT)))\n"); + *f << stringf(" )\n"); + *f << stringf(" )\n"); for (auto &cell_it : lib_cell_ports) { - fprintf(f, " (cell %s\n", EDIF_NAME(cell_it.first)); - fprintf(f, " (cellType GENERIC)\n"); - fprintf(f, " (view VIEW_NETLIST\n"); - fprintf(f, " (viewType NETLIST)\n"); - fprintf(f, " (interface\n"); + *f << stringf(" (cell %s\n", EDIF_DEF(cell_it.first)); + *f << stringf(" (cellType GENERIC)\n"); + *f << stringf(" (view VIEW_NETLIST\n"); + *f << stringf(" (viewType NETLIST)\n"); + *f << stringf(" (interface\n"); for (auto &port_it : cell_it.second) { const char *dir = "INOUT"; if (ct.cell_known(cell_it.first)) { @@ -195,23 +200,23 @@ struct EdifBackend : public Backend { else if (!ct.cell_input(cell_it.first, port_it)) dir = "OUTPUT"; } - fprintf(f, " (port %s (direction %s))\n", EDIF_NAME(port_it), dir); + *f << stringf(" (port %s (direction %s))\n", EDIF_DEF(port_it), dir); } - fprintf(f, " )\n"); - fprintf(f, " )\n"); - fprintf(f, " )\n"); + *f << stringf(" )\n"); + *f << stringf(" )\n"); + *f << stringf(" )\n"); } - fprintf(f, " )\n"); + *f << stringf(" )\n"); std::vector<RTLIL::Module*> sorted_modules; // extract module dependencies std::map<RTLIL::Module*, std::set<RTLIL::Module*>> module_deps; - for (auto &mod_it : design->modules) { + for (auto &mod_it : design->modules_) { module_deps[mod_it.second] = std::set<RTLIL::Module*>(); - for (auto &cell_it : mod_it.second->cells) - if (design->modules.count(cell_it.second->type) > 0) - module_deps[mod_it.second].insert(design->modules.at(cell_it.second->type)); + for (auto &cell_it : mod_it.second->cells_) + if (design->modules_.count(cell_it.second->type) > 0) + module_deps[mod_it.second].insert(design->modules_.at(cell_it.second->type)); } // simple good-enough topological sort @@ -233,9 +238,9 @@ struct EdifBackend : public Backend { } - fprintf(f, " (library DESIGN\n"); - fprintf(f, " (edifLevel 0)\n"); - fprintf(f, " (technology (numberDefinition))\n"); + *f << stringf(" (library DESIGN\n"); + *f << stringf(" (edifLevel 0)\n"); + *f << stringf(" (technology (numberDefinition))\n"); for (auto module : sorted_modules) { if (module->get_bool_attribute("\\blackbox")) @@ -244,12 +249,12 @@ struct EdifBackend : public Backend { SigMap sigmap(module); std::map<RTLIL::SigSpec, std::set<std::string>> net_join_db; - fprintf(f, " (cell %s\n", EDIF_NAME(module->name)); - fprintf(f, " (cellType GENERIC)\n"); - fprintf(f, " (view VIEW_NETLIST\n"); - fprintf(f, " (viewType NETLIST)\n"); - fprintf(f, " (interface\n"); - for (auto &wire_it : module->wires) { + *f << stringf(" (cell %s\n", EDIF_DEF(module->name)); + *f << stringf(" (cellType GENERIC)\n"); + *f << stringf(" (view VIEW_NETLIST\n"); + *f << stringf(" (viewType NETLIST)\n"); + *f << stringf(" (interface\n"); + for (auto &wire_it : module->wires_) { RTLIL::Wire *wire = wire_it.second; if (wire->port_id == 0) continue; @@ -259,31 +264,31 @@ struct EdifBackend : public Backend { else if (!wire->port_input) dir = "OUTPUT"; if (wire->width == 1) { - fprintf(f, " (port %s (direction %s))\n", EDIF_NAME(wire->name), dir); + *f << stringf(" (port %s (direction %s))\n", EDIF_DEF(wire->name), dir); RTLIL::SigSpec sig = sigmap(RTLIL::SigSpec(wire)); - net_join_db[sig].insert(stringf("(portRef %s)", EDIF_NAME(wire->name))); + net_join_db[sig].insert(stringf("(portRef %s)", EDIF_REF(wire->name))); } else { - fprintf(f, " (port (array %s %d) (direction %s))\n", EDIF_NAME(wire->name), wire->width, dir); + *f << stringf(" (port (array %s %d) (direction %s))\n", EDIF_DEF(wire->name), wire->width, dir); for (int i = 0; i < wire->width; i++) { - RTLIL::SigSpec sig = sigmap(RTLIL::SigSpec(wire, 1, i)); - net_join_db[sig].insert(stringf("(portRef (member %s %d))", EDIF_NAME(wire->name), i)); + RTLIL::SigSpec sig = sigmap(RTLIL::SigSpec(wire, i)); + net_join_db[sig].insert(stringf("(portRef (member %s %d))", EDIF_REF(wire->name), i)); } } } - fprintf(f, " )\n"); - fprintf(f, " (contents\n"); - fprintf(f, " (instance GND (viewRef VIEW_NETLIST (cellRef GND (libraryRef LIB))))\n"); - fprintf(f, " (instance VCC (viewRef VIEW_NETLIST (cellRef VCC (libraryRef LIB))))\n"); - for (auto &cell_it : module->cells) { + *f << stringf(" )\n"); + *f << stringf(" (contents\n"); + *f << stringf(" (instance GND (viewRef VIEW_NETLIST (cellRef GND (libraryRef LIB))))\n"); + *f << stringf(" (instance VCC (viewRef VIEW_NETLIST (cellRef VCC (libraryRef LIB))))\n"); + for (auto &cell_it : module->cells_) { RTLIL::Cell *cell = cell_it.second; - fprintf(f, " (instance %s\n", EDIF_NAME(cell->name)); - fprintf(f, " (viewRef VIEW_NETLIST (cellRef %s%s))", EDIF_NAME(cell->type), + *f << stringf(" (instance %s\n", EDIF_DEF(cell->name)); + *f << stringf(" (viewRef VIEW_NETLIST (cellRef %s%s))", EDIF_REF(cell->type), lib_cell_ports.count(cell->type) > 0 ? " (libraryRef LIB)" : ""); for (auto &p : cell->parameters) if ((p.second.flags & RTLIL::CONST_FLAG_STRING) != 0) - fprintf(f, "\n (property %s (string \"%s\"))", EDIF_NAME(p.first), p.second.decode_string().c_str()); + *f << stringf("\n (property %s (string \"%s\"))", EDIF_DEF(p.first), p.second.decode_string().c_str()); else if (p.second.bits.size() <= 32 && RTLIL::SigSpec(p.second).is_fully_def()) - fprintf(f, "\n (property %s (integer %u))", EDIF_NAME(p.first), p.second.as_int()); + *f << stringf("\n (property %s (integer %u))", EDIF_DEF(p.first), p.second.as_int()); else { std::string hex_string = ""; for (size_t i = 0; i < p.second.bits.size(); i += 4) { @@ -295,53 +300,48 @@ struct EdifBackend : public Backend { char digit_str[2] = { "0123456789abcdef"[digit_value], 0 }; hex_string = std::string(digit_str) + hex_string; } - fprintf(f, "\n (property %s (string \"%s\"))", EDIF_NAME(p.first), hex_string.c_str()); + *f << stringf("\n (property %s (string \"%s\"))", EDIF_DEF(p.first), hex_string.c_str()); } - fprintf(f, ")\n"); - for (auto &p : cell->connections) { + *f << stringf(")\n"); + for (auto &p : cell->connections()) { RTLIL::SigSpec sig = sigmap(p.second); - sig.expand(); - for (int i = 0; i < sig.width; i++) { - RTLIL::SigSpec sigbit(sig.chunks.at(i)); - std::string portname = sig.width > 1 ? stringf("%s[%d]", RTLIL::id2cstr(p.first), i) : RTLIL::id2cstr(p.first); - net_join_db[sigbit].insert(stringf("(portRef %s (instanceRef %s))", edif_names(portname).c_str(), EDIF_NAME(cell->name))); - } + for (int i = 0; i < SIZE(sig); i++) + if (sig.size() == 1) + net_join_db[sig[i]].insert(stringf("(portRef %s (instanceRef %s))", EDIF_REF(p.first), EDIF_REF(cell->name))); + else + net_join_db[sig[i]].insert(stringf("(portRef (member %s %d) (instanceRef %s))", EDIF_REF(p.first), i, EDIF_REF(cell->name))); } } for (auto &it : net_join_db) { - RTLIL::SigSpec sig = it.first; - sig.optimize(); - log_assert(sig.width == 1); - if (sig.chunks.at(0).wire == NULL) { - if (sig.chunks.at(0).data.bits.at(0) != RTLIL::State::S0 && sig.chunks.at(0).data.bits.at(0) != RTLIL::State::S1) - continue; - } + RTLIL::SigBit sig = it.first; + if (sig.wire == NULL && sig != RTLIL::State::S0 && sig != RTLIL::State::S1) + continue; std::string netname = log_signal(sig); for (size_t i = 0; i < netname.size(); i++) if (netname[i] == ' ' || netname[i] == '\\') netname.erase(netname.begin() + i--); - fprintf(f, " (net %s (joined\n", edif_names(netname).c_str()); + *f << stringf(" (net %s (joined\n", EDIF_DEF(netname)); for (auto &ref : it.second) - fprintf(f, " %s\n", ref.c_str()); - if (sig.chunks.at(0).wire == NULL) { - if (sig.chunks.at(0).data.bits.at(0) == RTLIL::State::S0) - fprintf(f, " (portRef G (instanceRef GND))\n"); - if (sig.chunks.at(0).data.bits.at(0) == RTLIL::State::S1) - fprintf(f, " (portRef P (instanceRef VCC))\n"); + *f << stringf(" %s\n", ref.c_str()); + if (sig.wire == NULL) { + if (sig == RTLIL::State::S0) + *f << stringf(" (portRef G (instanceRef GND))\n"); + if (sig == RTLIL::State::S1) + *f << stringf(" (portRef P (instanceRef VCC))\n"); } - fprintf(f, " ))\n"); + *f << stringf(" ))\n"); } - fprintf(f, " )\n"); - fprintf(f, " )\n"); - fprintf(f, " )\n"); + *f << stringf(" )\n"); + *f << stringf(" )\n"); + *f << stringf(" )\n"); } - fprintf(f, " )\n"); + *f << stringf(" )\n"); - fprintf(f, " (design %s\n", EDIF_NAME(top_module_name)); - fprintf(f, " (cellRef %s (libraryRef DESIGN))\n", EDIF_NAME(top_module_name)); - fprintf(f, " )\n"); + *f << stringf(" (design %s\n", EDIF_DEF(top_module_name)); + *f << stringf(" (cellRef %s (libraryRef DESIGN))\n", EDIF_REF(top_module_name)); + *f << stringf(" )\n"); - fprintf(f, ")\n"); + *f << stringf(")\n"); } } EdifBackend; diff --git a/backends/ilang/ilang_backend.cc b/backends/ilang/ilang_backend.cc index c585d40c5..48d818d76 100644 --- a/backends/ilang/ilang_backend.cc +++ b/backends/ilang/ilang_backend.cc @@ -23,16 +23,12 @@ */ #include "ilang_backend.h" -#include "kernel/register.h" -#include "kernel/log.h" -#include <string> -#include <assert.h> -#include <string.h> +#include "kernel/yosys.h" #include <errno.h> using namespace ILANG_BACKEND; -void ILANG_BACKEND::dump_const(FILE *f, const RTLIL::Const &data, int width, int offset, bool autoint) +void ILANG_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int width, int offset, bool autoint) { if (width < 0) width = data.bits.size() - offset; @@ -40,7 +36,7 @@ void ILANG_BACKEND::dump_const(FILE *f, const RTLIL::Const &data, int width, int if (width == 32 && autoint) { int32_t val = 0; for (int i = 0; i < width; i++) { - assert(offset+i < (int)data.bits.size()); + log_assert(offset+i < (int)data.bits.size()); switch (data.bits[offset+i]) { case RTLIL::S0: break; case RTLIL::S1: val |= 1 << i; break; @@ -48,220 +44,230 @@ void ILANG_BACKEND::dump_const(FILE *f, const RTLIL::Const &data, int width, int } } if (val >= 0) { - fprintf(f, "%d", val); + f << stringf("%d", val); return; } } - fprintf(f, "%d'", width); + f << stringf("%d'", width); for (int i = offset+width-1; i >= offset; i--) { - assert(i < (int)data.bits.size()); + log_assert(i < (int)data.bits.size()); switch (data.bits[i]) { - case RTLIL::S0: fprintf(f, "0"); break; - case RTLIL::S1: fprintf(f, "1"); break; - case RTLIL::Sx: fprintf(f, "x"); break; - case RTLIL::Sz: fprintf(f, "z"); break; - case RTLIL::Sa: fprintf(f, "-"); break; - case RTLIL::Sm: fprintf(f, "m"); break; + 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 { - fprintf(f, "\""); + f << stringf("\""); std::string str = data.decode_string(); for (size_t i = 0; i < str.size(); i++) { if (str[i] == '\n') - fprintf(f, "\\n"); + f << stringf("\\n"); else if (str[i] == '\t') - fprintf(f, "\\t"); + f << stringf("\\t"); else if (str[i] < 32) - fprintf(f, "\\%03o", str[i]); + f << stringf("\\%03o", str[i]); else if (str[i] == '"') - fprintf(f, "\\\""); + f << stringf("\\\""); else if (str[i] == '\\') - fprintf(f, "\\\\"); + f << stringf("\\\\"); else - fputc(str[i], f); + f << str[i]; } - fprintf(f, "\""); + f << stringf("\""); } } -void ILANG_BACKEND::dump_sigchunk(FILE *f, const RTLIL::SigChunk &chunk, bool autoint) +void ILANG_BACKEND::dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool autoint) { if (chunk.wire == NULL) { dump_const(f, chunk.data, chunk.width, chunk.offset, autoint); } else { if (chunk.width == chunk.wire->width && chunk.offset == 0) - fprintf(f, "%s", chunk.wire->name.c_str()); + f << stringf("%s", chunk.wire->name.c_str()); else if (chunk.width == 1) - fprintf(f, "%s [%d]", chunk.wire->name.c_str(), chunk.offset); + f << stringf("%s [%d]", chunk.wire->name.c_str(), chunk.offset); else - fprintf(f, "%s [%d:%d]", chunk.wire->name.c_str(), chunk.offset+chunk.width-1, chunk.offset); + f << stringf("%s [%d:%d]", chunk.wire->name.c_str(), chunk.offset+chunk.width-1, chunk.offset); } } -void ILANG_BACKEND::dump_sigspec(FILE *f, const RTLIL::SigSpec &sig, bool autoint) +void ILANG_BACKEND::dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, bool autoint) { - if (sig.chunks.size() == 1) { - dump_sigchunk(f, sig.chunks[0], autoint); + if (sig.is_chunk()) { + dump_sigchunk(f, sig.as_chunk(), autoint); } else { - fprintf(f, "{ "); - for (auto it = sig.chunks.rbegin(); it != sig.chunks.rend(); it++) { + f << stringf("{ "); + for (auto it = sig.chunks().rbegin(); it != sig.chunks().rend(); it++) { dump_sigchunk(f, *it, false); - fprintf(f, " "); + f << stringf(" "); } - fprintf(f, "}"); + f << stringf("}"); } } -void ILANG_BACKEND::dump_wire(FILE *f, std::string indent, const RTLIL::Wire *wire) +void ILANG_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire) { - for (auto it = wire->attributes.begin(); it != wire->attributes.end(); it++) { - fprintf(f, "%s" "attribute %s ", indent.c_str(), it->first.c_str()); + std::map<RTLIL::IdString, RTLIL::Const, RTLIL::sort_by_id_str> sorted_attributes(wire->attributes.begin(), wire->attributes.end()); + + for (auto it = sorted_attributes.begin(); it != sorted_attributes.end(); it++) { + f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str()); dump_const(f, it->second); - fprintf(f, "\n"); + f << stringf("\n"); } - fprintf(f, "%s" "wire ", indent.c_str()); + f << stringf("%s" "wire ", indent.c_str()); if (wire->width != 1) - fprintf(f, "width %d ", wire->width); + f << stringf("width %d ", wire->width); + if (wire->upto) + f << stringf("upto "); if (wire->start_offset != 0) - fprintf(f, "offset %d ", wire->start_offset); + f << stringf("offset %d ", wire->start_offset); if (wire->port_input && !wire->port_output) - fprintf(f, "input %d ", wire->port_id); + f << stringf("input %d ", wire->port_id); if (!wire->port_input && wire->port_output) - fprintf(f, "output %d ", wire->port_id); + f << stringf("output %d ", wire->port_id); if (wire->port_input && wire->port_output) - fprintf(f, "inout %d ", wire->port_id); - fprintf(f, "%s\n", wire->name.c_str()); + f << stringf("inout %d ", wire->port_id); + f << stringf("%s\n", wire->name.c_str()); } -void ILANG_BACKEND::dump_memory(FILE *f, std::string indent, const RTLIL::Memory *memory) +void ILANG_BACKEND::dump_memory(std::ostream &f, std::string indent, const RTLIL::Memory *memory) { - for (auto it = memory->attributes.begin(); it != memory->attributes.end(); it++) { - fprintf(f, "%s" "attribute %s ", indent.c_str(), it->first.c_str()); + std::map<RTLIL::IdString, RTLIL::Const, RTLIL::sort_by_id_str> sorted_attributes(memory->attributes.begin(), memory->attributes.end()); + + for (auto it = sorted_attributes.begin(); it != sorted_attributes.end(); it++) { + f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str()); dump_const(f, it->second); - fprintf(f, "\n"); + f << stringf("\n"); } - fprintf(f, "%s" "memory ", indent.c_str()); + f << stringf("%s" "memory ", indent.c_str()); if (memory->width != 1) - fprintf(f, "width %d ", memory->width); + f << stringf("width %d ", memory->width); if (memory->size != 0) - fprintf(f, "size %d ", memory->size); - fprintf(f, "%s\n", memory->name.c_str()); + f << stringf("size %d ", memory->size); + f << stringf("%s\n", memory->name.c_str()); } -void ILANG_BACKEND::dump_cell(FILE *f, std::string indent, const RTLIL::Cell *cell) +void ILANG_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL::Cell *cell) { - for (auto it = cell->attributes.begin(); it != cell->attributes.end(); it++) { - fprintf(f, "%s" "attribute %s ", indent.c_str(), it->first.c_str()); + std::map<RTLIL::IdString, RTLIL::Const, RTLIL::sort_by_id_str> sorted_attributes(cell->attributes.begin(), cell->attributes.end()); + std::map<RTLIL::IdString, RTLIL::Const, RTLIL::sort_by_id_str> sorted_parameters(cell->parameters.begin(), cell->parameters.end()); + std::map<RTLIL::IdString, RTLIL::SigSpec, RTLIL::sort_by_id_str> sorted_connections(cell->connections().begin(), cell->connections().end()); + + for (auto it = sorted_attributes.begin(); it != sorted_attributes.end(); it++) { + f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str()); dump_const(f, it->second); - fprintf(f, "\n"); + f << stringf("\n"); } - fprintf(f, "%s" "cell %s %s\n", indent.c_str(), cell->type.c_str(), cell->name.c_str()); - for (auto it = cell->parameters.begin(); it != cell->parameters.end(); it++) { - fprintf(f, "%s parameter%s %s ", indent.c_str(), (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "", it->first.c_str()); + f << stringf("%s" "cell %s %s\n", indent.c_str(), cell->type.c_str(), cell->name.c_str()); + for (auto it = sorted_parameters.begin(); it != sorted_parameters.end(); it++) { + f << stringf("%s parameter%s %s ", indent.c_str(), (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "", it->first.c_str()); dump_const(f, it->second); - fprintf(f, "\n"); + f << stringf("\n"); } - for (auto it = cell->connections.begin(); it != cell->connections.end(); it++) { - fprintf(f, "%s connect %s ", indent.c_str(), it->first.c_str()); + for (auto it = sorted_connections.begin(); it != sorted_connections.end(); it++) { + f << stringf("%s connect %s ", indent.c_str(), it->first.c_str()); dump_sigspec(f, it->second); - fprintf(f, "\n"); + f << stringf("\n"); } - fprintf(f, "%s" "end\n", indent.c_str()); + f << stringf("%s" "end\n", indent.c_str()); } -void ILANG_BACKEND::dump_proc_case_body(FILE *f, std::string indent, const RTLIL::CaseRule *cs) +void ILANG_BACKEND::dump_proc_case_body(std::ostream &f, std::string indent, const RTLIL::CaseRule *cs) { for (auto it = cs->actions.begin(); it != cs->actions.end(); it++) { - fprintf(f, "%s" "assign ", indent.c_str()); + f << stringf("%s" "assign ", indent.c_str()); dump_sigspec(f, it->first); - fprintf(f, " "); + f << stringf(" "); dump_sigspec(f, it->second); - fprintf(f, "\n"); + f << stringf("\n"); } for (auto it = cs->switches.begin(); it != cs->switches.end(); it++) dump_proc_switch(f, indent, *it); } -void ILANG_BACKEND::dump_proc_switch(FILE *f, std::string indent, const RTLIL::SwitchRule *sw) +void ILANG_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const RTLIL::SwitchRule *sw) { for (auto it = sw->attributes.begin(); it != sw->attributes.end(); it++) { - fprintf(f, "%s" "attribute %s ", indent.c_str(), it->first.c_str()); + f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str()); dump_const(f, it->second); - fprintf(f, "\n"); + f << stringf("\n"); } - fprintf(f, "%s" "switch ", indent.c_str()); + f << stringf("%s" "switch ", indent.c_str()); dump_sigspec(f, sw->signal); - fprintf(f, "\n"); + f << stringf("\n"); for (auto it = sw->cases.begin(); it != sw->cases.end(); it++) { - fprintf(f, "%s case ", indent.c_str()); + f << stringf("%s case ", indent.c_str()); for (size_t i = 0; i < (*it)->compare.size(); i++) { if (i > 0) - fprintf(f, ", "); + f << stringf(", "); dump_sigspec(f, (*it)->compare[i]); } - fprintf(f, "\n"); + f << stringf("\n"); dump_proc_case_body(f, indent + " ", *it); } - fprintf(f, "%s" "end\n", indent.c_str()); + f << stringf("%s" "end\n", indent.c_str()); } -void ILANG_BACKEND::dump_proc_sync(FILE *f, std::string indent, const RTLIL::SyncRule *sy) +void ILANG_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RTLIL::SyncRule *sy) { - fprintf(f, "%s" "sync ", indent.c_str()); + f << stringf("%s" "sync ", indent.c_str()); switch (sy->type) { - if (0) case RTLIL::ST0: fprintf(f, "low "); - if (0) case RTLIL::ST1: fprintf(f, "high "); - if (0) case RTLIL::STp: fprintf(f, "posedge "); - if (0) case RTLIL::STn: fprintf(f, "negedge "); - if (0) case RTLIL::STe: fprintf(f, "edge "); + if (0) case RTLIL::ST0: f << stringf("low "); + if (0) case RTLIL::ST1: f << stringf("high "); + if (0) case RTLIL::STp: f << stringf("posedge "); + if (0) case RTLIL::STn: f << stringf("negedge "); + if (0) case RTLIL::STe: f << stringf("edge "); dump_sigspec(f, sy->signal); - fprintf(f, "\n"); + f << stringf("\n"); break; - case RTLIL::STa: fprintf(f, "always\n"); break; - case RTLIL::STi: fprintf(f, "init\n"); break; + case RTLIL::STa: f << stringf("always\n"); break; + case RTLIL::STi: f << stringf("init\n"); break; } for (auto it = sy->actions.begin(); it != sy->actions.end(); it++) { - fprintf(f, "%s update ", indent.c_str()); + f << stringf("%s update ", indent.c_str()); dump_sigspec(f, it->first); - fprintf(f, " "); + f << stringf(" "); dump_sigspec(f, it->second); - fprintf(f, "\n"); + f << stringf("\n"); } } -void ILANG_BACKEND::dump_proc(FILE *f, std::string indent, const RTLIL::Process *proc) +void ILANG_BACKEND::dump_proc(std::ostream &f, std::string indent, const RTLIL::Process *proc) { for (auto it = proc->attributes.begin(); it != proc->attributes.end(); it++) { - fprintf(f, "%s" "attribute %s ", indent.c_str(), it->first.c_str()); + f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str()); dump_const(f, it->second); - fprintf(f, "\n"); + f << stringf("\n"); } - fprintf(f, "%s" "process %s\n", indent.c_str(), proc->name.c_str()); + f << stringf("%s" "process %s\n", indent.c_str(), proc->name.c_str()); dump_proc_case_body(f, indent + " ", &proc->root_case); for (auto it = proc->syncs.begin(); it != proc->syncs.end(); it++) dump_proc_sync(f, indent + " ", *it); - fprintf(f, "%s" "end\n", indent.c_str()); + f << stringf("%s" "end\n", indent.c_str()); } -void ILANG_BACKEND::dump_conn(FILE *f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right) +void ILANG_BACKEND::dump_conn(std::ostream &f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right) { - fprintf(f, "%s" "connect ", indent.c_str()); + f << stringf("%s" "connect ", indent.c_str()); dump_sigspec(f, left); - fprintf(f, " "); + f << stringf(" "); dump_sigspec(f, right); - fprintf(f, "\n"); + f << stringf("\n"); } -void ILANG_BACKEND::dump_module(FILE *f, std::string indent, const RTLIL::Module *module, const RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n) +void ILANG_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Module *module, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n) { bool print_header = flag_m || design->selected_whole_module(module->name); bool print_body = !flag_n || !design->selected_whole_module(module->name); @@ -269,51 +275,71 @@ void ILANG_BACKEND::dump_module(FILE *f, std::string indent, const RTLIL::Module if (print_header) { for (auto it = module->attributes.begin(); it != module->attributes.end(); it++) { - fprintf(f, "%s" "attribute %s ", indent.c_str(), it->first.c_str()); + f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str()); dump_const(f, it->second); - fprintf(f, "\n"); + f << stringf("\n"); } - fprintf(f, "%s" "module %s\n", indent.c_str(), module->name.c_str()); + f << stringf("%s" "module %s\n", indent.c_str(), module->name.c_str()); } if (print_body) { - for (auto it = module->wires.begin(); it != module->wires.end(); it++) - if (!only_selected || design->selected(module, it->second)) { + std::vector<RTLIL::Wire*> sorted_wires; + for (auto it : module->wires()) + sorted_wires.push_back(it); + std::sort(sorted_wires.begin(), sorted_wires.end(), RTLIL::sort_by_name_str<RTLIL::Wire>()); + + std::vector<RTLIL::Memory*> sorted_memories; + for (auto it : module->memories) + sorted_memories.push_back(it.second); + std::sort(sorted_memories.begin(), sorted_memories.end(), RTLIL::sort_by_name_str<RTLIL::Memory>()); + + std::vector<RTLIL::Cell*> sorted_cells; + for (auto it : module->cells()) + sorted_cells.push_back(it); + std::sort(sorted_cells.begin(), sorted_cells.end(), RTLIL::sort_by_name_str<RTLIL::Cell>()); + + std::vector<RTLIL::Process*> sorted_processes; + for (auto it : module->processes) + sorted_processes.push_back(it.second); + std::sort(sorted_processes.begin(), sorted_processes.end(), RTLIL::sort_by_name_str<RTLIL::Process>()); + + for (auto it : sorted_wires) + if (!only_selected || design->selected(module, it)) { if (only_selected) - fprintf(f, "\n"); - dump_wire(f, indent + " ", it->second); + f << stringf("\n"); + dump_wire(f, indent + " ", it); } - for (auto it = module->memories.begin(); it != module->memories.end(); it++) - if (!only_selected || design->selected(module, it->second)) { + for (auto it : sorted_memories) + if (!only_selected || design->selected(module, it)) { if (only_selected) - fprintf(f, "\n"); - dump_memory(f, indent + " ", it->second); + f << stringf("\n"); + dump_memory(f, indent + " ", it); } - for (auto it = module->cells.begin(); it != module->cells.end(); it++) - if (!only_selected || design->selected(module, it->second)) { + for (auto it : sorted_cells) + if (!only_selected || design->selected(module, it)) { if (only_selected) - fprintf(f, "\n"); - dump_cell(f, indent + " ", it->second); + f << stringf("\n"); + dump_cell(f, indent + " ", it); } - for (auto it = module->processes.begin(); it != module->processes.end(); it++) - if (!only_selected || design->selected(module, it->second)) { + for (auto it : sorted_processes) + if (!only_selected || design->selected(module, it)) { if (only_selected) - fprintf(f, "\n"); - dump_proc(f, indent + " ", it->second); + f << stringf("\n"); + dump_proc(f, indent + " ", it); } bool first_conn_line = true; - for (auto it = module->connections.begin(); it != module->connections.end(); it++) { + for (auto it = module->connections().begin(); it != module->connections().end(); it++) { bool show_conn = !only_selected; if (only_selected) { RTLIL::SigSpec sigs = it->first; sigs.append(it->second); - for (auto &c : sigs.chunks) { + for (auto &c : sigs.chunks()) { if (c.wire == NULL || !design->selected(module, c.wire)) continue; show_conn = true; @@ -321,7 +347,7 @@ void ILANG_BACKEND::dump_module(FILE *f, std::string indent, const RTLIL::Module } if (show_conn) { if (only_selected && first_conn_line) - fprintf(f, "\n"); + f << stringf("\n"); dump_conn(f, indent + " ", it->first, it->second); first_conn_line = false; } @@ -329,27 +355,40 @@ void ILANG_BACKEND::dump_module(FILE *f, std::string indent, const RTLIL::Module } if (print_header) - fprintf(f, "%s" "end\n", indent.c_str()); + f << stringf("%s" "end\n", indent.c_str()); } -void ILANG_BACKEND::dump_design(FILE *f, const RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n) +void ILANG_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n) { + int init_autoidx = autoidx; + if (!flag_m) { int count_selected_mods = 0; - for (auto it = design->modules.begin(); it != design->modules.end(); it++) + for (auto it = design->modules_.begin(); it != design->modules_.end(); it++) { + if (design->selected_whole_module(it->first)) + flag_m = true; if (design->selected(it->second)) count_selected_mods++; + } if (count_selected_mods > 1) flag_m = true; } - for (auto it = design->modules.begin(); it != design->modules.end(); it++) { + if (!only_selected || flag_m) { + if (only_selected) + f << stringf("\n"); + f << stringf("autoidx %d\n", autoidx); + } + + for (auto it = design->modules_.begin(); it != design->modules_.end(); it++) { if (!only_selected || design->selected(it->second)) { if (only_selected) - fprintf(f, "\n"); + f << stringf("\n"); dump_module(f, "", it->second, design, only_selected, flag_m, flag_n); } } + + log_assert(init_autoidx == autoidx); } struct IlangBackend : public Backend { @@ -367,7 +406,7 @@ struct IlangBackend : public Backend { log(" only write selected parts of the design.\n"); log("\n"); } - virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) + virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) { bool selected = false; @@ -385,8 +424,8 @@ struct IlangBackend : public Backend { extra_args(f, filename, args, argidx); log("Output filename: %s\n", filename.c_str()); - fprintf(f, "# Generated by %s\n", yosys_version_str); - ILANG_BACKEND::dump_design(f, design, selected, true, false); + *f << stringf("# Generated by %s\n", yosys_version_str); + ILANG_BACKEND::dump_design(*f, design, selected, true, false); } } IlangBackend; @@ -446,25 +485,27 @@ struct DumpPass : public Pass { } extra_args(args, argidx, design); - FILE *f = NULL; - char *buf_ptr; - size_t buf_size; + std::ostream *f; + std::stringstream buf; if (!filename.empty()) { - f = fopen(filename.c_str(), append ? "a" : "w"); - if (f == NULL) + std::ofstream *ff = new std::ofstream; + ff->open(filename.c_str(), append ? std::ofstream::app : std::ofstream::trunc); + if (ff->fail()) { + delete ff; log_error("Can't open file `%s' for writing: %s\n", filename.c_str(), strerror(errno)); + } + f = ff; } else { - f = open_memstream(&buf_ptr, &buf_size); + f = &buf; } - ILANG_BACKEND::dump_design(f, design, true, flag_m, flag_n); + ILANG_BACKEND::dump_design(*f, design, true, flag_m, flag_n); - fclose(f); - - if (filename.empty()) { - log("%s", buf_ptr); - free(buf_ptr); + if (!filename.empty()) { + delete f; + } else { + log("%s", buf.str().c_str()); } } } DumpPass; diff --git a/backends/ilang/ilang_backend.h b/backends/ilang/ilang_backend.h index fecbcc1fe..159cd7192 100644 --- a/backends/ilang/ilang_backend.h +++ b/backends/ilang/ilang_backend.h @@ -25,23 +25,27 @@ #ifndef ILANG_BACKEND_H #define ILANG_BACKEND_H -#include "kernel/rtlil.h" +#include "kernel/yosys.h" #include <stdio.h> +YOSYS_NAMESPACE_BEGIN + namespace ILANG_BACKEND { - void dump_const(FILE *f, const RTLIL::Const &data, int width = -1, int offset = 0, bool autoint = true); - void dump_sigchunk(FILE *f, const RTLIL::SigChunk &chunk, bool autoint = true); - void dump_sigspec(FILE *f, const RTLIL::SigSpec &sig, bool autoint = true); - void dump_wire(FILE *f, std::string indent, const RTLIL::Wire *wire); - void dump_memory(FILE *f, std::string indent, const RTLIL::Memory *memory); - void dump_cell(FILE *f, std::string indent, const RTLIL::Cell *cell); - void dump_proc_case_body(FILE *f, std::string indent, const RTLIL::CaseRule *cs); - void dump_proc_switch(FILE *f, std::string indent, const RTLIL::SwitchRule *sw); - void dump_proc_sync(FILE *f, std::string indent, const RTLIL::SyncRule *sy); - void dump_proc(FILE *f, std::string indent, const RTLIL::Process *proc); - void dump_conn(FILE *f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right); - void dump_module(FILE *f, std::string indent, const RTLIL::Module *module, const RTLIL::Design *design, bool only_selected, bool flag_m = true, bool flag_n = false); - void dump_design(FILE *f, const RTLIL::Design *design, bool only_selected, bool flag_m = true, bool flag_n = false); + void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int offset = 0, bool autoint = true); + void dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool autoint = true); + void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, bool autoint = true); + void dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire); + void dump_memory(std::ostream &f, std::string indent, const RTLIL::Memory *memory); + void dump_cell(std::ostream &f, std::string indent, const RTLIL::Cell *cell); + void dump_proc_case_body(std::ostream &f, std::string indent, const RTLIL::CaseRule *cs); + void dump_proc_switch(std::ostream &f, std::string indent, const RTLIL::SwitchRule *sw); + void dump_proc_sync(std::ostream &f, std::string indent, const RTLIL::SyncRule *sy); + void dump_proc(std::ostream &f, std::string indent, const RTLIL::Process *proc); + void dump_conn(std::ostream &f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right); + void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module, RTLIL::Design *design, bool only_selected, bool flag_m = true, bool flag_n = false); + void dump_design(std::ostream &f, RTLIL::Design *design, bool only_selected, bool flag_m = true, bool flag_n = false); } +YOSYS_NAMESPACE_END + #endif diff --git a/backends/intersynth/intersynth.cc b/backends/intersynth/intersynth.cc index 47c1125f7..8502d90fc 100644 --- a/backends/intersynth/intersynth.cc +++ b/backends/intersynth/intersynth.cc @@ -23,30 +23,23 @@ #include "kernel/celltypes.h" #include "kernel/log.h" #include <string> -#include <assert.h> static std::string netname(std::set<std::string> &conntypes_code, std::set<std::string> &celltypes_code, std::set<std::string> &constcells_code, RTLIL::SigSpec sig) { - sig.optimize(); - - if (sig.chunks.size() != 1) -error: + if (!sig.is_fully_const() && !sig.is_wire()) log_error("Can't export composite or non-word-wide signal %s.\n", log_signal(sig)); - conntypes_code.insert(stringf("conntype b%d %d 2 %d\n", sig.width, sig.width, sig.width)); + conntypes_code.insert(stringf("conntype b%d %d 2 %d\n", sig.size(), sig.size(), sig.size())); - if (sig.chunks[0].wire == NULL) { - celltypes_code.insert(stringf("celltype CONST_%d b%d *CONST cfg:%d VALUE\n", sig.width, sig.width, sig.width)); - constcells_code.insert(stringf("node CONST_%d_0x%x CONST_%d CONST CONST_%d_0x%x VALUE 0x%x\n", sig.width, sig.chunks[0].data.as_int(), - sig.width, sig.width, sig.chunks[0].data.as_int(), sig.chunks[0].data.as_int())); - return stringf("CONST_%d_0x%x", sig.width, sig.chunks[0].data.as_int()); + if (sig.is_fully_const()) { + celltypes_code.insert(stringf("celltype CONST_%d b%d *CONST cfg:%d VALUE\n", sig.size(), sig.size(), sig.size())); + constcells_code.insert(stringf("node CONST_%d_0x%x CONST_%d CONST CONST_%d_0x%x VALUE 0x%x\n", + sig.size(), sig.as_int(), sig.size(), sig.size(), sig.as_int(), sig.as_int())); + return stringf("CONST_%d_0x%x", sig.size(), sig.as_int()); } - if (sig.chunks[0].offset != 0 || sig.width != sig.chunks[0].wire->width) - goto error; - - return RTLIL::unescape_id(sig.chunks[0].wire->name); + return RTLIL::unescape_id(sig.as_wire()->name); } struct IntersynthBackend : public Backend { @@ -76,7 +69,7 @@ struct IntersynthBackend : public Backend { log("http://www.clifford.at/intersynth/\n"); log("\n"); } - virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) + virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) { log_header("Executing INTERSYNTH backend.\n"); log_push(); @@ -108,13 +101,13 @@ struct IntersynthBackend : public Backend { log("Output filename: %s\n", filename.c_str()); for (auto filename : libfiles) { - FILE *f = fopen(filename.c_str(), "rt"); - if (f == NULL) + std::ifstream f; + f.open(filename.c_str()); + if (f.fail()) log_error("Can't open lib file `%s'.\n", filename.c_str()); RTLIL::Design *lib = new RTLIL::Design; - Frontend::frontend_call(lib, f, filename, (filename.size() > 3 && filename.substr(filename.size()-3) == ".il") ? "ilang" : "verilog"); + Frontend::frontend_call(lib, &f, filename, (filename.size() > 3 && filename.substr(filename.size()-3) == ".il") ? "ilang" : "verilog"); libs.push_back(lib); - fclose(f); } if (libs.size() > 0) @@ -127,14 +120,14 @@ struct IntersynthBackend : public Backend { for (auto lib : libs) ct.setup_design(lib); - for (auto module_it : design->modules) + for (auto module_it : design->modules_) { RTLIL::Module *module = module_it.second; SigMap sigmap(module); if (module->get_bool_attribute("\\blackbox")) continue; - if (module->memories.size() == 0 && module->processes.size() == 0 && module->cells.size() == 0) + if (module->memories.size() == 0 && module->processes.size() == 0 && module->cells_.size() == 0) continue; if (selected && !design->selected_whole_module(module->name)) { @@ -153,7 +146,7 @@ struct IntersynthBackend : public Backend { netlists_code += stringf("netlist %s\n", RTLIL::id2cstr(module->name)); // Module Ports: "std::set<string> celltypes_code" prevents duplicate top level ports - for (auto wire_it : module->wires) { + for (auto wire_it : module->wires_) { RTLIL::Wire *wire = wire_it.second; if (wire->port_input || wire->port_output) { celltypes_code.insert(stringf("celltype !%s b%d %sPORT\n" "%s %s %d %s PORT\n", @@ -165,7 +158,7 @@ struct IntersynthBackend : public Backend { } // Submodules: "std::set<string> celltypes_code" prevents duplicate cell types - for (auto cell_it : module->cells) + for (auto cell_it : module->cells_) { RTLIL::Cell *cell = cell_it.second; std::string celltype_code, node_code; @@ -175,11 +168,11 @@ struct IntersynthBackend : public Backend { celltype_code = stringf("celltype %s", RTLIL::id2cstr(cell->type)); node_code = stringf("node %s %s", RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); - for (auto &port : cell->connections) { + for (auto &port : cell->connections()) { RTLIL::SigSpec sig = sigmap(port.second); - if (sig.width != 0) { - conntypes_code.insert(stringf("conntype b%d %d 2 %d\n", sig.width, sig.width, sig.width)); - celltype_code += stringf(" b%d %s%s", sig.width, ct.cell_output(cell->type, port.first) ? "*" : "", RTLIL::id2cstr(port.first)); + if (sig.size() != 0) { + conntypes_code.insert(stringf("conntype b%d %d 2 %d\n", sig.size(), sig.size(), sig.size())); + celltype_code += stringf(" b%d %s%s", sig.size(), ct.cell_output(cell->type, port.first) ? "*" : "", RTLIL::id2cstr(port.first)); node_code += stringf(" %s %s", RTLIL::id2cstr(port.first), netname(conntypes_code, celltypes_code, constcells_code, sig).c_str()); } } @@ -205,15 +198,15 @@ struct IntersynthBackend : public Backend { } if (!flag_notypes) { - fprintf(f, "### Connection Types\n"); + *f << stringf("### Connection Types\n"); for (auto code : conntypes_code) - fprintf(f, "%s", code.c_str()); - fprintf(f, "\n### Cell Types\n"); + *f << stringf("%s", code.c_str()); + *f << stringf("\n### Cell Types\n"); for (auto code : celltypes_code) - fprintf(f, "%s", code.c_str()); + *f << stringf("%s", code.c_str()); } - fprintf(f, "\n### Netlists\n"); - fprintf(f, "%s", netlists_code.c_str()); + *f << stringf("\n### Netlists\n"); + *f << stringf("%s", netlists_code.c_str()); for (auto lib : libs) delete lib; diff --git a/backends/spice/spice.cc b/backends/spice/spice.cc index e7926e90e..b057063cd 100644 --- a/backends/spice/spice.cc +++ b/backends/spice/spice.cc @@ -23,53 +23,51 @@ #include "kernel/celltypes.h" #include "kernel/log.h" #include <string> -#include <assert.h> -static void print_spice_net(FILE *f, RTLIL::SigSpec s, std::string &neg, std::string &pos, std::string &ncpf, int &nc_counter) +static void print_spice_net(std::ostream &f, RTLIL::SigBit s, std::string &neg, std::string &pos, std::string &ncpf, int &nc_counter) { - log_assert(s.chunks.size() == 1 && s.chunks[0].width == 1); - if (s.chunks[0].wire) { - if (s.chunks[0].wire->width > 1) - fprintf(f, " %s[%d]", RTLIL::id2cstr(s.chunks[0].wire->name), s.chunks[0].offset); + if (s.wire) { + if (s.wire->width > 1) + f << stringf(" %s[%d]", RTLIL::id2cstr(s.wire->name), s.offset); else - fprintf(f, " %s", RTLIL::id2cstr(s.chunks[0].wire->name)); + f << stringf(" %s", RTLIL::id2cstr(s.wire->name)); } else { - if (s.chunks[0].data.bits.at(0) == RTLIL::State::S0) - fprintf(f, " %s", neg.c_str()); - else if (s.chunks[0].data.bits.at(0) == RTLIL::State::S1) - fprintf(f, " %s", pos.c_str()); + if (s == RTLIL::State::S0) + f << stringf(" %s", neg.c_str()); + else if (s == RTLIL::State::S1) + f << stringf(" %s", pos.c_str()); else - fprintf(f, " %s%d", ncpf.c_str(), nc_counter++); + f << stringf(" %s%d", ncpf.c_str(), nc_counter++); } } -static void print_spice_module(FILE *f, RTLIL::Module *module, RTLIL::Design *design, std::string &neg, std::string &pos, std::string &ncpf, bool big_endian) +static void print_spice_module(std::ostream &f, RTLIL::Module *module, RTLIL::Design *design, std::string &neg, std::string &pos, std::string &ncpf, bool big_endian) { SigMap sigmap(module); int cell_counter = 0, conn_counter = 0, nc_counter = 0; - for (auto &cell_it : module->cells) + for (auto &cell_it : module->cells_) { RTLIL::Cell *cell = cell_it.second; - fprintf(f, "X%d", cell_counter++); + f << stringf("X%d", cell_counter++); std::vector<RTLIL::SigSpec> port_sigs; - if (design->modules.count(cell->type) == 0) + if (design->modules_.count(cell->type) == 0) { log("Warning: no (blackbox) module for cell type `%s' (%s.%s) found! Guessing order of ports.\n", RTLIL::id2cstr(cell->type), RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name)); - for (auto &conn : cell->connections) { + for (auto &conn : cell->connections()) { RTLIL::SigSpec sig = sigmap(conn.second); port_sigs.push_back(sig); } } else { - RTLIL::Module *mod = design->modules.at(cell->type); + RTLIL::Module *mod = design->modules_.at(cell->type); std::vector<RTLIL::Wire*> ports; - for (auto wire_it : mod->wires) { + for (auto wire_it : mod->wires_) { RTLIL::Wire *wire = wire_it.second; if (wire->port_id == 0) continue; @@ -81,8 +79,8 @@ static void print_spice_module(FILE *f, RTLIL::Module *module, RTLIL::Design *de for (RTLIL::Wire *wire : ports) { log_assert(wire != NULL); RTLIL::SigSpec sig(RTLIL::State::Sz, wire->width); - if (cell->connections.count(wire->name) > 0) { - sig = sigmap(cell->connections.at(wire->name)); + if (cell->hasPort(wire->name)) { + sig = sigmap(cell->getPort(wire->name)); sig.extend(wire->width, false); } port_sigs.push_back(sig); @@ -90,22 +88,21 @@ static void print_spice_module(FILE *f, RTLIL::Module *module, RTLIL::Design *de } for (auto &sig : port_sigs) { - for (int i = 0; i < sig.width; i++) { - RTLIL::SigSpec s = sig.extract(big_endian ? sig.width - 1 - i : i, 1); - log_assert(s.chunks.size() == 1 && s.chunks[0].width == 1); + for (int i = 0; i < sig.size(); i++) { + RTLIL::SigSpec s = sig.extract(big_endian ? sig.size() - 1 - i : i, 1); print_spice_net(f, s, neg, pos, ncpf, nc_counter); } } - fprintf(f, " %s\n", RTLIL::id2cstr(cell->type)); + f << stringf(" %s\n", RTLIL::id2cstr(cell->type)); } - for (auto &conn : module->connections) - for (int i = 0; i < conn.first.width; i++) { - fprintf(f, "V%d", conn_counter++); + for (auto &conn : module->connections()) + for (int i = 0; i < conn.first.size(); i++) { + f << stringf("V%d", conn_counter++); print_spice_net(f, conn.first.extract(i, 1), neg, pos, ncpf, nc_counter); print_spice_net(f, conn.second.extract(i, 1), neg, pos, ncpf, nc_counter); - fprintf(f, " DC 0\n"); + f << stringf(" DC 0\n"); } } @@ -136,7 +133,7 @@ struct SpiceBackend : public Backend { log(" set the specified module as design top module\n"); log("\n"); } - virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) + virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) { std::string top_module_name; RTLIL::Module *top_module = NULL; @@ -173,14 +170,14 @@ struct SpiceBackend : public Backend { extra_args(f, filename, args, argidx); if (top_module_name.empty()) - for (auto & mod_it:design->modules) + for (auto & mod_it:design->modules_) if (mod_it.second->get_bool_attribute("\\top")) - top_module_name = mod_it.first; + top_module_name = mod_it.first.str(); - fprintf(f, "* SPICE netlist generated by %s\n", yosys_version_str); - fprintf(f, "\n"); + *f << stringf("* SPICE netlist generated by %s\n", yosys_version_str); + *f << stringf("\n"); - for (auto module_it : design->modules) + for (auto module_it : design->modules_) { RTLIL::Module *module = module_it.second; if (module->get_bool_attribute("\\blackbox")) @@ -197,7 +194,7 @@ struct SpiceBackend : public Backend { } std::vector<RTLIL::Wire*> ports; - for (auto wire_it : module->wires) { + for (auto wire_it : module->wires_) { RTLIL::Wire *wire = wire_it.second; if (wire->port_id == 0) continue; @@ -206,31 +203,31 @@ struct SpiceBackend : public Backend { ports.at(wire->port_id-1) = wire; } - fprintf(f, ".SUBCKT %s", RTLIL::id2cstr(module->name)); + *f << stringf(".SUBCKT %s", RTLIL::id2cstr(module->name)); for (RTLIL::Wire *wire : ports) { log_assert(wire != NULL); if (wire->width > 1) { for (int i = 0; i < wire->width; i++) - fprintf(f, " %s[%d]", RTLIL::id2cstr(wire->name), big_endian ? wire->width - 1 - i : i); + *f << stringf(" %s[%d]", RTLIL::id2cstr(wire->name), big_endian ? wire->width - 1 - i : i); } else - fprintf(f, " %s", RTLIL::id2cstr(wire->name)); + *f << stringf(" %s", RTLIL::id2cstr(wire->name)); } - fprintf(f, "\n"); - print_spice_module(f, module, design, neg, pos, ncpf, big_endian); - fprintf(f, ".ENDS %s\n\n", RTLIL::id2cstr(module->name)); + *f << stringf("\n"); + print_spice_module(*f, module, design, neg, pos, ncpf, big_endian); + *f << stringf(".ENDS %s\n\n", RTLIL::id2cstr(module->name)); } if (!top_module_name.empty()) { if (top_module == NULL) log_error("Can't find top module `%s'!\n", top_module_name.c_str()); - print_spice_module(f, top_module, design, neg, pos, ncpf, big_endian); - fprintf(f, "\n"); + print_spice_module(*f, top_module, design, neg, pos, ncpf, big_endian); + *f << stringf("\n"); } - fprintf(f, "************************\n"); - fprintf(f, "* end of SPICE netlist *\n"); - fprintf(f, "************************\n"); - fprintf(f, "\n"); + *f << stringf("************************\n"); + *f << stringf("* end of SPICE netlist *\n"); + *f << stringf("************************\n"); + *f << stringf("\n"); } } SpiceBackend; diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index d7fe4c4e2..bbdbbbfaf 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -30,7 +30,6 @@ #include "kernel/register.h" #include "kernel/celltypes.h" #include "kernel/log.h" -#include <assert.h> #include <string> #include <sstream> #include <set> @@ -40,14 +39,12 @@ namespace { bool norename, noattr, attr2comment, noexpr; int auto_name_counter, auto_name_offset, auto_name_digits; -std::map<std::string, int> auto_name_map; +std::map<RTLIL::IdString, int> auto_name_map; +std::set<RTLIL::IdString> reg_wires, reg_ct; -std::set<std::string> reg_wires; - -CellTypes reg_ct; RTLIL::Module *active_module; -void reset_auto_counter_id(const std::string &id, bool may_rename) +void reset_auto_counter_id(RTLIL::IdString id, bool may_rename) { const char *str = id.c_str(); @@ -76,10 +73,10 @@ void reset_auto_counter(RTLIL::Module *module) reset_auto_counter_id(module->name, false); - for (auto it = module->wires.begin(); it != module->wires.end(); it++) + for (auto it = module->wires_.begin(); it != module->wires_.end(); it++) reset_auto_counter_id(it->second->name, true); - for (auto it = module->cells.begin(); it != module->cells.end(); it++) { + for (auto it = module->cells_.begin(); it != module->cells_.end(); it++) { reset_auto_counter_id(it->second->name, true); reset_auto_counter_id(it->second->type, false); } @@ -95,7 +92,7 @@ void reset_auto_counter(RTLIL::Module *module) log(" renaming `%s' to `_%0*d_'.\n", it->first.c_str(), auto_name_digits, auto_name_offset + it->second); } -std::string id(std::string internal_id, bool may_rename = true) +std::string id(RTLIL::IdString internal_id, bool may_rename = true) { const char *str = internal_id.c_str(); bool do_escape = false; @@ -133,23 +130,27 @@ std::string id(std::string internal_id, bool may_rename = true) bool is_reg_wire(RTLIL::SigSpec sig, std::string ®_name) { - sig.optimize(); - if (sig.chunks.size() != 1 || sig.chunks[0].wire == NULL) + if (!sig.is_chunk() || sig.as_chunk().wire == NULL) return false; - if (reg_wires.count(sig.chunks[0].wire->name) == 0) + + RTLIL::SigChunk chunk = sig.as_chunk(); + + if (reg_wires.count(chunk.wire->name) == 0) return false; - reg_name = id(sig.chunks[0].wire->name); - if (sig.width != sig.chunks[0].wire->width) { - if (sig.width == 1) - reg_name += stringf("[%d]", sig.chunks[0].wire->start_offset + sig.chunks[0].offset); + + reg_name = id(chunk.wire->name); + if (sig.size() != chunk.wire->width) { + if (sig.size() == 1) + reg_name += stringf("[%d]", chunk.wire->start_offset + chunk.offset); else - reg_name += stringf("[%d:%d]", sig.chunks[0].wire->start_offset + sig.chunks[0].offset + sig.chunks[0].width - 1, - sig.chunks[0].wire->start_offset + sig.chunks[0].offset); + reg_name += stringf("[%d:%d]", chunk.wire->start_offset + chunk.offset + chunk.width - 1, + chunk.wire->start_offset + chunk.offset); } + return true; } -void dump_const(FILE *f, RTLIL::Const &data, int width = -1, int offset = 0, bool no_decimal = false, bool set_signed = false) +void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int offset = 0, bool no_decimal = false, bool set_signed = false) { if (width < 0) width = data.bits.size() - offset; @@ -157,159 +158,172 @@ void dump_const(FILE *f, RTLIL::Const &data, int width = -1, int offset = 0, boo if (width == 32 && !no_decimal) { int32_t val = 0; for (int i = offset+width-1; i >= offset; i--) { - assert(i < (int)data.bits.size()); + log_assert(i < (int)data.bits.size()); if (data.bits[i] != RTLIL::S0 && data.bits[i] != RTLIL::S1) goto dump_bits; + if (data.bits[i] == RTLIL::S1 && (i - offset) == 31) + goto dump_bits; if (data.bits[i] == RTLIL::S1) val |= 1 << (i - offset); } - // fprintf(f, "%s32'sd%u", val < 0 ? "-" : "", abs(val)); - fprintf(f, "%d", val); + f << stringf("32'%sd%d", set_signed ? "s" : "", val); } else { dump_bits: - fprintf(f, "%d'%sb", width, set_signed ? "s" : ""); + f << stringf("%d'%sb", width, set_signed ? "s" : ""); if (width == 0) - fprintf(f, "0"); + f << stringf("0"); for (int i = offset+width-1; i >= offset; i--) { - assert(i < (int)data.bits.size()); + log_assert(i < (int)data.bits.size()); switch (data.bits[i]) { - case RTLIL::S0: fprintf(f, "0"); break; - case RTLIL::S1: fprintf(f, "1"); break; - case RTLIL::Sx: fprintf(f, "x"); break; - case RTLIL::Sz: fprintf(f, "z"); break; - case RTLIL::Sa: fprintf(f, "z"); break; + 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("z"); break; case RTLIL::Sm: log_error("Found marker state in final netlist."); } } } } else { - fprintf(f, "\""); + f << stringf("\""); std::string str = data.decode_string(); for (size_t i = 0; i < str.size(); i++) { if (str[i] == '\n') - fprintf(f, "\\n"); + f << stringf("\\n"); else if (str[i] == '\t') - fprintf(f, "\\t"); + f << stringf("\\t"); else if (str[i] < 32) - fprintf(f, "\\%03o", str[i]); + f << stringf("\\%03o", str[i]); else if (str[i] == '"') - fprintf(f, "\\\""); + f << stringf("\\\""); else if (str[i] == '\\') - fprintf(f, "\\\\"); + f << stringf("\\\\"); else - fputc(str[i], f); + f << str[i]; } - fprintf(f, "\""); + f << stringf("\""); } } -void dump_sigchunk(FILE *f, RTLIL::SigChunk &chunk, bool no_decimal = false) +void dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool no_decimal = false) { if (chunk.wire == NULL) { dump_const(f, chunk.data, chunk.width, chunk.offset, no_decimal); } else { - if (chunk.width == chunk.wire->width && chunk.offset == 0) - fprintf(f, "%s", id(chunk.wire->name).c_str()); - else if (chunk.width == 1) - fprintf(f, "%s[%d]", id(chunk.wire->name).c_str(), chunk.offset + chunk.wire->start_offset); - else - fprintf(f, "%s[%d:%d]", id(chunk.wire->name).c_str(), - chunk.offset + chunk.wire->start_offset + chunk.width - 1, - chunk.offset + chunk.wire->start_offset); + if (chunk.width == chunk.wire->width && chunk.offset == 0) { + f << stringf("%s", id(chunk.wire->name).c_str()); + } else if (chunk.width == 1) { + if (chunk.wire->upto) + f << stringf("%s[%d]", id(chunk.wire->name).c_str(), (chunk.wire->width - chunk.offset - 1) + chunk.wire->start_offset); + else + f << stringf("%s[%d]", id(chunk.wire->name).c_str(), chunk.offset + chunk.wire->start_offset); + } else { + if (chunk.wire->upto) + f << stringf("%s[%d:%d]", id(chunk.wire->name).c_str(), + (chunk.wire->width - (chunk.offset + chunk.width - 1) - 1) + chunk.wire->start_offset, + (chunk.wire->width - chunk.offset - 1) + chunk.wire->start_offset); + else + f << stringf("%s[%d:%d]", id(chunk.wire->name).c_str(), + (chunk.offset + chunk.width - 1) + chunk.wire->start_offset, + chunk.offset + chunk.wire->start_offset); + } } } -void dump_sigspec(FILE *f, RTLIL::SigSpec &sig) +void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig) { - if (sig.chunks.size() == 1) { - dump_sigchunk(f, sig.chunks[0]); + if (sig.is_chunk()) { + dump_sigchunk(f, sig.as_chunk()); } else { - fprintf(f, "{ "); - for (auto it = sig.chunks.rbegin(); it != sig.chunks.rend(); it++) { - if (it != sig.chunks.rbegin()) - fprintf(f, ", "); + f << stringf("{ "); + for (auto it = sig.chunks().rbegin(); it != sig.chunks().rend(); it++) { + if (it != sig.chunks().rbegin()) + f << stringf(", "); dump_sigchunk(f, *it, true); } - fprintf(f, " }"); + f << stringf(" }"); } } -void dump_attributes(FILE *f, std::string indent, std::map<RTLIL::IdString, RTLIL::Const> &attributes, char term = '\n') +void dump_attributes(std::ostream &f, std::string indent, std::map<RTLIL::IdString, RTLIL::Const> &attributes, char term = '\n') { if (noattr) return; for (auto it = attributes.begin(); it != attributes.end(); it++) { - fprintf(f, "%s" "%s %s", indent.c_str(), attr2comment ? "/*" : "(*", id(it->first).c_str()); - fprintf(f, " = "); + f << stringf("%s" "%s %s", indent.c_str(), attr2comment ? "/*" : "(*", id(it->first).c_str()); + f << stringf(" = "); dump_const(f, it->second); - fprintf(f, " %s%c", attr2comment ? "*/" : "*)", term); + f << stringf(" %s%c", attr2comment ? "*/" : "*)", term); } } -void dump_wire(FILE *f, std::string indent, RTLIL::Wire *wire) +void dump_wire(std::ostream &f, std::string indent, RTLIL::Wire *wire) { dump_attributes(f, indent, wire->attributes); #if 0 if (wire->port_input && !wire->port_output) - fprintf(f, "%s" "input %s", indent.c_str(), reg_wires.count(wire->name) ? "reg " : ""); + f << stringf("%s" "input %s", indent.c_str(), reg_wires.count(wire->name) ? "reg " : ""); else if (!wire->port_input && wire->port_output) - fprintf(f, "%s" "output %s", indent.c_str(), reg_wires.count(wire->name) ? "reg " : ""); + f << stringf("%s" "output %s", indent.c_str(), reg_wires.count(wire->name) ? "reg " : ""); else if (wire->port_input && wire->port_output) - fprintf(f, "%s" "inout %s", indent.c_str(), reg_wires.count(wire->name) ? "reg " : ""); + f << stringf("%s" "inout %s", indent.c_str(), reg_wires.count(wire->name) ? "reg " : ""); else - fprintf(f, "%s" "%s ", indent.c_str(), reg_wires.count(wire->name) ? "reg" : "wire"); + f << stringf("%s" "%s ", indent.c_str(), reg_wires.count(wire->name) ? "reg" : "wire"); if (wire->width != 1) - fprintf(f, "[%d:%d] ", wire->width - 1 + wire->start_offset, wire->start_offset); - fprintf(f, "%s;\n", id(wire->name).c_str()); + f << stringf("[%d:%d] ", wire->width - 1 + wire->start_offset, wire->start_offset); + f << stringf("%s;\n", id(wire->name).c_str()); #else // do not use Verilog-2k "outut reg" syntax in verilog export std::string range = ""; - if (wire->width != 1) - range = stringf(" [%d:%d]", wire->width - 1 + wire->start_offset, wire->start_offset); + if (wire->width != 1) { + if (wire->upto) + range = stringf(" [%d:%d]", wire->start_offset, wire->width - 1 + wire->start_offset); + else + range = stringf(" [%d:%d]", wire->width - 1 + wire->start_offset, wire->start_offset); + } if (wire->port_input && !wire->port_output) - fprintf(f, "%s" "input%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str()); + f << stringf("%s" "input%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str()); if (!wire->port_input && wire->port_output) - fprintf(f, "%s" "output%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str()); + f << stringf("%s" "output%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str()); if (wire->port_input && wire->port_output) - fprintf(f, "%s" "inout%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str()); + f << stringf("%s" "inout%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str()); if (reg_wires.count(wire->name)) - fprintf(f, "%s" "reg%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str()); + f << stringf("%s" "reg%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str()); else if (!wire->port_input && !wire->port_output) - fprintf(f, "%s" "wire%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str()); + f << stringf("%s" "wire%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str()); #endif } -void dump_memory(FILE *f, std::string indent, RTLIL::Memory *memory) +void dump_memory(std::ostream &f, std::string indent, RTLIL::Memory *memory) { dump_attributes(f, indent, memory->attributes); - fprintf(f, "%s" "reg [%d:0] %s [%d:0];\n", indent.c_str(), memory->width-1, id(memory->name).c_str(), memory->size-1); + f << stringf("%s" "reg [%d:0] %s [%d:0];\n", indent.c_str(), memory->width-1, id(memory->name).c_str(), memory->size-1); } -void dump_cell_expr_port(FILE *f, RTLIL::Cell *cell, std::string port, bool gen_signed = true) +void dump_cell_expr_port(std::ostream &f, RTLIL::Cell *cell, std::string port, bool gen_signed = true) { if (gen_signed && cell->parameters.count("\\" + port + "_SIGNED") > 0 && cell->parameters["\\" + port + "_SIGNED"].as_bool()) { - fprintf(f, "$signed("); - dump_sigspec(f, cell->connections["\\" + port]); - fprintf(f, ")"); + f << stringf("$signed("); + dump_sigspec(f, cell->getPort("\\" + port)); + f << stringf(")"); } else - dump_sigspec(f, cell->connections["\\" + port]); + dump_sigspec(f, cell->getPort("\\" + port)); } std::string cellname(RTLIL::Cell *cell) { - if (!norename && cell->name[0] == '$' && reg_ct.cell_known(cell->type) && cell->connections.count("\\Q") > 0) + if (!norename && cell->name[0] == '$' && reg_ct.count(cell->type) && cell->hasPort("\\Q")) { - RTLIL::SigSpec sig = cell->connections["\\Q"]; - if (sig.width != 1 || sig.is_fully_const()) + RTLIL::SigSpec sig = cell->getPort("\\Q"); + if (SIZE(sig) != 1 || sig.is_fully_const()) goto no_special_reg_name; - sig.optimize(); - RTLIL::Wire *wire = sig.chunks[0].wire; + RTLIL::Wire *wire = sig[0].wire; if (wire->name[0] != '\\') goto no_special_reg_name; - std::string cell_name = wire->name; + std::string cell_name = wire->name.str(); size_t pos = cell_name.find('['); if (pos != std::string::npos) @@ -318,7 +332,7 @@ std::string cellname(RTLIL::Cell *cell) cell_name = cell_name + "_reg"; if (wire->width != 1) - cell_name += stringf("[%d]", wire->start_offset + sig.chunks[0].offset); + cell_name += stringf("[%d]", wire->start_offset + sig[0].offset); if (active_module && active_module->count_id(cell_name) > 0) goto no_special_reg_name; @@ -332,107 +346,143 @@ no_special_reg_name: } } -void dump_cell_expr_uniop(FILE *f, std::string indent, RTLIL::Cell *cell, std::string op) +void dump_cell_expr_uniop(std::ostream &f, std::string indent, RTLIL::Cell *cell, std::string op) { - fprintf(f, "%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->connections["\\Y"]); - fprintf(f, " = %s ", op.c_str()); + f << stringf("%s" "assign ", indent.c_str()); + dump_sigspec(f, cell->getPort("\\Y")); + f << stringf(" = %s ", op.c_str()); dump_attributes(f, "", cell->attributes, ' '); dump_cell_expr_port(f, cell, "A", true); - fprintf(f, ";\n"); + f << stringf(";\n"); } -void dump_cell_expr_binop(FILE *f, std::string indent, RTLIL::Cell *cell, std::string op) +void dump_cell_expr_binop(std::ostream &f, std::string indent, RTLIL::Cell *cell, std::string op) { - fprintf(f, "%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->connections["\\Y"]); - fprintf(f, " = "); + f << stringf("%s" "assign ", indent.c_str()); + dump_sigspec(f, cell->getPort("\\Y")); + f << stringf(" = "); dump_cell_expr_port(f, cell, "A", true); - fprintf(f, " %s ", op.c_str()); + f << stringf(" %s ", op.c_str()); dump_attributes(f, "", cell->attributes, ' '); dump_cell_expr_port(f, cell, "B", true); - fprintf(f, ";\n"); + f << stringf(";\n"); } -bool dump_cell_expr(FILE *f, std::string indent, RTLIL::Cell *cell) +bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) { - if (cell->type == "$_INV_") { - fprintf(f, "%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->connections["\\Y"]); - fprintf(f, " = "); - fprintf(f, "~"); + if (cell->type == "$_NOT_") { + f << stringf("%s" "assign ", indent.c_str()); + dump_sigspec(f, cell->getPort("\\Y")); + f << stringf(" = "); + f << stringf("~"); dump_attributes(f, "", cell->attributes, ' '); dump_cell_expr_port(f, cell, "A", false); - fprintf(f, ";\n"); + f << stringf(";\n"); return true; } - if (cell->type == "$_AND_" || cell->type == "$_OR_" || cell->type == "$_XOR_") { - fprintf(f, "%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->connections["\\Y"]); - fprintf(f, " = "); + if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_")) { + f << stringf("%s" "assign ", indent.c_str()); + dump_sigspec(f, cell->getPort("\\Y")); + f << stringf(" = "); + if (cell->type.in("$_NAND_", "$_NOR_", "$_XNOR_")) + f << stringf("~("); dump_cell_expr_port(f, cell, "A", false); - fprintf(f, " "); - if (cell->type == "$_AND_") - fprintf(f, "&"); - if (cell->type == "$_OR_") - fprintf(f, "|"); - if (cell->type == "$_XOR_") - fprintf(f, "^"); + f << stringf(" "); + if (cell->type.in("$_AND_", "$_NAND_")) + f << stringf("&"); + if (cell->type.in("$_OR_", "$_NOR_")) + f << stringf("|"); + if (cell->type.in("$_XOR_", "$_XNOR_")) + f << stringf("^"); dump_attributes(f, "", cell->attributes, ' '); - fprintf(f, " "); + f << stringf(" "); dump_cell_expr_port(f, cell, "B", false); - fprintf(f, ";\n"); + if (cell->type.in("$_NAND_", "$_NOR_", "$_XNOR_")) + f << stringf(")"); + f << stringf(";\n"); return true; } if (cell->type == "$_MUX_") { - fprintf(f, "%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->connections["\\Y"]); - fprintf(f, " = "); + f << stringf("%s" "assign ", indent.c_str()); + dump_sigspec(f, cell->getPort("\\Y")); + f << stringf(" = "); dump_cell_expr_port(f, cell, "S", false); - fprintf(f, " ? "); + f << stringf(" ? "); dump_attributes(f, "", cell->attributes, ' '); dump_cell_expr_port(f, cell, "B", false); - fprintf(f, " : "); + f << stringf(" : "); + dump_cell_expr_port(f, cell, "A", false); + f << stringf(";\n"); + return true; + } + + if (cell->type.in("$_AOI3_", "$_OAI3_")) { + f << stringf("%s" "assign ", indent.c_str()); + dump_sigspec(f, cell->getPort("\\Y")); + f << stringf(" = ~(("); dump_cell_expr_port(f, cell, "A", false); - fprintf(f, ";\n"); + f << stringf(cell->type == "$_AOI3_" ? " & " : " | "); + dump_cell_expr_port(f, cell, "B", false); + f << stringf(cell->type == "$_AOI3_" ? ") |" : ") &"); + dump_attributes(f, "", cell->attributes, ' '); + f << stringf(" "); + dump_cell_expr_port(f, cell, "C", false); + f << stringf(");\n"); + return true; + } + + if (cell->type.in("$_AOI4_", "$_OAI4_")) { + f << stringf("%s" "assign ", indent.c_str()); + dump_sigspec(f, cell->getPort("\\Y")); + f << stringf(" = ~(("); + dump_cell_expr_port(f, cell, "A", false); + f << stringf(cell->type == "$_AOI4_" ? " & " : " | "); + dump_cell_expr_port(f, cell, "B", false); + f << stringf(cell->type == "$_AOI4_" ? ") |" : ") &"); + dump_attributes(f, "", cell->attributes, ' '); + f << stringf(" ("); + dump_cell_expr_port(f, cell, "C", false); + f << stringf(cell->type == "$_AOI4_" ? " & " : " | "); + dump_cell_expr_port(f, cell, "D", false); + f << stringf("));\n"); return true; } if (cell->type.substr(0, 6) == "$_DFF_") { std::string reg_name = cellname(cell); - bool out_is_reg_wire = is_reg_wire(cell->connections["\\Q"], reg_name); + bool out_is_reg_wire = is_reg_wire(cell->getPort("\\Q"), reg_name); if (!out_is_reg_wire) - fprintf(f, "%s" "reg %s;\n", indent.c_str(), reg_name.c_str()); + f << stringf("%s" "reg %s;\n", indent.c_str(), reg_name.c_str()); dump_attributes(f, indent, cell->attributes); - fprintf(f, "%s" "always @(%sedge ", indent.c_str(), cell->type[6] == 'P' ? "pos" : "neg"); - dump_sigspec(f, cell->connections["\\C"]); + f << stringf("%s" "always @(%sedge ", indent.c_str(), cell->type[6] == 'P' ? "pos" : "neg"); + dump_sigspec(f, cell->getPort("\\C")); if (cell->type[7] != '_') { - fprintf(f, " or %sedge ", cell->type[7] == 'P' ? "pos" : "neg"); - dump_sigspec(f, cell->connections["\\R"]); + f << stringf(" or %sedge ", cell->type[7] == 'P' ? "pos" : "neg"); + dump_sigspec(f, cell->getPort("\\R")); } - fprintf(f, ")\n"); + f << stringf(")\n"); if (cell->type[7] != '_') { - fprintf(f, "%s" " if (%s", indent.c_str(), cell->type[7] == 'P' ? "" : "!"); - dump_sigspec(f, cell->connections["\\R"]); - fprintf(f, ")\n"); - fprintf(f, "%s" " %s <= %c;\n", indent.c_str(), reg_name.c_str(), cell->type[8]); - fprintf(f, "%s" " else\n", indent.c_str()); + f << stringf("%s" " if (%s", indent.c_str(), cell->type[7] == 'P' ? "" : "!"); + dump_sigspec(f, cell->getPort("\\R")); + f << stringf(")\n"); + f << stringf("%s" " %s <= %c;\n", indent.c_str(), reg_name.c_str(), cell->type[8]); + f << stringf("%s" " else\n", indent.c_str()); } - fprintf(f, "%s" " %s <= ", indent.c_str(), reg_name.c_str()); + f << stringf("%s" " %s <= ", indent.c_str(), reg_name.c_str()); dump_cell_expr_port(f, cell, "D", false); - fprintf(f, ";\n"); + f << stringf(";\n"); if (!out_is_reg_wire) { - fprintf(f, "%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->connections["\\Q"]); - fprintf(f, " = %s;\n", reg_name.c_str()); + f << stringf("%s" "assign ", indent.c_str()); + dump_sigspec(f, cell->getPort("\\Q")); + f << stringf(" = %s;\n", reg_name.c_str()); } return true; @@ -443,39 +493,39 @@ bool dump_cell_expr(FILE *f, std::string indent, RTLIL::Cell *cell) char pol_c = cell->type[8], pol_s = cell->type[9], pol_r = cell->type[10]; std::string reg_name = cellname(cell); - bool out_is_reg_wire = is_reg_wire(cell->connections["\\Q"], reg_name); + bool out_is_reg_wire = is_reg_wire(cell->getPort("\\Q"), reg_name); if (!out_is_reg_wire) - fprintf(f, "%s" "reg %s;\n", indent.c_str(), reg_name.c_str()); + f << stringf("%s" "reg %s;\n", indent.c_str(), reg_name.c_str()); dump_attributes(f, indent, cell->attributes); - fprintf(f, "%s" "always @(%sedge ", indent.c_str(), pol_c == 'P' ? "pos" : "neg"); - dump_sigspec(f, cell->connections["\\C"]); - fprintf(f, " or %sedge ", pol_s == 'P' ? "pos" : "neg"); - dump_sigspec(f, cell->connections["\\S"]); - fprintf(f, " or %sedge ", pol_r == 'P' ? "pos" : "neg"); - dump_sigspec(f, cell->connections["\\R"]); - fprintf(f, ")\n"); - - fprintf(f, "%s" " if (%s", indent.c_str(), pol_r == 'P' ? "" : "!"); - dump_sigspec(f, cell->connections["\\R"]); - fprintf(f, ")\n"); - fprintf(f, "%s" " %s <= 0;\n", indent.c_str(), reg_name.c_str()); - - fprintf(f, "%s" " else if (%s", indent.c_str(), pol_s == 'P' ? "" : "!"); - dump_sigspec(f, cell->connections["\\S"]); - fprintf(f, ")\n"); - fprintf(f, "%s" " %s <= 1;\n", indent.c_str(), reg_name.c_str()); - - fprintf(f, "%s" " else\n", indent.c_str()); - fprintf(f, "%s" " %s <= ", indent.c_str(), reg_name.c_str()); + f << stringf("%s" "always @(%sedge ", indent.c_str(), pol_c == 'P' ? "pos" : "neg"); + dump_sigspec(f, cell->getPort("\\C")); + f << stringf(" or %sedge ", pol_s == 'P' ? "pos" : "neg"); + dump_sigspec(f, cell->getPort("\\S")); + f << stringf(" or %sedge ", pol_r == 'P' ? "pos" : "neg"); + dump_sigspec(f, cell->getPort("\\R")); + f << stringf(")\n"); + + f << stringf("%s" " if (%s", indent.c_str(), pol_r == 'P' ? "" : "!"); + dump_sigspec(f, cell->getPort("\\R")); + f << stringf(")\n"); + f << stringf("%s" " %s <= 0;\n", indent.c_str(), reg_name.c_str()); + + f << stringf("%s" " else if (%s", indent.c_str(), pol_s == 'P' ? "" : "!"); + dump_sigspec(f, cell->getPort("\\S")); + f << stringf(")\n"); + f << stringf("%s" " %s <= 1;\n", indent.c_str(), reg_name.c_str()); + + f << stringf("%s" " else\n", indent.c_str()); + f << stringf("%s" " %s <= ", indent.c_str(), reg_name.c_str()); dump_cell_expr_port(f, cell, "D", false); - fprintf(f, ";\n"); + f << stringf(";\n"); if (!out_is_reg_wire) { - fprintf(f, "%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->connections["\\Q"]); - fprintf(f, " = %s;\n", reg_name.c_str()); + f << stringf("%s" "assign ", indent.c_str()); + dump_sigspec(f, cell->getPort("\\Q")); + f << stringf(" = %s;\n", reg_name.c_str()); } return true; @@ -529,67 +579,87 @@ bool dump_cell_expr(FILE *f, std::string indent, RTLIL::Cell *cell) #undef HANDLE_UNIOP #undef HANDLE_BINOP - if (cell->type == "$mux" || cell->type == "$pmux" || cell->type == "$pmux_safe") + if (cell->type == "$mux") + { + f << stringf("%s" "assign ", indent.c_str()); + dump_sigspec(f, cell->getPort("\\Y")); + f << stringf(" = "); + dump_sigspec(f, cell->getPort("\\S")); + f << stringf(" ? "); + dump_attributes(f, "", cell->attributes, ' '); + dump_sigspec(f, cell->getPort("\\B")); + f << stringf(" : "); + dump_sigspec(f, cell->getPort("\\A")); + f << stringf(";\n"); + return true; + } + + if (cell->type == "$pmux" || cell->type == "$pmux_safe") { int width = cell->parameters["\\WIDTH"].as_int(); - int s_width = cell->connections["\\S"].width; - std::string reg_name = cellname(cell); - fprintf(f, "%s" "reg [%d:0] %s;\n", indent.c_str(), width-1, reg_name.c_str()); + int s_width = cell->getPort("\\S").size(); + std::string func_name = cellname(cell); - dump_attributes(f, indent, cell->attributes); - if (!noattr) - fprintf(f, "%s" "(* parallel_case *)\n", indent.c_str()); - fprintf(f, "%s" "always @*\n", indent.c_str()); - fprintf(f, "%s" " casez (", indent.c_str()); - dump_sigspec(f, cell->connections["\\S"]); - fprintf(f, noattr ? ") // synopsys parallel_case\n" : ")\n"); + f << stringf("%s" "function [%d:0] %s;\n", indent.c_str(), width-1, func_name.c_str()); + f << stringf("%s" " input [%d:0] a;\n", indent.c_str(), width-1); + f << stringf("%s" " input [%d:0] b;\n", indent.c_str(), s_width*width-1); + f << stringf("%s" " input [%d:0] s;\n", indent.c_str(), s_width-1); + + dump_attributes(f, indent + " ", cell->attributes); + if (cell->type != "$pmux_safe" && !noattr) + f << stringf("%s" " (* parallel_case *)\n", indent.c_str()); + f << stringf("%s" " casez (s)", indent.c_str()); + if (cell->type != "$pmux_safe") + f << stringf(noattr ? " // synopsys parallel_case\n" : "\n"); for (int i = 0; i < s_width; i++) { - fprintf(f, "%s" " %d'b", indent.c_str(), s_width); + f << stringf("%s" " %d'b", indent.c_str(), s_width); for (int j = s_width-1; j >= 0; j--) - fprintf(f, "%c", j == i ? '1' : cell->type == "$pmux_safe" ? '0' : '?'); + f << stringf("%c", j == i ? '1' : cell->type == "$pmux_safe" ? '0' : '?'); - fprintf(f, ":\n"); - fprintf(f, "%s" " %s = ", indent.c_str(), reg_name.c_str()); - - RTLIL::SigSpec s = cell->connections["\\B"].extract(i * width, width); - dump_sigspec(f, s); - fprintf(f, ";\n"); + f << stringf(":\n"); + f << stringf("%s" " %s = b[%d:%d];\n", indent.c_str(), func_name.c_str(), (i+1)*width-1, i*width); } - fprintf(f, "%s" " default:\n", indent.c_str()); - fprintf(f, "%s" " %s = ", indent.c_str(), reg_name.c_str()); - dump_sigspec(f, cell->connections["\\A"]); - fprintf(f, ";\n"); - - fprintf(f, "%s" " endcase\n", indent.c_str()); - fprintf(f, "%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->connections["\\Y"]); - fprintf(f, " = %s;\n", reg_name.c_str()); + f << stringf("%s" " default:\n", indent.c_str()); + f << stringf("%s" " %s = a;\n", indent.c_str(), func_name.c_str()); + + f << stringf("%s" " endcase\n", indent.c_str()); + f << stringf("%s" "endfunction\n", indent.c_str()); + + f << stringf("%s" "assign ", indent.c_str()); + dump_sigspec(f, cell->getPort("\\Y")); + f << stringf(" = %s(", func_name.c_str()); + dump_sigspec(f, cell->getPort("\\A")); + f << stringf(", "); + dump_sigspec(f, cell->getPort("\\B")); + f << stringf(", "); + dump_sigspec(f, cell->getPort("\\S")); + f << stringf(");\n"); return true; } if (cell->type == "$slice") { - fprintf(f, "%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->connections["\\Y"]); - fprintf(f, " = "); - dump_sigspec(f, cell->connections["\\A"]); - fprintf(f, " >> %d;\n", cell->parameters.at("\\OFFSET").as_int()); + f << stringf("%s" "assign ", indent.c_str()); + dump_sigspec(f, cell->getPort("\\Y")); + f << stringf(" = "); + dump_sigspec(f, cell->getPort("\\A")); + f << stringf(" >> %d;\n", cell->parameters.at("\\OFFSET").as_int()); return true; } if (cell->type == "$concat") { - fprintf(f, "%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->connections["\\Y"]); - fprintf(f, " = { "); - dump_sigspec(f, cell->connections["\\B"]); - fprintf(f, " , "); - dump_sigspec(f, cell->connections["\\A"]); - fprintf(f, " };\n"); + f << stringf("%s" "assign ", indent.c_str()); + dump_sigspec(f, cell->getPort("\\Y")); + f << stringf(" = { "); + dump_sigspec(f, cell->getPort("\\B")); + f << stringf(" , "); + dump_sigspec(f, cell->getPort("\\A")); + f << stringf(" };\n"); return true; } @@ -598,59 +668,59 @@ bool dump_cell_expr(FILE *f, std::string indent, RTLIL::Cell *cell) RTLIL::SigSpec sig_clk, sig_arst, val_arst; bool pol_clk, pol_arst = false; - sig_clk = cell->connections["\\CLK"]; + sig_clk = cell->getPort("\\CLK"); pol_clk = cell->parameters["\\CLK_POLARITY"].as_bool(); if (cell->type == "$adff") { - sig_arst = cell->connections["\\ARST"]; + sig_arst = cell->getPort("\\ARST"); pol_arst = cell->parameters["\\ARST_POLARITY"].as_bool(); val_arst = RTLIL::SigSpec(cell->parameters["\\ARST_VALUE"]); } std::string reg_name = cellname(cell); - bool out_is_reg_wire = is_reg_wire(cell->connections["\\Q"], reg_name); + bool out_is_reg_wire = is_reg_wire(cell->getPort("\\Q"), reg_name); if (!out_is_reg_wire) - fprintf(f, "%s" "reg [%d:0] %s;\n", indent.c_str(), cell->parameters["\\WIDTH"].as_int()-1, reg_name.c_str()); + f << stringf("%s" "reg [%d:0] %s;\n", indent.c_str(), cell->parameters["\\WIDTH"].as_int()-1, reg_name.c_str()); - fprintf(f, "%s" "always @(%sedge ", indent.c_str(), pol_clk ? "pos" : "neg"); + f << stringf("%s" "always @(%sedge ", indent.c_str(), pol_clk ? "pos" : "neg"); dump_sigspec(f, sig_clk); if (cell->type == "$adff") { - fprintf(f, " or %sedge ", pol_arst ? "pos" : "neg"); + f << stringf(" or %sedge ", pol_arst ? "pos" : "neg"); dump_sigspec(f, sig_arst); } - fprintf(f, ")\n"); + f << stringf(")\n"); if (cell->type == "$adff") { - fprintf(f, "%s" " if (%s", indent.c_str(), pol_arst ? "" : "!"); + f << stringf("%s" " if (%s", indent.c_str(), pol_arst ? "" : "!"); dump_sigspec(f, sig_arst); - fprintf(f, ")\n"); - fprintf(f, "%s" " %s <= ", indent.c_str(), reg_name.c_str()); + f << stringf(")\n"); + f << stringf("%s" " %s <= ", indent.c_str(), reg_name.c_str()); dump_sigspec(f, val_arst); - fprintf(f, ";\n"); - fprintf(f, "%s" " else\n", indent.c_str()); + f << stringf(";\n"); + f << stringf("%s" " else\n", indent.c_str()); } - fprintf(f, "%s" " %s <= ", indent.c_str(), reg_name.c_str()); + f << stringf("%s" " %s <= ", indent.c_str(), reg_name.c_str()); dump_cell_expr_port(f, cell, "D", false); - fprintf(f, ";\n"); + f << stringf(";\n"); if (!out_is_reg_wire) { - fprintf(f, "%s" "assign ", indent.c_str()); - dump_sigspec(f, cell->connections["\\Q"]); - fprintf(f, " = %s;\n", reg_name.c_str()); + f << stringf("%s" "assign ", indent.c_str()); + dump_sigspec(f, cell->getPort("\\Q")); + f << stringf(" = %s;\n", reg_name.c_str()); } return true; } - // FIXME: $_SR_[PN][PN]_, $_DLATCH_[PN]_ + // FIXME: $_SR_[PN][PN]_, $_DLATCH_[PN]_, $_DLATCHSR_[PN][PN][PN]_ // FIXME: $sr, $dffsr, $dlatch, $memrd, $memwr, $mem, $fsm return false; } -void dump_cell(FILE *f, std::string indent, RTLIL::Cell *cell) +void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) { if (cell->type[0] == '$' && !noexpr) { if (dump_cell_expr(f, indent, cell)) @@ -658,39 +728,39 @@ void dump_cell(FILE *f, std::string indent, RTLIL::Cell *cell) } dump_attributes(f, indent, cell->attributes); - fprintf(f, "%s" "%s", indent.c_str(), id(cell->type, false).c_str()); + f << stringf("%s" "%s", indent.c_str(), id(cell->type, false).c_str()); if (cell->parameters.size() > 0) { - fprintf(f, " #("); + f << stringf(" #("); for (auto it = cell->parameters.begin(); it != cell->parameters.end(); it++) { if (it != cell->parameters.begin()) - fprintf(f, ","); - fprintf(f, "\n%s .%s(", indent.c_str(), id(it->first).c_str()); + 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, !is_signed, is_signed); - fprintf(f, ")"); + f << stringf(")"); } - fprintf(f, "\n%s" ")", indent.c_str()); + f << stringf("\n%s" ")", indent.c_str()); } std::string cell_name = cellname(cell); if (cell_name != id(cell->name)) - fprintf(f, " %s /* %s */ (", cell_name.c_str(), id(cell->name).c_str()); + f << stringf(" %s /* %s */ (", cell_name.c_str(), id(cell->name).c_str()); else - fprintf(f, " %s (", cell_name.c_str()); + f << stringf(" %s (", cell_name.c_str()); bool first_arg = true; - std::set<std::string> numbered_ports; + std::set<RTLIL::IdString> numbered_ports; for (int i = 1; true; i++) { char str[16]; snprintf(str, 16, "$%d", i); - for (auto it = cell->connections.begin(); it != cell->connections.end(); it++) { + for (auto it = cell->connections().begin(); it != cell->connections().end(); it++) { if (it->first != str) continue; if (!first_arg) - fprintf(f, ","); + f << stringf(","); first_arg = false; - fprintf(f, "\n%s ", indent.c_str()); + f << stringf("\n%s ", indent.c_str()); dump_sigspec(f, it->second); numbered_ports.insert(it->first); goto found_numbered_port; @@ -698,90 +768,90 @@ void dump_cell(FILE *f, std::string indent, RTLIL::Cell *cell) break; found_numbered_port:; } - for (auto it = cell->connections.begin(); it != cell->connections.end(); it++) { + for (auto it = cell->connections().begin(); it != cell->connections().end(); it++) { if (numbered_ports.count(it->first)) continue; if (!first_arg) - fprintf(f, ","); + f << stringf(","); first_arg = false; - fprintf(f, "\n%s .%s(", indent.c_str(), id(it->first).c_str()); - if (it->second.width > 0) + f << stringf("\n%s .%s(", indent.c_str(), id(it->first).c_str()); + if (it->second.size() > 0) dump_sigspec(f, it->second); - fprintf(f, ")"); + f << stringf(")"); } - fprintf(f, "\n%s" ");\n", indent.c_str()); + f << stringf("\n%s" ");\n", indent.c_str()); } -void dump_conn(FILE *f, std::string indent, RTLIL::SigSpec &left, RTLIL::SigSpec &right) +void dump_conn(std::ostream &f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right) { - fprintf(f, "%s" "assign ", indent.c_str()); + f << stringf("%s" "assign ", indent.c_str()); dump_sigspec(f, left); - fprintf(f, " = "); + f << stringf(" = "); dump_sigspec(f, right); - fprintf(f, ";\n"); + f << stringf(";\n"); } -void dump_proc_switch(FILE *f, std::string indent, RTLIL::SwitchRule *sw); +void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw); -void dump_case_body(FILE *f, std::string indent, RTLIL::CaseRule *cs, bool omit_trailing_begin = false) +void dump_case_body(std::ostream &f, std::string indent, RTLIL::CaseRule *cs, bool omit_trailing_begin = false) { int number_of_stmts = cs->switches.size() + cs->actions.size(); if (!omit_trailing_begin && number_of_stmts >= 2) - fprintf(f, "%s" "begin\n", indent.c_str()); + f << stringf("%s" "begin\n", indent.c_str()); for (auto it = cs->actions.begin(); it != cs->actions.end(); it++) { - if (it->first.width == 0) + if (it->first.size() == 0) continue; - fprintf(f, "%s ", indent.c_str()); + f << stringf("%s ", indent.c_str()); dump_sigspec(f, it->first); - fprintf(f, " = "); + f << stringf(" = "); dump_sigspec(f, it->second); - fprintf(f, ";\n"); + f << stringf(";\n"); } for (auto it = cs->switches.begin(); it != cs->switches.end(); it++) dump_proc_switch(f, indent + " ", *it); if (!omit_trailing_begin && number_of_stmts == 0) - fprintf(f, "%s /* empty */;\n", indent.c_str()); + f << stringf("%s /* empty */;\n", indent.c_str()); if (omit_trailing_begin || number_of_stmts >= 2) - fprintf(f, "%s" "end\n", indent.c_str()); + f << stringf("%s" "end\n", indent.c_str()); } -void dump_proc_switch(FILE *f, std::string indent, RTLIL::SwitchRule *sw) +void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw) { - if (sw->signal.width == 0) { - fprintf(f, "%s" "begin\n", indent.c_str()); + if (sw->signal.size() == 0) { + f << stringf("%s" "begin\n", indent.c_str()); for (auto it = sw->cases.begin(); it != sw->cases.end(); it++) { if ((*it)->compare.size() == 0) dump_case_body(f, indent + " ", *it); } - fprintf(f, "%s" "end\n", indent.c_str()); + f << stringf("%s" "end\n", indent.c_str()); return; } - fprintf(f, "%s" "casez (", indent.c_str()); + f << stringf("%s" "casez (", indent.c_str()); dump_sigspec(f, sw->signal); - fprintf(f, ")\n"); + f << stringf(")\n"); for (auto it = sw->cases.begin(); it != sw->cases.end(); it++) { - fprintf(f, "%s ", indent.c_str()); + f << stringf("%s ", indent.c_str()); if ((*it)->compare.size() == 0) - fprintf(f, "default"); + f << stringf("default"); else { for (size_t i = 0; i < (*it)->compare.size(); i++) { if (i > 0) - fprintf(f, ", "); + f << stringf(", "); dump_sigspec(f, (*it)->compare[i]); } } - fprintf(f, ":\n"); + f << stringf(":\n"); dump_case_body(f, indent + " ", *it); } - fprintf(f, "%s" "endcase\n", indent.c_str()); + f << stringf("%s" "endcase\n", indent.c_str()); } void case_body_find_regs(RTLIL::CaseRule *cs) @@ -791,26 +861,26 @@ void case_body_find_regs(RTLIL::CaseRule *cs) case_body_find_regs(*it2); for (auto it = cs->actions.begin(); it != cs->actions.end(); it++) { - for (size_t i = 0; i < it->first.chunks.size(); i++) - if (it->first.chunks[i].wire) - reg_wires.insert(it->first.chunks[i].wire->name); + for (auto &c : it->first.chunks()) + if (c.wire != NULL) + reg_wires.insert(c.wire->name); } } -void dump_process(FILE *f, std::string indent, RTLIL::Process *proc, bool find_regs = false) +void dump_process(std::ostream &f, std::string indent, RTLIL::Process *proc, bool find_regs = false) { if (find_regs) { case_body_find_regs(&proc->root_case); for (auto it = proc->syncs.begin(); it != proc->syncs.end(); it++) for (auto it2 = (*it)->actions.begin(); it2 != (*it)->actions.end(); it2++) { - for (size_t i = 0; i < it2->first.chunks.size(); i++) - if (it2->first.chunks[i].wire) - reg_wires.insert(it2->first.chunks[i].wire->name); + for (auto &c : it2->first.chunks()) + if (c.wire != NULL) + reg_wires.insert(c.wire->name); } return; } - fprintf(f, "%s" "always @* begin\n", indent.c_str()); + f << stringf("%s" "always @* begin\n", indent.c_str()); dump_case_body(f, indent, &proc->root_case, true); std::string backup_indent = indent; @@ -821,23 +891,23 @@ void dump_process(FILE *f, std::string indent, RTLIL::Process *proc, bool find_r indent = backup_indent; if (sync->type == RTLIL::STa) { - fprintf(f, "%s" "always @* begin\n", indent.c_str()); + f << stringf("%s" "always @* begin\n", indent.c_str()); } else { - fprintf(f, "%s" "always @(", indent.c_str()); + f << stringf("%s" "always @(", indent.c_str()); if (sync->type == RTLIL::STp || sync->type == RTLIL::ST1) - fprintf(f, "posedge "); + f << stringf("posedge "); if (sync->type == RTLIL::STn || sync->type == RTLIL::ST0) - fprintf(f, "negedge "); + f << stringf("negedge "); dump_sigspec(f, sync->signal); - fprintf(f, ") begin\n"); + f << stringf(") begin\n"); } std::string ends = indent + "end\n"; indent += " "; if (sync->type == RTLIL::ST0 || sync->type == RTLIL::ST1) { - fprintf(f, "%s" "if (%s", indent.c_str(), sync->type == RTLIL::ST0 ? "!" : ""); + f << stringf("%s" "if (%s", indent.c_str(), sync->type == RTLIL::ST0 ? "!" : ""); dump_sigspec(f, sync->signal); - fprintf(f, ") begin\n"); + f << stringf(") begin\n"); ends = indent + "end\n" + ends; indent += " "; } @@ -846,9 +916,9 @@ void dump_process(FILE *f, std::string indent, RTLIL::Process *proc, bool find_r for (size_t j = 0; j < proc->syncs.size(); j++) { RTLIL::SyncRule *sync2 = proc->syncs[j]; if (sync2->type == RTLIL::ST0 || sync2->type == RTLIL::ST1) { - fprintf(f, "%s" "if (%s", indent.c_str(), sync2->type == RTLIL::ST1 ? "!" : ""); + f << stringf("%s" "if (%s", indent.c_str(), sync2->type == RTLIL::ST1 ? "!" : ""); dump_sigspec(f, sync2->signal); - fprintf(f, ") begin\n"); + f << stringf(") begin\n"); ends = indent + "end\n" + ends; indent += " "; } @@ -856,90 +926,93 @@ void dump_process(FILE *f, std::string indent, RTLIL::Process *proc, bool find_r } for (auto it = sync->actions.begin(); it != sync->actions.end(); it++) { - if (it->first.width == 0) + if (it->first.size() == 0) continue; - fprintf(f, "%s ", indent.c_str()); + f << stringf("%s ", indent.c_str()); dump_sigspec(f, it->first); - fprintf(f, " <= "); + f << stringf(" <= "); dump_sigspec(f, it->second); - fprintf(f, ";\n"); + f << stringf(";\n"); } - fprintf(f, "%s", ends.c_str()); + f << stringf("%s", ends.c_str()); } } -void dump_module(FILE *f, std::string indent, RTLIL::Module *module) +void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) { reg_wires.clear(); reset_auto_counter(module); active_module = module; - fprintf(f, "\n"); + f << stringf("\n"); for (auto it = module->processes.begin(); it != module->processes.end(); it++) dump_process(f, indent + " ", it->second, true); if (!noexpr) { std::set<std::pair<RTLIL::Wire*,int>> reg_bits; - for (auto &it : module->cells) + for (auto &it : module->cells_) { RTLIL::Cell *cell = it.second; - if (!reg_ct.cell_known(cell->type) || cell->connections.count("\\Q") == 0) + if (!reg_ct.count(cell->type) || !cell->hasPort("\\Q")) continue; - RTLIL::SigSpec sig = cell->connections["\\Q"]; - sig.optimize(); + RTLIL::SigSpec sig = cell->getPort("\\Q"); - if (sig.chunks.size() == 1 && sig.chunks[0].wire) - for (int i = 0; i < sig.chunks[0].width; i++) - reg_bits.insert(std::pair<RTLIL::Wire*,int>(sig.chunks[0].wire, sig.chunks[0].offset+i)); + if (sig.is_chunk()) { + RTLIL::SigChunk chunk = sig.as_chunk(); + if (chunk.wire != NULL) + for (int i = 0; i < chunk.width; i++) + reg_bits.insert(std::pair<RTLIL::Wire*,int>(chunk.wire, chunk.offset+i)); + } } - for (auto &it : module->wires) + for (auto &it : module->wires_) { RTLIL::Wire *wire = it.second; for (int i = 0; i < wire->width; i++) if (reg_bits.count(std::pair<RTLIL::Wire*,int>(wire, i)) == 0) goto this_wire_aint_reg; - reg_wires.insert(wire->name); + if (wire->width) + reg_wires.insert(wire->name); this_wire_aint_reg:; } } dump_attributes(f, indent, module->attributes); - fprintf(f, "%s" "module %s(", indent.c_str(), id(module->name, false).c_str()); + f << stringf("%s" "module %s(", indent.c_str(), id(module->name, false).c_str()); bool keep_running = true; for (int port_id = 1; keep_running; port_id++) { keep_running = false; - for (auto it = module->wires.begin(); it != module->wires.end(); it++) { + for (auto it = module->wires_.begin(); it != module->wires_.end(); it++) { RTLIL::Wire *wire = it->second; if (wire->port_id == port_id) { if (port_id != 1) - fprintf(f, ", "); - fprintf(f, "%s", id(wire->name).c_str()); + f << stringf(", "); + f << stringf("%s", id(wire->name).c_str()); keep_running = true; continue; } } } - fprintf(f, ");\n"); + f << stringf(");\n"); - for (auto it = module->wires.begin(); it != module->wires.end(); it++) + for (auto it = module->wires_.begin(); it != module->wires_.end(); it++) dump_wire(f, indent + " ", it->second); for (auto it = module->memories.begin(); it != module->memories.end(); it++) dump_memory(f, indent + " ", it->second); - for (auto it = module->cells.begin(); it != module->cells.end(); it++) + for (auto it = module->cells_.begin(); it != module->cells_.end(); it++) dump_cell(f, indent + " ", it->second); for (auto it = module->processes.begin(); it != module->processes.end(); it++) dump_process(f, indent + " ", it->second); - for (auto it = module->connections.begin(); it != module->connections.end(); it++) + for (auto it = module->connections().begin(); it != module->connections().end(); it++) dump_conn(f, indent + " ", it->first, it->second); - fprintf(f, "%s" "endmodule\n", indent.c_str()); + f << stringf("%s" "endmodule\n", indent.c_str()); active_module = NULL; } @@ -980,7 +1053,7 @@ struct VerilogBackend : public Backend { log(" not at all.\n"); log("\n"); } - virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) + virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) { log_header("Executing Verilog backend.\n"); @@ -993,10 +1066,30 @@ struct VerilogBackend : public Backend { bool selected = false; reg_ct.clear(); - reg_ct.setup_stdcells_mem(); - reg_ct.cell_types.insert("$sr"); - reg_ct.cell_types.insert("$dff"); - reg_ct.cell_types.insert("$adff"); + + reg_ct.insert("$dff"); + reg_ct.insert("$adff"); + + reg_ct.insert("$_DFF_N_"); + reg_ct.insert("$_DFF_P_"); + + reg_ct.insert("$_DFF_NN0_"); + reg_ct.insert("$_DFF_NN1_"); + reg_ct.insert("$_DFF_NP0_"); + reg_ct.insert("$_DFF_NP1_"); + reg_ct.insert("$_DFF_PN0_"); + reg_ct.insert("$_DFF_PN1_"); + reg_ct.insert("$_DFF_PP0_"); + reg_ct.insert("$_DFF_PP1_"); + + reg_ct.insert("$_DFFSR_NNN_"); + reg_ct.insert("$_DFFSR_NNP_"); + reg_ct.insert("$_DFFSR_NPN_"); + reg_ct.insert("$_DFFSR_NPP_"); + reg_ct.insert("$_DFFSR_PNN_"); + reg_ct.insert("$_DFFSR_PNP_"); + reg_ct.insert("$_DFFSR_PPN_"); + reg_ct.insert("$_DFFSR_PPP_"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -1029,8 +1122,8 @@ struct VerilogBackend : public Backend { } extra_args(f, filename, args, argidx); - fprintf(f, "/* Generated by %s */\n", yosys_version_str); - for (auto it = design->modules.begin(); it != design->modules.end(); it++) { + *f << stringf("/* Generated by %s */\n", yosys_version_str); + for (auto it = design->modules_.begin(); it != design->modules_.end(); it++) { if (it->second->get_bool_attribute("\\blackbox") != blackboxes) continue; if (selected && !design->selected_whole_module(it->first)) { @@ -1039,7 +1132,7 @@ struct VerilogBackend : public Backend { continue; } log("Dumping module `%s'.\n", it->first.c_str()); - dump_module(f, "", it->second); + dump_module(*f, "", it->second); } reg_ct.clear(); diff --git a/backends/verilog/verilog_backend.h b/backends/verilog/verilog_backend.h index c40830ef2..7e6ef5ab9 100644 --- a/backends/verilog/verilog_backend.h +++ b/backends/verilog/verilog_backend.h @@ -29,11 +29,10 @@ #ifndef VERILOG_BACKEND_H #define VERILOG_BACKEND_H -#include "kernel/rtlil.h" -#include <stdio.h> +#include "kernel/yosys.h" namespace VERILOG_BACKEND { - void verilog_backend(FILE *f, std::vector<std::string> args, RTLIL::Design *design); + void verilog_backend(std::ostream &f, std::vector<std::string> args, RTLIL::Design *design); } #endif |