3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-07-23 12:48:54 +00:00

kernel/mem: Introduce transparency masks.

This commit is contained in:
Marcelina Kościelnicka 2021-07-31 23:21:37 +02:00
parent 681a1c07e5
commit e6f3d1c225
8 changed files with 407 additions and 117 deletions

View file

@ -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