3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-08-03 09:50:24 +00:00
This commit is contained in:
Kelvin Chung 2025-07-31 09:54:10 +01:00 committed by GitHub
commit 22e50bee4d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 85 additions and 19 deletions

View file

@ -31,7 +31,7 @@ struct MemoryPass : public Pass {
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" memory [-norom] [-nomap] [-nordff] [-nowiden] [-nosat] [-memx] [-no-rw-check] [-bram <bram_rules>] [selection]\n");
log(" memory [-external-init] [-norom] [-nomap] [-nordff] [-nowiden] [-nosat] [-memx] [-no-rw-check] [-bram <bram_rules>] [selection]\n");
log("\n");
log("This pass calls all the other memory_* passes in a useful order:\n");
log("\n");
@ -59,6 +59,7 @@ struct MemoryPass : public Pass {
bool flag_nomap = false;
bool flag_nordff = false;
bool flag_memx = false;
string opt_mem_opts;
string memory_dff_opts;
string memory_bram_opts;
string memory_share_opts;
@ -68,6 +69,10 @@ struct MemoryPass : public Pass {
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
if (args[argidx] == "-external-init") {
opt_mem_opts += " -external-init";
continue;
}
if (args[argidx] == "-norom") {
flag_norom = true;
continue;
@ -105,7 +110,7 @@ struct MemoryPass : public Pass {
}
extra_args(args, argidx, design);
Pass::call(design, "opt_mem");
Pass::call(design, "opt_mem" + opt_mem_opts);
Pass::call(design, "opt_mem_priority");
Pass::call(design, "opt_mem_feedback");
if (!flag_norom)

View file

@ -17,16 +17,16 @@
*
*/
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
#include "kernel/mem.h"
#include "kernel/ff.h"
#include "kernel/mem.h"
#include "kernel/sigtools.h"
#include "kernel/yosys.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct OptMemPass : public Pass {
OptMemPass() : Pass("opt_mem", "optimize memories") { }
OptMemPass() : Pass("opt_mem", "optimize memories") {}
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
@ -35,17 +35,23 @@ struct OptMemPass : public Pass {
log("\n");
log("This pass performs various optimizations on memories in the design.\n");
log("\n");
log(" -external-init\n");
log(" Assume memories are initialised externally, i.e. the memory\n");
log(" is pre-populated so content is available even when there is no\n");
log(" write within the circuit.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
log_header(design, "Executing OPT_MEM pass (optimize memories).\n");
bool external_init = false;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
// if (args[argidx] == "-nomux") {
// mode_nomux = true;
// continue;
// }
if (args[argidx] == "-external-init") {
external_init = true;
continue;
}
break;
}
extra_args(args, argidx, design);
@ -102,7 +108,7 @@ struct OptMemPass : public Pass {
}
std::vector<int> swizzle;
for (int i = 0; i < mem.width; i++) {
if (!always_0[i] && !always_1[i]) {
if ((!always_0[i] && !always_1[i]) || external_init) {
swizzle.push_back(i);
continue;
}
@ -118,7 +124,7 @@ struct OptMemPass : public Pass {
bit = State::Sx;
}
// Reconnect read port data.
for (auto &port: mem.rd_ports) {
for (auto &port : mem.rd_ports) {
for (int sub = 0; sub < (1 << port.wide_log2); sub++) {
int bidx = sub * mem.width + i;
if (!port.clk_enable) {
@ -161,11 +167,11 @@ struct OptMemPass : public Pass {
continue;
}
if (GetSize(swizzle) != mem.width) {
for (auto &port: mem.wr_ports) {
for (auto &port : mem.wr_ports) {
SigSpec new_data;
SigSpec new_en;
for (int sub = 0; sub < (1 << port.wide_log2); sub++) {
for (auto i: swizzle) {
for (auto i : swizzle) {
new_data.append(port.data[sub * mem.width + i]);
new_en.append(port.en[sub * mem.width + i]);
}
@ -173,13 +179,13 @@ struct OptMemPass : public Pass {
port.data = new_data;
port.en = new_en;
}
for (auto &port: mem.rd_ports) {
for (auto &port : mem.rd_ports) {
SigSpec new_data;
Const new_init;
Const new_arst;
Const new_srst;
for (int sub = 0; sub < (1 << port.wide_log2); sub++) {
for (auto i: swizzle) {
for (auto i : swizzle) {
int bidx = sub * mem.width + i;
new_data.append(port.data[bidx]);
new_init.bits().push_back(port.init_value[bidx]);
@ -192,15 +198,15 @@ struct OptMemPass : public Pass {
port.arst_value = new_arst;
port.srst_value = new_srst;
}
for (auto &init: mem.inits) {
for (auto &init : mem.inits) {
Const new_data;
Const new_en;
for (int s = 0; s < GetSize(init.data); s += mem.width) {
for (auto i: swizzle) {
for (auto i : swizzle) {
new_data.bits().push_back(init.data[s + i]);
}
}
for (auto i: swizzle) {
for (auto i : swizzle) {
new_en.bits().push_back(init.en[i]);
}
init.data = new_data;

View file

@ -0,0 +1,55 @@
read_verilog << EOF
module Mem #(
parameter WIDTH = 8,
parameter SIZE = 16,
parameter IDX_SIZE = 16
) (
input wire [WIDTH-1:0] addr,
input wire [WIDTH-1:0] write_data,
input wire write_en,
input wire clk,
output reg [WIDTH-1:0] read_data,
);
reg [WIDTH-1:0] mem[SIZE-1:0];
always @(posedge clk) begin
if (write_en)
mem[addr0[IDX_SIZE-1:0]] <= write_data;
read_data <= mem[addr0[IDX_SIZE-1:0]];
end
endmodule
module test_keep_at_instance (clk, addr, data);
input wire clk;
input wire [15:0] addr;
output wire[7:0] data;
Mem mem (
.clk(clk),
.addr(addr),
.read_data(data),
.write_en(1'b0),
.write_data()
);
endmodule
EOF
hierarchy -auto-top;
flatten;
proc;
select -assert-any t:$mem*
opt_mem -external-init
select -assert-any t:$mem*
select -assert-any t:$mem*
opt_mem
select -assert-none t:$mem*