Added support for initialized brams
authorClifford Wolf <clifford@clifford.at>
Mon, 6 Apr 2015 15:06:15 +0000 (17:06 +0200)
committerClifford Wolf <clifford@clifford.at>
Mon, 6 Apr 2015 15:06:15 +0000 (17:06 +0200)
kernel/rtlil.h
passes/memory/memory_bram.cc

index 702addd7efb668b891825347416933354fcd48bd..9b9afcee04e594756db20ea3fc470dbc1c7cb0e8 100644 (file)
@@ -474,7 +474,16 @@ struct RTLIL::Const
        std::string decode_string() const;
 
        inline int size() const { return bits.size(); }
-       inline RTLIL::State operator[](int index) { return bits.at(index); }
+       inline RTLIL::State &operator[](int index) { return bits.at(index); }
+       inline const RTLIL::State &operator[](int index) const { return bits.at(index); };
+
+       inline RTLIL::Const extract(int offset, int len = 1, RTLIL::State padding = RTLIL::State::S0) const {
+               RTLIL::Const ret;
+               ret.bits.reserve(len);
+               for (int i = offset; i < offset + len; i++)
+                       ret.bits.push_back(i < GetSize(bits) ? bits[i] : padding);
+               return ret;
+       }
 
        inline unsigned int hash() const {
                unsigned int h = mkhash_init;
index 958cc88b4d2a22694a6506fdbd7d6ffc1b2ea6d9..e651a977b70bf68020de1ccd9ed88ecc80be1c76 100644 (file)
@@ -393,6 +393,16 @@ bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram,
        int mem_width = cell->getParam("\\WIDTH").as_int();
        // int mem_offset = cell->getParam("\\OFFSET").as_int();
 
+       bool cell_init = !SigSpec(cell->getParam("\\INIT")).is_fully_undef();
+       vector<Const> initdata;
+
+       if (cell_init) {
+               Const initparam = cell->getParam("\\INIT");
+               initdata.reserve(mem_size);
+               for (int i=0; i < mem_size; i++)
+                       initdata.push_back(initparam.extract(mem_width*i, mem_width, State::Sx));
+       }
+
        int wr_ports = cell->getParam("\\WR_PORTS").as_int();
        auto wr_clken = SigSpec(cell->getParam("\\WR_CLK_ENABLE"));
        auto wr_clkpol = SigSpec(cell->getParam("\\WR_CLK_POLARITY"));
@@ -789,6 +799,22 @@ grow_read_ports:;
                        for (auto &vp : variant_params)
                                c->setParam(vp.first, vp.second);
 
+                       if (cell_init) {
+                               int init_offset = grid_a*(1 << bram.abits);
+                               int init_shift = grid_d*bram.dbits;
+                               int init_size = (1 << bram.abits);
+                               Const initparam(State::Sx, init_size*bram.dbits);
+                               for (int i = 0; i < init_size; i++) {
+                                       State padding = State::Sx;
+                                       for (int j = 0; j < bram.dbits; j++)
+                                               if (init_offset+i < GetSize(initdata) && init_shift+j < GetSize(initdata[init_offset+i]))
+                                                       padding = initparam[i*bram.dbits+j] = initdata[init_offset+i][init_shift+j];
+                                               else
+                                                       initparam[i*bram.dbits+j] = padding;
+                               }
+                               c->setParam("\\INIT", initparam);
+                       }
+
                        for (auto &pi : portinfos)
                        {
                                if (pi.dupidx != dupidx)
@@ -905,10 +931,7 @@ void handle_cell(Cell *cell, const rules_t &rules)
 {
        log("Processing %s.%s:\n", log_id(cell->module), log_id(cell));
 
-       if (!SigSpec(cell->getParam("\\INIT")).is_fully_undef()) {
-               log("  initialized memories are not supported yet.");
-               return;
-       }
+       bool cell_init = !SigSpec(cell->getParam("\\INIT")).is_fully_undef();
 
        dict<string, int> match_properties;
        match_properties["words"]  = cell->getParam("\\SIZE").as_int();
@@ -980,6 +1003,12 @@ void handle_cell(Cell *cell, const rules_t &rules)
                        log("    Metrics for %s: awaste=%d dwaste=%d bwaste=%d waste=%d efficiency=%d\n",
                                        log_id(match.name), awaste, dwaste, bwaste, waste, efficiency);
 
+                       if (cell_init && bram.init == 0) {
+                               log("    Rule #%d for bram type %s (variant %d) rejected: cannot be initialized.\n",
+                                               i+1, log_id(bram.name), bram.variant);
+                               goto next_match_rule;
+                       }
+
                        for (auto it : match.min_limits) {
                                if (it.first == "waste" || it.first == "dups" || it.first == "acells" || it.first == "dcells" || it.first == "cells")
                                        continue;
@@ -992,6 +1021,7 @@ void handle_cell(Cell *cell, const rules_t &rules)
                                                i+1, log_id(bram.name), bram.variant, it.first.c_str(), it.second);
                                goto next_match_rule;
                        }
+
                        for (auto it : match.max_limits) {
                                if (it.first == "acells" || it.first == "dcells" || it.first == "cells")
                                        continue;
@@ -1021,9 +1051,6 @@ void handle_cell(Cell *cell, const rules_t &rules)
                                log("      Storing for later selection.\n");
                                best_rule_cache[pair<int, int>(i, vi)] = std::tuple<int, int, int>(match_properties["efficiency"], -match_properties["cells"], -match_properties["acells"]);
 
-                               if (or_next_if_better)
-                                       goto next_match_rule;
-
                next_match_rule:
                                if (or_next_if_better || best_rule_cache.empty())
                                        continue;
@@ -1075,7 +1102,7 @@ struct MemoryBramPass : public Pass {
                log("rules. A block ram description looks like this:\n");
                log("\n");
                log("    bram RAMB1024X32     # name of BRAM cell\n");
-               // log("      init 1             # set to '1' if BRAM can be initialized\n");
+               log("      init 1             # set to '1' if BRAM can be initialized\n");
                log("      abits 10           # number of address bits\n");
                log("      dbits 32           # number of data bits\n");
                log("      groups 2           # number of port groups\n");