diff options
43 files changed, 2108 insertions, 1053 deletions
@@ -364,16 +364,16 @@ Verilog Attributes and non-standard features    it as the external-facing pin of an I/O pad, and prevents ``iopadmap``    from inserting another pad cell on it. -- The module attribute ``abc_box_id`` specifies a positive integer linking a +- The module attribute ``abc9_box_id`` specifies a positive integer linking a    blackbox or whitebox definition to a corresponding entry in a `abc9`    box-file. -- The port attribute ``abc_carry`` marks the carry-in (if an input port) and +- The port attribute ``abc9_carry`` marks the carry-in (if an input port) and    carry-out (if output port) ports of a box. This information is necessary for    `abc9` to preserve the integrity of carry-chains. Specifying this attribute    onto a bus port will affect only its most significant bit. -- The port attribute ``abc_arrival`` specifies an integer (for output ports +- The port attribute ``abc9_arrival`` specifies an integer (for output ports    only) to be used as the arrival time of this sequential port. It can be used,    for example, to specify the clk-to-Q delay of a flip-flop for consideration    during techmapping. diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 46890b071..627133314 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -153,11 +153,6 @@ struct XAigerWriter  			if (wire->port_input)  				sigmap.add(wire); -		// promote output wires -		for (auto wire : module->wires()) -			if (wire->port_output) -				sigmap.add(wire); -  		for (auto wire : module->wires())  		{  			bool keep = wire->attributes.count("\\keep"); @@ -173,7 +168,7 @@ struct XAigerWriter  				}  				if (keep) -					keep_bits.insert(bit); +					keep_bits.insert(wirebit);  				if (wire->port_input || keep) {  					if (bit != wirebit) @@ -824,7 +819,7 @@ struct XAigerBackend : public Backend {  		log("        write ASCII version of AIGER format\n");  		log("\n");  		log("    -map <filename>\n"); -		log("        write an extra file with port and latch symbols\n"); +		log("        write an extra file with port and box symbols\n");  		log("\n");  		log("    -vmap <filename>\n");  		log("        like -map, but more verbose\n"); diff --git a/frontends/ilang/ilang_parser.y b/frontends/ilang/ilang_parser.y index b4b9693da..4e0b62edd 100644 --- a/frontends/ilang/ilang_parser.y +++ b/frontends/ilang/ilang_parser.y @@ -430,10 +430,14 @@ sigspec:  		free($1);  	} |  	sigspec '[' TOK_INT ']' { +		if ($3 >= $1->size() || $3 < 0) +			rtlil_frontend_ilang_yyerror("bit index out of range");  		$$ = new RTLIL::SigSpec($1->extract($3));  		delete $1;  	} |  	sigspec '[' TOK_INT ':' TOK_INT ']' { +		if ($3 >= $1->size() || $3 < 0 || $3 < $5) +			rtlil_frontend_ilang_yyerror("invalid slice");  		$$ = new RTLIL::SigSpec($1->extract($5, $3 - $5 + 1));  		delete $1;  	} | diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index daea3b43a..a30935e0a 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -2242,7 +2242,7 @@ gen_stmt:  		ast_stack.back()->children.push_back(node);  		ast_stack.push_back(node);  	} opt_arg_list ';'{ -		ast_stack.pop_back();		 +		ast_stack.pop_back();  	};  gen_stmt_block: @@ -2413,19 +2413,19 @@ basic_expr:  		append_attr($$, $2);  	} |  	basic_expr OP_SHL attr basic_expr { -		$$ = new AstNode(AST_SHIFT_LEFT, $1, $4); +		$$ = new AstNode(AST_SHIFT_LEFT, $1, new AstNode(AST_TO_UNSIGNED, $4));  		append_attr($$, $3);  	} |  	basic_expr OP_SHR attr basic_expr { -		$$ = new AstNode(AST_SHIFT_RIGHT, $1, $4); +		$$ = new AstNode(AST_SHIFT_RIGHT, $1, new AstNode(AST_TO_UNSIGNED, $4));  		append_attr($$, $3);  	} |  	basic_expr OP_SSHL attr basic_expr { -		$$ = new AstNode(AST_SHIFT_SLEFT, $1, $4); +		$$ = new AstNode(AST_SHIFT_SLEFT, $1, new AstNode(AST_TO_UNSIGNED, $4));  		append_attr($$, $3);  	} |  	basic_expr OP_SSHR attr basic_expr { -		$$ = new AstNode(AST_SHIFT_SRIGHT, $1, $4); +		$$ = new AstNode(AST_SHIFT_SRIGHT, $1, new AstNode(AST_TO_UNSIGNED, $4));  		append_attr($$, $3);  	} |  	basic_expr '<' attr basic_expr { diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index bd2fd91a3..7c73f94c8 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -783,6 +783,14 @@ namespace {  			return v;  		} +		int param_bool(RTLIL::IdString name, bool expected) +		{ +			int v = param_bool(name); +			if (v != expected) +				error(__LINE__); +			return v; +		} +  		void param_bits(RTLIL::IdString name, int width)  		{  			param(name); @@ -869,13 +877,23 @@ namespace {  				return;  			} -			if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx))) { +			if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr))) { +				param_bool(ID(A_SIGNED)); +				param_bool(ID(B_SIGNED), /*expected=*/false); +				port(ID::A, param(ID(A_WIDTH))); +				port(ID::B, param(ID(B_WIDTH))); +				port(ID::Y, param(ID(Y_WIDTH))); +				check_expected(/*check_matched_sign=*/false); +				return; +			} + +			if (cell->type.in(ID($shift), ID($shiftx))) {  				param_bool(ID(A_SIGNED));  				param_bool(ID(B_SIGNED));  				port(ID::A, param(ID(A_WIDTH)));  				port(ID::B, param(ID(B_WIDTH)));  				port(ID::Y, param(ID(Y_WIDTH))); -				check_expected(false); +				check_expected(/*check_matched_sign=*/false);  				return;  			} @@ -957,7 +975,7 @@ namespace {  				port(ID::A, param(ID(A_WIDTH)));  				port(ID::B, param(ID(B_WIDTH)));  				port(ID::Y, param(ID(Y_WIDTH))); -				check_expected(false); +				check_expected(/*check_matched_sign=*/false);  				return;  			} diff --git a/manual/CHAPTER_CellLib.tex b/manual/CHAPTER_CellLib.tex index 0106059b6..00a88cc82 100644 --- a/manual/CHAPTER_CellLib.tex +++ b/manual/CHAPTER_CellLib.tex @@ -65,6 +65,11 @@ Verilog & Cell Type \\  \label{tab:CellLib_unary}  \end{table} +For the unary cells that output a logical value ({\tt \$reduce\_and}, {\tt \$reduce\_or}, +{\tt \$reduce\_xor}, {\tt \$reduce\_xnor}, {\tt \$reduce\_bool}, {\tt \$logic\_not}), +when the \B{Y\_WIDTH} parameter is greater than 1, the output is zero-extended, +and only the least significant bit varies. +  Note that {\tt \$reduce\_or} and {\tt \$reduce\_bool} actually represent the same  logic function. But the HDL frontends generate them in different situations. A  {\tt \$reduce\_or} cell is generated when the prefix {\tt |} operator is being used. A @@ -97,41 +102,6 @@ The width of the output port \B{Y}.  Table~\ref{tab:CellLib_binary} lists all cells for binary RTL operators. -\subsection{Multiplexers} - -Multiplexers are generated by the Verilog HDL frontend for {\tt -?:}-expressions. Multiplexers are also generated by the {\tt proc} pass to map the decision trees -from RTLIL::Process objects to logic. - -The simplest multiplexer cell type is {\tt \$mux}. Cells of this type have a \B{WIDTH} parameter -and data inputs \B{A} and \B{B} and a data output \B{Y}, all of the specified width. This cell also -has a single bit control input \B{S}. If \B{S} is 0 the value from the \B{A} input is sent to -the output, if it is 1 the value from the \B{B} input is sent to the output. So the {\tt \$mux} -cell implements the function \lstinline[language=Verilog]; Y = S ? B : A;. - -The {\tt \$pmux} cell is used to multiplex between many inputs using a one-hot select signal. Cells -of this type have a \B{WIDTH} and a \B{S\_WIDTH} parameter and inputs \B{A}, \B{B}, and \B{S} and -an output \B{Y}. The \B{S} input is \B{S\_WIDTH} bits wide. The \B{A} input and the output are both -\B{WIDTH} bits wide and the \B{B} input is \B{WIDTH}*\B{S\_WIDTH} bits wide. When all bits of -\B{S} are zero, the value from \B{A} input is sent to the output. If the $n$'th bit from \B{S} is -set, the value $n$'th \B{WIDTH} bits wide slice of the \B{B} input is sent to the output. When more -than one bit from \B{S} is set the output is undefined. Cells of this type are used to model -``parallel cases'' (defined by using the {\tt parallel\_case} attribute or detected by -an optimization). - -The {\tt \$tribuf} cell is used to implement tristate logic. Cells of this type have a \B{WIDTH} -parameter and inputs \B{A} and \B{EN} and an output \B{Y}. The \B{A} input and \B{Y} output are -\B{WIDTH} bits wide, and the \B{EN} input is one bit wide. When \B{EN} is 0, the output \B{Y} -is not driven. When \B{EN} is 1, the value from \B{A} input is sent to the \B{Y} output. Therefore, -the {\tt \$tribuf} cell implements the function \lstinline[language=Verilog]; Y = EN ? A : 'bz;. - -Behavioural code with cascaded {\tt if-then-else}- and {\tt case}-statements -usually results in trees of multiplexer cells. Many passes (from various -optimizations to FSM extraction) heavily depend on these multiplexer trees to -understand dependencies between signals. Therefore optimizations should not -break these multiplexer trees (e.g.~by replacing a multiplexer between a -calculated signal and a constant zero with an {\tt \$and} gate). -  \begin{table}[t!]  \hfil  \begin{tabular}[t]{ll} @@ -175,6 +145,57 @@ Verilog & Cell Type \\  \label{tab:CellLib_binary}  \end{table} +The {\tt \$shl} and {\tt \$shr} cells implement logical shifts, whereas the {\tt \$sshl} and +{\tt \$sshr} cells implement arithmetic shifts. The {\tt \$shl} and {\tt \$sshl} cells implement +the same operation. All four of these cells interpret the second operand as unsigned, and require +\B{B\_SIGNED} to be zero. + +Two additional shift operator cells are available that do not directly correspond to any operator +in Verilog, {\tt \$shift} and {\tt \$shiftx}. The {\tt \$shift} cell performs a right logical shift +if the second operand is positive (or unsigned), and a left logical shift if it is negative. +The {\tt \$shiftx} cell performs the same operation as the {\tt \$shift} cell, but the vacated bit +positions are filled with undef (x) bits, and corresponds to the Verilog indexed part-select expression. + +For the binary cells that output a logical value ({\tt \$logic\_and}, {\tt \$logic\_or}, +{\tt \$eqx}, {\tt \$nex}, {\tt \$lt}, {\tt \$le}, {\tt \$eq}, {\tt \$ne}, {\tt \$ge}, +{\tt \$gt}), when the \B{Y\_WIDTH} parameter is greater than 1, the output is zero-extended, +and only the least significant bit varies. + +\subsection{Multiplexers} + +Multiplexers are generated by the Verilog HDL frontend for {\tt +?:}-expressions. Multiplexers are also generated by the {\tt proc} pass to map the decision trees +from RTLIL::Process objects to logic. + +The simplest multiplexer cell type is {\tt \$mux}. Cells of this type have a \B{WIDTH} parameter +and data inputs \B{A} and \B{B} and a data output \B{Y}, all of the specified width. This cell also +has a single bit control input \B{S}. If \B{S} is 0 the value from the \B{A} input is sent to +the output, if it is 1 the value from the \B{B} input is sent to the output. So the {\tt \$mux} +cell implements the function \lstinline[language=Verilog]; Y = S ? B : A;. + +The {\tt \$pmux} cell is used to multiplex between many inputs using a one-hot select signal. Cells +of this type have a \B{WIDTH} and a \B{S\_WIDTH} parameter and inputs \B{A}, \B{B}, and \B{S} and +an output \B{Y}. The \B{S} input is \B{S\_WIDTH} bits wide. The \B{A} input and the output are both +\B{WIDTH} bits wide and the \B{B} input is \B{WIDTH}*\B{S\_WIDTH} bits wide. When all bits of +\B{S} are zero, the value from \B{A} input is sent to the output. If the $n$'th bit from \B{S} is +set, the value $n$'th \B{WIDTH} bits wide slice of the \B{B} input is sent to the output. When more +than one bit from \B{S} is set the output is undefined. Cells of this type are used to model +``parallel cases'' (defined by using the {\tt parallel\_case} attribute or detected by +an optimization). + +The {\tt \$tribuf} cell is used to implement tristate logic. Cells of this type have a \B{WIDTH} +parameter and inputs \B{A} and \B{EN} and an output \B{Y}. The \B{A} input and \B{Y} output are +\B{WIDTH} bits wide, and the \B{EN} input is one bit wide. When \B{EN} is 0, the output \B{Y} +is not driven. When \B{EN} is 1, the value from \B{A} input is sent to the \B{Y} output. Therefore, +the {\tt \$tribuf} cell implements the function \lstinline[language=Verilog]; Y = EN ? A : 'bz;. + +Behavioural code with cascaded {\tt if-then-else}- and {\tt case}-statements +usually results in trees of multiplexer cells. Many passes (from various +optimizations to FSM extraction) heavily depend on these multiplexer trees to +understand dependencies between signals. Therefore optimizations should not +break these multiplexer trees (e.g.~by replacing a multiplexer between a +calculated signal and a constant zero with an {\tt \$and} gate). +  \subsection{Registers}  D-Type Flip-Flops are represented by {\tt \$dff} cells. These cells have a clock port \B{CLK}, diff --git a/passes/memory/memory_collect.cc b/passes/memory/memory_collect.cc index 6acbce62f..9dcb3f024 100644 --- a/passes/memory/memory_collect.cc +++ b/passes/memory/memory_collect.cc @@ -218,6 +218,10 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory)  	mem->setPort("\\RD_DATA", sig_rd_data);  	mem->setPort("\\RD_EN", sig_rd_en); +	// Copy attributes from RTLIL memory to $mem +	for (auto attr : memory->attributes) +		mem->attributes[attr.first] = attr.second; +  	for (auto c : memcells)  		module->remove(c); diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc index 2c456705c..f59f978a6 100644 --- a/passes/opt/opt_share.cc +++ b/passes/opt/opt_share.cc @@ -83,7 +83,9 @@ struct ExtSigSpec {  	bool operator==(const ExtSigSpec &other) const { return is_signed == other.is_signed && sign == other.sign && sig == other.sig && semantics == other.semantics; }  }; -#define BITWISE_OPS ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_), ID($and), ID($or), ID($xor), ID($xnor) +#define FINE_BITWISE_OPS ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_) + +#define BITWISE_OPS FINE_BITWISE_OPS, ID($and), ID($or), ID($xor), ID($xnor)  #define REDUCTION_OPS ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool), ID($reduce_nand) @@ -250,14 +252,19 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector<  		shared_op->setPort(ID(CO), alu_co.extract(0, conn_width));  	} -	shared_op->setParam(ID(Y_WIDTH), conn_width); +	bool is_fine = shared_op->type.in(FINE_BITWISE_OPS); + +	if (!is_fine) +		shared_op->setParam(ID(Y_WIDTH), conn_width);  	if (decode_port(shared_op, ID::A, &assign_map) == operand) {  		shared_op->setPort(ID::B, mux_to_oper); -		shared_op->setParam(ID(B_WIDTH), max_width); +		if (!is_fine) +			shared_op->setParam(ID(B_WIDTH), max_width);  	} else {  		shared_op->setPort(ID::A, mux_to_oper); -		shared_op->setParam(ID(A_WIDTH), max_width); +		if (!is_fine) +			shared_op->setParam(ID(A_WIDTH), max_width);  	}  } diff --git a/passes/pmgen/ice40_wrapcarry.cc b/passes/pmgen/ice40_wrapcarry.cc index 69ef3cd82..6e154147f 100644 --- a/passes/pmgen/ice40_wrapcarry.cc +++ b/passes/pmgen/ice40_wrapcarry.cc @@ -50,6 +50,14 @@ void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm)  	cell->setPort("\\O", st.lut->getPort("\\O"));  	cell->setParam("\\LUT", st.lut->getParam("\\LUT_INIT")); +	for (const auto &a : st.carry->attributes) +		cell->attributes[stringf("\\SB_CARRY.%s", a.first.c_str())] = a.second; +	for (const auto &a : st.lut->attributes) +		cell->attributes[stringf("\\SB_LUT4.%s", a.first.c_str())] = a.second; +	cell->attributes[ID(SB_LUT4.name)] = Const(st.lut->name.str()); +	if (st.carry->get_bool_attribute(ID::keep) || st.lut->get_bool_attribute(ID::keep)) +		cell->attributes[ID::keep] = true; +  	pm.autoremove(st.carry);  	pm.autoremove(st.lut);  } @@ -62,28 +70,79 @@ struct Ice40WrapCarryPass : public Pass {  		log("\n");  		log("    ice40_wrapcarry [selection]\n");  		log("\n"); -		log("Wrap manually instantiated SB_CARRY cells, along with their associated SB_LUTs,\n"); +		log("Wrap manually instantiated SB_CARRY cells, along with their associated SB_LUT4s,\n");  		log("into an internal $__ICE40_CARRY_WRAPPER cell for preservation across technology\n"); -		log("mapping."); +		log("mapping.\n"); +		log("\n"); +		log("Attributes on both cells will have their names prefixed with 'SB_CARRY.' or\n"); +		log("'SB_LUT4.' and attached to the wrapping cell.\n"); +		log("A (* keep *) attribute on either cell will be logically OR-ed together.\n"); +		log("\n"); +		log("    -unwrap\n"); +		log("        unwrap $__ICE40_CARRY_WRAPPER cells back into SB_CARRYs and SB_LUT4s,\n"); +		log("        including restoring their attributes.\n");  		log("\n");  	}  	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE  	{ +		bool unwrap = false; +  		log_header(design, "Executing ICE40_WRAPCARRY pass (wrap carries).\n");  		size_t argidx;  		for (argidx = 1; argidx < args.size(); argidx++)  		{ -			// if (args[argidx] == "-singleton") { -			// 	singleton_mode = true; -			// 	continue; -			// } +			if (args[argidx] == "-unwrap") { +				unwrap = true; +				continue; +			}  			break;  		}  		extra_args(args, argidx, design); -		for (auto module : design->selected_modules()) -			ice40_wrapcarry_pm(module, module->selected_cells()).run_ice40_wrapcarry(create_ice40_wrapcarry); +		for (auto module : design->selected_modules()) { +			if (!unwrap) +				ice40_wrapcarry_pm(module, module->selected_cells()).run_ice40_wrapcarry(create_ice40_wrapcarry); +			else { +				for (auto cell : module->selected_cells()) { +					if (cell->type != ID($__ICE40_CARRY_WRAPPER)) +						continue; + +					auto carry = module->addCell(NEW_ID, ID(SB_CARRY)); +					carry->setPort(ID(I0), cell->getPort(ID(A))); +					carry->setPort(ID(I1), cell->getPort(ID(B))); +					carry->setPort(ID(CI), cell->getPort(ID(CI))); +					carry->setPort(ID(CO), cell->getPort(ID(CO))); +					module->swap_names(carry, cell); +					auto lut_name = cell->attributes.at(ID(SB_LUT4.name), Const(NEW_ID.str())).decode_string(); +					auto lut = module->addCell(lut_name, ID($lut)); +					lut->setParam(ID(WIDTH), 4); +					lut->setParam(ID(LUT), cell->getParam(ID(LUT))); +					lut->setPort(ID(A), {cell->getPort(ID(I0)), cell->getPort(ID(A)), cell->getPort(ID(B)), cell->getPort(ID(I3)) }); +					lut->setPort(ID(Y), cell->getPort(ID(O))); + +					Const src; +					for (const auto &a : cell->attributes) +						if (a.first.begins_with("\\SB_CARRY.\\")) +							carry->attributes[a.first.c_str() + strlen("\\SB_CARRY.")] = a.second; +						else if (a.first.begins_with("\\SB_LUT4.\\")) +							lut->attributes[a.first.c_str() + strlen("\\SB_LUT4.")] = a.second; +						else if (a.first == ID(src)) +							src = a.second; +						else if (a.first.in(ID(SB_LUT4.name), ID::keep, ID(module_not_derived))) +							continue; +						else +							log_abort(); + +					if (!src.empty()) { +						carry->attributes.insert(std::make_pair(ID(src), src)); +						lut->attributes.insert(std::make_pair(ID(src), src)); +					} + +					module->remove(cell); +				} +			} +		}  	}  } Ice40WrapCarryPass; diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 0ba529011..5d3b9c2eb 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -347,9 +347,9 @@ match postAdd  	index <SigBit> port(postAdd, AB)[0] === sigP[0]  	filter GetSize(port(postAdd, AB)) >= GetSize(sigP)  	filter port(postAdd, AB).extract(0, GetSize(sigP)) == sigP -	// Check that remainder of AB is a sign-extension -	define <bool> AB_SIGNED (param(postAdd, AB == \A ? \A_SIGNED : \B_SIGNED).as_bool()) -	filter port(postAdd, AB).extract_end(GetSize(sigP)) == SigSpec(AB_SIGNED ? sigP[GetSize(sigP)-1] : State::S0, GetSize(port(postAdd, AB))-GetSize(sigP)) +	// Check that remainder of AB is a sign- or zero-extension +	filter port(postAdd, AB).extract_end(GetSize(sigP)) == SigSpec(sigP[GetSize(sigP)-1], GetSize(port(postAdd, AB))-GetSize(sigP)) || port(postAdd, AB).extract_end(GetSize(sigP)) == SigSpec(State::S0, GetSize(port(postAdd, AB))-GetSize(sigP)) +  	set postAddAB AB  	optional  endmatch diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 27106cc5d..8276c3c16 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -94,20 +94,30 @@ void handle_loops(RTLIL::Design *design)  					if (cell->output(c.first)) {  						SigBit b = c.second.as_bit();  						Wire *w = b.wire; -						log_assert(!w->port_input); -						w->port_input = true; -						w = module->wire(stringf("%s.abci", w->name.c_str())); -						if (!w) { -							w = module->addWire(stringf("%s.abci", b.wire->name.c_str()), GetSize(b.wire)); -							w->port_output = true; +						if (w->port_input) { +							// In this case, hopefully the loop break has been already created +							// Get the non-prefixed wire +							Wire *wo = module->wire(stringf("%s.abco", b.wire->name.c_str())); +							log_assert(wo != nullptr); +							log_assert(wo->port_output); +							log_assert(b.offset < GetSize(wo)); +							c.second = RTLIL::SigBit(wo, b.offset);  						}  						else { -							log_assert(w->port_input); -							log_assert(b.offset < GetSize(w)); +							// Create a new output/input loop break +							w->port_input = true; +							w = module->wire(stringf("%s.abco", w->name.c_str())); +							if (!w) { +								w = module->addWire(stringf("%s.abco", b.wire->name.c_str()), GetSize(b.wire)); +								w->port_output = true; +							} +							else { +								log_assert(w->port_input); +								log_assert(b.offset < GetSize(w)); +							} +							w->set_bool_attribute(ID(abc9_scc_break)); +							c.second = RTLIL::SigBit(w, b.offset);  						} -						w->set_bool_attribute(ID(abc9_scc_break)); -						module->swap_names(b.wire, w); -						c.second = RTLIL::SigBit(w, b.offset);  					}  				}  			} @@ -420,24 +430,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri  		design->selection_stack.pop_back(); -		// Now 'unexpose' those wires by undoing -		// the expose operation -- remove them from PO/PI -		// and re-connecting them back together -		for (auto wire : module->wires()) { -			auto it = wire->attributes.find(ID(abc9_scc_break)); -			if (it != wire->attributes.end()) { -				wire->attributes.erase(it); -				log_assert(wire->port_output); -				wire->port_output = false; -				RTLIL::Wire *i_wire = module->wire(wire->name.str() + ".abci"); -				log_assert(i_wire); -				log_assert(i_wire->port_input); -				i_wire->port_input = false; -				module->connect(i_wire, wire); -			} -		} -		module->fixup_ports(); -  		log_header(design, "Executing ABC9.\n");  		if (!lut_costs.empty()) { @@ -781,6 +773,25 @@ clone_lut:  			}  		} +		// Now 'unexpose' those wires by undoing +		// the expose operation -- remove them from PO/PI +		// and re-connecting them back together +		for (auto wire : module->wires()) { +			auto it = wire->attributes.find(ID(abc9_scc_break)); +			if (it != wire->attributes.end()) { +				wire->attributes.erase(it); +				log_assert(wire->port_output); +				wire->port_output = false; +				std::string name = wire->name.str(); +				RTLIL::Wire *i_wire = module->wire(name.substr(0, GetSize(name) - 5)); +				log_assert(i_wire); +				log_assert(i_wire->port_input); +				i_wire->port_input = false; +				module->connect(i_wire, wire); +			} +		} +		module->fixup_ports(); +  		//log("ABC RESULTS:        internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires);  		log("ABC RESULTS:           input signals: %8d\n", in_wires);  		log("ABC RESULTS:          output signals: %8d\n", out_wires); diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc index c868b9a87..90cfef71e 100644 --- a/passes/techmap/iopadmap.cc +++ b/passes/techmap/iopadmap.cc @@ -87,11 +87,11 @@ struct IopadmapPass : public Pass {  	{  		log_header(design, "Executing IOPADMAP pass (mapping inputs/outputs to IO-PAD cells).\n"); -		std::string inpad_celltype, inpad_portname, inpad_portname2; -		std::string outpad_celltype, outpad_portname, outpad_portname2; -		std::string inoutpad_celltype, inoutpad_portname, inoutpad_portname2; -		std::string toutpad_celltype, toutpad_portname, toutpad_portname2, toutpad_portname3; -		std::string tinoutpad_celltype, tinoutpad_portname, tinoutpad_portname2, tinoutpad_portname3, tinoutpad_portname4; +		std::string inpad_celltype, inpad_portname_o, inpad_portname_pad; +		std::string outpad_celltype, outpad_portname_i, outpad_portname_pad; +		std::string inoutpad_celltype, inoutpad_portname_io, inoutpad_portname_pad; +		std::string toutpad_celltype, toutpad_portname_oe, toutpad_portname_i, toutpad_portname_pad; +		std::string tinoutpad_celltype, tinoutpad_portname_oe, tinoutpad_portname_o, tinoutpad_portname_i, tinoutpad_portname_pad;  		std::string widthparam, nameparam;  		pool<pair<IdString, IdString>> ignore;  		bool flag_bits = false; @@ -102,35 +102,35 @@ struct IopadmapPass : public Pass {  			std::string arg = args[argidx];  			if (arg == "-inpad" && argidx+2 < args.size()) {  				inpad_celltype = args[++argidx]; -				inpad_portname = args[++argidx]; -				split_portname_pair(inpad_portname, inpad_portname2); +				inpad_portname_o = args[++argidx]; +				split_portname_pair(inpad_portname_o, inpad_portname_pad);  				continue;  			}  			if (arg == "-outpad" && argidx+2 < args.size()) {  				outpad_celltype = args[++argidx]; -				outpad_portname = args[++argidx]; -				split_portname_pair(outpad_portname, outpad_portname2); +				outpad_portname_i = args[++argidx]; +				split_portname_pair(outpad_portname_i, outpad_portname_pad);  				continue;  			}  			if (arg == "-inoutpad" && argidx+2 < args.size()) {  				inoutpad_celltype = args[++argidx]; -				inoutpad_portname = args[++argidx]; -				split_portname_pair(inoutpad_portname, inoutpad_portname2); +				inoutpad_portname_io = args[++argidx]; +				split_portname_pair(inoutpad_portname_io, inoutpad_portname_pad);  				continue;  			}  			if (arg == "-toutpad" && argidx+2 < args.size()) {  				toutpad_celltype = args[++argidx]; -				toutpad_portname = args[++argidx]; -				split_portname_pair(toutpad_portname, toutpad_portname2); -				split_portname_pair(toutpad_portname2, toutpad_portname3); +				toutpad_portname_oe = args[++argidx]; +				split_portname_pair(toutpad_portname_oe, toutpad_portname_i); +				split_portname_pair(toutpad_portname_i, toutpad_portname_pad);  				continue;  			}  			if (arg == "-tinoutpad" && argidx+2 < args.size()) {  				tinoutpad_celltype = args[++argidx]; -				tinoutpad_portname = args[++argidx]; -				split_portname_pair(tinoutpad_portname, tinoutpad_portname2); -				split_portname_pair(tinoutpad_portname2, tinoutpad_portname3); -				split_portname_pair(tinoutpad_portname3, tinoutpad_portname4); +				tinoutpad_portname_oe = args[++argidx]; +				split_portname_pair(tinoutpad_portname_oe, tinoutpad_portname_o); +				split_portname_pair(tinoutpad_portname_o, tinoutpad_portname_i); +				split_portname_pair(tinoutpad_portname_i, tinoutpad_portname_pad);  				continue;  			}  			if (arg == "-ignore" && argidx+2 < args.size()) { @@ -161,16 +161,16 @@ struct IopadmapPass : public Pass {  		}  		extra_args(args, argidx, design); -		if (!inpad_portname2.empty()) -			ignore.insert(make_pair(RTLIL::escape_id(inpad_celltype), RTLIL::escape_id(inpad_portname2))); -		if (!outpad_portname2.empty()) -			ignore.insert(make_pair(RTLIL::escape_id(outpad_celltype), RTLIL::escape_id(outpad_portname2))); -		if (!inoutpad_portname2.empty()) -			ignore.insert(make_pair(RTLIL::escape_id(inoutpad_celltype), RTLIL::escape_id(inoutpad_portname2))); -		if (!toutpad_portname3.empty()) -			ignore.insert(make_pair(RTLIL::escape_id(toutpad_celltype), RTLIL::escape_id(toutpad_portname3))); -		if (!tinoutpad_portname4.empty()) -			ignore.insert(make_pair(RTLIL::escape_id(tinoutpad_celltype), RTLIL::escape_id(tinoutpad_portname4))); +		if (!inpad_portname_pad.empty()) +			ignore.insert(make_pair(RTLIL::escape_id(inpad_celltype), RTLIL::escape_id(inpad_portname_pad))); +		if (!outpad_portname_pad.empty()) +			ignore.insert(make_pair(RTLIL::escape_id(outpad_celltype), RTLIL::escape_id(outpad_portname_pad))); +		if (!inoutpad_portname_pad.empty()) +			ignore.insert(make_pair(RTLIL::escape_id(inoutpad_celltype), RTLIL::escape_id(inoutpad_portname_pad))); +		if (!toutpad_portname_pad.empty()) +			ignore.insert(make_pair(RTLIL::escape_id(toutpad_celltype), RTLIL::escape_id(toutpad_portname_pad))); +		if (!tinoutpad_portname_pad.empty()) +			ignore.insert(make_pair(RTLIL::escape_id(tinoutpad_celltype), RTLIL::escape_id(tinoutpad_portname_pad)));  		for (auto module : design->modules())  			if (module->get_blackbox_attribute()) @@ -180,34 +180,25 @@ struct IopadmapPass : public Pass {  		for (auto module : design->selected_modules())  		{ -			dict<IdString, pool<int>> skip_wires;  			pool<SigBit> skip_wire_bits; -			SigMap sigmap(module); +			dict<Wire *, dict<int, pair<Cell *, IdString>>> rewrite_bits;  			for (auto cell : module->cells())  			for (auto port : cell->connections())  				if (ignore.count(make_pair(cell->type, port.first))) -					for (auto bit : sigmap(port.second)) +					for (auto bit : port.second)  						skip_wire_bits.insert(bit);  			if (!toutpad_celltype.empty() || !tinoutpad_celltype.empty())  			{ -				dict<SigBit, pair<IdString, pool<IdString>>> tbuf_bits; -				pool<pair<IdString, IdString>> norewrites; -				SigMap rewrites; +				dict<SigBit, Cell *> tbuf_bits;  				for (auto cell : module->cells())  					if (cell->type == ID($_TBUF_)) { -						SigBit bit = sigmap(cell->getPort(ID::Y).as_bit()); -						tbuf_bits[bit].first = cell->name; +						SigBit bit = cell->getPort(ID::Y).as_bit(); +						tbuf_bits[bit] = cell;  					} -				for (auto cell : module->cells()) -				for (auto port : cell->connections()) -				for (auto bit : sigmap(port.second)) -					if (tbuf_bits.count(bit)) -						tbuf_bits.at(bit).second.insert(cell->name); -  				for (auto wire : module->selected_wires())  				{  					if (!wire->port_output) @@ -216,16 +207,11 @@ struct IopadmapPass : public Pass {  					for (int i = 0; i < GetSize(wire); i++)  					{  						SigBit wire_bit(wire, i); -						SigBit mapped_wire_bit = sigmap(wire_bit); -						if (tbuf_bits.count(mapped_wire_bit) == 0) +						if (tbuf_bits.count(wire_bit) == 0)  							continue; -						if (skip_wire_bits.count(mapped_wire_bit)) -							continue; - -						auto &tbuf_cache = tbuf_bits.at(mapped_wire_bit); -						Cell *tbuf_cell = module->cell(tbuf_cache.first); +						Cell *tbuf_cell = tbuf_bits.at(wire_bit);  						if (tbuf_cell == nullptr)  							continue; @@ -238,37 +224,16 @@ struct IopadmapPass : public Pass {  							log("Mapping port %s.%s[%d] using %s.\n", log_id(module), log_id(wire), i, tinoutpad_celltype.c_str());  							Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(tinoutpad_celltype)); -							Wire *owire = module->addWire(NEW_ID); -							cell->setPort(RTLIL::escape_id(tinoutpad_portname), en_sig); -							cell->setPort(RTLIL::escape_id(tinoutpad_portname2), owire); -							cell->setPort(RTLIL::escape_id(tinoutpad_portname3), data_sig); -							cell->setPort(RTLIL::escape_id(tinoutpad_portname4), wire_bit); +							cell->setPort(RTLIL::escape_id(tinoutpad_portname_oe), en_sig); +							cell->setPort(RTLIL::escape_id(tinoutpad_portname_o), wire_bit); +							cell->setPort(RTLIL::escape_id(tinoutpad_portname_i), data_sig);  							cell->attributes[ID::keep] = RTLIL::Const(1); -							for (auto cn : tbuf_cache.second) { -								auto c = module->cell(cn); -								if (c == nullptr) -									continue; -								for (auto port : c->connections()) { -									SigSpec sig = port.second; -									bool newsig = false; -									for (auto &bit : sig) -										if (sigmap(bit) == mapped_wire_bit) { -											bit = owire; -											newsig = true; -										} -									if (newsig) -										c->setPort(port.first, sig); -								} -							} - -  							module->remove(tbuf_cell); -							skip_wires[wire->name].insert(i); - -							norewrites.insert(make_pair(cell->name, RTLIL::escape_id(tinoutpad_portname4))); -							rewrites.add(sigmap(wire_bit), owire); +							skip_wire_bits.insert(wire_bit); +							if (!tinoutpad_portname_pad.empty()) +								rewrite_bits[wire][i] = make_pair(cell, RTLIL::escape_id(tinoutpad_portname_pad));  							continue;  						} @@ -278,50 +243,19 @@ struct IopadmapPass : public Pass {  							Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(toutpad_celltype)); -							cell->setPort(RTLIL::escape_id(toutpad_portname), en_sig); -							cell->setPort(RTLIL::escape_id(toutpad_portname2), data_sig); -							cell->setPort(RTLIL::escape_id(toutpad_portname3), wire_bit); +							cell->setPort(RTLIL::escape_id(toutpad_portname_oe), en_sig); +							cell->setPort(RTLIL::escape_id(toutpad_portname_i), data_sig);  							cell->attributes[ID::keep] = RTLIL::Const(1); -							for (auto cn : tbuf_cache.second) { -								auto c = module->cell(cn); -								if (c == nullptr) -									continue; -								for (auto port : c->connections()) { -									SigSpec sig = port.second; -									bool newsig = false; -									for (auto &bit : sig) -										if (sigmap(bit) == mapped_wire_bit) { -											bit = data_sig; -											newsig = true; -										} -									if (newsig) -										c->setPort(port.first, sig); -								} -							} -  							module->remove(tbuf_cell); -							skip_wires[wire->name].insert(i); +							module->connect(wire_bit, data_sig); +							skip_wire_bits.insert(wire_bit); +							if (!toutpad_portname_pad.empty()) +								rewrite_bits[wire][i] = make_pair(cell, RTLIL::escape_id(toutpad_portname_pad));  							continue;  						}  					}  				} - -				if (GetSize(norewrites)) -				{ -					for (auto cell : module->cells()) -					for (auto port : cell->connections()) -					{ -						if (norewrites.count(make_pair(cell->name, port.first))) -							continue; - -						SigSpec orig_sig = sigmap(port.second); -						SigSpec new_sig = rewrites(orig_sig); - -						if (orig_sig != new_sig) -							cell->setPort(port.first, new_sig); -					} -				}  			}  			for (auto wire : module->selected_wires()) @@ -329,17 +263,11 @@ struct IopadmapPass : public Pass {  				if (!wire->port_id)  					continue; -				std::string celltype, portname, portname2; +				std::string celltype, portname_int, portname_pad;  				pool<int> skip_bit_indices; -				if (skip_wires.count(wire->name)) { -					if (!flag_bits) -						continue; -					skip_bit_indices = skip_wires.at(wire->name); -				} -  				for (int i = 0; i < GetSize(wire); i++) -					if (skip_wire_bits.count(sigmap(SigBit(wire, i)))) +					if (skip_wire_bits.count(SigBit(wire, i)))  						skip_bit_indices.insert(i);  				if (GetSize(wire) == GetSize(skip_bit_indices)) @@ -351,8 +279,8 @@ struct IopadmapPass : public Pass {  						continue;  					}  					celltype = inpad_celltype; -					portname = inpad_portname; -					portname2 = inpad_portname2; +					portname_int = inpad_portname_o; +					portname_pad = inpad_portname_pad;  				} else  				if (!wire->port_input && wire->port_output) {  					if (outpad_celltype.empty()) { @@ -360,8 +288,8 @@ struct IopadmapPass : public Pass {  						continue;  					}  					celltype = outpad_celltype; -					portname = outpad_portname; -					portname2 = outpad_portname2; +					portname_int = outpad_portname_i; +					portname_pad = outpad_portname_pad;  				} else  				if (wire->port_input && wire->port_output) {  					if (inoutpad_celltype.empty()) { @@ -369,8 +297,8 @@ struct IopadmapPass : public Pass {  						continue;  					}  					celltype = inoutpad_celltype; -					portname = inoutpad_portname; -					portname2 = inoutpad_portname2; +					portname_int = inoutpad_portname_io; +					portname_pad = inoutpad_portname_pad;  				} else  					log_abort(); @@ -381,29 +309,20 @@ struct IopadmapPass : public Pass {  				log("Mapping port %s.%s using %s.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire->name), celltype.c_str()); -				RTLIL::Wire *new_wire = NULL; -				if (!portname2.empty()) { -					new_wire = module->addWire(NEW_ID, wire); -					module->swap_names(new_wire, wire); -					wire->attributes.clear(); -				} -  				if (flag_bits)  				{  					for (int i = 0; i < wire->width; i++)  					{ -						if (skip_bit_indices.count(i)) { -							if (wire->port_output) -								module->connect(SigSpec(new_wire, i), SigSpec(wire, i)); -							else -								module->connect(SigSpec(wire, i), SigSpec(new_wire, i)); +						if (skip_bit_indices.count(i))  							continue; -						} + +						SigBit wire_bit(wire, i);  						RTLIL::Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(celltype)); -						cell->setPort(RTLIL::escape_id(portname), RTLIL::SigSpec(wire, i)); -						if (!portname2.empty()) -							cell->setPort(RTLIL::escape_id(portname2), RTLIL::SigSpec(new_wire, i)); +						cell->setPort(RTLIL::escape_id(portname_int), wire_bit); + +						if (!portname_pad.empty()) +							rewrite_bits[wire][i] = make_pair(cell, RTLIL::escape_id(portname_pad));  						if (!widthparam.empty())  							cell->parameters[RTLIL::escape_id(widthparam)] = RTLIL::Const(1);  						if (!nameparam.empty()) @@ -414,9 +333,15 @@ struct IopadmapPass : public Pass {  				else  				{  					RTLIL::Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(celltype)); -					cell->setPort(RTLIL::escape_id(portname), RTLIL::SigSpec(wire)); -					if (!portname2.empty()) -						cell->setPort(RTLIL::escape_id(portname2), RTLIL::SigSpec(new_wire)); +					cell->setPort(RTLIL::escape_id(portname_int), RTLIL::SigSpec(wire)); + +					if (!portname_pad.empty()) { +						RTLIL::Wire *new_wire = NULL; +						new_wire = module->addWire(NEW_ID, wire); +						module->swap_names(new_wire, wire); +						wire->attributes.clear(); +						cell->setPort(RTLIL::escape_id(portname_pad), RTLIL::SigSpec(new_wire)); +					}  					if (!widthparam.empty())  						cell->parameters[RTLIL::escape_id(widthparam)] = RTLIL::Const(wire->width);  					if (!nameparam.empty()) @@ -424,6 +349,32 @@ struct IopadmapPass : public Pass {  					cell->attributes[ID::keep] = RTLIL::Const(1);  				} +				if (!rewrite_bits.count(wire)) { +					wire->port_id = 0; +					wire->port_input = false; +					wire->port_output = false; +				} +			} + +			for (auto &it : rewrite_bits) { +				RTLIL::Wire *wire = it.first; +				RTLIL::Wire *new_wire = module->addWire(NEW_ID, wire); +				module->swap_names(new_wire, wire); +				wire->attributes.clear(); +				for (int i = 0; i < wire->width; i++) +				{ +					SigBit wire_bit(wire, i); +					if (!it.second.count(i)) { +						if (wire->port_output) +							module->connect(SigSpec(new_wire, i), SigSpec(wire, i)); +						else +							module->connect(SigSpec(wire, i), SigSpec(new_wire, i)); +					} else { +						auto &new_conn = it.second.at(i); +						new_conn.first->setPort(new_conn.second, RTLIL::SigSpec(new_wire, i)); +					} +				} +  				wire->port_id = 0;  				wire->port_input = false;  				wire->port_output = false; diff --git a/techlibs/ecp5/cells_ff.vh b/techlibs/ecp5/cells_ff.vh index 501c1b3b2..6b745f391 100644 --- a/techlibs/ecp5/cells_ff.vh +++ b/techlibs/ecp5/cells_ff.vh @@ -1,12 +1,12 @@  // Diamond flip-flops -module FD1P3AX(input     D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))        _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0),  .CE(SP), .DI(D), .Q(Q)); endmodule -module FD1P3AY(input     D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("ASYNC"))        _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0),  .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3AX(input     D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))        _TECHMAP_REPLACE_ (.CLK(CK), .LSR(|0), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3AY(input     D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("ASYNC"))        _TECHMAP_REPLACE_ (.CLK(CK), .LSR(|0), .CE(SP), .DI(D), .Q(Q)); endmodule  module FD1P3BX(input PD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("ASYNC"))        _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule  module FD1P3DX(input CD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))        _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule  module FD1P3IX(input CD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE"))  _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule  module FD1P3JX(input PD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("LSR_OVER_CE"))  _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module FD1S3AX(input     D,     CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"),  .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))        _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0),           .DI(D), .Q(Q)); endmodule -module FD1S3AY(input     D,     CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"),  .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("ASYNC"))        _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0),           .DI(D), .Q(Q)); endmodule +module FD1S3AX(input     D,     CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"),  .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))        _TECHMAP_REPLACE_ (.CLK(CK), .LSR(|0),          .DI(D), .Q(Q)); endmodule +module FD1S3AY(input     D,     CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"),  .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("ASYNC"))        _TECHMAP_REPLACE_ (.CLK(CK), .LSR(|0),          .DI(D), .Q(Q)); endmodule  module FD1S3BX(input PD, D,     CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"),  .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("ASYNC"))        _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD),          .DI(D), .Q(Q)); endmodule  module FD1S3DX(input CD, D,     CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"),  .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))        _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD),          .DI(D), .Q(Q)); endmodule  module FD1S3IX(input CD, D,     CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"),  .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE"))  _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD),          .DI(D), .Q(Q)); endmodule diff --git a/techlibs/gowin/cells_map.v b/techlibs/gowin/cells_map.v index 9845e56a7..aee912256 100644 --- a/techlibs/gowin/cells_map.v +++ b/techlibs/gowin/cells_map.v @@ -1,133 +1,282 @@ +`default_nettype none  //All DFF* have INIT, but the hardware is always initialised to the reset  //value regardless. The parameter is ignored. -// DFFN      D Flip-Flop with Negative-Edge Clock -module  \$_DFF_N_ (input D, C, output Q); DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C)); endmodule -// DFF       D Flip-Flop -module  \$_DFF_P_ (input D, C, output Q); DFF _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C)); endmodule +// DFFN			 D Flip-Flop with Negative-Edge Clock +module	\$_DFF_N_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, output Q); +	generate +		if (_TECHMAP_WIREINIT_Q_ === 1'b1) +			DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(1'b0)); +		else +			DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C)); +	endgenerate +	wire _TECHMAP_REMOVEINIT_Q_ = 1; +endmodule + +// DFF			 D Flip-Flop +module	\$_DFF_P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, output Q); +	generate +		if (_TECHMAP_WIREINIT_Q_ === 1'b1) +			DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(1'b0)); +		else +			DFF _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C)); +	endgenerate +	wire _TECHMAP_REMOVEINIT_Q_ = 1; +endmodule -// DFFE      D Flip-Flop with Clock Enable -module  \$_DFFE_PP_ (input D, C, E, output Q); DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E)); endmodule -module  \$_DFFE_PN_ (input D, C, E, output Q); DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E)); endmodule +// DFFE			 D Flip-Flop with Clock Enable +module	\$_DFFE_PP_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, E, output Q); +	generate +		if (_TECHMAP_WIREINIT_Q_ === 1'b1) +			DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E), .SET(1'b0)); +		else +			DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E)); +	endgenerate +	wire _TECHMAP_REMOVEINIT_Q_ = 1; +endmodule + +module	\$_DFFE_PN_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, E, output Q); +	generate +		if (_TECHMAP_WIREINIT_Q_ === 1'b1) +			DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E), .SET(1'b0)); +		else +			DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E)); +	endgenerate +	wire _TECHMAP_REMOVEINIT_Q_ = 1; +endmodule -// DFFNE     D Flip-Flop with Negative-Edge Clock and Clock Enable -module  \$_DFFE_NP_ (input D, C, E, output Q); DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E)); endmodule -module  \$_DFFE_NN_ (input D, C, E, output Q); DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E)); endmodule +// DFFNE		 D Flip-Flop with Negative-Edge Clock and Clock Enable +module	\$_DFFE_NP_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, E, output Q); +	generate +		if (_TECHMAP_WIREINIT_Q_ === 1'b1) +			DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E), .SET(1'b0)); +		else +			DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E)); +	endgenerate +	wire _TECHMAP_REMOVEINIT_Q_ = 1; +endmodule + +module	\$_DFFE_NN_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, E, output Q); +	generate +		if (_TECHMAP_WIREINIT_Q_ === 1'b1) +			DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E), .SET(1'b0)); +		else +			DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E)); +	endgenerate +	wire _TECHMAP_REMOVEINIT_Q_ = 1; +endmodule + +// DFFR			 D Flip-Flop with Synchronous Reset +module	\$__DFFS_PN0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); +	DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; +endmodule -// DFFR      D Flip-Flop with Synchronous Reset -module  \$__DFFS_PN0_ (input D, C, R, output Q); DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R)); endmodule -module  \$__DFFS_PP0_ (input D, C, R, output Q); DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R)); endmodule +module	\$__DFFS_PP0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); +	DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; +endmodule -// DFFNR     D Flip-Flop with Negative-Edge Clock and Synchronous Reset -module  \$__DFFS_NN0_ (input D, C, R, output Q); DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R)); endmodule -module  \$__DFFS_NP0_ (input D, C, R, output Q); DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R)); endmodule +// DFFNR		 D Flip-Flop with Negative-Edge Clock and Synchronous Reset +module	\$__DFFS_NN0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); +	DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; +endmodule +module	\$__DFFS_NP0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); +	DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; +endmodule -// DFFRE     D Flip-Flop with Clock Enable and Synchronous Reset -module  \$__DFFSE_PN0 (input D, C, R, E, output Q); DFFRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R), .CE(E)); endmodule -module  \$__DFFSE_PP0 (input D, C, R, E, output Q); DFFRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R), .CE(E)); endmodule +// DFFRE		 D Flip-Flop with Clock Enable and Synchronous Reset +module	\$__DFFSE_PN0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +	DFFRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R), .CE(E)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; +endmodule +module	\$__DFFSE_PP0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +	DFFRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R), .CE(E)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; +endmodule -// DFFNRE    D Flip-Flop with Negative-Edge Clock,Clock Enable, and Synchronous Reset -module  \$__DFFNSE_PN0 (input D, C, R, E, output Q); DFFNRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R), .CE(E)); endmodule -module  \$__DFFNSE_PP0 (input D, C, R, E, output Q); DFFNRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R), .CE(E)); endmodule +// DFFNRE		 D Flip-Flop with Negative-Edge Clock,Clock Enable, and Synchronous Reset +module	\$__DFFSE_NN0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +	DFFNRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R), .CE(E)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; +endmodule +module	\$__DFFSE_NP0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +	DFFNRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R), .CE(E)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; +endmodule -// DFFS      D Flip-Flop with Synchronous Set -module  \$__DFFS_PN1_ (input D, C, R, output Q); DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R)); endmodule -module  \$__DFFS_PP1_ (input D, C, R, output Q); DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R)); endmodule +// DFFS			 D Flip-Flop with Synchronous Set +module	\$__DFFS_PN1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); +	DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; +endmodule +module	\$__DFFS_PP1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); +	DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; +endmodule -// DFFNS     D Flip-Flop with Negative-Edge Clock and Synchronous Set -module  \$__DFFS_NN1_ (input D, C, R, output Q); DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R)); endmodule -module  \$__DFFS_NP1_ (input D, C, R, output Q); DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R)); endmodule +// DFFNS		 D Flip-Flop with Negative-Edge Clock and Synchronous Set +module	\$__DFFS_NN1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); +	DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; +endmodule +module	\$__DFFS_NP1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); +	DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; +endmodule -// DFFSE     D Flip-Flop with Clock Enable and Synchronous Set -module  \$__DFFSE_PN1 (input D, C, R, E, output Q); DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R), .CE(E)); endmodule -module  \$__DFFSE_PP1 (input D, C, R, E, output Q); DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R), .CE(E)); endmodule +// DFFSE		 D Flip-Flop with Clock Enable and Synchronous Set +module	\$__DFFSE_PN1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +	DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R), .CE(E)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; +endmodule +module	\$__DFFSE_PP1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +	DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R), .CE(E)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; +endmodule -// DFFNSE    D Flip-Flop with Negative-Edge Clock,Clock Enable,and Synchronous Set -module  \$__DFFSE_NN1 (input D, C, R, E, output Q); DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R), .CE(E)); endmodule -module  \$__DFFSE_NP1 (input D, C, R, E, output Q); DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R), .CE(E)); endmodule +// DFFNSE		 D Flip-Flop with Negative-Edge Clock,Clock Enable,and Synchronous Set +module	\$__DFFSE_NN1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +	DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R), .CE(E)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; +endmodule +module	\$__DFFSE_NP1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +	DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R), .CE(E)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; +endmodule -// DFFP      D Flip-Flop with Asynchronous Preset -module  \$_DFF_PP1_ (input D, C, R, output Q); DFFP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R)); endmodule -module  \$_DFF_PN1_ (input D, C, R, output Q); DFFP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R)); endmodule +// DFFP			 D Flip-Flop with Asynchronous Preset +module	\$_DFF_PP1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); +	DFFP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; +endmodule +module	\$_DFF_PN1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); +	DFFP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; +endmodule -// DFFNP     D Flip-Flop with Negative-Edge Clock and Asynchronous Preset -module  \$_DFF_NP1_ (input D, C, R, output Q); DFFNP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R)); endmodule -module  \$_DFF_NN1_ (input D, C, R, output Q); DFFNP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R)); endmodule +// DFFNP		 D Flip-Flop with Negative-Edge Clock and Asynchronous Preset +module	\$_DFF_NP1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); +	DFFNP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; +endmodule +module	\$_DFF_NN1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); +	DFFNP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; +endmodule -// DFFC      D Flip-Flop with Asynchronous Clear -module  \$_DFF_PP0_ (input D, C, R, output Q); DFFC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R)); endmodule -module  \$_DFF_PN0_ (input D, C, R, output Q); DFFC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R)); endmodule +// DFFC			 D Flip-Flop with Asynchronous Clear +module	\$_DFF_PP0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); +	DFFC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; +endmodule +module	\$_DFF_PN0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); +	DFFC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; +endmodule -// DFFNC     D Flip-Flop with Negative-Edge Clock and Asynchronous Clear -module  \$_DFF_NP0_ (input D, C, R, output Q); DFFNC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R)); endmodule -module  \$_DFF_NN0_ (input D, C, R, output Q); DFFNC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R)); endmodule +// DFFNC		 D Flip-Flop with Negative-Edge Clock and Asynchronous Clear +module	\$_DFF_NP0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); +	DFFNC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; +endmodule +module	\$_DFF_NN0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q); +	DFFNC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; +endmodule -// DFFPE     D Flip-Flop with Clock Enable and Asynchronous Preset -module  \$__DFFE_PP1 (input D, C, R, E, output Q); DFFPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R), .CE(E)); endmodule -module  \$__DFFE_PN1 (input D, C, R, E, output Q); DFFPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R), .CE(E)); endmodule +// DFFPE		 D Flip-Flop with Clock Enable and Asynchronous Preset +module	\$__DFFE_PP1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +	DFFPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R), .CE(E)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; +endmodule +module	\$__DFFE_PN1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +	DFFPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R), .CE(E)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; +endmodule -// DFFNPE    D Flip-Flop with Negative-Edge Clock,Clock Enable, and Asynchronous Preset -module  \$__DFFE_NP1 (input D, C, R, E, output Q); DFFNPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R), .CE(E)); endmodule -module  \$__DFFE_NN1 (input D, C, R, E, output Q); DFFNPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R), .CE(E)); endmodule +// DFFNPE		 D Flip-Flop with Negative-Edge Clock,Clock Enable, and Asynchronous Preset +module	\$__DFFE_NP1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +	DFFNPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R), .CE(E)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; +endmodule +module	\$__DFFE_NN1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +	DFFNPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R), .CE(E)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0; +endmodule -// DFFCE     D Flip-Flop with Clock Enable and Asynchronous Clear -module  \$__DFFE_PP0 (input D, C, R, E, output Q); DFFCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R), .CE(E)); endmodule -module  \$__DFFE_PN0 (input D, C, R, E, output Q); DFFCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R), .CE(E)); endmodule +// DFFCE		 D Flip-Flop with Clock Enable and Asynchronous Clear +module	\$__DFFE_PP0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +	DFFCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R), .CE(E)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; +endmodule +module	\$__DFFE_PN0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +	DFFCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R), .CE(E)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; +endmodule -// DFFNCE    D Flip-Flop with Negative-Edge Clock,Clock Enable and Asynchronous Clear -module  \$__DFFE_NP0 (input D, C, R, E, output Q); DFFNCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R), .CE(E)); endmodule -module  \$__DFFE_NN0 (input D, C, R, E, output Q); DFFNCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R), .CE(E)); endmodule +// DFFNCE		 D Flip-Flop with Negative-Edge Clock,Clock Enable and Asynchronous Clear +module	\$__DFFE_NP0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +	DFFNCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R), .CE(E)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; +endmodule +module	\$__DFFE_NN0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q); +	DFFNCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R), .CE(E)); +	wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1; +endmodule  module \$lut (A, Y); -  parameter WIDTH = 0; -  parameter LUT = 0; - -  input [WIDTH-1:0] A; -  output Y; - -  generate -    if (WIDTH == 1) begin -      LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y), -        .I0(A[0])); -    end else -    if (WIDTH == 2) begin -      LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y), -        .I0(A[0]), .I1(A[1])); -    end else -    if (WIDTH == 3) begin -      LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y), -        .I0(A[0]), .I1(A[1]), .I2(A[2])); -    end else -    if (WIDTH == 4) begin -      LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y), -        .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3])); -    end else -    if (WIDTH == 5) begin -      wire f0, f1; -      \$lut #(.LUT(LUT[15: 0]), .WIDTH(4)) lut0 (.A(A[3:0]), .Y(f0)); -      \$lut #(.LUT(LUT[31:16]), .WIDTH(4)) lut1 (.A(A[3:0]), .Y(f1)); -      MUX2_LUT5 mux5(.I0(f0), .I1(f1), .S0(A[4]), .O(Y)); -    end else -    if (WIDTH == 6) begin -      wire f0, f1; -      \$lut #(.LUT(LUT[31: 0]), .WIDTH(5)) lut0 (.A(A[4:0]), .Y(f0)); -      \$lut #(.LUT(LUT[63:32]), .WIDTH(5)) lut1 (.A(A[4:0]), .Y(f1)); -      MUX2_LUT6 mux6(.I0(f0), .I1(f1), .S0(A[5]), .O(Y)); -    end else -    if (WIDTH == 7) begin -      wire f0, f1; -      \$lut #(.LUT(LUT[63: 0]), .WIDTH(6)) lut0 (.A(A[5:0]), .Y(f0)); -      \$lut #(.LUT(LUT[127:64]), .WIDTH(6)) lut1 (.A(A[5:0]), .Y(f1)); -      MUX2_LUT7 mux7(.I0(f0), .I1(f1), .S0(A[6]), .O(Y)); -    end else -    if (WIDTH == 8) begin -      wire f0, f1; -      \$lut #(.LUT(LUT[127: 0]), .WIDTH(7)) lut0 (.A(A[6:0]), .Y(f0)); -      \$lut #(.LUT(LUT[255:128]), .WIDTH(7)) lut1 (.A(A[6:0]), .Y(f1)); -      MUX2_LUT8 mux8(.I0(f0), .I1(f1), .S0(A[7]), .O(Y)); -    end else begin -      wire _TECHMAP_FAIL_ = 1; -    end -  endgenerate +	parameter WIDTH = 0; +	parameter LUT = 0; + +	input [WIDTH-1:0] A; +	output Y; + +	generate +		if (WIDTH == 1) begin +			LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y), +				.I0(A[0])); +		end else +		if (WIDTH == 2) begin +			LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y), +				.I0(A[0]), .I1(A[1])); +		end else +		if (WIDTH == 3) begin +			LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y), +				.I0(A[0]), .I1(A[1]), .I2(A[2])); +		end else +		if (WIDTH == 4) begin +			LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y), +				.I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3])); +		end else +		if (WIDTH == 5) begin +			wire f0, f1; +			\$lut #(.LUT(LUT[15: 0]), .WIDTH(4)) lut0 (.A(A[3:0]), .Y(f0)); +			\$lut #(.LUT(LUT[31:16]), .WIDTH(4)) lut1 (.A(A[3:0]), .Y(f1)); +			MUX2_LUT5 mux5(.I0(f0), .I1(f1), .S0(A[4]), .O(Y)); +		end else +		if (WIDTH == 6) begin +			wire f0, f1; +			\$lut #(.LUT(LUT[31: 0]), .WIDTH(5)) lut0 (.A(A[4:0]), .Y(f0)); +			\$lut #(.LUT(LUT[63:32]), .WIDTH(5)) lut1 (.A(A[4:0]), .Y(f1)); +			MUX2_LUT6 mux6(.I0(f0), .I1(f1), .S0(A[5]), .O(Y)); +		end else +		if (WIDTH == 7) begin +			wire f0, f1; +			\$lut #(.LUT(LUT[63: 0]), .WIDTH(6)) lut0 (.A(A[5:0]), .Y(f0)); +			\$lut #(.LUT(LUT[127:64]), .WIDTH(6)) lut1 (.A(A[5:0]), .Y(f1)); +			MUX2_LUT7 mux7(.I0(f0), .I1(f1), .S0(A[6]), .O(Y)); +		end else +		if (WIDTH == 8) begin +			wire f0, f1; +			\$lut #(.LUT(LUT[127: 0]), .WIDTH(7)) lut0 (.A(A[6:0]), .Y(f0)); +			\$lut #(.LUT(LUT[255:128]), .WIDTH(7)) lut1 (.A(A[6:0]), .Y(f1)); +			MUX2_LUT8 mux8(.I0(f0), .I1(f1), .S0(A[7]), .O(Y)); +		end else begin +			wire _TECHMAP_FAIL_ = 1; +		end +	endgenerate  endmodule diff --git a/techlibs/gowin/synth_gowin.cc b/techlibs/gowin/synth_gowin.cc index 3c1426414..6cf058f29 100644 --- a/techlibs/gowin/synth_gowin.cc +++ b/techlibs/gowin/synth_gowin.cc @@ -67,6 +67,9 @@ struct SynthGowinPass : public ScriptPass  		log("    -nowidelut\n");  		log("        do not use muxes to implement LUTs larger than LUT4s\n");  		log("\n"); +		log("    -noiopads\n"); +		log("        do not emit IOB at top level ports\n"); +		log("\n");  		log("    -abc9\n");  		log("        use new ABC9 flow (EXPERIMENTAL)\n");  		log("\n"); @@ -77,7 +80,7 @@ struct SynthGowinPass : public ScriptPass  	}  	string top_opt, vout_file; -	bool retime, nobram, nodram, flatten, nodffe, nowidelut, abc9; +	bool retime, nobram, nodram, flatten, nodffe, nowidelut, abc9, noiopads;  	void clear_flags() YS_OVERRIDE  	{ @@ -90,6 +93,7 @@ struct SynthGowinPass : public ScriptPass  		nodram = false;  		nowidelut = false;  		abc9 = false; +		noiopads = false;  	}  	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE @@ -144,6 +148,10 @@ struct SynthGowinPass : public ScriptPass  				abc9 = true;  				continue;  			} +			if (args[argidx] == "-noiopads") { +				noiopads = true; +				continue; +			}  			break;  		}  		extra_args(args, argidx, design); @@ -208,7 +216,7 @@ struct SynthGowinPass : public ScriptPass  		if (check_label("map_ffs"))  		{  			run("dffsr2dff"); -			run("dff2dffs"); +			run("dff2dffs -match-init");  			run("opt_clean");  			if (!nodffe)  				run("dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*"); @@ -236,8 +244,9 @@ struct SynthGowinPass : public ScriptPass  			run("techmap -map +/gowin/cells_map.v");  			run("setundef -undriven -params -zero");  			run("hilomap -singleton -hicell VCC V -locell GND G"); -			run("iopadmap -bits -inpad IBUF O:I -outpad OBUF I:O " -				"-toutpad TBUF OEN:I:O -tinoutpad IOBUF OEN:O:I:IO", "(unless -noiopads)"); +			if (!noiopads || help_mode) +				run("iopadmap -bits -inpad IBUF O:I -outpad OBUF I:O " +					"-toutpad TBUF OEN:I:O -tinoutpad IOBUF OEN:O:I:IO", "(unless -noiopads)");  			run("clean");  		} diff --git a/techlibs/ice40/arith_map.v b/techlibs/ice40/arith_map.v index 26b24db9e..00a07247b 100644 --- a/techlibs/ice40/arith_map.v +++ b/techlibs/ice40/arith_map.v @@ -50,7 +50,7 @@ module _80_ice40_alu (A, B, CI, BI, X, Y, CO);  			//    A[2]: 1111 0000 1111 0000  			//    A[3]: 1111 1111 0000 0000  			.LUT(16'b 0110_1001_1001_0110) -		) fadd ( +		) carry (  			.A(AA[i]),  			.B(BB[i]),  			.CI(C[i]), diff --git a/techlibs/ice40/cells_map.v b/techlibs/ice40/cells_map.v index 662423f0a..759549e30 100644 --- a/techlibs/ice40/cells_map.v +++ b/techlibs/ice40/cells_map.v @@ -61,22 +61,3 @@ module \$lut (A, Y);    endgenerate  endmodule  `endif - -`ifndef NO_ADDER -module \$__ICE40_CARRY_WRAPPER (output CO, O, input A, B, CI, I0, I3); -  parameter LUT = 0; -  SB_CARRY carry ( -    .I0(A), -    .I1(B), -    .CI(CI), -    .CO(CO) -  ); -  \$lut #( -    .WIDTH(4), -    .LUT(LUT) -  ) lut ( -    .A({I0,A,B,I3}), -    .Y(O) -  ); -endmodule -`endif diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc index ea56d3f4d..371ceb623 100644 --- a/techlibs/ice40/ice40_opt.cc +++ b/techlibs/ice40/ice40_opt.cc @@ -41,6 +41,11 @@ static void run_ice40_opts(Module *module)  	for (auto cell : module->selected_cells())  	{ +		if (!cell->type.in("\\SB_LUT4", "\\SB_CARRY", "$__ICE40_CARRY_WRAPPER")) +			continue; +		if (cell->has_keep_attr()) +			continue; +  		if (cell->type == "\\SB_LUT4")  		{  			sb_lut_cells.push_back(cell); @@ -112,6 +117,21 @@ static void run_ice40_opts(Module *module)  			if (GetSize(replacement_output)) {  				optimized_co.insert(sigmap(cell->getPort("\\CO")[0])); +				auto it = cell->attributes.find(ID(SB_LUT4.name)); +				if (it != cell->attributes.end()) { +					module->rename(cell, it->second.decode_string()); +					decltype(Cell::attributes) new_attr; +					for (const auto &a : cell->attributes) +						if (a.first.begins_with("\\SB_LUT4.\\")) +							new_attr[a.first.c_str() + strlen("\\SB_LUT4.")] = a.second; +						else if (a.first == ID(src)) +							new_attr.insert(std::make_pair(a.first, a.second)); +						else if (a.first.in(ID(SB_LUT4.name), ID::keep, ID(module_not_derived))) +							continue; +						else +							log_abort(); +					cell->attributes = std::move(new_attr); +				}  				module->connect(cell->getPort("\\CO")[0], replacement_output);  				module->design->scratchpad_set_bool("opt.did_something", true);  				log("Optimized $__ICE40_CARRY_WRAPPER cell back to logic (without SB_CARRY) %s.%s: CO=%s\n", diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 901194b06..ed7a16c08 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -363,6 +363,7 @@ struct SynthIce40Pass : public ScriptPass  				else  					run(abc + " -dress -lut 4", "(skip if -noabc)");  			} +			run("ice40_wrapcarry -unwrap");  			run("techmap -D NO_LUT -map +/ice40/cells_map.v");  			run("clean");  			run("opt_lut -dlogic SB_CARRY:I0=2:I1=1:CI=0"); diff --git a/techlibs/intel/Makefile.inc b/techlibs/intel/Makefile.inc index 4e8f423c8..d97a9b58f 100644 --- a/techlibs/intel/Makefile.inc +++ b/techlibs/intel/Makefile.inc @@ -7,7 +7,7 @@ $(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_m9k.  $(eval $(call add_share_file,share/intel/common,techlibs/intel/common/brams_map_m9k.v))  # Add the cell models and mappings for the VQM backend -families := max10 a10gx cyclonev cyclone10 cycloneiv cycloneive +families := max10 arria10gx cyclonev cyclone10lp cycloneiv cycloneive  $(foreach family,$(families), $(eval $(call add_share_file,share/intel/$(family),techlibs/intel/$(family)/cells_sim.v)))  $(foreach family,$(families), $(eval $(call add_share_file,share/intel/$(family),techlibs/intel/$(family)/cells_map.v)))  #$(eval $(call add_share_file,share/intel/cycloneive,techlibs/intel/cycloneive/arith_map.v)) diff --git a/techlibs/intel/a10gx/cells_arith.v b/techlibs/intel/arria10gx/cells_arith.v index 89fb4561f..89fb4561f 100644 --- a/techlibs/intel/a10gx/cells_arith.v +++ b/techlibs/intel/arria10gx/cells_arith.v diff --git a/techlibs/intel/a10gx/cells_map.v b/techlibs/intel/arria10gx/cells_map.v index 1430e8551..1430e8551 100644 --- a/techlibs/intel/a10gx/cells_map.v +++ b/techlibs/intel/arria10gx/cells_map.v diff --git a/techlibs/intel/a10gx/cells_sim.v b/techlibs/intel/arria10gx/cells_sim.v index e892b377e..e892b377e 100644 --- a/techlibs/intel/a10gx/cells_sim.v +++ b/techlibs/intel/arria10gx/cells_sim.v diff --git a/techlibs/intel/cyclone10/cells_arith.v b/techlibs/intel/cyclone10lp/cells_arith.v index 5ae8d6cea..5ae8d6cea 100644 --- a/techlibs/intel/cyclone10/cells_arith.v +++ b/techlibs/intel/cyclone10lp/cells_arith.v diff --git a/techlibs/intel/cyclone10/cells_map.v b/techlibs/intel/cyclone10lp/cells_map.v index c2f6f403c..c2f6f403c 100644 --- a/techlibs/intel/cyclone10/cells_map.v +++ b/techlibs/intel/cyclone10lp/cells_map.v diff --git a/techlibs/intel/cyclone10/cells_sim.v b/techlibs/intel/cyclone10lp/cells_sim.v index f5a8aee2b..f5a8aee2b 100644 --- a/techlibs/intel/cyclone10/cells_sim.v +++ b/techlibs/intel/cyclone10lp/cells_sim.v diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc index e5dc1adc7..c8c690e45 100644 --- a/techlibs/intel/synth_intel.cc +++ b/techlibs/intel/synth_intel.cc @@ -36,10 +36,10 @@ struct SynthIntelPass : public ScriptPass {  		log("\n");  		log("This command runs synthesis for Intel FPGAs.\n");  		log("\n"); -		log("    -family < max10 | a10gx | cyclone10 | cyclonev | cycloneiv | cycloneive>\n"); +		log("    -family <max10 | arria10gx | cyclone10lp | cyclonev | cycloneiv | cycloneive>\n");  		log("        generate the synthesis netlist for the specified family.\n");  		log("        MAX10 is the default target if no family argument specified.\n"); -		log("        For Cyclone GX devices, use cycloneiv argument; For Cyclone E, use cycloneive.\n"); +		log("        For Cyclone IV GX devices, use cycloneiv argument; for Cyclone IV E, use cycloneive.\n");  		log("        Cyclone V and Arria 10 GX devices are experimental.\n");  		log("\n");  		log("    -top <module>\n"); @@ -148,11 +148,11 @@ struct SynthIntelPass : public ScriptPass {  		if (!design->full_selection())  			log_cmd_error("This command only operates on fully selected designs!\n");  		if (family_opt != "max10" && -		    family_opt != "a10gx" && +		    family_opt != "arria10gx" &&  		    family_opt != "cyclonev" &&  		    family_opt != "cycloneiv" &&  		    family_opt != "cycloneive" && -		    family_opt != "cyclone10") +		    family_opt != "cyclone10lp")  			log_cmd_error("Invalid or no family specified: '%s'\n", family_opt.c_str());  		log_header(design, "Executing SYNTH_INTEL pass.\n"); @@ -214,7 +214,7 @@ struct SynthIntelPass : public ScriptPass {  		}  		if (check_label("map_luts")) { -			if (family_opt == "a10gx" || family_opt == "cyclonev") +			if (family_opt == "arria10gx" || family_opt == "cyclonev")  				run("abc -luts 2:2,3,6:5" + string(retime ? " -dff" : ""));  			else  				run("abc -lut 4" + string(retime ? " -dff" : "")); diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index a15884ec4..de2068bc5 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -363,3 +363,11 @@ module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1);    else      MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O));  endmodule + +module \$__XILINX_TINOUTPAD (input I, OE, output O, inout IO); +  IOBUF _TECHMAP_REPLACE_ (.I(I), .O(O), .T(~OE), .IO(IO)); +endmodule + +module \$__XILINX_TOUTPAD (input I, OE, output O); +  OBUFT _TECHMAP_REPLACE_ (.I(I), .O(O), .T(~OE)); +endmodule diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 1be43f9d4..3ed0759db 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -471,6 +471,473 @@ module LDPE (      else if (GE && g) Q = D;  endmodule +// LUTRAM. + +// Single port. + +module RAM16X1S ( +  output O, +  input A0, A1, A2, A3, +  input D, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input WCLK, +  input WE +); +  parameter [15:0] INIT = 16'h0000; +  parameter [0:0] IS_WCLK_INVERTED = 1'b0; +  wire [3:0] a = {A3, A2, A1, A0}; +  reg [15:0] mem = INIT; +  assign O = mem[a]; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  always @(posedge clk) if (WE) mem[a] <= D; +endmodule + +module RAM16X1S_1 ( +  output O, +  input A0, A1, A2, A3, +  input D, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input WCLK, +  input WE +); +  parameter [15:0] INIT = 16'h0000; +  parameter [0:0] IS_WCLK_INVERTED = 1'b0; +  wire [3:0] a = {A3, A2, A1, A0}; +  reg [15:0] mem = INIT; +  assign O = mem[a]; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  always @(negedge clk) if (WE) mem[a] <= D; +endmodule + +module RAM32X1S ( +  output O, +  input A0, A1, A2, A3, A4, +  input D, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input WCLK, +  input WE +); +  parameter [31:0] INIT = 32'h00000000; +  parameter [0:0] IS_WCLK_INVERTED = 1'b0; +  wire [4:0] a = {A4, A3, A2, A1, A0}; +  reg [31:0] mem = INIT; +  assign O = mem[a]; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  always @(posedge clk) if (WE) mem[a] <= D; +endmodule + +module RAM32X1S_1 ( +  output O, +  input A0, A1, A2, A3, A4, +  input D, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input WCLK, +  input WE +); +  parameter [31:0] INIT = 32'h00000000; +  parameter [0:0] IS_WCLK_INVERTED = 1'b0; +  wire [4:0] a = {A4, A3, A2, A1, A0}; +  reg [31:0] mem = INIT; +  assign O = mem[a]; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  always @(negedge clk) if (WE) mem[a] <= D; +endmodule + +module RAM64X1S ( +  output O, +  input A0, A1, A2, A3, A4, A5, +  input D, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input WCLK, +  input WE +); +  parameter [63:0] INIT = 64'h0000000000000000; +  parameter [0:0] IS_WCLK_INVERTED = 1'b0; +  wire [5:0] a = {A5, A4, A3, A2, A1, A0}; +  reg [63:0] mem = INIT; +  assign O = mem[a]; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  always @(posedge clk) if (WE) mem[a] <= D; +endmodule + +module RAM64X1S_1 ( +  output O, +  input A0, A1, A2, A3, A4, A5, +  input D, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input WCLK, +  input WE +); +  parameter [63:0] INIT = 64'h0000000000000000; +  parameter [0:0] IS_WCLK_INVERTED = 1'b0; +  wire [5:0] a = {A5, A4, A3, A2, A1, A0}; +  reg [63:0] mem = INIT; +  assign O = mem[a]; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  always @(negedge clk) if (WE) mem[a] <= D; +endmodule + +module RAM128X1S ( +  output O, +  input A0, A1, A2, A3, A4, A5, A6, +  input D, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input WCLK, +  input WE +); +  parameter [127:0] INIT = 128'h00000000000000000000000000000000; +  parameter [0:0] IS_WCLK_INVERTED = 1'b0; +  wire [6:0] a = {A6, A5, A4, A3, A2, A1, A0}; +  reg [127:0] mem = INIT; +  assign O = mem[a]; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  always @(posedge clk) if (WE) mem[a] <= D; +endmodule + +module RAM128X1S_1 ( +  output O, +  input A0, A1, A2, A3, A4, A5, A6, +  input D, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input WCLK, +  input WE +); +  parameter [127:0] INIT = 128'h00000000000000000000000000000000; +  parameter [0:0] IS_WCLK_INVERTED = 1'b0; +  wire [6:0] a = {A6, A5, A4, A3, A2, A1, A0}; +  reg [127:0] mem = INIT; +  assign O = mem[a]; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  always @(negedge clk) if (WE) mem[a] <= D; +endmodule + +module RAM256X1S ( +  output O, +  input [7:0] A, +  input D, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input WCLK, +  input WE +); +  parameter [255:0] INIT = 256'h0; +  parameter [0:0] IS_WCLK_INVERTED = 1'b0; +  reg [255:0] mem = INIT; +  assign O = mem[A]; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  always @(posedge clk) if (WE) mem[A] <= D; +endmodule + +module RAM512X1S ( +  output O, +  input [8:0] A, +  input D, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input WCLK, +  input WE +); +  parameter [511:0] INIT = 512'h0; +  parameter [0:0] IS_WCLK_INVERTED = 1'b0; +  reg [511:0] mem = INIT; +  assign O = mem[A]; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  always @(posedge clk) if (WE) mem[A] <= D; +endmodule + +// Single port, wide. + +module RAM16X2S ( +  output O0, O1, +  input A0, A1, A2, A3, +  input D0, D1, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input WCLK, +  input WE +); +  parameter [15:0] INIT_00 = 16'h0000; +  parameter [15:0] INIT_01 = 16'h0000; +  parameter [0:0] IS_WCLK_INVERTED = 1'b0; +  wire [3:0] a = {A3, A2, A1, A0}; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  reg [15:0] mem0 = INIT_00; +  reg [15:0] mem1 = INIT_01; +  assign O0 = mem0[a]; +  assign O1 = mem1[a]; +  always @(posedge clk) +    if (WE) begin +      mem0[a] <= D0; +      mem1[a] <= D1; +    end +endmodule + +module RAM32X2S ( +  output O0, O1, +  input A0, A1, A2, A3, A4, +  input D0, D1, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input WCLK, +  input WE +); +  parameter [31:0] INIT_00 = 32'h00000000; +  parameter [31:0] INIT_01 = 32'h00000000; +  parameter [0:0] IS_WCLK_INVERTED = 1'b0; +  wire [4:0] a = {A4, A3, A2, A1, A0}; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  reg [31:0] mem0 = INIT_00; +  reg [31:0] mem1 = INIT_01; +  assign O0 = mem0[a]; +  assign O1 = mem1[a]; +  always @(posedge clk) +    if (WE) begin +      mem0[a] <= D0; +      mem1[a] <= D1; +    end +endmodule + +module RAM64X2S ( +  output O0, O1, +  input A0, A1, A2, A3, A4, A5, +  input D0, D1, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input WCLK, +  input WE +); +  parameter [63:0] INIT_00 = 64'h0000000000000000; +  parameter [63:0] INIT_01 = 64'h0000000000000000; +  parameter [0:0] IS_WCLK_INVERTED = 1'b0; +  wire [5:0] a = {A5, A3, A2, A1, A0}; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  reg [63:0] mem0 = INIT_00; +  reg [63:0] mem1 = INIT_01; +  assign O0 = mem0[a]; +  assign O1 = mem1[a]; +  always @(posedge clk) +    if (WE) begin +      mem0[a] <= D0; +      mem1[a] <= D1; +    end +endmodule + +module RAM16X4S ( +  output O0, O1, O2, O3, +  input A0, A1, A2, A3, +  input D0, D1, D2, D3, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input WCLK, +  input WE +); +  parameter [15:0] INIT_00 = 16'h0000; +  parameter [15:0] INIT_01 = 16'h0000; +  parameter [15:0] INIT_02 = 16'h0000; +  parameter [15:0] INIT_03 = 16'h0000; +  parameter [0:0] IS_WCLK_INVERTED = 1'b0; +  wire [3:0] a = {A3, A2, A1, A0}; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  reg [15:0] mem0 = INIT_00; +  reg [15:0] mem1 = INIT_01; +  reg [15:0] mem2 = INIT_02; +  reg [15:0] mem3 = INIT_03; +  assign O0 = mem0[a]; +  assign O1 = mem1[a]; +  assign O2 = mem2[a]; +  assign O3 = mem3[a]; +  always @(posedge clk) +    if (WE) begin +      mem0[a] <= D0; +      mem1[a] <= D1; +      mem2[a] <= D2; +      mem3[a] <= D3; +    end +endmodule + +module RAM32X4S ( +  output O0, O1, O2, O3, +  input A0, A1, A2, A3, A4, +  input D0, D1, D2, D3, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input WCLK, +  input WE +); +  parameter [31:0] INIT_00 = 32'h00000000; +  parameter [31:0] INIT_01 = 32'h00000000; +  parameter [31:0] INIT_02 = 32'h00000000; +  parameter [31:0] INIT_03 = 32'h00000000; +  parameter [0:0] IS_WCLK_INVERTED = 1'b0; +  wire [4:0] a = {A4, A3, A2, A1, A0}; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  reg [31:0] mem0 = INIT_00; +  reg [31:0] mem1 = INIT_01; +  reg [31:0] mem2 = INIT_02; +  reg [31:0] mem3 = INIT_03; +  assign O0 = mem0[a]; +  assign O1 = mem1[a]; +  assign O2 = mem2[a]; +  assign O3 = mem3[a]; +  always @(posedge clk) +    if (WE) begin +      mem0[a] <= D0; +      mem1[a] <= D1; +      mem2[a] <= D2; +      mem3[a] <= D3; +    end +endmodule + +module RAM16X8S ( +  output [7:0] O, +  input A0, A1, A2, A3, +  input [7:0] D, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input WCLK, +  input WE +); +  parameter [15:0] INIT_00 = 16'h0000; +  parameter [15:0] INIT_01 = 16'h0000; +  parameter [15:0] INIT_02 = 16'h0000; +  parameter [15:0] INIT_03 = 16'h0000; +  parameter [15:0] INIT_04 = 16'h0000; +  parameter [15:0] INIT_05 = 16'h0000; +  parameter [15:0] INIT_06 = 16'h0000; +  parameter [15:0] INIT_07 = 16'h0000; +  parameter [0:0] IS_WCLK_INVERTED = 1'b0; +  wire [3:0] a = {A3, A2, A1, A0}; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  reg [15:0] mem0 = INIT_00; +  reg [15:0] mem1 = INIT_01; +  reg [15:0] mem2 = INIT_02; +  reg [15:0] mem3 = INIT_03; +  reg [15:0] mem4 = INIT_04; +  reg [15:0] mem5 = INIT_05; +  reg [15:0] mem6 = INIT_06; +  reg [15:0] mem7 = INIT_07; +  assign O[0] = mem0[a]; +  assign O[1] = mem1[a]; +  assign O[2] = mem2[a]; +  assign O[3] = mem3[a]; +  assign O[4] = mem4[a]; +  assign O[5] = mem5[a]; +  assign O[6] = mem6[a]; +  assign O[7] = mem7[a]; +  always @(posedge clk) +    if (WE) begin +      mem0[a] <= D[0]; +      mem1[a] <= D[1]; +      mem2[a] <= D[2]; +      mem3[a] <= D[3]; +      mem4[a] <= D[4]; +      mem5[a] <= D[5]; +      mem6[a] <= D[6]; +      mem7[a] <= D[7]; +    end +endmodule + +module RAM32X8S ( +  output [7:0] O, +  input A0, A1, A2, A3, A4, +  input [7:0] D, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input WCLK, +  input WE +); +  parameter [31:0] INIT_00 = 32'h00000000; +  parameter [31:0] INIT_01 = 32'h00000000; +  parameter [31:0] INIT_02 = 32'h00000000; +  parameter [31:0] INIT_03 = 32'h00000000; +  parameter [31:0] INIT_04 = 32'h00000000; +  parameter [31:0] INIT_05 = 32'h00000000; +  parameter [31:0] INIT_06 = 32'h00000000; +  parameter [31:0] INIT_07 = 32'h00000000; +  parameter [0:0] IS_WCLK_INVERTED = 1'b0; +  wire [4:0] a = {A4, A3, A2, A1, A0}; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  reg [31:0] mem0 = INIT_00; +  reg [31:0] mem1 = INIT_01; +  reg [31:0] mem2 = INIT_02; +  reg [31:0] mem3 = INIT_03; +  reg [31:0] mem4 = INIT_04; +  reg [31:0] mem5 = INIT_05; +  reg [31:0] mem6 = INIT_06; +  reg [31:0] mem7 = INIT_07; +  assign O[0] = mem0[a]; +  assign O[1] = mem1[a]; +  assign O[2] = mem2[a]; +  assign O[3] = mem3[a]; +  assign O[4] = mem4[a]; +  assign O[5] = mem5[a]; +  assign O[6] = mem6[a]; +  assign O[7] = mem7[a]; +  always @(posedge clk) +    if (WE) begin +      mem0[a] <= D[0]; +      mem1[a] <= D[1]; +      mem2[a] <= D[2]; +      mem3[a] <= D[3]; +      mem4[a] <= D[4]; +      mem5[a] <= D[5]; +      mem6[a] <= D[6]; +      mem7[a] <= D[7]; +    end +endmodule + +// Dual port. + +module RAM16X1D ( +  output DPO, SPO, +  input  D, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input  WCLK, +  input  WE, +  input  A0, A1, A2, A3, +  input  DPRA0, DPRA1, DPRA2, DPRA3 +); +  parameter INIT = 16'h0; +  parameter IS_WCLK_INVERTED = 1'b0; +  wire [3:0] a = {A3, A2, A1, A0}; +  wire [3:0] dpra = {DPRA3, DPRA2, DPRA1, DPRA0}; +  reg [15:0] mem = INIT; +  assign SPO = mem[a]; +  assign DPO = mem[dpra]; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  always @(posedge clk) if (WE) mem[a] <= D; +endmodule + +module RAM16X1D_1 ( +  output DPO, SPO, +  input  D, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input  WCLK, +  input  WE, +  input  A0, A1, A2, A3, +  input  DPRA0, DPRA1, DPRA2, DPRA3 +); +  parameter INIT = 16'h0; +  parameter IS_WCLK_INVERTED = 1'b0; +  wire [3:0] a = {A3, A2, A1, A0}; +  wire [3:0] dpra = {DPRA3, DPRA2, DPRA1, DPRA0}; +  reg [15:0] mem = INIT; +  assign SPO = mem[a]; +  assign DPO = mem[dpra]; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  always @(negedge clk) if (WE) mem[a] <= D; +endmodule +  module RAM32X1D (    // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957    (* abc9_arrival=1153 *) @@ -494,6 +961,29 @@ module RAM32X1D (    always @(posedge clk) if (WE) mem[a] <= D;  endmodule +module RAM32X1D_1 ( +  // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 +  (* abc9_arrival=1153 *) +  output DPO, SPO, +  input  D, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input  WCLK, +  input  WE, +  input  A0, A1, A2, A3, A4, +  input  DPRA0, DPRA1, DPRA2, DPRA3, DPRA4 +); +  parameter INIT = 32'h0; +  parameter IS_WCLK_INVERTED = 1'b0; +  wire [4:0] a = {A4, A3, A2, A1, A0}; +  wire [4:0] dpra = {DPRA4, DPRA3, DPRA2, DPRA1, DPRA0}; +  reg [31:0] mem = INIT; +  assign SPO = mem[a]; +  assign DPO = mem[dpra]; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  always @(negedge clk) if (WE) mem[a] <= D; +endmodule +  module RAM64X1D (    // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957    (* abc9_arrival=1153 *) @@ -517,6 +1007,29 @@ module RAM64X1D (    always @(posedge clk) if (WE) mem[a] <= D;  endmodule +module RAM64X1D_1 ( +  // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 +  (* abc9_arrival=1153 *) +  output DPO, SPO, +  input  D, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input  WCLK, +  input  WE, +  input  A0, A1, A2, A3, A4, A5, +  input  DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5 +); +  parameter INIT = 64'h0; +  parameter IS_WCLK_INVERTED = 1'b0; +  wire [5:0] a = {A5, A4, A3, A2, A1, A0}; +  wire [5:0] dpra = {DPRA5, DPRA4, DPRA3, DPRA2, DPRA1, DPRA0}; +  reg [63:0] mem = INIT; +  assign SPO = mem[a]; +  assign DPO = mem[dpra]; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  always @(negedge clk) if (WE) mem[a] <= D; +endmodule +  module RAM128X1D (    // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957    (* abc9_arrival=1153 *) @@ -537,6 +1050,290 @@ module RAM128X1D (    always @(posedge clk) if (WE) mem[A] <= D;  endmodule +module RAM256X1D ( +  output DPO, SPO, +  input        D, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input        WCLK, +  input        WE, +  input  [7:0] A, DPRA +); +  parameter INIT = 256'h0; +  parameter IS_WCLK_INVERTED = 1'b0; +  reg [255:0] mem = INIT; +  assign SPO = mem[A]; +  assign DPO = mem[DPRA]; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  always @(posedge clk) if (WE) mem[A] <= D; +endmodule + +// Multi port. + +module RAM32M ( +  output [1:0] DOA, +  output [1:0] DOB, +  output [1:0] DOC, +  output [1:0] DOD, +  input [4:0] ADDRA, +  input [4:0] ADDRB, +  input [4:0] ADDRC, +  input [4:0] ADDRD, +  input [1:0] DIA, +  input [1:0] DIB, +  input [1:0] DIC, +  input [1:0] DID, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input WCLK, +  input WE +); +  parameter [63:0] INIT_A = 64'h0000000000000000; +  parameter [63:0] INIT_B = 64'h0000000000000000; +  parameter [63:0] INIT_C = 64'h0000000000000000; +  parameter [63:0] INIT_D = 64'h0000000000000000; +  parameter [0:0] IS_WCLK_INVERTED = 1'b0; +  reg [63:0] mem_a = INIT_A; +  reg [63:0] mem_b = INIT_B; +  reg [63:0] mem_c = INIT_C; +  reg [63:0] mem_d = INIT_D; +  assign DOA = mem_a[2*ADDRA+:2]; +  assign DOB = mem_b[2*ADDRB+:2]; +  assign DOC = mem_c[2*ADDRC+:2]; +  assign DOD = mem_d[2*ADDRD+:2]; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  always @(posedge clk) +    if (WE) begin +      mem_a[2*ADDRD+:2] <= DIA; +      mem_b[2*ADDRD+:2] <= DIB; +      mem_c[2*ADDRD+:2] <= DIC; +      mem_d[2*ADDRD+:2] <= DID; +    end +endmodule + +module RAM32M16 ( +  output [1:0] DOA, +  output [1:0] DOB, +  output [1:0] DOC, +  output [1:0] DOD, +  output [1:0] DOE, +  output [1:0] DOF, +  output [1:0] DOG, +  output [1:0] DOH, +  input [4:0] ADDRA, +  input [4:0] ADDRB, +  input [4:0] ADDRC, +  input [4:0] ADDRD, +  input [4:0] ADDRE, +  input [4:0] ADDRF, +  input [4:0] ADDRG, +  input [4:0] ADDRH, +  input [1:0] DIA, +  input [1:0] DIB, +  input [1:0] DIC, +  input [1:0] DID, +  input [1:0] DIE, +  input [1:0] DIF, +  input [1:0] DIG, +  input [1:0] DIH, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input WCLK, +  input WE +); +  parameter [63:0] INIT_A = 64'h0000000000000000; +  parameter [63:0] INIT_B = 64'h0000000000000000; +  parameter [63:0] INIT_C = 64'h0000000000000000; +  parameter [63:0] INIT_D = 64'h0000000000000000; +  parameter [63:0] INIT_E = 64'h0000000000000000; +  parameter [63:0] INIT_F = 64'h0000000000000000; +  parameter [63:0] INIT_G = 64'h0000000000000000; +  parameter [63:0] INIT_H = 64'h0000000000000000; +  parameter [0:0] IS_WCLK_INVERTED = 1'b0; +  reg [63:0] mem_a = INIT_A; +  reg [63:0] mem_b = INIT_B; +  reg [63:0] mem_c = INIT_C; +  reg [63:0] mem_d = INIT_D; +  reg [63:0] mem_e = INIT_E; +  reg [63:0] mem_f = INIT_F; +  reg [63:0] mem_g = INIT_G; +  reg [63:0] mem_h = INIT_H; +  assign DOA = mem_a[2*ADDRA+:2]; +  assign DOB = mem_b[2*ADDRB+:2]; +  assign DOC = mem_c[2*ADDRC+:2]; +  assign DOD = mem_d[2*ADDRD+:2]; +  assign DOE = mem_e[2*ADDRE+:2]; +  assign DOF = mem_f[2*ADDRF+:2]; +  assign DOG = mem_g[2*ADDRG+:2]; +  assign DOH = mem_h[2*ADDRH+:2]; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  always @(posedge clk) +    if (WE) begin +      mem_a[2*ADDRH+:2] <= DIA; +      mem_b[2*ADDRH+:2] <= DIB; +      mem_c[2*ADDRH+:2] <= DIC; +      mem_d[2*ADDRH+:2] <= DID; +      mem_e[2*ADDRH+:2] <= DIE; +      mem_f[2*ADDRH+:2] <= DIF; +      mem_g[2*ADDRH+:2] <= DIG; +      mem_h[2*ADDRH+:2] <= DIH; +    end +endmodule + +module RAM64M ( +  output DOA, +  output DOB, +  output DOC, +  output DOD, +  input [4:0] ADDRA, +  input [4:0] ADDRB, +  input [4:0] ADDRC, +  input [4:0] ADDRD, +  input DIA, +  input DIB, +  input DIC, +  input DID, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input WCLK, +  input WE +); +  parameter [63:0] INIT_A = 64'h0000000000000000; +  parameter [63:0] INIT_B = 64'h0000000000000000; +  parameter [63:0] INIT_C = 64'h0000000000000000; +  parameter [63:0] INIT_D = 64'h0000000000000000; +  parameter [0:0] IS_WCLK_INVERTED = 1'b0; +  reg [63:0] mem_a = INIT_A; +  reg [63:0] mem_b = INIT_B; +  reg [63:0] mem_c = INIT_C; +  reg [63:0] mem_d = INIT_D; +  assign DOA = mem_a[ADDRA]; +  assign DOB = mem_b[ADDRB]; +  assign DOC = mem_c[ADDRC]; +  assign DOD = mem_d[ADDRD]; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  always @(posedge clk) +    if (WE) begin +      mem_a[ADDRD] <= DIA; +      mem_b[ADDRD] <= DIB; +      mem_c[ADDRD] <= DIC; +      mem_d[ADDRD] <= DID; +    end +endmodule + +module RAM64M8 ( +  output DOA, +  output DOB, +  output DOC, +  output DOD, +  output DOE, +  output DOF, +  output DOG, +  output DOH, +  input [4:0] ADDRA, +  input [4:0] ADDRB, +  input [4:0] ADDRC, +  input [4:0] ADDRD, +  input [4:0] ADDRE, +  input [4:0] ADDRF, +  input [4:0] ADDRG, +  input [4:0] ADDRH, +  input DIA, +  input DIB, +  input DIC, +  input DID, +  input DIE, +  input DIF, +  input DIG, +  input DIH, +  (* clkbuf_sink *) +  (* invertible_pin = "IS_WCLK_INVERTED" *) +  input WCLK, +  input WE +); +  parameter [63:0] INIT_A = 64'h0000000000000000; +  parameter [63:0] INIT_B = 64'h0000000000000000; +  parameter [63:0] INIT_C = 64'h0000000000000000; +  parameter [63:0] INIT_D = 64'h0000000000000000; +  parameter [63:0] INIT_E = 64'h0000000000000000; +  parameter [63:0] INIT_F = 64'h0000000000000000; +  parameter [63:0] INIT_G = 64'h0000000000000000; +  parameter [63:0] INIT_H = 64'h0000000000000000; +  parameter [0:0] IS_WCLK_INVERTED = 1'b0; +  reg [63:0] mem_a = INIT_A; +  reg [63:0] mem_b = INIT_B; +  reg [63:0] mem_c = INIT_C; +  reg [63:0] mem_d = INIT_D; +  reg [63:0] mem_e = INIT_E; +  reg [63:0] mem_f = INIT_F; +  reg [63:0] mem_g = INIT_G; +  reg [63:0] mem_h = INIT_H; +  assign DOA = mem_a[ADDRA]; +  assign DOB = mem_b[ADDRB]; +  assign DOC = mem_c[ADDRC]; +  assign DOD = mem_d[ADDRD]; +  assign DOE = mem_e[ADDRE]; +  assign DOF = mem_f[ADDRF]; +  assign DOG = mem_g[ADDRG]; +  assign DOH = mem_h[ADDRH]; +  wire clk = WCLK ^ IS_WCLK_INVERTED; +  always @(posedge clk) +    if (WE) begin +      mem_a[ADDRH] <= DIA; +      mem_b[ADDRH] <= DIB; +      mem_c[ADDRH] <= DIC; +      mem_d[ADDRH] <= DID; +      mem_e[ADDRH] <= DIE; +      mem_f[ADDRH] <= DIF; +      mem_g[ADDRH] <= DIG; +      mem_h[ADDRH] <= DIH; +    end +endmodule + +// ROM. + +module ROM16X1 ( +  output O, +  input A0, A1, A2, A3 +); +  parameter [15:0] INIT = 16'h0; +  assign O = INIT[{A3, A2, A1, A0}]; +endmodule + +module ROM32X1 ( +  output O, +  input A0, A1, A2, A3, A4 +); +  parameter [31:0] INIT = 32'h0; +  assign O = INIT[{A4, A3, A2, A1, A0}]; +endmodule + +module ROM64X1 ( +  output O, +  input A0, A1, A2, A3, A4, A5 +); +  parameter [63:0] INIT = 64'h0; +  assign O = INIT[{A5, A4, A3, A2, A1, A0}]; +endmodule + +module ROM128X1 ( +  output O, +  input A0, A1, A2, A3, A4, A5, A6 +); +  parameter [127:0] INIT = 128'h0; +  assign O = INIT[{A6, A5, A4, A3, A2, A1, A0}]; +endmodule + +module ROM256X1 ( +  output O, +  input A0, A1, A2, A3, A4, A5, A6, A7 +); +  parameter [255:0] INIT = 256'h0; +  assign O = INIT[{A7, A6, A5, A4, A3, A2, A1, A0}]; +endmodule + +// Shift registers. +  module SRL16E (    // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904-L905    (* abc9_arrival=1472 *) diff --git a/techlibs/xilinx/cells_xtra.py b/techlibs/xilinx/cells_xtra.py index 82e403f78..e4c580b9d 100644 --- a/techlibs/xilinx/cells_xtra.py +++ b/techlibs/xilinx/cells_xtra.py @@ -28,40 +28,40 @@ CELLS = [      # - UG974 (Ultrascale)      # CLB -- RAM/ROM. -    Cell('RAM16X1S', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM16X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM32X1S', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM32X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM64X1S', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM64X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM128X1S', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM128X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM256X1S', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM512X1S', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM16X2S', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM32X2S', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM64X2S', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM16X4S', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM32X4S', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM16X8S', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM32X8S', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM16X1D', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM16X1D_1', port_attrs={'WCLK': ['clkbuf_sink']}), -    #Cell('RAM32X1D', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM32X1D_1', port_attrs={'WCLK': ['clkbuf_sink']}), -    #Cell('RAM64X1D', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM64X1D_1', port_attrs={'WCLK': ['clkbuf_sink']}), -    #Cell('RAM128X1D', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM256X1D', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM32M', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM32M16', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM64M', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('RAM64M8', port_attrs={'WCLK': ['clkbuf_sink']}), -    Cell('ROM16X1'), -    Cell('ROM32X1'), -    Cell('ROM64X1'), -    Cell('ROM128X1'), -    Cell('ROM256X1'), +    # Cell('RAM16X1S', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM16X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM32X1S', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM32X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM64X1S', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM64X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM128X1S', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM128X1S_1', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM256X1S', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM512X1S', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM16X2S', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM32X2S', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM64X2S', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM16X4S', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM32X4S', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM16X8S', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM32X8S', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM16X1D', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM16X1D_1', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM32X1D', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM32X1D_1', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM64X1D', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM64X1D_1', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM128X1D', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM256X1D', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM32M', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM32M16', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM64M', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('RAM64M8', port_attrs={'WCLK': ['clkbuf_sink']}), +    # Cell('ROM16X1'), +    # Cell('ROM32X1'), +    # Cell('ROM64X1'), +    # Cell('ROM128X1'), +    # Cell('ROM256X1'),      # CLB -- registers/latches.      # Virtex 1/2/4/5, Spartan 3. @@ -372,6 +372,7 @@ CELLS = [      Cell('BUFIO2', port_attrs={'IOCLK': ['clkbuf_driver'], 'DIVCLK': ['clkbuf_driver']}),      Cell('BUFIO2_2CLK', port_attrs={'IOCLK': ['clkbuf_driver'], 'DIVCLK': ['clkbuf_driver']}),      Cell('BUFIO2FB', port_attrs={'O': ['clkbuf_driver']}), +    Cell('BUFPLL', port_attrs={'IOCLK': ['clkbuf_driver']}),      Cell('BUFPLL_MCB', port_attrs={'IOCLK0': ['clkbuf_driver'], 'IOCLK1': ['clkbuf_driver']}),      # Clock buffers (IO and regional) -- Virtex. diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v index 671d16e8a..8ac596459 100644 --- a/techlibs/xilinx/cells_xtra.v +++ b/techlibs/xilinx/cells_xtra.v @@ -1,595 +1,5 @@  // Created by cells_xtra.py from Xilinx models -module RAM16X1S (...); -    parameter [15:0] INIT = 16'h0000; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output O; -    input A0; -    input A1; -    input A2; -    input A3; -    input D; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -endmodule - -module RAM16X1S_1 (...); -    parameter [15:0] INIT = 16'h0000; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output O; -    input A0; -    input A1; -    input A2; -    input A3; -    input D; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -endmodule - -module RAM32X1S (...); -    parameter [31:0] INIT = 32'h00000000; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output O; -    input A0; -    input A1; -    input A2; -    input A3; -    input A4; -    input D; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -endmodule - -module RAM32X1S_1 (...); -    parameter [31:0] INIT = 32'h00000000; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output O; -    input A0; -    input A1; -    input A2; -    input A3; -    input A4; -    input D; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -endmodule - -module RAM64X1S (...); -    parameter [63:0] INIT = 64'h0000000000000000; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output O; -    input A0; -    input A1; -    input A2; -    input A3; -    input A4; -    input A5; -    input D; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -endmodule - -module RAM64X1S_1 (...); -    parameter [63:0] INIT = 64'h0000000000000000; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output O; -    input A0; -    input A1; -    input A2; -    input A3; -    input A4; -    input A5; -    input D; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -endmodule - -module RAM128X1S (...); -    parameter [127:0] INIT = 128'h00000000000000000000000000000000; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output O; -    input A0; -    input A1; -    input A2; -    input A3; -    input A4; -    input A5; -    input A6; -    input D; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -endmodule - -module RAM128X1S_1 (...); -    parameter [127:0] INIT = 128'h00000000000000000000000000000000; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output O; -    input A0; -    input A1; -    input A2; -    input A3; -    input A4; -    input A5; -    input A6; -    input D; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -endmodule - -module RAM256X1S (...); -    parameter [255:0] INIT = 256'h0; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output O; -    input [7:0] A; -    input D; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -endmodule - -module RAM512X1S (...); -    parameter [511:0] INIT = 512'h0; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output O; -    input [8:0] A; -    input D; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -endmodule - -module RAM16X2S (...); -    parameter [15:0] INIT_00 = 16'h0000; -    parameter [15:0] INIT_01 = 16'h0000; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output O0; -    output O1; -    input A0; -    input A1; -    input A2; -    input A3; -    input D0; -    input D1; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -endmodule - -module RAM32X2S (...); -    parameter [31:0] INIT_00 = 32'h00000000; -    parameter [31:0] INIT_01 = 32'h00000000; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output O0; -    output O1; -    input A0; -    input A1; -    input A2; -    input A3; -    input A4; -    input D0; -    input D1; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -endmodule - -module RAM64X2S (...); -    parameter [63:0] INIT_00 = 64'h0000000000000000; -    parameter [63:0] INIT_01 = 64'h0000000000000000; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output O0; -    output O1; -    input A0; -    input A1; -    input A2; -    input A3; -    input A4; -    input A5; -    input D0; -    input D1; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -endmodule - -module RAM16X4S (...); -    parameter [15:0] INIT_00 = 16'h0000; -    parameter [15:0] INIT_01 = 16'h0000; -    parameter [15:0] INIT_02 = 16'h0000; -    parameter [15:0] INIT_03 = 16'h0000; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output O0; -    output O1; -    output O2; -    output O3; -    input A0; -    input A1; -    input A2; -    input A3; -    input D0; -    input D1; -    input D2; -    input D3; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -endmodule - -module RAM32X4S (...); -    parameter [31:0] INIT_00 = 32'h00000000; -    parameter [31:0] INIT_01 = 32'h00000000; -    parameter [31:0] INIT_02 = 32'h00000000; -    parameter [31:0] INIT_03 = 32'h00000000; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output O0; -    output O1; -    output O2; -    output O3; -    input A0; -    input A1; -    input A2; -    input A3; -    input A4; -    input D0; -    input D1; -    input D2; -    input D3; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -endmodule - -module RAM16X8S (...); -    parameter [15:0] INIT_00 = 16'h0000; -    parameter [15:0] INIT_01 = 16'h0000; -    parameter [15:0] INIT_02 = 16'h0000; -    parameter [15:0] INIT_03 = 16'h0000; -    parameter [15:0] INIT_04 = 16'h0000; -    parameter [15:0] INIT_05 = 16'h0000; -    parameter [15:0] INIT_06 = 16'h0000; -    parameter [15:0] INIT_07 = 16'h0000; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output [7:0] O; -    input A0; -    input A1; -    input A2; -    input A3; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -    input [7:0] D; -endmodule - -module RAM32X8S (...); -    parameter [31:0] INIT_00 = 32'h00000000; -    parameter [31:0] INIT_01 = 32'h00000000; -    parameter [31:0] INIT_02 = 32'h00000000; -    parameter [31:0] INIT_03 = 32'h00000000; -    parameter [31:0] INIT_04 = 32'h00000000; -    parameter [31:0] INIT_05 = 32'h00000000; -    parameter [31:0] INIT_06 = 32'h00000000; -    parameter [31:0] INIT_07 = 32'h00000000; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output [7:0] O; -    input A0; -    input A1; -    input A2; -    input A3; -    input A4; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -    input [7:0] D; -endmodule - -module RAM16X1D (...); -    parameter [15:0] INIT = 16'h0000; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output DPO; -    output SPO; -    input A0; -    input A1; -    input A2; -    input A3; -    input D; -    input DPRA0; -    input DPRA1; -    input DPRA2; -    input DPRA3; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -endmodule - -module RAM16X1D_1 (...); -    parameter [15:0] INIT = 16'h0000; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output DPO; -    output SPO; -    input A0; -    input A1; -    input A2; -    input A3; -    input D; -    input DPRA0; -    input DPRA1; -    input DPRA2; -    input DPRA3; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -endmodule - -module RAM32X1D_1 (...); -    parameter [31:0] INIT = 32'h00000000; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output DPO; -    output SPO; -    input A0; -    input A1; -    input A2; -    input A3; -    input A4; -    input D; -    input DPRA0; -    input DPRA1; -    input DPRA2; -    input DPRA3; -    input DPRA4; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -endmodule - -module RAM64X1D_1 (...); -    parameter [63:0] INIT = 64'h0000000000000000; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output DPO; -    output SPO; -    input A0; -    input A1; -    input A2; -    input A3; -    input A4; -    input A5; -    input D; -    input DPRA0; -    input DPRA1; -    input DPRA2; -    input DPRA3; -    input DPRA4; -    input DPRA5; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -endmodule - -module RAM256X1D (...); -    parameter [255:0] INIT = 256'h0000000000000000000000000000000000000000000000000000000000000000; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output DPO; -    output SPO; -    input [7:0] A; -    input D; -    input [7:0] DPRA; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -endmodule - -module RAM32M (...); -    parameter [63:0] INIT_A = 64'h0000000000000000; -    parameter [63:0] INIT_B = 64'h0000000000000000; -    parameter [63:0] INIT_C = 64'h0000000000000000; -    parameter [63:0] INIT_D = 64'h0000000000000000; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output [1:0] DOA; -    output [1:0] DOB; -    output [1:0] DOC; -    output [1:0] DOD; -    input [4:0] ADDRA; -    input [4:0] ADDRB; -    input [4:0] ADDRC; -    input [4:0] ADDRD; -    input [1:0] DIA; -    input [1:0] DIB; -    input [1:0] DIC; -    input [1:0] DID; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -endmodule - -module RAM32M16 (...); -    parameter [63:0] INIT_A = 64'h0000000000000000; -    parameter [63:0] INIT_B = 64'h0000000000000000; -    parameter [63:0] INIT_C = 64'h0000000000000000; -    parameter [63:0] INIT_D = 64'h0000000000000000; -    parameter [63:0] INIT_E = 64'h0000000000000000; -    parameter [63:0] INIT_F = 64'h0000000000000000; -    parameter [63:0] INIT_G = 64'h0000000000000000; -    parameter [63:0] INIT_H = 64'h0000000000000000; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output [1:0] DOA; -    output [1:0] DOB; -    output [1:0] DOC; -    output [1:0] DOD; -    output [1:0] DOE; -    output [1:0] DOF; -    output [1:0] DOG; -    output [1:0] DOH; -    input [4:0] ADDRA; -    input [4:0] ADDRB; -    input [4:0] ADDRC; -    input [4:0] ADDRD; -    input [4:0] ADDRE; -    input [4:0] ADDRF; -    input [4:0] ADDRG; -    input [4:0] ADDRH; -    input [1:0] DIA; -    input [1:0] DIB; -    input [1:0] DIC; -    input [1:0] DID; -    input [1:0] DIE; -    input [1:0] DIF; -    input [1:0] DIG; -    input [1:0] DIH; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -endmodule - -module RAM64M (...); -    parameter [63:0] INIT_A = 64'h0000000000000000; -    parameter [63:0] INIT_B = 64'h0000000000000000; -    parameter [63:0] INIT_C = 64'h0000000000000000; -    parameter [63:0] INIT_D = 64'h0000000000000000; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output DOA; -    output DOB; -    output DOC; -    output DOD; -    input [5:0] ADDRA; -    input [5:0] ADDRB; -    input [5:0] ADDRC; -    input [5:0] ADDRD; -    input DIA; -    input DIB; -    input DIC; -    input DID; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -endmodule - -module RAM64M8 (...); -    parameter [63:0] INIT_A = 64'h0000000000000000; -    parameter [63:0] INIT_B = 64'h0000000000000000; -    parameter [63:0] INIT_C = 64'h0000000000000000; -    parameter [63:0] INIT_D = 64'h0000000000000000; -    parameter [63:0] INIT_E = 64'h0000000000000000; -    parameter [63:0] INIT_F = 64'h0000000000000000; -    parameter [63:0] INIT_G = 64'h0000000000000000; -    parameter [63:0] INIT_H = 64'h0000000000000000; -    parameter [0:0] IS_WCLK_INVERTED = 1'b0; -    output DOA; -    output DOB; -    output DOC; -    output DOD; -    output DOE; -    output DOF; -    output DOG; -    output DOH; -    input [5:0] ADDRA; -    input [5:0] ADDRB; -    input [5:0] ADDRC; -    input [5:0] ADDRD; -    input [5:0] ADDRE; -    input [5:0] ADDRF; -    input [5:0] ADDRG; -    input [5:0] ADDRH; -    input DIA; -    input DIB; -    input DIC; -    input DID; -    input DIE; -    input DIF; -    input DIG; -    input DIH; -    (* clkbuf_sink *) -    (* invertible_pin = "IS_WCLK_INVERTED" *) -    input WCLK; -    input WE; -endmodule - -module ROM16X1 (...); -    parameter [127:0] INIT = 16'h0000; -    output O; -    input A0; -    input A1; -    input A2; -    input A3; -endmodule - -module ROM32X1 (...); -    parameter [31:0] INIT = 32'h00000000; -    output O; -    input A0; -    input A1; -    input A2; -    input A3; -    input A4; -endmodule - -module ROM64X1 (...); -    parameter [63:0] INIT = 64'h0000000000000000; -    output O; -    input A0; -    input A1; -    input A2; -    input A3; -    input A4; -    input A5; -endmodule - -module ROM128X1 (...); -    parameter [127:0] INIT = 128'h00000000000000000000000000000000; -    output O; -    input A0; -    input A1; -    input A2; -    input A3; -    input A4; -    input A5; -    input A6; -endmodule - -module ROM256X1 (...); -    parameter [255:0] INIT = 256'h0000000000000000000000000000000000000000000000000000000000000000; -    output O; -    input A0; -    input A1; -    input A2; -    input A3; -    input A4; -    input A5; -    input A6; -    input A7; -endmodule -  module FDCPE (...);      parameter [0:0] INIT = 1'b0;      parameter [0:0] IS_C_INVERTED = 1'b0; @@ -5240,9 +4650,13 @@ module RAMB18E1 (...);      parameter IS_RSTRAMB_INVERTED = 1'b0;      parameter IS_RSTREGARSTREG_INVERTED = 1'b0;      parameter IS_RSTREGB_INVERTED = 1'b0; +    (* abc9_arrival=2454 *)      output [15:0] DOADO; +    (* abc9_arrival=2454 *)      output [15:0] DOBDO; +    (* abc9_arrival=2454 *)      output [1:0] DOPADOP; +    (* abc9_arrival=2454 *)      output [1:0] DOPBDOP;      (* clkbuf_sink *)      (* invertible_pin = "IS_CLKARDCLK_INVERTED" *) @@ -5452,9 +4866,13 @@ module RAMB36E1 (...);      parameter IS_RSTREGB_INVERTED = 1'b0;      output CASCADEOUTA;      output CASCADEOUTB; +    (* abc9_arrival=2454 *)      output [31:0] DOADO; +    (* abc9_arrival=2454 *)      output [31:0] DOBDO; +    (* abc9_arrival=2454 *)      output [3:0] DOPADOP; +    (* abc9_arrival=2454 *)      output [3:0] DOPBDOP;      output [7:0] ECCPARITY;      output [8:0] RDADDRECC; @@ -8527,6 +7945,18 @@ module BUFIO2FB (...);      input I;  endmodule +module BUFPLL (...); +    parameter integer DIVIDE = 1; +    parameter ENABLE_SYNC = "TRUE"; +    (* clkbuf_driver *) +    output IOCLK; +    output LOCK; +    output SERDESSTROBE; +    input GCLK; +    input LOCKED; +    input PLLIN; +endmodule +  module BUFPLL_MCB (...);      parameter integer DIVIDE = 2;      parameter LOCK_SRC = "LOCK_TO_0"; diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 3d4a65c5d..2c5686a35 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -282,6 +282,7 @@ struct SynthXilinxPass : public ScriptPass  	void script() YS_OVERRIDE  	{ +		bool do_iopad = iopad || (ise && !noiopad);  		std::string ff_map_file;  		if (help_mode)  			ff_map_file = "+/xilinx/{family}_ff_map.v"; @@ -305,6 +306,8 @@ struct SynthXilinxPass : public ScriptPass  			run("proc");  			if (flatten || help_mode)  				run("flatten", "(with '-flatten')"); +			run("tribuf -logic"); +			run("deminout");  			run("opt_expr");  			run("opt_clean");  			run("check"); @@ -503,6 +506,9 @@ struct SynthXilinxPass : public ScriptPass  		}  		if (check_label("map_cells")) { +			// Needs to be done before logic optimization, so that inverters (OE vs T) are handled. +			if (help_mode || do_iopad) +				run("iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I -toutpad $__XILINX_TOUTPAD OE:I:O -tinoutpad $__XILINX_TINOUTPAD OE:O:I:IO A:top", "(only if '-iopad' or '-ise' and not '-noiopad')");  			std::string techmap_args = "-map +/techmap.v -map +/xilinx/cells_map.v";  			if (widemux > 0)  				techmap_args += stringf(" -D MIN_MUX_INPUTS=%d", widemux); @@ -561,15 +567,8 @@ struct SynthXilinxPass : public ScriptPass  		}  		if (check_label("finalize")) { -			bool do_iopad = iopad || (ise && !noiopad); -			if (help_mode || !noclkbuf) { -				if (help_mode || do_iopad) -					run("clkbufmap -buf BUFG O:I -inpad IBUFG O:I", "(skip if '-noclkbuf', '-inpad' passed if '-iopad' or '-ise' and not '-noiopad')"); -				else -					run("clkbufmap -buf BUFG O:I"); -			} -			if (help_mode || do_iopad) -				run("iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I A:top", "(only if '-iopad' or '-ise' and not '-noiopad')"); +			if (help_mode || !noclkbuf) +				run("clkbufmap -buf BUFG O:I ", "(skip if '-noclkbuf')");  			if (help_mode || ise)  				run("extractinv -inv INV O:I", "(only if '-ise')");  		} diff --git a/tests/arch/gowin/adffs.ys b/tests/arch/gowin/adffs.ys index fc7ee01f2..87fba83a6 100644 --- a/tests/arch/gowin/adffs.ys +++ b/tests/arch/gowin/adffs.ys @@ -34,11 +34,12 @@ proc  equiv_opt -async2sync -assert -map +/gowin/cells_sim.v synth_gowin # equivalency check  design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)  cd dffs # Constrain all select calls below inside the top module -select -assert-count 1 t:DFFS +select -assert-count 1 t:DFF +select -assert-count 1 t:LUT2  select -assert-count 4 t:IBUF  select -assert-count 1 t:OBUF -select -assert-none t:DFFS t:IBUF t:OBUF %% t:* %D +select -assert-none t:DFF t:LUT2 t:IBUF t:OBUF %% t:* %D  design -load read diff --git a/tests/arch/gowin/init.v b/tests/arch/gowin/init.v new file mode 100644 index 000000000..3c30f602d --- /dev/null +++ b/tests/arch/gowin/init.v @@ -0,0 +1,224 @@ +module myDFF (output reg Q, input CLK, D); +	parameter [0:0] INIT = 1'b0; +	initial Q = INIT; +	always @(posedge CLK) +		Q <= D; +endmodule + +module myDFFE (output reg Q, input D, CLK, CE); +	parameter [0:0] INIT = 1'b0; +	initial Q = INIT; +	always @(posedge CLK) begin +		if (CE) +			Q <= D; +	end +endmodule // DFFE (positive clock edge; clock enable) + + +module myDFFS (output reg Q, input D, CLK, SET); +	parameter [0:0] INIT = 1'b1; +	initial Q = INIT; +	always @(posedge CLK) begin +		if (SET) +			Q <= 1'b1; +		else +			Q <= D; +	end +endmodule // DFFS (positive clock edge; synchronous set) + + +module myDFFSE (output reg Q, input D, CLK, CE, SET); +	parameter [0:0] INIT = 1'b1; +	initial Q = INIT; +	always @(posedge CLK) begin +		if (SET) +			Q <= 1'b1; +		else if (CE) +			Q <= D; +end +endmodule // DFFSE (positive clock edge; synchronous set takes precedence over clock enable) + + +module myDFFR (output reg Q, input D, CLK, RESET); +	parameter [0:0] INIT = 1'b0; +	initial Q = INIT; +	always @(posedge CLK) begin +		if (RESET) +			Q <= 1'b0; +		else +			Q <= D; +	end +endmodule // DFFR (positive clock edge; synchronous reset) + + +module myDFFRE (output reg Q, input D, CLK, CE, RESET); +	parameter [0:0] INIT = 1'b0; +	initial Q = INIT; +	always @(posedge CLK) begin +		if (RESET) +			Q <= 1'b0; +		else if (CE) +			Q <= D; +	end +endmodule // DFFRE (positive clock edge; synchronous reset takes precedence over clock enable) + + +module myDFFP (output reg Q, input D, CLK, PRESET); +	parameter [0:0] INIT = 1'b1; +	initial Q = INIT; +	always @(posedge CLK or posedge PRESET) begin +		if(PRESET) +			Q <= 1'b1; +		else +			Q <= D; +	end +endmodule // DFFP (positive clock edge; asynchronous preset) + + +module myDFFPE (output reg Q, input D, CLK, CE, PRESET); +	parameter [0:0] INIT = 1'b1; +	initial Q = INIT; +	always @(posedge CLK or posedge PRESET) begin +		if(PRESET) +			Q <= 1'b1; +		else if (CE) +			Q <= D; +	end +endmodule // DFFPE (positive clock edge; asynchronous preset; clock enable) + + +module myDFFC (output reg Q, input D, CLK, CLEAR); +	parameter [0:0] INIT = 1'b0; +	initial Q = INIT; +	always @(posedge CLK or posedge CLEAR) begin +		if(CLEAR) +			Q <= 1'b0; +		else +			Q <= D; +	end +endmodule // DFFC (positive clock edge; asynchronous clear) + + +module myDFFCE (output reg Q, input D, CLK, CE, CLEAR); +	parameter [0:0] INIT = 1'b0; +	initial Q = INIT; +	always @(posedge CLK or posedge CLEAR) begin +		if(CLEAR) +			Q <= 1'b0; +		else if (CE) +			Q <= D; +	end +endmodule // DFFCE (positive clock edge; asynchronous clear; clock enable) + + +module myDFFN (output reg Q, input CLK, D); +	parameter [0:0] INIT = 1'b0; +	initial Q = INIT; +	always @(negedge CLK) +		Q <= D; +endmodule + +module myDFFNE (output reg Q, input D, CLK, CE); +	parameter [0:0] INIT = 1'b0; +	initial Q = INIT; +	always @(negedge CLK) begin +		if (CE) +			Q <= D; +	end +endmodule // DFFNE (negative clock edge; clock enable) + + +module myDFFNS (output reg Q, input D, CLK, SET); +	parameter [0:0] INIT = 1'b1; +	initial Q = INIT; +	always @(negedge CLK) begin +		if (SET) +			Q <= 1'b1; +		else +			Q <= D; +	end +endmodule // DFFNS (negative clock edge; synchronous set) + + +module myDFFNSE (output reg Q, input D, CLK, CE, SET); +	parameter [0:0] INIT = 1'b1; +	initial Q = INIT; +	always @(negedge CLK) begin +		if (SET) +			Q <= 1'b1; +		else if (CE) +			Q <= D; +end +endmodule // DFFNSE (negative clock edge; synchronous set takes precedence over clock enable) + + +module myDFFNR (output reg Q, input D, CLK, RESET); +	parameter [0:0] INIT = 1'b0; +	initial Q = INIT; +	always @(negedge CLK) begin +		if (RESET) +			Q <= 1'b0; +		else +			Q <= D; +	end +endmodule // DFFNR (negative clock edge; synchronous reset) + + +module myDFFNRE (output reg Q, input D, CLK, CE, RESET); +	parameter [0:0] INIT = 1'b0; +	initial Q = INIT; +	always @(negedge CLK) begin +		if (RESET) +			Q <= 1'b0; +		else if (CE) +			Q <= D; +	end +endmodule // DFFNRE (negative clock edge; synchronous reset takes precedence over clock enable) + + +module myDFFNP (output reg Q, input D, CLK, PRESET); +	parameter [0:0] INIT = 1'b1; +	initial Q = INIT; +	always @(negedge CLK or posedge PRESET) begin +		if(PRESET) +			Q <= 1'b1; +		else +			Q <= D; +	end +endmodule // DFFNP (negative clock edge; asynchronous preset) + + +module myDFFNPE (output reg Q, input D, CLK, CE, PRESET); +	parameter [0:0] INIT = 1'b1; +	initial Q = INIT; +	always @(negedge CLK or posedge PRESET) begin +		if(PRESET) +			Q <= 1'b1; +		else if (CE) +			Q <= D; +	end +endmodule // DFFNPE (negative clock edge; asynchronous preset; clock enable) + + +module myDFFNC (output reg Q, input D, CLK, CLEAR); +	parameter [0:0] INIT = 1'b0; +	initial Q = INIT; +	always @(negedge CLK or posedge CLEAR) begin +		if(CLEAR) +			Q <= 1'b0; +		else +			Q <= D; +	end +endmodule // DFFNC (negative clock edge; asynchronous clear) + + +module myDFFNCE (output reg Q, input D, CLK, CE, CLEAR); +	parameter [0:0] INIT = 1'b0; +	initial Q = INIT; +	always @(negedge CLK or posedge CLEAR) begin +		if(CLEAR) +			Q <= 1'b0; +		else if (CE) +			Q <= D; +	end +endmodule // DFFNCE (negative clock edge; asynchronous clear; clock enable) diff --git a/tests/arch/gowin/init.ys b/tests/arch/gowin/init.ys new file mode 100644 index 000000000..ddc0e4757 --- /dev/null +++ b/tests/arch/gowin/init.ys @@ -0,0 +1,74 @@ +read_verilog init.v +read_verilog -lib +/gowin/cells_sim.v +design -save read + +proc +flatten +synth_gowin -run coarse: + +# check if all init values are handled +check -assert -noinit +# check if every flop mapped correctly +select -assert-count 1 t:DFF +select -assert-count 1 t:DFFC +select -assert-count 1 t:DFFCE +select -assert-count 1 t:DFFE +select -assert-count 1 t:DFFN +select -assert-count 1 t:DFFNC +select -assert-count 1 t:DFFNCE +select -assert-count 1 t:DFFNE +select -assert-count 1 t:DFFNP +select -assert-count 1 t:DFFNPE +select -assert-count 1 t:DFFNR +select -assert-count 1 t:DFFNRE +select -assert-count 1 t:DFFNS +select -assert-count 1 t:DFFNSE +select -assert-count 1 t:DFFP +select -assert-count 1 t:DFFPE +select -assert-count 1 t:DFFR +select -assert-count 1 t:DFFRE +select -assert-count 1 t:DFFS +select -assert-count 1 t:DFFSE + +delete +design -load read + +# these should synth to a flop with reset +chparam -set INIT 1 myDFF myDFFN myDFFE myDFFNE + +# async should give a warning +# sync should synth to a mux +chparam -set INIT 0 myDFF*S* myDFF*P* +chparam -set INIT 1 myDFF*R* myDFF*C* + +proc +flatten +synth_gowin -run coarse: + +# check the flops mapped as expected +select -assert-count 1 t:DFF +select -assert-count 1 t:DFFC +select -assert-count 1 t:DFFCE +select -assert-count 1 t:DFFE +select -assert-count 1 t:DFFN +select -assert-count 1 t:DFFNC +select -assert-count 1 t:DFFNCE +select -assert-count 1 t:DFFNE +select -assert-count 1 t:DFFNP +select -assert-count 1 t:DFFNPE +select -assert-count 0 t:DFFNR +select -assert-count 0 t:DFFNRE +select -assert-count 2 t:DFFNS +select -assert-count 2 t:DFFNSE +select -assert-count 1 t:DFFP +select -assert-count 1 t:DFFPE +select -assert-count 0 t:DFFR +select -assert-count 0 t:DFFRE +select -assert-count 2 t:DFFS +select -assert-count 2 t:DFFSE +select -assert-count 12 t:LUT2 + +# check the expected leftover init values +# this would happen if your reset value is not the initial value +# which would be weird +select -assert-count 8 a:init diff --git a/tests/arch/ice40/ice40_opt.ys b/tests/arch/ice40/ice40_opt.ys index b17c69c91..5186d4800 100644 --- a/tests/arch/ice40/ice40_opt.ys +++ b/tests/arch/ice40/ice40_opt.ys @@ -1,4 +1,24 @@  read_verilog -icells -formal <<EOT +module \$__ICE40_CARRY_WRAPPER (output CO, O, input A, B, CI, I0, I3); +  parameter LUT = 0; +  SB_CARRY carry ( +    .I0(A), +    .I1(B), +    .CI(CI), +    .CO(CO) +  ); +  \$lut #( +    .WIDTH(4), +    .LUT(LUT) +  ) lut ( +    .A({I0,A,B,I3}), +    .Y(O) +  ); +endmodule +EOT +design -stash unmap + +read_verilog -icells -formal <<EOT  module top(input CI, I0, output [1:0] CO, output O);      wire A = 1'b0, B = 1'b0;  	\$__ICE40_CARRY_WRAPPER #( @@ -20,7 +40,68 @@ module top(input CI, I0, output [1:0] CO, output O);  endmodule  EOT -equiv_opt -assert -map +/ice40/cells_map.v -map +/ice40/cells_sim.v ice40_opt +equiv_opt -assert -map %unmap -map +/ice40/cells_sim.v ice40_opt  design -load postopt  select -assert-count 1 t:*  select -assert-count 1 t:$lut + +# https://github.com/YosysHQ/yosys/issues/1543 +design -reset +read_verilog <<EOT +module delay_element (input wire clk, input wire reset, input wire enable, +                      input wire chainin,  output wire chainout, output reg latch); + + +   reg                           const_zero = 0; +   reg                           const_one = 1; + +    wire                         delay_tap; + + +   //carry logic +   (* keep *) SB_CARRY carry ( .CO(chainout), .I0(const_zero), +                    .I1(const_one), .CI(chainin)); + + +   //flip flop latch +   (* keep *) SB_DFFER flipflop( .Q(latch), .C(clk), .E(enable), +                      .D(delay_tap), .R(reset)); + + +   //LUT table +   // the LUT should just echo the carry in (I3) +   // carry I0 = LUT I1 +   // carry I1 = LUT I2 +   // carry in = LUT I3 +   // LUT_INIT[0] = 0 +   // LUT_INIT[1] = 0 +   // LUT_INIT[2] = 0 +   // LUT_INIT[3] = 0 +   // LUT_INIT[4] = 0 +   // LUT_INIT[5] = 0 +   // LUT_INIT[6] = 0 +   // LUT_INIT[7] = 0 +   // LUT_INIT[8] = 1 +   // LUT_INIT[9] = 1 +   // LUT_INIT[10] = 1 +   // LUT_INIT[11] = 1 +   // LUT_INIT[12] = 1 +   // LUT_INIT[13] = 1 +   // LUT_INIT[14] = 1 +   // LUT_INIT[15] = 1 + +   (* keep *) SB_LUT4 lut( .O(delay_tap), .I0(const_zero), .I1(const_zero), +                .I2(const_one), .I3(chainin)); + +   //TODO: is this the right way round?? +   defparam lut.LUT_INIT=16'hFF00; + + +endmodule // delay_element +EOT + +synth_ice40 +select -assert-count 1 t:SB_LUT4 +select -assert-count 1 t:SB_CARRY +select -assert-count 1 t:SB_CARRY a:keep %i +select -assert-count 1 t:SB_CARRY c:carry %i diff --git a/tests/arch/ice40/ice40_wrapcarry.ys b/tests/arch/ice40/ice40_wrapcarry.ys new file mode 100644 index 000000000..fb9fccc3a --- /dev/null +++ b/tests/arch/ice40/ice40_wrapcarry.ys @@ -0,0 +1,54 @@ +read_verilog <<EOT +module top(input A, B, CI, output O, CO); +	SB_CARRY carry ( +		.I0(A), +		.I1(B), +		.CI(CI), +		.CO(CO) +	); +	SB_LUT4 #( +		.LUT_INIT(16'b 0110_1001_1001_0110) +	) adder ( +		.I0(1'b0), +		.I1(A), +		.I2(B), +		.I3(1'b0), +		.O(O) +	); +endmodule +EOT + +ice40_wrapcarry +select -assert-count 1 t:$__ICE40_CARRY_WRAPPER + +design -reset +read_verilog <<EOT +module top(input A, B, CI, output O, CO); +    (* foo = "bar", answer = 42, keep=0 *) +	SB_CARRY carry ( +		.I0(A), +		.I1(B), +		.CI(CI), +		.CO(CO) +	); +    (* keep, blah="blah", answer = 43 *) +	SB_LUT4 #( +		.LUT_INIT(16'b 0110_1001_1001_0110) +	) adder ( +		.I0(1'b0), +		.I1(A), +		.I2(B), +		.I3(1'b0), +		.O(O) +	); +endmodule +EOT + +ice40_wrapcarry +select -assert-count 1 t:$__ICE40_CARRY_WRAPPER +select -assert-count 0 t:* t:$__ICE40_CARRY_WRAPPER %d +select -assert-count 1 a:keep=1 a:SB_CARRY.\foo=bar %i a:SB_CARRY.\answer=42 %i a:SB_LUT4.\blah=blah %i a:SB_LUT4.\answer=43 %i + +ice40_wrapcarry -unwrap +select -assert-count 1 c:carry a:src=<<EOT:3 %i a:keep=0 %i a:foo=bar %i a:answer=42 %i +select -assert-count 1 c:adder a:src=<<EOT:10 %i a:keep=1 %i a:blah=blah %i a:answer=43 %i diff --git a/tests/arch/ice40/wrapcarry.ys b/tests/arch/ice40/wrapcarry.ys deleted file mode 100644 index 10c029e68..000000000 --- a/tests/arch/ice40/wrapcarry.ys +++ /dev/null @@ -1,22 +0,0 @@ -read_verilog <<EOT -module top(input A, B, CI, output O, CO); -	SB_CARRY carry ( -		.I0(A), -		.I1(B), -		.CI(CI), -		.CO(CO) -	); -	SB_LUT4 #( -		.LUT_INIT(16'b 0110_1001_1001_0110) -	) adder ( -		.I0(1'b0), -		.I1(A), -		.I2(B), -		.I3(1'b0), -		.O(O) -	); -endmodule -EOT - -ice40_wrapcarry -select -assert-count 1 t:$__ICE40_CARRY_WRAPPER diff --git a/tests/arch/xilinx/dsp_fastfir.ys b/tests/arch/xilinx/dsp_fastfir.ys new file mode 100644 index 000000000..0067a822b --- /dev/null +++ b/tests/arch/xilinx/dsp_fastfir.ys @@ -0,0 +1,69 @@ +read_verilog <<EOT +// Citation https://github.com/ZipCPU/dspfilters/blob/master/rtl/fastfir.v +module fastfir_dynamictaps(i_clk, i_reset, i_tap_wr, i_tap, i_ce, i_sample, o_result); +  wire [30:0] _00_; +  wire [23:0] _01_; +  wire [11:0] _02_; +  wire [30:0] _03_; +  wire [23:0] _04_; +  wire [30:0] _05_; +  wire [23:0] _06_; +  wire [30:0] _07_; +  wire [23:0] _08_; +  wire [11:0] _09_; +  wire [30:0] _10_; +  wire [23:0] _11_; +  wire [30:0] _12_; +  wire [23:0] _13_; +  wire [11:0] \fir.FILTER[0].tapk.delayed_sample ; +  reg [30:0] \fir.FILTER[0].tapk.o_acc  = 31'h00000000; +  wire [11:0] \fir.FILTER[0].tapk.o_sample ; +  reg [23:0] \fir.FILTER[0].tapk.product ; +  reg [11:0] \fir.FILTER[0].tapk.tap  = 12'h000; +  wire [11:0] \fir.FILTER[1].tapk.delayed_sample ; +  wire [30:0] \fir.FILTER[1].tapk.o_acc ; +  wire [11:0] \fir.FILTER[1].tapk.o_sample ; +  reg [23:0] \fir.FILTER[1].tapk.product ; +  reg [11:0] \fir.FILTER[1].tapk.tap  = 12'h000; +  input i_ce; +  input i_clk; +  input i_reset; +  input [11:0] i_sample; +  input [11:0] i_tap; +  input i_tap_wr; +  output [30:0] o_result; +  reg [30:0] o_result; +  assign _03_ = 31'h00000000 + { \fir.FILTER[0].tapk.product [23], \fir.FILTER[0].tapk.product [23], \fir.FILTER[0].tapk.product [23], \fir.FILTER[0].tapk.product [23], \fir.FILTER[0].tapk.product [23], \fir.FILTER[0].tapk.product [23], \fir.FILTER[0].tapk.product [23], \fir.FILTER[0].tapk.product  }; +  assign _04_ = $signed(\fir.FILTER[0].tapk.tap ) * $signed(i_sample); +  always @(posedge i_clk) +      \fir.FILTER[0].tapk.tap  <= _02_; +  always @(posedge i_clk) +      \fir.FILTER[0].tapk.o_acc  <= _00_; +  always @(posedge i_clk) +      \fir.FILTER[0].tapk.product  <= _01_; +  assign _02_ = i_tap_wr ? i_tap : \fir.FILTER[0].tapk.tap ; +  assign _05_ = i_ce ? _03_ : \fir.FILTER[0].tapk.o_acc ; +  assign _00_ = i_reset ? 31'h00000000 : _05_; +  assign _06_ = i_ce ? _04_ : \fir.FILTER[0].tapk.product ; +  assign _01_ = i_reset ? 24'h000000 : _06_; +  assign _10_ = \fir.FILTER[0].tapk.o_acc  + { \fir.FILTER[1].tapk.product [23], \fir.FILTER[1].tapk.product [23], \fir.FILTER[1].tapk.product [23], \fir.FILTER[1].tapk.product [23], \fir.FILTER[1].tapk.product [23], \fir.FILTER[1].tapk.product [23], \fir.FILTER[1].tapk.product [23], \fir.FILTER[1].tapk.product  }; +  assign _11_ = $signed(\fir.FILTER[1].tapk.tap ) * $signed(i_sample); +  always @(posedge i_clk) +      \fir.FILTER[1].tapk.tap  <= _09_; +  always @(posedge i_clk) +      o_result <= _07_; +  always @(posedge i_clk) +      \fir.FILTER[1].tapk.product  <= _08_; +  assign _09_ = i_tap_wr ? \fir.FILTER[0].tapk.tap  : \fir.FILTER[1].tapk.tap ; +  assign _12_ = i_ce ? _10_ : o_result; +  assign _07_ = i_reset ? 31'h00000000 : _12_; +  assign _13_ = i_ce ? _11_ : \fir.FILTER[1].tapk.product ; +  assign _08_ = i_reset ? 24'h000000 : _13_; +  assign \fir.FILTER[1].tapk.o_acc  = o_result; +endmodule +EOT + +synth_xilinx +cd fastfir_dynamictaps +select -assert-count 2 t:DSP48E1 +select -assert-none t:* t:DSP48E1 %d t:BUFG %d diff --git a/tests/arch/xilinx/macc.sh b/tests/arch/xilinx/macc.sh index 2272679ee..154a29848 100644 --- a/tests/arch/xilinx/macc.sh +++ b/tests/arch/xilinx/macc.sh @@ -1,3 +1,3 @@ -../../../yosys -qp "synth_xilinx -top macc2; rename -top macc2_uut" macc.v -o macc_uut.v +../../../yosys -qp "synth_xilinx -top macc2; rename -top macc2_uut" -o macc_uut.v macc.v  iverilog -o test_macc macc_tb.v macc_uut.v macc.v ../../../techlibs/xilinx/cells_sim.v  vvp -N ./test_macc diff --git a/tests/opt/bug1525.ys b/tests/opt/bug1525.ys new file mode 100644 index 000000000..972bc0ac7 --- /dev/null +++ b/tests/opt/bug1525.ys @@ -0,0 +1,13 @@ +read_verilog << EOF +module top(...); +input A1, A2, B, S; +output O; + +assign O = S ? (A1 & B) : (A2 & B); + +endmodule +EOF + +simplemap +opt_share +dump diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v index 64b625efe..de60619d1 100644 --- a/tests/simple_abc9/abc9.v +++ b/tests/simple_abc9/abc9.v @@ -218,12 +218,6 @@ module MUXF8(input I0, I1, S, output O);  endmodule  // Citation: https://github.com/alexforencich/verilog-ethernet -// TODO: yosys -p "synth_xilinx -abc9 -top abc9_test022" abc9.v -q -// returns before b4321a31 -//   Warning: Wire abc9_test022.\m_eth_payload_axis_tkeep [7] is used but has no -//   driver. -//   Warning: Wire abc9_test022.\m_eth_payload_axis_tkeep [3] is used but has no -//   driver.  module abc9_test022  (      input  wire        clk, @@ -237,9 +231,6 @@ module abc9_test022  endmodule  // Citation: https://github.com/riscv/riscv-bitmanip -// TODO: yosys -p "synth_xilinx -abc9 -top abc9_test023" abc9.v -q -// returns before 14233843 -//   Warning: Wire abc9_test023.\dout [1] is used but has no driver.  module abc9_test023 #(  	parameter integer N = 2,  	parameter integer M = 2 @@ -267,3 +258,9 @@ module abc9_test026(output [3:0] o, p);  assign o = { 1'b1, 1'bx };  assign p = { 1'b1, 1'bx, 1'b0 };  endmodule + +module abc9_test030(input [3:0] d, input en, output reg [3:0] q); +always @* +  if (en) +    q <= d; +endmodule diff --git a/tests/techmap/iopadmap.ys b/tests/techmap/iopadmap.ys new file mode 100644 index 000000000..f4345e906 --- /dev/null +++ b/tests/techmap/iopadmap.ys @@ -0,0 +1,99 @@ +read_verilog << EOT +module ibuf ((* iopad_external_pin *) input i, output o); endmodule +module obuf (input i, (* iopad_external_pin *) output o); endmodule +module obuft (input i, input oe, (* iopad_external_pin *) output o); endmodule +module iobuf (input i, input oe, output o, (* iopad_external_pin *) inout io); endmodule + +module a(input i, output o); +assign o = i; +endmodule + +module b(input i, output o); +assign o = i; +ibuf b (.i(i), .o(o)); +endmodule + +module c(input i, output o); +obuf b (.i(i), .o(o)); +endmodule + +module d(input i, oe, output o, o2, o3); +assign o = oe ? i : 1'bz; +assign o2 = o; +assign o3 = ~o; +endmodule + +module e(input i, oe, inout io, output o2, o3); +assign io = oe ? i : 1'bz; +assign o2 = io; +assign o3 = ~io; +endmodule +EOT + +opt_clean +tribuf +simplemap +iopadmap -bits -inpad ibuf o:i -outpad obuf i:o -toutpad obuft oe:i:o -tinoutpad iobuf oe:o:i:io +opt_clean + +select -assert-count 1 a/t:ibuf +select -assert-count 1 a/t:obuf +select -set ib w:i %a %co a/t:ibuf %i +select -set ob w:o %a %ci a/t:obuf %i +select -assert-count 1 @ib +select -assert-count 1 @ob +select -assert-count 1 @ib %co %co @ob %i + +select -assert-count 1 b/t:ibuf +select -assert-count 1 b/t:obuf +select -set ib w:i %a %co b/t:ibuf %i +select -set ob w:o %a %ci b/t:obuf %i +select -assert-count 1 @ib +select -assert-count 1 @ob +select -assert-count 1 @ib %co %co @ob %i + +select -assert-count 1 c/t:ibuf +select -assert-count 1 c/t:obuf +select -set ib w:i %a %co c/t:ibuf %i +select -set ob w:o %a %ci c/t:obuf %i +select -assert-count 1 @ib +select -assert-count 1 @ob +select -assert-count 1 @ib %co %co @ob %i + +select -assert-count 2 d/t:ibuf +select -assert-count 2 d/t:obuf +select -assert-count 1 d/t:obuft +select -set ib w:i %a %co d/t:ibuf %i +select -set oeb w:oe %a %co d/t:ibuf %i +select -set ob w:o %a %ci d/t:obuft %i +select -set o2b w:o2 %a %ci d/t:obuf %i +select -set o3b w:o3 %a %ci d/t:obuf %i +select -assert-count 1 @ib +select -assert-count 1 @oeb +select -assert-count 1 @ob +select -assert-count 1 @o2b +select -assert-count 1 @o3b +select -assert-count 1 @ib %co %co @ob %i +select -assert-count 1 @oeb %co %co @ob %i +select -assert-count 1 @ib %co %co @o2b %i +select -assert-count 1 @ib %co %co t:$_NOT_ %i +select -assert-count 1 @o3b %ci %ci t:$_NOT_ %i + +select -assert-count 2 e/t:ibuf +select -assert-count 2 e/t:obuf +select -assert-count 1 e/t:iobuf +select -set ib w:i %a %co e/t:ibuf %i +select -set oeb w:oe %a %co e/t:ibuf %i +select -set iob w:io %a %ci e/t:iobuf %i +select -set o2b w:o2 %a %ci e/t:obuf %i +select -set o3b w:o3 %a %ci e/t:obuf %i +select -assert-count 1 @ib +select -assert-count 1 @oeb +select -assert-count 1 @iob +select -assert-count 1 @o2b +select -assert-count 1 @o3b +select -assert-count 1 @ib %co %co @iob %i +select -assert-count 1 @oeb %co %co @iob %i +select -assert-count 1 @iob %co %co @o2b %i +select -assert-count 1 @iob %co %co t:$_NOT_ %i +select -assert-count 1 @o3b %ci %ci t:$_NOT_ %i  | 
