33class ObjTreeComparison
36 enum class Op : std::uint8_t { LT, LTE, GT, GTE, EQ, NEQ, CHANGED, INVALID };
37 enum class valType : std::uint8_t { OBJ, CONST, UNKNOWN };
38 static Op getOperationFromString(
const std::string& op)
40 if ( op ==
"<" )
return Op::LT;
41 if ( op ==
"<=" )
return Op::LTE;
42 if ( op ==
">" )
return Op::GT;
43 if ( op ==
">=" )
return Op::GTE;
44 if ( op ==
"==" )
return Op::EQ;
45 if ( op ==
"!=" )
return Op::NEQ;
46 if ( op ==
"changed" )
return Op::CHANGED;
50 static std::string getStringFromOp(Op op)
77 std::vector<std::tuple<std::deque<std::string>, valType, std::unique_ptr<ObjTreeCont>>> objectsToCompare;
78 std::vector<Op> operators;
80 void print(std::stringstream& s,
unsigned startIdx,
unsigned stopIdx)
const
82 if ( objectsToCompare.empty() || operators.empty() ) {
85 if ( objectsToCompare.size() < startIdx || objectsToCompare.size() < stopIdx ) {
88 for (
size_t i = startIdx; i < stopIdx; i++ ) {
89 if ( std::get<valType>(objectsToCompare[i]) == valType::UNKNOWN ) {
92 if ( std::get<valType>(objectsToCompare[i]) == valType::CONST ) {
93 s << std::get<std::deque<std::string>>(objectsToCompare[i]).back();
98 for (
size_t j = 0; j < std::get<std::deque<std::string>>(objectsToCompare[i]).size(); j++ ) {
100 s << std::get<std::deque<std::string>>(objectsToCompare[i])[j];
103 if ( (i % 2 == 0) && (i / 2 < operators.size()) ) {
104 s <<
" " << getStringFromOp(operators[i / 2]);
113 ObjTreeComparison() =
default;
114 ~ObjTreeComparison() =
default;
117class ObjTreeTraceBuffer
121 ObjTreeTraceBuffer(
size_t sz,
size_t pdelay) :
125 tagBuffer_.resize(bufSize_);
126 cycleBuffer_.resize(bufSize_);
127 handlerBuffer_.resize(bufSize_);
130 virtual ~ObjTreeTraceBuffer() =
default;
132 void setBufferReset() { reset_ =
true; }
134 void resetTraceBuffer()
146 for (
size_t obj = 0; obj < objBuffers_.size(); obj++ ) {
147 auto& [bufVec, storedTriggerIdx] = objBuffers_[obj];
148 auto e = bufVec.end();
150 bufVec.erase(bufVec.begin(), e);
151 bufVec.front()->syncFromSim();
152 storedTriggerIdx = INT_MAX;
156 size_t getBufferSize() {
return bufSize_; }
158 void addObjectBuffer(std::unique_ptr<ObjTreeCont> vb)
160 std::vector<std::unique_ptr<ObjTreeCont>> newBuf;
161 newBuf.push_back(std::move(vb));
162 objBuffers_.emplace_back(std::move(newBuf), INT_MAX);
165 enum BufferState :
int {
172 const std::map<BufferState, char> state2char { { CLEAR,
'-' }, { TRIGGER,
'!' }, { POSTTRIGGER,
'+' },
175 bool sampleT(
bool trigger, uint64_t cycle,
const std::string& handler)
177 size_t start_state = state_;
178 bool invokeAction =
false;
182 if ( start_state == CLEAR ) {
188 if ( start_state == TRIGGER || start_state == POSTTRIGGER ) {
189 state_ = POSTTRIGGER;
193 if ( !(state_ == POSTTRIGGER && postCount_ >= postDelay_) ) {
195 std::cout <<
" Sample:" << handler <<
": numRecs:" << numRecs_ <<
" first:" << first_ <<
" cur:" << cur_
196 <<
" state:" << state2char.at(state_) <<
" isOverrun:" << isOverrun_
197 <<
" samplesLost:" << samplesLost_ << std::endl;
199 cycleBuffer_[cur_] = cycle;
200 handlerBuffer_[cur_] = handler;
202 triggerCycle = cycle;
208 for (
size_t obj = 0; obj < objBuffers_.size(); obj++ ) {
209 auto& [bufVec, storedTriggerIdx] = objBuffers_[obj];
210 varBuffer_ = bufVec.back().get();
211 if ( storedTriggerIdx != INT_MAX ) {
212 std::unique_ptr<ObjTreeCont> updatedBuf(varBuffer_->clone());
213 updatedBuf->syncFromSim();
214 bufVec.push_back(std::move(updatedBuf));
215 unsigned triggerIdx = trigger ? bufVec.size() - 1 : storedTriggerIdx;
216 storedTriggerIdx = triggerIdx;
219 bufVec.back()->syncFromSim();
220 storedTriggerIdx = 0;
225 if ( numRecs_ < bufSize_ ) {
226 tagBuffer_[cur_] = state_;
228 cur_ = (cur_ + 1) % bufSize_;
229 if ( cur_ == 0 ) first_ = 0;
233 if ( tagBuffer_[cur_] == TRIGGER ) {
236 tagBuffer_[cur_] = state_;
238 cur_ = (cur_ + 1) % bufSize_;
240 for (
size_t obj = 0; obj < objBuffers_.size(); obj++ ) {
241 auto& [bufVec, storedTriggerIdx] = objBuffers_[obj];
242 bufVec.erase(bufVec.begin());
243 if ( storedTriggerIdx == bufVec.size() ) {
254 if ( (state_ == TRIGGER) && (postDelay_ == 0) ) {
258 if ( state_ == POSTTRIGGER ) {
260 if ( postCount_ >= postDelay_ ) {
268 void dumpTraceBufferT(std::ostream& os = std::cout)
270 if ( numRecs_ == 0 )
return;
283 for (
int j = start;; j++ ) {
284 size_t i = j % bufSize_;
286 os <<
"buf[" << i <<
"] " << handlerBuffer_.at(i) <<
" @" << cycleBuffer_.at(i) <<
" ("
287 << state2char.at(tagBuffer_.at(i)) <<
") ";
289 std::ostringstream tmpBuf;
290 std::string objNames;
291 for (
size_t obj = 0; obj < objBuffers_.size(); obj++ ) {
293 std::get<std::vector<std::unique_ptr<ObjTreeCont>>>(objBuffers_[obj])[buf].get();
294 varBuffer_->
Dump(1, std::ios_base::dec, tmpBuf);
295 objNames.append(tmpBuf.str());
296 if ( !objNames.empty() && objNames.back() ==
'\n' ) {
298 objNames.push_back(
' ');
303 os << objNames << std::endl;
312 void dumpTriggerRecord(std::ostream& os = std::cout)
314 if ( numRecs_ == 0 ) {
315 std::cout <<
"No trace samples in current buffer" << std::endl;
318 if ( state_ != CLEAR ) {
319 std::stringstream ss;
320 std::ostringstream tmpBuf;
321 std::string objNames;
322 unsigned idxToPrint = 0;
324 ss <<
"LastTriggerRecord:@cycle" << triggerCycle <<
": SamplesLost=" << samplesLost_ <<
": ";
325 for (
size_t obj = 0; obj < objBuffers_.size(); obj++ ) {
326 unsigned triggerIdx = std::get<unsigned>(objBuffers_[obj]);
327 auto* record = &std::get<std::vector<std::unique_ptr<ObjTreeCont>>>(objBuffers_[obj]);
328 if ( triggerIdx < record->size() ) {
329 idxToPrint = triggerIdx;
332 idxToPrint = record->size() - 1;
334 ObjTreeCont* varBuffer_ = (*record)[idxToPrint].get();
336 varBuffer_->
Dump(1, std::ios_base::dec, tmpBuf);
337 objNames.append(tmpBuf.str());
338 if ( !objNames.empty() && objNames.back() ==
'\n' ) {
340 objNames.push_back(
' ');
345 ss << objNames << std::endl;
350 void printVars(std::stringstream& ss)
352 for (
size_t obj = 0; obj < objBuffers_.size(); obj++ ) {
354 std::get<std::vector<std::unique_ptr<ObjTreeCont>>>(objBuffers_[obj]).back().get();
355 ss << varBuffer_->getObjName() <<
" ";
359 void printConfig(std::stringstream& ss)
361 ss <<
"bufsize = " << bufSize_ <<
" postDelay = " << postDelay_ <<
" : ";
366 size_t bufSize_ = 64;
367 size_t postDelay_ = 8;
368 size_t postCount_ = 0;
372 bool isOverrun_ =
false;
373 size_t samplesLost_ = 0;
375 BufferState state_ = CLEAR;
377 std::vector<BufferState> tagBuffer_;
378 std::vector<std::string> handlerBuffer_;
381 std::vector<std::tuple<std::vector<std::unique_ptr<ObjTreeCont>>,
unsigned>> objBuffers_;
382 std::vector<uint64_t> cycleBuffer_;
383 uint64_t triggerCycle;