Optimize memory address port width in wreduce and memory_collect, not verilog front-end

This commit is contained in:
Clifford Wolf 2016-08-19 18:38:25 +02:00
parent 9b8e06bee1
commit f6629b9c29
4 changed files with 44 additions and 7 deletions

View File

@ -1253,13 +1253,15 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
int mem_width, mem_size, addr_bits; int mem_width, mem_size, addr_bits;
id2ast->meminfo(mem_width, mem_size, addr_bits); id2ast->meminfo(mem_width, mem_size, addr_bits);
RTLIL::SigSpec addr_sig = children[0]->genRTLIL();
cell->setPort("\\CLK", RTLIL::SigSpec(RTLIL::State::Sx, 1)); cell->setPort("\\CLK", RTLIL::SigSpec(RTLIL::State::Sx, 1));
cell->setPort("\\EN", RTLIL::SigSpec(RTLIL::State::Sx, 1)); cell->setPort("\\EN", RTLIL::SigSpec(RTLIL::State::Sx, 1));
cell->setPort("\\ADDR", children[0]->genWidthRTLIL(addr_bits)); cell->setPort("\\ADDR", addr_sig);
cell->setPort("\\DATA", RTLIL::SigSpec(wire)); cell->setPort("\\DATA", RTLIL::SigSpec(wire));
cell->parameters["\\MEMID"] = RTLIL::Const(str); cell->parameters["\\MEMID"] = RTLIL::Const(str);
cell->parameters["\\ABITS"] = RTLIL::Const(addr_bits); cell->parameters["\\ABITS"] = RTLIL::Const(GetSize(addr_sig));
cell->parameters["\\WIDTH"] = RTLIL::Const(wire->width); cell->parameters["\\WIDTH"] = RTLIL::Const(wire->width);
cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(0); cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(0);
@ -1290,11 +1292,13 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
cell->parameters["\\WORDS"] = RTLIL::Const(num_words); cell->parameters["\\WORDS"] = RTLIL::Const(num_words);
} }
cell->setPort("\\ADDR", children[0]->genWidthRTLIL(addr_bits)); SigSpec addr_sig = children[0]->genRTLIL();
cell->setPort("\\ADDR", addr_sig);
cell->setPort("\\DATA", children[1]->genWidthRTLIL(current_module->memories[str]->width * num_words)); cell->setPort("\\DATA", children[1]->genWidthRTLIL(current_module->memories[str]->width * num_words));
cell->parameters["\\MEMID"] = RTLIL::Const(str); cell->parameters["\\MEMID"] = RTLIL::Const(str);
cell->parameters["\\ABITS"] = RTLIL::Const(addr_bits); cell->parameters["\\ABITS"] = RTLIL::Const(GetSize(addr_sig));
cell->parameters["\\WIDTH"] = RTLIL::Const(current_module->memories[str]->width); cell->parameters["\\WIDTH"] = RTLIL::Const(current_module->memories[str]->width);
if (type == AST_MEMWR) { if (type == AST_MEMWR) {

View File

@ -1490,6 +1490,11 @@ skip_dynamic_range_lvalue_expansion:;
int mem_width, mem_size, addr_bits; int mem_width, mem_size, addr_bits;
children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits); children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits);
int addr_width_hint = -1;
bool addr_sign_hint = true;
children[0]->children[0]->children[0]->detectSignWidthWorker(addr_width_hint, addr_sign_hint);
addr_bits = std::max(addr_bits, addr_width_hint);
AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true))); AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true)));
wire_addr->str = id_addr; wire_addr->str = id_addr;
current_ast_mod->children.push_back(wire_addr); current_ast_mod->children.push_back(wire_addr);

View File

@ -37,8 +37,6 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory)
log("Collecting $memrd, $memwr and $meminit for memory `%s' in module `%s':\n", log("Collecting $memrd, $memwr and $meminit for memory `%s' in module `%s':\n",
memory->name.c_str(), module->name.c_str()); memory->name.c_str(), module->name.c_str());
int addr_bits = 0;
Const init_data(State::Sx, memory->size * memory->width); Const init_data(State::Sx, memory->size * memory->width);
SigMap sigmap(module); SigMap sigmap(module);
@ -59,16 +57,28 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory)
SigSpec sig_rd_data; SigSpec sig_rd_data;
SigSpec sig_rd_en; SigSpec sig_rd_en;
int addr_bits = 0;
std::vector<Cell*> memcells; std::vector<Cell*> memcells;
for (auto &cell_it : module->cells_) { for (auto &cell_it : module->cells_) {
Cell *cell = cell_it.second; Cell *cell = cell_it.second;
if (cell->type.in("$memrd", "$memwr", "$meminit") && memory->name == cell->parameters["\\MEMID"].decode_string()) { if (cell->type.in("$memrd", "$memwr", "$meminit") && memory->name == cell->parameters["\\MEMID"].decode_string()) {
addr_bits = max(addr_bits, cell->getParam("\\ABITS").as_int()); SigSpec addr = sigmap(cell->getPort("\\ADDR"));
for (int i = 0; i < GetSize(addr); i++)
if (addr[i] != State::S0)
addr_bits = std::max(addr_bits, i+1);
memcells.push_back(cell); memcells.push_back(cell);
} }
} }
if (memory->start_offset == 0 && addr_bits < 30 && (1 << addr_bits) < memory->size)
memory->size = 1 << addr_bits;
if (memory->start_offset >= 0)
addr_bits = std::min(addr_bits, ceil_log2(memory->size + memory->start_offset));
addr_bits = std::max(addr_bits, 1);
if (memcells.empty()) { if (memcells.empty()) {
log(" no cells found. removing memory.\n"); log(" no cells found. removing memory.\n");
return nullptr; return nullptr;

View File

@ -385,6 +385,7 @@ struct WreducePass : public Pass {
continue; continue;
for (auto c : module->selected_cells()) for (auto c : module->selected_cells())
{
if (c->type.in("$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool", if (c->type.in("$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool",
"$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt", "$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt",
"$logic_not", "$logic_and", "$logic_or") && GetSize(c->getPort("\\Y")) > 1) { "$logic_not", "$logic_and", "$logic_or") && GetSize(c->getPort("\\Y")) > 1) {
@ -396,6 +397,23 @@ struct WreducePass : public Pass {
module->connect(sig, Const(0, GetSize(sig))); module->connect(sig, Const(0, GetSize(sig)));
} }
} }
if (c->type.in("$memrd", "$memwr", "$meminit")) {
IdString memid = c->getParam("\\MEMID").decode_string();
RTLIL::Memory *mem = module->memories.at(memid);
if (mem->start_offset == 0) {
int cur_addrbits = c->getParam("\\ABITS").as_int();
int max_addrbits = ceil_log2(mem->size);
if (cur_addrbits > max_addrbits) {
log("Removed top %d address bits (of %d) from memory %s port %s.%s (%s).\n",
cur_addrbits-max_addrbits, cur_addrbits,
c->type == "$memrd" ? "read" : c->type == "$memwr" ? "write" : "init",
log_id(module), log_id(c), log_id(memid));
c->setParam("\\ABITS", max_addrbits);
c->setPort("\\ADDR", c->getPort("\\ADDR").extract(0, max_addrbits));
}
}
}
}
WreduceWorker worker(&config, module); WreduceWorker worker(&config, module);
worker.run(); worker.run();