blif: Use library cells' start_offset and upto for wideports.
authorMarcelina Kościelnicka <mwk@0x04.net>
Wed, 5 May 2021 18:31:27 +0000 (20:31 +0200)
committerMarcelina Kościelnicka <mwk@0x04.net>
Sat, 8 May 2021 13:50:03 +0000 (15:50 +0200)
Fixes #2729.

Makefile
frontends/blif/blifparse.cc
tests/blif/bug2729.ys [new file with mode: 0644]
tests/blif/run-test.sh [new file with mode: 0755]

index 4760eaa35a31e41f5d8b45ae71f8dcb4d7315dcf..ff62aca25621e0df7040b174c8a7a5f908a35c71 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -804,6 +804,7 @@ test: $(TARGETS) $(EXTRA_TARGETS)
        +cd tests/svinterfaces && bash run-test.sh $(SEEDOPT)
        +cd tests/svtypes && bash run-test.sh $(SEEDOPT)
        +cd tests/proc && bash run-test.sh
+       +cd tests/blif && bash run-test.sh
        +cd tests/opt && bash run-test.sh
        +cd tests/aiger && bash run-test.sh $(ABCOPT)
        +cd tests/arch && bash run-test.sh
index 9ae3fac2c0e0e34cc8f27322a9d263c7c8da8236..52b46c228e9a21d9aefb23794d67be17b5ab38e7 100644 (file)
@@ -65,17 +65,21 @@ static std::pair<RTLIL::IdString, int> wideports_split(std::string name)
        for (int i = 0; i+1 < GetSize(name); i++) {
                if (name[i] == '[')
                        pos = i;
-               else if (name[i] < '0' || name[i] > '9')
+               else if (name[i] != '-' && (name[i] < '0' || name[i] > '9'))
+                       pos = -1;
+               else if (name[i] == '-' && ((i != pos+1) || name[i+1] == ']'))
+                       pos = -1;
+               else if (i == pos+2 && name[i] == '0' && name[i-1] == '-')
                        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);
+               return std::pair<RTLIL::IdString, int>("\\" + name.substr(0, pos), atoi(name.c_str() + pos+1));
 
 failed:
-       return std::pair<RTLIL::IdString, int>("\\" + name, 0);
+       return std::pair<RTLIL::IdString, int>(RTLIL::IdString(), 0);
 }
 
 void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool run_clean, bool sop_mode, bool wideports)
@@ -263,8 +267,8 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
 
                                        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);
+                                               if (!wp.first.empty() && wp.second >= 0) {
+                                                       wideports_cache[wp.first].first = std::max(wideports_cache[wp.first].first, wp.second + 1);
                                                        wideports_cache[wp.first].second = !strcmp(cmd, ".inputs");
                                                }
                                        }
@@ -375,6 +379,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
 
                                IdString celltype = RTLIL::escape_id(p);
                                RTLIL::Cell *cell = module->addCell(NEW_ID, celltype);
+                               RTLIL::Module *cell_mod = design->module(celltype);
 
                                dict<RTLIL::IdString, dict<int, SigBit>> cell_wideports_cache;
 
@@ -387,10 +392,10 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
 
                                        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
+                                               if (wp.first.empty())
                                                        cell->setPort(RTLIL::escape_id(p), *q ? blif_wire(q) : SigSpec());
+                                               else
+                                                       cell_wideports_cache[wp.first][wp.second] = blif_wire(q);
                                        } else {
                                                cell->setPort(RTLIL::escape_id(p), *q ? blif_wire(q) : SigSpec());
                                        }
@@ -399,14 +404,26 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
                                for (auto &it : cell_wideports_cache)
                                {
                                        int width = 0;
+                                       int offset = 0;
+                                       bool upto = false;
                                        for (auto &b : it.second)
                                                width = std::max(width, b.first + 1);
 
+                                       if (cell_mod) {
+                                               Wire *cell_port = cell_mod->wire(it.first);
+                                               if (cell_port && (cell_port->port_input || cell_port->port_output)) {
+                                                       offset = cell_port->start_offset;
+                                                       upto = cell_port->upto;
+                                                       width = cell_port->width;
+                                               }
+                                       }
+
                                        SigSpec sig;
 
                                        for (int i = 0; i < width; i++) {
-                                               if (it.second.count(i))
-                                                       sig.append(it.second.at(i));
+                                               int idx = offset + (upto ? width - 1 - i: i);
+                                               if (it.second.count(idx))
+                                                       sig.append(it.second.at(idx));
                                                else
                                                        sig.append(module->addWire(NEW_ID));
                                        }
diff --git a/tests/blif/bug2729.ys b/tests/blif/bug2729.ys
new file mode 100644 (file)
index 0000000..0cbc21a
--- /dev/null
@@ -0,0 +1,20 @@
+read_verilog <<EOF
+
+module cell (input [2:12] I, output [5:-5] O);
+endmodule
+
+module top(input [10:0] A, output [10:0] B);
+cell my_cell(.I(A), .O(B));
+endmodule
+
+EOF
+
+write_blif tmp-bug2729.blif
+delete top
+read_blif -wideports tmp-bug2729.blif
+!rm tmp-bug2729.blif
+rename -enumerate t:cell
+dump
+cd top
+connect -assert -port _0_ I A
+connect -assert -port _0_ O B
diff --git a/tests/blif/run-test.sh b/tests/blif/run-test.sh
new file mode 100755 (executable)
index 0000000..44ce7e6
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/bash
+set -e
+for x in *.ys; do
+  echo "Running $x.."
+  ../../yosys -ql ${x%.ys}.log $x
+done