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/qcsat.h))
 | 
				
			||||||
$(eval $(call add_include_file,kernel/ff.h))
 | 
					$(eval $(call add_include_file,kernel/ff.h))
 | 
				
			||||||
$(eval $(call add_include_file,kernel/ffinit.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,kernel/mem.h))
 | 
				
			||||||
$(eval $(call add_include_file,libs/ezsat/ezsat.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/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/sha1/sha1.h))
 | 
				
			||||||
$(eval $(call add_include_file,libs/json11/json11.hpp))
 | 
					$(eval $(call add_include_file,libs/json11/json11.hpp))
 | 
				
			||||||
$(eval $(call add_include_file,passes/fsm/fsmdata.h))
 | 
					$(eval $(call add_include_file,passes/fsm/fsmdata.h))
 | 
				
			||||||
| 
						 | 
					@ -618,7 +620,7 @@ ifneq ($(ABCEXTERNAL),)
 | 
				
			||||||
kernel/yosys.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"'
 | 
					kernel/yosys.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"'
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
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/log.o: CXXFLAGS += -DYOSYS_SRC='"$(YOSYS_SRC)"'
 | 
				
			||||||
kernel/yosys.o: CXXFLAGS += -DYOSYS_DATDIR='"$(DATDIR)"' -DYOSYS_PROGRAM_PREFIX='"$(PROGRAM_PREFIX)"'
 | 
					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/Solver.o
 | 
				
			||||||
OBJS += libs/minisat/System.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)/frontends/*/Makefile.inc
 | 
				
			||||||
include $(YOSYS_SRC)/passes/*/Makefile.inc
 | 
					include $(YOSYS_SRC)/passes/*/Makefile.inc
 | 
				
			||||||
include $(YOSYS_SRC)/backends/*/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
 | 
					rm -rf YosysVS-Tpl-v2.zip YosysVS
 | 
				
			||||||
wget https://yosyshq.net/yosys/nogit/YosysVS-Tpl-v2.zip
 | 
					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
 | 
					unzip YosysVS-Tpl-v2.zip
 | 
				
			||||||
rm -f 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)
 | 
						n=$(grep -B999 '<ItemGroup>' "$vcxsrc"/YosysVS/YosysVS.vcxproj | wc -l)
 | 
				
			||||||
	head -n$n "$vcxsrc"/YosysVS/YosysVS.vcxproj
 | 
						head -n$n "$vcxsrc"/YosysVS/YosysVS.vcxproj
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,12 +21,49 @@
 | 
				
			||||||
#include "kernel/sigtools.h"
 | 
					#include "kernel/sigtools.h"
 | 
				
			||||||
#include "kernel/celltypes.h"
 | 
					#include "kernel/celltypes.h"
 | 
				
			||||||
#include "kernel/mem.h"
 | 
					#include "kernel/mem.h"
 | 
				
			||||||
 | 
					#include "kernel/fstdata.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <ctime>
 | 
					#include <ctime>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
USING_YOSYS_NAMESPACE
 | 
					USING_YOSYS_NAMESPACE
 | 
				
			||||||
PRIVATE_NAMESPACE_BEGIN
 | 
					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
 | 
					struct SimShared
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	bool debug = false;
 | 
						bool debug = false;
 | 
				
			||||||
| 
						 | 
					@ -34,6 +71,11 @@ struct SimShared
 | 
				
			||||||
	bool writeback = false;
 | 
						bool writeback = false;
 | 
				
			||||||
	bool zinit = false;
 | 
						bool zinit = false;
 | 
				
			||||||
	int rstlen = 1;
 | 
						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)
 | 
					void zinit(State &v)
 | 
				
			||||||
| 
						 | 
					@ -52,6 +94,7 @@ struct SimInstance
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	SimShared *shared;
 | 
						SimShared *shared;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
 | 
						std::string scope;
 | 
				
			||||||
	Module *module;
 | 
						Module *module;
 | 
				
			||||||
	Cell *instance;
 | 
						Cell *instance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -92,9 +135,11 @@ struct SimInstance
 | 
				
			||||||
	std::vector<Mem> memories;
 | 
						std::vector<Mem> memories;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dict<Wire*, pair<int, Const>> vcd_database;
 | 
						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) :
 | 
						SimInstance(SimShared *shared, std::string scope, Module *module, Cell *instance = nullptr, SimInstance *parent = nullptr) :
 | 
				
			||||||
			shared(shared), module(module), instance(instance), parent(parent), sigmap(module)
 | 
								shared(shared), scope(scope), module(module), instance(instance), parent(parent), sigmap(module)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		log_assert(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)) {
 | 
								if (wire->attributes.count(ID::init)) {
 | 
				
			||||||
				Const initval = wire->attributes.at(ID::init);
 | 
									Const initval = wire->attributes.at(ID::init);
 | 
				
			||||||
				for (int i = 0; i < GetSize(sig) && i < GetSize(initval); i++)
 | 
									for (int i = 0; i < GetSize(sig) && i < GetSize(initval); i++)
 | 
				
			||||||
| 
						 | 
					@ -144,7 +196,7 @@ struct SimInstance
 | 
				
			||||||
			Module *mod = module->design->module(cell->type);
 | 
								Module *mod = module->design->module(cell->type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (mod != nullptr) {
 | 
								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()) {
 | 
								for (auto &port : cell->connections()) {
 | 
				
			||||||
| 
						 | 
					@ -622,14 +674,125 @@ struct SimInstance
 | 
				
			||||||
		for (auto child : children)
 | 
							for (auto child : children)
 | 
				
			||||||
			child.second->write_vcd_step(f);
 | 
								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
 | 
					struct SimWorker : SimShared
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	SimInstance *top = nullptr;
 | 
						SimInstance *top = nullptr;
 | 
				
			||||||
	std::ofstream vcdfile;
 | 
						std::ofstream vcdfile;
 | 
				
			||||||
 | 
						struct fstContext *fstfile = nullptr;
 | 
				
			||||||
	pool<IdString> clock, clockn, reset, resetn;
 | 
						pool<IdString> clock, clockn, reset, resetn;
 | 
				
			||||||
	std::string timescale;
 | 
						std::string timescale;
 | 
				
			||||||
 | 
						std::string sim_filename;
 | 
				
			||||||
 | 
						std::string scope;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	~SimWorker()
 | 
						~SimWorker()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					@ -638,9 +801,6 @@ struct SimWorker : SimShared
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void write_vcd_header()
 | 
						void write_vcd_header()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (!vcdfile.is_open())
 | 
					 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		vcdfile << stringf("$version %s $end\n", yosys_version_str);
 | 
							vcdfile << stringf("$version %s $end\n", yosys_version_str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::time_t t = std::time(nullptr);
 | 
							std::time_t t = std::time(nullptr);
 | 
				
			||||||
| 
						 | 
					@ -660,13 +820,53 @@ struct SimWorker : SimShared
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void write_vcd_step(int t)
 | 
						void write_vcd_step(int t)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (!vcdfile.is_open())
 | 
					 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		vcdfile << stringf("#%d\n", t);
 | 
							vcdfile << stringf("#%d\n", t);
 | 
				
			||||||
		top->write_vcd_step(vcdfile);
 | 
							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()
 | 
						void update()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		while (1)
 | 
							while (1)
 | 
				
			||||||
| 
						 | 
					@ -705,7 +905,7 @@ struct SimWorker : SimShared
 | 
				
			||||||
	void run(Module *topmod, int numcycles)
 | 
						void run(Module *topmod, int numcycles)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		log_assert(top == nullptr);
 | 
							log_assert(top == nullptr);
 | 
				
			||||||
		top = new SimInstance(this, topmod);
 | 
							top = new SimInstance(this, scope, topmod);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (debug)
 | 
							if (debug)
 | 
				
			||||||
			log("\n===== 0 =====\n");
 | 
								log("\n===== 0 =====\n");
 | 
				
			||||||
| 
						 | 
					@ -720,24 +920,25 @@ struct SimWorker : SimShared
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		update();
 | 
							update();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		write_vcd_header();
 | 
							write_output_header();
 | 
				
			||||||
		write_vcd_step(0);
 | 
							write_output_step(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (int cycle = 0; cycle < numcycles; cycle++)
 | 
							for (int cycle = 0; cycle < numcycles; cycle++)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (debug)
 | 
								if (debug)
 | 
				
			||||||
				log("\n===== %d =====\n", 10*cycle + 5);
 | 
									log("\n===== %d =====\n", 10*cycle + 5);
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									log("Simulating cycle %d.\n", (cycle*2)+1);
 | 
				
			||||||
			set_inports(clock, State::S0);
 | 
								set_inports(clock, State::S0);
 | 
				
			||||||
			set_inports(clockn, State::S1);
 | 
								set_inports(clockn, State::S1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			update();
 | 
								update();
 | 
				
			||||||
			write_vcd_step(10*cycle + 5);
 | 
								write_output_step(10*cycle + 5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (debug)
 | 
								if (debug)
 | 
				
			||||||
				log("\n===== %d =====\n", 10*cycle + 10);
 | 
									log("\n===== %d =====\n", 10*cycle + 10);
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
				log("Simulating cycle %d.\n", cycle+1);
 | 
									log("Simulating cycle %d.\n", (cycle*2)+2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			set_inports(clock, State::S1);
 | 
								set_inports(clock, State::S1);
 | 
				
			||||||
			set_inports(clockn, State::S0);
 | 
								set_inports(clockn, State::S0);
 | 
				
			||||||
| 
						 | 
					@ -748,11 +949,132 @@ struct SimWorker : SimShared
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			update();
 | 
								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) {
 | 
							if (writeback) {
 | 
				
			||||||
			pool<Module*> wbmods;
 | 
								pool<Module*> wbmods;
 | 
				
			||||||
			top->writeback(wbmods);
 | 
								top->writeback(wbmods);
 | 
				
			||||||
| 
						 | 
					@ -773,6 +1095,9 @@ struct SimPass : public Pass {
 | 
				
			||||||
		log("    -vcd <filename>\n");
 | 
							log("    -vcd <filename>\n");
 | 
				
			||||||
		log("        write the simulation results to the given VCD file\n");
 | 
							log("        write the simulation results to the given VCD file\n");
 | 
				
			||||||
		log("\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("    -clock <portname>\n");
 | 
				
			||||||
		log("        name of top-level clock input\n");
 | 
							log("        name of top-level clock input\n");
 | 
				
			||||||
		log("\n");
 | 
							log("\n");
 | 
				
			||||||
| 
						 | 
					@ -795,14 +1120,41 @@ struct SimPass : public Pass {
 | 
				
			||||||
		log("        include the specified timescale declaration in the vcd\n");
 | 
							log("        include the specified timescale declaration in the vcd\n");
 | 
				
			||||||
		log("\n");
 | 
							log("\n");
 | 
				
			||||||
		log("    -n <integer>\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("\n");
 | 
				
			||||||
		log("    -a\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("\n");
 | 
				
			||||||
		log("    -w\n");
 | 
							log("    -w\n");
 | 
				
			||||||
		log("        writeback mode: use final simulation state as new init state\n");
 | 
							log("        writeback mode: use final simulation state as new init state\n");
 | 
				
			||||||
		log("\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("    -d\n");
 | 
				
			||||||
		log("        enable debug output\n");
 | 
							log("        enable debug output\n");
 | 
				
			||||||
		log("\n");
 | 
							log("\n");
 | 
				
			||||||
| 
						 | 
					@ -811,6 +1163,7 @@ struct SimPass : public Pass {
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		SimWorker worker;
 | 
							SimWorker worker;
 | 
				
			||||||
		int numcycles = 20;
 | 
							int numcycles = 20;
 | 
				
			||||||
 | 
							bool start_set = false, stop_set = false, at_set = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		log_header(design, "Executing SIM pass (simulate the circuit).\n");
 | 
							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());
 | 
									worker.vcdfile.open(vcd_filename.c_str());
 | 
				
			||||||
				continue;
 | 
									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()) {
 | 
								if (args[argidx] == "-n" && argidx+1 < args.size()) {
 | 
				
			||||||
				numcycles = atoi(args[++argidx].c_str());
 | 
									numcycles = atoi(args[++argidx].c_str());
 | 
				
			||||||
 | 
									worker.cycles_set = true;
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (args[argidx] == "-rstlen" && argidx+1 < args.size()) {
 | 
								if (args[argidx] == "-rstlen" && argidx+1 < args.size()) {
 | 
				
			||||||
| 
						 | 
					@ -866,9 +1226,55 @@ struct SimPass : public Pass {
 | 
				
			||||||
				worker.zinit = true;
 | 
									worker.zinit = true;
 | 
				
			||||||
				continue;
 | 
									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;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		extra_args(args, argidx, design);
 | 
							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;
 | 
							Module *top_mod = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -884,7 +1290,10 @@ struct SimPass : public Pass {
 | 
				
			||||||
			top_mod = mods.front();
 | 
								top_mod = mods.front();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		worker.run(top_mod, numcycles);
 | 
							if (worker.sim_filename.empty())
 | 
				
			||||||
 | 
								worker.run(top_mod, numcycles);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								worker.run_cosim(top_mod, numcycles);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
} SimPass;
 | 
					} SimPass;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								tests/sat/.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								tests/sat/.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
					@ -1,2 +1,4 @@
 | 
				
			||||||
*.log
 | 
					*.log
 | 
				
			||||||
run-test.mk
 | 
					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