Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 43 additions & 25 deletions passes/cmds/autoname.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,24 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

int autoname_worker(Module *module, const dict<Wire*, int>& wire_score)
typedef struct name_proposal {
string name;
unsigned int score;
name_proposal() : name(""), score(-1) { }
name_proposal(string name, unsigned int score) : name(name), score(score) { }
bool operator<(const name_proposal &other) const {
if (score != other.score)
return score < other.score;
else
return name.length() < other.name.length();
}
} name_proposal;

int autoname_worker(Module *module, const dict<Wire*, unsigned int>& wire_score)
{
dict<Cell*, pair<int, string>> proposed_cell_names;
dict<Wire*, pair<int, string>> proposed_wire_names;
int best_score = -1;
dict<Cell*, name_proposal> proposed_cell_names;
dict<Wire*, name_proposal> proposed_wire_names;
name_proposal best_name;

for (auto cell : module->selected_cells()) {
if (cell->name[0] == '$') {
Expand All @@ -36,14 +49,14 @@ int autoname_worker(Module *module, const dict<Wire*, int>& wire_score)
if (bit.wire != nullptr && bit.wire->name[0] != '$') {
if (suffix.empty())
suffix = stringf("_%s_%s", log_id(cell->type), log_id(conn.first));
string new_name(bit.wire->name.str() + suffix);
int score = wire_score.at(bit.wire);
if (cell->output(conn.first)) score = 0;
score = 10000*score + new_name.size();
if (!proposed_cell_names.count(cell) || score < proposed_cell_names.at(cell).first) {
if (best_score < 0 || score < best_score)
best_score = score;
proposed_cell_names[cell] = make_pair(score, new_name);
name_proposal proposed_name(
bit.wire->name.str() + suffix,
cell->output(conn.first) ? 0 : wire_score.at(bit.wire)
);
if (!proposed_cell_names.count(cell) || proposed_name < proposed_cell_names.at(cell)) {
if (proposed_name < best_name)
best_name = proposed_name;
proposed_cell_names[cell] = proposed_name;
}
}
}
Expand All @@ -54,32 +67,36 @@ int autoname_worker(Module *module, const dict<Wire*, int>& wire_score)
if (bit.wire != nullptr && bit.wire->name[0] == '$' && !bit.wire->port_id) {
if (suffix.empty())
suffix = stringf("_%s", log_id(conn.first));
string new_name(cell->name.str() + suffix);
int score = wire_score.at(bit.wire);
if (cell->output(conn.first)) score = 0;
score = 10000*score + new_name.size();
if (!proposed_wire_names.count(bit.wire) || score < proposed_wire_names.at(bit.wire).first) {
if (best_score < 0 || score < best_score)
best_score = score;
proposed_wire_names[bit.wire] = make_pair(score, new_name);
name_proposal proposed_name(
cell->name.str() + suffix,
cell->output(conn.first) ? 0 : wire_score.at(bit.wire)
);
if (!proposed_wire_names.count(bit.wire) || proposed_name < proposed_wire_names.at(bit.wire)) {
if (proposed_name < best_name)
best_name = proposed_name;
proposed_wire_names[bit.wire] = proposed_name;
}
}
}
}
}

// compare against double best score for following comparisons so we don't
// pre-empt a future iteration
best_name.score *= 2;

for (auto &it : proposed_cell_names) {
if (best_score*2 < it.second.first)
if (best_name < it.second)
continue;
IdString n = module->uniquify(IdString(it.second.second));
IdString n = module->uniquify(IdString(it.second.name));
log_debug("Rename cell %s in %s to %s.\n", log_id(it.first), log_id(module), log_id(n));
module->rename(it.first, n);
}

for (auto &it : proposed_wire_names) {
if (best_score*2 < it.second.first)
if (best_name < it.second)
continue;
IdString n = module->uniquify(IdString(it.second.second));
IdString n = module->uniquify(IdString(it.second.name));
log_debug("Rename wire %s in %s to %s.\n", log_id(it.first), log_id(module), log_id(n));
module->rename(it.first, n);
}
Expand Down Expand Up @@ -110,12 +127,13 @@ struct AutonamePass : public Pass {
// }
break;
}
extra_args(args, argidx, design);

log_header(design, "Executing AUTONAME pass.\n");

for (auto module : design->selected_modules())
{
dict<Wire*, int> wire_score;
dict<Wire*, unsigned int> wire_score;
for (auto cell : module->selected_cells())
for (auto &conn : cell->connections())
for (auto bit : conn.second)
Expand Down
175 changes: 173 additions & 2 deletions tests/various/autoname.ys
Original file line number Diff line number Diff line change
@@ -1,19 +1,190 @@
# prefer output name
design -reset
read_rtlil <<EOT
module \top
wire output 3 \y
wire input 1 \a
wire input 2 \b
cell $and $name
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \a
connect \B \b
connect \Y \y
end
end
EOT
logger -expect log "Rename cell .name in top to y_.and_Y" 1
debug autoname
logger -check-expected

# fallback to shortest name if output is private
design -reset
read_rtlil <<EOT
autoidx 2
module \top
wire output 3 $y
wire input 1 \ab
wire input 2 \abcd
cell $or $name
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \ab
connect \B \abcd
connect \Y $y
end
end
EOT
logger -expect log "Rename cell .name in top to ab_.or_A" 1
debug autoname
logger -check-expected

# prefer low fanout over low name length
design -reset
read_rtlil <<EOT
module \top
wire output 1 $y
wire input 2 \a
wire input 3 \bcd
wire input 4 \c_has_a_long_name
cell $and $name
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \a
connect \B \bcd
connect \Y $y
end

cell $or $name2
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \a
connect \B \c_has_a_long_name
connect \Y $y
end
end
EOT
logger -expect log "Rename cell .name in top to bcd_.and_B" 1
logger -expect log "Rename cell .name2 in top to c_has_a_long_name_.or_B" 1
debug autoname
logger -check-expected

# names are unique
design -reset
read_rtlil <<EOT
module \top
wire output 3 \y
wire input 1 \a
wire input 2 \b
cell $and \b_$and_B
cell $and $name
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \a
connect \B \b
connect \Y \y
end

cell $and $name2
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \a
connect \B \b
connect \Y \y
end
end
EOT
logger -expect log "Rename cell .name in top to y_.and_Y" 1
logger -expect log "Rename cell .name2 in top to y_.and_Y_1" 1
debug autoname
logger -check-expected

# wires get autonames too
design -reset
read_rtlil <<EOT
module \top
wire output 1 $y
wire input 2 \a
wire input 3 \bcd
wire $c
wire $d
wire $e
cell $__unknown $name
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \a
connect \B \bcd
connect \Y $c
end

cell $or \or
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \a
connect \B \bcd
connect \Y $d
end

cell $or $name2
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A $c
connect \B $d
connect \Y $e
end

cell $and $name3
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A $c
connect \B $e
connect \Y $y
end
end
EOT
autoname
# wires are named for being cell outputs
logger -expect log "Rename wire .d in top to or_Y" 1
logger -expect log "Rename cell .name2 in top to or_Y_.or_B" 1
debug autoname t:$or
logger -check-expected

# $name gets shortest name (otherwise bcd_$__unknown_B)
logger -expect log "Rename cell .name in top to a_.__unknown_A" 1
# another output wire
logger -expect log "Rename wire .e in top to or_Y_.or_B_Y" 1
# $name3 named for lowest fanout wire (otherwise a_$__unknown_A_Y_$and_A)
logger -expect log "Rename cell .name3 in top to or_Y_.or_B_Y_.and_B" 1
# $c gets shortest name, since the cell driving it doesn't have known port
# directions
logger -expect log "Rename wire .c in top to or_Y_.or_B_A" 1
debug autoname
logger -check-expected
Loading