mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-23 09:05:32 +00:00
Merge branch 'YosysHQ:master' into master
This commit is contained in:
commit
8c731658c2
40 changed files with 868 additions and 559 deletions
144
kernel/fmt.cc
144
kernel/fmt.cc
|
@ -110,9 +110,9 @@ void Fmt::parse_rtlil(const RTLIL::Cell *cell) {
|
|||
} else if (fmt[i] == 'c') {
|
||||
part.type = FmtPart::CHARACTER;
|
||||
} else if (fmt[i] == 't') {
|
||||
part.type = FmtPart::TIME;
|
||||
part.type = FmtPart::VLOG_TIME;
|
||||
} else if (fmt[i] == 'r') {
|
||||
part.type = FmtPart::TIME;
|
||||
part.type = FmtPart::VLOG_TIME;
|
||||
part.realtime = true;
|
||||
} else {
|
||||
log_assert(false && "Unexpected character in format substitution");
|
||||
|
@ -172,7 +172,7 @@ void Fmt::emit_rtlil(RTLIL::Cell *cell) const {
|
|||
}
|
||||
break;
|
||||
|
||||
case FmtPart::TIME:
|
||||
case FmtPart::VLOG_TIME:
|
||||
log_assert(part.sig.size() == 0);
|
||||
YS_FALLTHROUGH
|
||||
case FmtPart::CHARACTER:
|
||||
|
@ -205,7 +205,7 @@ 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) {
|
||||
} else if (part.type == FmtPart::VLOG_TIME) {
|
||||
if (part.realtime)
|
||||
fmt += 'r';
|
||||
else
|
||||
|
@ -328,7 +328,7 @@ void Fmt::parse_verilog(const std::vector<VerilogFmtArg> &args, bool sformat_lik
|
|||
|
||||
case VerilogFmtArg::TIME: {
|
||||
FmtPart part = {};
|
||||
part.type = FmtPart::TIME;
|
||||
part.type = FmtPart::VLOG_TIME;
|
||||
part.realtime = arg->realtime;
|
||||
part.padding = ' ';
|
||||
part.width = 20;
|
||||
|
@ -419,7 +419,7 @@ void Fmt::parse_verilog(const std::vector<VerilogFmtArg> &args, bool sformat_lik
|
|||
part.padding = ' ';
|
||||
} else if (fmt[i] == 't' || fmt[i] == 'T') {
|
||||
if (arg->type == VerilogFmtArg::TIME) {
|
||||
part.type = FmtPart::TIME;
|
||||
part.type = FmtPart::VLOG_TIME;
|
||||
part.realtime = arg->realtime;
|
||||
if (!has_width && !has_leading_zero)
|
||||
part.width = 20;
|
||||
|
@ -541,7 +541,7 @@ std::vector<VerilogFmtArg> Fmt::emit_verilog() const
|
|||
break;
|
||||
}
|
||||
|
||||
case FmtPart::TIME: {
|
||||
case FmtPart::VLOG_TIME: {
|
||||
VerilogFmtArg arg;
|
||||
arg.type = VerilogFmtArg::TIME;
|
||||
if (part.realtime)
|
||||
|
@ -569,82 +569,60 @@ std::vector<VerilogFmtArg> Fmt::emit_verilog() const
|
|||
return args;
|
||||
}
|
||||
|
||||
void Fmt::emit_cxxrtl(std::ostream &f, std::function<void(const RTLIL::SigSpec &)> emit_sig) const
|
||||
std::string escape_cxx_string(const std::string &input)
|
||||
{
|
||||
for (auto &part : parts) {
|
||||
switch (part.type) {
|
||||
case FmtPart::STRING:
|
||||
f << " << \"";
|
||||
for (char c : part.str) {
|
||||
switch (c) {
|
||||
case '\\':
|
||||
YS_FALLTHROUGH
|
||||
case '"':
|
||||
f << '\\' << c;
|
||||
break;
|
||||
case '\a':
|
||||
f << "\\a";
|
||||
break;
|
||||
case '\b':
|
||||
f << "\\b";
|
||||
break;
|
||||
case '\f':
|
||||
f << "\\f";
|
||||
break;
|
||||
case '\n':
|
||||
f << "\\n";
|
||||
break;
|
||||
case '\r':
|
||||
f << "\\r";
|
||||
break;
|
||||
case '\t':
|
||||
f << "\\t";
|
||||
break;
|
||||
case '\v':
|
||||
f << "\\v";
|
||||
break;
|
||||
default:
|
||||
f << c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
f << '"';
|
||||
break;
|
||||
|
||||
case FmtPart::INTEGER:
|
||||
case FmtPart::CHARACTER: {
|
||||
f << " << value_formatted<" << part.sig.size() << ">(";
|
||||
emit_sig(part.sig);
|
||||
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.plus;
|
||||
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.plus;
|
||||
f << ')';
|
||||
break;
|
||||
}
|
||||
|
||||
default: log_abort();
|
||||
std::string output = "\"";
|
||||
for (auto c : input) {
|
||||
if (::isprint(c)) {
|
||||
if (c == '\\')
|
||||
output.push_back('\\');
|
||||
output.push_back(c);
|
||||
} else {
|
||||
char l = c & 0xf, h = (c >> 4) & 0xf;
|
||||
output.append("\\x");
|
||||
output.push_back((h < 10 ? '0' + h : 'a' + h - 10));
|
||||
output.push_back((l < 10 ? '0' + l : 'a' + l - 10));
|
||||
}
|
||||
}
|
||||
output.push_back('"');
|
||||
if (output.find('\0') != std::string::npos) {
|
||||
output.insert(0, "std::string {");
|
||||
output.append(stringf(", %zu}", input.size()));
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
void Fmt::emit_cxxrtl(std::ostream &os, std::string indent, std::function<void(const RTLIL::SigSpec &)> emit_sig, const std::string &context) const
|
||||
{
|
||||
os << indent << "std::string buf;\n";
|
||||
for (auto &part : parts) {
|
||||
os << indent << "buf += fmt_part { ";
|
||||
os << "fmt_part::";
|
||||
switch (part.type) {
|
||||
case FmtPart::STRING: os << "STRING"; break;
|
||||
case FmtPart::INTEGER: os << "INTEGER"; break;
|
||||
case FmtPart::CHARACTER: os << "CHARACTER"; break;
|
||||
case FmtPart::VLOG_TIME: os << "VLOG_TIME"; break;
|
||||
}
|
||||
os << ", ";
|
||||
os << escape_cxx_string(part.str) << ", ";
|
||||
os << "fmt_part::";
|
||||
switch (part.justify) {
|
||||
case FmtPart::LEFT: os << "LEFT"; break;
|
||||
case FmtPart::RIGHT: os << "RIGHT"; break;
|
||||
}
|
||||
os << ", ";
|
||||
os << "(char)" << (int)part.padding << ", ";
|
||||
os << part.width << ", ";
|
||||
os << part.base << ", ";
|
||||
os << part.signed_ << ", ";
|
||||
os << part.plus << ", ";
|
||||
os << part.realtime;
|
||||
os << " }.render(";
|
||||
emit_sig(part.sig);
|
||||
os << ", " << context << ");\n";
|
||||
}
|
||||
os << indent << "return buf;\n";
|
||||
}
|
||||
|
||||
std::string Fmt::render() const
|
||||
|
@ -658,8 +636,8 @@ std::string Fmt::render() const
|
|||
break;
|
||||
|
||||
case FmtPart::INTEGER:
|
||||
case FmtPart::TIME:
|
||||
case FmtPart::CHARACTER: {
|
||||
case FmtPart::CHARACTER:
|
||||
case FmtPart::VLOG_TIME: {
|
||||
std::string buf;
|
||||
if (part.type == FmtPart::INTEGER) {
|
||||
RTLIL::Const value = part.sig.as_const();
|
||||
|
@ -742,7 +720,7 @@ std::string Fmt::render() const
|
|||
} else log_abort();
|
||||
} else if (part.type == FmtPart::CHARACTER) {
|
||||
buf = part.sig.as_const().decode_string();
|
||||
} else if (part.type == FmtPart::TIME) {
|
||||
} else if (part.type == FmtPart::VLOG_TIME) {
|
||||
// We only render() during initial, so time is always zero.
|
||||
buf = "0";
|
||||
}
|
||||
|
|
11
kernel/fmt.h
11
kernel/fmt.h
|
@ -50,12 +50,13 @@ struct VerilogFmtArg {
|
|||
|
||||
// RTLIL format part, such as the substitutions in:
|
||||
// "foo {4:> 4du} bar {2:<01hs}"
|
||||
// Must be kept in sync with `struct fmt_part` in backends/cxxrtl/runtime/cxxrtl/cxxrtl.h!
|
||||
struct FmtPart {
|
||||
enum {
|
||||
STRING = 0,
|
||||
INTEGER = 1,
|
||||
CHARACTER = 2,
|
||||
TIME = 3,
|
||||
VLOG_TIME = 3,
|
||||
} type;
|
||||
|
||||
// STRING type
|
||||
|
@ -64,20 +65,20 @@ struct FmtPart {
|
|||
// INTEGER/CHARACTER types
|
||||
RTLIL::SigSpec sig;
|
||||
|
||||
// INTEGER/CHARACTER/TIME types
|
||||
// INTEGER/CHARACTER/VLOG_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 plus = false;
|
||||
|
||||
// TIME type
|
||||
// VLOG_TIME type
|
||||
bool realtime = false;
|
||||
};
|
||||
|
||||
|
@ -93,7 +94,7 @@ public:
|
|||
void parse_verilog(const std::vector<VerilogFmtArg> &args, bool sformat_like, int default_base, RTLIL::IdString task_name, RTLIL::IdString module_name);
|
||||
std::vector<VerilogFmtArg> emit_verilog() const;
|
||||
|
||||
void emit_cxxrtl(std::ostream &f, std::function<void(const RTLIL::SigSpec &)> emit_sig) const;
|
||||
void emit_cxxrtl(std::ostream &os, std::string indent, std::function<void(const RTLIL::SigSpec &)> emit_sig, const std::string &context) const;
|
||||
|
||||
std::string render() const;
|
||||
|
||||
|
|
|
@ -2157,17 +2157,10 @@ void RTLIL::Module::remove(const pool<RTLIL::Wire*> &wires)
|
|||
}
|
||||
|
||||
void operator()(RTLIL::SigSpec &lhs, RTLIL::SigSpec &rhs) {
|
||||
log_assert(GetSize(lhs) == GetSize(rhs));
|
||||
lhs.unpack();
|
||||
rhs.unpack();
|
||||
for (int i = 0; i < GetSize(lhs); i++) {
|
||||
RTLIL::SigBit &lhs_bit = lhs.bits_[i];
|
||||
RTLIL::SigBit &rhs_bit = rhs.bits_[i];
|
||||
if ((lhs_bit.wire != nullptr && wires_p->count(lhs_bit.wire)) || (rhs_bit.wire != nullptr && wires_p->count(rhs_bit.wire))) {
|
||||
lhs_bit = State::Sx;
|
||||
rhs_bit = State::Sx;
|
||||
}
|
||||
}
|
||||
// If a deleted wire occurs on the lhs or rhs we just remove that part
|
||||
// of the assignment
|
||||
lhs.remove2(*wires_p, &rhs);
|
||||
rhs.remove2(*wires_p, &lhs);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -3693,6 +3686,9 @@ RTLIL::SigChunk::SigChunk(const RTLIL::SigBit &bit)
|
|||
|
||||
RTLIL::SigChunk RTLIL::SigChunk::extract(int offset, int length) const
|
||||
{
|
||||
log_assert(offset >= 0);
|
||||
log_assert(length >= 0);
|
||||
log_assert(offset + length <= width);
|
||||
RTLIL::SigChunk ret;
|
||||
if (wire) {
|
||||
ret.wire = wire;
|
||||
|
@ -4238,6 +4234,34 @@ void RTLIL::SigSpec::remove2(const std::set<RTLIL::SigBit> &pattern, RTLIL::SigS
|
|||
check();
|
||||
}
|
||||
|
||||
void RTLIL::SigSpec::remove2(const pool<RTLIL::Wire*> &pattern, RTLIL::SigSpec *other)
|
||||
{
|
||||
if (other)
|
||||
cover("kernel.rtlil.sigspec.remove_other");
|
||||
else
|
||||
cover("kernel.rtlil.sigspec.remove");
|
||||
|
||||
unpack();
|
||||
|
||||
if (other != NULL) {
|
||||
log_assert(width_ == other->width_);
|
||||
other->unpack();
|
||||
}
|
||||
|
||||
for (int i = GetSize(bits_) - 1; i >= 0; i--) {
|
||||
if (bits_[i].wire != NULL && pattern.count(bits_[i].wire)) {
|
||||
bits_.erase(bits_.begin() + i);
|
||||
width_--;
|
||||
if (other != NULL) {
|
||||
other->bits_.erase(other->bits_.begin() + i);
|
||||
other->width_--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
check();
|
||||
}
|
||||
|
||||
RTLIL::SigSpec RTLIL::SigSpec::extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other) const
|
||||
{
|
||||
if (other)
|
||||
|
@ -4377,6 +4401,9 @@ void RTLIL::SigSpec::remove(int offset, int length)
|
|||
|
||||
RTLIL::SigSpec RTLIL::SigSpec::extract(int offset, int length) const
|
||||
{
|
||||
log_assert(offset >= 0);
|
||||
log_assert(length >= 0);
|
||||
log_assert(offset + length <= width_);
|
||||
unpack();
|
||||
cover("kernel.rtlil.sigspec.extract_pos");
|
||||
return std::vector<RTLIL::SigBit>(bits_.begin() + offset, bits_.begin() + offset + length);
|
||||
|
|
|
@ -924,6 +924,7 @@ public:
|
|||
void remove(const pool<RTLIL::SigBit> &pattern, RTLIL::SigSpec *other) const;
|
||||
void remove2(const pool<RTLIL::SigBit> &pattern, RTLIL::SigSpec *other);
|
||||
void remove2(const std::set<RTLIL::SigBit> &pattern, RTLIL::SigSpec *other);
|
||||
void remove2(const pool<RTLIL::Wire*> &pattern, RTLIL::SigSpec *other);
|
||||
|
||||
void remove(int offset, int length = 1);
|
||||
void remove_const();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue