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

opt_merge: hashing performance and correctness #4677

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
26 changes: 13 additions & 13 deletions backends/cxxrtl/cxxrtl_backend.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ struct Scheduler {
struct Vertex {
T *data;
Vertex *prev, *next;
pool<Vertex*, hash_ptr_ops> preds, succs;
pool<Vertex*> preds, succs;

Vertex() : data(NULL), prev(this), next(this) {}
Vertex(T *data) : data(data), prev(NULL), next(NULL) {}
Expand Down Expand Up @@ -300,10 +300,10 @@ struct FlowGraph {
};

std::vector<Node*> nodes;
dict<const RTLIL::Wire*, pool<Node*, hash_ptr_ops>> wire_comb_defs, wire_sync_defs, wire_uses;
dict<Node*, pool<const RTLIL::Wire*>, hash_ptr_ops> node_comb_defs, node_sync_defs, node_uses;
dict<const RTLIL::Wire*, pool<Node*>> wire_comb_defs, wire_sync_defs, wire_uses;
dict<Node*, pool<const RTLIL::Wire*>> node_comb_defs, node_sync_defs, node_uses;
dict<const RTLIL::Wire*, bool> wire_def_inlinable;
dict<const RTLIL::Wire*, dict<Node*, bool, hash_ptr_ops>> wire_use_inlinable;
dict<const RTLIL::Wire*, dict<Node*, bool>> wire_use_inlinable;
dict<RTLIL::SigBit, bool> bit_has_state;

~FlowGraph()
Expand Down Expand Up @@ -365,7 +365,7 @@ struct FlowGraph {
return false;
}

bool is_inlinable(const RTLIL::Wire *wire, const pool<Node*, hash_ptr_ops> &nodes) const
bool is_inlinable(const RTLIL::Wire *wire, const pool<Node*> &nodes) const
{
// Can the wire be inlined, knowing that the given nodes are reachable?
if (nodes.size() != 1)
Expand Down Expand Up @@ -3080,7 +3080,7 @@ struct CxxrtlWorker {
// without feedback arcs can generally be evaluated in a single pass, i.e. it always requires only
// a single delta cycle.
Scheduler<FlowGraph::Node> scheduler;
dict<FlowGraph::Node*, Scheduler<FlowGraph::Node>::Vertex*, hash_ptr_ops> node_vertex_map;
dict<FlowGraph::Node*, Scheduler<FlowGraph::Node>::Vertex*> node_vertex_map;
for (auto node : flow.nodes)
node_vertex_map[node] = scheduler.add(node);
for (auto node_comb_def : flow.node_comb_defs) {
Expand All @@ -3095,7 +3095,7 @@ struct CxxrtlWorker {

// Find out whether the order includes any feedback arcs.
std::vector<FlowGraph::Node*> node_order;
pool<FlowGraph::Node*, hash_ptr_ops> evaluated_nodes;
pool<FlowGraph::Node*> evaluated_nodes;
pool<const RTLIL::Wire*> feedback_wires;
for (auto vertex : scheduler.schedule()) {
auto node = vertex->data;
Expand Down Expand Up @@ -3139,7 +3139,7 @@ struct CxxrtlWorker {
}

// Discover nodes reachable from primary outputs (i.e. members) and collect reachable wire users.
pool<FlowGraph::Node*, hash_ptr_ops> worklist;
pool<FlowGraph::Node*> worklist;
for (auto node : flow.nodes) {
if (node->type == FlowGraph::Node::Type::CELL_EVAL && !is_internal_cell(node->cell->type))
worklist.insert(node); // node evaluates a submodule
Expand All @@ -3159,8 +3159,8 @@ struct CxxrtlWorker {
worklist.insert(node); // node drives public wires
}
}
dict<const RTLIL::Wire*, pool<FlowGraph::Node*, hash_ptr_ops>> live_wires;
pool<FlowGraph::Node*, hash_ptr_ops> live_nodes;
dict<const RTLIL::Wire*, pool<FlowGraph::Node*>> live_wires;
pool<FlowGraph::Node*> live_nodes;
while (!worklist.empty()) {
auto node = worklist.pop();
live_nodes.insert(node);
Expand Down Expand Up @@ -3290,15 +3290,15 @@ struct CxxrtlWorker {

// Discover nodes reachable from primary outputs (i.e. outlines) up until primary inputs (i.e. members)
// and collect reachable wire users.
pool<FlowGraph::Node*, hash_ptr_ops> worklist;
pool<FlowGraph::Node*> worklist;
for (auto node : flow.nodes) {
if (flow.node_comb_defs.count(node))
for (auto wire : flow.node_comb_defs[node])
if (debug_wire_types[wire].is_outline())
worklist.insert(node); // node drives outline
}
dict<const RTLIL::Wire*, pool<FlowGraph::Node*, hash_ptr_ops>> debug_live_wires;
pool<FlowGraph::Node*, hash_ptr_ops> debug_live_nodes;
dict<const RTLIL::Wire*, pool<FlowGraph::Node*>> debug_live_wires;
pool<FlowGraph::Node*> debug_live_nodes;
while (!worklist.empty()) {
auto node = worklist.pop();
debug_live_nodes.insert(node);
Expand Down
2 changes: 1 addition & 1 deletion examples/cxx-api/scopeinfo_example.cc
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ struct ScopeinfoExamplePass : public Pass {

// Shuffle wires so this example produces more interesting outputs
std::sort(wires.begin(), wires.end(), [](Wire *a, Wire *b) {
return mkhash_xorshift(a->name.hash() * 0x2c9277b5) < mkhash_xorshift(b->name.hash() * 0x2c9277b5);
return mkhash_xorshift(run_hash(a->name) * 0x2c9277b5) < mkhash_xorshift(run_hash(b->name) * 0x2c9277b5);
});

ModuleHdlnameIndex index(module);
Expand Down
2 changes: 1 addition & 1 deletion frontends/ast/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ namespace AST
{
// for dict<> and pool<>
unsigned int hashidx_;
unsigned int hash() const { return hashidx_; }
Hasher hash_acc(Hasher h) const { h.acc(hashidx_); return h; }

// this nodes type
AstNodeType type;
Expand Down
16 changes: 8 additions & 8 deletions frontends/verific/verific.cc
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@ RTLIL::SigSpec VerificImporter::operatorInportCase(Instance *inst, const char *p
}
}

RTLIL::SigSpec VerificImporter::operatorOutput(Instance *inst, const pool<Net*, hash_ptr_ops> *any_all_nets)
RTLIL::SigSpec VerificImporter::operatorOutput(Instance *inst, const pool<Net*> *any_all_nets)
{
RTLIL::SigSpec sig;
RTLIL::Wire *dummy_wire = NULL;
Expand Down Expand Up @@ -1567,9 +1567,9 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma

module->fixup_ports();

dict<Net*, char, hash_ptr_ops> init_nets;
pool<Net*, hash_ptr_ops> anyconst_nets, anyseq_nets;
pool<Net*, hash_ptr_ops> allconst_nets, allseq_nets;
dict<Net*, char> init_nets;
pool<Net*> anyconst_nets, anyseq_nets;
pool<Net*> allconst_nets, allseq_nets;
any_all_nets.clear();

FOREACH_NET_OF_NETLIST(nl, mi, net)
Expand Down Expand Up @@ -1832,10 +1832,10 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
module->connect(net_map_at(net), module->Anyseq(new_verific_id(net)));

#ifdef VERIFIC_SYSTEMVERILOG_SUPPORT
pool<Instance*, hash_ptr_ops> sva_asserts;
pool<Instance*, hash_ptr_ops> sva_assumes;
pool<Instance*, hash_ptr_ops> sva_covers;
pool<Instance*, hash_ptr_ops> sva_triggers;
pool<Instance*> sva_asserts;
pool<Instance*> sva_assumes;
pool<Instance*> sva_covers;
pool<Instance*> sva_triggers;
#endif

pool<RTLIL::Cell*> past_ffs;
Expand Down
4 changes: 2 additions & 2 deletions frontends/verific/verific.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ struct VerificImporter

std::map<Verific::Net*, RTLIL::SigBit> net_map;
std::map<Verific::Net*, Verific::Net*> sva_posedge_map;
pool<Verific::Net*, hash_ptr_ops> any_all_nets;
pool<Verific::Net*> any_all_nets;

bool mode_gates, mode_keep, mode_nosva, mode_names, mode_verific;
bool mode_autocover, mode_fullinit;
Expand All @@ -89,7 +89,7 @@ struct VerificImporter
RTLIL::SigSpec operatorInput2(Verific::Instance *inst);
RTLIL::SigSpec operatorInport(Verific::Instance *inst, const char *portname);
RTLIL::SigSpec operatorInportCase(Verific::Instance *inst, const char *portname);
RTLIL::SigSpec operatorOutput(Verific::Instance *inst, const pool<Verific::Net*, hash_ptr_ops> *any_all_nets = nullptr);
RTLIL::SigSpec operatorOutput(Verific::Instance *inst, const pool<Verific::Net*> *any_all_nets = nullptr);

bool import_netlist_instance_gates(Verific::Instance *inst, RTLIL::IdString inst_name);
bool import_netlist_instance_cells(Verific::Instance *inst, RTLIL::IdString inst_name);
Expand Down
2 changes: 1 addition & 1 deletion frontends/verific/verificsva.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1051,7 +1051,7 @@ struct VerificSvaImporter
msg.c_str(), inst->View()->Owner()->Name(), inst->Name()), inst->Linefile());
}

dict<Net*, bool, hash_ptr_ops> check_expression_cache;
dict<Net*, bool> check_expression_cache;

bool check_expression(Net *net, bool raise_error = false)
{
Expand Down
11 changes: 6 additions & 5 deletions kernel/bitpattern.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ struct BitPatternPool
int width;
struct bits_t {
std::vector<RTLIL::State> bitdata;
mutable unsigned int cached_hash;
mutable Hasher::hash_t cached_hash;
bits_t(int width = 0) : bitdata(width), cached_hash(0) { }
RTLIL::State &operator[](int index) {
return bitdata[index];
Expand All @@ -39,14 +39,15 @@ struct BitPatternPool
return bitdata[index];
}
bool operator==(const bits_t &other) const {
if (hash() != other.hash())
if (run_hash(*this) != run_hash(other))
return false;
return bitdata == other.bitdata;
}
unsigned int hash() const {
Hasher hash_acc(Hasher h) const {
if (!cached_hash)
cached_hash = hash_ops<std::vector<RTLIL::State>>::hash(bitdata);
return cached_hash;
cached_hash = run_hash(bitdata);
h.acc(cached_hash);
return h;
}
};
pool<bits_t> database;
Expand Down
17 changes: 9 additions & 8 deletions kernel/cellaigs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ bool AigNode::operator==(const AigNode &other) const
return true;
}

unsigned int AigNode::hash() const
Hasher AigNode::hash_acc(Hasher h) const
{
unsigned int h = mkhash_init;
h = mkhash(portname.hash(), portbit);
h = mkhash(h, inverter);
h = mkhash(h, left_parent);
h = mkhash(h, right_parent);
h.acc(portname);
h.acc(portbit);
h.acc(inverter);
h.acc(left_parent);
h.acc(right_parent);
return h;
}

Expand All @@ -54,9 +54,10 @@ bool Aig::operator==(const Aig &other) const
return name == other.name;
}

unsigned int Aig::hash() const
Hasher Aig::hash_acc(Hasher h) const
{
return hash_ops<std::string>::hash(name);
h.acc(name);
return h;
}

struct AigMaker
Expand Down
4 changes: 2 additions & 2 deletions kernel/cellaigs.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ struct AigNode

AigNode();
bool operator==(const AigNode &other) const;
unsigned int hash() const;
Hasher hash_acc(Hasher h) const;
};

struct Aig
Expand All @@ -44,7 +44,7 @@ struct Aig
Aig(Cell *cell);

bool operator==(const Aig &other) const;
unsigned int hash() const;
Hasher hash_acc(Hasher h) const;
};

YOSYS_NAMESPACE_END
Expand Down
7 changes: 7 additions & 0 deletions kernel/driver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/

#include "kernel/yosys.h"
#include "kernel/hashlib.h"
#include "libs/sha1/sha1.h"
#include "libs/cxxopts/include/cxxopts.hpp"
#include <iostream>
Expand Down Expand Up @@ -276,6 +277,8 @@ int main(int argc, char **argv)
options.add_options("developer")
("X,trace", "enable tracing of core data structure changes. for debugging")
("M,randomize-pointers", "will slightly randomize allocated pointer addresses. for debugging")
("hash-seed", "mix up hashing values with <seed>, for extreme optimization and testing",
cxxopts::value<uint64_t>(), "<seed>")
("A,abort", "will call abort() at the end of the script. for debugging")
("x,experimental", "do not print warnings for the experimental <feature>",
cxxopts::value<std::vector<std::string>>(), "<feature>")
Expand Down Expand Up @@ -427,6 +430,10 @@ int main(int argc, char **argv)
if (result.count("infile")) {
frontend_files = result["infile"].as<std::vector<std::string>>();
}
if (result.count("hash-seed")) {
int seed = result["hash-seed"].as<uint64_t>();
Hasher::set_fudge((Hasher::hash_t)seed);
}

if (log_errfile == NULL) {
log_files.push_back(stdout);
Expand Down
Loading
Loading