mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	kernel/mem: Add model for wide ports.
Such ports cannot actually be created or used yet, this just adds the necessary plumbing in the helper. Subsequent commits will gradually add wide port support to various yosys passes.
This commit is contained in:
		
							parent
							
								
									95a39d3425
								
							
						
					
					
						commit
						ff9713dd86
					
				
					 2 changed files with 28 additions and 6 deletions
				
			
		| 
						 | 
					@ -121,6 +121,8 @@ void Mem::emit() {
 | 
				
			||||||
			abits = std::max(abits, GetSize(port.addr));
 | 
								abits = std::max(abits, GetSize(port.addr));
 | 
				
			||||||
		cell->parameters[ID::ABITS] = Const(abits);
 | 
							cell->parameters[ID::ABITS] = Const(abits);
 | 
				
			||||||
		for (auto &port : rd_ports) {
 | 
							for (auto &port : rd_ports) {
 | 
				
			||||||
 | 
								// TODO: remove
 | 
				
			||||||
 | 
								log_assert(port.wide_log2 == 0);
 | 
				
			||||||
			if (port.cell) {
 | 
								if (port.cell) {
 | 
				
			||||||
				module->remove(port.cell);
 | 
									module->remove(port.cell);
 | 
				
			||||||
				port.cell = nullptr;
 | 
									port.cell = nullptr;
 | 
				
			||||||
| 
						 | 
					@ -152,6 +154,8 @@ void Mem::emit() {
 | 
				
			||||||
		cell->setPort(ID::RD_ADDR, rd_addr);
 | 
							cell->setPort(ID::RD_ADDR, rd_addr);
 | 
				
			||||||
		cell->setPort(ID::RD_DATA, rd_data);
 | 
							cell->setPort(ID::RD_DATA, rd_data);
 | 
				
			||||||
		for (auto &port : wr_ports) {
 | 
							for (auto &port : wr_ports) {
 | 
				
			||||||
 | 
								// TODO: remove
 | 
				
			||||||
 | 
								log_assert(port.wide_log2 == 0);
 | 
				
			||||||
			if (port.cell) {
 | 
								if (port.cell) {
 | 
				
			||||||
				module->remove(port.cell);
 | 
									module->remove(port.cell);
 | 
				
			||||||
				port.cell = nullptr;
 | 
									port.cell = nullptr;
 | 
				
			||||||
| 
						 | 
					@ -206,7 +210,7 @@ void Mem::emit() {
 | 
				
			||||||
				port.cell = module->addCell(NEW_ID, ID($memrd));
 | 
									port.cell = module->addCell(NEW_ID, ID($memrd));
 | 
				
			||||||
			port.cell->parameters[ID::MEMID] = memid.str();
 | 
								port.cell->parameters[ID::MEMID] = memid.str();
 | 
				
			||||||
			port.cell->parameters[ID::ABITS] = GetSize(port.addr);
 | 
								port.cell->parameters[ID::ABITS] = GetSize(port.addr);
 | 
				
			||||||
			port.cell->parameters[ID::WIDTH] = width;
 | 
								port.cell->parameters[ID::WIDTH] = width << port.wide_log2;
 | 
				
			||||||
			port.cell->parameters[ID::CLK_ENABLE] = port.clk_enable;
 | 
								port.cell->parameters[ID::CLK_ENABLE] = port.clk_enable;
 | 
				
			||||||
			port.cell->parameters[ID::CLK_POLARITY] = port.clk_polarity;
 | 
								port.cell->parameters[ID::CLK_POLARITY] = port.clk_polarity;
 | 
				
			||||||
			port.cell->parameters[ID::TRANSPARENT] = port.transparent;
 | 
								port.cell->parameters[ID::TRANSPARENT] = port.transparent;
 | 
				
			||||||
| 
						 | 
					@ -221,7 +225,7 @@ void Mem::emit() {
 | 
				
			||||||
				port.cell = module->addCell(NEW_ID, ID($memwr));
 | 
									port.cell = module->addCell(NEW_ID, ID($memwr));
 | 
				
			||||||
			port.cell->parameters[ID::MEMID] = memid.str();
 | 
								port.cell->parameters[ID::MEMID] = memid.str();
 | 
				
			||||||
			port.cell->parameters[ID::ABITS] = GetSize(port.addr);
 | 
								port.cell->parameters[ID::ABITS] = GetSize(port.addr);
 | 
				
			||||||
			port.cell->parameters[ID::WIDTH] = width;
 | 
								port.cell->parameters[ID::WIDTH] = width << port.wide_log2;
 | 
				
			||||||
			port.cell->parameters[ID::CLK_ENABLE] = port.clk_enable;
 | 
								port.cell->parameters[ID::CLK_ENABLE] = port.clk_enable;
 | 
				
			||||||
			port.cell->parameters[ID::CLK_POLARITY] = port.clk_polarity;
 | 
								port.cell->parameters[ID::CLK_POLARITY] = port.clk_polarity;
 | 
				
			||||||
			port.cell->parameters[ID::PRIORITY] = idx++;
 | 
								port.cell->parameters[ID::PRIORITY] = idx++;
 | 
				
			||||||
| 
						 | 
					@ -264,23 +268,32 @@ Const Mem::get_init_data() const {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Mem::check() {
 | 
					void Mem::check() {
 | 
				
			||||||
 | 
						int max_wide_log2 = 0;
 | 
				
			||||||
	for (auto &port : rd_ports) {
 | 
						for (auto &port : rd_ports) {
 | 
				
			||||||
		if (port.removed)
 | 
							if (port.removed)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		log_assert(GetSize(port.clk) == 1);
 | 
							log_assert(GetSize(port.clk) == 1);
 | 
				
			||||||
		log_assert(GetSize(port.en) == 1);
 | 
							log_assert(GetSize(port.en) == 1);
 | 
				
			||||||
		log_assert(GetSize(port.data) == width);
 | 
							log_assert(GetSize(port.data) == (width << port.wide_log2));
 | 
				
			||||||
		if (!port.clk_enable) {
 | 
							if (!port.clk_enable) {
 | 
				
			||||||
			log_assert(!port.transparent);
 | 
								log_assert(!port.transparent);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							for (int j = 0; j < port.wide_log2; j++) {
 | 
				
			||||||
 | 
								log_assert(port.addr[j] == State::S0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							max_wide_log2 = std::max(max_wide_log2, port.wide_log2);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for (int i = 0; i < GetSize(wr_ports); i++) {
 | 
						for (int i = 0; i < GetSize(wr_ports); i++) {
 | 
				
			||||||
		auto &port = wr_ports[i];
 | 
							auto &port = wr_ports[i];
 | 
				
			||||||
		if (port.removed)
 | 
							if (port.removed)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		log_assert(GetSize(port.clk) == 1);
 | 
							log_assert(GetSize(port.clk) == 1);
 | 
				
			||||||
		log_assert(GetSize(port.en) == width);
 | 
							log_assert(GetSize(port.en) == (width << port.wide_log2));
 | 
				
			||||||
		log_assert(GetSize(port.data) == width);
 | 
							log_assert(GetSize(port.data) == (width << port.wide_log2));
 | 
				
			||||||
 | 
							for (int j = 0; j < port.wide_log2; j++) {
 | 
				
			||||||
 | 
								log_assert(port.addr[j] == State::S0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							max_wide_log2 = std::max(max_wide_log2, port.wide_log2);
 | 
				
			||||||
		log_assert(GetSize(port.priority_mask) == GetSize(wr_ports));
 | 
							log_assert(GetSize(port.priority_mask) == GetSize(wr_ports));
 | 
				
			||||||
		for (int j = 0; j < GetSize(wr_ports); j++) {
 | 
							for (int j = 0; j < GetSize(wr_ports); j++) {
 | 
				
			||||||
			auto &wport = wr_ports[j];
 | 
								auto &wport = wr_ports[j];
 | 
				
			||||||
| 
						 | 
					@ -294,6 +307,9 @@ void Mem::check() {
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						int mask = (1 << max_wide_log2) - 1;
 | 
				
			||||||
 | 
						log_assert(!(start_offset & mask));
 | 
				
			||||||
 | 
						log_assert(!(size & mask));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace {
 | 
					namespace {
 | 
				
			||||||
| 
						 | 
					@ -331,6 +347,7 @@ namespace {
 | 
				
			||||||
				mrd.en = cell->getPort(ID::EN);
 | 
									mrd.en = cell->getPort(ID::EN);
 | 
				
			||||||
				mrd.addr = cell->getPort(ID::ADDR);
 | 
									mrd.addr = cell->getPort(ID::ADDR);
 | 
				
			||||||
				mrd.data = cell->getPort(ID::DATA);
 | 
									mrd.data = cell->getPort(ID::DATA);
 | 
				
			||||||
 | 
									mrd.wide_log2 = ceil_log2(GetSize(mrd.data) / mem->width);
 | 
				
			||||||
				res.rd_ports.push_back(mrd);
 | 
									res.rd_ports.push_back(mrd);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -346,6 +363,7 @@ namespace {
 | 
				
			||||||
				mwr.en = cell->getPort(ID::EN);
 | 
									mwr.en = cell->getPort(ID::EN);
 | 
				
			||||||
				mwr.addr = cell->getPort(ID::ADDR);
 | 
									mwr.addr = cell->getPort(ID::ADDR);
 | 
				
			||||||
				mwr.data = cell->getPort(ID::DATA);
 | 
									mwr.data = cell->getPort(ID::DATA);
 | 
				
			||||||
 | 
									mwr.wide_log2 = ceil_log2(GetSize(mwr.data) / mem->width);
 | 
				
			||||||
				ports.push_back(std::make_pair(cell->parameters.at(ID::PRIORITY).as_int(), mwr));
 | 
									ports.push_back(std::make_pair(cell->parameters.at(ID::PRIORITY).as_int(), mwr));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			std::sort(ports.begin(), ports.end(), [](const std::pair<int, MemWr> &a, const std::pair<int, MemWr> &b) { return a.first < b.first; });
 | 
								std::sort(ports.begin(), ports.end(), [](const std::pair<int, MemWr> &a, const std::pair<int, MemWr> &b) { return a.first < b.first; });
 | 
				
			||||||
| 
						 | 
					@ -424,6 +442,7 @@ namespace {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		for (int i = 0; i < cell->parameters.at(ID::RD_PORTS).as_int(); i++) {
 | 
							for (int i = 0; i < cell->parameters.at(ID::RD_PORTS).as_int(); i++) {
 | 
				
			||||||
			MemRd mrd;
 | 
								MemRd mrd;
 | 
				
			||||||
 | 
								mrd.wide_log2 = 0;
 | 
				
			||||||
			mrd.clk_enable = cell->parameters.at(ID::RD_CLK_ENABLE).extract(i, 1).as_bool();
 | 
								mrd.clk_enable = cell->parameters.at(ID::RD_CLK_ENABLE).extract(i, 1).as_bool();
 | 
				
			||||||
			mrd.clk_polarity = cell->parameters.at(ID::RD_CLK_POLARITY).extract(i, 1).as_bool();
 | 
								mrd.clk_polarity = cell->parameters.at(ID::RD_CLK_POLARITY).extract(i, 1).as_bool();
 | 
				
			||||||
			mrd.transparent = cell->parameters.at(ID::RD_TRANSPARENT).extract(i, 1).as_bool();
 | 
								mrd.transparent = cell->parameters.at(ID::RD_TRANSPARENT).extract(i, 1).as_bool();
 | 
				
			||||||
| 
						 | 
					@ -435,6 +454,7 @@ namespace {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		for (int i = 0; i < cell->parameters.at(ID::WR_PORTS).as_int(); i++) {
 | 
							for (int i = 0; i < cell->parameters.at(ID::WR_PORTS).as_int(); i++) {
 | 
				
			||||||
			MemWr mwr;
 | 
								MemWr mwr;
 | 
				
			||||||
 | 
								mwr.wide_log2 = 0;
 | 
				
			||||||
			mwr.clk_enable = cell->parameters.at(ID::WR_CLK_ENABLE).extract(i, 1).as_bool();
 | 
								mwr.clk_enable = cell->parameters.at(ID::WR_CLK_ENABLE).extract(i, 1).as_bool();
 | 
				
			||||||
			mwr.clk_polarity = cell->parameters.at(ID::WR_CLK_POLARITY).extract(i, 1).as_bool();
 | 
								mwr.clk_polarity = cell->parameters.at(ID::WR_CLK_POLARITY).extract(i, 1).as_bool();
 | 
				
			||||||
			mwr.clk = cell->getPort(ID::WR_CLK).extract(i, 1);
 | 
								mwr.clk = cell->getPort(ID::WR_CLK).extract(i, 1);
 | 
				
			||||||
| 
						 | 
					@ -507,7 +527,7 @@ Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		SigSpec sig_d = module->addWire(stringf("%s$rdreg[%d]$d", memid.c_str(), idx), width);
 | 
							SigSpec sig_d = module->addWire(stringf("%s$rdreg[%d]$d", memid.c_str(), idx), GetSize(port.data));
 | 
				
			||||||
		SigSpec sig_q = port.data;
 | 
							SigSpec sig_q = port.data;
 | 
				
			||||||
		port.data = sig_d;
 | 
							port.data = sig_d;
 | 
				
			||||||
		c = module->addDffe(stringf("%s$rdreg[%d]", memid.c_str(), idx), port.clk, port.en, sig_d, sig_q, port.clk_polarity, true);
 | 
							c = module->addDffe(stringf("%s$rdreg[%d]", memid.c_str(), idx), port.clk, port.en, sig_d, sig_q, port.clk_polarity, true);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,6 +29,7 @@ struct MemRd {
 | 
				
			||||||
	bool removed;
 | 
						bool removed;
 | 
				
			||||||
	dict<IdString, Const> attributes;
 | 
						dict<IdString, Const> attributes;
 | 
				
			||||||
	Cell *cell;
 | 
						Cell *cell;
 | 
				
			||||||
 | 
						int wide_log2;
 | 
				
			||||||
	bool clk_enable, clk_polarity;
 | 
						bool clk_enable, clk_polarity;
 | 
				
			||||||
	bool transparent;
 | 
						bool transparent;
 | 
				
			||||||
	SigSpec clk, en, addr, data;
 | 
						SigSpec clk, en, addr, data;
 | 
				
			||||||
| 
						 | 
					@ -39,6 +40,7 @@ struct MemWr {
 | 
				
			||||||
	bool removed;
 | 
						bool removed;
 | 
				
			||||||
	dict<IdString, Const> attributes;
 | 
						dict<IdString, Const> attributes;
 | 
				
			||||||
	Cell *cell;
 | 
						Cell *cell;
 | 
				
			||||||
 | 
						int wide_log2;
 | 
				
			||||||
	bool clk_enable, clk_polarity;
 | 
						bool clk_enable, clk_polarity;
 | 
				
			||||||
	std::vector<bool> priority_mask;
 | 
						std::vector<bool> priority_mask;
 | 
				
			||||||
	SigSpec clk, en, addr, data;
 | 
						SigSpec clk, en, addr, data;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue