mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-03 21:09:12 +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.
 | 
			
		||||
 | 
			
		||||
		template<typename T, typename... Args>
 | 
			
		||||
		bool in(T first, Args... rest) {
 | 
			
		||||
		bool in(T first, Args... rest) const {
 | 
			
		||||
			return in(first) || in(rest...);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		bool in(IdString rhs) { return *this == rhs; }
 | 
			
		||||
		bool in(const char *rhs) { return *this == rhs; }
 | 
			
		||||
		bool in(const std::string &rhs) { return *this == rhs; }
 | 
			
		||||
		bool in(const pool<IdString> &rhs) { return rhs.count(*this) != 0; }
 | 
			
		||||
		bool in(IdString rhs) const { return *this == rhs; }
 | 
			
		||||
		bool in(const char *rhs) const { return *this == rhs; }
 | 
			
		||||
		bool in(const std::string &rhs) const { return *this == rhs; }
 | 
			
		||||
		bool in(const pool<IdString> &rhs) const { return rhs.count(*this) != 0; }
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	static inline std::string escape_id(std::string str) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -137,6 +137,8 @@ YOSYS_NAMESPACE_BEGIN
 | 
			
		|||
 | 
			
		||||
using std::vector;
 | 
			
		||||
using std::string;
 | 
			
		||||
using std::pair;
 | 
			
		||||
 | 
			
		||||
using hashlib::mkhash;
 | 
			
		||||
using hashlib::mkhash_init;
 | 
			
		||||
using hashlib::mkhash_add;
 | 
			
		||||
| 
						 | 
				
			
			@ -221,6 +223,8 @@ YOSYS_NAMESPACE_END
 | 
			
		|||
 | 
			
		||||
YOSYS_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
using RTLIL::State;
 | 
			
		||||
 | 
			
		||||
namespace hashlib {
 | 
			
		||||
	template<> struct hash_ops<RTLIL::State> : hash_ops<int> {};
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,10 +24,33 @@ PRIVATE_NAMESPACE_BEGIN
 | 
			
		|||
 | 
			
		||||
struct rules_t
 | 
			
		||||
{
 | 
			
		||||
	struct portinfo_t {
 | 
			
		||||
		int group, index;
 | 
			
		||||
		int wrmode, enable, transp, clocks, clkpol;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	struct bram_t {
 | 
			
		||||
		IdString name;
 | 
			
		||||
		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 {
 | 
			
		||||
| 
						 | 
				
			
			@ -80,7 +103,7 @@ struct rules_t
 | 
			
		|||
		if (GetSize(tokens) >= 2 && tokens[0] == stmt) {
 | 
			
		||||
			value.resize(GetSize(tokens)-1);
 | 
			
		||||
			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 false;
 | 
			
		||||
| 
						 | 
				
			
			@ -113,13 +136,13 @@ struct rules_t
 | 
			
		|||
			if (parse_single_int("init", data.init))
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			if (parse_int_vect("wports", data.wports))
 | 
			
		||||
			if (parse_int_vect("ports", data.ports))
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			if (parse_int_vect("rports", data.rports))
 | 
			
		||||
			if (parse_int_vect("wrmode", data.wrmode))
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			if (parse_int_vect("wenabl", data.wenabl))
 | 
			
		||||
			if (parse_int_vect("enable", data.enable))
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			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");
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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("\n");
 | 
			
		||||
 | 
			
		||||
	pool<IdString> failed_brams;
 | 
			
		||||
 | 
			
		||||
	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) {
 | 
			
		||||
			if (!mem_properties.count(it.first))
 | 
			
		||||
				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))
 | 
			
		||||
			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;
 | 
			
		||||
 | 
			
		||||
	next_match_rule:;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,9 +7,9 @@ bram XILINX_RAMB36_SDP32
 | 
			
		|||
  abits 10
 | 
			
		||||
  dbits 32
 | 
			
		||||
  groups 2
 | 
			
		||||
  wports 1 0
 | 
			
		||||
  rports 0 1
 | 
			
		||||
  wenabl 2 0
 | 
			
		||||
  ports  1 1
 | 
			
		||||
  wrmode 1 0
 | 
			
		||||
  enable 4 0
 | 
			
		||||
  transp 0 2
 | 
			
		||||
  clocks 1 2
 | 
			
		||||
endbram
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue