mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	Support subtraction as well
This commit is contained in:
		
							parent
							
								
									31e60353ac
								
							
						
					
					
						commit
						02cf9933b9
					
				
					 1 changed files with 114 additions and 103 deletions
				
			
		| 
						 | 
					@ -59,10 +59,11 @@ static Cell* addDsp(Module *module) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void pack_xilinx_simd(Module *module, const std::vector<Cell*> &selected_cells)
 | 
					void pack_xilinx_simd(Module *module, const std::vector<Cell*> &selected_cells)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	std::deque<Cell*> simd12, simd24;
 | 
						std::deque<Cell*> simd12_add, simd12_sub;
 | 
				
			||||||
 | 
						std::deque<Cell*> simd24_add, simd24_sub;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (auto cell : selected_cells) {
 | 
						for (auto cell : selected_cells) {
 | 
				
			||||||
		if (!cell->type.in("$add"))
 | 
							if (!cell->type.in("$add", "$sub"))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		SigSpec Y = cell->getPort("\\Y");
 | 
							SigSpec Y = cell->getPort("\\Y");
 | 
				
			||||||
		if (!Y.is_chunk())
 | 
							if (!Y.is_chunk())
 | 
				
			||||||
| 
						 | 
					@ -78,24 +79,26 @@ void pack_xilinx_simd(Module *module, const std::vector<Cell*> &selected_cells)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			if (GetSize(B) > 12)
 | 
								if (GetSize(B) > 12)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			simd12.push_back(cell);
 | 
								if (cell->type == "$add")
 | 
				
			||||||
 | 
									simd12_add.push_back(cell);
 | 
				
			||||||
 | 
								else if (cell->type == "$sub")
 | 
				
			||||||
 | 
									simd12_sub.push_back(cell);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else if (GetSize(Y) <= 25) {
 | 
							else if (GetSize(Y) <= 25) {
 | 
				
			||||||
			if (GetSize(A) > 24)
 | 
								if (GetSize(A) > 24)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			if (GetSize(B) > 24)
 | 
								if (GetSize(B) > 24)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			simd24.push_back(cell);
 | 
								if (cell->type == "$add")
 | 
				
			||||||
 | 
									simd24_add.push_back(cell);
 | 
				
			||||||
 | 
								else if (cell->type == "$sub")
 | 
				
			||||||
 | 
									simd24_sub.push_back(cell);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			log_abort();
 | 
								log_abort();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SigSpec AB;
 | 
						auto f12 = [module](SigSpec &AB, SigSpec &C, SigSpec &P, SigSpec &CARRYOUT, Cell *lane) {
 | 
				
			||||||
	SigSpec C;
 | 
					 | 
				
			||||||
	SigSpec P;
 | 
					 | 
				
			||||||
	SigSpec CARRYOUT;
 | 
					 | 
				
			||||||
	auto f12 = [&AB,&C,&P,&CARRYOUT,module](Cell *lane) {
 | 
					 | 
				
			||||||
		SigSpec A = lane->getPort("\\A");
 | 
							SigSpec A = lane->getPort("\\A");
 | 
				
			||||||
		SigSpec B = lane->getPort("\\B");
 | 
							SigSpec B = lane->getPort("\\B");
 | 
				
			||||||
		SigSpec Y = lane->getPort("\\Y");
 | 
							SigSpec Y = lane->getPort("\\Y");
 | 
				
			||||||
| 
						 | 
					@ -110,84 +113,86 @@ void pack_xilinx_simd(Module *module, const std::vector<Cell*> &selected_cells)
 | 
				
			||||||
		P.append(Y.extract(0, 12));
 | 
							P.append(Y.extract(0, 12));
 | 
				
			||||||
		CARRYOUT.append(Y[12]);
 | 
							CARRYOUT.append(Y[12]);
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	while (simd12.size() > 1) {
 | 
						auto g12 = [&f12,module](std::deque<Cell*> &simd12) {
 | 
				
			||||||
		AB = SigSpec();
 | 
							while (simd12.size() > 1) {
 | 
				
			||||||
		C = SigSpec();
 | 
								SigSpec AB, C, P, CARRYOUT;
 | 
				
			||||||
		P = SigSpec();
 | 
					 | 
				
			||||||
		CARRYOUT = SigSpec();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Cell *lane1 = simd12.front();
 | 
								Cell *lane1 = simd12.front();
 | 
				
			||||||
		simd12.pop_front();
 | 
					 | 
				
			||||||
		Cell *lane2 = simd12.front();
 | 
					 | 
				
			||||||
		simd12.pop_front();
 | 
					 | 
				
			||||||
		Cell *lane3 = nullptr;
 | 
					 | 
				
			||||||
		Cell *lane4 = nullptr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (!simd12.empty()) {
 | 
					 | 
				
			||||||
			lane3 = simd12.front();
 | 
					 | 
				
			||||||
			simd12.pop_front();
 | 
								simd12.pop_front();
 | 
				
			||||||
 | 
								Cell *lane2 = simd12.front();
 | 
				
			||||||
 | 
								simd12.pop_front();
 | 
				
			||||||
 | 
								Cell *lane3 = nullptr;
 | 
				
			||||||
 | 
								Cell *lane4 = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (!simd12.empty()) {
 | 
								if (!simd12.empty()) {
 | 
				
			||||||
				lane4 = simd12.front();
 | 
									lane3 = simd12.front();
 | 
				
			||||||
				simd12.pop_front();
 | 
									simd12.pop_front();
 | 
				
			||||||
 | 
									if (!simd12.empty()) {
 | 
				
			||||||
 | 
										lane4 = simd12.front();
 | 
				
			||||||
 | 
										simd12.pop_front();
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		log("Analysing %s.%s for Xilinx DSP SIMD12 packing.\n", log_id(module), log_id(lane1));
 | 
								log("Analysing %s.%s for Xilinx DSP SIMD12 packing.\n", log_id(module), log_id(lane1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Cell *cell = addDsp(module);
 | 
								Cell *cell = addDsp(module);
 | 
				
			||||||
		cell->setParam("\\USE_SIMD", Const("FOUR12"));
 | 
								cell->setParam("\\USE_SIMD", Const("FOUR12"));
 | 
				
			||||||
		// X = A:B
 | 
								// X = A:B
 | 
				
			||||||
		// Y = 0
 | 
								// Y = 0
 | 
				
			||||||
		// Z = C
 | 
								// Z = C
 | 
				
			||||||
		cell->setPort("\\OPMODE", Const::from_string("0110011"));
 | 
								cell->setPort("\\OPMODE", Const::from_string("0110011"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		log_assert(lane1);
 | 
								log_assert(lane1);
 | 
				
			||||||
		log_assert(lane2);
 | 
								log_assert(lane2);
 | 
				
			||||||
		f12(lane1);
 | 
								f12(AB, C, P, CARRYOUT, lane1);
 | 
				
			||||||
		f12(lane2);
 | 
								f12(AB, C, P, CARRYOUT, lane2);
 | 
				
			||||||
		if (lane3) {
 | 
								if (lane3) {
 | 
				
			||||||
			f12(lane3);
 | 
									f12(AB, C, P, CARRYOUT, lane3);
 | 
				
			||||||
			if (lane4)
 | 
									if (lane4)
 | 
				
			||||||
				f12(lane4);
 | 
										f12(AB, C, P, CARRYOUT, lane4);
 | 
				
			||||||
 | 
									else {
 | 
				
			||||||
 | 
										AB.append(Const(0, 12));
 | 
				
			||||||
 | 
										C.append(Const(0, 12));
 | 
				
			||||||
 | 
										P.append(module->addWire(NEW_ID, 12));
 | 
				
			||||||
 | 
										CARRYOUT.append(module->addWire(NEW_ID, 1));
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			else {
 | 
								else {
 | 
				
			||||||
				AB.append(Const(0, 12));
 | 
									AB.append(Const(0, 24));
 | 
				
			||||||
				C.append(Const(0, 12));
 | 
									C.append(Const(0, 24));
 | 
				
			||||||
				P.append(module->addWire(NEW_ID, 12));
 | 
									P.append(module->addWire(NEW_ID, 24));
 | 
				
			||||||
				CARRYOUT.append(module->addWire(NEW_ID, 1));
 | 
									CARRYOUT.append(module->addWire(NEW_ID, 2));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								log_assert(GetSize(AB) == 48);
 | 
				
			||||||
 | 
								log_assert(GetSize(C) == 48);
 | 
				
			||||||
 | 
								log_assert(GetSize(P) == 48);
 | 
				
			||||||
 | 
								log_assert(GetSize(CARRYOUT) == 4);
 | 
				
			||||||
 | 
								cell->setPort("\\A", AB.extract(18, 30));
 | 
				
			||||||
 | 
								cell->setPort("\\B", AB.extract(0, 18));
 | 
				
			||||||
 | 
								cell->setPort("\\C", C);
 | 
				
			||||||
 | 
								cell->setPort("\\P", P);
 | 
				
			||||||
 | 
								cell->setPort("\\CARRYOUT", CARRYOUT);
 | 
				
			||||||
 | 
								if (lane1->type == "$sub")
 | 
				
			||||||
 | 
									cell->setPort("\\ALUMODE", Const::from_string("0011"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								module->remove(lane1);
 | 
				
			||||||
 | 
								module->remove(lane2);
 | 
				
			||||||
 | 
								if (lane3) module->remove(lane3);
 | 
				
			||||||
 | 
								if (lane4) module->remove(lane4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								module->design->select(module, cell);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else {
 | 
						};
 | 
				
			||||||
			AB.append(Const(0, 24));
 | 
						g12(simd12_add);
 | 
				
			||||||
			C.append(Const(0, 24));
 | 
						g12(simd12_sub);
 | 
				
			||||||
			P.append(module->addWire(NEW_ID, 24));
 | 
					 | 
				
			||||||
			CARRYOUT.append(module->addWire(NEW_ID, 2));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		log_assert(GetSize(AB) == 48);
 | 
					 | 
				
			||||||
		log_assert(GetSize(C) == 48);
 | 
					 | 
				
			||||||
		log_assert(GetSize(P) == 48);
 | 
					 | 
				
			||||||
		log_assert(GetSize(CARRYOUT) == 4);
 | 
					 | 
				
			||||||
		cell->setPort("\\A", AB.extract(18, 30));
 | 
					 | 
				
			||||||
		cell->setPort("\\B", AB.extract(0, 18));
 | 
					 | 
				
			||||||
		cell->setPort("\\C", C);
 | 
					 | 
				
			||||||
		cell->setPort("\\P", P);
 | 
					 | 
				
			||||||
		cell->setPort("\\CARRYOUT", CARRYOUT);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		module->remove(lane1);
 | 
						auto f24 = [module](SigSpec &AB, SigSpec &C, SigSpec &P, SigSpec &CARRYOUT, Cell *lane) {
 | 
				
			||||||
		module->remove(lane2);
 | 
					 | 
				
			||||||
		if (lane3) module->remove(lane3);
 | 
					 | 
				
			||||||
		if (lane4) module->remove(lane4);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		module->design->select(module, cell);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	auto f24 = [&AB,&C,&P,&CARRYOUT,module](Cell *lane) {
 | 
					 | 
				
			||||||
		SigSpec A = lane->getPort("\\A");
 | 
							SigSpec A = lane->getPort("\\A");
 | 
				
			||||||
		SigSpec B = lane->getPort("\\B");
 | 
							SigSpec B = lane->getPort("\\B");
 | 
				
			||||||
		SigSpec Y = lane->getPort("\\Y");
 | 
							SigSpec Y = lane->getPort("\\Y");
 | 
				
			||||||
		A.extend_u0(24, lane->getParam("\\A_SIGNED").as_bool());
 | 
							A.extend_u0(24, lane->getParam("\\A_SIGNED").as_bool());
 | 
				
			||||||
		B.extend_u0(24, lane->getParam("\\B_SIGNED").as_bool());
 | 
							B.extend_u0(24, lane->getParam("\\B_SIGNED").as_bool());
 | 
				
			||||||
		AB.append(A);
 | 
							AB.append(B);
 | 
				
			||||||
		C.append(B);
 | 
					 | 
				
			||||||
		if (GetSize(Y) < 25)
 | 
							if (GetSize(Y) < 25)
 | 
				
			||||||
			Y.append(module->addWire(NEW_ID, 25-GetSize(Y)));
 | 
								Y.append(module->addWire(NEW_ID, 25-GetSize(Y)));
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
| 
						 | 
					@ -196,45 +201,51 @@ void pack_xilinx_simd(Module *module, const std::vector<Cell*> &selected_cells)
 | 
				
			||||||
		CARRYOUT.append(module->addWire(NEW_ID)); // TWO24 uses every other bit
 | 
							CARRYOUT.append(module->addWire(NEW_ID)); // TWO24 uses every other bit
 | 
				
			||||||
		CARRYOUT.append(Y[24]);
 | 
							CARRYOUT.append(Y[24]);
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	while (simd24.size() > 1) {
 | 
						auto g24 = [&f24,module](std::deque<Cell*> &simd24) {
 | 
				
			||||||
		AB = SigSpec();
 | 
							while (simd24.size() > 1) {
 | 
				
			||||||
		C = SigSpec();
 | 
								SigSpec AB;
 | 
				
			||||||
		P = SigSpec();
 | 
								SigSpec C;
 | 
				
			||||||
		CARRYOUT = SigSpec();
 | 
								SigSpec P;
 | 
				
			||||||
 | 
								SigSpec CARRYOUT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Cell *lane1 = simd24.front();
 | 
								Cell *lane1 = simd24.front();
 | 
				
			||||||
		simd24.pop_front();
 | 
								simd24.pop_front();
 | 
				
			||||||
		Cell *lane2 = simd24.front();
 | 
								Cell *lane2 = simd24.front();
 | 
				
			||||||
		simd24.pop_front();
 | 
								simd24.pop_front();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		log("Analysing %s.%s for Xilinx DSP SIMD24 packing.\n", log_id(module), log_id(lane1));
 | 
								log("Analysing %s.%s for Xilinx DSP SIMD24 packing.\n", log_id(module), log_id(lane1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Cell *cell = addDsp(module);
 | 
								Cell *cell = addDsp(module);
 | 
				
			||||||
		cell->setParam("\\USE_SIMD", Const("TWO24"));
 | 
								cell->setParam("\\USE_SIMD", Const("TWO24"));
 | 
				
			||||||
		// X = A:B
 | 
								// X = A:B
 | 
				
			||||||
		// Y = 0
 | 
								// Y = 0
 | 
				
			||||||
		// Z = C
 | 
								// Z = C
 | 
				
			||||||
		cell->setPort("\\OPMODE", Const::from_string("0110011"));
 | 
								cell->setPort("\\OPMODE", Const::from_string("0110011"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		log_assert(lane1);
 | 
								log_assert(lane1);
 | 
				
			||||||
		log_assert(lane2);
 | 
								log_assert(lane2);
 | 
				
			||||||
		f24(lane1);
 | 
								f24(AB, C, P, CARRYOUT, lane1);
 | 
				
			||||||
		f24(lane2);
 | 
								f24(AB, C, P, CARRYOUT, lane2);
 | 
				
			||||||
		log_assert(GetSize(AB) == 48);
 | 
								log_assert(GetSize(AB) == 48);
 | 
				
			||||||
		log_assert(GetSize(C) == 48);
 | 
								log_assert(GetSize(C) == 48);
 | 
				
			||||||
		log_assert(GetSize(P) == 48);
 | 
								log_assert(GetSize(P) == 48);
 | 
				
			||||||
		log_assert(GetSize(CARRYOUT) == 4);
 | 
								log_assert(GetSize(CARRYOUT) == 4);
 | 
				
			||||||
		cell->setPort("\\A", AB.extract(18, 30));
 | 
								cell->setPort("\\A", AB.extract(18, 30));
 | 
				
			||||||
		cell->setPort("\\B", AB.extract(0, 18));
 | 
								cell->setPort("\\B", AB.extract(0, 18));
 | 
				
			||||||
		cell->setPort("\\C", C);
 | 
								cell->setPort("\\C", C);
 | 
				
			||||||
		cell->setPort("\\P", P);
 | 
								cell->setPort("\\P", P);
 | 
				
			||||||
		cell->setPort("\\CARRYOUT", CARRYOUT);
 | 
								cell->setPort("\\CARRYOUT", CARRYOUT);
 | 
				
			||||||
 | 
								if (lane1->type == "$sub")
 | 
				
			||||||
 | 
									cell->setPort("\\ALUMODE", Const::from_string("0011"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		module->remove(lane1);
 | 
								module->remove(lane1);
 | 
				
			||||||
		module->remove(lane2);
 | 
								module->remove(lane2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		module->design->select(module, cell);
 | 
								module->design->select(module, cell);
 | 
				
			||||||
	}
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						g24(simd24_add);
 | 
				
			||||||
 | 
						g24(simd24_sub);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue