mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	Progress in memory_bram
This commit is contained in:
		
							parent
							
								
									94e6b70736
								
							
						
					
					
						commit
						327a5d42b6
					
				
					 4 changed files with 127 additions and 15 deletions
				
			
		|  | @ -250,14 +250,14 @@ namespace RTLIL | ||||||
| 		// of cell types). the following functions helps with that.
 | 		// of cell types). the following functions helps with that.
 | ||||||
| 
 | 
 | ||||||
| 		template<typename T, typename... Args> | 		template<typename T, typename... Args> | ||||||
| 		bool in(T first, Args... rest) { | 		bool in(T first, Args... rest) const { | ||||||
| 			return in(first) || in(rest...); | 			return in(first) || in(rest...); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		bool in(IdString rhs) { return *this == rhs; } | 		bool in(IdString rhs) const { return *this == rhs; } | ||||||
| 		bool in(const char *rhs) { return *this == rhs; } | 		bool in(const char *rhs) const { return *this == rhs; } | ||||||
| 		bool in(const std::string &rhs) { return *this == rhs; } | 		bool in(const std::string &rhs) const { return *this == rhs; } | ||||||
| 		bool in(const pool<IdString> &rhs) { return rhs.count(*this) != 0; } | 		bool in(const pool<IdString> &rhs) const { return rhs.count(*this) != 0; } | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	static inline std::string escape_id(std::string str) { | 	static inline std::string escape_id(std::string str) { | ||||||
|  |  | ||||||
|  | @ -137,6 +137,8 @@ YOSYS_NAMESPACE_BEGIN | ||||||
| 
 | 
 | ||||||
| using std::vector; | using std::vector; | ||||||
| using std::string; | using std::string; | ||||||
|  | using std::pair; | ||||||
|  | 
 | ||||||
| using hashlib::mkhash; | using hashlib::mkhash; | ||||||
| using hashlib::mkhash_init; | using hashlib::mkhash_init; | ||||||
| using hashlib::mkhash_add; | using hashlib::mkhash_add; | ||||||
|  | @ -221,6 +223,8 @@ YOSYS_NAMESPACE_END | ||||||
| 
 | 
 | ||||||
| YOSYS_NAMESPACE_BEGIN | YOSYS_NAMESPACE_BEGIN | ||||||
| 
 | 
 | ||||||
|  | using RTLIL::State; | ||||||
|  | 
 | ||||||
| namespace hashlib { | namespace hashlib { | ||||||
| 	template<> struct hash_ops<RTLIL::State> : hash_ops<int> {}; | 	template<> struct hash_ops<RTLIL::State> : hash_ops<int> {}; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,10 +24,33 @@ PRIVATE_NAMESPACE_BEGIN | ||||||
| 
 | 
 | ||||||
| struct rules_t | struct rules_t | ||||||
| { | { | ||||||
|  | 	struct portinfo_t { | ||||||
|  | 		int group, index; | ||||||
|  | 		int wrmode, enable, transp, clocks, clkpol; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
| 	struct bram_t { | 	struct bram_t { | ||||||
| 		IdString name; | 		IdString name; | ||||||
| 		int groups, abits, dbits, init; | 		int groups, abits, dbits, init; | ||||||
| 		vector<int> wports, rports, wenabl, transp, clocks, clkpol; | 		vector<int> ports, wrmode, enable, transp, clocks, clkpol; | ||||||
|  | 
 | ||||||
|  | 		vector<portinfo_t> make_portinfos() const | ||||||
|  | 		{ | ||||||
|  | 			vector<portinfo_t> portinfos; | ||||||
|  | 			for (int i = 0; i < groups && i < GetSize(ports); i++) | ||||||
|  | 			for (int j = 0; j < ports[i]; j++) { | ||||||
|  | 				portinfo_t pi; | ||||||
|  | 				pi.group = i; | ||||||
|  | 				pi.index = j; | ||||||
|  | 				pi.wrmode = i < GetSize(wrmode) ? wrmode[i] : 0; | ||||||
|  | 				pi.enable = i < GetSize(enable) ? enable[i] : 0; | ||||||
|  | 				pi.transp = i < GetSize(transp) ? transp[i] : 0; | ||||||
|  | 				pi.clocks = i < GetSize(clocks) ? clocks[i] : 0; | ||||||
|  | 				pi.clkpol = i < GetSize(clkpol) ? clkpol[i] : 0; | ||||||
|  | 				portinfos.push_back(pi); | ||||||
|  | 			} | ||||||
|  | 			return portinfos; | ||||||
|  | 		} | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	struct match_t { | 	struct match_t { | ||||||
|  | @ -80,7 +103,7 @@ struct rules_t | ||||||
| 		if (GetSize(tokens) >= 2 && tokens[0] == stmt) { | 		if (GetSize(tokens) >= 2 && tokens[0] == stmt) { | ||||||
| 			value.resize(GetSize(tokens)-1); | 			value.resize(GetSize(tokens)-1); | ||||||
| 			for (int i = 1; i < GetSize(tokens); i++) | 			for (int i = 1; i < GetSize(tokens); i++) | ||||||
| 				value[i] = atoi(tokens[i].c_str()); | 				value[i-1] = atoi(tokens[i].c_str()); | ||||||
| 			return true; | 			return true; | ||||||
| 		} | 		} | ||||||
| 		return false; | 		return false; | ||||||
|  | @ -113,13 +136,13 @@ struct rules_t | ||||||
| 			if (parse_single_int("init", data.init)) | 			if (parse_single_int("init", data.init)) | ||||||
| 				continue; | 				continue; | ||||||
| 
 | 
 | ||||||
| 			if (parse_int_vect("wports", data.wports)) | 			if (parse_int_vect("ports", data.ports)) | ||||||
| 				continue; | 				continue; | ||||||
| 
 | 
 | ||||||
| 			if (parse_int_vect("rports", data.rports)) | 			if (parse_int_vect("wrmode", data.wrmode)) | ||||||
| 				continue; | 				continue; | ||||||
| 
 | 
 | ||||||
| 			if (parse_int_vect("wenabl", data.wenabl)) | 			if (parse_int_vect("enable", data.enable)) | ||||||
| 				continue; | 				continue; | ||||||
| 
 | 
 | ||||||
| 			if (parse_int_vect("transp", data.transp)) | 			if (parse_int_vect("transp", data.transp)) | ||||||
|  | @ -187,9 +210,85 @@ struct rules_t | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void replace_cell(Cell*, const rules_t::bram_t&, const rules_t::match_t&) | bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_t&) | ||||||
| { | { | ||||||
|  | 	auto portinfos = bram.make_portinfos(); | ||||||
|  | 	dict<int, pair<SigBit, bool>> clock_domains; | ||||||
|  | 	vector<int> mapped_wr_ports; | ||||||
|  | 
 | ||||||
|  | 	log("  Mapping to bram type %s:\n", log_id(bram.name)); | ||||||
|  | 
 | ||||||
|  | 	int wr_ports_n = cell->getParam("\\WR_PORTS").as_int(); | ||||||
|  | 	auto wr_clken = SigSpec(cell->getParam("\\WR_CLK_ENABLE")); | ||||||
|  | 	auto wr_clkpol = SigSpec(cell->getParam("\\WR_CLK_POLARITY")); | ||||||
|  | 	wr_clken.extend_u0(wr_ports_n); | ||||||
|  | 	wr_clkpol.extend_u0(wr_ports_n); | ||||||
|  | 
 | ||||||
|  | 	SigSpec wr_clk = cell->getPort("\\WR_CLK"); | ||||||
|  | 	SigSpec wr_en = cell->getPort("\\WR_EN"); | ||||||
|  | 
 | ||||||
|  | 	for (int cell_port_i = 0, bram_port_i = 0; cell_port_i < wr_ports_n; cell_port_i++) | ||||||
|  | 	{ | ||||||
|  | 		bool clken = wr_clken[cell_port_i] == State::S1; | ||||||
|  | 		auto clkpol = wr_clkpol[cell_port_i] == State::S1; | ||||||
|  | 		auto clksig = wr_clk[cell_port_i]; | ||||||
|  | 
 | ||||||
|  | 		pair<SigBit, bool> clkdom(clksig, clkpol); | ||||||
|  | 		if (!clken) | ||||||
|  | 			clkdom = pair<SigBit, bool>(State::S1, false); | ||||||
|  | 
 | ||||||
|  | 		log("    Write port #%d is in clock domain %s%s.\n", | ||||||
|  | 				cell_port_i, clkdom.second ? "" : "!", | ||||||
|  | 				clken ? log_signal(clkdom.first) : "~async~"); | ||||||
|  | 
 | ||||||
|  | 		for (; bram_port_i < GetSize(portinfos); bram_port_i++) | ||||||
|  | 		{ | ||||||
|  | 			auto &pi = portinfos[bram_port_i]; | ||||||
|  | 
 | ||||||
|  | 			if (pi.wrmode != 1) | ||||||
|  | 		skip_bram_wport: | ||||||
|  | 				continue; | ||||||
|  | 
 | ||||||
|  | 			if (clken) { | ||||||
|  | 				if (pi.clocks == 0) { | ||||||
|  | 					log("      Bram port %c%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1); | ||||||
|  | 					goto skip_bram_wport; | ||||||
|  | 				} | ||||||
|  | 				if (clock_domains.count(pi.clocks) && clock_domains.at(pi.clocks) != clkdom) { | ||||||
|  | 					log("      Bram port %c%d is in a different clock domain.\n", pi.group + 'A', pi.index + 1); | ||||||
|  | 					goto skip_bram_wport; | ||||||
|  | 				} | ||||||
|  | 			} else { | ||||||
|  | 				if (pi.clocks != 0) { | ||||||
|  | 					log("      Bram port %c%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1); | ||||||
|  | 					goto skip_bram_wport; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			SigBit last_en_bit = State::S1; | ||||||
|  | 			for (int i = 0; i < bram.dbits; i++) { | ||||||
|  | 				if (pi.enable && i % (bram.dbits / pi.enable) == 0) | ||||||
|  | 					last_en_bit = wr_en[i]; | ||||||
|  | 				if (last_en_bit != wr_en[i]) { | ||||||
|  | 					log("      Bram port %c%d has incompatible enable structure.\n", pi.group + 'A', pi.index + 1); | ||||||
|  | 					goto skip_bram_wport; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			log("      Mapped to bram port %c%d.\n", pi.group + 'A', pi.index + 1); | ||||||
|  | 			if (clken) | ||||||
|  | 				clock_domains[pi.clocks] = clkdom; | ||||||
|  | 			mapped_wr_ports.push_back(bram_port_i); | ||||||
|  | 			goto mapped_port; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		log("    Failed to map write port #%d.\n", cell_port_i); | ||||||
|  | 		return false; | ||||||
|  | 	mapped_port:; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	log("  FIXME: The core of memory_bram is not implemented yet.\n"); | 	log("  FIXME: The core of memory_bram is not implemented yet.\n"); | ||||||
|  | 	return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void handle_cell(Cell *cell, const rules_t &rules) | void handle_cell(Cell *cell, const rules_t &rules) | ||||||
|  | @ -210,8 +309,13 @@ void handle_cell(Cell *cell, const rules_t &rules) | ||||||
| 		log(" %s=%d", it.first.c_str(), it.second); | 		log(" %s=%d", it.first.c_str(), it.second); | ||||||
| 	log("\n"); | 	log("\n"); | ||||||
| 
 | 
 | ||||||
|  | 	pool<IdString> failed_brams; | ||||||
|  | 
 | ||||||
| 	for (int i = 0; i < GetSize(rules.matches); i++) | 	for (int i = 0; i < GetSize(rules.matches); i++) | ||||||
| 	{ | 	{ | ||||||
|  | 		if (rules.matches[i].name.in(failed_brams)) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
| 		for (auto it : rules.matches[i].min_limits) { | 		for (auto it : rules.matches[i].min_limits) { | ||||||
| 			if (!mem_properties.count(it.first)) | 			if (!mem_properties.count(it.first)) | ||||||
| 				log_error("Unknown property '%s' in match rule for bram type %s.\n", | 				log_error("Unknown property '%s' in match rule for bram type %s.\n", | ||||||
|  | @ -237,7 +341,11 @@ void handle_cell(Cell *cell, const rules_t &rules) | ||||||
| 		if (!rules.brams.count(rules.matches[i].name)) | 		if (!rules.brams.count(rules.matches[i].name)) | ||||||
| 			log_error("No bram description for resource %s found!\n", log_id(rules.matches[i].name)); | 			log_error("No bram description for resource %s found!\n", log_id(rules.matches[i].name)); | ||||||
| 
 | 
 | ||||||
| 		replace_cell(cell, rules.brams.at(rules.matches[i].name), rules.matches[i]); | 		if (!replace_cell(cell, rules.brams.at(rules.matches[i].name), rules.matches[i])) { | ||||||
|  | 			log("  Mapping to bram type %s failed.\n", log_id(rules.matches[i].name)); | ||||||
|  | 			failed_brams.insert(rules.matches[i].name); | ||||||
|  | 			goto next_match_rule; | ||||||
|  | 		} | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	next_match_rule:; | 	next_match_rule:; | ||||||
|  |  | ||||||
|  | @ -7,9 +7,9 @@ bram XILINX_RAMB36_SDP32 | ||||||
|   abits 10 |   abits 10 | ||||||
|   dbits 32 |   dbits 32 | ||||||
|   groups 2 |   groups 2 | ||||||
|   wports 1 0 |   ports  1 1 | ||||||
|   rports 0 1 |   wrmode 1 0 | ||||||
|   wenabl 2 0 |   enable 4 0 | ||||||
|   transp 0 2 |   transp 0 2 | ||||||
|   clocks 1 2 |   clocks 1 2 | ||||||
| endbram | endbram | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue