diff options
| author | Jim Lawson <ucbjrl@berkeley.edu> | 2019-04-01 11:09:12 -0700 | 
|---|---|---|
| committer | Jim Lawson <ucbjrl@berkeley.edu> | 2019-04-01 11:09:12 -0700 | 
| commit | b8dfda876795dbf08bec49ab06ac8603025d2114 (patch) | |
| tree | 35cd5485c70c17e93426d54a104018bae90ed924 /techlibs | |
| parent | 6d2ea6fe5563205c0f565810d615c4900d4508d8 (diff) | |
| parent | 22035c20ff071ec5c30990258850ecf97de5d5b3 (diff) | |
| download | yosys-b8dfda876795dbf08bec49ab06ac8603025d2114.tar.gz yosys-b8dfda876795dbf08bec49ab06ac8603025d2114.tar.bz2 yosys-b8dfda876795dbf08bec49ab06ac8603025d2114.zip  | |
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'techlibs')
| -rw-r--r-- | techlibs/ecp5/ecp5_ffinit.cc | 9 | ||||
| -rw-r--r-- | techlibs/ice40/Makefile.inc | 1 | ||||
| -rw-r--r-- | techlibs/ice40/cells_sim.v | 75 | ||||
| -rw-r--r-- | techlibs/ice40/ice40_braminit.cc | 159 | ||||
| -rw-r--r-- | techlibs/ice40/synth_ice40.cc | 1 | ||||
| -rw-r--r-- | techlibs/sf2/cells_map.v | 64 | ||||
| -rw-r--r-- | techlibs/sf2/cells_sim.v | 281 | ||||
| -rw-r--r-- | techlibs/sf2/sf2_iobs.cc | 217 | ||||
| -rw-r--r-- | techlibs/sf2/synth_sf2.cc | 16 | ||||
| -rw-r--r-- | techlibs/xilinx/Makefile.inc | 3 | ||||
| -rw-r--r-- | techlibs/xilinx/arith_map.v | 282 | ||||
| -rw-r--r-- | techlibs/xilinx/cells_map.v | 104 | ||||
| -rw-r--r-- | techlibs/xilinx/cells_sim.v | 65 | ||||
| -rw-r--r-- | techlibs/xilinx/cells_xtra.sh | 17 | ||||
| -rw-r--r-- | techlibs/xilinx/cells_xtra.v | 24 | ||||
| -rw-r--r-- | techlibs/xilinx/ff_map.v | 42 | ||||
| -rw-r--r-- | techlibs/xilinx/lut2lut.v | 65 | ||||
| -rw-r--r-- | techlibs/xilinx/lut_map.v | 94 | ||||
| -rw-r--r-- | techlibs/xilinx/synth_xilinx.cc | 72 | 
19 files changed, 1238 insertions, 353 deletions
diff --git a/techlibs/ecp5/ecp5_ffinit.cc b/techlibs/ecp5/ecp5_ffinit.cc index 02945fff4..dbd16cac9 100644 --- a/techlibs/ecp5/ecp5_ffinit.cc +++ b/techlibs/ecp5/ecp5_ffinit.cc @@ -79,10 +79,12 @@ struct Ecp5FfinitPass : public Pass {  						continue;  					if (initbits.count(bit)) { -						if (initbits.at(bit) != val) -							log_error("Conflicting init values for signal %s (%s = %s, %s = %s).\n", +						if (initbits.at(bit) != val) { +							log_warning("Conflicting init values for signal %s (%s = %s, %s = %s).\n",  									log_signal(bit), log_signal(SigBit(wire, i)), log_signal(val),  									log_signal(initbit_to_wire[bit]), log_signal(initbits.at(bit))); +							initbits.at(bit) = State::Sx; +						}  						continue;  					} @@ -121,6 +123,9 @@ struct Ecp5FfinitPass : public Pass {  				State val = initbits.at(bit_q); +				if (val == State::Sx) +					continue; +  				log("FF init value for cell %s (%s): %s = %c\n", log_id(cell), log_id(cell->type),  						log_signal(bit_q), val != State::S0 ? '1' : '0');  				// Initval is the same as the reset state. Matches hardware, nowt more to do diff --git a/techlibs/ice40/Makefile.inc b/techlibs/ice40/Makefile.inc index 2750901c8..723b59d6f 100644 --- a/techlibs/ice40/Makefile.inc +++ b/techlibs/ice40/Makefile.inc @@ -1,5 +1,6 @@  OBJS += techlibs/ice40/synth_ice40.o +OBJS += techlibs/ice40/ice40_braminit.o  OBJS += techlibs/ice40/ice40_ffssr.o  OBJS += techlibs/ice40/ice40_ffinit.o  OBJS += techlibs/ice40/ice40_opt.o diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index 2041693cc..62a28364b 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -326,6 +326,8 @@ module SB_RAM40_4K (  	parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;  	parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000; +	parameter INIT_FILE = ""; +  `ifndef BLACKBOX  	wire [15:0] WMASK_I;  	wire [15:0] RMASK_I; @@ -408,43 +410,27 @@ module SB_RAM40_4K (  	reg [15:0] memory [0:255];  	initial begin -		for (i=0; i<16; i=i+1) begin -`ifdef YOSYS -			memory[ 0*16 + i] <= INIT_0[16*i +: 16]; -			memory[ 1*16 + i] <= INIT_1[16*i +: 16]; -			memory[ 2*16 + i] <= INIT_2[16*i +: 16]; -			memory[ 3*16 + i] <= INIT_3[16*i +: 16]; -			memory[ 4*16 + i] <= INIT_4[16*i +: 16]; -			memory[ 5*16 + i] <= INIT_5[16*i +: 16]; -			memory[ 6*16 + i] <= INIT_6[16*i +: 16]; -			memory[ 7*16 + i] <= INIT_7[16*i +: 16]; -			memory[ 8*16 + i] <= INIT_8[16*i +: 16]; -			memory[ 9*16 + i] <= INIT_9[16*i +: 16]; -			memory[10*16 + i] <= INIT_A[16*i +: 16]; -			memory[11*16 + i] <= INIT_B[16*i +: 16]; -			memory[12*16 + i] <= INIT_C[16*i +: 16]; -			memory[13*16 + i] <= INIT_D[16*i +: 16]; -			memory[14*16 + i] <= INIT_E[16*i +: 16]; -			memory[15*16 + i] <= INIT_F[16*i +: 16]; -`else -			memory[ 0*16 + i] = INIT_0[16*i +: 16]; -			memory[ 1*16 + i] = INIT_1[16*i +: 16]; -			memory[ 2*16 + i] = INIT_2[16*i +: 16]; -			memory[ 3*16 + i] = INIT_3[16*i +: 16]; -			memory[ 4*16 + i] = INIT_4[16*i +: 16]; -			memory[ 5*16 + i] = INIT_5[16*i +: 16]; -			memory[ 6*16 + i] = INIT_6[16*i +: 16]; -			memory[ 7*16 + i] = INIT_7[16*i +: 16]; -			memory[ 8*16 + i] = INIT_8[16*i +: 16]; -			memory[ 9*16 + i] = INIT_9[16*i +: 16]; -			memory[10*16 + i] = INIT_A[16*i +: 16]; -			memory[11*16 + i] = INIT_B[16*i +: 16]; -			memory[12*16 + i] = INIT_C[16*i +: 16]; -			memory[13*16 + i] = INIT_D[16*i +: 16]; -			memory[14*16 + i] = INIT_E[16*i +: 16]; -			memory[15*16 + i] = INIT_F[16*i +: 16]; -`endif -		end +		if (INIT_FILE != "") +			$readmemh(INIT_FILE, memory); +		else +			for (i=0; i<16; i=i+1) begin +				memory[ 0*16 + i] = INIT_0[16*i +: 16]; +				memory[ 1*16 + i] = INIT_1[16*i +: 16]; +				memory[ 2*16 + i] = INIT_2[16*i +: 16]; +				memory[ 3*16 + i] = INIT_3[16*i +: 16]; +				memory[ 4*16 + i] = INIT_4[16*i +: 16]; +				memory[ 5*16 + i] = INIT_5[16*i +: 16]; +				memory[ 6*16 + i] = INIT_6[16*i +: 16]; +				memory[ 7*16 + i] = INIT_7[16*i +: 16]; +				memory[ 8*16 + i] = INIT_8[16*i +: 16]; +				memory[ 9*16 + i] = INIT_9[16*i +: 16]; +				memory[10*16 + i] = INIT_A[16*i +: 16]; +				memory[11*16 + i] = INIT_B[16*i +: 16]; +				memory[12*16 + i] = INIT_C[16*i +: 16]; +				memory[13*16 + i] = INIT_D[16*i +: 16]; +				memory[14*16 + i] = INIT_E[16*i +: 16]; +				memory[15*16 + i] = INIT_F[16*i +: 16]; +			end  	end  	always @(posedge WCLK) begin @@ -504,6 +490,8 @@ module SB_RAM40_4KNR (  	parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;  	parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000; +	parameter INIT_FILE = ""; +  	SB_RAM40_4K #(  		.WRITE_MODE(WRITE_MODE),  		.READ_MODE (READ_MODE ), @@ -522,7 +510,8 @@ module SB_RAM40_4KNR (  		.INIT_C    (INIT_C    ),  		.INIT_D    (INIT_D    ),  		.INIT_E    (INIT_E    ), -		.INIT_F    (INIT_F    ) +		.INIT_F    (INIT_F    ), +		.INIT_FILE (INIT_FILE )  	) RAM (  		.RDATA(RDATA),  		.RCLK (~RCLKN), @@ -566,6 +555,8 @@ module SB_RAM40_4KNW (  	parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;  	parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000; +	parameter INIT_FILE = ""; +  	SB_RAM40_4K #(  		.WRITE_MODE(WRITE_MODE),  		.READ_MODE (READ_MODE ), @@ -584,7 +575,8 @@ module SB_RAM40_4KNW (  		.INIT_C    (INIT_C    ),  		.INIT_D    (INIT_D    ),  		.INIT_E    (INIT_E    ), -		.INIT_F    (INIT_F    ) +		.INIT_F    (INIT_F    ), +		.INIT_FILE (INIT_FILE )  	) RAM (  		.RDATA(RDATA),  		.RCLK (RCLK ), @@ -628,6 +620,8 @@ module SB_RAM40_4KNRNW (  	parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;  	parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000; +	parameter INIT_FILE = ""; +  	SB_RAM40_4K #(  		.WRITE_MODE(WRITE_MODE),  		.READ_MODE (READ_MODE ), @@ -646,7 +640,8 @@ module SB_RAM40_4KNRNW (  		.INIT_C    (INIT_C    ),  		.INIT_D    (INIT_D    ),  		.INIT_E    (INIT_E    ), -		.INIT_F    (INIT_F    ) +		.INIT_F    (INIT_F    ), +		.INIT_FILE (INIT_FILE )  	) RAM (  		.RDATA(RDATA),  		.RCLK (~RCLKN), diff --git a/techlibs/ice40/ice40_braminit.cc b/techlibs/ice40/ice40_braminit.cc new file mode 100644 index 000000000..4fa6b0792 --- /dev/null +++ b/techlibs/ice40/ice40_braminit.cc @@ -0,0 +1,159 @@ +/* + *  yosys -- Yosys Open SYnthesis Suite + * + *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> + * + *  Permission to use, copy, modify, and/or distribute this software for any + *  purpose with or without fee is hereby granted, provided that the above + *  copyright notice and this permission notice appear in all copies. + * + *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/yosys.h" +#include "kernel/sigtools.h" +#include <stdlib.h> +#include <stdio.h> +#include <bitset> + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +static void run_ice40_braminit(Module *module) +{ +	for (auto cell : module->selected_cells()) +	{ +		uint16_t mem[256]; + +		/* Only consider cells we're interested in */ +		if (cell->type != "\\SB_RAM40_4K" && +		    cell->type != "\\SB_RAM40_4KNR" && +		    cell->type != "\\SB_RAM40_4KNW" && +		    cell->type != "\\SB_RAM40_4KNRNW") +			continue; +		if (!cell->hasParam("\\INIT_FILE")) +			continue; +		std::string init_file = cell->getParam("\\INIT_FILE").decode_string(); +		cell->unsetParam("\\INIT_FILE"); +		if (init_file == "") +			continue; + +		/* Open file */ +		log("Processing %s : %s\n", RTLIL::id2cstr(cell->name), init_file.c_str()); + +		std::ifstream f; +		f.open(init_file.c_str()); +		if (f.fail()) { +			log("Can not open file `%s`.\n", init_file.c_str()); +			continue; +		} + +		/* Defaults to 0 */ +		memset(mem, 0x00, sizeof(mem)); + +		/* Process each line */ +		bool in_comment = false; +		int cursor = 0; + +		while (!f.eof()) +		{ +			std::string line, token; +			std::getline(f, line); + +			for (int i = 0; i < GetSize(line); i++) +			{ +				if (in_comment && line.substr(i, 2) == "*/") { +					line[i] = ' '; +					line[i+1] = ' '; +					in_comment = false; +					continue; +				} +				if (!in_comment && line.substr(i, 2) == "/*") +					in_comment = true; +				if (in_comment) +					line[i] = ' '; +			} + +			while (1) +			{ +				bool set_cursor = false; +				long value; + +				token = next_token(line, " \t\r\n"); +				if (token.empty() || token.substr(0, 2) == "//") +					break; + +				if (token[0] == '@') { +					token = token.substr(1); +					set_cursor = true; +				} + +				const char *nptr = token.c_str(); +				char *endptr; +				value = strtol(nptr, &endptr, 16); +				if (!*nptr || *endptr) { +					log("Can not parse %s `%s` for %s.\n", +						set_cursor ? "address" : "value", +						nptr, token.c_str() +					); +					continue; +				} + +				if (set_cursor) +					cursor = value; +				else if (cursor >= 0 && cursor < 256) +					mem[cursor++] = value; +				else +					log("Attempt to initialize non existent address %d\n", cursor); +			} +		} + +		/* Set attributes */ +		const char *hex = "0123456789ABCDEF"; +		for (int i=0; i<16; i++) { +			std::string val = ""; +			for (int j=15; j>=0; j--) +				val += std::bitset<16>(mem[i*16+j]).to_string(); +			cell->setParam("\\INIT_" + std::string(1, hex[i]), RTLIL::Const::from_string(val)); +		} +	} +} + +struct Ice40BRAMInitPass : public Pass { +	Ice40BRAMInitPass() : Pass("ice40_braminit", "iCE40: perform SB_RAM40_4K initialization from file") { } +	void help() YS_OVERRIDE +	{ +		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +		log("\n"); +		log("    ice40_braminit\n"); +		log("\n"); +		log("This command processes all SB_RAM40_4K blocks with a non-empty INIT_FILE\n"); +		log("parameter and converts it into the required INIT_x attributes\n"); +		log("\n"); +	} +	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE +	{ +		log_header(design, "Executing ICE40_BRAMINIT pass.\n"); + +		size_t argidx; +		for (argidx = 1; argidx < args.size(); argidx++) { +			// if (args[argidx] == "-???") { +			//  continue; +			// } +			break; +		} +		extra_args(args, argidx, design); + +		for (auto module : design->selected_modules()) +			run_ice40_braminit(module); +	} +} Ice40BRAMInitPass; + +PRIVATE_NAMESPACE_END diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 34501b335..8899bfcc4 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -257,6 +257,7 @@ struct SynthIce40Pass : public ScriptPass  		{  			run("memory_bram -rules +/ice40/brams.txt");  			run("techmap -map +/ice40/brams_map.v"); +			run("ice40_braminit");  		}  		if (check_label("map")) diff --git a/techlibs/sf2/cells_map.v b/techlibs/sf2/cells_map.v index 5b8888294..6ad7807d2 100644 --- a/techlibs/sf2/cells_map.v +++ b/techlibs/sf2/cells_map.v @@ -1,40 +1,54 @@ -// module  \$_DFF_N_ (input D, C, output Q); SB_DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule +module  \$_DFF_N_ (input D, C, output Q); +  SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(1'b1), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule  module  \$_DFF_P_ (input D, C, output Q); -  SLE _TECHMAP_REPLACE_ ( -    .D(D), -    .CLK(C), -    .EN(1'b1), -    .ALn(1'b1), -    .ADn(1'b1), -    .SLn(1'b1), -    .SD(1'b0), -    .LAT(1'b0), -    .Q(Q) -  ); +  SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(1'b1), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFF_NN0_ (input D, C, R, output Q); +  SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFF_NN1_ (input D, C, R, output Q); +  SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFF_NP0_ (input D, C, R, output Q); +  SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(!R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFF_NP1_ (input D, C, R, output Q); +  SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(!R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFF_PN0_ (input D, C, R, output Q); +  SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFF_PN1_ (input D, C, R, output Q); +  SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFF_PP0_ (input D, C, R, output Q); +  SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(!R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFF_PP1_ (input D, C, R, output Q); +  SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(!R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));  endmodule  // module  \$_DFFE_NN_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule  // module  \$_DFFE_PN_ (input D, C, E, output Q); SB_DFFE  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule -//  +//  // module  \$_DFFE_NP_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule  // module  \$_DFFE_PP_ (input D, C, E, output Q); SB_DFFE  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule -//  -// module  \$_DFF_NN0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule -// module  \$_DFF_NN1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule -// module  \$_DFF_PN0_ (input D, C, R, output Q); SB_DFFR  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule -// module  \$_DFF_PN1_ (input D, C, R, output Q); SB_DFFS  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule -//  -// module  \$_DFF_NP0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule -// module  \$_DFF_NP1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule -// module  \$_DFF_PP0_ (input D, C, R, output Q); SB_DFFR  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule -// module  \$_DFF_PP1_ (input D, C, R, output Q); SB_DFFS  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule -//  +//  // module  \$__DFFE_NN0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule  // module  \$__DFFE_NN1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule  // module  \$__DFFE_PN0 (input D, C, E, R, output Q); SB_DFFER  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule  // module  \$__DFFE_PN1 (input D, C, E, R, output Q); SB_DFFES  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule -//  +//  // module  \$__DFFE_NP0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule  // module  \$__DFFE_NP1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule  // module  \$__DFFE_PP0 (input D, C, E, R, output Q); SB_DFFER  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule diff --git a/techlibs/sf2/cells_sim.v b/techlibs/sf2/cells_sim.v index f967068af..c62748b11 100644 --- a/techlibs/sf2/cells_sim.v +++ b/techlibs/sf2/cells_sim.v @@ -1,3 +1,114 @@ +// https://coredocs.s3.amazonaws.com/Libero/12_0_0/Tool/sf2_mlg.pdf + +module ADD2 ( + +	input A, B, +	output Y +); +	assign Y = A & B; +endmodule + +module ADD3 ( +	input A, B, C, +	output Y +); +	assign Y = A & B & C; +endmodule + +module ADD4 ( +	input A, B, C, D, +	output Y +); +	assign Y = A & B & C & D; +endmodule + +module CFG1 ( +	output Y, +	input A +); +	parameter [1:0] INIT = 2'h0; +	assign Y = INIT >> A; +endmodule + +module CFG2 ( +	output Y, +	input A, +	input B +); +	parameter [3:0] INIT = 4'h0; +	assign Y = INIT >> {B, A}; +endmodule + +module CFG3 ( +	output Y, +	input A, +	input B, +	input C +); +	parameter [7:0] INIT = 8'h0; +	assign Y = INIT >> {C, B, A}; +endmodule + +module CFG4 ( +	output Y, +	input A, +	input B, +	input C, +	input D +); +	parameter [15:0] INIT = 16'h0; +	assign Y = INIT >> {D, C, B, A}; +endmodule + +module BUFF ( +	input A, +	output Y +); +	assign Y = A; +endmodule + +module BUFD ( +	input A, +	output Y +); +	assign Y = A; +endmodule + +module CLKINT ( +	input A, +	output Y +); +	assign Y = A; +endmodule + +module CLKINT_PRESERVE ( +	input A, +	output Y +); +	assign Y = A; +endmodule + +module GCLKINT ( +	input A, EN, +	output Y +); +	assign Y = A & EN; +endmodule + +module RCLKINT ( +	input A, +	output Y +); +	assign Y = A; +endmodule + +module RGCLKINT ( +	input A, EN, +	output Y +); +	assign Y = A & EN; +endmodule +  module SLE (  	output Q,  	input ADn, @@ -36,44 +147,151 @@ module SLE (  	assign Q = LAT ? q_latch : q_ff;  endmodule -module CFG1 ( -	output Y, -	input A +// module AR1 +// module FCEND_BUFF +// module FCINIT_BUFF +// module FLASH_FREEZE +// module OSCILLATOR +// module SYSRESET +// module SYSCTRL_RESET_STATUS +// module LIVE_PROBE_FB +// module GCLKBUF +// module GCLKBUF_DIFF +// module GCLKBIBUF +// module DFN1 +// module DFN1C0 +// module DFN1E1 +// module DFN1E1C0 +// module DFN1E1P0 +// module DFN1P0 +// module DLN1 +// module DLN1C0 +// module DLN1P0 + +module INV ( +	input A, +	output Y  ); -	parameter [1:0] INIT = 2'h0; -	assign Y = INIT >> A; +	assign Y = !A;  endmodule -module CFG2 ( -	output Y, +module INVD (  	input A, -	input B +	output Y  ); -	parameter [3:0] INIT = 4'h0; -	assign Y = INIT >> {B, A}; +	assign Y = !A;  endmodule -module CFG3 ( -	output Y, -	input A, -	input B, -	input C +module MX2 ( +	input A, B, S, +	output Y  ); -	parameter [7:0] INIT = 8'h0; -	assign Y = INIT >> {C, B, A}; +	assign Y = S ? B : A;  endmodule -module CFG4 ( -	output Y, -	input A, -	input B, -	input C, -	input D +module MX4 ( +	input D0, D1, D2, D3, S0, S1, +	output Y  ); -	parameter [15:0] INIT = 16'h0; -	assign Y = INIT >> {D, C, B, A}; +	assign Y = S1 ? (S0 ? D3 : D2) : (S0 ? D1 : D0); +endmodule + +module NAND2 ( +	input A, B, +	output Y +); +	assign Y = !(A & B); +endmodule + +module NAND3 ( +	input A, B, C, +	output Y +); +	assign Y = !(A & B & C); +endmodule + +module NAND4 ( +	input A, B, C, D, +	output Y +); +	assign Y = !(A & B & C & D); +endmodule + +module NOR2 ( +	input A, B, +	output Y +); +	assign Y = !(A | B); +endmodule + +module NOR3 ( +	input A, B, C, +	output Y +); +	assign Y = !(A | B | C); +endmodule + +module NOR4 ( +	input A, B, C, D, +	output Y +); +	assign Y = !(A | B | C | D);  endmodule +module OR2 ( +	input A, B, +	output Y +); +	assign Y = A | B; +endmodule + +module OR3 ( +	input A, B, C, +	output Y +); +	assign Y = A | B | C; +endmodule + +module OR4 ( +	input A, B, C, D, +	output Y +); +	assign Y = A | B | C | D; +endmodule + +module XOR2 ( +	input A, B, +	output Y +); +	assign Y = A ^ B; +endmodule + +module XOR3 ( +	input A, B, C, +	output Y +); +	assign Y = A ^ B ^ C; +endmodule + +module XOR4 ( +	input A, B, C, D, +	output Y +); +	assign Y = A ^ B ^ C ^ D; +endmodule + +module XOR8 ( +	input A, B, C, D, E, F, G, H, +	output Y +); +	assign Y = A ^ B ^ C ^ D ^ E ^ F ^ G ^ H; +endmodule + +// module UJTAG +// module BIBUF +// module BIBUF_DIFF +// module CLKBIBUF +  module CLKBUF (  	input PAD,  	output Y @@ -81,6 +299,8 @@ module CLKBUF (  	assign Y = PAD;  endmodule +// module CLKBUF_DIFF +  module INBUF (  	input PAD,  	output Y @@ -88,9 +308,20 @@ module INBUF (  	assign Y = PAD;  endmodule +// module INBUF_DIFF +  module OUTBUF (  	input D,  	output PAD  );  	assign PAD = D;  endmodule + +// module OUTBUF_DIFF +// module TRIBUFF +// module TRIBUFF_DIFF +// module DDR_IN +// module DDR_OUT +// module RAM1K18 +// module RAM64x18 +// module MACC diff --git a/techlibs/sf2/sf2_iobs.cc b/techlibs/sf2/sf2_iobs.cc index 27141430c..3d43332e2 100644 --- a/techlibs/sf2/sf2_iobs.cc +++ b/techlibs/sf2/sf2_iobs.cc @@ -23,6 +23,136 @@  USING_YOSYS_NAMESPACE  PRIVATE_NAMESPACE_BEGIN +static void handle_iobufs(Module *module, bool clkbuf_mode) +{ +	SigMap sigmap(module); + +	pool<SigBit> clk_bits; +	pool<SigBit> handled_io_bits; +	dict<SigBit, SigBit> rewrite_bits; +	vector<pair<Cell*, SigBit>> pad_bits; + +	for (auto cell : module->cells()) +	{ +		if (clkbuf_mode && cell->type == "\\SLE") { +			for (auto bit : sigmap(cell->getPort("\\CLK"))) +				clk_bits.insert(bit); +		} +		if (cell->type.in("\\INBUF", "\\OUTBUF", "\\TRIBUFF", "\\BIBUF", "\\CLKBUF", "\\CLKBIBUF", +				"\\INBUF_DIFF", "\\OUTBUF_DIFF", "\\BIBUFF_DIFF", "\\TRIBUFF_DIFF", "\\CLKBUF_DIFF", +				"\\GCLKBUF", "\\GCLKBUF_DIFF", "\\GCLKBIBUF")) { +			for (auto bit : sigmap(cell->getPort("\\PAD"))) +				handled_io_bits.insert(bit); +		} +	} + +	for (auto wire : vector<Wire*>(module->wires())) +	{ +		if (!wire->port_input && !wire->port_output) +			continue; + +		for (int index = 0; index < GetSize(wire); index++) +		{ +			SigBit bit(wire, index); +			SigBit canonical_bit = sigmap(bit); + +			if (handled_io_bits.count(canonical_bit)) +				continue; + +			if (wire->port_input && wire->port_output) +				log_error("Failed to add buffer for inout port bit %s.\n", log_signal(bit)); + +			IdString buf_type, buf_port; + +			if (wire->port_output) { +				buf_type = "\\OUTBUF"; +				buf_port = "\\D"; +			} else if (clkbuf_mode && clk_bits.count(canonical_bit)) { +				buf_type = "\\CLKBUF"; +				buf_port = "\\Y"; +			} else { +				buf_type = "\\INBUF"; +				buf_port = "\\Y"; +			} + +			Cell *c = module->addCell(NEW_ID, buf_type); +			SigBit new_bit = module->addWire(NEW_ID); +			c->setPort(buf_port, new_bit); +			pad_bits.push_back(make_pair(c, bit)); +			rewrite_bits[canonical_bit] = new_bit; + +			log("Added %s cell %s for port bit %s.\n", log_id(c->type), log_id(c), log_signal(bit)); +		} +	} + +	auto rewrite_function = [&](SigSpec &s) { +		for (auto &bit : s) { +			SigBit canonical_bit = sigmap(bit); +			if (rewrite_bits.count(canonical_bit)) +				bit = rewrite_bits.at(canonical_bit); +		} +	}; + +	module->rewrite_sigspecs(rewrite_function); + +	for (auto &it : pad_bits) +		it.first->setPort("\\PAD", it.second); +} + +static void handle_clkint(Module *module) +{ +	SigMap sigmap(module); + +	pool<SigBit> clk_bits; +	vector<SigBit> handled_clk_bits; + +	for (auto cell : module->cells()) +	{ +		if (cell->type == "\\SLE") { +			for (auto bit : sigmap(cell->getPort("\\CLK"))) +				clk_bits.insert(bit); +		} +		if (cell->type.in("\\CLKBUF", "\\CLKBIBUF", "\\CLKBUF_DIFF", "\\GCLKBUF", "\\GCLKBUF_DIFF", "\\GCLKBIBUF", +				"\\CLKINT", "\\CLKINT_PRESERVE", "\\GCLKINT", "\\RCLKINT", "\\RGCLKINT")) { +			for (auto bit : sigmap(cell->getPort("\\Y"))) +				handled_clk_bits.push_back(bit); +		} +	} + +	for (auto bit : handled_clk_bits) +		clk_bits.erase(bit); + +	for (auto cell : vector<Cell*>(module->cells())) +	for (auto &conn : cell->connections()) +	{ +		if (!cell->output(conn.first)) +			continue; + +		SigSpec sig = conn.second; +		bool did_something = false; + +		for (auto &bit : sig) { +			SigBit canonical_bit = sigmap(bit); +			if (clk_bits.count(canonical_bit)) { +				Cell *c = module->addCell(NEW_ID, "\\CLKINT"); +				SigBit new_bit = module->addWire(NEW_ID); +				c->setPort("\\A", new_bit); +				c->setPort("\\Y", bit); +				log("Added %s cell %s for clock signal %s.\n", log_id(c->type), log_id(c), log_signal(bit)); +				clk_bits.erase(canonical_bit); +				did_something = true; +				bit = new_bit; +			} +		} + +		if (did_something) +			cell->setPort(conn.first, sig); +	} + +	for (auto bit : clk_bits) +		log_error("Failed to insert CLKINT for clock signal %s.\n", log_signal(bit)); +} +  struct Sf2IobsPass : public Pass {  	Sf2IobsPass() : Pass("sf2_iobs", "SF2: insert IO buffers") { }  	void help() YS_OVERRIDE @@ -31,20 +161,25 @@ struct Sf2IobsPass : public Pass {  		log("\n");  		log("    sf2_iobs [options] [selection]\n");  		log("\n"); -		log("Add SF2 I/O buffers to top module IOs as needed.\n"); +		log("Add SF2 I/O buffers and global buffers to top module as needed.\n"); +		log("\n"); +		log("    -clkbuf\n"); +		log("        Insert PAD->global_net clock buffers\n");  		log("\n");  	}  	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE  	{ +		bool clkbuf_mode = false; +  		log_header(design, "Executing sf2_iobs pass (insert IO buffers).\n");  		size_t argidx;  		for (argidx = 1; argidx < args.size(); argidx++)  		{ -			// if (args[argidx] == "-singleton") { -			// 	singleton_mode = true; -			// 	continue; -			// } +			if (args[argidx] == "-clkbuf") { +				clkbuf_mode = true; +				continue; +			}  			break;  		}  		extra_args(args, argidx, design); @@ -54,76 +189,8 @@ struct Sf2IobsPass : public Pass {  		if (module == nullptr)  			log_cmd_error("No top module found.\n"); -		SigMap sigmap(module); - -		pool<SigBit> clk_bits; -		pool<SigBit> handled_io_bits; -		dict<SigBit, SigBit> rewrite_bits; -		vector<pair<Cell*, SigBit>> pad_bits; - -		for (auto cell : module->cells()) -		{ -			if (cell->type == "\\SLE") { -				for (auto bit : sigmap(cell->getPort("\\CLK"))) -					clk_bits.insert(bit); -			} -			if (cell->type.in("\\INBUF", "\\OUTBUF", "\\CLKBUF")) { -				for (auto bit : sigmap(cell->getPort("\\PAD"))) -					handled_io_bits.insert(bit); -			} -		} - -		for (auto wire : vector<Wire*>(module->wires())) -		{ -			if (!wire->port_input && !wire->port_output) -				continue; - -			for (int index = 0; index < GetSize(wire); index++) -			{ -				SigBit bit(wire, index); -				SigBit canonical_bit = sigmap(bit); - -				if (handled_io_bits.count(canonical_bit)) -					continue; - -				if (wire->port_input && wire->port_output) -					log_error("Failed to add buffer for inout port bit %s.\n", log_signal(bit)); - -				IdString buf_type, buf_port; - -				if (wire->port_output) { -					buf_type = "\\OUTBUF"; -					buf_port = "\\D"; -				} else if (clk_bits.count(canonical_bit)) { -					buf_type = "\\CLKBUF"; -					buf_port = "\\Y"; -				} else { -					buf_type = "\\INBUF"; -					buf_port = "\\Y"; -				} - -				Cell *c = module->addCell(NEW_ID, buf_type); -				SigBit new_bit = module->addWire(NEW_ID); -				c->setPort(buf_port, new_bit); -				pad_bits.push_back(make_pair(c, bit)); -				rewrite_bits[canonical_bit] = new_bit; - -				log("Added %s cell %s for port bit %s.\n", log_id(c->type), log_id(c), log_signal(bit)); -			} -		} - -		auto rewrite_function = [&](SigSpec &s) { -			for (auto &bit : s) { -				SigBit canonical_bit = sigmap(bit); -				if (rewrite_bits.count(canonical_bit)) -					bit = rewrite_bits.at(canonical_bit); -			} -		}; - -		module->rewrite_sigspecs(rewrite_function); - -		for (auto &it : pad_bits) -			it.first->setPort("\\PAD", it.second); +		handle_iobufs(module, clkbuf_mode); +		handle_clkint(module);  	}  } Sf2IobsPass; diff --git a/techlibs/sf2/synth_sf2.cc b/techlibs/sf2/synth_sf2.cc index bdc20456d..0924df7a6 100644 --- a/techlibs/sf2/synth_sf2.cc +++ b/techlibs/sf2/synth_sf2.cc @@ -63,6 +63,9 @@ struct SynthSf2Pass : public ScriptPass  		log("    -noiobs\n");  		log("        run synthesis in \"block mode\", i.e. do not insert IO buffers\n");  		log("\n"); +		log("    -clkbuf\n"); +		log("        insert direct PAD->global_net buffers\n"); +		log("\n");  		log("    -retime\n");  		log("        run 'abc' with -dff option\n");  		log("\n"); @@ -73,7 +76,7 @@ struct SynthSf2Pass : public ScriptPass  	}  	string top_opt, edif_file, vlog_file, json_file; -	bool flatten, retime, iobs; +	bool flatten, retime, iobs, clkbuf;  	void clear_flags() YS_OVERRIDE  	{ @@ -84,6 +87,7 @@ struct SynthSf2Pass : public ScriptPass  		flatten = true;  		retime = false;  		iobs = true; +		clkbuf = false;  	}  	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE @@ -130,6 +134,10 @@ struct SynthSf2Pass : public ScriptPass  				iobs = false;  				continue;  			} +			if (args[argidx] == "-clkbuf") { +				clkbuf = true; +				continue; +			}  			break;  		}  		extra_args(args, argidx, design); @@ -201,8 +209,10 @@ struct SynthSf2Pass : public ScriptPass  		if (check_label("map_iobs"))  		{ -			if (iobs || help_mode) -				run("sf2_iobs", "(unless -noiobs)"); +			if (help_mode) +				run("sf2_iobs [-clkbuf]", "(unless -noiobs)"); +			else if (iobs) +				run(clkbuf ? "sf2_iobs -clkbuf" : "sf2_iobs");  			run("clean");  		} diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index 887ea27d9..d68f03bb4 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -28,7 +28,8 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/brams_bb.v))  $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams.txt))  $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams_map.v))  $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v)) -$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut2lut.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/ff_map.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v))  $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_36.vh))  $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_32.vh)) diff --git a/techlibs/xilinx/arith_map.v b/techlibs/xilinx/arith_map.v index 03719659b..09a5f07e8 100644 --- a/techlibs/xilinx/arith_map.v +++ b/techlibs/xilinx/arith_map.v @@ -17,6 +17,9 @@   *   */ +// ============================================================================ +// LCU +  (* techmap_celltype = "$lcu" *)  module _80_xilinx_lcu (P, G, CI, CO);  	parameter WIDTH = 2; @@ -28,10 +31,78 @@ module _80_xilinx_lcu (P, G, CI, CO);  	wire _TECHMAP_FAIL_ = WIDTH <= 2; +	genvar i; + +`ifdef _CLB_CARRY + +	localparam CARRY4_COUNT = (WIDTH + 3) / 4; +	localparam MAX_WIDTH    = CARRY4_COUNT * 4; +	localparam PAD_WIDTH    = MAX_WIDTH - WIDTH; + +	wire [MAX_WIDTH-1:0] S  = {{PAD_WIDTH{1'b0}}, P & ~G}; +	wire [MAX_WIDTH-1:0] C  = CO; + +	generate for (i = 0; i < CARRY4_COUNT; i = i + 1) begin:slice + +		// Partially occupied CARRY4 +		if ((i+1)*4 > WIDTH) begin + +			// First one +			if (i == 0) begin +				CARRY4 carry4_1st_part +				( +				.CYINIT(CI), +				.CI    (1'd0), +				.DI    (G [(Y_WIDTH - 1):i*4]), +				.S     (S [(Y_WIDTH - 1):i*4]), +				.CO    (CO[(Y_WIDTH - 1):i*4]), +				); +			// Another one +			end else begin +				CARRY4 carry4_part +				( +				.CYINIT(1'd0), +				.CI    (C [i*4 - 1]), +				.DI    (G [(Y_WIDTH - 1):i*4]), +				.S     (S [(Y_WIDTH - 1):i*4]), +				.CO    (CO[(Y_WIDTH - 1):i*4]), +				); +			end + +		// Fully occupied CARRY4 +		end else begin + +			// First one +			if (i == 0) begin +				CARRY4 carry4_1st_full +				( +				.CYINIT(CI), +				.CI    (1'd0), +				.DI    (G [((i+1)*4 - 1):i*4]), +				.S     (S [((i+1)*4 - 1):i*4]), +				.CO    (CO[((i+1)*4 - 1):i*4]), +				); +			// Another one +			end else begin +				CARRY4 carry4_full +				( +				.CYINIT(1'd0), +				.CI    (C [i*4 - 1]), +				.DI    (G [((i+1)*4 - 1):i*4]), +				.S     (S [((i+1)*4 - 1):i*4]), +				.CO    (CO[((i+1)*4 - 1):i*4]), +				); +			end + +		end + +	end endgenerate + +`elsif _EXPLICIT_CARRY +  	wire [WIDTH-1:0] C = {CO, CI};  	wire [WIDTH-1:0] S = P & ~G; -	genvar i;  	generate for (i = 0; i < WIDTH; i = i + 1) begin:slice  		MUXCY muxcy (  			.CI(C[i]), @@ -40,8 +111,28 @@ module _80_xilinx_lcu (P, G, CI, CO);  			.O(CO[i])  		);  	end endgenerate + +`else + +	wire [WIDTH-1:0] C = {CO, CI}; +	wire [WIDTH-1:0] S = P & ~G; + +	generate for (i = 0; i < WIDTH; i = i + 1) begin:slice +		MUXCY muxcy ( +			.CI(C[i]), +			.DI(G[i]), +			.S(S[i]), +			.O(CO[i]) +		); +	end endgenerate +`endif +  endmodule + +// ============================================================================ +// ALU +  (* techmap_celltype = "$alu" *)  module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);  	parameter A_SIGNED = 0; @@ -49,6 +140,8 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);  	parameter A_WIDTH = 1;  	parameter B_WIDTH = 1;  	parameter Y_WIDTH = 1; +	parameter _TECHMAP_CONSTVAL_CI_ = 0; +	parameter _TECHMAP_CONSTMSK_CI_ = 0;  	input [A_WIDTH-1:0] A;  	input [B_WIDTH-1:0] B; @@ -66,16 +159,189 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);  	wire [Y_WIDTH-1:0] AA = A_buf;  	wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; -	wire [Y_WIDTH-1:0] P = AA ^ BB; -	wire [Y_WIDTH-1:0] G = AA & BB; -	wire [Y_WIDTH-1:0] C = {CO, CI}; -	wire [Y_WIDTH-1:0] S = P & ~G; +	genvar i; + +`ifdef _CLB_CARRY + +	localparam CARRY4_COUNT = (Y_WIDTH + 3) / 4; +	localparam MAX_WIDTH    = CARRY4_COUNT * 4; +	localparam PAD_WIDTH    = MAX_WIDTH - Y_WIDTH; + +	wire [MAX_WIDTH-1:0] S  = {{PAD_WIDTH{1'b0}}, AA ^ BB}; +	wire [MAX_WIDTH-1:0] DI = {{PAD_WIDTH{1'b0}}, AA & BB}; + +	wire [MAX_WIDTH-1:0] C  = CO;  	genvar i; +	generate for (i = 0; i < CARRY4_COUNT; i = i + 1) begin:slice + +		// Partially occupied CARRY4 +		if ((i+1)*4 > Y_WIDTH) begin + +			// First one +			if (i == 0) begin +				CARRY4 #(.IS_INITIALIZED(1'd1)) carry4_1st_part +				( +				.CYINIT(CI), +				.CI    (1'd0), +				.DI    (DI[(Y_WIDTH - 1):i*4]), +				.S     (S [(Y_WIDTH - 1):i*4]), +				.O     (Y [(Y_WIDTH - 1):i*4]), +				.CO    (CO[(Y_WIDTH - 1):i*4]) +				); +			// Another one +			end else begin +				CARRY4 carry4_part +				( +				.CYINIT(1'd0), +				.CI    (C [i*4 - 1]), +				.DI    (DI[(Y_WIDTH - 1):i*4]), +				.S     (S [(Y_WIDTH - 1):i*4]), +				.O     (Y [(Y_WIDTH - 1):i*4]), +				.CO    (CO[(Y_WIDTH - 1):i*4]) +				); +			end + +		// Fully occupied CARRY4 +		end else begin + +			// First one +			if (i == 0) begin +				CARRY4 #(.IS_INITIALIZED(1'd1)) carry4_1st_full +				( +				.CYINIT(CI), +				.CI    (1'd0), +				.DI    (DI[((i+1)*4 - 1):i*4]), +				.S     (S [((i+1)*4 - 1):i*4]), +				.O     (Y [((i+1)*4 - 1):i*4]), +				.CO    (CO[((i+1)*4 - 1):i*4]) +				); +			// Another one +			end else begin +				CARRY4 carry4_full +				( +				.CYINIT(1'd0), +				.CI    (C [i*4 - 1]), +				.DI    (DI[((i+1)*4 - 1):i*4]), +				.S     (S [((i+1)*4 - 1):i*4]), +				.O     (Y [((i+1)*4 - 1):i*4]), +				.CO    (CO[((i+1)*4 - 1):i*4]) +				); +			end + +		end + +	end endgenerate + +`elsif _EXPLICIT_CARRY + +	wire [Y_WIDTH-1:0] S = AA ^ BB; +	wire [Y_WIDTH-1:0] DI = AA & BB; + +	wire CINIT; +	// Carry chain. +	// +	// VPR requires that the carry chain never hit the fabric.	The CO input +	// to this techmap is the carry outputs for synthesis, e.g. might hit the +	// fabric. +	// +	// So we maintain two wire sets, CO_CHAIN is the carry that is for VPR, +	// e.g. off fabric dedicated chain.  CO is the carry outputs that are +	// available to the fabric. +	wire [Y_WIDTH-1:0] CO_CHAIN; +	wire [Y_WIDTH-1:0] C = {CO_CHAIN, CINIT}; + +	// If carry chain is being initialized to a constant, techmap the constant +	// source.	Otherwise techmap the fabric source. +	generate for (i = 0; i < 1; i = i + 1) begin:slice +		CARRY0 #(.CYINIT_FABRIC(1)) carry( +			.CI_INIT(CI), +			.DI(DI[0]), +			.S(S[0]), +			.CO_CHAIN(CO_CHAIN[0]), +			.CO_FABRIC(CO[0]), +			.O(Y[0]) +		); +	end endgenerate + +	generate for (i = 1; i < Y_WIDTH-1; i = i + 1) begin:slice +		if(i % 4 == 0) begin +			CARRY0 carry ( +				.CI(C[i]), +				.DI(DI[i]), +				.S(S[i]), +				.CO_CHAIN(CO_CHAIN[i]), +				.CO_FABRIC(CO[i]), +				.O(Y[i]) +			); +		end +		else +		begin +			CARRY carry ( +				.CI(C[i]), +				.DI(DI[i]), +				.S(S[i]), +				.CO_CHAIN(CO_CHAIN[i]), +				.CO_FABRIC(CO[i]), +				.O(Y[i]) +			); +		end +	end endgenerate + +	generate for (i = Y_WIDTH-1; i < Y_WIDTH; i = i + 1) begin:slice +		if(i % 4 == 0) begin +			CARRY0 top_of_carry ( +				.CI(C[i]), +				.DI(DI[i]), +				.S(S[i]), +				.CO_CHAIN(CO_CHAIN[i]), +				.O(Y[i]) +			); +		end +		else +		begin +			CARRY top_of_carry ( +				.CI(C[i]), +				.DI(DI[i]), +				.S(S[i]), +				.CO_CHAIN(CO_CHAIN[i]), +				.O(Y[i]) +			); +		end +		// Turns out CO_FABRIC and O both use [ABCD]MUX, so provide +		// a non-congested path to output the top of the carry chain. +		// Registering the output of the CARRY block would solve this, but not +		// all designs do that. +		if((i+1) % 4 == 0) begin +			CARRY0 carry_output ( +				.CI(CO_CHAIN[i]), +				.DI(0), +				.S(0), +				.O(CO[i]) +			); +		end +		else +		begin +			CARRY carry_output ( +				.CI(CO_CHAIN[i]), +				.DI(0), +				.S(0), +				.O(CO[i]) +			); +		end +	end endgenerate + +`else + +	wire [Y_WIDTH-1:0] S = AA ^ BB; +	wire [Y_WIDTH-1:0] DI = AA & BB; + +	wire [Y_WIDTH-1:0] C = {CO, CI}; +  	generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice  		MUXCY muxcy (  			.CI(C[i]), -			.DI(G[i]), +			.DI(DI[i]),  			.S(S[i]),  			.O(CO[i])  		); @@ -86,6 +352,8 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);  		);  	end endgenerate -	assign X = P; +`endif + +	assign X = S;  endmodule diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 0771be0b9..d5801c0fc 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -1,86 +1,20 @@ +/* + *  yosys -- Yosys Open SYnthesis Suite + * + *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> + * + *  Permission to use, copy, modify, and/or distribute this software for any + *  purpose with or without fee is hereby granted, provided that the above + *  copyright notice and this permission notice appear in all copies. + * + *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ -module  \$_DFF_N_ (input D, C, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule -module  \$_DFF_P_ (input D, C, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule - -module  \$_DFFE_NP_ (input D, C, E, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule -module  \$_DFFE_PP_ (input D, C, E, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule - -module  \$_DFF_NN0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule -module  \$_DFF_NP0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule -module  \$_DFF_PN0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule -module  \$_DFF_PP0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule - -module  \$_DFF_NN1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule -module  \$_DFF_NP1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule -module  \$_DFF_PN1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule -module  \$_DFF_PP1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule - -`ifndef NO_LUT -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_ (.O(Y), -        .I0(A[0])); -    end else -    if (WIDTH == 2) begin -      LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), -        .I0(A[0]), .I1(A[1])); -    end else -    if (WIDTH == 3) begin -      LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), -        .I0(A[0]), .I1(A[1]), .I2(A[2])); -    end else -    if (WIDTH == 4) begin -      LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), -        .I0(A[0]), .I1(A[1]), .I2(A[2]), -        .I3(A[3])); -    end else -    if (WIDTH == 5) begin -      LUT5 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), -        .I0(A[0]), .I1(A[1]), .I2(A[2]), -        .I3(A[3]), .I4(A[4])); -    end else -    if (WIDTH == 6) begin -      LUT6 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), -        .I0(A[0]), .I1(A[1]), .I2(A[2]), -        .I3(A[3]), .I4(A[4]), .I5(A[5])); -    end else -    if (WIDTH == 7) begin -      wire T0, T1; -      LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0), -        .I0(A[0]), .I1(A[1]), .I2(A[2]), -        .I3(A[3]), .I4(A[4]), .I5(A[5])); -      LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1), -        .I0(A[0]), .I1(A[1]), .I2(A[2]), -        .I3(A[3]), .I4(A[4]), .I5(A[5])); -      MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[6])); -    end else -    if (WIDTH == 8) begin -      wire T0, T1, T2, T3, T4, T5; -      LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0), -        .I0(A[0]), .I1(A[1]), .I2(A[2]), -        .I3(A[3]), .I4(A[4]), .I5(A[5])); -      LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1), -        .I0(A[0]), .I1(A[1]), .I2(A[2]), -        .I3(A[3]), .I4(A[4]), .I5(A[5])); -      LUT6 #(.INIT(LUT[191:128])) fpga_lut_2 (.O(T2), -        .I0(A[0]), .I1(A[1]), .I2(A[2]), -        .I3(A[3]), .I4(A[4]), .I5(A[5])); -      LUT6 #(.INIT(LUT[255:192])) fpga_lut_3 (.O(T3), -        .I0(A[0]), .I1(A[1]), .I2(A[2]), -        .I3(A[3]), .I4(A[4]), .I5(A[5])); -      MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[6])); -      MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[6])); -      MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[7])); -    end else begin -      wire _TECHMAP_FAIL_ = 1; -    end -  endgenerate -endmodule -`endif +// Empty for now diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index eba17ac9c..ff5ff0726 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -1,3 +1,21 @@ +/* + *  yosys -- Yosys Open SYnthesis Suite + * + *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> + * + *  Permission to use, copy, modify, and/or distribute this software for any + *  purpose with or without fee is hereby granted, provided that the above + *  copyright notice and this permission notice appear in all copies. + * + *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */  // See Xilinx UG953 and UG474 for a description of the cell types below.  // http://www.xilinx.com/support/documentation/user_guides/ug474_7Series_CLB.pdf @@ -104,6 +122,29 @@ module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S);    assign CO[3] = S[3] ? CO[2] : DI[3];  endmodule +`ifdef _EXPLICIT_CARRY + +module CARRY0(output CO_CHAIN, CO_FABRIC, O, input CI, CI_INIT, DI, S); +  parameter CYINIT_FABRIC = 0; +  wire CI_COMBINE; +  if(CYINIT_FABRIC) begin +    assign CI_COMBINE = CI_INIT; +  end else begin +    assign CI_COMBINE = CI; +  end +  assign CO_CHAIN = S ? CI_COMBINE : DI; +  assign CO_FABRIC = S ? CI_COMBINE : DI; +  assign O = S ^ CI_COMBINE; +endmodule + +module CARRY(output CO_CHAIN, CO_FABRIC, O, input CI, DI, S); +  assign CO_CHAIN = S ? CI : DI; +  assign CO_FABRIC = S ? CI : DI; +  assign O = S ^ CI; +endmodule + +`endif +  module FDRE (output reg Q, input C, CE, D, R);    parameter [0:0] INIT = 1'b0;    parameter [0:0] IS_C_INVERTED = 1'b0; @@ -156,6 +197,30 @@ module FDPE (output reg Q, input C, CE, D, PRE);    endcase endgenerate  endmodule +module FDRE_1 (output reg Q, input C, CE, D, R); +  parameter [0:0] INIT = 1'b0; +  initial Q <= INIT; +  always @(negedge C) if (R) Q <= 1'b0; else if(CE) Q <= D; +endmodule + +module FDSE_1 (output reg Q, input C, CE, D, S); +  parameter [0:0] INIT = 1'b1; +  initial Q <= INIT; +  always @(negedge C) if (S) Q <= 1'b1; else if(CE) Q <= D; +endmodule + +module FDCE_1 (output reg Q, input C, CE, D, CLR); +  parameter [0:0] INIT = 1'b0; +  initial Q <= INIT; +  always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D; +endmodule + +module FDPE_1 (output reg Q, input C, CE, D, PRE); +  parameter [0:0] INIT = 1'b1; +  initial Q <= INIT; +  always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; +endmodule +  module RAM64X1D (    output DPO, SPO,    input  D, WCLK, WE, diff --git a/techlibs/xilinx/cells_xtra.sh b/techlibs/xilinx/cells_xtra.sh index 0480410f5..56520ea10 100644 --- a/techlibs/xilinx/cells_xtra.sh +++ b/techlibs/xilinx/cells_xtra.sh @@ -7,6 +7,7 @@ function xtract_cell_decl()  {  	for dir in $libdir/xeclib $libdir/retarget; do  		[ -f $dir/$1.v ] || continue +		[ -z "$2" ] || echo $2  		egrep '^\s*((end)?module|parameter|input|inout|output|(end)?function|(end)?task)' $dir/$1.v |  			sed -re '/UNPLACED/ d; /^\s*function/,/endfunction/ d; /^\s*task/,/endtask/ d;  			         s,//.*,,; s/#?\(.*/(...);/; s/^(input|output|parameter)/ \1/; @@ -37,10 +38,10 @@ function xtract_cell_decl()  	xtract_cell_decl BUFMR  	xtract_cell_decl BUFMRCE  	xtract_cell_decl BUFR -	xtract_cell_decl CAPTUREE2 +	xtract_cell_decl CAPTUREE2 "(* keep *)"  	# xtract_cell_decl CARRY4  	xtract_cell_decl CFGLUT5 -	xtract_cell_decl DCIRESET +	xtract_cell_decl DCIRESET "(* keep *)"  	xtract_cell_decl DNA_PORT  	xtract_cell_decl DSP48E1  	xtract_cell_decl EFUSE_USR @@ -67,10 +68,10 @@ function xtract_cell_decl()  	xtract_cell_decl IBUFDS_GTE2  	xtract_cell_decl IBUFDS_IBUFDISABLE  	xtract_cell_decl IBUFDS_INTERMDISABLE -	xtract_cell_decl ICAPE2 +	xtract_cell_decl ICAPE2 "(* keep *)"  	xtract_cell_decl IDDR  	xtract_cell_decl IDDR_2CLK -	xtract_cell_decl IDELAYCTRL +	xtract_cell_decl IDELAYCTRL "(* keep *)"  	xtract_cell_decl IDELAYE2  	xtract_cell_decl IN_FIFO  	xtract_cell_decl IOBUF @@ -112,10 +113,10 @@ function xtract_cell_decl()  	xtract_cell_decl PHY_CONTROL  	xtract_cell_decl PLLE2_ADV  	xtract_cell_decl PLLE2_BASE -	xtract_cell_decl PS7 +	xtract_cell_decl PS7 "(* keep *)"  	xtract_cell_decl PULLDOWN  	xtract_cell_decl PULLUP -	# xtract_cell_decl RAM128X1D +	xtract_cell_decl RAM128X1D  	xtract_cell_decl RAM128X1S  	xtract_cell_decl RAM256X1S  	xtract_cell_decl RAM32M @@ -124,7 +125,7 @@ function xtract_cell_decl()  	xtract_cell_decl RAM32X1S_1  	xtract_cell_decl RAM32X2S  	xtract_cell_decl RAM64M -	# xtract_cell_decl RAM64X1D +	xtract_cell_decl RAM64X1D  	xtract_cell_decl RAM64X1S  	xtract_cell_decl RAM64X1S_1  	xtract_cell_decl RAM64X2S @@ -136,7 +137,7 @@ function xtract_cell_decl()  	xtract_cell_decl ROM64X1  	xtract_cell_decl SRL16E  	xtract_cell_decl SRLC32E -	xtract_cell_decl STARTUPE2 +	xtract_cell_decl STARTUPE2 "(* keep *)"  	xtract_cell_decl USR_ACCESSE2  	xtract_cell_decl XADC  } > cells_xtra.new diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v index 8d8b91ddc..497518d35 100644 --- a/techlibs/xilinx/cells_xtra.v +++ b/techlibs/xilinx/cells_xtra.v @@ -114,6 +114,7 @@ module BUFR (...);      parameter SIM_DEVICE = "7SERIES";  endmodule +(* keep *)  module CAPTUREE2 (...);      parameter ONESHOT = "TRUE";      input CAP; @@ -130,6 +131,7 @@ module CFGLUT5 (...);      input CDI, CE, CLK;  endmodule +(* keep *)  module DCIRESET (...);      output LOCKED;      input RST; @@ -2102,6 +2104,7 @@ module IBUFDS_INTERMDISABLE (...);      input INTERMDISABLE;  endmodule +(* keep *)  module ICAPE2 (...);      parameter [31:0] DEVICE_ID = 32'h04244093;      parameter ICAP_WIDTH = "X32"; @@ -2149,6 +2152,7 @@ module IDDR_2CLK (...);      input S;  endmodule +(* keep *)  module IDELAYCTRL (...);      parameter SIM_DEVICE = "7SERIES";      output RDY; @@ -3057,6 +3061,7 @@ module PLLE2_BASE (...);      input RST;  endmodule +(* keep *)  module PS7 (...);      output DMA0DAVALID;      output DMA0DRREADY; @@ -3688,6 +3693,17 @@ module PULLUP (...);      output O;  endmodule +module RAM128X1D (...); +    parameter [127:0] INIT = 128'h00000000000000000000000000000000; +    parameter [0:0] IS_WCLK_INVERTED = 1'b0; +    output DPO, SPO; +    input [6:0] A; +    input [6:0] DPRA; +    input D; +    input WCLK; +    input WE; +endmodule +  module RAM128X1S (...);      parameter [127:0] INIT = 128'h00000000000000000000000000000000;      parameter [0:0] IS_WCLK_INVERTED = 1'b0; @@ -3778,6 +3794,13 @@ module RAM64M (...);      input WE;  endmodule +module RAM64X1D (...); +    parameter [63:0] INIT = 64'h0000000000000000; +    parameter [0:0] IS_WCLK_INVERTED = 1'b0; +    output DPO, SPO; +    input A0, A1, A2, A3, A4, A5, D, DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5, WCLK, WE; +endmodule +  module RAM64X1S (...);      parameter [63:0] INIT = 64'h0000000000000000;      parameter [0:0] IS_WCLK_INVERTED = 1'b0; @@ -3840,6 +3863,7 @@ module SRLC32E (...);      input CE, CLK, D;  endmodule +(* keep *)  module STARTUPE2 (...);      parameter PROG_USR = "FALSE";      parameter real SIM_CCLK_FREQ = 0.0; diff --git a/techlibs/xilinx/ff_map.v b/techlibs/xilinx/ff_map.v new file mode 100644 index 000000000..13beaa6ae --- /dev/null +++ b/techlibs/xilinx/ff_map.v @@ -0,0 +1,42 @@ +/* + *  yosys -- Yosys Open SYnthesis Suite + * + *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> + * + *  Permission to use, copy, modify, and/or distribute this software for any + *  purpose with or without fee is hereby granted, provided that the above + *  copyright notice and this permission notice appear in all copies. + * + *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +// ============================================================================ +// FF mapping + +`ifndef _NO_FFS + +module  \$_DFF_N_   (input D, C, output Q);    FDRE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule +module  \$_DFF_P_   (input D, C, output Q);    FDRE   #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule + +module  \$_DFFE_NP_ (input D, C, E, output Q); FDRE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E),    .R(1'b0)); endmodule +module  \$_DFFE_PP_ (input D, C, E, output Q); FDRE   #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E),    .R(1'b0)); endmodule + +module  \$_DFF_NN0_ (input D, C, R, output Q); FDCE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R)); endmodule +module  \$_DFF_NP0_ (input D, C, R, output Q); FDCE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); endmodule +module  \$_DFF_PN0_ (input D, C, R, output Q); FDCE   #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R)); endmodule +module  \$_DFF_PP0_ (input D, C, R, output Q); FDCE   #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); endmodule + +module  \$_DFF_NN1_ (input D, C, R, output Q); FDPE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); endmodule +module  \$_DFF_NP1_ (input D, C, R, output Q); FDPE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule +module  \$_DFF_PN1_ (input D, C, R, output Q); FDPE   #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); endmodule +module  \$_DFF_PP1_ (input D, C, R, output Q); FDPE   #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule + +`endif + diff --git a/techlibs/xilinx/lut2lut.v b/techlibs/xilinx/lut2lut.v deleted file mode 100644 index 061ad2041..000000000 --- a/techlibs/xilinx/lut2lut.v +++ /dev/null @@ -1,65 +0,0 @@ -module LUT1(output O, input I0); -  parameter [1:0] INIT = 0; -  \$lut #( -    .WIDTH(1), -    .LUT(INIT) -  ) _TECHMAP_REPLACE_ ( -    .A(I0), -    .Y(O) -  ); -endmodule - -module LUT2(output O, input I0, I1); -  parameter [3:0] INIT = 0; -  \$lut #( -    .WIDTH(2), -    .LUT(INIT) -  ) _TECHMAP_REPLACE_ ( -    .A({I1, I0}), -    .Y(O) -  ); -endmodule - -module LUT3(output O, input I0, I1, I2); -  parameter [7:0] INIT = 0; -  \$lut #( -    .WIDTH(3), -    .LUT(INIT) -  ) _TECHMAP_REPLACE_ ( -    .A({I2, I1, I0}), -    .Y(O) -  ); -endmodule - -module LUT4(output O, input I0, I1, I2, I3); -  parameter [15:0] INIT = 0; -  \$lut #( -    .WIDTH(4), -    .LUT(INIT) -  ) _TECHMAP_REPLACE_ ( -    .A({I3, I2, I1, I0}), -    .Y(O) -  ); -endmodule - -module LUT5(output O, input I0, I1, I2, I3, I4); -  parameter [31:0] INIT = 0; -  \$lut #( -    .WIDTH(5), -    .LUT(INIT) -  ) _TECHMAP_REPLACE_ ( -    .A({I4, I3, I2, I1, I0}), -    .Y(O) -  ); -endmodule - -module LUT6(output O, input I0, I1, I2, I3, I4, I5); -  parameter [63:0] INIT = 0; -  \$lut #( -    .WIDTH(6), -    .LUT(INIT) -  ) _TECHMAP_REPLACE_ ( -    .A({I5, I4, I3, I2, I1, I0}), -    .Y(O) -  ); -endmodule diff --git a/techlibs/xilinx/lut_map.v b/techlibs/xilinx/lut_map.v new file mode 100644 index 000000000..d07c59dee --- /dev/null +++ b/techlibs/xilinx/lut_map.v @@ -0,0 +1,94 @@ +/* + *  yosys -- Yosys Open SYnthesis Suite + * + *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> + * + *  Permission to use, copy, modify, and/or distribute this software for any + *  purpose with or without fee is hereby granted, provided that the above + *  copyright notice and this permission notice appear in all copies. + * + *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +// ============================================================================ +// LUT mapping + +`ifndef _NO_LUTS + +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_ (.O(Y), +        .I0(A[0])); +    end else +    if (WIDTH == 2) begin +      LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), +        .I0(A[0]), .I1(A[1])); +    end else +    if (WIDTH == 3) begin +      LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), +        .I0(A[0]), .I1(A[1]), .I2(A[2])); +    end else +    if (WIDTH == 4) begin +      LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), +        .I0(A[0]), .I1(A[1]), .I2(A[2]), +        .I3(A[3])); +    end else +    if (WIDTH == 5) begin +      LUT5 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), +        .I0(A[0]), .I1(A[1]), .I2(A[2]), +        .I3(A[3]), .I4(A[4])); +    end else +    if (WIDTH == 6) begin +      LUT6 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), +        .I0(A[0]), .I1(A[1]), .I2(A[2]), +        .I3(A[3]), .I4(A[4]), .I5(A[5])); +    end else +    if (WIDTH == 7) begin +      wire T0, T1; +      LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0), +        .I0(A[0]), .I1(A[1]), .I2(A[2]), +        .I3(A[3]), .I4(A[4]), .I5(A[5])); +      LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1), +        .I0(A[0]), .I1(A[1]), .I2(A[2]), +        .I3(A[3]), .I4(A[4]), .I5(A[5])); +      MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[6])); +    end else +    if (WIDTH == 8) begin +      wire T0, T1, T2, T3, T4, T5; +      LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0), +        .I0(A[0]), .I1(A[1]), .I2(A[2]), +        .I3(A[3]), .I4(A[4]), .I5(A[5])); +      LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1), +        .I0(A[0]), .I1(A[1]), .I2(A[2]), +        .I3(A[3]), .I4(A[4]), .I5(A[5])); +      LUT6 #(.INIT(LUT[191:128])) fpga_lut_2 (.O(T2), +        .I0(A[0]), .I1(A[1]), .I2(A[2]), +        .I3(A[3]), .I4(A[4]), .I5(A[5])); +      LUT6 #(.INIT(LUT[255:192])) fpga_lut_3 (.O(T3), +        .I0(A[0]), .I1(A[1]), .I2(A[2]), +        .I3(A[3]), .I4(A[4]), .I5(A[5])); +      MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[6])); +      MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[6])); +      MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[7])); +    end else begin +      wire _TECHMAP_FAIL_ = 1; +    end +  endgenerate +endmodule + +`endif + diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 6c11d885d..805ae8e6e 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -63,6 +63,12 @@ struct SynthXilinxPass : public Pass  		log("        generate an output netlist (and BLIF file) suitable for VPR\n");  		log("        (this feature is experimental and incomplete)\n");  		log("\n"); +		log("    -nobram\n"); +		log("        disable infering of block rams\n"); +		log("\n"); +		log("    -nodram\n"); +		log("        disable infering of distributed rams\n"); +		log("\n");  		log("    -run <from_label>:<to_label>\n");  		log("        only run the commands between the labels (see below). an empty\n");  		log("        from label is synonymous to 'begin', and empty to label is\n"); @@ -90,11 +96,11 @@ struct SynthXilinxPass : public Pass  		log("    coarse:\n");  		log("        synth -run coarse\n");  		log("\n"); -		log("    bram:\n"); +		log("    bram: (only executed when '-nobram' is not given)\n");  		log("        memory_bram -rules +/xilinx/brams.txt\n");  		log("        techmap -map +/xilinx/brams_map.v\n");  		log("\n"); -		log("    dram:\n"); +		log("    dram: (only executed when '-nodram' is not given)\n");  		log("        memory_bram -rules +/xilinx/drams.txt\n");  		log("        techmap -map +/xilinx/drams_map.v\n");  		log("\n"); @@ -104,16 +110,18 @@ struct SynthXilinxPass : public Pass  		log("        dffsr2dff\n");  		log("        dff2dffe\n");  		log("        opt -full\n"); -		log("        techmap -map +/techmap.v -map +/xilinx/arith_map.v\n"); +		log("        techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v\n");  		log("        opt -fast\n");  		log("\n");  		log("    map_luts:\n"); -		log("        abc -luts 2:2,3,6:5,10,20 [-dff]\n"); +		log("        abc -luts 2:2,3,6:5,10,20 [-dff] (without '-vpr' only!)\n"); +		log("        abc -lut 5 [-dff] (with '-vpr' only!)\n");  		log("        clean\n");  		log("\n");  		log("    map_cells:\n"); -		log("        techmap -map +/xilinx/cells_map.v (with -D NO_LUT in vpr mode)\n"); -		log("        dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT\n"); +		log("        techmap -map +/xilinx/cells_map.v\n"); +		log("        dffinit -ff FDRE   Q INIT -ff FDCE   Q INIT -ff FDPE   Q INIT -ff FDSE   Q INIT \\\n"); +		log("                -ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT\n");  		log("        clean\n");  		log("\n");  		log("    check:\n"); @@ -137,6 +145,8 @@ struct SynthXilinxPass : public Pass  		bool flatten = false;  		bool retime = false;  		bool vpr = false; +		bool nobram = false; +		bool nodram = false;  		size_t argidx;  		for (argidx = 1; argidx < args.size(); argidx++) @@ -173,6 +183,14 @@ struct SynthXilinxPass : public Pass  				vpr = true;  				continue;  			} +			if (args[argidx] == "-nobram") { +				nobram = true; +				continue; +			} +			if (args[argidx] == "-nodram") { +				nodram = true; +				continue; +			}  			break;  		}  		extra_args(args, argidx, design); @@ -187,9 +205,18 @@ struct SynthXilinxPass : public Pass  		if (check_label(active, run_from, run_to, "begin"))  		{ -			Pass::call(design, "read_verilog -lib +/xilinx/cells_sim.v"); +			if (vpr) { +				Pass::call(design, "read_verilog -lib -D_EXPLICIT_CARRY +/xilinx/cells_sim.v"); +			} else { +				Pass::call(design, "read_verilog -lib +/xilinx/cells_sim.v"); +			} +  			Pass::call(design, "read_verilog -lib +/xilinx/cells_xtra.v"); -			Pass::call(design, "read_verilog -lib +/xilinx/brams_bb.v"); + +			if (!nobram) { +				Pass::call(design, "read_verilog -lib +/xilinx/brams_bb.v"); +			} +  			Pass::call(design, stringf("hierarchy -check %s", top_opt.c_str()));  		} @@ -206,14 +233,18 @@ struct SynthXilinxPass : public Pass  		if (check_label(active, run_from, run_to, "bram"))  		{ -			Pass::call(design, "memory_bram -rules +/xilinx/brams.txt"); -			Pass::call(design, "techmap -map +/xilinx/brams_map.v"); +			if (!nobram) { +				Pass::call(design, "memory_bram -rules +/xilinx/brams.txt"); +				Pass::call(design, "techmap -map +/xilinx/brams_map.v"); +			}  		}  		if (check_label(active, run_from, run_to, "dram"))  		{ -			Pass::call(design, "memory_bram -rules +/xilinx/drams.txt"); -			Pass::call(design, "techmap -map +/xilinx/drams_map.v"); +			if (!nodram) { +				Pass::call(design, "memory_bram -rules +/xilinx/drams.txt"); +				Pass::call(design, "techmap -map +/xilinx/drams_map.v"); +			}  		}  		if (check_label(active, run_from, run_to, "fine")) @@ -223,7 +254,14 @@ struct SynthXilinxPass : public Pass  			Pass::call(design, "dffsr2dff");  			Pass::call(design, "dff2dffe");  			Pass::call(design, "opt -full"); -			Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v"); + +			if (vpr) { +				Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v -D _EXPLICIT_CARRY"); +			} else { +				Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v"); +			} + +			Pass::call(design, "hierarchy -check");  			Pass::call(design, "opt -fast");  		} @@ -231,14 +269,14 @@ struct SynthXilinxPass : public Pass  		{  			Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : ""));  			Pass::call(design, "clean"); +			Pass::call(design, "techmap -map +/xilinx/lut_map.v");  		}  		if (check_label(active, run_from, run_to, "map_cells"))  		{  			Pass::call(design, "techmap -map +/xilinx/cells_map.v"); -			if (vpr) -			    Pass::call(design, "techmap -map +/xilinx/lut2lut.v"); -			Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT"); +			Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " +					"-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT");  			Pass::call(design, "clean");  		} @@ -252,7 +290,7 @@ struct SynthXilinxPass : public Pass  		if (check_label(active, run_from, run_to, "edif"))  		{  			if (!edif_file.empty()) -				Pass::call(design, stringf("write_edif %s", edif_file.c_str())); +				Pass::call(design, stringf("write_edif -pvector bra %s", edif_file.c_str()));  		}  		if (check_label(active, run_from, run_to, "blif"))  		{  | 
