diff options
Diffstat (limited to 'passes')
| -rw-r--r-- | passes/cmds/clean_zerowidth.cc | 2 | ||||
| -rw-r--r-- | passes/cmds/stat.cc | 4 | ||||
| -rw-r--r-- | passes/sat/sim.cc | 6 | ||||
| -rw-r--r-- | passes/techmap/Makefile.inc | 2 | ||||
| -rw-r--r-- | passes/techmap/bmuxmap.cc | 76 | ||||
| -rw-r--r-- | passes/techmap/demuxmap.cc | 80 | ||||
| -rw-r--r-- | passes/techmap/simplemap.cc | 26 | ||||
| -rw-r--r-- | passes/tests/test_cell.cc | 46 | 
8 files changed, 239 insertions, 3 deletions
diff --git a/passes/cmds/clean_zerowidth.cc b/passes/cmds/clean_zerowidth.cc index 4e7c68093..bac6b1521 100644 --- a/passes/cmds/clean_zerowidth.cc +++ b/passes/cmds/clean_zerowidth.cc @@ -80,7 +80,7 @@ struct CleanZeroWidthPass : public Pass {  					if (GetSize(cell->getPort(ID::Q)) == 0) {  						module->remove(cell);  					} -				} else if (cell->type == ID($pmux)) { +				} else if (cell->type.in(ID($pmux), ID($bmux), ID($demux))) {  					// Remove altogether if WIDTH is 0, replace with  					// a connection if S_WIDTH is 0.  					if (cell->getParam(ID::WIDTH).as_int() == 0) { diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index 14a27ed99..fffdda48e 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -117,6 +117,10 @@ struct statdata_t  				}  				else if (cell_type.in(ID($mux), ID($pmux)))  					cell_type = stringf("%s_%d", cell_type.c_str(), GetSize(cell->getPort(ID::Y))); +				else if (cell_type == ID($bmux)) +					cell_type = stringf("%s_%d_%d", cell_type.c_str(), GetSize(cell->getPort(ID::Y)), GetSize(cell->getPort(ID::S))); +				else if (cell_type == ID($demux)) +					cell_type = stringf("%s_%d_%d", cell_type.c_str(), GetSize(cell->getPort(ID::A)), GetSize(cell->getPort(ID::S)));  				else if (cell_type.in(  						ID($sr), ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($dffsre),  						ID($adff), ID($adffe), ID($sdff), ID($sdffe), ID($sdffce), diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index 4e158da62..8a44830d2 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -313,6 +313,12 @@ struct SimInstance  				return;  			} +			// (A,S -> Y) cells +			if (has_a && !has_b && !has_c && !has_d && has_s && has_y) { +				set_state(sig_y, CellTypes::eval(cell, get_state(sig_a), get_state(sig_s))); +				return; +			} +  			// (A,B,S -> Y) cells  			if (has_a && has_b && !has_c && !has_d && has_s && has_y) {  				set_state(sig_y, CellTypes::eval(cell, get_state(sig_a), get_state(sig_b), get_state(sig_s))); diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index 035699603..98ccfc303 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -29,6 +29,8 @@ OBJS += passes/techmap/extract_reduce.o  OBJS += passes/techmap/alumacc.o  OBJS += passes/techmap/dffinit.o  OBJS += passes/techmap/pmuxtree.o +OBJS += passes/techmap/bmuxmap.o +OBJS += passes/techmap/demuxmap.o  OBJS += passes/techmap/muxcover.o  OBJS += passes/techmap/aigmap.o  OBJS += passes/techmap/tribuf.o diff --git a/passes/techmap/bmuxmap.cc b/passes/techmap/bmuxmap.cc new file mode 100644 index 000000000..03673c278 --- /dev/null +++ b/passes/techmap/bmuxmap.cc @@ -0,0 +1,76 @@ +/* + *  yosys -- Yosys Open SYnthesis Suite + * + *  Copyright (C) 2022  Marcelina KoĆcielnicka <mwk@0x04.net> + * + *  Permission to use, copy, modify, and/or distribute this software for any + *  purpose with or without fee is hereby granted, provided that the above + *  copyright notice and this permission notice appear in all copies. + * + *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/yosys.h" +#include "kernel/sigtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct BmuxmapPass : public Pass { +	BmuxmapPass() : Pass("bmuxmap", "transform $bmux cells to trees of $mux cells") { } +	void help() override +	{ +		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +		log("\n"); +		log("    bmuxmap [selection]\n"); +		log("\n"); +		log("This pass transforms $bmux cells to trees of $mux cells.\n"); +		log("\n"); +	} +	void execute(std::vector<std::string> args, RTLIL::Design *design) override +	{ +		log_header(design, "Executing BMUXMAP pass.\n"); + +		size_t argidx; +		for (argidx = 1; argidx < args.size(); argidx++) { +			break; +		} +		extra_args(args, argidx, design); + +		for (auto module : design->selected_modules()) +		for (auto cell : module->selected_cells()) +		{ +			if (cell->type != ID($bmux)) +				continue; + +			SigSpec sel = cell->getPort(ID::S); +			SigSpec data = cell->getPort(ID::A); +			int width = GetSize(cell->getPort(ID::Y)); + +			for (int idx = 0; idx < GetSize(sel); idx++) { +				SigSpec new_data = module->addWire(NEW_ID, GetSize(data)/2); +				for (int i = 0; i < GetSize(new_data); i += width) { +					RTLIL::Cell *mux = module->addMux(NEW_ID, +							data.extract(i*2, width), +							data.extract(i*2+width, width), +							sel[idx], +							new_data.extract(i, width)); +					mux->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); +				} +				data = new_data; +			} + +			module->connect(cell->getPort(ID::Y), data); +			module->remove(cell); +		} +	} +} BmuxmapPass; + +PRIVATE_NAMESPACE_END diff --git a/passes/techmap/demuxmap.cc b/passes/techmap/demuxmap.cc new file mode 100644 index 000000000..292b18bad --- /dev/null +++ b/passes/techmap/demuxmap.cc @@ -0,0 +1,80 @@ +/* + *  yosys -- Yosys Open SYnthesis Suite + * + *  Copyright (C) 2022  Marcelina KoĆcielnicka <mwk@0x04.net> + * + *  Permission to use, copy, modify, and/or distribute this software for any + *  purpose with or without fee is hereby granted, provided that the above + *  copyright notice and this permission notice appear in all copies. + * + *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/yosys.h" +#include "kernel/sigtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct DemuxmapPass : public Pass { +	DemuxmapPass() : Pass("demuxmap", "transform $demux cells to $eq + $mux cells") { } +	void help() override +	{ +		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +		log("\n"); +		log("    demuxmap [selection]\n"); +		log("\n"); +		log("This pass transforms $demux cells to a bunch of equality comparisons.\n"); +		log("\n"); +	} +	void execute(std::vector<std::string> args, RTLIL::Design *design) override +	{ +		log_header(design, "Executing DEMUXMAP pass.\n"); + +		size_t argidx; +		for (argidx = 1; argidx < args.size(); argidx++) { +			break; +		} +		extra_args(args, argidx, design); + +		for (auto module : design->selected_modules()) +		for (auto cell : module->selected_cells()) +		{ +			if (cell->type != ID($demux)) +				continue; + +			SigSpec sel = cell->getPort(ID::S); +			SigSpec data = cell->getPort(ID::A); +			SigSpec out = cell->getPort(ID::Y); +			int width = GetSize(cell->getPort(ID::A)); + +			for (int i = 0; i < 1 << GetSize(sel); i++) { +				if (width == 1 && data == State::S1) { +					RTLIL::Cell *eq_cell = module->addEq(NEW_ID, sel, Const(i, GetSize(sel)), out[i]); +					eq_cell->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); +				} else { +					Wire *eq = module->addWire(NEW_ID); +					RTLIL::Cell *eq_cell = module->addEq(NEW_ID, sel, Const(i, GetSize(sel)), eq); +					eq_cell->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); +					RTLIL::Cell *mux = module->addMux(NEW_ID, +							Const(State::S0, width), +							data, +							eq, +							out.extract(i*width, width)); +					mux->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); +				} +			} + +			module->remove(cell); +		} +	} +} DemuxmapPass; + +PRIVATE_NAMESPACE_END diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc index 68f44cf6d..7d8dba439 100644 --- a/passes/techmap/simplemap.cc +++ b/passes/techmap/simplemap.cc @@ -299,6 +299,30 @@ void simplemap_tribuf(RTLIL::Module *module, RTLIL::Cell *cell)  	}  } +void simplemap_bmux(RTLIL::Module *module, RTLIL::Cell *cell) +{ +	SigSpec sel = cell->getPort(ID::S); +	SigSpec data = cell->getPort(ID::A); +	int width = GetSize(cell->getPort(ID::Y)); + +	for (int idx = 0; idx < GetSize(sel); idx++) { +		SigSpec new_data = module->addWire(NEW_ID, GetSize(data)/2); +		for (int i = 0; i < GetSize(new_data); i += width) { +			for (int k = 0; k < width; k++) { +				RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_)); +				gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src)); +				gate->setPort(ID::A, data[i*2+k]); +				gate->setPort(ID::B, data[i*2+width+k]); +				gate->setPort(ID::S, sel[idx]); +				gate->setPort(ID::Y, new_data[i+k]); +			} +		} +		data = new_data; +	} + +	module->connect(cell->getPort(ID::Y), data); +} +  void simplemap_lut(RTLIL::Module *module, RTLIL::Cell *cell)  {  	SigSpec lut_ctrl = cell->getPort(ID::A); @@ -306,7 +330,6 @@ void simplemap_lut(RTLIL::Module *module, RTLIL::Cell *cell)  	lut_data.extend_u0(1 << cell->getParam(ID::WIDTH).as_int());  	for (int idx = 0; GetSize(lut_data) > 1; idx++) { -		SigSpec sig_s = lut_ctrl[idx];  		SigSpec new_lut_data = module->addWire(NEW_ID, GetSize(lut_data)/2);  		for (int i = 0; i < GetSize(lut_data); i += 2) {  			RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_)); @@ -400,6 +423,7 @@ void simplemap_get_mappers(dict<IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)>  	mappers[ID($nex)]         = simplemap_eqne;  	mappers[ID($mux)]         = simplemap_mux;  	mappers[ID($tribuf)]      = simplemap_tribuf; +	mappers[ID($bmux)]        = simplemap_bmux;  	mappers[ID($lut)]         = simplemap_lut;  	mappers[ID($sop)]         = simplemap_sop;  	mappers[ID($slice)]       = simplemap_slice; diff --git a/passes/tests/test_cell.cc b/passes/tests/test_cell.cc index 4e437e409..e21ec452c 100644 --- a/passes/tests/test_cell.cc +++ b/passes/tests/test_cell.cc @@ -69,6 +69,48 @@ static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type,  		cell->setPort(ID::Y, wire);  	} +	if (cell_type == ID($bmux)) +	{ +		int width = 1 + xorshift32(8); +		int swidth = 1 + xorshift32(4); + +		wire = module->addWire(ID::A); +		wire->width = width << swidth; +		wire->port_input = true; +		cell->setPort(ID::A, wire); + +		wire = module->addWire(ID::S); +		wire->width = swidth; +		wire->port_input = true; +		cell->setPort(ID::S, wire); + +		wire = module->addWire(ID::Y); +		wire->width = width; +		wire->port_output = true; +		cell->setPort(ID::Y, wire); +	} + +	if (cell_type == ID($demux)) +	{ +		int width = 1 + xorshift32(8); +		int swidth = 1 + xorshift32(6); + +		wire = module->addWire(ID::A); +		wire->width = width; +		wire->port_input = true; +		cell->setPort(ID::A, wire); + +		wire = module->addWire(ID::S); +		wire->width = swidth; +		wire->port_input = true; +		cell->setPort(ID::S, wire); + +		wire = module->addWire(ID::Y); +		wire->width = width << swidth; +		wire->port_output = true; +		cell->setPort(ID::Y, wire); +	} +  	if (cell_type == ID($fa))  	{  		int width = 1 + xorshift32(8); @@ -855,8 +897,10 @@ struct TestCellPass : public Pass {  		cell_types[ID($logic_and)] = "ABSY";  		cell_types[ID($logic_or)]  = "ABSY"; +		cell_types[ID($mux)] = "*"; +		cell_types[ID($bmux)] = "*"; +		cell_types[ID($demux)] = "*";  		if (edges) { -			cell_types[ID($mux)] = "*";  			cell_types[ID($pmux)] = "*";  		}  | 
