mirror of https://github.com/YosysHQ/yosys.git
memory_dff: Remove now-useless write port handling.
This commit is contained in:
parent
89c74ffd71
commit
a3528649c8
|
@ -36,7 +36,7 @@ struct MemoryPass : public Pass {
|
||||||
log("This pass calls all the other memory_* passes in a useful order:\n");
|
log("This pass calls all the other memory_* passes in a useful order:\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" opt_mem\n");
|
log(" opt_mem\n");
|
||||||
log(" memory_dff [-nordff] (-memx implies -nordff)\n");
|
log(" memory_dff (skipped if called with -nordff or -memx)\n");
|
||||||
log(" opt_clean\n");
|
log(" opt_clean\n");
|
||||||
log(" memory_share\n");
|
log(" memory_share\n");
|
||||||
log(" opt_clean\n");
|
log(" opt_clean\n");
|
||||||
|
@ -83,7 +83,8 @@ struct MemoryPass : public Pass {
|
||||||
extra_args(args, argidx, design);
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
Pass::call(design, "opt_mem");
|
Pass::call(design, "opt_mem");
|
||||||
Pass::call(design, flag_nordff ? "memory_dff -nordff" : "memory_dff");
|
if (!flag_nordff)
|
||||||
|
Pass::call(design, "memory_dff");
|
||||||
Pass::call(design, "opt_clean");
|
Pass::call(design, "opt_clean");
|
||||||
Pass::call(design, "memory_share");
|
Pass::call(design, "memory_share");
|
||||||
if (flag_memx)
|
if (flag_memx)
|
||||||
|
|
|
@ -33,7 +33,6 @@ struct MemoryDffWorker
|
||||||
vector<Cell*> dff_cells;
|
vector<Cell*> dff_cells;
|
||||||
dict<SigBit, SigBit> invbits;
|
dict<SigBit, SigBit> invbits;
|
||||||
dict<SigBit, int> sigbit_users_count;
|
dict<SigBit, int> sigbit_users_count;
|
||||||
pool<Cell*> forward_merged_dffs, candidate_dffs;
|
|
||||||
FfInitVals initvals;
|
FfInitVals initvals;
|
||||||
|
|
||||||
MemoryDffWorker(Module *module) : module(module), sigmap(module)
|
MemoryDffWorker(Module *module) : module(module), sigmap(module)
|
||||||
|
@ -113,7 +112,6 @@ struct MemoryDffWorker
|
||||||
bit = d;
|
bit = d;
|
||||||
clk = this_clk;
|
clk = this_clk;
|
||||||
clk_polarity = this_clk_polarity;
|
clk_polarity = this_clk_polarity;
|
||||||
candidate_dffs.insert(cell);
|
|
||||||
goto replaced_this_bit;
|
goto replaced_this_bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,8 +133,6 @@ struct MemoryDffWorker
|
||||||
|
|
||||||
for (auto cell : dff_cells)
|
for (auto cell : dff_cells)
|
||||||
{
|
{
|
||||||
if (forward_merged_dffs.count(cell))
|
|
||||||
continue;
|
|
||||||
if (!cell->type.in(ID($dff), ID($dffe)))
|
if (!cell->type.in(ID($dff), ID($dffe)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -186,7 +182,6 @@ struct MemoryDffWorker
|
||||||
clk_polarity = this_clk_polarity;
|
clk_polarity = this_clk_polarity;
|
||||||
en = this_en;
|
en = this_en;
|
||||||
en_polarity = this_en_polarity;
|
en_polarity = this_en_polarity;
|
||||||
candidate_dffs.insert(cell);
|
|
||||||
goto replaced_this_bit;
|
goto replaced_this_bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,51 +192,6 @@ struct MemoryDffWorker
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_wr_cell(RTLIL::Cell *cell)
|
|
||||||
{
|
|
||||||
log("Checking cell `%s' in module `%s': ", cell->name.c_str(), module->name.c_str());
|
|
||||||
|
|
||||||
RTLIL::SigSpec clk = RTLIL::SigSpec(RTLIL::State::Sx);
|
|
||||||
bool clk_polarity = 0;
|
|
||||||
candidate_dffs.clear();
|
|
||||||
|
|
||||||
RTLIL::SigSpec sig_addr = cell->getPort(ID::ADDR);
|
|
||||||
if (!find_sig_before_dff(sig_addr, clk, clk_polarity)) {
|
|
||||||
log("no (compatible) $dff for address input found.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RTLIL::SigSpec sig_data = cell->getPort(ID::DATA);
|
|
||||||
if (!find_sig_before_dff(sig_data, clk, clk_polarity)) {
|
|
||||||
log("no (compatible) $dff for data input found.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RTLIL::SigSpec sig_en = cell->getPort(ID::EN);
|
|
||||||
if (!find_sig_before_dff(sig_en, clk, clk_polarity)) {
|
|
||||||
log("no (compatible) $dff for enable input found.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clk != RTLIL::SigSpec(RTLIL::State::Sx))
|
|
||||||
{
|
|
||||||
for (auto cell : candidate_dffs)
|
|
||||||
forward_merged_dffs.insert(cell);
|
|
||||||
|
|
||||||
cell->setPort(ID::CLK, clk);
|
|
||||||
cell->setPort(ID::ADDR, sig_addr);
|
|
||||||
cell->setPort(ID::DATA, sig_data);
|
|
||||||
cell->setPort(ID::EN, sig_en);
|
|
||||||
cell->parameters[ID::CLK_ENABLE] = RTLIL::Const(1);
|
|
||||||
cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(clk_polarity);
|
|
||||||
|
|
||||||
log("merged $dff to cell.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
log("no (compatible) $dff found.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void disconnect_dff(RTLIL::SigSpec sig)
|
void disconnect_dff(RTLIL::SigSpec sig)
|
||||||
{
|
{
|
||||||
sigmap.apply(sig);
|
sigmap.apply(sig);
|
||||||
|
@ -309,7 +259,7 @@ struct MemoryDffWorker
|
||||||
log("no (compatible) $dff found.\n");
|
log("no (compatible) $dff found.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void run(bool flag_wr_only)
|
void run()
|
||||||
{
|
{
|
||||||
for (auto wire : module->wires()) {
|
for (auto wire : module->wires()) {
|
||||||
if (wire->port_output)
|
if (wire->port_output)
|
||||||
|
@ -337,51 +287,37 @@ struct MemoryDffWorker
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto cell : module->selected_cells())
|
for (auto cell : module->selected_cells())
|
||||||
if (cell->type == ID($memwr) && !cell->parameters[ID::CLK_ENABLE].as_bool())
|
if (cell->type == ID($memrd) && !cell->parameters[ID::CLK_ENABLE].as_bool())
|
||||||
handle_wr_cell(cell);
|
handle_rd_cell(cell);
|
||||||
|
|
||||||
if (!flag_wr_only)
|
|
||||||
for (auto cell : module->selected_cells())
|
|
||||||
if (cell->type == ID($memrd) && !cell->parameters[ID::CLK_ENABLE].as_bool())
|
|
||||||
handle_rd_cell(cell);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MemoryDffPass : public Pass {
|
struct MemoryDffPass : public Pass {
|
||||||
MemoryDffPass() : Pass("memory_dff", "merge input/output DFFs into memories") { }
|
MemoryDffPass() : Pass("memory_dff", "merge input/output DFFs into memory read ports") { }
|
||||||
void help() override
|
void help() override
|
||||||
{
|
{
|
||||||
// |---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_dff [options] [selection]\n");
|
log(" memory_dff [options] [selection]\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log("This pass detects DFFs at memory ports and merges them into the memory port.\n");
|
log("This pass detects DFFs at memory read ports and merges them into the memory port.\n");
|
||||||
log("I.e. it consumes an asynchronous memory port and the flip-flops at its\n");
|
log("I.e. it consumes an asynchronous memory port and the flip-flops at its\n");
|
||||||
log("interface and yields a synchronous memory port.\n");
|
log("interface and yields a synchronous memory port.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -nordfff\n");
|
|
||||||
log(" do not merge registers on read ports\n");
|
|
||||||
log("\n");
|
|
||||||
}
|
}
|
||||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||||
{
|
{
|
||||||
bool flag_wr_only = false;
|
log_header(design, "Executing MEMORY_DFF pass (merging $dff cells to $memrd).\n");
|
||||||
|
|
||||||
log_header(design, "Executing MEMORY_DFF pass (merging $dff cells to $memrd and $memwr).\n");
|
|
||||||
|
|
||||||
size_t argidx;
|
size_t argidx;
|
||||||
for (argidx = 1; argidx < args.size(); argidx++) {
|
for (argidx = 1; argidx < args.size(); argidx++) {
|
||||||
if (args[argidx] == "-nordff" || args[argidx] == "-wr_only") {
|
|
||||||
flag_wr_only = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
extra_args(args, argidx, design);
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
for (auto mod : design->selected_modules()) {
|
for (auto mod : design->selected_modules()) {
|
||||||
MemoryDffWorker worker(mod);
|
MemoryDffWorker worker(mod);
|
||||||
worker.run(flag_wr_only);
|
worker.run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} MemoryDffPass;
|
} MemoryDffPass;
|
||||||
|
|
|
@ -33,7 +33,7 @@ struct MemoryNordffPass : public Pass {
|
||||||
log(" memory_nordff [options] [selection]\n");
|
log(" memory_nordff [options] [selection]\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log("This pass extracts FFs from memory read ports. This results in a netlist\n");
|
log("This pass extracts FFs from memory read ports. This results in a netlist\n");
|
||||||
log("similar to what one would get from calling memory_dff with -nordff.\n");
|
log("similar to what one would get from not calling memory_dff.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
}
|
}
|
||||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||||
|
|
|
@ -61,7 +61,7 @@ struct PrepPass : public ScriptPass
|
||||||
log(" do not run any of the memory_* passes\n");
|
log(" do not run any of the memory_* passes\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -rdff\n");
|
log(" -rdff\n");
|
||||||
log(" do not pass -nordff to 'memory_dff'. This enables merging of FFs into\n");
|
log(" call 'memory_dff'. This enables merging of FFs into\n");
|
||||||
log(" memory read ports.\n");
|
log(" memory read ports.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -nokeepdc\n");
|
log(" -nokeepdc\n");
|
||||||
|
@ -79,7 +79,7 @@ struct PrepPass : public ScriptPass
|
||||||
}
|
}
|
||||||
|
|
||||||
string top_module, fsm_opts;
|
string top_module, fsm_opts;
|
||||||
bool autotop, flatten, ifxmode, memxmode, nomemmode, nokeepdc, nordff;
|
bool autotop, flatten, ifxmode, memxmode, nomemmode, nokeepdc, rdff;
|
||||||
|
|
||||||
void clear_flags() override
|
void clear_flags() override
|
||||||
{
|
{
|
||||||
|
@ -91,7 +91,7 @@ struct PrepPass : public ScriptPass
|
||||||
memxmode = false;
|
memxmode = false;
|
||||||
nomemmode = false;
|
nomemmode = false;
|
||||||
nokeepdc = false;
|
nokeepdc = false;
|
||||||
nordff = true;
|
rdff = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||||
|
@ -137,11 +137,11 @@ struct PrepPass : public ScriptPass
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (args[argidx] == "-nordff") {
|
if (args[argidx] == "-nordff") {
|
||||||
nordff = true;
|
rdff = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (args[argidx] == "-rdff") {
|
if (args[argidx] == "-rdff") {
|
||||||
nordff = false;
|
rdff = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (args[argidx] == "-nokeepdc") {
|
if (args[argidx] == "-nokeepdc") {
|
||||||
|
@ -202,7 +202,8 @@ struct PrepPass : public ScriptPass
|
||||||
run(memxmode ? "wreduce -keepdc -memx" : "wreduce -keepdc");
|
run(memxmode ? "wreduce -keepdc -memx" : "wreduce -keepdc");
|
||||||
}
|
}
|
||||||
if (!nomemmode) {
|
if (!nomemmode) {
|
||||||
run(string("memory_dff") + (help_mode ? " [-nordff]" : nordff ? " -nordff" : ""));
|
if (help_mode || rdff)
|
||||||
|
run("memory_dff", "(if -rdff)");
|
||||||
if (help_mode || memxmode)
|
if (help_mode || memxmode)
|
||||||
run("memory_memx", "(if -memx)");
|
run("memory_memx", "(if -memx)");
|
||||||
run("opt_clean");
|
run("opt_clean");
|
||||||
|
|
|
@ -22,7 +22,6 @@ endmodule
|
||||||
EOT
|
EOT
|
||||||
|
|
||||||
proc
|
proc
|
||||||
memory_dff
|
|
||||||
|
|
||||||
select -assert-count 2 t:$memrd
|
select -assert-count 2 t:$memrd
|
||||||
select -assert-count 1 t:$memwr
|
select -assert-count 1 t:$memwr
|
||||||
|
|
|
@ -197,7 +197,7 @@ do
|
||||||
test_passes -f "$frontend $include_opts" -p "hierarchy; synth -run coarse; techmap; opt; abc -dff" ${bn}_ref.${refext}
|
test_passes -f "$frontend $include_opts" -p "hierarchy; synth -run coarse; techmap; opt; abc -dff" ${bn}_ref.${refext}
|
||||||
if [ -n "$firrtl2verilog" ]; then
|
if [ -n "$firrtl2verilog" ]; then
|
||||||
if test -z "$xfirrtl" || ! grep "$fn" "$xfirrtl" ; then
|
if test -z "$xfirrtl" || ! grep "$fn" "$xfirrtl" ; then
|
||||||
"$toolsdir"/../../yosys -b "firrtl" -o ${bn}_ref.fir -f "$frontend $include_opts" -p "prep -nordff; proc; opt -nodffe -nosdff; fsm; opt; memory; opt -full -fine; pmuxtree" ${bn}_ref.${refext}
|
"$toolsdir"/../../yosys -b "firrtl" -o ${bn}_ref.fir -f "$frontend $include_opts" -p "prep; proc; opt -nodffe -nosdff; fsm; opt; memory; opt -full -fine; pmuxtree" ${bn}_ref.${refext}
|
||||||
$firrtl2verilog -i ${bn}_ref.fir -o ${bn}_ref.fir.v
|
$firrtl2verilog -i ${bn}_ref.fir -o ${bn}_ref.fir.v
|
||||||
test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt -nodffe -nosdff; fsm; opt; memory; opt -full -fine" ${bn}_ref.fir.v
|
test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt -nodffe -nosdff; fsm; opt; memory; opt -full -fine" ${bn}_ref.fir.v
|
||||||
fi
|
fi
|
||||||
|
|
Loading…
Reference in New Issue