mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	Optimize memory address port width in wreduce and memory_collect, not verilog front-end
This commit is contained in:
		
							parent
							
								
									9b8e06bee1
								
							
						
					
					
						commit
						f6629b9c29
					
				
					 4 changed files with 44 additions and 7 deletions
				
			
		| 
						 | 
				
			
			@ -1253,13 +1253,15 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
 | 
			
		|||
			int 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("\\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->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["\\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->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->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);
 | 
			
		||||
 | 
			
		||||
			if (type == AST_MEMWR) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1490,6 +1490,11 @@ skip_dynamic_range_lvalue_expansion:;
 | 
			
		|||
		int 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)));
 | 
			
		||||
		wire_addr->str = id_addr;
 | 
			
		||||
		current_ast_mod->children.push_back(wire_addr);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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",
 | 
			
		||||
			memory->name.c_str(), module->name.c_str());
 | 
			
		||||
 | 
			
		||||
	int addr_bits = 0;
 | 
			
		||||
 | 
			
		||||
	Const init_data(State::Sx, memory->size * memory->width);
 | 
			
		||||
	SigMap sigmap(module);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -59,16 +57,28 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory)
 | 
			
		|||
	SigSpec sig_rd_data;
 | 
			
		||||
	SigSpec sig_rd_en;
 | 
			
		||||
 | 
			
		||||
	int addr_bits = 0;
 | 
			
		||||
	std::vector<Cell*> memcells;
 | 
			
		||||
 | 
			
		||||
	for (auto &cell_it : module->cells_) {
 | 
			
		||||
		Cell *cell = cell_it.second;
 | 
			
		||||
		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);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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()) {
 | 
			
		||||
		log("  no cells found. removing memory.\n");
 | 
			
		||||
		return nullptr;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -385,6 +385,7 @@ struct WreducePass : public Pass {
 | 
			
		|||
				continue;
 | 
			
		||||
 | 
			
		||||
			for (auto c : module->selected_cells())
 | 
			
		||||
			{
 | 
			
		||||
				if (c->type.in("$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool",
 | 
			
		||||
						"$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt",
 | 
			
		||||
						"$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)));
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				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);
 | 
			
		||||
			worker.run();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue