2020-10-17 15:19:34 -05:00
|
|
|
/*
|
|
|
|
* yosys -- Yosys Open SYnthesis Suite
|
|
|
|
*
|
|
|
|
* Copyright (C) 2020 Marcelina Kościelnicka <mwk@0x04.net>
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef MEM_H
|
|
|
|
#define MEM_H
|
|
|
|
|
|
|
|
#include "kernel/yosys.h"
|
2021-05-23 11:29:44 -05:00
|
|
|
#include "kernel/ffinit.h"
|
2020-10-17 15:19:34 -05:00
|
|
|
|
|
|
|
YOSYS_NAMESPACE_BEGIN
|
|
|
|
|
2021-07-11 19:11:54 -05:00
|
|
|
struct MemRd : RTLIL::AttrObject {
|
2021-05-22 09:10:18 -05:00
|
|
|
bool removed;
|
2020-10-17 15:19:34 -05:00
|
|
|
Cell *cell;
|
2021-05-22 09:48:46 -05:00
|
|
|
int wide_log2;
|
2021-05-22 10:18:59 -05:00
|
|
|
bool clk_enable, clk_polarity, ce_over_srst;
|
|
|
|
Const arst_value, srst_value, init_value;
|
2020-10-17 15:19:34 -05:00
|
|
|
bool transparent;
|
2021-05-22 10:18:59 -05:00
|
|
|
SigSpec clk, en, arst, srst, addr, data;
|
2021-05-25 19:49:50 -05:00
|
|
|
|
2021-05-22 09:10:18 -05:00
|
|
|
MemRd() : removed(false), cell(nullptr) {}
|
2021-05-25 19:49:50 -05:00
|
|
|
|
|
|
|
// Returns the address of given subword index accessed by this port.
|
|
|
|
SigSpec sub_addr(int sub) {
|
|
|
|
SigSpec res = addr;
|
|
|
|
for (int i = 0; i < wide_log2; i++)
|
|
|
|
res[i] = State(sub >> i & 1);
|
|
|
|
return res;
|
|
|
|
}
|
2020-10-17 15:19:34 -05:00
|
|
|
};
|
|
|
|
|
2021-07-11 19:11:54 -05:00
|
|
|
struct MemWr : RTLIL::AttrObject {
|
2021-05-22 09:10:18 -05:00
|
|
|
bool removed;
|
2020-10-17 15:19:34 -05:00
|
|
|
Cell *cell;
|
2021-05-22 09:48:46 -05:00
|
|
|
int wide_log2;
|
2020-10-17 15:19:34 -05:00
|
|
|
bool clk_enable, clk_polarity;
|
2021-05-22 10:00:20 -05:00
|
|
|
std::vector<bool> priority_mask;
|
2020-10-17 15:19:34 -05:00
|
|
|
SigSpec clk, en, addr, data;
|
2021-05-25 19:49:50 -05:00
|
|
|
|
2021-05-22 09:10:18 -05:00
|
|
|
MemWr() : removed(false), cell(nullptr) {}
|
2021-05-25 19:49:50 -05:00
|
|
|
|
|
|
|
// Returns the address of given subword index accessed by this port.
|
|
|
|
SigSpec sub_addr(int sub) {
|
|
|
|
SigSpec res = addr;
|
|
|
|
for (int i = 0; i < wide_log2; i++)
|
|
|
|
res[i] = State(sub >> i & 1);
|
|
|
|
return res;
|
|
|
|
}
|
2020-10-17 15:19:34 -05:00
|
|
|
};
|
|
|
|
|
2021-07-11 19:11:54 -05:00
|
|
|
struct MemInit : RTLIL::AttrObject {
|
2021-07-12 10:10:40 -05:00
|
|
|
bool removed;
|
2020-10-17 15:19:34 -05:00
|
|
|
Cell *cell;
|
|
|
|
Const addr;
|
|
|
|
Const data;
|
2021-05-20 19:26:52 -05:00
|
|
|
Const en;
|
2021-07-12 10:10:40 -05:00
|
|
|
MemInit() : removed(false), cell(nullptr) {}
|
2020-10-17 15:19:34 -05:00
|
|
|
};
|
|
|
|
|
2021-07-11 19:11:54 -05:00
|
|
|
struct Mem : RTLIL::AttrObject {
|
2020-10-17 15:19:34 -05:00
|
|
|
Module *module;
|
|
|
|
IdString memid;
|
|
|
|
bool packed;
|
|
|
|
RTLIL::Memory *mem;
|
|
|
|
Cell *cell;
|
|
|
|
int width, start_offset, size;
|
|
|
|
std::vector<MemInit> inits;
|
|
|
|
std::vector<MemRd> rd_ports;
|
|
|
|
std::vector<MemWr> wr_ports;
|
|
|
|
|
2021-07-12 10:40:12 -05:00
|
|
|
// Removes this memory from the module. The data in helper structures
|
|
|
|
// is unaffected except for the cell/mem fields.
|
2020-10-17 15:19:34 -05:00
|
|
|
void remove();
|
2021-07-12 10:40:12 -05:00
|
|
|
|
|
|
|
// Commits all changes in helper structures into the module — ports and
|
|
|
|
// inits marked as removed are actually removed, new ports/inits create
|
|
|
|
// new cells, modified port/inits are commited into their existing
|
|
|
|
// cells. Note that this reindexes the ports and inits array (actually
|
|
|
|
// removing the ports/inits marked as removed).
|
2020-10-17 15:19:34 -05:00
|
|
|
void emit();
|
2021-07-12 10:40:12 -05:00
|
|
|
|
|
|
|
// Marks all inits as removed.
|
2020-10-17 15:19:34 -05:00
|
|
|
void clear_inits();
|
2021-07-12 10:40:12 -05:00
|
|
|
|
2021-07-12 13:04:59 -05:00
|
|
|
// Coalesces inits: whenever two inits have overlapping or touching
|
|
|
|
// address ranges, they are combined into one, with the higher-priority
|
|
|
|
// one's data overwriting the other. Running this results in
|
|
|
|
// an inits list equivalent to the original, in which all entries
|
2021-05-20 19:26:52 -05:00
|
|
|
// cover disjoint (and non-touching) address ranges, and all enable
|
|
|
|
// masks are all-1.
|
2021-07-12 13:04:59 -05:00
|
|
|
void coalesce_inits();
|
|
|
|
|
2021-07-12 10:40:12 -05:00
|
|
|
// Checks consistency of this memory and all its ports/inits, using
|
|
|
|
// log_assert.
|
2021-05-22 09:36:50 -05:00
|
|
|
void check();
|
2021-07-12 10:40:12 -05:00
|
|
|
|
|
|
|
// Gathers all initialization data into a single big const covering
|
|
|
|
// the whole memory. For all non-initialized bits, Sx will be returned.
|
2020-10-17 15:19:34 -05:00
|
|
|
Const get_init_data() const;
|
2021-07-12 10:40:12 -05:00
|
|
|
|
|
|
|
// Constructs and returns the helper structures for all memories
|
|
|
|
// in a module.
|
2020-10-17 15:19:34 -05:00
|
|
|
static std::vector<Mem> get_all_memories(Module *module);
|
2021-07-12 10:40:12 -05:00
|
|
|
|
|
|
|
// Constructs and returns the helper structures for all selected
|
|
|
|
// memories in a module.
|
2020-10-17 15:19:34 -05:00
|
|
|
static std::vector<Mem> get_selected_memories(Module *module);
|
2021-07-12 10:40:12 -05:00
|
|
|
|
|
|
|
// Converts a synchronous read port into an asynchronous one by
|
|
|
|
// extracting the data (or, in some rare cases, address) register
|
|
|
|
// into a separate cell, together with any soft-transparency
|
|
|
|
// logic necessary to preserve its semantics. Returns the created
|
|
|
|
// register cell, if any. Note that in some rare cases this function
|
|
|
|
// may succeed and perform a conversion without creating a new
|
|
|
|
// register — a nullptr result doesn't imply nothing was done.
|
2021-05-23 11:29:44 -05:00
|
|
|
Cell *extract_rdff(int idx, FfInitVals *initvals);
|
2021-07-12 10:40:12 -05:00
|
|
|
|
|
|
|
// Splits all wide ports in this memory into equivalent narrow ones.
|
|
|
|
// This function performs no modifications at all to the actual
|
|
|
|
// netlist unless and until emit() is called.
|
2021-05-24 17:58:17 -05:00
|
|
|
void narrow();
|
|
|
|
|
2021-05-24 19:56:35 -05:00
|
|
|
// 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);
|
|
|
|
|
2021-05-25 19:06:44 -05:00
|
|
|
// 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);
|
|
|
|
|
2021-05-25 20:07:51 -05:00
|
|
|
// Prepares the memory for widening a port to a given width. This
|
|
|
|
// involves ensuring that start_offset and size are aligned to the
|
|
|
|
// target width.
|
|
|
|
void widen_prep(int wide_log2);
|
|
|
|
|
|
|
|
// Widens a write port up to a given width. The newly port is
|
|
|
|
// equivalent to the original, made by replicating enable/data bits
|
|
|
|
// and masking enable bits with decoders on the low part of the
|
|
|
|
// original address.
|
|
|
|
void widen_wr_port(int idx, int wide_log2);
|
|
|
|
|
2020-10-17 15:19:34 -05:00
|
|
|
Mem(Module *module, IdString memid, int width, int start_offset, int size) : module(module), memid(memid), packed(false), mem(nullptr), cell(nullptr), width(width), start_offset(start_offset), size(size) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
YOSYS_NAMESPACE_END
|
|
|
|
|
|
|
|
#endif
|