mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-03 21:09:12 +00:00 
			
		
		
		
	Add support for various ff/latch cells simulation
This commit is contained in:
		
							parent
							
								
									1586000048
								
							
						
					
					
						commit
						fb22d7cdc4
					
				
					 3 changed files with 260 additions and 171 deletions
				
			
		| 
						 | 
				
			
			@ -109,8 +109,7 @@ void FstData::extractVarNames()
 | 
			
		|||
				}
 | 
			
		||||
				if (clean_name[0]=='\\')
 | 
			
		||||
					clean_name = clean_name.substr(1);
 | 
			
		||||
				//log("adding %s.%s\n",var.scope.c_str(), clean_name.c_str());
 | 
			
		||||
				
 | 
			
		||||
 | 
			
		||||
				name_to_handle[var.scope+"."+clean_name] = h->u.var.handle;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -118,48 +117,6 @@ void FstData::extractVarNames()
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void reconstruct_edges_varlen(void *user_data, uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t plen)
 | 
			
		||||
{
 | 
			
		||||
	FstData *ptr = (FstData*)user_data;
 | 
			
		||||
	ptr->reconstruct_edges_callback(pnt_time, pnt_facidx, pnt_value, plen);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void reconstruct_edges(void *user_data, uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value)
 | 
			
		||||
{
 | 
			
		||||
	FstData *ptr = (FstData*)user_data;
 | 
			
		||||
	uint32_t plen = (pnt_value) ?  strlen((const char *)pnt_value) : 0;
 | 
			
		||||
	ptr->reconstruct_edges_callback(pnt_time, pnt_facidx, pnt_value, plen);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FstData::reconstruct_edges_callback(uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t /* plen */)
 | 
			
		||||
{
 | 
			
		||||
	std::string val = std::string((const char *)pnt_value);
 | 
			
		||||
	std::string prev = last_data[pnt_facidx];
 | 
			
		||||
	if (pnt_time>=start_time) {
 | 
			
		||||
		if (prev!="1" && val=="1")
 | 
			
		||||
			edges.push_back(pnt_time);
 | 
			
		||||
		if (prev!="0" && val=="0")
 | 
			
		||||
			edges.push_back(pnt_time);
 | 
			
		||||
	}
 | 
			
		||||
	last_data[pnt_facidx] = val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::vector<uint64_t> FstData::getAllEdges(std::vector<fstHandle> &signal, uint64_t start, uint64_t end)
 | 
			
		||||
{
 | 
			
		||||
	start_time = start;
 | 
			
		||||
	end_time = end;
 | 
			
		||||
	last_data.clear();
 | 
			
		||||
	for(auto &s : signal) {
 | 
			
		||||
		last_data[s] = "x";
 | 
			
		||||
	}
 | 
			
		||||
	edges.clear();
 | 
			
		||||
	fstReaderSetLimitTimeRange(ctx, start_time, end_time);
 | 
			
		||||
	fstReaderClrFacProcessMaskAll(ctx);
 | 
			
		||||
	for(const auto sig : signal)
 | 
			
		||||
		fstReaderSetFacProcessMask(ctx,sig);
 | 
			
		||||
	fstReaderIterBlocks2(ctx, reconstruct_edges, reconstruct_edges_varlen, this, nullptr);
 | 
			
		||||
	return edges;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void reconstruct_clb_varlen_attimes(void *user_data, uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t plen)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -176,77 +133,65 @@ static void reconstruct_clb_attimes(void *user_data, uint64_t pnt_time, fstHandl
 | 
			
		|||
 | 
			
		||||
void FstData::reconstruct_callback_attimes(uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t /* plen */)
 | 
			
		||||
{
 | 
			
		||||
	if (sample_times_ndx >= sample_times.size()) return;
 | 
			
		||||
 | 
			
		||||
	uint64_t time = sample_times[sample_times_ndx];
 | 
			
		||||
	if (pnt_time > end_time) return;
 | 
			
		||||
	// if we are past the timestamp
 | 
			
		||||
	if (pnt_time > time) {
 | 
			
		||||
		for (auto const& c : last_data)
 | 
			
		||||
		{
 | 
			
		||||
			handle_to_data[c.first].push_back(std::make_pair(time,c.second));
 | 
			
		||||
			size_t index = handle_to_data[c.first].size() - 1;
 | 
			
		||||
			time_to_index[c.first][time] = index;
 | 
			
		||||
	bool is_clock = false;
 | 
			
		||||
	if (!all_samples) {
 | 
			
		||||
		for(auto &s : clk_signals) {
 | 
			
		||||
			if (s==pnt_facidx)  { 
 | 
			
		||||
				is_clock=true;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (pnt_time > past_time) {
 | 
			
		||||
		past_data = last_data;
 | 
			
		||||
		past_time = pnt_time;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (pnt_time > last_time) {
 | 
			
		||||
		if (all_samples) {
 | 
			
		||||
			callback(last_time);
 | 
			
		||||
			last_time = pnt_time;
 | 
			
		||||
		} else {
 | 
			
		||||
			if (is_clock) {
 | 
			
		||||
				std::string val = std::string((const char *)pnt_value);
 | 
			
		||||
				std::string prev = past_data[pnt_facidx];
 | 
			
		||||
				if ((prev!="1" && val=="1") || (prev!="0" && val=="0")) {
 | 
			
		||||
					callback(last_time);
 | 
			
		||||
					last_time = pnt_time;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		sample_times_ndx++;
 | 
			
		||||
	}
 | 
			
		||||
	// always update last_data
 | 
			
		||||
	last_data[pnt_facidx] =  std::string((const char *)pnt_value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FstData::reconstructAtTimes(std::vector<fstHandle> &signal, std::vector<uint64_t> time)
 | 
			
		||||
void FstData::reconstructAllAtTimes(std::vector<fstHandle> &signal, uint64_t start, uint64_t end, CallbackFunction cb)
 | 
			
		||||
{
 | 
			
		||||
	handle_to_data.clear();
 | 
			
		||||
	time_to_index.clear();
 | 
			
		||||
	clk_signals = signal;
 | 
			
		||||
	callback = cb;
 | 
			
		||||
	start_time = start;
 | 
			
		||||
	end_time = end;
 | 
			
		||||
	last_data.clear();
 | 
			
		||||
	sample_times_ndx = 0;
 | 
			
		||||
	sample_times = time;
 | 
			
		||||
	fstReaderSetUnlimitedTimeRange(ctx);
 | 
			
		||||
	fstReaderClrFacProcessMaskAll(ctx);
 | 
			
		||||
	for(const auto sig : signal)
 | 
			
		||||
		fstReaderSetFacProcessMask(ctx,sig);
 | 
			
		||||
	fstReaderIterBlocks2(ctx, reconstruct_clb_attimes, reconstruct_clb_varlen_attimes, this, nullptr);
 | 
			
		||||
 | 
			
		||||
	if (time_to_index[signal.back()].count(time.back())==0) {
 | 
			
		||||
		for (auto const& c : last_data)
 | 
			
		||||
		{
 | 
			
		||||
			handle_to_data[c.first].push_back(std::make_pair(time.back(),c.second));
 | 
			
		||||
			size_t index = handle_to_data[c.first].size() - 1;
 | 
			
		||||
			time_to_index[c.first][time.back()] = index;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FstData::reconstructAllAtTimes(std::vector<uint64_t> time)
 | 
			
		||||
{
 | 
			
		||||
	handle_to_data.clear();
 | 
			
		||||
	time_to_index.clear();
 | 
			
		||||
	last_data.clear();
 | 
			
		||||
	sample_times_ndx = 0;
 | 
			
		||||
	sample_times = time;
 | 
			
		||||
	last_time = start_time;
 | 
			
		||||
	past_data.clear();
 | 
			
		||||
	past_time = start_time;
 | 
			
		||||
	all_samples = clk_signals.empty();
 | 
			
		||||
 | 
			
		||||
	fstReaderSetUnlimitedTimeRange(ctx);
 | 
			
		||||
	fstReaderSetFacProcessMaskAll(ctx);
 | 
			
		||||
	fstReaderIterBlocks2(ctx, reconstruct_clb_attimes, reconstruct_clb_varlen_attimes, this, nullptr);
 | 
			
		||||
 | 
			
		||||
	if (time_to_index[1].count(time.back())==0) {
 | 
			
		||||
		for (auto const& c : last_data)
 | 
			
		||||
		{
 | 
			
		||||
			handle_to_data[c.first].push_back(std::make_pair(time.back(),c.second));
 | 
			
		||||
			size_t index = handle_to_data[c.first].size() - 1;
 | 
			
		||||
			time_to_index[c.first][time.back()] = index;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	callback(last_time);
 | 
			
		||||
	if (last_time!=end_time)
 | 
			
		||||
		callback(end_time);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string FstData::valueAt(fstHandle signal, uint64_t time)
 | 
			
		||||
std::string FstData::valueOf(fstHandle signal)
 | 
			
		||||
{
 | 
			
		||||
	if (handle_to_data.find(signal) == handle_to_data.end())
 | 
			
		||||
	if (past_data.find(signal) == past_data.end())
 | 
			
		||||
		log_error("Signal id %d not found\n", (int)signal);
 | 
			
		||||
	auto &data = handle_to_data[signal];
 | 
			
		||||
	if (time_to_index[signal].count(time)!=0) {
 | 
			
		||||
		size_t index = time_to_index[signal][time];
 | 
			
		||||
		return data.at(index).second;
 | 
			
		||||
	} else {
 | 
			
		||||
		log_error("No data for signal %d at time %d\n", (int)signal, (int)time);
 | 
			
		||||
	}
 | 
			
		||||
	return past_data[signal];
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,9 @@
 | 
			
		|||
 | 
			
		||||
YOSYS_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
typedef std::function<void(uint64_t)> CallbackFunction;
 | 
			
		||||
struct fst_end_of_data_exception { };
 | 
			
		||||
 | 
			
		||||
struct FstVar
 | 
			
		||||
{
 | 
			
		||||
	fstHandle id;
 | 
			
		||||
| 
						 | 
				
			
			@ -45,14 +48,10 @@ class FstData
 | 
			
		|||
 | 
			
		||||
	std::vector<FstVar>& getVars() { return vars; };
 | 
			
		||||
 | 
			
		||||
	void reconstruct_edges_callback(uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t plen);
 | 
			
		||||
	std::vector<uint64_t> getAllEdges(std::vector<fstHandle> &signal, uint64_t start_time, uint64_t end_time);
 | 
			
		||||
 | 
			
		||||
	void reconstruct_callback_attimes(uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t plen);
 | 
			
		||||
	void reconstructAtTimes(std::vector<fstHandle> &signal,std::vector<uint64_t> time);
 | 
			
		||||
	void reconstructAllAtTimes(std::vector<uint64_t> time);
 | 
			
		||||
	void reconstructAllAtTimes(std::vector<fstHandle> &signal, uint64_t start_time, uint64_t end_time, CallbackFunction cb);
 | 
			
		||||
 | 
			
		||||
	std::string valueAt(fstHandle signal, uint64_t time);
 | 
			
		||||
	std::string valueOf(fstHandle signal);
 | 
			
		||||
	fstHandle getHandle(std::string name);
 | 
			
		||||
	double getTimescale() { return timescale; }
 | 
			
		||||
	const char *getTimescaleString() { return timescale_str.c_str(); }
 | 
			
		||||
| 
						 | 
				
			
			@ -64,16 +63,17 @@ private:
 | 
			
		|||
	std::vector<FstVar> vars;
 | 
			
		||||
	std::map<fstHandle, FstVar> handle_to_var;
 | 
			
		||||
	std::map<std::string, fstHandle> name_to_handle;
 | 
			
		||||
	std::map<fstHandle, std::vector<std::pair<uint64_t, std::string>>> handle_to_data;
 | 
			
		||||
	std::map<fstHandle, std::string> last_data;
 | 
			
		||||
	std::map<fstHandle, std::map<uint64_t, size_t>> time_to_index;
 | 
			
		||||
	std::vector<uint64_t> sample_times;
 | 
			
		||||
	size_t sample_times_ndx;
 | 
			
		||||
	uint64_t last_time;
 | 
			
		||||
	std::map<fstHandle, std::string> past_data;
 | 
			
		||||
	uint64_t past_time;
 | 
			
		||||
	double timescale;
 | 
			
		||||
	std::string timescale_str;
 | 
			
		||||
	uint64_t start_time;
 | 
			
		||||
	uint64_t end_time;
 | 
			
		||||
	std::vector<uint64_t> edges;
 | 
			
		||||
	CallbackFunction callback;
 | 
			
		||||
	std::vector<fstHandle> clk_signals;
 | 
			
		||||
	bool all_samples;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
YOSYS_NAMESPACE_END
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue