mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-03 21:09:12 +00:00 
			
		
		
		
	intel_alm: ABC9 sequential optimisations
This commit is contained in:
		
							parent
							
								
									a9b61080a4
								
							
						
					
					
						commit
						83cde2d02b
					
				
					 7 changed files with 149 additions and 19 deletions
				
			
		| 
						 | 
					@ -2,6 +2,9 @@
 | 
				
			||||||
OBJS += techlibs/intel_alm/synth_intel_alm.o
 | 
					OBJS += techlibs/intel_alm/synth_intel_alm.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Techmap
 | 
					# Techmap
 | 
				
			||||||
 | 
					$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/abc9_map.v))
 | 
				
			||||||
 | 
					$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/abc9_unmap.v))
 | 
				
			||||||
 | 
					$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/abc9_model.v))
 | 
				
			||||||
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/alm_map.v))
 | 
					$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/alm_map.v))
 | 
				
			||||||
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/alm_sim.v))
 | 
					$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/alm_sim.v))
 | 
				
			||||||
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/arith_alm_map.v))
 | 
					$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/arith_alm_map.v))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										18
									
								
								techlibs/intel_alm/common/abc9_map.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								techlibs/intel_alm/common/abc9_map.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,18 @@
 | 
				
			||||||
 | 
					// This file exists to map purely-synchronous flops to ABC9 flops, while 
 | 
				
			||||||
 | 
					// mapping flops with asynchronous-clear as boxes, this is because ABC9 
 | 
				
			||||||
 | 
					// doesn't support asynchronous-clear flops in sequential synthesis.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module MISTRAL_FF(
 | 
				
			||||||
 | 
					    input DATAIN, CLK, ACLR, ENA, SCLR, SLOAD, SDATA,
 | 
				
			||||||
 | 
					    output reg Q
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					parameter _TECHMAP_CONSTMSK_ACLR_ = 1'b0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// If the async-clear is constant, we assume it's disabled.
 | 
				
			||||||
 | 
					if (_TECHMAP_CONSTMSK_ACLR_ != 1'b0)
 | 
				
			||||||
 | 
					    MISTRAL_FF_SYNCONLY _TECHMAP_REPLACE_ (.DATAIN(DATAIN), .CLK(CLK), .ENA(ENA), .SCLR(SCLR), .SLOAD(SLOAD), .SDATA(SDATA), .Q(Q));
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
					    wire _TECHMAP_FAIL_ = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
							
								
								
									
										55
									
								
								techlibs/intel_alm/common/abc9_model.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								techlibs/intel_alm/common/abc9_model.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,55 @@
 | 
				
			||||||
 | 
					`ifdef cyclonev
 | 
				
			||||||
 | 
					`define SYNCPATH 262
 | 
				
			||||||
 | 
					`define SYNCSETUP 522
 | 
				
			||||||
 | 
					`define COMBPATH 0
 | 
				
			||||||
 | 
					`endif
 | 
				
			||||||
 | 
					`ifdef cyclone10gx
 | 
				
			||||||
 | 
					`define SYNCPATH 219
 | 
				
			||||||
 | 
					`define SYNCSETUP 268
 | 
				
			||||||
 | 
					`define COMBPATH 0
 | 
				
			||||||
 | 
					`endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// fallback for when a family isn't detected (e.g. when techmapping for equivalence)
 | 
				
			||||||
 | 
					`ifndef SYNCPATH
 | 
				
			||||||
 | 
					`define SYNCPATH 0
 | 
				
			||||||
 | 
					`define SYNCSETUP 0
 | 
				
			||||||
 | 
					`define COMBPATH 0
 | 
				
			||||||
 | 
					`endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This is a purely-synchronous flop, that ABC9 can use for sequential synthesis.
 | 
				
			||||||
 | 
					(* abc9_flop, lib_whitebox *)
 | 
				
			||||||
 | 
					module MISTRAL_FF_SYNCONLY(
 | 
				
			||||||
 | 
					    input DATAIN, CLK, ENA, SCLR, SLOAD, SDATA,
 | 
				
			||||||
 | 
					    output reg Q
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					specify
 | 
				
			||||||
 | 
					    if (ENA) (posedge CLK => (Q : DATAIN)) = `SYNCPATH;
 | 
				
			||||||
 | 
					    if (ENA) (posedge CLK => (Q : SCLR)) = `SYNCPATH;
 | 
				
			||||||
 | 
					    if (ENA) (posedge CLK => (Q : SLOAD)) = `SYNCPATH;
 | 
				
			||||||
 | 
					    if (ENA) (posedge CLK => (Q : SDATA)) = `SYNCPATH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $setup(DATAIN, posedge CLK, `SYNCSETUP);
 | 
				
			||||||
 | 
					    $setup(ENA, posedge CLK, `SYNCSETUP);
 | 
				
			||||||
 | 
					    $setup(SCLR, posedge CLK, `SYNCSETUP);
 | 
				
			||||||
 | 
					    $setup(SLOAD, posedge CLK, `SYNCSETUP);
 | 
				
			||||||
 | 
					    $setup(SDATA, posedge CLK, `SYNCSETUP);
 | 
				
			||||||
 | 
					endspecify
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					initial begin
 | 
				
			||||||
 | 
					    // Altera flops initialise to zero.
 | 
				
			||||||
 | 
						Q = 0;
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					always @(posedge CLK) begin
 | 
				
			||||||
 | 
					    // Clock-enable
 | 
				
			||||||
 | 
						if (ENA) begin
 | 
				
			||||||
 | 
					        // Synchronous clear
 | 
				
			||||||
 | 
					        if (SCLR) Q <= 0;
 | 
				
			||||||
 | 
					        // Synchronous load
 | 
				
			||||||
 | 
					        else if (SLOAD) Q <= SDATA;
 | 
				
			||||||
 | 
					        else Q <= DATAIN;
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
							
								
								
									
										11
									
								
								techlibs/intel_alm/common/abc9_unmap.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								techlibs/intel_alm/common/abc9_unmap.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,11 @@
 | 
				
			||||||
 | 
					// After performing sequential synthesis, map the synchronous flops back to
 | 
				
			||||||
 | 
					// standard MISTRAL_FF flops.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module MISTRAL_FF_SYNCONLY(
 | 
				
			||||||
 | 
					    input DATAIN, CLK, ENA, SCLR, SLOAD, SDATA,
 | 
				
			||||||
 | 
					    output reg Q
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MISTRAL_FF _TECHMAP_REPLACE_ (.DATAIN(DATAIN), .CLK(CLK), .ACLR(1'b1), .ENA(ENA), .SCLR(SCLR), .SLOAD(SLOAD), .SDATA(SDATA), .Q(Q));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
| 
						 | 
					@ -53,23 +53,45 @@
 | 
				
			||||||
// Q: data output
 | 
					// Q: data output
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Note: the DFFEAS primitive is mostly emulated; it does not reflect what the hardware implements.
 | 
					// Note: the DFFEAS primitive is mostly emulated; it does not reflect what the hardware implements.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`ifdef cyclonev
 | 
				
			||||||
 | 
					`define SYNCPATH 262
 | 
				
			||||||
 | 
					`define SYNCSETUP 522
 | 
				
			||||||
 | 
					`define COMBPATH 0
 | 
				
			||||||
 | 
					`endif
 | 
				
			||||||
 | 
					`ifdef cyclone10gx
 | 
				
			||||||
 | 
					`define SYNCPATH 219
 | 
				
			||||||
 | 
					`define SYNCSETUP 268
 | 
				
			||||||
 | 
					`define COMBPATH 0
 | 
				
			||||||
 | 
					`endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// fallback for when a family isn't detected (e.g. when techmapping for equivalence)
 | 
				
			||||||
 | 
					`ifndef SYNCPATH
 | 
				
			||||||
 | 
					`define SYNCPATH 0
 | 
				
			||||||
 | 
					`define SYNCSETUP 0
 | 
				
			||||||
 | 
					`define COMBPATH 0
 | 
				
			||||||
 | 
					`endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(* abc9_box, lib_whitebox *)
 | 
				
			||||||
module MISTRAL_FF(
 | 
					module MISTRAL_FF(
 | 
				
			||||||
    input DATAIN, CLK, ACLR, ENA, SCLR, SLOAD, SDATA,
 | 
					    input DATAIN, CLK, ACLR, ENA, SCLR, SLOAD, SDATA,
 | 
				
			||||||
    output reg Q
 | 
					    output reg Q
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
`ifdef cyclonev
 | 
					 | 
				
			||||||
specify
 | 
					specify
 | 
				
			||||||
    (posedge CLK => (Q : DATAIN)) = 262;
 | 
					    if (ENA) (posedge CLK => (Q : DATAIN)) = `SYNCPATH;
 | 
				
			||||||
    $setup(DATAIN, posedge CLK, 522);
 | 
					    if (ENA) (posedge CLK => (Q : SCLR)) = `SYNCPATH;
 | 
				
			||||||
 | 
					    if (ENA) (posedge CLK => (Q : SLOAD)) = `SYNCPATH;
 | 
				
			||||||
 | 
					    if (ENA) (posedge CLK => (Q : SDATA)) = `SYNCPATH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $setup(DATAIN, posedge CLK, `SYNCSETUP);
 | 
				
			||||||
 | 
					    $setup(ENA, posedge CLK, `SYNCSETUP);
 | 
				
			||||||
 | 
					    $setup(SCLR, posedge CLK, `SYNCSETUP);
 | 
				
			||||||
 | 
					    $setup(SLOAD, posedge CLK, `SYNCSETUP);
 | 
				
			||||||
 | 
					    $setup(SDATA, posedge CLK, `SYNCSETUP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    (ACLR => Q) = `COMBPATH;
 | 
				
			||||||
endspecify
 | 
					endspecify
 | 
				
			||||||
`endif
 | 
					 | 
				
			||||||
`ifdef cyclone10gx
 | 
					 | 
				
			||||||
specify
 | 
					 | 
				
			||||||
    (posedge CLK => (Q : DATAIN)) = 219;
 | 
					 | 
				
			||||||
    $setup(DATAIN, posedge CLK, 268);
 | 
					 | 
				
			||||||
endspecify
 | 
					 | 
				
			||||||
`endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
initial begin
 | 
					initial begin
 | 
				
			||||||
    // Altera flops initialise to zero.
 | 
					    // Altera flops initialise to zero.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,10 +48,20 @@
 | 
				
			||||||
// the following model because it's very difficult to trigger this in practice
 | 
					// the following model because it's very difficult to trigger this in practice
 | 
				
			||||||
// as clock cycles will be much longer than any potential blip of 'x, so the
 | 
					// as clock cycles will be much longer than any potential blip of 'x, so the
 | 
				
			||||||
// model can be treated as always returning a defined result.
 | 
					// model can be treated as always returning a defined result.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(* abc9_box, lib_whitebox *)
 | 
				
			||||||
module MISTRAL_MLAB(input [4:0] A1ADDR, input A1DATA, A1EN, CLK1, input [4:0] B1ADDR, output B1DATA);
 | 
					module MISTRAL_MLAB(input [4:0] A1ADDR, input A1DATA, A1EN, CLK1, input [4:0] B1ADDR, output B1DATA);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
reg [31:0] mem = 32'b0;
 | 
					reg [31:0] mem = 32'b0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO
 | 
				
			||||||
 | 
					specify
 | 
				
			||||||
 | 
					    $setup(A1ADDR, posedge CLK1, 0);
 | 
				
			||||||
 | 
					    $setup(A1DATA, posedge CLK1, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    (B1ADDR *> B1DATA) = 0;
 | 
				
			||||||
 | 
					endspecify
 | 
				
			||||||
 | 
					
 | 
				
			||||||
always @(posedge CLK1)
 | 
					always @(posedge CLK1)
 | 
				
			||||||
    if (A1EN) mem[A1ADDR] <= A1DATA;
 | 
					    if (A1EN) mem[A1ADDR] <= A1DATA;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,20 +38,26 @@ struct SynthIntelALMPass : public ScriptPass {
 | 
				
			||||||
		log("This command runs synthesis for ALM-based Intel FPGAs.\n");
 | 
							log("This command runs synthesis for ALM-based Intel FPGAs.\n");
 | 
				
			||||||
		log("\n");
 | 
							log("\n");
 | 
				
			||||||
		log("    -top <module>\n");
 | 
							log("    -top <module>\n");
 | 
				
			||||||
		log("        use the specified module as top module (default='top')\n");
 | 
							log("        use the specified module as top module\n");
 | 
				
			||||||
		log("\n");
 | 
							log("\n");
 | 
				
			||||||
		log("    -family <family>\n");
 | 
							log("    -family <family>\n");
 | 
				
			||||||
		log("        target one of:\n");
 | 
							log("        target one of:\n");
 | 
				
			||||||
		log("        \"cyclonev\"    - Cyclone V (default)\n");
 | 
							log("        \"cyclonev\"    - Cyclone V (default)\n");
 | 
				
			||||||
		log("        \"cyclone10gx\" - Cyclone 10GX\n");
 | 
							log("        \"cyclone10gx\" - Cyclone 10GX\n");
 | 
				
			||||||
		log("\n");
 | 
							log("\n");
 | 
				
			||||||
		log("    -quartus\n");
 | 
					 | 
				
			||||||
		log("        output a netlist using Quartus cells instead of MISTRAL_* cells\n");
 | 
					 | 
				
			||||||
		log("\n");
 | 
					 | 
				
			||||||
		log("    -vqm <file>\n");
 | 
							log("    -vqm <file>\n");
 | 
				
			||||||
		log("        write the design to the specified Verilog Quartus Mapping File. Writing of an\n");
 | 
							log("        write the design to the specified Verilog Quartus Mapping File. Writing of an\n");
 | 
				
			||||||
		log("        output file is omitted if this parameter is not specified. Implies -quartus.\n");
 | 
							log("        output file is omitted if this parameter is not specified. Implies -quartus.\n");
 | 
				
			||||||
		log("\n");
 | 
							log("\n");
 | 
				
			||||||
 | 
							log("    -noflatten\n");
 | 
				
			||||||
 | 
							log("        do not flatten design before synthesis; useful for per-module area statistics\n");
 | 
				
			||||||
 | 
							log("\n");
 | 
				
			||||||
 | 
							log("    -quartus\n");
 | 
				
			||||||
 | 
							log("        output a netlist using Quartus cells instead of MISTRAL_* cells\n");
 | 
				
			||||||
 | 
							log("\n");
 | 
				
			||||||
 | 
							log("    -dff\n");
 | 
				
			||||||
 | 
							log("        pass DFFs to ABC to perform sequential logic optimisations (EXPERIMENTAL)\n");
 | 
				
			||||||
 | 
							log("\n");
 | 
				
			||||||
		log("    -run <from_label>:<to_label>\n");
 | 
							log("    -run <from_label>:<to_label>\n");
 | 
				
			||||||
		log("        only run the commands between the labels (see below). an empty\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");
 | 
							log("        from label is synonymous to 'begin', and empty to label is\n");
 | 
				
			||||||
| 
						 | 
					@ -63,16 +69,13 @@ struct SynthIntelALMPass : public ScriptPass {
 | 
				
			||||||
		log("    -nobram\n");
 | 
							log("    -nobram\n");
 | 
				
			||||||
		log("        do not use block RAM cells in output netlist\n");
 | 
							log("        do not use block RAM cells in output netlist\n");
 | 
				
			||||||
		log("\n");
 | 
							log("\n");
 | 
				
			||||||
		log("    -noflatten\n");
 | 
					 | 
				
			||||||
		log("        do not flatten design before synthesis\n");
 | 
					 | 
				
			||||||
		log("\n");
 | 
					 | 
				
			||||||
		log("The following commands are executed by this synthesis command:\n");
 | 
							log("The following commands are executed by this synthesis command:\n");
 | 
				
			||||||
		help_script();
 | 
							help_script();
 | 
				
			||||||
		log("\n");
 | 
							log("\n");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	string top_opt, family_opt, bram_type, vout_file;
 | 
						string top_opt, family_opt, bram_type, vout_file;
 | 
				
			||||||
	bool flatten, quartus, nolutram, nobram;
 | 
						bool flatten, quartus, nolutram, nobram, dff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void clear_flags() override
 | 
						void clear_flags() override
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					@ -84,6 +87,7 @@ struct SynthIntelALMPass : public ScriptPass {
 | 
				
			||||||
		quartus = false;
 | 
							quartus = false;
 | 
				
			||||||
		nolutram = false;
 | 
							nolutram = false;
 | 
				
			||||||
		nobram = false;
 | 
							nobram = false;
 | 
				
			||||||
 | 
							dff = false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void execute(std::vector<std::string> args, RTLIL::Design *design) override
 | 
						void execute(std::vector<std::string> args, RTLIL::Design *design) override
 | 
				
			||||||
| 
						 | 
					@ -130,6 +134,10 @@ struct SynthIntelALMPass : public ScriptPass {
 | 
				
			||||||
				flatten = false;
 | 
									flatten = false;
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								if (args[argidx] == "-dff") {
 | 
				
			||||||
 | 
									dff = true;
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		extra_args(args, argidx, design);
 | 
							extra_args(args, argidx, design);
 | 
				
			||||||
| 
						 | 
					@ -165,6 +173,7 @@ struct SynthIntelALMPass : public ScriptPass {
 | 
				
			||||||
			run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/alm_sim.v", family_opt.c_str()));
 | 
								run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/alm_sim.v", family_opt.c_str()));
 | 
				
			||||||
			run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/dff_sim.v", family_opt.c_str()));
 | 
								run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/dff_sim.v", family_opt.c_str()));
 | 
				
			||||||
			run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/mem_sim.v", family_opt.c_str()));
 | 
								run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/mem_sim.v", family_opt.c_str()));
 | 
				
			||||||
 | 
								run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/abc9_model.v", family_opt.c_str()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Misc and common cells
 | 
								// Misc and common cells
 | 
				
			||||||
			run("read_verilog -lib +/intel/common/altpll_bb.v");
 | 
								run("read_verilog -lib +/intel/common/altpll_bb.v");
 | 
				
			||||||
| 
						 | 
					@ -209,7 +218,9 @@ struct SynthIntelALMPass : public ScriptPass {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (check_label("map_luts")) {
 | 
							if (check_label("map_luts")) {
 | 
				
			||||||
			run("abc9 -maxlut 6 -W 200");
 | 
								run("techmap -map +/intel_alm/common/abc9_map.v");
 | 
				
			||||||
 | 
								run(stringf("abc9 %s -maxlut 6 -W 200", help_mode ? "[-dff]" : dff ? "-dff" : ""));
 | 
				
			||||||
 | 
								run("techmap -map +/intel_alm/common/abc9_unmap.v");
 | 
				
			||||||
			run("techmap -map +/intel_alm/common/alm_map.v");
 | 
								run("techmap -map +/intel_alm/common/alm_map.v");
 | 
				
			||||||
			run("opt -fast");
 | 
								run("opt -fast");
 | 
				
			||||||
			run("autoname");
 | 
								run("autoname");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue