Skip to content

Commit 4a5164b

Browse files
authored
Merge pull request #102 from siliconcompiler/ram-libs
cleanup ramlib generator
2 parents 96c2918 + 17870cc commit 4a5164b

File tree

3 files changed

+171
-14
lines changed

3 files changed

+171
-14
lines changed

lambdalib/utils/__init__.py

+11-10
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
from jinja2 import Template
22
import os
3-
import math
43
from collections import OrderedDict
54

65

7-
def write_la_spram(fout, memories, control_signals=None, la_type='ram', minbits=None):
6+
def write_la_ram(fout,
7+
memories,
8+
control_signals=None,
9+
la_type='la_spram',
10+
minsize=None):
811
template_path = os.path.abspath(os.path.join(os.path.dirname(__file__),
912
'templates',
10-
'la_spmemory.v'))
13+
f'{la_type}memory.v'))
1114

1215
widths_table = []
1316
depths_table = []
1417
memory_port_map = {}
1518
selection_table = {}
1619
memory_inst_map = {}
1720

21+
if minsize is None:
22+
minsize = 0
23+
1824
for memory, info in memories.items():
1925
widths_table.append(
2026
(memory, info['DW'])
@@ -35,12 +41,6 @@ def write_la_spram(fout, memories, control_signals=None, la_type='ram', minbits=
3541
for aw, items in selection_table.items():
3642
selection_table[aw] = OrderedDict(sorted(items.items(), reverse=True))
3743

38-
if minbits is not None:
39-
depth = 2**aw
40-
dw = int(math.floor(minbits / depth))
41-
if dw > 0:
42-
selection_table[aw][dw] = "SOFT"
43-
selection_table[min(selection_table.keys()) - 1] = {0: "SOFT"}
4444
widths_table.sort()
4545
depths_table.sort()
4646

@@ -54,4 +54,5 @@ def write_la_spram(fout, memories, control_signals=None, la_type='ram', minbits=
5454
selection_table=selection_table,
5555
inst_map=memory_inst_map,
5656
port_mapping=memory_port_map,
57-
control_signals=control_signals))
57+
control_signals=control_signals,
58+
minsize=minsize))
+153
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/*****************************************************************************
2+
* Function: Dual Port Memory ({{ type }})
3+
* Copyright: Lambda Project Authors. All rights Reserved.
4+
* License: MIT (see LICENSE file in Lambda repository)
5+
*
6+
* Docs:
7+
*
8+
* This is a wrapper for selecting from a set of hardened memory macros.
9+
*
10+
* A synthesizable reference model is used when the PROP is DEFAULT. The
11+
* synthesizable model does not implement the cfg and test interface and should
12+
* only be used for basic testing and for synthesizing for FPGA devices.
13+
* Advanced ASIC development should rely on complete functional models
14+
* supplied on a per macro basis.
15+
*
16+
* Technologoy specific implementations of "{{ type }}" would generally include
17+
* one or more hardcoded instantiations of {{ type }} modules with a generate
18+
* statement relying on the "PROP" to select between the list of modules
19+
* at build time.
20+
*
21+
****************************************************************************/
22+
23+
module {{ type }}
24+
#(parameter DW = 32, // Memory width
25+
parameter AW = 10, // Address width (derived)
26+
parameter PROP = "DEFAULT", // Pass through variable for hard macro
27+
parameter CTRLW = 128, // Width of asic ctrl interface
28+
parameter TESTW = 128 // Width of asic test interface
29+
)
30+
(// Memory interface
31+
// Write port
32+
input wr_clk, // write clock
33+
input wr_ce, // write chip-enable
34+
input wr_we, // write enable
35+
input [DW-1:0] wr_wmask, // write mask
36+
input [AW-1:0] wr_addr, // write address
37+
input [DW-1:0] wr_din, //write data in
38+
// Read port
39+
input rd_clk, // read clock
40+
input rd_ce, // read chip-enable
41+
input [AW-1:0] rd_addr, // read address
42+
output [DW-1:0] rd_dout, //read data out
43+
// Power signals
44+
input vss, // ground signal
45+
input vdd, // memory core array power
46+
input vddio, // periphery/io power
47+
// Generic interfaces
48+
input [CTRLW-1:0] ctrl, // pass through ASIC control interface
49+
input [TESTW-1:0] test // pass through ASIC test interface
50+
);
51+
52+
// Total number of bits
53+
localparam TOTAL_BITS = (2 ** AW) * DW;
54+
55+
// Determine which memory to select
56+
localparam MEM_PROP = (PROP != "DEFAULT") ? PROP :{% if minsize > 0 %} ({{ minsize }} >= TOTAL_BITS) ? "SOFT" :{% endif %}{% for aw, dw_select in selection_table.items() %}
57+
{% if loop.nextitem is defined %}(AW >= {{ aw }}) ? {% endif %}{% for dw, memory in dw_select.items() %}{% if loop.nextitem is defined %}(DW >= {{dw}}) ? {% endif %}"{{ memory}}"{% if loop.nextitem is defined %} : {% endif%}{% endfor %}{% if loop.nextitem is defined %} :{% else %};{% endif %}{% endfor %}
58+
59+
localparam MEM_WIDTH = {% for memory, width in width_table %}
60+
(MEM_PROP == "{{ memory }}") ? {{ width }} :{% endfor %}
61+
0;
62+
63+
localparam MEM_DEPTH = {% for memory, depth in depth_table %}
64+
(MEM_PROP == "{{ memory }}") ? {{ depth }} :{% endfor %}
65+
0;
66+
67+
generate
68+
if (MEM_PROP == "SOFT") begin: isoft
69+
la_dpram_impl #(
70+
.DW(DW),
71+
.AW(AW),
72+
.PROP(PROP),
73+
.CTRLW(CTRLW),
74+
.TESTW(TESTW)
75+
) memory(
76+
.clk(clk),
77+
.ce(ce),
78+
.we(we),
79+
.wmask(wmask),
80+
.addr(addr),
81+
.din(din),
82+
.dout(dout),
83+
.vss(vss),
84+
.vdd(vdd),
85+
.vddio(vddio),
86+
.ctrl(ctrl),
87+
.test(test)
88+
);
89+
end
90+
if (MEM_PROP != "SOFT") begin: itech
91+
// Create memories
92+
localparam MEM_ADDRS = 2**(AW - MEM_DEPTH) < 1 ? 1 : 2**(AW - MEM_DEPTH);
93+
94+
{% if control_signals %}// Control signals{% for line in control_signals %}
95+
{{ line }}{% endfor %}{% endif %}
96+
97+
genvar o;
98+
for (o = 0; o < DW; o = o + 1) begin: OUTPUTS
99+
wire [MEM_ADDRS-1:0] mem_outputs;
100+
assign rd_dout[o] = |mem_outputs;
101+
end
102+
103+
genvar a;
104+
for (a = 0; a < MEM_ADDRS; a = a + 1) begin: ADDR
105+
wire selected;
106+
wire [MEM_DEPTH-1:0] wr_mem_addr;
107+
wire [MEM_DEPTH-1:0] rd_mem_addr;
108+
109+
if (MEM_ADDRS == 1) begin: FITS
110+
assign selected = 1'b1;
111+
assign wr_mem_addr = wr_addr;
112+
assign rd_mem_addr = rd_addr;
113+
end else begin: NOFITS
114+
assign selected = addr[AW-1:MEM_DEPTH] == a;
115+
assign wr_mem_addr = wr_addr[MEM_DEPTH-1:0];
116+
assign rd_mem_addr = rd_addr[MEM_DEPTH-1:0];
117+
end
118+
119+
genvar n;
120+
for (n = 0; n < DW; n = n + MEM_WIDTH) begin: WORD
121+
wire [MEM_WIDTH-1:0] mem_din;
122+
wire [MEM_WIDTH-1:0] mem_dout;
123+
wire [MEM_WIDTH-1:0] mem_wmask;
124+
125+
genvar i;
126+
for (i = 0; i < MEM_WIDTH; i = i + 1) begin: WORD_SELECT
127+
if (n + i < DW) begin: ACTIVE
128+
assign mem_din[i] = wr_din[n + i];
129+
assign mem_wmask[i] = wr_wmask[n + i];
130+
assign OUTPUTS[n + i].mem_outputs[a] = selected ? mem_dout[i] : 1'b0;
131+
end
132+
else begin: INACTIVE
133+
assign mem_din[i] = 1'b0;
134+
assign mem_wmask[i] = 1'b0;
135+
end
136+
end
137+
138+
wire ce_in;
139+
wire we_in;
140+
assign wr_ce_in = wr_ce && selected;
141+
assign rd_ce_in = rd_ce && selected;
142+
assign we_in = wr_we && selected;
143+
{% for memory, inst_name in inst_map.items() %}
144+
if (MEM_PROP == "{{ memory }}") begin: i{{ memory }}
145+
{{ inst_name }} memory ({% for port, net in port_mapping[memory] %}
146+
.{{ port }}({{ net }}){% if loop.nextitem is defined %},{% endif %}{% endfor %}
147+
);
148+
end{% endfor %}
149+
end
150+
end
151+
end
152+
endgenerate
153+
endmodule

lambdalib/utils/templates/la_spmemory.v renamed to lambdalib/utils/templates/la_sprammemory.v

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*****************************************************************************
2-
* Function: Single Port {{ type }}
2+
* Function: Single Port Memory ({{ type }})
33
* Copyright: Lambda Project Authors. All rights Reserved.
44
* License: MIT (see LICENSE file in Lambda repository)
55
*
@@ -13,14 +13,14 @@
1313
* Advanced ASIC development should rely on complete functional models
1414
* supplied on a per macro basis.
1515
*
16-
* Technologoy specific implementations of "la_sp{{ type }}" would generally include
16+
* Technologoy specific implementations of "{{ type }}" would generally include
1717
* one or more hardcoded instantiations of {{ type }} modules with a generate
1818
* statement relying on the "PROP" to select between the list of modules
1919
* at build time.
2020
*
2121
****************************************************************************/
2222

23-
module la_sp{{ type }}
23+
module {{ type }}
2424
#(parameter DW = 32, // Memory width
2525
parameter AW = 10, // Address width (derived)
2626
parameter PROP = "DEFAULT", // Pass through variable for hard macro
@@ -44,8 +44,11 @@ module la_sp{{ type }}
4444
input [TESTW-1:0] test // pass through ASIC test interface
4545
);
4646

47+
// Total number of bits
48+
localparam TOTAL_BITS = (2 ** AW) * DW;
49+
4750
// Determine which memory to select
48-
localparam MEM_PROP = (PROP != "DEFAULT") ? PROP :{% for aw, dw_select in selection_table.items() %}
51+
localparam MEM_PROP = (PROP != "DEFAULT") ? PROP :{% if minsize > 0 %} ({{ minsize }} >= TOTAL_BITS) ? "SOFT" :{% endif %}{% for aw, dw_select in selection_table.items() %}
4952
{% if loop.nextitem is defined %}(AW >= {{ aw }}) ? {% endif %}{% for dw, memory in dw_select.items() %}{% if loop.nextitem is defined %}(DW >= {{dw}}) ? {% endif %}"{{ memory}}"{% if loop.nextitem is defined %} : {% endif%}{% endfor %}{% if loop.nextitem is defined %} :{% else %};{% endif %}{% endfor %}
5053

5154
localparam MEM_WIDTH = {% for memory, width in width_table %}

0 commit comments

Comments
 (0)