diff options
Diffstat (limited to 'techlibs/sf2')
| -rw-r--r-- | techlibs/sf2/cells_map.v | 64 | ||||
| -rw-r--r-- | techlibs/sf2/cells_sim.v | 281 | ||||
| -rw-r--r-- | techlibs/sf2/sf2_iobs.cc | 217 | ||||
| -rw-r--r-- | techlibs/sf2/synth_sf2.cc | 16 | 
4 files changed, 450 insertions, 128 deletions
| diff --git a/techlibs/sf2/cells_map.v b/techlibs/sf2/cells_map.v index 5b8888294..6ad7807d2 100644 --- a/techlibs/sf2/cells_map.v +++ b/techlibs/sf2/cells_map.v @@ -1,40 +1,54 @@ -// module  \$_DFF_N_ (input D, C, output Q); SB_DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule +module  \$_DFF_N_ (input D, C, output Q); +  SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(1'b1), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule  module  \$_DFF_P_ (input D, C, output Q); -  SLE _TECHMAP_REPLACE_ ( -    .D(D), -    .CLK(C), -    .EN(1'b1), -    .ALn(1'b1), -    .ADn(1'b1), -    .SLn(1'b1), -    .SD(1'b0), -    .LAT(1'b0), -    .Q(Q) -  ); +  SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(1'b1), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFF_NN0_ (input D, C, R, output Q); +  SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFF_NN1_ (input D, C, R, output Q); +  SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFF_NP0_ (input D, C, R, output Q); +  SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(!R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFF_NP1_ (input D, C, R, output Q); +  SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(!R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFF_PN0_ (input D, C, R, output Q); +  SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFF_PN1_ (input D, C, R, output Q); +  SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFF_PP0_ (input D, C, R, output Q); +  SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(!R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFF_PP1_ (input D, C, R, output Q); +  SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(!R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));  endmodule  // module  \$_DFFE_NN_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule  // module  \$_DFFE_PN_ (input D, C, E, output Q); SB_DFFE  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule -//  +//  // module  \$_DFFE_NP_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule  // module  \$_DFFE_PP_ (input D, C, E, output Q); SB_DFFE  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule -//  -// module  \$_DFF_NN0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule -// module  \$_DFF_NN1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule -// module  \$_DFF_PN0_ (input D, C, R, output Q); SB_DFFR  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule -// module  \$_DFF_PN1_ (input D, C, R, output Q); SB_DFFS  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule -//  -// module  \$_DFF_NP0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule -// module  \$_DFF_NP1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule -// module  \$_DFF_PP0_ (input D, C, R, output Q); SB_DFFR  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule -// module  \$_DFF_PP1_ (input D, C, R, output Q); SB_DFFS  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule -//  +//  // module  \$__DFFE_NN0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule  // module  \$__DFFE_NN1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule  // module  \$__DFFE_PN0 (input D, C, E, R, output Q); SB_DFFER  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule  // module  \$__DFFE_PN1 (input D, C, E, R, output Q); SB_DFFES  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule -//  +//  // module  \$__DFFE_NP0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule  // module  \$__DFFE_NP1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule  // module  \$__DFFE_PP0 (input D, C, E, R, output Q); SB_DFFER  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule diff --git a/techlibs/sf2/cells_sim.v b/techlibs/sf2/cells_sim.v index f967068af..c62748b11 100644 --- a/techlibs/sf2/cells_sim.v +++ b/techlibs/sf2/cells_sim.v @@ -1,3 +1,114 @@ +// https://coredocs.s3.amazonaws.com/Libero/12_0_0/Tool/sf2_mlg.pdf + +module ADD2 ( + +	input A, B, +	output Y +); +	assign Y = A & B; +endmodule + +module ADD3 ( +	input A, B, C, +	output Y +); +	assign Y = A & B & C; +endmodule + +module ADD4 ( +	input A, B, C, D, +	output Y +); +	assign Y = A & B & C & D; +endmodule + +module CFG1 ( +	output Y, +	input A +); +	parameter [1:0] INIT = 2'h0; +	assign Y = INIT >> A; +endmodule + +module CFG2 ( +	output Y, +	input A, +	input B +); +	parameter [3:0] INIT = 4'h0; +	assign Y = INIT >> {B, A}; +endmodule + +module CFG3 ( +	output Y, +	input A, +	input B, +	input C +); +	parameter [7:0] INIT = 8'h0; +	assign Y = INIT >> {C, B, A}; +endmodule + +module CFG4 ( +	output Y, +	input A, +	input B, +	input C, +	input D +); +	parameter [15:0] INIT = 16'h0; +	assign Y = INIT >> {D, C, B, A}; +endmodule + +module BUFF ( +	input A, +	output Y +); +	assign Y = A; +endmodule + +module BUFD ( +	input A, +	output Y +); +	assign Y = A; +endmodule + +module CLKINT ( +	input A, +	output Y +); +	assign Y = A; +endmodule + +module CLKINT_PRESERVE ( +	input A, +	output Y +); +	assign Y = A; +endmodule + +module GCLKINT ( +	input A, EN, +	output Y +); +	assign Y = A & EN; +endmodule + +module RCLKINT ( +	input A, +	output Y +); +	assign Y = A; +endmodule + +module RGCLKINT ( +	input A, EN, +	output Y +); +	assign Y = A & EN; +endmodule +  module SLE (  	output Q,  	input ADn, @@ -36,44 +147,151 @@ module SLE (  	assign Q = LAT ? q_latch : q_ff;  endmodule -module CFG1 ( -	output Y, -	input A +// module AR1 +// module FCEND_BUFF +// module FCINIT_BUFF +// module FLASH_FREEZE +// module OSCILLATOR +// module SYSRESET +// module SYSCTRL_RESET_STATUS +// module LIVE_PROBE_FB +// module GCLKBUF +// module GCLKBUF_DIFF +// module GCLKBIBUF +// module DFN1 +// module DFN1C0 +// module DFN1E1 +// module DFN1E1C0 +// module DFN1E1P0 +// module DFN1P0 +// module DLN1 +// module DLN1C0 +// module DLN1P0 + +module INV ( +	input A, +	output Y  ); -	parameter [1:0] INIT = 2'h0; -	assign Y = INIT >> A; +	assign Y = !A;  endmodule -module CFG2 ( -	output Y, +module INVD (  	input A, -	input B +	output Y  ); -	parameter [3:0] INIT = 4'h0; -	assign Y = INIT >> {B, A}; +	assign Y = !A;  endmodule -module CFG3 ( -	output Y, -	input A, -	input B, -	input C +module MX2 ( +	input A, B, S, +	output Y  ); -	parameter [7:0] INIT = 8'h0; -	assign Y = INIT >> {C, B, A}; +	assign Y = S ? B : A;  endmodule -module CFG4 ( -	output Y, -	input A, -	input B, -	input C, -	input D +module MX4 ( +	input D0, D1, D2, D3, S0, S1, +	output Y  ); -	parameter [15:0] INIT = 16'h0; -	assign Y = INIT >> {D, C, B, A}; +	assign Y = S1 ? (S0 ? D3 : D2) : (S0 ? D1 : D0); +endmodule + +module NAND2 ( +	input A, B, +	output Y +); +	assign Y = !(A & B); +endmodule + +module NAND3 ( +	input A, B, C, +	output Y +); +	assign Y = !(A & B & C); +endmodule + +module NAND4 ( +	input A, B, C, D, +	output Y +); +	assign Y = !(A & B & C & D); +endmodule + +module NOR2 ( +	input A, B, +	output Y +); +	assign Y = !(A | B); +endmodule + +module NOR3 ( +	input A, B, C, +	output Y +); +	assign Y = !(A | B | C); +endmodule + +module NOR4 ( +	input A, B, C, D, +	output Y +); +	assign Y = !(A | B | C | D);  endmodule +module OR2 ( +	input A, B, +	output Y +); +	assign Y = A | B; +endmodule + +module OR3 ( +	input A, B, C, +	output Y +); +	assign Y = A | B | C; +endmodule + +module OR4 ( +	input A, B, C, D, +	output Y +); +	assign Y = A | B | C | D; +endmodule + +module XOR2 ( +	input A, B, +	output Y +); +	assign Y = A ^ B; +endmodule + +module XOR3 ( +	input A, B, C, +	output Y +); +	assign Y = A ^ B ^ C; +endmodule + +module XOR4 ( +	input A, B, C, D, +	output Y +); +	assign Y = A ^ B ^ C ^ D; +endmodule + +module XOR8 ( +	input A, B, C, D, E, F, G, H, +	output Y +); +	assign Y = A ^ B ^ C ^ D ^ E ^ F ^ G ^ H; +endmodule + +// module UJTAG +// module BIBUF +// module BIBUF_DIFF +// module CLKBIBUF +  module CLKBUF (  	input PAD,  	output Y @@ -81,6 +299,8 @@ module CLKBUF (  	assign Y = PAD;  endmodule +// module CLKBUF_DIFF +  module INBUF (  	input PAD,  	output Y @@ -88,9 +308,20 @@ module INBUF (  	assign Y = PAD;  endmodule +// module INBUF_DIFF +  module OUTBUF (  	input D,  	output PAD  );  	assign PAD = D;  endmodule + +// module OUTBUF_DIFF +// module TRIBUFF +// module TRIBUFF_DIFF +// module DDR_IN +// module DDR_OUT +// module RAM1K18 +// module RAM64x18 +// module MACC diff --git a/techlibs/sf2/sf2_iobs.cc b/techlibs/sf2/sf2_iobs.cc index 27141430c..3d43332e2 100644 --- a/techlibs/sf2/sf2_iobs.cc +++ b/techlibs/sf2/sf2_iobs.cc @@ -23,6 +23,136 @@  USING_YOSYS_NAMESPACE  PRIVATE_NAMESPACE_BEGIN +static void handle_iobufs(Module *module, bool clkbuf_mode) +{ +	SigMap sigmap(module); + +	pool<SigBit> clk_bits; +	pool<SigBit> handled_io_bits; +	dict<SigBit, SigBit> rewrite_bits; +	vector<pair<Cell*, SigBit>> pad_bits; + +	for (auto cell : module->cells()) +	{ +		if (clkbuf_mode && cell->type == "\\SLE") { +			for (auto bit : sigmap(cell->getPort("\\CLK"))) +				clk_bits.insert(bit); +		} +		if (cell->type.in("\\INBUF", "\\OUTBUF", "\\TRIBUFF", "\\BIBUF", "\\CLKBUF", "\\CLKBIBUF", +				"\\INBUF_DIFF", "\\OUTBUF_DIFF", "\\BIBUFF_DIFF", "\\TRIBUFF_DIFF", "\\CLKBUF_DIFF", +				"\\GCLKBUF", "\\GCLKBUF_DIFF", "\\GCLKBIBUF")) { +			for (auto bit : sigmap(cell->getPort("\\PAD"))) +				handled_io_bits.insert(bit); +		} +	} + +	for (auto wire : vector<Wire*>(module->wires())) +	{ +		if (!wire->port_input && !wire->port_output) +			continue; + +		for (int index = 0; index < GetSize(wire); index++) +		{ +			SigBit bit(wire, index); +			SigBit canonical_bit = sigmap(bit); + +			if (handled_io_bits.count(canonical_bit)) +				continue; + +			if (wire->port_input && wire->port_output) +				log_error("Failed to add buffer for inout port bit %s.\n", log_signal(bit)); + +			IdString buf_type, buf_port; + +			if (wire->port_output) { +				buf_type = "\\OUTBUF"; +				buf_port = "\\D"; +			} else if (clkbuf_mode && clk_bits.count(canonical_bit)) { +				buf_type = "\\CLKBUF"; +				buf_port = "\\Y"; +			} else { +				buf_type = "\\INBUF"; +				buf_port = "\\Y"; +			} + +			Cell *c = module->addCell(NEW_ID, buf_type); +			SigBit new_bit = module->addWire(NEW_ID); +			c->setPort(buf_port, new_bit); +			pad_bits.push_back(make_pair(c, bit)); +			rewrite_bits[canonical_bit] = new_bit; + +			log("Added %s cell %s for port bit %s.\n", log_id(c->type), log_id(c), log_signal(bit)); +		} +	} + +	auto rewrite_function = [&](SigSpec &s) { +		for (auto &bit : s) { +			SigBit canonical_bit = sigmap(bit); +			if (rewrite_bits.count(canonical_bit)) +				bit = rewrite_bits.at(canonical_bit); +		} +	}; + +	module->rewrite_sigspecs(rewrite_function); + +	for (auto &it : pad_bits) +		it.first->setPort("\\PAD", it.second); +} + +static void handle_clkint(Module *module) +{ +	SigMap sigmap(module); + +	pool<SigBit> clk_bits; +	vector<SigBit> handled_clk_bits; + +	for (auto cell : module->cells()) +	{ +		if (cell->type == "\\SLE") { +			for (auto bit : sigmap(cell->getPort("\\CLK"))) +				clk_bits.insert(bit); +		} +		if (cell->type.in("\\CLKBUF", "\\CLKBIBUF", "\\CLKBUF_DIFF", "\\GCLKBUF", "\\GCLKBUF_DIFF", "\\GCLKBIBUF", +				"\\CLKINT", "\\CLKINT_PRESERVE", "\\GCLKINT", "\\RCLKINT", "\\RGCLKINT")) { +			for (auto bit : sigmap(cell->getPort("\\Y"))) +				handled_clk_bits.push_back(bit); +		} +	} + +	for (auto bit : handled_clk_bits) +		clk_bits.erase(bit); + +	for (auto cell : vector<Cell*>(module->cells())) +	for (auto &conn : cell->connections()) +	{ +		if (!cell->output(conn.first)) +			continue; + +		SigSpec sig = conn.second; +		bool did_something = false; + +		for (auto &bit : sig) { +			SigBit canonical_bit = sigmap(bit); +			if (clk_bits.count(canonical_bit)) { +				Cell *c = module->addCell(NEW_ID, "\\CLKINT"); +				SigBit new_bit = module->addWire(NEW_ID); +				c->setPort("\\A", new_bit); +				c->setPort("\\Y", bit); +				log("Added %s cell %s for clock signal %s.\n", log_id(c->type), log_id(c), log_signal(bit)); +				clk_bits.erase(canonical_bit); +				did_something = true; +				bit = new_bit; +			} +		} + +		if (did_something) +			cell->setPort(conn.first, sig); +	} + +	for (auto bit : clk_bits) +		log_error("Failed to insert CLKINT for clock signal %s.\n", log_signal(bit)); +} +  struct Sf2IobsPass : public Pass {  	Sf2IobsPass() : Pass("sf2_iobs", "SF2: insert IO buffers") { }  	void help() YS_OVERRIDE @@ -31,20 +161,25 @@ struct Sf2IobsPass : public Pass {  		log("\n");  		log("    sf2_iobs [options] [selection]\n");  		log("\n"); -		log("Add SF2 I/O buffers to top module IOs as needed.\n"); +		log("Add SF2 I/O buffers and global buffers to top module as needed.\n"); +		log("\n"); +		log("    -clkbuf\n"); +		log("        Insert PAD->global_net clock buffers\n");  		log("\n");  	}  	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE  	{ +		bool clkbuf_mode = false; +  		log_header(design, "Executing sf2_iobs pass (insert IO buffers).\n");  		size_t argidx;  		for (argidx = 1; argidx < args.size(); argidx++)  		{ -			// if (args[argidx] == "-singleton") { -			// 	singleton_mode = true; -			// 	continue; -			// } +			if (args[argidx] == "-clkbuf") { +				clkbuf_mode = true; +				continue; +			}  			break;  		}  		extra_args(args, argidx, design); @@ -54,76 +189,8 @@ struct Sf2IobsPass : public Pass {  		if (module == nullptr)  			log_cmd_error("No top module found.\n"); -		SigMap sigmap(module); - -		pool<SigBit> clk_bits; -		pool<SigBit> handled_io_bits; -		dict<SigBit, SigBit> rewrite_bits; -		vector<pair<Cell*, SigBit>> pad_bits; - -		for (auto cell : module->cells()) -		{ -			if (cell->type == "\\SLE") { -				for (auto bit : sigmap(cell->getPort("\\CLK"))) -					clk_bits.insert(bit); -			} -			if (cell->type.in("\\INBUF", "\\OUTBUF", "\\CLKBUF")) { -				for (auto bit : sigmap(cell->getPort("\\PAD"))) -					handled_io_bits.insert(bit); -			} -		} - -		for (auto wire : vector<Wire*>(module->wires())) -		{ -			if (!wire->port_input && !wire->port_output) -				continue; - -			for (int index = 0; index < GetSize(wire); index++) -			{ -				SigBit bit(wire, index); -				SigBit canonical_bit = sigmap(bit); - -				if (handled_io_bits.count(canonical_bit)) -					continue; - -				if (wire->port_input && wire->port_output) -					log_error("Failed to add buffer for inout port bit %s.\n", log_signal(bit)); - -				IdString buf_type, buf_port; - -				if (wire->port_output) { -					buf_type = "\\OUTBUF"; -					buf_port = "\\D"; -				} else if (clk_bits.count(canonical_bit)) { -					buf_type = "\\CLKBUF"; -					buf_port = "\\Y"; -				} else { -					buf_type = "\\INBUF"; -					buf_port = "\\Y"; -				} - -				Cell *c = module->addCell(NEW_ID, buf_type); -				SigBit new_bit = module->addWire(NEW_ID); -				c->setPort(buf_port, new_bit); -				pad_bits.push_back(make_pair(c, bit)); -				rewrite_bits[canonical_bit] = new_bit; - -				log("Added %s cell %s for port bit %s.\n", log_id(c->type), log_id(c), log_signal(bit)); -			} -		} - -		auto rewrite_function = [&](SigSpec &s) { -			for (auto &bit : s) { -				SigBit canonical_bit = sigmap(bit); -				if (rewrite_bits.count(canonical_bit)) -					bit = rewrite_bits.at(canonical_bit); -			} -		}; - -		module->rewrite_sigspecs(rewrite_function); - -		for (auto &it : pad_bits) -			it.first->setPort("\\PAD", it.second); +		handle_iobufs(module, clkbuf_mode); +		handle_clkint(module);  	}  } Sf2IobsPass; diff --git a/techlibs/sf2/synth_sf2.cc b/techlibs/sf2/synth_sf2.cc index bdc20456d..0924df7a6 100644 --- a/techlibs/sf2/synth_sf2.cc +++ b/techlibs/sf2/synth_sf2.cc @@ -63,6 +63,9 @@ struct SynthSf2Pass : public ScriptPass  		log("    -noiobs\n");  		log("        run synthesis in \"block mode\", i.e. do not insert IO buffers\n");  		log("\n"); +		log("    -clkbuf\n"); +		log("        insert direct PAD->global_net buffers\n"); +		log("\n");  		log("    -retime\n");  		log("        run 'abc' with -dff option\n");  		log("\n"); @@ -73,7 +76,7 @@ struct SynthSf2Pass : public ScriptPass  	}  	string top_opt, edif_file, vlog_file, json_file; -	bool flatten, retime, iobs; +	bool flatten, retime, iobs, clkbuf;  	void clear_flags() YS_OVERRIDE  	{ @@ -84,6 +87,7 @@ struct SynthSf2Pass : public ScriptPass  		flatten = true;  		retime = false;  		iobs = true; +		clkbuf = false;  	}  	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE @@ -130,6 +134,10 @@ struct SynthSf2Pass : public ScriptPass  				iobs = false;  				continue;  			} +			if (args[argidx] == "-clkbuf") { +				clkbuf = true; +				continue; +			}  			break;  		}  		extra_args(args, argidx, design); @@ -201,8 +209,10 @@ struct SynthSf2Pass : public ScriptPass  		if (check_label("map_iobs"))  		{ -			if (iobs || help_mode) -				run("sf2_iobs", "(unless -noiobs)"); +			if (help_mode) +				run("sf2_iobs [-clkbuf]", "(unless -noiobs)"); +			else if (iobs) +				run(clkbuf ? "sf2_iobs -clkbuf" : "sf2_iobs");  			run("clean");  		} | 
