mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	verilog: Bufnorm cell backend and frontend support
This makes the Verilog backend handle the $connect and $input_port cells. This represents the undirected $connect cell using the `tran` primitive, so we also extend the frontend to support this.
This commit is contained in:
		
							parent
							
								
									4f239b536b
								
							
						
					
					
						commit
						79e05a195d
					
				
					 3 changed files with 69 additions and 9 deletions
				
			
		| 
						 | 
					@ -1099,6 +1099,33 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (cell->type.in(ID($_BUF_), ID($buf))) {
 | 
						if (cell->type.in(ID($_BUF_), ID($buf))) {
 | 
				
			||||||
 | 
							if (cell->type == ID($buf) && cell->getPort(ID::A).has_const(State::Sz)) {
 | 
				
			||||||
 | 
								RTLIL::SigSpec a = cell->getPort(ID::A);
 | 
				
			||||||
 | 
								RTLIL::SigSpec y = cell->getPort(ID::Y);
 | 
				
			||||||
 | 
								a.extend_u0(GetSize(y));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (a.has_const(State::Sz)) {
 | 
				
			||||||
 | 
									SigSpec new_a;
 | 
				
			||||||
 | 
									SigSpec new_y;
 | 
				
			||||||
 | 
									for (int i = 0; i < GetSize(a); ++i) {
 | 
				
			||||||
 | 
										SigBit b = a[i];
 | 
				
			||||||
 | 
										if (b == State::Sz)
 | 
				
			||||||
 | 
											continue;
 | 
				
			||||||
 | 
										new_a.append(b);
 | 
				
			||||||
 | 
										new_y.append(y[i]);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									a = std::move(new_a);
 | 
				
			||||||
 | 
									y = std::move(new_y);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (!y.empty()) {
 | 
				
			||||||
 | 
									f << stringf("%s" "assign ", indent);
 | 
				
			||||||
 | 
									dump_sigspec(f, y);
 | 
				
			||||||
 | 
									f << stringf(" = ");
 | 
				
			||||||
 | 
									dump_sigspec(f, a);
 | 
				
			||||||
 | 
									f << stringf(";\n");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		f << stringf("%s" "assign ", indent);
 | 
							f << stringf("%s" "assign ", indent);
 | 
				
			||||||
		dump_sigspec(f, cell->getPort(ID::Y));
 | 
							dump_sigspec(f, cell->getPort(ID::Y));
 | 
				
			||||||
		f << stringf(" = ");
 | 
							f << stringf(" = ");
 | 
				
			||||||
| 
						 | 
					@ -1498,6 +1525,29 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cell->type == ID($input_port))
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cell->type == ID($connect))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							int width = cell->getParam(ID::WIDTH).as_int() ;
 | 
				
			||||||
 | 
							if (width == 1) {
 | 
				
			||||||
 | 
								f << stringf("%s" "tran(", indent);
 | 
				
			||||||
 | 
								dump_sigspec(f, cell->getPort(ID::A));
 | 
				
			||||||
 | 
								f << stringf(", ");
 | 
				
			||||||
 | 
								dump_sigspec(f, cell->getPort(ID::B));
 | 
				
			||||||
 | 
								f << stringf(");\n");
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								auto tran_id = next_auto_id();
 | 
				
			||||||
 | 
								f << stringf("%s" "tran %s[%d:0](", indent, tran_id, width - 1);
 | 
				
			||||||
 | 
								dump_sigspec(f, cell->getPort(ID::A));
 | 
				
			||||||
 | 
								f << stringf(", ");
 | 
				
			||||||
 | 
								dump_sigspec(f, cell->getPort(ID::B));
 | 
				
			||||||
 | 
								f << stringf(");\n");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (cell->is_builtin_ff())
 | 
						if (cell->is_builtin_ff())
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		FfData ff(nullptr, cell);
 | 
							FfData ff(nullptr, cell);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2756,19 +2756,24 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
 | 
				
			||||||
		newNode = std::make_unique<AstNode>(location, AST_GENBLOCK);
 | 
							newNode = std::make_unique<AstNode>(location, AST_GENBLOCK);
 | 
				
			||||||
		int num = max(children.at(0)->range_left, children.at(0)->range_right) - min(children.at(0)->range_left, children.at(0)->range_right) + 1;
 | 
							int num = max(children.at(0)->range_left, children.at(0)->range_right) - min(children.at(0)->range_left, children.at(0)->range_right) + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (this->children.at(1)->type == AST_PRIMITIVE) {
 | 
				
			||||||
 | 
								// Move the range to the AST_PRIMITIVE node and replace this with the AST_PRIMITIVE node handled below
 | 
				
			||||||
 | 
								newNode = std::move(this->children.at(1));
 | 
				
			||||||
 | 
								newNode->range_left = this->children.at(0)->range_left;
 | 
				
			||||||
 | 
								newNode->range_right = this->children.at(0)->range_right;
 | 
				
			||||||
 | 
								newNode->range_valid = true;
 | 
				
			||||||
 | 
								goto apply_newNode;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (int i = 0; i < num; i++) {
 | 
							for (int i = 0; i < num; i++) {
 | 
				
			||||||
			int idx = children.at(0)->range_left > children.at(0)->range_right ? children.at(0)->range_right + i : children.at(0)->range_right - i;
 | 
								int idx = children.at(0)->range_left > children.at(0)->range_right ? children.at(0)->range_right + i : children.at(0)->range_right - i;
 | 
				
			||||||
			auto new_cell_owned = children.at(1)->clone();
 | 
								auto new_cell_owned = children.at(1)->clone();
 | 
				
			||||||
			auto* new_cell = new_cell_owned.get();
 | 
								auto* new_cell = new_cell_owned.get();
 | 
				
			||||||
			newNode->children.push_back(std::move(new_cell_owned));
 | 
								newNode->children.push_back(std::move(new_cell_owned));
 | 
				
			||||||
			new_cell->str += stringf("[%d]", idx);
 | 
								new_cell->str += stringf("[%d]", idx);
 | 
				
			||||||
			if (new_cell->type == AST_PRIMITIVE) {
 | 
					
 | 
				
			||||||
				input_error("Cell arrays of primitives are currently not supported.\n");
 | 
								log_assert(new_cell->children.at(0)->type == AST_CELLTYPE);
 | 
				
			||||||
			} else {
 | 
								new_cell->children.at(0)->str = stringf("$array:%d:%d:%s", i, num, new_cell->children.at(0)->str);
 | 
				
			||||||
				this->dumpAst(NULL, "    ");
 | 
					 | 
				
			||||||
				log_assert(new_cell->children.at(0)->type == AST_CELLTYPE);
 | 
					 | 
				
			||||||
				new_cell->children.at(0)->str = stringf("$array:%d:%d:%s", i, num, new_cell->children.at(0)->str);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		goto apply_newNode;
 | 
							goto apply_newNode;
 | 
				
			||||||
| 
						 | 
					@ -2789,6 +2794,11 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		children.clear();
 | 
							children.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// TODO handle bit-widths of primitives and support cell arrays for more primitives
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (range_valid && str != "tran")
 | 
				
			||||||
 | 
								input_error("Cell arrays of primitives are currently not supported.\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (str == "bufif0" || str == "bufif1" || str == "notif0" || str == "notif1")
 | 
							if (str == "bufif0" || str == "bufif1" || str == "notif0" || str == "notif1")
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (children_list.size() != 3)
 | 
								if (children_list.size() != 3)
 | 
				
			||||||
| 
						 | 
					@ -2817,7 +2827,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
 | 
				
			||||||
			fixup_hierarchy_flags();
 | 
								fixup_hierarchy_flags();
 | 
				
			||||||
			did_something = true;
 | 
								did_something = true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else if (str == "buf" || str == "not")
 | 
							else if (str == "buf" || str == "not" || str == "tran")
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			auto& input = children_list.back();
 | 
								auto& input = children_list.back();
 | 
				
			||||||
			if (str == "not")
 | 
								if (str == "not")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -493,7 +493,7 @@ TIME_SCALE_SUFFIX [munpf]?s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
\"{3}(\"{0,2}([^\\"]|\\.|\\\n))*\"{3}	{ return process_str(yytext + 3, yyleng - 6, true, out_loc); }
 | 
					\"{3}(\"{0,2}([^\\"]|\\.|\\\n))*\"{3}	{ return process_str(yytext + 3, yyleng - 6, true, out_loc); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
and|nand|or|nor|xor|xnor|not|buf|bufif0|bufif1|notif0|notif1 {
 | 
					and|nand|or|nor|xor|xnor|not|buf|bufif0|bufif1|notif0|notif1|tran {
 | 
				
			||||||
	auto val = std::make_unique<std::string>(YYText());
 | 
						auto val = std::make_unique<std::string>(YYText());
 | 
				
			||||||
	return parser::make_TOK_PRIMITIVE(std::move(val), out_loc);
 | 
						return parser::make_TOK_PRIMITIVE(std::move(val), out_loc);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue