Skip to content

Commit 93a426c

Browse files
Merge pull request #4008 from nakengelhardt/mem_libmap_data_attr
memory_libmap: look for ram_style attributes on surrounding signals
2 parents c58fec6 + f9ab6e1 commit 93a426c

File tree

7 files changed

+166
-8
lines changed

7 files changed

+166
-8
lines changed

frontends/verific/verific.cc

+6-1
Original file line numberDiff line numberDiff line change
@@ -1347,7 +1347,12 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
13471347
wire->start_offset = min(portbus->LeftIndex(), portbus->RightIndex());
13481348
wire->upto = portbus->IsUp();
13491349
import_attributes(wire->attributes, portbus, nl);
1350-
1350+
SetIter si ;
1351+
Port *port ;
1352+
FOREACH_PORT_OF_PORTBUS(portbus, si, port) {
1353+
import_attributes(wire->attributes, port->GetNet(), nl);
1354+
break;
1355+
}
13511356
bool portbus_input = portbus->GetDir() == DIR_INOUT || portbus->GetDir() == DIR_IN;
13521357
if (portbus_input)
13531358
wire->port_input = true;

kernel/constids.inc

+1
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ X(nomem2reg)
140140
X(nomeminit)
141141
X(nosync)
142142
X(nowrshmsk)
143+
X(no_ram)
143144
X(no_rw_check)
144145
X(O)
145146
X(OFFSET)

kernel/mem.cc

+9
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ void Mem::emit() {
148148
for (int j = 0; j < (1 << wr_ports[i].wide_log2); j++)
149149
wr_port_xlat.push_back(i);
150150
for (auto &port : rd_ports) {
151+
for (auto attr: port.attributes)
152+
if (!cell->has_attribute(attr.first))
153+
cell->attributes.insert(attr);
151154
if (port.cell) {
152155
module->remove(port.cell);
153156
port.cell = nullptr;
@@ -210,6 +213,9 @@ void Mem::emit() {
210213
cell->setPort(ID::RD_ADDR, rd_addr);
211214
cell->setPort(ID::RD_DATA, rd_data);
212215
for (auto &port : wr_ports) {
216+
for (auto attr: port.attributes)
217+
if (!cell->has_attribute(attr.first))
218+
cell->attributes.insert(attr);
213219
if (port.cell) {
214220
module->remove(port.cell);
215221
port.cell = nullptr;
@@ -246,6 +252,9 @@ void Mem::emit() {
246252
cell->setPort(ID::WR_ADDR, wr_addr);
247253
cell->setPort(ID::WR_DATA, wr_data);
248254
for (auto &init : inits) {
255+
for (auto attr: init.attributes)
256+
if (!cell->has_attribute(attr.first))
257+
cell->attributes.insert(attr);
249258
if (init.cell) {
250259
module->remove(init.cell);
251260
init.cell = nullptr;

passes/memory/memory_libmap.cc

+48-5
Original file line numberDiff line numberDiff line change
@@ -481,18 +481,58 @@ void MemMapping::dump_config(MemConfig &cfg) {
481481
}
482482
}
483483

484+
std::pair<bool, Const> search_for_attribute(Mem mem, IdString attr) {
485+
// priority of attributes:
486+
// 1. attributes on memory itself
487+
// 2. attributes on a read or write port
488+
// 3. attributes on data signal of a read or write port
489+
// 4. attributes on address signal of a read or write port
490+
491+
if (mem.has_attribute(attr))
492+
return std::make_pair(true, mem.attributes.at(attr));
493+
494+
for (auto &port: mem.rd_ports)
495+
if (port.has_attribute(attr))
496+
return std::make_pair(true, port.attributes.at(attr));
497+
for (auto &port: mem.wr_ports)
498+
if (port.has_attribute(attr))
499+
return std::make_pair(true, port.attributes.at(attr));
500+
501+
for (auto &port: mem.rd_ports)
502+
for (SigBit bit: port.data)
503+
if (bit.is_wire() && bit.wire->has_attribute(attr))
504+
return std::make_pair(true, bit.wire->attributes.at(attr));
505+
for (auto &port: mem.wr_ports)
506+
for (SigBit bit: port.data)
507+
if (bit.is_wire() && bit.wire->has_attribute(attr))
508+
return std::make_pair(true, bit.wire->attributes.at(attr));
509+
510+
for (auto &port: mem.rd_ports)
511+
for (SigBit bit: port.addr)
512+
if (bit.is_wire() && bit.wire->has_attribute(attr))
513+
return std::make_pair(true, bit.wire->attributes.at(attr));
514+
for (auto &port: mem.wr_ports)
515+
for (SigBit bit: port.addr)
516+
if (bit.is_wire() && bit.wire->has_attribute(attr))
517+
return std::make_pair(true, bit.wire->attributes.at(attr));
518+
519+
return std::make_pair(false, Const());
520+
}
521+
484522
// Go through memory attributes to determine user-requested mapping style.
485523
void MemMapping::determine_style() {
486524
kind = RamKind::Auto;
487525
style = "";
488-
if (mem.get_bool_attribute(ID::lram)) {
526+
auto find_attr = search_for_attribute(mem, ID::lram);
527+
if (find_attr.first && find_attr.second.as_bool()) {
489528
kind = RamKind::Huge;
490529
log("found attribute 'lram' on memory %s.%s, forced mapping to huge RAM\n", log_id(mem.module->name), log_id(mem.memid));
491530
return;
492531
}
493532
for (auto attr: {ID::ram_block, ID::rom_block, ID::ram_style, ID::rom_style, ID::ramstyle, ID::romstyle, ID::syn_ramstyle, ID::syn_romstyle}) {
494-
if (mem.has_attribute(attr)) {
495-
Const val = mem.attributes.at(attr);
533+
find_attr = search_for_attribute(mem, attr);
534+
if (find_attr.first) {
535+
Const val = find_attr.second;
496536
if (val == 1) {
497537
kind = RamKind::NotLogic;
498538
log("found attribute '%s = 1' on memory %s.%s, disabled mapping to FF\n", log_id(attr), log_id(mem.module->name), log_id(mem.memid));
@@ -526,8 +566,11 @@ void MemMapping::determine_style() {
526566
return;
527567
}
528568
}
529-
if (mem.get_bool_attribute(ID::logic_block))
530-
kind = RamKind::Logic;
569+
for (auto attr: {ID::logic_block, ID::no_ram}){
570+
find_attr = search_for_attribute(mem, attr);
571+
if (find_attr.first && find_attr.second.as_bool())
572+
kind = RamKind::Logic;
573+
}
531574
}
532575

533576
// Determine whether the memory can be mapped entirely to soft logic.

tests/memlib/generate.py

+22
Original file line numberDiff line numberDiff line change
@@ -1513,6 +1513,28 @@ def __init__(self, name, src, libs, defs, cells):
15131513
["block_sp_full"], defs,
15141514
{"RAM_BLOCK_SP": 1, "$*": add_logic}
15151515
))
1516+
1517+
ROM_CASE = """
1518+
module rom(input clk, input [2:0] addr, {attr}output reg [7:0] data);
1519+
1520+
always @(posedge clk) begin
1521+
case (addr)
1522+
3'b000: data <= 8'h12;
1523+
3'b001: data <= 8'hAB;
1524+
3'b010: data <= 8'h42;
1525+
3'b011: data <= 8'h23;
1526+
3'b100: data <= 8'h66;
1527+
3'b101: data <= 8'hC0;
1528+
3'b110: data <= 8'h3F;
1529+
3'b111: data <= 8'h95;
1530+
endcase
1531+
end
1532+
1533+
endmodule
1534+
"""
1535+
1536+
TESTS.append(Test("rom_case", ROM_CASE.format(attr=""), ["block_sdp"], [], {"RAM_BLOCK_SDP" : 0}))
1537+
TESTS.append(Test("rom_case_block", ROM_CASE.format(attr="(* rom_style = \"block\" *) "), ["block_sdp"], [], {"RAM_BLOCK_SDP" : 1}))
15161538

15171539
with open("run-test.mk", "w") as mf:
15181540
mf.write("ifneq ($(strip $(SEED)),)\n")

tests/verific/memory_semantics.ys

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ reg [DEPTH_LOG2-1:0] counter = 0;
2626
reg done = 1'b0;
2727
always @(posedge clk) begin
2828
if (!done)
29-
counter = counter + 1;
29+
counter = counter + 1'b1;
3030
if (counter == 0)
31-
done = 1;
31+
done = 1'b1;
3232
end
3333

3434
wire [WIDTH-1:0] old_data = PRIME1 * counter;

tests/verific/rom_case.ys

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
verific -sv <<EOF
2+
module rom(input clk, input [2:0] addr, (* ram_style = "block" *) output reg [7:0] data);
3+
4+
always @(posedge clk) begin
5+
case (addr)
6+
3'b000: data <= 8'h12;
7+
3'b001: data <= 8'hAB;
8+
3'b010: data <= 8'h42;
9+
3'b011: data <= 8'h23;
10+
3'b100: data <= 8'h66;
11+
3'b101: data <= 8'hC0;
12+
3'b110: data <= 8'h3F;
13+
3'b111: data <= 8'h95;
14+
endcase
15+
end
16+
17+
endmodule
18+
EOF
19+
hierarchy -top rom
20+
proc
21+
opt
22+
opt -full
23+
memory -nomap
24+
dump
25+
memory_libmap -lib ../memlib/memlib_block_sdp.txt
26+
memory_map
27+
stat
28+
select -assert-count 1 t:RAM_BLOCK_SDP
29+
30+
31+
design -reset
32+
33+
verific -vhdl <<EOF
34+
library IEEE;
35+
use IEEE.std_logic_1164.all;
36+
use ieee.std_logic_unsigned.all;
37+
38+
entity rom_example is
39+
port (
40+
clk : in std_logic;
41+
addr : in std_logic_vector(2 downto 0);
42+
data : out std_logic_vector (7 downto 0)
43+
);
44+
end entity rom_example;
45+
46+
architecture rtl of rom_example is
47+
attribute rom_style : string;
48+
attribute rom_style of data : signal is "block";
49+
begin
50+
51+
p_rom : process(clk)
52+
begin
53+
if rising_edge(clk) then
54+
case addr is
55+
when "000" => data <= X"12";
56+
when "001" => data <= X"AB";
57+
when "010" => data <= X"42";
58+
when "011" => data <= X"23";
59+
when "100" => data <= X"66";
60+
when "101" => data <= X"C0";
61+
when "110" => data <= X"3F";
62+
when others => data <= X"95";
63+
end case;
64+
end if;
65+
end process p_rom;
66+
67+
end architecture rtl;
68+
EOF
69+
hierarchy -top rom_example
70+
proc
71+
opt
72+
opt -full
73+
memory -nomap
74+
dump
75+
memory_libmap -lib ../memlib/memlib_block_sdp.txt
76+
memory_map
77+
stat
78+
select -assert-count 1 t:RAM_BLOCK_SDP

0 commit comments

Comments
 (0)