mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 13:29:12 +00:00 
			
		
		
		
	Add <modname>_init() function generator to simpleC back-end
This commit is contained in:
		
							parent
							
								
									35be567605
								
							
						
					
					
						commit
						9f4fbc5e74
					
				
					 2 changed files with 152 additions and 88 deletions
				
			
		| 
						 | 
				
			
			@ -26,6 +26,40 @@ PRIVATE_NAMESPACE_BEGIN
 | 
			
		|||
 | 
			
		||||
struct HierDirtyFlags;
 | 
			
		||||
 | 
			
		||||
static pool<string> reserved_cids;
 | 
			
		||||
static dict<IdString, string> id2cid;
 | 
			
		||||
 | 
			
		||||
static string cid(IdString id)
 | 
			
		||||
{
 | 
			
		||||
	if (id2cid.count(id) == 0)
 | 
			
		||||
	{
 | 
			
		||||
		string s = id.str();
 | 
			
		||||
		if (GetSize(s) < 2) log_abort();
 | 
			
		||||
 | 
			
		||||
		if (s[0] == '\\')
 | 
			
		||||
			s = s.substr(1);
 | 
			
		||||
 | 
			
		||||
		if ('0' <= s[0] && s[0] <= '9') {
 | 
			
		||||
			s = "_" + s;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for (int i = 0; i < GetSize(s); i++) {
 | 
			
		||||
			if ('0' <= s[i] && s[i] <= '9') continue;
 | 
			
		||||
			if ('A' <= s[i] && s[i] <= 'Z') continue;
 | 
			
		||||
			if ('a' <= s[i] && s[i] <= 'z') continue;
 | 
			
		||||
			s[i] = '_';
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		while (reserved_cids.count(s))
 | 
			
		||||
			s += "_";
 | 
			
		||||
 | 
			
		||||
		reserved_cids.insert(s);
 | 
			
		||||
		id2cid[id] = s;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return id2cid.at(id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct HierDirtyFlags
 | 
			
		||||
{
 | 
			
		||||
	int dirty;
 | 
			
		||||
| 
						 | 
				
			
			@ -36,12 +70,15 @@ struct HierDirtyFlags
 | 
			
		|||
	pool<Cell*> dirty_cells;
 | 
			
		||||
	pool<SigBit> sticky_dirty_bits;
 | 
			
		||||
	dict<IdString, HierDirtyFlags*> children;
 | 
			
		||||
	string prefix, log_prefix;
 | 
			
		||||
 | 
			
		||||
	HierDirtyFlags(Module *module, IdString hiername, HierDirtyFlags *parent) : dirty(0), module(module), hiername(hiername), parent(parent)
 | 
			
		||||
	HierDirtyFlags(Module *module, IdString hiername, HierDirtyFlags *parent, const string &prefix, const string &log_prefix) :
 | 
			
		||||
			dirty(0), module(module), hiername(hiername), parent(parent), prefix(prefix), log_prefix(log_prefix)
 | 
			
		||||
	{
 | 
			
		||||
		for (Cell *cell : module->cells()) {
 | 
			
		||||
			Module *mod = module->design->module(cell->type);
 | 
			
		||||
			if (mod) children[cell->name] = new HierDirtyFlags(mod, cell->name, this);
 | 
			
		||||
			if (mod) children[cell->name] = new HierDirtyFlags(mod, cell->name, this,
 | 
			
		||||
					prefix + cid(cell->name) + ".", log_prefix + "." + prefix + log_id(cell->name));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -130,11 +167,9 @@ struct SimplecWorker
 | 
			
		|||
 | 
			
		||||
	vector<string> funct_declarations;
 | 
			
		||||
 | 
			
		||||
	pool<string> reserved_cids;
 | 
			
		||||
	dict<IdString, string> id2cid;
 | 
			
		||||
 | 
			
		||||
	dict<Module*, dict<SigBit, pool<tuple<Cell*, IdString, int>>>> bit2cell;
 | 
			
		||||
	dict<Module*, dict<SigBit, pool<SigBit>>> bit2output;
 | 
			
		||||
	dict<Module*, pool<SigBit>> driven_bits;
 | 
			
		||||
 | 
			
		||||
	dict<Cell*, int> topoidx;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -247,37 +282,6 @@ struct SimplecWorker
 | 
			
		|||
		return stringf("  %s(&%s, %s);", util_name.c_str(), signame.c_str(), expr.c_str());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	string cid(IdString id)
 | 
			
		||||
	{
 | 
			
		||||
		if (id2cid.count(id) == 0)
 | 
			
		||||
		{
 | 
			
		||||
			string s = id.str();
 | 
			
		||||
			if (GetSize(s) < 2) log_abort();
 | 
			
		||||
 | 
			
		||||
			if (s[0] == '\\')
 | 
			
		||||
				s = s.substr(1);
 | 
			
		||||
 | 
			
		||||
			if ('0' <= s[0] && s[0] <= '9') {
 | 
			
		||||
				s = "_" + s;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for (int i = 0; i < GetSize(s); i++) {
 | 
			
		||||
				if ('0' <= s[i] && s[i] <= '9') continue;
 | 
			
		||||
				if ('A' <= s[i] && s[i] <= 'Z') continue;
 | 
			
		||||
				if ('a' <= s[i] && s[i] <= 'z') continue;
 | 
			
		||||
				s[i] = '_';
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			while (reserved_cids.count(s))
 | 
			
		||||
				s += "_";
 | 
			
		||||
 | 
			
		||||
			reserved_cids.insert(s);
 | 
			
		||||
			id2cid[id] = s;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return id2cid.at(id);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void create_module_struct(Module *mod)
 | 
			
		||||
	{
 | 
			
		||||
		if (generated_structs.count(mod->name))
 | 
			
		||||
| 
						 | 
				
			
			@ -297,8 +301,11 @@ struct SimplecWorker
 | 
			
		|||
		{
 | 
			
		||||
			for (auto &conn : c->connections())
 | 
			
		||||
			{
 | 
			
		||||
				if (!c->input(conn.first))
 | 
			
		||||
				if (!c->input(conn.first)) {
 | 
			
		||||
					for (auto bit : sigmaps.at(mod)(conn.second))
 | 
			
		||||
						driven_bits[mod].insert(bit);
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				int idx = 0;
 | 
			
		||||
				for (auto bit : sigmaps.at(mod)(conn.second))
 | 
			
		||||
| 
						 | 
				
			
			@ -369,21 +376,21 @@ struct SimplecWorker
 | 
			
		|||
		struct_declarations.push_back("#endif");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void eval_cell(HierDirtyFlags *work, const string &prefix, const string &/* log_prefix */, Cell *cell)
 | 
			
		||||
	void eval_cell(HierDirtyFlags *work, Cell *cell)
 | 
			
		||||
	{
 | 
			
		||||
		if (cell->type.in("$_BUF_", "$_NOT_"))
 | 
			
		||||
		{
 | 
			
		||||
			SigBit a = sigmaps.at(work->module)(cell->getPort("\\A"));
 | 
			
		||||
			SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y"));
 | 
			
		||||
 | 
			
		||||
			string a_expr = a.wire ? util_get_bit(prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0";
 | 
			
		||||
			string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0";
 | 
			
		||||
			string expr;
 | 
			
		||||
 | 
			
		||||
			if (cell->type == "$_BUF_")  expr = a_expr;
 | 
			
		||||
			if (cell->type == "$_NOT_")  expr = "!" + a_expr;
 | 
			
		||||
 | 
			
		||||
			log_assert(y.wire);
 | 
			
		||||
			funct_declarations.push_back(util_set_bit(prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
 | 
			
		||||
			funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
 | 
			
		||||
					stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
 | 
			
		||||
 | 
			
		||||
			work->set_dirty(y);
 | 
			
		||||
| 
						 | 
				
			
			@ -396,8 +403,8 @@ struct SimplecWorker
 | 
			
		|||
			SigBit b = sigmaps.at(work->module)(cell->getPort("\\B"));
 | 
			
		||||
			SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y"));
 | 
			
		||||
 | 
			
		||||
			string a_expr = a.wire ? util_get_bit(prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0";
 | 
			
		||||
			string b_expr = b.wire ? util_get_bit(prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0";
 | 
			
		||||
			string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0";
 | 
			
		||||
			string b_expr = b.wire ? util_get_bit(work->prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0";
 | 
			
		||||
			string expr;
 | 
			
		||||
 | 
			
		||||
			if (cell->type == "$_AND_")  expr = stringf("%s & %s",    a_expr.c_str(), b_expr.c_str());
 | 
			
		||||
| 
						 | 
				
			
			@ -408,7 +415,7 @@ struct SimplecWorker
 | 
			
		|||
			if (cell->type == "$_XNOR_") expr = stringf("!(%s ^ %s)", a_expr.c_str(), b_expr.c_str());
 | 
			
		||||
 | 
			
		||||
			log_assert(y.wire);
 | 
			
		||||
			funct_declarations.push_back(util_set_bit(prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
 | 
			
		||||
			funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
 | 
			
		||||
					stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
 | 
			
		||||
 | 
			
		||||
			work->set_dirty(y);
 | 
			
		||||
| 
						 | 
				
			
			@ -422,16 +429,16 @@ struct SimplecWorker
 | 
			
		|||
			SigBit c = sigmaps.at(work->module)(cell->getPort("\\C"));
 | 
			
		||||
			SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y"));
 | 
			
		||||
 | 
			
		||||
			string a_expr = a.wire ? util_get_bit(prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0";
 | 
			
		||||
			string b_expr = b.wire ? util_get_bit(prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0";
 | 
			
		||||
			string c_expr = c.wire ? util_get_bit(prefix + cid(c.wire->name), c.wire->width, c.offset) : c.data ? "1" : "0";
 | 
			
		||||
			string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0";
 | 
			
		||||
			string b_expr = b.wire ? util_get_bit(work->prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0";
 | 
			
		||||
			string c_expr = c.wire ? util_get_bit(work->prefix + cid(c.wire->name), c.wire->width, c.offset) : c.data ? "1" : "0";
 | 
			
		||||
			string expr;
 | 
			
		||||
 | 
			
		||||
			if (cell->type == "$_AOI3_") expr = stringf("!((%s & %s) | %s)", a_expr.c_str(), b_expr.c_str(), c_expr.c_str());
 | 
			
		||||
			if (cell->type == "$_OAI3_") expr = stringf("!((%s | %s) & %s)", a_expr.c_str(), b_expr.c_str(), c_expr.c_str());
 | 
			
		||||
 | 
			
		||||
			log_assert(y.wire);
 | 
			
		||||
			funct_declarations.push_back(util_set_bit(prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
 | 
			
		||||
			funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
 | 
			
		||||
					stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
 | 
			
		||||
 | 
			
		||||
			work->set_dirty(y);
 | 
			
		||||
| 
						 | 
				
			
			@ -446,17 +453,17 @@ struct SimplecWorker
 | 
			
		|||
			SigBit d = sigmaps.at(work->module)(cell->getPort("\\D"));
 | 
			
		||||
			SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y"));
 | 
			
		||||
 | 
			
		||||
			string a_expr = a.wire ? util_get_bit(prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0";
 | 
			
		||||
			string b_expr = b.wire ? util_get_bit(prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0";
 | 
			
		||||
			string c_expr = c.wire ? util_get_bit(prefix + cid(c.wire->name), c.wire->width, c.offset) : c.data ? "1" : "0";
 | 
			
		||||
			string d_expr = d.wire ? util_get_bit(prefix + cid(d.wire->name), d.wire->width, d.offset) : d.data ? "1" : "0";
 | 
			
		||||
			string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0";
 | 
			
		||||
			string b_expr = b.wire ? util_get_bit(work->prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0";
 | 
			
		||||
			string c_expr = c.wire ? util_get_bit(work->prefix + cid(c.wire->name), c.wire->width, c.offset) : c.data ? "1" : "0";
 | 
			
		||||
			string d_expr = d.wire ? util_get_bit(work->prefix + cid(d.wire->name), d.wire->width, d.offset) : d.data ? "1" : "0";
 | 
			
		||||
			string expr;
 | 
			
		||||
 | 
			
		||||
			if (cell->type == "$_AOI4_") expr = stringf("!((%s & %s) | (%s & %s))", a_expr.c_str(), b_expr.c_str(), c_expr.c_str(), d_expr.c_str());
 | 
			
		||||
			if (cell->type == "$_OAI4_") expr = stringf("!((%s | %s) & (%s | %s))", a_expr.c_str(), b_expr.c_str(), c_expr.c_str(), d_expr.c_str());
 | 
			
		||||
 | 
			
		||||
			log_assert(y.wire);
 | 
			
		||||
			funct_declarations.push_back(util_set_bit(prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
 | 
			
		||||
			funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
 | 
			
		||||
					stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
 | 
			
		||||
 | 
			
		||||
			work->set_dirty(y);
 | 
			
		||||
| 
						 | 
				
			
			@ -470,13 +477,13 @@ struct SimplecWorker
 | 
			
		|||
			SigBit s = sigmaps.at(work->module)(cell->getPort("\\S"));
 | 
			
		||||
			SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y"));
 | 
			
		||||
 | 
			
		||||
			string a_expr = a.wire ? util_get_bit(prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0";
 | 
			
		||||
			string b_expr = b.wire ? util_get_bit(prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0";
 | 
			
		||||
			string s_expr = s.wire ? util_get_bit(prefix + cid(s.wire->name), s.wire->width, s.offset) : s.data ? "1" : "0";
 | 
			
		||||
			string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0";
 | 
			
		||||
			string b_expr = b.wire ? util_get_bit(work->prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0";
 | 
			
		||||
			string s_expr = s.wire ? util_get_bit(work->prefix + cid(s.wire->name), s.wire->width, s.offset) : s.data ? "1" : "0";
 | 
			
		||||
			string expr = stringf("%s ? %s : %s", s_expr.c_str(), b_expr.c_str(), a_expr.c_str());
 | 
			
		||||
 | 
			
		||||
			log_assert(y.wire);
 | 
			
		||||
			funct_declarations.push_back(util_set_bit(prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
 | 
			
		||||
			funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
 | 
			
		||||
					stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
 | 
			
		||||
 | 
			
		||||
			work->set_dirty(y);
 | 
			
		||||
| 
						 | 
				
			
			@ -486,12 +493,12 @@ struct SimplecWorker
 | 
			
		|||
		log_error("No C model for %s available at the moment (FIXME).\n", log_id(cell->type));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void eval_dirty(HierDirtyFlags *work, const string &prefix, const string &log_prefix, const string &parent_prefix, const string &parent_log_prefix)
 | 
			
		||||
	void eval_dirty(HierDirtyFlags *work)
 | 
			
		||||
	{
 | 
			
		||||
		while (work->dirty)
 | 
			
		||||
		{
 | 
			
		||||
			if (verbose && (!work->dirty_bits.empty() || !work->dirty_cells.empty()))
 | 
			
		||||
				log("  In %s:\n", log_prefix.c_str());
 | 
			
		||||
				log("  In %s:\n", work->log_prefix.c_str());
 | 
			
		||||
 | 
			
		||||
			while (!work->dirty_bits.empty() || !work->dirty_cells.empty())
 | 
			
		||||
			{
 | 
			
		||||
| 
						 | 
				
			
			@ -501,9 +508,11 @@ struct SimplecWorker
 | 
			
		|||
					dirtysig.sort_and_unify();
 | 
			
		||||
 | 
			
		||||
					for (SigChunk chunk : dirtysig.chunks()) {
 | 
			
		||||
						if (chunk.wire == nullptr)
 | 
			
		||||
							continue;
 | 
			
		||||
						if (verbose)
 | 
			
		||||
							log("    Propagating %s.%s[%d:%d].\n", log_prefix.c_str(), log_id(chunk.wire), chunk.offset+chunk.width-1, chunk.offset);
 | 
			
		||||
						funct_declarations.push_back(stringf("  // Updated signal in %s: %s", log_prefix.c_str(), log_signal(chunk)));
 | 
			
		||||
							log("    Propagating %s.%s[%d:%d].\n", work->log_prefix.c_str(), log_id(chunk.wire), chunk.offset+chunk.width-1, chunk.offset);
 | 
			
		||||
						funct_declarations.push_back(stringf("  // Updated signal in %s: %s", work->log_prefix.c_str(), log_signal(chunk)));
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					for (SigBit bit : dirtysig)
 | 
			
		||||
| 
						 | 
				
			
			@ -519,13 +528,13 @@ struct SimplecWorker
 | 
			
		|||
								SigBit parent_bit = sigmaps.at(parent_mod)(parent_cell->getPort(port_name)[port_offset]);
 | 
			
		||||
 | 
			
		||||
								log_assert(bit.wire && parent_bit.wire);
 | 
			
		||||
								funct_declarations.push_back(util_set_bit(parent_prefix + cid(parent_bit.wire->name), parent_bit.wire->width, parent_bit.offset,
 | 
			
		||||
										util_get_bit(prefix + cid(bit.wire->name), bit.wire->width, bit.offset)));
 | 
			
		||||
								funct_declarations.push_back(util_set_bit(work->parent->prefix + cid(parent_bit.wire->name), parent_bit.wire->width, parent_bit.offset,
 | 
			
		||||
										util_get_bit(work->prefix + cid(bit.wire->name), bit.wire->width, bit.offset)));
 | 
			
		||||
								work->parent->set_dirty(parent_bit);
 | 
			
		||||
 | 
			
		||||
								if (verbose)
 | 
			
		||||
									log("      Propagating %s.%s[%d] -> %s.%s[%d].\n", log_prefix.c_str(), log_id(bit.wire), bit.offset,
 | 
			
		||||
											parent_log_prefix.c_str(), log_id(parent_bit.wire), parent_bit.offset);
 | 
			
		||||
									log("      Propagating %s.%s[%d] -> %s.%s[%d].\n", work->log_prefix.c_str(), log_id(bit.wire), bit.offset,
 | 
			
		||||
											work->parent->log_prefix.c_str(), log_id(parent_bit.wire), parent_bit.offset);
 | 
			
		||||
							}
 | 
			
		||||
 | 
			
		||||
						for (auto &port : bit2cell[work->module][bit])
 | 
			
		||||
| 
						 | 
				
			
			@ -536,17 +545,17 @@ struct SimplecWorker
 | 
			
		|||
								SigBit child_bit = sigmaps.at(child->module)(SigBit(child->module->wire(std::get<1>(port)), std::get<2>(port)));
 | 
			
		||||
								log_assert(bit.wire && child_bit.wire);
 | 
			
		||||
 | 
			
		||||
								funct_declarations.push_back(util_set_bit(prefix + cid(child->hiername) + "." + cid(child_bit.wire->name),
 | 
			
		||||
										child_bit.wire->width, child_bit.offset, util_get_bit(prefix + cid(bit.wire->name), bit.wire->width, bit.offset)));
 | 
			
		||||
								funct_declarations.push_back(util_set_bit(work->prefix + cid(child->hiername) + "." + cid(child_bit.wire->name),
 | 
			
		||||
										child_bit.wire->width, child_bit.offset, util_get_bit(work->prefix + cid(bit.wire->name), bit.wire->width, bit.offset)));
 | 
			
		||||
								child->set_dirty(child_bit);
 | 
			
		||||
 | 
			
		||||
								if (verbose)
 | 
			
		||||
									log("      Propagating %s.%s[%d] -> %s.%s.%s[%d].\n", log_prefix.c_str(), log_id(bit.wire), bit.offset,
 | 
			
		||||
											log_prefix.c_str(), log_id(std::get<0>(port)), log_id(child_bit.wire), child_bit.offset);
 | 
			
		||||
									log("      Propagating %s.%s[%d] -> %s.%s.%s[%d].\n", work->log_prefix.c_str(), log_id(bit.wire), bit.offset,
 | 
			
		||||
											work->log_prefix.c_str(), log_id(std::get<0>(port)), log_id(child_bit.wire), child_bit.offset);
 | 
			
		||||
							} else {
 | 
			
		||||
								if (verbose)
 | 
			
		||||
									log("      Marking cell %s.%s (via %s.%s[%d]).\n", log_prefix.c_str(), log_id(std::get<0>(port)),
 | 
			
		||||
											log_prefix.c_str(), log_id(bit.wire), bit.offset);
 | 
			
		||||
									log("      Marking cell %s.%s (via %s.%s[%d]).\n", work->log_prefix.c_str(), log_id(std::get<0>(port)),
 | 
			
		||||
											work->log_prefix.c_str(), log_id(bit.wire), bit.offset);
 | 
			
		||||
								work->set_dirty(std::get<0>(port));
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
| 
						 | 
				
			
			@ -561,7 +570,7 @@ struct SimplecWorker
 | 
			
		|||
						if (cell == nullptr || topoidx.at(cell) < topoidx.at(c))
 | 
			
		||||
							cell = c;
 | 
			
		||||
 | 
			
		||||
					string hiername = log_prefix + "." + log_id(cell);
 | 
			
		||||
					string hiername = work->log_prefix + "." + log_id(cell);
 | 
			
		||||
 | 
			
		||||
					if (verbose)
 | 
			
		||||
						log("    Evaluating %s (%s, best of %d).\n", hiername.c_str(), log_id(cell->type), GetSize(work->dirty_cells));
 | 
			
		||||
| 
						 | 
				
			
			@ -570,17 +579,17 @@ struct SimplecWorker
 | 
			
		|||
						reactivated_cells.insert(hiername);
 | 
			
		||||
					activated_cells.insert(hiername);
 | 
			
		||||
 | 
			
		||||
					eval_cell(work, prefix, log_prefix, cell);
 | 
			
		||||
					eval_cell(work, cell);
 | 
			
		||||
					work->unset_dirty(cell);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for (auto &child : work->children)
 | 
			
		||||
				eval_dirty(child.second, prefix + cid(child.first) + ".", log_prefix + "." + cid(child.first), prefix, log_prefix);
 | 
			
		||||
				eval_dirty(child.second);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void eval_sticky_dirty(HierDirtyFlags *work, const string &prefix, const string &log_prefix)
 | 
			
		||||
	void eval_sticky_dirty(HierDirtyFlags *work)
 | 
			
		||||
	{
 | 
			
		||||
		Module *mod = work->module;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -595,23 +604,25 @@ struct SimplecWorker
 | 
			
		|||
			if (work->sticky_dirty_bits.count(canonical_bit) == 0)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			log_assert(bit.wire && canonical_bit.wire);
 | 
			
		||||
			funct_declarations.push_back(util_set_bit(prefix + cid(bit.wire->name), bit.wire->width, bit.offset,
 | 
			
		||||
					util_get_bit(prefix + cid(canonical_bit.wire->name), canonical_bit.wire->width, canonical_bit.offset).c_str()));
 | 
			
		||||
			if (bit.wire == nullptr || canonical_bit.wire == nullptr)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			funct_declarations.push_back(util_set_bit(work->prefix + cid(bit.wire->name), bit.wire->width, bit.offset,
 | 
			
		||||
					util_get_bit(work->prefix + cid(canonical_bit.wire->name), canonical_bit.wire->width, canonical_bit.offset).c_str()));
 | 
			
		||||
 | 
			
		||||
			if (verbose)
 | 
			
		||||
				log("  Propagating alias %s.%s[%d] -> %s.%s[%d].\n",
 | 
			
		||||
						log_prefix.c_str(), log_id(canonical_bit.wire), canonical_bit.offset,
 | 
			
		||||
						log_prefix.c_str(), log_id(bit.wire), bit.offset);
 | 
			
		||||
						work->log_prefix.c_str(), log_id(canonical_bit.wire), canonical_bit.offset,
 | 
			
		||||
						work->log_prefix.c_str(), log_id(bit.wire), bit.offset);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		work->sticky_dirty_bits.clear();
 | 
			
		||||
 | 
			
		||||
		for (auto &child : work->children)
 | 
			
		||||
			eval_sticky_dirty(child.second, prefix + cid(child.first) + ".", log_prefix + "." + cid(child.first));
 | 
			
		||||
			eval_sticky_dirty(child.second);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void make_func(HierDirtyFlags *work, const string &func_name)
 | 
			
		||||
	void make_func(HierDirtyFlags *work, const string &func_name, const vector<string> &preamble)
 | 
			
		||||
	{
 | 
			
		||||
		log("Generating function %s():\n", func_name.c_str());
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -621,21 +632,65 @@ struct SimplecWorker
 | 
			
		|||
		funct_declarations.push_back("");
 | 
			
		||||
		funct_declarations.push_back(stringf("static void %s(struct %s_state_t *state)", func_name.c_str(), cid(work->module->name).c_str()));
 | 
			
		||||
		funct_declarations.push_back("{");
 | 
			
		||||
		eval_dirty(work, "state->", log_id(work->module->name), "", "");
 | 
			
		||||
		eval_sticky_dirty(work, "state->", log_id(work->module->name));
 | 
			
		||||
		for (auto &line : preamble)
 | 
			
		||||
			funct_declarations.push_back(line);
 | 
			
		||||
		eval_dirty(work);
 | 
			
		||||
		eval_sticky_dirty(work);
 | 
			
		||||
		funct_declarations.push_back("}");
 | 
			
		||||
 | 
			
		||||
		log("  Activated %d cells (%d activated more than once).\n", GetSize(activated_cells), GetSize(reactivated_cells));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void make_init_func(HierDirtyFlags* /* work */)
 | 
			
		||||
	void eval_init(HierDirtyFlags *work, vector<string> &preamble)
 | 
			
		||||
	{
 | 
			
		||||
		// FIXME
 | 
			
		||||
		Module *module = work->module;
 | 
			
		||||
 | 
			
		||||
		for (Wire *w : module->wires())
 | 
			
		||||
		{
 | 
			
		||||
			if (w->attributes.count("\\init"))
 | 
			
		||||
			{
 | 
			
		||||
				SigSpec sig = sigmaps.at(module)(w);
 | 
			
		||||
				Const val = w->attributes.at("\\init");
 | 
			
		||||
				val.bits.resize(GetSize(sig), State::Sx);
 | 
			
		||||
 | 
			
		||||
				for (int i = 0; i < GetSize(sig); i++)
 | 
			
		||||
					if (val[i] == State::S0 || val[i] == State::S1) {
 | 
			
		||||
						SigBit bit = sig[i];
 | 
			
		||||
						preamble.push_back(util_set_bit(work->prefix + cid(bit.wire->name), bit.wire->width, bit.offset, val == State::S1 ? "true" : "false"));
 | 
			
		||||
						work->set_dirty(bit);
 | 
			
		||||
					}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for (SigBit bit : SigSpec(w))
 | 
			
		||||
			{
 | 
			
		||||
				SigBit val = sigmaps.at(module)(bit);
 | 
			
		||||
 | 
			
		||||
				if (val == State::S0 || val == State::S1)
 | 
			
		||||
					preamble.push_back(util_set_bit(work->prefix + cid(bit.wire->name), bit.wire->width, bit.offset, val == State::S1 ? "true" : "false"));
 | 
			
		||||
 | 
			
		||||
				if (driven_bits.at(module).count(val) == 0)
 | 
			
		||||
					work->set_dirty(val);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		work->set_dirty(State::S0);
 | 
			
		||||
		work->set_dirty(State::S1);
 | 
			
		||||
 | 
			
		||||
		for (auto &child : work->children)
 | 
			
		||||
			eval_init(child.second, preamble);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void make_init_func(HierDirtyFlags *work)
 | 
			
		||||
	{
 | 
			
		||||
		vector<string> preamble;
 | 
			
		||||
		eval_init(work, preamble);
 | 
			
		||||
		make_func(work, cid(work->module->name) + "_init", preamble);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void make_eval_func(HierDirtyFlags *work)
 | 
			
		||||
	{
 | 
			
		||||
		Module *mod = work->module;
 | 
			
		||||
		vector<string> preamble;
 | 
			
		||||
 | 
			
		||||
		for (Wire *w : mod->wires()) {
 | 
			
		||||
			if (w->port_input)
 | 
			
		||||
| 
						 | 
				
			
			@ -643,7 +698,7 @@ struct SimplecWorker
 | 
			
		|||
					work->set_dirty(bit);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		make_func(work, cid(work->module->name) + "_eval");
 | 
			
		||||
		make_func(work, cid(work->module->name) + "_eval", preamble);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void make_tick_func(HierDirtyFlags* /* work */)
 | 
			
		||||
| 
						 | 
				
			
			@ -655,7 +710,7 @@ struct SimplecWorker
 | 
			
		|||
	{
 | 
			
		||||
		create_module_struct(mod);
 | 
			
		||||
 | 
			
		||||
		HierDirtyFlags work(mod, IdString(), nullptr);
 | 
			
		||||
		HierDirtyFlags work(mod, IdString(), nullptr, "state->", log_id(mod->name));
 | 
			
		||||
 | 
			
		||||
		make_init_func(&work);
 | 
			
		||||
		make_eval_func(&work);
 | 
			
		||||
| 
						 | 
				
			
			@ -704,6 +759,9 @@ struct SimplecBackend : public Backend {
 | 
			
		|||
	}
 | 
			
		||||
	virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
 | 
			
		||||
	{
 | 
			
		||||
		reserved_cids.clear();
 | 
			
		||||
		id2cid.clear();
 | 
			
		||||
 | 
			
		||||
		SimplecWorker worker(design);
 | 
			
		||||
 | 
			
		||||
		log_header(design, "Executing SIMPLEC backend.\n");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,6 +15,7 @@ int main()
 | 
			
		|||
{
 | 
			
		||||
	struct test_state_t state;
 | 
			
		||||
	uint32_t a, b, c, x, y, z, w;
 | 
			
		||||
	bool first_eval = true;
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < 10; i++)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -42,7 +43,12 @@ int main()
 | 
			
		|||
		state.c.value_23_16 = c >> 16;
 | 
			
		||||
		state.c.value_31_24 = c >> 24;
 | 
			
		||||
 | 
			
		||||
		test_eval(&state);
 | 
			
		||||
		if (first_eval) {
 | 
			
		||||
			first_eval = false;
 | 
			
		||||
			test_init(&state);
 | 
			
		||||
		} else {
 | 
			
		||||
			test_eval(&state);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		uint32_t uut_x = 0;
 | 
			
		||||
		uut_x |= (uint32_t)state.x.value_7_0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue