diff --git a/Makefile b/Makefile index f67d1e1db..d1b05e0cf 100644 --- a/Makefile +++ b/Makefile @@ -594,9 +594,12 @@ $(eval $(call add_include_file,kernel/satgen.h)) $(eval $(call add_include_file,kernel/qcsat.h)) $(eval $(call add_include_file,kernel/ff.h)) $(eval $(call add_include_file,kernel/ffinit.h)) +$(eval $(call add_include_file,kernel/fstdata.h)) $(eval $(call add_include_file,kernel/mem.h)) $(eval $(call add_include_file,libs/ezsat/ezsat.h)) $(eval $(call add_include_file,libs/ezsat/ezminisat.h)) +$(eval $(call add_include_file,libs/fst/fstapi.h)) +$(eval $(call add_include_file,libs/fst/fst_win_unistd.h)) $(eval $(call add_include_file,libs/sha1/sha1.h)) $(eval $(call add_include_file,libs/json11/json11.hpp)) $(eval $(call add_include_file,passes/fsm/fsmdata.h)) @@ -618,7 +621,7 @@ ifneq ($(ABCEXTERNAL),) kernel/yosys.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"' endif endif -OBJS += kernel/cellaigs.o kernel/celledges.o kernel/satgen.o kernel/qcsat.o kernel/mem.o kernel/ffmerge.o kernel/ff.o +OBJS += kernel/cellaigs.o kernel/celledges.o kernel/satgen.o kernel/qcsat.o kernel/mem.o kernel/ffmerge.o kernel/ff.o kernel/fstdata.o kernel/log.o: CXXFLAGS += -DYOSYS_SRC='"$(YOSYS_SRC)"' kernel/yosys.o: CXXFLAGS += -DYOSYS_DATDIR='"$(DATDIR)"' -DYOSYS_PROGRAM_PREFIX='"$(PROGRAM_PREFIX)"' diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc new file mode 100644 index 000000000..e497ff7ad --- /dev/null +++ b/kernel/fstdata.cc @@ -0,0 +1,265 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2022 Miodrag Milanovic + * + * 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) +{ + ctx = (fstReaderContext *)fstReaderOpen(filename.c_str()); + 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 + log("Not found key %s\n", name.c_str()); + 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;iu.var.name);i++) + { + char c = h->u.var.name[i]; + if(c==' ') break; + clean_name += c; + } + //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_clb_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_callback(pnt_time, pnt_facidx, pnt_value, plen); +} + +static void reconstruct_clb(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(pnt_time, pnt_facidx, pnt_value, plen); +} + +void FstData::reconstruct_callback(uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t /* plen */) +{ + handle_to_data[pnt_facidx].push_back(std::make_pair(pnt_time, std::string((const char *)pnt_value))); + size_t index = handle_to_data[pnt_facidx].size() - 1; + time_to_index[pnt_facidx][pnt_time] = index; + index_to_time[pnt_facidx][index] = pnt_time; +} + +void FstData::reconstruct(std::vector &signal) +{ + handle_to_data.clear(); + time_to_index.clear(); + index_to_time.clear(); + fstReaderClrFacProcessMaskAll(ctx); + for(const auto sig : signal) + fstReaderSetFacProcessMask(ctx,sig); + fstReaderIterBlocks2(ctx, reconstruct_clb, reconstruct_clb_varlen, this, nullptr); +} + +void FstData::reconstuctAll() +{ + handle_to_data.clear(); + time_to_index.clear(); + index_to_time.clear(); + fstReaderSetFacProcessMaskAll(ctx); + fstReaderIterBlocks2(ctx, reconstruct_clb, reconstruct_clb_varlen, this, nullptr); +} + +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 : current) + { + 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; + index_to_time[c.first][index] = time; + } + sample_times_ndx++; + } + // always update current + current[pnt_facidx] = std::string((const char *)pnt_value); +} + +void FstData::reconstructAtTimes(std::vector &signal, std::vector time) +{ + handle_to_data.clear(); + time_to_index.clear(); + index_to_time.clear(); + current.clear(); + sample_times_ndx = 0; + sample_times = time; + 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 : current) + { + 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; + index_to_time[c.first][index] = time.back(); + } + } +} + +void FstData::reconstructAllAtTimes(std::vector time) +{ + handle_to_data.clear(); + time_to_index.clear(); + index_to_time.clear(); + current.clear(); + sample_times_ndx = 0; + sample_times = time; + fstReaderSetFacProcessMaskAll(ctx); + 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 : current) + { + 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; + index_to_time[c.first][index] = time.back(); + } + }*/ +} + +std::string FstData::valueAt(fstHandle signal, uint64_t time) +{ + // TODO: Check if signal exist + 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 { + size_t index = 0; + for(size_t i = 0; i< data.size(); i++) { + uint64_t t = index_to_time[signal][i]; + if (t > time) + break; + index = i; + } + return data.at(index).second; + } +} + +std::vector FstData::edges(fstHandle signal, bool positive, bool negative) +{ + // TODO: Check if signal exist + auto &data = handle_to_data[signal]; + std::string prev = "x"; + std::vector retVal; + for(auto &d : data) { + if (positive && prev=="0" && d.second=="1") + retVal.push_back(d.first); + if (negative && prev=="1" && d.second=="0") + retVal.push_back(d.first); + prev = d.second; + } + return retVal; +} + +void FstData::recalc_time_offsets(fstHandle signal, std::vector time) +{ + size_t index = 0; + auto &data = handle_to_data[signal]; + for(auto curr : time) { + for(size_t i = index; i< data.size(); i++) { + uint64_t t = index_to_time[signal][i]; + if (t > curr) + break; + index = i; + } + time_to_index[signal][curr] = index; + } +} diff --git a/kernel/fstdata.h b/kernel/fstdata.h new file mode 100644 index 000000000..c9a933836 --- /dev/null +++ b/kernel/fstdata.h @@ -0,0 +1,79 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2022 Miodrag Milanovic + * + * 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& getVars() { return vars; }; + + void reconstruct_callback(uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t plen); + void reconstruct(std::vector &signal); + void reconstuctAll(); + + void reconstruct_callback_attimes(uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t plen); + void reconstructAtTimes(std::vector &signal,std::vector time); + void reconstructAllAtTimes(std::vector time); + + std::string valueAt(fstHandle signal, uint64_t time); + std::vector edges(fstHandle signal, bool positive, bool negative); + void recalc_time_offsets(fstHandle signal, std::vector time); + + fstHandle getHandle(std::string name); + private: + void extractVarNames(); + + struct fstReaderContext *ctx; + std::vector scopes; + std::vector vars; + std::map handle_to_var; + std::map name_to_handle; + std::map>> handle_to_data; + std::map> time_to_index; + std::map> index_to_time; + std::vector sample_times; + size_t sample_times_ndx; + std::map current; +}; + +YOSYS_NAMESPACE_END + +#endif