diff options
Diffstat (limited to 'kernel/mem.h')
-rw-r--r-- | kernel/mem.h | 41 |
1 files changed, 36 insertions, 5 deletions
diff --git a/kernel/mem.h b/kernel/mem.h index 24c2d64c8..87a148beb 100644 --- a/kernel/mem.h +++ b/kernel/mem.h @@ -31,7 +31,19 @@ struct MemRd : RTLIL::AttrObject { int wide_log2; bool clk_enable, clk_polarity, ce_over_srst; Const arst_value, srst_value, init_value; - bool transparent; + // One bit for every write port, true iff simultanous read on this + // port and write on the other port will bypass the written data + // to this port's output (default behavior is to read old value). + // Can only be set for write ports that have the same clock domain. + std::vector<bool> transparency_mask; + // One bit for every write port, true iff simultanous read on this + // port and write on the other port will return an all-X (don't care) + // value. Mutually exclusive with transparency_mask. + // Can only be set for write ports that have the same clock domain. + // For optimization purposes, this will also be set if we can + // determine that the two ports can never be active simultanously + // (making the above vacuously true). + std::vector<bool> collision_x_mask; SigSpec clk, en, arst, srst, addr, data; MemRd() : removed(false), cell(nullptr) {} @@ -139,15 +151,34 @@ struct Mem : RTLIL::AttrObject { // If write port idx2 currently has priority over write port idx1, // inserts extra logic on idx1's enable signal to disable writes // when idx2 is writing to the same address, then removes the priority - // from the priority mask. - void emulate_priority(int idx1, int idx2); + // from the priority mask. If there is a memory port that is + // transparent with idx1, but not with idx2, that port is converted + // to use soft transparency logic. + void emulate_priority(int idx1, int idx2, FfInitVals *initvals); + + // Creates soft-transparency logic on read port ridx, bypassing the + // data from write port widx. Should only be called when ridx is + // transparent wrt widx in the first place. Once we're done, the + // transparency_mask bit will be cleared, and the collision_x_mask + // bit will be set instead (since whatever value is read will be + // replaced by the soft transparency logic). + void emulate_transparency(int widx, int ridx, FfInitVals *initvals); // Prepares for merging write port idx2 into idx1 (where idx1 < idx2). // Specifically, takes care of priority masks: any priority relations // that idx2 had are replicated onto idx1, unless they conflict with // priorities already present on idx1, in which case emulate_priority - // is called. - void prepare_wr_merge(int idx1, int idx2); + // is called. Likewise, ensures transparency and undefined collision + // masks of all read ports have the same values for both ports, + // calling emulate_transparency if necessary. + void prepare_wr_merge(int idx1, int idx2, FfInitVals *initvals); + + // Prepares for merging read port idx2 into idx1. + // Specifically, makes sure the transparency and undefined collision + // masks of both ports are equal, by changing undefined behavior + // of one port to the other's defined behavior, or by calling + // emulate_transparency if necessary. + void prepare_rd_merge(int idx1, int idx2, FfInitVals *initvals); // Prepares the memory for widening a port to a given width. This // involves ensuring that start_offset and size are aligned to the |