mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-28 10:19:26 +00:00 
			
		
		
		
	add qlf_k6n10f architecture + bram inference
(Copied from QuickLogic Yosys plugin repo)
This commit is contained in:
		
							parent
							
								
									98769010af
								
							
						
					
					
						commit
						48c1fdc33d
					
				
					 13 changed files with 90338 additions and 21 deletions
				
			
		|  | @ -1,4 +1,6 @@ | |||
| OBJS += techlibs/quicklogic/synth_quicklogic.o | ||||
| OBJS += techlibs/quicklogic/ql-bram-merge.o | ||||
| OBJS += techlibs/quicklogic/quicklogic_eqn.o | ||||
| 
 | ||||
| $(eval $(call add_share_file,share/quicklogic/common,techlibs/quicklogic/common/cells_sim.v)) | ||||
| 
 | ||||
|  | @ -10,3 +12,13 @@ $(eval $(call add_share_file,share/quicklogic/pp3,techlibs/quicklogic/pp3/cells_ | |||
| $(eval $(call add_share_file,share/quicklogic/pp3,techlibs/quicklogic/pp3/abc9_model.v)) | ||||
| $(eval $(call add_share_file,share/quicklogic/pp3,techlibs/quicklogic/pp3/abc9_map.v)) | ||||
| $(eval $(call add_share_file,share/quicklogic/pp3,techlibs/quicklogic/pp3/abc9_unmap.v)) | ||||
| 
 | ||||
| $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/arith_map.v)) | ||||
| $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/libmap_brams.txt)) | ||||
| $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/libmap_brams_map.v)) | ||||
| $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/brams_map.v)) | ||||
| $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/brams_final_map.v)) | ||||
| $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/brams_sim.v)) | ||||
| $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/bram_types_sim.v)) | ||||
| $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/cells_sim.v)) | ||||
| $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/ffs_map.v)) | ||||
							
								
								
									
										216
									
								
								techlibs/quicklogic/ql-bram-merge.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								techlibs/quicklogic/ql-bram-merge.cc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,216 @@ | |||
| /*
 | ||||
|  *  yosys -- Yosys Open SYnthesis Suite | ||||
|  * | ||||
|  *  Copyright (C) 2023  N. Engelhardt <nak@yosyshq.com> | ||||
|  * | ||||
|  *  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/log.h" | ||||
| #include "kernel/register.h" | ||||
| #include "kernel/rtlil.h" | ||||
| #include "kernel/sigtools.h" | ||||
| 
 | ||||
| USING_YOSYS_NAMESPACE | ||||
| PRIVATE_NAMESPACE_BEGIN | ||||
| 
 | ||||
| // ============================================================================
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| struct QlBramMergeWorker { | ||||
| 
 | ||||
|     const RTLIL::IdString split_cell_type = ID($__QLF_TDP36K); | ||||
|     const RTLIL::IdString merged_cell_type = ID($__QLF_TDP36K_MERGED); | ||||
| 
 | ||||
|     // can be used to record parameter values that have to match on both sides
 | ||||
|     typedef dict<RTLIL::IdString, RTLIL::Const> MergeableGroupKeyType; | ||||
| 
 | ||||
|     RTLIL::Module *module; | ||||
|     dict<MergeableGroupKeyType, pool<RTLIL::Cell*>> mergeable_groups; | ||||
| 
 | ||||
|     QlBramMergeWorker(RTLIL::Module* module) : module(module) | ||||
|     { | ||||
|         for (RTLIL::Cell* cell : module->selected_cells()) | ||||
|         { | ||||
|             if(cell->type != split_cell_type) continue; | ||||
|             if(!cell->hasParam(ID(OPTION_SPLIT))) continue; | ||||
|             if(cell->getParam(ID(OPTION_SPLIT)) != RTLIL::Const(1, 32)) continue; | ||||
|             mergeable_groups[get_key(cell)].insert(cell); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     static MergeableGroupKeyType get_key(RTLIL::Cell* cell) | ||||
|     { | ||||
|         MergeableGroupKeyType key; | ||||
|         // For now, there are no restrictions on which cells can be merged
 | ||||
|         (void) cell; | ||||
|         return key; | ||||
|     } | ||||
| 
 | ||||
|     const dict<RTLIL::IdString, RTLIL::IdString>& param_map(bool second) | ||||
|     { | ||||
|         static const dict<RTLIL::IdString, RTLIL::IdString> bram1_map = { | ||||
|             { ID(INIT),                     ID(INIT1) }, | ||||
|             { ID(PORT_A_WIDTH),             ID(PORT_A1_WIDTH) }, | ||||
|             { ID(PORT_B_WIDTH),             ID(PORT_B1_WIDTH) }, | ||||
|             { ID(PORT_A_WR_BE_WIDTH),       ID(PORT_A1_WR_BE_WIDTH) }, | ||||
|             { ID(PORT_B_WR_BE_WIDTH),       ID(PORT_B1_WR_BE_WIDTH) } | ||||
|         }; | ||||
|         static const dict<RTLIL::IdString, RTLIL::IdString> bram2_map = { | ||||
|             { ID(INIT),                     ID(INIT2) }, | ||||
|             { ID(PORT_A_WIDTH),             ID(PORT_A2_WIDTH) }, | ||||
|             { ID(PORT_B_WIDTH),             ID(PORT_B2_WIDTH) }, | ||||
|             { ID(PORT_A_WR_BE_WIDTH),       ID(PORT_A2_WR_BE_WIDTH) }, | ||||
|             { ID(PORT_B_WR_BE_WIDTH),       ID(PORT_B2_WR_BE_WIDTH) } | ||||
|         }; | ||||
| 
 | ||||
|         if(second) | ||||
|             return bram2_map; | ||||
|         else | ||||
|             return bram1_map; | ||||
|     } | ||||
| 
 | ||||
|     const dict<RTLIL::IdString, RTLIL::IdString>& port_map(bool second) | ||||
|     { | ||||
|         static const dict<RTLIL::IdString, RTLIL::IdString> bram1_map = { | ||||
|             { ID(PORT_A_CLK),       ID(PORT_A1_CLK) }, | ||||
|             { ID(PORT_B_CLK),       ID(PORT_B1_CLK) }, | ||||
|             { ID(PORT_A_CLK_EN),    ID(PORT_A1_CLK_EN) }, | ||||
|             { ID(PORT_B_CLK_EN),    ID(PORT_B1_CLK_EN) }, | ||||
|             { ID(PORT_A_ADDR),      ID(PORT_A1_ADDR) }, | ||||
|             { ID(PORT_B_ADDR),      ID(PORT_B1_ADDR) }, | ||||
|             { ID(PORT_A_WR_DATA),   ID(PORT_A1_WR_DATA) }, | ||||
|             { ID(PORT_B_WR_DATA),   ID(PORT_B1_WR_DATA) }, | ||||
|             { ID(PORT_A_WR_EN),     ID(PORT_A1_WR_EN) }, | ||||
|             { ID(PORT_B_WR_EN),     ID(PORT_B1_WR_EN) }, | ||||
|             { ID(PORT_A_WR_BE),     ID(PORT_A1_WR_BE) }, | ||||
|             { ID(PORT_B_WR_BE),     ID(PORT_B1_WR_BE) }, | ||||
|             { ID(PORT_A_RD_DATA),   ID(PORT_A1_RD_DATA) }, | ||||
|             { ID(PORT_B_RD_DATA),   ID(PORT_B1_RD_DATA) } | ||||
|         }; | ||||
|         static const dict<RTLIL::IdString, RTLIL::IdString> bram2_map = { | ||||
|             { ID(PORT_A_CLK),       ID(PORT_A2_CLK) }, | ||||
|             { ID(PORT_B_CLK),       ID(PORT_B2_CLK) }, | ||||
|             { ID(PORT_A_CLK_EN),    ID(PORT_A2_CLK_EN) }, | ||||
|             { ID(PORT_B_CLK_EN),    ID(PORT_B2_CLK_EN) }, | ||||
|             { ID(PORT_A_ADDR),      ID(PORT_A2_ADDR) }, | ||||
|             { ID(PORT_B_ADDR),      ID(PORT_B2_ADDR) }, | ||||
|             { ID(PORT_A_WR_DATA),   ID(PORT_A2_WR_DATA) }, | ||||
|             { ID(PORT_B_WR_DATA),   ID(PORT_B2_WR_DATA) }, | ||||
|             { ID(PORT_A_WR_EN),     ID(PORT_A2_WR_EN) }, | ||||
|             { ID(PORT_B_WR_EN),     ID(PORT_B2_WR_EN) }, | ||||
|             { ID(PORT_A_WR_BE),     ID(PORT_A2_WR_BE) }, | ||||
|             { ID(PORT_B_WR_BE),     ID(PORT_B2_WR_BE) }, | ||||
|             { ID(PORT_A_RD_DATA),   ID(PORT_A2_RD_DATA) }, | ||||
|             { ID(PORT_B_RD_DATA),   ID(PORT_B2_RD_DATA) } | ||||
|         }; | ||||
| 
 | ||||
|         if(second) | ||||
|             return bram2_map; | ||||
|         else | ||||
|             return bram1_map; | ||||
|     } | ||||
| 
 | ||||
|     void merge_brams(RTLIL::Cell* bram1, RTLIL::Cell* bram2) | ||||
|     { | ||||
| 
 | ||||
|         // Create the new cell
 | ||||
|         RTLIL::Cell* merged = module->addCell(NEW_ID, merged_cell_type); | ||||
|         log_debug("Merging split BRAM cells %s and %s -> %s\n", log_id(bram1->name), log_id(bram2->name), log_id(merged->name)); | ||||
| 
 | ||||
|         for (auto &it : param_map(false)) | ||||
|         { | ||||
|             if(bram1->hasParam(it.first)) | ||||
|                 merged->setParam(it.second, bram1->getParam(it.first)); | ||||
|         } | ||||
|         for (auto &it : param_map(true)) | ||||
|         { | ||||
|             if(bram2->hasParam(it.first)) | ||||
|                 merged->setParam(it.second, bram2->getParam(it.first)); | ||||
|         } | ||||
| 
 | ||||
|         for (auto &it : port_map(false)) | ||||
|         { | ||||
|             if (bram1->hasPort(it.first)) | ||||
|                 merged->setPort(it.second, bram1->getPort(it.first)); | ||||
|             else | ||||
|                 log_error("Can't find port %s on cell %s!\n", log_id(it.first), log_id(bram1->name)); | ||||
|         } | ||||
|         for (auto &it : port_map(true)) | ||||
|         { | ||||
|             if (bram2->hasPort(it.first)) | ||||
|                 merged->setPort(it.second, bram2->getPort(it.first)); | ||||
|             else | ||||
|                 log_error("Can't find port %s on cell %s!\n", log_id(it.first), log_id(bram2->name)); | ||||
|         } | ||||
|         merged->attributes = bram1->attributes; | ||||
|         for (auto attr: bram2->attributes) | ||||
|             if (!merged->has_attribute(attr.first)) | ||||
|                 merged->attributes.insert(attr); | ||||
| 
 | ||||
|         // Remove the old cells
 | ||||
|         module->remove(bram1); | ||||
|         module->remove(bram2); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     void merge_bram_groups() | ||||
|     { | ||||
|         for (auto &it : mergeable_groups) | ||||
|         { | ||||
|             while (it.second.size() > 1) | ||||
|             { | ||||
|                 merge_brams(it.second.pop(), it.second.pop()); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| struct QlBramMergePass : public Pass { | ||||
|      | ||||
|     QlBramMergePass() : Pass("ql_bram_merge", "Infers QuickLogic k6n10f BRAM pairs that can operate independently") {} | ||||
| 
 | ||||
|     void help() override | ||||
|     { | ||||
|         //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||
|         log("\n"); | ||||
|         log("    ql_bram_merge [selection]\n"); | ||||
|         log("\n"); | ||||
|         log("    This pass identifies k6n10f 18K BRAM cells and packs pairs of them together\n"); | ||||
|         log("    into a TDP36K cell operating in split mode\n"); | ||||
|         log("\n"); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     void execute(std::vector<std::string> args, RTLIL::Design *design) override | ||||
|     { | ||||
|         log_header(design, "Executing QL_BRAM_MERGE pass.\n"); | ||||
| 
 | ||||
|         size_t argidx = 1; | ||||
|         extra_args(args, argidx, design); | ||||
| 
 | ||||
|         for (RTLIL::Module* module : design->selected_modules()) | ||||
|         { | ||||
|             QlBramMergeWorker worker(module); | ||||
|             worker.merge_bram_groups(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } QlBramMergePass; | ||||
| 
 | ||||
| PRIVATE_NAMESPACE_END | ||||
							
								
								
									
										99
									
								
								techlibs/quicklogic/qlf_k6n10f/arith_map.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								techlibs/quicklogic/qlf_k6n10f/arith_map.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,99 @@ | |||
| // Copyright 2020-2022 F4PGA Authors
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| //
 | ||||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| (* techmap_celltype = "$alu" *) | ||||
| module _80_quicklogic_alu (A, B, CI, BI, X, Y, CO); | ||||
| 	parameter A_SIGNED = 0; | ||||
| 	parameter B_SIGNED = 0; | ||||
| 	parameter A_WIDTH = 2; | ||||
| 	parameter B_WIDTH = 2; | ||||
| 	parameter Y_WIDTH = 2; | ||||
| 	parameter _TECHMAP_CONSTVAL_CI_ = 0; | ||||
| 	parameter _TECHMAP_CONSTMSK_CI_ = 0; | ||||
| 
 | ||||
| 	(* force_downto *) | ||||
| 	input [A_WIDTH-1:0] A; | ||||
| 	(* force_downto *) | ||||
| 	input [B_WIDTH-1:0] B; | ||||
| 	(* force_downto *) | ||||
| 	output [Y_WIDTH-1:0] X, Y; | ||||
| 
 | ||||
| 	input CI, BI; | ||||
| 	(* force_downto *) | ||||
| 	output [Y_WIDTH-1:0] CO; | ||||
| 
 | ||||
| 
 | ||||
| 	wire _TECHMAP_FAIL_ = Y_WIDTH <= 2; | ||||
| 
 | ||||
| 	(* force_downto *) | ||||
| 	wire [Y_WIDTH-1:0] A_buf, B_buf; | ||||
| 	\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); | ||||
| 	\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); | ||||
| 
 | ||||
| 	(* force_downto *) | ||||
| 	wire [Y_WIDTH-1:0] AA = A_buf; | ||||
| 	(* force_downto *) | ||||
| 	wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; | ||||
| 
 | ||||
| 	genvar i; | ||||
| 	wire co; | ||||
| 
 | ||||
| 	(* force_downto *) | ||||
| 	//wire [Y_WIDTH-1:0] C = {CO, CI};
 | ||||
| 	wire [Y_WIDTH:0] C; | ||||
| 	(* force_downto *) | ||||
| 	wire [Y_WIDTH-1:0] S  = {AA ^ BB}; | ||||
| 	assign CO[Y_WIDTH-1:0] = C[Y_WIDTH:1]; | ||||
|         //assign CO[Y_WIDTH-1] = co;
 | ||||
| 
 | ||||
| 	generate | ||||
| 	     adder_carry intermediate_adder ( | ||||
| 	       .cin     ( ), | ||||
| 	       .cout    (C[0]), | ||||
| 	       .p       (1'b0), | ||||
| 	       .g       (CI), | ||||
| 	       .sumout    () | ||||
| 	     ); | ||||
| 	endgenerate | ||||
| 	genvar i; | ||||
| 	generate if (Y_WIDTH > 2) begin | ||||
| 	  for (i = 0; i < Y_WIDTH-2; i = i + 1) begin:slice | ||||
| 		adder_carry  my_adder ( | ||||
| 			.cin(C[i]), | ||||
| 			.g(AA[i]), | ||||
| 			.p(S[i]), | ||||
| 			.cout(C[i+1]), | ||||
| 		        .sumout(Y[i]) | ||||
| 		); | ||||
| 	      end | ||||
| 	end endgenerate | ||||
| 	generate | ||||
| 	     adder_carry final_adder ( | ||||
| 	       .cin     (C[Y_WIDTH-2]), | ||||
| 	       .cout    (), | ||||
| 	       .p       (1'b0), | ||||
| 	       .g       (1'b0), | ||||
| 	       .sumout    (co) | ||||
| 	     ); | ||||
| 	endgenerate | ||||
| 
 | ||||
| 	assign Y[Y_WIDTH-2] = S[Y_WIDTH-2] ^ co; | ||||
|         assign C[Y_WIDTH-1] = S[Y_WIDTH-2] ? co : AA[Y_WIDTH-2]; | ||||
| 	assign Y[Y_WIDTH-1] = S[Y_WIDTH-1] ^ C[Y_WIDTH-1]; | ||||
|         assign C[Y_WIDTH] = S[Y_WIDTH-1] ? C[Y_WIDTH-1] : AA[Y_WIDTH-1]; | ||||
| 
 | ||||
| 	assign X = S; | ||||
| endmodule | ||||
| 
 | ||||
							
								
								
									
										73373
									
								
								techlibs/quicklogic/qlf_k6n10f/bram_types_sim.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										73373
									
								
								techlibs/quicklogic/qlf_k6n10f/bram_types_sim.v
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										1464
									
								
								techlibs/quicklogic/qlf_k6n10f/brams_final_map.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1464
									
								
								techlibs/quicklogic/qlf_k6n10f/brams_final_map.v
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										2839
									
								
								techlibs/quicklogic/qlf_k6n10f/brams_map.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2839
									
								
								techlibs/quicklogic/qlf_k6n10f/brams_map.v
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										11081
									
								
								techlibs/quicklogic/qlf_k6n10f/brams_sim.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11081
									
								
								techlibs/quicklogic/qlf_k6n10f/brams_sim.v
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										376
									
								
								techlibs/quicklogic/qlf_k6n10f/cells_sim.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										376
									
								
								techlibs/quicklogic/qlf_k6n10f/cells_sim.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,376 @@ | |||
| // Copyright 2020-2022 F4PGA Authors
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| //
 | ||||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| 
 | ||||
| `timescale 1ps/1ps | ||||
| 
 | ||||
| `default_nettype none | ||||
| (* abc9_lut=1 *) | ||||
| module LUT1(output wire O, input wire I0); | ||||
|   parameter [1:0] INIT = 0; | ||||
|   assign O = I0 ? INIT[1] : INIT[0]; | ||||
|   specify | ||||
|     (I0 => O) = 74; | ||||
|   endspecify | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_lut=2 *) | ||||
| module LUT2(output wire O, input wire I0, I1); | ||||
|   parameter [3:0] INIT = 0; | ||||
|   wire [ 1: 0] s1 = I1 ? INIT[ 3: 2] : INIT[ 1: 0]; | ||||
|   assign O = I0 ? s1[1] : s1[0]; | ||||
|   specify | ||||
|     (I0 => O) = 116; | ||||
|     (I1 => O) = 74; | ||||
|   endspecify | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_lut=3 *) | ||||
| module LUT3(output wire O, input wire I0, I1, I2); | ||||
|   parameter [7:0] INIT = 0; | ||||
|   wire [ 3: 0] s2 = I2 ? INIT[ 7: 4] : INIT[ 3: 0]; | ||||
|   wire [ 1: 0] s1 = I1 ?   s2[ 3: 2] :   s2[ 1: 0]; | ||||
|   assign O = I0 ? s1[1] : s1[0]; | ||||
|   specify | ||||
|     (I0 => O) = 162; | ||||
|     (I1 => O) = 116; | ||||
|     (I2 => O) = 174; | ||||
|   endspecify | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_lut=3 *) | ||||
| module LUT4(output wire O, input wire I0, I1, I2, I3); | ||||
|   parameter [15:0] INIT = 0; | ||||
|   wire [ 7: 0] s3 = I3 ? INIT[15: 8] : INIT[ 7: 0]; | ||||
|   wire [ 3: 0] s2 = I2 ?   s3[ 7: 4] :   s3[ 3: 0]; | ||||
|   wire [ 1: 0] s1 = I1 ?   s2[ 3: 2] :   s2[ 1: 0]; | ||||
|   assign O = I0 ? s1[1] : s1[0]; | ||||
|   specify | ||||
|     (I0 => O) = 201; | ||||
|     (I1 => O) = 162; | ||||
|     (I2 => O) = 116; | ||||
|     (I3 => O) = 74; | ||||
|   endspecify | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_lut=3 *) | ||||
| module LUT5(output wire O, input wire I0, I1, I2, I3, I4); | ||||
|   parameter [31:0] INIT = 0; | ||||
|   wire [15: 0] s4 = I4 ? INIT[31:16] : INIT[15: 0]; | ||||
|   wire [ 7: 0] s3 = I3 ?   s4[15: 8] :   s4[ 7: 0]; | ||||
|   wire [ 3: 0] s2 = I2 ?   s3[ 7: 4] :   s3[ 3: 0]; | ||||
|   wire [ 1: 0] s1 = I1 ?   s2[ 3: 2] :   s2[ 1: 0]; | ||||
|   assign O = I0 ? s1[1] : s1[0]; | ||||
|   specify | ||||
|     (I0 => O) = 228; | ||||
|     (I1 => O) = 189; | ||||
|     (I2 => O) = 143; | ||||
|     (I3 => O) = 100; | ||||
|     (I4 => O) = 55; | ||||
|   endspecify | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_lut=5 *) | ||||
| module LUT6(output wire O, input wire I0, I1, I2, I3, I4, I5); | ||||
|   parameter [63:0] INIT = 0; | ||||
|   wire [31: 0] s5 = I5 ? INIT[63:32] : INIT[31: 0]; | ||||
|   wire [15: 0] s4 = I4 ?   s5[31:16] :   s5[15: 0]; | ||||
|   wire [ 7: 0] s3 = I3 ?   s4[15: 8] :   s4[ 7: 0]; | ||||
|   wire [ 3: 0] s2 = I2 ?   s3[ 7: 4] :   s3[ 3: 0]; | ||||
|   wire [ 1: 0] s1 = I1 ?   s2[ 3: 2] :   s2[ 1: 0]; | ||||
|   assign O = I0 ? s1[1] : s1[0]; | ||||
|   specify | ||||
|     (I0 => O) = 251; | ||||
|     (I1 => O) = 212; | ||||
|     (I2 => O) = 166; | ||||
|     (I3 => O) = 123; | ||||
|     (I4 => O) = 77; | ||||
|     (I5 => O) = 43; | ||||
|   endspecify | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| module sh_dff( | ||||
|     output reg Q, | ||||
|     input wire D, | ||||
|     (* clkbuf_sink *) | ||||
|     input wire C | ||||
| ); | ||||
| 
 | ||||
|     initial Q <= 1'b0; | ||||
|     always @(posedge C) | ||||
|         Q <= D; | ||||
| 		 | ||||
|     specify | ||||
|       (posedge C => (Q +: D)) = 0; | ||||
|       $setuphold(posedge C, D, 0, 0); | ||||
|     endspecify | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_box, lib_whitebox *) | ||||
| (* blackbox *) | ||||
| (* keep *) | ||||
| module adder_carry( | ||||
|     output wire sumout, | ||||
|     (* abc9_carry *) | ||||
|     output wire cout, | ||||
|     input wire p, | ||||
|     input wire g, | ||||
|     (* abc9_carry *) | ||||
|     input wire cin | ||||
| ); | ||||
|     assign sumout = p ^ cin; | ||||
|     assign cout = p ? cin : g; | ||||
| 	 | ||||
|     specify | ||||
|         (p => sumout) = 35; | ||||
|         (g => sumout) = 35; | ||||
|         (cin => sumout) = 40; | ||||
|         (p => cout) = 67; | ||||
|         (g => cout) = 65; | ||||
|         (cin => cout) = 69; | ||||
|     endspecify | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| module dff( | ||||
|     output reg Q, | ||||
|     input wire D, | ||||
|     (* clkbuf_sink *) | ||||
|     input wire C | ||||
| ); | ||||
|     initial Q <= 1'b0; | ||||
| 
 | ||||
|     always @(posedge C) | ||||
|       Q <= D; | ||||
| 
 | ||||
|     specify | ||||
| 	    (posedge C=>(Q+:D)) = 285; | ||||
| 	    $setuphold(posedge C, D, 56, 0); | ||||
|     endspecify | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| module dffn( | ||||
|     output reg Q, | ||||
|     input wire D, | ||||
|     (* clkbuf_sink *) | ||||
|     input wire C | ||||
| ); | ||||
|     initial Q <= 1'b0; | ||||
| 
 | ||||
|     always @(negedge C) | ||||
|       Q <= D; | ||||
| 	   | ||||
|     specify | ||||
| 	    (negedge C=>(Q+:D)) = 285; | ||||
| 	    $setuphold(negedge C, D, 56, 0); | ||||
|     endspecify | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| module dffsre( | ||||
|     output reg Q, | ||||
|     input wire D, | ||||
|     (* clkbuf_sink *) | ||||
|     input wire C, | ||||
|     input wire E, | ||||
|     input wire R, | ||||
|     input wire S | ||||
| ); | ||||
|     initial Q <= 1'b0; | ||||
| 
 | ||||
|     always @(posedge C or negedge S or negedge R) | ||||
|       if (!R) | ||||
|         Q <= 1'b0; | ||||
|       else if (!S) | ||||
|         Q <= 1'b1; | ||||
|       else if (E) | ||||
|         Q <= D; | ||||
| 
 | ||||
|     specify | ||||
|       (posedge C => (Q +: D)) = 280; | ||||
|       (R => Q) = 0; | ||||
|       (S => Q) = 0; | ||||
|       $setuphold(posedge C, D, 56, 0); | ||||
|       $setuphold(posedge C, E, 32, 0); | ||||
|       $setuphold(posedge C, R, 0, 0); | ||||
|       $setuphold(posedge C, S, 0, 0); | ||||
|       $recrem(posedge R, posedge C, 0, 0); | ||||
|       $recrem(posedge S, posedge C, 0, 0); | ||||
|     endspecify | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| module dffnsre( | ||||
|     output reg Q, | ||||
|     input wire D, | ||||
|     (* clkbuf_sink *) | ||||
|     input wire C, | ||||
|     input wire E, | ||||
|     input wire R, | ||||
|     input wire S | ||||
| ); | ||||
|     initial Q <= 1'b0; | ||||
| 
 | ||||
|     always @(negedge C or negedge S or negedge R) | ||||
|       if (!R) | ||||
|         Q <= 1'b0; | ||||
|       else if (!S) | ||||
|         Q <= 1'b1; | ||||
|       else if (E) | ||||
|         Q <= D; | ||||
| 		 | ||||
|     specify | ||||
|       (negedge C => (Q +: D)) = 280; | ||||
|       (R => Q) = 0; | ||||
|       (S => Q) = 0; | ||||
|       $setuphold(negedge C, D, 56, 0); | ||||
|       $setuphold(negedge C, E, 32, 0); | ||||
|       $setuphold(negedge C, R, 0, 0); | ||||
|       $setuphold(negedge C, S, 0, 0); | ||||
|       $recrem(posedge R, negedge C, 0, 0); | ||||
|       $recrem(posedge S, negedge C, 0, 0); | ||||
|     endspecify | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| module sdffsre( | ||||
|     output reg Q, | ||||
|     input wire D, | ||||
|     (* clkbuf_sink *) | ||||
|     input wire C, | ||||
|     input wire E, | ||||
|     input wire R, | ||||
|     input wire S | ||||
| ); | ||||
|     initial Q <= 1'b0; | ||||
| 
 | ||||
|     always @(posedge C) | ||||
|       if (!R) | ||||
|         Q <= 1'b0; | ||||
|       else if (!S) | ||||
|         Q <= 1'b1; | ||||
|       else if (E) | ||||
|         Q <= D; | ||||
| 		 | ||||
|     specify | ||||
|         (posedge C => (Q +: D)) = 280; | ||||
|         $setuphold(posedge C, D, 56, 0); | ||||
|         $setuphold(posedge C, R, 32, 0); | ||||
|         $setuphold(posedge C, S, 0, 0); | ||||
|         $setuphold(posedge C, E, 0, 0); | ||||
|     endspecify | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| module sdffnsre( | ||||
|     output reg Q, | ||||
|     input wire D, | ||||
|     (* clkbuf_sink *) | ||||
|     input wire C, | ||||
|     input wire E, | ||||
|     input wire R, | ||||
|     input wire S | ||||
| ); | ||||
|     initial Q <= 1'b0; | ||||
| 
 | ||||
|     always @(negedge C) | ||||
|       if (!R) | ||||
|         Q <= 1'b0; | ||||
|       else if (!S) | ||||
|         Q <= 1'b1; | ||||
|       else if (E) | ||||
|         Q <= D; | ||||
| 		 | ||||
|     specify | ||||
|         (negedge C => (Q +: D)) = 280; | ||||
|         $setuphold(negedge C, D, 56, 0); | ||||
|         $setuphold(negedge C, R, 32, 0); | ||||
|         $setuphold(negedge C, S, 0, 0); | ||||
|         $setuphold(negedge C, E, 0, 0); | ||||
|     endspecify | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| module latchsre ( | ||||
|     output reg Q, | ||||
|     input wire S, | ||||
|     input wire R, | ||||
|     input wire D, | ||||
|     input wire G, | ||||
|     input wire E | ||||
| ); | ||||
|     initial Q <= 1'b0; | ||||
| 
 | ||||
|     always @* | ||||
|       begin | ||||
|         if (!R) | ||||
|           Q <= 1'b0; | ||||
|         else if (!S) | ||||
|           Q <= 1'b1; | ||||
|         else if (E && G) | ||||
|           Q <= D; | ||||
|       end | ||||
| 	   | ||||
|     specify | ||||
|       (posedge G => (Q +: D)) = 0; | ||||
|       $setuphold(posedge G, D, 0, 0); | ||||
|       $setuphold(posedge G, E, 0, 0); | ||||
|       $setuphold(posedge G, R, 0, 0); | ||||
|       $setuphold(posedge G, S, 0, 0); | ||||
|     endspecify       | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| module latchnsre ( | ||||
|     output reg Q, | ||||
|     input wire S, | ||||
|     input wire R, | ||||
|     input wire D, | ||||
|     input wire G, | ||||
|     input wire E | ||||
| ); | ||||
|     initial Q <= 1'b0; | ||||
| 
 | ||||
|     always @* | ||||
|       begin | ||||
|         if (!R) | ||||
|           Q <= 1'b0; | ||||
|         else if (!S) | ||||
|           Q <= 1'b1; | ||||
|         else if (E && !G) | ||||
|           Q <= D; | ||||
|       end | ||||
| 	   | ||||
|     specify | ||||
|       (negedge G => (Q +: D)) = 0; | ||||
|       $setuphold(negedge G, D, 0, 0); | ||||
|       $setuphold(negedge G, E, 0, 0); | ||||
|       $setuphold(negedge G, R, 0, 0); | ||||
|       $setuphold(negedge G, S, 0, 0); | ||||
|     endspecify  | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
							
								
								
									
										133
									
								
								techlibs/quicklogic/qlf_k6n10f/ffs_map.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								techlibs/quicklogic/qlf_k6n10f/ffs_map.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,133 @@ | |||
| // Copyright 2020-2022 F4PGA Authors
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| //
 | ||||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| 
 | ||||
| // DFF, asynchronous set/reset, enable
 | ||||
| module \$_DFFSRE_PNNP_ (C, S, R, E, D, Q); | ||||
|     input  C; | ||||
|     input  S; | ||||
|     input  R; | ||||
|     input  E; | ||||
|     input  D; | ||||
|     output Q; | ||||
|     dffsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(R), .S(S)); | ||||
| endmodule | ||||
| 
 | ||||
| module \$_DFFSRE_NNNP_ (C, S, R, E, D, Q); | ||||
|     input  C; | ||||
|     input  S; | ||||
|     input  R; | ||||
|     input  E; | ||||
|     input  D; | ||||
|     output Q; | ||||
|     dffnsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(R), .S(S)); | ||||
| endmodule | ||||
| 
 | ||||
| // DFF, synchronous set or reset, enable
 | ||||
| module \$_SDFFE_PN0P_ (D, C, R, E, Q); | ||||
|     input  D; | ||||
|     input  C; | ||||
|     input  R; | ||||
|     input  E; | ||||
|     output Q; | ||||
|     sdffsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(R), .S(1'b1)); | ||||
| endmodule | ||||
| 
 | ||||
| module \$_SDFFE_PN1P_ (D, C, R, E, Q); | ||||
|     input  D; | ||||
|     input  C; | ||||
|     input  R; | ||||
|     input  E; | ||||
|     output Q; | ||||
|     sdffsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(1'b1), .S(R)); | ||||
| endmodule | ||||
| 
 | ||||
| module \$_SDFFE_NN0P_ (D, C, R, E, Q); | ||||
|     input  D; | ||||
|     input  C; | ||||
|     input  R; | ||||
|     input  E; | ||||
|     output Q; | ||||
|     sdffnsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(R), .S(1'b1)); | ||||
| endmodule | ||||
| 
 | ||||
| module \$_SDFFE_NN1P_ (D, C, R, E, Q); | ||||
|     input  D; | ||||
|     input  C; | ||||
|     input  R; | ||||
|     input  E; | ||||
|     output Q; | ||||
|     sdffnsre _TECHMAP_REPLACE_ (.Q(Q), .D(D), .C(C), .E(E), .R(1'b1), .S(R)); | ||||
| endmodule | ||||
| 
 | ||||
| // Latch, no set/reset, no enable
 | ||||
| module  \$_DLATCH_P_ (input E, D, output Q); | ||||
|     latchsre  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .E(1'b1), .G(E), .R(1'b1), .S(1'b1)); | ||||
| endmodule | ||||
| 
 | ||||
| module  \$_DLATCH_N_ (input E, D, output Q); | ||||
|     latchnsre _TECHMAP_REPLACE_ (.D(D), .Q(Q), .E(1'b1), .G(E), .R(1'b1), .S(1'b1)); | ||||
| endmodule | ||||
| 
 | ||||
| // Latch with async set and reset and enable
 | ||||
| module  \$_DLATCHSR_PPP_ (input E, S, R, D, output Q); | ||||
|     latchsre  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .E(1'b1), .G(E),  .R(!R), .S(!S)); | ||||
| endmodule | ||||
| 
 | ||||
| module  \$_DLATCHSR_NPP_ (input E, S, R, D, output Q); | ||||
|     latchnsre _TECHMAP_REPLACE_ (.D(D), .Q(Q), .E(1'b1), .G(E),  .R(!R), .S(!S)); | ||||
| endmodule | ||||
| 
 | ||||
| module \$__SHREG_DFF_P_ (D, Q, C); | ||||
|     input  D; | ||||
|     input  C; | ||||
|     output Q; | ||||
| 
 | ||||
|     parameter DEPTH = 2; | ||||
| 
 | ||||
|     reg [DEPTH-2:0] q; | ||||
| 
 | ||||
|     genvar i; | ||||
|     generate for (i = 0; i < DEPTH; i = i + 1) begin: slice | ||||
| 
 | ||||
|         // First in chain
 | ||||
|         generate if (i == 0) begin | ||||
|                  sh_dff #() shreg_beg ( | ||||
|                     .Q(q[i]), | ||||
|                     .D(D), | ||||
|                     .C(C) | ||||
|                 ); | ||||
|         end endgenerate | ||||
|         // Middle in chain
 | ||||
|         generate if (i > 0 && i != DEPTH-1) begin | ||||
|                  sh_dff #() shreg_mid ( | ||||
|                     .Q(q[i]), | ||||
|                     .D(q[i-1]), | ||||
|                     .C(C) | ||||
|                 ); | ||||
|         end endgenerate | ||||
|         // Last in chain
 | ||||
|         generate if (i == DEPTH-1) begin | ||||
|                  sh_dff #() shreg_end ( | ||||
|                     .Q(Q), | ||||
|                     .D(q[i-1]), | ||||
|                     .C(C) | ||||
|                 ); | ||||
|         end endgenerate | ||||
|    end: slice | ||||
|    endgenerate | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
							
								
								
									
										22
									
								
								techlibs/quicklogic/qlf_k6n10f/libmap_brams.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								techlibs/quicklogic/qlf_k6n10f/libmap_brams.txt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| ram block $__QLF_TDP36K { | ||||
| 	init any; | ||||
| 	byte 9; | ||||
| 	option "SPLIT" 0 { | ||||
| 		abits 15; | ||||
| 		widths 1 2 4 9 18 36 per_port; | ||||
| 	} | ||||
| 	option "SPLIT" 1 { | ||||
| 		abits 14; | ||||
| 		widths 1 2 4 9 18 per_port; | ||||
| 	} | ||||
| 	cost 65; | ||||
| 	port srsw "A" "B" { | ||||
| 		width tied; | ||||
| 		clock posedge; | ||||
| 		# wen causes read even when ren is low | ||||
| 		# map clken = wen || ren | ||||
| 		clken; | ||||
| 		wrbe_separate; | ||||
| 		rdwr old; | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										457
									
								
								techlibs/quicklogic/qlf_k6n10f/libmap_brams_map.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										457
									
								
								techlibs/quicklogic/qlf_k6n10f/libmap_brams_map.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,457 @@ | |||
| // Copyright 2020-2022 F4PGA Authors
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| //
 | ||||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| 
 | ||||
| module \$__QLF_TDP36K (PORT_A_CLK, PORT_A_ADDR, PORT_A_WR_DATA, PORT_A_WR_EN, PORT_A_WR_BE, PORT_A_CLK_EN, PORT_A_RD_DATA, | ||||
| 					   PORT_B_CLK, PORT_B_ADDR, PORT_B_WR_DATA, PORT_B_WR_EN, PORT_B_WR_BE, PORT_B_CLK_EN, PORT_B_RD_DATA);   | ||||
| 
 | ||||
| parameter INIT = 0; | ||||
| 
 | ||||
| parameter OPTION_SPLIT = 0; | ||||
| 
 | ||||
| parameter PORT_A_WIDTH = 1; | ||||
| parameter PORT_A_WR_BE_WIDTH = 1; | ||||
| 
 | ||||
| parameter PORT_B_WIDTH = 1; | ||||
| parameter PORT_B_WR_BE_WIDTH = 1; | ||||
| 
 | ||||
| input PORT_A_CLK; | ||||
| input [14:0] PORT_A_ADDR; | ||||
| input [PORT_A_WIDTH-1:0] PORT_A_WR_DATA; | ||||
| input PORT_A_WR_EN; | ||||
| input [PORT_A_WR_BE_WIDTH-1:0] PORT_A_WR_BE; | ||||
| input PORT_A_CLK_EN; | ||||
| output [PORT_A_WIDTH-1:0] PORT_A_RD_DATA; | ||||
| 
 | ||||
| input PORT_B_CLK; | ||||
| input [14:0] PORT_B_ADDR; | ||||
| input [PORT_B_WIDTH-1:0] PORT_B_WR_DATA; | ||||
| input PORT_B_WR_EN; | ||||
| input [PORT_B_WR_BE_WIDTH-1:0] PORT_B_WR_BE; | ||||
| input PORT_B_CLK_EN; | ||||
| output [PORT_B_WIDTH-1:0] PORT_B_RD_DATA; | ||||
| 
 | ||||
| 
 | ||||
| // Fixed mode settings
 | ||||
| localparam [ 0:0] SYNC_FIFO1_i  = 1'd0; | ||||
| localparam [ 0:0] FMODE1_i      = 1'd0; | ||||
| localparam [ 0:0] POWERDN1_i    = 1'd0; | ||||
| localparam [ 0:0] SLEEP1_i      = 1'd0; | ||||
| localparam [ 0:0] PROTECT1_i    = 1'd0; | ||||
| localparam [11:0] UPAE1_i       = 12'd10; | ||||
| localparam [11:0] UPAF1_i       = 12'd10; | ||||
| 
 | ||||
| localparam [ 0:0] SYNC_FIFO2_i  = 1'd0; | ||||
| localparam [ 0:0] FMODE2_i      = 1'd0; | ||||
| localparam [ 0:0] POWERDN2_i    = 1'd0; | ||||
| localparam [ 0:0] SLEEP2_i      = 1'd0; | ||||
| localparam [ 0:0] PROTECT2_i    = 1'd0; | ||||
| localparam [10:0] UPAE2_i       = 11'd10; | ||||
| localparam [10:0] UPAF2_i       = 11'd10; | ||||
| 
 | ||||
| // Width mode function
 | ||||
| function [2:0] mode; | ||||
| input integer width; | ||||
| case (width) | ||||
| 1: mode = 3'b101; | ||||
| 2: mode = 3'b110; | ||||
| 4: mode = 3'b100; | ||||
| 8,9: mode = 3'b001; | ||||
| 16, 18: mode = 3'b010; | ||||
| 32, 36: mode = 3'b011; | ||||
| default: mode = 3'b000; | ||||
| endcase | ||||
| endfunction | ||||
| 
 | ||||
| wire REN_A1_i; | ||||
| wire REN_A2_i; | ||||
| 
 | ||||
| wire REN_B1_i; | ||||
| wire REN_B2_i; | ||||
| 
 | ||||
| wire WEN_A1_i; | ||||
| wire WEN_A2_i; | ||||
| 
 | ||||
| wire WEN_B1_i; | ||||
| wire WEN_B2_i; | ||||
| 
 | ||||
| wire [1:0] BE_A1_i; | ||||
| wire [1:0] BE_A2_i; | ||||
| 
 | ||||
| wire [1:0] BE_B1_i; | ||||
| wire [1:0] BE_B2_i; | ||||
| 
 | ||||
| wire [14:0] ADDR_A1_i; | ||||
| wire [13:0] ADDR_A2_i; | ||||
| 
 | ||||
| wire [14:0] ADDR_B1_i; | ||||
| wire [13:0] ADDR_B2_i; | ||||
| 
 | ||||
| wire [17:0] WDATA_A1_i; | ||||
| wire [17:0] WDATA_A2_i; | ||||
| 
 | ||||
| wire [17:0] WDATA_B1_i; | ||||
| wire [17:0] WDATA_B2_i; | ||||
| 
 | ||||
| wire [17:0] RDATA_A1_o; | ||||
| wire [17:0] RDATA_A2_o; | ||||
| 
 | ||||
| wire [17:0] RDATA_B1_o; | ||||
| wire [17:0] RDATA_B2_o; | ||||
| 
 | ||||
| 
 | ||||
| // Set port width mode (In non-split mode A2/B2 is not active. Set same values anyway to match previous behavior.)
 | ||||
| localparam [ 2:0] RMODE_A1_i    = mode(PORT_A_WIDTH); | ||||
| localparam [ 2:0] WMODE_A1_i    = mode(PORT_A_WIDTH); | ||||
| localparam [ 2:0] RMODE_A2_i    = mode(PORT_A_WIDTH); | ||||
| localparam [ 2:0] WMODE_A2_i    = mode(PORT_A_WIDTH); | ||||
| 
 | ||||
| localparam [ 2:0] RMODE_B1_i    = mode(PORT_B_WIDTH); | ||||
| localparam [ 2:0] WMODE_B1_i    = mode(PORT_B_WIDTH); | ||||
| localparam [ 2:0] RMODE_B2_i    = mode(PORT_B_WIDTH); | ||||
| localparam [ 2:0] WMODE_B2_i    = mode(PORT_B_WIDTH); | ||||
| 
 | ||||
| assign REN_A1_i = PORT_A_CLK_EN; | ||||
| assign WEN_A1_i = PORT_A_CLK_EN & PORT_A_WR_EN; | ||||
| assign {BE_A2_i, BE_A1_i} = PORT_A_WR_BE; | ||||
| 
 | ||||
| assign REN_B1_i = PORT_B_CLK_EN; | ||||
| assign WEN_B1_i = PORT_B_CLK_EN & PORT_B_WR_EN; | ||||
| assign {BE_B2_i, BE_B1_i} = PORT_B_WR_BE; | ||||
| 
 | ||||
| case (PORT_A_WIDTH) | ||||
| 9: assign { WDATA_A1_i[16], WDATA_A1_i[7:0] } = PORT_A_WR_DATA; | ||||
| 18: assign { WDATA_A1_i[17], WDATA_A1_i[15:8], WDATA_A1_i[16], WDATA_A1_i[7:0] } = PORT_A_WR_DATA; | ||||
| 36: assign { WDATA_A2_i[17], WDATA_A2_i[15:8], WDATA_A2_i[16], WDATA_A2_i[7:0], WDATA_A1_i[17], WDATA_A1_i[15:8], WDATA_A1_i[16], WDATA_A1_i[7:0]} = PORT_A_WR_DATA; | ||||
| default: assign WDATA_A1_i = PORT_A_WR_DATA; // 1,2,4
 | ||||
| endcase | ||||
| 
 | ||||
| case (PORT_B_WIDTH) | ||||
| 9: assign { WDATA_B1_i[16], WDATA_B1_i[7:0] } = PORT_B_WR_DATA; | ||||
| 18: assign { WDATA_B1_i[17], WDATA_B1_i[15:8], WDATA_B1_i[16], WDATA_B1_i[7:0] } = PORT_B_WR_DATA; | ||||
| 36: assign { WDATA_B2_i[17], WDATA_B2_i[15:8], WDATA_B2_i[16], WDATA_B2_i[7:0], WDATA_B1_i[17], WDATA_B1_i[15:8], WDATA_B1_i[16], WDATA_B1_i[7:0]} = PORT_B_WR_DATA; | ||||
| default: assign WDATA_B1_i = PORT_B_WR_DATA; // 1,2,4
 | ||||
| endcase | ||||
| 
 | ||||
| case (PORT_A_WIDTH) | ||||
| 9: assign PORT_A_RD_DATA = { RDATA_A1_o[16], RDATA_A1_o[7:0] }; | ||||
| 18: assign PORT_A_RD_DATA = { RDATA_A1_o[17], RDATA_A1_o[15:8], RDATA_A1_o[16], RDATA_A1_o[7:0] }; | ||||
| 36: assign PORT_A_RD_DATA = { RDATA_A2_o[17], RDATA_A2_o[15:8], RDATA_A2_o[16], RDATA_A2_o[7:0], RDATA_A1_o[17], RDATA_A1_o[15:8], RDATA_A1_o[16], RDATA_A1_o[7:0]}; | ||||
| default: assign PORT_A_RD_DATA = RDATA_A1_o; // 1,2,4
 | ||||
| endcase | ||||
| 
 | ||||
| case (PORT_B_WIDTH) | ||||
| 9: assign PORT_B_RD_DATA = { RDATA_B1_o[16], RDATA_B1_o[7:0] }; | ||||
| 18: assign PORT_B_RD_DATA = { RDATA_B1_o[17], RDATA_B1_o[15:8], RDATA_B1_o[16], RDATA_B1_o[7:0] }; | ||||
| 36: assign PORT_B_RD_DATA = { RDATA_B2_o[17], RDATA_B2_o[15:8], RDATA_B2_o[16], RDATA_B2_o[7:0], RDATA_B1_o[17], RDATA_B1_o[15:8], RDATA_B1_o[16], RDATA_B1_o[7:0]}; | ||||
| default: assign PORT_B_RD_DATA = RDATA_B1_o; // 1,2,4
 | ||||
| endcase | ||||
| 
 | ||||
| defparam _TECHMAP_REPLACE_.MODE_BITS = { 1'b0, | ||||
| 	UPAF2_i, UPAE2_i, PROTECT2_i, SLEEP2_i, POWERDN2_i, FMODE2_i, WMODE_B2_i, WMODE_A2_i, RMODE_B2_i, RMODE_A2_i, SYNC_FIFO2_i, | ||||
| 	UPAF1_i, UPAE1_i, PROTECT1_i, SLEEP1_i, POWERDN1_i, FMODE1_i, WMODE_B1_i, WMODE_A1_i, RMODE_B1_i, RMODE_A1_i, SYNC_FIFO1_i | ||||
| }; | ||||
| 
 | ||||
| (* is_inferred = 1 *) | ||||
| (* is_split = 0 *) | ||||
| (* port_a_width = PORT_A_WIDTH *) | ||||
| (* port_b_width = PORT_B_WIDTH *) | ||||
| TDP36K _TECHMAP_REPLACE_ ( | ||||
| 	.RESET_ni(1'b1), | ||||
| 
 | ||||
| 	.CLK_A1_i(PORT_A_CLK), | ||||
| 	.ADDR_A1_i(PORT_A_ADDR), | ||||
| 	.WEN_A1_i(WEN_A1_i), | ||||
| 	.BE_A1_i(BE_A1_i), | ||||
| 	.WDATA_A1_i(WDATA_A1_i), | ||||
| 	.REN_A1_i(REN_A1_i), | ||||
| 	.RDATA_A1_o(RDATA_A1_o), | ||||
| 
 | ||||
| 	.CLK_A2_i(PORT_A_CLK), | ||||
| 	.ADDR_A2_i(PORT_A_ADDR[13:0]), | ||||
| 	.WEN_A2_i(WEN_A1_i), | ||||
| 	.BE_A2_i(BE_A2_i), | ||||
| 	.WDATA_A2_i(WDATA_A2_i), | ||||
| 	.REN_A2_i(REN_A1_i), | ||||
| 	.RDATA_A2_o(RDATA_A2_o), | ||||
| 
 | ||||
| 	.CLK_B1_i(PORT_B_CLK), | ||||
| 	.ADDR_B1_i(PORT_B_ADDR), | ||||
| 	.WEN_B1_i(WEN_B1_i), | ||||
| 	.BE_B1_i(BE_B1_i), | ||||
| 	.WDATA_B1_i(WDATA_B1_i), | ||||
| 	.REN_B1_i(REN_B1_i), | ||||
| 	.RDATA_B1_o(RDATA_B1_o), | ||||
| 
 | ||||
| 	.CLK_B2_i(PORT_B_CLK), | ||||
| 	.ADDR_B2_i(PORT_B_ADDR[13:0]), | ||||
| 	.WEN_B2_i(WEN_B1_i), | ||||
| 	.BE_B2_i(BE_B2_i), | ||||
| 	.WDATA_B2_i(WDATA_B2_i), | ||||
| 	.REN_B2_i(REN_B1_i), | ||||
| 	.RDATA_B2_o(RDATA_B2_o), | ||||
| 
 | ||||
| 	.FLUSH1_i(1'b0), | ||||
| 	.FLUSH2_i(1'b0) | ||||
| ); | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| 
 | ||||
| module \$__QLF_TDP36K_MERGED (...); | ||||
| 
 | ||||
| parameter INIT1 = 0; | ||||
| 
 | ||||
| parameter PORT_A1_WIDTH = 1; | ||||
| parameter PORT_B1_WIDTH = 1; | ||||
| 
 | ||||
| parameter PORT_A1_WR_BE_WIDTH = 1; | ||||
| parameter PORT_B1_WR_BE_WIDTH = 1; | ||||
| 
 | ||||
| input PORT_A1_CLK; | ||||
| input [14:0] PORT_A1_ADDR; | ||||
| input [PORT_A1_WIDTH-1:0] PORT_A1_WR_DATA; | ||||
| input PORT_A1_WR_EN; | ||||
| input [PORT_A1_WR_BE_WIDTH-1:0] PORT_A1_WR_BE; | ||||
| input PORT_A1_CLK_EN; | ||||
| output [PORT_A1_WIDTH-1:0] PORT_A1_RD_DATA; | ||||
| 
 | ||||
| input PORT_B1_CLK; | ||||
| input [14:0] PORT_B1_ADDR; | ||||
| input [PORT_B1_WIDTH-1:0] PORT_B1_WR_DATA; | ||||
| input PORT_B1_WR_EN; | ||||
| input [PORT_B1_WR_BE_WIDTH-1:0] PORT_B1_WR_BE; | ||||
| input PORT_B1_CLK_EN; | ||||
| output [PORT_B1_WIDTH-1:0] PORT_B1_RD_DATA; | ||||
| 
 | ||||
| parameter INIT2 = 0; | ||||
| 
 | ||||
| parameter PORT_A2_WIDTH = 1; | ||||
| parameter PORT_B2_WIDTH = 1; | ||||
| parameter PORT_A2_WR_BE_WIDTH = 1; | ||||
| parameter PORT_B2_WR_BE_WIDTH = 1; | ||||
| 
 | ||||
| input PORT_A2_CLK; | ||||
| input [14:0] PORT_A2_ADDR; | ||||
| input [PORT_A2_WIDTH-1:0] PORT_A2_WR_DATA; | ||||
| input PORT_A2_WR_EN; | ||||
| input [PORT_A2_WR_BE_WIDTH-1:0] PORT_A2_WR_BE; | ||||
| input PORT_A2_CLK_EN; | ||||
| output [PORT_A2_WIDTH-1:0] PORT_A2_RD_DATA; | ||||
| 
 | ||||
| input PORT_B2_CLK; | ||||
| input [14:0] PORT_B2_ADDR; | ||||
| input [PORT_B2_WIDTH-1:0] PORT_B2_WR_DATA; | ||||
| input PORT_B2_WR_EN; | ||||
| input [PORT_B2_WR_BE_WIDTH-1:0] PORT_B2_WR_BE; | ||||
| input PORT_B2_CLK_EN; | ||||
| output [PORT_B2_WIDTH-1:0] PORT_B2_RD_DATA; | ||||
| 
 | ||||
| 
 | ||||
| // Fixed mode settings
 | ||||
| localparam [ 0:0] SYNC_FIFO1_i  = 1'd0; | ||||
| localparam [ 0:0] FMODE1_i      = 1'd0; | ||||
| localparam [ 0:0] POWERDN1_i    = 1'd0; | ||||
| localparam [ 0:0] SLEEP1_i      = 1'd0; | ||||
| localparam [ 0:0] PROTECT1_i    = 1'd0; | ||||
| localparam [11:0] UPAE1_i       = 12'd10; | ||||
| localparam [11:0] UPAF1_i       = 12'd10; | ||||
| 
 | ||||
| localparam [ 0:0] SYNC_FIFO2_i  = 1'd0; | ||||
| localparam [ 0:0] FMODE2_i      = 1'd0; | ||||
| localparam [ 0:0] POWERDN2_i    = 1'd0; | ||||
| localparam [ 0:0] SLEEP2_i      = 1'd0; | ||||
| localparam [ 0:0] PROTECT2_i    = 1'd0; | ||||
| localparam [10:0] UPAE2_i       = 11'd10; | ||||
| localparam [10:0] UPAF2_i       = 11'd10; | ||||
| 
 | ||||
| // Width mode function
 | ||||
| function [2:0] mode; | ||||
| input integer width; | ||||
| case (width) | ||||
| 1: mode = 3'b101; | ||||
| 2: mode = 3'b110; | ||||
| 4: mode = 3'b100; | ||||
| 8,9: mode = 3'b001; | ||||
| 16, 18: mode = 3'b010; | ||||
| default: mode = 3'b000; | ||||
| endcase | ||||
| endfunction | ||||
| 
 | ||||
| wire REN_A1_i; | ||||
| wire REN_A2_i; | ||||
| 
 | ||||
| wire REN_B1_i; | ||||
| wire REN_B2_i; | ||||
| 
 | ||||
| wire WEN_A1_i; | ||||
| wire WEN_A2_i; | ||||
| 
 | ||||
| wire WEN_B1_i; | ||||
| wire WEN_B2_i; | ||||
| 
 | ||||
| wire [1:0] BE_A1_i; | ||||
| wire [1:0] BE_A2_i; | ||||
| 
 | ||||
| wire [1:0] BE_B1_i; | ||||
| wire [1:0] BE_B2_i; | ||||
| 
 | ||||
| wire [14:0] ADDR_A1_i; | ||||
| wire [13:0] ADDR_A2_i; | ||||
| 
 | ||||
| wire [14:0] ADDR_B1_i; | ||||
| wire [13:0] ADDR_B2_i; | ||||
| 
 | ||||
| wire [17:0] WDATA_A1_i; | ||||
| wire [17:0] WDATA_A2_i; | ||||
| 
 | ||||
| wire [17:0] WDATA_B1_i; | ||||
| wire [17:0] WDATA_B2_i; | ||||
| 
 | ||||
| wire [17:0] RDATA_A1_o; | ||||
| wire [17:0] RDATA_A2_o; | ||||
| 
 | ||||
| wire [17:0] RDATA_B1_o; | ||||
| wire [17:0] RDATA_B2_o; | ||||
| 
 | ||||
| 
 | ||||
| // Set port width mode (In non-split mode A2/B2 is not active. Set same values anyway to match previous behavior.)
 | ||||
| localparam [ 2:0] RMODE_A1_i    = mode(PORT_A1_WIDTH); | ||||
| localparam [ 2:0] WMODE_A1_i    = mode(PORT_A1_WIDTH); | ||||
| localparam [ 2:0] RMODE_B1_i    = mode(PORT_B1_WIDTH); | ||||
| localparam [ 2:0] WMODE_B1_i    = mode(PORT_B1_WIDTH); | ||||
| 
 | ||||
| localparam [ 2:0] RMODE_A2_i    = mode(PORT_A2_WIDTH); | ||||
| localparam [ 2:0] WMODE_A2_i    = mode(PORT_A2_WIDTH); | ||||
| localparam [ 2:0] RMODE_B2_i    = mode(PORT_B2_WIDTH); | ||||
| localparam [ 2:0] WMODE_B2_i    = mode(PORT_B2_WIDTH); | ||||
| 
 | ||||
| assign REN_A1_i = PORT_A1_CLK_EN; | ||||
| assign WEN_A1_i = PORT_A1_CLK_EN & PORT_A1_WR_EN; | ||||
| assign BE_A1_i = PORT_A1_WR_BE; | ||||
| 
 | ||||
| assign REN_B1_i = PORT_B1_CLK_EN; | ||||
| assign WEN_B1_i = PORT_B1_CLK_EN & PORT_B1_WR_EN; | ||||
| assign BE_B1_i = PORT_B1_WR_BE; | ||||
| 
 | ||||
| assign REN_A2_i = PORT_A2_CLK_EN; | ||||
| assign WEN_A2_i = PORT_A2_CLK_EN & PORT_A2_WR_EN; | ||||
| assign BE_A2_i = PORT_A2_WR_BE; | ||||
| 
 | ||||
| assign REN_B2_i = PORT_B2_CLK_EN; | ||||
| assign WEN_B2_i = PORT_B2_CLK_EN & PORT_B2_WR_EN; | ||||
| assign BE_B2_i = PORT_B2_WR_BE; | ||||
| 
 | ||||
| assign ADDR_A1_i = PORT_A1_ADDR; | ||||
| assign ADDR_B1_i = PORT_B1_ADDR; | ||||
| assign ADDR_A2_i = PORT_A2_ADDR; | ||||
| assign ADDR_B2_i = PORT_B2_ADDR; | ||||
| 
 | ||||
| case (PORT_A1_WIDTH) | ||||
| 9: assign { WDATA_A1_i[16], WDATA_A1_i[7:0] } = PORT_A1_WR_DATA; | ||||
| 18: assign { WDATA_A1_i[17], WDATA_A1_i[15:8], WDATA_A1_i[16], WDATA_A1_i[7:0] } = PORT_A1_WR_DATA; | ||||
| default: assign WDATA_A1_i = PORT_A1_WR_DATA; // 1,2,4,8,16
 | ||||
| endcase | ||||
| 
 | ||||
| case (PORT_B1_WIDTH) | ||||
| 9: assign { WDATA_B1_i[16], WDATA_B1_i[7:0] } = PORT_B1_WR_DATA; | ||||
| 18: assign { WDATA_B1_i[17], WDATA_B1_i[15:8], WDATA_B1_i[16], WDATA_B1_i[7:0] } = PORT_B1_WR_DATA; | ||||
| default: assign WDATA_B1_i = PORT_B1_WR_DATA; // 1,2,4,8,16
 | ||||
| endcase | ||||
| 
 | ||||
| case (PORT_A1_WIDTH) | ||||
| 9: assign PORT_A1_RD_DATA = { RDATA_A1_o[16], RDATA_A1_o[7:0] }; | ||||
| 18: assign PORT_A1_RD_DATA = { RDATA_A1_o[17], RDATA_A1_o[15:8], RDATA_A1_o[16], RDATA_A1_o[7:0] }; | ||||
| default: assign PORT_A1_RD_DATA = RDATA_A1_o; // 1,2,4,8,16
 | ||||
| endcase | ||||
| 
 | ||||
| case (PORT_B1_WIDTH) | ||||
| 9: assign PORT_B1_RD_DATA = { RDATA_B1_o[16], RDATA_B1_o[7:0] }; | ||||
| 18: assign PORT_B1_RD_DATA = { RDATA_B1_o[17], RDATA_B1_o[15:8], RDATA_B1_o[16], RDATA_B1_o[7:0] }; | ||||
| default: assign PORT_B1_RD_DATA = RDATA_B1_o; // 1,2,4,8,16
 | ||||
| endcase | ||||
| 
 | ||||
| case (PORT_A2_WIDTH) | ||||
| 9: assign { WDATA_A2_i[16], WDATA_A2_i[7:0] } = PORT_A2_WR_DATA; | ||||
| 18: assign { WDATA_A2_i[17], WDATA_A2_i[15:8], WDATA_A2_i[16], WDATA_A2_i[7:0] } = PORT_A2_WR_DATA; | ||||
| default: assign WDATA_A2_i = PORT_A2_WR_DATA; // 1,2,4,8,16
 | ||||
| endcase | ||||
| 
 | ||||
| case (PORT_B2_WIDTH) | ||||
| 9: assign { WDATA_B2_i[16], WDATA_B2_i[7:0] } = PORT_B2_WR_DATA; | ||||
| 18: assign { WDATA_B2_i[17], WDATA_B2_i[15:8], WDATA_B2_i[16], WDATA_B2_i[7:0] } = PORT_B2_WR_DATA; | ||||
| default: assign WDATA_B2_i = PORT_B2_WR_DATA; // 1,2,4,8,16
 | ||||
| endcase | ||||
| 
 | ||||
| case (PORT_A2_WIDTH) | ||||
| 9: assign PORT_A2_RD_DATA = { RDATA_A2_o[16], RDATA_A2_o[7:0] }; | ||||
| 18: assign PORT_A2_RD_DATA = { RDATA_A2_o[17], RDATA_A2_o[15:8], RDATA_A2_o[16], RDATA_A2_o[7:0] }; | ||||
| default: assign PORT_A2_RD_DATA = RDATA_A2_o; // 1,2,4,8,16
 | ||||
| endcase | ||||
| 
 | ||||
| case (PORT_B2_WIDTH) | ||||
| 9: assign PORT_B2_RD_DATA = { RDATA_B2_o[16], RDATA_B2_o[7:0] }; | ||||
| 18: assign PORT_B2_RD_DATA = { RDATA_B2_o[17], RDATA_B2_o[15:8], RDATA_B2_o[16], RDATA_B2_o[7:0] }; | ||||
| default: assign PORT_B2_RD_DATA = RDATA_B2_o; // 1,2,4,8,16
 | ||||
| endcase | ||||
| 
 | ||||
| defparam _TECHMAP_REPLACE_.MODE_BITS = {1'b1, | ||||
| 			UPAF2_i, UPAE2_i, PROTECT2_i, SLEEP2_i, POWERDN2_i, FMODE2_i, WMODE_B2_i, WMODE_A2_i, RMODE_B2_i, RMODE_A2_i, SYNC_FIFO2_i, | ||||
| 			UPAF1_i, UPAE1_i, PROTECT1_i, SLEEP1_i, POWERDN1_i, FMODE1_i, WMODE_B1_i, WMODE_A1_i, RMODE_B1_i, RMODE_A1_i, SYNC_FIFO1_i | ||||
| 		}; | ||||
| 
 | ||||
| (* is_inferred = 1 *) | ||||
| (* is_split = 1 *) | ||||
| (* port_a1_width = PORT_A1_WIDTH *) | ||||
| (* port_a2_width = PORT_A2_WIDTH *) | ||||
| (* port_b1_width = PORT_B1_WIDTH *) | ||||
| (* port_b2_width = PORT_B2_WIDTH *) | ||||
| TDP36K _TECHMAP_REPLACE_ ( | ||||
| 	.RESET_ni(1'b1), | ||||
| 	.WDATA_A1_i(WDATA_A1_i), | ||||
| 	.WDATA_A2_i(WDATA_A2_i), | ||||
| 	.RDATA_A1_o(RDATA_A1_o), | ||||
| 	.RDATA_A2_o(RDATA_A2_o), | ||||
| 	.ADDR_A1_i(ADDR_A1_i), | ||||
| 	.ADDR_A2_i(ADDR_A2_i), | ||||
| 	.CLK_A1_i(PORT_A1_CLK), | ||||
| 	.CLK_A2_i(PORT_A2_CLK), | ||||
| 	.REN_A1_i(REN_A1_i), | ||||
| 	.REN_A2_i(REN_A2_i), | ||||
| 	.WEN_A1_i(WEN_A1_i), | ||||
| 	.WEN_A2_i(WEN_A2_i), | ||||
| 	.BE_A1_i(BE_A1_i), | ||||
| 	.BE_A2_i(BE_A2_i), | ||||
| 
 | ||||
| 	.WDATA_B1_i(WDATA_B1_i), | ||||
| 	.WDATA_B2_i(WDATA_B2_i), | ||||
| 	.RDATA_B1_o(RDATA_B1_o), | ||||
| 	.RDATA_B2_o(RDATA_B2_o), | ||||
| 	.ADDR_B1_i(ADDR_B1_i), | ||||
| 	.ADDR_B2_i(ADDR_B2_i), | ||||
| 	.CLK_B1_i(PORT_B1_CLK), | ||||
| 	.CLK_B2_i(PORT_B2_CLK), | ||||
| 	.REN_B1_i(REN_B1_i), | ||||
| 	.REN_B2_i(REN_B2_i), | ||||
| 	.WEN_B1_i(WEN_B1_i), | ||||
| 	.WEN_B2_i(WEN_B2_i), | ||||
| 	.BE_B1_i(BE_B1_i), | ||||
| 	.BE_B2_i(BE_B2_i), | ||||
| 
 | ||||
| 	.FLUSH1_i(1'b0), | ||||
| 	.FLUSH2_i(1'b0) | ||||
| ); | ||||
| 
 | ||||
| endmodule | ||||
							
								
								
									
										100
									
								
								techlibs/quicklogic/quicklogic_eqn.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								techlibs/quicklogic/quicklogic_eqn.cc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,100 @@ | |||
| /*
 | ||||
|  * Copyright 2020-2022 F4PGA Authors | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  * | ||||
|  * SPDX-License-Identifier: Apache-2.0 | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #include "kernel/sigtools.h" | ||||
| #include "kernel/yosys.h" | ||||
| 
 | ||||
| USING_YOSYS_NAMESPACE | ||||
| PRIVATE_NAMESPACE_BEGIN | ||||
| 
 | ||||
| struct QuicklogicEqnPass : public Pass { | ||||
|     QuicklogicEqnPass() : Pass("quicklogic_eqn", "Quicklogic: Calculate equations for luts") {} | ||||
|     void help() override | ||||
|     { | ||||
|         log("\n"); | ||||
|         log("    quicklogic_eqn [selection]\n"); | ||||
|         log("\n"); | ||||
|         log("Calculate equations for luts since bitstream generator depends on it.\n"); | ||||
|         log("\n"); | ||||
|     } | ||||
| 
 | ||||
|     Const init2eqn(Const init, int inputs) | ||||
|     { | ||||
|         std::string init_bits = init.as_string(); | ||||
|         const char *names[] = {"I0", "I1", "I2", "I3", "I4"}; | ||||
| 
 | ||||
|         std::string eqn; | ||||
|         int width = (int)pow(2, inputs); | ||||
|         for (int i = 0; i < width; i++) { | ||||
|             if (init_bits[width - 1 - i] == '1') { | ||||
|                 eqn += "("; | ||||
|                 for (int j = 0; j < inputs; j++) { | ||||
|                     if (i & (1 << j)) | ||||
|                         eqn += names[j]; | ||||
|                     else | ||||
|                         eqn += std::string("~") + names[j]; | ||||
| 
 | ||||
|                     if (j != (inputs - 1)) | ||||
|                         eqn += "*"; | ||||
|                 } | ||||
|                 eqn += ")+"; | ||||
|             } | ||||
|         } | ||||
|         if (eqn.empty()) | ||||
|             return Const("0"); | ||||
|         eqn = eqn.substr(0, eqn.length() - 1); | ||||
|         return Const(eqn); | ||||
|     } | ||||
| 
 | ||||
|     void execute(std::vector<std::string> args, RTLIL::Design *design) override | ||||
|     { | ||||
|         log_header(design, "Executing Quicklogic_EQN pass (calculate equations for luts).\n"); | ||||
| 
 | ||||
|         extra_args(args, args.size(), design); | ||||
| 
 | ||||
|         int cnt = 0; | ||||
|         for (auto module : design->selected_modules()) { | ||||
|             for (auto cell : module->selected_cells()) { | ||||
|                 if (cell->type == ID(LUT1)) { | ||||
|                     cell->setParam(ID(EQN), init2eqn(cell->getParam(ID::INIT), 1)); | ||||
|                     cnt++; | ||||
|                 } | ||||
|                 if (cell->type == ID(LUT2)) { | ||||
|                     cell->setParam(ID(EQN), init2eqn(cell->getParam(ID::INIT), 2)); | ||||
|                     cnt++; | ||||
|                 } | ||||
|                 if (cell->type == ID(LUT3)) { | ||||
|                     cell->setParam(ID(EQN), init2eqn(cell->getParam(ID::INIT), 3)); | ||||
|                     cnt++; | ||||
|                 } | ||||
|                 if (cell->type == ID(LUT4)) { | ||||
|                     cell->setParam(ID(EQN), init2eqn(cell->getParam(ID::INIT), 4)); | ||||
|                     cnt++; | ||||
|                 } | ||||
|                 if (cell->type == ID(LUT5)) { | ||||
|                     cell->setParam(ID(EQN), init2eqn(cell->getParam(ID::INIT), 5)); | ||||
|                     cnt++; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         log_header(design, "Updated %d of LUT* elements with equation.\n", cnt); | ||||
|     } | ||||
| } QuicklogicEqnPass; | ||||
| 
 | ||||
| PRIVATE_NAMESPACE_END | ||||
|  | @ -2,6 +2,7 @@ | |||
|  *  yosys -- Yosys Open SYnthesis Suite | ||||
|  * | ||||
|  *  Copyright (C) 2021 QuickLogic Corp. | ||||
|  *  Copyright 2020-2022 F4PGA Authors | ||||
|  * | ||||
|  *  Permission to use, copy, modify, and/or distribute this software for any | ||||
|  *  purpose with or without fee is hereby granted, provided that the above | ||||
|  | @ -30,6 +31,7 @@ struct SynthQuickLogicPass : public ScriptPass { | |||
| 
 | ||||
| 	void help() override | ||||
| 	{ | ||||
| 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||
| 		log("\n"); | ||||
| 		log("   synth_quicklogic [options]\n"); | ||||
| 		log("This command runs synthesis for QuickLogic FPGAs\n"); | ||||
|  | @ -42,6 +44,17 @@ struct SynthQuickLogicPass : public ScriptPass { | |||
| 		log("        generate the synthesis netlist for the specified family.\n"); | ||||
| 		log("        supported values:\n"); | ||||
| 		log("        - pp3: PolarPro 3 \n"); | ||||
| 		log("        - qlf_k6n10f: K6N10f\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -nocarry\n"); | ||||
| 		log("        do not use adder_carry cells in output netlist.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -nobram\n"); | ||||
| 		log("        do not use block RAM cells in output netlist.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -bramtypes\n"); | ||||
| 		log("        Emit specialized BRAM cells for particular address and data width\n"); | ||||
| 		log("        configurations.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -blif <file>\n"); | ||||
| 		log("        write the design to the specified BLIF file. writing of an output file\n"); | ||||
|  | @ -61,7 +74,7 @@ struct SynthQuickLogicPass : public ScriptPass { | |||
| 	} | ||||
| 
 | ||||
| 	string top_opt, blif_file, edif_file, family, currmodule, verilog_file, lib_path; | ||||
| 	bool abc9; | ||||
| 	bool abc9, inferAdder, nobram, bramTypes; | ||||
| 
 | ||||
| 	void clear_flags() override | ||||
| 	{ | ||||
|  | @ -72,12 +85,26 @@ struct SynthQuickLogicPass : public ScriptPass { | |||
| 		currmodule = ""; | ||||
| 		family = "pp3"; | ||||
| 		abc9 = true; | ||||
| 		inferAdder = true; | ||||
| 		nobram = false; | ||||
| 		bramTypes = false; | ||||
| 		lib_path = "+/quicklogic/"; | ||||
| 	} | ||||
| 
 | ||||
| 	void set_scratchpad_defaults(RTLIL::Design *design) { | ||||
| 		lib_path = design->scratchpad_get_string("ql.lib_path", lib_path); | ||||
| 		if (lib_path.back() != '/') | ||||
| 			lib_path += "/"; | ||||
| 		inferAdder = !design->scratchpad_get_bool("ql.nocarry", false); | ||||
| 		nobram = design->scratchpad_get_bool("ql.nobram", false); | ||||
| 		bramTypes = design->scratchpad_get_bool("ql.bramtypes", false); | ||||
| 	} | ||||
| 
 | ||||
| 	void execute(std::vector<std::string> args, RTLIL::Design *design) override | ||||
| 	{ | ||||
| 		string run_from, run_to; | ||||
| 		clear_flags(); | ||||
| 		set_scratchpad_defaults(design); | ||||
| 
 | ||||
| 		size_t argidx; | ||||
| 		for (argidx = 1; argidx < args.size(); argidx++) | ||||
|  | @ -114,6 +141,18 @@ struct SynthQuickLogicPass : public ScriptPass { | |||
| 				abc9 = false; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-nocarry") { | ||||
| 				inferAdder = false; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-nobram") { | ||||
| 				nobram = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-bramtypes") { | ||||
| 				bramTypes = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 		extra_args(args, argidx, design); | ||||
|  | @ -121,7 +160,7 @@ struct SynthQuickLogicPass : public ScriptPass { | |||
| 		if (!design->full_selection()) | ||||
| 			log_cmd_error("This command only operates on fully selected designs!\n"); | ||||
| 
 | ||||
| 		if (family != "pp3") | ||||
| 		if (family != "pp3" && family != "qlf_k6n10f") | ||||
| 			log_cmd_error("Invalid family specified: '%s'\n", family.c_str()); | ||||
| 
 | ||||
| 		if (abc9 && design->scratchpad_get_int("abc9.D", 0) == 0) { | ||||
|  | @ -144,14 +183,22 @@ struct SynthQuickLogicPass : public ScriptPass { | |||
| 		} | ||||
| 
 | ||||
| 		if (check_label("begin")) { | ||||
| 			run(stringf("read_verilog -lib -specify +/quicklogic/common/cells_sim.v +/quicklogic/%s/cells_sim.v", family.c_str())); | ||||
| 			std::string read_simlibs = stringf("read_verilog -lib -specify %scommon/cells_sim.v %s%s/cells_sim.v", lib_path.c_str(), lib_path.c_str(), family.c_str()); | ||||
| 			if (family == "qlf_k6n10f") { | ||||
| 				read_simlibs += stringf(" %sqlf_k6n10f/brams_sim.v", lib_path.c_str()); | ||||
| 				if (bramTypes) | ||||
| 					read_simlibs += stringf(" %sqlf_k6n10f/bram_types_sim.v", lib_path.c_str()); | ||||
| 			} | ||||
| 			run(read_simlibs); | ||||
| 			run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str())); | ||||
| 		} | ||||
| 
 | ||||
| 		if (check_label("prepare")) { | ||||
| 			run("proc"); | ||||
| 			run("flatten"); | ||||
| 			run("tribuf -logic"); | ||||
| 			if (help_mode || family == "pp3") { | ||||
| 				run("tribuf -logic", "                   (for pp3)"); | ||||
| 			} | ||||
| 			run("deminout"); | ||||
| 			run("opt_expr"); | ||||
| 			run("opt_clean"); | ||||
|  | @ -176,6 +223,71 @@ struct SynthQuickLogicPass : public ScriptPass { | |||
| 			run("opt_clean"); | ||||
| 		} | ||||
| 
 | ||||
| 		if (check_label("map_bram", "(for qlf_k6n10f, skip if -no_bram)") && (help_mode || family == "qlf_k6n10f")) { | ||||
| 			run("memory_libmap -lib " + lib_path + family + "/libmap_brams.txt"); | ||||
| 			run("ql_bram_merge"); | ||||
| 			run("techmap -map " + lib_path + family + "/libmap_brams_map.v"); | ||||
| 			run("techmap -autoproc -map " + lib_path + family + "/brams_map.v"); | ||||
| 			run("techmap -map " + lib_path + family + "/brams_final_map.v"); | ||||
| 
 | ||||
| 			if (help_mode) { | ||||
| 				run("chtype -set TDP36K_<mode> t:TDP36K a:<mode>", "(if -bram_types)"); | ||||
| 			} | ||||
| 			else if (bramTypes) { | ||||
| 				for (int a_dwidth : {1, 2, 4, 9, 18, 36}) | ||||
| 					for (int b_dwidth: {1, 2, 4, 9, 18, 36}) { | ||||
| 						run(stringf("chtype -set TDP36K_BRAM_A_X%d_B_X%d_nonsplit t:TDP36K a:is_inferred=0 %%i " | ||||
| 									"a:is_fifo=0 %%i a:port_a_dwidth=%d %%i a:port_b_dwidth=%d %%i", | ||||
| 									 a_dwidth, b_dwidth, a_dwidth, b_dwidth)); | ||||
| 						 | ||||
| 						run(stringf("chtype -set TDP36K_FIFO_ASYNC_A_X%d_B_X%d_nonsplit t:TDP36K a:is_inferred=0 %%i " | ||||
| 									"a:is_fifo=1 %%i a:sync_fifo=0 %%i a:port_a_dwidth=%d %%i a:port_b_dwidth=%d %%i",  | ||||
| 									 a_dwidth, b_dwidth, a_dwidth, b_dwidth)); | ||||
| 
 | ||||
| 						run(stringf("chtype -set TDP36K_FIFO_SYNC_A_X%d_B_X%d_nonsplit t:TDP36K a:is_inferred=0 %%i " | ||||
| 									"a:is_fifo=1 %%i a:sync_fifo=1 %%i a:port_a_dwidth=%d %%i a:port_b_dwidth=%d %%i",  | ||||
| 									 a_dwidth, b_dwidth, a_dwidth, b_dwidth)); | ||||
| 					} | ||||
| 
 | ||||
| 				for (int a1_dwidth : {1, 2, 4, 9, 18}) | ||||
| 					for (int b1_dwidth: {1, 2, 4, 9, 18}) | ||||
| 						for (int a2_dwidth : {1, 2, 4, 9, 18}) | ||||
| 							for (int b2_dwidth: {1, 2, 4, 9, 18}) { | ||||
| 								run(stringf("chtype -set TDP36K_BRAM_A1_X%d_B1_X%d_A2_X%d_B2_X%d_split t:TDP36K a:is_inferred=0 %%i " | ||||
| 											"a:is_split=1 %%i a:is_fifo=0 %%i " | ||||
| 											"a:port_a1_dwidth=%d %%i a:port_b1_dwidth=%d %%i a:port_a2_dwidth=%d %%i a:port_b2_dwidth=%d %%i", | ||||
| 											 a1_dwidth, b1_dwidth, a2_dwidth, b2_dwidth, a1_dwidth, b1_dwidth, a2_dwidth, b2_dwidth));	 | ||||
| 										 | ||||
| 								run(stringf("chtype -set TDP36K_FIFO_ASYNC_A1_X%d_B1_X%d_A2_X%d_B2_X%d_split t:TDP36K a:is_inferred=0 %%i " | ||||
| 											"a:is_split=1 %%i a:is_fifo=1 %%i a:sync_fifo=0 %%i " | ||||
| 											"a:port_a1_dwidth=%d %%i a:port_b1_dwidth=%d %%i a:port_a2_dwidth=%d %%i a:port_b2_dwidth=%d %%i", | ||||
| 											 a1_dwidth, b1_dwidth, a2_dwidth, b2_dwidth, a1_dwidth, b1_dwidth, a2_dwidth, b2_dwidth)); | ||||
| 
 | ||||
| 								run(stringf("chtype -set TDP36K_FIFO_SYNC_A1_X%d_B1_X%d_A2_X%d_B2_X%d_split t:TDP36K a:is_inferred=0 %%i " | ||||
| 											"a:is_split=1 %%i a:is_fifo=1 %%i a:sync_fifo=1 %%i " | ||||
| 											"a:port_a1_dwidth=%d %%i a:port_b1_dwidth=%d %%i a:port_a2_dwidth=%d %%i a:port_b2_dwidth=%d %%i", | ||||
| 											 a1_dwidth, b1_dwidth, a2_dwidth, b2_dwidth, a1_dwidth, b1_dwidth, a2_dwidth, b2_dwidth)); | ||||
| 							} | ||||
| 				 | ||||
| 
 | ||||
| 				for (int a_width : {1, 2, 4, 9, 18, 36}) | ||||
| 					for (int b_width: {1, 2, 4, 9, 18, 36}) { | ||||
| 						run(stringf("chtype -set TDP36K_BRAM_A_X%d_B_X%d_nonsplit t:TDP36K a:is_inferred=1 %%i " | ||||
| 									"a:port_a_width=%d %%i a:port_b_width=%d %%i", | ||||
| 						 			 a_width, b_width, a_width, b_width)); | ||||
| 					} | ||||
| 
 | ||||
| 				for (int a1_width : {1, 2, 4, 9, 18}) | ||||
| 					for (int b1_width: {1, 2, 4, 9, 18}) | ||||
| 						for (int a2_width : {1, 2, 4, 9, 18}) | ||||
| 							for (int b2_width: {1, 2, 4, 9, 18}) { | ||||
| 								run(stringf("chtype -set TDP36K_BRAM_A1_X%d_B1_X%d_A2_X%d_B2_X%d_split t:TDP36K a:is_inferred=1 %%i " | ||||
| 											"a:port_a1_width=%d %%i a:port_b1_width=%d %%i a:port_a2_width=%d %%i a:port_b2_width=%d %%i", | ||||
| 											 a1_width, b1_width, a2_width, b2_width, a1_width, b1_width, a2_width, b2_width)); | ||||
| 							} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if (check_label("map_ffram")) { | ||||
| 			run("opt -fast -mux_undef -undriven -fine"); | ||||
| 			run("memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block " | ||||
|  | @ -185,36 +297,65 @@ struct SynthQuickLogicPass : public ScriptPass { | |||
| 		} | ||||
| 
 | ||||
| 		if (check_label("map_gates")) { | ||||
| 			run("techmap"); | ||||
| 			if (inferAdder && family == "qlf_k6n10f") { | ||||
| 				run("techmap -map +/techmap.v -map " + lib_path + family + "/arith_map.v", "(unless -no_adder)"); | ||||
| 			} else { | ||||
| 				run("techmap"); | ||||
| 			} | ||||
| 			run("opt -fast"); | ||||
| 			run("muxcover -mux8 -mux4"); | ||||
| 			if (help_mode || family == "pp3") { | ||||
| 				run("muxcover -mux8 -mux4", "(for pp3)"); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if (check_label("map_ffs")) { | ||||
| 			run("opt_expr"); | ||||
| 			run("dfflegalize -cell $_DFFSRE_PPPP_ 0 -cell $_DLATCH_?_ x"); | ||||
| 
 | ||||
| 			run(stringf("techmap -map +/quicklogic/%s/cells_map.v -map +/quicklogic/%s/ffs_map.v", family.c_str(), family.c_str())); | ||||
| 
 | ||||
| 			run("opt_expr -mux_undef"); | ||||
| 			if (help_mode) { | ||||
| 				run("shregmap -minlen <min> -maxlen <max>", "(for qlf_k6n10f)"); | ||||
| 				run("dfflegalize -cell <supported FF types>"); | ||||
| 				run("techmap -map " + lib_path + family + "/cells_map.v", "(for pp3)"); | ||||
| 			} | ||||
| 			if (family == "pp3") { | ||||
| 				run("dfflegalize -cell $_DFFSRE_PPPP_ 0 -cell $_DLATCH_?_ x"); | ||||
| 				run("techmap -map " + lib_path + family + "/cells_map.v -map " + lib_path + family + "/ffs_map.v"); | ||||
| 				run("opt_expr -mux_undef"); | ||||
| 			} else if (family == "qlf_k6n10f") { | ||||
| 				run("shregmap -minlen 8 -maxlen 20"); | ||||
| 				// FIXME: Apparently dfflegalize leaves around $_DLATCH_[NP]_ even if
 | ||||
| 				// not in the allowed set. As a workaround we put them in the allowed
 | ||||
| 				// set explicitly and map them later to $_DLATCHSR_[NP]NN_.
 | ||||
| 				run("dfflegalize -cell $_DFFSRE_?NNP_ 0 -cell $_DLATCHSR_?NN_ 0 -cell $_DLATCH_?_ 0" " -cell $_SDFFE_?N?P_ 0"); | ||||
| 			} | ||||
| 			run("opt"); | ||||
| 		} | ||||
| 
 | ||||
| 		if (check_label("map_luts")) { | ||||
| 			run(stringf("techmap -map +/quicklogic/%s/latches_map.v", family.c_str())); | ||||
| 		if (check_label("map_luts", "(for pp3)") && (help_mode || family == "pp3")) { | ||||
| 			run("techmap -map " + lib_path + family + "/latches_map.v"); | ||||
| 			if (abc9) { | ||||
| 				run(stringf("read_verilog -lib -specify -icells +/quicklogic/%s/abc9_model.v", family.c_str())); | ||||
| 				run(stringf("techmap -map +/quicklogic/%s/abc9_map.v", family.c_str())); | ||||
| 				run("read_verilog -lib -specify -icells " + lib_path + family + "/abc9_model.v"); | ||||
| 				run("techmap -map " + lib_path + family + "/abc9_map.v"); | ||||
| 				run("abc9 -maxlut 4 -dff"); | ||||
| 				run(stringf("techmap -map +/quicklogic/%s/abc9_unmap.v", family.c_str())); | ||||
| 				run("techmap -map " + lib_path + family + "/abc9_unmap.v"); | ||||
| 			} else { | ||||
| 				run("abc -luts 1,2,2,4 -dress"); | ||||
| 			} | ||||
| 			run("clean"); | ||||
| 		} | ||||
| 
 | ||||
| 		if (check_label("map_cells")) { | ||||
| 			run(stringf("techmap -map +/quicklogic/%s/lut_map.v", family.c_str())); | ||||
| 		if (check_label("map_luts", "(for qlf_k6n10f)") && (help_mode || family == "qlf_k6n10f")) { | ||||
| 			if (abc9) { | ||||
| 				run("abc9 -maxlut 6"); | ||||
| 			} else { | ||||
| 				run("abc -lut 6 -dress"); | ||||
| 			} | ||||
| 			run("clean"); | ||||
| 			run("opt_lut"); | ||||
| 		} | ||||
| 
 | ||||
| 		if (check_label("map_cells", "(for pp3)") && (help_mode || family == "pp3")) { | ||||
| 			run("techmap -map " + lib_path + family + "/lut_map.v"); | ||||
| 			run("clean"); | ||||
| 			run("opt_lut"); | ||||
| 		} | ||||
| 
 | ||||
| 		if (check_label("check")) { | ||||
|  | @ -224,14 +365,18 @@ struct SynthQuickLogicPass : public ScriptPass { | |||
| 			run("check -noinit"); | ||||
| 		} | ||||
| 
 | ||||
| 		if (check_label("iomap")) { | ||||
| 		if (check_label("iomap", "(for pp3)") && (family == "pp3" || help_mode)) { | ||||
| 			run("clkbufmap -inpad ckpad Q:P"); | ||||
| 			run("iopadmap -bits -outpad outpad A:P -inpad inpad Q:P -tinoutpad bipad EN:Q:A:P A:top"); | ||||
| 		} | ||||
| 
 | ||||
| 		if (check_label("finalize")) { | ||||
| 			run("setundef -zero -params -undriven"); | ||||
| 			run("hilomap -hicell logic_1 A -locell logic_0 A -singleton A:top"); | ||||
| 			if (help_mode || family == "pp3") { | ||||
| 				run("setundef -zero -params -undriven", "(for pp3)"); | ||||
| 			} | ||||
| 			if (family == "pp3" || !edif_file.empty()) { | ||||
| 				run("hilomap -hicell logic_1 A -locell logic_0 A -singleton A:top", "(for pp3 or if -edif)"); | ||||
| 			} | ||||
| 			run("opt_clean -purge"); | ||||
| 			run("check"); | ||||
| 			run("blackbox =A:whitebox"); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue