Merge pull request #1603 from whitequark/ice40-ram_style

ice40/ecp5: add support for both 1364.1 and Synplify/LSE RAM/ROM attributes
This commit is contained in:
whitequark 2020-04-10 14:51:01 +00:00 committed by GitHub
commit 93ef516d91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 837 additions and 51 deletions

View File

@ -137,9 +137,26 @@ struct rules_t
vector<vector<std::tuple<bool,IdString,Const>>> attributes; vector<vector<std::tuple<bool,IdString,Const>>> attributes;
}; };
bool attr_icase;
dict<IdString, vector<bram_t>> brams; dict<IdString, vector<bram_t>> brams;
vector<match_t> matches; vector<match_t> matches;
std::string map_case(std::string value) const
{
if (attr_icase) {
for (char &c : value)
c = tolower(c);
}
return value;
}
RTLIL::Const map_case(RTLIL::Const value) const
{
if (value.flags & RTLIL::CONST_FLAG_STRING)
return map_case(value.decode_string());
return value;
}
std::ifstream infile; std::ifstream infile;
vector<string> tokens; vector<string> tokens;
vector<string> labels; vector<string> labels;
@ -337,7 +354,7 @@ struct rules_t
IdString key = RTLIL::escape_id(tokens[idx].substr(c1, c2)); IdString key = RTLIL::escape_id(tokens[idx].substr(c1, c2));
Const val = c2 != std::string::npos ? tokens[idx].substr(c2+1) : RTLIL::Const(1); Const val = c2 != std::string::npos ? tokens[idx].substr(c2+1) : RTLIL::Const(1);
data.attributes.back().emplace_back(exists, key, val); data.attributes.back().emplace_back(exists, key, map_case(val));
} }
continue; continue;
} }
@ -351,6 +368,7 @@ struct rules_t
rewrite_filename(filename); rewrite_filename(filename);
infile.open(filename); infile.open(filename);
linecount = 0; linecount = 0;
attr_icase = false;
if (infile.fail()) if (infile.fail())
log_error("Can't open rules file `%s'.\n", filename.c_str()); log_error("Can't open rules file `%s'.\n", filename.c_str());
@ -360,6 +378,11 @@ struct rules_t
if (!labels.empty()) if (!labels.empty())
syntax_error(); syntax_error();
if (GetSize(tokens) == 2 && tokens[0] == "attr_icase") {
attr_icase = atoi(tokens[1].c_str());
continue;
}
if (tokens[0] == "bram") { if (tokens[0] == "bram") {
parse_bram(); parse_bram();
continue; continue;
@ -843,7 +866,7 @@ grow_read_ports:;
} }
else if (!exists) else if (!exists)
continue; continue;
if (it->second != value) if (rules.map_case(it->second) != value)
continue; continue;
found = true; found = true;
break; break;
@ -855,7 +878,7 @@ grow_read_ports:;
ss << "!"; ss << "!";
IdString key = std::get<1>(sums.front()); IdString key = std::get<1>(sums.front());
ss << log_id(key); ss << log_id(key);
const Const &value = std::get<2>(sums.front()); const Const &value = rules.map_case(std::get<2>(sums.front()));
if (exists && value != Const(1)) if (exists && value != Const(1))
ss << "=\"" << value.decode_string() << "\""; ss << "=\"" << value.decode_string() << "\"";
@ -1167,7 +1190,7 @@ void handle_cell(Cell *cell, const rules_t &rules)
} }
else if (!exists) else if (!exists)
continue; continue;
if (it->second != value) if (rules.map_case(it->second) != value)
continue; continue;
found = true; found = true;
break; break;
@ -1179,7 +1202,7 @@ void handle_cell(Cell *cell, const rules_t &rules)
ss << "!"; ss << "!";
IdString key = std::get<1>(sums.front()); IdString key = std::get<1>(sums.front());
ss << log_id(key); ss << log_id(key);
const Const &value = std::get<2>(sums.front()); const Const &value = rules.map_case(std::get<2>(sums.front()));
if (exists && value != Const(1)) if (exists && value != Const(1))
ss << "=\"" << value.decode_string() << "\""; ss << "=\"" << value.decode_string() << "\"";
@ -1252,8 +1275,13 @@ struct MemoryBramPass : public Pass {
log("The given rules file describes the available resources and how they should be\n"); log("The given rules file describes the available resources and how they should be\n");
log("used.\n"); log("used.\n");
log("\n"); log("\n");
log("The rules file contains a set of block ram description and a sequence of match\n"); log("The rules file contains configuration options, a set of block ram description\n");
log("rules. A block ram description looks like this:\n"); log("and a sequence of match rules.\n");
log("\n");
log("The option 'attr_icase' configures how attribute values are matched. The value 0\n");
log("means case-sensitive, 1 means case-insensitive.\n");
log("\n");
log("A block ram description looks like this:\n");
log("\n"); log("\n");
log(" bram RAMB1024X32 # name of BRAM cell\n"); log(" bram RAMB1024X32 # name of BRAM cell\n");
log(" init 1 # set to '1' if BRAM can be initialized\n"); log(" init 1 # set to '1' if BRAM can be initialized\n");

View File

@ -28,11 +28,32 @@ PRIVATE_NAMESPACE_BEGIN
struct MemoryMapWorker struct MemoryMapWorker
{ {
bool attr_icase = false;
dict<RTLIL::IdString, std::vector<RTLIL::Const>> attributes;
RTLIL::Design *design; RTLIL::Design *design;
RTLIL::Module *module; RTLIL::Module *module;
std::map<std::pair<RTLIL::SigSpec, RTLIL::SigSpec>, RTLIL::SigBit> decoder_cache; std::map<std::pair<RTLIL::SigSpec, RTLIL::SigSpec>, RTLIL::SigBit> decoder_cache;
MemoryMapWorker(RTLIL::Design *design, RTLIL::Module *module) : design(design), module(module) {}
std::string map_case(std::string value) const
{
if (attr_icase) {
for (char &c : value)
c = tolower(c);
}
return value;
}
RTLIL::Const map_case(RTLIL::Const value) const
{
if (value.flags & RTLIL::CONST_FLAG_STRING)
return map_case(value.decode_string());
return value;
}
std::string genid(RTLIL::IdString name, std::string token1 = "", int i = -1, std::string token2 = "", int j = -1, std::string token3 = "", int k = -1, std::string token4 = "") std::string genid(RTLIL::IdString name, std::string token1 = "", int i = -1, std::string token2 = "", int j = -1, std::string token3 = "", int k = -1, std::string token4 = "")
{ {
std::stringstream sstr; std::stringstream sstr;
@ -98,6 +119,36 @@ struct MemoryMapWorker
return; return;
} }
// check if attributes allow us to infer FFRAM for this cell
for (const auto &attr : attributes) {
if (cell->attributes.count(attr.first)) {
const auto &cell_attr = cell->attributes[attr.first];
if (attr.second.empty()) {
log("Not mapping memory cell %s in module %s (attribute %s is set).\n",
cell->name.c_str(), module->name.c_str(), attr.first.c_str());
return;
}
bool found = false;
for (auto &value : attr.second) {
if (map_case(cell_attr) == map_case(value)) {
found = true;
break;
}
}
if (!found) {
if (cell_attr.flags & RTLIL::CONST_FLAG_STRING) {
log("Not mapping memory cell %s in module %s (attribute %s is set to \"%s\").\n",
cell->name.c_str(), module->name.c_str(), attr.first.c_str(), cell_attr.decode_string().c_str());
} else {
log("Not mapping memory cell %s in module %s (attribute %s is set to %d).\n",
cell->name.c_str(), module->name.c_str(), attr.first.c_str(), cell_attr.as_int());
}
return;
}
}
}
// all write ports must share the same clock // all write ports must share the same clock
RTLIL::SigSpec clocks = cell->getPort(ID::WR_CLK); RTLIL::SigSpec clocks = cell->getPort(ID::WR_CLK);
RTLIL::Const clocks_pol = cell->parameters[ID::WR_CLK_POLARITY]; RTLIL::Const clocks_pol = cell->parameters[ID::WR_CLK_POLARITY];
@ -339,7 +390,7 @@ struct MemoryMapWorker
module->remove(cell); module->remove(cell);
} }
MemoryMapWorker(RTLIL::Design *design, RTLIL::Module *module) : design(design), module(module) void run()
{ {
std::vector<RTLIL::Cell*> cells; std::vector<RTLIL::Cell*> cells;
for (auto cell : module->selected_cells()) for (auto cell : module->selected_cells())
@ -356,17 +407,73 @@ struct MemoryMapPass : public Pass {
{ {
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n"); log("\n");
log(" memory_map [selection]\n"); log(" memory_map [options] [selection]\n");
log("\n"); log("\n");
log("This pass converts multiport memory cells as generated by the memory_collect\n"); log("This pass converts multiport memory cells as generated by the memory_collect\n");
log("pass to word-wide DFFs and address decoders.\n"); log("pass to word-wide DFFs and address decoders.\n");
log("\n"); log("\n");
log(" -attr !<name>\n");
log(" do not map memories that have attribute <name> set.\n");
log("\n");
log(" -attr <name>[=<value>]\n");
log(" for memories that have attribute <name> set, only map them if its value\n");
log(" is a string <value> (if specified), or an integer 1 (otherwise). if this\n");
log(" option is specified multiple times, map the memory if the attribute is\n");
log(" to any of the values.\n");
log("\n");
log(" -iattr\n");
log(" for -attr, ignore case of <value>.\n");
log("\n");
} }
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool attr_icase = false;
dict<RTLIL::IdString, std::vector<RTLIL::Const>> attributes;
log_header(design, "Executing MEMORY_MAP pass (converting $mem cells to logic and flip-flops).\n"); log_header(design, "Executing MEMORY_MAP pass (converting $mem cells to logic and flip-flops).\n");
extra_args(args, 1, design);
for (auto mod : design->selected_modules()) size_t argidx;
MemoryMapWorker(design, mod); for (argidx = 1; argidx < args.size(); argidx++)
{
if (args[argidx] == "-attr" && argidx + 1 < args.size())
{
std::string attr_arg = args[++argidx];
std::string name;
RTLIL::Const value;
size_t eq_at = attr_arg.find('=');
if (eq_at != std::string::npos) {
name = attr_arg.substr(0, eq_at);
value = attr_arg.substr(eq_at + 1);
} else {
name = attr_arg;
value = RTLIL::Const(1);
}
if (attr_arg.size() > 1 && attr_arg[0] == '!') {
if (value != RTLIL::Const(1)) {
--argidx;
break; // we don't support -attr !<name>=<value>
}
attributes[RTLIL::escape_id(name.substr(1))].clear();
} else {
attributes[RTLIL::escape_id(name)].push_back(value);
}
continue;
}
if (args[argidx] == "-iattr")
{
attr_icase = true;
continue;
}
break;
}
extra_args(args, argidx, design);
for (auto mod : design->selected_modules()) {
MemoryMapWorker worker(design, mod);
worker.attr_icase = attr_icase;
worker.attributes = attributes;
worker.run();
}
} }
} MemoryMapPass; } MemoryMapPass;

View File

@ -37,7 +37,17 @@ bram $__ECP5_DP16KD
clkpol 2 3 clkpol 2 3
endbram endbram
# The syn_* attributes are described in:
# https://www.latticesemi.com/-/media/LatticeSemi/Documents/Tutorials/AK/LatticeDiamondTutorial311.ashx
attr_icase 1
match $__ECP5_PDPW16KD match $__ECP5_PDPW16KD
# implicitly requested RAM or ROM
attribute !syn_ramstyle syn_ramstyle=auto
attribute !syn_romstyle syn_romstyle=auto
attribute !ram_block
attribute !rom_block
attribute !logic_block
min bits 2048 min bits 2048
min efficiency 5 min efficiency 5
shuffle_enable A shuffle_enable A
@ -45,8 +55,60 @@ match $__ECP5_PDPW16KD
or_next_if_better or_next_if_better
endmatch endmatch
match $__ECP5_PDPW16KD
# explicitly requested RAM
attribute syn_ramstyle=block_ram ram_block
attribute !syn_romstyle
attribute !rom_block
attribute !logic_block
min wports 1
shuffle_enable A
make_transp
or_next_if_better
endmatch
match $__ECP5_PDPW16KD
# explicitly requested ROM
attribute syn_romstyle=ebr rom_block
attribute !syn_ramstyle
attribute !ram_block
attribute !logic_block
max wports 0
shuffle_enable A
make_transp
or_next_if_better
endmatch
match $__ECP5_DP16KD match $__ECP5_DP16KD
# implicitly requested RAM or ROM
attribute !syn_ramstyle syn_ramstyle=auto
attribute !syn_romstyle syn_romstyle=auto
attribute !ram_block
attribute !rom_block
attribute !logic_block
min bits 2048 min bits 2048
min efficiency 5 min efficiency 5
shuffle_enable A shuffle_enable A
or_next_if_better
endmatch
match $__ECP5_DP16KD
# explicitly requested RAM
attribute syn_ramstyle=block_ram ram_block
attribute !syn_romstyle
attribute !rom_block
attribute !logic_block
min wports 1
shuffle_enable A
or_next_if_better
endmatch
match $__ECP5_DP16KD
# explicitly requested ROM
attribute syn_romstyle=ebr rom_block
attribute !syn_ramstyle
attribute !ram_block
attribute !logic_block
max wports 0
shuffle_enable A
endmatch endmatch

View File

@ -11,7 +11,16 @@ bram $__TRELLIS_DPR16X4
clkpol 0 2 clkpol 0 2
endbram endbram
# The syn_* attributes are described in:
# https://www.latticesemi.com/-/media/LatticeSemi/Documents/Tutorials/AK/LatticeDiamondTutorial311.ashx
attr_icase 1
match $__TRELLIS_DPR16X4 match $__TRELLIS_DPR16X4
attribute !syn_ramstyle syn_ramstyle=auto syn_ramstyle=distributed
attribute !syn_romstyle syn_romstyle=auto
attribute !ram_block
attribute !rom_block
attribute !logic_block
make_outreg make_outreg
min wports 1 min wports 1
endmatch endmatch

View File

@ -279,7 +279,9 @@ struct SynthEcp5Pass : public ScriptPass
if (check_label("map_ffram")) if (check_label("map_ffram"))
{ {
run("opt -fast -mux_undef -undriven -fine"); run("opt -fast -mux_undef -undriven -fine");
run("memory_map"); run("memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block "
"-attr syn_ramstyle=auto -attr syn_ramstyle=registers "
"-attr syn_romstyle=auto -attr syn_romstyle=logic");
run("opt -undriven -fine"); run("opt -undriven -fine");
} }

View File

@ -28,13 +28,73 @@ bram $__ICE40_RAM4K_M123
clkpol 2 3 clkpol 2 3
endbram endbram
# The syn_* attributes are described in:
# https://www.latticesemi.com/-/media/LatticeSemi/Documents/Tutorials/AK/LatticeDiamondTutorial311.ashx
attr_icase 1
match $__ICE40_RAM4K_M0 match $__ICE40_RAM4K_M0
# implicitly requested RAM or ROM
attribute !syn_ramstyle syn_ramstyle=auto
attribute !syn_romstyle syn_romstyle=auto
attribute !ram_block
attribute !rom_block
attribute !logic_block
min efficiency 2
make_transp
or_next_if_better
endmatch
match $__ICE40_RAM4K_M0
# explicitly requested RAM
attribute syn_ramstyle=block_ram ram_block
attribute !syn_romstyle
attribute !rom_block
attribute !logic_block
min wports 1
make_transp
or_next_if_better
endmatch
match $__ICE40_RAM4K_M0
# explicitly requested ROM
attribute syn_romstyle=ebr rom_block
attribute !syn_ramstyle
attribute !ram_block
attribute !logic_block
max wports 0
make_transp
or_next_if_better
endmatch
match $__ICE40_RAM4K_M123
# implicitly requested RAM or ROM
attribute !syn_ramstyle syn_ramstyle=auto
attribute !syn_romstyle syn_romstyle=auto
attribute !ram_block
attribute !rom_block
attribute !logic_block
min efficiency 2 min efficiency 2
make_transp make_transp
or_next_if_better or_next_if_better
endmatch endmatch
match $__ICE40_RAM4K_M123 match $__ICE40_RAM4K_M123
min efficiency 2 # explicitly requested RAM
attribute syn_ramstyle=block_ram ram_block
attribute !syn_romstyle
attribute !rom_block
attribute !logic_block
min wports 1
make_transp
or_next_if_better
endmatch
match $__ICE40_RAM4K_M123
# explicitly requested ROM
attribute syn_romstyle=ebr rom_block
attribute !syn_ramstyle
attribute !ram_block
attribute !logic_block
max wports 0
make_transp make_transp
endmatch endmatch

View File

@ -319,7 +319,9 @@ struct SynthIce40Pass : public ScriptPass
if (check_label("map_ffram")) if (check_label("map_ffram"))
{ {
run("opt -fast -mux_undef -undriven -fine"); run("opt -fast -mux_undef -undriven -fine");
run("memory_map"); run("memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block "
"-attr syn_ramstyle=auto -attr syn_ramstyle=registers "
"-attr syn_romstyle=auto -attr syn_romstyle=logic");
run("opt -undriven -fine"); run("opt -undriven -fine");
} }

View File

@ -5,19 +5,20 @@ module sync_ram_sp #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10)
input wire [ADDRESS_WIDTH-1:0] address_in, input wire [ADDRESS_WIDTH-1:0] address_in,
output wire [DATA_WIDTH-1:0] data_out); output wire [DATA_WIDTH-1:0] data_out);
localparam WORD = (DATA_WIDTH-1); localparam WORD = (DATA_WIDTH-1);
localparam DEPTH = (2**ADDRESS_WIDTH-1); localparam DEPTH = (2**ADDRESS_WIDTH-1);
reg [WORD:0] data_out_r; reg [WORD:0] data_out_r;
reg [WORD:0] memory [0:DEPTH]; reg [WORD:0] memory [0:DEPTH];
always @(posedge clk) begin always @(posedge clk) begin
if (write_enable) if (write_enable)
memory[address_in] <= data_in; memory[address_in] <= data_in;
data_out_r <= memory[address_in]; data_out_r <= memory[address_in];
end end
assign data_out = data_out_r;
assign data_out = data_out_r;
endmodule // sync_ram_sp endmodule // sync_ram_sp
@ -28,18 +29,19 @@ module sync_ram_sdp #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10)
input wire [ADDRESS_WIDTH-1:0] address_in_r, address_in_w, input wire [ADDRESS_WIDTH-1:0] address_in_r, address_in_w,
output wire [DATA_WIDTH-1:0] data_out); output wire [DATA_WIDTH-1:0] data_out);
localparam WORD = (DATA_WIDTH-1); localparam WORD = (DATA_WIDTH-1);
localparam DEPTH = (2**ADDRESS_WIDTH-1); localparam DEPTH = (2**ADDRESS_WIDTH-1);
reg [WORD:0] data_out_r; reg [WORD:0] data_out_r;
reg [WORD:0] memory [0:DEPTH]; reg [WORD:0] memory [0:DEPTH];
always @(posedge clk) begin always @(posedge clk) begin
if (write_enable) if (write_enable)
memory[address_in_w] <= data_in; memory[address_in_w] <= data_in;
data_out_r <= memory[address_in_r]; data_out_r <= memory[address_in_r];
end end
assign data_out = data_out_r;
assign data_out = data_out_r;
endmodule // sync_ram_sdp endmodule // sync_ram_sdp

View File

@ -0,0 +1,31 @@
`default_nettype none
module sync_rom #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10)
(input wire clk,
input wire [ADDRESS_WIDTH-1:0] address_in,
output wire [DATA_WIDTH-1:0] data_out);
localparam WORD = (DATA_WIDTH-1);
localparam DEPTH = (2**ADDRESS_WIDTH-1);
reg [WORD:0] data_out_r;
reg [WORD:0] memory [0:DEPTH];
integer i,j = 64'hF4B1CA8127865242;
initial
for (i = 0; i <= DEPTH; i++) begin
// In case this ROM will be implemented in fabric: fill the memory with some data
// uncorrelated with the address, or Yosys might see through the ruse and e.g. not
// emit any LUTs at all for `memory[i] = i;`, just a latch.
memory[i] = j * 64'h2545F4914F6CDD1D;
j = j ^ (j >> 12);
j = j ^ (j << 25);
j = j ^ (j >> 27);
end
always @(posedge clk) begin
data_out_r <= memory[address_in];
end
assign data_out = data_out_r;
endmodule // sync_rom

330
tests/arch/ecp5/memories.ys Normal file
View File

@ -0,0 +1,330 @@
# ================================ RAM ================================
# RAM bits <= 18K; Data width <= 36; Address width <= 9: -> PDPW16KD
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 36 sync_ram_sdp
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:PDPW16KD
## With parameters
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 0 t:PDPW16KD # too inefficient
select -assert-count 9 t:TRELLIS_DPR16X4
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
setattr -set syn_ramstyle "block_ram" m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:PDPW16KD
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
setattr -set syn_ramstyle "Block_RAM" m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:PDPW16KD # any case works
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
setattr -set ram_block 1 m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:PDPW16KD
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
setattr -set syn_ramstyle "registers" m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 0 t:PDPW16KD # requested FFRAM explicitly
select -assert-count 180 t:TRELLIS_FF
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
setattr -set logic_block 1 m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 0 t:PDPW16KD # requested FFRAM explicitly
select -assert-count 180 t:TRELLIS_FF
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
setattr -set syn_romstyle "ebr" m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:$mem # requested BROM but this is a RAM
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
setattr -set rom_block 1 m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:$mem # requested BROM but this is a RAM
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
setattr -set syn_ramstyle "block_ram" m:memory
synth_ecp5 -top sync_ram_sdp -nobram; cd sync_ram_sdp
select -assert-count 1 t:$mem # requested BRAM but BRAM is disabled
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
setattr -set ram_block 1 m:memory
synth_ecp5 -top sync_ram_sdp -nobram; cd sync_ram_sdp
select -assert-count 1 t:$mem # requested BRAM but BRAM is disabled
# RAM bits <= 18K; Data width <= 18; Address width <= 10: -> DP16KD
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 18 sync_ram_sdp
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:DP16KD
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 11 -set DATA_WIDTH 9 sync_ram_sdp
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:DP16KD
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 12 -set DATA_WIDTH 4 sync_ram_sdp
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:DP16KD
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 13 -set DATA_WIDTH 2 sync_ram_sdp
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:DP16KD
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 14 -set DATA_WIDTH 1 sync_ram_sdp
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:DP16KD
## With parameters
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 0 t:DP16KD # too inefficient
select -assert-count 5 t:TRELLIS_DPR16X4
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
setattr -set syn_ramstyle "block_ram" m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:DP16KD
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
setattr -set syn_ramstyle "Block_RAM" m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:DP16KD # any case works
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
setattr -set ram_block 1 m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:DP16KD
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
setattr -set syn_ramstyle "registers" m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 0 t:DP16KD # requested FFRAM explicitly
select -assert-count 90 t:TRELLIS_FF
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
setattr -set logic_block 1 m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 0 t:DP16KD # requested FFRAM explicitly
select -assert-count 90 t:TRELLIS_FF
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
setattr -set syn_romstyle "ebr" m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:$mem # requested BROM but this is a RAM
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
setattr -set rom_block 1 m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:$mem # requested BROM but this is a RAM
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
setattr -set syn_ramstyle "block_ram" m:memory
synth_ecp5 -top sync_ram_sdp -nobram; cd sync_ram_sdp
select -assert-count 1 t:$mem # requested BRAM but BRAM is disabled
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
setattr -set ram_block 1 m:memory
synth_ecp5 -top sync_ram_sdp -nobram; cd sync_ram_sdp
select -assert-count 1 t:$mem # requested BRAM but BRAM is disabled
# RAM bits <= 64; Data width <= 4; Address width <= 4: -> DPR16X4
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 4 -set DATA_WIDTH 4 sync_ram_sdp
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:TRELLIS_DPR16X4
## With parameters
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 4 -set DATA_WIDTH 4 sync_ram_sdp
setattr -set syn_ramstyle "distributed" m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:TRELLIS_DPR16X4
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 4 -set DATA_WIDTH 4 sync_ram_sdp
setattr -set syn_ramstyle "registers" m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 0 t:TRELLIS_DPR16X4 # requested FFRAM explicitly
select -assert-count 68 t:TRELLIS_FF
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 4 -set DATA_WIDTH 4 sync_ram_sdp
setattr -set logic_block 1 m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 0 t:TRELLIS_DPR16X4 # requested FFRAM explicitly
select -assert-count 68 t:TRELLIS_FF
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 4 -set DATA_WIDTH 4 sync_ram_sdp
setattr -set syn_ramstyle "distributed" m:memory
synth_ecp5 -top sync_ram_sdp -nolutram; cd sync_ram_sdp
select -assert-count 1 t:$mem # requested LUTRAM but LUTRAM is disabled
# ================================ ROM ================================
# ROM bits <= 18K; Data width <= 36; Address width <= 9: -> PDPW16KD
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 36 sync_rom
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 1 t:PDPW16KD
## With parameters
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 36 sync_rom
write_ilang
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 0 t:PDPW16KD # too inefficient
select -assert-min 18 t:LUT4
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom
setattr -set syn_romstyle "ebr" m:memory
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 1 t:PDPW16KD
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom
setattr -set rom_block 1 m:memory
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 1 t:PDPW16KD
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 36 sync_rom
setattr -set syn_romstyle "logic" m:memory
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 0 t:PDPW16KD # requested LUTROM explicitly
select -assert-min 18 t:LUT4
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 36 sync_rom
setattr -set logic_block 1 m:memory
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 0 t:PDPW16KD # requested LUTROM explicitly
select -assert-min 18 t:LUT4
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom
setattr -set syn_ramstyle "block_ram" m:memory
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 1 t:$mem # requested BRAM but this is a ROM
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom
setattr -set ram_block 1 m:memory
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 1 t:$mem # requested BRAM but this is a ROM
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom
setattr -set syn_ramstyle "block_rom" m:memory
synth_ecp5 -top sync_rom -nobram; cd sync_rom
select -assert-count 1 t:$mem # requested BROM but BRAM is disabled
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom
setattr -set rom_block 1 m:memory
synth_ecp5 -top sync_rom -nobram; cd sync_rom
select -assert-count 1 t:$mem # requested BROM but BRAM is disabled
# ROM bits <= 18K; Data width <= 18; Address width <= 10: -> DP16KD
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 18 sync_rom
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 1 t:DP16KD
## With parameters
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 18 sync_rom
write_ilang
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 0 t:DP16KD # too inefficient
select -assert-min 9 t:LUT4
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom
setattr -set syn_romstyle "ebr" m:memory
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 1 t:DP16KD
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom
setattr -set rom_block 1 m:memory
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 1 t:DP16KD
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 18 sync_rom
setattr -set syn_romstyle "logic" m:memory
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 0 t:DP16KD # requested LUTROM explicitly
select -assert-min 9 t:LUT4
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 18 sync_rom
setattr -set logic_block 1 m:memory
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 0 t:DP16KD # requested LUTROM explicitly
select -assert-min 9 t:LUT4
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom
setattr -set syn_ramstyle "block_ram" m:memory
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 1 t:$mem # requested BRAM but this is a ROM
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom
setattr -set ram_block 1 m:memory
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 1 t:$mem # requested BRAM but this is a ROM
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom
setattr -set syn_ramstyle "block_rom" m:memory
synth_ecp5 -top sync_rom -nobram; cd sync_rom
select -assert-count 1 t:$mem # requested BROM but BRAM is disabled
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom
setattr -set rom_block 1 m:memory
synth_ecp5 -top sync_rom -nobram; cd sync_rom
select -assert-count 1 t:$mem # requested BROM but BRAM is disabled

View File

@ -1,15 +0,0 @@
read_verilog ../common/lutram.v
hierarchy -top lutram_1w1r
proc
memory -nomap
equiv_opt -run :prove -map +/ice40/cells_sim.v synth_ice40
memory
opt -full
miter -equiv -flatten -make_assert -make_outputs gold gate miter
sat -verify -prove-asserts -seq 5 -set-init-zero -show-inputs -show-outputs miter
design -load postopt
cd lutram_1w1r
select -assert-count 1 t:SB_RAM40_4K
select -assert-none t:SB_RAM40_4K %% t:* %D

View File

@ -0,0 +1,168 @@
# ================================ RAM ================================
# RAM bits <= 4K; Data width <= 16; Address width <= 11: -> SB_RAM40_4K
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 11 -set DATA_WIDTH 2 sync_ram_sdp
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:SB_RAM40_4K
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 4 sync_ram_sdp
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:SB_RAM40_4K
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 8 sync_ram_sdp
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:SB_RAM40_4K
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 8 -set DATA_WIDTH 16 sync_ram_sdp
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:SB_RAM40_4K
## With parameters
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 0 t:SB_RAM40_4K # too inefficient
select -assert-min 1 t:SB_DFFE
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
setattr -set syn_ramstyle "block_ram" m:memory
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:SB_RAM40_4K
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
setattr -set syn_ramstyle "Block_RAM" m:memory
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:SB_RAM40_4K # any case works
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
setattr -set ram_block 1 m:memory
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:SB_RAM40_4K
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
setattr -set syn_ramstyle "registers" m:memory
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 0 t:SB_RAM40_4K # requested FFRAM explicitly
select -assert-min 1 t:SB_DFFE
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
setattr -set logic_block 1 m:memory
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 0 t:SB_RAM40_4K # requested FFRAM explicitly
select -assert-min 1 t:SB_DFFE
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
setattr -set syn_romstyle "ebr" m:memory
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:$mem # requested BROM but this is a RAM
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
setattr -set rom_block 1 m:memory
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:$mem # requested BROM but this is a RAM
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
setattr -set syn_ramstyle "block_ram" m:memory
synth_ice40 -top sync_ram_sdp -nobram; cd sync_ram_sdp
select -assert-count 1 t:$mem # requested BRAM but BRAM is disabled
design -reset; read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
setattr -set ram_block 1 m:memory
synth_ice40 -top sync_ram_sdp -nobram; cd sync_ram_sdp
select -assert-count 1 t:$mem # requested BRAM but BRAM is disabled
# ================================ ROM ================================
# ROM bits <= 4K; Data width <= 16; Address width <= 11: -> SB_RAM40_4K
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 11 -set DATA_WIDTH 2 sync_rom
synth_ice40 -top sync_rom; cd sync_rom
select -assert-count 1 t:SB_RAM40_4K
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 4 sync_rom
synth_ice40 -top sync_rom; cd sync_rom
select -assert-count 1 t:SB_RAM40_4K
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 8 sync_rom
synth_ice40 -top sync_rom; cd sync_rom
select -assert-count 1 t:SB_RAM40_4K
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 8 -set DATA_WIDTH 16 sync_rom
synth_ice40 -top sync_rom; cd sync_rom
select -assert-count 1 t:SB_RAM40_4K
## With parameters
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
write_ilang
synth_ice40 -top sync_rom; cd sync_rom
select -assert-count 0 t:SB_RAM40_4K # too inefficient
select -assert-min 1 t:SB_LUT4
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
setattr -set syn_romstyle "ebr" m:memory
synth_ice40 -top sync_rom; cd sync_rom
select -assert-count 1 t:SB_RAM40_4K
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
setattr -set rom_block 1 m:memory
synth_ice40 -top sync_rom; cd sync_rom
select -assert-count 1 t:SB_RAM40_4K
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
setattr -set syn_romstyle "logic" m:memory
synth_ice40 -top sync_rom; cd sync_rom
select -assert-count 0 t:SB_RAM40_4K # requested LUTROM explicitly
select -assert-min 1 t:SB_LUT4
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
setattr -set logic_block 1 m:memory
synth_ice40 -top sync_rom; cd sync_rom
select -assert-count 0 t:SB_RAM40_4K # requested LUTROM explicitly
select -assert-min 1 t:SB_LUT4
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
setattr -set syn_ramstyle "block_ram" m:memory
synth_ice40 -top sync_rom; cd sync_rom
select -assert-count 1 t:$mem # requested BRAM but this is a ROM
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
setattr -set ram_block 1 m:memory
synth_ice40 -top sync_rom; cd sync_rom
select -assert-count 1 t:$mem # requested BRAM but this is a ROM
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
setattr -set syn_romstyle "ebr" m:memory
synth_ice40 -top sync_rom -nobram; cd sync_rom
select -assert-count 1 t:$mem # requested BROM but BRAM is disabled
design -reset; read_verilog ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
setattr -set rom_block 1 m:memory
synth_ice40 -top sync_rom -nobram; cd sync_rom
select -assert-count 1 t:$mem # requested BROM but BRAM is disabled