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()
97 std::string fst_scope_name
;
99 while ((h
= fstReaderIterateHier(ctx
))) {
102 fst_scope_name
= fstReaderPushScope(ctx
, h
->u
.scope
.name
, NULL
);
105 case FST_HT_UPSCOPE
: {
106 fst_scope_name
= fstReaderPopScope(ctx
);
111 var
.id
= h
->u
.var
.handle
;
112 var
.is_alias
= h
->u
.var
.is_alias
;
113 var
.is_reg
= (fstVarType
)h
->u
.var
.typ
== FST_VT_VCD_REG
;
114 var
.name
= remove_spaces(h
->u
.var
.name
);
115 var
.scope
= fst_scope_name
;
116 var
.width
= h
->u
.var
.length
;
119 handle_to_var
[h
->u
.var
.handle
] = var
;
120 std::string clean_name
;
121 for(size_t i
=0;i
<strlen(h
->u
.var
.name
);i
++)
123 char c
= h
->u
.var
.name
[i
];
127 if (clean_name
[0]=='\\')
128 clean_name
= clean_name
.substr(1);
130 name_to_handle
[var
.scope
+"."+clean_name
] = h
->u
.var
.handle
;
138 static void reconstruct_clb_varlen_attimes(void *user_data
, uint64_t pnt_time
, fstHandle pnt_facidx
, const unsigned char *pnt_value
, uint32_t plen
)
140 FstData
*ptr
= (FstData
*)user_data
;
141 ptr
->reconstruct_callback_attimes(pnt_time
, pnt_facidx
, pnt_value
, plen
);
144 static void reconstruct_clb_attimes(void *user_data
, uint64_t pnt_time
, fstHandle pnt_facidx
, const unsigned char *pnt_value
)
146 FstData
*ptr
= (FstData
*)user_data
;
147 uint32_t plen
= (pnt_value
) ? strlen((const char *)pnt_value
) : 0;
148 ptr
->reconstruct_callback_attimes(pnt_time
, pnt_facidx
, pnt_value
, plen
);
151 void FstData::reconstruct_callback_attimes(uint64_t pnt_time
, fstHandle pnt_facidx
, const unsigned char *pnt_value
, uint32_t /* plen */)
153 if (pnt_time
> end_time
) return;
154 // if we are past the timestamp
155 bool is_clock
= false;
157 for(auto &s
: clk_signals
) {
165 if (pnt_time
> past_time
) {
166 past_data
= last_data
;
167 past_time
= pnt_time
;
170 if (pnt_time
> last_time
) {
173 last_time
= pnt_time
;
176 std::string val
= std::string((const char *)pnt_value
);
177 std::string prev
= past_data
[pnt_facidx
];
178 if ((prev
!="1" && val
=="1") || (prev
!="0" && val
=="0")) {
180 last_time
= pnt_time
;
185 // always update last_data
186 last_data
[pnt_facidx
] = std::string((const char *)pnt_value
);
189 void FstData::reconstructAllAtTimes(std::vector
<fstHandle
> &signal
, uint64_t start
, uint64_t end
, CallbackFunction cb
)
191 clk_signals
= signal
;
196 last_time
= start_time
;
198 past_time
= start_time
;
199 all_samples
= clk_signals
.empty();
201 fstReaderSetUnlimitedTimeRange(ctx
);
202 fstReaderSetFacProcessMaskAll(ctx
);
203 fstReaderIterBlocks2(ctx
, reconstruct_clb_attimes
, reconstruct_clb_varlen_attimes
, this, nullptr);
204 past_data
= last_data
;
206 if (last_time
!=end_time
)
210 std::string
FstData::valueOf(fstHandle signal
)
212 if (past_data
.find(signal
) == past_data
.end())
213 log_error("Signal id %d not found\n", (int)signal
);
214 return past_data
[signal
];