mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-29 18:52:30 +00:00 
			
		
		
		
	Merge cd370bf6d1 into c2291c10a6
				
					
				
			This commit is contained in:
		
						commit
						b3baba4522
					
				
					 79 changed files with 1002 additions and 484 deletions
				
			
		|  | @ -709,12 +709,13 @@ struct BtorWorker | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			Const initval; | 			Const::Builder initval_bits(GetSize(sig_q)); | ||||||
| 			for (int i = 0; i < GetSize(sig_q); i++) | 			for (int i = 0; i < GetSize(sig_q); i++) | ||||||
| 				if (initbits.count(sig_q[i])) | 				if (initbits.count(sig_q[i])) | ||||||
| 					initval.bits().push_back(initbits.at(sig_q[i]) ? State::S1 : State::S0); | 					initval_bits.push_back(initbits.at(sig_q[i]) ? State::S1 : State::S0); | ||||||
| 				else | 				else | ||||||
| 					initval.bits().push_back(State::Sx); | 					initval_bits.push_back(State::Sx); | ||||||
|  | 			Const initval = initval_bits.build(); | ||||||
| 
 | 
 | ||||||
| 			int nid_init_val = -1; | 			int nid_init_val = -1; | ||||||
| 
 | 
 | ||||||
|  | @ -1043,10 +1044,11 @@ struct BtorWorker | ||||||
| 				{ | 				{ | ||||||
| 					if (bit.wire == nullptr) | 					if (bit.wire == nullptr) | ||||||
| 					{ | 					{ | ||||||
| 						Const c(bit.data); | 						Const::Builder c_bits; | ||||||
| 
 | 						c_bits.push_back(bit.data); | ||||||
| 						while (i+GetSize(c) < GetSize(sig) && sig[i+GetSize(c)].wire == nullptr) | 						while (i + GetSize(c_bits) < GetSize(sig) && sig[i + GetSize(c_bits)].wire == nullptr) | ||||||
| 							c.bits().push_back(sig[i+GetSize(c)].data); | 							c_bits.push_back(sig[i + GetSize(c_bits)].data); | ||||||
|  | 						Const c = c_bits.build(); | ||||||
| 
 | 
 | ||||||
| 						if (consts.count(c) == 0) { | 						if (consts.count(c) == 0) { | ||||||
| 							int sid = get_bv_sid(GetSize(c)); | 							int sid = get_bv_sid(GetSize(c)); | ||||||
|  |  | ||||||
|  | @ -1668,26 +1668,29 @@ struct CxxrtlWorker { | ||||||
| 						f << signal_temp << " == "; | 						f << signal_temp << " == "; | ||||||
| 						dump_sigspec(compare, /*is_lhs=*/false, for_debug); | 						dump_sigspec(compare, /*is_lhs=*/false, for_debug); | ||||||
| 					} else if (compare.is_fully_const()) { | 					} else if (compare.is_fully_const()) { | ||||||
| 						RTLIL::Const compare_mask, compare_value; | 						RTLIL::Const::Builder compare_mask_builder(compare.size()); | ||||||
|  | 						RTLIL::Const::Builder compare_value_builder(compare.size()); | ||||||
| 						for (auto bit : compare.as_const()) { | 						for (auto bit : compare.as_const()) { | ||||||
| 							switch (bit) { | 							switch (bit) { | ||||||
| 								case RTLIL::S0: | 								case RTLIL::S0: | ||||||
| 								case RTLIL::S1: | 								case RTLIL::S1: | ||||||
| 									compare_mask.bits().push_back(RTLIL::S1); | 									compare_mask_builder.push_back(RTLIL::S1); | ||||||
| 									compare_value.bits().push_back(bit); | 									compare_value_builder.push_back(bit); | ||||||
| 									break; | 									break; | ||||||
| 
 | 
 | ||||||
| 								case RTLIL::Sx: | 								case RTLIL::Sx: | ||||||
| 								case RTLIL::Sz: | 								case RTLIL::Sz: | ||||||
| 								case RTLIL::Sa: | 								case RTLIL::Sa: | ||||||
| 									compare_mask.bits().push_back(RTLIL::S0); | 									compare_mask_builder.push_back(RTLIL::S0); | ||||||
| 									compare_value.bits().push_back(RTLIL::S0); | 									compare_value_builder.push_back(RTLIL::S0); | ||||||
| 									break; | 									break; | ||||||
| 
 | 
 | ||||||
| 								default: | 								default: | ||||||
| 									log_assert(false); | 									log_assert(false); | ||||||
| 							} | 							} | ||||||
| 						} | 						} | ||||||
|  | 						RTLIL::Const compare_mask = compare_mask_builder.build(); | ||||||
|  | 						RTLIL::Const compare_value = compare_value_builder.build(); | ||||||
| 						f << "and_uu<" << compare.size() << ">(" << signal_temp << ", "; | 						f << "and_uu<" << compare.size() << ">(" << signal_temp << ", "; | ||||||
| 						dump_const(compare_mask); | 						dump_const(compare_mask); | ||||||
| 						f << ") == "; | 						f << ") == "; | ||||||
|  | @ -3042,7 +3045,7 @@ struct CxxrtlWorker { | ||||||
| 								if (init == RTLIL::Const()) { | 								if (init == RTLIL::Const()) { | ||||||
| 									init = RTLIL::Const(State::Sx, GetSize(bit.wire)); | 									init = RTLIL::Const(State::Sx, GetSize(bit.wire)); | ||||||
| 								} | 								} | ||||||
| 								init.bits()[bit.offset] = port.init_value[i]; | 								init.set(bit.offset, port.init_value[i]); | ||||||
| 							} | 							} | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
|  | @ -105,7 +105,7 @@ struct MemContentsTest { | ||||||
| 				RTLIL::Const values; | 				RTLIL::Const values; | ||||||
| 				for(addr_t addr = low; addr <= high; addr++) { | 				for(addr_t addr = low; addr <= high; addr++) { | ||||||
| 					RTLIL::Const word(data_dist(rnd), data_width); | 					RTLIL::Const word(data_dist(rnd), data_width); | ||||||
| 					values.bits().insert(values.bits().end(), word.begin(), word.end()); | 					values.append(word); | ||||||
| 				} | 				} | ||||||
| 				insert_concatenated(low, values); | 				insert_concatenated(low, values); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | @ -657,7 +657,7 @@ struct SimplecWorker | ||||||
| 			{ | 			{ | ||||||
| 				SigSpec sig = sigmaps.at(module)(w); | 				SigSpec sig = sigmaps.at(module)(w); | ||||||
| 				Const val = w->attributes.at(ID::init); | 				Const val = w->attributes.at(ID::init); | ||||||
| 				val.bits().resize(GetSize(sig), State::Sx); | 				val.resize(GetSize(sig), State::Sx); | ||||||
| 
 | 
 | ||||||
| 				for (int i = 0; i < GetSize(sig); i++) | 				for (int i = 0; i < GetSize(sig); i++) | ||||||
| 					if (val[i] == State::S0 || val[i] == State::S1) { | 					if (val[i] == State::S0 || val[i] == State::S1) { | ||||||
|  |  | ||||||
|  | @ -1079,14 +1079,14 @@ struct Smt2Worker | ||||||
| 
 | 
 | ||||||
| 				RTLIL::SigSpec sig = sigmap(wire); | 				RTLIL::SigSpec sig = sigmap(wire); | ||||||
| 				Const val = wire->attributes.at(ID::init); | 				Const val = wire->attributes.at(ID::init); | ||||||
| 				val.bits().resize(GetSize(sig), State::Sx); | 				val.resize(GetSize(sig), State::Sx); | ||||||
| 				if (bvmode && GetSize(sig) > 1) { | 				if (bvmode && GetSize(sig) > 1) { | ||||||
| 					Const mask(State::S1, GetSize(sig)); | 					Const mask(State::S1, GetSize(sig)); | ||||||
| 					bool use_mask = false; | 					bool use_mask = false; | ||||||
| 					for (int i = 0; i < GetSize(sig); i++) | 					for (int i = 0; i < GetSize(sig); i++) | ||||||
| 						if (val[i] != State::S0 && val[i] != State::S1) { | 						if (val[i] != State::S0 && val[i] != State::S1) { | ||||||
| 							val.bits()[i] = State::S0; | 							val.set(i, State::S0); | ||||||
| 							mask.bits()[i] = State::S0; | 							mask.set(i, State::S0); | ||||||
| 							use_mask = true; | 							use_mask = true; | ||||||
| 						} | 						} | ||||||
| 					if (use_mask) | 					if (use_mask) | ||||||
|  | @ -1361,10 +1361,10 @@ struct Smt2Worker | ||||||
| 					for (int k = 0; k < GetSize(initword); k++) { | 					for (int k = 0; k < GetSize(initword); k++) { | ||||||
| 						if (initword[k] == State::S0 || initword[k] == State::S1) { | 						if (initword[k] == State::S0 || initword[k] == State::S1) { | ||||||
| 							gen_init_constr = true; | 							gen_init_constr = true; | ||||||
| 							initmask.bits()[k] = State::S1; | 							initmask.set(k, State::S1); | ||||||
| 						} else { | 						} else { | ||||||
| 							initmask.bits()[k] = State::S0; | 							initmask.set(k, State::S0); | ||||||
| 							initword.bits()[k] = State::S0; | 							initword.set(k, State::S0); | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -327,19 +327,20 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o | ||||||
| 
 | 
 | ||||||
| void dump_reg_init(std::ostream &f, SigSpec sig) | void dump_reg_init(std::ostream &f, SigSpec sig) | ||||||
| { | { | ||||||
| 	Const initval; |  | ||||||
| 	bool gotinit = false; | 	bool gotinit = false; | ||||||
| 
 | 
 | ||||||
|  | 	Const::Builder initval_bits(sig.size()); | ||||||
| 	for (auto bit : active_sigmap(sig)) { | 	for (auto bit : active_sigmap(sig)) { | ||||||
| 		if (active_initdata.count(bit)) { | 		if (active_initdata.count(bit)) { | ||||||
| 			initval.bits().push_back(active_initdata.at(bit)); | 			initval_bits.push_back(active_initdata.at(bit)); | ||||||
| 			gotinit = true; | 			gotinit = true; | ||||||
| 		} else { | 		} else { | ||||||
| 			initval.bits().push_back(State::Sx); | 			initval_bits.push_back(State::Sx); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (gotinit) { | 	if (gotinit) { | ||||||
|  | 		Const initval = initval_bits.build(); | ||||||
| 		f << " = "; | 		f << " = "; | ||||||
| 		dump_const(f, initval); | 		dump_const(f, initval); | ||||||
| 	} | 	} | ||||||
|  | @ -767,9 +768,10 @@ void dump_memory(std::ostream &f, std::string indent, Mem &mem) | ||||||
| 					dump_sigspec(os, port.data.extract(sub * mem.width, mem.width)); | 					dump_sigspec(os, port.data.extract(sub * mem.width, mem.width)); | ||||||
| 					os << stringf(" = %s[", mem_id);; | 					os << stringf(" = %s[", mem_id);; | ||||||
| 					if (port.wide_log2) { | 					if (port.wide_log2) { | ||||||
| 						Const addr_lo; | 						Const::Builder addr_lo_builder(port.wide_log2); | ||||||
| 						for (int i = 0; i < port.wide_log2; i++) | 						for (int i = 0; i < port.wide_log2; i++) | ||||||
| 							addr_lo.bits().push_back(State(sub >> i & 1)); | 							addr_lo_builder.push_back(State(sub >> i & 1)); | ||||||
|  | 						Const addr_lo = addr_lo_builder.build(); | ||||||
| 						os << "{"; | 						os << "{"; | ||||||
| 						os << temp_id; | 						os << temp_id; | ||||||
| 						os << ", "; | 						os << ", "; | ||||||
|  |  | ||||||
|  | @ -448,7 +448,7 @@ void AigerReader::parse_xaiger() | ||||||
| 					bool success = ce.eval(o); | 					bool success = ce.eval(o); | ||||||
| 					log_assert(success); | 					log_assert(success); | ||||||
| 					log_assert(o.wire == nullptr); | 					log_assert(o.wire == nullptr); | ||||||
| 					lut_mask.bits()[gray] = o.data; | 					lut_mask.set(gray, o.data); | ||||||
| 				} | 				} | ||||||
| 				RTLIL::Cell *output_cell = module->cell(stringf("$and$aiger%d$%d", aiger_autoidx, rootNodeID)); | 				RTLIL::Cell *output_cell = module->cell(stringf("$and$aiger%d$%d", aiger_autoidx, rootNodeID)); | ||||||
| 				log_assert(output_cell); | 				log_assert(output_cell); | ||||||
|  |  | ||||||
|  | @ -1076,8 +1076,10 @@ RTLIL::Const AstNode::realAsConst(int width) | ||||||
| 		bool is_negative = v < 0; | 		bool is_negative = v < 0; | ||||||
| 		if (is_negative) | 		if (is_negative) | ||||||
| 			v *= -1; | 			v *= -1; | ||||||
|  | 		RTLIL::Const::Builder b(width); | ||||||
| 		for (int i = 0; i < width; i++, v /= 2) | 		for (int i = 0; i < width; i++, v /= 2) | ||||||
| 			result.bits().push_back((fmod(floor(v), 2) != 0) ? RTLIL::State::S1 : RTLIL::State::S0); | 			b.push_back((fmod(floor(v), 2) != 0) ? RTLIL::State::S1 : RTLIL::State::S0); | ||||||
|  | 		result = b.build(); | ||||||
| 		if (is_negative) | 		if (is_negative) | ||||||
| 			result = const_neg(result, result, false, false, result.size()); | 			result = const_neg(result, result, false, false, result.size()); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -732,16 +732,17 @@ struct AST_INTERNAL::ProcessGenerator | ||||||
| 				current_case->actions.push_back(SigSig(en, true)); | 				current_case->actions.push_back(SigSig(en, true)); | ||||||
| 
 | 
 | ||||||
| 				RTLIL::SigSpec triggers; | 				RTLIL::SigSpec triggers; | ||||||
| 				RTLIL::Const polarity; | 				RTLIL::Const::Builder polarity_builder; | ||||||
| 				for (auto sync : proc->syncs) { | 				for (auto sync : proc->syncs) { | ||||||
| 					if (sync->type == RTLIL::STp) { | 					if (sync->type == RTLIL::STp) { | ||||||
| 						triggers.append(sync->signal); | 						triggers.append(sync->signal); | ||||||
| 						polarity.bits().push_back(RTLIL::S1); | 						polarity_builder.push_back(RTLIL::S1); | ||||||
| 					} else if (sync->type == RTLIL::STn) { | 					} else if (sync->type == RTLIL::STn) { | ||||||
| 						triggers.append(sync->signal); | 						triggers.append(sync->signal); | ||||||
| 						polarity.bits().push_back(RTLIL::S0); | 						polarity_builder.push_back(RTLIL::S0); | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
|  | 				RTLIL::Const polarity = polarity_builder.build(); | ||||||
| 
 | 
 | ||||||
| 				RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($print)); | 				RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($print)); | ||||||
| 				set_src_attr(cell, ast); | 				set_src_attr(cell, ast); | ||||||
|  | @ -829,16 +830,17 @@ struct AST_INTERNAL::ProcessGenerator | ||||||
| 				current_case->actions.push_back(SigSig(en, true)); | 				current_case->actions.push_back(SigSig(en, true)); | ||||||
| 
 | 
 | ||||||
| 				RTLIL::SigSpec triggers; | 				RTLIL::SigSpec triggers; | ||||||
| 				RTLIL::Const polarity; | 				RTLIL::Const::Builder polarity_builder; | ||||||
| 				for (auto sync : proc->syncs) { | 				for (auto sync : proc->syncs) { | ||||||
| 					if (sync->type == RTLIL::STp) { | 					if (sync->type == RTLIL::STp) { | ||||||
| 						triggers.append(sync->signal); | 						triggers.append(sync->signal); | ||||||
| 						polarity.bits().push_back(RTLIL::S1); | 						polarity_builder.push_back(RTLIL::S1); | ||||||
| 					} else if (sync->type == RTLIL::STn) { | 					} else if (sync->type == RTLIL::STn) { | ||||||
| 						triggers.append(sync->signal); | 						triggers.append(sync->signal); | ||||||
| 						polarity.bits().push_back(RTLIL::S0); | 						polarity_builder.push_back(RTLIL::S0); | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
|  | 				RTLIL::Const polarity = polarity_builder.build(); | ||||||
| 
 | 
 | ||||||
| 				RTLIL::Cell *cell = current_module->addCell(cellname, ID($check)); | 				RTLIL::Cell *cell = current_module->addCell(cellname, ID($check)); | ||||||
| 				set_src_attr(cell, ast); | 				set_src_attr(cell, ast); | ||||||
|  | @ -893,7 +895,7 @@ struct AST_INTERNAL::ProcessGenerator | ||||||
| 				RTLIL::Const priority_mask = RTLIL::Const(0, cur_idx); | 				RTLIL::Const priority_mask = RTLIL::Const(0, cur_idx); | ||||||
| 				for (int i = 0; i < portid; i++) { | 				for (int i = 0; i < portid; i++) { | ||||||
| 					int new_bit = port_map[std::make_pair(memid, i)]; | 					int new_bit = port_map[std::make_pair(memid, i)]; | ||||||
| 					priority_mask.bits()[new_bit] = orig_priority_mask[i]; | 					priority_mask.set(new_bit, orig_priority_mask[i]); | ||||||
| 				} | 				} | ||||||
| 				action.priority_mask = priority_mask; | 				action.priority_mask = priority_mask; | ||||||
| 				sync->mem_write_actions.push_back(action); | 				sync->mem_write_actions.push_back(action); | ||||||
|  |  | ||||||
|  | @ -4366,7 +4366,7 @@ replace_fcall_later:; | ||||||
| 					log_assert(a.size() == b.size()); | 					log_assert(a.size() == b.size()); | ||||||
| 					for (auto i = 0; i < a.size(); i++) | 					for (auto i = 0; i < a.size(); i++) | ||||||
| 						if (a[i] != b[i]) | 						if (a[i] != b[i]) | ||||||
| 							a.bits()[i] = RTLIL::State::Sx; | 							a.set(i, RTLIL::State::Sx); | ||||||
| 					newNode = mkconst_bits(location, a.to_bits(), sign_hint); | 					newNode = mkconst_bits(location, a.to_bits(), sign_hint); | ||||||
| 				} else if (children[1]->isConst() && children[2]->isConst()) { | 				} else if (children[1]->isConst() && children[2]->isConst()) { | ||||||
| 					newNode = std::make_unique<AstNode>(location, AST_REALVALUE); | 					newNode = std::make_unique<AstNode>(location, AST_REALVALUE); | ||||||
|  | @ -5368,8 +5368,11 @@ bool AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &varia | ||||||
| 		offset -= variables.at(str).offset; | 		offset -= variables.at(str).offset; | ||||||
| 		if (variables.at(str).range_swapped) | 		if (variables.at(str).range_swapped) | ||||||
| 			offset = -offset; | 			offset = -offset; | ||||||
| 		std::vector<RTLIL::State> &var_bits = variables.at(str).val.bits(); | 		const RTLIL::Const &val = variables.at(str).val; | ||||||
| 		std::vector<RTLIL::State> new_bits(var_bits.begin() + offset, var_bits.begin() + offset + width); | 		std::vector<RTLIL::State> new_bits; | ||||||
|  | 		new_bits.reserve(width); | ||||||
|  | 		for (int i = 0; i < width; i++) | ||||||
|  | 			new_bits.push_back(val[offset+i]); | ||||||
| 		auto newNode = mkconst_bits(location, new_bits, variables.at(str).is_signed); | 		auto newNode = mkconst_bits(location, new_bits, variables.at(str).is_signed); | ||||||
| 		newNode->cloneInto(*this); | 		newNode->cloneInto(*this); | ||||||
| 		return true; | 		return true; | ||||||
|  | @ -5513,7 +5516,7 @@ std::unique_ptr<AstNode> AstNode::eval_const_function(AstNode *fcall, bool must_ | ||||||
| 					int index = i + offset - v.offset; | 					int index = i + offset - v.offset; | ||||||
| 					if (v.range_swapped) | 					if (v.range_swapped) | ||||||
| 						index = -index; | 						index = -index; | ||||||
| 					v.val.bits().at(index) = r.at(i); | 					v.val.set(index, r.at(i)); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -149,7 +149,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool | ||||||
| 		if (buffer[0] == '.') | 		if (buffer[0] == '.') | ||||||
| 		{ | 		{ | ||||||
| 			if (lutptr) { | 			if (lutptr) { | ||||||
| 				for (auto &bit : lutptr->bits()) | 				for (auto bit : *lutptr) | ||||||
| 					if (bit == RTLIL::State::Sx) | 					if (bit == RTLIL::State::Sx) | ||||||
| 						bit = lut_default_state; | 						bit = lut_default_state; | ||||||
| 				lutptr = NULL; | 				lutptr = NULL; | ||||||
|  | @ -321,9 +321,10 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool | ||||||
| 					const_v = Const(str); | 					const_v = Const(str); | ||||||
| 				} else { | 				} else { | ||||||
| 					int n = strlen(v); | 					int n = strlen(v); | ||||||
| 					const_v.bits().resize(n); | 					Const::Builder const_v_builder(n); | ||||||
| 					for (int i = 0; i < n; i++) | 					for (int i = 0; i < n; i++) | ||||||
| 						const_v.bits()[i] = v[n-i-1] != '0' ? State::S1 : State::S0; | 						const_v_builder.push_back(v[n-i-1] != '0' ? State::S1 : State::S0); | ||||||
|  | 					const_v = const_v_builder.build(); | ||||||
| 				} | 				} | ||||||
| 				if (!strcmp(cmd, ".attr")) { | 				if (!strcmp(cmd, ".attr")) { | ||||||
| 					if (obj_attributes == nullptr) { | 					if (obj_attributes == nullptr) { | ||||||
|  | @ -563,21 +564,23 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool | ||||||
| 			log_assert(sopcell->parameters[ID::WIDTH].as_int() == input_len); | 			log_assert(sopcell->parameters[ID::WIDTH].as_int() == input_len); | ||||||
| 			sopcell->parameters[ID::DEPTH] = sopcell->parameters[ID::DEPTH].as_int() + 1; | 			sopcell->parameters[ID::DEPTH] = sopcell->parameters[ID::DEPTH].as_int() + 1; | ||||||
| 
 | 
 | ||||||
|  | 			Const::Builder table_bits_builder(input_len * 2); | ||||||
| 			for (int i = 0; i < input_len; i++) | 			for (int i = 0; i < input_len; i++) | ||||||
| 				switch (input[i]) { | 				switch (input[i]) { | ||||||
| 					case '0': | 					case '0': | ||||||
| 						sopcell->parameters[ID::TABLE].bits().push_back(State::S1); | 						table_bits_builder.push_back(State::S1); | ||||||
| 						sopcell->parameters[ID::TABLE].bits().push_back(State::S0); | 						table_bits_builder.push_back(State::S0); | ||||||
| 						break; | 						break; | ||||||
| 					case '1': | 					case '1': | ||||||
| 						sopcell->parameters[ID::TABLE].bits().push_back(State::S0); | 						table_bits_builder.push_back(State::S0); | ||||||
| 						sopcell->parameters[ID::TABLE].bits().push_back(State::S1); | 						table_bits_builder.push_back(State::S1); | ||||||
| 						break; | 						break; | ||||||
| 					default: | 					default: | ||||||
| 						sopcell->parameters[ID::TABLE].bits().push_back(State::S0); | 						table_bits_builder.push_back(State::S0); | ||||||
| 						sopcell->parameters[ID::TABLE].bits().push_back(State::S0); | 						table_bits_builder.push_back(State::S0); | ||||||
| 						break; | 						break; | ||||||
| 				} | 				} | ||||||
|  | 			sopcell->parameters[ID::TABLE].append(table_bits_builder.build()); | ||||||
| 
 | 
 | ||||||
| 			if (sopmode == -1) { | 			if (sopmode == -1) { | ||||||
| 				sopmode = (*output == '1'); | 				sopmode = (*output == '1'); | ||||||
|  | @ -605,7 +608,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool | ||||||
| 							goto try_next_value; | 							goto try_next_value; | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 				lutptr->bits().at(i) = !strcmp(output, "0") ? RTLIL::State::S0 : RTLIL::State::S1; | 				lutptr->set(i, !strcmp(output, "0") ? RTLIL::State::S0 : RTLIL::State::S1); | ||||||
| 			try_next_value:; | 			try_next_value:; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -258,7 +258,7 @@ Const json_parse_attr_param_value(JsonNode *node) | ||||||
| 		} | 		} | ||||||
| 	} else | 	} else | ||||||
| 	if (node->type == 'N') { | 	if (node->type == 'N') { | ||||||
| 		value = Const(node->data_number, 32); | 		value = Const(node->data_number); | ||||||
| 		if (node->data_number < 0) | 		if (node->data_number < 0) | ||||||
| 			value.flags |= RTLIL::CONST_FLAG_SIGNED; | 			value.flags |= RTLIL::CONST_FLAG_SIGNED; | ||||||
| 	} else | 	} else | ||||||
|  |  | ||||||
|  | @ -455,16 +455,17 @@ constant: | ||||||
| 		} | 		} | ||||||
| 		while ((int)bits.size() > width) | 		while ((int)bits.size() > width) | ||||||
| 			bits.pop_back(); | 			bits.pop_back(); | ||||||
| 		$$ = new RTLIL::Const; | 		RTLIL::Const::Builder builder(bits.size()); | ||||||
| 		for (auto it = bits.begin(); it != bits.end(); it++) | 		for (RTLIL::State bit : bits) | ||||||
| 			$$->bits().push_back(*it); | 			builder.push_back(bit); | ||||||
|  | 		$$ = new RTLIL::Const(builder.build()); | ||||||
| 		if (is_signed) { | 		if (is_signed) { | ||||||
| 			$$->flags |= RTLIL::CONST_FLAG_SIGNED; | 			$$->flags |= RTLIL::CONST_FLAG_SIGNED; | ||||||
| 		} | 		} | ||||||
| 		free($1); | 		free($1); | ||||||
| 	} | | 	} | | ||||||
| 	TOK_INT { | 	TOK_INT { | ||||||
| 		$$ = new RTLIL::Const($1, 32); | 		$$ = new RTLIL::Const($1); | ||||||
| 	} | | 	} | | ||||||
| 	TOK_STRING { | 	TOK_STRING { | ||||||
| 		$$ = new RTLIL::Const($1); | 		$$ = new RTLIL::Const($1); | ||||||
|  |  | ||||||
|  | @ -267,13 +267,13 @@ static const RTLIL::Const extract_vhdl_bit_vector(std::string &val, std::string | ||||||
| static const RTLIL::Const extract_vhdl_integer(std::string &val) | static const RTLIL::Const extract_vhdl_integer(std::string &val) | ||||||
| { | { | ||||||
| 	char *end; | 	char *end; | ||||||
| 	return RTLIL::Const((int)std::strtol(val.c_str(), &end, 10), 32); | 	return RTLIL::Const((int)std::strtol(val.c_str(), &end, 10)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static const RTLIL::Const extract_vhdl_char(std::string &val) | static const RTLIL::Const extract_vhdl_char(std::string &val) | ||||||
| { | { | ||||||
| 	if (val.size()==3 && val[0]=='\"' && val.back()=='\"') | 	if (val.size()==3 && val[0]=='\"' && val.back()=='\"') | ||||||
| 		return RTLIL::Const((int)val[1], 32); | 		return RTLIL::Const((int)val[1]); | ||||||
| 	log_error("Error parsing VHDL character.\n"); | 	log_error("Error parsing VHDL character.\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -311,7 +311,7 @@ static const  RTLIL::Const extract_vhdl_const(const char *value, bool output_sig | ||||||
| 	} else if ((value[0] == '-' || (value[0] >= '0' && value[0] <= '9')) && | 	} else if ((value[0] == '-' || (value[0] >= '0' && value[0] <= '9')) && | ||||||
| 			((decimal = std::strtol(value, &end, 10)), !end[0])) { | 			((decimal = std::strtol(value, &end, 10)), !end[0])) { | ||||||
| 		is_signed = output_signed; | 		is_signed = output_signed; | ||||||
| 		c = RTLIL::Const((int)decimal, 32); | 		c = RTLIL::Const((int)decimal); | ||||||
| 	} else if (val == "false") { | 	} else if (val == "false") { | ||||||
| 		c = RTLIL::Const::from_string("0"); | 		c = RTLIL::Const::from_string("0"); | ||||||
| 	} else if (val == "true") { | 	} else if (val == "true") { | ||||||
|  | @ -344,7 +344,7 @@ static const  RTLIL::Const extract_verilog_const(const char *value, bool allow_s | ||||||
| 	} else if ((value[0] == '-' || (value[0] >= '0' && value[0] <= '9')) && | 	} else if ((value[0] == '-' || (value[0] >= '0' && value[0] <= '9')) && | ||||||
| 			((decimal = std::strtol(value, &end, 10)), !end[0])) { | 			((decimal = std::strtol(value, &end, 10)), !end[0])) { | ||||||
| 		is_signed = output_signed; | 		is_signed = output_signed; | ||||||
| 		c = RTLIL::Const((int)decimal, 32); | 		c = RTLIL::Const((int)decimal); | ||||||
| 	} else if (allow_string) { | 	} else if (allow_string) { | ||||||
| 		c = RTLIL::Const(val); | 		c = RTLIL::Const(val); | ||||||
| 	} else { | 	} else { | ||||||
|  |  | ||||||
|  | @ -100,7 +100,7 @@ struct BitPatternPool | ||||||
| 	bits_t sig2bits(RTLIL::SigSpec sig) | 	bits_t sig2bits(RTLIL::SigSpec sig) | ||||||
| 	{ | 	{ | ||||||
| 		bits_t bits; | 		bits_t bits; | ||||||
| 		bits.bitdata = sig.as_const().bits(); | 		bits.bitdata = sig.as_const().to_bits(); | ||||||
| 		for (auto &b : bits.bitdata) | 		for (auto &b : bits.bitdata) | ||||||
| 			if (b > RTLIL::State::S1) | 			if (b > RTLIL::State::S1) | ||||||
| 				b = RTLIL::State::Sa; | 				b = RTLIL::State::Sa; | ||||||
|  |  | ||||||
|  | @ -33,10 +33,7 @@ static void extend_u0(RTLIL::Const &arg, int width, bool is_signed) | ||||||
| 	if (arg.size() > 0 && is_signed) | 	if (arg.size() > 0 && is_signed) | ||||||
| 		padding = arg.back(); | 		padding = arg.back(); | ||||||
| 
 | 
 | ||||||
| 	while (GetSize(arg) < width) | 	arg.resize(width, padding); | ||||||
| 		arg.bits().push_back(padding); |  | ||||||
| 
 |  | ||||||
| 	arg.bits().resize(width); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static BigInteger const2big(const RTLIL::Const &val, bool as_signed, int &undef_bit_pos) | static BigInteger const2big(const RTLIL::Const &val, bool as_signed, int &undef_bit_pos) | ||||||
|  | @ -79,12 +76,12 @@ static RTLIL::Const big2const(const BigInteger &val, int result_len, int undef_b | ||||||
| 		{ | 		{ | ||||||
| 			mag--; | 			mag--; | ||||||
| 			for (auto i = 0; i < result_len; i++) | 			for (auto i = 0; i < result_len; i++) | ||||||
| 				result.bits()[i] = mag.getBit(i) ? RTLIL::State::S0 : RTLIL::State::S1; | 				result.set(i, mag.getBit(i) ? RTLIL::State::S0 : RTLIL::State::S1); | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| 			for (auto i = 0; i < result_len; i++) | 			for (auto i = 0; i < result_len; i++) | ||||||
| 				result.bits()[i] = mag.getBit(i) ? RTLIL::State::S1 : RTLIL::State::S0; | 				result.set(i, mag.getBit(i) ? RTLIL::State::S1 : RTLIL::State::S0); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -140,11 +137,11 @@ RTLIL::Const RTLIL::const_not(const RTLIL::Const &arg1, const RTLIL::Const&, boo | ||||||
| 	RTLIL::Const result(RTLIL::State::Sx, result_len); | 	RTLIL::Const result(RTLIL::State::Sx, result_len); | ||||||
| 	for (auto i = 0; i < result_len; i++) { | 	for (auto i = 0; i < result_len; i++) { | ||||||
| 		if (i >= GetSize(arg1_ext)) | 		if (i >= GetSize(arg1_ext)) | ||||||
| 			result.bits()[i] = RTLIL::State::S0; | 			result.set(i, RTLIL::State::S0); | ||||||
| 		else if (arg1_ext.bits()[i] == RTLIL::State::S0) | 		else if (arg1_ext[i] == RTLIL::State::S0) | ||||||
| 			result.bits()[i] = RTLIL::State::S1; | 			result.set(i, RTLIL::State::S1); | ||||||
| 		else if (arg1_ext.bits()[i] == RTLIL::State::S1) | 		else if (arg1_ext[i] == RTLIL::State::S1) | ||||||
| 			result.bits()[i] = RTLIL::State::S0; | 			result.set(i, RTLIL::State::S0); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return result; | 	return result; | ||||||
|  | @ -161,9 +158,9 @@ static RTLIL::Const logic_wrapper(RTLIL::State(*logic_func)(RTLIL::State, RTLIL: | ||||||
| 
 | 
 | ||||||
| 	RTLIL::Const result(RTLIL::State::Sx, result_len); | 	RTLIL::Const result(RTLIL::State::Sx, result_len); | ||||||
| 	for (auto i = 0; i < result_len; i++) { | 	for (auto i = 0; i < result_len; i++) { | ||||||
| 		RTLIL::State a = i < GetSize(arg1) ? arg1.bits()[i] : RTLIL::State::S0; | 		RTLIL::State a = i < GetSize(arg1) ? arg1[i] : RTLIL::State::S0; | ||||||
| 		RTLIL::State b = i < GetSize(arg2) ? arg2.bits()[i] : RTLIL::State::S0; | 		RTLIL::State b = i < GetSize(arg2) ? arg2[i] : RTLIL::State::S0; | ||||||
| 		result.bits()[i] = logic_func(a, b); | 		result.set(i, logic_func(a, b)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return result; | 	return result; | ||||||
|  | @ -197,8 +194,8 @@ static RTLIL::Const logic_reduce_wrapper(RTLIL::State initial, RTLIL::State(*log | ||||||
| 		temp = logic_func(temp, arg1[i]); | 		temp = logic_func(temp, arg1[i]); | ||||||
| 
 | 
 | ||||||
| 	RTLIL::Const result(temp); | 	RTLIL::Const result(temp); | ||||||
| 	while (GetSize(result) < result_len) | 	if (GetSize(result) < result_len) | ||||||
| 		result.bits().push_back(RTLIL::State::S0); | 		result.resize(result_len, RTLIL::State::S0); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -222,9 +219,9 @@ RTLIL::Const RTLIL::const_reduce_xnor(const RTLIL::Const &arg1, const RTLIL::Con | ||||||
| 	RTLIL::Const buffer = logic_reduce_wrapper(RTLIL::State::S0, logic_xor, arg1, result_len); | 	RTLIL::Const buffer = logic_reduce_wrapper(RTLIL::State::S0, logic_xor, arg1, result_len); | ||||||
| 	if (!buffer.empty()) { | 	if (!buffer.empty()) { | ||||||
| 		if (buffer.front() == RTLIL::State::S0) | 		if (buffer.front() == RTLIL::State::S0) | ||||||
| 			buffer.bits().front() = RTLIL::State::S1; | 			buffer.set(0, RTLIL::State::S1); | ||||||
| 		else if (buffer.front() == RTLIL::State::S1) | 		else if (buffer.front() == RTLIL::State::S1) | ||||||
| 			buffer.bits().front() = RTLIL::State::S0; | 			buffer.set(0, RTLIL::State::S0); | ||||||
| 	} | 	} | ||||||
| 	return buffer; | 	return buffer; | ||||||
| } | } | ||||||
|  | @ -239,9 +236,8 @@ RTLIL::Const RTLIL::const_logic_not(const RTLIL::Const &arg1, const RTLIL::Const | ||||||
| 	int undef_bit_pos_a = -1; | 	int undef_bit_pos_a = -1; | ||||||
| 	BigInteger a = const2big(arg1, signed1, undef_bit_pos_a); | 	BigInteger a = const2big(arg1, signed1, undef_bit_pos_a); | ||||||
| 	RTLIL::Const result(a.isZero() ? undef_bit_pos_a >= 0 ? RTLIL::State::Sx : RTLIL::State::S1 : RTLIL::State::S0); | 	RTLIL::Const result(a.isZero() ? undef_bit_pos_a >= 0 ? RTLIL::State::Sx : RTLIL::State::S1 : RTLIL::State::S0); | ||||||
| 
 | 	if (GetSize(result) < result_len) | ||||||
| 	while (GetSize(result) < result_len) | 		result.resize(result_len, RTLIL::State::S0); | ||||||
| 		result.bits().push_back(RTLIL::State::S0); |  | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -254,9 +250,8 @@ RTLIL::Const RTLIL::const_logic_and(const RTLIL::Const &arg1, const RTLIL::Const | ||||||
| 	RTLIL::State bit_a = a.isZero() ? undef_bit_pos_a >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1; | 	RTLIL::State bit_a = a.isZero() ? undef_bit_pos_a >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1; | ||||||
| 	RTLIL::State bit_b = b.isZero() ? undef_bit_pos_b >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1; | 	RTLIL::State bit_b = b.isZero() ? undef_bit_pos_b >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1; | ||||||
| 	RTLIL::Const result(logic_and(bit_a, bit_b)); | 	RTLIL::Const result(logic_and(bit_a, bit_b)); | ||||||
| 
 | 	if (GetSize(result) < result_len) | ||||||
| 	while (GetSize(result) < result_len) | 		result.resize(result_len, RTLIL::State::S0); | ||||||
| 		result.bits().push_back(RTLIL::State::S0); |  | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -269,9 +264,8 @@ RTLIL::Const RTLIL::const_logic_or(const RTLIL::Const &arg1, const RTLIL::Const | ||||||
| 	RTLIL::State bit_a = a.isZero() ? undef_bit_pos_a >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1; | 	RTLIL::State bit_a = a.isZero() ? undef_bit_pos_a >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1; | ||||||
| 	RTLIL::State bit_b = b.isZero() ? undef_bit_pos_b >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1; | 	RTLIL::State bit_b = b.isZero() ? undef_bit_pos_b >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1; | ||||||
| 	RTLIL::Const result(logic_or(bit_a, bit_b)); | 	RTLIL::Const result(logic_or(bit_a, bit_b)); | ||||||
| 
 | 	if (GetSize(result) < result_len) | ||||||
| 	while (GetSize(result) < result_len) | 		result.resize(result_len, RTLIL::State::S0); | ||||||
| 		result.bits().push_back(RTLIL::State::S0); |  | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -295,11 +289,11 @@ static RTLIL::Const const_shift_worker(const RTLIL::Const &arg1, const RTLIL::Co | ||||||
| 	for (int i = 0; i < result_len; i++) { | 	for (int i = 0; i < result_len; i++) { | ||||||
| 		BigInteger pos = BigInteger(i) + offset; | 		BigInteger pos = BigInteger(i) + offset; | ||||||
| 		if (pos < 0) | 		if (pos < 0) | ||||||
| 			result.bits()[i] = vacant_bits; | 			result.set(i, vacant_bits); | ||||||
| 		else if (pos >= BigInteger(GetSize(arg1))) | 		else if (pos >= BigInteger(GetSize(arg1))) | ||||||
| 			result.bits()[i] = sign_ext ? arg1.back() : vacant_bits; | 			result.set(i, sign_ext ? arg1.back() : vacant_bits); | ||||||
| 		else | 		else | ||||||
| 			result.bits()[i] = arg1[pos.toInt()]; | 			result.set(i, arg1[pos.toInt()]); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return result; | 	return result; | ||||||
|  | @ -346,9 +340,8 @@ RTLIL::Const RTLIL::const_lt(const RTLIL::Const &arg1, const RTLIL::Const &arg2, | ||||||
| 	int undef_bit_pos = -1; | 	int undef_bit_pos = -1; | ||||||
| 	bool y = const2big(arg1, signed1, undef_bit_pos) < const2big(arg2, signed2, undef_bit_pos); | 	bool y = const2big(arg1, signed1, undef_bit_pos) < const2big(arg2, signed2, undef_bit_pos); | ||||||
| 	RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0); | 	RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0); | ||||||
| 
 | 	if (GetSize(result) < result_len) | ||||||
| 	while (GetSize(result) < result_len) | 		result.resize(result_len, RTLIL::State::S0); | ||||||
| 		result.bits().push_back(RTLIL::State::S0); |  | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -357,9 +350,8 @@ RTLIL::Const RTLIL::const_le(const RTLIL::Const &arg1, const RTLIL::Const &arg2, | ||||||
| 	int undef_bit_pos = -1; | 	int undef_bit_pos = -1; | ||||||
| 	bool y = const2big(arg1, signed1, undef_bit_pos) <= const2big(arg2, signed2, undef_bit_pos); | 	bool y = const2big(arg1, signed1, undef_bit_pos) <= const2big(arg2, signed2, undef_bit_pos); | ||||||
| 	RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0); | 	RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0); | ||||||
| 
 | 	if (GetSize(result) < result_len) | ||||||
| 	while (GetSize(result) < result_len) | 		result.resize(result_len, RTLIL::State::S0); | ||||||
| 		result.bits().push_back(RTLIL::State::S0); |  | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -383,7 +375,7 @@ RTLIL::Const RTLIL::const_eq(const RTLIL::Const &arg1, const RTLIL::Const &arg2, | ||||||
| 			matched_status = RTLIL::State::Sx; | 			matched_status = RTLIL::State::Sx; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	result.bits().front() = matched_status; | 	result.set(0, matched_status); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -391,9 +383,9 @@ RTLIL::Const RTLIL::const_ne(const RTLIL::Const &arg1, const RTLIL::Const &arg2, | ||||||
| { | { | ||||||
| 	RTLIL::Const result = RTLIL::const_eq(arg1, arg2, signed1, signed2, result_len); | 	RTLIL::Const result = RTLIL::const_eq(arg1, arg2, signed1, signed2, result_len); | ||||||
| 	if (result.front() == RTLIL::State::S0) | 	if (result.front() == RTLIL::State::S0) | ||||||
| 		result.bits().front() = RTLIL::State::S1; | 		result.set(0, RTLIL::State::S1); | ||||||
| 	else if (result.front() == RTLIL::State::S1) | 	else if (result.front() == RTLIL::State::S1) | ||||||
| 		result.bits().front() = RTLIL::State::S0; | 		result.set(0, RTLIL::State::S0); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -412,7 +404,7 @@ RTLIL::Const RTLIL::const_eqx(const RTLIL::Const &arg1, const RTLIL::Const &arg2 | ||||||
| 			return result; | 			return result; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	result.bits().front() = RTLIL::State::S1; | 	result.set(0, RTLIL::State::S1); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -420,9 +412,9 @@ RTLIL::Const RTLIL::const_nex(const RTLIL::Const &arg1, const RTLIL::Const &arg2 | ||||||
| { | { | ||||||
| 	RTLIL::Const result = RTLIL::const_eqx(arg1, arg2, signed1, signed2, result_len); | 	RTLIL::Const result = RTLIL::const_eqx(arg1, arg2, signed1, signed2, result_len); | ||||||
| 	if (result.front() == RTLIL::State::S0) | 	if (result.front() == RTLIL::State::S0) | ||||||
| 		result.bits().front() = RTLIL::State::S1; | 		result.set(0, RTLIL::State::S1); | ||||||
| 	else if (result.front() == RTLIL::State::S1) | 	else if (result.front() == RTLIL::State::S1) | ||||||
| 		result.bits().front() = RTLIL::State::S0; | 		result.set(0, RTLIL::State::S0); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -431,9 +423,8 @@ RTLIL::Const RTLIL::const_ge(const RTLIL::Const &arg1, const RTLIL::Const &arg2, | ||||||
| 	int undef_bit_pos = -1; | 	int undef_bit_pos = -1; | ||||||
| 	bool y = const2big(arg1, signed1, undef_bit_pos) >= const2big(arg2, signed2, undef_bit_pos); | 	bool y = const2big(arg1, signed1, undef_bit_pos) >= const2big(arg2, signed2, undef_bit_pos); | ||||||
| 	RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0); | 	RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0); | ||||||
| 
 | 	if (GetSize(result) < result_len) | ||||||
| 	while (GetSize(result) < result_len) | 		result.resize(result_len, RTLIL::State::S0); | ||||||
| 		result.bits().push_back(RTLIL::State::S0); |  | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -442,9 +433,8 @@ RTLIL::Const RTLIL::const_gt(const RTLIL::Const &arg1, const RTLIL::Const &arg2, | ||||||
| 	int undef_bit_pos = -1; | 	int undef_bit_pos = -1; | ||||||
| 	bool y = const2big(arg1, signed1, undef_bit_pos) > const2big(arg2, signed2, undef_bit_pos); | 	bool y = const2big(arg1, signed1, undef_bit_pos) > const2big(arg2, signed2, undef_bit_pos); | ||||||
| 	RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0); | 	RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0); | ||||||
| 
 | 	if (GetSize(result) < result_len) | ||||||
| 	while (GetSize(result) < result_len) | 		result.resize(result_len, RTLIL::State::S0); | ||||||
| 		result.bits().push_back(RTLIL::State::S0); |  | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -628,7 +618,7 @@ RTLIL::Const RTLIL::const_mux(const RTLIL::Const &arg1, const RTLIL::Const &arg2 | ||||||
| 	RTLIL::Const ret = arg1; | 	RTLIL::Const ret = arg1; | ||||||
| 	for (auto i = 0; i < ret.size(); i++) | 	for (auto i = 0; i < ret.size(); i++) | ||||||
| 		if (ret[i] != arg2[i]) | 		if (ret[i] != arg2[i]) | ||||||
| 			ret.bits()[i] = State::Sx; | 			ret.set(i, State::Sx); | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -703,7 +693,7 @@ RTLIL::Const RTLIL::const_bweqx(const RTLIL::Const &arg1, const RTLIL::Const &ar | ||||||
| 	log_assert(arg2.size() == arg1.size()); | 	log_assert(arg2.size() == arg1.size()); | ||||||
| 	RTLIL::Const result(RTLIL::State::S0, arg1.size()); | 	RTLIL::Const result(RTLIL::State::S0, arg1.size()); | ||||||
| 	for (auto i = 0; i < arg1.size(); i++) | 	for (auto i = 0; i < arg1.size(); i++) | ||||||
| 		result.bits()[i] = arg1[i] == arg2[i] ? State::S1 : State::S0; | 		result.set(i, arg1[i] == arg2[i] ? State::S1 : State::S0); | ||||||
| 
 | 
 | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  | @ -715,7 +705,7 @@ RTLIL::Const RTLIL::const_bwmux(const RTLIL::Const &arg1, const RTLIL::Const &ar | ||||||
| 	RTLIL::Const result(RTLIL::State::Sx, arg1.size()); | 	RTLIL::Const result(RTLIL::State::Sx, arg1.size()); | ||||||
| 	for (auto i = 0; i < arg1.size(); i++) { | 	for (auto i = 0; i < arg1.size(); i++) { | ||||||
| 		if (arg3[i] != State::Sx || arg1[i] == arg2[i]) | 		if (arg3[i] != State::Sx || arg1[i] == arg2[i]) | ||||||
| 			result.bits()[i] = arg3[i] == State::S1 ? arg2[i] : arg1[i]; | 			result.set(i, arg3[i] == State::S1 ? arg2[i] : arg1[i]); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return result; | 	return result; | ||||||
|  |  | ||||||
|  | @ -328,7 +328,7 @@ struct CellTypes | ||||||
| 
 | 
 | ||||||
| 	static RTLIL::Const eval_not(RTLIL::Const v) | 	static RTLIL::Const eval_not(RTLIL::Const v) | ||||||
| 	{ | 	{ | ||||||
| 		for (auto &bit : v.bits()) | 		for (auto bit : v) | ||||||
| 			if (bit == State::S0) bit = State::S1; | 			if (bit == State::S0) bit = State::S1; | ||||||
| 			else if (bit == State::S1) bit = State::S0; | 			else if (bit == State::S1) bit = State::S0; | ||||||
| 		return v; | 		return v; | ||||||
|  | @ -421,16 +421,14 @@ struct CellTypes | ||||||
| 	static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool *errp = nullptr) | 	static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool *errp = nullptr) | ||||||
| 	{ | 	{ | ||||||
| 		if (cell->type == ID($slice)) { | 		if (cell->type == ID($slice)) { | ||||||
| 			RTLIL::Const ret; |  | ||||||
| 			int width = cell->parameters.at(ID::Y_WIDTH).as_int(); | 			int width = cell->parameters.at(ID::Y_WIDTH).as_int(); | ||||||
| 			int offset = cell->parameters.at(ID::OFFSET).as_int(); | 			int offset = cell->parameters.at(ID::OFFSET).as_int(); | ||||||
| 			ret.bits().insert(ret.bits().end(), arg1.begin()+offset, arg1.begin()+offset+width); | 			return arg1.extract(offset, width); | ||||||
| 			return ret; |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (cell->type == ID($concat)) { | 		if (cell->type == ID($concat)) { | ||||||
| 			RTLIL::Const ret = arg1; | 			RTLIL::Const ret = arg1; | ||||||
| 			ret.bits().insert(ret.bits().end(), arg2.begin(), arg2.end()); | 			ret.append(arg2); | ||||||
| 			return ret; | 			return ret; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -115,7 +115,7 @@ struct ConstEval | ||||||
| 
 | 
 | ||||||
| 				for (int i = 0; i < GetSize(coval); i++) { | 				for (int i = 0; i < GetSize(coval); i++) { | ||||||
| 					carry = (sig_g[i] == State::S1) || (sig_p[i] == RTLIL::S1 && carry); | 					carry = (sig_g[i] == State::S1) || (sig_p[i] == RTLIL::S1 && carry); | ||||||
| 					coval.bits()[i] = carry ? State::S1 : State::S0; | 					coval.set(i, carry ? State::S1 : State::S0); | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				set(sig_co, coval); | 				set(sig_co, coval); | ||||||
|  | @ -249,7 +249,7 @@ struct ConstEval | ||||||
| 
 | 
 | ||||||
| 			for (int i = 0; i < GetSize(val_y); i++) | 			for (int i = 0; i < GetSize(val_y); i++) | ||||||
| 				if (val_y[i] == RTLIL::Sx) | 				if (val_y[i] == RTLIL::Sx) | ||||||
| 					val_x.bits()[i] = RTLIL::Sx; | 					val_x.set(i, RTLIL::Sx); | ||||||
| 
 | 
 | ||||||
| 			set(sig_y, val_y); | 			set(sig_y, val_y); | ||||||
| 			set(sig_x, val_x); | 			set(sig_x, val_x); | ||||||
|  |  | ||||||
|  | @ -260,7 +260,7 @@ bool DriveChunkMultiple::try_append(DriveBitMultiple const &bit) | ||||||
| 		switch (single.type()) | 		switch (single.type()) | ||||||
| 		{ | 		{ | ||||||
| 			case DriveType::CONSTANT: { | 			case DriveType::CONSTANT: { | ||||||
| 				single.constant().bits().push_back(constant); | 				single.constant().append(RTLIL::Const(constant)); | ||||||
| 			} break; | 			} break; | ||||||
| 			case DriveType::WIRE: { | 			case DriveType::WIRE: { | ||||||
| 				single.wire().width += 1; | 				single.wire().width += 1; | ||||||
|  | @ -295,8 +295,7 @@ bool DriveChunkMultiple::try_append(DriveChunkMultiple const &chunk) | ||||||
| 		switch (single.type()) | 		switch (single.type()) | ||||||
| 		{ | 		{ | ||||||
| 			case DriveType::CONSTANT: { | 			case DriveType::CONSTANT: { | ||||||
| 				auto &bits = single.constant().bits(); | 				single.constant().append(constant); | ||||||
| 				bits.insert(bits.end(), constant.bits().begin(), constant.bits().end()); |  | ||||||
| 			} break; | 			} break; | ||||||
| 			case DriveType::WIRE: { | 			case DriveType::WIRE: { | ||||||
| 				single.wire().width += width; | 				single.wire().width += width; | ||||||
|  | @ -349,7 +348,7 @@ bool DriveChunk::try_append(DriveBit const &bit) | ||||||
| 			none_ += 1; | 			none_ += 1; | ||||||
| 			return true; | 			return true; | ||||||
| 		case DriveType::CONSTANT: | 		case DriveType::CONSTANT: | ||||||
| 			constant_.bits().push_back(bit.constant()); | 			constant_.append(RTLIL::Const(bit.constant())); | ||||||
| 			return true; | 			return true; | ||||||
| 		case DriveType::WIRE: | 		case DriveType::WIRE: | ||||||
| 			return wire_.try_append(bit.wire()); | 			return wire_.try_append(bit.wire()); | ||||||
|  | @ -375,7 +374,7 @@ bool DriveChunk::try_append(DriveChunk const &chunk) | ||||||
| 			none_ += chunk.none_; | 			none_ += chunk.none_; | ||||||
| 			return true; | 			return true; | ||||||
| 		case DriveType::CONSTANT: | 		case DriveType::CONSTANT: | ||||||
| 			constant_.bits().insert(constant_.bits().end(), chunk.constant_.begin(), chunk.constant_.end()); | 			constant_.append(chunk.constant_); | ||||||
| 			return true; | 			return true; | ||||||
| 		case DriveType::WIRE: | 		case DriveType::WIRE: | ||||||
| 			return wire_.try_append(chunk.wire()); | 			return wire_.try_append(chunk.wire()); | ||||||
|  |  | ||||||
							
								
								
									
										31
									
								
								kernel/ff.cc
									
										
									
									
									
								
							
							
						
						
									
										31
									
								
								kernel/ff.cc
									
										
									
									
									
								
							|  | @ -287,6 +287,16 @@ FfData FfData::slice(const std::vector<int> &bits) { | ||||||
| 	res.pol_clr = pol_clr; | 	res.pol_clr = pol_clr; | ||||||
| 	res.pol_set = pol_set; | 	res.pol_set = pol_set; | ||||||
| 	res.attributes = attributes; | 	res.attributes = attributes; | ||||||
|  | 	std::optional<Const::Builder> arst_bits; | ||||||
|  | 	if (has_arst) | ||||||
|  | 		arst_bits.emplace(bits.size()); | ||||||
|  | 	std::optional<Const::Builder> srst_bits; | ||||||
|  | 	if (has_srst) | ||||||
|  | 		srst_bits.emplace(bits.size()); | ||||||
|  | 	std::optional<Const::Builder> init_bits; | ||||||
|  | 	if (initvals) | ||||||
|  | 		init_bits.emplace(bits.size()); | ||||||
|  | 
 | ||||||
| 	for (int i : bits) { | 	for (int i : bits) { | ||||||
| 		res.sig_q.append(sig_q[i]); | 		res.sig_q.append(sig_q[i]); | ||||||
| 		if (has_clk || has_gclk) | 		if (has_clk || has_gclk) | ||||||
|  | @ -298,12 +308,19 @@ FfData FfData::slice(const std::vector<int> &bits) { | ||||||
| 			res.sig_set.append(sig_set[i]); | 			res.sig_set.append(sig_set[i]); | ||||||
| 		} | 		} | ||||||
| 		if (has_arst) | 		if (has_arst) | ||||||
| 			res.val_arst.bits().push_back(val_arst[i]); | 			arst_bits->push_back(val_arst[i]); | ||||||
| 		if (has_srst) | 		if (has_srst) | ||||||
| 			res.val_srst.bits().push_back(val_srst[i]); | 			srst_bits->push_back(val_srst[i]); | ||||||
| 		if (initvals) | 		if (initvals) | ||||||
| 			res.val_init.bits().push_back(val_init[i]); | 			init_bits->push_back(val_init[i]); | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	if (has_arst) | ||||||
|  | 		res.val_arst = arst_bits->build(); | ||||||
|  | 	if (has_srst) | ||||||
|  | 		res.val_srst = srst_bits->build(); | ||||||
|  | 	if (initvals) | ||||||
|  | 		res.val_init = init_bits->build(); | ||||||
| 	res.width = GetSize(res.sig_q); | 	res.width = GetSize(res.sig_q); | ||||||
| 	return res; | 	return res; | ||||||
| } | } | ||||||
|  | @ -688,10 +705,10 @@ void FfData::flip_rst_bits(const pool<int> &bits) { | ||||||
| 
 | 
 | ||||||
| 	for (auto bit: bits) { | 	for (auto bit: bits) { | ||||||
| 		if (has_arst) | 		if (has_arst) | ||||||
| 			val_arst.bits()[bit] = invert(val_arst[bit]); | 			val_arst.set(bit, invert(val_arst[bit])); | ||||||
| 		if (has_srst) | 		if (has_srst) | ||||||
| 			val_srst.bits()[bit] = invert(val_srst[bit]); | 			val_srst.set(bit, invert(val_srst[bit])); | ||||||
| 		val_init.bits()[bit] = invert(val_init[bit]); | 		val_init.set(bit, invert(val_init[bit])); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -760,7 +777,7 @@ void FfData::flip_bits(const pool<int> &bits) { | ||||||
| 
 | 
 | ||||||
| 		Const mask = Const(State::S0, width); | 		Const mask = Const(State::S0, width); | ||||||
| 		for (auto bit: bits) | 		for (auto bit: bits) | ||||||
| 			mask.bits()[bit] = State::S1; | 			mask.set(bit, State::S1); | ||||||
| 
 | 
 | ||||||
| 		if (has_clk || has_gclk) | 		if (has_clk || has_gclk) | ||||||
| 			sig_d = module->Xor(NEW_ID, sig_d, mask); | 			sig_d = module->Xor(NEW_ID, sig_d, mask); | ||||||
|  |  | ||||||
|  | @ -74,10 +74,10 @@ struct FfInitVals | ||||||
| 
 | 
 | ||||||
| 	RTLIL::Const operator()(const RTLIL::SigSpec &sig) const | 	RTLIL::Const operator()(const RTLIL::SigSpec &sig) const | ||||||
| 	{ | 	{ | ||||||
| 		RTLIL::Const res; | 		RTLIL::Const::Builder res_bits(GetSize(sig)); | ||||||
| 		for (auto bit : sig) | 		for (auto bit : sig) | ||||||
| 			res.bits().push_back((*this)(bit)); | 			res_bits.push_back((*this)(bit)); | ||||||
| 		return res; | 		return res_bits.build(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void set_init(RTLIL::SigBit bit, RTLIL::State val) | 	void set_init(RTLIL::SigBit bit, RTLIL::State val) | ||||||
|  | @ -93,12 +93,12 @@ struct FfInitVals | ||||||
| 		initbits[mbit] = std::make_pair(val,abit); | 		initbits[mbit] = std::make_pair(val,abit); | ||||||
| 		auto it2 = abit.wire->attributes.find(ID::init); | 		auto it2 = abit.wire->attributes.find(ID::init); | ||||||
| 		if (it2 != abit.wire->attributes.end()) { | 		if (it2 != abit.wire->attributes.end()) { | ||||||
| 			it2->second.bits()[abit.offset] = val; | 			it2->second.set(abit.offset, val); | ||||||
| 			if (it2->second.is_fully_undef()) | 			if (it2->second.is_fully_undef()) | ||||||
| 				abit.wire->attributes.erase(it2); | 				abit.wire->attributes.erase(it2); | ||||||
| 		} else if (val != State::Sx) { | 		} else if (val != State::Sx) { | ||||||
| 			Const cval(State::Sx, GetSize(abit.wire)); | 			Const cval(State::Sx, GetSize(abit.wire)); | ||||||
| 			cval.bits()[abit.offset] = val; | 			cval.set(abit.offset, val); | ||||||
| 			abit.wire->attributes[ID::init] = cval; | 			abit.wire->attributes[ID::init] = cval; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -42,9 +42,9 @@ bool FfMergeHelper::find_output_ff(RTLIL::SigSpec sig, FfData &ff, pool<std::pai | ||||||
| 			ff.sig_d.append(bit); | 			ff.sig_d.append(bit); | ||||||
| 			ff.sig_clr.append(State::Sx); | 			ff.sig_clr.append(State::Sx); | ||||||
| 			ff.sig_set.append(State::Sx); | 			ff.sig_set.append(State::Sx); | ||||||
| 			ff.val_init.bits().push_back(State::Sx); | 			ff.val_init.append(RTLIL::Const(State::Sx)); | ||||||
| 			ff.val_srst.bits().push_back(State::Sx); | 			ff.val_srst.append(RTLIL::Const(State::Sx)); | ||||||
| 			ff.val_arst.bits().push_back(State::Sx); | 			ff.val_arst.append(RTLIL::Const(State::Sx)); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -147,9 +147,9 @@ bool FfMergeHelper::find_output_ff(RTLIL::SigSpec sig, FfData &ff, pool<std::pai | ||||||
| 		ff.sig_q.append(cur_ff.sig_q[idx]); | 		ff.sig_q.append(cur_ff.sig_q[idx]); | ||||||
| 		ff.sig_clr.append(ff.has_sr ? cur_ff.sig_clr[idx] : State::S0); | 		ff.sig_clr.append(ff.has_sr ? cur_ff.sig_clr[idx] : State::S0); | ||||||
| 		ff.sig_set.append(ff.has_sr ? cur_ff.sig_set[idx] : State::S0); | 		ff.sig_set.append(ff.has_sr ? cur_ff.sig_set[idx] : State::S0); | ||||||
| 		ff.val_arst.bits().push_back(ff.has_arst ? cur_ff.val_arst[idx] : State::Sx); | 		ff.val_arst.append(RTLIL::Const(ff.has_arst ? cur_ff.val_arst[idx] : State::Sx)); | ||||||
| 		ff.val_srst.bits().push_back(ff.has_srst ? cur_ff.val_srst[idx] : State::Sx); | 		ff.val_srst.append(RTLIL::Const(ff.has_srst ? cur_ff.val_srst[idx] : State::Sx)); | ||||||
| 		ff.val_init.bits().push_back(cur_ff.val_init[idx]); | 		ff.val_init.append(RTLIL::Const(cur_ff.val_init[idx])); | ||||||
| 		found = true; | 		found = true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -174,9 +174,9 @@ bool FfMergeHelper::find_input_ff(RTLIL::SigSpec sig, FfData &ff, pool<std::pair | ||||||
| 			// These two will be fixed up later.
 | 			// These two will be fixed up later.
 | ||||||
| 			ff.sig_clr.append(State::Sx); | 			ff.sig_clr.append(State::Sx); | ||||||
| 			ff.sig_set.append(State::Sx); | 			ff.sig_set.append(State::Sx); | ||||||
| 			ff.val_init.bits().push_back(bit.data); | 			ff.val_init.append(RTLIL::Const(bit.data)); | ||||||
| 			ff.val_srst.bits().push_back(bit.data); | 			ff.val_srst.append(RTLIL::Const(bit.data)); | ||||||
| 			ff.val_arst.bits().push_back(bit.data); | 			ff.val_arst.append(RTLIL::Const(bit.data)); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -274,9 +274,9 @@ bool FfMergeHelper::find_input_ff(RTLIL::SigSpec sig, FfData &ff, pool<std::pair | ||||||
| 		ff.sig_q.append(cur_ff.sig_q[idx]); | 		ff.sig_q.append(cur_ff.sig_q[idx]); | ||||||
| 		ff.sig_clr.append(ff.has_sr ? cur_ff.sig_clr[idx] : State::S0); | 		ff.sig_clr.append(ff.has_sr ? cur_ff.sig_clr[idx] : State::S0); | ||||||
| 		ff.sig_set.append(ff.has_sr ? cur_ff.sig_set[idx] : State::S0); | 		ff.sig_set.append(ff.has_sr ? cur_ff.sig_set[idx] : State::S0); | ||||||
| 		ff.val_arst.bits().push_back(ff.has_arst ? cur_ff.val_arst[idx] : State::Sx); | 		ff.val_arst.append(RTLIL::Const(ff.has_arst ? cur_ff.val_arst[idx] : State::Sx)); | ||||||
| 		ff.val_srst.bits().push_back(ff.has_srst ? cur_ff.val_srst[idx] : State::Sx); | 		ff.val_srst.append(RTLIL::Const(ff.has_srst ? cur_ff.val_srst[idx] : State::Sx)); | ||||||
| 		ff.val_init.bits().push_back(cur_ff.val_init[idx]); | 		ff.val_init.append(RTLIL::Const(cur_ff.val_init[idx])); | ||||||
| 		found = true; | 		found = true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -168,8 +168,17 @@ struct hash_ops { | ||||||
| 		} else if constexpr (std::is_pointer_v<T>) { | 		} else if constexpr (std::is_pointer_v<T>) { | ||||||
| 			return hash_ops<uintptr_t>::hash_into((uintptr_t) a, h); | 			return hash_ops<uintptr_t>::hash_into((uintptr_t) a, h); | ||||||
| 		} else if constexpr (std::is_same_v<T, std::string>) { | 		} else if constexpr (std::is_same_v<T, std::string>) { | ||||||
| 			for (auto c : a) | 			int size = a.size(); | ||||||
| 				h.hash32(c); | 			int i = 0; | ||||||
|  | 			while (i + 8 < size) { | ||||||
|  | 				uint64_t v; | ||||||
|  | 				memcpy(&v, a.data() + i, 8); | ||||||
|  | 				h.hash64(v); | ||||||
|  | 				i += 8; | ||||||
|  | 			} | ||||||
|  | 			uint64_t v = 0; | ||||||
|  | 			memcpy(&v, a.data() + i, size - i); | ||||||
|  | 			h.hash64(v); | ||||||
| 			return h; | 			return h; | ||||||
| 		} else { | 		} else { | ||||||
| 			return a.hash_into(h); | 			return a.hash_into(h); | ||||||
|  |  | ||||||
|  | @ -262,7 +262,7 @@ struct Macc | ||||||
| 
 | 
 | ||||||
| 	bool eval(RTLIL::Const &result) const | 	bool eval(RTLIL::Const &result) const | ||||||
| 	{ | 	{ | ||||||
| 		for (auto &bit : result.bits()) | 		for (auto bit : result) | ||||||
| 			bit = State::S0; | 			bit = State::S0; | ||||||
| 
 | 
 | ||||||
| 		for (auto &port : terms) | 		for (auto &port : terms) | ||||||
|  |  | ||||||
|  | @ -131,9 +131,6 @@ void Mem::emit() { | ||||||
| 		cell->parameters[ID::WIDTH] = Const(width); | 		cell->parameters[ID::WIDTH] = Const(width); | ||||||
| 		cell->parameters[ID::OFFSET] = Const(start_offset); | 		cell->parameters[ID::OFFSET] = Const(start_offset); | ||||||
| 		cell->parameters[ID::SIZE] = Const(size); | 		cell->parameters[ID::SIZE] = Const(size); | ||||||
| 		Const rd_wide_continuation, rd_clk_enable, rd_clk_polarity, rd_transparency_mask, rd_collision_x_mask; |  | ||||||
| 		Const wr_wide_continuation, wr_clk_enable, wr_clk_polarity, wr_priority_mask; |  | ||||||
| 		Const rd_ce_over_srst, rd_arst_value, rd_srst_value, rd_init_value; |  | ||||||
| 		SigSpec rd_clk, rd_en, rd_addr, rd_data; | 		SigSpec rd_clk, rd_en, rd_addr, rd_data; | ||||||
| 		SigSpec wr_clk, wr_en, wr_addr, wr_data; | 		SigSpec wr_clk, wr_en, wr_addr, wr_data; | ||||||
| 		SigSpec rd_arst, rd_srst; | 		SigSpec rd_arst, rd_srst; | ||||||
|  | @ -147,6 +144,15 @@ void Mem::emit() { | ||||||
| 		for (int i = 0; i < GetSize(wr_ports); i++) | 		for (int i = 0; i < GetSize(wr_ports); i++) | ||||||
| 			for (int j = 0; j < (1 << wr_ports[i].wide_log2); j++) | 			for (int j = 0; j < (1 << wr_ports[i].wide_log2); j++) | ||||||
| 				wr_port_xlat.push_back(i); | 				wr_port_xlat.push_back(i); | ||||||
|  | 		Const::Builder rd_wide_continuation_builder; | ||||||
|  | 		Const::Builder rd_clk_enable_builder; | ||||||
|  | 		Const::Builder rd_clk_polarity_builder; | ||||||
|  | 		Const::Builder rd_transparency_mask_builder; | ||||||
|  | 		Const::Builder rd_collision_x_mask_builder; | ||||||
|  | 		Const::Builder rd_ce_over_srst_builder; | ||||||
|  | 		Const::Builder rd_arst_value_builder; | ||||||
|  | 		Const::Builder rd_srst_value_builder; | ||||||
|  | 		Const::Builder rd_init_value_builder; | ||||||
| 		for (auto &port : rd_ports) { | 		for (auto &port : rd_ports) { | ||||||
| 			for (auto attr: port.attributes) | 			for (auto attr: port.attributes) | ||||||
| 				if (!cell->has_attribute(attr.first)) | 				if (!cell->has_attribute(attr.first)) | ||||||
|  | @ -157,10 +163,10 @@ void Mem::emit() { | ||||||
| 			} | 			} | ||||||
| 			for (int sub = 0; sub < (1 << port.wide_log2); sub++) | 			for (int sub = 0; sub < (1 << port.wide_log2); sub++) | ||||||
| 			{ | 			{ | ||||||
| 				rd_wide_continuation.bits().push_back(State(sub != 0)); | 				rd_wide_continuation_builder.push_back(State(sub != 0)); | ||||||
| 				rd_clk_enable.bits().push_back(State(port.clk_enable)); | 				rd_clk_enable_builder.push_back(State(port.clk_enable)); | ||||||
| 				rd_clk_polarity.bits().push_back(State(port.clk_polarity)); | 				rd_clk_polarity_builder.push_back(State(port.clk_polarity)); | ||||||
| 				rd_ce_over_srst.bits().push_back(State(port.ce_over_srst)); | 				rd_ce_over_srst_builder.push_back(State(port.ce_over_srst)); | ||||||
| 				rd_clk.append(port.clk); | 				rd_clk.append(port.clk); | ||||||
| 				rd_arst.append(port.arst); | 				rd_arst.append(port.arst); | ||||||
| 				rd_srst.append(port.srst); | 				rd_srst.append(port.srst); | ||||||
|  | @ -170,18 +176,27 @@ void Mem::emit() { | ||||||
| 				rd_addr.append(addr); | 				rd_addr.append(addr); | ||||||
| 				log_assert(GetSize(addr) == abits); | 				log_assert(GetSize(addr) == abits); | ||||||
| 				for (auto idx : wr_port_xlat) { | 				for (auto idx : wr_port_xlat) { | ||||||
| 					rd_transparency_mask.bits().push_back(State(bool(port.transparency_mask[idx]))); | 					rd_transparency_mask_builder.push_back(State(bool(port.transparency_mask[idx]))); | ||||||
| 					rd_collision_x_mask.bits().push_back(State(bool(port.collision_x_mask[idx]))); | 					rd_collision_x_mask_builder.push_back(State(bool(port.collision_x_mask[idx]))); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			rd_data.append(port.data); | 			rd_data.append(port.data); | ||||||
| 			for (auto bit : port.arst_value) | 			for (auto bit : port.arst_value) | ||||||
| 				rd_arst_value.bits().push_back(bit); | 				rd_arst_value_builder.push_back(bit); | ||||||
| 			for (auto bit : port.srst_value) | 			for (auto bit : port.srst_value) | ||||||
| 				rd_srst_value.bits().push_back(bit); | 				rd_srst_value_builder.push_back(bit); | ||||||
| 			for (auto bit : port.init_value) | 			for (auto bit : port.init_value) | ||||||
| 				rd_init_value.bits().push_back(bit); | 				rd_init_value_builder.push_back(bit); | ||||||
| 		} | 		} | ||||||
|  | 		Const rd_wide_continuation = rd_wide_continuation_builder.build(); | ||||||
|  | 		Const rd_clk_enable = rd_clk_enable_builder.build(); | ||||||
|  | 		Const rd_clk_polarity = rd_clk_polarity_builder.build(); | ||||||
|  | 		Const rd_transparency_mask = rd_transparency_mask_builder.build(); | ||||||
|  | 		Const rd_collision_x_mask = rd_collision_x_mask_builder.build(); | ||||||
|  | 		Const rd_ce_over_srst = rd_ce_over_srst_builder.build(); | ||||||
|  | 		Const rd_arst_value = rd_arst_value_builder.build(); | ||||||
|  | 		Const rd_srst_value = rd_srst_value_builder.build(); | ||||||
|  | 		Const rd_init_value = rd_init_value_builder.build(); | ||||||
| 		if (rd_ports.empty()) { | 		if (rd_ports.empty()) { | ||||||
| 			rd_wide_continuation = State::S0; | 			rd_wide_continuation = State::S0; | ||||||
| 			rd_clk_enable = State::S0; | 			rd_clk_enable = State::S0; | ||||||
|  | @ -212,6 +227,10 @@ void Mem::emit() { | ||||||
| 		cell->setPort(ID::RD_SRST, rd_srst); | 		cell->setPort(ID::RD_SRST, rd_srst); | ||||||
| 		cell->setPort(ID::RD_ADDR, rd_addr); | 		cell->setPort(ID::RD_ADDR, rd_addr); | ||||||
| 		cell->setPort(ID::RD_DATA, rd_data); | 		cell->setPort(ID::RD_DATA, rd_data); | ||||||
|  | 		Const::Builder wr_wide_continuation_builder; | ||||||
|  | 		Const::Builder wr_clk_enable_builder; | ||||||
|  | 		Const::Builder wr_clk_polarity_builder; | ||||||
|  | 		Const::Builder wr_priority_mask_builder; | ||||||
| 		for (auto &port : wr_ports) { | 		for (auto &port : wr_ports) { | ||||||
| 			for (auto attr: port.attributes) | 			for (auto attr: port.attributes) | ||||||
| 				if (!cell->has_attribute(attr.first)) | 				if (!cell->has_attribute(attr.first)) | ||||||
|  | @ -222,12 +241,12 @@ void Mem::emit() { | ||||||
| 			} | 			} | ||||||
| 			for (int sub = 0; sub < (1 << port.wide_log2); sub++) | 			for (int sub = 0; sub < (1 << port.wide_log2); sub++) | ||||||
| 			{ | 			{ | ||||||
| 				wr_wide_continuation.bits().push_back(State(sub != 0)); | 				wr_wide_continuation_builder.push_back(State(sub != 0)); | ||||||
| 				wr_clk_enable.bits().push_back(State(port.clk_enable)); | 				wr_clk_enable_builder.push_back(State(port.clk_enable)); | ||||||
| 				wr_clk_polarity.bits().push_back(State(port.clk_polarity)); | 				wr_clk_polarity_builder.push_back(State(port.clk_polarity)); | ||||||
| 				wr_clk.append(port.clk); | 				wr_clk.append(port.clk); | ||||||
| 				for (auto idx : wr_port_xlat) | 				for (auto idx : wr_port_xlat) | ||||||
| 					wr_priority_mask.bits().push_back(State(bool(port.priority_mask[idx]))); | 					wr_priority_mask_builder.push_back(State(bool(port.priority_mask[idx]))); | ||||||
| 				SigSpec addr = port.sub_addr(sub); | 				SigSpec addr = port.sub_addr(sub); | ||||||
| 				addr.extend_u0(abits, false); | 				addr.extend_u0(abits, false); | ||||||
| 				wr_addr.append(addr); | 				wr_addr.append(addr); | ||||||
|  | @ -236,6 +255,10 @@ void Mem::emit() { | ||||||
| 			wr_en.append(port.en); | 			wr_en.append(port.en); | ||||||
| 			wr_data.append(port.data); | 			wr_data.append(port.data); | ||||||
| 		} | 		} | ||||||
|  | 		Const wr_wide_continuation = wr_wide_continuation_builder.build(); | ||||||
|  | 		Const wr_clk_enable = wr_clk_enable_builder.build(); | ||||||
|  | 		Const wr_clk_polarity = wr_clk_polarity_builder.build(); | ||||||
|  | 		Const wr_priority_mask = wr_priority_mask_builder.build(); | ||||||
| 		if (wr_ports.empty()) { | 		if (wr_ports.empty()) { | ||||||
| 			wr_wide_continuation = State::S0; | 			wr_wide_continuation = State::S0; | ||||||
| 			wr_clk_enable = State::S0; | 			wr_clk_enable = State::S0; | ||||||
|  | @ -414,7 +437,7 @@ void Mem::coalesce_inits() { | ||||||
| 			if (!init.en.is_fully_ones()) { | 			if (!init.en.is_fully_ones()) { | ||||||
| 				for (int i = 0; i < GetSize(init.data); i++) | 				for (int i = 0; i < GetSize(init.data); i++) | ||||||
| 					if (init.en[i % width] != State::S1) | 					if (init.en[i % width] != State::S1) | ||||||
| 						init.data.bits()[i] = State::Sx; | 						init.data.set(i, State::Sx); | ||||||
| 				init.en = Const(State::S1, width); | 				init.en = Const(State::S1, width); | ||||||
| 			} | 			} | ||||||
| 			continue; | 			continue; | ||||||
|  | @ -427,7 +450,7 @@ void Mem::coalesce_inits() { | ||||||
| 			log_assert(offset + GetSize(init.data) <= GetSize(cdata)); | 			log_assert(offset + GetSize(init.data) <= GetSize(cdata)); | ||||||
| 			for (int i = 0; i < GetSize(init.data); i++) | 			for (int i = 0; i < GetSize(init.data); i++) | ||||||
| 				if (init.en[i % width] == State::S1) | 				if (init.en[i % width] == State::S1) | ||||||
| 					cdata.bits()[i+offset] = init.data[i]; | 					cdata.set(i+offset, init.data[i]); | ||||||
| 			init.removed = true; | 			init.removed = true; | ||||||
| 		} | 		} | ||||||
| 		MemInit new_init; | 		MemInit new_init; | ||||||
|  | @ -446,7 +469,7 @@ Const Mem::get_init_data() const { | ||||||
| 		int offset = (init.addr.as_int() - start_offset) * width; | 		int offset = (init.addr.as_int() - start_offset) * width; | ||||||
| 		for (int i = 0; i < GetSize(init.data); i++) | 		for (int i = 0; i < GetSize(init.data); i++) | ||||||
| 			if (0 <= i+offset && i+offset < GetSize(init_data) && init.en[i % width] == State::S1) | 			if (0 <= i+offset && i+offset < GetSize(init_data) && init.en[i % width] == State::S1) | ||||||
| 				init_data.bits()[i+offset] = init.data[i]; | 				init_data.set(i+offset, init.data[i]); | ||||||
| 	} | 	} | ||||||
| 	return init_data; | 	return init_data; | ||||||
| } | } | ||||||
|  | @ -1700,7 +1723,7 @@ MemContents::MemContents(Mem *mem) : | ||||||
| 				RTLIL::Const previous = (*this)[addr + i]; | 				RTLIL::Const previous = (*this)[addr + i]; | ||||||
| 				for(int j = 0; j < _data_width; j++) | 				for(int j = 0; j < _data_width; j++) | ||||||
| 					if(init.en[j] != State::S1) | 					if(init.en[j] != State::S1) | ||||||
| 						data.bits()[_data_width * i + j] = previous[j]; | 						data.set(_data_width * i + j, previous[j]); | ||||||
| 			} | 			} | ||||||
| 			insert_concatenated(init.addr.as_int(), data); | 			insert_concatenated(init.addr.as_int(), data); | ||||||
| 		} | 		} | ||||||
|  | @ -1846,7 +1869,7 @@ std::map<MemContents::addr_t, RTLIL::Const>::iterator MemContents::_reserve_rang | ||||||
| 		// we have two different ranges touching at either end, we need to merge them
 | 		// we have two different ranges touching at either end, we need to merge them
 | ||||||
| 		auto upper_end = _range_end(upper_it); | 		auto upper_end = _range_end(upper_it); | ||||||
| 		// make range bigger (maybe reserve here instead of resize?)
 | 		// make range bigger (maybe reserve here instead of resize?)
 | ||||||
| 		lower_it->second.bits().resize(_range_offset(lower_it, upper_end), State::Sx); | 		lower_it->second.resize(_range_offset(lower_it, upper_end), State::Sx); | ||||||
| 		// copy only the data beyond our range
 | 		// copy only the data beyond our range
 | ||||||
| 		std::copy(_range_data(upper_it, end_addr), _range_data(upper_it, upper_end), _range_data(lower_it, end_addr)); | 		std::copy(_range_data(upper_it, end_addr), _range_data(upper_it, upper_end), _range_data(lower_it, end_addr)); | ||||||
| 		// keep lower_it, but delete upper_it
 | 		// keep lower_it, but delete upper_it
 | ||||||
|  | @ -1854,16 +1877,16 @@ std::map<MemContents::addr_t, RTLIL::Const>::iterator MemContents::_reserve_rang | ||||||
| 		return lower_it; | 		return lower_it; | ||||||
| 	} else if (lower_touch) { | 	} else if (lower_touch) { | ||||||
| 		// we have a range to the left, just make it bigger and delete any other that may exist.
 | 		// we have a range to the left, just make it bigger and delete any other that may exist.
 | ||||||
| 		lower_it->second.bits().resize(_range_offset(lower_it, end_addr), State::Sx); | 		lower_it->second.resize(_range_offset(lower_it, end_addr), State::Sx); | ||||||
| 		// keep lower_it and upper_it
 | 		// keep lower_it and upper_it
 | ||||||
| 		_values.erase(std::next(lower_it), upper_it); | 		_values.erase(std::next(lower_it), upper_it); | ||||||
| 		return lower_it; | 		return lower_it; | ||||||
| 	} else if (upper_touch) { | 	} else if (upper_touch) { | ||||||
| 		// we have a range to the right, we need to expand it
 | 		// we have a range to the right, we need to expand it
 | ||||||
| 		// since we need to erase and reinsert to a new address, steal the data
 | 		// since we need to erase and reinsert to a new address, steal the data
 | ||||||
| 		RTLIL::Const data = std::move(upper_it->second); |  | ||||||
| 		// note that begin_addr is not in upper_it, otherwise the whole range covered check would have tripped
 | 		// note that begin_addr is not in upper_it, otherwise the whole range covered check would have tripped
 | ||||||
| 		data.bits().insert(data.bits().begin(), (_range_begin(upper_it) - begin_addr) * _data_width, State::Sx); | 		RTLIL::Const data(State::Sx, (_range_begin(upper_it) - begin_addr) * _data_width); | ||||||
|  | 		data.append(std::move(upper_it->second)); | ||||||
| 		// delete lower_it and upper_it, then reinsert
 | 		// delete lower_it and upper_it, then reinsert
 | ||||||
| 		_values.erase(lower_it, std::next(upper_it)); | 		_values.erase(lower_it, std::next(upper_it)); | ||||||
| 		return _values.emplace(begin_addr, std::move(data)).first; | 		return _values.emplace(begin_addr, std::move(data)).first; | ||||||
|  | @ -1886,7 +1909,7 @@ void MemContents::insert_concatenated(addr_t addr, RTLIL::Const const &values) { | ||||||
| 	std::fill(to_begin + values.size(), to_begin + words * _data_width, State::S0); | 	std::fill(to_begin + values.size(), to_begin + words * _data_width, State::S0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::vector<State>::iterator MemContents::_range_write(std::vector<State>::iterator it, RTLIL::Const const &word) { | RTLIL::Const::iterator MemContents::_range_write(RTLIL::Const::iterator it, RTLIL::Const const &word) { | ||||||
| 	auto from_end = word.size() <= _data_width ? word.end() : word.begin() + _data_width; | 	auto from_end = word.size() <= _data_width ? word.end() : word.begin() + _data_width; | ||||||
| 	auto to_end = std::copy(word.begin(), from_end, it); | 	auto to_end = std::copy(word.begin(), from_end, it); | ||||||
| 	auto it_next = std::next(it, _data_width); | 	auto it_next = std::next(it, _data_width); | ||||||
|  |  | ||||||
|  | @ -255,11 +255,13 @@ private: | ||||||
| 	// return the offset the addr would have in the range at `it`
 | 	// return the offset the addr would have in the range at `it`
 | ||||||
| 	size_t _range_offset(std::map<addr_t, RTLIL::Const>::iterator it, addr_t addr) const { return (addr - it->first) * _data_width; } | 	size_t _range_offset(std::map<addr_t, RTLIL::Const>::iterator it, addr_t addr) const { return (addr - it->first) * _data_width; } | ||||||
| 	// assuming _range_contains(it, addr), return an iterator pointing to the data at addr
 | 	// assuming _range_contains(it, addr), return an iterator pointing to the data at addr
 | ||||||
| 	std::vector<State>::iterator _range_data(std::map<addr_t, RTLIL::Const>::iterator it, addr_t addr) { return it->second.bits().begin() + _range_offset(it, addr); } | 	RTLIL::Const::iterator _range_data(std::map<addr_t, RTLIL::Const>::iterator it, addr_t addr) { | ||||||
|  | 		return RTLIL::Const::iterator(it->second, _range_offset(it, addr)); | ||||||
|  | 	} | ||||||
| 	// internal version of reserve_range that returns an iterator to the range
 | 	// internal version of reserve_range that returns an iterator to the range
 | ||||||
| 	std::map<addr_t, RTLIL::Const>::iterator _reserve_range(addr_t begin_addr, addr_t end_addr); | 	std::map<addr_t, RTLIL::Const>::iterator _reserve_range(addr_t begin_addr, addr_t end_addr); | ||||||
| 	// write a single word at addr, return iterator to next word
 | 	// write a single word at addr, return iterator to next word
 | ||||||
| 	std::vector<State>::iterator _range_write(std::vector<State>::iterator it, RTLIL::Const const &data); | 	RTLIL::Const::iterator _range_write(RTLIL::Const::iterator it, RTLIL::Const const &data); | ||||||
| public: | public: | ||||||
| 	class range { | 	class range { | ||||||
| 		int _data_width; | 		int _data_width; | ||||||
|  |  | ||||||
							
								
								
									
										195
									
								
								kernel/rtlil.cc
									
										
									
									
									
								
							
							
						
						
									
										195
									
								
								kernel/rtlil.cc
									
										
									
									
									
								
							|  | @ -240,12 +240,22 @@ const pool<IdString> &RTLIL::builtin_ff_cell_types() { | ||||||
| 
 | 
 | ||||||
| #define check(condition) log_assert(condition && "malformed Const union") | #define check(condition) log_assert(condition && "malformed Const union") | ||||||
| 
 | 
 | ||||||
| Const::bitvectype& Const::get_bits() const { | const Const::bitvectype& Const::get_bits() const { | ||||||
| 	check(is_bits()); | 	check(is_bits()); | ||||||
| 	return *get_if_bits(); | 	return *get_if_bits(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::string& Const::get_str() const { | const std::string& Const::get_str() const { | ||||||
|  | 	check(is_str()); | ||||||
|  | 	return *get_if_str(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Const::bitvectype& Const::get_bits() { | ||||||
|  | 	check(is_bits()); | ||||||
|  | 	return *get_if_bits(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::string& Const::get_str() { | ||||||
| 	check(is_str()); | 	check(is_str()); | ||||||
| 	return *get_if_str(); | 	return *get_if_str(); | ||||||
| } | } | ||||||
|  | @ -257,9 +267,34 @@ RTLIL::Const::Const(const std::string &str) | ||||||
| 	tag = backing_tag::string; | 	tag = backing_tag::string; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | RTLIL::Const::Const(long long val) // default width 32
 | ||||||
|  | { | ||||||
|  | 	flags = RTLIL::CONST_FLAG_NONE; | ||||||
|  | 	char bytes[] = { | ||||||
|  | 		(char)(val >> 24), (char)(val >> 16), (char)(val >> 8), (char)val | ||||||
|  | 	}; | ||||||
|  | 	new ((void*)&str_) std::string(bytes, 4); | ||||||
|  | 	tag = backing_tag::string; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| RTLIL::Const::Const(long long val, int width) | RTLIL::Const::Const(long long val, int width) | ||||||
| { | { | ||||||
| 	flags = RTLIL::CONST_FLAG_NONE; | 	flags = RTLIL::CONST_FLAG_NONE; | ||||||
|  | 	if ((width & 7) == 0) { | ||||||
|  | 		new ((void*)&str_) std::string(); | ||||||
|  | 		tag = backing_tag::string; | ||||||
|  | 		std::string& str = get_str(); | ||||||
|  | 		int bytes = width >> 3; | ||||||
|  | 		signed char sign_byte = val < 0 ? -1 : 0; | ||||||
|  | 		str.resize(bytes, sign_byte); | ||||||
|  | 		bytes = std::min<int>(bytes, sizeof(val)); | ||||||
|  | 		for (int i = 0; i < bytes; i++) { | ||||||
|  | 			str[str.size() - 1 - i] = val; | ||||||
|  | 			val = val >> 8; | ||||||
|  | 		} | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	new ((void*)&bits_) bitvectype(); | 	new ((void*)&bits_) bitvectype(); | ||||||
| 	tag = backing_tag::bits; | 	tag = backing_tag::bits; | ||||||
| 	bitvectype& bv = get_bits(); | 	bitvectype& bv = get_bits(); | ||||||
|  | @ -363,6 +398,11 @@ bool RTLIL::Const::operator<(const RTLIL::Const &other) const | ||||||
| 
 | 
 | ||||||
| bool RTLIL::Const::operator ==(const RTLIL::Const &other) const | bool RTLIL::Const::operator ==(const RTLIL::Const &other) const | ||||||
| { | { | ||||||
|  | 	if (is_str() && other.is_str()) | ||||||
|  | 		return get_str() == other.get_str(); | ||||||
|  | 	if (is_bits() && other.is_bits()) | ||||||
|  | 		return get_bits() == other.get_bits(); | ||||||
|  | 
 | ||||||
| 	if (size() != other.size()) | 	if (size() != other.size()) | ||||||
| 		return false; | 		return false; | ||||||
| 
 | 
 | ||||||
|  | @ -378,9 +418,9 @@ bool RTLIL::Const::operator !=(const RTLIL::Const &other) const | ||||||
| 	return !(*this == other); | 	return !(*this == other); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::vector<RTLIL::State>& RTLIL::Const::bits() | std::vector<RTLIL::State>& RTLIL::Const::bits_internal() | ||||||
| { | { | ||||||
| 	bitvectorize(); | 	bitvectorize_internal(); | ||||||
| 	return get_bits(); | 	return get_bits(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -394,8 +434,14 @@ std::vector<RTLIL::State> RTLIL::Const::to_bits() const | ||||||
| 
 | 
 | ||||||
| bool RTLIL::Const::as_bool() const | bool RTLIL::Const::as_bool() const | ||||||
| { | { | ||||||
| 	bitvectorize(); | 	if (is_str()) { | ||||||
| 	bitvectype& bv = get_bits(); | 		for (char ch : get_str()) | ||||||
|  | 			if (ch != 0) | ||||||
|  | 				return true; | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	const bitvectype& bv = get_bits(); | ||||||
| 	for (size_t i = 0; i < bv.size(); i++) | 	for (size_t i = 0; i < bv.size(); i++) | ||||||
| 		if (bv[i] == State::S1) | 		if (bv[i] == State::S1) | ||||||
| 			return true; | 			return true; | ||||||
|  | @ -404,15 +450,24 @@ bool RTLIL::Const::as_bool() const | ||||||
| 
 | 
 | ||||||
| int RTLIL::Const::as_int(bool is_signed) const | int RTLIL::Const::as_int(bool is_signed) const | ||||||
| { | { | ||||||
| 	bitvectorize(); |  | ||||||
| 	bitvectype& bv = get_bits(); |  | ||||||
| 	int32_t ret = 0; | 	int32_t ret = 0; | ||||||
| 	for (size_t i = 0; i < bv.size() && i < 32; i++) | 	if (is_str()) { | ||||||
|  | 		const std::string& s = get_str(); | ||||||
|  | 		int size = GetSize(s); | ||||||
|  | 		for (int i = std::min(4, size); i > 0; i--) | ||||||
|  | 			ret |= static_cast<unsigned char>(s[size - i]) << ((i - 1) * 8); | ||||||
|  | 		if (is_signed && size > 0 && size < 4 && (s[0] & 0x80)) | ||||||
|  | 			ret |= -1 << size*8; | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	const bitvectype& bv = get_bits(); | ||||||
|  | 	int significant_bits = std::min(GetSize(bv), 32); | ||||||
|  | 	for (int i = 0; i < significant_bits; i++) | ||||||
| 		if (bv[i] == State::S1) | 		if (bv[i] == State::S1) | ||||||
| 			ret |= 1 << i; | 			ret |= 1 << i; | ||||||
| 	if (is_signed && bv.back() == State::S1) | 	if (is_signed && significant_bits > 0 && significant_bits < 32 && bv.back() == State::S1 ) | ||||||
| 		for (size_t i = bv.size(); i < 32; i++) | 		ret |= -1 << significant_bits; | ||||||
| 			ret |= 1 << i; |  | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -432,7 +487,7 @@ bool RTLIL::Const::convertible_to_int(bool is_signed) const | ||||||
| 	if (size == 32) { | 	if (size == 32) { | ||||||
| 		if (is_signed) | 		if (is_signed) | ||||||
| 			return true; | 			return true; | ||||||
| 		return get_bits().at(31) != State::S1; | 		return back() != State::S1; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return false; | 	return false; | ||||||
|  | @ -453,7 +508,7 @@ int RTLIL::Const::as_int_saturating(bool is_signed) const | ||||||
| 
 | 
 | ||||||
| 		const auto min_size = get_min_size(is_signed); | 		const auto min_size = get_min_size(is_signed); | ||||||
| 		log_assert(min_size > 0); | 		log_assert(min_size > 0); | ||||||
| 		const auto neg = get_bits().at(min_size - 1); | 		const auto neg = (*this)[min_size - 1]; | ||||||
| 		return neg ? std::numeric_limits<int>::min() : std::numeric_limits<int>::max(); | 		return neg ? std::numeric_limits<int>::min() : std::numeric_limits<int>::max(); | ||||||
| 	} | 	} | ||||||
| 	return as_int(is_signed); | 	return as_int(is_signed); | ||||||
|  | @ -486,7 +541,7 @@ int RTLIL::Const::get_min_size(bool is_signed) const | ||||||
| void RTLIL::Const::compress(bool is_signed) | void RTLIL::Const::compress(bool is_signed) | ||||||
| { | { | ||||||
| 	auto idx = get_min_size(is_signed); | 	auto idx = get_min_size(is_signed); | ||||||
| 	bits().erase(bits().begin() + idx, bits().end()); | 	resize(idx, RTLIL::State::S0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::optional<int> RTLIL::Const::as_int_compress(bool is_signed) const | std::optional<int> RTLIL::Const::as_int_compress(bool is_signed) const | ||||||
|  | @ -496,18 +551,17 @@ std::optional<int> RTLIL::Const::as_int_compress(bool is_signed) const | ||||||
| 
 | 
 | ||||||
| std::string RTLIL::Const::as_string(const char* any) const | std::string RTLIL::Const::as_string(const char* any) const | ||||||
| { | { | ||||||
| 	bitvectorize(); | 	int sz = size(); | ||||||
| 	bitvectype& bv = get_bits(); |  | ||||||
| 	std::string ret; | 	std::string ret; | ||||||
| 	ret.reserve(bv.size()); | 	ret.reserve(sz); | ||||||
| 	for (size_t i = bv.size(); i > 0; i--) | 	for (int i = sz - 1; i >= 0; --i) | ||||||
| 		switch (bv[i-1]) { | 		switch ((*this)[i]) { | ||||||
| 			case S0: ret += "0"; break; | 			case S0: ret.push_back('0'); break; | ||||||
| 			case S1: ret += "1"; break; | 			case S1: ret.push_back('1'); break; | ||||||
| 			case Sx: ret += "x"; break; | 			case Sx: ret.push_back('x'); break; | ||||||
| 			case Sz: ret += "z"; break; | 			case Sz: ret.push_back('z'); break; | ||||||
| 			case Sa: ret += any; break; | 			case Sa: ret += any; break; | ||||||
| 			case Sm: ret += "m"; break; | 			case Sm: ret.push_back('m'); break; | ||||||
| 		} | 		} | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
|  | @ -534,8 +588,7 @@ std::string RTLIL::Const::decode_string() const | ||||||
| 	if (auto str = get_if_str()) | 	if (auto str = get_if_str()) | ||||||
| 		return *str; | 		return *str; | ||||||
| 
 | 
 | ||||||
| 	bitvectorize(); | 	const bitvectype& bv = get_bits(); | ||||||
| 	bitvectype& bv = get_bits(); |  | ||||||
| 	const int n = GetSize(bv); | 	const int n = GetSize(bv); | ||||||
| 	const int n_over_8 = n / 8; | 	const int n_over_8 = n / 8; | ||||||
| 	std::string s; | 	std::string s; | ||||||
|  | @ -583,7 +636,7 @@ bool RTLIL::Const::empty() const { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RTLIL::Const::bitvectorize() const { | void RTLIL::Const::bitvectorize_internal() { | ||||||
| 	if (tag == backing_tag::bits) | 	if (tag == backing_tag::bits) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
|  | @ -609,26 +662,33 @@ void RTLIL::Const::bitvectorize() const { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RTLIL::Const::append(const RTLIL::Const &other) { | void RTLIL::Const::append(const RTLIL::Const &other) { | ||||||
| 	bitvectorize(); | 	bitvectorize_internal(); | ||||||
| 	bitvectype& bv = get_bits(); | 	bitvectype& bv = get_bits(); | ||||||
| 	bv.insert(bv.end(), other.begin(), other.end()); | 	bv.insert(bv.end(), other.begin(), other.end()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| RTLIL::State RTLIL::Const::const_iterator::operator*() const { | RTLIL::State RTLIL::Const::const_iterator::operator*() const { | ||||||
| 	if (auto bv = parent.get_if_bits()) | 	if (auto bv = parent->get_if_bits()) | ||||||
| 		return (*bv)[idx]; | 		return (*bv)[idx]; | ||||||
| 
 | 
 | ||||||
| 	int char_idx = parent.get_str().size() - idx / 8 - 1; | 	int char_idx = parent->get_str().size() - idx / 8 - 1; | ||||||
| 	bool bit = (parent.get_str()[char_idx] & (1 << (idx % 8))); | 	bool bit = (parent->get_str()[char_idx] & (1 << (idx % 8))); | ||||||
| 	return bit ? State::S1 : State::S0; | 	return bit ? State::S1 : State::S0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool RTLIL::Const::is_fully_zero() const | bool RTLIL::Const::is_fully_zero() const | ||||||
| { | { | ||||||
| 	bitvectorize(); |  | ||||||
| 	bitvectype& bv = get_bits(); |  | ||||||
| 	cover("kernel.rtlil.const.is_fully_zero"); | 	cover("kernel.rtlil.const.is_fully_zero"); | ||||||
| 
 | 
 | ||||||
|  | 	if (auto str = get_if_str()) { | ||||||
|  | 		for (char ch : *str) | ||||||
|  | 			if (ch != 0) | ||||||
|  | 				return false; | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	const bitvectype& bv = get_bits(); | ||||||
|  | 
 | ||||||
| 	for (const auto &bit : bv) | 	for (const auto &bit : bv) | ||||||
| 		if (bit != RTLIL::State::S0) | 		if (bit != RTLIL::State::S0) | ||||||
| 			return false; | 			return false; | ||||||
|  | @ -638,10 +698,16 @@ bool RTLIL::Const::is_fully_zero() const | ||||||
| 
 | 
 | ||||||
| bool RTLIL::Const::is_fully_ones() const | bool RTLIL::Const::is_fully_ones() const | ||||||
| { | { | ||||||
| 	bitvectorize(); |  | ||||||
| 	bitvectype& bv = get_bits(); |  | ||||||
| 	cover("kernel.rtlil.const.is_fully_ones"); | 	cover("kernel.rtlil.const.is_fully_ones"); | ||||||
| 
 | 
 | ||||||
|  | 	if (auto str = get_if_str()) { | ||||||
|  | 		for (char ch : *str) | ||||||
|  | 			if (ch != (char)0xff) | ||||||
|  | 				return false; | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	const bitvectype& bv = get_bits(); | ||||||
| 	for (const auto &bit : bv) | 	for (const auto &bit : bv) | ||||||
| 		if (bit != RTLIL::State::S1) | 		if (bit != RTLIL::State::S1) | ||||||
| 			return false; | 			return false; | ||||||
|  | @ -653,9 +719,10 @@ bool RTLIL::Const::is_fully_def() const | ||||||
| { | { | ||||||
| 	cover("kernel.rtlil.const.is_fully_def"); | 	cover("kernel.rtlil.const.is_fully_def"); | ||||||
| 
 | 
 | ||||||
| 	bitvectorize(); | 	if (is_str()) | ||||||
| 	bitvectype& bv = get_bits(); | 		return true; | ||||||
| 
 | 
 | ||||||
|  | 	const bitvectype& bv = get_bits(); | ||||||
| 	for (const auto &bit : bv) | 	for (const auto &bit : bv) | ||||||
| 		if (bit != RTLIL::State::S0 && bit != RTLIL::State::S1) | 		if (bit != RTLIL::State::S0 && bit != RTLIL::State::S1) | ||||||
| 			return false; | 			return false; | ||||||
|  | @ -667,9 +734,10 @@ bool RTLIL::Const::is_fully_undef() const | ||||||
| { | { | ||||||
| 	cover("kernel.rtlil.const.is_fully_undef"); | 	cover("kernel.rtlil.const.is_fully_undef"); | ||||||
| 
 | 
 | ||||||
| 	bitvectorize(); | 	if (auto str = get_if_str()) | ||||||
| 	bitvectype& bv = get_bits(); | 		return str->empty(); | ||||||
| 
 | 
 | ||||||
|  | 	const bitvectype& bv = get_bits(); | ||||||
| 	for (const auto &bit : bv) | 	for (const auto &bit : bv) | ||||||
| 		if (bit != RTLIL::State::Sx && bit != RTLIL::State::Sz) | 		if (bit != RTLIL::State::Sx && bit != RTLIL::State::Sz) | ||||||
| 			return false; | 			return false; | ||||||
|  | @ -681,9 +749,10 @@ bool RTLIL::Const::is_fully_undef_x_only() const | ||||||
| { | { | ||||||
| 	cover("kernel.rtlil.const.is_fully_undef_x_only"); | 	cover("kernel.rtlil.const.is_fully_undef_x_only"); | ||||||
| 
 | 
 | ||||||
| 	bitvectorize(); | 	if (auto str = get_if_str()) | ||||||
| 	bitvectype& bv = get_bits(); | 		return str->empty(); | ||||||
| 
 | 
 | ||||||
|  | 	const bitvectype& bv = get_bits(); | ||||||
| 	for (const auto &bit : bv) | 	for (const auto &bit : bv) | ||||||
| 		if (bit != RTLIL::State::Sx) | 		if (bit != RTLIL::State::Sx) | ||||||
| 			return false; | 			return false; | ||||||
|  | @ -695,12 +764,10 @@ bool RTLIL::Const::is_onehot(int *pos) const | ||||||
| { | { | ||||||
| 	cover("kernel.rtlil.const.is_onehot"); | 	cover("kernel.rtlil.const.is_onehot"); | ||||||
| 
 | 
 | ||||||
| 	bitvectorize(); |  | ||||||
| 	bitvectype& bv = get_bits(); |  | ||||||
| 
 |  | ||||||
| 	bool found = false; | 	bool found = false; | ||||||
| 	for (int i = 0; i < GetSize(*this); i++) { | 	int size = GetSize(*this); | ||||||
| 		auto &bit = bv[i]; | 	for (int i = 0; i < size; i++) { | ||||||
|  | 		State bit = (*this)[i]; | ||||||
| 		if (bit != RTLIL::State::S0 && bit != RTLIL::State::S1) | 		if (bit != RTLIL::State::S0 && bit != RTLIL::State::S1) | ||||||
| 			return false; | 			return false; | ||||||
| 		if (bit == RTLIL::State::S1) { | 		if (bit == RTLIL::State::S1) { | ||||||
|  | @ -714,6 +781,40 @@ bool RTLIL::Const::is_onehot(int *pos) const | ||||||
| 	return found; | 	return found; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | Hasher RTLIL::Const::hash_into(Hasher h) const | ||||||
|  | { | ||||||
|  | 	if (auto str = get_if_str()) | ||||||
|  | 		return hashlib::hash_ops<std::string>::hash_into(*str, h); | ||||||
|  | 
 | ||||||
|  | 	// If the bits are all 0/1, hash packed bits using the string hash.
 | ||||||
|  | 	// Otherwise hash the leading packed bits with the rest of the bits individually.
 | ||||||
|  | 	const bitvectype &bv = get_bits(); | ||||||
|  | 	int size = GetSize(bv); | ||||||
|  | 	std::string packed; | ||||||
|  | 	int packed_size = (size + 7) >> 3; | ||||||
|  | 	packed.resize(packed_size, 0); | ||||||
|  | 	for (int bi = 0; bi < packed_size; ++bi) { | ||||||
|  | 		char ch = 0; | ||||||
|  | 		int end = std::min((bi + 1)*8, size); | ||||||
|  | 		for (int i = bi*8; i < end; ++i) { | ||||||
|  | 			RTLIL::State b = bv[i]; | ||||||
|  | 			if (b > RTLIL::State::S1) { | ||||||
|  | 				// Hash the packed bits we've seen so far, plus the remaining bits.
 | ||||||
|  | 				h = hashlib::hash_ops<std::string>::hash_into(packed, h); | ||||||
|  | 				h = hashlib::hash_ops<char>::hash_into(ch, h); | ||||||
|  | 				for (; i < size; ++i) { | ||||||
|  | 					h = hashlib::hash_ops<RTLIL::State>::hash_into(bv[i], h); | ||||||
|  | 				} | ||||||
|  | 				h.eat(size); | ||||||
|  | 				return h; | ||||||
|  | 			} | ||||||
|  | 			ch |= static_cast<int>(b) << (i & 7); | ||||||
|  | 		} | ||||||
|  | 		packed[packed_size - 1 - bi] = ch; | ||||||
|  | 	} | ||||||
|  | 	return hashlib::hash_ops<std::string>::hash_into(packed, h); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| RTLIL::Const RTLIL::Const::extract(int offset, int len, RTLIL::State padding) const { | RTLIL::Const RTLIL::Const::extract(int offset, int len, RTLIL::State padding) const { | ||||||
| 	bitvectype ret_bv; | 	bitvectype ret_bv; | ||||||
| 	ret_bv.reserve(len); | 	ret_bv.reserve(len); | ||||||
|  |  | ||||||
							
								
								
									
										136
									
								
								kernel/rtlil.h
									
										
									
									
									
								
							
							
						
						
									
										136
									
								
								kernel/rtlil.h
									
										
									
									
									
								
							|  | @ -831,38 +831,61 @@ private: | ||||||
| 	using bitvectype = std::vector<RTLIL::State>; | 	using bitvectype = std::vector<RTLIL::State>; | ||||||
| 	enum class backing_tag: bool { bits, string }; | 	enum class backing_tag: bool { bits, string }; | ||||||
| 	// Do not access the union or tag even in Const methods unless necessary
 | 	// Do not access the union or tag even in Const methods unless necessary
 | ||||||
| 	mutable backing_tag tag; | 	backing_tag tag; | ||||||
| 	union { | 	union { | ||||||
| 		mutable bitvectype bits_; | 		bitvectype bits_; | ||||||
| 		mutable std::string str_; | 		std::string str_; | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	// Use these private utilities instead
 | 	// Use these private utilities instead
 | ||||||
| 	bool is_bits() const { return tag == backing_tag::bits; } | 	bool is_bits() const { return tag == backing_tag::bits; } | ||||||
| 	bool is_str() const { return tag == backing_tag::string; } | 	bool is_str() const { return tag == backing_tag::string; } | ||||||
| 
 | 
 | ||||||
| 	bitvectype* get_if_bits() const { return is_bits() ? &bits_ : NULL; } | 	bitvectype* get_if_bits() { return is_bits() ? &bits_ : NULL; } | ||||||
| 	std::string* get_if_str() const { return is_str() ? &str_ : NULL; } | 	std::string* get_if_str() { return is_str() ? &str_ : NULL; } | ||||||
|  | 	const bitvectype* get_if_bits() const { return is_bits() ? &bits_ : NULL; } | ||||||
|  | 	const std::string* get_if_str() const { return is_str() ? &str_ : NULL; } | ||||||
|  | 
 | ||||||
|  | 	bitvectype& get_bits(); | ||||||
|  | 	std::string& get_str(); | ||||||
|  | 	const bitvectype& get_bits() const; | ||||||
|  | 	const std::string& get_str() const; | ||||||
|  | 	std::vector<RTLIL::State>& bits_internal(); | ||||||
|  | 	void bitvectorize_internal(); | ||||||
| 
 | 
 | ||||||
| 	bitvectype& get_bits() const; |  | ||||||
| 	std::string& get_str() const; |  | ||||||
| public: | public: | ||||||
| 	Const() : flags(RTLIL::CONST_FLAG_NONE), tag(backing_tag::bits), bits_(std::vector<RTLIL::State>()) {} | 	Const() : flags(RTLIL::CONST_FLAG_NONE), tag(backing_tag::bits), bits_(std::vector<RTLIL::State>()) {} | ||||||
| 	Const(const std::string &str); | 	Const(const std::string &str); | ||||||
| 	Const(long long val, int width = 32); | 	Const(long long val); // default width is 32
 | ||||||
|  | 	Const(long long val, int width); | ||||||
| 	Const(RTLIL::State bit, int width = 1); | 	Const(RTLIL::State bit, int width = 1); | ||||||
| 	Const(const std::vector<RTLIL::State> &bits) : flags(RTLIL::CONST_FLAG_NONE), tag(backing_tag::bits), bits_(bits) {} | 	Const(std::vector<RTLIL::State> bits) : flags(RTLIL::CONST_FLAG_NONE), tag(backing_tag::bits), bits_(std::move(bits)) {} | ||||||
| 	Const(const std::vector<bool> &bits); | 	Const(const std::vector<bool> &bits); | ||||||
| 	Const(const RTLIL::Const &other); | 	Const(const RTLIL::Const &other); | ||||||
| 	Const(RTLIL::Const &&other); | 	Const(RTLIL::Const &&other); | ||||||
| 	RTLIL::Const &operator =(const RTLIL::Const &other); | 	RTLIL::Const &operator =(const RTLIL::Const &other); | ||||||
| 	~Const(); | 	~Const(); | ||||||
| 
 | 
 | ||||||
|  | 	struct Builder | ||||||
|  | 	{ | ||||||
|  | 		Builder() {} | ||||||
|  | 		Builder(int expected_width) { bits.reserve(expected_width); } | ||||||
|  | 		void push_back(RTLIL::State b) { bits.push_back(b); } | ||||||
|  | 		int size() const { return static_cast<int>(bits.size()); } | ||||||
|  | 		Const build() { return Const(std::move(bits)); } | ||||||
|  | 	private: | ||||||
|  | 		std::vector<RTLIL::State> bits; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
| 	bool operator <(const RTLIL::Const &other) const; | 	bool operator <(const RTLIL::Const &other) const; | ||||||
| 	bool operator ==(const RTLIL::Const &other) const; | 	bool operator ==(const RTLIL::Const &other) const; | ||||||
| 	bool operator !=(const RTLIL::Const &other) const; | 	bool operator !=(const RTLIL::Const &other) const; | ||||||
| 
 | 
 | ||||||
| 	std::vector<RTLIL::State>& bits(); | 	[[deprecated("Don't use direct access to the internal std::vector<State>, that's an implementation detail.")]] | ||||||
|  | 	std::vector<RTLIL::State>& bits() { return bits_internal(); } | ||||||
|  | 	[[deprecated("Don't call bitvectorize() directly, it's an implementation detail.")]] | ||||||
|  | 	void bitvectorize() const { const_cast<Const*>(this)->bitvectorize_internal(); } | ||||||
|  | 
 | ||||||
| 	bool as_bool() const; | 	bool as_bool() const; | ||||||
| 
 | 
 | ||||||
| 	// Convert the constant value to a C++ int.
 | 	// Convert the constant value to a C++ int.
 | ||||||
|  | @ -891,37 +914,42 @@ public: | ||||||
| 	std::string decode_string() const; | 	std::string decode_string() const; | ||||||
| 	int size() const; | 	int size() const; | ||||||
| 	bool empty() const; | 	bool empty() const; | ||||||
| 	void bitvectorize() const; |  | ||||||
| 
 | 
 | ||||||
| 	void append(const RTLIL::Const &other); | 	void append(const RTLIL::Const &other); | ||||||
|  | 	void set(int i, RTLIL::State state) { | ||||||
|  | 		bits_internal()[i] = state; | ||||||
|  | 	} | ||||||
|  | 	void resize(int size, RTLIL::State fill) { | ||||||
|  | 		bits_internal().resize(size, fill); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	class const_iterator { | 	class const_iterator { | ||||||
| 	private: | 	private: | ||||||
| 		const Const& parent; | 		const Const* parent; | ||||||
| 		size_t idx; | 		size_t idx; | ||||||
| 
 | 
 | ||||||
| 	public: | 	public: | ||||||
| 		using iterator_category = std::input_iterator_tag; | 		using iterator_category = std::bidirectional_iterator_tag; | ||||||
| 		using value_type = State; | 		using value_type = State; | ||||||
| 		using difference_type = std::ptrdiff_t; | 		using difference_type = std::ptrdiff_t; | ||||||
| 		using pointer = const State*; | 		using pointer = const State*; | ||||||
| 		using reference = const State&; | 		using reference = const State&; | ||||||
| 
 | 
 | ||||||
| 		const_iterator(const Const& c, size_t i) : parent(c), idx(i) {} | 		const_iterator(const Const& c, size_t i) : parent(&c), idx(i) {} | ||||||
| 
 | 
 | ||||||
| 		State operator*() const; | 		State operator*() const; | ||||||
| 
 | 
 | ||||||
| 		const_iterator& operator++() { ++idx; return *this; } | 		const_iterator& operator++() { ++idx; return *this; } | ||||||
| 		const_iterator& operator--() { --idx; return *this; } | 		const_iterator& operator--() { --idx; return *this; } | ||||||
| 		const_iterator& operator++(int) { ++idx; return *this; } | 		const_iterator operator++(int) { const_iterator result(*this); ++idx; return result; } | ||||||
| 		const_iterator& operator--(int) { --idx; return *this; } | 		const_iterator operator--(int) { const_iterator result(*this); --idx; return result; } | ||||||
| 		const_iterator& operator+=(int i) { idx += i; return *this; } | 		const_iterator& operator+=(int i) { idx += i; return *this; } | ||||||
| 
 | 
 | ||||||
| 		const_iterator operator+(int add) { | 		const_iterator operator+(int add) { | ||||||
| 			return const_iterator(parent, idx + add); | 			return const_iterator(*parent, idx + add); | ||||||
| 		} | 		} | ||||||
| 		const_iterator operator-(int sub) { | 		const_iterator operator-(int sub) { | ||||||
| 			return const_iterator(parent, idx - sub); | 			return const_iterator(*parent, idx - sub); | ||||||
| 		} | 		} | ||||||
| 		int operator-(const const_iterator& other) { | 		int operator-(const const_iterator& other) { | ||||||
| 			return idx - other.idx; | 			return idx - other.idx; | ||||||
|  | @ -936,12 +964,69 @@ public: | ||||||
| 		} | 		} | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
|  | 	class iterator { | ||||||
|  | 	private: | ||||||
|  | 		Const* parent; | ||||||
|  | 		size_t idx; | ||||||
|  | 
 | ||||||
|  | 	public: | ||||||
|  | 		class proxy { | ||||||
|  | 		private: | ||||||
|  | 			Const* parent; | ||||||
|  | 			size_t idx; | ||||||
|  | 		public: | ||||||
|  | 			proxy(Const* parent, size_t idx) : parent(parent), idx(idx) {} | ||||||
|  | 			operator State() const { return (*parent)[idx]; } | ||||||
|  | 			proxy& operator=(State s) { parent->set(idx, s); return *this; } | ||||||
|  | 			proxy& operator=(const proxy& other) { parent->set(idx, (*other.parent)[other.idx]); return *this; } | ||||||
|  | 		}; | ||||||
|  | 
 | ||||||
|  | 		using iterator_category = std::bidirectional_iterator_tag; | ||||||
|  | 		using value_type = State; | ||||||
|  | 		using difference_type = std::ptrdiff_t; | ||||||
|  | 		using pointer = proxy*; | ||||||
|  | 		using reference = proxy; | ||||||
|  | 
 | ||||||
|  | 		iterator(Const& c, size_t i) : parent(&c), idx(i) {} | ||||||
|  | 
 | ||||||
|  | 		proxy operator*() const { return proxy(parent, idx); } | ||||||
|  | 		iterator& operator++() { ++idx; return *this; } | ||||||
|  | 		iterator& operator--() { --idx; return *this; } | ||||||
|  | 		iterator operator++(int) { iterator result(*this); ++idx; return result; } | ||||||
|  | 		iterator operator--(int) { iterator result(*this); --idx; return result; } | ||||||
|  | 		iterator& operator+=(int i) { idx += i; return *this; } | ||||||
|  | 
 | ||||||
|  | 		iterator operator+(int add) { | ||||||
|  | 			return iterator(*parent, idx + add); | ||||||
|  | 		} | ||||||
|  | 		iterator operator-(int sub) { | ||||||
|  | 			return iterator(*parent, idx - sub); | ||||||
|  | 		} | ||||||
|  | 		int operator-(const iterator& other) { | ||||||
|  | 			return idx - other.idx; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		bool operator==(const iterator& other) const { | ||||||
|  | 			return idx == other.idx; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		bool operator!=(const iterator& other) const { | ||||||
|  | 			return !(*this == other); | ||||||
|  | 		} | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
| 	const_iterator begin() const { | 	const_iterator begin() const { | ||||||
| 		return const_iterator(*this, 0); | 		return const_iterator(*this, 0); | ||||||
| 	} | 	} | ||||||
| 	const_iterator end() const { | 	const_iterator end() const { | ||||||
| 		return const_iterator(*this, size()); | 		return const_iterator(*this, size()); | ||||||
| 	} | 	} | ||||||
|  | 	iterator begin() { | ||||||
|  | 		return iterator(*this, 0); | ||||||
|  | 	} | ||||||
|  | 	iterator end() { | ||||||
|  | 		return iterator(*this, size()); | ||||||
|  | 	} | ||||||
| 	State back() const { | 	State back() const { | ||||||
| 		return *(end() - 1); | 		return *(end() - 1); | ||||||
| 	} | 	} | ||||||
|  | @ -973,20 +1058,14 @@ public: | ||||||
| 	std::optional<int> as_int_compress(bool is_signed) const; | 	std::optional<int> as_int_compress(bool is_signed) const; | ||||||
| 
 | 
 | ||||||
| 	void extu(int width) { | 	void extu(int width) { | ||||||
| 		bits().resize(width, RTLIL::State::S0); | 		resize(width, RTLIL::State::S0); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void exts(int width) { | 	void exts(int width) { | ||||||
| 		bitvectype& bv = bits(); | 		resize(width, empty() ? RTLIL::State::Sx : back()); | ||||||
| 		bv.resize(width, bv.empty() ? RTLIL::State::Sx : bv.back()); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	[[nodiscard]] Hasher hash_into(Hasher h) const { | 	[[nodiscard]] Hasher hash_into(Hasher h) const; | ||||||
| 		h.eat(size()); |  | ||||||
| 		for (auto b : *this) |  | ||||||
| 			h.eat(b); |  | ||||||
| 		return h; |  | ||||||
| 	} |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct RTLIL::AttrObject | struct RTLIL::AttrObject | ||||||
|  | @ -1041,7 +1120,8 @@ struct RTLIL::SigChunk | ||||||
| 	SigChunk(RTLIL::Wire *wire) : wire(wire), width(GetSize(wire)), offset(0) {} | 	SigChunk(RTLIL::Wire *wire) : wire(wire), width(GetSize(wire)), offset(0) {} | ||||||
| 	SigChunk(RTLIL::Wire *wire, int offset, int width = 1) : wire(wire), width(width), offset(offset) {} | 	SigChunk(RTLIL::Wire *wire, int offset, int width = 1) : wire(wire), width(width), offset(offset) {} | ||||||
| 	SigChunk(const std::string &str) : SigChunk(RTLIL::Const(str)) {} | 	SigChunk(const std::string &str) : SigChunk(RTLIL::Const(str)) {} | ||||||
| 	SigChunk(int val, int width = 32) : SigChunk(RTLIL::Const(val, width)) {} | 	SigChunk(int val) /*default width 32*/ : SigChunk(RTLIL::Const(val)) {} | ||||||
|  | 	SigChunk(int val, int width) : SigChunk(RTLIL::Const(val, width)) {} | ||||||
| 	SigChunk(RTLIL::State bit, int width = 1) : SigChunk(RTLIL::Const(bit, width)) {} | 	SigChunk(RTLIL::State bit, int width = 1) : SigChunk(RTLIL::Const(bit, width)) {} | ||||||
| 	SigChunk(const RTLIL::SigBit &bit); | 	SigChunk(const RTLIL::SigBit &bit); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -214,18 +214,19 @@ bool mp_int_to_const(mp_int *a, Const &b, bool is_signed) | ||||||
| 	buf.resize(mp_unsigned_bin_size(a)); | 	buf.resize(mp_unsigned_bin_size(a)); | ||||||
| 	mp_to_unsigned_bin(a, buf.data()); | 	mp_to_unsigned_bin(a, buf.data()); | ||||||
| 
 | 
 | ||||||
| 	b.bits().reserve(mp_count_bits(a) + is_signed); | 	Const::Builder b_bits(mp_count_bits(a) + is_signed); | ||||||
| 	for (int i = 0; i < mp_count_bits(a);) { | 	for (int i = 0; i < mp_count_bits(a);) { | ||||||
| 		for (int j = 0; j < 8 && i < mp_count_bits(a); j++, i++) { | 		for (int j = 0; j < 8 && i < mp_count_bits(a); j++, i++) { | ||||||
| 			bool bv = ((buf.back() & (1 << j)) != 0) ^ negative; | 			bool bv = ((buf.back() & (1 << j)) != 0) ^ negative; | ||||||
| 			b.bits().push_back(bv ? RTLIL::S1 : RTLIL::S0); | 			b_bits.push_back(bv ? RTLIL::S1 : RTLIL::S0); | ||||||
| 		} | 		} | ||||||
| 		buf.pop_back(); | 		buf.pop_back(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (is_signed) { | 	if (is_signed) { | ||||||
| 		b.bits().push_back(negative ? RTLIL::S1 : RTLIL::S0); | 		b_bits.push_back(negative ? RTLIL::S1 : RTLIL::S0); | ||||||
| 	} | 	} | ||||||
|  | 	b = b_bits.build(); | ||||||
| 
 | 
 | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -185,7 +185,6 @@ RTLIL::Const ReadWitness::get_bits(int t, int bits_offset, int width) const | ||||||
| 	const std::string &bits = steps[t].bits; | 	const std::string &bits = steps[t].bits; | ||||||
| 
 | 
 | ||||||
| 	RTLIL::Const result(State::Sa, width); | 	RTLIL::Const result(State::Sa, width); | ||||||
| 	result.bits().reserve(width); |  | ||||||
| 
 | 
 | ||||||
| 	int read_begin = GetSize(bits) - 1 - bits_offset; | 	int read_begin = GetSize(bits) - 1 - bits_offset; | ||||||
| 	int read_end = max(-1, read_begin - width); | 	int read_end = max(-1, read_begin - width); | ||||||
|  | @ -200,7 +199,7 @@ RTLIL::Const ReadWitness::get_bits(int t, int bits_offset, int width) const | ||||||
| 			default: | 			default: | ||||||
| 				log_abort(); | 				log_abort(); | ||||||
| 		} | 		} | ||||||
| 		result.bits()[j] = bit; | 		result.set(j, bit); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return result; | 	return result; | ||||||
|  |  | ||||||
|  | @ -405,7 +405,11 @@ struct BugpointPass : public Pass { | ||||||
| 								for (auto it2 = sy->mem_write_actions.begin(); it2 != sy->mem_write_actions.end(); ++it2) { | 								for (auto it2 = sy->mem_write_actions.begin(); it2 != sy->mem_write_actions.end(); ++it2) { | ||||||
| 									auto &mask = it2->priority_mask; | 									auto &mask = it2->priority_mask; | ||||||
| 									if (GetSize(mask) > i) { | 									if (GetSize(mask) > i) { | ||||||
| 										mask.bits().erase(mask.bits().begin() + i); | 										RTLIL::Const::Builder new_mask_builder(GetSize(mask) - 1); | ||||||
|  | 										for (int k = 0; k < GetSize(mask); k++) | ||||||
|  | 											if (k != i) | ||||||
|  | 												new_mask_builder.push_back(mask[k]); | ||||||
|  | 										mask = new_mask_builder.build(); | ||||||
| 									} | 									} | ||||||
| 								} | 								} | ||||||
| 								return design_copy; | 								return design_copy; | ||||||
|  |  | ||||||
|  | @ -158,11 +158,11 @@ struct CleanZeroWidthPass : public Pass { | ||||||
| 							continue; | 							continue; | ||||||
| 						if (GetSize(memwr.address) == 0) | 						if (GetSize(memwr.address) == 0) | ||||||
| 							memwr.address = State::S0; | 							memwr.address = State::S0; | ||||||
| 						Const priority_mask; | 						RTLIL::Const::Builder new_mask_bits(swizzle.size()); | ||||||
| 						for (auto x : swizzle) { | 						for (auto x : swizzle) { | ||||||
| 							priority_mask.bits().push_back(memwr.priority_mask[x]); | 							new_mask_bits.push_back(memwr.priority_mask[x]); | ||||||
| 						} | 						} | ||||||
| 						memwr.priority_mask = priority_mask; | 						memwr.priority_mask = new_mask_bits.build(); | ||||||
| 						swizzle.push_back(i); | 						swizzle.push_back(i); | ||||||
| 						new_memwr_actions.push_back(memwr); | 						new_memwr_actions.push_back(memwr); | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
|  | @ -884,8 +884,10 @@ struct DftTagWorker { | ||||||
| 	{ | 	{ | ||||||
| 		if (sig_a.is_fully_const()) { | 		if (sig_a.is_fully_const()) { | ||||||
| 			auto const_val = sig_a.as_const(); | 			auto const_val = sig_a.as_const(); | ||||||
| 			for (State& bit : const_val.bits()) | 			for (auto bit : const_val) { | ||||||
| 				bit = bit == State::S0 ? State::S1 : bit == State::S1 ? State::S0 : bit; | 				State b = bit; | ||||||
|  | 				bit = b == State::S0 ? State::S1 : b == State::S1 ? State::S0 : b; | ||||||
|  | 			} | ||||||
| 			return const_val; | 			return const_val; | ||||||
| 		} | 		} | ||||||
| 		return module->Not(name, sig_a); | 		return module->Not(name, sig_a); | ||||||
|  |  | ||||||
|  | @ -243,7 +243,7 @@ struct SetundefPass : public Pass { | ||||||
| 			{ | 			{ | ||||||
| 				for (auto *cell : module->selected_cells()) { | 				for (auto *cell : module->selected_cells()) { | ||||||
| 					for (auto ¶meter : cell->parameters) { | 					for (auto ¶meter : cell->parameters) { | ||||||
| 						for (auto &bit : parameter.second.bits()) { | 						for (auto bit : parameter.second) { | ||||||
| 							if (bit > RTLIL::State::S1) | 							if (bit > RTLIL::State::S1) | ||||||
| 								bit = worker.next_bit(); | 								bit = worker.next_bit(); | ||||||
| 						} | 						} | ||||||
|  | @ -390,12 +390,12 @@ struct SetundefPass : public Pass { | ||||||
| 					for (auto wire : initwires) | 					for (auto wire : initwires) | ||||||
| 					{ | 					{ | ||||||
| 						Const &initval = wire->attributes[ID::init]; | 						Const &initval = wire->attributes[ID::init]; | ||||||
| 						initval.bits().resize(GetSize(wire), State::Sx); | 						initval.resize(GetSize(wire), State::Sx); | ||||||
| 
 | 
 | ||||||
| 						for (int i = 0; i < GetSize(wire); i++) { | 						for (int i = 0; i < GetSize(wire); i++) { | ||||||
| 							SigBit bit = sigmap(SigBit(wire, i)); | 							SigBit bit = sigmap(SigBit(wire, i)); | ||||||
| 							if (initval[i] == State::Sx && ffbits.count(bit)) { | 							if (initval[i] == State::Sx && ffbits.count(bit)) { | ||||||
| 								initval.bits()[i] = worker.next_bit(); | 								initval.set(i, worker.next_bit()); | ||||||
| 								ffbits.erase(bit); | 								ffbits.erase(bit); | ||||||
| 							} | 							} | ||||||
| 						} | 						} | ||||||
|  | @ -421,7 +421,7 @@ struct SetundefPass : public Pass { | ||||||
| 								continue; | 								continue; | ||||||
| 
 | 
 | ||||||
| 							Const &initval = wire->attributes[ID::init]; | 							Const &initval = wire->attributes[ID::init]; | ||||||
| 							initval.bits().resize(GetSize(wire), State::Sx); | 							initval.resize(GetSize(wire), State::Sx); | ||||||
| 
 | 
 | ||||||
| 							if (initval.is_fully_undef()) { | 							if (initval.is_fully_undef()) { | ||||||
| 								wire->attributes.erase(ID::init); | 								wire->attributes.erase(ID::init); | ||||||
|  |  | ||||||
|  | @ -75,10 +75,11 @@ struct SplitnetsWorker | ||||||
| 
 | 
 | ||||||
| 		it = wire->attributes.find(ID::init); | 		it = wire->attributes.find(ID::init); | ||||||
| 		if (it != wire->attributes.end()) { | 		if (it != wire->attributes.end()) { | ||||||
| 			Const old_init = it->second, new_init; | 			Const old_init = it->second; | ||||||
|  | 			RTLIL::Const::Builder new_init_bits_builder(width); | ||||||
| 			for (int i = offset; i < offset+width; i++) | 			for (int i = offset; i < offset+width; i++) | ||||||
| 				new_init.bits().push_back(i < GetSize(old_init) ? old_init.at(i) : State::Sx); | 				new_init_bits_builder.push_back(i < GetSize(old_init) ? old_init.at(i) : State::Sx); | ||||||
| 			new_wire->attributes.emplace(ID::init, new_init); | 			new_wire->attributes.emplace(ID::init, new_init_bits_builder.build()); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		std::vector<RTLIL::SigBit> sigvec = RTLIL::SigSpec(new_wire).to_sigbit_vector(); | 		std::vector<RTLIL::SigBit> sigvec = RTLIL::SigSpec(new_wire).to_sigbit_vector(); | ||||||
|  |  | ||||||
|  | @ -828,9 +828,9 @@ struct XpropWorker | ||||||
| 			auto init_q_is_1 = init_q; | 			auto init_q_is_1 = init_q; | ||||||
| 			auto init_q_is_x = init_q; | 			auto init_q_is_x = init_q; | ||||||
| 
 | 
 | ||||||
| 			for (auto &bit : init_q_is_1.bits()) | 			for (auto bit : init_q_is_1) | ||||||
| 				bit = bit == State::S1 ? State::S1 : State::S0; | 				bit = bit == State::S1 ? State::S1 : State::S0; | ||||||
| 			for (auto &bit : init_q_is_x.bits()) | 			for (auto bit : init_q_is_x) | ||||||
| 				bit = bit == State::Sx ? State::S1 : State::S0; | 				bit = bit == State::Sx ? State::S1 : State::S0; | ||||||
| 
 | 
 | ||||||
| 			initvals.remove_init(sig_q); | 			initvals.remove_init(sig_q); | ||||||
|  | @ -865,14 +865,14 @@ struct XpropWorker | ||||||
| 					auto init_q_is_x = init_q; | 					auto init_q_is_x = init_q; | ||||||
| 
 | 
 | ||||||
| 					if (ff.is_anyinit) { | 					if (ff.is_anyinit) { | ||||||
| 						for (auto &bit : init_q_is_1.bits()) | 						for (auto bit : init_q_is_1) | ||||||
| 							bit = State::Sx; | 							bit = State::Sx; | ||||||
| 						for (auto &bit : init_q_is_x.bits()) | 						for (auto bit : init_q_is_x) | ||||||
| 							bit = State::S0; | 							bit = State::S0; | ||||||
| 					} else { | 					} else { | ||||||
| 						for (auto &bit : init_q_is_1.bits()) | 						for (auto bit : init_q_is_1) | ||||||
| 							bit = bit == State::S1 ? State::S1 : State::S0; | 							bit = bit == State::S1 ? State::S1 : State::S0; | ||||||
| 						for (auto &bit : init_q_is_x.bits()) | 						for (auto bit : init_q_is_x) | ||||||
| 							bit = bit == State::Sx ? State::S1 : State::S0; | 							bit = bit == State::Sx ? State::S1 : State::S0; | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -171,7 +171,7 @@ undef_bit_in_next_state: | ||||||
| 			if (tr.ctrl_in.at(it.second) == State::S1 && exclusive_ctrls.count(it.first) != 0) | 			if (tr.ctrl_in.at(it.second) == State::S1 && exclusive_ctrls.count(it.first) != 0) | ||||||
| 				for (auto &dc_bit : exclusive_ctrls.at(it.first)) | 				for (auto &dc_bit : exclusive_ctrls.at(it.first)) | ||||||
| 					if (ctrl_in_bit_indices.count(dc_bit)) | 					if (ctrl_in_bit_indices.count(dc_bit)) | ||||||
| 						tr.ctrl_in.bits().at(ctrl_in_bit_indices.at(dc_bit)) = RTLIL::State::Sa; | 						tr.ctrl_in.set(ctrl_in_bit_indices.at(dc_bit), RTLIL::State::Sa); | ||||||
| 
 | 
 | ||||||
| 		RTLIL::Const log_state_in = RTLIL::Const(RTLIL::State::Sx, fsm_data.state_bits); | 		RTLIL::Const log_state_in = RTLIL::Const(RTLIL::State::Sx, fsm_data.state_bits); | ||||||
| 		if (state_in >= 0) | 		if (state_in >= 0) | ||||||
|  |  | ||||||
|  | @ -176,7 +176,7 @@ static void map_fsm(RTLIL::Cell *fsm_cell, RTLIL::Module *module) | ||||||
| 		state_dff->type = ID($adff); | 		state_dff->type = ID($adff); | ||||||
| 		state_dff->parameters[ID::ARST_POLARITY] = fsm_cell->parameters[ID::ARST_POLARITY]; | 		state_dff->parameters[ID::ARST_POLARITY] = fsm_cell->parameters[ID::ARST_POLARITY]; | ||||||
| 		state_dff->parameters[ID::ARST_VALUE] = fsm_data.state_table[fsm_data.reset_state]; | 		state_dff->parameters[ID::ARST_VALUE] = fsm_data.state_table[fsm_data.reset_state]; | ||||||
| 		for (auto &bit : state_dff->parameters[ID::ARST_VALUE].bits()) | 		for (auto bit : state_dff->parameters[ID::ARST_VALUE]) | ||||||
| 			if (bit != RTLIL::State::S1) | 			if (bit != RTLIL::State::S1) | ||||||
| 				bit = RTLIL::State::S0; | 				bit = RTLIL::State::S0; | ||||||
| 		state_dff->setPort(ID::ARST, fsm_cell->getPort(ID::ARST)); | 		state_dff->setPort(ID::ARST, fsm_cell->getPort(ID::ARST)); | ||||||
|  |  | ||||||
|  | @ -169,13 +169,16 @@ struct FsmOpt | ||||||
| 
 | 
 | ||||||
| 				for (auto tr : fsm_data.transition_table) | 				for (auto tr : fsm_data.transition_table) | ||||||
| 				{ | 				{ | ||||||
| 					RTLIL::State &si = tr.ctrl_in.bits()[i]; | 					RTLIL::State si = tr.ctrl_in[i]; | ||||||
| 					RTLIL::State &sj = tr.ctrl_in.bits()[j]; | 					RTLIL::State sj = tr.ctrl_in[j]; | ||||||
| 
 | 
 | ||||||
| 					if (si > RTLIL::State::S1) | 					if (si > RTLIL::State::S1) { | ||||||
| 						si = sj; | 						si = sj; | ||||||
| 					else if (sj > RTLIL::State::S1) | 						tr.ctrl_in.set(i, si); | ||||||
|  | 					} else if (sj > RTLIL::State::S1) { | ||||||
| 						sj = si; | 						sj = si; | ||||||
|  | 						tr.ctrl_in.set(j, sj); | ||||||
|  | 					} | ||||||
| 
 | 
 | ||||||
| 					if (si == sj) { | 					if (si == sj) { | ||||||
| 						RTLIL::SigSpec tmp(tr.ctrl_in); | 						RTLIL::SigSpec tmp(tr.ctrl_in); | ||||||
|  | @ -207,8 +210,8 @@ struct FsmOpt | ||||||
| 
 | 
 | ||||||
| 				for (auto tr : fsm_data.transition_table) | 				for (auto tr : fsm_data.transition_table) | ||||||
| 				{ | 				{ | ||||||
| 					RTLIL::State &si = tr.ctrl_in.bits()[i]; | 					RTLIL::State si = tr.ctrl_in[i]; | ||||||
| 					RTLIL::State &sj = tr.ctrl_out.bits()[j]; | 					RTLIL::State sj = tr.ctrl_out[j]; | ||||||
| 
 | 
 | ||||||
| 					if (si > RTLIL::State::S1 || si == sj) { | 					if (si > RTLIL::State::S1 || si == sj) { | ||||||
| 						RTLIL::SigSpec tmp(tr.ctrl_in); | 						RTLIL::SigSpec tmp(tr.ctrl_in); | ||||||
|  | @ -240,14 +243,14 @@ struct FsmOpt | ||||||
| 			RTLIL::Const other_pattern = pattern; | 			RTLIL::Const other_pattern = pattern; | ||||||
| 
 | 
 | ||||||
| 			if (pattern[bit] == RTLIL::State::S1) | 			if (pattern[bit] == RTLIL::State::S1) | ||||||
| 				other_pattern.bits()[bit] = RTLIL::State::S0; | 				other_pattern.set(bit, RTLIL::State::S0); | ||||||
| 			else | 			else | ||||||
| 				other_pattern.bits()[bit] = RTLIL::State::S1; | 				other_pattern.set(bit, RTLIL::State::S1); | ||||||
| 
 | 
 | ||||||
| 			if (set.count(other_pattern) > 0) { | 			if (set.count(other_pattern) > 0) { | ||||||
| 				log("  Merging pattern %s and %s from group (%d %d %s).\n", log_signal(pattern), log_signal(other_pattern), | 				log("  Merging pattern %s and %s from group (%d %d %s).\n", log_signal(pattern), log_signal(other_pattern), | ||||||
| 						tr.state_in, tr.state_out, log_signal(tr.ctrl_out)); | 						tr.state_in, tr.state_out, log_signal(tr.ctrl_out)); | ||||||
| 				other_pattern.bits()[bit] = RTLIL::State::Sa; | 				other_pattern.set(bit, RTLIL::State::Sa); | ||||||
| 				new_set.insert(other_pattern); | 				new_set.insert(other_pattern); | ||||||
| 				did_something = true; | 				did_something = true; | ||||||
| 				continue; | 				continue; | ||||||
|  |  | ||||||
|  | @ -106,7 +106,7 @@ static void fsm_recode(RTLIL::Cell *cell, RTLIL::Module *module, FILE *fm_set_fs | ||||||
| 
 | 
 | ||||||
| 		if (encoding == "one-hot") { | 		if (encoding == "one-hot") { | ||||||
| 			new_code = RTLIL::Const(RTLIL::State::Sa, fsm_data.state_bits); | 			new_code = RTLIL::Const(RTLIL::State::Sa, fsm_data.state_bits); | ||||||
| 			new_code.bits()[state_idx] = RTLIL::State::S1; | 			new_code.set(state_idx, RTLIL::State::S1); | ||||||
| 		} else | 		} else | ||||||
| 		if (encoding == "binary") { | 		if (encoding == "binary") { | ||||||
| 			new_code = RTLIL::Const(state_idx, fsm_data.state_bits); | 			new_code = RTLIL::Const(state_idx, fsm_data.state_bits); | ||||||
|  |  | ||||||
|  | @ -45,35 +45,27 @@ struct FsmData | ||||||
| 		cell->parameters[ID::STATE_NUM] = RTLIL::Const(state_table.size()); | 		cell->parameters[ID::STATE_NUM] = RTLIL::Const(state_table.size()); | ||||||
| 		cell->parameters[ID::STATE_NUM_LOG2] = RTLIL::Const(state_num_log2); | 		cell->parameters[ID::STATE_NUM_LOG2] = RTLIL::Const(state_num_log2); | ||||||
| 		cell->parameters[ID::STATE_RST] = RTLIL::Const(reset_state); | 		cell->parameters[ID::STATE_RST] = RTLIL::Const(reset_state); | ||||||
| 		cell->parameters[ID::STATE_TABLE] = RTLIL::Const(); | 		RTLIL::Const cell_state_table; | ||||||
| 
 | 		for (const RTLIL::Const &c : state_table) | ||||||
| 		for (int i = 0; i < int(state_table.size()); i++) { | 			cell_state_table.append(c); | ||||||
| 			std::vector<RTLIL::State> &bits_table = cell->parameters[ID::STATE_TABLE].bits(); | 		cell->parameters[ID::STATE_TABLE] = std::move(cell_state_table); | ||||||
| 			std::vector<RTLIL::State> &bits_state = state_table[i].bits(); |  | ||||||
| 			bits_table.insert(bits_table.end(), bits_state.begin(), bits_state.end()); |  | ||||||
| 		} |  | ||||||
| 
 | 
 | ||||||
| 		cell->parameters[ID::TRANS_NUM] = RTLIL::Const(transition_table.size()); | 		cell->parameters[ID::TRANS_NUM] = RTLIL::Const(transition_table.size()); | ||||||
| 		cell->parameters[ID::TRANS_TABLE] = RTLIL::Const(); | 		RTLIL::Const cell_trans_table; | ||||||
| 		for (int i = 0; i < int(transition_table.size()); i++) | 		for (int i = 0; i < int(transition_table.size()); i++) | ||||||
| 		{ | 		{ | ||||||
| 			std::vector<RTLIL::State> &bits_table = cell->parameters[ID::TRANS_TABLE].bits(); |  | ||||||
| 			transition_t &tr = transition_table[i]; | 			transition_t &tr = transition_table[i]; | ||||||
| 
 | 
 | ||||||
| 			RTLIL::Const const_state_in = RTLIL::Const(tr.state_in, state_num_log2); | 			RTLIL::Const const_state_in = RTLIL::Const(tr.state_in, state_num_log2); | ||||||
| 			RTLIL::Const const_state_out = RTLIL::Const(tr.state_out, state_num_log2); | 			RTLIL::Const const_state_out = RTLIL::Const(tr.state_out, state_num_log2); | ||||||
| 			std::vector<RTLIL::State> &bits_state_in = const_state_in.bits(); |  | ||||||
| 			std::vector<RTLIL::State> &bits_state_out = const_state_out.bits(); |  | ||||||
| 
 |  | ||||||
| 			std::vector<RTLIL::State> &bits_ctrl_in = tr.ctrl_in.bits(); |  | ||||||
| 			std::vector<RTLIL::State> &bits_ctrl_out = tr.ctrl_out.bits(); |  | ||||||
| 
 | 
 | ||||||
| 			// append lsb first
 | 			// append lsb first
 | ||||||
| 			bits_table.insert(bits_table.end(), bits_ctrl_out.begin(), bits_ctrl_out.end()); | 			cell_trans_table.append(tr.ctrl_out); | ||||||
| 			bits_table.insert(bits_table.end(), bits_state_out.begin(), bits_state_out.end()); | 			cell_trans_table.append(const_state_out); | ||||||
| 			bits_table.insert(bits_table.end(), bits_ctrl_in.begin(), bits_ctrl_in.end()); | 			cell_trans_table.append(tr.ctrl_in); | ||||||
| 			bits_table.insert(bits_table.end(), bits_state_in.begin(), bits_state_in.end()); | 			cell_trans_table.append(const_state_in); | ||||||
| 		} | 		} | ||||||
|  | 		cell->parameters[ID::TRANS_TABLE] = std::move(cell_trans_table); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void copy_from_cell(RTLIL::Cell *cell) | 	void copy_from_cell(RTLIL::Cell *cell) | ||||||
|  | @ -95,25 +87,18 @@ struct FsmData | ||||||
| 		const RTLIL::Const &trans_table = cell->parameters[ID::TRANS_TABLE]; | 		const RTLIL::Const &trans_table = cell->parameters[ID::TRANS_TABLE]; | ||||||
| 
 | 
 | ||||||
| 		for (int i = 0; i < state_num; i++) { | 		for (int i = 0; i < state_num; i++) { | ||||||
| 			RTLIL::Const state_code; | 			int off_begin = i*state_bits; | ||||||
| 			int off_begin = i*state_bits, off_end = off_begin + state_bits; | 			RTLIL::Const state_code = state_table.extract(off_begin, state_bits); | ||||||
| 			state_code.bits().insert(state_code.bits().begin(), state_table.begin()+off_begin, state_table.begin()+off_end); |  | ||||||
| 			this->state_table.push_back(state_code); | 			this->state_table.push_back(state_code); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		for (int i = 0; i < trans_num; i++) | 		for (int i = 0; i < trans_num; i++) | ||||||
| 		{ | 		{ | ||||||
| 			auto off_ctrl_out = trans_table.begin() + i*(num_inputs+num_outputs+2*state_num_log2); | 			int base_offset = i*(num_inputs+num_outputs+2*state_num_log2); | ||||||
| 			auto off_state_out = off_ctrl_out + num_outputs; | 			RTLIL::Const ctrl_out = trans_table.extract(base_offset, num_outputs); | ||||||
| 			auto off_ctrl_in = off_state_out + state_num_log2; | 			RTLIL::Const state_out = trans_table.extract(base_offset + num_outputs, state_num_log2); | ||||||
| 			auto off_state_in = off_ctrl_in + num_inputs; | 			RTLIL::Const ctrl_in = trans_table.extract(base_offset + num_outputs + state_num_log2, num_inputs); | ||||||
| 			auto off_end = off_state_in + state_num_log2; | 			RTLIL::Const state_in = trans_table.extract(base_offset + num_outputs + state_num_log2 + num_inputs, state_num_log2); | ||||||
| 
 |  | ||||||
| 			RTLIL::Const state_in, state_out, ctrl_in, ctrl_out; |  | ||||||
| 			ctrl_out.bits().insert(ctrl_out.bits().begin(), off_ctrl_out, off_state_out); |  | ||||||
| 			state_out.bits().insert(state_out.bits().begin(), off_state_out, off_ctrl_in); |  | ||||||
| 			ctrl_in.bits().insert(ctrl_in.bits().begin(), off_ctrl_in, off_state_in); |  | ||||||
| 			state_in.bits().insert(state_in.bits().begin(), off_state_in, off_end); |  | ||||||
| 
 | 
 | ||||||
| 			transition_t tr; | 			transition_t tr; | ||||||
| 			tr.state_in = state_in.as_int(); | 			tr.state_in = state_in.as_int(); | ||||||
|  |  | ||||||
|  | @ -79,7 +79,7 @@ struct SubmodWorker | ||||||
| 				flag_wire(c.wire, create, set_int_used, set_ext_driven, set_ext_used); | 				flag_wire(c.wire, create, set_int_used, set_ext_driven, set_ext_used); | ||||||
| 				if (set_int_driven) | 				if (set_int_driven) | ||||||
| 					for (int i = c.offset; i < c.offset+c.width; i++) { | 					for (int i = c.offset; i < c.offset+c.width; i++) { | ||||||
| 						wire_flags.at(c.wire).is_int_driven.bits()[i] = State::S1; | 						wire_flags.at(c.wire).is_int_driven.set(i, State::S1); | ||||||
| 						flag_found_something = true; | 						flag_found_something = true; | ||||||
| 					} | 					} | ||||||
| 			} | 			} | ||||||
|  | @ -185,8 +185,8 @@ struct SubmodWorker | ||||||
| 					auto it = sig[i].wire->attributes.find(ID::init); | 					auto it = sig[i].wire->attributes.find(ID::init); | ||||||
| 					if (it != sig[i].wire->attributes.end()) { | 					if (it != sig[i].wire->attributes.end()) { | ||||||
| 						auto jt = new_wire->attributes.insert(std::make_pair(ID::init, Const(State::Sx, GetSize(sig)))).first; | 						auto jt = new_wire->attributes.insert(std::make_pair(ID::init, Const(State::Sx, GetSize(sig)))).first; | ||||||
| 						jt->second.bits()[i] = it->second[sig[i].offset]; | 						jt->second.set(i, it->second[sig[i].offset]); | ||||||
| 						it->second.bits()[sig[i].offset] = State::Sx; | 						it->second.set(sig[i].offset, State::Sx); | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | @ -848,9 +848,9 @@ grow_read_ports:; | ||||||
| 		for (int i = 0; i < mem.width; i++) | 		for (int i = 0; i < mem.width; i++) | ||||||
| 			if (shuffle_map[i] != -1) { | 			if (shuffle_map[i] != -1) { | ||||||
| 				module->connect(port.data[shuffle_map[i]], new_data[i]); | 				module->connect(port.data[shuffle_map[i]], new_data[i]); | ||||||
| 				new_init_value.bits()[i] = port.init_value[shuffle_map[i]]; | 				new_init_value.set(i, port.init_value[shuffle_map[i]]); | ||||||
| 				new_arst_value.bits()[i] = port.arst_value[shuffle_map[i]]; | 				new_arst_value.set(i, port.arst_value[shuffle_map[i]]); | ||||||
| 				new_srst_value.bits()[i] = port.srst_value[shuffle_map[i]]; | 				new_srst_value.set(i, port.srst_value[shuffle_map[i]]); | ||||||
| 			} | 			} | ||||||
| 		port.data = new_data; | 		port.data = new_data; | ||||||
| 		port.init_value = new_init_value; | 		port.init_value = new_init_value; | ||||||
|  | @ -887,9 +887,9 @@ grow_read_ports:; | ||||||
| 				for (int i = 0; i < init_size; i++) | 				for (int i = 0; i < init_size; i++) | ||||||
| 					for (int j = 0; j < bram.dbits; j++) | 					for (int j = 0; j < bram.dbits; j++) | ||||||
| 						if (init_offset+i < GetSize(initdata) && init_offset+i >= 0) | 						if (init_offset+i < GetSize(initdata) && init_offset+i >= 0) | ||||||
| 							initparam.bits()[i*bram.dbits+j] = initdata[init_offset+i][init_shift+j]; | 							initparam.set(i*bram.dbits+j, initdata[init_offset+i][init_shift+j]); | ||||||
| 						else | 						else | ||||||
| 							initparam.bits()[i*bram.dbits+j] = State::Sx; | 							initparam.set(i*bram.dbits+j, State::Sx); | ||||||
| 				c->setParam(ID::INIT, initparam); | 				c->setParam(ID::INIT, initparam); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -60,16 +60,17 @@ struct MemoryShareWorker | ||||||
| 	bool merge_rst_value(Mem &mem, Const &res, int wide_log2, const Const &src1, int sub1, const Const &src2, int sub2) { | 	bool merge_rst_value(Mem &mem, Const &res, int wide_log2, const Const &src1, int sub1, const Const &src2, int sub2) { | ||||||
| 		res = Const(State::Sx, mem.width << wide_log2); | 		res = Const(State::Sx, mem.width << wide_log2); | ||||||
| 		for (int i = 0; i < GetSize(src1); i++) | 		for (int i = 0; i < GetSize(src1); i++) | ||||||
| 			res.bits()[i + sub1 * mem.width] = src1[i]; | 			res.set(i + sub1 * mem.width, src1[i]); | ||||||
| 		for (int i = 0; i < GetSize(src2); i++) { | 		for (int i = 0; i < GetSize(src2); i++) { | ||||||
| 			if (src2[i] == State::Sx) | 			if (src2[i] == State::Sx) | ||||||
| 				continue; | 				continue; | ||||||
| 			auto &dst = res.bits()[i + sub2 * mem.width]; | 			int idx = i + sub2 * mem.width; | ||||||
|  | 			RTLIL::State dst = res[idx]; | ||||||
| 			if (dst == src2[i]) | 			if (dst == src2[i]) | ||||||
| 				continue; | 				continue; | ||||||
| 			if (dst != State::Sx) | 			if (dst != State::Sx) | ||||||
| 				return false; | 				return false; | ||||||
| 			dst = src2[i]; | 			res.set(idx, src2[i]); | ||||||
| 		} | 		} | ||||||
| 		return true; | 		return true; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -406,7 +406,7 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos | ||||||
| 		for (int i = 0; i < wire->width; i++) { | 		for (int i = 0; i < wire->width; i++) { | ||||||
| 			auto it = init_bits.find(RTLIL::SigBit(wire, i)); | 			auto it = init_bits.find(RTLIL::SigBit(wire, i)); | ||||||
| 			if (it != init_bits.end()) { | 			if (it != init_bits.end()) { | ||||||
| 				val.bits()[i] = it->second; | 				val.set(i, it->second); | ||||||
| 				found = true; | 				found = true; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -425,7 +425,7 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos | ||||||
| 		if (wire->attributes.count(ID::init)) | 		if (wire->attributes.count(ID::init)) | ||||||
| 			initval = wire->attributes.at(ID::init); | 			initval = wire->attributes.at(ID::init); | ||||||
| 		if (GetSize(initval) != GetSize(wire)) | 		if (GetSize(initval) != GetSize(wire)) | ||||||
| 			initval.bits().resize(GetSize(wire), State::Sx); | 			initval.resize(GetSize(wire), State::Sx); | ||||||
| 		if (initval.is_fully_undef()) | 		if (initval.is_fully_undef()) | ||||||
| 			wire->attributes.erase(ID::init); | 			wire->attributes.erase(ID::init); | ||||||
| 
 | 
 | ||||||
|  | @ -457,7 +457,7 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos | ||||||
| 				if (s1[i] != s2[i]) { | 				if (s1[i] != s2[i]) { | ||||||
| 					if (s2[i] == State::Sx && (initval[i] == State::S0 || initval[i] == State::S1)) { | 					if (s2[i] == State::Sx && (initval[i] == State::S0 || initval[i] == State::S1)) { | ||||||
| 						s2[i] = initval[i]; | 						s2[i] = initval[i]; | ||||||
| 						initval.bits()[i] = State::Sx; | 						initval.set(i, State::Sx); | ||||||
| 					} | 					} | ||||||
| 					new_conn.first.append(s1[i]); | 					new_conn.first.append(s1[i]); | ||||||
| 					new_conn.second.append(s2[i]); | 					new_conn.second.append(s2[i]); | ||||||
|  |  | ||||||
|  | @ -405,27 +405,29 @@ struct OptDffWorker | ||||||
| 				} else if (ff.pol_clr == ff.pol_set) { | 				} else if (ff.pol_clr == ff.pol_set) { | ||||||
| 					// Try a more complex conversion to plain async reset.
 | 					// Try a more complex conversion to plain async reset.
 | ||||||
| 					State val_neutral = ff.pol_set ? State::S0 : State::S1; | 					State val_neutral = ff.pol_set ? State::S0 : State::S1; | ||||||
| 					Const val_arst; |  | ||||||
| 					SigBit sig_arst; | 					SigBit sig_arst; | ||||||
| 					if (ff.sig_clr[0] == val_neutral) | 					if (ff.sig_clr[0] == val_neutral) | ||||||
| 						sig_arst = ff.sig_set[0]; | 						sig_arst = ff.sig_set[0]; | ||||||
| 					else | 					else | ||||||
| 						sig_arst = ff.sig_clr[0]; | 						sig_arst = ff.sig_clr[0]; | ||||||
| 					bool failed = false; | 					bool failed = false; | ||||||
|  | 					Const::Builder val_arst_builder(ff.width); | ||||||
| 					for (int i = 0; i < ff.width; i++) { | 					for (int i = 0; i < ff.width; i++) { | ||||||
| 						if (ff.sig_clr[i] == sig_arst && ff.sig_set[i] == val_neutral) | 						if (ff.sig_clr[i] == sig_arst && ff.sig_set[i] == val_neutral) | ||||||
| 							val_arst.bits().push_back(State::S0); | 							val_arst_builder.push_back(State::S0); | ||||||
| 						else if (ff.sig_set[i] == sig_arst && ff.sig_clr[i] == val_neutral) | 						else if (ff.sig_set[i] == sig_arst && ff.sig_clr[i] == val_neutral) | ||||||
| 							val_arst.bits().push_back(State::S1); | 							val_arst_builder.push_back(State::S1); | ||||||
| 						else | 						else { | ||||||
| 							failed = true; | 							failed = true; | ||||||
|  | 							break; | ||||||
|  | 						} | ||||||
| 					} | 					} | ||||||
| 					if (!failed) { | 					if (!failed) { | ||||||
| 						log("Converting CLR/SET to ARST on %s (%s) from module %s.\n", | 						log("Converting CLR/SET to ARST on %s (%s) from module %s.\n", | ||||||
| 								log_id(cell), log_id(cell->type), log_id(module)); | 								log_id(cell), log_id(cell->type), log_id(module)); | ||||||
| 						ff.has_sr = false; | 						ff.has_sr = false; | ||||||
| 						ff.has_arst = true; | 						ff.has_arst = true; | ||||||
| 						ff.val_arst = val_arst; | 						ff.val_arst = val_arst_builder.build(); | ||||||
| 						ff.sig_arst = sig_arst; | 						ff.sig_arst = sig_arst; | ||||||
| 						ff.pol_arst = ff.pol_clr; | 						ff.pol_arst = ff.pol_clr; | ||||||
| 						changed = true; | 						changed = true; | ||||||
|  | @ -637,7 +639,7 @@ struct OptDffWorker | ||||||
| 					// Try to merge sync resets.
 | 					// Try to merge sync resets.
 | ||||||
| 					std::map<ctrls_t, std::vector<int>> groups; | 					std::map<ctrls_t, std::vector<int>> groups; | ||||||
| 					std::vector<int> remaining_indices; | 					std::vector<int> remaining_indices; | ||||||
| 					Const val_srst; | 					Const::Builder val_srst_builder(ff.width); | ||||||
| 
 | 
 | ||||||
| 					for (int i = 0 ; i < ff.width; i++) { | 					for (int i = 0 ; i < ff.width; i++) { | ||||||
| 						ctrls_t resets; | 						ctrls_t resets; | ||||||
|  | @ -679,16 +681,18 @@ struct OptDffWorker | ||||||
| 							groups[resets].push_back(i); | 							groups[resets].push_back(i); | ||||||
| 						} else | 						} else | ||||||
| 							remaining_indices.push_back(i); | 							remaining_indices.push_back(i); | ||||||
| 						val_srst.bits().push_back(reset_val); | 						val_srst_builder.push_back(reset_val); | ||||||
| 					} | 					} | ||||||
|  | 					Const val_srst = val_srst_builder.build(); | ||||||
| 
 | 
 | ||||||
| 					for (auto &it : groups) { | 					for (auto &it : groups) { | ||||||
| 						FfData new_ff = ff.slice(it.second); | 						FfData new_ff = ff.slice(it.second); | ||||||
| 						new_ff.val_srst = Const(); | 						Const::Builder new_val_srst_builder(new_ff.width); | ||||||
| 						for (int i = 0; i < new_ff.width; i++) { | 						for (int i = 0; i < new_ff.width; i++) { | ||||||
| 							int j = it.second[i]; | 							int j = it.second[i]; | ||||||
| 							new_ff.val_srst.bits().push_back(val_srst[j]); | 							new_val_srst_builder.push_back(val_srst[j]); | ||||||
| 						} | 						} | ||||||
|  | 						new_ff.val_srst = new_val_srst_builder.build(); | ||||||
| 						ctrl_t srst = combine_resets(it.first, ff.is_fine); | 						ctrl_t srst = combine_resets(it.first, ff.is_fine); | ||||||
| 
 | 
 | ||||||
| 						new_ff.has_srst = true; | 						new_ff.has_srst = true; | ||||||
|  |  | ||||||
|  | @ -83,7 +83,7 @@ void replace_undriven(RTLIL::Module *module, const CellTypes &ct) | ||||||
| 			auto cursor = initbits.find(bit); | 			auto cursor = initbits.find(bit); | ||||||
| 			if (cursor != initbits.end()) { | 			if (cursor != initbits.end()) { | ||||||
| 				revisit_initwires.insert(cursor->second.first); | 				revisit_initwires.insert(cursor->second.first); | ||||||
| 				val.bits()[i] = cursor->second.second; | 				val.set(i, cursor->second.second); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -101,7 +101,7 @@ void replace_undriven(RTLIL::Module *module, const CellTypes &ct) | ||||||
| 			Const initval = wire->attributes.at(ID::init); | 			Const initval = wire->attributes.at(ID::init); | ||||||
| 			for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++) { | 			for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++) { | ||||||
| 				if (SigBit(initval[i]) == sig[i]) | 				if (SigBit(initval[i]) == sig[i]) | ||||||
| 					initval.bits()[i] = State::Sx; | 					initval.set(i, State::Sx); | ||||||
| 			} | 			} | ||||||
| 			if (initval.is_fully_undef()) { | 			if (initval.is_fully_undef()) { | ||||||
| 				log_debug("Removing init attribute from %s/%s.\n", log_id(module), log_id(wire)); | 				log_debug("Removing init attribute from %s/%s.\n", log_id(module), log_id(wire)); | ||||||
|  |  | ||||||
|  | @ -96,10 +96,10 @@ struct OptFfInvWorker | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 				Const mask = lut->getParam(ID::LUT); | 				Const mask = lut->getParam(ID::LUT); | ||||||
| 				Const new_mask; | 				Const::Builder new_mask_builder(1 << GetSize(sig_a)); | ||||||
| 				for (int j = 0; j < (1 << GetSize(sig_a)); j++) { | 				for (int j = 0; j < (1 << GetSize(sig_a)); j++) | ||||||
| 					new_mask.bits().push_back(mask[j ^ flip_mask]); | 					new_mask_builder.push_back(mask[j ^ flip_mask]); | ||||||
| 				} | 				Const new_mask = new_mask_builder.build(); | ||||||
| 				if (GetSize(sig_a) == 1 && new_mask.as_int() == 2) { | 				if (GetSize(sig_a) == 1 && new_mask.as_int() == 2) { | ||||||
| 					module->connect(lut->getPort(ID::Y), ff.sig_q); | 					module->connect(lut->getPort(ID::Y), ff.sig_q); | ||||||
| 					module->remove(lut); | 					module->remove(lut); | ||||||
|  | @ -178,13 +178,14 @@ struct OptFfInvWorker | ||||||
| 
 | 
 | ||||||
| 		if (d_lut->type == ID($lut)) { | 		if (d_lut->type == ID($lut)) { | ||||||
| 			Const mask = d_lut->getParam(ID::LUT); | 			Const mask = d_lut->getParam(ID::LUT); | ||||||
| 			Const new_mask; | 			Const::Builder new_mask_builder(GetSize(mask)); | ||||||
| 			for (int i = 0; i < GetSize(mask); i++) { | 			for (int i = 0; i < GetSize(mask); i++) { | ||||||
| 				if (mask[i] == State::S0) | 				if (mask[i] == State::S0) | ||||||
| 					new_mask.bits().push_back(State::S1); | 					new_mask_builder.push_back(State::S1); | ||||||
| 				else | 				else | ||||||
| 					new_mask.bits().push_back(State::S0); | 					new_mask_builder.push_back(State::S0); | ||||||
| 			} | 			} | ||||||
|  | 			Const new_mask = new_mask_builder.build(); | ||||||
| 			d_lut->setParam(ID::LUT, new_mask); | 			d_lut->setParam(ID::LUT, new_mask); | ||||||
| 			if (d_lut->getParam(ID::WIDTH) == 1 && new_mask.as_int() == 2) { | 			if (d_lut->getParam(ID::WIDTH) == 1 && new_mask.as_int() == 2) { | ||||||
| 				module->connect(ff.sig_d, d_lut->getPort(ID::A)); | 				module->connect(ff.sig_d, d_lut->getPort(ID::A)); | ||||||
|  |  | ||||||
|  | @ -493,7 +493,7 @@ struct OptLutWorker | ||||||
| 							eval_inputs[lutM_new_inputs[i]] = (eval >> i) & 1; | 							eval_inputs[lutM_new_inputs[i]] = (eval >> i) & 1; | ||||||
| 						} | 						} | ||||||
| 						eval_inputs[lutA_output] = evaluate_lut(lutA, eval_inputs); | 						eval_inputs[lutA_output] = evaluate_lut(lutA, eval_inputs); | ||||||
| 						lutM_new_table.bits()[eval] = (RTLIL::State) evaluate_lut(lutB, eval_inputs); | 						lutM_new_table.set(eval, (RTLIL::State) evaluate_lut(lutB, eval_inputs)); | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					log_debug("  Cell A truth table: %s.\n", lutA->getParam(ID::LUT).as_string().c_str()); | 					log_debug("  Cell A truth table: %s.\n", lutA->getParam(ID::LUT).as_string().c_str()); | ||||||
|  |  | ||||||
|  | @ -213,7 +213,7 @@ struct OptLutInsPass : public Pass { | ||||||
| 						} | 						} | ||||||
| 						lidx |= val << j; | 						lidx |= val << j; | ||||||
| 					} | 					} | ||||||
| 					new_lut.bits()[i] = lut[lidx]; | 					new_lut.set(i, lut[lidx]); | ||||||
| 				} | 				} | ||||||
| 				// For lattice, and gowin do not replace with a const driver — the nextpnr
 | 				// For lattice, and gowin do not replace with a const driver — the nextpnr
 | ||||||
| 				// packer requires a complete set of LUTs for wide LUT muxes.
 | 				// packer requires a complete set of LUTs for wide LUT muxes.
 | ||||||
|  |  | ||||||
|  | @ -175,36 +175,36 @@ struct OptMemPass : public Pass { | ||||||
| 					} | 					} | ||||||
| 					for (auto &port: mem.rd_ports) { | 					for (auto &port: mem.rd_ports) { | ||||||
| 						SigSpec new_data; | 						SigSpec new_data; | ||||||
| 						Const new_init; | 						Const::Builder new_init_bits; | ||||||
| 						Const new_arst; | 						Const::Builder new_arst_bits; | ||||||
| 						Const new_srst; | 						Const::Builder new_srst_bits; | ||||||
| 						for (int sub = 0; sub < (1 << port.wide_log2); sub++) { | 						for (int sub = 0; sub < (1 << port.wide_log2); sub++) { | ||||||
| 							for (auto i: swizzle) { | 							for (auto i: swizzle) { | ||||||
| 								int bidx = sub * mem.width + i; | 								int bidx = sub * mem.width + i; | ||||||
| 								new_data.append(port.data[bidx]); | 								new_data.append(port.data[bidx]); | ||||||
| 								new_init.bits().push_back(port.init_value[bidx]); | 								new_init_bits.push_back(port.init_value[bidx]); | ||||||
| 								new_arst.bits().push_back(port.arst_value[bidx]); | 								new_arst_bits.push_back(port.arst_value[bidx]); | ||||||
| 								new_srst.bits().push_back(port.srst_value[bidx]); | 								new_srst_bits.push_back(port.srst_value[bidx]); | ||||||
| 							} | 							} | ||||||
| 						} | 						} | ||||||
| 						port.data = new_data; | 						port.data = new_data; | ||||||
| 						port.init_value = new_init; | 						port.init_value = new_init_bits.build(); | ||||||
| 						port.arst_value = new_arst; | 						port.arst_value = new_arst_bits.build(); | ||||||
| 						port.srst_value = new_srst; | 						port.srst_value = new_srst_bits.build(); | ||||||
| 					} | 					} | ||||||
| 					for (auto &init: mem.inits) { | 					for (auto &init: mem.inits) { | ||||||
| 						Const new_data; | 						Const::Builder new_data_bits; | ||||||
| 						Const new_en; |  | ||||||
| 						for (int s = 0; s < GetSize(init.data); s += mem.width) { | 						for (int s = 0; s < GetSize(init.data); s += mem.width) { | ||||||
| 							for (auto i: swizzle) { | 							for (auto i: swizzle) { | ||||||
| 								new_data.bits().push_back(init.data[s + i]); | 								new_data_bits.push_back(init.data[s + i]); | ||||||
| 							} | 							} | ||||||
| 						} | 						} | ||||||
|  | 						init.data = new_data_bits.build(); | ||||||
|  | 						Const::Builder new_en_bits; | ||||||
| 						for (auto i: swizzle) { | 						for (auto i: swizzle) { | ||||||
| 							new_en.bits().push_back(init.en[i]); | 							new_en_bits.push_back(init.en[i]); | ||||||
| 						} | 						} | ||||||
| 						init.data = new_data; | 						init.en = new_en_bits.build(); | ||||||
| 						init.en = new_en; |  | ||||||
| 					} | 					} | ||||||
| 					mem.width = GetSize(swizzle); | 					mem.width = GetSize(swizzle); | ||||||
| 					changed = true; | 					changed = true; | ||||||
|  |  | ||||||
|  | @ -321,11 +321,12 @@ struct Pmux2ShiftxPass : public Pass { | ||||||
| 
 | 
 | ||||||
| 					bits.sort(); | 					bits.sort(); | ||||||
| 					pair<SigSpec, Const> entry; | 					pair<SigSpec, Const> entry; | ||||||
| 
 | 					RTLIL::Const::Builder entry_bits_builder(GetSize(bits)); | ||||||
| 					for (auto it : bits) { | 					for (auto it : bits) { | ||||||
| 						entry.first.append(it.first); | 						entry.first.append(it.first); | ||||||
| 						entry.second.bits().push_back(it.second); | 						entry_bits_builder.push_back(it.second); | ||||||
| 					} | 					} | ||||||
|  | 					entry.second = entry_bits_builder.build(); | ||||||
| 
 | 
 | ||||||
| 					eqdb[sigmap(cell->getPort(ID::Y)[0])] = entry; | 					eqdb[sigmap(cell->getPort(ID::Y)[0])] = entry; | ||||||
| 					goto next_cell; | 					goto next_cell; | ||||||
|  | @ -342,11 +343,12 @@ struct Pmux2ShiftxPass : public Pass { | ||||||
| 
 | 
 | ||||||
| 					bits.sort(); | 					bits.sort(); | ||||||
| 					pair<SigSpec, Const> entry; | 					pair<SigSpec, Const> entry; | ||||||
| 
 | 					RTLIL::Const::Builder entry_bits_builder(GetSize(bits)); | ||||||
| 					for (auto it : bits) { | 					for (auto it : bits) { | ||||||
| 						entry.first.append(it.first); | 						entry.first.append(it.first); | ||||||
| 						entry.second.bits().push_back(it.second); | 						entry_bits_builder.push_back(it.second); | ||||||
| 					} | 					} | ||||||
|  | 					entry.second = entry_bits_builder.build(); | ||||||
| 
 | 
 | ||||||
| 					eqdb[sigmap(cell->getPort(ID::Y)[0])] = entry; | 					eqdb[sigmap(cell->getPort(ID::Y)[0])] = entry; | ||||||
| 					goto next_cell; | 					goto next_cell; | ||||||
|  | @ -591,7 +593,7 @@ struct Pmux2ShiftxPass : public Pass { | ||||||
| 
 | 
 | ||||||
| 							used_src_columns[best_src_col] = true; | 							used_src_columns[best_src_col] = true; | ||||||
| 							perm_new_from_old[dst_col] = best_src_col; | 							perm_new_from_old[dst_col] = best_src_col; | ||||||
| 							perm_xormask.bits()[dst_col] = best_inv ? State::S1 : State::S0; | 							perm_xormask.set(dst_col, best_inv ? State::S1 : State::S0); | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
|  | @ -614,7 +616,7 @@ struct Pmux2ShiftxPass : public Pass { | ||||||
| 						Const new_c(State::S0, GetSize(old_c)); | 						Const new_c(State::S0, GetSize(old_c)); | ||||||
| 
 | 
 | ||||||
| 						for (int i = 0; i < GetSize(old_c); i++) | 						for (int i = 0; i < GetSize(old_c); i++) | ||||||
| 							new_c.bits()[i] = old_c[perm_new_from_old[i]]; | 							new_c.set(i, old_c[perm_new_from_old[i]]); | ||||||
| 
 | 
 | ||||||
| 						Const new_c_before_xor = new_c; | 						Const new_c_before_xor = new_c; | ||||||
| 						new_c = const_xor(new_c, perm_xormask, false, false, GetSize(new_c)); | 						new_c = const_xor(new_c, perm_xormask, false, false, GetSize(new_c)); | ||||||
|  | @ -687,7 +689,7 @@ struct Pmux2ShiftxPass : public Pass { | ||||||
| 					if (!full_case) { | 					if (!full_case) { | ||||||
| 						Const enable_mask(State::S0, max_choice+1); | 						Const enable_mask(State::S0, max_choice+1); | ||||||
| 						for (auto &it : perm_choices) | 						for (auto &it : perm_choices) | ||||||
| 							enable_mask.bits()[it.first.as_int()] = State::S1; | 							enable_mask.set(it.first.as_int(), State::S1); | ||||||
| 						en = module->addWire(NEW_ID); | 						en = module->addWire(NEW_ID); | ||||||
| 						module->addShift(NEW_ID, enable_mask, cmp, en, false, src); | 						module->addShift(NEW_ID, enable_mask, cmp, en, false, src); | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
|  | @ -790,12 +790,13 @@ struct ShareWorker | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		p.first = RTLIL::SigSpec(); | 		p.first = RTLIL::SigSpec(); | ||||||
| 		p.second.bits().clear(); |  | ||||||
| 
 | 
 | ||||||
|  | 		RTLIL::Const::Builder new_bits(p_bits.size()); | ||||||
| 		for (auto &it : p_bits) { | 		for (auto &it : p_bits) { | ||||||
| 			p.first.append(it.first); | 			p.first.append(it.first); | ||||||
| 			p.second.bits().push_back(it.second); | 			new_bits.push_back(it.second); | ||||||
| 		} | 		} | ||||||
|  | 		p.second = new_bits.build(); | ||||||
| 
 | 
 | ||||||
| 		return true; | 		return true; | ||||||
| 	} | 	} | ||||||
|  | @ -818,9 +819,9 @@ struct ShareWorker | ||||||
| 				auto otherval = val; | 				auto otherval = val; | ||||||
| 
 | 
 | ||||||
| 				if (otherval[i] == State::S0) | 				if (otherval[i] == State::S0) | ||||||
| 					otherval.bits()[i] = State::S1; | 					otherval.set(i, State::S1); | ||||||
| 				else if (otherval[i] == State::S1) | 				else if (otherval[i] == State::S1) | ||||||
| 					otherval.bits()[i] = State::S0; | 					otherval.set(i, State::S0); | ||||||
| 				else | 				else | ||||||
| 					continue; | 					continue; | ||||||
| 
 | 
 | ||||||
|  | @ -829,8 +830,11 @@ struct ShareWorker | ||||||
| 					auto newsig = sig; | 					auto newsig = sig; | ||||||
| 					newsig.remove(i); | 					newsig.remove(i); | ||||||
| 
 | 
 | ||||||
| 					auto newval = val; | 					RTLIL::Const::Builder new_bits(val.size() - 1); | ||||||
| 					newval.bits().erase(newval.bits().begin() + i); | 					for (int j = 0; j < val.size(); ++j) | ||||||
|  | 						if (j != i) | ||||||
|  | 							new_bits.push_back(val[j]); | ||||||
|  | 					RTLIL::Const newval = new_bits.build(); | ||||||
| 
 | 
 | ||||||
| 					db[newsig].insert(newval); | 					db[newsig].insert(newval); | ||||||
| 					db[sig].erase(otherval); | 					db[sig].erase(otherval); | ||||||
|  | @ -926,7 +930,8 @@ struct ShareWorker | ||||||
| 			if (used_in_a) | 			if (used_in_a) | ||||||
| 				for (auto p : c_patterns) { | 				for (auto p : c_patterns) { | ||||||
| 					for (int i = 0; i < GetSize(sig_s); i++) | 					for (int i = 0; i < GetSize(sig_s); i++) | ||||||
| 						p.first.append(sig_s[i]), p.second.bits().push_back(RTLIL::State::S0); | 						p.first.append(sig_s[i]); | ||||||
|  | 					p.second.append(RTLIL::Const(RTLIL::State::S0, GetSize(sig_s))); | ||||||
| 					if (sort_check_activation_pattern(p)) | 					if (sort_check_activation_pattern(p)) | ||||||
| 						if (!insert_capped(activation_patterns_cache[cell], p)) { | 						if (!insert_capped(activation_patterns_cache[cell], p)) { | ||||||
| 							recursion_state.erase(cell); | 							recursion_state.erase(cell); | ||||||
|  | @ -936,7 +941,8 @@ struct ShareWorker | ||||||
| 
 | 
 | ||||||
| 			for (int idx : used_in_b_parts) | 			for (int idx : used_in_b_parts) | ||||||
| 				for (auto p : c_patterns) { | 				for (auto p : c_patterns) { | ||||||
| 					p.first.append(sig_s[idx]), p.second.bits().push_back(RTLIL::State::S1); | 					p.first.append(sig_s[idx]); | ||||||
|  | 					p.second.append(RTLIL::Const(RTLIL::State::S1)); | ||||||
| 					if (sort_check_activation_pattern(p)) | 					if (sort_check_activation_pattern(p)) | ||||||
| 					if (!insert_capped(activation_patterns_cache[cell], p)) { | 					if (!insert_capped(activation_patterns_cache[cell], p)) { | ||||||
| 						recursion_state.erase(cell); | 						recursion_state.erase(cell); | ||||||
|  | @ -989,12 +995,14 @@ struct ShareWorker | ||||||
| 		{ | 		{ | ||||||
| 			std::vector<RTLIL::SigBit> p_first = p.first; | 			std::vector<RTLIL::SigBit> p_first = p.first; | ||||||
| 			ssc_pair_t new_p; | 			ssc_pair_t new_p; | ||||||
|  | 			RTLIL::Const::Builder new_p_second_bits; | ||||||
| 
 | 
 | ||||||
| 			for (int i = 0; i < GetSize(p_first); i++) | 			for (int i = 0; i < GetSize(p_first); i++) | ||||||
| 				if (filter_bits.count(p_first[i]) == 0) { | 				if (filter_bits.count(p_first[i]) == 0) { | ||||||
| 					new_p.first.append(p_first[i]); | 					new_p.first.append(p_first[i]); | ||||||
| 					new_p.second.bits().push_back(p.second.at(i)); | 					new_p_second_bits.push_back(p.second.at(i)); | ||||||
| 				} | 				} | ||||||
|  | 			new_p.second = new_p_second_bits.build(); | ||||||
| 
 | 
 | ||||||
| 			out.insert(new_p); | 			out.insert(new_p); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -220,10 +220,10 @@ struct WreduceWorker | ||||||
| 
 | 
 | ||||||
| 		// Narrow ARST_VALUE parameter to new size.
 | 		// Narrow ARST_VALUE parameter to new size.
 | ||||||
| 		if (cell->parameters.count(ID::ARST_VALUE)) { | 		if (cell->parameters.count(ID::ARST_VALUE)) { | ||||||
| 			rst_value.bits().resize(GetSize(sig_q)); | 			rst_value.resize(GetSize(sig_q), State::S0); | ||||||
| 			cell->setParam(ID::ARST_VALUE, rst_value); | 			cell->setParam(ID::ARST_VALUE, rst_value); | ||||||
| 		} else if (cell->parameters.count(ID::SRST_VALUE)) { | 		} else if (cell->parameters.count(ID::SRST_VALUE)) { | ||||||
| 			rst_value.bits().resize(GetSize(sig_q)); | 			rst_value.resize(GetSize(sig_q), State::S0); | ||||||
| 			cell->setParam(ID::SRST_VALUE, rst_value); | 			cell->setParam(ID::SRST_VALUE, rst_value); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -52,17 +52,15 @@ void proc_init(RTLIL::Module *mod, SigMap &sigmap, RTLIL::Process *proc) | ||||||
| 
 | 
 | ||||||
| 						Const value = valuesig.as_const(); | 						Const value = valuesig.as_const(); | ||||||
| 						Const &wireinit = lhs_c.wire->attributes[ID::init]; | 						Const &wireinit = lhs_c.wire->attributes[ID::init]; | ||||||
| 
 | 						if (GetSize(wireinit) < lhs_c.wire->width) | ||||||
| 						while (GetSize(wireinit) < lhs_c.wire->width) | 							wireinit.resize(lhs_c.wire->width, State::Sx); | ||||||
| 							wireinit.bits().push_back(State::Sx); |  | ||||||
| 
 |  | ||||||
| 						for (int i = 0; i < lhs_c.width; i++) { | 						for (int i = 0; i < lhs_c.width; i++) { | ||||||
| 							auto &initbit = wireinit.bits()[i + lhs_c.offset]; | 							int index = i + lhs_c.offset; | ||||||
|  | 							State initbit = wireinit[index]; | ||||||
| 							if (initbit != State::Sx && initbit != value[i]) | 							if (initbit != State::Sx && initbit != value[i]) | ||||||
| 								log_cmd_error("Conflicting initialization values for %s.\n", log_signal(lhs_c)); | 								log_cmd_error("Conflicting initialization values for %s.\n", log_signal(lhs_c)); | ||||||
| 							initbit = value[i]; | 							wireinit.set(index, value[i]); | ||||||
| 						} | 						} | ||||||
| 
 |  | ||||||
| 						log("  Set init value: %s = %s\n", log_signal(lhs_c.wire), log_signal(wireinit)); | 						log("  Set init value: %s = %s\n", log_signal(lhs_c.wire), log_signal(wireinit)); | ||||||
| 					} | 					} | ||||||
| 					offset += lhs_c.width; | 					offset += lhs_c.width; | ||||||
|  |  | ||||||
|  | @ -39,7 +39,7 @@ void proc_memwr(RTLIL::Module *mod, RTLIL::Process *proc, dict<IdString, int> &n | ||||||
| 			Const priority_mask(State::S0, port_id); | 			Const priority_mask(State::S0, port_id); | ||||||
| 			for (int i = 0; i < GetSize(prev_port_ids); i++) | 			for (int i = 0; i < GetSize(prev_port_ids); i++) | ||||||
| 				if (memwr.priority_mask[i] == State::S1) | 				if (memwr.priority_mask[i] == State::S1) | ||||||
| 					priority_mask.bits()[prev_port_ids[i]] = State::S1; | 					priority_mask.set(prev_port_ids[i], State::S1); | ||||||
| 			prev_port_ids.push_back(port_id); | 			prev_port_ids.push_back(port_id); | ||||||
| 
 | 
 | ||||||
| 			RTLIL::Cell *cell = mod->addCell(NEW_ID, ID($memwr_v2)); | 			RTLIL::Cell *cell = mod->addCell(NEW_ID, ID($memwr_v2)); | ||||||
|  |  | ||||||
|  | @ -97,7 +97,7 @@ struct RomWorker | ||||||
| 						log_debug("rejecting switch: lhs not uniform\n"); | 						log_debug("rejecting switch: lhs not uniform\n"); | ||||||
| 						return; | 						return; | ||||||
| 					} | 					} | ||||||
| 					val.bits()[it2->second] = it.second[i].data; | 					val.set(it2->second, it.second[i].data); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			for (auto bit: val) { | 			for (auto bit: val) { | ||||||
|  | @ -114,7 +114,7 @@ struct RomWorker | ||||||
| 				} | 				} | ||||||
| 				Const c = addr.as_const(); | 				Const c = addr.as_const(); | ||||||
| 				while (GetSize(c) && c.back() == State::S0) | 				while (GetSize(c) && c.back() == State::S0) | ||||||
| 					c.bits().pop_back(); | 					c.resize(c.size() - 1, State::S0); | ||||||
| 				if (GetSize(c) > swsigbits) | 				if (GetSize(c) > swsigbits) | ||||||
| 					continue; | 					continue; | ||||||
| 				if (GetSize(c) > 30) { | 				if (GetSize(c) > 30) { | ||||||
|  | @ -155,22 +155,22 @@ struct RomWorker | ||||||
| 		Mem mem(module, NEW_ID, GetSize(lhs), 0, 1 << abits); | 		Mem mem(module, NEW_ID, GetSize(lhs), 0, 1 << abits); | ||||||
| 		mem.attributes = sw->attributes; | 		mem.attributes = sw->attributes; | ||||||
| 
 | 
 | ||||||
| 		Const init_data; | 		Const::Builder builder(mem.size * GetSize(lhs)); | ||||||
| 		for (int i = 0; i < mem.size; i++) { | 		for (int i = 0; i < mem.size; i++) { | ||||||
| 			auto it = vals.find(i); | 			auto it = vals.find(i); | ||||||
| 			if (it == vals.end()) { | 			if (it == vals.end()) { | ||||||
| 				log_assert(got_default); | 				log_assert(got_default); | ||||||
| 				for (auto bit: default_val) | 				for (auto bit: default_val) | ||||||
| 					init_data.bits().push_back(bit); | 					builder.push_back(bit); | ||||||
| 			} else { | 			} else { | ||||||
| 				for (auto bit: it->second) | 				for (auto bit: it->second) | ||||||
| 					init_data.bits().push_back(bit); | 					builder.push_back(bit); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		MemInit init; | 		MemInit init; | ||||||
| 		init.addr = 0; | 		init.addr = 0; | ||||||
| 		init.data = init_data; | 		init.data = builder.build(); | ||||||
| 		init.en = Const(State::S1, GetSize(lhs)); | 		init.en = Const(State::S1, GetSize(lhs)); | ||||||
| 		mem.inits.push_back(std::move(init)); | 		mem.inits.push_back(std::move(init)); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -256,7 +256,7 @@ struct VlogHammerReporter | ||||||
| 					for (int j = input_widths[i]-1; j >= 0; j--) { | 					for (int j = input_widths[i]-1; j >= 0; j--) { | ||||||
| 						ce.set(RTLIL::SigSpec(wire, j), bits.back()); | 						ce.set(RTLIL::SigSpec(wire, j), bits.back()); | ||||||
| 						recorded_set_vars.append(RTLIL::SigSpec(wire, j)); | 						recorded_set_vars.append(RTLIL::SigSpec(wire, j)); | ||||||
| 						recorded_set_vals.bits().push_back(bits.back()); | 						recorded_set_vars.append(RTLIL::Const(bits.back())); | ||||||
| 						bits.pop_back(); | 						bits.pop_back(); | ||||||
| 					} | 					} | ||||||
| 					if (module == modules.front()) { | 					if (module == modules.front()) { | ||||||
|  | @ -346,7 +346,7 @@ struct VlogHammerReporter | ||||||
| 				log_error("Pattern %s is to short!\n", pattern.c_str()); | 				log_error("Pattern %s is to short!\n", pattern.c_str()); | ||||||
| 			patterns.push_back(sig.as_const()); | 			patterns.push_back(sig.as_const()); | ||||||
| 			if (invert_pattern) { | 			if (invert_pattern) { | ||||||
| 				for (auto &bit : patterns.back().bits()) | 				for (auto bit : patterns.back()) | ||||||
| 					if (bit == RTLIL::State::S0) | 					if (bit == RTLIL::State::S0) | ||||||
| 						bit = RTLIL::State::S1; | 						bit = RTLIL::State::S1; | ||||||
| 					else if (bit == RTLIL::State::S1) | 					else if (bit == RTLIL::State::S1) | ||||||
|  |  | ||||||
|  | @ -851,7 +851,7 @@ struct FormalFfPass : public Pass { | ||||||
| 						auto before = ff.val_init; | 						auto before = ff.val_init; | ||||||
| 						for (int i = 0; i < ff.width; i++) | 						for (int i = 0; i < ff.width; i++) | ||||||
| 							if (ff.val_init[i] == State::Sx && !worker.is_initval_used(ff.sig_q[i])) | 							if (ff.val_init[i] == State::Sx && !worker.is_initval_used(ff.sig_q[i])) | ||||||
| 								ff.val_init.bits()[i] = State::S0; | 								ff.val_init.set(i, State::S0); | ||||||
| 
 | 
 | ||||||
| 						if (ff.val_init != before) { | 						if (ff.val_init != before) { | ||||||
| 							log("Setting unused undefined initial value of %s.%s (%s) from %s to %s\n", | 							log("Setting unused undefined initial value of %s.%s (%s) from %s to %s\n", | ||||||
|  |  | ||||||
|  | @ -620,14 +620,18 @@ struct SatHelper | ||||||
| 		int last_timestep = -2; | 		int last_timestep = -2; | ||||||
| 		for (auto &info : modelInfo) | 		for (auto &info : modelInfo) | ||||||
| 		{ | 		{ | ||||||
| 			RTLIL::Const value; |  | ||||||
| 			bool found_undef = false; | 			bool found_undef = false; | ||||||
| 
 | 
 | ||||||
|  | 			RTLIL::Const::Builder value_builder(info.width); | ||||||
| 			for (int i = 0; i < info.width; i++) { | 			for (int i = 0; i < info.width; i++) { | ||||||
| 				value.bits().push_back(modelValues.at(info.offset+i) ? RTLIL::State::S1 : RTLIL::State::S0); | 				RTLIL::State bit = modelValues.at(info.offset+i) ? RTLIL::State::S1 : RTLIL::State::S0; | ||||||
| 				if (enable_undef && modelValues.at(modelExpressions.size()/2 + info.offset + i)) | 				if (enable_undef && modelValues.at(modelExpressions.size()/2 + info.offset + i)) { | ||||||
| 					value.bits().back() = RTLIL::State::Sx, found_undef = true; | 					bit = RTLIL::State::Sx; | ||||||
|  | 					found_undef = true; | ||||||
| 				} | 				} | ||||||
|  | 				value_builder.push_back(bit); | ||||||
|  | 			} | ||||||
|  | 			RTLIL::Const value = value_builder.build(); | ||||||
| 
 | 
 | ||||||
| 			if (info.timestep != last_timestep) { | 			if (info.timestep != last_timestep) { | ||||||
| 				const char *hline = "---------------------------------------------------------------------------------------------------" | 				const char *hline = "---------------------------------------------------------------------------------------------------" | ||||||
|  | @ -732,13 +736,14 @@ struct SatHelper | ||||||
| 		int last_timestep = -2; | 		int last_timestep = -2; | ||||||
| 		for (auto &info : modelInfo) | 		for (auto &info : modelInfo) | ||||||
| 		{ | 		{ | ||||||
| 			RTLIL::Const value; | 			RTLIL::Const::Builder value_builder(info.width); | ||||||
| 
 |  | ||||||
| 			for (int i = 0; i < info.width; i++) { | 			for (int i = 0; i < info.width; i++) { | ||||||
| 				value.bits().push_back(modelValues.at(info.offset+i) ? RTLIL::State::S1 : RTLIL::State::S0); | 				RTLIL::State bit = modelValues.at(info.offset+i) ? RTLIL::State::S1 : RTLIL::State::S0; | ||||||
| 				if (enable_undef && modelValues.at(modelExpressions.size()/2 + info.offset + i)) | 				if (enable_undef && modelValues.at(modelExpressions.size()/2 + info.offset + i)) | ||||||
| 					value.bits().back() = RTLIL::State::Sx; | 					bit = RTLIL::State::Sx; | ||||||
|  | 				value_builder.push_back(bit); | ||||||
| 			} | 			} | ||||||
|  | 			RTLIL::Const value = value_builder.build(); | ||||||
| 
 | 
 | ||||||
| 			if (info.timestep != last_timestep) { | 			if (info.timestep != last_timestep) { | ||||||
| 				if(last_timestep == 0) | 				if(last_timestep == 0) | ||||||
|  | @ -779,12 +784,14 @@ struct SatHelper | ||||||
| 
 | 
 | ||||||
| 		for (auto &info : modelInfo) | 		for (auto &info : modelInfo) | ||||||
| 		{ | 		{ | ||||||
| 			Const value; | 			RTLIL::Const::Builder value_builder(info.width); | ||||||
| 			for (int i = 0; i < info.width; i++) { | 			for (int i = 0; i < info.width; i++) { | ||||||
| 				value.bits().push_back(modelValues.at(info.offset+i) ? RTLIL::State::S1 : RTLIL::State::S0); | 				RTLIL::State bit = modelValues.at(info.offset+i) ? RTLIL::State::S1 : RTLIL::State::S0; | ||||||
| 				if (enable_undef && modelValues.at(modelExpressions.size()/2 + info.offset + i)) | 				if (enable_undef && modelValues.at(modelExpressions.size()/2 + info.offset + i)) | ||||||
| 					value.bits().back() = RTLIL::State::Sx; | 					bit = RTLIL::State::Sx; | ||||||
|  | 				value_builder.push_back(bit); | ||||||
| 			} | 			} | ||||||
|  | 			Const value = value_builder.build(); | ||||||
| 
 | 
 | ||||||
| 			wavedata[info.description].first = info.width; | 			wavedata[info.description].first = info.width; | ||||||
| 			wavedata[info.description].second[info.timestep] = value; | 			wavedata[info.description].second[info.timestep] = value; | ||||||
|  |  | ||||||
|  | @ -127,16 +127,11 @@ struct SimShared | ||||||
| 	bool initstate = true; | 	bool initstate = true; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void zinit(State &v) |  | ||||||
| { |  | ||||||
| 	if (v != State::S1) |  | ||||||
| 		v = State::S0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void zinit(Const &v) | void zinit(Const &v) | ||||||
| { | { | ||||||
| 	for (auto &bit : v.bits()) | 	for (auto bit : v) | ||||||
| 		zinit(bit); | 		if (bit != State::S1) | ||||||
|  | 			bit = State::S0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct SimInstance | struct SimInstance | ||||||
|  | @ -419,16 +414,17 @@ struct SimInstance | ||||||
| 
 | 
 | ||||||
| 	Const get_state(SigSpec sig) | 	Const get_state(SigSpec sig) | ||||||
| 	{ | 	{ | ||||||
| 		Const value; | 		Const::Builder builder(GetSize(sig)); | ||||||
| 
 | 
 | ||||||
| 		for (auto bit : sigmap(sig)) | 		for (auto bit : sigmap(sig)) | ||||||
| 			if (bit.wire == nullptr) | 			if (bit.wire == nullptr) | ||||||
| 				value.bits().push_back(bit.data); | 				builder.push_back(bit.data); | ||||||
| 			else if (state_nets.count(bit)) | 			else if (state_nets.count(bit)) | ||||||
| 				value.bits().push_back(state_nets.at(bit)); | 				builder.push_back(state_nets.at(bit)); | ||||||
| 			else | 			else | ||||||
| 				value.bits().push_back(State::Sz); | 				builder.push_back(State::Sz); | ||||||
| 
 | 
 | ||||||
|  | 		Const value = builder.build(); | ||||||
| 		if (shared->debug) | 		if (shared->debug) | ||||||
| 			log("[%s] get %s: %s\n", hiername().c_str(), log_signal(sig), log_signal(value)); | 			log("[%s] get %s: %s\n", hiername().c_str(), log_signal(sig), log_signal(value)); | ||||||
| 		return value; | 		return value; | ||||||
|  | @ -488,7 +484,7 @@ struct SimInstance | ||||||
| 		for (int i = 0; i < GetSize(data); i++) | 		for (int i = 0; i < GetSize(data); i++) | ||||||
| 			if (0 <= i+offset && i+offset < state.mem->size * state.mem->width && data[i] != State::Sa) | 			if (0 <= i+offset && i+offset < state.mem->size * state.mem->width && data[i] != State::Sa) | ||||||
| 				if (state.data[i+offset] != data[i]) | 				if (state.data[i+offset] != data[i]) | ||||||
| 					dirty = true, state.data.bits()[i+offset] = data[i]; | 					dirty = true, state.data.set(i+offset, data[i]); | ||||||
| 
 | 
 | ||||||
| 		if (dirty) | 		if (dirty) | ||||||
| 			dirty_memories.insert(memid); | 			dirty_memories.insert(memid); | ||||||
|  | @ -500,7 +496,7 @@ struct SimInstance | ||||||
| 		if (offset >= state.mem->size * state.mem->width) | 		if (offset >= state.mem->size * state.mem->width) | ||||||
| 			log_error("Addressing out of bounds bit %d/%d of memory %s\n", offset, state.mem->size * state.mem->width, log_id(memid)); | 			log_error("Addressing out of bounds bit %d/%d of memory %s\n", offset, state.mem->size * state.mem->width, log_id(memid)); | ||||||
| 		if (state.data[offset] != data) { | 		if (state.data[offset] != data) { | ||||||
| 			state.data.bits()[offset] = data; | 			state.data.set(offset, data); | ||||||
| 			dirty_memories.insert(memid); | 			dirty_memories.insert(memid); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -717,10 +713,10 @@ struct SimInstance | ||||||
| 
 | 
 | ||||||
| 				for(int i=0;i<ff.past_d.size();i++) { | 				for(int i=0;i<ff.past_d.size();i++) { | ||||||
| 					if (current_clr[i] == (ff_data.pol_clr ? State::S1 : State::S0)) { | 					if (current_clr[i] == (ff_data.pol_clr ? State::S1 : State::S0)) { | ||||||
| 						current_q.bits()[i] = State::S0; | 						current_q.set(i, State::S0); | ||||||
| 					} | 					} | ||||||
| 					else if (current_set[i] == (ff_data.pol_set ? State::S1 : State::S0)) { | 					else if (current_set[i] == (ff_data.pol_set ? State::S1 : State::S0)) { | ||||||
| 						current_q.bits()[i] = State::S1; | 						current_q.set(i, State::S1); | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | @ -770,7 +766,7 @@ struct SimInstance | ||||||
| 					if (index >= 0 && index < mem.size) | 					if (index >= 0 && index < mem.size) | ||||||
| 						for (int i = 0; i < (mem.width << port.wide_log2); i++) | 						for (int i = 0; i < (mem.width << port.wide_log2); i++) | ||||||
| 							if (enable[i] == State::S1 && mdb.data.at(index*mem.width+i) != data[i]) { | 							if (enable[i] == State::S1 && mdb.data.at(index*mem.width+i) != data[i]) { | ||||||
| 								mdb.data.bits().at(index*mem.width+i) = data[i]; | 								mdb.data.set(index*mem.width+i, data[i]); | ||||||
| 								dirty_memories.insert(mem.memid); | 								dirty_memories.insert(mem.memid); | ||||||
| 								did_something = true; | 								did_something = true; | ||||||
| 							} | 							} | ||||||
|  | @ -971,7 +967,7 @@ struct SimInstance | ||||||
| 				if (w->attributes.count(ID::init) == 0) | 				if (w->attributes.count(ID::init) == 0) | ||||||
| 					w->attributes[ID::init] = Const(State::Sx, GetSize(w)); | 					w->attributes[ID::init] = Const(State::Sx, GetSize(w)); | ||||||
| 
 | 
 | ||||||
| 				w->attributes[ID::init].bits()[sig_q[i].offset] = initval[i]; | 				w->attributes[ID::init].set(sig_q[i].offset, initval[i]); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1216,7 +1216,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) | ||||||
| 			auto Qi = initmap(Q); | 			auto Qi = initmap(Q); | ||||||
| 			auto it = Qi.wire->attributes.find(ID::init); | 			auto it = Qi.wire->attributes.find(ID::init); | ||||||
| 			if (it != Qi.wire->attributes.end()) | 			if (it != Qi.wire->attributes.end()) | ||||||
| 				it->second.bits()[Qi.offset] = State::Sx; | 				it->second.set(Qi.offset, State::Sx); | ||||||
| 		} | 		} | ||||||
| 		else if (cell->type.in(ID($_AND_), ID($_NOT_))) | 		else if (cell->type.in(ID($_AND_), ID($_NOT_))) | ||||||
| 			module->remove(cell); | 			module->remove(cell); | ||||||
|  | @ -1526,8 +1526,11 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) | ||||||
| 			log_assert(index < GetSize(A)); | 			log_assert(index < GetSize(A)); | ||||||
| 			int i = 0; | 			int i = 0; | ||||||
| 			while (i < GetSize(mask)) { | 			while (i < GetSize(mask)) { | ||||||
| 				for (int j = 0; j < (1 << index); j++) | 				for (int j = 0; j < (1 << index); j++) { | ||||||
| 					std::swap(mask.bits()[i+j], mask.bits()[i+j+(1 << index)]); | 					State bit = mask[i+j]; | ||||||
|  | 					mask.set(i+j, mask[i+j+(1 << index)]); | ||||||
|  | 					mask.set(i+j+(1 << index), bit); | ||||||
|  | 				} | ||||||
| 				i += 1 << (index+1); | 				i += 1 << (index+1); | ||||||
| 			} | 			} | ||||||
| 			A[index] = y_bit; | 			A[index] = y_bit; | ||||||
|  | @ -1542,7 +1545,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) | ||||||
| 		// and get cleaned away
 | 		// and get cleaned away
 | ||||||
| clone_lut: | clone_lut: | ||||||
| 		driver_mask = driver_lut->getParam(ID::LUT); | 		driver_mask = driver_lut->getParam(ID::LUT); | ||||||
| 		for (auto &b : driver_mask.bits()) { | 		for (auto b : driver_mask) { | ||||||
| 			if (b == RTLIL::State::S0) b = RTLIL::State::S1; | 			if (b == RTLIL::State::S0) b = RTLIL::State::S1; | ||||||
| 			else if (b == RTLIL::State::S1) b = RTLIL::State::S0; | 			else if (b == RTLIL::State::S1) b = RTLIL::State::S0; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -118,13 +118,13 @@ struct DffinitPass : public Pass { | ||||||
| 					for (int i = 0; i < GetSize(sig); i++) { | 					for (int i = 0; i < GetSize(sig); i++) { | ||||||
| 						if (initval[i] == State::Sx) | 						if (initval[i] == State::Sx) | ||||||
| 							continue; | 							continue; | ||||||
| 						while (GetSize(value) <= i) | 						if (GetSize(value) <= i) | ||||||
| 							value.bits().push_back(State::S0); | 							value.resize(i + 1, State::S0); | ||||||
| 						if (noreinit && value[i] != State::Sx && value[i] != initval[i]) | 						if (noreinit && value[i] != State::Sx && value[i] != initval[i]) | ||||||
| 							log_error("Trying to assign a different init value for %s.%s.%s which technically " | 							log_error("Trying to assign a different init value for %s.%s.%s which technically " | ||||||
| 									"have a conflicted init value.\n", | 									"have a conflicted init value.\n", | ||||||
| 									log_id(module), log_id(cell), log_id(it.second)); | 									log_id(module), log_id(cell), log_id(it.second)); | ||||||
| 						value.bits()[i] = initval[i]; | 						value.set(i, initval[i]); | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					if (highlow_mode && GetSize(value) != 0) { | 					if (highlow_mode && GetSize(value) != 0) { | ||||||
|  |  | ||||||
|  | @ -869,17 +869,17 @@ struct DffLegalizePass : public Pass { | ||||||
| 			if (ff.has_arst) { | 			if (ff.has_arst) { | ||||||
| 				if (ff.val_arst[i] == State::Sx) { | 				if (ff.val_arst[i] == State::Sx) { | ||||||
| 					if (!(supported & (mask << 8))) | 					if (!(supported & (mask << 8))) | ||||||
| 						ff.val_arst.bits()[i] = State::S0; | 						ff.val_arst.set(i, State::S0); | ||||||
| 					if (!(supported & (mask << 4))) | 					if (!(supported & (mask << 4))) | ||||||
| 						ff.val_arst.bits()[i] = State::S1; | 						ff.val_arst.set(i, State::S1); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			if (ff.has_srst) { | 			if (ff.has_srst) { | ||||||
| 				if (ff.val_srst[i] == State::Sx) { | 				if (ff.val_srst[i] == State::Sx) { | ||||||
| 					if (!(supported & (mask << 8))) | 					if (!(supported & (mask << 8))) | ||||||
| 						ff.val_srst.bits()[i] = State::S0; | 						ff.val_srst.set(i, State::S0); | ||||||
| 					if (!(supported & (mask << 4))) | 					if (!(supported & (mask << 4))) | ||||||
| 						ff.val_srst.bits()[i] = State::S1; | 						ff.val_srst.set(i, State::S1); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -1401,7 +1401,7 @@ struct FlowmapWorker | ||||||
| 					          log_signal(node), log_signal(undef), env.c_str()); | 					          log_signal(node), log_signal(undef), env.c_str()); | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				lut_table.bits()[i] = value.as_bool() ? State::S1 : State::S0; | 				lut_table.set(i, value.as_bool() ? State::S1 : State::S0); | ||||||
| 				ce.pop(); | 				ce.pop(); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -680,15 +680,16 @@ struct TechmapWorker | ||||||
| 
 | 
 | ||||||
| 					for (auto &conn : cell->connections()) | 					for (auto &conn : cell->connections()) | ||||||
| 						if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first))) != 0) { | 						if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first))) != 0) { | ||||||
| 							RTLIL::Const value; | 							SigSpec sm = sigmap(conn.second); | ||||||
| 							for (auto &bit : sigmap(conn.second)) { | 							RTLIL::Const::Builder builder(GetSize(sm) * bits); | ||||||
|  | 							for (auto &bit : sm) { | ||||||
| 								int val = unique_bit_id.at(bit); | 								int val = unique_bit_id.at(bit); | ||||||
| 								for (int i = 0; i < bits; i++) { | 								for (int i = 0; i < bits; i++) { | ||||||
| 									value.bits().push_back((val & 1) != 0 ? State::S1 : State::S0); | 									builder.push_back((val & 1) != 0 ? State::S1 : State::S0); | ||||||
| 									val = val >> 1; | 									val = val >> 1; | ||||||
| 								} | 								} | ||||||
| 							} | 							} | ||||||
| 							parameters.emplace(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first)), value); | 							parameters.emplace(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first)), builder.build()); | ||||||
| 						} | 						} | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -76,7 +76,7 @@ struct ZinitPass : public Pass { | ||||||
| 					if (ff.val_init[i] == State::S1) | 					if (ff.val_init[i] == State::S1) | ||||||
| 						bits.insert(i); | 						bits.insert(i); | ||||||
| 					else if (ff.val_init[i] != State::S0 && all_mode) | 					else if (ff.val_init[i] != State::S0 && all_mode) | ||||||
| 						ff.val_init.bits()[i] = State::S0; | 						ff.val_init.set(i, State::S0); | ||||||
| 				} | 				} | ||||||
| 				ff.flip_bits(bits); | 				ff.flip_bits(bits); | ||||||
| 				ff.emit(); | 				ff.emit(); | ||||||
|  |  | ||||||
|  | @ -641,15 +641,16 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std:: | ||||||
| 			if (!gold_wire->port_input) | 			if (!gold_wire->port_input) | ||||||
| 				continue; | 				continue; | ||||||
| 
 | 
 | ||||||
| 			RTLIL::Const in_value; | 			RTLIL::Const::Builder in_value_builder(GetSize(gold_wire)); | ||||||
| 			for (int i = 0; i < GetSize(gold_wire); i++) | 			for (int i = 0; i < GetSize(gold_wire); i++) | ||||||
| 				in_value.bits().push_back(xorshift32(2) ? State::S1 : State::S0); | 				in_value_builder.push_back(xorshift32(2) ? State::S1 : State::S0); | ||||||
|  | 			RTLIL::Const in_value = in_value_builder.build(); | ||||||
| 
 | 
 | ||||||
| 			if (xorshift32(4) == 0) { | 			if (xorshift32(4) == 0) { | ||||||
| 				int inv_chance = 1 + xorshift32(8); | 				int inv_chance = 1 + xorshift32(8); | ||||||
| 				for (int i = 0; i < GetSize(gold_wire); i++) | 				for (int i = 0; i < GetSize(gold_wire); i++) | ||||||
| 					if (xorshift32(inv_chance) == 0) | 					if (xorshift32(inv_chance) == 0) | ||||||
| 						in_value.bits()[i] = RTLIL::Sx; | 						in_value.set(i, RTLIL::Sx); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			if (verbose) | 			if (verbose) | ||||||
|  |  | ||||||
|  | @ -82,7 +82,7 @@ struct FoldInvWorker { | ||||||
|         Const result(State::S0, GetSize(lut)); |         Const result(State::S0, GetSize(lut)); | ||||||
|         for (int i = 0; i < GetSize(lut); i++) { |         for (int i = 0; i < GetSize(lut); i++) { | ||||||
|             int j = i ^ (1 << bit); |             int j = i ^ (1 << bit); | ||||||
|             result.bits()[j] = lut[i]; |             result.set(j, lut[i]); | ||||||
|         } |         } | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
|  | @ -91,7 +91,7 @@ struct FoldInvWorker { | ||||||
|     { |     { | ||||||
|         Const result(State::S0, GetSize(lut)); |         Const result(State::S0, GetSize(lut)); | ||||||
|         for (int i = 0; i < GetSize(lut); i++) |         for (int i = 0; i < GetSize(lut); i++) | ||||||
|             result.bits()[i] = (lut[i] == State::S1) ? State::S0 : State::S1; |             result.set(i, (lut[i] == State::S1) ? State::S0 : State::S1); | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -36,9 +36,9 @@ void invert_gp_dff(Cell *cell, bool invert_input) | ||||||
| 		Const initval = cell->getParam(ID::INIT); | 		Const initval = cell->getParam(ID::INIT); | ||||||
| 		if (GetSize(initval) >= 1) { | 		if (GetSize(initval) >= 1) { | ||||||
| 			if (initval[0] == State::S0) | 			if (initval[0] == State::S0) | ||||||
| 				initval.bits()[0] = State::S1; | 				initval.set(0, State::S1); | ||||||
| 			else if (initval[0] == State::S1) | 			else if (initval[0] == State::S1) | ||||||
| 				initval.bits()[0] = State::S0; | 				initval.set(0, State::S0); | ||||||
| 			cell->setParam(ID::INIT, initval); | 			cell->setParam(ID::INIT, initval); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -47,9 +47,9 @@ void invert_gp_dff(Cell *cell, bool invert_input) | ||||||
| 			Const srmode = cell->getParam(ID(SRMODE)); | 			Const srmode = cell->getParam(ID(SRMODE)); | ||||||
| 			if (GetSize(srmode) >= 1) { | 			if (GetSize(srmode) >= 1) { | ||||||
| 				if (srmode[0] == State::S0) | 				if (srmode[0] == State::S0) | ||||||
| 					srmode.bits()[0] = State::S1; | 					srmode.set(0, State::S1); | ||||||
| 				else if (srmode[0] == State::S1) | 				else if (srmode[0] == State::S1) | ||||||
| 					srmode.bits()[0] = State::S0; | 					srmode.set(0, State::S0); | ||||||
| 				cell->setParam(ID(SRMODE), srmode); | 				cell->setParam(ID(SRMODE), srmode); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -82,7 +82,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) | ||||||
| 
 | 
 | ||||||
| 	SigSpec CD = st.sigCD; | 	SigSpec CD = st.sigCD; | ||||||
| 	if (CD.empty()) | 	if (CD.empty()) | ||||||
| 		CD = RTLIL::Const(0, 32); | 		CD = RTLIL::Const(0); | ||||||
| 	else | 	else | ||||||
| 		log_assert(GetSize(CD) == 32); | 		log_assert(GetSize(CD) == 32); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -93,7 +93,7 @@ bool merge_lut(LutData &result, const LutData &data, const LutData select, bool | ||||||
| 			int lut_idx = i >> idx_data & ((1 << GetSize(data.second)) - 1); | 			int lut_idx = i >> idx_data & ((1 << GetSize(data.second)) - 1); | ||||||
| 			new_bit = data.first[lut_idx] == State::S1; | 			new_bit = data.first[lut_idx] == State::S1; | ||||||
| 		} | 		} | ||||||
| 		result.first.bits()[i] = new_bit ? State::S1 : State::S0; | 		result.first.set(i, new_bit ? State::S1 : State::S0); | ||||||
| 	} | 	} | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -128,7 +128,7 @@ void microchip_dsp_pack(microchip_dsp_pm &pm) | ||||||
| 					continue; | 					continue; | ||||||
| 				for (int i = c.offset; i < c.offset + c.width; i++) { | 				for (int i = c.offset; i < c.offset + c.width; i++) { | ||||||
| 					log_assert(it->second[i] == State::S0 || it->second[i] == State::Sx); | 					log_assert(it->second[i] == State::S0 || it->second[i] == State::Sx); | ||||||
| 					it->second.bits()[i] = State::Sx; | 					it->second.set(i, State::Sx); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		}; | 		}; | ||||||
|  | @ -244,7 +244,7 @@ void microchip_dsp_packC(microchip_dsp_CREG_pm &pm) | ||||||
| 					continue; | 					continue; | ||||||
| 				for (int i = c.offset; i < c.offset + c.width; i++) { | 				for (int i = c.offset; i < c.offset + c.width; i++) { | ||||||
| 					log_assert(it->second[i] == State::S0 || it->second[i] == State::Sx); | 					log_assert(it->second[i] == State::S0 || it->second[i] == State::Sx); | ||||||
| 					it->second.bits()[i] = State::Sx; | 					it->second.set(i, State::Sx); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		}; | 		}; | ||||||
|  |  | ||||||
|  | @ -45,7 +45,7 @@ struct QlBramMergeWorker { | ||||||
| 		{ | 		{ | ||||||
| 			if(cell->type != split_cell_type) continue; | 			if(cell->type != split_cell_type) continue; | ||||||
| 			if(!cell->hasParam(ID(OPTION_SPLIT))) continue; | 			if(!cell->hasParam(ID(OPTION_SPLIT))) continue; | ||||||
| 			if(cell->getParam(ID(OPTION_SPLIT)) != RTLIL::Const(1, 32)) continue; | 			if(cell->getParam(ID(OPTION_SPLIT)) != RTLIL::Const(1)) continue; | ||||||
| 			mergeable_groups[get_key(cell)].insert(cell); | 			mergeable_groups[get_key(cell)].insert(cell); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -200,10 +200,8 @@ struct QlDspSimdPass : public Pass { | ||||||
| 						auto val_a = dsp_a->getParam(it); | 						auto val_a = dsp_a->getParam(it); | ||||||
| 						auto val_b = dsp_b->getParam(it); | 						auto val_b = dsp_b->getParam(it); | ||||||
| 
 | 
 | ||||||
| 						mode_bits.bits().insert(mode_bits.bits().end(), | 						mode_bits.append(val_a); | ||||||
| 							val_a.begin(), val_a.end()); | 						mode_bits.append(val_b); | ||||||
| 						mode_bits.bits().insert(mode_bits.bits().end(), |  | ||||||
| 							val_b.begin(), val_b.end()); |  | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					// Enable the fractured mode by connecting the control
 | 					// Enable the fractured mode by connecting the control
 | ||||||
|  |  | ||||||
|  | @ -92,7 +92,7 @@ bool merge_lut(LutData &result, const LutData &data, const LutData select, bool | ||||||
| 			int lut_idx = i >> idx_data & ((1 << GetSize(data.second)) - 1); | 			int lut_idx = i >> idx_data & ((1 << GetSize(data.second)) - 1); | ||||||
| 			new_bit = data.first[lut_idx] == State::S1; | 			new_bit = data.first[lut_idx] == State::S1; | ||||||
| 		} | 		} | ||||||
| 		result.first.bits()[i] = new_bit ? State::S1 : State::S0; | 		result.first.set(i, new_bit ? State::S1 : State::S0); | ||||||
| 	} | 	} | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  | @ -211,8 +211,8 @@ lut_sigin_done: | ||||||
| 				Cell *cell_d = it_D->second.second; | 				Cell *cell_d = it_D->second.second; | ||||||
| 				if (cell->hasParam(ID(IS_D_INVERTED)) && cell->getParam(ID(IS_D_INVERTED)).as_bool()) { | 				if (cell->hasParam(ID(IS_D_INVERTED)) && cell->getParam(ID(IS_D_INVERTED)).as_bool()) { | ||||||
| 					// Flip all bits in the LUT.
 | 					// Flip all bits in the LUT.
 | ||||||
| 					for (int i = 0; i < GetSize(lut_d.first); i++) | 					for (auto bit : lut_d.first) | ||||||
| 						lut_d.first.bits()[i] = (lut_d.first[i] == State::S1) ? State::S0 : State::S1; | 						bit = (bit == State::S1) ? State::S0 : State::S1; | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				LutData lut_d_post_ce; | 				LutData lut_d_post_ce; | ||||||
|  |  | ||||||
|  | @ -343,7 +343,7 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) | ||||||
| 			// Since B is an exact power of 2, subtract 1
 | 			// Since B is an exact power of 2, subtract 1
 | ||||||
| 			//   by inverting all bits up until hitting
 | 			//   by inverting all bits up until hitting
 | ||||||
| 			//   that one hi bit
 | 			//   that one hi bit
 | ||||||
| 			for (auto &b : B.bits()) | 			for (auto b : B) | ||||||
| 				if (b == State::S0) b = State::S1; | 				if (b == State::S0) b = State::S1; | ||||||
| 				else if (b == State::S1) { | 				else if (b == State::S1) { | ||||||
| 					b = State::S0; | 					b = State::S0; | ||||||
|  | @ -392,7 +392,7 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) | ||||||
| 					continue; | 					continue; | ||||||
| 				for (int i = c.offset; i < c.offset+c.width; i++) { | 				for (int i = c.offset; i < c.offset+c.width; i++) { | ||||||
| 					log_assert(it->second[i] == State::S0 || it->second[i] == State::Sx); | 					log_assert(it->second[i] == State::S0 || it->second[i] == State::Sx); | ||||||
| 					it->second.bits()[i] = State::Sx; | 					it->second.set(i, State::Sx); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		}; | 		}; | ||||||
|  | @ -579,7 +579,7 @@ void xilinx_dsp48a_pack(xilinx_dsp48a_pm &pm) | ||||||
| 					continue; | 					continue; | ||||||
| 				for (int i = c.offset; i < c.offset+c.width; i++) { | 				for (int i = c.offset; i < c.offset+c.width; i++) { | ||||||
| 					log_assert(it->second[i] == State::S0 || it->second[i] == State::Sx); | 					log_assert(it->second[i] == State::S0 || it->second[i] == State::Sx); | ||||||
| 					it->second.bits()[i] = State::Sx; | 					it->second.set(i, State::Sx); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		}; | 		}; | ||||||
|  | @ -702,7 +702,7 @@ void xilinx_dsp_packC(xilinx_dsp_CREG_pm &pm) | ||||||
| 					continue; | 					continue; | ||||||
| 				for (int i = c.offset; i < c.offset+c.width; i++) { | 				for (int i = c.offset; i < c.offset+c.width; i++) { | ||||||
| 					log_assert(it->second[i] == State::S0 || it->second[i] == State::Sx); | 					log_assert(it->second[i] == State::S0 || it->second[i] == State::Sx); | ||||||
| 					it->second.bits()[i] = State::Sx; | 					it->second.set(i, State::Sx); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		}; | 		}; | ||||||
|  |  | ||||||
|  | @ -40,9 +40,8 @@ void run_fixed(xilinx_srl_pm &pm) | ||||||
| 			log_assert(Q.wire); | 			log_assert(Q.wire); | ||||||
| 			auto it = Q.wire->attributes.find(ID::init); | 			auto it = Q.wire->attributes.find(ID::init); | ||||||
| 			if (it != Q.wire->attributes.end()) { | 			if (it != Q.wire->attributes.end()) { | ||||||
| 				auto &i = it->second.bits()[Q.offset]; | 				initval.append(it->second[Q.offset]); | ||||||
| 				initval.append(i); | 				it->second.set(Q.offset, State::Sx); | ||||||
| 				i = State::Sx; |  | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 				initval.append(State::Sx); | 				initval.append(State::Sx); | ||||||
|  | @ -121,9 +120,8 @@ void run_variable(xilinx_srl_pm &pm) | ||||||
| 			log_assert(Q.wire); | 			log_assert(Q.wire); | ||||||
| 			auto it = Q.wire->attributes.find(ID::init); | 			auto it = Q.wire->attributes.find(ID::init); | ||||||
| 			if (it != Q.wire->attributes.end()) { | 			if (it != Q.wire->attributes.end()) { | ||||||
| 				auto &i = it->second.bits()[Q.offset]; | 				initval.append(it->second[Q.offset]); | ||||||
| 				initval.append(i); | 				it->second.set(Q.offset, State::Sx); | ||||||
| 				i = State::Sx; |  | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 				initval.append(State::Sx); | 				initval.append(State::Sx); | ||||||
|  |  | ||||||
|  | @ -80,14 +80,282 @@ namespace RTLIL { | ||||||
| 			EXPECT_EQ(i, 16); | 			EXPECT_EQ(i, 16); | ||||||
| 			EXPECT_TRUE(cs1.is_str()); | 			EXPECT_TRUE(cs1.is_str()); | ||||||
| 
 | 
 | ||||||
| 			// It can be mutated with the bits() view
 | 			// It can be mutated via bit iteration and decays into unpacked
 | ||||||
| 			// and decays into unpacked
 | 			// when an non-defined bit is set.
 | ||||||
| 			for (auto& bit : cs1.bits()) { | 			for (auto b : cs1) { | ||||||
| 				bit = State::Sx; | 				b = State::Sx; | ||||||
| 			} | 			} | ||||||
| 			EXPECT_TRUE(cs1.is_bits()); | 			EXPECT_TRUE(cs1.is_bits()); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		{ | ||||||
|  | 			Const c(0x12345678); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 			EXPECT_EQ(c.as_int(), 0x12345678); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		{ | ||||||
|  | 			Const c(0xab, 8); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 			EXPECT_EQ(c.as_int(), 0xab); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		{ | ||||||
|  | 			Const c(0x12345678, 80); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 			EXPECT_EQ(c.as_int(), 0x12345678); | ||||||
|  | 			EXPECT_EQ(c[79], S0); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		{ | ||||||
|  | 			Const c(-1, 80); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 			EXPECT_EQ(c.as_int(), -1); | ||||||
|  | 			EXPECT_EQ(c[79], S1); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		{ | ||||||
|  | 			Const c(1 << 24); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 			EXPECT_TRUE(c.as_bool()); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		{ | ||||||
|  | 			Const c(0x2, 8); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 			EXPECT_EQ(c.as_string(), "00000010"); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		{ | ||||||
|  | 			Const c(" "); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 			EXPECT_EQ(c.decode_string(), " "); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		{ | ||||||
|  | 			Const c(" "); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 			EXPECT_EQ(c.decode_string(), " "); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		{ | ||||||
|  | 			std::vector<State> v = {S0, S0, S0, S0, S0, S1, S0, S0}; | ||||||
|  | 			Const c(v); | ||||||
|  | 			EXPECT_EQ(c.decode_string(), " "); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		{ | ||||||
|  | 			std::vector<State> v = {S0, S0, S0, S0, S0, S1, S0, Sx}; | ||||||
|  | 			Const c(v); | ||||||
|  | 			EXPECT_EQ(c.decode_string(), " "); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		{ | ||||||
|  | 			Const c(" "); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 			EXPECT_FALSE(c.is_fully_zero()); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		{ | ||||||
|  | 			Const c(" "); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 			EXPECT_FALSE(c.is_fully_ones()); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		{ | ||||||
|  | 			Const c(" "); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 			EXPECT_TRUE(c.is_fully_def()); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		{ | ||||||
|  | 			Const c(" "); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 			EXPECT_FALSE(c.is_fully_undef()); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		{ | ||||||
|  | 			Const c(" "); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 			EXPECT_FALSE(c.is_fully_undef_x_only()); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		{ | ||||||
|  | 			Const c(" "); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 			int pos; | ||||||
|  | 			EXPECT_TRUE(c.is_onehot(&pos)); | ||||||
|  | 			EXPECT_EQ(pos, 5); | ||||||
|  | 			EXPECT_TRUE(c.is_str()); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	TEST_F(KernelRtlilTest, ConstConstIteratorWorks) { | ||||||
|  | 		const Const c(0x2, 2); | ||||||
|  | 		Const::const_iterator it = c.begin(); | ||||||
|  | 		ASSERT_NE(it, c.end()); | ||||||
|  | 		EXPECT_EQ(*it, State::S0); | ||||||
|  | 		++it; | ||||||
|  | 		ASSERT_NE(it, c.end()); | ||||||
|  | 		EXPECT_EQ(*it, State::S1); | ||||||
|  | 		++it; | ||||||
|  | 		EXPECT_EQ(it, c.end()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	TEST_F(KernelRtlilTest, ConstConstIteratorPreincrement) { | ||||||
|  | 		const Const c(0x2, 2); | ||||||
|  | 		Const::const_iterator it = c.begin(); | ||||||
|  | 		EXPECT_EQ(*++it, State::S1); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	TEST_F(KernelRtlilTest, ConstConstIteratorPostincrement) { | ||||||
|  | 		const Const c(0x2, 2); | ||||||
|  | 		Const::const_iterator it = c.begin(); | ||||||
|  | 		EXPECT_EQ(*it++, State::S0); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	TEST_F(KernelRtlilTest, ConstIteratorWorks) { | ||||||
|  | 		Const c(0x2, 2); | ||||||
|  | 		Const::iterator it = c.begin(); | ||||||
|  | 		ASSERT_NE(it, c.end()); | ||||||
|  | 		EXPECT_EQ(*it, State::S0); | ||||||
|  | 		++it; | ||||||
|  | 		ASSERT_NE(it, c.end()); | ||||||
|  | 		EXPECT_EQ(*it, State::S1); | ||||||
|  | 		++it; | ||||||
|  | 		ASSERT_EQ(it, c.end()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	TEST_F(KernelRtlilTest, ConstIteratorPreincrement) { | ||||||
|  | 		Const c(0x2, 2); | ||||||
|  | 		Const::iterator it = c.begin(); | ||||||
|  | 		EXPECT_EQ(*++it, State::S1); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	TEST_F(KernelRtlilTest, ConstIteratorPostincrement) { | ||||||
|  | 		Const c(0x2, 2); | ||||||
|  | 		Const::iterator it = c.begin(); | ||||||
|  | 		EXPECT_EQ(*it++, State::S0); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	TEST_F(KernelRtlilTest, ConstIteratorWriteWorks) { | ||||||
|  | 		Const c(0x2, 2); | ||||||
|  | 		Const::iterator it = c.begin(); | ||||||
|  | 		EXPECT_EQ(*it, State::S0); | ||||||
|  | 		*it = State::S1; | ||||||
|  | 		EXPECT_EQ(*it, State::S1); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	TEST_F(KernelRtlilTest, ConstBuilder) { | ||||||
|  | 		Const::Builder b; | ||||||
|  | 		EXPECT_EQ(GetSize(b), 0); | ||||||
|  | 		b.push_back(S0); | ||||||
|  | 		EXPECT_EQ(GetSize(b), 1); | ||||||
|  | 		b.push_back(S1); | ||||||
|  | 		EXPECT_EQ(GetSize(b), 2); | ||||||
|  | 		EXPECT_EQ(b.build(), Const(0x2, 2)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	TEST_F(KernelRtlilTest, ConstSet) { | ||||||
|  | 		Const c(0x2, 2); | ||||||
|  | 		c.set(0, S1); | ||||||
|  | 		EXPECT_EQ(c, Const(0x3, 2)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	TEST_F(KernelRtlilTest, ConstResize) { | ||||||
|  | 		Const c(0x2, 2); | ||||||
|  | 		c.resize(4, S1); | ||||||
|  | 		EXPECT_EQ(c, Const(0xe, 4)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	TEST_F(KernelRtlilTest, ConstEqualStr) { | ||||||
|  | 		EXPECT_EQ(Const("abc"), Const("abc")); | ||||||
|  | 		EXPECT_NE(Const("abc"), Const("def")); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	TEST_F(KernelRtlilTest, ConstEqualBits) { | ||||||
|  | 		std::vector<State> v1 = {S0, S1}; | ||||||
|  | 		std::vector<State> v2 = {S1, S0}; | ||||||
|  | 		EXPECT_EQ(Const(v1), Const(v1)); | ||||||
|  | 		EXPECT_NE(Const(v1), Const(v2)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	TEST_F(KernelRtlilTest, ConstEqualStrBits) { | ||||||
|  | 		std::vector<State> v1 = {S0, S0, S0, S0, S0, S1, S0, S0}; | ||||||
|  | 		EXPECT_EQ(Const(v1), Const(" ")); | ||||||
|  | 		EXPECT_NE(Const(v1), Const("a")); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	static Hasher::hash_t hash(const Const &c) { | ||||||
|  | 		Hasher h; | ||||||
|  | 		h = c.hash_into(h); | ||||||
|  | 		return h.yield(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	TEST_F(KernelRtlilTest, ConstEqualHashStrBits) { | ||||||
|  | 		std::vector<State> v1 = {S0, S0, S0, S0, S0, S1, S0, S0}; | ||||||
|  | 		EXPECT_EQ(hash(Const(v1)), hash(Const(" "))); | ||||||
|  | 		EXPECT_NE(hash(Const(v1)), hash(Const("a"))); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	TEST_F(KernelRtlilTest, ConstIsFullyZero) { | ||||||
|  | 		EXPECT_TRUE(Const(0, 8).is_fully_zero()); | ||||||
|  | 		EXPECT_FALSE(Const(8, 8).is_fully_zero()); | ||||||
|  | 		EXPECT_TRUE(Const().is_fully_zero()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	TEST_F(KernelRtlilTest, ConstIsFullyOnes) { | ||||||
|  | 		EXPECT_TRUE(Const(0xf, 4).is_fully_ones()); | ||||||
|  | 		EXPECT_FALSE(Const(3, 4).is_fully_ones()); | ||||||
|  | 		EXPECT_TRUE(Const().is_fully_ones()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	TEST_F(KernelRtlilTest, ConstIsFullyDef) { | ||||||
|  | 		EXPECT_TRUE(Const(0xf, 4).is_fully_def()); | ||||||
|  | 		std::vector<State> v1 = {S0, Sx}; | ||||||
|  | 		EXPECT_FALSE(Const(v1).is_fully_def()); | ||||||
|  | 		EXPECT_TRUE(Const().is_fully_def()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	TEST_F(KernelRtlilTest, ConstIsFullyUndef) { | ||||||
|  | 		std::vector<State> v1 = {S0, Sx}; | ||||||
|  | 		EXPECT_FALSE(Const(v1).is_fully_undef()); | ||||||
|  | 		EXPECT_TRUE(Const(Sz, 2).is_fully_undef()); | ||||||
|  | 		EXPECT_TRUE(Const().is_fully_undef()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	TEST_F(KernelRtlilTest, ConstIsFullyUndefXOnly) { | ||||||
|  | 		std::vector<State> v1 = {Sx, Sz}; | ||||||
|  | 		EXPECT_FALSE(Const(v1).is_fully_undef_x_only()); | ||||||
|  | 		EXPECT_TRUE(Const(Sx, 2).is_fully_undef_x_only()); | ||||||
|  | 		EXPECT_TRUE(Const().is_fully_undef_x_only()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	TEST_F(KernelRtlilTest, ConstIsOnehot) { | ||||||
|  | 		int pos; | ||||||
|  | 		EXPECT_TRUE(Const(0x80, 8).is_onehot(&pos)); | ||||||
|  | 		EXPECT_EQ(pos, 7); | ||||||
|  | 		EXPECT_FALSE(Const(0x82, 8).is_onehot(&pos)); | ||||||
|  | 		EXPECT_FALSE(Const(0, 8).is_onehot(&pos)); | ||||||
|  | 		EXPECT_TRUE(Const(1, 1).is_onehot(&pos)); | ||||||
|  | 		EXPECT_EQ(pos, 0); | ||||||
|  | 		EXPECT_FALSE(Const(Sx, 1).is_onehot(&pos)); | ||||||
|  | 		std::vector<State> v1 = {Sx, S1}; | ||||||
|  | 		EXPECT_FALSE(Const(v1).is_onehot(&pos)); | ||||||
|  | 		EXPECT_FALSE(Const().is_onehot(&pos)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	class WireRtlVsHdlIndexConversionTest : | 	class WireRtlVsHdlIndexConversionTest : | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue