mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	Add pmgen "generate" feature
Signed-off-by: Clifford Wolf <clifford@clifford.at>
This commit is contained in:
		
							parent
							
								
									4a57b7e1ab
								
							
						
					
					
						commit
						c710df181c
					
				
					 3 changed files with 208 additions and 13 deletions
				
			
		| 
						 | 
				
			
			@ -23,7 +23,12 @@
 | 
			
		|||
USING_YOSYS_NAMESPACE
 | 
			
		||||
PRIVATE_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
// for peepopt_pm
 | 
			
		||||
bool did_something;
 | 
			
		||||
 | 
			
		||||
#include "passes/pmgen/test_pmgen_pm.h"
 | 
			
		||||
#include "passes/pmgen/ice40_dsp_pm.h"
 | 
			
		||||
#include "passes/pmgen/peepopt_pm.h"
 | 
			
		||||
 | 
			
		||||
void reduce_chain(test_pmgen_pm &pm)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -94,6 +99,100 @@ void reduce_tree(test_pmgen_pm &pm)
 | 
			
		|||
	log("    -> %s (%s)\n", log_id(c), log_id(c->type));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define GENERATE_PATTERN(pmclass, pattern) \
 | 
			
		||||
	generate_pattern<pmclass>([](pmclass &pm, std::function<void()> f){ return pm.run_ ## pattern(f); }, #pmclass, #pattern, design)
 | 
			
		||||
 | 
			
		||||
void pmtest_addports(Module *module)
 | 
			
		||||
{
 | 
			
		||||
	pool<SigBit> driven_bits, used_bits;
 | 
			
		||||
	SigMap sigmap(module);
 | 
			
		||||
	int icnt = 0, ocnt = 0;
 | 
			
		||||
 | 
			
		||||
	for (auto cell : module->cells())
 | 
			
		||||
	for (auto conn : cell->connections())
 | 
			
		||||
	{
 | 
			
		||||
		if (cell->input(conn.first))
 | 
			
		||||
			for (auto bit : sigmap(conn.second))
 | 
			
		||||
				used_bits.insert(bit);
 | 
			
		||||
		if (cell->output(conn.first))
 | 
			
		||||
			for (auto bit : sigmap(conn.second))
 | 
			
		||||
				driven_bits.insert(bit);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (auto wire : vector<Wire*>(module->wires()))
 | 
			
		||||
	{
 | 
			
		||||
		SigSpec ibits, obits;
 | 
			
		||||
		for (auto bit : sigmap(wire)) {
 | 
			
		||||
			if (!used_bits.count(bit))
 | 
			
		||||
				obits.append(bit);
 | 
			
		||||
			if (!driven_bits.count(bit))
 | 
			
		||||
				ibits.append(bit);
 | 
			
		||||
		}
 | 
			
		||||
		if (!ibits.empty()) {
 | 
			
		||||
			Wire *w = module->addWire(stringf("\\i%d", icnt++), GetSize(ibits));
 | 
			
		||||
			w->port_input = true;
 | 
			
		||||
			module->connect(ibits, w);
 | 
			
		||||
		}
 | 
			
		||||
		if (!obits.empty()) {
 | 
			
		||||
			Wire *w = module->addWire(stringf("\\o%d", ocnt++), GetSize(obits));
 | 
			
		||||
			w->port_output = true;
 | 
			
		||||
			module->connect(w, obits);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	module->fixup_ports();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class pm>
 | 
			
		||||
void generate_pattern(std::function<void(pm&,std::function<void()>)> run, const char *pmclass, const char *pattern, Design *design)
 | 
			
		||||
{
 | 
			
		||||
	log("Generating \"%s\" patterns for pattern matcher \"%s\".\n", pattern, pmclass);
 | 
			
		||||
 | 
			
		||||
	int modcnt = 0;
 | 
			
		||||
 | 
			
		||||
	while (modcnt < 100)
 | 
			
		||||
	{
 | 
			
		||||
		int submodcnt = 0, itercnt = 0, cellcnt = 0;
 | 
			
		||||
		Module *mod = design->addModule(NEW_ID);
 | 
			
		||||
 | 
			
		||||
		while (submodcnt < 10 && itercnt++ < 1000)
 | 
			
		||||
		{
 | 
			
		||||
			pm matcher(mod, mod->cells());
 | 
			
		||||
 | 
			
		||||
			matcher.rng(1);
 | 
			
		||||
			matcher.rngseed += modcnt;
 | 
			
		||||
			matcher.rng(1);
 | 
			
		||||
			matcher.rngseed += submodcnt;
 | 
			
		||||
			matcher.rng(1);
 | 
			
		||||
			matcher.rngseed += itercnt;
 | 
			
		||||
			matcher.rng(1);
 | 
			
		||||
			matcher.rngseed += cellcnt;
 | 
			
		||||
			matcher.rng(1);
 | 
			
		||||
 | 
			
		||||
			if (GetSize(mod->cells()) != cellcnt)
 | 
			
		||||
			{
 | 
			
		||||
				bool found_match = false;
 | 
			
		||||
				run(matcher, [&](){ found_match = true; });
 | 
			
		||||
 | 
			
		||||
				if (found_match) {
 | 
			
		||||
					Module *m = design->addModule(stringf("\\pmtest_%s_%s_%05d",
 | 
			
		||||
							pmclass, pattern, modcnt++));
 | 
			
		||||
					mod->cloneInto(m);
 | 
			
		||||
					pmtest_addports(m);
 | 
			
		||||
					submodcnt++;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				cellcnt = GetSize(mod->cells());
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			matcher.generate_mode = true;
 | 
			
		||||
			run(matcher, [](){});
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		design->remove(mod);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct TestPmgenPass : public Pass {
 | 
			
		||||
	TestPmgenPass() : Pass("test_pmgen", "test pass for pmgen") { }
 | 
			
		||||
	void help() YS_OVERRIDE
 | 
			
		||||
| 
						 | 
				
			
			@ -104,11 +203,18 @@ struct TestPmgenPass : public Pass {
 | 
			
		|||
		log("\n");
 | 
			
		||||
		log("Demo for recursive pmgen patterns. Map chains of AND/OR/XOR to $reduce_*.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    test_pmgen -reduce_tree [options] [selection]\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("Demo for recursive pmgen patterns. Map trees of AND/OR/XOR to $reduce_*.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    test_pmgen -generate [options] <pattern_name>\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("Create modules that match the specified pattern.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void execute_reduce_chain(std::vector<std::string> args, RTLIL::Design *design)
 | 
			
		||||
| 
						 | 
				
			
			@ -149,6 +255,40 @@ struct TestPmgenPass : public Pass {
 | 
			
		|||
			test_pmgen_pm(module, module->selected_cells()).run_reduce(reduce_tree);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void execute_generate(std::vector<std::string> args, RTLIL::Design *design)
 | 
			
		||||
	{
 | 
			
		||||
		log_header(design, "Executing TEST_PMGEN pass (-generate).\n");
 | 
			
		||||
 | 
			
		||||
		size_t argidx;
 | 
			
		||||
		for (argidx = 2; argidx < args.size(); argidx++)
 | 
			
		||||
		{
 | 
			
		||||
			// if (args[argidx] == "-singleton") {
 | 
			
		||||
			// 	singleton_mode = true;
 | 
			
		||||
			// 	continue;
 | 
			
		||||
			// }
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (argidx+1 != args.size())
 | 
			
		||||
			log_cmd_error("Expected exactly one pattern.\n");
 | 
			
		||||
 | 
			
		||||
		string pattern = args[argidx];
 | 
			
		||||
 | 
			
		||||
		if (pattern == "reduce")
 | 
			
		||||
			return GENERATE_PATTERN(test_pmgen_pm, reduce);
 | 
			
		||||
 | 
			
		||||
		if (pattern == "ice40_dsp")
 | 
			
		||||
			return GENERATE_PATTERN(ice40_dsp_pm, ice40_dsp);
 | 
			
		||||
 | 
			
		||||
		if (pattern == "peepopt-muldiv")
 | 
			
		||||
			return GENERATE_PATTERN(peepopt_pm, muldiv);
 | 
			
		||||
 | 
			
		||||
		if (pattern == "peepopt-shiftmul")
 | 
			
		||||
			return GENERATE_PATTERN(peepopt_pm, shiftmul);
 | 
			
		||||
 | 
			
		||||
		log_cmd_error("Unkown pattern: %s\n", pattern.c_str());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 | 
			
		||||
	{
 | 
			
		||||
		if (GetSize(args) > 1)
 | 
			
		||||
| 
						 | 
				
			
			@ -157,6 +297,8 @@ struct TestPmgenPass : public Pass {
 | 
			
		|||
				return execute_reduce_chain(args, design);
 | 
			
		||||
			if (args[1] == "-reduce_tree")
 | 
			
		||||
				return execute_reduce_tree(args, design);
 | 
			
		||||
			if (args[1] == "-generate")
 | 
			
		||||
				return execute_generate(args, design);
 | 
			
		||||
		}
 | 
			
		||||
		log_cmd_error("Missing or unsupported mode parameter.\n");
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue