mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	Merge remote-tracking branch 'upstream/master'
This commit is contained in:
		
						commit
						4cce7f6967
					
				
					 31 changed files with 622 additions and 105 deletions
				
			
		|  | @ -169,7 +169,6 @@ struct FirrtlWorker | |||
| 		return *str == '\\' ? str + 1 : str; | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 	std::string cellname(RTLIL::Cell *cell) | ||||
| 	{ | ||||
| 		return fid(cell->name).c_str(); | ||||
|  | @ -219,29 +218,42 @@ struct FirrtlWorker | |||
| 			if (it->second.size() > 0) { | ||||
| 				const SigSpec &secondSig = it->second; | ||||
| 				const std::string firstName = cell_name + "." + make_id(it->first); | ||||
| 				const std::string secondName = make_expr(secondSig); | ||||
| 				const std::string secondExpr = make_expr(secondSig); | ||||
| 				// Find the direction for this port.
 | ||||
| 				FDirection dir = getPortFDirection(it->first, instModule); | ||||
| 				std::string source, sink; | ||||
| 				std::string sourceExpr, sinkExpr; | ||||
| 				const SigSpec *sinkSig = nullptr; | ||||
| 				switch (dir) { | ||||
| 					case FD_INOUT: | ||||
| 						log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", cell_type.c_str(), log_signal(it->second)); | ||||
| 					case FD_OUT: | ||||
| 						source = firstName; | ||||
| 						sink = secondName; | ||||
| 						sourceExpr = firstName; | ||||
| 						sinkExpr = secondExpr; | ||||
| 						sinkSig = &secondSig; | ||||
| 						break; | ||||
| 					case FD_NODIRECTION: | ||||
| 						log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", cell_type.c_str(), log_signal(it->second)); | ||||
| 						/* FALL_THROUGH */ | ||||
| 					case FD_IN: | ||||
| 						source = secondName; | ||||
| 						sink = firstName; | ||||
| 						sourceExpr = secondExpr; | ||||
| 						sinkExpr = firstName; | ||||
| 						break; | ||||
| 					default: | ||||
| 						log_error("Instance port %s.%s unrecognized connection direction 0x%x !\n", cell_type.c_str(), log_signal(it->second), dir); | ||||
| 						break; | ||||
| 				} | ||||
| 				wire_exprs.push_back(stringf("\n%s%s <= %s", indent.c_str(), sink.c_str(), source.c_str())); | ||||
| 				// Check for subfield assignment.
 | ||||
| 				std::string bitsString = "bits("; | ||||
| 				if (sinkExpr.substr(0, bitsString.length()) == bitsString ) { | ||||
| 					if (sinkSig == nullptr) | ||||
| 						log_error("Unknown subfield %s.%s\n", cell_type.c_str(), sinkExpr.c_str()); | ||||
| 					// Don't generate the assignment here.
 | ||||
| 					// Add the source and sink to the "reverse_wire_map" and we'll output the assignment
 | ||||
| 					//  as part of the coalesced subfield assignments for this wire.
 | ||||
| 					register_reverse_wire_map(sourceExpr, *sinkSig); | ||||
| 				} else { | ||||
| 					wire_exprs.push_back(stringf("\n%s%s <= %s", indent.c_str(), sinkExpr.c_str(), sourceExpr.c_str())); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		wire_exprs.push_back(stringf("\n")); | ||||
|  |  | |||
|  | @ -48,7 +48,7 @@ struct ProtobufDesignSerializer | |||
| 
 | ||||
| 	ProtobufDesignSerializer(bool use_selection, bool aig_mode) : | ||||
| 			aig_mode_(aig_mode), use_selection_(use_selection) { } | ||||
| 	 | ||||
| 
 | ||||
| 	string get_name(IdString name) | ||||
| 	{ | ||||
| 		return RTLIL::unescape_id(name); | ||||
|  | @ -60,7 +60,7 @@ struct ProtobufDesignSerializer | |||
| 	{ | ||||
| 		for (auto ¶m : parameters) { | ||||
| 			std::string key = get_name(param.first); | ||||
| 			 | ||||
| 
 | ||||
| 
 | ||||
| 			yosys::pb::Parameter pb_param; | ||||
| 
 | ||||
|  | @ -207,7 +207,7 @@ struct ProtobufDesignSerializer | |||
| 			(*models)[aig.name] = pb_model; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 
 | ||||
| 	void serialize_design(yosys::pb::Design *pb, Design *design) | ||||
| 	{ | ||||
| 		GOOGLE_PROTOBUF_VERIFY_VERSION; | ||||
|  |  | |||
|  | @ -1103,20 +1103,27 @@ struct Smt2Worker | |||
| 							break; | ||||
| 
 | ||||
| 						Const initword = init_data.extract(i*width, width, State::Sx); | ||||
| 						Const initmask = initword; | ||||
| 						bool gen_init_constr = false; | ||||
| 
 | ||||
| 						for (auto bit : initword.bits) | ||||
| 							if (bit == State::S0 || bit == State::S1) | ||||
| 						for (int k = 0; k < GetSize(initword); k++) { | ||||
| 							if (initword[k] == State::S0 || initword[k] == State::S1) { | ||||
| 								gen_init_constr = true; | ||||
| 								initmask[k] = State::S1; | ||||
| 							} else { | ||||
| 								initmask[k] = State::S0; | ||||
| 								initword[k] = State::S0; | ||||
| 							} | ||||
| 						} | ||||
| 
 | ||||
| 						if (gen_init_constr) | ||||
| 						{ | ||||
| 							if (statebv) | ||||
| 								/* FIXME */; | ||||
| 							else | ||||
| 								init_list.push_back(stringf("(= (select (|%s#%d#0| state) #b%s) #b%s) ; %s[%d]", | ||||
| 								init_list.push_back(stringf("(= (bvand (select (|%s#%d#0| state) #b%s) #b%s) #b%s) ; %s[%d]", | ||||
| 										get_id(module), arrayid, Const(i, abits).as_string().c_str(), | ||||
| 										initword.as_string().c_str(), get_id(cell), i)); | ||||
| 										initmask.as_string().c_str(), initword.as_string().c_str(), get_id(cell), i)); | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
|  |  | |||
|  | @ -33,7 +33,7 @@ | |||
| USING_YOSYS_NAMESPACE | ||||
| PRIVATE_NAMESPACE_BEGIN | ||||
| 
 | ||||
| bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, defparam, decimal; | ||||
| bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, defparam, decimal, siminit; | ||||
| int auto_name_counter, auto_name_offset, auto_name_digits; | ||||
| std::map<RTLIL::IdString, int> auto_name_map; | ||||
| std::set<RTLIL::IdString> reg_wires, reg_ct; | ||||
|  | @ -1310,7 +1310,7 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (reg_ct.count(cell->type) && cell->hasPort("\\Q")) { | ||||
| 	if (siminit && reg_ct.count(cell->type) && cell->hasPort("\\Q")) { | ||||
| 		std::stringstream ss; | ||||
| 		dump_reg_init(ss, cell->getPort("\\Q")); | ||||
| 		if (!ss.str().empty()) { | ||||
|  | @ -1607,6 +1607,10 @@ struct VerilogBackend : public Backend { | |||
| 		log("        without this option all internal cells are converted to Verilog\n"); | ||||
| 		log("        expressions.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -siminit\n"); | ||||
| 		log("        add initial statements with hierarchical refs to initialize FFs when\n"); | ||||
| 		log("        in -noexpr mode.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -nodec\n"); | ||||
| 		log("        32-bit constant values are by default dumped as decimal numbers,\n"); | ||||
| 		log("        not bit pattern. This option deactivates this feature and instead\n"); | ||||
|  | @ -1663,6 +1667,7 @@ struct VerilogBackend : public Backend { | |||
| 		nostr = false; | ||||
| 		defparam = false; | ||||
| 		decimal = false; | ||||
| 		siminit = false; | ||||
| 		auto_prefix = ""; | ||||
| 
 | ||||
| 		bool blackboxes = false; | ||||
|  | @ -1739,6 +1744,10 @@ struct VerilogBackend : public Backend { | |||
| 				decimal = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (arg == "-siminit") { | ||||
| 				siminit = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (arg == "-blackboxes") { | ||||
| 				blackboxes = true; | ||||
| 				continue; | ||||
|  |  | |||
|  | @ -2316,7 +2316,7 @@ struct ReadPass : public Pass { | |||
| 	} | ||||
| 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||
| 	{ | ||||
| 		if (args.size() < 2) | ||||
| 		if (args.size() < 2 || args[1][0] != '-') | ||||
| 			log_cmd_error("Missing mode parameter.\n"); | ||||
| 
 | ||||
| 		if (args.size() < 3) | ||||
|  |  | |||
|  | @ -1,12 +1,12 @@ | |||
| // | ||||
| // yosys -- Yosys Open SYnthesis Suite | ||||
| //  | ||||
| // | ||||
| // Copyright (C) 2018  Serge Bazanski <q3k@symbioticeda.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 | ||||
|  | @ -73,7 +73,7 @@ message Module { | |||
|         BitVector bits = 2; | ||||
|     } | ||||
|     map<string, Port> port = 2; | ||||
|      | ||||
| 
 | ||||
|     // Named cells in this module. | ||||
|     message Cell { | ||||
|         // Set to true when the name of this cell is automatically created and | ||||
|  | @ -129,7 +129,7 @@ message Model { | |||
|             TYPE_FALSE = 6; | ||||
|         }; | ||||
|         Type type = 1; | ||||
|      | ||||
| 
 | ||||
|         message Port { | ||||
|             // Name of port. | ||||
|             string portname = 1; | ||||
|  | @ -148,7 +148,7 @@ message Model { | |||
|             // Set for AND, NAND. | ||||
|             Gate gate = 3; | ||||
|         } | ||||
|      | ||||
| 
 | ||||
|         // Set when the node drives given output port(s). | ||||
|         message OutPort { | ||||
|             // Name of port. | ||||
|  |  | |||
|  | @ -53,6 +53,7 @@ struct WreduceWorker | |||
| 	std::set<Cell*, IdString::compare_ptr_by_name<Cell>> work_queue_cells; | ||||
| 	std::set<SigBit> work_queue_bits; | ||||
| 	pool<SigBit> keep_bits; | ||||
| 	dict<SigBit, State> init_bits; | ||||
| 
 | ||||
| 	WreduceWorker(WreduceConfig *config, Module *module) : | ||||
| 			config(config), module(module), mi(module) { } | ||||
|  | @ -141,6 +142,7 @@ struct WreduceWorker | |||
| 
 | ||||
| 		SigSpec sig_d = mi.sigmap(cell->getPort("\\D")); | ||||
| 		SigSpec sig_q = mi.sigmap(cell->getPort("\\Q")); | ||||
| 		Const initval; | ||||
| 
 | ||||
| 		int width_before = GetSize(sig_q); | ||||
| 
 | ||||
|  | @ -150,16 +152,24 @@ struct WreduceWorker | |||
| 		bool zero_ext = sig_d[GetSize(sig_d)-1] == State::S0; | ||||
| 		bool sign_ext = !zero_ext; | ||||
| 
 | ||||
| 		for (int i = 0; i < GetSize(sig_q); i++) { | ||||
| 			SigBit bit = sig_q[i]; | ||||
| 			if (init_bits.count(bit)) | ||||
| 				initval.bits.push_back(init_bits.at(bit)); | ||||
| 			else | ||||
| 				initval.bits.push_back(State::Sx); | ||||
| 		} | ||||
| 
 | ||||
| 		for (int i = GetSize(sig_q)-1; i >= 0; i--) | ||||
| 		{ | ||||
| 			if (zero_ext && sig_d[i] == State::S0) { | ||||
| 			if (zero_ext && sig_d[i] == State::S0 && (initval[i] == State::S0 || initval[i] == State::Sx)) { | ||||
| 				module->connect(sig_q[i], State::S0); | ||||
| 				sig_d.remove(i); | ||||
| 				sig_q.remove(i); | ||||
| 				continue; | ||||
| 			} | ||||
| 
 | ||||
| 			if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1]) { | ||||
| 			if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1] && initval[i] == initval[i-1]) { | ||||
| 				module->connect(sig_q[i], sig_q[i-1]); | ||||
| 				sig_d.remove(i); | ||||
| 				sig_q.remove(i); | ||||
|  | @ -167,7 +177,7 @@ struct WreduceWorker | |||
| 			} | ||||
| 
 | ||||
| 			auto info = mi.query(sig_q[i]); | ||||
| 			if (!info->is_output && GetSize(info->ports) <= 1 && !keep_bits.count(mi.sigmap(sig_q[i]))) { | ||||
| 			if (!info->is_output && GetSize(info->ports) == 1 && !keep_bits.count(mi.sigmap(sig_q[i]))) { | ||||
| 				sig_d.remove(i); | ||||
| 				sig_q.remove(i); | ||||
| 				zero_ext = false; | ||||
|  | @ -183,10 +193,11 @@ struct WreduceWorker | |||
| 
 | ||||
| 		if (GetSize(sig_q) == 0) { | ||||
| 			log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); | ||||
| 			module->remove(cell); | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		log("Removed top %d bits (of %d) from mux cell %s.%s (%s).\n", width_before - GetSize(sig_q), width_before, | ||||
| 		log("Removed top %d bits (of %d) from FF cell %s.%s (%s).\n", width_before - GetSize(sig_q), width_before, | ||||
| 				log_id(module), log_id(cell), log_id(cell->type)); | ||||
| 
 | ||||
| 		for (auto bit : sig_d) | ||||
|  | @ -376,10 +387,18 @@ struct WreduceWorker | |||
| 
 | ||||
| 	void run() | ||||
| 	{ | ||||
| 		for (auto w : module->wires()) | ||||
| 		for (auto w : module->wires()) { | ||||
| 			if (w->get_bool_attribute("\\keep")) | ||||
| 				for (auto bit : mi.sigmap(w)) | ||||
| 					keep_bits.insert(bit); | ||||
| 			if (w->attributes.count("\\init")) { | ||||
| 				Const initval = w->attributes.at("\\init"); | ||||
| 				SigSpec initsig = mi.sigmap(w); | ||||
| 				int width = std::min(GetSize(initval), GetSize(initsig)); | ||||
| 				for (int i = 0; i < width; i++) | ||||
| 					init_bits[initsig[i]] = initval[i]; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		for (auto c : module->selected_cells()) | ||||
| 			work_queue_cells.insert(c); | ||||
|  |  | |||
|  | @ -4,5 +4,5 @@ passes/pmgen/ice40_dsp.o: passes/pmgen/ice40_dsp_pm.h | |||
| EXTRA_OBJS += passes/pmgen/ice40_dsp_pm.h | ||||
| .SECONDARY: passes/pmgen/ice40_dsp_pm.h | ||||
| 
 | ||||
| passes/pmgen/ice40_dsp_pm.h: passes/pmgen/ice40_dsp.pmg passes/pmgen/pmgen.py | ||||
| 	$(P) cd passes/pmgen && python3 pmgen.py ice40_dsp | ||||
| passes/pmgen/ice40_dsp_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_dsp.pmg | ||||
| 	$(P) mkdir -p passes/pmgen && python3 $^ | ||||
|  |  | |||
|  | @ -6,7 +6,10 @@ import pprint | |||
| 
 | ||||
| pp = pprint.PrettyPrinter(indent=4) | ||||
| 
 | ||||
| prefix = sys.argv[1] | ||||
| pmgfile = sys.argv[1] | ||||
| assert pmgfile.endswith(".pmg") | ||||
| prefix = pmgfile[0:-4] | ||||
| pmname = prefix.split('/')[-1] | ||||
| 
 | ||||
| state_types = dict() | ||||
| udata_types = dict() | ||||
|  | @ -73,7 +76,7 @@ def rewrite_cpp(s): | |||
| 
 | ||||
|     return "".join(t) | ||||
| 
 | ||||
| with open("%s.pmg" % prefix, "r") as f: | ||||
| with open(pmgfile, "r") as f: | ||||
|     while True: | ||||
|         line = f.readline() | ||||
|         if line == "": break | ||||
|  | @ -82,7 +85,7 @@ with open("%s.pmg" % prefix, "r") as f: | |||
|         cmd = line.split() | ||||
|         if len(cmd) == 0 or cmd[0].startswith("//"): continue | ||||
|         cmd = cmd[0] | ||||
|          | ||||
| 
 | ||||
|         if cmd == "state": | ||||
|             m = re.match(r"^state\s+<(.*?)>\s+(([A-Za-z_][A-Za-z_0-9]*\s+)*[A-Za-z_][A-Za-z_0-9]*)\s*$", line) | ||||
|             assert m | ||||
|  | @ -187,10 +190,10 @@ with open("%s_pm.h" % prefix, "w") as f: | |||
|     print("YOSYS_NAMESPACE_BEGIN", file=f) | ||||
|     print("", file=f) | ||||
| 
 | ||||
|     print("struct {}_pm {{".format(prefix), file=f) | ||||
|     print("struct {}_pm {{".format(pmname), file=f) | ||||
|     print("  Module *module;", file=f) | ||||
|     print("  SigMap sigmap;", file=f) | ||||
|     print("  std::function<void()> on_accept;".format(prefix), file=f) | ||||
|     print("  std::function<void()> on_accept;".format(pmname), file=f) | ||||
|     print("", file=f) | ||||
| 
 | ||||
|     for index in range(len(blocks)): | ||||
|  | @ -288,7 +291,7 @@ with open("%s_pm.h" % prefix, "w") as f: | |||
|     print("  }", file=f) | ||||
|     print("", file=f) | ||||
| 
 | ||||
|     print("  {}_pm(Module *module, const vector<Cell*> &cells) :".format(prefix), file=f) | ||||
|     print("  {}_pm(Module *module, const vector<Cell*> &cells) :".format(pmname), file=f) | ||||
|     print("      module(module), sigmap(module) {", file=f) | ||||
|     for s, t in sorted(udata_types.items()): | ||||
|         if t.endswith("*"): | ||||
|  | @ -318,7 +321,7 @@ with open("%s_pm.h" % prefix, "w") as f: | |||
|     print("  }", file=f) | ||||
|     print("", file=f) | ||||
| 
 | ||||
|     print("  ~{}_pm() {{".format(prefix), file=f) | ||||
|     print("  ~{}_pm() {{".format(pmname), file=f) | ||||
|     print("    for (auto cell : autoremove_cells)", file=f) | ||||
|     print("      module->remove(cell);", file=f) | ||||
|     print("  }", file=f) | ||||
|  | @ -337,7 +340,7 @@ with open("%s_pm.h" % prefix, "w") as f: | |||
|     print("  }", file=f) | ||||
|     print("", file=f) | ||||
| 
 | ||||
|     print("  void run(std::function<void({}_pm&)> on_accept_f) {{".format(prefix), file=f) | ||||
|     print("  void run(std::function<void({}_pm&)> on_accept_f) {{".format(pmname), file=f) | ||||
|     print("    run([&](){on_accept_f(*this);});", file=f) | ||||
|     print("  }", file=f) | ||||
|     print("", file=f) | ||||
|  |  | |||
|  | @ -8,4 +8,5 @@ OBJS += passes/sat/expose.o | |||
| OBJS += passes/sat/assertpmux.o | ||||
| OBJS += passes/sat/clk2fflogic.o | ||||
| OBJS += passes/sat/async2sync.o | ||||
| OBJS += passes/sat/supercover.o | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										92
									
								
								passes/sat/supercover.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								passes/sat/supercover.cc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,92 @@ | |||
| /*
 | ||||
|  *  yosys -- Yosys Open SYnthesis Suite | ||||
|  * | ||||
|  *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> | ||||
|  * | ||||
|  *  Permission to use, copy, modify, and/or distribute this software for any | ||||
|  *  purpose with or without fee is hereby granted, provided that the above | ||||
|  *  copyright notice and this permission notice appear in all copies. | ||||
|  * | ||||
|  *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||
|  *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||
|  *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||
|  *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||
|  *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||
|  *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||
|  *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #include "kernel/yosys.h" | ||||
| #include "kernel/sigtools.h" | ||||
| 
 | ||||
| USING_YOSYS_NAMESPACE | ||||
| PRIVATE_NAMESPACE_BEGIN | ||||
| 
 | ||||
| struct SupercoverPass : public Pass { | ||||
| 	SupercoverPass() : Pass("supercover", "add hi/lo cover cells for each wire bit") { } | ||||
| 	void help() YS_OVERRIDE | ||||
| 	{ | ||||
| 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||
| 		log("\n"); | ||||
| 		log("    supercover [options] [selection]\n"); | ||||
| 		log("\n"); | ||||
| 		log("This command adds two cover cells for each bit of each selected wire, one\n"); | ||||
| 		log("checking for a hi signal level and one checking for lo level.\n"); | ||||
| 		log("\n"); | ||||
| 	} | ||||
| 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||
| 	{ | ||||
| 		// bool flag_noinit = false;
 | ||||
| 
 | ||||
| 		log_header(design, "Executing SUPERCOVER pass.\n"); | ||||
| 
 | ||||
| 		size_t argidx; | ||||
| 		for (argidx = 1; argidx < args.size(); argidx++) | ||||
| 		{ | ||||
| 			// if (args[argidx] == "-noinit") {
 | ||||
| 			// 	flag_noinit = true;
 | ||||
| 			// 	continue;
 | ||||
| 			// }
 | ||||
| 			break; | ||||
| 		} | ||||
| 		extra_args(args, argidx, design); | ||||
| 
 | ||||
| 		for (auto module : design->selected_modules()) | ||||
| 		{ | ||||
| 			SigMap sigmap(module); | ||||
| 			pool<SigBit> handled_bits; | ||||
| 
 | ||||
| 			int cnt_wire = 0, cnt_bits = 0; | ||||
| 			log("Adding cover cells to module %s.\n", log_id(module)); | ||||
| 			for (auto wire : module->selected_wires()) | ||||
| 			{ | ||||
| 				bool counted_wire = false; | ||||
| 				std::string src = wire->get_src_attribute(); | ||||
| 
 | ||||
| 				for (auto bit : sigmap(SigSpec(wire))) | ||||
| 				{ | ||||
| 					if (bit.wire == nullptr) | ||||
| 						continue; | ||||
| 
 | ||||
| 					if (handled_bits.count(bit)) | ||||
| 						continue; | ||||
| 
 | ||||
| 					SigSpec inv = module->Not(NEW_ID, bit); | ||||
| 					module->addCover(NEW_ID, bit, State::S1, src); | ||||
| 					module->addCover(NEW_ID, inv, State::S1, src); | ||||
| 
 | ||||
| 					handled_bits.insert(bit); | ||||
| 					if (!counted_wire) { | ||||
| 						counted_wire = false; | ||||
| 						cnt_wire++; | ||||
| 					} | ||||
| 					cnt_bits++; | ||||
| 				} | ||||
| 			} | ||||
| 			log("  added cover cells to %d wires, %d bits.\n", cnt_wire, cnt_bits); | ||||
| 		} | ||||
| 	} | ||||
| } SupercoverPass; | ||||
| 
 | ||||
| PRIVATE_NAMESPACE_END | ||||
|  | @ -660,8 +660,8 @@ struct DfflibmapPass : public Pass { | |||
| 		map_adff_to_dff("$_DFF_PP0_", "$_DFF_P_"); | ||||
| 		map_adff_to_dff("$_DFF_PP1_", "$_DFF_P_"); | ||||
| 
 | ||||
|  		log("  final dff cell mappings:\n"); | ||||
|  		logmap_all(); | ||||
| 		log("  final dff cell mappings:\n"); | ||||
| 		logmap_all(); | ||||
| 
 | ||||
| 		for (auto &it : design->modules_) | ||||
| 			if (design->selected(it.second) && !it.second->get_bool_attribute("\\blackbox")) | ||||
|  |  | |||
|  | @ -132,9 +132,9 @@ static void dump_dot_graph(string filename, | |||
|                            pool<RTLIL::SigBit> nodes, dict<RTLIL::SigBit, pool<RTLIL::SigBit>> edges, | ||||
|                            pool<RTLIL::SigBit> inputs, pool<RTLIL::SigBit> outputs, | ||||
|                            std::function<GraphStyle(RTLIL::SigBit)> node_style = | ||||
|                            		[](RTLIL::SigBit) { return GraphStyle{}; }, | ||||
|                                    [](RTLIL::SigBit) { return GraphStyle{}; }, | ||||
|                            std::function<GraphStyle(RTLIL::SigBit, RTLIL::SigBit)> edge_style = | ||||
|                            		[](RTLIL::SigBit, RTLIL::SigBit) { return GraphStyle{}; }, | ||||
|                                    [](RTLIL::SigBit, RTLIL::SigBit) { return GraphStyle{}; }, | ||||
|                            string name = "") | ||||
| { | ||||
| 	FILE *f = fopen(filename.c_str(), "w"); | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ endmodule | |||
| module PADOUT (output padout, input padin, input oe); | ||||
|    assign padout  = padin; | ||||
|    assign oe = oe; | ||||
| endmodule  | ||||
| endmodule | ||||
| 
 | ||||
| module LUT4 (output dout, | ||||
|              input  din0, din1, din2, din3); | ||||
|  | @ -66,14 +66,14 @@ always @(dataa_w or datab_w or datac_w or datad_w) begin | |||
|                          datac_w, datad_w); | ||||
| end | ||||
| assign dout = combout_rt & 1'b1; | ||||
| endmodule  | ||||
| endmodule | ||||
| 
 | ||||
| module DFF (output q, | ||||
|             input  d, ck); | ||||
|    reg             q; | ||||
|    always @(posedge ck) | ||||
|      q <= d; | ||||
|     | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -52,13 +52,13 @@ struct AnlogicEqnPass : public Pass { | |||
| 						eqn += names[j]; | ||||
| 					else | ||||
| 						eqn += std::string("~") + names[j]; | ||||
| 					 | ||||
| 
 | ||||
| 					if (j!=(inputs-1)) eqn += "*"; | ||||
| 				} | ||||
| 				eqn += ")+"; | ||||
| 			} | ||||
| 		} | ||||
| 		if (eqn.empty()) return Const("0");		 | ||||
| 		if (eqn.empty()) return Const("0"); | ||||
| 		eqn = eqn.substr(0, eqn.length()-1); | ||||
| 		return Const(eqn); | ||||
| 	} | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| 
 | ||||
| OBJS += techlibs/ecp5/synth_ecp5.o | ||||
| OBJS += techlibs/ecp5/synth_ecp5.o techlibs/ecp5/ecp5_ffinit.o | ||||
| 
 | ||||
| $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v)) | ||||
| $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_sim.v)) | ||||
|  |  | |||
|  | @ -33,7 +33,7 @@ module _80_ecp5_alu (A, B, CI, BI, X, Y, CO); | |||
| 	input CI, BI; | ||||
| 	output [Y_WIDTH-1:0] CO; | ||||
| 
 | ||||
| 	wire _TECHMAP_FAIL_ = Y_WIDTH <= 2; | ||||
| 	wire _TECHMAP_FAIL_ = Y_WIDTH <= 4; | ||||
| 
 | ||||
| 	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)); | ||||
|  |  | |||
|  | @ -156,6 +156,41 @@ module OSCG( | |||
| parameter DIV = 128; | ||||
| endmodule | ||||
| 
 | ||||
| (* blackbox *) (* keep *) | ||||
| module USRMCLK( | ||||
| 	input USRMCLKI, USRMCLKTS, | ||||
| 	output USRMCLKO | ||||
| ); | ||||
| endmodule | ||||
| 
 | ||||
| (* blackbox *) (* keep *) | ||||
| module JTAGG( | ||||
| 	input TCK, TMS, TDI, JTDO2, JTDO1, | ||||
| 	output TDO, JTDI, JTCK, JRTI2, JRTI1, | ||||
| 	output JSHIFT, JUPDATE, JRSTN, JCE2, JCE1 | ||||
| ); | ||||
| parameter ER1 = "ENABLED"; | ||||
| parameter ER2 = "ENABLED"; | ||||
| endmodule | ||||
| 
 | ||||
| (* blackbox *) | ||||
| module DELAYF( | ||||
| 	input A, LOADN, MOVE, DIRECTION, | ||||
| 	output Z, CFLAG | ||||
| ); | ||||
| 	parameter DEL_MODE = "USER_DEFINED"; | ||||
| 	parameter DEL_VALUE = 0; | ||||
| endmodule | ||||
| 
 | ||||
| (* blackbox *) | ||||
| module DELAYG( | ||||
| 	input A, | ||||
| 	output Z | ||||
| ); | ||||
| 	parameter DEL_MODE = "USER_DEFINED"; | ||||
| 	parameter DEL_VALUE = 0; | ||||
| endmodule | ||||
| 
 | ||||
| (* blackbox *) | ||||
| module IDDRX1F( | ||||
| 	input D, SCLK, RST, | ||||
|  | @ -164,6 +199,31 @@ module IDDRX1F( | |||
| 	parameter GSR = "ENABLED"; | ||||
| endmodule | ||||
| 
 | ||||
| (* blackbox *) | ||||
| module IDDRX2F( | ||||
| 	input D, SCLK, ECLK, RST, | ||||
| 	output Q0, Q1, Q2, Q3 | ||||
| ); | ||||
| 	parameter GSR = "ENABLED"; | ||||
| endmodule | ||||
| 
 | ||||
| (* blackbox *) | ||||
| module IDDR71B( | ||||
| 	input D, SCLK, ECLK, RST, ALIGNWD, | ||||
| 	output Q0, Q1, Q2, Q3, Q4, Q5, Q6 | ||||
| ); | ||||
| 	parameter GSR = "ENABLED"; | ||||
| endmodule | ||||
| 
 | ||||
| (* blackbox *) | ||||
| module IDDRX2DQA( | ||||
| 	input D, DQSR90, ECLK, SCLK, RST, | ||||
| 	input RDPNTR2, RDPNTR1, RDPNTR0, WRPNTR2, WRPNTR1, WRPNTR0, | ||||
| 	output Q0, Q1, Q2, Q3, QWL | ||||
| ); | ||||
| 	parameter GSR = "ENABLED"; | ||||
| endmodule | ||||
| 
 | ||||
| (* blackbox *) | ||||
| module ODDRX1F( | ||||
| 	input SCLK, RST, D0, D1, | ||||
|  | @ -172,6 +232,91 @@ module ODDRX1F( | |||
| 	parameter GSR = "ENABLED"; | ||||
| endmodule | ||||
| 
 | ||||
| (* blackbox *) | ||||
| module ODDRX2F( | ||||
| 	input SCLK, ECLK, RST, D0, D1, D2, D3, | ||||
| 	output Q | ||||
| ); | ||||
| 	parameter GSR = "ENABLED"; | ||||
| endmodule | ||||
| 
 | ||||
| (* blackbox *) | ||||
| module ODDR71B( | ||||
| 	input SCLK, ECLK, RST, D0, D1, D2, D3, D4, D5, D6, | ||||
| 	output Q | ||||
| ); | ||||
| 	parameter GSR = "ENABLED"; | ||||
| endmodule | ||||
| 
 | ||||
| (* blackbox *) | ||||
| module OSHX2A( | ||||
| 	input D0, D1, RST, ECLK, SCLK, | ||||
| 	output Q | ||||
| ); | ||||
| 	parameter GSR = "ENABLED"; | ||||
| endmodule | ||||
| 
 | ||||
| (* blackbox *) | ||||
| module ODDRX2DQA( | ||||
| 	input D0, D1, D2, D3, RST, ECLK, SCLK, DQSW270, | ||||
| 	output Q | ||||
| ); | ||||
| 	parameter GSR = "ENABLED"; | ||||
| endmodule | ||||
| 
 | ||||
| (* blackbox *) | ||||
| module ODDRX2DQSB( | ||||
| 	input D0, D1, D2, D3, RST, ECLK, SCLK, DQSW, | ||||
| 	output Q | ||||
| ); | ||||
| 	parameter GSR = "ENABLED"; | ||||
| endmodule | ||||
| 
 | ||||
| (* blackbox *) | ||||
| module TSHX2DQA( | ||||
| 	input T0, T1, SCLK, ECLK, DQSW270, RST, | ||||
| 	output Q | ||||
| ); | ||||
| 	parameter GSR = "ENABLED"; | ||||
| 	parameter REGSET = "SET"; | ||||
| endmodule | ||||
| 
 | ||||
| (* blackbox *) | ||||
| module TSHX2DQSA( | ||||
| 	input T0, T1, SCLK, ECLK, DQSW, RST, | ||||
| 	output Q | ||||
| ); | ||||
| 	parameter GSR = "ENABLED"; | ||||
| 	parameter REGSET = "SET"; | ||||
| endmodule | ||||
| 
 | ||||
| (* blackbox *) | ||||
| module DQSBUFM( | ||||
| 	input DQSI, READ1, READ0, READCLKSEL2, READCLKSEL1, READCLKSEL0, DDRDEL, | ||||
| 	input ECLK, SCLK, | ||||
| 	input DYNDELAY7, DYNDELAY6, DYNDELAY5, DYNDELAY4, | ||||
| 	input DYNDELAY3, DYNDELAY2, DYNDELAY1, DYNDELAY0,  | ||||
| 	input RST, RDLOADN, RDMOVE, RDDIRECTION, WRLOADN, WRMOVE, WRDIRECTION, PAUSE, | ||||
| 	output DQSR90, DQSW, DQSW270, | ||||
| 	output RDPNTR2, RDPNTR1, RDPNTR0, WRPNTR2, WRPNTR1, WRPNTR0, | ||||
| 	output DATAVALID, BURSTDET, RDCFLAG, WRCFLAG | ||||
| ); | ||||
| 	parameter DQS_LI_DEL_ADJ = "FACTORYONLY"; | ||||
| 	parameter DQS_LI_DEL_VAL = 0; | ||||
| 	parameter DQS_LO_DEL_ADJ = "FACTORYONLY"; | ||||
| 	parameter DQS_LO_DEL_VAL = 0; | ||||
| 	parameter GSR = "ENABLED"; | ||||
| endmodule | ||||
| 
 | ||||
| (* blackbox *) | ||||
| module DDRDLLA( | ||||
| 	input CLK, RST, UDDCNTLN, FREEZE, | ||||
| 	output LOCK, DDRDEL, DCNTL7, DCNTL6, DCNTL5, DCNTL4, DCNTL3, DCNTL2, DCNTL1, DCNTL0 | ||||
| ); | ||||
| 	parameter FORCE_MAX_DELAY = "NO"; | ||||
| 	parameter GSR = "ENABLED"; | ||||
| endmodule | ||||
| 
 | ||||
| (* blackbox *) | ||||
| module CLKDIVF( | ||||
| 	input CLKI, RST, ALIGNWD, | ||||
|  | @ -181,6 +326,13 @@ module CLKDIVF( | |||
| 	parameter DIV = "2.0"; | ||||
| endmodule | ||||
| 
 | ||||
| (* blackbox *) | ||||
| module ECLKSYNCB( | ||||
| 	input ECLKI, STOP, | ||||
| 	output ECLKO | ||||
| ); | ||||
| endmodule | ||||
| 
 | ||||
| (* blackbox *) | ||||
| module DCCA( | ||||
| 	input CLKI, CE, | ||||
|  |  | |||
|  | @ -47,6 +47,9 @@ module  \$__DFFSE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED" | |||
| module  \$__DFFSE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE"))  _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule | ||||
| module  \$__DFFSE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE"))  _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule | ||||
| 
 | ||||
| // For Diamond compatibility, FIXME: add all Diamond flipflop mappings | ||||
| module FD1S3BX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC"))  _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule | ||||
| 
 | ||||
| `ifndef NO_LUT | ||||
| module \$lut (A, Y); | ||||
|     parameter WIDTH = 0; | ||||
|  |  | |||
|  | @ -57,7 +57,7 @@ module TRELLIS_RAM16X2 ( | |||
| 	input RAD0, RAD1, RAD2, RAD3, | ||||
| 	output DO0, DO1 | ||||
| ); | ||||
|   	parameter WCKMUX = "WCK"; | ||||
| 	parameter WCKMUX = "WCK"; | ||||
| 	parameter WREMUX = "WRE"; | ||||
| 	parameter INITVAL_0 = 16'h0000; | ||||
| 	parameter INITVAL_1 = 16'h0000; | ||||
|  | @ -104,7 +104,7 @@ module TRELLIS_DPR16X4 ( | |||
| 	input [3:0] RAD, | ||||
| 	output [3:0] DO | ||||
| ); | ||||
|   	parameter WCKMUX = "WCK"; | ||||
| 	parameter WCKMUX = "WCK"; | ||||
| 	parameter WREMUX = "WRE"; | ||||
| 	parameter [63:0] INITVAL = 64'h0000000000000000; | ||||
| 
 | ||||
|  | @ -203,13 +203,14 @@ endmodule | |||
| 
 | ||||
| // --------------------------------------- | ||||
| 
 | ||||
| module TRELLIS_FF(input CLK, LSR, CE, DI, output reg Q); | ||||
| module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q); | ||||
| 	parameter GSR = "ENABLED"; | ||||
| 	parameter [127:0] CEMUX = "1"; | ||||
| 	parameter CLKMUX = "CLK"; | ||||
| 	parameter LSRMUX = "LSR"; | ||||
| 	parameter SRMODE = "LSR_OVER_CE"; | ||||
| 	parameter REGSET = "RESET"; | ||||
| 	parameter [127:0] LSRMODE = "LSR"; | ||||
| 
 | ||||
| 	reg muxce; | ||||
| 	always @(*) | ||||
|  | @ -222,8 +223,12 @@ module TRELLIS_FF(input CLK, LSR, CE, DI, output reg Q); | |||
| 
 | ||||
| 	wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR; | ||||
| 	wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK; | ||||
| 
 | ||||
| 	localparam srval = (REGSET == "SET") ? 1'b1 : 1'b0; | ||||
| 	generate | ||||
| 		if (LSRMODE == "PRLD") | ||||
| 			wire srval = M; | ||||
| 		else | ||||
| 			localparam srval = (REGSET == "SET") ? 1'b1 : 1'b0; | ||||
| 	endgenerate | ||||
| 
 | ||||
| 	initial Q = srval; | ||||
| 
 | ||||
|  | @ -339,6 +344,8 @@ module TRELLIS_SLICE( | |||
| 	parameter REG1_SD = "0"; | ||||
| 	parameter REG0_REGSET = "RESET"; | ||||
| 	parameter REG1_REGSET = "RESET"; | ||||
| 	parameter REG0_LSRMODE = "LSR"; | ||||
| 	parameter REG1_LSRMODE = "LSR"; | ||||
| 	parameter [127:0] CCU2_INJECT1_0 = "NO"; | ||||
| 	parameter [127:0] CCU2_INJECT1_1 = "NO"; | ||||
| 	parameter WREMUX = "WRE"; | ||||
|  | @ -428,10 +435,11 @@ module TRELLIS_SLICE( | |||
| 		.CLKMUX(CLKMUX), | ||||
| 		.LSRMUX(LSRMUX), | ||||
| 		.SRMODE(SRMODE), | ||||
| 		.REGSET(REG0_REGSET) | ||||
| 		.REGSET(REG0_REGSET), | ||||
| 		.LSRMODE(REG0_LSRMODE) | ||||
| 	) ff_0 ( | ||||
| 		.CLK(CLK), .LSR(LSR), .CE(CE), | ||||
| 		.DI(muxdi0), | ||||
| 		.DI(muxdi0), .M(M0), | ||||
| 		.Q(Q0) | ||||
| 	); | ||||
| 	TRELLIS_FF #( | ||||
|  | @ -440,10 +448,11 @@ module TRELLIS_SLICE( | |||
| 		.CLKMUX(CLKMUX), | ||||
| 		.LSRMUX(LSRMUX), | ||||
| 		.SRMODE(SRMODE), | ||||
| 		.REGSET(REG1_REGSET) | ||||
| 		.REGSET(REG1_REGSET), | ||||
| 		.LSRMODE(REG1_LSRMODE) | ||||
| 	) ff_1 ( | ||||
| 		.CLK(CLK), .LSR(LSR), .CE(CE), | ||||
| 		.DI(muxdi1), | ||||
| 		.DI(muxdi1), .M(M1), | ||||
| 		.Q(Q1) | ||||
| 	); | ||||
| endmodule | ||||
|  | @ -547,3 +556,20 @@ module DP16KD( | |||
|   parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; | ||||
|   parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; | ||||
| endmodule | ||||
| 
 | ||||
| // For Diamond compatibility, FIXME: add all Diamond flipflop mappings | ||||
| module FD1S3BX(input PD, D, CK, output Q); | ||||
| 	TRELLIS_FF #( | ||||
| 		.GSR("DISABLED"), | ||||
| 		.CEMUX("1"), | ||||
| 		.CLKMUX("CLK"), | ||||
| 		.LSRMUX("LSR"), | ||||
| 		.REGSET("SET"), | ||||
| 		.SRMODE("ASYNC") | ||||
| 	) tff_i ( | ||||
| 		.CLK(CK), | ||||
| 		.LSR(PD), | ||||
| 		.DI(D), | ||||
| 		.Q(Q) | ||||
| 	); | ||||
| endmodule | ||||
|  |  | |||
							
								
								
									
										198
									
								
								techlibs/ecp5/ecp5_ffinit.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										198
									
								
								techlibs/ecp5/ecp5_ffinit.cc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,198 @@ | |||
| /*
 | ||||
|  *  yosys -- Yosys Open SYnthesis Suite | ||||
|  * | ||||
|  *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> | ||||
|  *  Copyright (C) 2018-19  David Shah <david@symbioticeda.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/yosys.h" | ||||
| #include "kernel/sigtools.h" | ||||
| 
 | ||||
| USING_YOSYS_NAMESPACE | ||||
| PRIVATE_NAMESPACE_BEGIN | ||||
| 
 | ||||
| struct Ecp5FfinitPass : public Pass { | ||||
| 	Ecp5FfinitPass() : Pass("ecp5_ffinit", "ECP5: handle FF init values") { } | ||||
| 	void help() YS_OVERRIDE | ||||
| 	{ | ||||
| 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||
| 		log("\n"); | ||||
| 		log("    ecp5_ffinit [options] [selection]\n"); | ||||
| 		log("\n"); | ||||
| 		log("Remove init values for FF output signals when equal to reset value.\n"); | ||||
| 		log("If reset is not used, set the reset value to the init value, otherwise\n"); | ||||
| 		log("unmap out the reset (if not an async reset).\n"); | ||||
| 	} | ||||
| 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||
| 	{ | ||||
| 		log_header(design, "Executing ECP5_FFINIT pass (implement FF init values).\n"); | ||||
| 
 | ||||
| 		size_t argidx; | ||||
| 		for (argidx = 1; argidx < args.size(); argidx++) | ||||
| 		{ | ||||
| 			// if (args[argidx] == "-singleton") {
 | ||||
| 			// 	singleton_mode = true;
 | ||||
| 			// 	continue;
 | ||||
| 			// }
 | ||||
| 			break; | ||||
| 		} | ||||
| 		extra_args(args, argidx, design); | ||||
| 
 | ||||
| 		for (auto module : design->selected_modules()) | ||||
| 		{ | ||||
| 			log("Handling FF init values in %s.\n", log_id(module)); | ||||
| 
 | ||||
| 			SigMap sigmap(module); | ||||
| 			pool<Wire*> init_wires; | ||||
| 			dict<SigBit, State> initbits; | ||||
| 			dict<SigBit, SigBit> initbit_to_wire; | ||||
| 			pool<SigBit> handled_initbits; | ||||
| 
 | ||||
| 			for (auto wire : module->selected_wires()) | ||||
| 			{ | ||||
| 				if (wire->attributes.count("\\init") == 0) | ||||
| 					continue; | ||||
| 
 | ||||
| 				SigSpec wirebits = sigmap(wire); | ||||
| 				Const initval = wire->attributes.at("\\init"); | ||||
| 				init_wires.insert(wire); | ||||
| 
 | ||||
| 				for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++) | ||||
| 				{ | ||||
| 					SigBit bit = wirebits[i]; | ||||
| 					State val = initval[i]; | ||||
| 
 | ||||
| 					if (val != State::S0 && val != State::S1) | ||||
| 						continue; | ||||
| 
 | ||||
| 					if (initbits.count(bit)) { | ||||
| 						if (initbits.at(bit) != val) | ||||
| 							log_error("Conflicting init values for signal %s (%s = %s, %s = %s).\n", | ||||
| 									log_signal(bit), log_signal(SigBit(wire, i)), log_signal(val), | ||||
| 									log_signal(initbit_to_wire[bit]), log_signal(initbits.at(bit))); | ||||
| 						continue; | ||||
| 					} | ||||
| 
 | ||||
| 					initbits[bit] = val; | ||||
| 					initbit_to_wire[bit] = SigBit(wire, i); | ||||
| 				} | ||||
| 			} | ||||
| 			for (auto cell : module->selected_cells()) | ||||
| 			{ | ||||
| 				if (cell->type != "\\TRELLIS_FF") | ||||
| 					continue; | ||||
| 				SigSpec sig_d = cell->getPort("\\DI"); | ||||
| 				SigSpec sig_q = cell->getPort("\\Q"); | ||||
| 				SigSpec sig_lsr = cell->getPort("\\LSR"); | ||||
| 
 | ||||
| 				if (GetSize(sig_d) < 1 || GetSize(sig_q) < 1) | ||||
| 					continue; | ||||
| 
 | ||||
| 				SigBit bit_d = sigmap(sig_d[0]); | ||||
| 				SigBit bit_q = sigmap(sig_q[0]); | ||||
| 
 | ||||
| 				std::string regset = "RESET"; | ||||
| 				if (cell->hasParam("\\REGSET")) | ||||
| 					regset = cell->getParam("\\REGSET").decode_string(); | ||||
| 				State resetState; | ||||
| 				if (regset == "SET") | ||||
| 					resetState = State::S1; | ||||
| 				else if (regset == "RESET") | ||||
| 					resetState = State::S0; | ||||
| 				else | ||||
| 					log_error("FF cell %s has illegal REGSET value %s.\n", | ||||
| 						log_id(cell), regset.c_str()); | ||||
| 
 | ||||
| 				if (!initbits.count(bit_q)) | ||||
| 					continue; | ||||
| 
 | ||||
| 				State val = initbits.at(bit_q); | ||||
| 
 | ||||
| 				log("FF init value for cell %s (%s): %s = %c\n", log_id(cell), log_id(cell->type), | ||||
| 						log_signal(bit_q), val != State::S0 ? '1' : '0'); | ||||
| 				// Initval is the same as the reset state. Matches hardware, nowt more to do
 | ||||
| 				if (val == resetState) { | ||||
| 					handled_initbits.insert(bit_q); | ||||
| 					continue; | ||||
| 				} | ||||
| 
 | ||||
| 				if (GetSize(sig_lsr) >= 1 && sig_lsr[0] != State::S0) { | ||||
| 					std::string srmode = "LSR_OVER_CE"; | ||||
| 					if (cell->hasParam("\\SRMODE")) | ||||
| 						srmode = cell->getParam("\\SRMODE").decode_string(); | ||||
| 					if (srmode == "ASYNC") { | ||||
| 						log("Async reset value %c for FF cell %s inconsistent with init value %c.\n", | ||||
| 							resetState != State::S0 ? '1' : '0', log_id(cell), val != State::S0 ? '1' : '0'); | ||||
| 					} else { | ||||
| 						SigBit bit_lsr = sigmap(sig_lsr[0]); | ||||
| 						Wire *new_bit_d = module->addWire(NEW_ID); | ||||
| 						if (resetState == State::S0) { | ||||
| 							module->addAndnotGate(NEW_ID, bit_d, bit_lsr, new_bit_d); | ||||
| 						} else { | ||||
| 							module->addOrGate(NEW_ID, bit_d, bit_lsr, new_bit_d); | ||||
| 						} | ||||
| 
 | ||||
| 						cell->setPort("\\DI", new_bit_d); | ||||
| 						cell->setPort("\\LSR", State::S0); | ||||
| 
 | ||||
| 						if(cell->hasPort("\\CE")) { | ||||
| 							std::string cemux = "CE"; | ||||
| 							if (cell->hasParam("\\CEMUX")) | ||||
| 								cemux = cell->getParam("\\CEMUX").decode_string(); | ||||
| 							SigSpec sig_ce = cell->getPort("\\CE"); | ||||
| 							if (GetSize(sig_ce) >= 1) { | ||||
| 								SigBit bit_ce = sigmap(sig_ce[0]); | ||||
| 								Wire *new_bit_ce = module->addWire(NEW_ID); | ||||
| 								if (cemux == "INV") | ||||
| 									module->addAndnotGate(NEW_ID, bit_ce, bit_lsr, new_bit_ce); | ||||
| 								else | ||||
| 									module->addOrGate(NEW_ID, bit_ce, bit_lsr, new_bit_ce); | ||||
| 								cell->setPort("\\CE", new_bit_ce); | ||||
| 							} | ||||
| 						} | ||||
| 						cell->setParam("\\REGSET", val != State::S0 ? Const("SET") : Const("RESET")); | ||||
| 						handled_initbits.insert(bit_q); | ||||
| 					} | ||||
| 				} else { | ||||
| 					cell->setParam("\\REGSET", val != State::S0 ? Const("SET") : Const("RESET")); | ||||
| 					handled_initbits.insert(bit_q); | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			for (auto wire : init_wires) | ||||
| 			{ | ||||
| 				if (wire->attributes.count("\\init") == 0) | ||||
| 					continue; | ||||
| 
 | ||||
| 				SigSpec wirebits = sigmap(wire); | ||||
| 				Const &initval = wire->attributes.at("\\init"); | ||||
| 				bool remove_attribute = true; | ||||
| 
 | ||||
| 				for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++) { | ||||
| 					if (handled_initbits.count(wirebits[i])) | ||||
| 						initval[i] = State::Sx; | ||||
| 					else if (initval[i] != State::Sx) | ||||
| 						remove_attribute = false; | ||||
| 				} | ||||
| 
 | ||||
| 				if (remove_attribute) | ||||
| 					wire->attributes.erase("\\init"); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } Ecp5FfinitPass; | ||||
| 
 | ||||
| PRIVATE_NAMESPACE_END | ||||
|  | @ -255,10 +255,7 @@ struct SynthEcp5Pass : public ScriptPass | |||
| 			run("techmap -D NO_LUT -map +/ecp5/cells_map.v"); | ||||
| 			run("opt_expr -mux_undef"); | ||||
| 			run("simplemap"); | ||||
| 			// TODO
 | ||||
| #if 0 | ||||
| 			run("ecp5_ffinit"); | ||||
| #endif | ||||
| 		} | ||||
| 
 | ||||
| 		if (check_label("map_luts")) | ||||
|  |  | |||
|  | @ -25,24 +25,24 @@ module _80_gw1n_alu(A, B, CI, BI, X, Y, CO); | |||
|    parameter A_WIDTH = 1; | ||||
|    parameter B_WIDTH = 1; | ||||
|    parameter Y_WIDTH = 1; | ||||
|     | ||||
| 
 | ||||
|    input [A_WIDTH-1:0] A; | ||||
|    input [B_WIDTH-1:0] B; | ||||
|    output [Y_WIDTH-1:0] X, Y; | ||||
|     | ||||
| 
 | ||||
|    input 		CI, BI; | ||||
|    output [Y_WIDTH-1:0] CO; | ||||
|     | ||||
| 
 | ||||
|    wire 		_TECHMAP_FAIL_ = Y_WIDTH <= 2; | ||||
|     | ||||
| 
 | ||||
|    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)); | ||||
|     | ||||
| 
 | ||||
|    wire [Y_WIDTH-1:0] 	AA = A_buf; | ||||
|    wire [Y_WIDTH-1:0] 	BB = BI ? ~B_buf : B_buf; | ||||
|    wire [Y_WIDTH-1:0] 	C = {CO, CI}; | ||||
|     | ||||
| 
 | ||||
|    genvar 		i; | ||||
|    generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice | ||||
|       ALU #(.ALU_MODE(32'b0)) | ||||
|  |  | |||
|  | @ -111,7 +111,7 @@ struct SynthGowinPass : public ScriptPass | |||
| 			if (args[argidx] == "-noflatten") { | ||||
| 				flatten = false; | ||||
| 				continue; | ||||
| 			}			 | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 		extra_args(args, argidx, design); | ||||
|  |  | |||
|  | @ -112,14 +112,14 @@ module GP_OBUFT(input IN, input OE, output OUT); | |||
| endmodule | ||||
| 
 | ||||
| module \$lut (A, Y); | ||||
|   parameter WIDTH = 0; | ||||
|   parameter LUT = 0; | ||||
| 	parameter WIDTH = 0; | ||||
| 	parameter LUT = 0; | ||||
| 
 | ||||
|   input [WIDTH-1:0] A; | ||||
|   output Y; | ||||
| 	input [WIDTH-1:0] A; | ||||
| 	output Y; | ||||
| 
 | ||||
|   generate | ||||
|     if (WIDTH == 1) begin | ||||
| 	generate | ||||
| 		if (WIDTH == 1) begin | ||||
| 		if(LUT == 2'b01) begin | ||||
| 			GP_INV _TECHMAP_REPLACE_ (.OUT(Y), .IN(A[0]) ); | ||||
| 		end | ||||
|  | @ -127,22 +127,22 @@ module \$lut (A, Y); | |||
| 			GP_2LUT #(.INIT({2'b00, LUT})) _TECHMAP_REPLACE_ (.OUT(Y), | ||||
| 				.IN0(A[0]), .IN1(1'b0)); | ||||
| 		end | ||||
|     end else | ||||
|     if (WIDTH == 2) begin | ||||
|       GP_2LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y), | ||||
|       	.IN0(A[0]), .IN1(A[1])); | ||||
|     end else | ||||
|     if (WIDTH == 3) begin | ||||
|       GP_3LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y), | ||||
|       	.IN0(A[0]), .IN1(A[1]), .IN2(A[2])); | ||||
|     end else | ||||
|     if (WIDTH == 4) begin | ||||
|       GP_4LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y), | ||||
|       	.IN0(A[0]), .IN1(A[1]), .IN2(A[2]), .IN3(A[3])); | ||||
|     end else begin | ||||
|       wire _TECHMAP_FAIL_ = 1; | ||||
|     end | ||||
|   endgenerate | ||||
| 		end else | ||||
| 		if (WIDTH == 2) begin | ||||
| 			GP_2LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y), | ||||
| 				.IN0(A[0]), .IN1(A[1])); | ||||
| 		end else | ||||
| 		if (WIDTH == 3) begin | ||||
| 			GP_3LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y), | ||||
| 				.IN0(A[0]), .IN1(A[1]), .IN2(A[2])); | ||||
| 		end else | ||||
| 		if (WIDTH == 4) begin | ||||
| 			GP_4LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y), | ||||
| 				.IN0(A[0]), .IN1(A[1]), .IN2(A[2]), .IN3(A[3])); | ||||
| 		end else begin | ||||
| 			wire _TECHMAP_FAIL_ = 1; | ||||
| 		end | ||||
| 	endgenerate | ||||
| endmodule | ||||
| 
 | ||||
| module \$__COUNT_ (CE, CLK, OUT, POUT, RST, UP); | ||||
|  |  | |||
|  | @ -7,8 +7,8 @@ module \$__ICE40_RAM4K ( | |||
| 	input  [10:0] WADDR, | ||||
| 	input  [15:0] MASK, WDATA | ||||
| ); | ||||
| 	parameter integer READ_MODE = 0; | ||||
| 	parameter integer WRITE_MODE = 0; | ||||
| 	parameter [1:0] READ_MODE = 0; | ||||
| 	parameter [1:0] WRITE_MODE = 0; | ||||
| 	parameter [0:0] NEGCLK_R = 0; | ||||
| 	parameter [0:0] NEGCLK_W = 0; | ||||
| 
 | ||||
|  |  | |||
|  | @ -32,7 +32,7 @@ module fa | |||
|    wire   VCC; | ||||
| 
 | ||||
|    assign VCC = 1'b1; | ||||
|     | ||||
| 
 | ||||
|    cycloneiv_lcell_comb gen_sum_0 (.combout(sum_x), | ||||
|                                    .dataa(a_c), | ||||
|                                    .datab(b_c), | ||||
|  | @ -40,7 +40,7 @@ module fa | |||
|                                    .datad(VCC)); | ||||
|    defparam syn__05_.lut_mask = 16'b1001011010010110; | ||||
|    defparam syn__05_.sum_lutc_input = "datac"; | ||||
|     | ||||
| 
 | ||||
|    cycloneiv_lcell_comb gen_cout_0 (.combout(cout_t), | ||||
|                                     .dataa(cin_c), | ||||
|                                     .datab(b_c), | ||||
|  | @ -48,11 +48,11 @@ module fa | |||
|                                     .datad(VCC)); | ||||
|    defparam syn__06_.lut_mask = 16'b1110000011100000; | ||||
|    defparam syn__06_.sum_lutc_input = "datac"; | ||||
|     | ||||
| 
 | ||||
| endmodule // fa | ||||
| 
 | ||||
| module f_stage(); | ||||
|     | ||||
| 
 | ||||
| endmodule // f_stage | ||||
| 
 | ||||
| module f_end(); | ||||
|  | @ -88,7 +88,7 @@ module _80_cycloneive_alu (A, B, CI, BI, X, Y, CO); | |||
|           .cin_c(C[0]), | ||||
|           .cout_t(C0[1]), | ||||
|           .sum_x(Y[0])); | ||||
|     | ||||
| 
 | ||||
|    genvar i; | ||||
|    generate for (i = 1; i < Y_WIDTH; i = i + 1) begin:slice | ||||
|       cycloneive_lcell_comb #(.lut_mask(16'b0101_1010_0101_0000), .sum_lutc_input("cin")) arith_cell (.combout(Y[i]), .cout(CO[i]), .dataa(BB[i]), .datab(1'b1), .datac(1'b1), .datad(1'b1), .cin(C[i])); | ||||
|  |  | |||
|  | @ -76,7 +76,7 @@ module \$lut (A, Y); | |||
|    wire              VCC; | ||||
|    wire              GND; | ||||
|    assign {VCC,GND} = {1'b1,1'b0}; | ||||
|     | ||||
| 
 | ||||
|    generate | ||||
|       if (WIDTH == 1) begin | ||||
| 	 assign Y = ~A[0]; // Not need to spend 1 logic cell for such an easy function | ||||
|  | @ -151,7 +151,7 @@ module \$lut (A, Y); | |||
|                     TODO: There's not a just 7-input function on Cyclone V, see the following note: | ||||
|                     **Extended LUT Mode** | ||||
|                     Use extended LUT mode to implement a specific set of 7-input functions. The set must | ||||
|                     be a 2-to-1 multiplexer fed by two arbitrary 5-input functions sharing four inputs.  | ||||
|                     be a 2-to-1 multiplexer fed by two arbitrary 5-input functions sharing four inputs. | ||||
|                     [source](Device Interfaces and Integration Basics for Cyclone V Devices). | ||||
|                   end*/ | ||||
|                   else | ||||
|  |  | |||
|  | @ -6,7 +6,6 @@ code_hdl_models_d_latch_gates.v	combinational loop | |||
| code_hdl_models_dff_async_reset.v	$adff | ||||
| code_hdl_models_tff_async_reset.v	$adff | ||||
| code_hdl_models_uart.v	$adff | ||||
| code_specman_switch_fabric.v	subfield assignment (bits() <= ...) | ||||
| code_tidbits_asyn_reset.v	$adff | ||||
| code_tidbits_reg_seq_example.v	$adff | ||||
| code_verilog_tutorial_always_example.v	empty module | ||||
|  |  | |||
|  | @ -12,7 +12,6 @@ multiplier.v	inst id[0] of | |||
| muxtree.v	drops modules | ||||
| omsp_dbg_uart.v	$adff | ||||
| operators.v	$pow | ||||
| paramods.v	subfield assignment (bits() <= ...) | ||||
| partsel.v	drops modules | ||||
| process.v	drops modules | ||||
| realexpr.v	drops modules | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ verbose=false | |||
| keeprunning=false | ||||
| makejmode=false | ||||
| frontend="verilog" | ||||
| backend_opts="-noattr -noexpr" | ||||
| backend_opts="-noattr -noexpr -siminit" | ||||
| autotb_opts="" | ||||
| include_opts="" | ||||
| xinclude_opts="" | ||||
|  | @ -49,7 +49,7 @@ while getopts xmGl:wkjvref:s:p:n:S:I:-: opt; do | |||
| 		r) | ||||
| 			backend_opts="$backend_opts -norename" ;; | ||||
| 		e) | ||||
| 			backend_opts="$( echo " $backend_opts " | sed 's, -noexpr ,,; s,^ ,,; s, $,,;'; )" ;; | ||||
| 			backend_opts="$( echo " $backend_opts " | sed 's, -noexpr , ,; s,^ ,,; s, $,,;'; )" ;; | ||||
| 		f) | ||||
| 			frontend="$OPTARG" ;; | ||||
| 		s) | ||||
|  | @ -175,7 +175,7 @@ do | |||
| 			if [ -n "$firrtl2verilog" ]; then | ||||
| 			    if test -z "$xfirrtl" || ! grep "$fn" "$xfirrtl" ; then | ||||
| 				"$toolsdir"/../../yosys -b "firrtl" -o ${bn}_ref.fir -f "$frontend $include_opts" -p "prep -nordff; proc; opt; memory; opt; fsm; opt -full -fine; pmuxtree" ${bn}_ref.v | ||||
| 				$firrtl2verilog -i ${bn}_ref.fir -o ${bn}_ref.fir.v  -X verilog | ||||
| 				$firrtl2verilog -i ${bn}_ref.fir -o ${bn}_ref.fir.v | ||||
| 				test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.fir.v | ||||
| 			    fi | ||||
| 			fi | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue