diff options
author | Ahmed Irfan <ahmedirfan1983@gmail.com> | 2014-09-22 11:35:04 +0200 |
---|---|---|
committer | Ahmed Irfan <ahmedirfan1983@gmail.com> | 2014-09-22 11:35:04 +0200 |
commit | d3c67ad9b61f602de1100cd264efd227dcacb417 (patch) | |
tree | 88c462c53bdab128cd1edbded42483772f82612a /backends/blif/blif.cc | |
parent | b783dbe148e6d246ebd107c0913de2989ab5af48 (diff) | |
parent | 13117bb346dd02d2345f716b4403239aebe3d0e2 (diff) | |
download | yosys-d3c67ad9b61f602de1100cd264efd227dcacb417.tar.gz yosys-d3c67ad9b61f602de1100cd264efd227dcacb417.tar.bz2 yosys-d3c67ad9b61f602de1100cd264efd227dcacb417.zip |
Merge branch 'master' of https://github.com/cliffordwolf/yosys into btor
added case for memwr cell that is used in muxes (same cell is used more than one time)
corrected bug for xnor and logic_not
added pmux cell translation
Conflicts:
backends/btor/btor.cc
Diffstat (limited to 'backends/blif/blif.cc')
-rw-r--r-- | backends/blif/blif.cc | 221 |
1 files changed, 144 insertions, 77 deletions
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; |