mirror of https://github.com/YosysHQ/yosys.git
cxxrtl: always lazily format print messages.
This is mostly useful for collecting coverage for the future `$check` cell, where, depending on the flavor, formatting a message may not be wanted even for a failed assertion.
This commit is contained in:
parent
b74d33d1b8
commit
fc5ff7a265
|
@ -1072,21 +1072,43 @@ struct CxxrtlWorker {
|
||||||
dump_sigspec_rhs(cell->getPort(ID::EN));
|
dump_sigspec_rhs(cell->getPort(ID::EN));
|
||||||
f << " == value<1>{1u}) {\n";
|
f << " == value<1>{1u}) {\n";
|
||||||
inc_indent();
|
inc_indent();
|
||||||
f << indent << "auto formatter = [&](struct performer *performer) {\n";
|
dict<std::string, RTLIL::SigSpec> fmt_args;
|
||||||
|
f << indent << "struct : public lazy_fmt {\n";
|
||||||
inc_indent();
|
inc_indent();
|
||||||
fmt.emit_cxxrtl(f, indent, [this](const RTLIL::SigSpec &sig) { dump_sigspec_rhs(sig); }, "performer");
|
f << indent << "std::string operator() () const override {\n";
|
||||||
|
inc_indent();
|
||||||
|
fmt.emit_cxxrtl(f, indent, [&](const RTLIL::SigSpec &sig) {
|
||||||
|
if (sig.size() == 0)
|
||||||
|
f << "value<0>()";
|
||||||
|
else {
|
||||||
|
std::string arg_name = "arg" + std::to_string(fmt_args.size());
|
||||||
|
fmt_args[arg_name] = sig;
|
||||||
|
f << arg_name;
|
||||||
|
}
|
||||||
|
}, "performer");
|
||||||
|
dec_indent();
|
||||||
|
f << indent << "}\n";
|
||||||
|
f << indent << "struct performer *performer;\n";
|
||||||
|
for (auto arg : fmt_args)
|
||||||
|
f << indent << "value<" << arg.second.size() << "> " << arg.first << ";\n";
|
||||||
dec_indent();
|
dec_indent();
|
||||||
f << indent << "};\n";
|
f << indent << "} formatter;\n";
|
||||||
|
f << indent << "formatter.performer = performer;\n";
|
||||||
|
for (auto arg : fmt_args) {
|
||||||
|
f << indent << "formatter." << arg.first << " = ";
|
||||||
|
dump_sigspec_rhs(arg.second);
|
||||||
|
f << ";\n";
|
||||||
|
}
|
||||||
f << indent << "if (performer) {\n";
|
f << indent << "if (performer) {\n";
|
||||||
inc_indent();
|
inc_indent();
|
||||||
f << indent << "static const metadata_map attributes = ";
|
f << indent << "static const metadata_map attributes = ";
|
||||||
dump_metadata_map(cell->attributes);
|
dump_metadata_map(cell->attributes);
|
||||||
f << ";\n";
|
f << ";\n";
|
||||||
f << indent << "performer->on_print(formatter(performer), attributes);\n";
|
f << indent << "performer->on_print(formatter, attributes);\n";
|
||||||
dec_indent();
|
dec_indent();
|
||||||
f << indent << "} else {\n";
|
f << indent << "} else {\n";
|
||||||
inc_indent();
|
inc_indent();
|
||||||
f << indent << print_output << " << formatter(performer);\n";
|
f << indent << print_output << " << formatter();\n";
|
||||||
dec_indent();
|
dec_indent();
|
||||||
f << indent << "}\n";
|
f << indent << "}\n";
|
||||||
dec_indent();
|
dec_indent();
|
||||||
|
|
|
@ -945,16 +945,25 @@ struct metadata {
|
||||||
|
|
||||||
typedef std::map<std::string, metadata> metadata_map;
|
typedef std::map<std::string, metadata> metadata_map;
|
||||||
|
|
||||||
|
struct performer;
|
||||||
|
|
||||||
|
// An object that allows formatting a string lazily.
|
||||||
|
struct lazy_fmt {
|
||||||
|
virtual std::string operator() () const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
// An object that can be passed to a `eval()` method in order to act on side effects.
|
// An object that can be passed to a `eval()` method in order to act on side effects.
|
||||||
struct performer {
|
struct performer {
|
||||||
// Called to evaluate a Verilog `$time` expression.
|
// Called by generated formatting code to evaluate a Verilog `$time` expression.
|
||||||
virtual int64_t vlog_time() const { return 0; }
|
virtual int64_t vlog_time() const { return 0; }
|
||||||
|
|
||||||
// Called to evaluate a Verilog `$realtime` expression.
|
// Called by generated formatting code to evaluate a Verilog `$realtime` expression.
|
||||||
virtual double vlog_realtime() const { return vlog_time(); }
|
virtual double vlog_realtime() const { return vlog_time(); }
|
||||||
|
|
||||||
// Called when a `$print` cell is triggered.
|
// Called when a `$print` cell is triggered.
|
||||||
virtual void on_print(const std::string &output, const metadata_map &attributes) { std::cout << output; }
|
virtual void on_print(const lazy_fmt &formatter, const metadata_map &attributes) {
|
||||||
|
std::cout << formatter();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// An object that can be passed to a `commit()` method in order to produce a replay log of every state change in
|
// An object that can be passed to a `commit()` method in order to produce a replay log of every state change in
|
||||||
|
|
|
@ -4,7 +4,7 @@ int main()
|
||||||
{
|
{
|
||||||
struct : public performer {
|
struct : public performer {
|
||||||
int64_t vlog_time() const override { return 1; }
|
int64_t vlog_time() const override { return 1; }
|
||||||
void on_print(const std::string &output, const cxxrtl::metadata_map &) override { std::cerr << output; }
|
void on_print(const lazy_fmt &output, const cxxrtl::metadata_map &) override { std::cerr << output(); }
|
||||||
} performer;
|
} performer;
|
||||||
|
|
||||||
cxxrtl_design::p_always__full uut;
|
cxxrtl_design::p_always__full uut;
|
||||||
|
|
Loading…
Reference in New Issue