mirror of https://github.com/YosysHQ/yosys.git
Merge pull request #4008 from nakengelhardt/mem_libmap_data_attr
memory_libmap: look for ram_style attributes on surrounding signals
This commit is contained in:
commit
93a426cbbf
|
@ -1347,7 +1347,12 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
|
|||
wire->start_offset = min(portbus->LeftIndex(), portbus->RightIndex());
|
||||
wire->upto = portbus->IsUp();
|
||||
import_attributes(wire->attributes, portbus, nl);
|
||||
|
||||
SetIter si ;
|
||||
Port *port ;
|
||||
FOREACH_PORT_OF_PORTBUS(portbus, si, port) {
|
||||
import_attributes(wire->attributes, port->GetNet(), nl);
|
||||
break;
|
||||
}
|
||||
bool portbus_input = portbus->GetDir() == DIR_INOUT || portbus->GetDir() == DIR_IN;
|
||||
if (portbus_input)
|
||||
wire->port_input = true;
|
||||
|
|
|
@ -140,6 +140,7 @@ X(nomem2reg)
|
|||
X(nomeminit)
|
||||
X(nosync)
|
||||
X(nowrshmsk)
|
||||
X(no_ram)
|
||||
X(no_rw_check)
|
||||
X(O)
|
||||
X(OFFSET)
|
||||
|
|
|
@ -148,6 +148,9 @@ void Mem::emit() {
|
|||
for (int j = 0; j < (1 << wr_ports[i].wide_log2); j++)
|
||||
wr_port_xlat.push_back(i);
|
||||
for (auto &port : rd_ports) {
|
||||
for (auto attr: port.attributes)
|
||||
if (!cell->has_attribute(attr.first))
|
||||
cell->attributes.insert(attr);
|
||||
if (port.cell) {
|
||||
module->remove(port.cell);
|
||||
port.cell = nullptr;
|
||||
|
@ -210,6 +213,9 @@ void Mem::emit() {
|
|||
cell->setPort(ID::RD_ADDR, rd_addr);
|
||||
cell->setPort(ID::RD_DATA, rd_data);
|
||||
for (auto &port : wr_ports) {
|
||||
for (auto attr: port.attributes)
|
||||
if (!cell->has_attribute(attr.first))
|
||||
cell->attributes.insert(attr);
|
||||
if (port.cell) {
|
||||
module->remove(port.cell);
|
||||
port.cell = nullptr;
|
||||
|
@ -246,6 +252,9 @@ void Mem::emit() {
|
|||
cell->setPort(ID::WR_ADDR, wr_addr);
|
||||
cell->setPort(ID::WR_DATA, wr_data);
|
||||
for (auto &init : inits) {
|
||||
for (auto attr: init.attributes)
|
||||
if (!cell->has_attribute(attr.first))
|
||||
cell->attributes.insert(attr);
|
||||
if (init.cell) {
|
||||
module->remove(init.cell);
|
||||
init.cell = nullptr;
|
||||
|
|
|
@ -481,18 +481,58 @@ void MemMapping::dump_config(MemConfig &cfg) {
|
|||
}
|
||||
}
|
||||
|
||||
std::pair<bool, Const> search_for_attribute(Mem mem, IdString attr) {
|
||||
// priority of attributes:
|
||||
// 1. attributes on memory itself
|
||||
// 2. attributes on a read or write port
|
||||
// 3. attributes on data signal of a read or write port
|
||||
// 4. attributes on address signal of a read or write port
|
||||
|
||||
if (mem.has_attribute(attr))
|
||||
return std::make_pair(true, mem.attributes.at(attr));
|
||||
|
||||
for (auto &port: mem.rd_ports)
|
||||
if (port.has_attribute(attr))
|
||||
return std::make_pair(true, port.attributes.at(attr));
|
||||
for (auto &port: mem.wr_ports)
|
||||
if (port.has_attribute(attr))
|
||||
return std::make_pair(true, port.attributes.at(attr));
|
||||
|
||||
for (auto &port: mem.rd_ports)
|
||||
for (SigBit bit: port.data)
|
||||
if (bit.is_wire() && bit.wire->has_attribute(attr))
|
||||
return std::make_pair(true, bit.wire->attributes.at(attr));
|
||||
for (auto &port: mem.wr_ports)
|
||||
for (SigBit bit: port.data)
|
||||
if (bit.is_wire() && bit.wire->has_attribute(attr))
|
||||
return std::make_pair(true, bit.wire->attributes.at(attr));
|
||||
|
||||
for (auto &port: mem.rd_ports)
|
||||
for (SigBit bit: port.addr)
|
||||
if (bit.is_wire() && bit.wire->has_attribute(attr))
|
||||
return std::make_pair(true, bit.wire->attributes.at(attr));
|
||||
for (auto &port: mem.wr_ports)
|
||||
for (SigBit bit: port.addr)
|
||||
if (bit.is_wire() && bit.wire->has_attribute(attr))
|
||||
return std::make_pair(true, bit.wire->attributes.at(attr));
|
||||
|
||||
return std::make_pair(false, Const());
|
||||
}
|
||||
|
||||
// Go through memory attributes to determine user-requested mapping style.
|
||||
void MemMapping::determine_style() {
|
||||
kind = RamKind::Auto;
|
||||
style = "";
|
||||
if (mem.get_bool_attribute(ID::lram)) {
|
||||
auto find_attr = search_for_attribute(mem, ID::lram);
|
||||
if (find_attr.first && find_attr.second.as_bool()) {
|
||||
kind = RamKind::Huge;
|
||||
log("found attribute 'lram' on memory %s.%s, forced mapping to huge RAM\n", log_id(mem.module->name), log_id(mem.memid));
|
||||
return;
|
||||
}
|
||||
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}) {
|
||||
if (mem.has_attribute(attr)) {
|
||||
Const val = mem.attributes.at(attr);
|
||||
find_attr = search_for_attribute(mem, attr);
|
||||
if (find_attr.first) {
|
||||
Const val = find_attr.second;
|
||||
if (val == 1) {
|
||||
kind = RamKind::NotLogic;
|
||||
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() {
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (mem.get_bool_attribute(ID::logic_block))
|
||||
kind = RamKind::Logic;
|
||||
for (auto attr: {ID::logic_block, ID::no_ram}){
|
||||
find_attr = search_for_attribute(mem, attr);
|
||||
if (find_attr.first && find_attr.second.as_bool())
|
||||
kind = RamKind::Logic;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine whether the memory can be mapped entirely to soft logic.
|
||||
|
|
|
@ -1513,6 +1513,28 @@ end"""
|
|||
["block_sp_full"], defs,
|
||||
{"RAM_BLOCK_SP": 1, "$*": add_logic}
|
||||
))
|
||||
|
||||
ROM_CASE = """
|
||||
module rom(input clk, input [2:0] addr, {attr}output reg [7:0] data);
|
||||
|
||||
always @(posedge clk) begin
|
||||
case (addr)
|
||||
3'b000: data <= 8'h12;
|
||||
3'b001: data <= 8'hAB;
|
||||
3'b010: data <= 8'h42;
|
||||
3'b011: data <= 8'h23;
|
||||
3'b100: data <= 8'h66;
|
||||
3'b101: data <= 8'hC0;
|
||||
3'b110: data <= 8'h3F;
|
||||
3'b111: data <= 8'h95;
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
"""
|
||||
|
||||
TESTS.append(Test("rom_case", ROM_CASE.format(attr=""), ["block_sdp"], [], {"RAM_BLOCK_SDP" : 0}))
|
||||
TESTS.append(Test("rom_case_block", ROM_CASE.format(attr="(* rom_style = \"block\" *) "), ["block_sdp"], [], {"RAM_BLOCK_SDP" : 1}))
|
||||
|
||||
with open("run-test.mk", "w") as mf:
|
||||
mf.write("ifneq ($(strip $(SEED)),)\n")
|
||||
|
|
|
@ -26,9 +26,9 @@ reg [DEPTH_LOG2-1:0] counter = 0;
|
|||
reg done = 1'b0;
|
||||
always @(posedge clk) begin
|
||||
if (!done)
|
||||
counter = counter + 1;
|
||||
counter = counter + 1'b1;
|
||||
if (counter == 0)
|
||||
done = 1;
|
||||
done = 1'b1;
|
||||
end
|
||||
|
||||
wire [WIDTH-1:0] old_data = PRIME1 * counter;
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
verific -sv <<EOF
|
||||
module rom(input clk, input [2:0] addr, (* ram_style = "block" *) output reg [7:0] data);
|
||||
|
||||
always @(posedge clk) begin
|
||||
case (addr)
|
||||
3'b000: data <= 8'h12;
|
||||
3'b001: data <= 8'hAB;
|
||||
3'b010: data <= 8'h42;
|
||||
3'b011: data <= 8'h23;
|
||||
3'b100: data <= 8'h66;
|
||||
3'b101: data <= 8'hC0;
|
||||
3'b110: data <= 8'h3F;
|
||||
3'b111: data <= 8'h95;
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
EOF
|
||||
hierarchy -top rom
|
||||
proc
|
||||
opt
|
||||
opt -full
|
||||
memory -nomap
|
||||
dump
|
||||
memory_libmap -lib ../memlib/memlib_block_sdp.txt
|
||||
memory_map
|
||||
stat
|
||||
select -assert-count 1 t:RAM_BLOCK_SDP
|
||||
|
||||
|
||||
design -reset
|
||||
|
||||
verific -vhdl <<EOF
|
||||
library IEEE;
|
||||
use IEEE.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity rom_example is
|
||||
port (
|
||||
clk : in std_logic;
|
||||
addr : in std_logic_vector(2 downto 0);
|
||||
data : out std_logic_vector (7 downto 0)
|
||||
);
|
||||
end entity rom_example;
|
||||
|
||||
architecture rtl of rom_example is
|
||||
attribute rom_style : string;
|
||||
attribute rom_style of data : signal is "block";
|
||||
begin
|
||||
|
||||
p_rom : process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
case addr is
|
||||
when "000" => data <= X"12";
|
||||
when "001" => data <= X"AB";
|
||||
when "010" => data <= X"42";
|
||||
when "011" => data <= X"23";
|
||||
when "100" => data <= X"66";
|
||||
when "101" => data <= X"C0";
|
||||
when "110" => data <= X"3F";
|
||||
when others => data <= X"95";
|
||||
end case;
|
||||
end if;
|
||||
end process p_rom;
|
||||
|
||||
end architecture rtl;
|
||||
EOF
|
||||
hierarchy -top rom_example
|
||||
proc
|
||||
opt
|
||||
opt -full
|
||||
memory -nomap
|
||||
dump
|
||||
memory_libmap -lib ../memlib/memlib_block_sdp.txt
|
||||
memory_map
|
||||
stat
|
||||
select -assert-count 1 t:RAM_BLOCK_SDP
|
Loading…
Reference in New Issue