summaryrefslogtreecommitdiff
path: root/frontends/blif/blifparse.cc
diff options
context:
space:
mode:
Diffstat (limited to 'frontends/blif/blifparse.cc')
-rw-r--r--frontends/blif/blifparse.cc159
1 files changed, 145 insertions, 14 deletions
diff --git a/frontends/blif/blifparse.cc b/frontends/blif/blifparse.cc
index 6d4d6087..034b3e70 100644
--- a/frontends/blif/blifparse.cc
+++ b/frontends/blif/blifparse.cc
@@ -55,12 +55,37 @@ static bool read_next_line(char *&buffer, size_t &buffer_size, int &line_count,
}
}
-void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bool run_clean, bool sop_mode)
+static std::pair<RTLIL::IdString, int> wideports_split(std::string name)
+{
+ int pos = -1;
+
+ if (name.empty() || name.back() != ']')
+ goto failed;
+
+ for (int i = 0; i+1 < GetSize(name); i++) {
+ if (name[i] == '[')
+ pos = i;
+ else if (name[i] < '0' || name[i] > '9')
+ pos = -1;
+ else if (i == pos+1 && name[i] == '0' && name[i+1] != ']')
+ pos = -1;
+ }
+
+ if (pos >= 0)
+ return std::pair<RTLIL::IdString, int>("\\" + name.substr(0, pos), atoi(name.c_str() + pos+1)+1);
+
+failed:
+ return std::pair<RTLIL::IdString, int>("\\" + name, 0);
+}
+
+void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bool run_clean, bool sop_mode, bool wideports)
{
RTLIL::Module *module = nullptr;
RTLIL::Const *lutptr = NULL;
RTLIL::Cell *sopcell = NULL;
+ RTLIL::Cell *lastcell = nullptr;
RTLIL::State lut_default_state = RTLIL::State::Sx;
+ std::string err_reason;
int blif_maxnum = 0, sopmode = -1;
auto blif_wire = [&](const std::string &wire_name) -> Wire*
@@ -96,6 +121,8 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
dict<RTLIL::IdString, RTLIL::Const> *obj_attributes = nullptr;
dict<RTLIL::IdString, RTLIL::Const> *obj_parameters = nullptr;
+ dict<RTLIL::IdString, std::pair<int, bool>> wideports_cache;
+
size_t buffer_size = 4096;
char *buffer = (char*)malloc(buffer_size);
int line_count = 0;
@@ -134,6 +161,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
if (module != nullptr)
goto error;
module = new RTLIL::Module;
+ lastcell = nullptr;
module->name = RTLIL::escape_id(strtok(NULL, " \t\r\n"));
obj_attributes = &module->attributes;
obj_parameters = nullptr;
@@ -148,7 +176,32 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
if (!strcmp(cmd, ".end"))
{
+ for (auto &wp : wideports_cache)
+ {
+ auto name = wp.first;
+ int width = wp.second.first;
+ bool isinput = wp.second.second;
+
+ RTLIL::Wire *wire = module->addWire(name, width);
+ wire->port_input = isinput;
+ wire->port_output = !isinput;
+
+ for (int i = 0; i < width; i++) {
+ RTLIL::IdString other_name = name.str() + stringf("[%d]", i);
+ RTLIL::Wire *other_wire = module->wire(other_name);
+ if (other_wire) {
+ other_wire->port_input = false;
+ other_wire->port_output = false;
+ if (isinput)
+ module->connect(other_wire, SigSpec(wire, i));
+ else
+ module->connect(SigSpec(wire, i), other_wire);
+ }
+ }
+ }
+
module->fixup_ports();
+ wideports_cache.clear();
if (run_clean)
{
@@ -182,14 +235,17 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
}
module = nullptr;
+ lastcell = nullptr;
obj_attributes = nullptr;
obj_parameters = nullptr;
continue;
}
- if (!strcmp(cmd, ".inputs") || !strcmp(cmd, ".outputs")) {
+ if (!strcmp(cmd, ".inputs") || !strcmp(cmd, ".outputs"))
+ {
char *p;
- while ((p = strtok(NULL, " \t\r\n")) != NULL) {
+ while ((p = strtok(NULL, " \t\r\n")) != NULL)
+ {
RTLIL::IdString wire_name(stringf("\\%s", p));
RTLIL::Wire *wire = module->wire(wire_name);
if (wire == nullptr)
@@ -198,12 +254,36 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
wire->port_input = true;
else
wire->port_output = true;
+
+ if (wideports) {
+ std::pair<RTLIL::IdString, int> wp = wideports_split(p);
+ if (wp.second > 0) {
+ wideports_cache[wp.first].first = std::max(wideports_cache[wp.first].first, wp.second);
+ wideports_cache[wp.first].second = !strcmp(cmd, ".inputs");
+ }
+ }
}
obj_attributes = nullptr;
obj_parameters = nullptr;
continue;
}
+ if (!strcmp(cmd, ".cname"))
+ {
+ char *p = strtok(NULL, " \t\r\n");
+ if (p == NULL)
+ goto error;
+
+ if(lastcell == nullptr || module == nullptr)
+ {
+ err_reason = stringf("No primative object to attach .cname %s.", p);
+ goto error_with_reason;
+ }
+
+ module->rename(lastcell, p);
+ continue;
+ }
+
if (!strcmp(cmd, ".attr") || !strcmp(cmd, ".param")) {
char *n = strtok(NULL, " \t\r\n");
char *v = strtok(NULL, "\r\n");
@@ -221,12 +301,16 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
const_v.bits[i] = v[n-i-1] != '0' ? State::S1 : State::S0;
}
if (!strcmp(cmd, ".attr")) {
- if (obj_attributes == nullptr)
- goto error;
+ if (obj_attributes == nullptr) {
+ err_reason = stringf("No object to attach .attr too.");
+ goto error_with_reason;
+ }
(*obj_attributes)[id_n] = const_v;
} else {
- if (obj_parameters == nullptr)
- goto error;
+ if (obj_parameters == nullptr) {
+ err_reason = stringf("No object to attach .param too.");
+ goto error_with_reason;
+ }
(*obj_parameters)[id_n] = const_v;
}
continue;
@@ -271,6 +355,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
}
}
+ lastcell = cell;
obj_attributes = &cell->attributes;
obj_parameters = &cell->parameters;
continue;
@@ -285,14 +370,45 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
IdString celltype = RTLIL::escape_id(p);
RTLIL::Cell *cell = module->addCell(NEW_ID, celltype);
- while ((p = strtok(NULL, " \t\r\n")) != NULL) {
+ dict<RTLIL::IdString, dict<int, SigBit>> cell_wideports_cache;
+
+ while ((p = strtok(NULL, " \t\r\n")) != NULL)
+ {
char *q = strchr(p, '=');
if (q == NULL || !q[0])
goto error;
*(q++) = 0;
- cell->setPort(RTLIL::escape_id(p), *q ? blif_wire(q) : SigSpec());
+
+ if (wideports) {
+ std::pair<RTLIL::IdString, int> wp = wideports_split(p);
+ if (wp.second > 0)
+ cell_wideports_cache[wp.first][wp.second-1] = blif_wire(q);
+ else
+ cell->setPort(RTLIL::escape_id(p), *q ? blif_wire(q) : SigSpec());
+ } else {
+ cell->setPort(RTLIL::escape_id(p), *q ? blif_wire(q) : SigSpec());
+ }
+ }
+
+ for (auto &it : cell_wideports_cache)
+ {
+ int width = 0;
+ for (auto &b : it.second)
+ width = std::max(width, b.first + 1);
+
+ SigSpec sig;
+
+ for (int i = 0; i < width; i++) {
+ if (it.second.count(i))
+ sig.append(it.second.at(i));
+ else
+ sig.append(module->addWire(NEW_ID));
+ }
+
+ cell->setPort(it.first, sig);
}
+ lastcell = cell;
obj_attributes = &cell->attributes;
obj_parameters = &cell->parameters;
continue;
@@ -301,7 +417,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
obj_attributes = nullptr;
obj_parameters = nullptr;
- if (!strcmp(cmd, ".barbuf"))
+ if (!strcmp(cmd, ".barbuf") || !strcmp(cmd, ".conn"))
{
char *p = strtok(NULL, " \t\r\n");
if (p == NULL)
@@ -369,6 +485,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
sopcell->setPort("\\A", input_sig);
sopcell->setPort("\\Y", output_sig);
sopmode = -1;
+ lastcell = sopcell;
}
else
{
@@ -379,6 +496,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
cell->setPort("\\Y", output_sig);
lutptr = &cell->parameters.at("\\LUT");
lut_default_state = RTLIL::State::Sx;
+ lastcell = cell;
}
continue;
}
@@ -432,7 +550,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
if (lutptr)
{
- if (input_len > 8)
+ if (input_len > 12)
goto error;
for (int i = 0; i < (1 << input_len); i++) {
@@ -452,13 +570,17 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
}
}
+ return;
+
error:
log_error("Syntax error in line %d!\n", line_count);
+error_with_reason:
+ log_error("Syntax error in line %d: %s\n", line_count, err_reason.c_str());
}
struct BlifFrontend : public Frontend {
BlifFrontend() : Frontend("blif", "read BLIF file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -469,10 +591,15 @@ struct BlifFrontend : public Frontend {
log(" -sop\n");
log(" Create $sop cells instead of $lut cells\n");
log("\n");
+ log(" -wideports\n");
+ log(" Merge ports that match the pattern 'name[int]' into a single\n");
+ log(" multi-bit port 'name'.\n");
+ log("\n");
}
- virtual void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool sop_mode = false;
+ bool wideports = false;
log_header(design, "Executing BLIF frontend.\n");
@@ -483,11 +610,15 @@ struct BlifFrontend : public Frontend {
sop_mode = true;
continue;
}
+ if (arg == "-wideports") {
+ wideports = true;
+ continue;
+ }
break;
}
extra_args(f, filename, args, argidx);
- parse_blif(design, *f, "", true, sop_mode);
+ parse_blif(design, *f, "", true, sop_mode, wideports);
}
} BlifFrontend;