3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-23 09:05:32 +00:00

add generic writer class with formatting function to FunctionalTools

This commit is contained in:
Emily Schmidt 2024-07-04 10:22:51 +01:00
parent 32cdf25838
commit 9700df50d6
4 changed files with 203 additions and 160 deletions

View file

@ -443,4 +443,55 @@ void FunctionalIR::forward_buf() {
_graph.permute(perm, alias);
}
static std::string quote_fmt(const char *fmt)
{
std::string r;
for(const char *p = fmt; *p != 0; p++) {
switch(*p) {
case '\n': r += "\\n"; break;
case '\t': r += "\\t"; break;
case '"': r += "\\\""; break;
case '\\': r += "\\\\"; break;
default: r += *p; break;
}
}
return r;
}
void FunctionalTools::Writer::print_impl(const char *fmt, vector<std::function<void()>> &fns)
{
size_t next_index = 0;
for(const char *p = fmt; *p != 0; p++)
switch(*p) {
case '{':
if(*++p == '{') {
*os << '{';
} else {
char *pe;
size_t index = strtoul(p, &pe, 10);
if(*pe != '}')
log_error("invalid format string: expected {<number>}, {} or {{, got \"%s\": \"%s\"\n",
quote_fmt(std::string(p - 1, pe - p + 2).c_str()).c_str(),
quote_fmt(fmt).c_str());
if(p == pe)
index = next_index;
else
p = pe;
if(index >= fns.size())
log_error("invalid format string: index %zu out of bounds (%zu): \"%s\"\n", index, fns.size(), quote_fmt(fmt).c_str());
fns[index]();
next_index = index + 1;
}
break;
case '}':
p++;
if(*p != '}')
log_error("invalid format string: unescaped }: \"%s\"\n", quote_fmt(fmt).c_str());
*os << '}';
break;
default:
*os << *p;
}
}
YOSYS_NAMESPACE_END

View file

@ -29,58 +29,6 @@
USING_YOSYS_NAMESPACE
YOSYS_NAMESPACE_BEGIN
namespace FunctionalTools {
class Scope {
const char *_illegal_characters;
pool<std::string> _used_names;
dict<int, std::string> _by_id;
dict<IdString, std::string> _by_name;
std::string allocate_name(IdString suggestion) {
std::string str = RTLIL::unescape_id(suggestion);
for(size_t i = 0; i < str.size(); i++)
if(strchr(_illegal_characters, str[i]))
str[i] = '_';
if(_used_names.count(str) == 0) {
_used_names.insert(str);
return str;
}
for (int idx = 0 ; ; idx++){
std::string suffixed = str + "_" + std::to_string(idx);
if(_used_names.count(suffixed) == 0) {
_used_names.insert(suffixed);
return suffixed;
}
}
}
public:
Scope(const char *illegal_characters = "", const char **keywords = nullptr) {
_illegal_characters = illegal_characters;
if(keywords != nullptr)
for(const char **p = keywords; *p != nullptr; p++)
reserve(*p);
}
void reserve(std::string name) {
_used_names.insert(std::move(name));
}
std::string operator()(int id, IdString suggestion) {
auto it = _by_id.find(id);
if(it != _by_id.end())
return it->second;
std::string str = allocate_name(suggestion);
_by_id.insert({id, str});
return str;
}
std::string operator()(IdString idstring) {
auto it = _by_name.find(idstring);
if(it != _by_name.end())
return it->second;
std::string str = allocate_name(idstring);
_by_name.insert({idstring, str});
return str;
}
};
}
class FunctionalIR {
enum class Fn {
invalid,
@ -418,6 +366,82 @@ public:
Iterator end() { return Iterator(this, _graph.size()); }
};
namespace FunctionalTools {
class Scope {
const char *_illegal_characters;
pool<std::string> _used_names;
dict<int, std::string> _by_id;
dict<IdString, std::string> _by_name;
std::string allocate_name(IdString suggestion) {
std::string str = RTLIL::unescape_id(suggestion);
for(size_t i = 0; i < str.size(); i++)
if(strchr(_illegal_characters, str[i]))
str[i] = '_';
if(_used_names.count(str) == 0) {
_used_names.insert(str);
return str;
}
for (int idx = 0 ; ; idx++){
std::string suffixed = str + "_" + std::to_string(idx);
if(_used_names.count(suffixed) == 0) {
_used_names.insert(suffixed);
return suffixed;
}
}
}
public:
Scope(const char *illegal_characters = "", const char **keywords = nullptr) {
_illegal_characters = illegal_characters;
if(keywords != nullptr)
for(const char **p = keywords; *p != nullptr; p++)
reserve(*p);
}
void reserve(std::string name) {
_used_names.insert(std::move(name));
}
std::string operator()(int id, IdString suggestion) {
auto it = _by_id.find(id);
if(it != _by_id.end())
return it->second;
std::string str = allocate_name(suggestion);
_by_id.insert({id, str});
return str;
}
std::string operator()(IdString idstring) {
auto it = _by_name.find(idstring);
if(it != _by_name.end())
return it->second;
std::string str = allocate_name(idstring);
_by_name.insert({idstring, str});
return str;
}
};
class Writer {
std::ostream *os;
void print_impl(const char *fmt, vector<std::function<void()>>& fns);
public:
Writer(std::ostream &os) : os(&os) {}
template<class T> Writer& operator <<(T&& arg) { *os << std::forward<T>(arg); return *this; }
template<typename... Args>
void print(const char *fmt, Args&&... args)
{
vector<std::function<void()>> fns { [&]() { *this << args; }... };
print_impl(fmt, fns);
}
template<typename Fn, typename... Args>
void print_with(Fn fn, const char *fmt, Args&&... args)
{
vector<std::function<void()>> fns { [&]() {
if constexpr (std::is_invocable_v<Fn, Args>)
*this << fn(args);
else
*this << args; }...
};
print_impl(fmt, fns);
}
};
}
YOSYS_NAMESPACE_END
#endif