2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2022 Miodrag Milanovic <micko@yosyshq.com>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #include "kernel/fstdata.h"
25 static std::string
file_base_name(std::string
const & path
)
27 return path
.substr(path
.find_last_of("/\\") + 1);
30 FstData::FstData(std::string filename
) : ctx(nullptr)
32 #if !defined(YOSYS_DISABLE_SPAWN)
33 std::string filename_trim
= file_base_name(filename
);
34 if (filename_trim
.size() > 4 && filename_trim
.compare(filename_trim
.size()-4, std::string::npos
, ".vcd") == 0) {
35 filename_trim
.erase(filename_trim
.size()-4);
36 tmp_file
= stringf("/tmp/converted_%s.fst", filename_trim
.c_str());
37 std::string cmd
= stringf("vcd2fst %s %s", filename
.c_str(), tmp_file
.c_str());
38 log("Exec: %s\n", cmd
.c_str());
39 if (run_command(cmd
) != 0)
40 log_cmd_error("Shell command failed!\n");
44 const std::vector
<std::string
> g_units
= { "s", "ms", "us", "ns", "ps", "fs", "as", "zs" };
45 ctx
= (fstReaderContext
*)fstReaderOpen(filename
.c_str());
47 log_error("Error opening '%s' as FST file\n", filename
.c_str());
48 int scale
= (int)fstReaderGetTimescale(ctx
);
49 timescale
= pow(10.0, scale
);
56 if ((scale
% 3) == 0) {
60 zeros
= 3 - (-scale
% 3);
61 unit
= (-scale
/ 3) + 1;
64 for (int i
=0;i
<zeros
; i
++) timescale_str
+= "0";
65 timescale_str
+= g_units
[unit
];
73 if (!tmp_file
.empty())
74 remove(tmp_file
.c_str());
77 uint64_t FstData::getStartTime() { return fstReaderGetStartTime(ctx
); }
79 uint64_t FstData::getEndTime() { return fstReaderGetEndTime(ctx
); }
81 fstHandle
FstData::getHandle(std::string name
) {
82 if (name_to_handle
.find(name
) != name_to_handle
.end())
83 return name_to_handle
[name
];
88 static std::string
remove_spaces(std::string str
)
90 str
.erase(std::remove(str
.begin(), str
.end(), ' '), str
.end());
94 void FstData::extractVarNames()
99 while ((h
= fstReaderIterateHier(ctx
))) {
103 std::string fst_scope_name
= fstReaderPushScope(ctx
, h
->u
.scope
.name
, (void *)(snum
));
104 scopes
.push_back(fst_scope_name
);
107 case FST_HT_UPSCOPE
: {
108 fstReaderPopScope(ctx
);
109 snum
= fstReaderGetCurrentScopeLen(ctx
) ? (intptr_t)fstReaderGetCurrentScopeUserInfo(ctx
) : 0;
114 var
.id
= h
->u
.var
.handle
;
115 var
.is_alias
= h
->u
.var
.is_alias
;
116 var
.name
= remove_spaces(h
->u
.var
.name
);
117 var
.scope
= scopes
.back();
118 var
.width
= h
->u
.var
.length
;
121 handle_to_var
[h
->u
.var
.handle
] = var
;
122 std::string clean_name
;
123 for(size_t i
=0;i
<strlen(h
->u
.var
.name
);i
++)
125 char c
= h
->u
.var
.name
[i
];
129 if (clean_name
[0]=='\\')
130 clean_name
= clean_name
.substr(1);
132 name_to_handle
[var
.scope
+"."+clean_name
] = h
->u
.var
.handle
;
140 static void reconstruct_clb_varlen_attimes(void *user_data
, uint64_t pnt_time
, fstHandle pnt_facidx
, const unsigned char *pnt_value
, uint32_t plen
)
142 FstData
*ptr
= (FstData
*)user_data
;
143 ptr
->reconstruct_callback_attimes(pnt_time
, pnt_facidx
, pnt_value
, plen
);
146 static void reconstruct_clb_attimes(void *user_data
, uint64_t pnt_time
, fstHandle pnt_facidx
, const unsigned char *pnt_value
)
148 FstData
*ptr
= (FstData
*)user_data
;
149 uint32_t plen
= (pnt_value
) ? strlen((const char *)pnt_value
) : 0;
150 ptr
->reconstruct_callback_attimes(pnt_time
, pnt_facidx
, pnt_value
, plen
);
153 void FstData::reconstruct_callback_attimes(uint64_t pnt_time
, fstHandle pnt_facidx
, const unsigned char *pnt_value
, uint32_t /* plen */)
155 if (pnt_time
> end_time
) return;
156 // if we are past the timestamp
157 bool is_clock
= false;
159 for(auto &s
: clk_signals
) {
167 if (pnt_time
> past_time
) {
168 past_data
= last_data
;
169 past_time
= pnt_time
;
172 if (pnt_time
> last_time
) {
175 last_time
= pnt_time
;
178 std::string val
= std::string((const char *)pnt_value
);
179 std::string prev
= past_data
[pnt_facidx
];
180 if ((prev
!="1" && val
=="1") || (prev
!="0" && val
=="0")) {
182 last_time
= pnt_time
;
187 // always update last_data
188 last_data
[pnt_facidx
] = std::string((const char *)pnt_value
);
191 void FstData::reconstructAllAtTimes(std::vector
<fstHandle
> &signal
, uint64_t start
, uint64_t end
, CallbackFunction cb
)
193 clk_signals
= signal
;
198 last_time
= start_time
;
200 past_time
= start_time
;
201 all_samples
= clk_signals
.empty();
203 fstReaderSetUnlimitedTimeRange(ctx
);
204 fstReaderSetFacProcessMaskAll(ctx
);
205 fstReaderIterBlocks2(ctx
, reconstruct_clb_attimes
, reconstruct_clb_varlen_attimes
, this, nullptr);
206 past_data
= last_data
;
208 if (last_time
!=end_time
)
212 std::string
FstData::valueOf(fstHandle signal
)
214 if (past_data
.find(signal
) == past_data
.end())
215 log_error("Signal id %d not found\n", (int)signal
);
216 return past_data
[signal
];