mirror of https://github.com/YosysHQ/yosys.git
Compare commits
39 Commits
7db64427c0
...
7bed9e2bc4
| Author | SHA1 | Date |
|---|---|---|
|
|
7bed9e2bc4 | |
|
|
5d0847f6fb | |
|
|
24b69cabaa | |
|
|
0d3cd5d6c8 | |
|
|
45017e19ec | |
|
|
9a2fd4c31b | |
|
|
1af5d4f2db | |
|
|
ab525643a7 | |
|
|
a1f7d6c9bf | |
|
|
dbb8354996 | |
|
|
d314c47a55 | |
|
|
be530bef73 | |
|
|
973e8a3928 | |
|
|
8c9dd3209a | |
|
|
4672127610 | |
|
|
11a91af920 | |
|
|
8cb7cd7ac1 | |
|
|
82f86164d3 | |
|
|
0d45d9cc6e | |
|
|
a0e9e2d364 | |
|
|
000c081965 | |
|
|
04a6dbc562 | |
|
|
7bd6b4f287 | |
|
|
213d665ae1 | |
|
|
5c8f9f14ca | |
|
|
b2de56cae2 | |
|
|
8a88acd9b8 | |
|
|
58dbf75885 | |
|
|
20e64ee17b | |
|
|
bf4cfbd72d | |
|
|
fd7b4f4a8b | |
|
|
37e4c2e8f8 | |
|
|
c4f3e61339 | |
|
|
c599d6a67e | |
|
|
10a55119a9 | |
|
|
5d2d544109 | |
|
|
37ba29482e | |
|
|
7bb0a1913e | |
|
|
bbceaa6b5e |
2
Makefile
2
Makefile
|
|
@ -161,7 +161,7 @@ ifeq ($(OS), Haiku)
|
|||
CXXFLAGS += -D_DEFAULT_SOURCE
|
||||
endif
|
||||
|
||||
YOSYS_VER := 0.58+138
|
||||
YOSYS_VER := 0.58+162
|
||||
YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1)
|
||||
YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1)
|
||||
YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2)
|
||||
|
|
|
|||
|
|
@ -121,7 +121,8 @@ void RTLIL_BACKEND::dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, boo
|
|||
dump_sigchunk(f, sig.as_chunk(), autoint);
|
||||
} else {
|
||||
f << stringf("{ ");
|
||||
for (const auto& chunk : reversed(sig.chunks())) {
|
||||
auto chunks = sig.chunks();
|
||||
for (const auto& chunk : reversed(chunks)) {
|
||||
dump_sigchunk(f, chunk, false);
|
||||
f << stringf(" ");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -382,8 +382,9 @@ void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig)
|
|||
dump_sigchunk(f, sig.as_chunk());
|
||||
} else {
|
||||
f << stringf("{ ");
|
||||
for (auto it = sig.chunks().rbegin(); it != sig.chunks().rend(); ++it) {
|
||||
if (it != sig.chunks().rbegin())
|
||||
auto chunks = sig.chunks();
|
||||
for (auto it = chunks.rbegin(); it != chunks.rend(); ++it) {
|
||||
if (it != chunks.rbegin())
|
||||
f << stringf(", ");
|
||||
dump_sigchunk(f, *it, true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ Yosys and there are currently no plans to add support
|
|||
for them:
|
||||
|
||||
- Non-synthesizable language features as defined in
|
||||
IEC 62142(E):2005 / IEEE Std. 1364.1(E):2002
|
||||
IEC 62142(E):2005 / IEEE Std. 1364.1(E):2002
|
||||
|
||||
- The ``tri``, ``triand`` and ``trior`` net types
|
||||
|
||||
|
|
@ -356,21 +356,29 @@ from SystemVerilog:
|
|||
files being read into the same design afterwards.
|
||||
|
||||
- typedefs are supported (including inside packages)
|
||||
- type casts are currently not supported
|
||||
|
||||
- type casts are currently not supported
|
||||
|
||||
- enums are supported (including inside packages)
|
||||
- but are currently not strongly typed
|
||||
|
||||
- but are currently not strongly typed
|
||||
|
||||
- packed structs and unions are supported
|
||||
- arrays of packed structs/unions are currently not supported
|
||||
- structure literals are currently not supported
|
||||
|
||||
- arrays of packed structs/unions are currently not supported
|
||||
- structure literals are currently not supported
|
||||
|
||||
- multidimensional arrays are supported
|
||||
- array assignment of unpacked arrays is currently not supported
|
||||
- array literals are currently not supported
|
||||
|
||||
- SystemVerilog interfaces (SVIs) are supported. Modports for specifying whether
|
||||
ports are inputs or outputs are supported.
|
||||
- array assignment of unpacked arrays is currently not supported
|
||||
- array literals are currently not supported
|
||||
|
||||
- SystemVerilog interfaces (SVIs), including modports for specifying whether
|
||||
ports are inputs or outputs, are partially supported.
|
||||
|
||||
- interfaces must be provided as *named* arguments, not positional arguments.
|
||||
i.e. ``foo bar(.intf(intf0), .x(x));`` is supported but ``foo bar(intf0,
|
||||
x);`` is not.
|
||||
|
||||
- Assignments within expressions are supported.
|
||||
|
||||
|
|
|
|||
916
kernel/rtlil.cc
916
kernel/rtlil.cc
File diff suppressed because it is too large
Load Diff
259
kernel/rtlil.h
259
kernel/rtlil.h
|
|
@ -1223,9 +1223,10 @@ struct RTLIL::SigSpecConstIterator
|
|||
typedef RTLIL::SigBit& reference;
|
||||
|
||||
const RTLIL::SigSpec *sig_p;
|
||||
RTLIL::SigBit bit;
|
||||
int index;
|
||||
|
||||
inline const RTLIL::SigBit &operator*() const;
|
||||
inline const RTLIL::SigBit &operator*();
|
||||
inline bool operator!=(const RTLIL::SigSpecConstIterator &other) const { return index != other.index; }
|
||||
inline bool operator==(const RTLIL::SigSpecIterator &other) const { return index == other.index; }
|
||||
inline void operator++() { index++; }
|
||||
|
|
@ -1234,33 +1235,83 @@ struct RTLIL::SigSpecConstIterator
|
|||
struct RTLIL::SigSpec
|
||||
{
|
||||
private:
|
||||
int width_;
|
||||
Hasher::hash_t hash_;
|
||||
std::vector<RTLIL::SigChunk> chunks_; // LSB at index 0
|
||||
std::vector<RTLIL::SigBit> bits_; // LSB at index 0
|
||||
enum Representation : char {
|
||||
CHUNK,
|
||||
BITS,
|
||||
};
|
||||
// An AtomicHash is either clear or a nonzero integer.
|
||||
struct AtomicHash {
|
||||
// Create an initially clear value.
|
||||
AtomicHash() : atomic_(0) {}
|
||||
AtomicHash(const AtomicHash &rhs) : atomic_(rhs.load()) {}
|
||||
AtomicHash &operator=(const AtomicHash &rhs) { store(rhs.load()); return *this; }
|
||||
// Read the hash. Returns nullopt if the hash is clear.
|
||||
std::optional<Hasher::hash_t> read() const {
|
||||
Hasher::hash_t value = load();
|
||||
if (value == 0)
|
||||
return std::nullopt;
|
||||
return value;
|
||||
}
|
||||
// Set the hash. If the value is already set, then the new value must
|
||||
// equal the current value.
|
||||
void set(Hasher::hash_t value) const {
|
||||
log_assert(value != 0);
|
||||
Hasher::hash_t old = const_cast<std::atomic<Hasher::hash_t>&>(atomic_)
|
||||
.exchange(value, std::memory_order_relaxed);
|
||||
log_assert(old == 0 || old == value);
|
||||
}
|
||||
void clear() { store(0); }
|
||||
private:
|
||||
int load() const { return atomic_.load(std::memory_order_relaxed); }
|
||||
void store(Hasher::hash_t value) const {
|
||||
const_cast<std::atomic<Hasher::hash_t>&>(atomic_).store(value, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void pack() const;
|
||||
void unpack() const;
|
||||
void updhash() const;
|
||||
std::atomic<Hasher::hash_t> atomic_;
|
||||
};
|
||||
|
||||
inline bool packed() const {
|
||||
return bits_.empty();
|
||||
Representation rep_;
|
||||
AtomicHash hash_;
|
||||
union {
|
||||
RTLIL::SigChunk chunk_;
|
||||
std::vector<RTLIL::SigBit> bits_; // LSB at index 0
|
||||
};
|
||||
|
||||
void init_empty_bits() {
|
||||
rep_ = BITS;
|
||||
new (&bits_) std::vector<RTLIL::SigBit>;
|
||||
}
|
||||
|
||||
inline void inline_unpack() const {
|
||||
if (!chunks_.empty())
|
||||
void unpack();
|
||||
inline void inline_unpack() {
|
||||
if (rep_ == CHUNK)
|
||||
unpack();
|
||||
}
|
||||
|
||||
// Only used by Module::remove(const pool<Wire*> &wires)
|
||||
// but cannot be more specific as it isn't yet declared
|
||||
friend struct RTLIL::Module;
|
||||
Hasher::hash_t updhash() const;
|
||||
void destroy() {
|
||||
if (rep_ == CHUNK)
|
||||
chunk_.~SigChunk();
|
||||
else
|
||||
bits_.~vector();
|
||||
}
|
||||
friend struct Chunks;
|
||||
|
||||
public:
|
||||
SigSpec() : width_(0), hash_(0) {}
|
||||
SigSpec() { init_empty_bits(); }
|
||||
SigSpec(std::initializer_list<RTLIL::SigSpec> parts);
|
||||
SigSpec(const SigSpec &value) = default;
|
||||
SigSpec(SigSpec &&value) = default;
|
||||
SigSpec(const SigSpec &value) : rep_(value.rep_), hash_(value.hash_) {
|
||||
if (value.rep_ == CHUNK)
|
||||
new (&chunk_) RTLIL::SigChunk(value.chunk_);
|
||||
else
|
||||
new (&bits_) std::vector<RTLIL::SigBit>(value.bits_);
|
||||
}
|
||||
SigSpec(SigSpec &&value) : rep_(value.rep_), hash_(value.hash_) {
|
||||
if (value.rep_ == CHUNK)
|
||||
new (&chunk_) RTLIL::SigChunk(std::move(value.chunk_));
|
||||
else
|
||||
new (&bits_) std::vector<RTLIL::SigBit>(std::move(value.bits_));
|
||||
}
|
||||
SigSpec(const RTLIL::Const &value);
|
||||
SigSpec(RTLIL::Const &&value);
|
||||
SigSpec(const RTLIL::SigChunk &chunk);
|
||||
|
|
@ -1276,24 +1327,135 @@ public:
|
|||
SigSpec(const pool<RTLIL::SigBit> &bits);
|
||||
SigSpec(const std::set<RTLIL::SigBit> &bits);
|
||||
explicit SigSpec(bool bit);
|
||||
~SigSpec() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
SigSpec &operator=(const SigSpec &rhs) = default;
|
||||
SigSpec &operator=(SigSpec &&rhs) = default;
|
||||
SigSpec &operator=(const SigSpec &rhs) {
|
||||
destroy();
|
||||
rep_ = rhs.rep_;
|
||||
hash_ = rhs.hash_;
|
||||
if (rep_ == CHUNK)
|
||||
new (&chunk_) RTLIL::SigChunk(rhs.chunk_);
|
||||
else
|
||||
new (&bits_) std::vector<RTLIL::SigBit>(rhs.bits_);
|
||||
return *this;
|
||||
}
|
||||
SigSpec &operator=(SigSpec &&rhs) {
|
||||
destroy();
|
||||
rep_ = rhs.rep_;
|
||||
hash_ = rhs.hash_;
|
||||
if (rep_ == CHUNK)
|
||||
new (&chunk_) RTLIL::SigChunk(std::move(rhs.chunk_));
|
||||
else
|
||||
new (&bits_) std::vector<RTLIL::SigBit>(std::move(rhs.bits_));
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const std::vector<RTLIL::SigChunk> &chunks() const { pack(); return chunks_; }
|
||||
inline const std::vector<RTLIL::SigBit> &bits() const { inline_unpack(); return bits_; }
|
||||
struct Chunks {
|
||||
Chunks(const SigSpec &spec) : spec(spec) {}
|
||||
struct const_iterator {
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = const SigChunk &;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = const SigChunk *;
|
||||
using reference = const SigChunk &;
|
||||
|
||||
inline int size() const { return width_; }
|
||||
inline bool empty() const { return width_ == 0; }
|
||||
const SigSpec &spec;
|
||||
int bit_index;
|
||||
SigChunk chunk;
|
||||
|
||||
inline RTLIL::SigBit &operator[](int index) { inline_unpack(); return bits_.at(index); }
|
||||
inline const RTLIL::SigBit &operator[](int index) const { inline_unpack(); return bits_.at(index); }
|
||||
const_iterator(const SigSpec &spec) : spec(spec) {
|
||||
bit_index = 0;
|
||||
if (spec.rep_ == BITS)
|
||||
next_chunk_bits();
|
||||
}
|
||||
void next_chunk_bits();
|
||||
|
||||
const SigChunk &operator*() {
|
||||
if (spec.rep_ == CHUNK)
|
||||
return spec.chunk_;
|
||||
return chunk;
|
||||
};
|
||||
const SigChunk *operator->() { return &**this; }
|
||||
const_iterator &operator++() {
|
||||
bit_index += (**this).width;
|
||||
if (spec.rep_ == BITS)
|
||||
next_chunk_bits();
|
||||
return *this;
|
||||
}
|
||||
bool operator==(const const_iterator &rhs) const { return bit_index == rhs.bit_index; }
|
||||
bool operator!=(const const_iterator &rhs) const { return !(*this == rhs); }
|
||||
};
|
||||
const_iterator begin() const { return const_iterator(spec); }
|
||||
const_iterator end() const {
|
||||
const_iterator it(spec);
|
||||
it.bit_index = spec.size();
|
||||
return it;
|
||||
}
|
||||
// Later we should deprecate these and remove their in-tree calls,
|
||||
// so we can eventually remove chunk_vector.
|
||||
std::vector<RTLIL::SigChunk>::const_reverse_iterator rbegin() {
|
||||
ensure_chunk_vector();
|
||||
return chunk_vector.rbegin();
|
||||
}
|
||||
std::vector<RTLIL::SigChunk>::const_reverse_iterator rend() {
|
||||
ensure_chunk_vector();
|
||||
return chunk_vector.rend();
|
||||
}
|
||||
int size() {
|
||||
ensure_chunk_vector();
|
||||
return chunk_vector.size();
|
||||
}
|
||||
int size() const {
|
||||
int result = 0;
|
||||
for (const SigChunk &_: *this)
|
||||
++result;
|
||||
return result;
|
||||
}
|
||||
const SigChunk &at(int index) {
|
||||
ensure_chunk_vector();
|
||||
return chunk_vector.at(index);
|
||||
}
|
||||
operator const std::vector<RTLIL::SigChunk>&() {
|
||||
ensure_chunk_vector();
|
||||
return chunk_vector;
|
||||
}
|
||||
private:
|
||||
void ensure_chunk_vector() {
|
||||
if (spec.size() > 0 && chunk_vector.empty()) {
|
||||
for (const RTLIL::SigChunk &c : *this)
|
||||
chunk_vector.push_back(c);
|
||||
}
|
||||
}
|
||||
const SigSpec &spec;
|
||||
std::vector<RTLIL::SigChunk> chunk_vector;
|
||||
};
|
||||
friend struct Chunks::const_iterator;
|
||||
|
||||
inline Chunks chunks() const { return {*this}; }
|
||||
inline const SigSpec &bits() const { return *this; }
|
||||
|
||||
inline int size() const { return rep_ == CHUNK ? chunk_.width : GetSize(bits_); }
|
||||
inline bool empty() const { return size() == 0; };
|
||||
|
||||
inline RTLIL::SigBit &operator[](int index) { inline_unpack(); hash_.clear(); return bits_.at(index); }
|
||||
inline RTLIL::SigBit operator[](int index) const {
|
||||
if (rep_ == CHUNK) {
|
||||
if (index < 0 || index >= chunk_.width)
|
||||
throw std::out_of_range("SigSpec::operator[]");
|
||||
if (chunk_.wire)
|
||||
return RTLIL::SigBit(chunk_.wire, chunk_.offset + index);
|
||||
return RTLIL::SigBit(chunk_.data[index]);
|
||||
}
|
||||
return bits_.at(index);
|
||||
}
|
||||
|
||||
inline RTLIL::SigSpecIterator begin() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = 0; return it; }
|
||||
inline RTLIL::SigSpecIterator end() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = width_; return it; }
|
||||
inline RTLIL::SigSpecIterator end() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = size(); return it; }
|
||||
|
||||
inline RTLIL::SigSpecConstIterator begin() const { RTLIL::SigSpecConstIterator it; it.sig_p = this; it.index = 0; return it; }
|
||||
inline RTLIL::SigSpecConstIterator end() const { RTLIL::SigSpecConstIterator it; it.sig_p = this; it.index = width_; return it; }
|
||||
inline RTLIL::SigSpecConstIterator end() const { RTLIL::SigSpecConstIterator it; it.sig_p = this; it.index = size(); return it; }
|
||||
|
||||
void sort();
|
||||
void sort_and_unify();
|
||||
|
|
@ -1325,10 +1487,14 @@ public:
|
|||
RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other = NULL) const;
|
||||
RTLIL::SigSpec extract(const pool<RTLIL::SigBit> &pattern, const RTLIL::SigSpec *other = NULL) const;
|
||||
RTLIL::SigSpec extract(int offset, int length = 1) const;
|
||||
RTLIL::SigSpec extract_end(int offset) const { return extract(offset, width_ - offset); }
|
||||
RTLIL::SigSpec extract_end(int offset) const { return extract(offset, size() - offset); }
|
||||
|
||||
RTLIL::SigBit lsb() const { log_assert(width_); return (*this)[0]; };
|
||||
RTLIL::SigBit msb() const { log_assert(width_); return (*this)[width_ - 1]; };
|
||||
void rewrite_wires(std::function<void(RTLIL::Wire*& wire)> rewrite);
|
||||
|
||||
RTLIL::SigBit lsb() const { log_assert(size()); return (*this)[0]; };
|
||||
RTLIL::SigBit msb() const { log_assert(size()); return (*this)[size() - 1]; };
|
||||
RTLIL::SigBit front() const { return (*this)[0]; }
|
||||
RTLIL::SigBit back() const { return (*this)[size() - 1]; }
|
||||
|
||||
void append(const RTLIL::SigSpec &signal);
|
||||
inline void append(Wire *wire) { append(RTLIL::SigSpec(wire)); }
|
||||
|
|
@ -1351,7 +1517,7 @@ public:
|
|||
|
||||
bool is_wire() const;
|
||||
bool is_chunk() const;
|
||||
inline bool is_bit() const { return width_ == 1; }
|
||||
inline bool is_bit() const { return size() == 1; }
|
||||
|
||||
bool known_driver() const;
|
||||
|
||||
|
|
@ -1388,6 +1554,9 @@ public:
|
|||
int as_int_saturating(bool is_signed = false) const;
|
||||
|
||||
std::string as_string() const;
|
||||
// Returns std::nullopt if there are any non-constant bits. Returns an empty
|
||||
// Const if this has zero width.
|
||||
std::optional<RTLIL::Const> try_as_const() const;
|
||||
RTLIL::Const as_const() const;
|
||||
RTLIL::Wire *as_wire() const;
|
||||
RTLIL::SigChunk as_chunk() const;
|
||||
|
|
@ -1405,11 +1574,19 @@ public:
|
|||
static bool parse_sel(RTLIL::SigSpec &sig, RTLIL::Design *design, RTLIL::Module *module, std::string str);
|
||||
static bool parse_rhs(const RTLIL::SigSpec &lhs, RTLIL::SigSpec &sig, RTLIL::Module *module, std::string str);
|
||||
|
||||
operator std::vector<RTLIL::SigChunk>() const { return chunks(); }
|
||||
operator std::vector<RTLIL::SigBit>() const { return bits(); }
|
||||
const RTLIL::SigBit &at(int offset, const RTLIL::SigBit &defval) { return offset < width_ ? (*this)[offset] : defval; }
|
||||
operator std::vector<RTLIL::SigChunk>() const;
|
||||
operator std::vector<RTLIL::SigBit>() const { return to_sigbit_vector(); }
|
||||
const RTLIL::SigBit &at(int offset, const RTLIL::SigBit &defval) { return offset < size() ? (*this)[offset] : defval; }
|
||||
|
||||
[[nodiscard]] Hasher hash_into(Hasher h) const { if (!hash_) updhash(); h.eat(hash_); return h; }
|
||||
[[nodiscard]] Hasher hash_into(Hasher h) const {
|
||||
Hasher::hash_t val;
|
||||
if (std::optional<Hasher::hash_t> current = hash_.read())
|
||||
val = *current;
|
||||
else
|
||||
val = updhash();
|
||||
h.eat(val);
|
||||
return h;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void check(Module *mod = nullptr) const;
|
||||
|
|
@ -2314,13 +2491,15 @@ inline RTLIL::SigBit &RTLIL::SigSpecIterator::operator*() const {
|
|||
return (*sig_p)[index];
|
||||
}
|
||||
|
||||
inline const RTLIL::SigBit &RTLIL::SigSpecConstIterator::operator*() const {
|
||||
return (*sig_p)[index];
|
||||
inline const RTLIL::SigBit &RTLIL::SigSpecConstIterator::operator*() {
|
||||
bit = (*sig_p)[index];
|
||||
return bit;
|
||||
}
|
||||
|
||||
inline RTLIL::SigBit::SigBit(const RTLIL::SigSpec &sig) {
|
||||
log_assert(sig.size() == 1 && sig.chunks().size() == 1);
|
||||
*this = SigBit(sig.chunks().front());
|
||||
log_assert(sig.size() == 1);
|
||||
auto it = sig.chunks().begin();
|
||||
*this = SigBit(*it);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
|
|||
|
|
@ -277,14 +277,26 @@ inline int ceil_log2(int x)
|
|||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
auto reversed(T& container) {
|
||||
struct reverse_view {
|
||||
reverse_view(T& container) : container(container) {}
|
||||
auto begin() const { return container.rbegin(); }
|
||||
auto end() const { return container.rend(); }
|
||||
T& container;
|
||||
};
|
||||
return reverse_view{container};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
auto reversed(const T& container) {
|
||||
struct reverse_view {
|
||||
const T& cont;
|
||||
auto begin() const { return cont.rbegin(); }
|
||||
auto end() const { return cont.rend(); }
|
||||
};
|
||||
return reverse_view{container};
|
||||
struct reverse_view {
|
||||
reverse_view(const T& container) : container(container) {}
|
||||
auto begin() const { return container.rbegin(); }
|
||||
auto end() const { return container.rend(); }
|
||||
const T& container;
|
||||
};
|
||||
return reverse_view{container};
|
||||
}
|
||||
|
||||
YOSYS_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -278,11 +278,12 @@ struct ShowWorker
|
|||
std::vector<std::string> label_pieces;
|
||||
int bitpos = sig.size()-1;
|
||||
|
||||
for (int rep, chunk_idx = ((int) sig.chunks().size()) - 1; chunk_idx >= 0; chunk_idx -= rep) {
|
||||
const RTLIL::SigChunk &c = sig.chunks().at(chunk_idx);
|
||||
RTLIL::SigSpec::Chunks sig_chunks = sig.chunks();
|
||||
for (int rep, chunk_idx = ((int) sig_chunks.size()) - 1; chunk_idx >= 0; chunk_idx -= rep) {
|
||||
const RTLIL::SigChunk &c = sig_chunks.at(chunk_idx);
|
||||
|
||||
// Find the number of times this chunk is repeating
|
||||
for (rep = 1; chunk_idx - rep >= 0 && c == sig.chunks().at(chunk_idx - rep); rep++);
|
||||
for (rep = 1; chunk_idx - rep >= 0 && c == sig_chunks.at(chunk_idx - rep); rep++);
|
||||
|
||||
int cl, cr;
|
||||
cl = c.offset + c.width - 1;
|
||||
|
|
|
|||
|
|
@ -156,6 +156,21 @@ std::string basic_cell_type(const std::string celltype, int pos[3] = nullptr) {
|
|||
return basicType;
|
||||
}
|
||||
|
||||
// Try to read an IdString as a numbered connection name ("$123" or similar),
|
||||
// writing the result to dst. If the string isn't of the right format, ignore
|
||||
// dst and return false.
|
||||
bool read_id_num(RTLIL::IdString str, int *dst)
|
||||
{
|
||||
log_assert(dst);
|
||||
|
||||
const char *c_str = str.c_str();
|
||||
if (c_str[0] != '$' || !('0' <= c_str[1] && c_str[1] <= '9'))
|
||||
return false;
|
||||
|
||||
*dst = atoi(c_str + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
// A helper struct for expanding a module's interface connections in expand_module
|
||||
struct IFExpander
|
||||
{
|
||||
|
|
@ -283,15 +298,42 @@ struct IFExpander
|
|||
RTLIL::IdString conn_name,
|
||||
const RTLIL::SigSpec &conn_signals)
|
||||
{
|
||||
// Check if the connection is present as an interface in the sub-module's port list
|
||||
const RTLIL::Wire *wire = submodule.wire(conn_name);
|
||||
if (!wire || !wire->get_bool_attribute(ID::is_interface))
|
||||
// Does the connection look like an interface
|
||||
if (
|
||||
conn_signals.size() != 1 ||
|
||||
conn_signals[0].wire == nullptr ||
|
||||
conn_signals[0].wire->get_bool_attribute(ID::is_interface) == false ||
|
||||
conn_signals[0].wire->name.str().find("$dummywireforinterface") != 0
|
||||
)
|
||||
return;
|
||||
|
||||
// Check if the connection is present as an interface in the sub-module's port list
|
||||
int id;
|
||||
if (read_id_num(conn_name, &id)) {
|
||||
/* Interface expansion is incompatible with positional arguments
|
||||
* during expansion, the port list gets each interface signal
|
||||
* inserted after the interface itself which means that the argument
|
||||
* positions in the parent module no longer match.
|
||||
*
|
||||
* Supporting this would require expanding the interfaces in the
|
||||
* parent module, renumbering the arguments to match, and then
|
||||
* iterating over the ports list to find the matching interface
|
||||
* (refactoring on_interface to accept different conn_names on the
|
||||
* parent and child).
|
||||
*/
|
||||
log_error("Unable to connect `%s' to submodule `%s' with positional interface argument `%s'!\n",
|
||||
module.name,
|
||||
submodule.name,
|
||||
conn_signals[0].wire->name.str().substr(23)
|
||||
);
|
||||
} else {
|
||||
// Lookup connection by name
|
||||
const RTLIL::Wire *wire = submodule.wire(conn_name);
|
||||
if (!wire || !wire->get_bool_attribute(ID::is_interface))
|
||||
return;
|
||||
}
|
||||
// If the connection looks like an interface, handle it.
|
||||
const auto &bits = conn_signals;
|
||||
if (bits.size() == 1 && bits[0].wire->get_bool_attribute(ID::is_interface))
|
||||
on_interface(submodule, conn_name, conn_signals);
|
||||
on_interface(submodule, conn_name, conn_signals);
|
||||
}
|
||||
|
||||
// Iterate over the connections in a cell, tracking any interface
|
||||
|
|
@ -376,21 +418,6 @@ RTLIL::Module *get_module(RTLIL::Design &design,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// Try to read an IdString as a numbered connection name ("$123" or similar),
|
||||
// writing the result to dst. If the string isn't of the right format, ignore
|
||||
// dst and return false.
|
||||
bool read_id_num(RTLIL::IdString str, int *dst)
|
||||
{
|
||||
log_assert(dst);
|
||||
|
||||
const char *c_str = str.c_str();
|
||||
if (c_str[0] != '$' || !('0' <= c_str[1] && c_str[1] <= '9'))
|
||||
return false;
|
||||
|
||||
*dst = atoi(c_str + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check that the connections on the cell match those that are defined
|
||||
// on the type: each named connection should match the name of a port
|
||||
// and each positional connection should have an index smaller than
|
||||
|
|
|
|||
|
|
@ -1428,13 +1428,13 @@ void reintegrate(RTLIL::Module *module, bool dff_mode)
|
|||
// Copy connections (and rename) from mapped_mod to module
|
||||
for (auto conn : mapped_mod->connections()) {
|
||||
if (!conn.first.is_fully_const()) {
|
||||
auto chunks = conn.first.chunks();
|
||||
std::vector<RTLIL::SigChunk> chunks = conn.first.chunks();
|
||||
for (auto &c : chunks)
|
||||
c.wire = module->wires_.at(remap_name(c.wire->name));
|
||||
conn.first = std::move(chunks);
|
||||
}
|
||||
if (!conn.second.is_fully_const()) {
|
||||
auto chunks = conn.second.chunks();
|
||||
std::vector<RTLIL::SigChunk> chunks = conn.second.chunks();
|
||||
for (auto &c : chunks)
|
||||
if (c.wire)
|
||||
c.wire = module->wires_.at(remap_name(c.wire->name));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
read_verilog -sv << EOF
|
||||
interface simple_if;
|
||||
logic receiver;
|
||||
logic driver;
|
||||
endinterface
|
||||
|
||||
module driver_mod(simple_if intf, input in);
|
||||
assign intf.driver = in;
|
||||
endmodule
|
||||
|
||||
module receiver_mod(simple_if intf);
|
||||
assign intf.receiver = intf.driver;
|
||||
endmodule
|
||||
|
||||
module top(
|
||||
input logic [1:0] inputs,
|
||||
output logic [1:0] outputs
|
||||
);
|
||||
simple_if intf0();
|
||||
simple_if intf1();
|
||||
|
||||
driver_mod d0(intf0, inputs[0]);
|
||||
driver_mod d1(intf1, inputs[1]);
|
||||
|
||||
receiver_mod r0(intf0);
|
||||
receiver_mod r1(intf1);
|
||||
|
||||
assign outputs = {intf0.receiver, intf1.receiver};
|
||||
endmodule
|
||||
EOF
|
||||
|
||||
logger -expect error "Unable to connect.* with positional interface" 1
|
||||
hierarchy -top top
|
||||
|
|
@ -5,3 +5,4 @@
|
|||
|
||||
./run_simple.sh load_and_derive
|
||||
./run_simple.sh resolve_types
|
||||
./run_simple.sh positional_args
|
||||
|
|
|
|||
Loading…
Reference in New Issue