mirror of
https://github.com/YosysHQ/yosys
synced 2025-07-24 05:08:56 +00:00
Merge branch 'master' into krys/docs
Fix failing verific tests
This commit is contained in:
commit
8fad77bd0f
57 changed files with 2186 additions and 1394 deletions
|
@ -90,6 +90,12 @@ template<> struct hash_ops<uint32_t> : hash_int_ops
|
|||
return a;
|
||||
}
|
||||
};
|
||||
template<> struct hash_ops<uint64_t> : hash_int_ops
|
||||
{
|
||||
static inline unsigned int hash(uint64_t a) {
|
||||
return mkhash((unsigned int)(a), (unsigned int)(a >> 32));
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct hash_ops<std::string> {
|
||||
static inline bool cmp(const std::string &a, const std::string &b) {
|
||||
|
@ -988,7 +994,7 @@ public:
|
|||
return !operator==(other);
|
||||
}
|
||||
|
||||
bool hash() const {
|
||||
unsigned int hash() const {
|
||||
unsigned int hashval = mkhash_init;
|
||||
for (auto &it : entries)
|
||||
hashval ^= ops.hash(it.udata);
|
||||
|
|
|
@ -313,18 +313,33 @@ RTLIL::Const RTLIL::Const::from_string(const std::string &str)
|
|||
|
||||
std::string RTLIL::Const::decode_string() const
|
||||
{
|
||||
std::string string;
|
||||
string.reserve(GetSize(bits)/8);
|
||||
for (int i = 0; i < GetSize(bits); i += 8) {
|
||||
const int n = GetSize(bits);
|
||||
const int n_over_8 = n / 8;
|
||||
std::string s;
|
||||
s.reserve(n_over_8);
|
||||
int i = n_over_8 * 8;
|
||||
if (i < n) {
|
||||
char ch = 0;
|
||||
for (int j = 0; j < 8 && i + j < int (bits.size()); j++)
|
||||
if (bits[i + j] == RTLIL::State::S1)
|
||||
for (int j = 0; j < (n - i); j++) {
|
||||
if (bits[i + j] == RTLIL::State::S1) {
|
||||
ch |= 1 << j;
|
||||
}
|
||||
}
|
||||
if (ch != 0)
|
||||
string.append({ch});
|
||||
s.append({ch});
|
||||
}
|
||||
std::reverse(string.begin(), string.end());
|
||||
return string;
|
||||
i -= 8;
|
||||
for (; i >= 0; i -= 8) {
|
||||
char ch = 0;
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if (bits[i + j] == RTLIL::State::S1) {
|
||||
ch |= 1 << j;
|
||||
}
|
||||
}
|
||||
if (ch != 0)
|
||||
s.append({ch});
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
bool RTLIL::Const::is_fully_zero() const
|
||||
|
@ -2677,6 +2692,19 @@ RTLIL::Cell* RTLIL::Module::addPow(RTLIL::IdString name, const RTLIL::SigSpec &s
|
|||
return cell;
|
||||
}
|
||||
|
||||
RTLIL::Cell* RTLIL::Module::addFa(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_c, const RTLIL::SigSpec &sig_x, const RTLIL::SigSpec &sig_y, const std::string &src)
|
||||
{
|
||||
RTLIL::Cell *cell = addCell(name, ID($fa));
|
||||
cell->parameters[ID::WIDTH] = sig_a.size();
|
||||
cell->setPort(ID::A, sig_a);
|
||||
cell->setPort(ID::B, sig_b);
|
||||
cell->setPort(ID::C, sig_c);
|
||||
cell->setPort(ID::X, sig_x);
|
||||
cell->setPort(ID::Y, sig_y);
|
||||
cell->set_src_attribute(src);
|
||||
return cell;
|
||||
}
|
||||
|
||||
RTLIL::Cell* RTLIL::Module::addSlice(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, RTLIL::Const offset, const std::string &src)
|
||||
{
|
||||
RTLIL::Cell *cell = addCell(name, ID($slice));
|
||||
|
@ -4031,13 +4059,17 @@ void RTLIL::SigSpec::replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec
|
|||
unpack();
|
||||
other->unpack();
|
||||
|
||||
dict<RTLIL::SigBit, int> pattern_to_with;
|
||||
for (int i = 0; i < GetSize(pattern.bits_); i++) {
|
||||
if (pattern.bits_[i].wire != NULL) {
|
||||
for (int j = 0; j < GetSize(bits_); j++) {
|
||||
if (bits_[j] == pattern.bits_[i]) {
|
||||
other->bits_[j] = with.bits_[i];
|
||||
}
|
||||
}
|
||||
pattern_to_with.emplace(pattern.bits_[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < GetSize(bits_); j++) {
|
||||
auto it = pattern_to_with.find(bits_[j]);
|
||||
if (it != pattern_to_with.end()) {
|
||||
other->bits_[j] = with.bits_[it->second];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -308,10 +308,14 @@ namespace RTLIL
|
|||
bool operator!=(const char *rhs) const { return strcmp(c_str(), rhs) != 0; }
|
||||
|
||||
char operator[](size_t i) const {
|
||||
const char *p = c_str();
|
||||
const char *p = c_str();
|
||||
#ifndef NDEBUG
|
||||
for (; i != 0; i--, p++)
|
||||
log_assert(*p != 0);
|
||||
return *p;
|
||||
#else
|
||||
return *(p + i);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string substr(size_t pos = 0, size_t len = std::string::npos) const {
|
||||
|
@ -1298,6 +1302,8 @@ public:
|
|||
RTLIL::Cell* addModFloor (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addPow (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool a_signed = false, bool b_signed = false, const std::string &src = "");
|
||||
|
||||
RTLIL::Cell* addFa (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_c, const RTLIL::SigSpec &sig_x, const RTLIL::SigSpec &sig_y, const std::string &src = "");
|
||||
|
||||
RTLIL::Cell* addLogicNot (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addLogicAnd (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
RTLIL::Cell* addLogicOr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
|
||||
|
|
132
kernel/utils.h
132
kernel/utils.h
|
@ -128,41 +128,103 @@ public:
|
|||
// A simple class for topological sorting
|
||||
// ------------------------------------------------
|
||||
|
||||
template<typename T, typename C = std::less<T>>
|
||||
struct TopoSort
|
||||
template <typename T, typename C = std::less<T>, typename OPS = hash_ops<T>> class TopoSort
|
||||
{
|
||||
bool analyze_loops, found_loops;
|
||||
std::map<T, std::set<T, C>, C> database;
|
||||
std::set<std::set<T, C>> loops;
|
||||
std::vector<T> sorted;
|
||||
public:
|
||||
// We use this ordering of the edges in the adjacency matrix for
|
||||
// exact compatibility with an older implementation.
|
||||
struct IndirectCmp {
|
||||
IndirectCmp(const std::vector<T> &nodes) : node_cmp_(), nodes_(nodes) {}
|
||||
bool operator()(int a, int b) const
|
||||
{
|
||||
log_assert(static_cast<size_t>(a) < nodes_.size());
|
||||
log_assert(static_cast<size_t>(b) < nodes_.size());
|
||||
return node_cmp_(nodes_[a], nodes_[b]);
|
||||
}
|
||||
const C node_cmp_;
|
||||
const std::vector<T> &nodes_;
|
||||
};
|
||||
|
||||
TopoSort()
|
||||
bool analyze_loops;
|
||||
std::map<T, int, C> node_to_index;
|
||||
std::vector<std::set<int, IndirectCmp>> edges;
|
||||
std::vector<T> sorted;
|
||||
std::set<std::set<T, C>> loops;
|
||||
|
||||
TopoSort() : indirect_cmp(nodes)
|
||||
{
|
||||
analyze_loops = true;
|
||||
found_loops = false;
|
||||
}
|
||||
|
||||
void node(T n)
|
||||
int node(T n)
|
||||
{
|
||||
if (database.count(n) == 0)
|
||||
database[n] = std::set<T, C>();
|
||||
auto rv = node_to_index.emplace(n, static_cast<int>(nodes.size()));
|
||||
if (rv.second) {
|
||||
nodes.push_back(n);
|
||||
edges.push_back(std::set<int, IndirectCmp>(indirect_cmp));
|
||||
}
|
||||
return rv.first->second;
|
||||
}
|
||||
|
||||
void edge(T left, T right)
|
||||
void edge(int l_index, int r_index) { edges[r_index].insert(l_index); }
|
||||
|
||||
void edge(T left, T right) { edge(node(left), node(right)); }
|
||||
|
||||
bool has_node(const T &node) { return node_to_index.find(node) != node_to_index.end(); }
|
||||
|
||||
bool sort()
|
||||
{
|
||||
node(left);
|
||||
database[right].insert(left);
|
||||
log_assert(GetSize(node_to_index) == GetSize(edges));
|
||||
log_assert(GetSize(nodes) == GetSize(edges));
|
||||
|
||||
loops.clear();
|
||||
sorted.clear();
|
||||
found_loops = false;
|
||||
|
||||
std::vector<bool> marked_cells(edges.size(), false);
|
||||
std::vector<bool> active_cells(edges.size(), false);
|
||||
std::vector<int> active_stack;
|
||||
sorted.reserve(edges.size());
|
||||
|
||||
for (const auto &it : node_to_index)
|
||||
sort_worker(it.second, marked_cells, active_cells, active_stack);
|
||||
|
||||
log_assert(GetSize(sorted) == GetSize(nodes));
|
||||
|
||||
return !found_loops;
|
||||
}
|
||||
|
||||
void sort_worker(const T &n, std::set<T, C> &marked_cells, std::set<T, C> &active_cells, std::vector<T> &active_stack)
|
||||
// Build the more expensive representation of edges for
|
||||
// a few passes that use it directly.
|
||||
std::map<T, std::set<T, C>, C> get_database()
|
||||
{
|
||||
if (active_cells.count(n)) {
|
||||
std::map<T, std::set<T, C>, C> database;
|
||||
for (size_t i = 0; i < nodes.size(); ++i) {
|
||||
std::set<T, C> converted_edge_set;
|
||||
for (int other_node : edges[i]) {
|
||||
converted_edge_set.insert(nodes[other_node]);
|
||||
}
|
||||
database.emplace(nodes[i], converted_edge_set);
|
||||
}
|
||||
return database;
|
||||
}
|
||||
|
||||
private:
|
||||
bool found_loops;
|
||||
std::vector<T> nodes;
|
||||
const IndirectCmp indirect_cmp;
|
||||
|
||||
void sort_worker(const int root_index, std::vector<bool> &marked_cells, std::vector<bool> &active_cells, std::vector<int> &active_stack)
|
||||
{
|
||||
if (active_cells[root_index]) {
|
||||
found_loops = true;
|
||||
if (analyze_loops) {
|
||||
std::set<T, C> loop;
|
||||
for (int i = GetSize(active_stack)-1; i >= 0; i--) {
|
||||
loop.insert(active_stack[i]);
|
||||
if (active_stack[i] == n)
|
||||
for (int i = GetSize(active_stack) - 1; i >= 0; i--) {
|
||||
const int index = active_stack[i];
|
||||
loop.insert(nodes[index]);
|
||||
if (index == root_index)
|
||||
break;
|
||||
}
|
||||
loops.insert(loop);
|
||||
|
@ -170,42 +232,24 @@ struct TopoSort
|
|||
return;
|
||||
}
|
||||
|
||||
if (marked_cells.count(n))
|
||||
if (marked_cells[root_index])
|
||||
return;
|
||||
|
||||
if (!database.at(n).empty())
|
||||
{
|
||||
if (!edges[root_index].empty()) {
|
||||
if (analyze_loops)
|
||||
active_stack.push_back(n);
|
||||
active_cells.insert(n);
|
||||
active_stack.push_back(root_index);
|
||||
active_cells[root_index] = true;
|
||||
|
||||
for (auto &left_n : database.at(n))
|
||||
for (int left_n : edges[root_index])
|
||||
sort_worker(left_n, marked_cells, active_cells, active_stack);
|
||||
|
||||
if (analyze_loops)
|
||||
active_stack.pop_back();
|
||||
active_cells.erase(n);
|
||||
active_cells[root_index] = false;
|
||||
}
|
||||
|
||||
marked_cells.insert(n);
|
||||
sorted.push_back(n);
|
||||
}
|
||||
|
||||
bool sort()
|
||||
{
|
||||
loops.clear();
|
||||
sorted.clear();
|
||||
found_loops = false;
|
||||
|
||||
std::set<T, C> marked_cells;
|
||||
std::set<T, C> active_cells;
|
||||
std::vector<T> active_stack;
|
||||
|
||||
for (auto &it : database)
|
||||
sort_worker(it.first, marked_cells, active_cells, active_stack);
|
||||
|
||||
log_assert(GetSize(sorted) == GetSize(database));
|
||||
return !found_loops;
|
||||
marked_cells[root_index] = true;
|
||||
sorted.push_back(nodes[root_index]);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -175,48 +175,6 @@ int ceil_log2(int x)
|
|||
#endif
|
||||
}
|
||||
|
||||
std::string stringf(const char *fmt, ...)
|
||||
{
|
||||
std::string string;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
string = vstringf(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
std::string vstringf(const char *fmt, va_list ap)
|
||||
{
|
||||
std::string string;
|
||||
char *str = NULL;
|
||||
|
||||
#if defined(_WIN32 )|| defined(__CYGWIN__)
|
||||
int sz = 64, rc;
|
||||
while (1) {
|
||||
va_list apc;
|
||||
va_copy(apc, ap);
|
||||
str = (char*)realloc(str, sz);
|
||||
rc = vsnprintf(str, sz, fmt, apc);
|
||||
va_end(apc);
|
||||
if (rc >= 0 && rc < sz)
|
||||
break;
|
||||
sz *= 2;
|
||||
}
|
||||
#else
|
||||
if (vasprintf(&str, fmt, ap) < 0)
|
||||
str = NULL;
|
||||
#endif
|
||||
|
||||
if (str != NULL) {
|
||||
string = str;
|
||||
free(str);
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
int readsome(std::istream &f, char *s, int n)
|
||||
{
|
||||
int rc = int(f.readsome(s, n));
|
||||
|
@ -1395,8 +1353,12 @@ void shell(RTLIL::Design *design)
|
|||
if ((command = fgets(command_buffer, 4096, stdin)) == NULL)
|
||||
break;
|
||||
#endif
|
||||
if (command[strspn(command, " \t\r\n")] == 0)
|
||||
if (command[strspn(command, " \t\r\n")] == 0) {
|
||||
#if defined(YOSYS_ENABLE_READLINE) || defined(YOSYS_ENABLE_EDITLINE)
|
||||
free(command);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
#if defined(YOSYS_ENABLE_READLINE) || defined(YOSYS_ENABLE_EDITLINE)
|
||||
add_history(command);
|
||||
#endif
|
||||
|
@ -1418,10 +1380,17 @@ void shell(RTLIL::Design *design)
|
|||
log_reset_stack();
|
||||
}
|
||||
design->check();
|
||||
#if defined(YOSYS_ENABLE_READLINE) || defined(YOSYS_ENABLE_EDITLINE)
|
||||
if (command)
|
||||
free(command);
|
||||
#endif
|
||||
}
|
||||
if (command == NULL)
|
||||
printf("exit\n");
|
||||
|
||||
#if defined(YOSYS_ENABLE_READLINE) || defined(YOSYS_ENABLE_EDITLINE)
|
||||
else
|
||||
free(command);
|
||||
#endif
|
||||
recursion_counter--;
|
||||
log_cmd_error_throw = false;
|
||||
}
|
||||
|
|
|
@ -272,8 +272,64 @@ inline void memhasher() { if (memhasher_active) memhasher_do(); }
|
|||
|
||||
void yosys_banner();
|
||||
int ceil_log2(int x) YS_ATTRIBUTE(const);
|
||||
|
||||
inline std::string vstringf(const char *fmt, va_list ap)
|
||||
{
|
||||
// For the common case of strings shorter than 128, save a heap
|
||||
// allocation by using a stack allocated buffer.
|
||||
const int kBufSize = 128;
|
||||
char buf[kBufSize];
|
||||
buf[0] = '\0';
|
||||
va_list apc;
|
||||
va_copy(apc, ap);
|
||||
int n = vsnprintf(buf, kBufSize, fmt, apc);
|
||||
va_end(apc);
|
||||
if (n < kBufSize)
|
||||
return std::string(buf);
|
||||
|
||||
std::string string;
|
||||
char *str = NULL;
|
||||
#if defined(_WIN32 )|| defined(__CYGWIN__)
|
||||
int sz = 2 * kBufSize, rc;
|
||||
while (1) {
|
||||
va_copy(apc, ap);
|
||||
str = (char*)realloc(str, sz);
|
||||
rc = vsnprintf(str, sz, fmt, apc);
|
||||
va_end(apc);
|
||||
if (rc >= 0 && rc < sz)
|
||||
break;
|
||||
sz *= 2;
|
||||
}
|
||||
if (str != NULL) {
|
||||
string = str;
|
||||
free(str);
|
||||
}
|
||||
return string;
|
||||
#else
|
||||
if (vasprintf(&str, fmt, ap) < 0)
|
||||
str = NULL;
|
||||
if (str != NULL) {
|
||||
string = str;
|
||||
free(str);
|
||||
}
|
||||
return string;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string stringf(const char *fmt, ...) YS_ATTRIBUTE(format(printf, 1, 2));
|
||||
std::string vstringf(const char *fmt, va_list ap);
|
||||
|
||||
inline std::string stringf(const char *fmt, ...)
|
||||
{
|
||||
std::string string;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
string = vstringf(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
int readsome(std::istream &f, char *s, int n);
|
||||
std::string next_token(std::string &text, const char *sep = " \t\r\n", bool long_strings = false);
|
||||
std::vector<std::string> split_tokens(const std::string &text, const char *sep = " \t\r\n");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue