aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/mem.h
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/mem.h')
-rw-r--r--kernel/mem.h41
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