mirror of https://github.com/YosysHQ/yosys.git
fmt: %t/$time support
This commit is contained in:
parent
52dc397a50
commit
c382d7d3ac
|
@ -1330,7 +1330,10 @@ struct module {
|
|||
virtual bool eval() = 0;
|
||||
virtual bool commit() = 0;
|
||||
|
||||
unsigned int steps = 0;
|
||||
|
||||
size_t step() {
|
||||
++steps;
|
||||
size_t deltas = 0;
|
||||
bool converged = false;
|
||||
do {
|
||||
|
|
|
@ -1797,6 +1797,12 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
|
|||
dump_sigspec(f, arg.sig);
|
||||
f << ")";
|
||||
break;
|
||||
case VerilogFmtArg::TIME:
|
||||
if (arg.realtime)
|
||||
f << "$realtime";
|
||||
else
|
||||
f << "$time";
|
||||
break;
|
||||
default: log_abort();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -748,6 +748,11 @@ struct AST_INTERNAL::ProcessGenerator
|
|||
// and in case this will be used as an argument...
|
||||
arg.sig = node->bitsAsConst();
|
||||
arg.signed_ = false;
|
||||
} else if (node->type == AST_IDENTIFIER && node->str == "$time") {
|
||||
arg.type = VerilogFmtArg::TIME;
|
||||
} else if (node->type == AST_IDENTIFIER && node->str == "$realtime") {
|
||||
arg.type = VerilogFmtArg::TIME;
|
||||
arg.realtime = true;
|
||||
} else {
|
||||
arg.type = VerilogFmtArg::INTEGER;
|
||||
arg.sig = node->genRTLIL();
|
||||
|
|
|
@ -386,7 +386,7 @@ and|nand|or|nor|xor|xnor|not|buf|bufif0|bufif1|notif0|notif1 {
|
|||
supply0 { return TOK_SUPPLY0; }
|
||||
supply1 { return TOK_SUPPLY1; }
|
||||
|
||||
"$"(display[bho]?|write[bho]?|strobe|monitor|time|stop|finish|dumpfile|dumpvars|dumpon|dumpoff|dumpall) {
|
||||
"$"(display[bho]?|write[bho]?|strobe|monitor|time|realtime|stop|finish|dumpfile|dumpvars|dumpon|dumpoff|dumpall) {
|
||||
yylval->string = new std::string(yytext);
|
||||
return TOK_ID;
|
||||
}
|
||||
|
|
|
@ -51,8 +51,11 @@ void Fmt::parse_rtlil(const RTLIL::Cell *cell) {
|
|||
part = {};
|
||||
}
|
||||
|
||||
if (++i == fmt.size())
|
||||
log_assert(false && "Unexpected end in format substitution");
|
||||
|
||||
size_t arg_size = 0;
|
||||
for (++i; i < fmt.size(); i++) {
|
||||
for (; i < fmt.size(); i++) {
|
||||
if (fmt[i] >= '0' && fmt[i] <= '9') {
|
||||
arg_size *= 10;
|
||||
arg_size += fmt[i] - '0';
|
||||
|
@ -106,6 +109,11 @@ void Fmt::parse_rtlil(const RTLIL::Cell *cell) {
|
|||
part.base = 16;
|
||||
} else if (fmt[i] == 'c') {
|
||||
part.type = FmtPart::CHARACTER;
|
||||
} else if (fmt[i] == 't') {
|
||||
part.type = FmtPart::TIME;
|
||||
} else if (fmt[i] == 'r') {
|
||||
part.type = FmtPart::TIME;
|
||||
part.realtime = true;
|
||||
} else {
|
||||
log_assert(false && "Unexpected character in format substitution");
|
||||
}
|
||||
|
@ -170,6 +178,9 @@ void Fmt::emit_rtlil(RTLIL::Cell *cell) const {
|
|||
}
|
||||
break;
|
||||
|
||||
case FmtPart::TIME:
|
||||
log_assert(part.sig.size() == 0);
|
||||
YS_FALLTHROUGH
|
||||
case FmtPart::CHARACTER:
|
||||
log_assert(part.sig.size() % 8 == 0);
|
||||
YS_FALLTHROUGH
|
||||
|
@ -202,6 +213,11 @@ void Fmt::emit_rtlil(RTLIL::Cell *cell) const {
|
|||
fmt += part.signed_ ? 's' : 'u';
|
||||
} else if (part.type == FmtPart::CHARACTER) {
|
||||
fmt += 'c';
|
||||
} else if (part.type == FmtPart::TIME) {
|
||||
if (part.realtime)
|
||||
fmt += 'r';
|
||||
else
|
||||
fmt += 't';
|
||||
} else log_abort();
|
||||
fmt += '}';
|
||||
break;
|
||||
|
@ -339,6 +355,15 @@ void Fmt::parse_verilog(const std::vector<VerilogFmtArg> &args, bool sformat_lik
|
|||
part.sig.extend_u0((part.sig.size() + 7) / 8 * 8);
|
||||
// %10s and %010s not fully defined in IEEE 1800-2017 and do the same thing in iverilog
|
||||
part.padding = ' ';
|
||||
} else if (fmt[i] == 't' || fmt[i] == 'T') {
|
||||
if (arg->type == VerilogFmtArg::TIME) {
|
||||
part.type = FmtPart::TIME;
|
||||
part.realtime = arg->realtime;
|
||||
if (!has_width && !has_leading_zero)
|
||||
part.width = 20;
|
||||
} else {
|
||||
log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with format character `%c' in argument %zu, but the argument is not $time or $realtime.\n", task_name.c_str(), fmt[i], fmtarg - args.begin() + 1);
|
||||
}
|
||||
} else {
|
||||
log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with unrecognized format character `%c' in argument %zu.\n", task_name.c_str(), fmt[i], fmtarg - args.begin() + 1);
|
||||
}
|
||||
|
@ -458,6 +483,28 @@ std::vector<VerilogFmtArg> Fmt::emit_verilog() const
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case FmtPart::TIME: {
|
||||
VerilogFmtArg arg;
|
||||
arg.type = VerilogFmtArg::TIME;
|
||||
if (part.realtime)
|
||||
arg.realtime = true;
|
||||
args.push_back(arg);
|
||||
|
||||
fmt.str += '%';
|
||||
if (part.plus)
|
||||
fmt.str += '+';
|
||||
if (part.justify == FmtPart::LEFT)
|
||||
fmt.str += '-';
|
||||
log_assert(part.padding == ' ' || part.padding == '0');
|
||||
if (part.padding == '0' && part.width > 0)
|
||||
fmt.str += '0';
|
||||
fmt.str += std::to_string(part.width);
|
||||
fmt.str += 't';
|
||||
break;
|
||||
}
|
||||
|
||||
default: log_abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -522,6 +569,25 @@ void Fmt::emit_cxxrtl(std::ostream &f, std::function<void(const RTLIL::SigSpec &
|
|||
f << ')';
|
||||
break;
|
||||
}
|
||||
|
||||
case FmtPart::TIME: {
|
||||
// CXXRTL only records steps taken, so there's no difference between
|
||||
// the values taken by $time and $realtime.
|
||||
f << " << value_formatted<64>(";
|
||||
f << "value<64>{steps}";
|
||||
f << ", " << (part.type == FmtPart::CHARACTER);
|
||||
f << ", " << (part.justify == FmtPart::LEFT);
|
||||
f << ", (char)" << (int)part.padding;
|
||||
f << ", " << part.width;
|
||||
f << ", " << part.base;
|
||||
f << ", " << part.signed_;
|
||||
f << ", " << part.lzero;
|
||||
f << ", " << part.plus;
|
||||
f << ')';
|
||||
break;
|
||||
}
|
||||
|
||||
default: log_abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -636,6 +702,12 @@ std::string Fmt::render() const
|
|||
str += std::string(part.width - buf.size(), part.padding);
|
||||
break;
|
||||
}
|
||||
|
||||
case FmtPart::TIME: {
|
||||
// We only render() during initial, so time is always zero.
|
||||
str += "0";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
13
kernel/fmt.h
13
kernel/fmt.h
|
@ -30,6 +30,7 @@ struct VerilogFmtArg {
|
|||
enum {
|
||||
STRING = 0,
|
||||
INTEGER = 1,
|
||||
TIME = 2,
|
||||
} type;
|
||||
|
||||
// All types
|
||||
|
@ -42,6 +43,9 @@ struct VerilogFmtArg {
|
|||
// INTEGER type
|
||||
RTLIL::SigSpec sig;
|
||||
bool signed_ = false;
|
||||
|
||||
// TIME type
|
||||
bool realtime = false;
|
||||
};
|
||||
|
||||
// RTLIL format part, such as the substitutions in:
|
||||
|
@ -51,24 +55,31 @@ struct FmtPart {
|
|||
STRING = 0,
|
||||
INTEGER = 1,
|
||||
CHARACTER = 2,
|
||||
TIME = 3,
|
||||
} type;
|
||||
|
||||
// STRING type
|
||||
std::string str;
|
||||
|
||||
// INTEGER/CHARACTER type
|
||||
// INTEGER/CHARACTER types
|
||||
RTLIL::SigSpec sig;
|
||||
|
||||
// INTEGER/CHARACTER/TIME types
|
||||
enum {
|
||||
RIGHT = 0,
|
||||
LEFT = 1,
|
||||
} justify = RIGHT;
|
||||
char padding = '\0';
|
||||
size_t width = 0;
|
||||
|
||||
// INTEGER type
|
||||
unsigned base = 10;
|
||||
bool signed_ = false;
|
||||
bool lzero = false;
|
||||
bool plus = false;
|
||||
|
||||
// TIME type
|
||||
bool realtime = false;
|
||||
};
|
||||
|
||||
struct Fmt {
|
||||
|
|
|
@ -202,34 +202,44 @@ module always_full(input clk, output reg fin);
|
|||
if (counter == 176) $display(":%020b:", 16'shaaaa);
|
||||
if (counter == 177) $display(":%-020b:", 16'shaaaa);
|
||||
|
||||
if (counter == 178) $display("===> %%s");
|
||||
if (counter == 179) $display(":%10s:", "foo");
|
||||
if (counter == 180) $display(":%010s:", "foo");
|
||||
if (counter == 181) $display(":%-10s:", "foo");
|
||||
if (counter == 182) $display(":%-010s:", "foo");
|
||||
if (counter == 178) $display("==> time %%t");
|
||||
if (counter == 179) $display(":%t:", $time);
|
||||
if (counter == 180) $display(":%-t:", $time);
|
||||
if (counter == 181) $display(":%0t:", $time);
|
||||
if (counter == 182) $display(":%-0t:", $time);
|
||||
if (counter == 183) $display(":%10t:", $time);
|
||||
if (counter == 184) $display(":%-10t:", $time);
|
||||
if (counter == 185) $display(":%015t:", $time);
|
||||
if (counter == 186) $display(":%-015t:", $time);
|
||||
|
||||
if (counter == 183) $display("===> %%c");
|
||||
if (counter == 184) $display(":%10c:", "foo");
|
||||
if (counter == 185) $display(":%010c:", "foo");
|
||||
if (counter == 186) $display(":%-10c:", "foo");
|
||||
if (counter == 187) $display(":%-010c:", "foo");
|
||||
if (counter == 187) $display("===> %%s");
|
||||
if (counter == 188) $display(":%10s:", "foo");
|
||||
if (counter == 189) $display(":%010s:", "foo");
|
||||
if (counter == 190) $display(":%-10s:", "foo");
|
||||
if (counter == 191) $display(":%-010s:", "foo");
|
||||
|
||||
if (counter == 188) $display("==> aliases");
|
||||
if (counter == 189) $display(":%x:", 16'shaa);
|
||||
if (counter == 190) $display(":%X:", 16'shaa);
|
||||
if (counter == 191) $display(":%H:", 16'shaa);
|
||||
if (counter == 192) $display(":%O:", 16'shaa);
|
||||
if (counter == 193) $display(":%B:", 16'shaa);
|
||||
if (counter == 192) $display("===> %%c");
|
||||
if (counter == 193) $display(":%10c:", "foo");
|
||||
if (counter == 194) $display(":%010c:", "foo");
|
||||
if (counter == 195) $display(":%-10c:", "foo");
|
||||
if (counter == 196) $display(":%-010c:", "foo");
|
||||
|
||||
if (counter == 194) $display("==> default base");
|
||||
if (counter == 195) $displayh(16'haa);
|
||||
if (counter == 196) $displayo(16'haa);
|
||||
if (counter == 197) $displayb(16'haa);
|
||||
if (counter == 197) $display("==> aliases");
|
||||
if (counter == 198) $display(":%x:", 16'shaa);
|
||||
if (counter == 199) $display(":%X:", 16'shaa);
|
||||
if (counter == 200) $display(":%H:", 16'shaa);
|
||||
if (counter == 201) $display(":%O:", 16'shaa);
|
||||
if (counter == 202) $display(":%B:", 16'shaa);
|
||||
|
||||
if (counter == 198) $display("==> write/format");
|
||||
if (counter == 199) $display("%d", 1, "%d", 1);
|
||||
if (counter == 203) $display("==> default base");
|
||||
if (counter == 204) $displayh(16'haa);
|
||||
if (counter == 205) $displayo(16'haa);
|
||||
if (counter == 206) $displayb(16'haa);
|
||||
|
||||
if (counter == 200) begin
|
||||
if (counter == 207) $display("==> write/format");
|
||||
if (counter == 208) $display("%d", 1, "%d", 1);
|
||||
|
||||
if (counter == 209) begin
|
||||
$display("<<<END>>>");
|
||||
fin <= 1;
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue