blob: 30db9738106844176c1120ef3e9658915d0e22f6 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#pragma once
// A singleton class that listens to trace entries from the simulated core (as
// an OtbnTraceListener) and compares them with the trace coming out of the
// stepped ISS process.
//
// Trace entries from the simulated core appear as a result of DPI callbacks,
// so there's no way to propagate errors when they appear. ISS trace entries
// arrive through a synchronous interface, so the checker reports any mismatch
// at that point.
//
// For example, if "RTL A" means "trace event A from RTL" and "ISS B" means
// "trace event B from ISS" then the following is a correct series of trace
// events:
//
// RTL A; ISS A; ISS B; RTL B ...
//
// None of these are valid:
//
// RTL A; RTL B; ... (*)
// ISS A; ISS B; ...
// RTL A; ISS B; ...
//
// The only way that an invalid trace is not reported is if no ISS trace events
// appear after the error. Trace (*), above, is an example of this. Another
// example would be if the last trace events were one of:
//
// ...; ISS A; RTL B
// ...; ISS A (and nothing else)
//
// To catch these cases, the ISS simulation must call the Finish() method when
// it is done (which checks there are no outstanding events missing).
#include <iosfwd>
#include <string>
#include <vector>
#include "otbn_trace_listener.h"
class OtbnTraceChecker : public OtbnTraceListener {
public:
OtbnTraceChecker();
~OtbnTraceChecker();
// Get the singleton object
static OtbnTraceChecker &get();
// Take a trace entry from the wrapped RTL. Any mismatch error is stored
// until the next call to an API function that can respond with the error.
void AcceptTraceString(const std::string &trace,
unsigned int cycle_count) override;
// Take a trace entry from the wrapped ISS.
//
// Prints an error message to stderr and returns false on mismatch.
bool OnIssTrace(const std::vector<std::string> &lines);
// Call this when the ISS simulation completes an operation (on ECALL or
// error).
//
// Prints an error message to stderr and returns false if it detects a
// mismatch.
bool Finish();
private:
// If rtl_pending_ and iss_pending_ are not both true, return true
// immediately with no other change. Otherwise, compare the two pending trace
// entries. If they match, clear them both and return true. If not, print a
// message to stderr and return false.
bool MatchPair();
class TraceEntry {
public:
static TraceEntry from_rtl_trace(const std::string &trace);
static TraceEntry from_iss_trace(const std::vector<std::string> &lines);
bool operator==(const TraceEntry &other) const;
void print(const std::string &indent, std::ostream &os) const;
void take_writes(const TraceEntry &other);
std::string hdr_;
std::vector<std::string> writes_;
};
bool rtl_pending_;
bool rtl_stall_;
TraceEntry rtl_entry_;
TraceEntry rtl_stalled_entry_;
bool iss_pending_;
TraceEntry iss_entry_;
bool done_;
bool seen_err_;
};