mirror of https://github.com/YosysHQ/yosys.git
Merge from upstream
This commit is contained in:
commit
e21324d609
20
CHANGELOG
20
CHANGELOG
|
|
@ -2,9 +2,27 @@
|
|||
List of major changes and improvements between releases
|
||||
=======================================================
|
||||
|
||||
Yosys 0.58 .. Yosys 0.59-dev
|
||||
Yosys 0.59 .. Yosys 0.60-dev
|
||||
--------------------------
|
||||
|
||||
Yosys 0.58 .. Yosys 0.59
|
||||
--------------------------
|
||||
* Various
|
||||
- Pyosys is rewritten using pybind11.
|
||||
- alumacc: merge independent of sign.
|
||||
- write_btor: Include $assert and $assume cells in -ywmap output.
|
||||
- RTLIL parser rewritten for efficiency.
|
||||
- Wildcards enabled for Liberty file consuming.
|
||||
- timeest: Add top ports launching/sampling.
|
||||
|
||||
* New commands and options
|
||||
- Added "-apply_derived_type" option to "box_derive" pass.
|
||||
- Added "-publish_icells" option to "chtype" pass.
|
||||
- Added "-width" option to "sim" pass.
|
||||
- Added "sort" pass for sorting the design objects.
|
||||
- Merged "synth_ecp5" and "synth_nexus" into "synth_lattice" pass.
|
||||
- Added "-strict-gw5a-dffs" and "-setundef" options to "synth_gowin" pass.
|
||||
|
||||
Yosys 0.57 .. Yosys 0.58
|
||||
--------------------------
|
||||
* Various
|
||||
|
|
|
|||
4
Makefile
4
Makefile
|
|
@ -177,7 +177,7 @@ ifeq ($(OS), Haiku)
|
|||
CXXFLAGS += -D_DEFAULT_SOURCE
|
||||
endif
|
||||
|
||||
YOSYS_VER := 0.58+162
|
||||
YOSYS_VER := 0.59+9
|
||||
YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1)
|
||||
YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2)
|
||||
YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'.' -f3)
|
||||
|
|
@ -200,7 +200,7 @@ endif
|
|||
OBJS = kernel/version_$(GIT_REV).o
|
||||
|
||||
bumpversion:
|
||||
sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 157aabb.. | wc -l`/;" Makefile
|
||||
sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 03eb220.. | wc -l`/;" Makefile
|
||||
|
||||
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 ABC_USE_NAMESPACE=abc VERBOSE=$(Q)
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,9 @@ void RTLIL_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int wi
|
|||
return;
|
||||
}
|
||||
}
|
||||
f << stringf("%d'", width);
|
||||
if ((data.flags & RTLIL::CONST_FLAG_UNSIZED) == 0) {
|
||||
f << stringf("%d'", width);
|
||||
}
|
||||
if (data.flags & RTLIL::CONST_FLAG_SIGNED) {
|
||||
f << stringf("s");
|
||||
}
|
||||
|
|
@ -121,7 +123,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(" ");
|
||||
}
|
||||
|
|
@ -172,9 +175,10 @@ void RTLIL_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL::
|
|||
dump_attributes(f, indent, cell);
|
||||
f << stringf("%s" "cell %s %s\n", indent, cell->type, cell->name);
|
||||
for (const auto& [name, param] : reversed(cell->parameters)) {
|
||||
f << stringf("%s parameter%s%s %s ", indent,
|
||||
f << stringf("%s parameter%s%s%s %s ", indent,
|
||||
(param.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "",
|
||||
(param.flags & RTLIL::CONST_FLAG_REAL) != 0 ? " real" : "",
|
||||
(param.flags & RTLIL::CONST_FLAG_UNSIZED) != 0 ? " unsized" : "",
|
||||
name);
|
||||
dump_const(f, param);
|
||||
f << stringf("\n");
|
||||
|
|
|
|||
|
|
@ -396,8 +396,9 @@ void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig)
|
|||
} else {
|
||||
f << stringf("{ ");
|
||||
int i = 0;
|
||||
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(", ");
|
||||
if (i++ % 20 == 19)
|
||||
f << stringf("\n");
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import os
|
|||
project = 'YosysHQ Yosys'
|
||||
author = 'YosysHQ GmbH'
|
||||
copyright ='2025 YosysHQ GmbH'
|
||||
yosys_ver = "0.58"
|
||||
yosys_ver = "0.59"
|
||||
|
||||
# select HTML theme
|
||||
html_theme = 'furo-ys'
|
||||
|
|
|
|||
|
|
@ -194,17 +194,18 @@ RTLIL::SigSpec
|
|||
|
||||
A "signal" is everything that can be applied to a cell port. I.e.
|
||||
|
||||
- | Any constant value of arbitrary bit-width
|
||||
- | A bit from a wire (``RTLIL::SigBit``)
|
||||
| 1em For example: ``mywire[24]``
|
||||
|
||||
- | A range of bits from a wire (wire variant of ``RTLIL::SigChunk``)
|
||||
| 1em For example: ``mywire, mywire[15:8]``
|
||||
|
||||
- | Any constant value of arbitrary bit-width (``std::vector<RTLIL::State>>`` variant of ``RTLIL::SigChunk``)
|
||||
| 1em For example: ``1337, 16'b0000010100111001, 1'b1, 1'bx``
|
||||
|
||||
- | All bits of a wire or a selection of bits from a wire
|
||||
| 1em For example: ``mywire, mywire[24], mywire[15:8]``
|
||||
|
||||
- | Concatenations of the above
|
||||
| 1em For example: ``{16'd1337, mywire[15:8]}``
|
||||
|
||||
The ``RTLIL::SigSpec`` data type is used to represent signals. The
|
||||
``RTLIL::Cell`` object contains one ``RTLIL::SigSpec`` for each cell port.
|
||||
The ``RTLIL::SigSpec`` data type is used to represent signals.
|
||||
It contains a single ``RTLIL::SigChunk`` or a vector of ``RTLIL::SigBit``.
|
||||
The ``RTLIL::Cell`` object contains one ``RTLIL::SigSpec`` for each cell port.
|
||||
|
||||
In addition, connections between wires are represented using a pair of
|
||||
``RTLIL::SigSpec`` objects. Such pairs are needed in different locations.
|
||||
|
|
|
|||
|
|
@ -993,6 +993,8 @@ RTLIL::Const AstNode::asParaConst() const
|
|||
RTLIL::Const val = asAttrConst();
|
||||
if (is_signed)
|
||||
val.flags |= RTLIL::CONST_FLAG_SIGNED;
|
||||
if (is_unsized)
|
||||
val.flags |= RTLIL::CONST_FLAG_UNSIZED;
|
||||
return val;
|
||||
}
|
||||
|
||||
|
|
@ -1766,7 +1768,10 @@ static std::string serialize_param_value(const RTLIL::Const &val) {
|
|||
res.push_back('s');
|
||||
if (val.flags & RTLIL::ConstFlags::CONST_FLAG_REAL)
|
||||
res.push_back('r');
|
||||
res += stringf("%d", GetSize(val));
|
||||
if (val.flags & RTLIL::ConstFlags::CONST_FLAG_UNSIZED)
|
||||
res.push_back('u');
|
||||
else
|
||||
res += stringf("%d", GetSize(val));
|
||||
res.push_back('\'');
|
||||
res.append(val.as_string("?"));
|
||||
return res;
|
||||
|
|
@ -1860,7 +1865,7 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id
|
|||
} else if ((it->second.flags & RTLIL::CONST_FLAG_STRING) != 0)
|
||||
child->children[0] = AstNode::mkconst_str(loc, it->second.decode_string());
|
||||
else
|
||||
child->children[0] = AstNode::mkconst_bits(loc, it->second.to_bits(), (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0);
|
||||
child->children[0] = AstNode::mkconst_bits(loc, it->second.to_bits(), (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0, (it->second.flags & RTLIL::CONST_FLAG_UNSIZED) != 0);
|
||||
rewritten.insert(it->first);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -889,6 +889,52 @@ static void check_auto_nosync(AstNode *node)
|
|||
check_auto_nosync(child.get());
|
||||
}
|
||||
|
||||
class PackageImporter {
|
||||
std::set<std::string> import_items;
|
||||
bool is_wildcard;
|
||||
const AstNode* node;
|
||||
public:
|
||||
PackageImporter(const AstNode* n, const AstNode* child) : node(n) {
|
||||
is_wildcard = child->children.empty();
|
||||
// For specific imports, collect the list of items to import
|
||||
if (!is_wildcard) {
|
||||
for (auto& item : child->children) {
|
||||
import_items.insert(item->str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void import(std::map<std::string, AstNode*>& scope, AstNode* to_import) const {
|
||||
// Check if this is a specific import and if this item should be imported
|
||||
if (!is_wildcard && import_items.count(to_import->str) == 0)
|
||||
return;
|
||||
|
||||
if (to_import->type == AST_PARAMETER || to_import->type == AST_LOCALPARAM ||
|
||||
to_import->type == AST_TYPEDEF || to_import->type == AST_FUNCTION ||
|
||||
to_import->type == AST_TASK || to_import->type == AST_ENUM) {
|
||||
// For wildcard imports, check if item already exists (from specific import)
|
||||
if (is_wildcard && scope.count(to_import->str) > 0)
|
||||
return;
|
||||
scope[to_import->str] = to_import;
|
||||
}
|
||||
if (to_import->type == AST_ENUM) {
|
||||
for (auto& enode : to_import->children) {
|
||||
log_assert(enode->type==AST_ENUM_ITEM);
|
||||
// Check if this enum item should be imported
|
||||
if (!is_wildcard && import_items.count(enode->str) == 0)
|
||||
continue;
|
||||
// For wildcard imports, check if item already exists (from specific import)
|
||||
if (is_wildcard && scope.count(enode->str) > 0)
|
||||
continue;
|
||||
if (scope.count(enode->str) == 0)
|
||||
scope[enode->str] = enode.get();
|
||||
else
|
||||
node->input_error("enum item %s already exists in current scope\n", enode->str);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// convert the AST into a simpler AST that has all parameters substituted by their
|
||||
// values, unrolled for-loops, expanded generate blocks, etc. when this function
|
||||
// is done with an AST it can be converted into RTLIL using genRTLIL().
|
||||
|
|
@ -1123,22 +1169,10 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
|
|||
}
|
||||
|
||||
if (package_node) {
|
||||
// Import all names from the package into current scope
|
||||
PackageImporter importer(this, child);
|
||||
// Import names from the package into current scope
|
||||
for (auto& pkg_child : package_node->children) {
|
||||
if (pkg_child->type == AST_PARAMETER || pkg_child->type == AST_LOCALPARAM ||
|
||||
pkg_child->type == AST_TYPEDEF || pkg_child->type == AST_FUNCTION ||
|
||||
pkg_child->type == AST_TASK || pkg_child->type == AST_ENUM) {
|
||||
current_scope[pkg_child->str] = pkg_child.get();
|
||||
}
|
||||
if (pkg_child->type == AST_ENUM) {
|
||||
for (auto& enode : pkg_child->children) {
|
||||
log_assert(enode->type==AST_ENUM_ITEM);
|
||||
if (current_scope.count(enode->str) == 0)
|
||||
current_scope[enode->str] = enode.get();
|
||||
else
|
||||
input_error("enum item %s already exists in current scope\n", enode->str);
|
||||
}
|
||||
}
|
||||
importer.import(current_scope, pkg_child.get());
|
||||
}
|
||||
// Remove the import node since it's been processed
|
||||
children.erase(children.begin() + i);
|
||||
|
|
@ -2231,9 +2265,13 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
|
|||
}
|
||||
if (children[0]->type == AST_CONSTANT) {
|
||||
if (width != int(children[0]->bits.size())) {
|
||||
RTLIL::SigSpec sig(children[0]->bits);
|
||||
sig.extend_u0(width, children[0]->is_signed);
|
||||
children[0] = mkconst_bits(location, sig.as_const().to_bits(), is_signed);
|
||||
RTLIL::Const val;
|
||||
if (children[0]->is_unsized) {
|
||||
val = children[0]->bitsAsUnsizedConst(width);
|
||||
} else {
|
||||
val = children[0]->bitsAsConst(width);
|
||||
}
|
||||
children[0] = mkconst_bits(location, val.to_bits(), is_signed);
|
||||
fixup_hierarchy_flags();
|
||||
}
|
||||
children[0]->is_signed = is_signed;
|
||||
|
|
|
|||
|
|
@ -567,10 +567,13 @@ struct RTLILFrontendWorker {
|
|||
if (try_parse_keyword("parameter")) {
|
||||
bool is_signed = false;
|
||||
bool is_real = false;
|
||||
bool is_unsized = false;
|
||||
if (try_parse_keyword("signed")) {
|
||||
is_signed = true;
|
||||
} else if (try_parse_keyword("real")) {
|
||||
is_real = true;
|
||||
} else if (try_parse_keyword("unsized")) {
|
||||
is_unsized = true;
|
||||
}
|
||||
RTLIL::IdString param_name = parse_id();
|
||||
RTLIL::Const val = parse_const();
|
||||
|
|
@ -578,6 +581,8 @@ struct RTLILFrontendWorker {
|
|||
val.flags |= RTLIL::CONST_FLAG_SIGNED;
|
||||
if (is_real)
|
||||
val.flags |= RTLIL::CONST_FLAG_REAL;
|
||||
if (is_unsized)
|
||||
val.flags |= RTLIL::CONST_FLAG_UNSIZED;
|
||||
cell->parameters.insert({std::move(param_name), std::move(val)});
|
||||
expect_eol();
|
||||
} else if (try_parse_keyword("connect")) {
|
||||
|
|
|
|||
|
|
@ -829,11 +829,31 @@ package_body_stmt:
|
|||
typedef_decl | localparam_decl | param_decl | task_func_decl;
|
||||
|
||||
import_stmt:
|
||||
TOK_IMPORT hierarchical_id TOK_PACKAGESEP TOK_ASTER TOK_SEMICOL {
|
||||
// Create an import node to track package imports
|
||||
TOK_IMPORT TOK_ID TOK_PACKAGESEP TOK_ASTER TOK_SEMICOL {
|
||||
// Create an import node to track wildcard package imports
|
||||
auto import_node = std::make_unique<AstNode>(@$, AST_IMPORT);
|
||||
import_node->str = *$2;
|
||||
extra->ast_stack.back()->children.push_back(std::move(import_node));
|
||||
} |
|
||||
TOK_IMPORT TOK_ID TOK_PACKAGESEP {
|
||||
// Start a specific import: create and push the AST_IMPORT node
|
||||
AstNode* import_node = extra->pushChild(std::make_unique<AstNode>(@$, AST_IMPORT));
|
||||
import_node->str = *$2;
|
||||
} import_item_list TOK_SEMICOL {
|
||||
// Done collecting specific items, pop the AST_IMPORT node
|
||||
extra->ast_stack.pop_back();
|
||||
};
|
||||
|
||||
import_item_list:
|
||||
import_item |
|
||||
import_item_list TOK_COMMA import_item ;
|
||||
|
||||
import_item:
|
||||
TOK_ID {
|
||||
// Append this specific import name under the current AST_IMPORT
|
||||
auto item_node = std::make_unique<AstNode>(@$, AST_NONE);
|
||||
item_node->str = *$1;
|
||||
extra->ast_stack.back()->children.push_back(std::move(item_node));
|
||||
};
|
||||
|
||||
interface:
|
||||
|
|
|
|||
1009
kernel/rtlil.cc
1009
kernel/rtlil.cc
File diff suppressed because it is too large
Load Diff
272
kernel/rtlil.h
272
kernel/rtlil.h
|
|
@ -53,10 +53,11 @@ namespace RTLIL
|
|||
// Semantic metadata - how can this constant be interpreted?
|
||||
// Values may be generally non-exclusive
|
||||
enum ConstFlags : unsigned char {
|
||||
CONST_FLAG_NONE = 0,
|
||||
CONST_FLAG_STRING = 1,
|
||||
CONST_FLAG_SIGNED = 2, // only used for parameters
|
||||
CONST_FLAG_REAL = 4 // only used for parameters
|
||||
CONST_FLAG_NONE = 0,
|
||||
CONST_FLAG_STRING = 1,
|
||||
CONST_FLAG_SIGNED = 2, // only used for parameters
|
||||
CONST_FLAG_REAL = 4, // only used for parameters
|
||||
CONST_FLAG_UNSIZED = 8, // only used for parameters
|
||||
};
|
||||
|
||||
enum SelectPartials : unsigned char {
|
||||
|
|
@ -1230,9 +1231,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++; }
|
||||
|
|
@ -1241,33 +1243,84 @@ 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();
|
||||
}
|
||||
void try_repack();
|
||||
|
||||
// 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);
|
||||
|
|
@ -1283,24 +1336,138 @@ public:
|
|||
SigSpec(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_; }
|
||||
// SigSpec::Chunks holds one reconstructed chunk at a time
|
||||
// to provide the SigSpec::chunks() read-only chunks view
|
||||
// since vector<SigChunk> SigSpec::chunks_ has been removed
|
||||
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();
|
||||
}
|
||||
enum End { END };
|
||||
const_iterator(const SigSpec &spec, End) : spec(spec) {
|
||||
bit_index = spec.size();
|
||||
}
|
||||
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, const_iterator::END);
|
||||
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 {
|
||||
return std::distance(begin(), end());
|
||||
}
|
||||
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();
|
||||
|
|
@ -1332,10 +1499,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)); }
|
||||
|
|
@ -1358,7 +1529,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;
|
||||
|
||||
|
|
@ -1396,6 +1567,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;
|
||||
|
|
@ -1413,11 +1587,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;
|
||||
|
|
@ -2329,13 +2511,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;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -123,7 +123,9 @@ int LibertyInputStream::peek_cold(size_t offset)
|
|||
if (!extend_buffer_at_least(offset + 1))
|
||||
return EOF;
|
||||
}
|
||||
|
||||
#ifdef log_assert
|
||||
log_assert(buf_pos + offset < buffer.size());
|
||||
#endif
|
||||
return buffer[buf_pos + offset];
|
||||
}
|
||||
|
||||
|
|
@ -458,7 +460,6 @@ int LibertyParser::lexer_inner(std::string &str)
|
|||
// if it wasn't an identifer, number of array range,
|
||||
// maybe it's a string?
|
||||
if (c == '"') {
|
||||
f.consume(1);
|
||||
size_t i = 0;
|
||||
while (true) {
|
||||
c = f.peek(i);
|
||||
|
|
@ -469,14 +470,13 @@ int LibertyParser::lexer_inner(std::string &str)
|
|||
break;
|
||||
}
|
||||
str.clear();
|
||||
f.unget();
|
||||
str.append(f.buffered_data(), f.buffered_data() + i + 1);
|
||||
str.append(f.buffered_data(), f.buffered_data() + i);
|
||||
// Usage in filterlib is expected to retain quotes
|
||||
// but yosys expects to get unquoted
|
||||
#ifdef FILTERLIB
|
||||
str = "\"" + str + "\"";
|
||||
#endif
|
||||
f.consume(i + 2);
|
||||
f.consume(i + 1);
|
||||
return 'v';
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ pyosys_headers = [
|
|||
),
|
||||
PyosysClass("SigChunk"),
|
||||
PyosysClass("SigBit", hash_expr="s"),
|
||||
PyosysClass("SigSpec", hash_expr="s"),
|
||||
PyosysClass("SigSpec", hash_expr="s", denylist={"chunks"}),
|
||||
PyosysClass(
|
||||
"Cell",
|
||||
ref_only=True,
|
||||
|
|
|
|||
|
|
@ -38,3 +38,20 @@ module foo(
|
|||
assign b = bb;
|
||||
assign y = a + bb;
|
||||
endmodule
|
||||
|
||||
module set_param #(
|
||||
parameter [3:0] VALUE = 1'bx
|
||||
) (
|
||||
output logic [3:0] out
|
||||
);
|
||||
assign out = VALUE;
|
||||
endmodule
|
||||
|
||||
module use_param (
|
||||
output logic [3:0] a, b, c, d
|
||||
);
|
||||
set_param #($signed(1)) spa (a);
|
||||
set_param #('1) spb (b);
|
||||
set_param #(1.1) spc (c);
|
||||
set_param #(1'b1) spd (d);
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
package package_import_specific;
|
||||
|
||||
localparam integer
|
||||
DATA_WIDTH = 8,
|
||||
ADDR_WIDTH = 4;
|
||||
|
||||
localparam logic [2:0]
|
||||
IDLE = 3'b000,
|
||||
START = 3'b001,
|
||||
DATA = 3'b010,
|
||||
STOP = 3'b100,
|
||||
DONE = 3'b101;
|
||||
|
||||
endpackage
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
read_verilog -sv package_import_specific.sv
|
||||
read_verilog -sv package_import_specific_module.sv
|
||||
hierarchy -check
|
||||
proc
|
||||
opt -full
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
import package_import_specific::DATA_WIDTH;
|
||||
import package_import_specific::IDLE;
|
||||
|
||||
module package_import_specific_module;
|
||||
logic [DATA_WIDTH-1:0] data;
|
||||
logic [3:0] addr;
|
||||
logic [2:0] state;
|
||||
|
||||
always_comb begin
|
||||
case (state)
|
||||
IDLE: data = 8'h00;
|
||||
default: data = 8'hFF;
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -5,7 +5,20 @@ module pass_through(
|
|||
assign out = inp;
|
||||
endmodule
|
||||
|
||||
module set_param #(
|
||||
parameter logic [63:0] VALUE
|
||||
) (
|
||||
output logic [63:0] out
|
||||
);
|
||||
assign out = VALUE;
|
||||
endmodule
|
||||
|
||||
module top;
|
||||
localparam logic [63:0]
|
||||
l01 = '0,
|
||||
l02 = '1,
|
||||
l03 = 'x,
|
||||
l04 = 'z;
|
||||
logic [63:0]
|
||||
o01, o02, o03, o04,
|
||||
o05, o06, o07, o08,
|
||||
|
|
@ -23,6 +36,10 @@ module top;
|
|||
pass_through pt10('1, o10);
|
||||
pass_through pt11('x, o11);
|
||||
pass_through pt12('z, o12);
|
||||
set_param #('0) sp13(o13);
|
||||
set_param #('1) sp14(o14);
|
||||
set_param #('x) sp15(o15);
|
||||
set_param #('z) sp16(o16);
|
||||
always @* begin
|
||||
assert (o01 === {64 {1'b0}});
|
||||
assert (o02 === {64 {1'b1}});
|
||||
|
|
@ -36,5 +53,13 @@ module top;
|
|||
assert (o10 === {64 {1'b1}});
|
||||
assert (o11 === {64 {1'bx}});
|
||||
assert (o12 === {64 {1'bz}});
|
||||
assert (l01 === {64 {1'b0}});
|
||||
assert (l02 === {64 {1'b1}});
|
||||
assert (l03 === {64 {1'bx}});
|
||||
assert (l04 === {64 {1'bz}});
|
||||
assert (o13 === {64 {1'b0}});
|
||||
assert (o14 === {64 {1'b1}});
|
||||
assert (o15 === {64 {1'bx}});
|
||||
assert (o16 === {64 {1'bz}});
|
||||
end
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
read_verilog -sv unbased_unsized.sv
|
||||
hierarchy
|
||||
hierarchy -top top
|
||||
proc
|
||||
flatten
|
||||
opt -full
|
||||
|
|
|
|||
Loading…
Reference in New Issue