Make a few passes auto-call Mem::narrow instead of rejecting wide ports.
authorMarcelina Kościelnicka <mwk@0x04.net>
Thu, 27 May 2021 21:43:25 +0000 (23:43 +0200)
committerMarcelina Kościelnicka <mwk@0x04.net>
Thu, 27 May 2021 22:40:56 +0000 (00:40 +0200)
This essentially adds wide port support for free in passes that don't
have a usefully better way of handling wide ports than just breaking
them up to narrow ports, avoiding "please run memory_narrow" annoyance.

backends/btor/btor.cc
backends/firrtl/firrtl.cc
backends/smt2/smt2.cc
kernel/mem.cc
passes/memory/memory_bram.cc

index 999836882ee6c8802e278cc72f27ca3c2705bc75..a7e32bc5c431e556e50a04f9ae8032a70f18c9c6 100644 (file)
@@ -732,14 +732,6 @@ struct BtorWorker
                                if (port.clk_enable)
                                        log_error("Memory %s.%s has sync read ports.  Please use memory_nordff to convert them first.\n",
                                                        log_id(module), log_id(mem->memid));
-                               if (port.wide_log2)
-                                       log_error("Memory %s.%s has wide read ports.  Please use memory_narrow to convert them first.\n",
-                                                       log_id(module), log_id(mem->memid));
-                       }
-                       for (auto &port : mem->wr_ports) {
-                               if (port.wide_log2)
-                                       log_error("Memory %s.%s has wide write ports.  Please use memory_narrow to convert them first.\n",
-                                                       log_id(module), log_id(mem->memid));
                        }
 
                        int data_sid = get_bv_sid(mem->width);
@@ -1089,8 +1081,10 @@ struct BtorWorker
                memories = Mem::get_all_memories(module);
 
                dict<IdString, Mem*> mem_dict;
-               for (auto &mem : memories)
+               for (auto &mem : memories) {
+                       mem.narrow();
                        mem_dict[mem.memid] = &mem;
+               }
                for (auto cell : module->cells())
                        if (cell->is_mem_cell())
                                mem_cells[cell] = mem_dict[cell->parameters.at(ID::MEMID).decode_string()];
index dee24d0e2295a5ddac48f971fc2297e9c1e7abb5..86b1bbdf695a23b90f7833e0a10dd787428728a0 100644 (file)
@@ -542,6 +542,8 @@ struct FirrtlWorker
                vector<string> port_decls, wire_decls, mem_exprs, cell_exprs, wire_exprs;
 
                std::vector<Mem> memories = Mem::get_all_memories(module);
+               for (auto &mem : memories)
+                       mem.narrow();
 
                for (auto wire : module->wires())
                {
@@ -993,8 +995,6 @@ struct FirrtlWorker
 
                                if (port.clk_enable)
                                        log_error("Clocked read port %d on memory %s.%s.\n", i, log_id(module), log_id(mem.memid));
-                               if (port.wide_log2 != 0)
-                                       log_error("Wide read port %d on memory %s.%s.  Use memory_narrow to convert them first.\n", i, log_id(module), log_id(mem.memid));
 
                                std::ostringstream rpe;
 
@@ -1016,8 +1016,6 @@ struct FirrtlWorker
 
                                if (!port.clk_enable)
                                        log_error("Unclocked write port %d on memory %s.%s.\n", i, log_id(module), log_id(mem.memid));
-                               if (port.wide_log2 != 0)
-                                       log_error("Wide write port %d on memory %s.%s.  Use memory_narrow to convert them first.\n", i, log_id(module), log_id(mem.memid));
                                if (!port.clk_polarity)
                                        log_error("Negedge write port %d on memory %s.%s.\n", i, log_id(module), log_id(mem.memid));
                                for (int i = 1; i < GetSize(port.en); i++)
index 4dee0d4fbc9d6f08563f6a59ed2131f046756435..7f6779c7de16542373601be8aacd2a34a2478406 100644 (file)
@@ -124,6 +124,7 @@ struct Smt2Worker
                memories = Mem::get_all_memories(module);
                for (auto &mem : memories)
                {
+                       mem.narrow();
                        mem_dict[mem.memid] = &mem;
                        for (auto &port : mem.wr_ports)
                        {
@@ -715,12 +716,6 @@ struct Smt2Worker
                                        has_sync_wr = true;
                                else
                                        has_async_wr = true;
-                               if (port.wide_log2)
-                                       log_error("Memory %s.%s has wide write ports. This is not supported by \"write_smt2\".  Use memory_narrow to convert them first.\n", log_id(cell), log_id(module));
-                       }
-                       for (auto &port : mem->rd_ports) {
-                               if (port.wide_log2)
-                                       log_error("Memory %s.%s has wide read ports. This is not supported by \"write_smt2\".  Use memory_narrow to convert them first.\n", log_id(cell), log_id(module));
                        }
                        if (has_async_wr && has_sync_wr)
                                log_error("Memory %s.%s has mixed clocked/nonclocked write ports. This is not supported by \"write_smt2\".\n", log_id(cell), log_id(module));
index 021e1991e5d22a50111fddb400ae249194161e81..848dc9f3a95c6a7f9b1a5b91e86c070a00904ce2 100644 (file)
@@ -691,6 +691,9 @@ Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) {
 }
 
 void Mem::narrow() {
+       // NOTE: several passes depend on this function not modifying
+       // the design at all until (and unless) emit() is called.
+       // Be careful to preserve this.
        std::vector<MemRd> new_rd_ports;
        std::vector<MemWr> new_wr_ports;
        std::vector<std::pair<int, int>> new_rd_map;
index b708647665aaddab05aa81bc6d0f19b12a8ec753..c1476669d4eb3a15a8318428fab2d4ee21926278 100644 (file)
@@ -1052,6 +1052,7 @@ grow_read_ports:;
 void handle_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals)
 {
        log("Processing %s.%s:\n", log_id(mem.module), log_id(mem.memid));
+       mem.narrow();
 
        bool cell_init = !mem.inits.empty();
 
@@ -1069,20 +1070,6 @@ void handle_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals)
                log(" %s=%d", it.first.c_str(), it.second);
        log("\n");
 
-       for (auto &port : mem.rd_ports) {
-               if (port.wide_log2) {
-                       log("Wide read ports are not supported, skipping.\n");
-                       return;
-               }
-       }
-
-       for (auto &port : mem.wr_ports) {
-               if (port.wide_log2) {
-                       log("Wide write ports are not supported, skipping.\n");
-                       return;
-               }
-       }
-
        // This pass cannot deal with write port priority — we need to emulate it,
        // if present.  Since priority emulation will change the enable signals,
        // which in turn may change enable grouping and mapping eligibility in