mirror of
https://github.com/YosysHQ/yosys
synced 2026-03-02 11:46:57 +00:00
Merge branch 'main' into emil/turbo-celltypes
This commit is contained in:
commit
2a2c91e78a
265 changed files with 11258 additions and 3014 deletions
|
|
@ -291,7 +291,7 @@ static RTLIL::Const const_shift_worker(const RTLIL::Const &arg1, const RTLIL::Co
|
|||
if (pos < 0)
|
||||
result.set(i, vacant_bits);
|
||||
else if (pos >= BigInteger(GetSize(arg1)))
|
||||
result.set(i, sign_ext ? arg1.back() : vacant_bits);
|
||||
result.set(i, sign_ext && !arg1.empty() ? arg1.back() : vacant_bits);
|
||||
else
|
||||
result.set(i, arg1[pos.toInt()]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -185,50 +185,68 @@ struct AigMaker
|
|||
|
||||
int or_gate(int A, int B)
|
||||
{
|
||||
return nand_gate(not_gate(A), not_gate(B));
|
||||
int not_a = not_gate(A);
|
||||
int not_b = not_gate(B);
|
||||
return nand_gate(not_a, not_b);
|
||||
}
|
||||
|
||||
int nor_gate(int A, int B)
|
||||
{
|
||||
return and_gate(not_gate(A), not_gate(B));
|
||||
int not_a = not_gate(A);
|
||||
int not_b = not_gate(B);
|
||||
return and_gate(not_a, not_b);
|
||||
}
|
||||
|
||||
int xor_gate(int A, int B)
|
||||
{
|
||||
return nor_gate(and_gate(A, B), nor_gate(A, B));
|
||||
int a_and_b = and_gate(A, B);
|
||||
int a_nor_b = nor_gate(A, B);
|
||||
return nor_gate(a_and_b, a_nor_b);
|
||||
}
|
||||
|
||||
int xnor_gate(int A, int B)
|
||||
{
|
||||
return or_gate(and_gate(A, B), nor_gate(A, B));
|
||||
int a_and_b = and_gate(A, B);
|
||||
int a_nor_b = nor_gate(A, B);
|
||||
return or_gate(a_and_b, a_nor_b);
|
||||
}
|
||||
|
||||
int andnot_gate(int A, int B)
|
||||
{
|
||||
return and_gate(A, not_gate(B));
|
||||
int not_b = not_gate(B);
|
||||
return and_gate(A, not_b);
|
||||
}
|
||||
|
||||
int ornot_gate(int A, int B)
|
||||
{
|
||||
return or_gate(A, not_gate(B));
|
||||
int not_b = not_gate(B);
|
||||
return or_gate(A, not_b);
|
||||
}
|
||||
|
||||
int mux_gate(int A, int B, int S)
|
||||
{
|
||||
return or_gate(and_gate(A, not_gate(S)), and_gate(B, S));
|
||||
int not_s = not_gate(S);
|
||||
int a_active = and_gate(A, not_s);
|
||||
int b_active = and_gate(B, S);
|
||||
return or_gate(a_active, b_active);
|
||||
}
|
||||
|
||||
vector<int> adder(const vector<int> &A, const vector<int> &B, int carry, vector<int> *X = nullptr, vector<int> *CO = nullptr)
|
||||
vector<int> adder(const vector<int> &A, const vector<int> &B, int carry_in, vector<int> *X = nullptr, vector<int> *CO = nullptr)
|
||||
{
|
||||
vector<int> Y(GetSize(A));
|
||||
log_assert(GetSize(A) == GetSize(B));
|
||||
for (int i = 0; i < GetSize(A); i++) {
|
||||
Y[i] = xor_gate(xor_gate(A[i], B[i]), carry);
|
||||
carry = or_gate(and_gate(A[i], B[i]), and_gate(or_gate(A[i], B[i]), carry));
|
||||
int a_xor_b = xor_gate(A[i], B[i]);
|
||||
int a_or_b = or_gate(A[i], B[i]);
|
||||
int a_and_b = and_gate(A[i], B[i]);
|
||||
Y[i] = xor_gate(a_xor_b, carry_in);
|
||||
int tmp = and_gate(a_or_b, carry_in);
|
||||
int carry_out = or_gate(a_and_b, tmp);
|
||||
if (X != nullptr)
|
||||
X->at(i) = xor_gate(A[i], B[i]);
|
||||
X->at(i) = a_xor_b;
|
||||
if (CO != nullptr)
|
||||
CO->at(i) = carry;
|
||||
CO->at(i) = carry_out;
|
||||
carry_in = carry_out;
|
||||
}
|
||||
return Y;
|
||||
}
|
||||
|
|
@ -307,13 +325,13 @@ Aig::Aig(Cell *cell)
|
|||
int A = mk.inport(ID::A, i);
|
||||
int B = mk.inport(ID::B, i);
|
||||
int Y = cell->type.in(ID($and), ID($_AND_)) ? mk.and_gate(A, B) :
|
||||
cell->type.in(ID($_NAND_)) ? mk.nand_gate(A, B) :
|
||||
cell->type.in(ID($_NAND_)) ? mk.nand_gate(A, B) :
|
||||
cell->type.in(ID($or), ID($_OR_)) ? mk.or_gate(A, B) :
|
||||
cell->type.in(ID($_NOR_)) ? mk.nor_gate(A, B) :
|
||||
cell->type.in(ID($_NOR_)) ? mk.nor_gate(A, B) :
|
||||
cell->type.in(ID($xor), ID($_XOR_)) ? mk.xor_gate(A, B) :
|
||||
cell->type.in(ID($xnor), ID($_XNOR_)) ? mk.xnor_gate(A, B) :
|
||||
cell->type.in(ID($_ANDNOT_)) ? mk.andnot_gate(A, B) :
|
||||
cell->type.in(ID($_ORNOT_)) ? mk.ornot_gate(A, B) : -1;
|
||||
cell->type.in(ID($_ANDNOT_)) ? mk.andnot_gate(A, B) :
|
||||
cell->type.in(ID($_ORNOT_)) ? mk.ornot_gate(A, B) : -1;
|
||||
mk.outport(Y, ID::Y, i);
|
||||
}
|
||||
goto optimize;
|
||||
|
|
@ -465,7 +483,8 @@ Aig::Aig(Cell *cell)
|
|||
int B = mk.inport(ID::B);
|
||||
int C = mk.inport(ID::C);
|
||||
int D = mk.inport(ID::D);
|
||||
int Y = mk.nor_gate(mk.and_gate(A, B), mk.and_gate(C, D));
|
||||
int a_and_b = mk.and_gate(A, B);
|
||||
int Y = mk.nor_gate(a_and_b, mk.and_gate(C, D));
|
||||
mk.outport(Y, ID::Y);
|
||||
goto optimize;
|
||||
}
|
||||
|
|
@ -476,7 +495,8 @@ Aig::Aig(Cell *cell)
|
|||
int B = mk.inport(ID::B);
|
||||
int C = mk.inport(ID::C);
|
||||
int D = mk.inport(ID::D);
|
||||
int Y = mk.nand_gate(mk.or_gate(A, B), mk.or_gate(C, D));
|
||||
int a_or_b = mk.or_gate(A, B);
|
||||
int Y = mk.nand_gate(a_or_b, mk.or_gate(C, D));
|
||||
mk.outport(Y, ID::Y);
|
||||
goto optimize;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,6 +112,41 @@ void reduce_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
|||
db->add_edge(cell, ID::A, i, ID::Y, 0, -1);
|
||||
}
|
||||
|
||||
void logic_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
||||
{
|
||||
int a_width = GetSize(cell->getPort(ID::A));
|
||||
int b_width = GetSize(cell->getPort(ID::B));
|
||||
|
||||
for (int i = 0; i < a_width; i++)
|
||||
db->add_edge(cell, ID::A, i, ID::Y, 0, -1);
|
||||
for (int i = 0; i < b_width; i++)
|
||||
db->add_edge(cell, ID::B, i, ID::Y, 0, -1);
|
||||
}
|
||||
|
||||
void concat_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
||||
{
|
||||
int a_width = GetSize(cell->getPort(ID::A));
|
||||
int b_width = GetSize(cell->getPort(ID::B));
|
||||
|
||||
for (int i = 0; i < a_width; i++)
|
||||
db->add_edge(cell, ID::A, i, ID::Y, i, -1);
|
||||
for (int i = 0; i < b_width; i++)
|
||||
db->add_edge(cell, ID::B, i, ID::Y, a_width + i, -1);
|
||||
}
|
||||
|
||||
void slice_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
||||
{
|
||||
int offset = cell->getParam(ID::OFFSET).as_int();
|
||||
int a_width = GetSize(cell->getPort(ID::A));
|
||||
int y_width = GetSize(cell->getPort(ID::Y));
|
||||
|
||||
for (int i = 0; i < y_width; i++) {
|
||||
int a_bit = offset + i;
|
||||
if (a_bit >= 0 && a_bit < a_width)
|
||||
db->add_edge(cell, ID::A, a_bit, ID::Y, i, -1);
|
||||
}
|
||||
}
|
||||
|
||||
void compare_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
||||
{
|
||||
int a_width = GetSize(cell->getPort(ID::A));
|
||||
|
|
@ -254,7 +289,7 @@ void shift_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
|||
int skip = 1 << (k + 1);
|
||||
int base = skip -1;
|
||||
if (i % skip != base && i - a_width + 2 < 1 << b_width_capped)
|
||||
db->add_edge(cell, ID::B, k, ID::Y, i, -1);
|
||||
db->add_edge(cell, ID::B, k, ID::Y, i, -1);
|
||||
} else if (is_signed) {
|
||||
if (i - a_width + 2 < 1 << b_width_capped)
|
||||
db->add_edge(cell, ID::B, k, ID::Y, i, -1);
|
||||
|
|
@ -388,6 +423,64 @@ void ff_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
|||
db->add_edge(cell, ID::ARST, 0, ID::Q, k, -1);
|
||||
}
|
||||
|
||||
void full_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
||||
{
|
||||
std::vector<RTLIL::IdString> input_ports;
|
||||
std::vector<RTLIL::IdString> output_ports;
|
||||
|
||||
for (auto &conn : cell->connections())
|
||||
{
|
||||
RTLIL::IdString port = conn.first;
|
||||
RTLIL::PortDir dir = cell->port_dir(port);
|
||||
if (cell->input(port) || dir == RTLIL::PortDir::PD_INOUT)
|
||||
input_ports.push_back(port);
|
||||
if (cell->output(port) || dir == RTLIL::PortDir::PD_INOUT)
|
||||
output_ports.push_back(port);
|
||||
}
|
||||
|
||||
for (auto out_port : output_ports)
|
||||
{
|
||||
int out_width = GetSize(cell->getPort(out_port));
|
||||
for (int out_bit = 0; out_bit < out_width; out_bit++)
|
||||
{
|
||||
for (auto in_port : input_ports)
|
||||
{
|
||||
int in_width = GetSize(cell->getPort(in_port));
|
||||
for (int in_bit = 0; in_bit < in_width; in_bit++)
|
||||
db->add_edge(cell, in_port, in_bit, out_port, out_bit, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bweqx_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
||||
{
|
||||
int width = GetSize(cell->getPort(ID::Y));
|
||||
int a_width = GetSize(cell->getPort(ID::A));
|
||||
int b_width = GetSize(cell->getPort(ID::B));
|
||||
int max_width = std::min(width, std::min(a_width, b_width));
|
||||
|
||||
for (int i = 0; i < max_width; i++) {
|
||||
db->add_edge(cell, ID::A, i, ID::Y, i, -1);
|
||||
db->add_edge(cell, ID::B, i, ID::Y, i, -1);
|
||||
}
|
||||
}
|
||||
|
||||
void bwmux_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
|
||||
{
|
||||
int width = GetSize(cell->getPort(ID::Y));
|
||||
int a_width = GetSize(cell->getPort(ID::A));
|
||||
int b_width = GetSize(cell->getPort(ID::B));
|
||||
int s_width = GetSize(cell->getPort(ID::S));
|
||||
int max_width = std::min(width, std::min(a_width, std::min(b_width, s_width)));
|
||||
|
||||
for (int i = 0; i < max_width; i++) {
|
||||
db->add_edge(cell, ID::A, i, ID::Y, i, -1);
|
||||
db->add_edge(cell, ID::B, i, ID::Y, i, -1);
|
||||
db->add_edge(cell, ID::S, i, ID::Y, i, -1);
|
||||
}
|
||||
}
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
||||
|
||||
bool YOSYS_NAMESPACE_PREFIX AbstractCellEdgesDatabase::add_edges_from_cell(RTLIL::Cell *cell)
|
||||
|
|
@ -417,6 +510,21 @@ bool YOSYS_NAMESPACE_PREFIX AbstractCellEdgesDatabase::add_edges_from_cell(RTLIL
|
|||
return true;
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($logic_and), ID($logic_or))) {
|
||||
logic_op(this, cell);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cell->type == ID($slice)) {
|
||||
slice_op(this, cell);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cell->type == ID($concat)) {
|
||||
concat_op(this, cell);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx))) {
|
||||
shift_op(this, cell);
|
||||
return true;
|
||||
|
|
@ -442,6 +550,16 @@ bool YOSYS_NAMESPACE_PREFIX AbstractCellEdgesDatabase::add_edges_from_cell(RTLIL
|
|||
return true;
|
||||
}
|
||||
|
||||
if (cell->type == ID($bweqx)) {
|
||||
bweqx_op(this, cell);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cell->type == ID($bwmux)) {
|
||||
bwmux_op(this, cell);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cell->type.in(ID($mem_v2), ID($memrd), ID($memrd_v2), ID($memwr), ID($memwr_v2), ID($meminit))) {
|
||||
mem_op(this, cell);
|
||||
return true;
|
||||
|
|
@ -452,13 +570,24 @@ bool YOSYS_NAMESPACE_PREFIX AbstractCellEdgesDatabase::add_edges_from_cell(RTLIL
|
|||
return true;
|
||||
}
|
||||
|
||||
// FIXME: $mul $div $mod $divfloor $modfloor $slice $concat
|
||||
// FIXME: $lut $sop $alu $lcu $macc $macc_v2 $fa
|
||||
// FIXME: $mul $div $mod $divfloor $modfloor $pow $slice $concat $bweqx
|
||||
// FIXME: $lut $sop $alu $lcu $macc $fa $logic_and $logic_or $bwmux
|
||||
if (cell->type.in(ID($mul), ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($pow))) {
|
||||
full_op(this, cell);
|
||||
return true;
|
||||
}
|
||||
|
||||
// FIXME: $_BUF_ $_NOT_ $_AND_ $_NAND_ $_OR_ $_NOR_ $_XOR_ $_XNOR_ $_ANDNOT_ $_ORNOT_
|
||||
// FIXME: $_MUX_ $_NMUX_ $_MUX4_ $_MUX8_ $_MUX16_ $_AOI3_ $_OAI3_ $_AOI4_ $_OAI4_
|
||||
if (cell->type.in(ID($lut), ID($sop), ID($alu), ID($lcu), ID($macc), ID($macc_v2))) {
|
||||
full_op(this, cell);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cell->type.in(
|
||||
ID($_BUF_), ID($_NOT_), ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_),
|
||||
ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_), ID($_MUX_), ID($_NMUX_),
|
||||
ID($_MUX4_), ID($_MUX8_), ID($_MUX16_), ID($_AOI3_), ID($_OAI3_), ID($_AOI4_),
|
||||
ID($_OAI4_), ID($_TBUF_))) {
|
||||
full_op(this, cell);
|
||||
return true;
|
||||
}
|
||||
|
||||
// FIXME: $specify2 $specify3 $specrule ???
|
||||
// FIXME: $equiv $set_tag $get_tag $overwrite_tag $original_tag
|
||||
|
|
@ -468,4 +597,3 @@ bool YOSYS_NAMESPACE_PREFIX AbstractCellEdgesDatabase::add_edges_from_cell(RTLIL
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -305,18 +305,18 @@ struct CellTypes
|
|||
cell_types.clear();
|
||||
}
|
||||
|
||||
bool cell_known(const RTLIL::IdString &type) const
|
||||
bool cell_known(RTLIL::IdString type) const
|
||||
{
|
||||
return cell_types.count(type) != 0;
|
||||
}
|
||||
|
||||
bool cell_output(const RTLIL::IdString &type, const RTLIL::IdString &port) const
|
||||
bool cell_output(RTLIL::IdString type, RTLIL::IdString port) const
|
||||
{
|
||||
auto it = cell_types.find(type);
|
||||
return it != cell_types.end() && it->second.outputs.count(port) != 0;
|
||||
}
|
||||
|
||||
bool cell_input(const RTLIL::IdString &type, const RTLIL::IdString &port) const
|
||||
bool cell_input(RTLIL::IdString type, RTLIL::IdString port) const
|
||||
{
|
||||
auto it = cell_types.find(type);
|
||||
return it != cell_types.end() && it->second.inputs.count(port) != 0;
|
||||
|
|
@ -332,7 +332,7 @@ struct CellTypes
|
|||
return RTLIL::PortDir(is_input + is_output * 2);
|
||||
}
|
||||
|
||||
bool cell_evaluable(const RTLIL::IdString &type) const
|
||||
bool cell_evaluable(RTLIL::IdString type) const
|
||||
{
|
||||
auto it = cell_types.find(type);
|
||||
return it != cell_types.end() && it->second.is_evaluable;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,10 @@
|
|||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* ConstEval provides on-demand constant propagation by traversing input cones
|
||||
* with caching
|
||||
*/
|
||||
struct ConstEval
|
||||
{
|
||||
RTLIL::Module *module;
|
||||
|
|
|
|||
|
|
@ -255,6 +255,7 @@ int main(int argc, char **argv)
|
|||
("h,help", "print this help message. If given, print help for <command>.",
|
||||
cxxopts::value<std::string>(), "[<command>]")
|
||||
("V,version", "print version information and exit")
|
||||
("git-hash", "print git commit hash and exit")
|
||||
("infile", "input files", cxxopts::value<std::vector<std::string>>())
|
||||
;
|
||||
options.add_options("logging")
|
||||
|
|
@ -332,6 +333,10 @@ int main(int argc, char **argv)
|
|||
std::cout << yosys_version_str << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
if (result.count("git-hash")) {
|
||||
std::cout << yosys_git_hash_str << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
if (result.count("S")) {
|
||||
passes_commands.push_back("synth");
|
||||
run_shell = false;
|
||||
|
|
@ -764,33 +769,6 @@ int main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(YOSYS_ENABLE_COVER) && (defined(__linux__) || defined(__FreeBSD__))
|
||||
if (getenv("YOSYS_COVER_DIR") || getenv("YOSYS_COVER_FILE"))
|
||||
{
|
||||
string filename;
|
||||
FILE *f;
|
||||
|
||||
if (getenv("YOSYS_COVER_DIR")) {
|
||||
filename = stringf("%s/yosys_cover_%d_XXXXXX.txt", getenv("YOSYS_COVER_DIR"), getpid());
|
||||
filename = make_temp_file(filename);
|
||||
} else {
|
||||
filename = getenv("YOSYS_COVER_FILE");
|
||||
}
|
||||
|
||||
f = fopen(filename.c_str(), "a+");
|
||||
|
||||
if (f == NULL)
|
||||
log_error("Can't create coverage file `%s'.\n", filename);
|
||||
|
||||
log("<writing coverage file \"%s\">\n", filename);
|
||||
|
||||
for (auto &it : get_coverage_data())
|
||||
fprintf(f, "%-60s %10d %s\n", it.second.first.c_str(), it.second.second, it.first.c_str());
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
#endif
|
||||
|
||||
log_check_expected();
|
||||
|
||||
yosys_atexit();
|
||||
|
|
|
|||
|
|
@ -1321,6 +1321,12 @@ public:
|
|||
return i < 0 ? 0 : 1;
|
||||
}
|
||||
|
||||
int lookup(const K &key) const
|
||||
{
|
||||
Hasher::hash_t hash = database.do_hash(key);
|
||||
return database.do_lookup_no_rehash(key, hash);
|
||||
}
|
||||
|
||||
void expect(const K &key, int i)
|
||||
{
|
||||
int j = (*this)(key);
|
||||
|
|
|
|||
|
|
@ -602,7 +602,7 @@ void format_emit_string_view(std::string &result, std::string_view spec, int *dy
|
|||
}
|
||||
|
||||
void format_emit_idstring(std::string &result, std::string_view spec, int *dynamic_ints,
|
||||
DynamicIntCount num_dynamic_ints, const IdString &arg)
|
||||
DynamicIntCount num_dynamic_ints, const RTLIL::IdString &arg)
|
||||
{
|
||||
if (spec == "%s") {
|
||||
// Format checking will have guaranteed num_dynamic_ints == 0.
|
||||
|
|
|
|||
|
|
@ -90,11 +90,11 @@ int gettimeofday(struct timeval *tv, struct timezone *tz)
|
|||
QueryPerformanceFrequency(&freq);
|
||||
QueryPerformanceCounter(&counter);
|
||||
|
||||
counter.QuadPart *= 1000000;
|
||||
counter.QuadPart *= 1'000'000;
|
||||
counter.QuadPart /= freq.QuadPart;
|
||||
|
||||
tv->tv_sec = long(counter.QuadPart / 1000000);
|
||||
tv->tv_usec = counter.QuadPart % 1000000;
|
||||
tv->tv_usec = counter.QuadPart % 1'000'000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -135,7 +135,7 @@ static void logv_string(std::string_view format, std::string str) {
|
|||
initial_tv = tv;
|
||||
if (tv.tv_usec < initial_tv.tv_usec) {
|
||||
tv.tv_sec--;
|
||||
tv.tv_usec += 1000000;
|
||||
tv.tv_usec += 1'000'000;
|
||||
}
|
||||
tv.tv_sec -= initial_tv.tv_sec;
|
||||
tv.tv_usec -= initial_tv.tv_usec;
|
||||
|
|
@ -203,6 +203,8 @@ static void logv_string(std::string_view format, std::string str) {
|
|||
|
||||
void log_formatted_string(std::string_view format, std::string str)
|
||||
{
|
||||
log_assert(!Multithreading::active());
|
||||
|
||||
if (log_make_debug && !ys_debug(1))
|
||||
return;
|
||||
logv_string(format, std::move(str));
|
||||
|
|
@ -210,6 +212,8 @@ void log_formatted_string(std::string_view format, std::string str)
|
|||
|
||||
void log_formatted_header(RTLIL::Design *design, std::string_view format, std::string str)
|
||||
{
|
||||
log_assert(!Multithreading::active());
|
||||
|
||||
bool pop_errfile = false;
|
||||
|
||||
log_spacer();
|
||||
|
|
@ -249,6 +253,8 @@ void log_formatted_header(RTLIL::Design *design, std::string_view format, std::s
|
|||
|
||||
void log_formatted_warning(std::string_view prefix, std::string message)
|
||||
{
|
||||
log_assert(!Multithreading::active());
|
||||
|
||||
bool suppressed = false;
|
||||
|
||||
for (auto &re : log_nowarn_regexes)
|
||||
|
|
@ -681,55 +687,4 @@ void log_check_expected()
|
|||
check_err("prefixed error", pattern, item);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------
|
||||
// This is the magic behind the code coverage counters
|
||||
// ---------------------------------------------------
|
||||
#if defined(YOSYS_ENABLE_COVER) && (defined(__linux__) || defined(__FreeBSD__))
|
||||
|
||||
dict<std::string, std::pair<std::string, int>> extra_coverage_data;
|
||||
|
||||
void cover_extra(std::string parent, std::string id, bool increment) {
|
||||
if (extra_coverage_data.count(id) == 0) {
|
||||
for (CoverData *p = __start_yosys_cover_list; p != __stop_yosys_cover_list; p++)
|
||||
if (p->id == parent)
|
||||
extra_coverage_data[id].first = stringf("%s:%d:%s", p->file, p->line, p->func);
|
||||
log_assert(extra_coverage_data.count(id));
|
||||
}
|
||||
if (increment)
|
||||
extra_coverage_data[id].second++;
|
||||
}
|
||||
|
||||
dict<std::string, std::pair<std::string, int>> get_coverage_data()
|
||||
{
|
||||
dict<std::string, std::pair<std::string, int>> coverage_data;
|
||||
|
||||
for (auto &it : pass_register) {
|
||||
std::string key = stringf("passes.%s", it.first);
|
||||
coverage_data[key].first = stringf("%s:%d:%s", __FILE__, __LINE__, __FUNCTION__);
|
||||
coverage_data[key].second += it.second->call_counter;
|
||||
}
|
||||
|
||||
for (auto &it : extra_coverage_data) {
|
||||
if (coverage_data.count(it.first))
|
||||
log_warning("found duplicate coverage id \"%s\".\n", it.first);
|
||||
coverage_data[it.first].first = it.second.first;
|
||||
coverage_data[it.first].second += it.second.second;
|
||||
}
|
||||
|
||||
for (CoverData *p = __start_yosys_cover_list; p != __stop_yosys_cover_list; p++) {
|
||||
if (coverage_data.count(p->id))
|
||||
log_warning("found duplicate coverage id \"%s\".\n", p->id);
|
||||
coverage_data[p->id].first = stringf("%s:%d:%s", p->file, p->line, p->func);
|
||||
coverage_data[p->id].second += p->counter;
|
||||
}
|
||||
|
||||
for (auto &it : coverage_data)
|
||||
if (!it.second.first.compare(0, strlen(YOSYS_SRC "/"), YOSYS_SRC "/"))
|
||||
it.second.first = it.second.first.substr(strlen(YOSYS_SRC "/"));
|
||||
|
||||
return coverage_data;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
YOSYS_NAMESPACE_END
|
||||
|
|
|
|||
48
kernel/log.h
48
kernel/log.h
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include <time.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <regex>
|
||||
#define YS_REGEX_COMPILE(param) std::regex(param, \
|
||||
std::regex_constants::nosubs | \
|
||||
|
|
@ -290,53 +291,6 @@ void log_abort_internal(const char *file, int line);
|
|||
#define log_ping() YOSYS_NAMESPACE_PREFIX log("-- %s:%d %s --\n", __FILE__, __LINE__, __PRETTY_FUNCTION__)
|
||||
|
||||
|
||||
// ---------------------------------------------------
|
||||
// This is the magic behind the code coverage counters
|
||||
// ---------------------------------------------------
|
||||
|
||||
#if defined(YOSYS_ENABLE_COVER) && (defined(__linux__) || defined(__FreeBSD__))
|
||||
|
||||
#define cover(_id) do { \
|
||||
static CoverData __d __attribute__((section("yosys_cover_list"), aligned(1), used)) = { __FILE__, __FUNCTION__, _id, __LINE__, 0 }; \
|
||||
__d.counter++; \
|
||||
} while (0)
|
||||
|
||||
struct CoverData {
|
||||
const char *file, *func, *id;
|
||||
int line, counter;
|
||||
} YS_ATTRIBUTE(packed);
|
||||
|
||||
// this two symbols are created by the linker for the "yosys_cover_list" ELF section
|
||||
extern "C" struct CoverData __start_yosys_cover_list[];
|
||||
extern "C" struct CoverData __stop_yosys_cover_list[];
|
||||
|
||||
extern dict<std::string, std::pair<std::string, int>> extra_coverage_data;
|
||||
|
||||
void cover_extra(std::string parent, std::string id, bool increment = true);
|
||||
dict<std::string, std::pair<std::string, int>> get_coverage_data();
|
||||
|
||||
#define cover_list(_id, ...) do { cover(_id); \
|
||||
std::string r = cover_list_worker(_id, __VA_ARGS__); \
|
||||
log_assert(r.empty()); \
|
||||
} while (0)
|
||||
|
||||
static inline std::string cover_list_worker(std::string, std::string last) {
|
||||
return last;
|
||||
}
|
||||
|
||||
template<typename... T>
|
||||
std::string cover_list_worker(std::string prefix, std::string first, T... rest) {
|
||||
std::string selected = cover_list_worker(prefix, rest...);
|
||||
cover_extra(prefix, prefix + "." + first, first == selected);
|
||||
return first == selected ? "" : selected;
|
||||
}
|
||||
|
||||
#else
|
||||
# define cover(...) do { } while (0)
|
||||
# define cover_list(...) do { } while (0)
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// everything below this line are utilities for troubleshooting
|
||||
// ------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ ContentListing* ContentListing::open_option(const string &text,
|
|||
}
|
||||
|
||||
#define MAX_LINE_LEN 80
|
||||
void log_pass_str(const std::string &pass_str, std::string indent_str, bool leading_newline=false) {
|
||||
void log_body_str(const std::string &pass_str, std::string indent_str, bool leading_newline=false, bool is_formatted=false) {
|
||||
if (pass_str.empty())
|
||||
return;
|
||||
std::istringstream iss(pass_str);
|
||||
|
|
@ -86,26 +86,30 @@ void log_pass_str(const std::string &pass_str, std::string indent_str, bool lead
|
|||
log("\n");
|
||||
for (std::string line; std::getline(iss, line);) {
|
||||
log("%s", indent_str);
|
||||
auto curr_len = indent_str.length();
|
||||
std::istringstream lss(line);
|
||||
for (std::string word; std::getline(lss, word, ' ');) {
|
||||
while (word[0] == '`' && word.back() == '`')
|
||||
word = word.substr(1, word.length()-2);
|
||||
if (curr_len + word.length() >= MAX_LINE_LEN-1) {
|
||||
curr_len = 0;
|
||||
log("\n%s", indent_str);
|
||||
}
|
||||
if (word.length()) {
|
||||
log("%s ", word);
|
||||
curr_len += word.length() + 1;
|
||||
if (is_formatted) {
|
||||
log("%s", line);
|
||||
} else {
|
||||
auto curr_len = indent_str.length();
|
||||
std::istringstream lss(line);
|
||||
for (std::string word; std::getline(lss, word, ' ');) {
|
||||
while (word[0] == '`' && word.back() == '`')
|
||||
word = word.substr(1, word.length()-2);
|
||||
if (curr_len + word.length() >= MAX_LINE_LEN-1) {
|
||||
curr_len = 0;
|
||||
log("\n%s", indent_str);
|
||||
}
|
||||
if (word.length()) {
|
||||
log("%s ", word);
|
||||
curr_len += word.length() + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
log("\n");
|
||||
}
|
||||
}
|
||||
void log_pass_str(const std::string &pass_str, int indent=0, bool leading_newline=false) {
|
||||
void log_body(const ContentListing &content, int indent=0, bool leading_newline=false) {
|
||||
std::string indent_str(indent*4, ' ');
|
||||
log_pass_str(pass_str, indent_str, leading_newline);
|
||||
log_body_str(content.body, indent_str, leading_newline, content.type.compare("code") == 0);
|
||||
}
|
||||
|
||||
PrettyHelp *current_help = nullptr;
|
||||
|
|
@ -134,16 +138,16 @@ void PrettyHelp::log_help() const
|
|||
{
|
||||
for (auto &content : _root_listing) {
|
||||
if (content.type.compare("usage") == 0) {
|
||||
log_pass_str(content.body, 1, true);
|
||||
log_body(content, 1, true);
|
||||
log("\n");
|
||||
} else if (content.type.compare("option") == 0) {
|
||||
log_pass_str(content.body, 1);
|
||||
log_body(content, 1);
|
||||
for (auto text : content) {
|
||||
log_pass_str(text.body, 2);
|
||||
log_body(text, 2);
|
||||
log("\n");
|
||||
}
|
||||
} else {
|
||||
log_pass_str(content.body, 0);
|
||||
log_body(content, 0);
|
||||
log("\n");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,22 @@ YOSYS_NAMESPACE_BEGIN
|
|||
|
||||
struct ModIndex : public RTLIL::Monitor
|
||||
{
|
||||
struct PointerOrderedSigBit : public RTLIL::SigBit {
|
||||
PointerOrderedSigBit(SigBit s) {
|
||||
wire = s.wire;
|
||||
if (wire)
|
||||
offset = s.offset;
|
||||
else
|
||||
data = s.data;
|
||||
}
|
||||
inline bool operator<(const RTLIL::SigBit &other) const {
|
||||
if (wire == other.wire)
|
||||
return wire ? (offset < other.offset) : (data < other.data);
|
||||
if (wire != nullptr && other.wire != nullptr)
|
||||
return wire < other.wire; // look here
|
||||
return (wire != nullptr) < (other.wire != nullptr);
|
||||
}
|
||||
};
|
||||
struct PortInfo {
|
||||
RTLIL::Cell* cell;
|
||||
RTLIL::IdString port;
|
||||
|
|
@ -78,7 +94,7 @@ struct ModIndex : public RTLIL::Monitor
|
|||
|
||||
SigMap sigmap;
|
||||
RTLIL::Module *module;
|
||||
std::map<RTLIL::SigBit, SigBitInfo> database;
|
||||
std::map<PointerOrderedSigBit, SigBitInfo> database;
|
||||
int auto_reload_counter;
|
||||
bool auto_reload_module;
|
||||
|
||||
|
|
@ -95,8 +111,11 @@ struct ModIndex : public RTLIL::Monitor
|
|||
{
|
||||
for (int i = 0; i < GetSize(sig); i++) {
|
||||
RTLIL::SigBit bit = sigmap(sig[i]);
|
||||
if (bit.wire)
|
||||
if (bit.wire) {
|
||||
database[bit].ports.erase(PortInfo(cell, port, i));
|
||||
if (!database[bit].is_input && !database[bit].is_output && database[bit].ports.empty())
|
||||
database.erase(bit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -133,11 +152,11 @@ struct ModIndex : public RTLIL::Monitor
|
|||
}
|
||||
}
|
||||
|
||||
void check()
|
||||
bool ok()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (auto_reload_module)
|
||||
return;
|
||||
return true;
|
||||
|
||||
for (auto it : database)
|
||||
log_assert(it.first == sigmap(it.first));
|
||||
|
|
@ -157,12 +176,18 @@ struct ModIndex : public RTLIL::Monitor
|
|||
else if (!(it.second == database_bak.at(it.first)))
|
||||
log("ModuleIndex::check(): Different content for database[%s].\n", log_signal(it.first));
|
||||
|
||||
log_assert(database == database_bak);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, const RTLIL::SigSpec &sig) override
|
||||
void check()
|
||||
{
|
||||
log_assert(ok());
|
||||
}
|
||||
|
||||
void notify_connect(RTLIL::Cell *cell, RTLIL::IdString port, const RTLIL::SigSpec &old_sig, const RTLIL::SigSpec &sig) override
|
||||
{
|
||||
log_assert(module == cell->module);
|
||||
|
||||
|
|
|
|||
102
kernel/pattern.h
Normal file
102
kernel/pattern.h
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
#ifndef OPT_DFF_COMP_H
|
||||
#define OPT_DFF_COMP_H
|
||||
|
||||
#include "kernel/rtlil.h"
|
||||
#include <map>
|
||||
#include <optional>
|
||||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* Pattern matching utilities for control signal analysis.
|
||||
*
|
||||
* A pattern_t maps control signals to required values, representing a
|
||||
* product term (conjunction): {A=1, B=0} means "A AND !B".
|
||||
*
|
||||
* A patterns_t is a set of patterns representing a sum-of-products:
|
||||
* {{A=1, B=0}, {A=0, C=1}} means "(A AND !B) OR (!A AND C)".
|
||||
*
|
||||
* Used for analyzing MUX tree control paths in DFF optimization.
|
||||
*/
|
||||
|
||||
// Pattern matching for clock enable
|
||||
// A pattern maps control signals to their required values for a MUX path
|
||||
typedef std::map<RTLIL::SigBit, bool> pattern_t; // Set of control signals that must ALL match required vals
|
||||
typedef std::set<pattern_t> patterns_t; // Alternative patterns (OR)
|
||||
typedef std::pair<RTLIL::SigBit, bool> ctrl_t; // Control signal
|
||||
typedef std::set<ctrl_t> ctrls_t; // Set of control signals that must ALL be active
|
||||
|
||||
/**
|
||||
* Find if two patterns differ in exactly one variable.
|
||||
* Example: {A=1,B=1} vs {A=1,B=0} returns B, allows simplification: (A&B) | (A&!B) => A
|
||||
*/
|
||||
inline std::optional<RTLIL::SigBit> find_complementary_pattern_var(
|
||||
const pattern_t& left,
|
||||
const pattern_t& right
|
||||
) {
|
||||
std::optional<RTLIL::SigBit> ret;
|
||||
for (const auto &pt : left) {
|
||||
// Left requires signal that right doesn't constrain - incompatible domains
|
||||
if (right.count(pt.first) == 0)
|
||||
return std::nullopt;
|
||||
// Signal has same required value in both - not the complement variable
|
||||
if (right.at(pt.first) == pt.second)
|
||||
continue;
|
||||
// Already found one differing signal, now found another - not simplifiable
|
||||
if (ret)
|
||||
return std::nullopt;
|
||||
// First differing signal - candidate complement variable
|
||||
ret = pt.first;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplify a sum-of-products by merging complementary patterns: (A&B) | (A&!B) => A,
|
||||
* and removing redundant patterns: A | (A&B) => A
|
||||
*/
|
||||
inline void simplify_patterns(patterns_t& patterns) {
|
||||
auto new_patterns = patterns;
|
||||
|
||||
// Merge complementary patterns
|
||||
bool optimized;
|
||||
do {
|
||||
optimized = false;
|
||||
for (auto i = patterns.begin(); i != patterns.end(); i++) {
|
||||
for (auto j = std::next(i, 1); j != patterns.end(); j++) {
|
||||
const auto& left = (GetSize(*j) <= GetSize(*i)) ? *j : *i;
|
||||
auto right = (GetSize(*i) < GetSize(*j)) ? *j : *i;
|
||||
const auto complementary_var = find_complementary_pattern_var(left, right);
|
||||
|
||||
if (complementary_var && new_patterns.count(right)) {
|
||||
new_patterns.erase(right);
|
||||
right.erase(complementary_var.value());
|
||||
new_patterns.insert(right);
|
||||
optimized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
patterns = new_patterns;
|
||||
} while(optimized);
|
||||
|
||||
// Remove redundant patterns
|
||||
for (auto i = patterns.begin(); i != patterns.end(); ++i) {
|
||||
for (auto j = std::next(i, 1); j != patterns.end(); ++j) {
|
||||
const auto& left = (GetSize(*j) <= GetSize(*i)) ? *j : *i;
|
||||
const auto& right = (GetSize(*i) < GetSize(*j)) ? *j : *i;
|
||||
bool redundant = true;
|
||||
|
||||
for (const auto& pt : left)
|
||||
if (right.count(pt.first) == 0 || right.at(pt.first) != pt.second)
|
||||
redundant = false;
|
||||
if (redundant)
|
||||
new_patterns.erase(right);
|
||||
}
|
||||
}
|
||||
|
||||
patterns = std::move(new_patterns);
|
||||
}
|
||||
|
||||
YOSYS_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
|
|
@ -1207,7 +1207,7 @@ struct LicensePass : public Pass {
|
|||
log(" | |\n");
|
||||
log(" | yosys -- Yosys Open SYnthesis Suite |\n");
|
||||
log(" | |\n");
|
||||
log(" | Copyright (C) 2012 - 2025 Claire Xenia Wolf <claire@yosyshq.com> |\n");
|
||||
log(" | Copyright (C) 2012 - 2026 Claire Xenia Wolf <claire@yosyshq.com> |\n");
|
||||
log(" | |\n");
|
||||
log(" | Permission to use, copy, modify, and/or distribute this software for any |\n");
|
||||
log(" | purpose with or without fee is hereby granted, provided that the above |\n");
|
||||
|
|
|
|||
343
kernel/rtlil.cc
343
kernel/rtlil.cc
File diff suppressed because it is too large
Load diff
174
kernel/rtlil.h
174
kernel/rtlil.h
|
|
@ -134,6 +134,17 @@ struct RTLIL::IdString
|
|||
|
||||
std::string_view str_view() const { return {buf, static_cast<size_t>(size)}; }
|
||||
};
|
||||
struct AutoidxStorage {
|
||||
// Append the negated (i.e. positive) ID to this string to get
|
||||
// the real string. The prefix strings must live forever.
|
||||
const std::string *prefix;
|
||||
// Cache of the full string, or nullptr if not cached yet.
|
||||
std::atomic<char *> full_str;
|
||||
|
||||
AutoidxStorage(const std::string *prefix) : prefix(prefix), full_str(nullptr) {}
|
||||
AutoidxStorage(AutoidxStorage&& other) : prefix(other.prefix), full_str(other.full_str.exchange(nullptr, std::memory_order_relaxed)) {}
|
||||
~AutoidxStorage() { delete[] full_str.load(std::memory_order_acquire); }
|
||||
};
|
||||
|
||||
// the global id string cache
|
||||
|
||||
|
|
@ -147,17 +158,12 @@ struct RTLIL::IdString
|
|||
static std::vector<Storage> global_id_storage_;
|
||||
// Lookup table for non-autoidx IDs
|
||||
static std::unordered_map<std::string_view, int> global_id_index_;
|
||||
// Shared prefix string storage for autoidx IDs, which have negative
|
||||
// indices. Append the negated (i.e. positive) ID to this string to get
|
||||
// the real string. The prefix strings must live forever.
|
||||
static std::unordered_map<int, const std::string*> global_autoidx_id_prefix_storage_;
|
||||
// Explicit string storage for autoidx IDs
|
||||
static std::unordered_map<int, char*> global_autoidx_id_storage_;
|
||||
#ifndef YOSYS_NO_IDS_REFCNT
|
||||
// Storage for autoidx IDs, which have negative indices, i.e. all entries in this
|
||||
// map have negative keys.
|
||||
static std::unordered_map<int, AutoidxStorage> global_autoidx_id_storage_;
|
||||
// All (index, refcount) pairs in this map have refcount > 0.
|
||||
static std::unordered_map<int, int> global_refcount_storage_;
|
||||
static std::vector<int> global_free_idx_list_;
|
||||
#endif
|
||||
|
||||
static int refcount(int idx) {
|
||||
auto it = global_refcount_storage_.find(idx);
|
||||
|
|
@ -189,6 +195,7 @@ struct RTLIL::IdString
|
|||
static int insert(std::string_view p)
|
||||
{
|
||||
log_assert(destruct_guard_ok);
|
||||
log_assert(!Multithreading::active());
|
||||
|
||||
auto it = global_id_index_.find(p);
|
||||
if (it != global_id_index_.end()) {
|
||||
|
|
@ -204,8 +211,9 @@ struct RTLIL::IdString
|
|||
// Inserts an ID with string `prefix + autoidx', incrementing autoidx.
|
||||
// `prefix` must start with '$auto$', end with '$', and live forever.
|
||||
static IdString new_autoidx_with_prefix(const std::string *prefix) {
|
||||
log_assert(!Multithreading::active());
|
||||
int index = -(autoidx++);
|
||||
global_autoidx_id_prefix_storage_.insert({index, prefix});
|
||||
global_autoidx_id_storage_.insert({index, prefix});
|
||||
return from_index(index);
|
||||
}
|
||||
|
||||
|
|
@ -215,8 +223,8 @@ struct RTLIL::IdString
|
|||
|
||||
constexpr inline IdString() : index_(0) { }
|
||||
inline IdString(const char *str) : index_(insert(std::string_view(str))) { }
|
||||
constexpr inline IdString(const IdString &str) : index_(str.index_) { }
|
||||
inline IdString(IdString &&str) : index_(str.index_) { str.index_ = 0; }
|
||||
constexpr IdString(const IdString &str) = default;
|
||||
IdString(IdString &&str) = default;
|
||||
inline IdString(const std::string &str) : index_(insert(std::string_view(str))) { }
|
||||
inline IdString(std::string_view str) : index_(insert(str)) { }
|
||||
constexpr inline IdString(StaticId id) : index_(static_cast<short>(id)) {}
|
||||
|
|
@ -233,22 +241,23 @@ struct RTLIL::IdString
|
|||
*this = id;
|
||||
}
|
||||
|
||||
constexpr inline const IdString &id_string() const { return *this; }
|
||||
|
||||
inline const char *c_str() const {
|
||||
if (index_ >= 0)
|
||||
return global_id_storage_.at(index_).buf;
|
||||
auto it = global_autoidx_id_storage_.find(index_);
|
||||
if (it != global_autoidx_id_storage_.end())
|
||||
return it->second;
|
||||
|
||||
const std::string &prefix = *global_autoidx_id_prefix_storage_.at(index_);
|
||||
AutoidxStorage &s = global_autoidx_id_storage_.at(index_);
|
||||
char *full_str = s.full_str.load(std::memory_order_acquire);
|
||||
if (full_str != nullptr)
|
||||
return full_str;
|
||||
const std::string &prefix = *s.prefix;
|
||||
std::string suffix = std::to_string(-index_);
|
||||
char *c = new char[prefix.size() + suffix.size() + 1];
|
||||
memcpy(c, prefix.data(), prefix.size());
|
||||
memcpy(c + prefix.size(), suffix.c_str(), suffix.size() + 1);
|
||||
global_autoidx_id_storage_.insert(it, {index_, c});
|
||||
return c;
|
||||
if (s.full_str.compare_exchange_strong(full_str, c, std::memory_order_acq_rel))
|
||||
return c;
|
||||
delete[] c;
|
||||
return full_str;
|
||||
}
|
||||
|
||||
inline std::string str() const {
|
||||
|
|
@ -262,7 +271,7 @@ struct RTLIL::IdString
|
|||
*out += global_id_storage_.at(index_).str_view();
|
||||
return;
|
||||
}
|
||||
*out += *global_autoidx_id_prefix_storage_.at(index_);
|
||||
*out += *global_autoidx_id_storage_.at(index_).prefix;
|
||||
*out += std::to_string(-index_);
|
||||
}
|
||||
|
||||
|
|
@ -348,7 +357,7 @@ struct RTLIL::IdString
|
|||
if (index_ >= 0) {
|
||||
return const_iterator(global_id_storage_.at(index_));
|
||||
}
|
||||
return const_iterator(global_autoidx_id_prefix_storage_.at(index_), -index_);
|
||||
return const_iterator(global_autoidx_id_storage_.at(index_).prefix, -index_);
|
||||
}
|
||||
const_iterator end() const {
|
||||
return const_iterator();
|
||||
|
|
@ -358,10 +367,10 @@ struct RTLIL::IdString
|
|||
if (index_ >= 0) {
|
||||
return Substrings(global_id_storage_.at(index_));
|
||||
}
|
||||
return Substrings(global_autoidx_id_prefix_storage_.at(index_), -index_);
|
||||
return Substrings(global_autoidx_id_storage_.at(index_).prefix, -index_);
|
||||
}
|
||||
|
||||
inline bool lt_by_name(const IdString &rhs) const {
|
||||
inline bool lt_by_name(IdString rhs) const {
|
||||
Substrings lhs_it = substrings();
|
||||
Substrings rhs_it = rhs.substrings();
|
||||
std::string_view lhs_substr = lhs_it.first();
|
||||
|
|
@ -388,12 +397,12 @@ struct RTLIL::IdString
|
|||
}
|
||||
}
|
||||
|
||||
inline bool operator<(const IdString &rhs) const {
|
||||
inline bool operator<(IdString rhs) const {
|
||||
return index_ < rhs.index_;
|
||||
}
|
||||
|
||||
inline bool operator==(const IdString &rhs) const { return index_ == rhs.index_; }
|
||||
inline bool operator!=(const IdString &rhs) const { return index_ != rhs.index_; }
|
||||
inline bool operator==(IdString rhs) const { return index_ == rhs.index_; }
|
||||
inline bool operator!=(IdString rhs) const { return index_ != rhs.index_; }
|
||||
|
||||
// The methods below are just convenience functions for better compatibility with std::string.
|
||||
|
||||
|
|
@ -411,7 +420,7 @@ struct RTLIL::IdString
|
|||
#endif
|
||||
return *(storage.buf + i);
|
||||
}
|
||||
const std::string &id_start = *global_autoidx_id_prefix_storage_.at(index_);
|
||||
const std::string &id_start = *global_autoidx_id_storage_.at(index_).prefix;
|
||||
if (i < id_start.size())
|
||||
return id_start[i];
|
||||
i -= id_start.size();
|
||||
|
|
@ -517,7 +526,7 @@ struct RTLIL::IdString
|
|||
return (... || in(args));
|
||||
}
|
||||
|
||||
bool in(const IdString &rhs) const { return *this == rhs; }
|
||||
bool in(IdString rhs) const { return *this == rhs; }
|
||||
bool in(const char *rhs) const { return *this == rhs; }
|
||||
bool in(const std::string &rhs) const { return *this == rhs; }
|
||||
inline bool in(const pool<IdString> &rhs) const;
|
||||
|
|
@ -597,7 +606,8 @@ private:
|
|||
}
|
||||
static void get_reference(int idx)
|
||||
{
|
||||
#ifndef YOSYS_NO_IDS_REFCNT
|
||||
log_assert(!Multithreading::active());
|
||||
|
||||
if (idx < static_cast<short>(StaticId::STATIC_ID_END))
|
||||
return;
|
||||
auto it = global_refcount_storage_.find(idx);
|
||||
|
|
@ -605,7 +615,6 @@ private:
|
|||
global_refcount_storage_.insert(it, {idx, 1});
|
||||
else
|
||||
++it->second;
|
||||
#endif
|
||||
#ifdef YOSYS_XTRACE_GET_PUT
|
||||
if (yosys_xtrace && idx >= static_cast<short>(StaticId::STATIC_ID_END))
|
||||
log("#X# GET-BY-INDEX '%s' (index %d, refcount %u)\n", from_index(idx), idx, refcount(idx));
|
||||
|
|
@ -614,7 +623,8 @@ private:
|
|||
|
||||
void put_reference()
|
||||
{
|
||||
#ifndef YOSYS_NO_IDS_REFCNT
|
||||
log_assert(!Multithreading::active());
|
||||
|
||||
// put_reference() may be called from destructors after the destructor of
|
||||
// global_refcount_storage_ has been run. in this case we simply do nothing.
|
||||
if (index_ < static_cast<short>(StaticId::STATIC_ID_END) || !destruct_guard_ok)
|
||||
|
|
@ -628,20 +638,19 @@ private:
|
|||
if (--it->second == 0) {
|
||||
global_refcount_storage_.erase(it);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
namespace hashlib {
|
||||
template <>
|
||||
struct hash_ops<RTLIL::IdString> {
|
||||
static inline bool cmp(const RTLIL::IdString &a, const RTLIL::IdString &b) {
|
||||
static inline bool cmp(RTLIL::IdString a, RTLIL::IdString b) {
|
||||
return a == b;
|
||||
}
|
||||
[[nodiscard]] static inline Hasher hash(const RTLIL::IdString &id) {
|
||||
[[nodiscard]] static inline Hasher hash(RTLIL::IdString id) {
|
||||
return id.hash_top();
|
||||
}
|
||||
[[nodiscard]] static inline Hasher hash_into(const RTLIL::IdString &id, Hasher h) {
|
||||
[[nodiscard]] static inline Hasher hash_into(RTLIL::IdString id, Hasher h) {
|
||||
return id.hash_into(h);
|
||||
}
|
||||
};
|
||||
|
|
@ -748,11 +757,11 @@ namespace RTLIL {
|
|||
return str.substr(1);
|
||||
}
|
||||
|
||||
static inline std::string unescape_id(const RTLIL::IdString &str) {
|
||||
static inline std::string unescape_id(RTLIL::IdString str) {
|
||||
return unescape_id(str.str());
|
||||
}
|
||||
|
||||
static inline const char *id2cstr(const RTLIL::IdString &str) {
|
||||
static inline const char *id2cstr(RTLIL::IdString str) {
|
||||
return log_id(str);
|
||||
}
|
||||
|
||||
|
|
@ -769,7 +778,7 @@ namespace RTLIL {
|
|||
};
|
||||
|
||||
struct sort_by_id_str {
|
||||
bool operator()(const RTLIL::IdString &a, const RTLIL::IdString &b) const {
|
||||
bool operator()(RTLIL::IdString a, RTLIL::IdString b) const {
|
||||
return a.lt_by_name(b);
|
||||
}
|
||||
};
|
||||
|
|
@ -1235,22 +1244,22 @@ struct RTLIL::AttrObject
|
|||
{
|
||||
dict<RTLIL::IdString, RTLIL::Const> attributes;
|
||||
|
||||
bool has_attribute(const RTLIL::IdString &id) const;
|
||||
bool has_attribute(RTLIL::IdString id) const;
|
||||
|
||||
void set_bool_attribute(const RTLIL::IdString &id, bool value=true);
|
||||
bool get_bool_attribute(const RTLIL::IdString &id) const;
|
||||
void set_bool_attribute(RTLIL::IdString id, bool value=true);
|
||||
bool get_bool_attribute(RTLIL::IdString id) const;
|
||||
|
||||
[[deprecated("Use Module::get_blackbox_attribute() instead.")]]
|
||||
bool get_blackbox_attribute(bool ignore_wb=false) const {
|
||||
return get_bool_attribute(ID::blackbox) || (!ignore_wb && get_bool_attribute(ID::whitebox));
|
||||
}
|
||||
|
||||
void set_string_attribute(const RTLIL::IdString& id, string value);
|
||||
string get_string_attribute(const RTLIL::IdString &id) const;
|
||||
void set_string_attribute(RTLIL::IdString id, string value);
|
||||
string get_string_attribute(RTLIL::IdString id) const;
|
||||
|
||||
void set_strpool_attribute(const RTLIL::IdString& id, const pool<string> &data);
|
||||
void add_strpool_attribute(const RTLIL::IdString& id, const pool<string> &data);
|
||||
pool<string> get_strpool_attribute(const RTLIL::IdString &id) const;
|
||||
void set_strpool_attribute(RTLIL::IdString id, const pool<string> &data);
|
||||
void add_strpool_attribute(RTLIL::IdString id, const pool<string> &data);
|
||||
pool<string> get_strpool_attribute(RTLIL::IdString id) const;
|
||||
|
||||
void set_src_attribute(const std::string &src) {
|
||||
set_string_attribute(ID::src, src);
|
||||
|
|
@ -1262,8 +1271,8 @@ struct RTLIL::AttrObject
|
|||
void set_hdlname_attribute(const vector<string> &hierarchy);
|
||||
vector<string> get_hdlname_attribute() const;
|
||||
|
||||
void set_intvec_attribute(const RTLIL::IdString& id, const vector<int> &data);
|
||||
vector<int> get_intvec_attribute(const RTLIL::IdString &id) const;
|
||||
void set_intvec_attribute(RTLIL::IdString id, const vector<int> &data);
|
||||
vector<int> get_intvec_attribute(RTLIL::IdString id) const;
|
||||
};
|
||||
|
||||
struct RTLIL::NamedObject : public RTLIL::AttrObject
|
||||
|
|
@ -1770,18 +1779,18 @@ struct RTLIL::Selection
|
|||
|
||||
// checks if the given module exists in the current design and is a
|
||||
// boxed module, warning the user if the current design is not set
|
||||
bool boxed_module(const RTLIL::IdString &mod_name) const;
|
||||
bool boxed_module(RTLIL::IdString mod_name) const;
|
||||
|
||||
// checks if the given module is included in this selection
|
||||
bool selected_module(const RTLIL::IdString &mod_name) const;
|
||||
bool selected_module(RTLIL::IdString mod_name) const;
|
||||
|
||||
// checks if the given module is wholly included in this selection,
|
||||
// i.e. not partially selected
|
||||
bool selected_whole_module(const RTLIL::IdString &mod_name) const;
|
||||
bool selected_whole_module(RTLIL::IdString mod_name) const;
|
||||
|
||||
// checks if the given member from the given module is included in this
|
||||
// selection
|
||||
bool selected_member(const RTLIL::IdString &mod_name, const RTLIL::IdString &memb_name) const;
|
||||
bool selected_member(RTLIL::IdString mod_name, RTLIL::IdString memb_name) const;
|
||||
|
||||
// optimizes this selection for the given design by:
|
||||
// - removing non-existent modules and members, any boxed modules and
|
||||
|
|
@ -1851,7 +1860,7 @@ struct RTLIL::Monitor
|
|||
virtual ~Monitor() { }
|
||||
virtual void notify_module_add(RTLIL::Module*) { }
|
||||
virtual void notify_module_del(RTLIL::Module*) { }
|
||||
virtual void notify_connect(RTLIL::Cell*, const RTLIL::IdString&, const RTLIL::SigSpec&, const RTLIL::SigSpec&) { }
|
||||
virtual void notify_connect(RTLIL::Cell*, RTLIL::IdString, const RTLIL::SigSpec&, const RTLIL::SigSpec&) { }
|
||||
virtual void notify_connect(RTLIL::Module*, const RTLIL::SigSig&) { }
|
||||
virtual void notify_connect(RTLIL::Module*, const std::vector<RTLIL::SigSig>&) { }
|
||||
virtual void notify_blackout(RTLIL::Module*) { }
|
||||
|
|
@ -1886,11 +1895,11 @@ struct RTLIL::Design
|
|||
~Design();
|
||||
|
||||
RTLIL::ObjRange<RTLIL::Module*> modules();
|
||||
RTLIL::Module *module(const RTLIL::IdString &name);
|
||||
const RTLIL::Module *module(const RTLIL::IdString &name) const;
|
||||
RTLIL::Module *module(RTLIL::IdString name);
|
||||
const RTLIL::Module *module(RTLIL::IdString name) const;
|
||||
RTLIL::Module *top_module() const;
|
||||
|
||||
bool has(const RTLIL::IdString &id) const {
|
||||
bool has(RTLIL::IdString id) const {
|
||||
return modules_.count(id) != 0;
|
||||
}
|
||||
|
||||
|
|
@ -1917,15 +1926,15 @@ struct RTLIL::Design
|
|||
void optimize();
|
||||
|
||||
// checks if the given module is included in the current selection
|
||||
bool selected_module(const RTLIL::IdString &mod_name) const;
|
||||
bool selected_module(RTLIL::IdString mod_name) const;
|
||||
|
||||
// checks if the given module is wholly included in the current
|
||||
// selection, i.e. not partially selected
|
||||
bool selected_whole_module(const RTLIL::IdString &mod_name) const;
|
||||
bool selected_whole_module(RTLIL::IdString mod_name) const;
|
||||
|
||||
// checks if the given member from the given module is included in the
|
||||
// current selection
|
||||
bool selected_member(const RTLIL::IdString &mod_name, const RTLIL::IdString &memb_name) const;
|
||||
bool selected_member(RTLIL::IdString mod_name, RTLIL::IdString memb_name) const;
|
||||
|
||||
// checks if the given module is included in the current selection
|
||||
bool selected_module(RTLIL::Module *mod) const;
|
||||
|
|
@ -2022,7 +2031,10 @@ struct RTLIL::Design
|
|||
// returns all selected unboxed whole modules, warning the user if any
|
||||
// partially selected or boxed modules have been ignored
|
||||
std::vector<RTLIL::Module*> selected_unboxed_whole_modules_warn() const { return selected_modules(SELECT_WHOLE_WARN, SB_UNBOXED_WARN); }
|
||||
|
||||
static std::map<unsigned int, RTLIL::Design*> *get_all_designs(void);
|
||||
|
||||
std::string to_rtlil_str(bool only_selected = true) const;
|
||||
};
|
||||
|
||||
struct RTLIL::Module : public RTLIL::NamedObject
|
||||
|
|
@ -2057,7 +2069,7 @@ public:
|
|||
virtual ~Module();
|
||||
virtual RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> ¶meters, bool mayfail = false);
|
||||
virtual RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> ¶meters, const dict<RTLIL::IdString, RTLIL::Module*> &interfaces, const dict<RTLIL::IdString, RTLIL::IdString> &modports, bool mayfail = false);
|
||||
virtual size_t count_id(const RTLIL::IdString& id);
|
||||
virtual size_t count_id(RTLIL::IdString id);
|
||||
virtual void expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module *> &local_interfaces);
|
||||
virtual bool reprocess_if_necessary(RTLIL::Design *design);
|
||||
|
||||
|
|
@ -2109,32 +2121,37 @@ public:
|
|||
return design->selected_member(name, member->name);
|
||||
}
|
||||
|
||||
RTLIL::Wire* wire(const RTLIL::IdString &id) {
|
||||
RTLIL::Wire* wire(RTLIL::IdString id) {
|
||||
auto it = wires_.find(id);
|
||||
return it == wires_.end() ? nullptr : it->second;
|
||||
}
|
||||
RTLIL::Cell* cell(const RTLIL::IdString &id) {
|
||||
RTLIL::Cell* cell(RTLIL::IdString id) {
|
||||
auto it = cells_.find(id);
|
||||
return it == cells_.end() ? nullptr : it->second;
|
||||
}
|
||||
|
||||
const RTLIL::Wire* wire(const RTLIL::IdString &id) const{
|
||||
const RTLIL::Wire* wire(RTLIL::IdString id) const{
|
||||
auto it = wires_.find(id);
|
||||
return it == wires_.end() ? nullptr : it->second;
|
||||
}
|
||||
const RTLIL::Cell* cell(const RTLIL::IdString &id) const {
|
||||
const RTLIL::Cell* cell(RTLIL::IdString id) const {
|
||||
auto it = cells_.find(id);
|
||||
return it == cells_.end() ? nullptr : it->second;
|
||||
}
|
||||
|
||||
RTLIL::ObjRange<RTLIL::Wire*> wires() { return RTLIL::ObjRange<RTLIL::Wire*>(&wires_, &refcount_wires_); }
|
||||
int wires_size() const { return wires_.size(); }
|
||||
RTLIL::Wire* wire_at(int index) const { return wires_.element(index)->second; }
|
||||
RTLIL::ObjRange<RTLIL::Cell*> cells() { return RTLIL::ObjRange<RTLIL::Cell*>(&cells_, &refcount_cells_); }
|
||||
int cells_size() const { return cells_.size(); }
|
||||
RTLIL::Cell* cell_at(int index) const { return cells_.element(index)->second; }
|
||||
|
||||
void add(RTLIL::Binding *binding);
|
||||
|
||||
// Removing wires is expensive. If you have to remove wires, remove them all at once.
|
||||
void remove(const pool<RTLIL::Wire*> &wires);
|
||||
void remove(RTLIL::Cell *cell);
|
||||
void remove(RTLIL::Memory *memory);
|
||||
void remove(RTLIL::Process *process);
|
||||
|
||||
void rename(RTLIL::Wire *wire, RTLIL::IdString new_name);
|
||||
|
|
@ -2381,6 +2398,7 @@ public:
|
|||
RTLIL::SigSpec OriginalTag (RTLIL::IdString name, const std::string &tag, const RTLIL::SigSpec &sig_a, const std::string &src = "");
|
||||
RTLIL::SigSpec FutureFF (RTLIL::IdString name, const RTLIL::SigSpec &sig_e, const std::string &src = "");
|
||||
|
||||
std::string to_rtlil_str() const;
|
||||
#ifdef YOSYS_ENABLE_PYTHON
|
||||
static std::map<unsigned int, RTLIL::Module*> *get_all_modules(void);
|
||||
#endif
|
||||
|
|
@ -2434,6 +2452,7 @@ public:
|
|||
return zero_index + start_offset;
|
||||
}
|
||||
|
||||
std::string to_rtlil_str() const;
|
||||
#ifdef YOSYS_ENABLE_PYTHON
|
||||
static std::map<unsigned int, RTLIL::Wire*> *get_all_wires(void);
|
||||
#endif
|
||||
|
|
@ -2451,6 +2470,8 @@ struct RTLIL::Memory : public RTLIL::NamedObject
|
|||
Memory();
|
||||
|
||||
int width, start_offset, size;
|
||||
|
||||
std::string to_rtlil_str() const;
|
||||
#ifdef YOSYS_ENABLE_PYTHON
|
||||
~Memory();
|
||||
static std::map<unsigned int, RTLIL::Memory*> *get_all_memorys(void);
|
||||
|
|
@ -2479,23 +2500,23 @@ public:
|
|||
dict<RTLIL::IdString, RTLIL::Const> parameters;
|
||||
|
||||
// access cell ports
|
||||
bool hasPort(const RTLIL::IdString &portname) const;
|
||||
void unsetPort(const RTLIL::IdString &portname);
|
||||
void setPort(const RTLIL::IdString &portname, RTLIL::SigSpec signal);
|
||||
const RTLIL::SigSpec &getPort(const RTLIL::IdString &portname) const;
|
||||
bool hasPort(RTLIL::IdString portname) const;
|
||||
void unsetPort(RTLIL::IdString portname);
|
||||
void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal);
|
||||
const RTLIL::SigSpec &getPort(RTLIL::IdString portname) const;
|
||||
const dict<RTLIL::IdString, RTLIL::SigSpec> &connections() const;
|
||||
|
||||
// information about cell ports
|
||||
bool known() const;
|
||||
bool input(const RTLIL::IdString &portname) const;
|
||||
bool output(const RTLIL::IdString &portname) const;
|
||||
PortDir port_dir(const RTLIL::IdString &portname) const;
|
||||
bool input(RTLIL::IdString portname) const;
|
||||
bool output(RTLIL::IdString portname) const;
|
||||
PortDir port_dir(RTLIL::IdString portname) const;
|
||||
|
||||
// access cell parameters
|
||||
bool hasParam(const RTLIL::IdString ¶mname) const;
|
||||
void unsetParam(const RTLIL::IdString ¶mname);
|
||||
void setParam(const RTLIL::IdString ¶mname, RTLIL::Const value);
|
||||
const RTLIL::Const &getParam(const RTLIL::IdString ¶mname) const;
|
||||
bool hasParam(RTLIL::IdString paramname) const;
|
||||
void unsetParam(RTLIL::IdString paramname);
|
||||
void setParam(RTLIL::IdString paramname, RTLIL::Const value);
|
||||
const RTLIL::Const &getParam(RTLIL::IdString paramname) const;
|
||||
|
||||
void sort();
|
||||
void check();
|
||||
|
|
@ -2509,6 +2530,8 @@ public:
|
|||
template<typename T> void rewrite_sigspecs(T &functor);
|
||||
template<typename T> void rewrite_sigspecs2(T &functor);
|
||||
|
||||
std::string to_rtlil_str() const;
|
||||
|
||||
#ifdef YOSYS_ENABLE_PYTHON
|
||||
static std::map<unsigned int, RTLIL::Cell*> *get_all_cells(void);
|
||||
#endif
|
||||
|
|
@ -2587,6 +2610,7 @@ public:
|
|||
template<typename T> void rewrite_sigspecs(T &functor);
|
||||
template<typename T> void rewrite_sigspecs2(T &functor);
|
||||
RTLIL::Process *clone() const;
|
||||
std::string to_rtlil_str() const;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -526,7 +526,7 @@ void RTLIL::Module::bufNormalize()
|
|||
pending_deleted_cells.clear();
|
||||
}
|
||||
|
||||
void RTLIL::Cell::unsetPort(const RTLIL::IdString& portname)
|
||||
void RTLIL::Cell::unsetPort(RTLIL::IdString portname)
|
||||
{
|
||||
RTLIL::SigSpec signal;
|
||||
auto conn_it = connections_.find(portname);
|
||||
|
|
@ -586,7 +586,7 @@ void RTLIL::Cell::unsetPort(const RTLIL::IdString& portname)
|
|||
}
|
||||
}
|
||||
|
||||
void RTLIL::Cell::setPort(const RTLIL::IdString& portname, RTLIL::SigSpec signal)
|
||||
void RTLIL::Cell::setPort(RTLIL::IdString portname, RTLIL::SigSpec signal)
|
||||
{
|
||||
auto r = connections_.insert(portname);
|
||||
auto conn_it = r.first;
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ struct SatSolver
|
|||
|
||||
struct ezSatPtr : public std::unique_ptr<ezSAT> {
|
||||
ezSatPtr() : unique_ptr<ezSAT>(yosys_satsolver->create()) { }
|
||||
explicit ezSatPtr(SatSolver *solver) : unique_ptr<ezSAT>((solver ? solver : yosys_satsolver)->create()) { }
|
||||
};
|
||||
|
||||
struct SatGen
|
||||
|
|
|
|||
|
|
@ -97,13 +97,13 @@ static const char *attr_prefix(ScopeinfoAttrs attrs)
|
|||
}
|
||||
}
|
||||
|
||||
bool scopeinfo_has_attribute(const RTLIL::Cell *scopeinfo, ScopeinfoAttrs attrs, const RTLIL::IdString &id)
|
||||
bool scopeinfo_has_attribute(const RTLIL::Cell *scopeinfo, ScopeinfoAttrs attrs, RTLIL::IdString id)
|
||||
{
|
||||
log_assert(scopeinfo->type == ID($scopeinfo));
|
||||
return scopeinfo->has_attribute(attr_prefix(attrs) + RTLIL::unescape_id(id));
|
||||
}
|
||||
|
||||
RTLIL::Const scopeinfo_get_attribute(const RTLIL::Cell *scopeinfo, ScopeinfoAttrs attrs, const RTLIL::IdString &id)
|
||||
RTLIL::Const scopeinfo_get_attribute(const RTLIL::Cell *scopeinfo, ScopeinfoAttrs attrs, RTLIL::IdString id)
|
||||
{
|
||||
log_assert(scopeinfo->type == ID($scopeinfo));
|
||||
auto found = scopeinfo->attributes.find(attr_prefix(attrs) + RTLIL::unescape_id(id));
|
||||
|
|
|
|||
|
|
@ -433,10 +433,10 @@ enum class ScopeinfoAttrs {
|
|||
};
|
||||
|
||||
// Check whether the flattened module or flattened cell corresponding to a $scopeinfo cell had a specific attribute.
|
||||
bool scopeinfo_has_attribute(const RTLIL::Cell *scopeinfo, ScopeinfoAttrs attrs, const RTLIL::IdString &id);
|
||||
bool scopeinfo_has_attribute(const RTLIL::Cell *scopeinfo, ScopeinfoAttrs attrs, RTLIL::IdString id);
|
||||
|
||||
// Get a specific attribute from the flattened module or flattened cell corresponding to a $scopeinfo cell.
|
||||
RTLIL::Const scopeinfo_get_attribute(const RTLIL::Cell *scopeinfo, ScopeinfoAttrs attrs, const RTLIL::IdString &id);
|
||||
RTLIL::Const scopeinfo_get_attribute(const RTLIL::Cell *scopeinfo, ScopeinfoAttrs attrs, RTLIL::IdString id);
|
||||
|
||||
// Get all attribute from the flattened module or flattened cell corresponding to a $scopeinfo cell.
|
||||
dict<RTLIL::IdString, RTLIL::Const> scopeinfo_attributes(const RTLIL::Cell *scopeinfo, ScopeinfoAttrs attrs);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,20 @@
|
|||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
static int init_max_threads()
|
||||
{
|
||||
const char *v = getenv("YOSYS_MAX_THREADS");
|
||||
if (v == nullptr)
|
||||
return INT32_MAX;
|
||||
return atoi(v);
|
||||
}
|
||||
|
||||
static int get_max_threads()
|
||||
{
|
||||
static int max_threads = init_max_threads();
|
||||
return max_threads;
|
||||
}
|
||||
|
||||
void DeferredLogs::flush()
|
||||
{
|
||||
for (auto &m : logs)
|
||||
|
|
@ -12,10 +26,11 @@ void DeferredLogs::flush()
|
|||
YOSYS_NAMESPACE_PREFIX log("%s", m.text.c_str());
|
||||
}
|
||||
|
||||
int ThreadPool::pool_size(int reserved_cores, int max_threads)
|
||||
int ThreadPool::pool_size(int reserved_cores, int max_worker_threads)
|
||||
{
|
||||
#ifdef YOSYS_ENABLE_THREADS
|
||||
int num_threads = std::min<int>(std::thread::hardware_concurrency() - reserved_cores, max_threads);
|
||||
int available_threads = std::min<int>(std::thread::hardware_concurrency(), get_max_threads());
|
||||
int num_threads = std::min(available_threads - reserved_cores, max_worker_threads);
|
||||
return std::max(0, num_threads);
|
||||
#else
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -127,9 +127,9 @@ class ThreadPool
|
|||
public:
|
||||
// Computes the number of worker threads to use.
|
||||
// `reserved_cores` cores are set aside for other threads (e.g. work on the main thread).
|
||||
// `max_threads` --- don't return more workers than this.
|
||||
// `max_worker_threads` --- don't return more workers than this.
|
||||
// The result may be 0.
|
||||
static int pool_size(int reserved_cores, int max_threads);
|
||||
static int pool_size(int reserved_cores, int max_worker_threads);
|
||||
|
||||
// Create a pool of threads running the given closure (parameterized by thread number).
|
||||
// `pool_size` must be the result of a `pool_size()` call.
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "kernel/yosys.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include "kernel/log.h"
|
||||
|
||||
#ifdef YOSYS_ENABLE_READLINE
|
||||
# include <readline/readline.h>
|
||||
|
|
@ -80,7 +81,7 @@ extern "C" PyObject* PyInit_pyosys();
|
|||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
int autoidx = 1;
|
||||
Autoidx autoidx(1);
|
||||
int yosys_xtrace = 0;
|
||||
bool yosys_write_versions = true;
|
||||
const char* yosys_maybe_version() {
|
||||
|
|
@ -108,9 +109,30 @@ uint32_t Hasher::fudge = 0;
|
|||
std::string yosys_share_dirname;
|
||||
std::string yosys_abc_executable;
|
||||
|
||||
bool Multithreading::active_ = false;
|
||||
|
||||
void init_share_dirname();
|
||||
void init_abc_executable_name();
|
||||
|
||||
Multithreading::Multithreading() {
|
||||
log_assert(!active_);
|
||||
active_ = true;
|
||||
}
|
||||
|
||||
Multithreading::~Multithreading() {
|
||||
log_assert(active_);
|
||||
active_ = false;
|
||||
}
|
||||
|
||||
void Autoidx::ensure_at_least(int v) {
|
||||
value = std::max(value, v);
|
||||
}
|
||||
|
||||
int Autoidx::operator++(int) {
|
||||
log_assert(!Multithreading::active());
|
||||
return value++;
|
||||
}
|
||||
|
||||
void memhasher_on()
|
||||
{
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
|
|
@ -151,7 +173,7 @@ void yosys_banner()
|
|||
log("\n");
|
||||
log(" /----------------------------------------------------------------------------\\\n");
|
||||
log(" | yosys -- Yosys Open SYnthesis Suite |\n");
|
||||
log(" | Copyright (C) 2012 - 2025 Claire Xenia Wolf <claire@yosyshq.com> |\n");
|
||||
log(" | Copyright (C) 2012 - 2026 Claire Xenia Wolf <claire@yosyshq.com> |\n");
|
||||
log(" | Distributed under an ISC-like license, type \"license\" to see terms |\n");
|
||||
log(" \\----------------------------------------------------------------------------/\n");
|
||||
log(" %s\n", yosys_maybe_version());
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ extern std::set<std::string> yosys_input_files, yosys_output_files;
|
|||
|
||||
// from kernel/version_*.o (cc source generated from Makefile)
|
||||
extern const char *yosys_version_str;
|
||||
extern const char *yosys_git_hash_str;
|
||||
const char* yosys_maybe_version();
|
||||
|
||||
// from passes/cmds/design.cc
|
||||
|
|
|
|||
|
|
@ -267,7 +267,30 @@ int ceil_log2(int x) YS_ATTRIBUTE(const);
|
|||
template<typename T> int GetSize(const T &obj) { return obj.size(); }
|
||||
inline int GetSize(RTLIL::Wire *wire);
|
||||
|
||||
extern int autoidx;
|
||||
// When multiple threads are accessing RTLIL, one of these guard objects
|
||||
// must exist.
|
||||
struct Multithreading
|
||||
{
|
||||
Multithreading();
|
||||
~Multithreading();
|
||||
// Returns true when multiple threads are accessing RTLIL.
|
||||
// autoidx cannot be used during such times.
|
||||
// IdStrings cannot be created during such times.
|
||||
static bool active() { return active_; }
|
||||
private:
|
||||
static bool active_;
|
||||
};
|
||||
|
||||
struct Autoidx {
|
||||
Autoidx(int value) : value(value) {}
|
||||
operator int() const { return value; }
|
||||
void ensure_at_least(int v);
|
||||
int operator++(int);
|
||||
private:
|
||||
int value;
|
||||
};
|
||||
|
||||
extern Autoidx autoidx;
|
||||
extern int yosys_xtrace;
|
||||
extern bool yosys_write_versions;
|
||||
|
||||
|
|
@ -276,8 +299,8 @@ RTLIL::IdString new_id_suffix(std::string_view file, int line, std::string_view
|
|||
|
||||
#define NEW_ID \
|
||||
YOSYS_NAMESPACE_PREFIX RTLIL::IdString::new_autoidx_with_prefix([](std::string_view func) -> const std::string * { \
|
||||
static const std::string *prefix = YOSYS_NAMESPACE_PREFIX create_id_prefix(__FILE__, __LINE__, func); \
|
||||
return prefix; \
|
||||
static std::unique_ptr<const std::string> prefix(YOSYS_NAMESPACE_PREFIX create_id_prefix(__FILE__, __LINE__, func)); \
|
||||
return prefix.get(); \
|
||||
}(__FUNCTION__))
|
||||
#define NEW_ID_SUFFIX(suffix) \
|
||||
YOSYS_NAMESPACE_PREFIX new_id_suffix(__FILE__, __LINE__, __FUNCTION__, suffix)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue