memory_bram: Fix initdata bit order after shuffling
authorGraham Edgecombe <gpe@grahamedgecombe.com>
Sat, 8 Dec 2018 09:59:56 +0000 (09:59 +0000)
committerGraham Edgecombe <gpe@grahamedgecombe.com>
Tue, 11 Dec 2018 21:02:49 +0000 (21:02 +0000)
In some cases the memory_bram pass shuffles the order of the bits in a
memory's RD_DATA port. Although the order of the bits in the WR_DATA and
WR_EN ports is changed to match the RD_DATA port, the order of the bits
in the initialization data is not.

This causes reads of initialized memories to return invalid data (until
the initialization data is overwritten).

This commit fixes the bug by shuffling the initdata bits in exactly the
same order as the RD_DATA/WR_DATA/WR_EN bits.

passes/memory/memory_bram.cc

index 8740042c4ee75ab0c819d147d65795b4cae79543..cf4095d068f5ff09b9e6f0644a9be341436536e6 100644 (file)
@@ -472,8 +472,12 @@ bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram,
                std::vector<SigSpec> new_wr_en(GetSize(old_wr_en));
                std::vector<SigSpec> new_wr_data(GetSize(old_wr_data));
                std::vector<SigSpec> new_rd_data(GetSize(old_rd_data));
+               std::vector<std::vector<State>> new_initdata;
                std::vector<int> shuffle_map;
 
+               if (cell_init)
+                       new_initdata.resize(mem_size);
+
                for (auto &it : en_order)
                {
                        auto &bits = bits_wr_en.at(it);
@@ -489,6 +493,10 @@ bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram,
                                }
                                for (int j = 0; j < rd_ports; j++)
                                        new_rd_data[j].append(old_rd_data[j][bits[i]]);
+                               if (cell_init) {
+                                       for (int j = 0; j < mem_size; j++)
+                                               new_initdata[j].push_back(initdata[j][bits[i]]);
+                               }
                                shuffle_map.push_back(bits[i]);
                        }
 
@@ -499,6 +507,10 @@ bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram,
                                }
                                for (int j = 0; j < rd_ports; j++)
                                        new_rd_data[j].append(State::Sx);
+                               if (cell_init) {
+                                       for (int j = 0; j < mem_size; j++)
+                                               new_initdata[j].push_back(State::Sx);
+                               }
                                shuffle_map.push_back(-1);
                        }
                }
@@ -522,6 +534,11 @@ bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram,
 
                for (int i = 0; i < rd_ports; i++)
                        rd_data.replace(i*mem_width, new_rd_data[i]);
+
+               if (cell_init) {
+                       for (int i = 0; i < mem_size; i++)
+                               initdata[i] = Const(new_initdata[i]);
+               }
        }
 
        // assign write ports