Add fstdata helper class
authorMiodrag Milanovic <mmicko@gmail.com>
Wed, 26 Jan 2022 09:23:38 +0000 (10:23 +0100)
committerMiodrag Milanovic <mmicko@gmail.com>
Wed, 26 Jan 2022 09:23:38 +0000 (10:23 +0100)
Makefile
kernel/fstdata.cc [new file with mode: 0644]
kernel/fstdata.h [new file with mode: 0644]

index f67d1e1db5212abdfbc72dc311cb217cb6523a10..d1b05e0cf10d66e13f63a51e8fa0ed8902698705 100644 (file)
--- 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 (file)
index 0000000..e497ff7
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ *  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)
+{
+       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;i<strlen(h->u.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<fstHandle> &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<fstHandle> &signal, std::vector<uint64_t> 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<uint64_t> 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<uint64_t> 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<uint64_t> 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<uint64_t> 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 (file)
index 0000000..c9a9338
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ *  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_callback(uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t plen);
+    void reconstruct(std::vector<fstHandle> &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<fstHandle> &signal,std::vector<uint64_t> time);
+       void reconstructAllAtTimes(std::vector<uint64_t> time);
+
+    std::string valueAt(fstHandle signal, uint64_t time);
+    std::vector<uint64_t> edges(fstHandle signal, bool positive, bool negative);
+    void recalc_time_offsets(fstHandle signal, std::vector<uint64_t> time);
+
+       fstHandle getHandle(std::string name);
+  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::map<uint64_t, size_t>> time_to_index;
+    std::map<fstHandle, std::map<size_t, uint64_t>> index_to_time;
+    std::vector<uint64_t> sample_times;
+    size_t sample_times_ndx;
+    std::map<fstHandle, std::string> current;
+};
+
+YOSYS_NAMESPACE_END
+
+#endif