aboutsummaryrefslogtreecommitdiffstats
path: root/backends/blif/blif.cc
diff options
context:
space:
mode:
Diffstat (limited to 'backends/blif/blif.cc')
-rw-r--r--backends/blif/blif.cc152
1 files changed, 112 insertions, 40 deletions
diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc
index ee12546ce..f6aac0b41 100644
--- a/backends/blif/blif.cc
+++ b/backends/blif/blif.cc
@@ -28,6 +28,9 @@
#include "kernel/log.h"
#include <string>
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
struct BlifDumperConfig
{
bool icells_mode;
@@ -35,11 +38,14 @@ struct BlifDumperConfig
bool impltf_mode;
bool gates_mode;
bool param_mode;
+ bool attr_mode;
+ bool blackbox_mode;
std::string buf_type, buf_in, buf_out;
- std::string true_type, true_out, false_type, false_out;
+ std::map<RTLIL::IdString, std::pair<RTLIL::IdString, RTLIL::IdString>> unbuf_types;
+ std::string true_type, true_out, false_type, false_out, undef_type, undef_out;
- BlifDumperConfig() : icells_mode(false), conn_mode(false), impltf_mode(false), gates_mode(false), param_mode(false) { }
+ BlifDumperConfig() : icells_mode(false), conn_mode(false), impltf_mode(false), gates_mode(false), param_mode(false), attr_mode(false), blackbox_mode(false) { }
};
struct BlifDumper
@@ -69,8 +75,11 @@ struct BlifDumper
const char *cstr(RTLIL::SigBit sig)
{
- if (sig.wire == NULL)
- return sig == RTLIL::State::S1 ? "$true" : "$false";
+ if (sig.wire == NULL) {
+ if (sig == RTLIL::State::S0) return config->false_type == "-" ? config->false_out.c_str() : "$false";
+ if (sig == RTLIL::State::S1) return config->true_type == "-" ? config->true_out.c_str() : "$true";
+ return config->undef_type == "-" ? config->undef_out.c_str() : "$undef";
+ }
std::string str = RTLIL::unescape_id(sig.wire->name);
for (size_t i = 0; i < str.size(); i++)
@@ -95,6 +104,26 @@ struct BlifDumper
return "subckt";
}
+ void dump_params(const char *command, dict<IdString, Const> &params)
+ {
+ for (auto &param : params) {
+ f << stringf("%s %s ", command, 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());
+ }
+ }
+
void dump()
{
f << stringf("\n");
@@ -126,23 +155,44 @@ struct BlifDumper
}
f << stringf("\n");
+ if (module->get_bool_attribute("\\blackbox")) {
+ f << stringf(".blackbox\n");
+ f << stringf(".end\n");
+ return;
+ }
+
if (!config->impltf_mode) {
- if (!config->false_type.empty())
- f << stringf(".%s %s %s=$false\n", subckt_or_gate(config->false_type),
- config->false_type.c_str(), config->false_out.c_str());
- else
+ if (!config->false_type.empty()) {
+ if (config->false_type != "-")
+ f << stringf(".%s %s %s=$false\n", subckt_or_gate(config->false_type),
+ config->false_type.c_str(), config->false_out.c_str());
+ } else
f << stringf(".names $false\n");
- if (!config->true_type.empty())
- f << stringf(".%s %s %s=$true\n", subckt_or_gate(config->true_type),
- config->true_type.c_str(), config->true_out.c_str());
- else
+ if (!config->true_type.empty()) {
+ if (config->true_type != "-")
+ f << stringf(".%s %s %s=$true\n", subckt_or_gate(config->true_type),
+ config->true_type.c_str(), config->true_out.c_str());
+ } else
f << stringf(".names $true\n1\n");
+ if (!config->undef_type.empty()) {
+ if (config->undef_type != "-")
+ f << stringf(".%s %s %s=$undef\n", subckt_or_gate(config->undef_type),
+ config->undef_type.c_str(), config->undef_out.c_str());
+ } else
+ f << stringf(".names $undef\n");
}
for (auto &cell_it : module->cells_)
{
RTLIL::Cell *cell = cell_it.second;
+ if (config->unbuf_types.count(cell->type)) {
+ auto portnames = config->unbuf_types.at(cell->type);
+ f << stringf(".names %s %s\n1 1\n",
+ cstr(cell->getPort(portnames.first)), cstr(cell->getPort(portnames.second)));
+ continue;
+ }
+
if (!config->icells_mode && cell->type == "$_NOT_") {
f << stringf(".names %s %s\n0 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\Y")));
@@ -191,21 +241,21 @@ struct BlifDumper
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++) {
+ for (int i = width-1; i >= 0; 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');
+ RTLIL::SigSpec mask = cell->parameters.at("\\LUT");
+ for (int i = 0; i < (1 << width); i++)
+ if (mask[i] == RTLIL::S1) {
+ for (int j = width-1; j >= 0; j--) {
+ f << ((i>>j)&1 ? '1' : '0');
+ }
+ f << " 1\n";
}
- f << stringf(" %c\n", mask[i]);
- }
continue;
}
@@ -220,23 +270,10 @@ struct BlifDumper
}
f << stringf("\n");
+ if (config->attr_mode)
+ dump_params(".attr", cell->attributes);
if (config->param_mode)
- for (auto &param : 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());
- }
+ dump_params(".param", cell->parameters);
}
for (auto &conn : module->connections())
@@ -276,9 +313,17 @@ struct BlifBackend : public Backend {
log(" -buf <cell-type> <in-port> <out-port>\n");
log(" use cells of type <cell-type> with the specified port names for buffers\n");
log("\n");
+ log(" -unbuf <cell-type> <in-port> <out-port>\n");
+ log(" replace buffer cells with the specified name and port names with\n");
+ log(" a .names statement that models a buffer\n");
+ log("\n");
log(" -true <cell-type> <out-port>\n");
log(" -false <cell-type> <out-port>\n");
- log(" use the specified cell types to drive nets that are constant 1 or 0\n");
+ log(" -undef <cell-type> <out-port>\n");
+ log(" use the specified cell types to drive nets that are constant 1, 0, or\n");
+ log(" undefined. when '-' is used as <cell-type>, then <out-port> specifies\n");
+ log(" the wire name to be used for the constant signal and no cell driving\n");
+ log(" that wire is generated.\n");
log("\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");
@@ -296,11 +341,17 @@ struct BlifBackend : public Backend {
log(" do not generate buffers for connected wires. instead use the\n");
log(" non-standard .conn statement.\n");
log("\n");
+ log(" -attr\n");
+ log(" use the non-standard .attr statement to write cell attributes\n");
+ log("\n");
log(" -param\n");
- log(" use the non-standard .param statement to write module parameters\n");
+ log(" use the non-standard .param statement to write cell parameters\n");
+ log("\n");
+ log(" -blackbox\n");
+ log(" write blackbox cells with .blackbox statement.\n");
log("\n");
log(" -impltf\n");
- log(" do not write definitions for the $true and $false wires.\n");
+ log(" do not write definitions for the $true, $false and $undef wires.\n");
log("\n");
}
virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
@@ -326,6 +377,13 @@ struct BlifBackend : public Backend {
config.buf_out = args[++argidx];
continue;
}
+ if (args[argidx] == "-unbuf" && argidx+3 < args.size()) {
+ RTLIL::IdString unbuf_type = RTLIL::escape_id(args[++argidx]);
+ RTLIL::IdString unbuf_in = RTLIL::escape_id(args[++argidx]);
+ RTLIL::IdString unbuf_out = RTLIL::escape_id(args[++argidx]);
+ config.unbuf_types[unbuf_type] = std::pair<RTLIL::IdString, RTLIL::IdString>(unbuf_in, unbuf_out);
+ continue;
+ }
if (args[argidx] == "-true" && argidx+2 < args.size()) {
config.true_type = args[++argidx];
config.true_out = args[++argidx];
@@ -336,6 +394,11 @@ struct BlifBackend : public Backend {
config.false_out = args[++argidx];
continue;
}
+ if (args[argidx] == "-undef" && argidx+2 < args.size()) {
+ config.undef_type = args[++argidx];
+ config.undef_out = args[++argidx];
+ continue;
+ }
if (args[argidx] == "-icells") {
config.icells_mode = true;
continue;
@@ -352,6 +415,14 @@ struct BlifBackend : public Backend {
config.param_mode = true;
continue;
}
+ if (args[argidx] == "-attr") {
+ config.attr_mode = true;
+ continue;
+ }
+ if (args[argidx] == "-blackbox") {
+ config.blackbox_mode = true;
+ continue;
+ }
if (args[argidx] == "-impltf") {
config.impltf_mode = true;
continue;
@@ -372,7 +443,7 @@ struct BlifBackend : public Backend {
for (auto module_it : design->modules_)
{
RTLIL::Module *module = module_it.second;
- if (module->get_bool_attribute("\\blackbox"))
+ if (module->get_bool_attribute("\\blackbox") && !config.blackbox_mode)
continue;
if (module->processes.size() != 0)
@@ -397,3 +468,4 @@ struct BlifBackend : public Backend {
}
} BlifBackend;
+PRIVATE_NAMESPACE_END