3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-07-20 22:25:49 +00:00
This commit is contained in:
Emil J. Tywoniak 2026-06-11 13:17:54 +02:00
parent f592f2f3af
commit 8e522b08c0
206 changed files with 3081 additions and 2782 deletions

View file

@ -218,15 +218,15 @@ private:
y = factory.mux(y, factory.slice(b, a.width() * i, a.width()), factory.slice(s, i, 1));
return y;
}
dict<IdString, Node> handle_fa(Node a, Node b, Node c) {
dict<TwineRef, Node> handle_fa(Node a, Node b, Node c) {
Node t1 = factory.bitwise_xor(a, b);
Node t2 = factory.bitwise_and(a, b);
Node t3 = factory.bitwise_and(c, t1);
Node y = factory.bitwise_xor(c, t1);
Node x = factory.bitwise_or(t2, t3);
return {{ID(X), x}, {ID(Y), y}};
return {{TW::X, x}, {TW::Y, y}};
}
dict<IdString, Node> handle_alu(Node a_in, Node b_in, int y_width, bool is_signed, Node ci, Node bi) {
dict<TwineRef, Node> handle_alu(Node a_in, Node b_in, int y_width, bool is_signed, Node ci, Node bi) {
Node a = factory.extend(a_in, y_width, is_signed);
Node b_uninverted = factory.extend(b_in, y_width, is_signed);
Node b = factory.mux(b_uninverted, factory.bitwise_not(b_uninverted), bi);
@ -240,13 +240,13 @@ private:
Node y = factory.slice(y_extra, 0, y_width);
Node carries = factory.bitwise_xor(y_extra, factory.bitwise_xor(a_extra, b_extra));
Node co = factory.slice(carries, 1, y_width);
return {{ID(X), x}, {ID(Y), y}, {ID(CO), co}};
return {{TW::X, x}, {TW::Y, y}, {TW::CO, co}};
}
Node handle_lcu(Node p, Node g, Node ci) {
return handle_alu(g, factory.bitwise_or(p, g), g.width(), false, ci, factory.constant(Const(State::S0, 1))).at(ID(CO));
return handle_alu(g, factory.bitwise_or(p, g), g.width(), false, ci, factory.constant(Const(State::S0, 1))).at(TW::CO);
}
public:
std::variant<dict<IdString, Node>, Node> handle(IdString cellName, IdString cellType, dict<IdString, Const> parameters, dict<IdString, Node> inputs)
std::variant<dict<TwineRef, Node>, Node> handle(IdString cellName, IdString cellType, dict<IdString, Const> parameters, dict<TwineRef, Node> inputs)
{
int a_width = parameters.at(ID(A_WIDTH), Const(-1)).as_int();
int b_width = parameters.at(ID(B_WIDTH), Const(-1)).as_int();
@ -255,8 +255,8 @@ public:
bool b_signed = parameters.at(ID(B_SIGNED), Const(0)).as_bool();
if(cellType.in(ID($add), ID($sub), ID($and), ID($or), ID($xor), ID($xnor), ID($mul))){
bool is_signed = a_signed && b_signed;
Node a = factory.extend(inputs.at(ID(A)), y_width, is_signed);
Node b = factory.extend(inputs.at(ID(B)), y_width, is_signed);
Node a = factory.extend(inputs.at(TW::A), y_width, is_signed);
Node b = factory.extend(inputs.at(TW::B), y_width, is_signed);
if(cellType == ID($add))
return factory.add(a, b);
else if(cellType == ID($sub))
@ -276,8 +276,8 @@ public:
}else if(cellType.in(ID($eq), ID($ne), ID($eqx), ID($nex), ID($le), ID($lt), ID($ge), ID($gt))){
bool is_signed = a_signed && b_signed;
int width = max(a_width, b_width);
Node a = factory.extend(inputs.at(ID(A)), width, is_signed);
Node b = factory.extend(inputs.at(ID(B)), width, is_signed);
Node a = factory.extend(inputs.at(TW::A), width, is_signed);
Node b = factory.extend(inputs.at(TW::B), width, is_signed);
if(cellType.in(ID($eq), ID($eqx)))
return factory.extend(factory.equal(a, b), y_width, false);
else if(cellType.in(ID($ne), ID($nex)))
@ -293,48 +293,48 @@ public:
else
log_abort();
}else if(cellType.in(ID($logic_or), ID($logic_and))){
Node a = factory.reduce_or(inputs.at(ID(A)));
Node b = factory.reduce_or(inputs.at(ID(B)));
Node a = factory.reduce_or(inputs.at(TW::A));
Node b = factory.reduce_or(inputs.at(TW::B));
Node y = cellType == ID($logic_and) ? factory.bitwise_and(a, b) : factory.bitwise_or(a, b);
return factory.extend(y, y_width, false);
}else if(cellType == ID($not)){
Node a = factory.extend(inputs.at(ID(A)), y_width, a_signed);
Node a = factory.extend(inputs.at(TW::A), y_width, a_signed);
return factory.bitwise_not(a);
}else if(cellType == ID($pos)){
return factory.extend(inputs.at(ID(A)), y_width, a_signed);
return factory.extend(inputs.at(TW::A), y_width, a_signed);
}else if(cellType == ID($neg)){
Node a = factory.extend(inputs.at(ID(A)), y_width, a_signed);
Node a = factory.extend(inputs.at(TW::A), y_width, a_signed);
return factory.unary_minus(a);
}else if(cellType == ID($logic_not)){
Node a = factory.reduce_or(inputs.at(ID(A)));
Node a = factory.reduce_or(inputs.at(TW::A));
Node y = factory.bitwise_not(a);
return factory.extend(y, y_width, false);
}else if(cellType.in(ID($reduce_or), ID($reduce_bool))){
Node a = factory.reduce_or(inputs.at(ID(A)));
Node a = factory.reduce_or(inputs.at(TW::A));
return factory.extend(a, y_width, false);
}else if(cellType == ID($reduce_and)){
Node a = factory.reduce_and(inputs.at(ID(A)));
Node a = factory.reduce_and(inputs.at(TW::A));
return factory.extend(a, y_width, false);
}else if(cellType.in(ID($reduce_xor), ID($reduce_xnor))){
Node a = factory.reduce_xor(inputs.at(ID(A)));
Node a = factory.reduce_xor(inputs.at(TW::A));
Node y = cellType == ID($reduce_xnor) ? factory.bitwise_not(a) : a;
return factory.extend(y, y_width, false);
}else if(cellType == ID($shl) || cellType == ID($sshl)){
Node a = factory.extend(inputs.at(ID(A)), y_width, a_signed);
Node b = inputs.at(ID(B));
Node a = factory.extend(inputs.at(TW::A), y_width, a_signed);
Node b = inputs.at(TW::B);
return logical_shift_left(a, b);
}else if(cellType == ID($shr) || cellType == ID($sshr)){
int width = max(a_width, y_width);
Node a = factory.extend(inputs.at(ID(A)), width, a_signed);
Node b = inputs.at(ID(B));
Node a = factory.extend(inputs.at(TW::A), width, a_signed);
Node b = inputs.at(TW::B);
Node y = a_signed && cellType == ID($sshr) ?
arithmetic_shift_right(a, b) :
logical_shift_right(a, b);
return factory.extend(y, y_width, a_signed);
}else if(cellType == ID($shiftx) || cellType == ID($shift)){
int width = max(a_width, y_width);
Node a = factory.extend(inputs.at(ID(A)), width, cellType == ID($shift) && a_signed);
Node b = inputs.at(ID(B));
Node a = factory.extend(inputs.at(TW::A), width, cellType == ID($shift) && a_signed);
Node b = inputs.at(TW::B);
Node shr = logical_shift_right(a, b);
if(b_signed) {
Node shl = logical_shift_left(a, factory.unary_minus(b));
@ -344,22 +344,22 @@ public:
return factory.extend(shr, y_width, false);
}
}else if(cellType == ID($mux)){
return factory.mux(inputs.at(ID(A)), inputs.at(ID(B)), inputs.at(ID(S)));
return factory.mux(inputs.at(TW::A), inputs.at(TW::B), inputs.at(TW::S));
}else if(cellType == ID($pmux)){
return handle_pmux(inputs.at(ID(A)), inputs.at(ID(B)), inputs.at(ID(S)));
return handle_pmux(inputs.at(TW::A), inputs.at(TW::B), inputs.at(TW::S));
}else if(cellType == ID($concat)){
Node a = inputs.at(ID(A));
Node b = inputs.at(ID(B));
Node a = inputs.at(TW::A);
Node b = inputs.at(TW::B);
return factory.concat(a, b);
}else if(cellType == ID($slice)){
int offset = parameters.at(ID(OFFSET)).as_int();
Node a = inputs.at(ID(A));
Node a = inputs.at(TW::A);
return factory.slice(a, offset, y_width);
}else if(cellType.in(ID($div), ID($mod), ID($divfloor), ID($modfloor))) {
int width = max(a_width, b_width);
bool is_signed = a_signed && b_signed;
Node a = factory.extend(inputs.at(ID(A)), width, is_signed);
Node b = factory.extend(inputs.at(ID(B)), width, is_signed);
Node a = factory.extend(inputs.at(TW::A), width, is_signed);
Node b = factory.extend(inputs.at(TW::B), width, is_signed);
if(is_signed) {
if(cellType == ID($div)) {
// divide absolute values, then flip the sign if input signs differ
@ -403,44 +403,44 @@ public:
return factory.extend(factory.unsigned_div(a, b), y_width, false);
}
} else if(cellType == ID($pow)) {
return handle_pow(inputs.at(ID(A)), inputs.at(ID(B)), y_width, a_signed && b_signed);
return handle_pow(inputs.at(TW::A), inputs.at(TW::B), y_width, a_signed && b_signed);
} else if (cellType == ID($lut)) {
int width = parameters.at(ID(WIDTH)).as_int();
Const lut_table = parameters.at(ID(LUT));
lut_table.extu(1 << width);
return handle_bmux(factory.constant(lut_table), inputs.at(ID(A)), 0, 1, width);
return handle_bmux(factory.constant(lut_table), inputs.at(TW::A), 0, 1, width);
} else if (cellType == ID($bwmux)) {
Node a = inputs.at(ID(A));
Node b = inputs.at(ID(B));
Node s = inputs.at(ID(S));
Node a = inputs.at(TW::A);
Node b = inputs.at(TW::B);
Node s = inputs.at(TW::S);
return factory.bitwise_or(
factory.bitwise_and(a, factory.bitwise_not(s)),
factory.bitwise_and(b, s));
} else if (cellType == ID($bweqx)) {
Node a = inputs.at(ID(A));
Node b = inputs.at(ID(B));
Node a = inputs.at(TW::A);
Node b = inputs.at(TW::B);
return factory.bitwise_not(factory.bitwise_xor(a, b));
} else if(cellType == ID($bmux)) {
int width = parameters.at(ID(WIDTH)).as_int();
int s_width = parameters.at(ID(S_WIDTH)).as_int();
return handle_bmux(inputs.at(ID(A)), inputs.at(ID(S)), 0, width, s_width);
return handle_bmux(inputs.at(TW::A), inputs.at(TW::S), 0, width, s_width);
} else if(cellType == ID($demux)) {
int width = parameters.at(ID(WIDTH)).as_int();
int s_width = parameters.at(ID(S_WIDTH)).as_int();
int y_width = width << s_width;
int b_width = ceil_log2(y_width);
Node a = factory.extend(inputs.at(ID(A)), y_width, false);
Node s = factory.extend(inputs.at(ID(S)), b_width, false);
Node a = factory.extend(inputs.at(TW::A), y_width, false);
Node s = factory.extend(inputs.at(TW::S), b_width, false);
Node b = factory.mul(s, factory.constant(Const(width, b_width)));
return factory.logical_shift_left(a, b);
} else if(cellType == ID($fa)) {
return handle_fa(inputs.at(ID(A)), inputs.at(ID(B)), inputs.at(ID(C)));
return handle_fa(inputs.at(TW::A), inputs.at(TW::B), inputs.at(TW::C));
} else if(cellType == ID($lcu)) {
return handle_lcu(inputs.at(ID(P)), inputs.at(ID(G)), inputs.at(ID(CI)));
return handle_lcu(inputs.at(TW::P), inputs.at(TW::G), inputs.at(TW::CI));
} else if(cellType == ID($alu)) {
return handle_alu(inputs.at(ID(A)), inputs.at(ID(B)), y_width, a_signed && b_signed, inputs.at(ID(CI)), inputs.at(ID(BI)));
return handle_alu(inputs.at(TW::A), inputs.at(TW::B), y_width, a_signed && b_signed, inputs.at(TW::CI), inputs.at(TW::BI));
} else if(cellType.in(ID($assert), ID($assume), ID($live), ID($fair), ID($cover))) {
Node a = factory.mux(factory.constant(Const(State::S1, 1)), inputs.at(ID(A)), inputs.at(ID(EN)));
Node a = factory.mux(factory.constant(Const(State::S1, 1)), inputs.at(TW::A), inputs.at(TW::EN));
auto &output = factory.add_output(cellName, cellType, Sort(1));
output.set_value(a);
return {};
@ -468,7 +468,7 @@ public:
class FunctionalIRConstruction {
std::deque<std::variant<DriveSpec, Cell *>> queue;
dict<DriveSpec, Node> graph_nodes;
dict<std::pair<Cell *, IdString>, Node> cell_outputs;
dict<std::pair<Cell *, TwineRef>, Node> cell_outputs;
DriverMap driver_map;
Factory& factory;
CellSimplifier simplifier;
@ -488,7 +488,7 @@ class FunctionalIRConstruction {
}else
return it->second;
}
Node enqueue_cell(Cell *cell, IdString port_name)
Node enqueue_cell(Cell *cell, TwineRef port_name)
{
auto it = cell_outputs.find({cell, port_name});
if(it == cell_outputs.end()) {
@ -497,7 +497,7 @@ class FunctionalIRConstruction {
for(auto const &[name, sigspec] : cell->connections())
if(driver_map.celltypes.cell_output(cell->type, name)) {
auto node = factory.create_pending(sigspec.size());
factory.suggest_name(node, cell->name.str() + "$" + name.str());
factory.suggest_name(node, cell->name.str() + "$" + cell->module->design->twines.str(name));
cell_outputs.emplace({cell, name}, node);
if(name == port_name)
rv = node;
@ -539,7 +539,7 @@ private:
Node concatenate_read_results(Mem *mem, vector<Node> results)
{
// sanity check: all read ports concatenated should equal to the RD_DATA port
const SigSpec &rd_data = mem->cell->connections().at(ID(RD_DATA));
const SigSpec &rd_data = mem->cell->connections().at(TW::RD_DATA);
int current = 0;
for(size_t i = 0; i < mem->rd_ports.size(); i++) {
int width = mem->width << mem->rd_ports[i].wide_log2;
@ -604,7 +604,7 @@ private:
"Call memory_collect to avoid this error.\n", log_const(cell->parameters.at(ID(MEMID))));
}
Node node = handle_memory(mem);
factory.update_pending(cell_outputs.at({cell, ID(RD_DATA)}), node);
factory.update_pending(cell_outputs.at({cell, TW::RD_DATA}), node);
} else if (cell->is_builtin_ff()) {
FfData ff(&ff_initvals, cell);
if (!ff.has_gclk)
@ -613,12 +613,12 @@ private:
auto &state = factory.add_state(ff.name, ID($state), Sort(ff.width));
Node q_value = factory.value(state);
factory.suggest_name(q_value, ff.name);
factory.update_pending(cell_outputs.at({cell, ID(Q)}), q_value);
factory.update_pending(cell_outputs.at({cell, TW::Q}), q_value);
state.set_next_value(enqueue(ff.sig_d));
state.set_initial_value(ff.val_init);
} else {
dict<IdString, Node> connections;
IdString output_name; // for the single output case
dict<TwineRef, Node> connections;
TwineRef output_name; // for the single output case
int n_outputs = 0;
for(auto const &[name, sigspec] : cell->connections()) {
if(driver_map.celltypes.cell_input(cell->type, name) && sigspec.size() > 0)
@ -628,12 +628,12 @@ private:
n_outputs++;
}
}
std::variant<dict<IdString, Node>, Node> outputs = simplifier.handle(cell->name, cell->type, cell->parameters, connections);
std::variant<dict<TwineRef, Node>, Node> outputs = simplifier.handle(cell->name, cell->type, cell->parameters, connections);
if(auto *nodep = std::get_if<Node>(&outputs); nodep != nullptr) {
log_assert(n_outputs == 1);
factory.update_pending(cell_outputs.at({cell, output_name}), *nodep);
} else {
for(auto [name, node] : std::get<dict<IdString, Node>>(outputs))
for(auto [name, node] : std::get<dict<TwineRef, Node>>(outputs))
factory.update_pending(cell_outputs.at({cell, name}), node);
}
}
@ -695,7 +695,8 @@ public:
factory.update_pending(pending, node);
} else {
DriveSpec driver = driver_map(DriveSpec(port_chunk));
check_undriven(driver, port_chunk.cell->name.unescape() + " port " + port_chunk.port.unescape());
auto& twines = port_chunk.cell->module->design->twines;
check_undriven(driver, twines.str(port_chunk.cell->meta_->name) + " port " + twines.str(port_chunk.port));
factory.update_pending(pending, enqueue(driver));
}
} else {