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 "buffered-normalized mode", add $buf cell type, and add "bufnorm" command #3967

Merged
merged 11 commits into from
Sep 17, 2024
4 changes: 4 additions & 0 deletions backends/rtlil/rtlil_backend.cc
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::
dump_const(f, it.second);
f << stringf("\n");
}
if (wire->driverCell_) {
f << stringf("%s" "# driver %s %s\n", indent.c_str(),
wire->driverCell()->name.c_str(), wire->driverPort().c_str());
}
f << stringf("%s" "wire ", indent.c_str());
if (wire->width != 1)
f << stringf("width %d ", wire->width);
Expand Down
8 changes: 8 additions & 0 deletions kernel/calc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,14 @@ RTLIL::Const RTLIL::const_pos(const RTLIL::Const &arg1, const RTLIL::Const&, boo
return arg1_ext;
}

RTLIL::Const RTLIL::const_buf(const RTLIL::Const &arg1, const RTLIL::Const&, bool signed1, bool, int result_len)
{
RTLIL::Const arg1_ext = arg1;
extend_u0(arg1_ext, result_len, signed1);

return arg1_ext;
}

RTLIL::Const RTLIL::const_neg(const RTLIL::Const &arg1, const RTLIL::Const&, bool signed1, bool, int result_len)
{
RTLIL::Const arg1_ext = arg1;
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_)))
if (cell->type.in(ID($not), ID($_NOT_), ID($pos), ID($buf), 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->getParam(ID::A_SIGNED).as_bool();
bool is_signed = (cell->type != ID($buf)) && 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))) {
if (cell->type.in(ID($not), ID($pos), ID($buf))) {
bitwise_unary_op(this, cell);
return true;
}
Expand Down
5 changes: 3 additions & 2 deletions kernel/celltypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ struct CellTypes
void setup_internals_eval()
{
std::vector<RTLIL::IdString> unary_ops = {
ID($not), ID($pos), ID($neg),
ID($not), ID($pos), ID($buf), ID($neg),
ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool),
ID($logic_not), ID($slice), ID($lut), ID($sop)
};
Expand Down Expand Up @@ -339,7 +339,7 @@ struct CellTypes
type = ID($shl);

if (type != ID($sshr) && type != ID($sshl) && type != ID($shr) && type != ID($shl) && type != ID($shift) && type != ID($shiftx) &&
type != ID($pos) && type != ID($neg) && type != ID($not)) {
type != ID($pos) && type != ID($buf) && type != ID($neg) && type != ID($not)) {
if (!signed1 || !signed2)
signed1 = false, signed2 = false;
}
Expand Down Expand Up @@ -381,6 +381,7 @@ struct CellTypes
HANDLE_CELL_TYPE(modfloor)
HANDLE_CELL_TYPE(pow)
HANDLE_CELL_TYPE(pos)
HANDLE_CELL_TYPE(buf)
HANDLE_CELL_TYPE(neg)
#undef HANDLE_CELL_TYPE

Expand Down
1 change: 1 addition & 0 deletions kernel/constids.inc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ X(CE_OVER_SRST)
X(CFG_ABITS)
X(CFG_DBITS)
X(CFG_INIT)
X(chain)
X(CI)
X(CLK)
X(clkbuf_driver)
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_)))
if (cell->type.in(ID($concat), ID($slice), ID($pos), ID($buf), 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
167 changes: 165 additions & 2 deletions kernel/rtlil.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "kernel/macc.h"
#include "kernel/celltypes.h"
#include "kernel/binding.h"
#include "kernel/sigtools.h"
#include "frontends/verilog/verilog_frontend.h"
#include "frontends/verilog/preproc.h"
#include "backends/rtlil/rtlil_backend.h"
Expand Down Expand Up @@ -1108,6 +1109,13 @@ namespace {
cell->type.begins_with("$verific$") || cell->type.begins_with("$array:") || cell->type.begins_with("$extern:"))
return;

if (cell->type == ID($buf)) {
port(ID::A, param(ID::WIDTH));
port(ID::Y, param(ID::WIDTH));
check_expected();
return;
}

if (cell->type.in(ID($not), ID($pos), ID($neg))) {
param_bool(ID::A_SIGNED);
port(ID::A, param(ID::A_WIDTH));
Expand Down Expand Up @@ -2493,6 +2501,23 @@ DEF_METHOD(ReduceBool, 1, ID($reduce_bool))
DEF_METHOD(LogicNot, 1, ID($logic_not))
#undef DEF_METHOD

#define DEF_METHOD(_func, _y_size, _type) \
RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, bool /* is_signed */, const std::string &src) { \
RTLIL::Cell *cell = addCell(name, _type); \
cell->parameters[ID::WIDTH] = sig_a.size(); \
cell->setPort(ID::A, sig_a); \
cell->setPort(ID::Y, sig_y); \
cell->set_src_attribute(src); \
return cell; \
} \
RTLIL::SigSpec RTLIL::Module::_func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed, const std::string &src) { \
RTLIL::SigSpec sig_y = addWire(NEW_ID, _y_size); \
add ## _func(name, sig_a, sig_y, is_signed, src); \
return sig_y; \
}
DEF_METHOD(Buf, sig_a.size(), ID($buf))
#undef DEF_METHOD

#define DEF_METHOD(_func, _y_size, _type) \
RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, bool is_signed, const std::string &src) { \
RTLIL::Cell *cell = addCell(name, _type); \
Expand Down Expand Up @@ -3540,6 +3565,110 @@ void RTLIL::Cell::unsetPort(const RTLIL::IdString& portname)
}
}

void RTLIL::Design::bufNormalize(bool enable)
{
if (!enable)
{
if (!flagBufferedNormalized)
return;

for (auto module : modules()) {
module->bufNormQueue.clear();
for (auto wire : module->wires()) {
wire->driverCell_ = nullptr;
wire->driverPort_ = IdString();
}
}

flagBufferedNormalized = false;
return;
}

if (!flagBufferedNormalized)
{
for (auto module : modules())
{
for (auto cell : module->cells())
for (auto &conn : cell->connections()) {
if (!cell->output(conn.first) || GetSize(conn.second) == 0)
continue;
if (conn.second.is_wire()) {
Wire *wire = conn.second.as_wire();
log_assert(wire->driverCell_ == nullptr);
wire->driverCell_ = cell;
wire->driverPort_ = conn.first;
} else {
pair<RTLIL::Cell*, RTLIL::IdString> key(cell, conn.first);
module->bufNormQueue.insert(key);
}
}
}

flagBufferedNormalized = true;
}

for (auto module : modules())
module->bufNormalize();
}

void RTLIL::Module::bufNormalize()
{
if (!design->flagBufferedNormalized)
return;

while (GetSize(bufNormQueue) || !connections_.empty())
{
pool<pair<RTLIL::Cell*, RTLIL::IdString>> queue;
bufNormQueue.swap(queue);

pool<Wire*> outWires;
for (auto &conn : connections())
for (auto &chunk : conn.first.chunks())
if (chunk.wire) outWires.insert(chunk.wire);

SigMap sigmap(this);
new_connections({});

for (auto &key : queue)
{
Cell *cell = key.first;
const IdString &portname = key.second;
const SigSpec &sig = cell->getPort(portname);
if (GetSize(sig) == 0) continue;

if (sig.is_wire()) {
Wire *wire = sig.as_wire();
if (wire->driverCell_) {
log_error("Conflict between %s %s in module %s\n",
log_id(cell), log_id(wire->driverCell_), log_id(this));
}
log_assert(wire->driverCell_ == nullptr);
wire->driverCell_ = cell;
wire->driverPort_ = portname;
continue;
}

for (auto &chunk : sig.chunks())
if (chunk.wire) outWires.insert(chunk.wire);

Wire *wire = addWire(NEW_ID, GetSize(sig));
sigmap.add(sig, wire);
cell->setPort(portname, wire);

// FIXME: Move init attributes from old 'sig' to new 'wire'
}

for (auto wire : outWires)
{
SigSpec outsig = wire, insig = sigmap(wire);
for (int i = 0; i < GetSize(wire); i++)
if (insig[i] == outsig[i])
insig[i] = State::Sx;
addBuf(NEW_ID, insig, outsig);
}
}
}

void RTLIL::Cell::setPort(const RTLIL::IdString& portname, RTLIL::SigSpec signal)
{
auto r = connections_.insert(portname);
Expand All @@ -3559,6 +3688,40 @@ void RTLIL::Cell::setPort(const RTLIL::IdString& portname, RTLIL::SigSpec signal
log_backtrace("-X- ", yosys_xtrace-1);
}

while (module->design && module->design->flagBufferedNormalized && output(portname))
{
pair<RTLIL::Cell*, RTLIL::IdString> key(this, portname);

if (conn_it->second.is_wire()) {
Wire *w = conn_it->second.as_wire();
if (w->driverCell_ == this && w->driverPort_ == portname) {
w->driverCell_ = nullptr;
w->driverPort_ = IdString();
}
}

if (GetSize(signal) == 0) {
module->bufNormQueue.erase(key);
break;
}

if (!signal.is_wire()) {
module->bufNormQueue.insert(key);
break;
}

Wire *w = signal.as_wire();
if (w->driverCell_ != nullptr) {
pair<RTLIL::Cell*, RTLIL::IdString> other_key(w->driverCell_, w->driverPort_);
module->bufNormQueue.insert(other_key);
}
w->driverCell_ = this;
w->driverPort_ = portname;

module->bufNormQueue.erase(key);
break;
}

conn_it->second = std::move(signal);
}

Expand Down Expand Up @@ -3654,9 +3817,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($mux) || type == ID($pmux) || type == ID($bmux)) {
if (type == ID($buf) || type == ID($mux) || type == ID($pmux) || type == ID($bmux)) {
parameters[ID::WIDTH] = GetSize(connections_[ID::Y]);
if (type != ID($mux))
if (type != ID($buf) && type != ID($mux))
parameters[ID::S_WIDTH] = GetSize(connections_[ID::S]);
check();
return;
Expand Down
22 changes: 22 additions & 0 deletions kernel/rtlil.h
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,7 @@ namespace RTLIL
RTLIL::Const const_pow (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);

RTLIL::Const const_pos (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_buf (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_neg (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);

RTLIL::Const const_mux (const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3);
Expand Down Expand Up @@ -1065,6 +1066,9 @@ struct RTLIL::Design
pool<RTLIL::Monitor*> monitors;
dict<std::string, std::string> scratchpad;

bool flagBufferedNormalized = false;
void bufNormalize(bool enable=true);

int refcount_modules_;
dict<RTLIL::IdString, RTLIL::Module*> modules_;
std::vector<RTLIL::Binding*> bindings_;
Expand Down Expand Up @@ -1209,6 +1213,9 @@ struct RTLIL::Module : public RTLIL::AttrObject
std::vector<RTLIL::IdString> ports;
void fixup_ports();

pool<pair<RTLIL::Cell*, RTLIL::IdString>> bufNormQueue;
void bufNormalize();

template<typename T> void rewrite_sigspecs(T &functor);
template<typename T> void rewrite_sigspecs2(T &functor);
void cloneInto(RTLIL::Module *new_mod) const;
Expand Down Expand Up @@ -1280,6 +1287,7 @@ struct RTLIL::Module : public RTLIL::AttrObject

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* 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 = "");
Expand Down Expand Up @@ -1414,6 +1422,7 @@ struct RTLIL::Module : public RTLIL::AttrObject

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 And (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
Expand Down Expand Up @@ -1501,6 +1510,10 @@ struct RTLIL::Module : public RTLIL::AttrObject
#endif
};

namespace RTLIL_BACKEND {
void dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire);
}

struct RTLIL::Wire : public RTLIL::AttrObject
{
unsigned int hashidx_;
Expand All @@ -1512,6 +1525,12 @@ struct RTLIL::Wire : public RTLIL::AttrObject
Wire();
~Wire();

friend struct RTLIL::Design;
friend struct RTLIL::Cell;
friend void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire);
RTLIL::Cell *driverCell_ = nullptr;
RTLIL::IdString driverPort_;

public:
// do not simply copy wires
Wire(RTLIL::Wire &other) = delete;
Expand All @@ -1522,6 +1541,9 @@ struct RTLIL::Wire : public RTLIL::AttrObject
int width, start_offset, port_id;
bool port_input, port_output, upto, is_signed;

RTLIL::Cell *driverCell() const { log_assert(driverCell_); return driverCell_; };
RTLIL::IdString driverPort() const { log_assert(driverCell_); return driverPort_; };

#ifdef WITH_PYTHON
static std::map<unsigned int, RTLIL::Wire*> *get_all_wires(void);
#endif
Expand Down
Loading
Loading