Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Optimization Barriers #4763

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
6 changes: 3 additions & 3 deletions backends/aiger2/aiger.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

#define BITWISE_OPS ID($buf), ID($not), ID($mux), ID($and), ID($or), ID($xor), ID($xnor), ID($fa), \
ID($bwmux)
#define BITWISE_OPS ID($buf), ID($barrier), ID($not), ID($mux), ID($and), ID($or), ID($xor), ID($xnor), \
ID($fa), ID($bwmux)

#define REDUCE_OPS ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool)

Expand Down Expand Up @@ -331,7 +331,7 @@ struct Index {
a = CFALSE;
}

if (cell->type.in(ID($buf), ID($pos), ID($_BUF_))) {
if (cell->type.in(ID($buf), ID($barrier), ID($pos), ID($_BUF_))) {
return a;
} else if (cell->type.in(ID($not), ID($_NOT_))) {
return NOT(a);
Expand Down
6 changes: 3 additions & 3 deletions backends/btor/btor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ struct BtorWorker
goto okay;
}

if (cell->type.in(ID($not), ID($neg), ID($_NOT_), ID($pos)))
if (cell->type.in(ID($not), ID($neg), ID($_NOT_), ID($pos), ID($buf), ID($_BUF_), ID($barrier)))
{
string btor_op;
if (cell->type.in(ID($not), ID($_NOT_))) btor_op = "not";
Expand All @@ -520,9 +520,9 @@ struct BtorWorker
int nid_a = get_sig_nid(cell->getPort(ID::A), width, a_signed);
SigSpec sig = sigmap(cell->getPort(ID::Y));

// the $pos cell just passes through, all other cells need an actual operation applied
// buffer cells just pass through, all other cells need an actual operation applied
int nid = nid_a;
if (cell->type != ID($pos))
if (!cell->type.in(ID($pos), ID($buf), ID($_BUF_), ID($barrier)))
{
log_assert(!btor_op.empty());
int sid = get_bv_sid(width);
Expand Down
2 changes: 1 addition & 1 deletion backends/firrtl/firrtl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -966,7 +966,7 @@ struct FirrtlWorker
register_reverse_wire_map(y_id, cell->getPort(ID::Y));
continue;
}
if (cell->type == ID($pos)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's strange this interprets $pos without looking at the A_SIGNED parameter, but if there's a bug it's pre-existing

if (cell->type.in(ID($pos), ID($buf), ID($barrier))) {
// assign y = a;
// printCell(cell);
string a_expr = make_expr(cell->getPort(ID::A));
Expand Down
2 changes: 1 addition & 1 deletion backends/smt2/smt2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@ struct Smt2Worker
if (cell->type == ID($eqx)) return export_bvop(cell, "(= A B)", 'b');

if (cell->type == ID($not)) return export_bvop(cell, "(bvnot A)");
if (cell->type == ID($pos)) return export_bvop(cell, "A");
if (cell->type.in(ID($pos), ID($buf), ID($barrier))) return export_bvop(cell, "A");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will crash when given a $buf or $barrier as those don't have A_SIGNED

if (cell->type == ID($neg)) return export_bvop(cell, "(bvneg A)");

if (cell->type == ID($add)) return export_bvop(cell, "(bvadd A B)");
Expand Down
2 changes: 1 addition & 1 deletion backends/verilog/verilog_backend.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1071,7 +1071,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
return true;
}

if (cell->type == ID($_BUF_)) {
if (cell->type.in(ID($buf), ID($_BUF_), ID($barrier))) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We met here :) (see #4803)

f << stringf("%s" "assign ", indent.c_str());
dump_sigspec(f, cell->getPort(ID::Y));
f << stringf(" = ");
Expand Down
2 changes: 1 addition & 1 deletion kernel/cellaigs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ Aig::Aig(Cell *cell)
}
}

if (cell->type.in(ID($not), ID($_NOT_), ID($pos), ID($buf), ID($_BUF_)))
if (cell->type.in(ID($not), ID($_NOT_), ID($pos), ID($buf), ID($barrier), ID($_BUF_)))
{
for (int i = 0; i < GetSize(cell->getPort(ID::Y)); i++) {
int A = mk.inport(ID::A, i);
Expand Down
4 changes: 2 additions & 2 deletions kernel/celledges.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ PRIVATE_NAMESPACE_BEGIN

void bitwise_unary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
{
bool is_signed = (cell->type != ID($buf)) && cell->getParam(ID::A_SIGNED).as_bool();
bool is_signed = !cell->type.in(ID($buf), ID($barrier)) && cell->getParam(ID::A_SIGNED).as_bool();
int a_width = GetSize(cell->getPort(ID::A));
int y_width = GetSize(cell->getPort(ID::Y));

Expand Down Expand Up @@ -392,7 +392,7 @@ PRIVATE_NAMESPACE_END

bool YOSYS_NAMESPACE_PREFIX AbstractCellEdgesDatabase::add_edges_from_cell(RTLIL::Cell *cell)
{
if (cell->type.in(ID($not), ID($pos), ID($buf))) {
if (cell->type.in(ID($not), ID($pos), ID($buf), ID($barrier))) {
bitwise_unary_op(this, cell);
return true;
}
Expand Down
2 changes: 2 additions & 0 deletions kernel/celltypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ struct CellTypes
{
setup_internals_eval();

setup_type(ID($barrier), {ID::A}, {ID::Y});

setup_type(ID($tribuf), {ID::A, ID::EN}, {ID::Y}, true);

setup_type(ID($assert), {ID::A, ID::EN}, pool<RTLIL::IdString>(), true);
Expand Down
2 changes: 1 addition & 1 deletion kernel/qcsat.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ void QuickConeSat::prepare()

int QuickConeSat::cell_complexity(RTLIL::Cell *cell)
{
if (cell->type.in(ID($concat), ID($slice), ID($pos), ID($buf), ID($_BUF_)))
if (cell->type.in(ID($concat), ID($slice), ID($pos), ID($buf), ID($barrier), ID($_BUF_)))
return 0;
if (cell->type.in(ID($not), ID($and), ID($or), ID($xor), ID($xnor),
ID($reduce_and), ID($reduce_or), ID($reduce_xor),
Expand Down
9 changes: 5 additions & 4 deletions kernel/rtlil.cc
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@
}

// signed needs one leading bit
if (is_signed && idx < size()) {

Check warning on line 400 in kernel/rtlil.cc

View workflow job for this annotation

GitHub Actions / test-compile (ubuntu-20.04, clang-10)

comparison of integers of different signs: 'size_t' (aka 'unsigned long') and 'int' [-Wsign-compare]

Check warning on line 400 in kernel/rtlil.cc

View workflow job for this annotation

GitHub Actions / test-compile (ubuntu-latest, clang-14)

comparison of integers of different signs: 'size_t' (aka 'unsigned long') and 'int' [-Wsign-compare]

Check warning on line 400 in kernel/rtlil.cc

View workflow job for this annotation

GitHub Actions / test-compile (ubuntu-latest, gcc-10)

comparison of integer expressions of different signedness: ‘size_t’ {aka ‘long unsigned int’} and ‘int’ [-Wsign-compare]

Check warning on line 400 in kernel/rtlil.cc

View workflow job for this annotation

GitHub Actions / test-compile (macos-13, clang)

comparison of integers of different signs: 'size_t' (aka 'unsigned long') and 'int' [-Wsign-compare]

Check warning on line 400 in kernel/rtlil.cc

View workflow job for this annotation

GitHub Actions / test-compile (ubuntu-latest, clang-18)

comparison of integers of different signs: 'size_t' (aka 'unsigned long') and 'int' [-Wsign-compare]

Check warning on line 400 in kernel/rtlil.cc

View workflow job for this annotation

GitHub Actions / test-compile (ubuntu-latest, clang-18)

comparison of integers of different signs: 'size_t' (aka 'unsigned long') and 'int' [-Wsign-compare]

Check warning on line 400 in kernel/rtlil.cc

View workflow job for this annotation

GitHub Actions / test-compile (ubuntu-latest, gcc-13)

comparison of integer expressions of different signedness: ‘size_t’ {aka ‘long unsigned int’} and ‘int’ [-Wsign-compare]

Check warning on line 400 in kernel/rtlil.cc

View workflow job for this annotation

GitHub Actions / test-compile (ubuntu-latest, gcc-13)

comparison of integer expressions of different signedness: ‘size_t’ {aka ‘long unsigned int’} and ‘int’ [-Wsign-compare]
idx++;
}
// must be at least one bit
Expand Down Expand Up @@ -1340,7 +1340,7 @@
cell->type.begins_with("$verific$") || cell->type.begins_with("$array:") || cell->type.begins_with("$extern:"))
return;

if (cell->type == ID($buf)) {
if (cell->type.in(ID($buf), ID($barrier))) {
port(ID::A, param(ID::WIDTH));
port(ID::Y, param(ID::WIDTH));
check_expected();
Expand Down Expand Up @@ -2746,7 +2746,8 @@
add ## _func(name, sig_a, sig_y, is_signed, src); \
return sig_y; \
}
DEF_METHOD(Buf, sig_a.size(), ID($buf))
DEF_METHOD(Buf, sig_a.size(), ID($buf))
DEF_METHOD(Barrier, sig_a.size(), ID($barrier))
#undef DEF_METHOD

#define DEF_METHOD(_func, _y_size, _type) \
Expand Down Expand Up @@ -4048,9 +4049,9 @@
type.begins_with("$verific$") || type.begins_with("$array:") || type.begins_with("$extern:"))
return;

if (type == ID($buf) || type == ID($mux) || type == ID($pmux) || type == ID($bmux)) {
if (type.in(ID($buf), ID($barrier), ID($mux), ID($pmux), ID($bmux))) {
parameters[ID::WIDTH] = GetSize(connections_[ID::Y]);
if (type != ID($buf) && type != ID($mux))
if (!type.in(ID($buf), ID($barrier), ID($mux)))
parameters[ID::S_WIDTH] = GetSize(connections_[ID::S]);
check();
return;
Expand Down
18 changes: 10 additions & 8 deletions kernel/rtlil.h
Original file line number Diff line number Diff line change
Expand Up @@ -1371,10 +1371,11 @@ struct RTLIL::Module : public RTLIL::AttrObject

// The add* methods create a cell and return the created cell. All signals must exist in advance.

RTLIL::Cell* addNot (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
RTLIL::Cell* addPos (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
RTLIL::Cell* addBuf (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
RTLIL::Cell* addNeg (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
RTLIL::Cell* addNot (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
RTLIL::Cell* addPos (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
RTLIL::Cell* addBuf (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
RTLIL::Cell* addBarrier (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
RTLIL::Cell* addNeg (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");

RTLIL::Cell* addAnd (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
RTLIL::Cell* addOr (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed = false, const std::string &src = "");
Expand Down Expand Up @@ -1506,10 +1507,11 @@ struct RTLIL::Module : public RTLIL::AttrObject

// The methods without the add* prefix create a cell and an output signal. They return the newly created output signal.

RTLIL::SigSpec Not (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = "");
RTLIL::SigSpec Pos (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = "");
RTLIL::SigSpec Buf (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = "");
RTLIL::SigSpec Neg (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = "");
RTLIL::SigSpec Not (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = "");
RTLIL::SigSpec Pos (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = "");
RTLIL::SigSpec Buf (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = "");
RTLIL::SigSpec Barrier (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = "");
RTLIL::SigSpec Neg (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = "");

RTLIL::SigSpec And (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
RTLIL::SigSpec Or (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
Expand Down
6 changes: 3 additions & 3 deletions kernel/satgen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -430,15 +430,15 @@ bool SatGen::importCell(RTLIL::Cell *cell, int timestep)
return true;
}

if (cell->type.in(ID($pos), ID($buf), ID($neg)))
if (cell->type.in(ID($pos), ID($buf), ID($barrier), ID($neg)))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think by supplying a SAT model for $barrier to the optimization passes you are running the risk of barrier leakage. I would make the model opt-in, not sure how to do it best though

{
std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
extendSignalWidthUnary(a, y, cell);

std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;

if (cell->type.in(ID($pos), ID($buf))) {
if (cell->type.in(ID($pos), ID($buf), ID($barrier))) {
ez->assume(ez->vec_eq(a, yy));
} else {
std::vector<int> zero(a.size(), ez->CONST_FALSE);
Expand All @@ -451,7 +451,7 @@ bool SatGen::importCell(RTLIL::Cell *cell, int timestep)
std::vector<int> undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
extendSignalWidthUnary(undef_a, undef_y, cell);

if (cell->type.in(ID($pos), ID($buf))) {
if (cell->type.in(ID($pos), ID($buf), ID($barrier))) {
ez->assume(ez->vec_eq(undef_a, undef_y));
} else {
int undef_any_a = ez->expression(ezSAT::OpOr, undef_a);
Expand Down
1 change: 1 addition & 0 deletions passes/cmds/Makefile.inc
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,4 @@ OBJS += passes/cmds/future.o
OBJS += passes/cmds/box_derive.o
OBJS += passes/cmds/example_dt.o
OBJS += passes/cmds/portarcs.o
OBJS += passes/cmds/optbarriers.o
Loading
Loading