mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 13:29:12 +00:00 
			
		
		
		
	Merge pull request #3185 from YosysHQ/micko/co_sim
Add co-simulation in sim pass
This commit is contained in:
		
						commit
						d7f7227ce8
					
				
					 20 changed files with 11555 additions and 23 deletions
				
			
		
							
								
								
									
										8
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										8
									
								
								Makefile
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -594,9 +594,11 @@ $(eval $(call add_include_file,kernel/satgen.h))
 | 
			
		|||
$(eval $(call add_include_file,kernel/qcsat.h))
 | 
			
		||||
$(eval $(call add_include_file,kernel/ff.h))
 | 
			
		||||
$(eval $(call add_include_file,kernel/ffinit.h))
 | 
			
		||||
$(eval $(call add_include_file,kernel/fstdata.h))
 | 
			
		||||
$(eval $(call add_include_file,kernel/mem.h))
 | 
			
		||||
$(eval $(call add_include_file,libs/ezsat/ezsat.h))
 | 
			
		||||
$(eval $(call add_include_file,libs/ezsat/ezminisat.h))
 | 
			
		||||
$(eval $(call add_include_file,libs/fst/fstapi.h))
 | 
			
		||||
$(eval $(call add_include_file,libs/sha1/sha1.h))
 | 
			
		||||
$(eval $(call add_include_file,libs/json11/json11.hpp))
 | 
			
		||||
$(eval $(call add_include_file,passes/fsm/fsmdata.h))
 | 
			
		||||
| 
						 | 
				
			
			@ -618,7 +620,7 @@ ifneq ($(ABCEXTERNAL),)
 | 
			
		|||
kernel/yosys.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"'
 | 
			
		||||
endif
 | 
			
		||||
endif
 | 
			
		||||
OBJS += kernel/cellaigs.o kernel/celledges.o kernel/satgen.o kernel/qcsat.o kernel/mem.o kernel/ffmerge.o kernel/ff.o
 | 
			
		||||
OBJS += kernel/cellaigs.o kernel/celledges.o kernel/satgen.o kernel/qcsat.o kernel/mem.o kernel/ffmerge.o kernel/ff.o kernel/fstdata.o
 | 
			
		||||
 | 
			
		||||
kernel/log.o: CXXFLAGS += -DYOSYS_SRC='"$(YOSYS_SRC)"'
 | 
			
		||||
kernel/yosys.o: CXXFLAGS += -DYOSYS_DATDIR='"$(DATDIR)"' -DYOSYS_PROGRAM_PREFIX='"$(PROGRAM_PREFIX)"'
 | 
			
		||||
| 
						 | 
				
			
			@ -642,6 +644,10 @@ OBJS += libs/minisat/SimpSolver.o
 | 
			
		|||
OBJS += libs/minisat/Solver.o
 | 
			
		||||
OBJS += libs/minisat/System.o
 | 
			
		||||
 | 
			
		||||
OBJS += libs/fst/fstapi.o
 | 
			
		||||
OBJS += libs/fst/fastlz.o
 | 
			
		||||
OBJS += libs/fst/lz4.o
 | 
			
		||||
 | 
			
		||||
include $(YOSYS_SRC)/frontends/*/Makefile.inc
 | 
			
		||||
include $(YOSYS_SRC)/passes/*/Makefile.inc
 | 
			
		||||
include $(YOSYS_SRC)/backends/*/Makefile.inc
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										252
									
								
								kernel/fstdata.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										252
									
								
								kernel/fstdata.cc
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,252 @@
 | 
			
		|||
/*
 | 
			
		||||
 *  yosys -- Yosys Open SYnthesis Suite
 | 
			
		||||
 *
 | 
			
		||||
 *  Copyright (C) 2022  Miodrag Milanovic <micko@yosyshq.com>
 | 
			
		||||
 *
 | 
			
		||||
 *  Permission to use, copy, modify, and/or distribute this software for any
 | 
			
		||||
 *  purpose with or without fee is hereby granted, provided that the above
 | 
			
		||||
 *  copyright notice and this permission notice appear in all copies.
 | 
			
		||||
 *
 | 
			
		||||
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
			
		||||
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
			
		||||
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
			
		||||
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
			
		||||
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
			
		||||
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
			
		||||
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "kernel/fstdata.h"
 | 
			
		||||
 | 
			
		||||
USING_YOSYS_NAMESPACE
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
FstData::FstData(std::string filename) : ctx(nullptr)
 | 
			
		||||
{
 | 
			
		||||
	const std::vector<std::string> g_units = { "s", "ms", "us", "ns", "ps", "fs", "as", "zs" };
 | 
			
		||||
	ctx = (fstReaderContext *)fstReaderOpen(filename.c_str());
 | 
			
		||||
	if (!ctx)
 | 
			
		||||
		log_error("Error opening '%s'\n", filename.c_str());
 | 
			
		||||
	int scale = (int)fstReaderGetTimescale(ctx);	
 | 
			
		||||
	timescale = pow(10.0, scale);
 | 
			
		||||
	timescale_str = "";
 | 
			
		||||
	int unit = 0;
 | 
			
		||||
	int zeros = 0;
 | 
			
		||||
	if (scale > 0)  {
 | 
			
		||||
		zeros = scale;
 | 
			
		||||
	} else {
 | 
			
		||||
		if ((scale % 3) == 0) {
 | 
			
		||||
			zeros = (-scale % 3);
 | 
			
		||||
			unit = (-scale / 3);
 | 
			
		||||
		} else {
 | 
			
		||||
			zeros = 3 - (-scale % 3);
 | 
			
		||||
			unit = (-scale / 3) + 1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	for (int i=0;i<zeros; i++) timescale_str += "0";
 | 
			
		||||
	timescale_str += g_units[unit];
 | 
			
		||||
	extractVarNames();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FstData::~FstData()
 | 
			
		||||
{
 | 
			
		||||
	if (ctx)
 | 
			
		||||
		fstReaderClose(ctx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint64_t FstData::getStartTime() { return fstReaderGetStartTime(ctx); }
 | 
			
		||||
 | 
			
		||||
uint64_t FstData::getEndTime() { return fstReaderGetEndTime(ctx); }
 | 
			
		||||
 | 
			
		||||
fstHandle FstData::getHandle(std::string name) { 
 | 
			
		||||
	if (name_to_handle.find(name) != name_to_handle.end())
 | 
			
		||||
		return name_to_handle[name];
 | 
			
		||||
	else 
 | 
			
		||||
		return 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static std::string remove_spaces(std::string str)
 | 
			
		||||
{
 | 
			
		||||
	str.erase(std::remove(str.begin(), str.end(), ' '), str.end());
 | 
			
		||||
	return str;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FstData::extractVarNames()
 | 
			
		||||
{
 | 
			
		||||
	struct fstHier *h;
 | 
			
		||||
	intptr_t snum = 0;
 | 
			
		||||
 | 
			
		||||
	while ((h = fstReaderIterateHier(ctx))) {
 | 
			
		||||
		switch (h->htyp) {
 | 
			
		||||
			case FST_HT_SCOPE: {
 | 
			
		||||
				snum++;
 | 
			
		||||
				std::string fst_scope_name = fstReaderPushScope(ctx, h->u.scope.name, (void *)(snum));
 | 
			
		||||
				scopes.push_back(fst_scope_name);
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			case FST_HT_UPSCOPE: {
 | 
			
		||||
				fstReaderPopScope(ctx);
 | 
			
		||||
				snum = fstReaderGetCurrentScopeLen(ctx) ? (intptr_t)fstReaderGetCurrentScopeUserInfo(ctx) : 0;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			case FST_HT_VAR: {
 | 
			
		||||
				FstVar var;
 | 
			
		||||
				var.id = h->u.var.handle;
 | 
			
		||||
				var.is_alias = h->u.var.is_alias;
 | 
			
		||||
				var.name = remove_spaces(h->u.var.name);
 | 
			
		||||
				var.scope = scopes.back();
 | 
			
		||||
				var.width = h->u.var.length;
 | 
			
		||||
				vars.push_back(var);
 | 
			
		||||
				if (!var.is_alias)
 | 
			
		||||
					handle_to_var[h->u.var.handle] = var;
 | 
			
		||||
				std::string clean_name;
 | 
			
		||||
				for(size_t i=0;i<strlen(h->u.var.name);i++) 
 | 
			
		||||
				{
 | 
			
		||||
					char c = h->u.var.name[i];
 | 
			
		||||
					if(c==' ') break;
 | 
			
		||||
					clean_name += c;
 | 
			
		||||
				}
 | 
			
		||||
				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;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
	FstData *ptr = (FstData*)user_data;
 | 
			
		||||
	ptr->reconstruct_callback_attimes(pnt_time, pnt_facidx, pnt_value, plen);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void reconstruct_clb_attimes(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_callback_attimes(pnt_time, pnt_facidx, pnt_value, plen);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 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;
 | 
			
		||||
		}
 | 
			
		||||
		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)
 | 
			
		||||
{
 | 
			
		||||
	handle_to_data.clear();
 | 
			
		||||
	time_to_index.clear();
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string FstData::valueAt(fstHandle signal, uint64_t time)
 | 
			
		||||
{
 | 
			
		||||
	if (handle_to_data.find(signal) == handle_to_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);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										81
									
								
								kernel/fstdata.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								kernel/fstdata.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,81 @@
 | 
			
		|||
/*
 | 
			
		||||
 *  yosys -- Yosys Open SYnthesis Suite
 | 
			
		||||
 *
 | 
			
		||||
 *  Copyright (C) 2022  Miodrag Milanovic <micko@yosyshq.com>
 | 
			
		||||
 *
 | 
			
		||||
 *  Permission to use, copy, modify, and/or distribute this software for any
 | 
			
		||||
 *  purpose with or without fee is hereby granted, provided that the above
 | 
			
		||||
 *  copyright notice and this permission notice appear in all copies.
 | 
			
		||||
 *
 | 
			
		||||
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
			
		||||
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
			
		||||
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
			
		||||
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
			
		||||
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
			
		||||
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
			
		||||
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef FSTDATA_H
 | 
			
		||||
#define FSTDATA_H
 | 
			
		||||
 | 
			
		||||
#include "kernel/yosys.h"
 | 
			
		||||
#include "libs/fst/fstapi.h"
 | 
			
		||||
 | 
			
		||||
YOSYS_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
struct FstVar
 | 
			
		||||
{
 | 
			
		||||
	fstHandle id;
 | 
			
		||||
	std::string name;
 | 
			
		||||
	bool is_alias;
 | 
			
		||||
	std::string scope;
 | 
			
		||||
	int width;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class FstData
 | 
			
		||||
{
 | 
			
		||||
	public:
 | 
			
		||||
	FstData(std::string filename);
 | 
			
		||||
	~FstData();
 | 
			
		||||
 | 
			
		||||
	uint64_t getStartTime();
 | 
			
		||||
	uint64_t getEndTime();
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
	std::string valueAt(fstHandle signal, uint64_t time);
 | 
			
		||||
	fstHandle getHandle(std::string name);
 | 
			
		||||
	double getTimescale() { return timescale; }
 | 
			
		||||
	const char *getTimescaleString() { return timescale_str.c_str(); }
 | 
			
		||||
private:
 | 
			
		||||
	void extractVarNames();
 | 
			
		||||
 | 
			
		||||
	struct fstReaderContext *ctx;
 | 
			
		||||
	std::vector<std::string> scopes;
 | 
			
		||||
	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;
 | 
			
		||||
	double timescale;
 | 
			
		||||
	std::string timescale_str;
 | 
			
		||||
	uint64_t start_time;
 | 
			
		||||
	uint64_t end_time;
 | 
			
		||||
	std::vector<uint64_t> edges;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
YOSYS_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										130
									
								
								libs/fst/block_format.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								libs/fst/block_format.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,130 @@
 | 
			
		|||
See fstapi.h for the values for the FST_BL_XXX enums.
 | 
			
		||||
 | 
			
		||||
===========================================================================
 | 
			
		||||
 | 
			
		||||
compressed wrapper (typically over whole file)
 | 
			
		||||
 | 
			
		||||
uint8_t		FST_BL_ZWRAPPER
 | 
			
		||||
uint64_t        section length
 | 
			
		||||
uint64_t        length of uncompressed data
 | 
			
		||||
[zlib compressed data]
 | 
			
		||||
 | 
			
		||||
===========================================================================
 | 
			
		||||
 | 
			
		||||
header block
 | 
			
		||||
 | 
			
		||||
uint8_t		FST_BL_HDR
 | 
			
		||||
uint64_t	section length
 | 
			
		||||
uint64_t	start time
 | 
			
		||||
uint64_t	end time
 | 
			
		||||
double		endian test for "e"
 | 
			
		||||
uint64_t	memory used by writer
 | 
			
		||||
uint64_t	scope creation count
 | 
			
		||||
uint64_t	var creation count
 | 
			
		||||
uint64_t	max var idcode
 | 
			
		||||
uint64_t	vc section count
 | 
			
		||||
int8_t		timescale exponent
 | 
			
		||||
[128 bytes]	version
 | 
			
		||||
[128 bytes]	date
 | 
			
		||||
 | 
			
		||||
===========================================================================
 | 
			
		||||
 | 
			
		||||
geometry block
 | 
			
		||||
 | 
			
		||||
uint8_t         FST_BL_GEOM
 | 
			
		||||
uint64_t        section length
 | 
			
		||||
uint64_t        length of uncompressed geometry data
 | 
			
		||||
uint64_t        maxhandle
 | 
			
		||||
[compressed data]
 | 
			
		||||
 | 
			
		||||
(length of compressed data is section length - 24)
 | 
			
		||||
 | 
			
		||||
===========================================================================
 | 
			
		||||
 | 
			
		||||
hierarchy block
 | 
			
		||||
 | 
			
		||||
uint8_t         FST_BL_HIER
 | 
			
		||||
uint64_t        section length
 | 
			
		||||
uint64_t        length of uncompressed hier data
 | 
			
		||||
[zlib compressed data]
 | 
			
		||||
 | 
			
		||||
or
 | 
			
		||||
 | 
			
		||||
uint8_t         FST_BL_HIER_LZ4
 | 
			
		||||
uint64_t        section length
 | 
			
		||||
uint64_t        length of uncompressed hier data
 | 
			
		||||
[lz4 compressed data]
 | 
			
		||||
 | 
			
		||||
uint8_t         FST_BL_HIER_LZ4DUO
 | 
			
		||||
uint64_t        section length
 | 
			
		||||
uint64_t        length of uncompressed hier data
 | 
			
		||||
varint		length of hier data compressed once with lz4
 | 
			
		||||
[lz4 double compressed data]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
===========================================================================
 | 
			
		||||
 | 
			
		||||
dumpon/off block
 | 
			
		||||
 | 
			
		||||
uint8_t         FST_BL_BLACKOUT
 | 
			
		||||
uint64_t        section length
 | 
			
		||||
varint		num blackouts (section below is repeated this # times)
 | 
			
		||||
[
 | 
			
		||||
uint8_t		on/off (nonzero = on)
 | 
			
		||||
varint		delta time
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
===========================================================================
 | 
			
		||||
 | 
			
		||||
1..n value change blocks:
 | 
			
		||||
 | 
			
		||||
// header
 | 
			
		||||
 | 
			
		||||
uint8_t		FST_BL_VCDATA (or FST_BL_VCDATA_DYN_ALIAS)
 | 
			
		||||
uint64_t	section length
 | 
			
		||||
uint64_t	begin time of section
 | 
			
		||||
uint64_t	end time of section
 | 
			
		||||
uint64_t	amount of buffer memory required in reader for full vc traversal
 | 
			
		||||
varint		maxvalpos (length of uncompressed data)
 | 
			
		||||
varint		length of compressed data
 | 
			
		||||
varint		maxhandle associated with this checkpoint data
 | 
			
		||||
[compressed data]
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
// value changes
 | 
			
		||||
 | 
			
		||||
varint		maxhandle associated with the value change data
 | 
			
		||||
uint8_t		pack type ('F' is fastlz, '4' is lz4,
 | 
			
		||||
			others ['Z'/'!'] are zlib)
 | 
			
		||||
 | 
			
		||||
varint		chain 0 compressed data length (0 = uncompressed)
 | 
			
		||||
[compressed data]
 | 
			
		||||
...
 | 
			
		||||
varint		chain n compressed data length (0 = uncompressed)
 | 
			
		||||
[compressed data]
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
// index: chain pointer table (from 0..maxhandle-1)
 | 
			
		||||
 | 
			
		||||
varint		if &1 == 1, this is <<1 literal delta
 | 
			
		||||
		if &1 == 0, this is <<1 RLE count of zeros
 | 
			
		||||
		if == 0, next varint is handle of prev chain to use,
 | 
			
		||||
			bit only if FST_BL_VCDATA_DYN_ALIAS or
 | 
			
		||||
			later VCDATA format
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
uint64_t	index length (subtract from here to get index position)
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
[compressed data for time section]
 | 
			
		||||
uint64_t	uncompressed data length in bytes
 | 
			
		||||
uint64_t	compressed data length in bytes
 | 
			
		||||
uint64_t	number of time items
 | 
			
		||||
 | 
			
		||||
// end of section
 | 
			
		||||
 | 
			
		||||
===========================================================================
 | 
			
		||||
							
								
								
									
										27
									
								
								libs/fst/config.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								libs/fst/config.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
 | 
			
		||||
 */
 | 
			
		||||
#define HAVE_ALLOCA_H 1
 | 
			
		||||
 | 
			
		||||
/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
 | 
			
		||||
#define HAVE_FSEEKO 1
 | 
			
		||||
 | 
			
		||||
/* Define to 1 if you have the `pthread' library (-lpthread). */
 | 
			
		||||
#define HAVE_LIBPTHREAD 1
 | 
			
		||||
 | 
			
		||||
/* Define to 1 if you have the `realpath' function. */
 | 
			
		||||
#define HAVE_REALPATH 1
 | 
			
		||||
 | 
			
		||||
#if defined(__MINGW32__)
 | 
			
		||||
#undef HAVE_ALLOCA_H
 | 
			
		||||
#undef HAVE_REALPATH
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(_MSC_VER)
 | 
			
		||||
#undef HAVE_ALLOCA_H
 | 
			
		||||
#undef HAVE_REALPATH
 | 
			
		||||
#undef HAVE_LIBPTHREAD
 | 
			
		||||
#undef HAVE_FSEEKO
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
# ifndef __STDC_FORMAT_MACROS
 | 
			
		||||
#  define __STDC_FORMAT_MACROS 1
 | 
			
		||||
# endif
 | 
			
		||||
							
								
								
									
										528
									
								
								libs/fst/fastlz.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										528
									
								
								libs/fst/fastlz.cc
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,528 @@
 | 
			
		|||
/*
 | 
			
		||||
  FastLZ - lightning-fast lossless compression library
 | 
			
		||||
 | 
			
		||||
  Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
 | 
			
		||||
  Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
 | 
			
		||||
  Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
 | 
			
		||||
 | 
			
		||||
  Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
  of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
  in the Software without restriction, including without limitation the rights
 | 
			
		||||
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
  copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
  furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
  The above copyright notice and this permission notice shall be included in
 | 
			
		||||
  all copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
  THE SOFTWARE.
 | 
			
		||||
 | 
			
		||||
  SPDX-License-Identifier: MIT
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "fastlz.h"
 | 
			
		||||
 | 
			
		||||
#if !defined(FASTLZ__COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Always check for bound when decompressing.
 | 
			
		||||
 * Generally it is best to leave it defined.
 | 
			
		||||
 */
 | 
			
		||||
#define FASTLZ_SAFE
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Give hints to the compiler for branch prediction optimization.
 | 
			
		||||
 */
 | 
			
		||||
#if defined(__GNUC__) && (__GNUC__ > 2)
 | 
			
		||||
#define FASTLZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1))
 | 
			
		||||
#define FASTLZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0))
 | 
			
		||||
#else
 | 
			
		||||
#define FASTLZ_EXPECT_CONDITIONAL(c) (c)
 | 
			
		||||
#define FASTLZ_UNEXPECT_CONDITIONAL(c) (c)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Use inlined functions for supported systems.
 | 
			
		||||
 */
 | 
			
		||||
#if defined(__GNUC__) || defined(__DMC__) || defined(__POCC__) || defined(__WATCOMC__) || defined(__SUNPRO_C)
 | 
			
		||||
#define FASTLZ_INLINE inline
 | 
			
		||||
#elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__LCC__)
 | 
			
		||||
#define FASTLZ_INLINE __inline
 | 
			
		||||
#else
 | 
			
		||||
#define FASTLZ_INLINE
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Prevent accessing more than 8-bit at once, except on x86 architectures.
 | 
			
		||||
 */
 | 
			
		||||
#if !defined(FASTLZ_STRICT_ALIGN)
 | 
			
		||||
#define FASTLZ_STRICT_ALIGN
 | 
			
		||||
#if defined(__i386__) || defined(__386) /* GNU C, Sun Studio */
 | 
			
		||||
#undef FASTLZ_STRICT_ALIGN
 | 
			
		||||
#elif defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__amd64) /* GNU C */
 | 
			
		||||
#undef FASTLZ_STRICT_ALIGN
 | 
			
		||||
#elif defined(_M_IX86) /* Intel, MSVC */
 | 
			
		||||
#undef FASTLZ_STRICT_ALIGN
 | 
			
		||||
#elif defined(__386)
 | 
			
		||||
#undef FASTLZ_STRICT_ALIGN
 | 
			
		||||
#elif defined(_X86_) /* MinGW */
 | 
			
		||||
#undef FASTLZ_STRICT_ALIGN
 | 
			
		||||
#elif defined(__I86__) /* Digital Mars */
 | 
			
		||||
#undef FASTLZ_STRICT_ALIGN
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* prototypes */
 | 
			
		||||
int fastlz_compress(const void *input, int length, void *output);
 | 
			
		||||
int fastlz_compress_level(int level, const void *input, int length, void *output);
 | 
			
		||||
int fastlz_decompress(const void *input, int length, void *output, int maxout);
 | 
			
		||||
 | 
			
		||||
#define MAX_COPY 32
 | 
			
		||||
#define MAX_LEN 264 /* 256 + 8 */
 | 
			
		||||
#define MAX_DISTANCE 8192
 | 
			
		||||
 | 
			
		||||
#if !defined(FASTLZ_STRICT_ALIGN)
 | 
			
		||||
#define FASTLZ_READU16(p) *((const flzuint16 *)(p))
 | 
			
		||||
#else
 | 
			
		||||
#define FASTLZ_READU16(p) ((p)[0] | (p)[1] << 8)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define HASH_LOG 13
 | 
			
		||||
#define HASH_SIZE (1 << HASH_LOG)
 | 
			
		||||
#define HASH_MASK (HASH_SIZE - 1)
 | 
			
		||||
#define HASH_FUNCTION(v, p)                                                                                            \
 | 
			
		||||
    {                                                                                                                  \
 | 
			
		||||
        v = FASTLZ_READU16(p);                                                                                         \
 | 
			
		||||
        v ^= FASTLZ_READU16(p + 1) ^ (v >> (16 - HASH_LOG));                                                           \
 | 
			
		||||
        v &= HASH_MASK;                                                                                                \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#undef FASTLZ_LEVEL
 | 
			
		||||
#define FASTLZ_LEVEL 1
 | 
			
		||||
 | 
			
		||||
#undef FASTLZ_COMPRESSOR
 | 
			
		||||
#undef FASTLZ_DECOMPRESSOR
 | 
			
		||||
#define FASTLZ_COMPRESSOR fastlz1_compress
 | 
			
		||||
#define FASTLZ_DECOMPRESSOR fastlz1_decompress
 | 
			
		||||
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void *input, int length, void *output);
 | 
			
		||||
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void *input, int length, void *output, int maxout);
 | 
			
		||||
#include "fastlz.cc"
 | 
			
		||||
 | 
			
		||||
#undef FASTLZ_LEVEL
 | 
			
		||||
#define FASTLZ_LEVEL 2
 | 
			
		||||
 | 
			
		||||
#undef MAX_DISTANCE
 | 
			
		||||
#define MAX_DISTANCE 8191
 | 
			
		||||
#define MAX_FARDISTANCE (65535 + MAX_DISTANCE - 1)
 | 
			
		||||
 | 
			
		||||
#undef FASTLZ_COMPRESSOR
 | 
			
		||||
#undef FASTLZ_DECOMPRESSOR
 | 
			
		||||
#define FASTLZ_COMPRESSOR fastlz2_compress
 | 
			
		||||
#define FASTLZ_DECOMPRESSOR fastlz2_decompress
 | 
			
		||||
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void *input, int length, void *output);
 | 
			
		||||
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void *input, int length, void *output, int maxout);
 | 
			
		||||
#include "fastlz.cc"
 | 
			
		||||
 | 
			
		||||
int fastlz_compress(const void *input, int length, void *output)
 | 
			
		||||
{
 | 
			
		||||
    /* for short block, choose fastlz1 */
 | 
			
		||||
    if (length < 65536)
 | 
			
		||||
        return fastlz1_compress(input, length, output);
 | 
			
		||||
 | 
			
		||||
    /* else... */
 | 
			
		||||
    return fastlz2_compress(input, length, output);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fastlz_decompress(const void *input, int length, void *output, int maxout)
 | 
			
		||||
{
 | 
			
		||||
    /* magic identifier for compression level */
 | 
			
		||||
    int level = ((*(const flzuint8 *)input) >> 5) + 1;
 | 
			
		||||
 | 
			
		||||
    if (level == 1)
 | 
			
		||||
        return fastlz1_decompress(input, length, output, maxout);
 | 
			
		||||
    if (level == 2)
 | 
			
		||||
        return fastlz2_decompress(input, length, output, maxout);
 | 
			
		||||
 | 
			
		||||
    /* unknown level, trigger error */
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fastlz_compress_level(int level, const void *input, int length, void *output)
 | 
			
		||||
{
 | 
			
		||||
    if (level == 1)
 | 
			
		||||
        return fastlz1_compress(input, length, output);
 | 
			
		||||
    if (level == 2)
 | 
			
		||||
        return fastlz2_compress(input, length, output);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
 | 
			
		||||
 | 
			
		||||
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void *input, int length, void *output)
 | 
			
		||||
{
 | 
			
		||||
    const flzuint8 *ip = (const flzuint8 *)input;
 | 
			
		||||
    const flzuint8 *ip_bound = ip + length - 2;
 | 
			
		||||
    const flzuint8 *ip_limit = ip + length - 12;
 | 
			
		||||
    flzuint8 *op = (flzuint8 *)output;
 | 
			
		||||
 | 
			
		||||
    const flzuint8 *htab[HASH_SIZE];
 | 
			
		||||
    const flzuint8 **hslot;
 | 
			
		||||
    flzuint32 hval;
 | 
			
		||||
 | 
			
		||||
    flzuint32 copy;
 | 
			
		||||
 | 
			
		||||
    /* sanity check */
 | 
			
		||||
    if (FASTLZ_UNEXPECT_CONDITIONAL(length < 4)) {
 | 
			
		||||
        if (length) {
 | 
			
		||||
            /* create literal copy only */
 | 
			
		||||
            *op++ = length - 1;
 | 
			
		||||
            ip_bound++;
 | 
			
		||||
            while (ip <= ip_bound)
 | 
			
		||||
                *op++ = *ip++;
 | 
			
		||||
            return length + 1;
 | 
			
		||||
        } else
 | 
			
		||||
            return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* initializes hash table */
 | 
			
		||||
    for (hslot = htab; hslot < htab + HASH_SIZE; hslot++)
 | 
			
		||||
        *hslot = ip;
 | 
			
		||||
 | 
			
		||||
    /* we start with literal copy */
 | 
			
		||||
    copy = 2;
 | 
			
		||||
    *op++ = MAX_COPY - 1;
 | 
			
		||||
    *op++ = *ip++;
 | 
			
		||||
    *op++ = *ip++;
 | 
			
		||||
 | 
			
		||||
    /* main loop */
 | 
			
		||||
    while (FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit)) {
 | 
			
		||||
        const flzuint8 *ref;
 | 
			
		||||
        flzuint32 distance;
 | 
			
		||||
 | 
			
		||||
        /* minimum match length */
 | 
			
		||||
        flzuint32 len = 3;
 | 
			
		||||
 | 
			
		||||
        /* comparison starting-point */
 | 
			
		||||
        const flzuint8 *anchor = ip;
 | 
			
		||||
 | 
			
		||||
        /* check for a run */
 | 
			
		||||
#if FASTLZ_LEVEL == 2
 | 
			
		||||
        if (ip[0] == ip[-1] && FASTLZ_READU16(ip - 1) == FASTLZ_READU16(ip + 1)) {
 | 
			
		||||
            distance = 1;
 | 
			
		||||
            /* ip += 3; */ /* scan-build, never used */
 | 
			
		||||
            ref = anchor - 1 + 3;
 | 
			
		||||
            goto match;
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        /* find potential match */
 | 
			
		||||
        HASH_FUNCTION(hval, ip);
 | 
			
		||||
        hslot = htab + hval;
 | 
			
		||||
        ref = htab[hval];
 | 
			
		||||
 | 
			
		||||
        /* calculate distance to the match */
 | 
			
		||||
        distance = anchor - ref;
 | 
			
		||||
 | 
			
		||||
        /* update hash table */
 | 
			
		||||
        *hslot = anchor;
 | 
			
		||||
 | 
			
		||||
        /* is this a match? check the first 3 bytes */
 | 
			
		||||
        if (distance == 0 ||
 | 
			
		||||
#if FASTLZ_LEVEL == 1
 | 
			
		||||
            (distance >= MAX_DISTANCE) ||
 | 
			
		||||
#else
 | 
			
		||||
            (distance >= MAX_FARDISTANCE) ||
 | 
			
		||||
#endif
 | 
			
		||||
            *ref++ != *ip++ || *ref++ != *ip++ || *ref++ != *ip++)
 | 
			
		||||
            goto literal;
 | 
			
		||||
 | 
			
		||||
#if FASTLZ_LEVEL == 2
 | 
			
		||||
        /* far, needs at least 5-byte match */
 | 
			
		||||
        if (distance >= MAX_DISTANCE) {
 | 
			
		||||
            if (*ip++ != *ref++ || *ip++ != *ref++)
 | 
			
		||||
                goto literal;
 | 
			
		||||
            len += 2;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    match:
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        /* last matched byte */
 | 
			
		||||
        ip = anchor + len;
 | 
			
		||||
 | 
			
		||||
        /* distance is biased */
 | 
			
		||||
        distance--;
 | 
			
		||||
 | 
			
		||||
        if (!distance) {
 | 
			
		||||
            /* zero distance means a run */
 | 
			
		||||
            flzuint8 x = ip[-1];
 | 
			
		||||
            while (ip < ip_bound)
 | 
			
		||||
                if (*ref++ != x)
 | 
			
		||||
                    break;
 | 
			
		||||
                else
 | 
			
		||||
                    ip++;
 | 
			
		||||
        } else
 | 
			
		||||
            for (;;) {
 | 
			
		||||
                /* safe because the outer check against ip limit */
 | 
			
		||||
                if (*ref++ != *ip++)
 | 
			
		||||
                    break;
 | 
			
		||||
                if (*ref++ != *ip++)
 | 
			
		||||
                    break;
 | 
			
		||||
                if (*ref++ != *ip++)
 | 
			
		||||
                    break;
 | 
			
		||||
                if (*ref++ != *ip++)
 | 
			
		||||
                    break;
 | 
			
		||||
                if (*ref++ != *ip++)
 | 
			
		||||
                    break;
 | 
			
		||||
                if (*ref++ != *ip++)
 | 
			
		||||
                    break;
 | 
			
		||||
                if (*ref++ != *ip++)
 | 
			
		||||
                    break;
 | 
			
		||||
                if (*ref++ != *ip++)
 | 
			
		||||
                    break;
 | 
			
		||||
                while (ip < ip_bound)
 | 
			
		||||
                    if (*ref++ != *ip++)
 | 
			
		||||
                        break;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        /* if we have copied something, adjust the copy count */
 | 
			
		||||
        if (copy)
 | 
			
		||||
            /* copy is biased, '0' means 1 byte copy */
 | 
			
		||||
            *(op - copy - 1) = copy - 1;
 | 
			
		||||
        else
 | 
			
		||||
            /* back, to overwrite the copy count */
 | 
			
		||||
            op--;
 | 
			
		||||
 | 
			
		||||
        /* reset literal counter */
 | 
			
		||||
        copy = 0;
 | 
			
		||||
 | 
			
		||||
        /* length is biased, '1' means a match of 3 bytes */
 | 
			
		||||
        ip -= 3;
 | 
			
		||||
        len = ip - anchor;
 | 
			
		||||
 | 
			
		||||
        /* encode the match */
 | 
			
		||||
#if FASTLZ_LEVEL == 2
 | 
			
		||||
        if (distance < MAX_DISTANCE) {
 | 
			
		||||
            if (len < 7) {
 | 
			
		||||
                *op++ = (len << 5) + (distance >> 8);
 | 
			
		||||
                *op++ = (distance & 255);
 | 
			
		||||
            } else {
 | 
			
		||||
                *op++ = (7 << 5) + (distance >> 8);
 | 
			
		||||
                for (len -= 7; len >= 255; len -= 255)
 | 
			
		||||
                    *op++ = 255;
 | 
			
		||||
                *op++ = len;
 | 
			
		||||
                *op++ = (distance & 255);
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            /* far away, but not yet in the another galaxy... */
 | 
			
		||||
            if (len < 7) {
 | 
			
		||||
                distance -= MAX_DISTANCE;
 | 
			
		||||
                *op++ = (len << 5) + 31;
 | 
			
		||||
                *op++ = 255;
 | 
			
		||||
                *op++ = distance >> 8;
 | 
			
		||||
                *op++ = distance & 255;
 | 
			
		||||
            } else {
 | 
			
		||||
                distance -= MAX_DISTANCE;
 | 
			
		||||
                *op++ = (7 << 5) + 31;
 | 
			
		||||
                for (len -= 7; len >= 255; len -= 255)
 | 
			
		||||
                    *op++ = 255;
 | 
			
		||||
                *op++ = len;
 | 
			
		||||
                *op++ = 255;
 | 
			
		||||
                *op++ = distance >> 8;
 | 
			
		||||
                *op++ = distance & 255;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
        if (FASTLZ_UNEXPECT_CONDITIONAL(len > MAX_LEN - 2))
 | 
			
		||||
            while (len > MAX_LEN - 2) {
 | 
			
		||||
                *op++ = (7 << 5) + (distance >> 8);
 | 
			
		||||
                *op++ = MAX_LEN - 2 - 7 - 2;
 | 
			
		||||
                *op++ = (distance & 255);
 | 
			
		||||
                len -= MAX_LEN - 2;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        if (len < 7) {
 | 
			
		||||
            *op++ = (len << 5) + (distance >> 8);
 | 
			
		||||
            *op++ = (distance & 255);
 | 
			
		||||
        } else {
 | 
			
		||||
            *op++ = (7 << 5) + (distance >> 8);
 | 
			
		||||
            *op++ = len - 7;
 | 
			
		||||
            *op++ = (distance & 255);
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        /* update the hash at match boundary */
 | 
			
		||||
        HASH_FUNCTION(hval, ip);
 | 
			
		||||
        htab[hval] = ip++;
 | 
			
		||||
        HASH_FUNCTION(hval, ip);
 | 
			
		||||
        htab[hval] = ip++;
 | 
			
		||||
 | 
			
		||||
        /* assuming literal copy */
 | 
			
		||||
        *op++ = MAX_COPY - 1;
 | 
			
		||||
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
    literal:
 | 
			
		||||
        *op++ = *anchor++;
 | 
			
		||||
        ip = anchor;
 | 
			
		||||
        copy++;
 | 
			
		||||
        if (FASTLZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY)) {
 | 
			
		||||
            copy = 0;
 | 
			
		||||
            *op++ = MAX_COPY - 1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* left-over as literal copy */
 | 
			
		||||
    ip_bound++;
 | 
			
		||||
    while (ip <= ip_bound) {
 | 
			
		||||
        *op++ = *ip++;
 | 
			
		||||
        copy++;
 | 
			
		||||
        if (copy == MAX_COPY) {
 | 
			
		||||
            copy = 0;
 | 
			
		||||
            *op++ = MAX_COPY - 1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* if we have copied something, adjust the copy length */
 | 
			
		||||
    if (copy)
 | 
			
		||||
        *(op - copy - 1) = copy - 1;
 | 
			
		||||
    else
 | 
			
		||||
        op--;
 | 
			
		||||
 | 
			
		||||
#if FASTLZ_LEVEL == 2
 | 
			
		||||
    /* marker for fastlz2 */
 | 
			
		||||
    *(flzuint8 *)output |= (1 << 5);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    return op - (flzuint8 *)output;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void *input, int length, void *output, int maxout)
 | 
			
		||||
{
 | 
			
		||||
    const flzuint8 *ip = (const flzuint8 *)input;
 | 
			
		||||
    const flzuint8 *ip_limit = ip + length;
 | 
			
		||||
    flzuint8 *op = (flzuint8 *)output;
 | 
			
		||||
    flzuint8 *op_limit = op + maxout;
 | 
			
		||||
    flzuint32 ctrl = (*ip++) & 31;
 | 
			
		||||
    int loop = 1;
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
        const flzuint8 *ref = op;
 | 
			
		||||
        flzuint32 len = ctrl >> 5;
 | 
			
		||||
        flzuint32 ofs = (ctrl & 31) << 8;
 | 
			
		||||
 | 
			
		||||
        if (ctrl >= 32) {
 | 
			
		||||
#if FASTLZ_LEVEL == 2
 | 
			
		||||
            flzuint8 code;
 | 
			
		||||
#endif
 | 
			
		||||
            len--;
 | 
			
		||||
            ref -= ofs;
 | 
			
		||||
            if (len == 7 - 1)
 | 
			
		||||
#if FASTLZ_LEVEL == 1
 | 
			
		||||
                len += *ip++;
 | 
			
		||||
            ref -= *ip++;
 | 
			
		||||
#else
 | 
			
		||||
                do {
 | 
			
		||||
                    code = *ip++;
 | 
			
		||||
                    len += code;
 | 
			
		||||
                } while (code == 255);
 | 
			
		||||
            code = *ip++;
 | 
			
		||||
            ref -= code;
 | 
			
		||||
 | 
			
		||||
            /* match from 16-bit distance */
 | 
			
		||||
            if (FASTLZ_UNEXPECT_CONDITIONAL(code == 255))
 | 
			
		||||
                if (FASTLZ_EXPECT_CONDITIONAL(ofs == (31 << 8))) {
 | 
			
		||||
                    ofs = (*ip++) << 8;
 | 
			
		||||
                    ofs += *ip++;
 | 
			
		||||
                    ref = op - ofs - MAX_DISTANCE;
 | 
			
		||||
                }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef FASTLZ_SAFE
 | 
			
		||||
            if (FASTLZ_UNEXPECT_CONDITIONAL(op + len + 3 > op_limit))
 | 
			
		||||
                return 0;
 | 
			
		||||
 | 
			
		||||
            if (FASTLZ_UNEXPECT_CONDITIONAL(ref - 1 < (flzuint8 *)output))
 | 
			
		||||
                return 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
            if (FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
 | 
			
		||||
                ctrl = *ip++;
 | 
			
		||||
            else
 | 
			
		||||
                loop = 0;
 | 
			
		||||
 | 
			
		||||
            if (ref == op) {
 | 
			
		||||
                /* optimize copy for a run */
 | 
			
		||||
                flzuint8 b = ref[-1];
 | 
			
		||||
                *op++ = b;
 | 
			
		||||
                *op++ = b;
 | 
			
		||||
                *op++ = b;
 | 
			
		||||
                for (; len; --len)
 | 
			
		||||
                    *op++ = b;
 | 
			
		||||
            } else {
 | 
			
		||||
#if !defined(FASTLZ_STRICT_ALIGN)
 | 
			
		||||
                const flzuint16 *p;
 | 
			
		||||
                flzuint16 *q;
 | 
			
		||||
#endif
 | 
			
		||||
                /* copy from reference */
 | 
			
		||||
                ref--;
 | 
			
		||||
                *op++ = *ref++;
 | 
			
		||||
                *op++ = *ref++;
 | 
			
		||||
                *op++ = *ref++;
 | 
			
		||||
 | 
			
		||||
#if !defined(FASTLZ_STRICT_ALIGN)
 | 
			
		||||
                /* copy a byte, so that now it's word aligned */
 | 
			
		||||
                if (len & 1) {
 | 
			
		||||
                    *op++ = *ref++;
 | 
			
		||||
                    len--;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                /* copy 16-bit at once */
 | 
			
		||||
                q = (flzuint16 *)op;
 | 
			
		||||
                op += len;
 | 
			
		||||
                p = (const flzuint16 *)ref;
 | 
			
		||||
                for (len >>= 1; len > 4; len -= 4) {
 | 
			
		||||
                    *q++ = *p++;
 | 
			
		||||
                    *q++ = *p++;
 | 
			
		||||
                    *q++ = *p++;
 | 
			
		||||
                    *q++ = *p++;
 | 
			
		||||
                }
 | 
			
		||||
                for (; len; --len)
 | 
			
		||||
                    *q++ = *p++;
 | 
			
		||||
#else
 | 
			
		||||
                for (; len; --len)
 | 
			
		||||
                    *op++ = *ref++;
 | 
			
		||||
#endif
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            ctrl++;
 | 
			
		||||
#ifdef FASTLZ_SAFE
 | 
			
		||||
            if (FASTLZ_UNEXPECT_CONDITIONAL(op + ctrl > op_limit))
 | 
			
		||||
                return 0;
 | 
			
		||||
            if (FASTLZ_UNEXPECT_CONDITIONAL(ip + ctrl > ip_limit))
 | 
			
		||||
                return 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
            *op++ = *ip++;
 | 
			
		||||
            for (--ctrl; ctrl; ctrl--)
 | 
			
		||||
                *op++ = *ip++;
 | 
			
		||||
 | 
			
		||||
            loop = FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit);
 | 
			
		||||
            if (loop)
 | 
			
		||||
                ctrl = *ip++;
 | 
			
		||||
        }
 | 
			
		||||
    } while (FASTLZ_EXPECT_CONDITIONAL(loop));
 | 
			
		||||
 | 
			
		||||
    return op - (flzuint8 *)output;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
 | 
			
		||||
							
								
								
									
										109
									
								
								libs/fst/fastlz.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								libs/fst/fastlz.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,109 @@
 | 
			
		|||
/*
 | 
			
		||||
  FastLZ - lightning-fast lossless compression library
 | 
			
		||||
 | 
			
		||||
  Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
 | 
			
		||||
  Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
 | 
			
		||||
  Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
 | 
			
		||||
 | 
			
		||||
  Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
  of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
  in the Software without restriction, including without limitation the rights
 | 
			
		||||
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
  copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
  furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
  The above copyright notice and this permission notice shall be included in
 | 
			
		||||
  all copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
  THE SOFTWARE.
 | 
			
		||||
 | 
			
		||||
  SPDX-License-Identifier: MIT
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef FASTLZ_H
 | 
			
		||||
#define FASTLZ_H
 | 
			
		||||
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
 | 
			
		||||
#define flzuint8 uint8_t
 | 
			
		||||
#define flzuint16 uint16_t
 | 
			
		||||
#define flzuint32 uint32_t
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define FASTLZ_VERSION 0x000100
 | 
			
		||||
 | 
			
		||||
#define FASTLZ_VERSION_MAJOR     0
 | 
			
		||||
#define FASTLZ_VERSION_MINOR     0
 | 
			
		||||
#define FASTLZ_VERSION_REVISION  0
 | 
			
		||||
 | 
			
		||||
#define FASTLZ_VERSION_STRING "0.1.0"
 | 
			
		||||
 | 
			
		||||
#if defined (__cplusplus)
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  Compress a block of data in the input buffer and returns the size of
 | 
			
		||||
  compressed block. The size of input buffer is specified by length. The
 | 
			
		||||
  minimum input buffer size is 16.
 | 
			
		||||
 | 
			
		||||
  The output buffer must be at least 5% larger than the input buffer
 | 
			
		||||
  and can not be smaller than 66 bytes.
 | 
			
		||||
 | 
			
		||||
  If the input is not compressible, the return value might be larger than
 | 
			
		||||
  length (input buffer size).
 | 
			
		||||
 | 
			
		||||
  The input buffer and the output buffer can not overlap.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
int fastlz_compress(const void* input, int length, void* output);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  Decompress a block of compressed data and returns the size of the
 | 
			
		||||
  decompressed block. If error occurs, e.g. the compressed data is
 | 
			
		||||
  corrupted or the output buffer is not large enough, then 0 (zero)
 | 
			
		||||
  will be returned instead.
 | 
			
		||||
 | 
			
		||||
  The input buffer and the output buffer can not overlap.
 | 
			
		||||
 | 
			
		||||
  Decompression is memory safe and guaranteed not to write the output buffer
 | 
			
		||||
  more than what is specified in maxout.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
int fastlz_decompress(const void* input, int length, void* output, int maxout);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  Compress a block of data in the input buffer and returns the size of
 | 
			
		||||
  compressed block. The size of input buffer is specified by length. The
 | 
			
		||||
  minimum input buffer size is 16.
 | 
			
		||||
 | 
			
		||||
  The output buffer must be at least 5% larger than the input buffer
 | 
			
		||||
  and can not be smaller than 66 bytes.
 | 
			
		||||
 | 
			
		||||
  If the input is not compressible, the return value might be larger than
 | 
			
		||||
  length (input buffer size).
 | 
			
		||||
 | 
			
		||||
  The input buffer and the output buffer can not overlap.
 | 
			
		||||
 | 
			
		||||
  Compression level can be specified in parameter level. At the moment,
 | 
			
		||||
  only level 1 and level 2 are supported.
 | 
			
		||||
  Level 1 is the fastest compression and generally useful for short data.
 | 
			
		||||
  Level 2 is slightly slower but it gives better compression ratio.
 | 
			
		||||
 | 
			
		||||
  Note that the compressed data, regardless of the level, can always be
 | 
			
		||||
  decompressed using the function fastlz_decompress above.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
int fastlz_compress_level(int level, const void* input, int length, void* output);
 | 
			
		||||
 | 
			
		||||
#if defined (__cplusplus)
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* FASTLZ_H */
 | 
			
		||||
							
								
								
									
										6546
									
								
								libs/fst/fstapi.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6546
									
								
								libs/fst/fstapi.cc
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										500
									
								
								libs/fst/fstapi.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										500
									
								
								libs/fst/fstapi.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,500 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2009-2018 Tony Bybell.
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a
 | 
			
		||||
 * copy of this software and associated documentation files (the "Software"),
 | 
			
		||||
 * to deal in the Software without restriction, including without limitation
 | 
			
		||||
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | 
			
		||||
 * and/or sell copies of the Software, and to permit persons to whom the
 | 
			
		||||
 * Software is furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 | 
			
		||||
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | 
			
		||||
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 | 
			
		||||
 * DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: MIT
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef FST_API_H
 | 
			
		||||
#define FST_API_H
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#if defined(_MSC_VER)
 | 
			
		||||
#include "libs/zlib/zlib.h"
 | 
			
		||||
#include <io.h>
 | 
			
		||||
 | 
			
		||||
#include <process.h>
 | 
			
		||||
 | 
			
		||||
#define ftruncate _chsize_s
 | 
			
		||||
#define unlink _unlink
 | 
			
		||||
#define fileno _fileno
 | 
			
		||||
#define lseek _lseeki64
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN64
 | 
			
		||||
#define ssize_t __int64
 | 
			
		||||
#define SSIZE_MAX 9223372036854775807i64
 | 
			
		||||
#else
 | 
			
		||||
#define ssize_t long
 | 
			
		||||
#define SSIZE_MAX 2147483647L
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "stdint.h"
 | 
			
		||||
#else
 | 
			
		||||
#include <zlib.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#endif
 | 
			
		||||
#include <time.h>
 | 
			
		||||
 | 
			
		||||
#define FST_RDLOAD "FSTLOAD | "
 | 
			
		||||
 | 
			
		||||
typedef uint32_t fstHandle;
 | 
			
		||||
typedef uint32_t fstEnumHandle;
 | 
			
		||||
 | 
			
		||||
enum fstWriterPackType
 | 
			
		||||
{
 | 
			
		||||
    FST_WR_PT_ZLIB = 0,
 | 
			
		||||
    FST_WR_PT_FASTLZ = 1,
 | 
			
		||||
    FST_WR_PT_LZ4 = 2
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum fstFileType
 | 
			
		||||
{
 | 
			
		||||
    FST_FT_MIN = 0,
 | 
			
		||||
 | 
			
		||||
    FST_FT_VERILOG = 0,
 | 
			
		||||
    FST_FT_VHDL = 1,
 | 
			
		||||
    FST_FT_VERILOG_VHDL = 2,
 | 
			
		||||
 | 
			
		||||
    FST_FT_MAX = 2
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum fstBlockType
 | 
			
		||||
{
 | 
			
		||||
    FST_BL_HDR = 0,
 | 
			
		||||
    FST_BL_VCDATA = 1,
 | 
			
		||||
    FST_BL_BLACKOUT = 2,
 | 
			
		||||
    FST_BL_GEOM = 3,
 | 
			
		||||
    FST_BL_HIER = 4,
 | 
			
		||||
    FST_BL_VCDATA_DYN_ALIAS = 5,
 | 
			
		||||
    FST_BL_HIER_LZ4 = 6,
 | 
			
		||||
    FST_BL_HIER_LZ4DUO = 7,
 | 
			
		||||
    FST_BL_VCDATA_DYN_ALIAS2 = 8,
 | 
			
		||||
 | 
			
		||||
    FST_BL_ZWRAPPER = 254, /* indicates that whole trace is gz wrapped */
 | 
			
		||||
    FST_BL_SKIP = 255      /* used while block is being written */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum fstScopeType
 | 
			
		||||
{
 | 
			
		||||
    FST_ST_MIN = 0,
 | 
			
		||||
 | 
			
		||||
    FST_ST_VCD_MODULE = 0,
 | 
			
		||||
    FST_ST_VCD_TASK = 1,
 | 
			
		||||
    FST_ST_VCD_FUNCTION = 2,
 | 
			
		||||
    FST_ST_VCD_BEGIN = 3,
 | 
			
		||||
    FST_ST_VCD_FORK = 4,
 | 
			
		||||
    FST_ST_VCD_GENERATE = 5,
 | 
			
		||||
    FST_ST_VCD_STRUCT = 6,
 | 
			
		||||
    FST_ST_VCD_UNION = 7,
 | 
			
		||||
    FST_ST_VCD_CLASS = 8,
 | 
			
		||||
    FST_ST_VCD_INTERFACE = 9,
 | 
			
		||||
    FST_ST_VCD_PACKAGE = 10,
 | 
			
		||||
    FST_ST_VCD_PROGRAM = 11,
 | 
			
		||||
 | 
			
		||||
    FST_ST_VHDL_ARCHITECTURE = 12,
 | 
			
		||||
    FST_ST_VHDL_PROCEDURE = 13,
 | 
			
		||||
    FST_ST_VHDL_FUNCTION = 14,
 | 
			
		||||
    FST_ST_VHDL_RECORD = 15,
 | 
			
		||||
    FST_ST_VHDL_PROCESS = 16,
 | 
			
		||||
    FST_ST_VHDL_BLOCK = 17,
 | 
			
		||||
    FST_ST_VHDL_FOR_GENERATE = 18,
 | 
			
		||||
    FST_ST_VHDL_IF_GENERATE = 19,
 | 
			
		||||
    FST_ST_VHDL_GENERATE = 20,
 | 
			
		||||
    FST_ST_VHDL_PACKAGE = 21,
 | 
			
		||||
 | 
			
		||||
    FST_ST_MAX = 21,
 | 
			
		||||
 | 
			
		||||
    FST_ST_GEN_ATTRBEGIN = 252,
 | 
			
		||||
    FST_ST_GEN_ATTREND = 253,
 | 
			
		||||
 | 
			
		||||
    FST_ST_VCD_SCOPE = 254,
 | 
			
		||||
    FST_ST_VCD_UPSCOPE = 255
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum fstVarType
 | 
			
		||||
{
 | 
			
		||||
    FST_VT_MIN = 0, /* start of vartypes */
 | 
			
		||||
 | 
			
		||||
    FST_VT_VCD_EVENT = 0,
 | 
			
		||||
    FST_VT_VCD_INTEGER = 1,
 | 
			
		||||
    FST_VT_VCD_PARAMETER = 2,
 | 
			
		||||
    FST_VT_VCD_REAL = 3,
 | 
			
		||||
    FST_VT_VCD_REAL_PARAMETER = 4,
 | 
			
		||||
    FST_VT_VCD_REG = 5,
 | 
			
		||||
    FST_VT_VCD_SUPPLY0 = 6,
 | 
			
		||||
    FST_VT_VCD_SUPPLY1 = 7,
 | 
			
		||||
    FST_VT_VCD_TIME = 8,
 | 
			
		||||
    FST_VT_VCD_TRI = 9,
 | 
			
		||||
    FST_VT_VCD_TRIAND = 10,
 | 
			
		||||
    FST_VT_VCD_TRIOR = 11,
 | 
			
		||||
    FST_VT_VCD_TRIREG = 12,
 | 
			
		||||
    FST_VT_VCD_TRI0 = 13,
 | 
			
		||||
    FST_VT_VCD_TRI1 = 14,
 | 
			
		||||
    FST_VT_VCD_WAND = 15,
 | 
			
		||||
    FST_VT_VCD_WIRE = 16,
 | 
			
		||||
    FST_VT_VCD_WOR = 17,
 | 
			
		||||
    FST_VT_VCD_PORT = 18,
 | 
			
		||||
    FST_VT_VCD_SPARRAY = 19, /* used to define the rownum (index) port for a sparse array */
 | 
			
		||||
    FST_VT_VCD_REALTIME = 20,
 | 
			
		||||
 | 
			
		||||
    FST_VT_GEN_STRING =
 | 
			
		||||
            21, /* generic string type   (max len is defined dynamically via fstWriterEmitVariableLengthValueChange) */
 | 
			
		||||
 | 
			
		||||
    FST_VT_SV_BIT = 22,
 | 
			
		||||
    FST_VT_SV_LOGIC = 23,
 | 
			
		||||
    FST_VT_SV_INT = 24,      /* declare as size = 32 */
 | 
			
		||||
    FST_VT_SV_SHORTINT = 25, /* declare as size = 16 */
 | 
			
		||||
    FST_VT_SV_LONGINT = 26,  /* declare as size = 64 */
 | 
			
		||||
    FST_VT_SV_BYTE = 27,     /* declare as size = 8  */
 | 
			
		||||
    FST_VT_SV_ENUM = 28,     /* declare as appropriate type range */
 | 
			
		||||
    FST_VT_SV_SHORTREAL =
 | 
			
		||||
            29, /* declare and emit same as FST_VT_VCD_REAL (needs to be emitted as double, not a float) */
 | 
			
		||||
 | 
			
		||||
    FST_VT_MAX = 29 /* end of vartypes */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum fstVarDir
 | 
			
		||||
{
 | 
			
		||||
    FST_VD_MIN = 0,
 | 
			
		||||
 | 
			
		||||
    FST_VD_IMPLICIT = 0,
 | 
			
		||||
    FST_VD_INPUT = 1,
 | 
			
		||||
    FST_VD_OUTPUT = 2,
 | 
			
		||||
    FST_VD_INOUT = 3,
 | 
			
		||||
    FST_VD_BUFFER = 4,
 | 
			
		||||
    FST_VD_LINKAGE = 5,
 | 
			
		||||
 | 
			
		||||
    FST_VD_MAX = 5
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum fstHierType
 | 
			
		||||
{
 | 
			
		||||
    FST_HT_MIN = 0,
 | 
			
		||||
 | 
			
		||||
    FST_HT_SCOPE = 0,
 | 
			
		||||
    FST_HT_UPSCOPE = 1,
 | 
			
		||||
    FST_HT_VAR = 2,
 | 
			
		||||
    FST_HT_ATTRBEGIN = 3,
 | 
			
		||||
    FST_HT_ATTREND = 4,
 | 
			
		||||
 | 
			
		||||
    /* FST_HT_TREEBEGIN and FST_HT_TREEEND are not yet used by FST but are currently used when fstHier bridges other
 | 
			
		||||
       formats */
 | 
			
		||||
    FST_HT_TREEBEGIN = 5,
 | 
			
		||||
    FST_HT_TREEEND = 6,
 | 
			
		||||
 | 
			
		||||
    FST_HT_MAX = 6
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum fstAttrType
 | 
			
		||||
{
 | 
			
		||||
    FST_AT_MIN = 0,
 | 
			
		||||
 | 
			
		||||
    FST_AT_MISC = 0, /* self-contained: does not need matching FST_HT_ATTREND */
 | 
			
		||||
    FST_AT_ARRAY = 1,
 | 
			
		||||
    FST_AT_ENUM = 2,
 | 
			
		||||
    FST_AT_PACK = 3,
 | 
			
		||||
 | 
			
		||||
    FST_AT_MAX = 3
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum fstMiscType
 | 
			
		||||
{
 | 
			
		||||
    FST_MT_MIN = 0,
 | 
			
		||||
 | 
			
		||||
    FST_MT_COMMENT = 0,     /* use fstWriterSetComment() to emit */
 | 
			
		||||
    FST_MT_ENVVAR = 1,      /* use fstWriterSetEnvVar() to emit */
 | 
			
		||||
    FST_MT_SUPVAR = 2,      /* use fstWriterCreateVar2() to emit */
 | 
			
		||||
    FST_MT_PATHNAME = 3,    /* reserved for fstWriterSetSourceStem() string -> number management */
 | 
			
		||||
    FST_MT_SOURCESTEM = 4,  /* use fstWriterSetSourceStem() to emit */
 | 
			
		||||
    FST_MT_SOURCEISTEM = 5, /* use fstWriterSetSourceInstantiationStem() to emit */
 | 
			
		||||
    FST_MT_VALUELIST = 6,   /* use fstWriterSetValueList() to emit, followed by fstWriterCreateVar*() */
 | 
			
		||||
    FST_MT_ENUMTABLE = 7,   /* use fstWriterCreateEnumTable() and fstWriterEmitEnumTableRef() to emit */
 | 
			
		||||
    FST_MT_UNKNOWN = 8,
 | 
			
		||||
 | 
			
		||||
    FST_MT_MAX = 8
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum fstArrayType
 | 
			
		||||
{
 | 
			
		||||
    FST_AR_MIN = 0,
 | 
			
		||||
 | 
			
		||||
    FST_AR_NONE = 0,
 | 
			
		||||
    FST_AR_UNPACKED = 1,
 | 
			
		||||
    FST_AR_PACKED = 2,
 | 
			
		||||
    FST_AR_SPARSE = 3,
 | 
			
		||||
 | 
			
		||||
    FST_AR_MAX = 3
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum fstEnumValueType
 | 
			
		||||
{
 | 
			
		||||
    FST_EV_SV_INTEGER = 0,
 | 
			
		||||
    FST_EV_SV_BIT = 1,
 | 
			
		||||
    FST_EV_SV_LOGIC = 2,
 | 
			
		||||
    FST_EV_SV_INT = 3,
 | 
			
		||||
    FST_EV_SV_SHORTINT = 4,
 | 
			
		||||
    FST_EV_SV_LONGINT = 5,
 | 
			
		||||
    FST_EV_SV_BYTE = 6,
 | 
			
		||||
    FST_EV_SV_UNSIGNED_INTEGER = 7,
 | 
			
		||||
    FST_EV_SV_UNSIGNED_BIT = 8,
 | 
			
		||||
    FST_EV_SV_UNSIGNED_LOGIC = 9,
 | 
			
		||||
    FST_EV_SV_UNSIGNED_INT = 10,
 | 
			
		||||
    FST_EV_SV_UNSIGNED_SHORTINT = 11,
 | 
			
		||||
    FST_EV_SV_UNSIGNED_LONGINT = 12,
 | 
			
		||||
    FST_EV_SV_UNSIGNED_BYTE = 13,
 | 
			
		||||
 | 
			
		||||
    FST_EV_REG = 14,
 | 
			
		||||
    FST_EV_TIME = 15,
 | 
			
		||||
 | 
			
		||||
    FST_EV_MAX = 15
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum fstPackType
 | 
			
		||||
{
 | 
			
		||||
    FST_PT_NONE = 0,
 | 
			
		||||
    FST_PT_UNPACKED = 1,
 | 
			
		||||
    FST_PT_PACKED = 2,
 | 
			
		||||
    FST_PT_TAGGED_PACKED = 3,
 | 
			
		||||
 | 
			
		||||
    FST_PT_MAX = 3
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum fstSupplementalVarType
 | 
			
		||||
{
 | 
			
		||||
    FST_SVT_MIN = 0,
 | 
			
		||||
 | 
			
		||||
    FST_SVT_NONE = 0,
 | 
			
		||||
 | 
			
		||||
    FST_SVT_VHDL_SIGNAL = 1,
 | 
			
		||||
    FST_SVT_VHDL_VARIABLE = 2,
 | 
			
		||||
    FST_SVT_VHDL_CONSTANT = 3,
 | 
			
		||||
    FST_SVT_VHDL_FILE = 4,
 | 
			
		||||
    FST_SVT_VHDL_MEMORY = 5,
 | 
			
		||||
 | 
			
		||||
    FST_SVT_MAX = 5
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum fstSupplementalDataType
 | 
			
		||||
{
 | 
			
		||||
    FST_SDT_MIN = 0,
 | 
			
		||||
 | 
			
		||||
    FST_SDT_NONE = 0,
 | 
			
		||||
 | 
			
		||||
    FST_SDT_VHDL_BOOLEAN = 1,
 | 
			
		||||
    FST_SDT_VHDL_BIT = 2,
 | 
			
		||||
    FST_SDT_VHDL_BIT_VECTOR = 3,
 | 
			
		||||
    FST_SDT_VHDL_STD_ULOGIC = 4,
 | 
			
		||||
    FST_SDT_VHDL_STD_ULOGIC_VECTOR = 5,
 | 
			
		||||
    FST_SDT_VHDL_STD_LOGIC = 6,
 | 
			
		||||
    FST_SDT_VHDL_STD_LOGIC_VECTOR = 7,
 | 
			
		||||
    FST_SDT_VHDL_UNSIGNED = 8,
 | 
			
		||||
    FST_SDT_VHDL_SIGNED = 9,
 | 
			
		||||
    FST_SDT_VHDL_INTEGER = 10,
 | 
			
		||||
    FST_SDT_VHDL_REAL = 11,
 | 
			
		||||
    FST_SDT_VHDL_NATURAL = 12,
 | 
			
		||||
    FST_SDT_VHDL_POSITIVE = 13,
 | 
			
		||||
    FST_SDT_VHDL_TIME = 14,
 | 
			
		||||
    FST_SDT_VHDL_CHARACTER = 15,
 | 
			
		||||
    FST_SDT_VHDL_STRING = 16,
 | 
			
		||||
 | 
			
		||||
    FST_SDT_MAX = 16,
 | 
			
		||||
 | 
			
		||||
    FST_SDT_SVT_SHIFT_COUNT =
 | 
			
		||||
            10, /* FST_SVT_* is ORed in by fstWriterCreateVar2() to the left after shifting FST_SDT_SVT_SHIFT_COUNT */
 | 
			
		||||
    FST_SDT_ABS_MAX = ((1 << (FST_SDT_SVT_SHIFT_COUNT)) - 1)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct fstHier
 | 
			
		||||
{
 | 
			
		||||
    unsigned char htyp;
 | 
			
		||||
 | 
			
		||||
    union
 | 
			
		||||
    {
 | 
			
		||||
        /* if htyp == FST_HT_SCOPE */
 | 
			
		||||
        struct fstHierScope
 | 
			
		||||
        {
 | 
			
		||||
            unsigned char typ; /* FST_ST_MIN ... FST_ST_MAX */
 | 
			
		||||
            const char *name;
 | 
			
		||||
            const char *component;
 | 
			
		||||
            uint32_t name_length;      /* strlen(u.scope.name) */
 | 
			
		||||
            uint32_t component_length; /* strlen(u.scope.component) */
 | 
			
		||||
        } scope;
 | 
			
		||||
 | 
			
		||||
        /* if htyp == FST_HT_VAR */
 | 
			
		||||
        struct fstHierVar
 | 
			
		||||
        {
 | 
			
		||||
            unsigned char typ;           /* FST_VT_MIN ... FST_VT_MAX */
 | 
			
		||||
            unsigned char direction;     /* FST_VD_MIN ... FST_VD_MAX */
 | 
			
		||||
            unsigned char svt_workspace; /* zeroed out by FST reader, for client code use */
 | 
			
		||||
            unsigned char sdt_workspace; /* zeroed out by FST reader, for client code use */
 | 
			
		||||
            unsigned int sxt_workspace;  /* zeroed out by FST reader, for client code use */
 | 
			
		||||
            const char *name;
 | 
			
		||||
            uint32_t length;
 | 
			
		||||
            fstHandle handle;
 | 
			
		||||
            uint32_t name_length; /* strlen(u.var.name) */
 | 
			
		||||
            unsigned is_alias : 1;
 | 
			
		||||
        } var;
 | 
			
		||||
 | 
			
		||||
        /* if htyp == FST_HT_ATTRBEGIN */
 | 
			
		||||
        struct fstHierAttr
 | 
			
		||||
        {
 | 
			
		||||
            unsigned char typ;     /* FST_AT_MIN ... FST_AT_MAX */
 | 
			
		||||
            unsigned char subtype; /* from fstMiscType, fstArrayType, fstEnumValueType, fstPackType */
 | 
			
		||||
            const char *name;
 | 
			
		||||
            uint64_t arg; /* number of array elements, struct members, or some other payload (possibly ignored) */
 | 
			
		||||
            uint64_t arg_from_name; /* for when name is overloaded as a variable-length integer (FST_AT_MISC +
 | 
			
		||||
                                       FST_MT_SOURCESTEM) */
 | 
			
		||||
            uint32_t name_length;   /* strlen(u.attr.name) */
 | 
			
		||||
        } attr;
 | 
			
		||||
    } u;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct fstETab
 | 
			
		||||
{
 | 
			
		||||
    char *name;
 | 
			
		||||
    uint32_t elem_count;
 | 
			
		||||
    char **literal_arr;
 | 
			
		||||
    char **val_arr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * writer functions
 | 
			
		||||
 */
 | 
			
		||||
void fstWriterClose(void *ctx);
 | 
			
		||||
void *fstWriterCreate(const char *nam, int use_compressed_hier);
 | 
			
		||||
fstEnumHandle fstWriterCreateEnumTable(void *ctx, const char *name, uint32_t elem_count, unsigned int min_valbits,
 | 
			
		||||
                                       const char **literal_arr, const char **val_arr);
 | 
			
		||||
/* used for Verilog/SV */
 | 
			
		||||
fstHandle fstWriterCreateVar(void *ctx, enum fstVarType vt, enum fstVarDir vd, uint32_t len, const char *nam,
 | 
			
		||||
                             fstHandle aliasHandle);
 | 
			
		||||
/* future expansion for VHDL and other languages.  The variable type, data type, etc map onto
 | 
			
		||||
   the current Verilog/SV one.  The "type" string is optional for a more verbose or custom description */
 | 
			
		||||
fstHandle fstWriterCreateVar2(void *ctx, enum fstVarType vt, enum fstVarDir vd, uint32_t len, const char *nam,
 | 
			
		||||
                              fstHandle aliasHandle, const char *type, enum fstSupplementalVarType svt,
 | 
			
		||||
                              enum fstSupplementalDataType sdt);
 | 
			
		||||
void fstWriterEmitDumpActive(void *ctx, int enable);
 | 
			
		||||
void fstWriterEmitEnumTableRef(void *ctx, fstEnumHandle handle);
 | 
			
		||||
void fstWriterEmitValueChange(void *ctx, fstHandle handle, const void *val);
 | 
			
		||||
void fstWriterEmitValueChange32(void *ctx, fstHandle handle, uint32_t bits, uint32_t val);
 | 
			
		||||
void fstWriterEmitValueChange64(void *ctx, fstHandle handle, uint32_t bits, uint64_t val);
 | 
			
		||||
void fstWriterEmitValueChangeVec32(void *ctx, fstHandle handle, uint32_t bits, const uint32_t *val);
 | 
			
		||||
void fstWriterEmitValueChangeVec64(void *ctx, fstHandle handle, uint32_t bits, const uint64_t *val);
 | 
			
		||||
void fstWriterEmitVariableLengthValueChange(void *ctx, fstHandle handle, const void *val, uint32_t len);
 | 
			
		||||
void fstWriterEmitTimeChange(void *ctx, uint64_t tim);
 | 
			
		||||
void fstWriterFlushContext(void *ctx);
 | 
			
		||||
int fstWriterGetDumpSizeLimitReached(void *ctx);
 | 
			
		||||
int fstWriterGetFseekFailed(void *ctx);
 | 
			
		||||
void fstWriterSetAttrBegin(void *ctx, enum fstAttrType attrtype, int subtype, const char *attrname, uint64_t arg);
 | 
			
		||||
void fstWriterSetAttrEnd(void *ctx);
 | 
			
		||||
void fstWriterSetComment(void *ctx, const char *comm);
 | 
			
		||||
void fstWriterSetDate(void *ctx, const char *dat);
 | 
			
		||||
void fstWriterSetDumpSizeLimit(void *ctx, uint64_t numbytes);
 | 
			
		||||
void fstWriterSetEnvVar(void *ctx, const char *envvar);
 | 
			
		||||
void fstWriterSetFileType(void *ctx, enum fstFileType filetype);
 | 
			
		||||
void fstWriterSetPackType(void *ctx, enum fstWriterPackType typ);
 | 
			
		||||
void fstWriterSetParallelMode(void *ctx, int enable);
 | 
			
		||||
void fstWriterSetRepackOnClose(void *ctx, int enable); /* type = 0 (none), 1 (libz) */
 | 
			
		||||
void fstWriterSetScope(void *ctx, enum fstScopeType scopetype, const char *scopename, const char *scopecomp);
 | 
			
		||||
void fstWriterSetSourceInstantiationStem(void *ctx, const char *path, unsigned int line, unsigned int use_realpath);
 | 
			
		||||
void fstWriterSetSourceStem(void *ctx, const char *path, unsigned int line, unsigned int use_realpath);
 | 
			
		||||
void fstWriterSetTimescale(void *ctx, int ts);
 | 
			
		||||
void fstWriterSetTimescaleFromString(void *ctx, const char *s);
 | 
			
		||||
void fstWriterSetTimezero(void *ctx, int64_t tim);
 | 
			
		||||
void fstWriterSetUpscope(void *ctx);
 | 
			
		||||
void fstWriterSetValueList(void *ctx, const char *vl);
 | 
			
		||||
void fstWriterSetVersion(void *ctx, const char *vers);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * reader functions
 | 
			
		||||
 */
 | 
			
		||||
void fstReaderClose(void *ctx);
 | 
			
		||||
void fstReaderClrFacProcessMask(void *ctx, fstHandle facidx);
 | 
			
		||||
void fstReaderClrFacProcessMaskAll(void *ctx);
 | 
			
		||||
uint64_t fstReaderGetAliasCount(void *ctx);
 | 
			
		||||
const char *fstReaderGetCurrentFlatScope(void *ctx);
 | 
			
		||||
void *fstReaderGetCurrentScopeUserInfo(void *ctx);
 | 
			
		||||
int fstReaderGetCurrentScopeLen(void *ctx);
 | 
			
		||||
const char *fstReaderGetDateString(void *ctx);
 | 
			
		||||
int fstReaderGetDoubleEndianMatchState(void *ctx);
 | 
			
		||||
uint64_t fstReaderGetDumpActivityChangeTime(void *ctx, uint32_t idx);
 | 
			
		||||
unsigned char fstReaderGetDumpActivityChangeValue(void *ctx, uint32_t idx);
 | 
			
		||||
uint64_t fstReaderGetEndTime(void *ctx);
 | 
			
		||||
int fstReaderGetFacProcessMask(void *ctx, fstHandle facidx);
 | 
			
		||||
int fstReaderGetFileType(void *ctx);
 | 
			
		||||
int fstReaderGetFseekFailed(void *ctx);
 | 
			
		||||
fstHandle fstReaderGetMaxHandle(void *ctx);
 | 
			
		||||
uint64_t fstReaderGetMemoryUsedByWriter(void *ctx);
 | 
			
		||||
uint32_t fstReaderGetNumberDumpActivityChanges(void *ctx);
 | 
			
		||||
uint64_t fstReaderGetScopeCount(void *ctx);
 | 
			
		||||
uint64_t fstReaderGetStartTime(void *ctx);
 | 
			
		||||
signed char fstReaderGetTimescale(void *ctx);
 | 
			
		||||
int64_t fstReaderGetTimezero(void *ctx);
 | 
			
		||||
uint64_t fstReaderGetValueChangeSectionCount(void *ctx);
 | 
			
		||||
char *fstReaderGetValueFromHandleAtTime(void *ctx, uint64_t tim, fstHandle facidx, char *buf);
 | 
			
		||||
uint64_t fstReaderGetVarCount(void *ctx);
 | 
			
		||||
const char *fstReaderGetVersionString(void *ctx);
 | 
			
		||||
struct fstHier *fstReaderIterateHier(void *ctx);
 | 
			
		||||
int fstReaderIterateHierRewind(void *ctx);
 | 
			
		||||
int fstReaderIterBlocks(void *ctx,
 | 
			
		||||
                        void (*value_change_callback)(void *user_callback_data_pointer, uint64_t time, fstHandle facidx,
 | 
			
		||||
                                                      const unsigned char *value),
 | 
			
		||||
                        void *user_callback_data_pointer, FILE *vcdhandle);
 | 
			
		||||
int fstReaderIterBlocks2(void *ctx,
 | 
			
		||||
                         void (*value_change_callback)(void *user_callback_data_pointer, uint64_t time,
 | 
			
		||||
                                                       fstHandle facidx, const unsigned char *value),
 | 
			
		||||
                         void (*value_change_callback_varlen)(void *user_callback_data_pointer, uint64_t time,
 | 
			
		||||
                                                              fstHandle facidx, const unsigned char *value,
 | 
			
		||||
                                                              uint32_t len),
 | 
			
		||||
                         void *user_callback_data_pointer, FILE *vcdhandle);
 | 
			
		||||
void fstReaderIterBlocksSetNativeDoublesOnCallback(void *ctx, int enable);
 | 
			
		||||
void *fstReaderOpen(const char *nam);
 | 
			
		||||
void *fstReaderOpenForUtilitiesOnly(void);
 | 
			
		||||
const char *fstReaderPopScope(void *ctx);
 | 
			
		||||
int fstReaderProcessHier(void *ctx, FILE *vcdhandle);
 | 
			
		||||
const char *fstReaderPushScope(void *ctx, const char *nam, void *user_info);
 | 
			
		||||
void fstReaderResetScope(void *ctx);
 | 
			
		||||
void fstReaderSetFacProcessMask(void *ctx, fstHandle facidx);
 | 
			
		||||
void fstReaderSetFacProcessMaskAll(void *ctx);
 | 
			
		||||
void fstReaderSetLimitTimeRange(void *ctx, uint64_t start_time, uint64_t end_time);
 | 
			
		||||
void fstReaderSetUnlimitedTimeRange(void *ctx);
 | 
			
		||||
void fstReaderSetVcdExtensions(void *ctx, int enable);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * utility functions
 | 
			
		||||
 */
 | 
			
		||||
int fstUtilityBinToEscConvertedLen(const unsigned char *s, int len); /* used for mallocs for fstUtilityBinToEsc() */
 | 
			
		||||
int fstUtilityBinToEsc(unsigned char *d, const unsigned char *s, int len);
 | 
			
		||||
int fstUtilityEscToBin(unsigned char *d, unsigned char *s, int len);
 | 
			
		||||
struct fstETab *fstUtilityExtractEnumTableFromString(const char *s);
 | 
			
		||||
void fstUtilityFreeEnumTable(struct fstETab *etab); /* must use to free fstETab properly */
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										1615
									
								
								libs/fst/lz4.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1615
									
								
								libs/fst/lz4.cc
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										367
									
								
								libs/fst/lz4.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										367
									
								
								libs/fst/lz4.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,367 @@
 | 
			
		|||
/*
 | 
			
		||||
   LZ4 - Fast LZ compression algorithm
 | 
			
		||||
   Header File
 | 
			
		||||
   Copyright (C) 2011-2015, Yann Collet.
 | 
			
		||||
 | 
			
		||||
   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
 | 
			
		||||
 | 
			
		||||
   Redistribution and use in source and binary forms, with or without
 | 
			
		||||
   modification, are permitted provided that the following conditions are
 | 
			
		||||
   met:
 | 
			
		||||
 | 
			
		||||
       * Redistributions of source code must retain the above copyright
 | 
			
		||||
   notice, this list of conditions and the following disclaimer.
 | 
			
		||||
       * Redistributions in binary form must reproduce the above
 | 
			
		||||
   copyright notice, this list of conditions and the following disclaimer
 | 
			
		||||
   in the documentation and/or other materials provided with the
 | 
			
		||||
   distribution.
 | 
			
		||||
 | 
			
		||||
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
			
		||||
   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
			
		||||
   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
			
		||||
   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
			
		||||
   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
			
		||||
   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
   SPDX-License-Identifier: BSD-2-Clause
 | 
			
		||||
 | 
			
		||||
   You can contact the author at :
 | 
			
		||||
   - LZ4 source repository : https://github.com/Cyan4973/lz4
 | 
			
		||||
   - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
 | 
			
		||||
*/
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * lz4.h provides block compression functions, and gives full buffer control to programmer.
 | 
			
		||||
 * If you need to generate inter-operable compressed data (respecting LZ4 frame specification),
 | 
			
		||||
 * and can let the library handle its own memory, please use lz4frame.h instead.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**************************************
 | 
			
		||||
 *  Version
 | 
			
		||||
 **************************************/
 | 
			
		||||
#define LZ4_VERSION_MAJOR 1   /* for breaking interface changes  */
 | 
			
		||||
#define LZ4_VERSION_MINOR 7   /* for new (non-breaking) interface capabilities */
 | 
			
		||||
#define LZ4_VERSION_RELEASE 1 /* for tweaks, bug-fixes, or development */
 | 
			
		||||
#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR * 100 * 100 + LZ4_VERSION_MINOR * 100 + LZ4_VERSION_RELEASE)
 | 
			
		||||
int LZ4_versionNumber(void);
 | 
			
		||||
 | 
			
		||||
/**************************************
 | 
			
		||||
 *  Tuning parameter
 | 
			
		||||
 **************************************/
 | 
			
		||||
/*
 | 
			
		||||
 * LZ4_MEMORY_USAGE :
 | 
			
		||||
 * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
 | 
			
		||||
 * Increasing memory usage improves compression ratio
 | 
			
		||||
 * Reduced memory usage can improve speed, due to cache effect
 | 
			
		||||
 * Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
 | 
			
		||||
 */
 | 
			
		||||
#define LZ4_MEMORY_USAGE 14
 | 
			
		||||
 | 
			
		||||
/**************************************
 | 
			
		||||
 *  Simple Functions
 | 
			
		||||
 **************************************/
 | 
			
		||||
 | 
			
		||||
int LZ4_compress_default(const char *source, char *dest, int sourceSize, int maxDestSize);
 | 
			
		||||
int LZ4_decompress_safe(const char *source, char *dest, int compressedSize, int maxDecompressedSize);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
LZ4_compress_default() :
 | 
			
		||||
    Compresses 'sourceSize' bytes from buffer 'source'
 | 
			
		||||
    into already allocated 'dest' buffer of size 'maxDestSize'.
 | 
			
		||||
    Compression is guaranteed to succeed if 'maxDestSize' >= LZ4_compressBound(sourceSize).
 | 
			
		||||
    It also runs faster, so it's a recommended setting.
 | 
			
		||||
    If the function cannot compress 'source' into a more limited 'dest' budget,
 | 
			
		||||
    compression stops *immediately*, and the function result is zero.
 | 
			
		||||
    As a consequence, 'dest' content is not valid.
 | 
			
		||||
    This function never writes outside 'dest' buffer, nor read outside 'source' buffer.
 | 
			
		||||
        sourceSize  : Max supported value is LZ4_MAX_INPUT_VALUE
 | 
			
		||||
        maxDestSize : full or partial size of buffer 'dest' (which must be already allocated)
 | 
			
		||||
        return : the number of bytes written into buffer 'dest' (necessarily <= maxOutputSize)
 | 
			
		||||
              or 0 if compression fails
 | 
			
		||||
 | 
			
		||||
LZ4_decompress_safe() :
 | 
			
		||||
    compressedSize : is the precise full size of the compressed block.
 | 
			
		||||
    maxDecompressedSize : is the size of destination buffer, which must be already allocated.
 | 
			
		||||
    return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize)
 | 
			
		||||
             If destination buffer is not large enough, decoding will stop and output an error code (<0).
 | 
			
		||||
             If the source stream is detected malformed, the function will stop decoding and return a negative result.
 | 
			
		||||
             This function is protected against buffer overflow exploits, including malicious data packets.
 | 
			
		||||
             It never writes outside output buffer, nor reads outside input buffer.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**************************************
 | 
			
		||||
 *  Advanced Functions
 | 
			
		||||
 **************************************/
 | 
			
		||||
#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */
 | 
			
		||||
#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize) / 255) + 16)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
LZ4_compressBound() :
 | 
			
		||||
    Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible)
 | 
			
		||||
    This function is primarily useful for memory allocation purposes (destination buffer size).
 | 
			
		||||
    Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).
 | 
			
		||||
    Note that LZ4_compress_default() compress faster when dest buffer size is >= LZ4_compressBound(srcSize)
 | 
			
		||||
        inputSize  : max supported value is LZ4_MAX_INPUT_SIZE
 | 
			
		||||
        return : maximum output size in a "worst case" scenario
 | 
			
		||||
              or 0, if input size is too large ( > LZ4_MAX_INPUT_SIZE)
 | 
			
		||||
*/
 | 
			
		||||
int LZ4_compressBound(int inputSize);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
LZ4_compress_fast() :
 | 
			
		||||
    Same as LZ4_compress_default(), but allows to select an "acceleration" factor.
 | 
			
		||||
    The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
 | 
			
		||||
    It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
 | 
			
		||||
    An acceleration value of "1" is the same as regular LZ4_compress_default()
 | 
			
		||||
    Values <= 0 will be replaced by ACCELERATION_DEFAULT (see lz4.c), which is 1.
 | 
			
		||||
*/
 | 
			
		||||
int LZ4_compress_fast(const char *source, char *dest, int sourceSize, int maxDestSize, int acceleration);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
LZ4_compress_fast_extState() :
 | 
			
		||||
    Same compression function, just using an externally allocated memory space to store compression state.
 | 
			
		||||
    Use LZ4_sizeofState() to know how much memory must be allocated,
 | 
			
		||||
    and allocate it on 8-bytes boundaries (using malloc() typically).
 | 
			
		||||
    Then, provide it as 'void* state' to compression function.
 | 
			
		||||
*/
 | 
			
		||||
int LZ4_sizeofState(void);
 | 
			
		||||
int LZ4_compress_fast_extState(void *state, const char *source, char *dest, int inputSize, int maxDestSize,
 | 
			
		||||
                               int acceleration);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
LZ4_compress_destSize() :
 | 
			
		||||
    Reverse the logic, by compressing as much data as possible from 'source' buffer
 | 
			
		||||
    into already allocated buffer 'dest' of size 'targetDestSize'.
 | 
			
		||||
    This function either compresses the entire 'source' content into 'dest' if it's large enough,
 | 
			
		||||
    or fill 'dest' buffer completely with as much data as possible from 'source'.
 | 
			
		||||
        *sourceSizePtr : will be modified to indicate how many bytes where read from 'source' to fill 'dest'.
 | 
			
		||||
                         New value is necessarily <= old value.
 | 
			
		||||
        return : Nb bytes written into 'dest' (necessarily <= targetDestSize)
 | 
			
		||||
              or 0 if compression fails
 | 
			
		||||
*/
 | 
			
		||||
int LZ4_compress_destSize(const char *source, char *dest, int *sourceSizePtr, int targetDestSize);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
LZ4_decompress_fast() :
 | 
			
		||||
    originalSize : is the original and therefore uncompressed size
 | 
			
		||||
    return : the number of bytes read from the source buffer (in other words, the compressed size)
 | 
			
		||||
             If the source stream is detected malformed, the function will stop decoding and return a negative result.
 | 
			
		||||
             Destination buffer must be already allocated. Its size must be a minimum of 'originalSize' bytes.
 | 
			
		||||
    note : This function fully respect memory boundaries for properly formed compressed data.
 | 
			
		||||
           It is a bit faster than LZ4_decompress_safe().
 | 
			
		||||
           However, it does not provide any protection against intentionally modified data stream (malicious input).
 | 
			
		||||
           Use this function in trusted environment only (data to decode comes from a trusted source).
 | 
			
		||||
*/
 | 
			
		||||
int LZ4_decompress_fast(const char *source, char *dest, int originalSize);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
LZ4_decompress_safe_partial() :
 | 
			
		||||
    This function decompress a compressed block of size 'compressedSize' at position 'source'
 | 
			
		||||
    into destination buffer 'dest' of size 'maxDecompressedSize'.
 | 
			
		||||
    The function tries to stop decompressing operation as soon as 'targetOutputSize' has been reached,
 | 
			
		||||
    reducing decompression time.
 | 
			
		||||
    return : the number of bytes decoded in the destination buffer (necessarily <= maxDecompressedSize)
 | 
			
		||||
       Note : this number can be < 'targetOutputSize' should the compressed block to decode be smaller.
 | 
			
		||||
             Always control how many bytes were decoded.
 | 
			
		||||
             If the source stream is detected malformed, the function will stop decoding and return a negative result.
 | 
			
		||||
             This function never writes outside of output buffer, and never reads outside of input buffer. It is
 | 
			
		||||
therefore protected against malicious data packets
 | 
			
		||||
*/
 | 
			
		||||
int LZ4_decompress_safe_partial(const char *source, char *dest, int compressedSize, int targetOutputSize,
 | 
			
		||||
                                int maxDecompressedSize);
 | 
			
		||||
 | 
			
		||||
/***********************************************
 | 
			
		||||
 *  Streaming Compression Functions
 | 
			
		||||
 ***********************************************/
 | 
			
		||||
#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE - 3)) + 4)
 | 
			
		||||
#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(long long))
 | 
			
		||||
/*
 | 
			
		||||
 * LZ4_stream_t
 | 
			
		||||
 * information structure to track an LZ4 stream.
 | 
			
		||||
 * important : init this structure content before first use !
 | 
			
		||||
 * note : only allocated directly the structure if you are statically linking LZ4
 | 
			
		||||
 *        If you are using liblz4 as a DLL, please use below construction methods instead.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
    long long table[LZ4_STREAMSIZE_U64];
 | 
			
		||||
} LZ4_stream_t;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * LZ4_resetStream
 | 
			
		||||
 * Use this function to init an allocated LZ4_stream_t structure
 | 
			
		||||
 */
 | 
			
		||||
void LZ4_resetStream(LZ4_stream_t *streamPtr);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * LZ4_createStream will allocate and initialize an LZ4_stream_t structure
 | 
			
		||||
 * LZ4_freeStream releases its memory.
 | 
			
		||||
 * In the context of a DLL (liblz4), please use these methods rather than the static struct.
 | 
			
		||||
 * They are more future proof, in case of a change of LZ4_stream_t size.
 | 
			
		||||
 */
 | 
			
		||||
LZ4_stream_t *LZ4_createStream(void);
 | 
			
		||||
int LZ4_freeStream(LZ4_stream_t *streamPtr);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * LZ4_loadDict
 | 
			
		||||
 * Use this function to load a static dictionary into LZ4_stream.
 | 
			
		||||
 * Any previous data will be forgotten, only 'dictionary' will remain in memory.
 | 
			
		||||
 * Loading a size of 0 is allowed.
 | 
			
		||||
 * Return : dictionary size, in bytes (necessarily <= 64 KB)
 | 
			
		||||
 */
 | 
			
		||||
int LZ4_loadDict(LZ4_stream_t *streamPtr, const char *dictionary, int dictSize);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * LZ4_compress_fast_continue
 | 
			
		||||
 * Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression
 | 
			
		||||
 * ratio. Important : Previous data blocks are assumed to still be present and unmodified ! 'dst' buffer must be already
 | 
			
		||||
 * allocated. If maxDstSize >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster. If
 | 
			
		||||
 * not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function returns a zero.
 | 
			
		||||
 */
 | 
			
		||||
int LZ4_compress_fast_continue(LZ4_stream_t *streamPtr, const char *src, char *dst, int srcSize, int maxDstSize,
 | 
			
		||||
                               int acceleration);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * LZ4_saveDict
 | 
			
		||||
 * If previously compressed data block is not guaranteed to remain available at its memory location
 | 
			
		||||
 * save it into a safer place (char* safeBuffer)
 | 
			
		||||
 * Note : you don't need to call LZ4_loadDict() afterwards,
 | 
			
		||||
 *        dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue()
 | 
			
		||||
 * Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error
 | 
			
		||||
 */
 | 
			
		||||
int LZ4_saveDict(LZ4_stream_t *streamPtr, char *safeBuffer, int dictSize);
 | 
			
		||||
 | 
			
		||||
/************************************************
 | 
			
		||||
 *  Streaming Decompression Functions
 | 
			
		||||
 ************************************************/
 | 
			
		||||
 | 
			
		||||
#define LZ4_STREAMDECODESIZE_U64 4
 | 
			
		||||
#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long))
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
    unsigned long long table[LZ4_STREAMDECODESIZE_U64];
 | 
			
		||||
} LZ4_streamDecode_t;
 | 
			
		||||
/*
 | 
			
		||||
 * LZ4_streamDecode_t
 | 
			
		||||
 * information structure to track an LZ4 stream.
 | 
			
		||||
 * init this structure content using LZ4_setStreamDecode or memset() before first use !
 | 
			
		||||
 *
 | 
			
		||||
 * In the context of a DLL (liblz4) please prefer usage of construction methods below.
 | 
			
		||||
 * They are more future proof, in case of a change of LZ4_streamDecode_t size in the future.
 | 
			
		||||
 * LZ4_createStreamDecode will allocate and initialize an LZ4_streamDecode_t structure
 | 
			
		||||
 * LZ4_freeStreamDecode releases its memory.
 | 
			
		||||
 */
 | 
			
		||||
LZ4_streamDecode_t *LZ4_createStreamDecode(void);
 | 
			
		||||
int LZ4_freeStreamDecode(LZ4_streamDecode_t *LZ4_stream);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * LZ4_setStreamDecode
 | 
			
		||||
 * Use this function to instruct where to find the dictionary.
 | 
			
		||||
 * Setting a size of 0 is allowed (same effect as reset).
 | 
			
		||||
 * Return : 1 if OK, 0 if error
 | 
			
		||||
 */
 | 
			
		||||
int LZ4_setStreamDecode(LZ4_streamDecode_t *LZ4_streamDecode, const char *dictionary, int dictSize);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
*_continue() :
 | 
			
		||||
    These decoding functions allow decompression of multiple blocks in "streaming" mode.
 | 
			
		||||
    Previously decoded blocks *must* remain available at the memory position where they were decoded (up to 64 KB)
 | 
			
		||||
    In the case of a ring buffers, decoding buffer must be either :
 | 
			
		||||
    - Exactly same size as encoding buffer, with same update rule (block boundaries at same positions)
 | 
			
		||||
      In which case, the decoding & encoding ring buffer can have any size, including very small ones ( < 64 KB).
 | 
			
		||||
    - Larger than encoding buffer, by a minimum of maxBlockSize more bytes.
 | 
			
		||||
      maxBlockSize is implementation dependent. It's the maximum size you intend to compress into a single block.
 | 
			
		||||
      In which case, encoding and decoding buffers do not need to be synchronized,
 | 
			
		||||
      and encoding ring buffer can have any size, including small ones ( < 64 KB).
 | 
			
		||||
    - _At least_ 64 KB + 8 bytes + maxBlockSize.
 | 
			
		||||
      In which case, encoding and decoding buffers do not need to be synchronized,
 | 
			
		||||
      and encoding ring buffer can have any size, including larger than decoding buffer.
 | 
			
		||||
    Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer,
 | 
			
		||||
    and indicate where it is saved using LZ4_setStreamDecode()
 | 
			
		||||
*/
 | 
			
		||||
int LZ4_decompress_safe_continue(LZ4_streamDecode_t *LZ4_streamDecode, const char *source, char *dest,
 | 
			
		||||
                                 int compressedSize, int maxDecompressedSize);
 | 
			
		||||
int LZ4_decompress_fast_continue(LZ4_streamDecode_t *LZ4_streamDecode, const char *source, char *dest,
 | 
			
		||||
                                 int originalSize);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
Advanced decoding functions :
 | 
			
		||||
*_usingDict() :
 | 
			
		||||
    These decoding functions work the same as
 | 
			
		||||
    a combination of LZ4_setStreamDecode() followed by LZ4_decompress_x_continue()
 | 
			
		||||
    They are stand-alone. They don't need nor update an LZ4_streamDecode_t structure.
 | 
			
		||||
*/
 | 
			
		||||
int LZ4_decompress_safe_usingDict(const char *source, char *dest, int compressedSize, int maxDecompressedSize,
 | 
			
		||||
                                  const char *dictStart, int dictSize);
 | 
			
		||||
int LZ4_decompress_fast_usingDict(const char *source, char *dest, int originalSize, const char *dictStart,
 | 
			
		||||
                                  int dictSize);
 | 
			
		||||
 | 
			
		||||
/**************************************
 | 
			
		||||
 *  Obsolete Functions
 | 
			
		||||
 **************************************/
 | 
			
		||||
/* Deprecate Warnings */
 | 
			
		||||
/* Should these warnings messages be a problem,
 | 
			
		||||
   it is generally possible to disable them,
 | 
			
		||||
   with -Wno-deprecated-declarations for gcc
 | 
			
		||||
   or _CRT_SECURE_NO_WARNINGS in Visual for example.
 | 
			
		||||
   You can also define LZ4_DEPRECATE_WARNING_DEFBLOCK. */
 | 
			
		||||
#ifndef LZ4_DEPRECATE_WARNING_DEFBLOCK
 | 
			
		||||
#define LZ4_DEPRECATE_WARNING_DEFBLOCK
 | 
			
		||||
#define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
 | 
			
		||||
#if (LZ4_GCC_VERSION >= 405) || defined(__clang__)
 | 
			
		||||
#define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
 | 
			
		||||
#elif (LZ4_GCC_VERSION >= 301)
 | 
			
		||||
#define LZ4_DEPRECATED(message) __attribute__((deprecated))
 | 
			
		||||
#elif defined(_MSC_VER)
 | 
			
		||||
#define LZ4_DEPRECATED(message) __declspec(deprecated(message))
 | 
			
		||||
#else
 | 
			
		||||
#pragma message("WARNING: You need to implement LZ4_DEPRECATED for this compiler")
 | 
			
		||||
#define LZ4_DEPRECATED(message)
 | 
			
		||||
#endif
 | 
			
		||||
#endif /* LZ4_DEPRECATE_WARNING_DEFBLOCK */
 | 
			
		||||
 | 
			
		||||
/* Obsolete compression functions */
 | 
			
		||||
/* These functions are planned to start generate warnings by r131 approximately */
 | 
			
		||||
int LZ4_compress(const char *source, char *dest, int sourceSize);
 | 
			
		||||
int LZ4_compress_limitedOutput(const char *source, char *dest, int sourceSize, int maxOutputSize);
 | 
			
		||||
int LZ4_compress_withState(void *state, const char *source, char *dest, int inputSize);
 | 
			
		||||
int LZ4_compress_limitedOutput_withState(void *state, const char *source, char *dest, int inputSize, int maxOutputSize);
 | 
			
		||||
int LZ4_compress_continue(LZ4_stream_t *LZ4_streamPtr, const char *source, char *dest, int inputSize);
 | 
			
		||||
int LZ4_compress_limitedOutput_continue(LZ4_stream_t *LZ4_streamPtr, const char *source, char *dest, int inputSize,
 | 
			
		||||
                                        int maxOutputSize);
 | 
			
		||||
 | 
			
		||||
/* Obsolete decompression functions */
 | 
			
		||||
/* These function names are completely deprecated and must no longer be used.
 | 
			
		||||
   They are only provided here for compatibility with older programs.
 | 
			
		||||
    - LZ4_uncompress is the same as LZ4_decompress_fast
 | 
			
		||||
    - LZ4_uncompress_unknownOutputSize is the same as LZ4_decompress_safe
 | 
			
		||||
   These function prototypes are now disabled; uncomment them only if you really need them.
 | 
			
		||||
   It is highly recommended to stop using these prototypes and migrate to maintained ones */
 | 
			
		||||
/* int LZ4_uncompress (const char* source, char* dest, int outputSize); */
 | 
			
		||||
/* int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize); */
 | 
			
		||||
 | 
			
		||||
/* Obsolete streaming functions; use new streaming interface whenever possible */
 | 
			
		||||
LZ4_DEPRECATED("use LZ4_createStream() instead") void *LZ4_create(char *inputBuffer);
 | 
			
		||||
LZ4_DEPRECATED("use LZ4_createStream() instead") int LZ4_sizeofStreamState(void);
 | 
			
		||||
LZ4_DEPRECATED("use LZ4_resetStream() instead") int LZ4_resetStreamState(void *state, char *inputBuffer);
 | 
			
		||||
LZ4_DEPRECATED("use LZ4_saveDict() instead") char *LZ4_slideInputBuffer(void *state);
 | 
			
		||||
 | 
			
		||||
/* Obsolete streaming decoding functions */
 | 
			
		||||
LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead")
 | 
			
		||||
int LZ4_decompress_safe_withPrefix64k(const char *src, char *dst, int compressedSize, int maxDstSize);
 | 
			
		||||
LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead")
 | 
			
		||||
int LZ4_decompress_fast_withPrefix64k(const char *src, char *dst, int originalSize);
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -7,11 +7,20 @@ gitsha="$3"
 | 
			
		|||
 | 
			
		||||
rm -rf YosysVS-Tpl-v2.zip YosysVS
 | 
			
		||||
wget https://yosyshq.net/yosys/nogit/YosysVS-Tpl-v2.zip
 | 
			
		||||
wget https://zlib.net/zlib-1.2.11.tar.gz
 | 
			
		||||
 | 
			
		||||
unzip YosysVS-Tpl-v2.zip
 | 
			
		||||
rm -f YosysVS-Tpl-v2.zip
 | 
			
		||||
mv YosysVS "$vcxsrc"
 | 
			
		||||
tar xvfz zlib-1.2.11.tar.gz
 | 
			
		||||
 | 
			
		||||
mv YosysVS "$vcxsrc"
 | 
			
		||||
mkdir -p "$vcxsrc"/yosys
 | 
			
		||||
mkdir -p "$vcxsrc"/yosys/libs/zlib
 | 
			
		||||
mv zlib-1.2.11/* "$vcxsrc"/yosys/libs/zlib/.
 | 
			
		||||
rm -rf zlib-1.2.11
 | 
			
		||||
pushd "$vcxsrc"/yosys
 | 
			
		||||
ls libs/zlib/*.c | sed 's,.*:,,; s,//*,/,g; s,/[^/]*/\.\./,/,g; y, \\,\n\n,;' | grep '^[^/]'  >> ../../srcfiles.txt
 | 
			
		||||
popd
 | 
			
		||||
{
 | 
			
		||||
	n=$(grep -B999 '<ItemGroup>' "$vcxsrc"/YosysVS/YosysVS.vcxproj | wc -l)
 | 
			
		||||
	head -n$n "$vcxsrc"/YosysVS/YosysVS.vcxproj
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,12 +21,49 @@
 | 
			
		|||
#include "kernel/sigtools.h"
 | 
			
		||||
#include "kernel/celltypes.h"
 | 
			
		||||
#include "kernel/mem.h"
 | 
			
		||||
#include "kernel/fstdata.h"
 | 
			
		||||
 | 
			
		||||
#include <ctime>
 | 
			
		||||
 | 
			
		||||
USING_YOSYS_NAMESPACE
 | 
			
		||||
PRIVATE_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
enum class SimulationMode {
 | 
			
		||||
	sim,
 | 
			
		||||
	cmp,
 | 
			
		||||
	gold,
 | 
			
		||||
	gate,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const std::map<std::string, int> g_units =
 | 
			
		||||
{
 | 
			
		||||
	{ "",    -9 }, // default is ns
 | 
			
		||||
	{ "s",    0 },
 | 
			
		||||
	{ "ms",  -3 },
 | 
			
		||||
	{ "us",  -6 },
 | 
			
		||||
	{ "ns",  -9 },
 | 
			
		||||
	{ "ps", -12 },
 | 
			
		||||
	{ "fs", -15 },
 | 
			
		||||
	{ "as", -18 },
 | 
			
		||||
	{ "zs", -21 },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static double stringToTime(std::string str)
 | 
			
		||||
{
 | 
			
		||||
	if (str=="END") return -1;
 | 
			
		||||
 | 
			
		||||
	char *endptr;
 | 
			
		||||
	long value = strtol(str.c_str(), &endptr, 10);
 | 
			
		||||
 | 
			
		||||
	if (g_units.find(endptr)==g_units.end())
 | 
			
		||||
		log_error("Cannot parse '%s', bad unit '%s'\n", str.c_str(), endptr);
 | 
			
		||||
 | 
			
		||||
	if (value < 0)
 | 
			
		||||
		log_error("Time value '%s' must be positive\n", str.c_str());
 | 
			
		||||
 | 
			
		||||
	return value * pow(10.0, g_units.at(endptr));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct SimShared
 | 
			
		||||
{
 | 
			
		||||
	bool debug = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -34,6 +71,11 @@ struct SimShared
 | 
			
		|||
	bool writeback = false;
 | 
			
		||||
	bool zinit = false;
 | 
			
		||||
	int rstlen = 1;
 | 
			
		||||
	FstData *fst = nullptr;
 | 
			
		||||
	double start_time = 0;
 | 
			
		||||
	double stop_time = -1;
 | 
			
		||||
	SimulationMode sim_mode = SimulationMode::sim;
 | 
			
		||||
	bool cycles_set = false;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void zinit(State &v)
 | 
			
		||||
| 
						 | 
				
			
			@ -52,6 +94,7 @@ struct SimInstance
 | 
			
		|||
{
 | 
			
		||||
	SimShared *shared;
 | 
			
		||||
	
 | 
			
		||||
	std::string scope;
 | 
			
		||||
	Module *module;
 | 
			
		||||
	Cell *instance;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -92,9 +135,11 @@ struct SimInstance
 | 
			
		|||
	std::vector<Mem> memories;
 | 
			
		||||
 | 
			
		||||
	dict<Wire*, pair<int, Const>> vcd_database;
 | 
			
		||||
	dict<Wire*, pair<fstHandle, Const>> fst_database;
 | 
			
		||||
	dict<Wire*, fstHandle> fst_handles;
 | 
			
		||||
 | 
			
		||||
	SimInstance(SimShared *shared, Module *module, Cell *instance = nullptr, SimInstance *parent = nullptr) :
 | 
			
		||||
			shared(shared), module(module), instance(instance), parent(parent), sigmap(module)
 | 
			
		||||
	SimInstance(SimShared *shared, std::string scope, Module *module, Cell *instance = nullptr, SimInstance *parent = nullptr) :
 | 
			
		||||
			shared(shared), scope(scope), module(module), instance(instance), parent(parent), sigmap(module)
 | 
			
		||||
	{
 | 
			
		||||
		log_assert(module);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -116,6 +161,13 @@ struct SimInstance
 | 
			
		|||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if ((shared->fst) && !(shared->hide_internal && wire->name[0] == '$')) {
 | 
			
		||||
				fstHandle id = shared->fst->getHandle(scope + "." + RTLIL::unescape_id(wire->name));
 | 
			
		||||
				if (id==0 && wire->name.isPublic())
 | 
			
		||||
					log_warning("Unable to found wire %s in input file.\n", (scope + "." + RTLIL::unescape_id(wire->name)).c_str());
 | 
			
		||||
				fst_handles[wire] = id;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (wire->attributes.count(ID::init)) {
 | 
			
		||||
				Const initval = wire->attributes.at(ID::init);
 | 
			
		||||
				for (int i = 0; i < GetSize(sig) && i < GetSize(initval); i++)
 | 
			
		||||
| 
						 | 
				
			
			@ -144,7 +196,7 @@ struct SimInstance
 | 
			
		|||
			Module *mod = module->design->module(cell->type);
 | 
			
		||||
 | 
			
		||||
			if (mod != nullptr) {
 | 
			
		||||
				dirty_children.insert(new SimInstance(shared, mod, cell, this));
 | 
			
		||||
				dirty_children.insert(new SimInstance(shared, scope + "." + RTLIL::unescape_id(cell->name), mod, cell, this));
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for (auto &port : cell->connections()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -622,14 +674,125 @@ struct SimInstance
 | 
			
		|||
		for (auto child : children)
 | 
			
		||||
			child.second->write_vcd_step(f);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void write_fst_header(struct fstContext *f)
 | 
			
		||||
	{
 | 
			
		||||
		fstWriterSetScope(f, FST_ST_VCD_MODULE, stringf("%s",log_id(name())).c_str(), nullptr);
 | 
			
		||||
		for (auto wire : module->wires())
 | 
			
		||||
		{
 | 
			
		||||
			if (shared->hide_internal && wire->name[0] == '$')
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			fstHandle id = fstWriterCreateVar(f, FST_VT_VCD_WIRE, FST_VD_IMPLICIT, GetSize(wire),
 | 
			
		||||
												stringf("%s%s", wire->name[0] == '$' ? "\\" : "", log_id(wire)).c_str(), 0);
 | 
			
		||||
			fst_database[wire] = make_pair(id, Const());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for (auto child : children)
 | 
			
		||||
			child.second->write_fst_header(f);
 | 
			
		||||
 | 
			
		||||
		fstWriterSetUpscope(f);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void write_fst_step(struct fstContext *f)
 | 
			
		||||
	{
 | 
			
		||||
		for (auto &it : fst_database)
 | 
			
		||||
		{
 | 
			
		||||
			Wire *wire = it.first;
 | 
			
		||||
			Const value = get_state(wire);
 | 
			
		||||
			fstHandle id = it.second.first;
 | 
			
		||||
 | 
			
		||||
			if (it.second.second == value)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			it.second.second = value;
 | 
			
		||||
			std::stringstream ss;
 | 
			
		||||
			for (int i = GetSize(value)-1; i >= 0; i--) {
 | 
			
		||||
				switch (value[i]) {
 | 
			
		||||
					case State::S0: ss << "0"; break;
 | 
			
		||||
					case State::S1: ss << "1"; break;
 | 
			
		||||
					case State::Sx: ss << "x"; break;
 | 
			
		||||
					default: ss << "z";
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			fstWriterEmitValueChange(f, id, ss.str().c_str());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for (auto child : children)
 | 
			
		||||
			child.second->write_fst_step(f);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void setInitState(uint64_t time)
 | 
			
		||||
	{
 | 
			
		||||
		for (auto &it : ff_database)
 | 
			
		||||
		{
 | 
			
		||||
			Cell *cell = it.first;
 | 
			
		||||
			
 | 
			
		||||
			SigSpec qsig = cell->getPort(ID::Q);
 | 
			
		||||
			if (qsig.is_wire()) {
 | 
			
		||||
				IdString name = qsig.as_wire()->name;
 | 
			
		||||
				fstHandle id = shared->fst->getHandle(scope + "." + RTLIL::unescape_id(name));
 | 
			
		||||
				if (id==0 && name.isPublic())
 | 
			
		||||
					log_warning("Unable to found wire %s in input file.\n", (scope + "." + RTLIL::unescape_id(name)).c_str());
 | 
			
		||||
				if (id!=0) {
 | 
			
		||||
					Const fst_val = Const::from_string(shared->fst->valueAt(id, time));
 | 
			
		||||
					set_state(qsig, fst_val);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		for (auto child : children)
 | 
			
		||||
			child.second->setInitState(time);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool checkSignals(uint64_t time)
 | 
			
		||||
	{
 | 
			
		||||
		bool retVal = false;
 | 
			
		||||
		for(auto &item : fst_handles) {
 | 
			
		||||
			if (item.second==0) continue; // Ignore signals not found
 | 
			
		||||
			Const fst_val = Const::from_string(shared->fst->valueAt(item.second, time));
 | 
			
		||||
			Const sim_val = get_state(item.first);
 | 
			
		||||
			if (sim_val.size()!=fst_val.size())
 | 
			
		||||
				log_error("Signal '%s' size is different in gold and gate.\n", log_id(item.first));
 | 
			
		||||
			if (shared->sim_mode == SimulationMode::sim) {
 | 
			
		||||
				// No checks performed when using stimulus
 | 
			
		||||
			} else if (shared->sim_mode == SimulationMode::gate && !fst_val.is_fully_def()) { // FST data contains X
 | 
			
		||||
				for(int i=0;i<fst_val.size();i++) {
 | 
			
		||||
					if (fst_val[i]!=State::Sx && fst_val[i]!=sim_val[i]) {
 | 
			
		||||
						log_warning("Signal '%s' in file %s in simulation %s\n", log_id(item.first), log_signal(fst_val), log_signal(sim_val));
 | 
			
		||||
						retVal = true;
 | 
			
		||||
						break;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			} else if (shared->sim_mode == SimulationMode::gold && !sim_val.is_fully_def()) { // sim data contains X
 | 
			
		||||
				for(int i=0;i<sim_val.size();i++) {
 | 
			
		||||
					if (sim_val[i]!=State::Sx && fst_val[i]!=sim_val[i]) {
 | 
			
		||||
						log_warning("Signal '%s' in file %s in simulation %s\n", log_id(item.first), log_signal(fst_val), log_signal(sim_val));
 | 
			
		||||
						retVal = true;
 | 
			
		||||
						break;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				if (fst_val!=sim_val) {
 | 
			
		||||
					log_warning("Signal '%s' in file %s in simulation '%s'\n", log_id(item.first), log_signal(fst_val), log_signal(sim_val));
 | 
			
		||||
					retVal = true;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		for (auto child : children)
 | 
			
		||||
			retVal |= child.second->checkSignals(time);
 | 
			
		||||
		return retVal;
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct SimWorker : SimShared
 | 
			
		||||
{
 | 
			
		||||
	SimInstance *top = nullptr;
 | 
			
		||||
	std::ofstream vcdfile;
 | 
			
		||||
	struct fstContext *fstfile = nullptr;
 | 
			
		||||
	pool<IdString> clock, clockn, reset, resetn;
 | 
			
		||||
	std::string timescale;
 | 
			
		||||
	std::string sim_filename;
 | 
			
		||||
	std::string scope;
 | 
			
		||||
 | 
			
		||||
	~SimWorker()
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -638,9 +801,6 @@ struct SimWorker : SimShared
 | 
			
		|||
 | 
			
		||||
	void write_vcd_header()
 | 
			
		||||
	{
 | 
			
		||||
		if (!vcdfile.is_open())
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		vcdfile << stringf("$version %s $end\n", yosys_version_str);
 | 
			
		||||
 | 
			
		||||
		std::time_t t = std::time(nullptr);
 | 
			
		||||
| 
						 | 
				
			
			@ -660,13 +820,53 @@ struct SimWorker : SimShared
 | 
			
		|||
 | 
			
		||||
	void write_vcd_step(int t)
 | 
			
		||||
	{
 | 
			
		||||
		if (!vcdfile.is_open())
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		vcdfile << stringf("#%d\n", t);
 | 
			
		||||
		top->write_vcd_step(vcdfile);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void write_fst_header()
 | 
			
		||||
	{
 | 
			
		||||
		std::time_t t = std::time(nullptr);
 | 
			
		||||
		fstWriterSetDate(fstfile, asctime(std::localtime(&t)));
 | 
			
		||||
		fstWriterSetVersion(fstfile, yosys_version_str);
 | 
			
		||||
		if (!timescale.empty())
 | 
			
		||||
			fstWriterSetTimescaleFromString(fstfile, timescale.c_str());
 | 
			
		||||
 | 
			
		||||
		fstWriterSetPackType(fstfile, FST_WR_PT_FASTLZ);
 | 
			
		||||
		fstWriterSetRepackOnClose(fstfile, 1);
 | 
			
		||||
	   
 | 
			
		||||
		top->write_fst_header(fstfile);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void write_fst_step(int t)
 | 
			
		||||
	{
 | 
			
		||||
		fstWriterEmitTimeChange(fstfile, t);
 | 
			
		||||
 | 
			
		||||
		top->write_fst_step(fstfile);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void write_output_header()
 | 
			
		||||
	{
 | 
			
		||||
		if (vcdfile.is_open())
 | 
			
		||||
			write_vcd_header();
 | 
			
		||||
		if (fstfile)
 | 
			
		||||
			write_fst_header();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void write_output_step(int t)
 | 
			
		||||
	{
 | 
			
		||||
		if (vcdfile.is_open())
 | 
			
		||||
			write_vcd_step(t);
 | 
			
		||||
		if (fstfile)
 | 
			
		||||
			write_fst_step(t);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void write_output_end()
 | 
			
		||||
	{
 | 
			
		||||
		if (fstfile)
 | 
			
		||||
			fstWriterClose(fstfile);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void update()
 | 
			
		||||
	{
 | 
			
		||||
		while (1)
 | 
			
		||||
| 
						 | 
				
			
			@ -705,7 +905,7 @@ struct SimWorker : SimShared
 | 
			
		|||
	void run(Module *topmod, int numcycles)
 | 
			
		||||
	{
 | 
			
		||||
		log_assert(top == nullptr);
 | 
			
		||||
		top = new SimInstance(this, topmod);
 | 
			
		||||
		top = new SimInstance(this, scope, topmod);
 | 
			
		||||
 | 
			
		||||
		if (debug)
 | 
			
		||||
			log("\n===== 0 =====\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -720,24 +920,25 @@ struct SimWorker : SimShared
 | 
			
		|||
 | 
			
		||||
		update();
 | 
			
		||||
 | 
			
		||||
		write_vcd_header();
 | 
			
		||||
		write_vcd_step(0);
 | 
			
		||||
		write_output_header();
 | 
			
		||||
		write_output_step(0);
 | 
			
		||||
 | 
			
		||||
		for (int cycle = 0; cycle < numcycles; cycle++)
 | 
			
		||||
		{
 | 
			
		||||
			if (debug)
 | 
			
		||||
				log("\n===== %d =====\n", 10*cycle + 5);
 | 
			
		||||
 | 
			
		||||
			else
 | 
			
		||||
				log("Simulating cycle %d.\n", (cycle*2)+1);
 | 
			
		||||
			set_inports(clock, State::S0);
 | 
			
		||||
			set_inports(clockn, State::S1);
 | 
			
		||||
 | 
			
		||||
			update();
 | 
			
		||||
			write_vcd_step(10*cycle + 5);
 | 
			
		||||
			write_output_step(10*cycle + 5);
 | 
			
		||||
 | 
			
		||||
			if (debug)
 | 
			
		||||
				log("\n===== %d =====\n", 10*cycle + 10);
 | 
			
		||||
			else
 | 
			
		||||
				log("Simulating cycle %d.\n", cycle+1);
 | 
			
		||||
				log("Simulating cycle %d.\n", (cycle*2)+2);
 | 
			
		||||
 | 
			
		||||
			set_inports(clock, State::S1);
 | 
			
		||||
			set_inports(clockn, State::S0);
 | 
			
		||||
| 
						 | 
				
			
			@ -748,11 +949,132 @@ struct SimWorker : SimShared
 | 
			
		|||
			}
 | 
			
		||||
 | 
			
		||||
			update();
 | 
			
		||||
			write_vcd_step(10*cycle + 10);
 | 
			
		||||
			write_output_step(10*cycle + 10);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		write_vcd_step(10*numcycles + 2);
 | 
			
		||||
		write_output_step(10*numcycles + 2);
 | 
			
		||||
 | 
			
		||||
		write_output_end();
 | 
			
		||||
 | 
			
		||||
		if (writeback) {
 | 
			
		||||
			pool<Module*> wbmods;
 | 
			
		||||
			top->writeback(wbmods);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void run_cosim(Module *topmod, int numcycles)
 | 
			
		||||
	{
 | 
			
		||||
		log_assert(top == nullptr);
 | 
			
		||||
		fst = new FstData(sim_filename);
 | 
			
		||||
 | 
			
		||||
		if (scope.empty())
 | 
			
		||||
			log_error("Scope must be defined for co-simulation.\n");
 | 
			
		||||
 | 
			
		||||
		top = new SimInstance(this, scope, topmod);
 | 
			
		||||
 | 
			
		||||
		std::vector<fstHandle> fst_clock;
 | 
			
		||||
 | 
			
		||||
		for (auto portname : clock)
 | 
			
		||||
		{
 | 
			
		||||
			Wire *w = topmod->wire(portname);
 | 
			
		||||
			if (!w)
 | 
			
		||||
				log_error("Can't find port %s on module %s.\n", log_id(portname), log_id(top->module));
 | 
			
		||||
			if (!w->port_input)
 | 
			
		||||
				log_error("Clock port %s on module %s is not input.\n", log_id(portname), log_id(top->module));
 | 
			
		||||
			fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(portname));
 | 
			
		||||
			if (id==0)
 | 
			
		||||
				log_error("Can't find port %s.%s in FST.\n", scope.c_str(), log_id(portname));
 | 
			
		||||
			fst_clock.push_back(id);
 | 
			
		||||
		}
 | 
			
		||||
		for (auto portname : clockn)
 | 
			
		||||
		{
 | 
			
		||||
			Wire *w = topmod->wire(portname);
 | 
			
		||||
			if (!w)
 | 
			
		||||
				log_error("Can't find port %s on module %s.\n", log_id(portname), log_id(top->module));
 | 
			
		||||
			if (!w->port_input)
 | 
			
		||||
				log_error("Clock port %s on module %s is not input.\n", log_id(portname), log_id(top->module));
 | 
			
		||||
			fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(portname));
 | 
			
		||||
			if (id==0)
 | 
			
		||||
				log_error("Can't find port %s.%s in FST.\n", scope.c_str(), log_id(portname));
 | 
			
		||||
			fst_clock.push_back(id);
 | 
			
		||||
		}
 | 
			
		||||
		if (fst_clock.size()==0)
 | 
			
		||||
			log_error("No clock signals defined for input file\n");
 | 
			
		||||
 | 
			
		||||
		SigMap sigmap(topmod);
 | 
			
		||||
		std::map<Wire*,fstHandle> inputs;
 | 
			
		||||
 | 
			
		||||
		for (auto wire : topmod->wires()) {
 | 
			
		||||
			if (wire->port_input) {
 | 
			
		||||
				fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(wire->name));
 | 
			
		||||
				if (id==0)
 | 
			
		||||
					log_error("Unable to find required '%s' signal in file\n",(scope + "." + RTLIL::unescape_id(wire->name)).c_str());
 | 
			
		||||
				inputs[wire] = id;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		uint64_t startCount = 0;
 | 
			
		||||
		uint64_t stopCount = 0;
 | 
			
		||||
		if (start_time==0) {
 | 
			
		||||
			if (start_time < fst->getStartTime())
 | 
			
		||||
				log_warning("Start time is before simulation file start time\n");
 | 
			
		||||
			startCount = fst->getStartTime();
 | 
			
		||||
		} else if (start_time==-1) 
 | 
			
		||||
			startCount = fst->getEndTime();
 | 
			
		||||
		else {
 | 
			
		||||
			startCount = start_time / fst->getTimescale();
 | 
			
		||||
			if (startCount > fst->getEndTime()) {
 | 
			
		||||
				startCount = fst->getEndTime();
 | 
			
		||||
				log_warning("Start time is after simulation file end time\n");
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (stop_time==0) {
 | 
			
		||||
			if (stop_time < fst->getStartTime())
 | 
			
		||||
				log_warning("Stop time is before simulation file start time\n");
 | 
			
		||||
			stopCount = fst->getStartTime();
 | 
			
		||||
		} else if (stop_time==-1) 
 | 
			
		||||
			stopCount = fst->getEndTime();
 | 
			
		||||
		else {
 | 
			
		||||
			stopCount = stop_time / fst->getTimescale();
 | 
			
		||||
			if (stopCount > fst->getEndTime()) {
 | 
			
		||||
				stopCount = fst->getEndTime();
 | 
			
		||||
				log_warning("Stop time is after simulation file end time\n");
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (stopCount<startCount) {
 | 
			
		||||
			log_error("Stop time is before start time\n");
 | 
			
		||||
		}
 | 
			
		||||
		auto samples = fst->getAllEdges(fst_clock, startCount, stopCount);
 | 
			
		||||
 | 
			
		||||
		// Limit to number of cycles if provided
 | 
			
		||||
		if (cycles_set && ((size_t)(numcycles *2) < samples.size()))
 | 
			
		||||
			samples.erase(samples.begin() + (numcycles*2), samples.end());
 | 
			
		||||
 | 
			
		||||
		// Add setup time (start time)
 | 
			
		||||
		if (samples.empty() || samples.front()!=startCount)
 | 
			
		||||
			samples.insert(samples.begin(), startCount);
 | 
			
		||||
 | 
			
		||||
		fst->reconstructAllAtTimes(samples);
 | 
			
		||||
		bool initial = true;
 | 
			
		||||
		int cycle = 0;
 | 
			
		||||
		log("Co-simulation from %lu%s to %lu%s\n", (unsigned long)startCount, fst->getTimescaleString(), (unsigned long)stopCount, fst->getTimescaleString());
 | 
			
		||||
		for(auto &time : samples) {
 | 
			
		||||
			log("Co-simulating cycle %d [%lu%s].\n", cycle, (unsigned long)time, fst->getTimescaleString());
 | 
			
		||||
			for(auto &item : inputs) {
 | 
			
		||||
				std::string v = fst->valueAt(item.second, time);
 | 
			
		||||
				top->set_state(item.first, Const::from_string(v));
 | 
			
		||||
			}
 | 
			
		||||
			if (initial) {
 | 
			
		||||
				top->setInitState(time);
 | 
			
		||||
				initial = false;
 | 
			
		||||
			}
 | 
			
		||||
			update();
 | 
			
		||||
 | 
			
		||||
			bool status = top->checkSignals(time);
 | 
			
		||||
			if (status)
 | 
			
		||||
				log_error("Signal difference\n");
 | 
			
		||||
			cycle++;
 | 
			
		||||
		}
 | 
			
		||||
		if (writeback) {
 | 
			
		||||
			pool<Module*> wbmods;
 | 
			
		||||
			top->writeback(wbmods);
 | 
			
		||||
| 
						 | 
				
			
			@ -773,6 +1095,9 @@ struct SimPass : public Pass {
 | 
			
		|||
		log("    -vcd <filename>\n");
 | 
			
		||||
		log("        write the simulation results to the given VCD file\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -fst <filename>\n");
 | 
			
		||||
		log("        write the simulation results to the given FST file\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -clock <portname>\n");
 | 
			
		||||
		log("        name of top-level clock input\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -795,14 +1120,41 @@ struct SimPass : public Pass {
 | 
			
		|||
		log("        include the specified timescale declaration in the vcd\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -n <integer>\n");
 | 
			
		||||
		log("        number of cycles to simulate (default: 20)\n");
 | 
			
		||||
		log("        number of clock cycles to simulate (default: 20)\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -a\n");
 | 
			
		||||
		log("        include all nets in VCD output, not just those with public names\n");
 | 
			
		||||
		log("        use all nets in VCD/FST operations, not just those with public names\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -w\n");
 | 
			
		||||
		log("        writeback mode: use final simulation state as new init state\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -r\n");
 | 
			
		||||
		log("        read simulation results file (file formats supported: FST)\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -scope\n");
 | 
			
		||||
		log("        scope of simulation top model\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -at <time>\n");
 | 
			
		||||
		log("        sets start and stop time\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -start <time>\n");
 | 
			
		||||
		log("        start co-simulation in arbitary time (default 0)\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -stop <time>\n");
 | 
			
		||||
		log("        stop co-simulation in arbitary time (default END)\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -sim\n");
 | 
			
		||||
		log("        simulation with stimulus from FST (default)\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -sim-cmp\n");
 | 
			
		||||
		log("        co-simulation expect exact match\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -sim-gold\n");
 | 
			
		||||
		log("        co-simulation, x in simulation can match any value in FST\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -sim-gate\n");
 | 
			
		||||
		log("        co-simulation, x in FST can match any value in simulation\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -d\n");
 | 
			
		||||
		log("        enable debug output\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -811,6 +1163,7 @@ struct SimPass : public Pass {
 | 
			
		|||
	{
 | 
			
		||||
		SimWorker worker;
 | 
			
		||||
		int numcycles = 20;
 | 
			
		||||
		bool start_set = false, stop_set = false, at_set = false;
 | 
			
		||||
 | 
			
		||||
		log_header(design, "Executing SIM pass (simulate the circuit).\n");
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -822,8 +1175,15 @@ struct SimPass : public Pass {
 | 
			
		|||
				worker.vcdfile.open(vcd_filename.c_str());
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-fst" && argidx+1 < args.size()) {
 | 
			
		||||
				std::string fst_filename = args[++argidx];
 | 
			
		||||
				rewrite_filename(fst_filename);
 | 
			
		||||
				worker.fstfile = (struct fstContext *)fstWriterCreate(fst_filename.c_str(),1);
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-n" && argidx+1 < args.size()) {
 | 
			
		||||
				numcycles = atoi(args[++argidx].c_str());
 | 
			
		||||
				worker.cycles_set = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-rstlen" && argidx+1 < args.size()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -866,9 +1226,55 @@ struct SimPass : public Pass {
 | 
			
		|||
				worker.zinit = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-r" && argidx+1 < args.size()) {
 | 
			
		||||
				std::string sim_filename = args[++argidx];
 | 
			
		||||
				rewrite_filename(sim_filename);
 | 
			
		||||
				worker.sim_filename = sim_filename;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-scope" && argidx+1 < args.size()) {
 | 
			
		||||
				worker.scope = args[++argidx];
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-start" && argidx+1 < args.size()) {
 | 
			
		||||
				worker.start_time = stringToTime(args[++argidx]);
 | 
			
		||||
				start_set = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-stop" && argidx+1 < args.size()) {
 | 
			
		||||
				worker.stop_time = stringToTime(args[++argidx]);
 | 
			
		||||
				stop_set = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-at" && argidx+1 < args.size()) {
 | 
			
		||||
				worker.start_time = stringToTime(args[++argidx]);
 | 
			
		||||
				worker.stop_time = worker.start_time;
 | 
			
		||||
				at_set = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-sim") {
 | 
			
		||||
				worker.sim_mode = SimulationMode::sim;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-sim-cmp") {
 | 
			
		||||
				worker.sim_mode = SimulationMode::cmp;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-sim-gold") {
 | 
			
		||||
				worker.sim_mode = SimulationMode::gold;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-sim-gate") {
 | 
			
		||||
				worker.sim_mode = SimulationMode::gate;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		extra_args(args, argidx, design);
 | 
			
		||||
		if (at_set && (start_set || stop_set || worker.cycles_set))
 | 
			
		||||
			log_error("'at' option can only be defined separate of 'start','stop' and 'n'\n");
 | 
			
		||||
		if (stop_set && worker.cycles_set)
 | 
			
		||||
			log_error("'stop' and 'n' can only be used exclusively'\n");
 | 
			
		||||
 | 
			
		||||
		Module *top_mod = nullptr;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -884,7 +1290,10 @@ struct SimPass : public Pass {
 | 
			
		|||
			top_mod = mods.front();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (worker.sim_filename.empty())
 | 
			
		||||
			worker.run(top_mod, numcycles);
 | 
			
		||||
		else
 | 
			
		||||
			worker.run_cosim(top_mod, numcycles);
 | 
			
		||||
	}
 | 
			
		||||
} SimPass;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								tests/sat/.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								tests/sat/.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -1,2 +1,4 @@
 | 
			
		|||
*.log
 | 
			
		||||
run-test.mk
 | 
			
		||||
*.vcd
 | 
			
		||||
*.fst
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										79
									
								
								tests/sat/alu.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								tests/sat/alu.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,79 @@
 | 
			
		|||
module alu(
 | 
			
		||||
	input clk,
 | 
			
		||||
	input [7:0] A,
 | 
			
		||||
	input [7:0] B,
 | 
			
		||||
	input [3:0] operation,
 | 
			
		||||
	output reg [7:0] result,
 | 
			
		||||
	output reg CF,
 | 
			
		||||
	output reg ZF,
 | 
			
		||||
	output reg SF
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
	localparam ALU_OP_ADD /* verilator public_flat */ = 4'b0000;
 | 
			
		||||
	localparam ALU_OP_SUB /* verilator public_flat */ = 4'b0001;
 | 
			
		||||
	localparam ALU_OP_ADC /* verilator public_flat */ = 4'b0010;
 | 
			
		||||
	localparam ALU_OP_SBC /* verilator public_flat */ = 4'b0011;
 | 
			
		||||
 | 
			
		||||
	localparam ALU_OP_AND /* verilator public_flat */ = 4'b0100;
 | 
			
		||||
	localparam ALU_OP_OR  /* verilator public_flat */ = 4'b0101;
 | 
			
		||||
	localparam ALU_OP_NOT /* verilator public_flat */ = 4'b0110;
 | 
			
		||||
	localparam ALU_OP_XOR /* verilator public_flat */ = 4'b0111;
 | 
			
		||||
 | 
			
		||||
	localparam ALU_OP_SHL /* verilator public_flat */ = 4'b1000;
 | 
			
		||||
	localparam ALU_OP_SHR /* verilator public_flat */ = 4'b1001;
 | 
			
		||||
	localparam ALU_OP_SAL /* verilator public_flat */ = 4'b1010;
 | 
			
		||||
	localparam ALU_OP_SAR /* verilator public_flat */ = 4'b1011;
 | 
			
		||||
 | 
			
		||||
	localparam ALU_OP_ROL /* verilator public_flat */ = 4'b1100;
 | 
			
		||||
	localparam ALU_OP_ROR /* verilator public_flat */ = 4'b1101;
 | 
			
		||||
	localparam ALU_OP_RCL /* verilator public_flat */ = 4'b1110;
 | 
			
		||||
	localparam ALU_OP_RCR /* verilator public_flat */ = 4'b1111;
 | 
			
		||||
 | 
			
		||||
	reg [8:0] tmp;
 | 
			
		||||
 | 
			
		||||
	always @(posedge clk)
 | 
			
		||||
	begin
 | 
			
		||||
		case (operation)
 | 
			
		||||
			ALU_OP_ADD :
 | 
			
		||||
				tmp = A + B;
 | 
			
		||||
			ALU_OP_SUB :
 | 
			
		||||
				tmp = A - B;
 | 
			
		||||
			ALU_OP_ADC :
 | 
			
		||||
				tmp = A + B + { 7'b0000000, CF };
 | 
			
		||||
			ALU_OP_SBC :
 | 
			
		||||
				tmp = A - B - { 7'b0000000, CF };
 | 
			
		||||
			ALU_OP_AND :
 | 
			
		||||
				tmp = {1'b0, A & B };
 | 
			
		||||
			ALU_OP_OR :
 | 
			
		||||
				tmp = {1'b0, A | B };
 | 
			
		||||
			ALU_OP_NOT :
 | 
			
		||||
				tmp = {1'b0, ~B };
 | 
			
		||||
			ALU_OP_XOR :
 | 
			
		||||
				tmp = {1'b0, A ^ B};
 | 
			
		||||
			ALU_OP_SHL :
 | 
			
		||||
				tmp = { A[7], A[6:0], 1'b0};
 | 
			
		||||
			ALU_OP_SHR :
 | 
			
		||||
				tmp = { A[0], 1'b0, A[7:1]};
 | 
			
		||||
			ALU_OP_SAL :
 | 
			
		||||
				// Same as SHL
 | 
			
		||||
				tmp = { A[7], A[6:0], 1'b0};
 | 
			
		||||
			ALU_OP_SAR :
 | 
			
		||||
				tmp = { A[0], A[7], A[7:1]};
 | 
			
		||||
			ALU_OP_ROL :
 | 
			
		||||
				tmp = { A[7], A[6:0], A[7]};
 | 
			
		||||
			ALU_OP_ROR :
 | 
			
		||||
				tmp = { A[0], A[0], A[7:1]};
 | 
			
		||||
			ALU_OP_RCL :
 | 
			
		||||
				tmp = { A[7], A[6:0], CF};
 | 
			
		||||
			ALU_OP_RCR :
 | 
			
		||||
				tmp = { A[0], CF, A[7:1]};
 | 
			
		||||
		endcase
 | 
			
		||||
 | 
			
		||||
		CF <= tmp[8];
 | 
			
		||||
		ZF <= tmp[7:0] == 0;
 | 
			
		||||
		SF <= tmp[7];
 | 
			
		||||
 | 
			
		||||
		result <= tmp[7:0];
 | 
			
		||||
	end
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								tests/sat/grom.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								tests/sat/grom.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
read_verilog grom_computer.v grom_cpu.v alu.v ram_memory.v;
 | 
			
		||||
prep -top grom_computer; 
 | 
			
		||||
sim -clock clk -reset reset -fst grom.fst -vcd grom.vcd -n 80
 | 
			
		||||
 | 
			
		||||
sim -clock clk -r grom.fst -scope grom_computer -start 25ns -stop 100ns -sim-cmp
 | 
			
		||||
 | 
			
		||||
sim -clock clk -r grom.fst -scope grom_computer -stop 100ns -sim-gold
 | 
			
		||||
 | 
			
		||||
sim -clock clk -r grom.fst -scope grom_computer -n 10 -sim-gate
 | 
			
		||||
							
								
								
									
										31
									
								
								tests/sat/grom_computer.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								tests/sat/grom_computer.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,31 @@
 | 
			
		|||
module grom_computer
 | 
			
		||||
  (input  clk,     // Main Clock
 | 
			
		||||
   input  reset,   // reset
 | 
			
		||||
   output hlt,
 | 
			
		||||
   output reg[7:0] display_out
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
 wire [11:0] addr;
 | 
			
		||||
 wire [7:0] memory_out;
 | 
			
		||||
 wire [7:0] memory_in;
 | 
			
		||||
 wire mem_enable;
 | 
			
		||||
 wire  we;
 | 
			
		||||
 wire ioreq;
 | 
			
		||||
 | 
			
		||||
 grom_cpu cpu(.clk(clk),.reset(reset),.addr(addr),.data_in(memory_out),.data_out(memory_in),.we(we),.ioreq(ioreq),.hlt(hlt));
 | 
			
		||||
 | 
			
		||||
 assign mem_enable = we & ~ioreq;
 | 
			
		||||
 | 
			
		||||
 ram_memory memory(.clk(clk),.addr(addr),.data_in(memory_in),.we(mem_enable),.data_out(memory_out));
 | 
			
		||||
 | 
			
		||||
 always @(posedge clk)
 | 
			
		||||
	begin
 | 
			
		||||
		if(ioreq==1 && we==1)
 | 
			
		||||
		begin
 | 
			
		||||
			display_out <= memory_in;
 | 
			
		||||
			`ifdef DISASSEMBLY
 | 
			
		||||
			$display("Display output : %h", memory_in);
 | 
			
		||||
			`endif
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
endmodule
 | 
			
		||||
							
								
								
									
										747
									
								
								tests/sat/grom_cpu.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										747
									
								
								tests/sat/grom_cpu.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,747 @@
 | 
			
		|||
module grom_cpu(
 | 
			
		||||
	input clk,
 | 
			
		||||
	input reset,
 | 
			
		||||
	output reg [11:0] addr,
 | 
			
		||||
	input [7:0] data_in,
 | 
			
		||||
	output reg [7:0] data_out,
 | 
			
		||||
	output reg we,
 | 
			
		||||
	output reg ioreq,
 | 
			
		||||
	output reg hlt
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
	reg[11:0] PC /* verilator public_flat */;    		// Program counter
 | 
			
		||||
	reg[7:0] IR /* verilator public_flat */;    	    // Instruction register
 | 
			
		||||
	reg[7:0] VALUE /* verilator public_flat */;   		// Temp reg for storing 2nd operand
 | 
			
		||||
	reg[3:0] CS /* verilator public_flat */;    		// Code segment regiser
 | 
			
		||||
	reg[3:0] DS /* verilator public_flat */;    		// Data segment regiser
 | 
			
		||||
	reg[11:0] SP /* verilator public_flat */;    		// Stack pointer regiser
 | 
			
		||||
	reg[7:0] R[0:3] /* verilator public_flat */; 		// General purpose registers
 | 
			
		||||
	reg[11:0] FUTURE_PC /* verilator public_flat */;    // PC to jump to
 | 
			
		||||
 | 
			
		||||
	localparam STATE_RESET             /*verilator public_flat*/ = 5'b00000;
 | 
			
		||||
	localparam STATE_FETCH_PREP        /*verilator public_flat*/ = 5'b00001;
 | 
			
		||||
	localparam STATE_FETCH_WAIT        /*verilator public_flat*/ = 5'b00010;
 | 
			
		||||
	localparam STATE_FETCH             /*verilator public_flat*/ = 5'b00011;
 | 
			
		||||
	localparam STATE_EXECUTE           /*verilator public_flat*/ = 5'b00100;
 | 
			
		||||
	localparam STATE_FETCH_VALUE_PREP  /*verilator public_flat*/ = 5'b00101;
 | 
			
		||||
	localparam STATE_FETCH_VALUE       /*verilator public_flat*/ = 5'b00110;
 | 
			
		||||
	localparam STATE_EXECUTE_DBL       /*verilator public_flat*/ = 5'b00111;
 | 
			
		||||
	localparam STATE_LOAD_VALUE        /*verilator public_flat*/ = 5'b01000;
 | 
			
		||||
	localparam STATE_LOAD_VALUE_WAIT   /*verilator public_flat*/ = 5'b01001;
 | 
			
		||||
	localparam STATE_ALU_RESULT_WAIT   /*verilator public_flat*/ = 5'b01010;
 | 
			
		||||
	localparam STATE_ALU_RESULT        /*verilator public_flat*/ = 5'b01011;
 | 
			
		||||
	localparam STATE_PUSH_PC_LOW       /*verilator public_flat*/ = 5'b01100;
 | 
			
		||||
	localparam STATE_JUMP              /*verilator public_flat*/ = 5'b01101;
 | 
			
		||||
	localparam STATE_RET_VALUE_WAIT    /*verilator public_flat*/ = 5'b01110;
 | 
			
		||||
	localparam STATE_RET_VALUE         /*verilator public_flat*/ = 5'b01111;
 | 
			
		||||
	localparam STATE_RET_VALUE_WAIT2   /*verilator public_flat*/ = 5'b10000;
 | 
			
		||||
	localparam STATE_RET_VALUE2        /*verilator public_flat*/ = 5'b10001;
 | 
			
		||||
 | 
			
		||||
	reg [4:0] state /* verilator public_flat */ = STATE_RESET;
 | 
			
		||||
 | 
			
		||||
	reg [7:0]  alu_a /* verilator public_flat */;
 | 
			
		||||
	reg [7:0]  alu_b /* verilator public_flat */;
 | 
			
		||||
	reg [3:0]  alu_op /* verilator public_flat */;
 | 
			
		||||
 | 
			
		||||
	reg [1:0]  RESULT_REG /* verilator public_flat */;
 | 
			
		||||
 | 
			
		||||
	wire [7:0] alu_res /* verilator public_flat */;
 | 
			
		||||
	wire alu_CF /* verilator public_flat */;
 | 
			
		||||
	wire alu_ZF /* verilator public_flat */;
 | 
			
		||||
	wire alu_SF /* verilator public_flat */;
 | 
			
		||||
	reg jump;
 | 
			
		||||
 | 
			
		||||
	alu alu(.clk(clk),.A(alu_a),.B(alu_b),.operation(alu_op),.result(alu_res),.CF(alu_CF),.ZF(alu_ZF),.SF(alu_SF));
 | 
			
		||||
 | 
			
		||||
	always @(posedge clk)
 | 
			
		||||
	begin
 | 
			
		||||
		if (reset)
 | 
			
		||||
		begin
 | 
			
		||||
			state <= STATE_RESET;
 | 
			
		||||
			hlt   <= 0;
 | 
			
		||||
		end
 | 
			
		||||
		else
 | 
			
		||||
		begin
 | 
			
		||||
			case (state)
 | 
			
		||||
				STATE_RESET :
 | 
			
		||||
					begin
 | 
			
		||||
						PC    <= 12'h000;
 | 
			
		||||
						state <= STATE_FETCH_PREP;
 | 
			
		||||
						CS    <= 4'h0;
 | 
			
		||||
						DS    <= 4'h0;
 | 
			
		||||
						R[0]  <= 8'h00;
 | 
			
		||||
						R[1]  <= 8'h00;
 | 
			
		||||
						R[2]  <= 8'h00;
 | 
			
		||||
						R[3]  <= 8'h00;
 | 
			
		||||
						SP    <= 12'hfff;
 | 
			
		||||
					end
 | 
			
		||||
 | 
			
		||||
				STATE_FETCH_PREP :
 | 
			
		||||
					begin
 | 
			
		||||
						addr  <= PC;
 | 
			
		||||
						we    <= 0;
 | 
			
		||||
						ioreq <= 0;
 | 
			
		||||
 | 
			
		||||
						state <= STATE_FETCH_WAIT;
 | 
			
		||||
					end
 | 
			
		||||
 | 
			
		||||
				STATE_FETCH_WAIT :
 | 
			
		||||
					begin
 | 
			
		||||
						// Sync with memory due to CLK
 | 
			
		||||
						state <= (hlt) ? STATE_FETCH_PREP : STATE_FETCH;
 | 
			
		||||
					end
 | 
			
		||||
 | 
			
		||||
				STATE_FETCH :
 | 
			
		||||
					begin
 | 
			
		||||
						IR    <= data_in;
 | 
			
		||||
						PC    <= PC + 1;
 | 
			
		||||
 | 
			
		||||
						state <= STATE_EXECUTE;
 | 
			
		||||
					end
 | 
			
		||||
				STATE_EXECUTE :
 | 
			
		||||
					begin
 | 
			
		||||
						`ifdef DISASSEMBLY
 | 
			
		||||
						$display("    PC %h R0 %h R1 %h R2 %h R3 %h CS %h DS %h SP %h ALU [%d %d %d]", PC, R[0], R[1], R[2], R[3], CS, DS, SP, alu_CF,alu_SF,alu_ZF);
 | 
			
		||||
						`endif
 | 
			
		||||
						if (IR[7])
 | 
			
		||||
						begin
 | 
			
		||||
							addr  <= PC;
 | 
			
		||||
							state <= STATE_FETCH_VALUE_PREP;
 | 
			
		||||
							PC    <= PC + 1;
 | 
			
		||||
						end
 | 
			
		||||
						else
 | 
			
		||||
						begin
 | 
			
		||||
							case(IR[6:4])
 | 
			
		||||
								3'b000 :
 | 
			
		||||
									begin
 | 
			
		||||
										`ifdef DISASSEMBLY
 | 
			
		||||
										$display("MOV R%d,R%d",IR[3:2],IR[1:0]);
 | 
			
		||||
										`endif
 | 
			
		||||
										R[IR[3:2]] <= R[IR[1:0]];
 | 
			
		||||
										state <= STATE_FETCH_PREP;
 | 
			
		||||
									end
 | 
			
		||||
								3'b001 :
 | 
			
		||||
									begin
 | 
			
		||||
										alu_a   <= R[0];      // first input R0
 | 
			
		||||
										alu_b   <= R[IR[1:0]];
 | 
			
		||||
										RESULT_REG <= 0;         // result in R0
 | 
			
		||||
										alu_op  <= { 2'b00, IR[3:2] };
 | 
			
		||||
 | 
			
		||||
										state   <= STATE_ALU_RESULT_WAIT;
 | 
			
		||||
 | 
			
		||||
										`ifdef DISASSEMBLY
 | 
			
		||||
										case(IR[3:2])
 | 
			
		||||
											2'b00 : begin
 | 
			
		||||
													$display("ADD R%d",IR[1:0]);
 | 
			
		||||
													end
 | 
			
		||||
											2'b01 : begin
 | 
			
		||||
													$display("SUB R%d",IR[1:0]);
 | 
			
		||||
													end
 | 
			
		||||
											2'b10 : begin
 | 
			
		||||
													$display("ADC R%d",IR[1:0]);
 | 
			
		||||
													end
 | 
			
		||||
											2'b11 : begin
 | 
			
		||||
													$display("SBC R%d",IR[1:0]);
 | 
			
		||||
													end
 | 
			
		||||
										endcase
 | 
			
		||||
										`endif
 | 
			
		||||
									end
 | 
			
		||||
								3'b010 :
 | 
			
		||||
									begin
 | 
			
		||||
										alu_a   <= R[0];      // first input R0
 | 
			
		||||
										alu_b   <= R[IR[1:0]];
 | 
			
		||||
										RESULT_REG <= 0;         // result in R0
 | 
			
		||||
										alu_op  <= { 2'b01, IR[3:2] };
 | 
			
		||||
										state   <= STATE_ALU_RESULT_WAIT;
 | 
			
		||||
										`ifdef DISASSEMBLY
 | 
			
		||||
										case(IR[3:2])
 | 
			
		||||
											2'b00 : begin
 | 
			
		||||
													$display("AND R%d",IR[1:0]);
 | 
			
		||||
													end
 | 
			
		||||
											2'b01 : begin
 | 
			
		||||
													$display("OR R%d",IR[1:0]);
 | 
			
		||||
													end
 | 
			
		||||
											2'b10 : begin
 | 
			
		||||
													$display("NOT R%d",IR[1:0]);
 | 
			
		||||
													end
 | 
			
		||||
											2'b11 : begin
 | 
			
		||||
													$display("XOR R%d",IR[1:0]);
 | 
			
		||||
													end
 | 
			
		||||
										endcase
 | 
			
		||||
										`endif
 | 
			
		||||
									end
 | 
			
		||||
								3'b011 :
 | 
			
		||||
									begin
 | 
			
		||||
										RESULT_REG <= IR[1:0];  // result in REG
 | 
			
		||||
										// CMP and TEST are not storing result										
 | 
			
		||||
										state   <= IR[3] ? STATE_FETCH_PREP : STATE_ALU_RESULT_WAIT;
 | 
			
		||||
										// CMP and TEST are having first input R0, for INC and DEC is REG
 | 
			
		||||
										alu_a   <= IR[3] ? R[0] : R[IR[1:0]];								
 | 
			
		||||
										// CMP and TEST are having second input REG, for INC and DEC is 1
 | 
			
		||||
										alu_b   <= IR[3] ? R[IR[1:0]] : 8'b00000001;								
 | 
			
		||||
 | 
			
		||||
										case(IR[3:2])
 | 
			
		||||
											2'b00 : begin
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("INC R%d",IR[1:0]);
 | 
			
		||||
													`endif
 | 
			
		||||
													alu_op  <= 4'b0001;     // ALU_OP_ADD
 | 
			
		||||
													end
 | 
			
		||||
											2'b01 : begin
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("DEC R%d",IR[1:0]);
 | 
			
		||||
													`endif
 | 
			
		||||
													alu_op  <= 4'b0001;     // ALU_OP_SUB
 | 
			
		||||
													end
 | 
			
		||||
											2'b10 : begin
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("CMP R%d",IR[1:0]);
 | 
			
		||||
													`endif
 | 
			
		||||
													alu_op  <= 4'b0001;     // ALU_OP_SUB
 | 
			
		||||
													end
 | 
			
		||||
											2'b11 : begin
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("TST R%d",IR[1:0]);
 | 
			
		||||
													`endif
 | 
			
		||||
													alu_op  <= 4'b0100;     // ALU_OP_AND
 | 
			
		||||
													end
 | 
			
		||||
										endcase
 | 
			
		||||
									end
 | 
			
		||||
								3'b100 :
 | 
			
		||||
									begin
 | 
			
		||||
										if (IR[3]==0)
 | 
			
		||||
										begin
 | 
			
		||||
											alu_a   <= R[0];      // first input R0
 | 
			
		||||
											// no 2nd input
 | 
			
		||||
											RESULT_REG <= 0;         // result in R0
 | 
			
		||||
											alu_op  <= { 1'b1, IR[2:0] };
 | 
			
		||||
											`ifdef DISASSEMBLY
 | 
			
		||||
											case(IR[2:0])
 | 
			
		||||
												3'b000 : begin
 | 
			
		||||
														$display("SHL");
 | 
			
		||||
														end
 | 
			
		||||
												3'b001 : begin
 | 
			
		||||
														$display("SHR");
 | 
			
		||||
														end
 | 
			
		||||
												3'b010 : begin
 | 
			
		||||
														$display("SAL");
 | 
			
		||||
														end
 | 
			
		||||
												3'b011 : begin
 | 
			
		||||
														$display("SAR");
 | 
			
		||||
														end
 | 
			
		||||
												3'b100 : begin
 | 
			
		||||
														$display("ROL");
 | 
			
		||||
														end
 | 
			
		||||
												3'b101 : begin
 | 
			
		||||
														$display("ROR");
 | 
			
		||||
														end
 | 
			
		||||
												3'b110 : begin
 | 
			
		||||
														$display("RCL");
 | 
			
		||||
														end
 | 
			
		||||
												3'b111 : begin
 | 
			
		||||
														$display("RCR");
 | 
			
		||||
														end
 | 
			
		||||
											endcase
 | 
			
		||||
											`endif
 | 
			
		||||
											state   <= STATE_ALU_RESULT_WAIT;
 | 
			
		||||
										end
 | 
			
		||||
										else
 | 
			
		||||
										begin
 | 
			
		||||
											if (IR[2]==0)
 | 
			
		||||
											begin
 | 
			
		||||
												`ifdef DISASSEMBLY
 | 
			
		||||
												$display("PUSH R%d",IR[1:0]);
 | 
			
		||||
												`endif
 | 
			
		||||
												addr     <= SP;
 | 
			
		||||
												we       <= 1;
 | 
			
		||||
												ioreq    <= 0;
 | 
			
		||||
												data_out <= R[IR[1:0]];
 | 
			
		||||
												SP       <= SP - 1;
 | 
			
		||||
												state    <= STATE_FETCH_PREP;
 | 
			
		||||
											end
 | 
			
		||||
											else
 | 
			
		||||
											begin
 | 
			
		||||
												`ifdef DISASSEMBLY
 | 
			
		||||
												$display("POP R%d",IR[1:0]);
 | 
			
		||||
												`endif
 | 
			
		||||
												addr  <= SP + 1;
 | 
			
		||||
												we    <= 0;
 | 
			
		||||
												ioreq <= 0;
 | 
			
		||||
												RESULT_REG <= IR[1:0];
 | 
			
		||||
												SP    <= SP + 1;
 | 
			
		||||
												state <= STATE_LOAD_VALUE_WAIT;
 | 
			
		||||
											end
 | 
			
		||||
										end
 | 
			
		||||
									end
 | 
			
		||||
								3'b101 :
 | 
			
		||||
									begin
 | 
			
		||||
										`ifdef DISASSEMBLY
 | 
			
		||||
										$display("LOAD R%d,[R%d]", IR[3:2], IR[1:0]);
 | 
			
		||||
										`endif
 | 
			
		||||
										addr  <= { DS, R[IR[1:0]] };
 | 
			
		||||
										we    <= 0;
 | 
			
		||||
										ioreq <= 0;
 | 
			
		||||
										RESULT_REG <= IR[3:2];
 | 
			
		||||
 | 
			
		||||
										state <= STATE_LOAD_VALUE_WAIT;
 | 
			
		||||
									end
 | 
			
		||||
								3'b110 :
 | 
			
		||||
									begin
 | 
			
		||||
										`ifdef DISASSEMBLY
 | 
			
		||||
										$display("STORE [R%d],R%d", IR[3:2], IR[1:0]);
 | 
			
		||||
										`endif
 | 
			
		||||
										addr     <= { DS, R[IR[3:2]] };
 | 
			
		||||
										we       <= 1;
 | 
			
		||||
										ioreq    <= 0;
 | 
			
		||||
										data_out <= R[IR[1:0]];
 | 
			
		||||
 | 
			
		||||
										state    <= STATE_FETCH_PREP;
 | 
			
		||||
									end
 | 
			
		||||
								3'b111 :
 | 
			
		||||
									begin
 | 
			
		||||
										// Special instuctions
 | 
			
		||||
										case(IR[3:2])
 | 
			
		||||
											2'b00 : begin
 | 
			
		||||
													CS <= R[IR[1:0]][3:0];
 | 
			
		||||
													state <= STATE_FETCH_PREP;
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("MOV CS,R%d",IR[1:0]);
 | 
			
		||||
													`endif
 | 
			
		||||
													end
 | 
			
		||||
											2'b01 : begin
 | 
			
		||||
													DS <= R[IR[1:0]][3:0];
 | 
			
		||||
													state <= STATE_FETCH_PREP;
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("MOV DS,R%d",IR[1:0]);
 | 
			
		||||
													`endif
 | 
			
		||||
													end
 | 
			
		||||
											2'b10 : begin
 | 
			
		||||
														case(IR[1:0])
 | 
			
		||||
															2'b00 : begin
 | 
			
		||||
																	`ifdef DISASSEMBLY
 | 
			
		||||
																	$display("PUSH CS");
 | 
			
		||||
																	`endif
 | 
			
		||||
																	addr     <= SP;
 | 
			
		||||
																	we       <= 1;
 | 
			
		||||
																	ioreq    <= 0;
 | 
			
		||||
																	data_out <= { 4'b0000, CS};
 | 
			
		||||
																	SP       <= SP - 1;
 | 
			
		||||
																	state    <= STATE_FETCH_PREP;
 | 
			
		||||
																	end
 | 
			
		||||
															2'b01 : begin
 | 
			
		||||
																	`ifdef DISASSEMBLY
 | 
			
		||||
																	$display("PUSH DS");
 | 
			
		||||
																	`endif
 | 
			
		||||
																	addr     <= SP;
 | 
			
		||||
																	we       <= 1;
 | 
			
		||||
																	ioreq    <= 0;
 | 
			
		||||
																	data_out <= { 4'b0000, DS};
 | 
			
		||||
																	SP       <= SP - 1;
 | 
			
		||||
																	state    <= STATE_FETCH_PREP;
 | 
			
		||||
																	end
 | 
			
		||||
															2'b10 : begin
 | 
			
		||||
																	`ifdef DISASSEMBLY
 | 
			
		||||
																	$display("Unused opcode");
 | 
			
		||||
																	`endif
 | 
			
		||||
																	end
 | 
			
		||||
															2'b11 : begin
 | 
			
		||||
																	`ifdef DISASSEMBLY
 | 
			
		||||
																	$display("Unused opcode");
 | 
			
		||||
																	`endif
 | 
			
		||||
																end
 | 
			
		||||
														endcase
 | 
			
		||||
														state <= STATE_FETCH_PREP;
 | 
			
		||||
													end
 | 
			
		||||
											2'b11 : begin
 | 
			
		||||
														case(IR[1:0])
 | 
			
		||||
															2'b00 : begin
 | 
			
		||||
																	`ifdef DISASSEMBLY
 | 
			
		||||
																	$display("Unused opcode");
 | 
			
		||||
																	`endif
 | 
			
		||||
																	state <= STATE_FETCH_PREP;
 | 
			
		||||
																	end
 | 
			
		||||
															2'b01 : begin
 | 
			
		||||
																	`ifdef DISASSEMBLY
 | 
			
		||||
																	$display("Unused opcode");
 | 
			
		||||
																	`endif
 | 
			
		||||
																	state <= STATE_FETCH_PREP;
 | 
			
		||||
																	end
 | 
			
		||||
															2'b10 : begin
 | 
			
		||||
																	`ifdef DISASSEMBLY
 | 
			
		||||
																	$display("RET");
 | 
			
		||||
																	`endif
 | 
			
		||||
																	addr  <= SP + 1;
 | 
			
		||||
																	we    <= 0;
 | 
			
		||||
																	ioreq <= 0;
 | 
			
		||||
																	SP    <= SP + 1;
 | 
			
		||||
																	state <= STATE_RET_VALUE_WAIT;
 | 
			
		||||
																	end
 | 
			
		||||
															2'b11 : begin
 | 
			
		||||
																	hlt <= 1;
 | 
			
		||||
																	`ifdef DISASSEMBLY
 | 
			
		||||
																	$display("HALT");
 | 
			
		||||
																	`endif
 | 
			
		||||
																	state <= STATE_FETCH_PREP;
 | 
			
		||||
																	end
 | 
			
		||||
														endcase
 | 
			
		||||
												end
 | 
			
		||||
										endcase
 | 
			
		||||
									end
 | 
			
		||||
							endcase
 | 
			
		||||
						end
 | 
			
		||||
					end
 | 
			
		||||
				STATE_FETCH_VALUE_PREP :
 | 
			
		||||
					begin
 | 
			
		||||
						// Sync with memory due to CLK
 | 
			
		||||
						state <= STATE_FETCH_VALUE;
 | 
			
		||||
					end
 | 
			
		||||
				STATE_FETCH_VALUE :
 | 
			
		||||
					begin
 | 
			
		||||
						VALUE <= data_in;
 | 
			
		||||
						state <= STATE_EXECUTE_DBL;
 | 
			
		||||
					end
 | 
			
		||||
				STATE_EXECUTE_DBL :
 | 
			
		||||
					begin
 | 
			
		||||
						case(IR[6:4])
 | 
			
		||||
							3'b000 :
 | 
			
		||||
								begin
 | 
			
		||||
								if (IR[3]==0)
 | 
			
		||||
									begin
 | 
			
		||||
										case(IR[2:0])
 | 
			
		||||
											3'b000 :
 | 
			
		||||
												begin
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("JMP %h ",{ CS, VALUE[7:0] });
 | 
			
		||||
													`endif
 | 
			
		||||
													jump = 1;
 | 
			
		||||
												end
 | 
			
		||||
											3'b001 :
 | 
			
		||||
												begin
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("JC %h ",{CS, VALUE[7:0] });
 | 
			
		||||
													`endif
 | 
			
		||||
													jump = (alu_CF==1);
 | 
			
		||||
												end
 | 
			
		||||
											3'b010 :
 | 
			
		||||
												begin
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("JNC %h ",{CS, VALUE[7:0] });
 | 
			
		||||
													`endif
 | 
			
		||||
													jump = (alu_CF==0);
 | 
			
		||||
												end
 | 
			
		||||
											3'b011 :
 | 
			
		||||
												begin
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("JM %h ",{CS, VALUE[7:0] });
 | 
			
		||||
													`endif
 | 
			
		||||
													jump = (alu_SF==1);
 | 
			
		||||
												end
 | 
			
		||||
											3'b100 :
 | 
			
		||||
												begin
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("JP %h ",{CS, VALUE[7:0] });
 | 
			
		||||
													`endif
 | 
			
		||||
													jump = (alu_SF==0);
 | 
			
		||||
												end
 | 
			
		||||
											3'b101 :
 | 
			
		||||
												begin
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("JZ %h ",{CS, VALUE[7:0] });
 | 
			
		||||
													`endif
 | 
			
		||||
													jump = (alu_ZF==1);
 | 
			
		||||
												end
 | 
			
		||||
											3'b110 :
 | 
			
		||||
												begin
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("JNZ %h ",{CS, VALUE[7:0] });
 | 
			
		||||
													`endif
 | 
			
		||||
													jump = (alu_ZF==0);
 | 
			
		||||
												end
 | 
			
		||||
											3'b111 :
 | 
			
		||||
												begin
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("Unused opcode %h",IR);
 | 
			
		||||
													`endif
 | 
			
		||||
													jump = 0;
 | 
			
		||||
												end
 | 
			
		||||
										endcase
 | 
			
		||||
 | 
			
		||||
										if (jump)
 | 
			
		||||
										begin
 | 
			
		||||
											PC    <= { CS, VALUE[7:0] };
 | 
			
		||||
											addr  <= { CS, VALUE[7:0] };
 | 
			
		||||
											we    <= 0;
 | 
			
		||||
											ioreq <= 0;
 | 
			
		||||
										end
 | 
			
		||||
										state <= STATE_FETCH_PREP;
 | 
			
		||||
									end
 | 
			
		||||
								else
 | 
			
		||||
									begin
 | 
			
		||||
										case(IR[2:0])
 | 
			
		||||
											3'b000 :
 | 
			
		||||
												begin
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("JR %h ", PC + {VALUE[7],VALUE[7],VALUE[7],VALUE[7],VALUE[7:0]} );
 | 
			
		||||
													`endif
 | 
			
		||||
													jump = 1;
 | 
			
		||||
												end
 | 
			
		||||
											3'b001 :
 | 
			
		||||
												begin
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("JRC %h ",{CS, VALUE[7:0] });
 | 
			
		||||
													`endif
 | 
			
		||||
													jump = (alu_CF==1);
 | 
			
		||||
												end
 | 
			
		||||
											3'b010 :
 | 
			
		||||
												begin
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("JRNC %h ",{CS, VALUE[7:0] });
 | 
			
		||||
													`endif
 | 
			
		||||
													jump = (alu_CF==0);
 | 
			
		||||
												end
 | 
			
		||||
											3'b011 :
 | 
			
		||||
												begin
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("JRM %h ",{CS, VALUE[7:0] });
 | 
			
		||||
													`endif
 | 
			
		||||
													jump = (alu_SF==1);
 | 
			
		||||
												end
 | 
			
		||||
											3'b100 :
 | 
			
		||||
												begin
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("JRP %h ",{CS, VALUE[7:0] });
 | 
			
		||||
													`endif
 | 
			
		||||
													jump = (alu_SF==0);
 | 
			
		||||
												end
 | 
			
		||||
											3'b101 :
 | 
			
		||||
												begin
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("JRZ %h ",{CS, VALUE[7:0] });
 | 
			
		||||
													`endif
 | 
			
		||||
													jump = (alu_ZF==1);
 | 
			
		||||
												end
 | 
			
		||||
											3'b110 :
 | 
			
		||||
												begin
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("JRNZ %h ",{CS, VALUE[7:0] });
 | 
			
		||||
													`endif
 | 
			
		||||
													jump = (alu_ZF==0);
 | 
			
		||||
												end
 | 
			
		||||
											3'b111 :
 | 
			
		||||
												begin
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("Unused opcode %h",IR);
 | 
			
		||||
													`endif
 | 
			
		||||
													jump = 0;
 | 
			
		||||
												end
 | 
			
		||||
										endcase
 | 
			
		||||
										if (jump)
 | 
			
		||||
										begin
 | 
			
		||||
											PC    <= PC + {VALUE[7],VALUE[7],VALUE[7],VALUE[7],VALUE[7:0]};
 | 
			
		||||
											addr  <= PC + {VALUE[7],VALUE[7],VALUE[7],VALUE[7],VALUE[7:0]};
 | 
			
		||||
											we    <= 0;
 | 
			
		||||
											ioreq <= 0;
 | 
			
		||||
										end
 | 
			
		||||
										state <= STATE_FETCH_PREP;
 | 
			
		||||
									end
 | 
			
		||||
								end
 | 
			
		||||
							3'b001 :
 | 
			
		||||
								begin
 | 
			
		||||
									`ifdef DISASSEMBLY
 | 
			
		||||
									$display("JUMP %h ",{ IR[3:0], VALUE[7:0] });
 | 
			
		||||
									`endif
 | 
			
		||||
									PC    <= { IR[3:0], VALUE[7:0] };
 | 
			
		||||
									addr  <= { IR[3:0], VALUE[7:0] };
 | 
			
		||||
									we    <= 0;
 | 
			
		||||
									ioreq <= 0;
 | 
			
		||||
									state <= STATE_FETCH_PREP;
 | 
			
		||||
								end
 | 
			
		||||
							3'b010 :
 | 
			
		||||
								begin
 | 
			
		||||
									`ifdef DISASSEMBLY
 | 
			
		||||
									$display("CALL %h ",{ IR[3:0], VALUE[7:0] });
 | 
			
		||||
									`endif
 | 
			
		||||
									FUTURE_PC <= { IR[3:0], VALUE[7:0] };
 | 
			
		||||
									addr     <= SP;
 | 
			
		||||
									we       <= 1;
 | 
			
		||||
									ioreq    <= 0;
 | 
			
		||||
									data_out <= { 4'b0000, PC[11:8]};
 | 
			
		||||
									SP       <= SP - 1;
 | 
			
		||||
									state    <= STATE_PUSH_PC_LOW;
 | 
			
		||||
								end
 | 
			
		||||
							3'b011 :
 | 
			
		||||
								begin
 | 
			
		||||
									`ifdef DISASSEMBLY
 | 
			
		||||
									$display("MOV SP,%h ",{ IR[3:0], VALUE[7:0] });
 | 
			
		||||
									`endif
 | 
			
		||||
									SP <= { IR[3:0], VALUE[7:0] };
 | 
			
		||||
									state <= STATE_FETCH_PREP;
 | 
			
		||||
								end
 | 
			
		||||
							3'b100 :
 | 
			
		||||
								begin
 | 
			
		||||
									`ifdef DISASSEMBLY
 | 
			
		||||
									$display("IN R%d,[0x%h]",IR[1:0], VALUE);
 | 
			
		||||
									`endif
 | 
			
		||||
									ioreq <= 1;
 | 
			
		||||
									we    <= 0;
 | 
			
		||||
									addr  <= { 4'b0000, VALUE };
 | 
			
		||||
									RESULT_REG <= IR[1:0];
 | 
			
		||||
									state    <= STATE_LOAD_VALUE_WAIT;
 | 
			
		||||
								end
 | 
			
		||||
							3'b101 :
 | 
			
		||||
								begin
 | 
			
		||||
									`ifdef DISASSEMBLY
 | 
			
		||||
									$display("OUT [0x%h],R%d",VALUE,IR[1:0]);
 | 
			
		||||
									`endif
 | 
			
		||||
									ioreq <= 1;
 | 
			
		||||
									we    <= 1;
 | 
			
		||||
									addr  <= { 4'b0000, VALUE };
 | 
			
		||||
									data_out <= R[IR[1:0]];
 | 
			
		||||
									state    <= STATE_FETCH_PREP;
 | 
			
		||||
								end
 | 
			
		||||
							3'b110 :
 | 
			
		||||
								begin
 | 
			
		||||
									// Special instuctions
 | 
			
		||||
									case(IR[1:0])
 | 
			
		||||
										2'b00 : begin
 | 
			
		||||
												`ifdef DISASSEMBLY
 | 
			
		||||
												$display("MOV CS,0x%h",VALUE);
 | 
			
		||||
												`endif
 | 
			
		||||
												CS <= VALUE[3:0];
 | 
			
		||||
												state <= STATE_FETCH_PREP;
 | 
			
		||||
												end
 | 
			
		||||
										2'b01 : begin
 | 
			
		||||
												`ifdef DISASSEMBLY
 | 
			
		||||
												$display("MOV DS,0x%h",VALUE);
 | 
			
		||||
												`endif
 | 
			
		||||
												DS <= VALUE[3:0];
 | 
			
		||||
												state <= STATE_FETCH_PREP;
 | 
			
		||||
												end
 | 
			
		||||
										2'b10 : begin
 | 
			
		||||
												`ifdef DISASSEMBLY
 | 
			
		||||
												$display("Unused opcode %h",IR);
 | 
			
		||||
												`endif
 | 
			
		||||
												state <= STATE_FETCH_PREP;
 | 
			
		||||
												end
 | 
			
		||||
										2'b11 : begin
 | 
			
		||||
												`ifdef DISASSEMBLY
 | 
			
		||||
												$display("Unused opcode %h",IR);
 | 
			
		||||
												`endif
 | 
			
		||||
												state <= STATE_FETCH_PREP;
 | 
			
		||||
												end
 | 
			
		||||
									endcase
 | 
			
		||||
								end
 | 
			
		||||
							3'b111 :
 | 
			
		||||
								begin
 | 
			
		||||
									case(IR[3:2])
 | 
			
		||||
										2'b00 : begin
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("MOV R%d,0x%h",IR[1:0],VALUE);
 | 
			
		||||
													`endif
 | 
			
		||||
													R[IR[1:0]] <= VALUE;
 | 
			
		||||
													state <= STATE_FETCH_PREP;
 | 
			
		||||
												end
 | 
			
		||||
										2'b01 : begin
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("LOAD R%d,[0x%h]",IR[1:0], {DS, VALUE});
 | 
			
		||||
													`endif
 | 
			
		||||
													addr  <= { DS, VALUE };
 | 
			
		||||
													we    <= 0;
 | 
			
		||||
													ioreq <= 0;
 | 
			
		||||
													RESULT_REG <= IR[1:0];
 | 
			
		||||
 | 
			
		||||
													state <= STATE_LOAD_VALUE_WAIT;
 | 
			
		||||
												end
 | 
			
		||||
										2'b10 : begin
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("STORE [0x%h],R%d", {DS, VALUE}, IR[1:0]);
 | 
			
		||||
													`endif
 | 
			
		||||
													addr     <= { DS, VALUE };
 | 
			
		||||
													we       <= 1;
 | 
			
		||||
													ioreq    <= 0;
 | 
			
		||||
													data_out <= R[IR[1:0]];
 | 
			
		||||
 | 
			
		||||
													state    <= STATE_FETCH_PREP;
 | 
			
		||||
												end
 | 
			
		||||
										2'b11 : begin
 | 
			
		||||
													`ifdef DISASSEMBLY
 | 
			
		||||
													$display("Unused opcode %h",IR);
 | 
			
		||||
													`endif
 | 
			
		||||
													state <= STATE_FETCH_PREP;
 | 
			
		||||
												end
 | 
			
		||||
									endcase
 | 
			
		||||
								end
 | 
			
		||||
						endcase
 | 
			
		||||
					end
 | 
			
		||||
				STATE_LOAD_VALUE_WAIT :
 | 
			
		||||
					begin
 | 
			
		||||
						// Sync with memory due to CLK
 | 
			
		||||
						state <= STATE_LOAD_VALUE;
 | 
			
		||||
					end
 | 
			
		||||
				STATE_LOAD_VALUE :
 | 
			
		||||
					begin
 | 
			
		||||
						R[RESULT_REG] <= data_in;
 | 
			
		||||
						we    <= 0;
 | 
			
		||||
						state <= STATE_FETCH_PREP;
 | 
			
		||||
					end
 | 
			
		||||
				STATE_ALU_RESULT_WAIT :
 | 
			
		||||
					begin
 | 
			
		||||
						state <= STATE_ALU_RESULT;
 | 
			
		||||
					end
 | 
			
		||||
				STATE_ALU_RESULT :
 | 
			
		||||
					begin
 | 
			
		||||
						R[RESULT_REG] <= alu_res;
 | 
			
		||||
						state <= STATE_FETCH_PREP;
 | 
			
		||||
					end
 | 
			
		||||
				STATE_PUSH_PC_LOW :
 | 
			
		||||
					begin
 | 
			
		||||
						addr     <= SP;
 | 
			
		||||
						we       <= 1;
 | 
			
		||||
						ioreq    <= 0;
 | 
			
		||||
						data_out <= PC[7:0];
 | 
			
		||||
						SP       <= SP - 1;
 | 
			
		||||
						state    <= STATE_JUMP;
 | 
			
		||||
					end
 | 
			
		||||
				STATE_JUMP :
 | 
			
		||||
					begin
 | 
			
		||||
						`ifdef DISASSEMBLY
 | 
			
		||||
						$display("Jumping to %h",FUTURE_PC);
 | 
			
		||||
						`endif
 | 
			
		||||
						PC <= FUTURE_PC;
 | 
			
		||||
						state <= STATE_FETCH_PREP;
 | 
			
		||||
					end
 | 
			
		||||
				STATE_RET_VALUE_WAIT :
 | 
			
		||||
					begin
 | 
			
		||||
						// Sync with memory due to CLK
 | 
			
		||||
						state <= STATE_RET_VALUE;
 | 
			
		||||
					end
 | 
			
		||||
				STATE_RET_VALUE :
 | 
			
		||||
					begin
 | 
			
		||||
						FUTURE_PC <= { 4'b0000, data_in };
 | 
			
		||||
						we    <= 0;
 | 
			
		||||
						state <= STATE_RET_VALUE_WAIT2;
 | 
			
		||||
 | 
			
		||||
						addr  <= SP + 1;
 | 
			
		||||
						we    <= 0;
 | 
			
		||||
						ioreq <= 0;
 | 
			
		||||
						SP    <= SP + 1;
 | 
			
		||||
					end
 | 
			
		||||
				STATE_RET_VALUE_WAIT2 :
 | 
			
		||||
					begin
 | 
			
		||||
						// Sync with memory due to CLK
 | 
			
		||||
						state <= STATE_RET_VALUE2;
 | 
			
		||||
					end
 | 
			
		||||
				STATE_RET_VALUE2 :
 | 
			
		||||
					begin
 | 
			
		||||
						FUTURE_PC <= FUTURE_PC | ({ 4'b0000, data_in } << 8);
 | 
			
		||||
						we    <= 0;
 | 
			
		||||
						state <= STATE_JUMP;
 | 
			
		||||
					end
 | 
			
		||||
				default :
 | 
			
		||||
					begin
 | 
			
		||||
						state <= STATE_FETCH_PREP;
 | 
			
		||||
					end
 | 
			
		||||
			endcase
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
endmodule
 | 
			
		||||
							
								
								
									
										37
									
								
								tests/sat/ram_memory.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								tests/sat/ram_memory.v
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
module ram_memory(
 | 
			
		||||
  input clk,
 | 
			
		||||
  input [11:0] addr,
 | 
			
		||||
  input [7:0] data_in,
 | 
			
		||||
  input we,
 | 
			
		||||
  output reg [7:0] data_out
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
  reg [7:0] store[0:4095] /* verilator public_flat */;
 | 
			
		||||
 | 
			
		||||
  initial
 | 
			
		||||
  begin
 | 
			
		||||
	store[0] <= 8'b11100001; // MOV DS,2
 | 
			
		||||
	store[1] <= 8'b00000010; //
 | 
			
		||||
	store[2] <= 8'b01010100; // LOAD R1,[R0]
 | 
			
		||||
	store[3] <= 8'b00110001; // INC R1
 | 
			
		||||
	store[4] <= 8'b00110001; // INC R1
 | 
			
		||||
	store[5] <= 8'b01100001; // STORE [R0],R1
 | 
			
		||||
	store[6] <= 8'b11010001; // OUT [0],R1
 | 
			
		||||
	store[7] <= 8'b00000000; //
 | 
			
		||||
	store[8] <= 8'b00110001; // INC R1
 | 
			
		||||
	store[9] <= 8'b10100001; // CALL 0x100
 | 
			
		||||
	store[10] <= 8'b00000000; //
 | 
			
		||||
	store[11] <= 8'b01111111; // HLT
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	store[256] <= 8'b11010001; // OUT [0],R1
 | 
			
		||||
	store[257] <= 8'b00000000; //
 | 
			
		||||
	store[258] <= 8'b01111110; // RET
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  always @(posedge clk)
 | 
			
		||||
	if (we)
 | 
			
		||||
	  store[addr] <= data_in;
 | 
			
		||||
	else
 | 
			
		||||
	  data_out <= store[addr];
 | 
			
		||||
endmodule
 | 
			
		||||
							
								
								
									
										48
									
								
								tests/sat/sim_counter.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								tests/sat/sim_counter.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,48 @@
 | 
			
		|||
# Create stimulus file
 | 
			
		||||
read_verilog <<EOT
 | 
			
		||||
module top (clk, reset, cnt);
 | 
			
		||||
 | 
			
		||||
input		clk;
 | 
			
		||||
input		reset;
 | 
			
		||||
output	[7:0]	cnt;
 | 
			
		||||
 | 
			
		||||
reg	[7:0]	cnt;
 | 
			
		||||
 | 
			
		||||
endmodule
 | 
			
		||||
EOT
 | 
			
		||||
prep -top top;
 | 
			
		||||
sim -clock clk -reset reset -fst stimulus.fst -n 10
 | 
			
		||||
design -reset
 | 
			
		||||
 | 
			
		||||
# Counter implementation
 | 
			
		||||
read_verilog <<EOT
 | 
			
		||||
module top (clk, reset, cnt);
 | 
			
		||||
 | 
			
		||||
input		clk;
 | 
			
		||||
input		reset;
 | 
			
		||||
output	[7:0]	cnt;
 | 
			
		||||
 | 
			
		||||
reg	[7:0]	cnt;
 | 
			
		||||
 | 
			
		||||
always @(posedge clk)
 | 
			
		||||
	if (!reset)
 | 
			
		||||
		cnt = cnt + 1;
 | 
			
		||||
	else
 | 
			
		||||
		cnt = 0;
 | 
			
		||||
 | 
			
		||||
endmodule
 | 
			
		||||
EOT
 | 
			
		||||
prep -top top;
 | 
			
		||||
 | 
			
		||||
# Simulate with stimulus
 | 
			
		||||
sim -clock clk -scope top -r stimulus.fst
 | 
			
		||||
 | 
			
		||||
# Stimulus does not have counter values
 | 
			
		||||
# x in FST can match any value in simulation
 | 
			
		||||
sim -clock clk -scope top -r stimulus.fst -sim-gate
 | 
			
		||||
 | 
			
		||||
# Stimulus does not have counter values
 | 
			
		||||
# x in simulation can match any value in FST
 | 
			
		||||
# so we expect error
 | 
			
		||||
logger -expect error "Signal difference" 1
 | 
			
		||||
sim -clock clk -scope top -r stimulus.fst -sim-gold
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue