mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	Added support for initialized brams
This commit is contained in:
		
							parent
							
								
									d19866615b
								
							
						
					
					
						commit
						169d1c4711
					
				
					 2 changed files with 45 additions and 9 deletions
				
			
		| 
						 | 
					@ -474,7 +474,16 @@ struct RTLIL::Const
 | 
				
			||||||
	std::string decode_string() const;
 | 
						std::string decode_string() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inline int size() const { return bits.size(); }
 | 
						inline int size() const { return bits.size(); }
 | 
				
			||||||
	inline RTLIL::State operator[](int index) { return bits.at(index); }
 | 
						inline RTLIL::State &operator[](int index) { return bits.at(index); }
 | 
				
			||||||
 | 
						inline const RTLIL::State &operator[](int index) const { return bits.at(index); };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						inline RTLIL::Const extract(int offset, int len = 1, RTLIL::State padding = RTLIL::State::S0) const {
 | 
				
			||||||
 | 
							RTLIL::Const ret;
 | 
				
			||||||
 | 
							ret.bits.reserve(len);
 | 
				
			||||||
 | 
							for (int i = offset; i < offset + len; i++)
 | 
				
			||||||
 | 
								ret.bits.push_back(i < GetSize(bits) ? bits[i] : padding);
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inline unsigned int hash() const {
 | 
						inline unsigned int hash() const {
 | 
				
			||||||
		unsigned int h = mkhash_init;
 | 
							unsigned int h = mkhash_init;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -393,6 +393,16 @@ bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram,
 | 
				
			||||||
	int mem_width = cell->getParam("\\WIDTH").as_int();
 | 
						int mem_width = cell->getParam("\\WIDTH").as_int();
 | 
				
			||||||
	// int mem_offset = cell->getParam("\\OFFSET").as_int();
 | 
						// int mem_offset = cell->getParam("\\OFFSET").as_int();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool cell_init = !SigSpec(cell->getParam("\\INIT")).is_fully_undef();
 | 
				
			||||||
 | 
						vector<Const> initdata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cell_init) {
 | 
				
			||||||
 | 
							Const initparam = cell->getParam("\\INIT");
 | 
				
			||||||
 | 
							initdata.reserve(mem_size);
 | 
				
			||||||
 | 
							for (int i=0; i < mem_size; i++)
 | 
				
			||||||
 | 
								initdata.push_back(initparam.extract(mem_width*i, mem_width, State::Sx));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int wr_ports = cell->getParam("\\WR_PORTS").as_int();
 | 
						int wr_ports = cell->getParam("\\WR_PORTS").as_int();
 | 
				
			||||||
	auto wr_clken = SigSpec(cell->getParam("\\WR_CLK_ENABLE"));
 | 
						auto wr_clken = SigSpec(cell->getParam("\\WR_CLK_ENABLE"));
 | 
				
			||||||
	auto wr_clkpol = SigSpec(cell->getParam("\\WR_CLK_POLARITY"));
 | 
						auto wr_clkpol = SigSpec(cell->getParam("\\WR_CLK_POLARITY"));
 | 
				
			||||||
| 
						 | 
					@ -789,6 +799,22 @@ grow_read_ports:;
 | 
				
			||||||
			for (auto &vp : variant_params)
 | 
								for (auto &vp : variant_params)
 | 
				
			||||||
				c->setParam(vp.first, vp.second);
 | 
									c->setParam(vp.first, vp.second);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (cell_init) {
 | 
				
			||||||
 | 
									int init_offset = grid_a*(1 << bram.abits);
 | 
				
			||||||
 | 
									int init_shift = grid_d*bram.dbits;
 | 
				
			||||||
 | 
									int init_size = (1 << bram.abits);
 | 
				
			||||||
 | 
									Const initparam(State::Sx, init_size*bram.dbits);
 | 
				
			||||||
 | 
									for (int i = 0; i < init_size; i++) {
 | 
				
			||||||
 | 
										State padding = State::Sx;
 | 
				
			||||||
 | 
										for (int j = 0; j < bram.dbits; j++)
 | 
				
			||||||
 | 
											if (init_offset+i < GetSize(initdata) && init_shift+j < GetSize(initdata[init_offset+i]))
 | 
				
			||||||
 | 
												padding = initparam[i*bram.dbits+j] = initdata[init_offset+i][init_shift+j];
 | 
				
			||||||
 | 
											else
 | 
				
			||||||
 | 
												initparam[i*bram.dbits+j] = padding;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									c->setParam("\\INIT", initparam);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			for (auto &pi : portinfos)
 | 
								for (auto &pi : portinfos)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				if (pi.dupidx != dupidx)
 | 
									if (pi.dupidx != dupidx)
 | 
				
			||||||
| 
						 | 
					@ -905,10 +931,7 @@ void handle_cell(Cell *cell, const rules_t &rules)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	log("Processing %s.%s:\n", log_id(cell->module), log_id(cell));
 | 
						log("Processing %s.%s:\n", log_id(cell->module), log_id(cell));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!SigSpec(cell->getParam("\\INIT")).is_fully_undef()) {
 | 
						bool cell_init = !SigSpec(cell->getParam("\\INIT")).is_fully_undef();
 | 
				
			||||||
		log("  initialized memories are not supported yet.");
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dict<string, int> match_properties;
 | 
						dict<string, int> match_properties;
 | 
				
			||||||
	match_properties["words"]  = cell->getParam("\\SIZE").as_int();
 | 
						match_properties["words"]  = cell->getParam("\\SIZE").as_int();
 | 
				
			||||||
| 
						 | 
					@ -980,6 +1003,12 @@ void handle_cell(Cell *cell, const rules_t &rules)
 | 
				
			||||||
			log("    Metrics for %s: awaste=%d dwaste=%d bwaste=%d waste=%d efficiency=%d\n",
 | 
								log("    Metrics for %s: awaste=%d dwaste=%d bwaste=%d waste=%d efficiency=%d\n",
 | 
				
			||||||
					log_id(match.name), awaste, dwaste, bwaste, waste, efficiency);
 | 
										log_id(match.name), awaste, dwaste, bwaste, waste, efficiency);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (cell_init && bram.init == 0) {
 | 
				
			||||||
 | 
									log("    Rule #%d for bram type %s (variant %d) rejected: cannot be initialized.\n",
 | 
				
			||||||
 | 
											i+1, log_id(bram.name), bram.variant);
 | 
				
			||||||
 | 
									goto next_match_rule;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			for (auto it : match.min_limits) {
 | 
								for (auto it : match.min_limits) {
 | 
				
			||||||
				if (it.first == "waste" || it.first == "dups" || it.first == "acells" || it.first == "dcells" || it.first == "cells")
 | 
									if (it.first == "waste" || it.first == "dups" || it.first == "acells" || it.first == "dcells" || it.first == "cells")
 | 
				
			||||||
					continue;
 | 
										continue;
 | 
				
			||||||
| 
						 | 
					@ -992,6 +1021,7 @@ void handle_cell(Cell *cell, const rules_t &rules)
 | 
				
			||||||
						i+1, log_id(bram.name), bram.variant, it.first.c_str(), it.second);
 | 
											i+1, log_id(bram.name), bram.variant, it.first.c_str(), it.second);
 | 
				
			||||||
				goto next_match_rule;
 | 
									goto next_match_rule;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			for (auto it : match.max_limits) {
 | 
								for (auto it : match.max_limits) {
 | 
				
			||||||
				if (it.first == "acells" || it.first == "dcells" || it.first == "cells")
 | 
									if (it.first == "acells" || it.first == "dcells" || it.first == "cells")
 | 
				
			||||||
					continue;
 | 
										continue;
 | 
				
			||||||
| 
						 | 
					@ -1021,9 +1051,6 @@ void handle_cell(Cell *cell, const rules_t &rules)
 | 
				
			||||||
				log("      Storing for later selection.\n");
 | 
									log("      Storing for later selection.\n");
 | 
				
			||||||
				best_rule_cache[pair<int, int>(i, vi)] = std::tuple<int, int, int>(match_properties["efficiency"], -match_properties["cells"], -match_properties["acells"]);
 | 
									best_rule_cache[pair<int, int>(i, vi)] = std::tuple<int, int, int>(match_properties["efficiency"], -match_properties["cells"], -match_properties["acells"]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (or_next_if_better)
 | 
					 | 
				
			||||||
					goto next_match_rule;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		next_match_rule:
 | 
							next_match_rule:
 | 
				
			||||||
				if (or_next_if_better || best_rule_cache.empty())
 | 
									if (or_next_if_better || best_rule_cache.empty())
 | 
				
			||||||
					continue;
 | 
										continue;
 | 
				
			||||||
| 
						 | 
					@ -1075,7 +1102,7 @@ struct MemoryBramPass : public Pass {
 | 
				
			||||||
		log("rules. A block ram description looks like this:\n");
 | 
							log("rules. 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");
 | 
				
			||||||
		log("      abits 10           # number of address bits\n");
 | 
							log("      abits 10           # number of address bits\n");
 | 
				
			||||||
		log("      dbits 32           # number of data bits\n");
 | 
							log("      dbits 32           # number of data bits\n");
 | 
				
			||||||
		log("      groups 2           # number of port groups\n");
 | 
							log("      groups 2           # number of port groups\n");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue