mirror of https://github.com/YosysHQ/yosys.git
kernel: define $barrier cell
* This acts as an optimization barrier, limiting the rewriting allowed * For now this forbids all optimization, but attributes can be added to opt in to specific optimizations as required
This commit is contained in:
parent
18b616578a
commit
bdc978380c
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -1340,7 +1340,7 @@ namespace {
|
|||
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();
|
||||
|
@ -2746,7 +2746,8 @@ DEF_METHOD(LogicNot, 1, ID($logic_not))
|
|||
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) \
|
||||
|
@ -4048,9 +4049,9 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed)
|
|||
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;
|
||||
|
|
|
@ -1371,10 +1371,11 @@ public:
|
|||
|
||||
// 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 = "");
|
||||
|
@ -1506,10 +1507,11 @@ public:
|
|||
|
||||
// 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 = "");
|
||||
|
|
|
@ -430,7 +430,7 @@ 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)))
|
||||
{
|
||||
std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
|
||||
std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
|
||||
|
@ -438,7 +438,7 @@ bool SatGen::importCell(RTLIL::Cell *cell, int timestep)
|
|||
|
||||
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);
|
||||
|
@ -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);
|
||||
|
|
|
@ -108,6 +108,29 @@ endmodule
|
|||
|
||||
// --------------------------------------------------------
|
||||
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
//-
|
||||
//- $barrier (A, Y)
|
||||
//* group unary
|
||||
//-
|
||||
//- A coarse-grain buffer cell type that acts as a barrier for optimizations.
|
||||
//- Optimization passes are forbidden from rewriting patterns that include
|
||||
//- this cell (by merging, constant propagation etc) with the exception of
|
||||
//- opt_clean that can remove it if the output is unused.
|
||||
//-
|
||||
module \$barrier (A, Y);
|
||||
|
||||
parameter WIDTH = 0;
|
||||
|
||||
input [WIDTH-1:0] A;
|
||||
output [WIDTH-1:0] Y;
|
||||
|
||||
assign Y = A;
|
||||
|
||||
endmodule
|
||||
|
||||
// --------------------------------------------------------
|
||||
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
//-
|
||||
//- $neg (A, Y)
|
||||
|
|
Loading…
Reference in New Issue