kernel/mem: Make the Mem helpers inherit from AttrObject.
[yosys.git] / kernel / mem.h
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2020 Marcelina Koƛcielnicka <mwk@0x04.net>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20 #ifndef MEM_H
21 #define MEM_H
22
23 #include "kernel/yosys.h"
24 #include "kernel/ffinit.h"
25
26 YOSYS_NAMESPACE_BEGIN
27
28 struct MemRd : RTLIL::AttrObject {
29 bool removed;
30 Cell *cell;
31 int wide_log2;
32 bool clk_enable, clk_polarity, ce_over_srst;
33 Const arst_value, srst_value, init_value;
34 bool transparent;
35 SigSpec clk, en, arst, srst, addr, data;
36
37 MemRd() : removed(false), cell(nullptr) {}
38
39 // Returns the address of given subword index accessed by this port.
40 SigSpec sub_addr(int sub) {
41 SigSpec res = addr;
42 for (int i = 0; i < wide_log2; i++)
43 res[i] = State(sub >> i & 1);
44 return res;
45 }
46 };
47
48 struct MemWr : RTLIL::AttrObject {
49 bool removed;
50 Cell *cell;
51 int wide_log2;
52 bool clk_enable, clk_polarity;
53 std::vector<bool> priority_mask;
54 SigSpec clk, en, addr, data;
55
56 MemWr() : removed(false), cell(nullptr) {}
57
58 // Returns the address of given subword index accessed by this port.
59 SigSpec sub_addr(int sub) {
60 SigSpec res = addr;
61 for (int i = 0; i < wide_log2; i++)
62 res[i] = State(sub >> i & 1);
63 return res;
64 }
65 };
66
67 struct MemInit : RTLIL::AttrObject {
68 Cell *cell;
69 Const addr;
70 Const data;
71 MemInit() : cell(nullptr) {}
72 };
73
74 struct Mem : RTLIL::AttrObject {
75 Module *module;
76 IdString memid;
77 bool packed;
78 RTLIL::Memory *mem;
79 Cell *cell;
80 int width, start_offset, size;
81 std::vector<MemInit> inits;
82 std::vector<MemRd> rd_ports;
83 std::vector<MemWr> wr_ports;
84
85 void remove();
86 void emit();
87 void clear_inits();
88 void check();
89 Const get_init_data() const;
90 static std::vector<Mem> get_all_memories(Module *module);
91 static std::vector<Mem> get_selected_memories(Module *module);
92 Cell *extract_rdff(int idx, FfInitVals *initvals);
93 void narrow();
94
95 // If write port idx2 currently has priority over write port idx1,
96 // inserts extra logic on idx1's enable signal to disable writes
97 // when idx2 is writing to the same address, then removes the priority
98 // from the priority mask.
99 void emulate_priority(int idx1, int idx2);
100
101 // Prepares for merging write port idx2 into idx1 (where idx1 < idx2).
102 // Specifically, takes care of priority masks: any priority relations
103 // that idx2 had are replicated onto idx1, unless they conflict with
104 // priorities already present on idx1, in which case emulate_priority
105 // is called.
106 void prepare_wr_merge(int idx1, int idx2);
107
108 // Prepares the memory for widening a port to a given width. This
109 // involves ensuring that start_offset and size are aligned to the
110 // target width.
111 void widen_prep(int wide_log2);
112
113 // Widens a write port up to a given width. The newly port is
114 // equivalent to the original, made by replicating enable/data bits
115 // and masking enable bits with decoders on the low part of the
116 // original address.
117 void widen_wr_port(int idx, int wide_log2);
118
119 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) {}
120 };
121
122 YOSYS_NAMESPACE_END
123
124 #endif