mirror of https://github.com/YosysHQ/yosys.git
hashlib: redo interface for flexibility
This commit is contained in:
parent
a22ff47d62
commit
ea0be3b403
|
@ -47,7 +47,7 @@ struct Scheduler {
|
||||||
struct Vertex {
|
struct Vertex {
|
||||||
T *data;
|
T *data;
|
||||||
Vertex *prev, *next;
|
Vertex *prev, *next;
|
||||||
pool<Vertex*, hash_ptr_ops> preds, succs;
|
pool<Vertex*> preds, succs;
|
||||||
|
|
||||||
Vertex() : data(NULL), prev(this), next(this) {}
|
Vertex() : data(NULL), prev(this), next(this) {}
|
||||||
Vertex(T *data) : data(data), prev(NULL), next(NULL) {}
|
Vertex(T *data) : data(data), prev(NULL), next(NULL) {}
|
||||||
|
@ -300,10 +300,10 @@ struct FlowGraph {
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Node*> nodes;
|
std::vector<Node*> nodes;
|
||||||
dict<const RTLIL::Wire*, pool<Node*, hash_ptr_ops>> wire_comb_defs, wire_sync_defs, wire_uses;
|
dict<const RTLIL::Wire*, pool<Node*>> 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<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*, 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;
|
dict<RTLIL::SigBit, bool> bit_has_state;
|
||||||
|
|
||||||
~FlowGraph()
|
~FlowGraph()
|
||||||
|
@ -365,7 +365,7 @@ struct FlowGraph {
|
||||||
return false;
|
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?
|
// Can the wire be inlined, knowing that the given nodes are reachable?
|
||||||
if (nodes.size() != 1)
|
if (nodes.size() != 1)
|
||||||
|
@ -3080,7 +3080,7 @@ struct CxxrtlWorker {
|
||||||
// without feedback arcs can generally be evaluated in a single pass, i.e. it always requires only
|
// without feedback arcs can generally be evaluated in a single pass, i.e. it always requires only
|
||||||
// a single delta cycle.
|
// a single delta cycle.
|
||||||
Scheduler<FlowGraph::Node> scheduler;
|
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)
|
for (auto node : flow.nodes)
|
||||||
node_vertex_map[node] = scheduler.add(node);
|
node_vertex_map[node] = scheduler.add(node);
|
||||||
for (auto node_comb_def : flow.node_comb_defs) {
|
for (auto node_comb_def : flow.node_comb_defs) {
|
||||||
|
@ -3095,7 +3095,7 @@ struct CxxrtlWorker {
|
||||||
|
|
||||||
// Find out whether the order includes any feedback arcs.
|
// Find out whether the order includes any feedback arcs.
|
||||||
std::vector<FlowGraph::Node*> node_order;
|
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;
|
pool<const RTLIL::Wire*> feedback_wires;
|
||||||
for (auto vertex : scheduler.schedule()) {
|
for (auto vertex : scheduler.schedule()) {
|
||||||
auto node = vertex->data;
|
auto node = vertex->data;
|
||||||
|
@ -3139,7 +3139,7 @@ struct CxxrtlWorker {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Discover nodes reachable from primary outputs (i.e. members) and collect reachable wire users.
|
// 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) {
|
for (auto node : flow.nodes) {
|
||||||
if (node->type == FlowGraph::Node::Type::CELL_EVAL && !is_internal_cell(node->cell->type))
|
if (node->type == FlowGraph::Node::Type::CELL_EVAL && !is_internal_cell(node->cell->type))
|
||||||
worklist.insert(node); // node evaluates a submodule
|
worklist.insert(node); // node evaluates a submodule
|
||||||
|
@ -3159,8 +3159,8 @@ struct CxxrtlWorker {
|
||||||
worklist.insert(node); // node drives public wires
|
worklist.insert(node); // node drives public wires
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dict<const RTLIL::Wire*, pool<FlowGraph::Node*, hash_ptr_ops>> live_wires;
|
dict<const RTLIL::Wire*, pool<FlowGraph::Node*>> live_wires;
|
||||||
pool<FlowGraph::Node*, hash_ptr_ops> live_nodes;
|
pool<FlowGraph::Node*> live_nodes;
|
||||||
while (!worklist.empty()) {
|
while (!worklist.empty()) {
|
||||||
auto node = worklist.pop();
|
auto node = worklist.pop();
|
||||||
live_nodes.insert(node);
|
live_nodes.insert(node);
|
||||||
|
@ -3290,15 +3290,15 @@ struct CxxrtlWorker {
|
||||||
|
|
||||||
// Discover nodes reachable from primary outputs (i.e. outlines) up until primary inputs (i.e. members)
|
// Discover nodes reachable from primary outputs (i.e. outlines) up until primary inputs (i.e. members)
|
||||||
// and collect reachable wire users.
|
// and collect reachable wire users.
|
||||||
pool<FlowGraph::Node*, hash_ptr_ops> worklist;
|
pool<FlowGraph::Node*> worklist;
|
||||||
for (auto node : flow.nodes) {
|
for (auto node : flow.nodes) {
|
||||||
if (flow.node_comb_defs.count(node))
|
if (flow.node_comb_defs.count(node))
|
||||||
for (auto wire : flow.node_comb_defs[node])
|
for (auto wire : flow.node_comb_defs[node])
|
||||||
if (debug_wire_types[wire].is_outline())
|
if (debug_wire_types[wire].is_outline())
|
||||||
worklist.insert(node); // node drives outline
|
worklist.insert(node); // node drives outline
|
||||||
}
|
}
|
||||||
dict<const RTLIL::Wire*, pool<FlowGraph::Node*, hash_ptr_ops>> debug_live_wires;
|
dict<const RTLIL::Wire*, pool<FlowGraph::Node*>> debug_live_wires;
|
||||||
pool<FlowGraph::Node*, hash_ptr_ops> debug_live_nodes;
|
pool<FlowGraph::Node*> debug_live_nodes;
|
||||||
while (!worklist.empty()) {
|
while (!worklist.empty()) {
|
||||||
auto node = worklist.pop();
|
auto node = worklist.pop();
|
||||||
debug_live_nodes.insert(node);
|
debug_live_nodes.insert(node);
|
||||||
|
|
|
@ -90,7 +90,7 @@ struct ScopeinfoExamplePass : public Pass {
|
||||||
|
|
||||||
// Shuffle wires so this example produces more interesting outputs
|
// Shuffle wires so this example produces more interesting outputs
|
||||||
std::sort(wires.begin(), wires.end(), [](Wire *a, Wire *b) {
|
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);
|
ModuleHdlnameIndex index(module);
|
||||||
|
|
|
@ -177,7 +177,7 @@ namespace AST
|
||||||
{
|
{
|
||||||
// for dict<> and pool<>
|
// for dict<> and pool<>
|
||||||
unsigned int hashidx_;
|
unsigned int hashidx_;
|
||||||
unsigned int hash() const { return hashidx_; }
|
Hasher hash_acc(Hasher h) const { h.acc(hashidx_); return h; }
|
||||||
|
|
||||||
// this nodes type
|
// this nodes type
|
||||||
AstNodeType type;
|
AstNodeType type;
|
||||||
|
|
|
@ -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::SigSpec sig;
|
||||||
RTLIL::Wire *dummy_wire = NULL;
|
RTLIL::Wire *dummy_wire = NULL;
|
||||||
|
@ -1567,9 +1567,9 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
|
||||||
|
|
||||||
module->fixup_ports();
|
module->fixup_ports();
|
||||||
|
|
||||||
dict<Net*, char, hash_ptr_ops> init_nets;
|
dict<Net*, char> init_nets;
|
||||||
pool<Net*, hash_ptr_ops> anyconst_nets, anyseq_nets;
|
pool<Net*> anyconst_nets, anyseq_nets;
|
||||||
pool<Net*, hash_ptr_ops> allconst_nets, allseq_nets;
|
pool<Net*> allconst_nets, allseq_nets;
|
||||||
any_all_nets.clear();
|
any_all_nets.clear();
|
||||||
|
|
||||||
FOREACH_NET_OF_NETLIST(nl, mi, net)
|
FOREACH_NET_OF_NETLIST(nl, mi, net)
|
||||||
|
@ -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)));
|
module->connect(net_map_at(net), module->Anyseq(new_verific_id(net)));
|
||||||
|
|
||||||
#ifdef VERIFIC_SYSTEMVERILOG_SUPPORT
|
#ifdef VERIFIC_SYSTEMVERILOG_SUPPORT
|
||||||
pool<Instance*, hash_ptr_ops> sva_asserts;
|
pool<Instance*> sva_asserts;
|
||||||
pool<Instance*, hash_ptr_ops> sva_assumes;
|
pool<Instance*> sva_assumes;
|
||||||
pool<Instance*, hash_ptr_ops> sva_covers;
|
pool<Instance*> sva_covers;
|
||||||
pool<Instance*, hash_ptr_ops> sva_triggers;
|
pool<Instance*> sva_triggers;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pool<RTLIL::Cell*> past_ffs;
|
pool<RTLIL::Cell*> past_ffs;
|
||||||
|
|
|
@ -71,7 +71,7 @@ struct VerificImporter
|
||||||
|
|
||||||
std::map<Verific::Net*, RTLIL::SigBit> net_map;
|
std::map<Verific::Net*, RTLIL::SigBit> net_map;
|
||||||
std::map<Verific::Net*, Verific::Net*> sva_posedge_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_gates, mode_keep, mode_nosva, mode_names, mode_verific;
|
||||||
bool mode_autocover, mode_fullinit;
|
bool mode_autocover, mode_fullinit;
|
||||||
|
@ -89,7 +89,7 @@ struct VerificImporter
|
||||||
RTLIL::SigSpec operatorInput2(Verific::Instance *inst);
|
RTLIL::SigSpec operatorInput2(Verific::Instance *inst);
|
||||||
RTLIL::SigSpec operatorInport(Verific::Instance *inst, const char *portname);
|
RTLIL::SigSpec operatorInport(Verific::Instance *inst, const char *portname);
|
||||||
RTLIL::SigSpec operatorInportCase(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_gates(Verific::Instance *inst, RTLIL::IdString inst_name);
|
||||||
bool import_netlist_instance_cells(Verific::Instance *inst, RTLIL::IdString inst_name);
|
bool import_netlist_instance_cells(Verific::Instance *inst, RTLIL::IdString inst_name);
|
||||||
|
|
|
@ -1051,7 +1051,7 @@ struct VerificSvaImporter
|
||||||
msg.c_str(), inst->View()->Owner()->Name(), inst->Name()), inst->Linefile());
|
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)
|
bool check_expression(Net *net, bool raise_error = false)
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,7 +30,7 @@ struct BitPatternPool
|
||||||
int width;
|
int width;
|
||||||
struct bits_t {
|
struct bits_t {
|
||||||
std::vector<RTLIL::State> bitdata;
|
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) { }
|
bits_t(int width = 0) : bitdata(width), cached_hash(0) { }
|
||||||
RTLIL::State &operator[](int index) {
|
RTLIL::State &operator[](int index) {
|
||||||
return bitdata[index];
|
return bitdata[index];
|
||||||
|
@ -39,14 +39,15 @@ struct BitPatternPool
|
||||||
return bitdata[index];
|
return bitdata[index];
|
||||||
}
|
}
|
||||||
bool operator==(const bits_t &other) const {
|
bool operator==(const bits_t &other) const {
|
||||||
if (hash() != other.hash())
|
if (run_hash(*this) != run_hash(other))
|
||||||
return false;
|
return false;
|
||||||
return bitdata == other.bitdata;
|
return bitdata == other.bitdata;
|
||||||
}
|
}
|
||||||
unsigned int hash() const {
|
Hasher hash_acc(Hasher h) const {
|
||||||
if (!cached_hash)
|
if (!cached_hash)
|
||||||
cached_hash = hash_ops<std::vector<RTLIL::State>>::hash(bitdata);
|
cached_hash = run_hash(bitdata);
|
||||||
return cached_hash;
|
h.acc(cached_hash);
|
||||||
|
return h;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
pool<bits_t> database;
|
pool<bits_t> database;
|
||||||
|
|
|
@ -39,13 +39,13 @@ bool AigNode::operator==(const AigNode &other) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int AigNode::hash() const
|
Hasher AigNode::hash_acc(Hasher h) const
|
||||||
{
|
{
|
||||||
unsigned int h = mkhash_init;
|
h.acc(portname);
|
||||||
h = mkhash(portname.hash(), portbit);
|
h.acc(portbit);
|
||||||
h = mkhash(h, inverter);
|
h.acc(inverter);
|
||||||
h = mkhash(h, left_parent);
|
h.acc(left_parent);
|
||||||
h = mkhash(h, right_parent);
|
h.acc(right_parent);
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,9 +54,10 @@ bool Aig::operator==(const Aig &other) const
|
||||||
return name == other.name;
|
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
|
struct AigMaker
|
||||||
|
|
|
@ -34,7 +34,7 @@ struct AigNode
|
||||||
|
|
||||||
AigNode();
|
AigNode();
|
||||||
bool operator==(const AigNode &other) const;
|
bool operator==(const AigNode &other) const;
|
||||||
unsigned int hash() const;
|
Hasher hash_acc(Hasher h) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Aig
|
struct Aig
|
||||||
|
@ -44,7 +44,7 @@ struct Aig
|
||||||
Aig(Cell *cell);
|
Aig(Cell *cell);
|
||||||
|
|
||||||
bool operator==(const Aig &other) const;
|
bool operator==(const Aig &other) const;
|
||||||
unsigned int hash() const;
|
Hasher hash_acc(Hasher h) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
YOSYS_NAMESPACE_END
|
YOSYS_NAMESPACE_END
|
||||||
|
|
|
@ -74,10 +74,8 @@ struct DriveBitWire
|
||||||
return offset < other.offset;
|
return offset < other.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int hash() const
|
Hasher hash_acc(Hasher h) const;
|
||||||
{
|
|
||||||
return mkhash_add(wire->name.hash(), offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
operator SigBit() const
|
operator SigBit() const
|
||||||
{
|
{
|
||||||
|
@ -107,10 +105,8 @@ struct DriveBitPort
|
||||||
return offset < other.offset;
|
return offset < other.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int hash() const
|
Hasher hash_acc(Hasher h) const;
|
||||||
{
|
|
||||||
return mkhash_add(mkhash(cell->name.hash(), port.hash()), offset);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -133,10 +129,7 @@ struct DriveBitMarker
|
||||||
return offset < other.offset;
|
return offset < other.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int hash() const
|
Hasher hash_acc(Hasher h) const;
|
||||||
{
|
|
||||||
return mkhash_add(marker, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -171,10 +164,7 @@ public:
|
||||||
return multiple_ == other.multiple_;
|
return multiple_ == other.multiple_;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int hash() const
|
Hasher hash_acc(Hasher h) const;
|
||||||
{
|
|
||||||
return multiple_.hash();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DriveBit
|
struct DriveBit
|
||||||
|
@ -362,32 +352,7 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int hash() const
|
Hasher hash_acc(Hasher h) const;
|
||||||
{
|
|
||||||
unsigned int inner;
|
|
||||||
switch (type_)
|
|
||||||
{
|
|
||||||
case DriveType::NONE:
|
|
||||||
inner = 0;
|
|
||||||
break;
|
|
||||||
case DriveType::CONSTANT:
|
|
||||||
inner = constant_;
|
|
||||||
break;
|
|
||||||
case DriveType::WIRE:
|
|
||||||
inner = wire_.hash();
|
|
||||||
break;
|
|
||||||
case DriveType::PORT:
|
|
||||||
inner = port_.hash();
|
|
||||||
break;
|
|
||||||
case DriveType::MARKER:
|
|
||||||
inner = marker_.hash();
|
|
||||||
break;
|
|
||||||
case DriveType::MULTIPLE:
|
|
||||||
inner = multiple_.hash();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return mkhash((unsigned int)type_, inner);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const DriveBit &other) const
|
bool operator==(const DriveBit &other) const
|
||||||
{
|
{
|
||||||
|
@ -508,10 +473,7 @@ struct DriveChunkWire
|
||||||
return offset < other.offset;
|
return offset < other.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int hash() const
|
Hasher hash_acc(Hasher h) const;
|
||||||
{
|
|
||||||
return mkhash_add(mkhash(wire->name.hash(), width), offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit operator SigChunk() const
|
explicit operator SigChunk() const
|
||||||
{
|
{
|
||||||
|
@ -569,10 +531,7 @@ struct DriveChunkPort
|
||||||
return offset < other.offset;
|
return offset < other.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int hash() const
|
Hasher hash_acc(Hasher h) const;
|
||||||
{
|
|
||||||
return mkhash_add(mkhash(mkhash(cell->name.hash(), port.hash()), width), offset);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -613,10 +572,7 @@ struct DriveChunkMarker
|
||||||
return offset < other.offset;
|
return offset < other.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int hash() const
|
Hasher hash_acc(Hasher h) const;
|
||||||
{
|
|
||||||
return mkhash_add(mkhash(marker, width), offset);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DriveChunkMultiple
|
struct DriveChunkMultiple
|
||||||
|
@ -656,10 +612,7 @@ public:
|
||||||
return false; // TODO implement, canonicalize order
|
return false; // TODO implement, canonicalize order
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int hash() const
|
Hasher hash_acc(Hasher h) const;
|
||||||
{
|
|
||||||
return mkhash(width_, multiple_.hash());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DriveChunk
|
struct DriveChunk
|
||||||
|
@ -910,32 +863,7 @@ public:
|
||||||
bool try_append(DriveBit const &bit);
|
bool try_append(DriveBit const &bit);
|
||||||
bool try_append(DriveChunk const &chunk);
|
bool try_append(DriveChunk const &chunk);
|
||||||
|
|
||||||
unsigned int hash() const
|
Hasher hash_acc(Hasher h) const;
|
||||||
{
|
|
||||||
unsigned int inner;
|
|
||||||
switch (type_)
|
|
||||||
{
|
|
||||||
case DriveType::NONE:
|
|
||||||
inner = 0;
|
|
||||||
break;
|
|
||||||
case DriveType::CONSTANT:
|
|
||||||
inner = constant_.hash();
|
|
||||||
break;
|
|
||||||
case DriveType::WIRE:
|
|
||||||
inner = wire_.hash();
|
|
||||||
break;
|
|
||||||
case DriveType::PORT:
|
|
||||||
inner = port_.hash();
|
|
||||||
break;
|
|
||||||
case DriveType::MARKER:
|
|
||||||
inner = marker_.hash();
|
|
||||||
break;
|
|
||||||
case DriveType::MULTIPLE:
|
|
||||||
inner = multiple_.hash();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return mkhash((unsigned int)type_, inner);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const DriveChunk &other) const
|
bool operator==(const DriveChunk &other) const
|
||||||
{
|
{
|
||||||
|
@ -1138,17 +1066,19 @@ public:
|
||||||
DriveSpec &operator=(DriveBitMarker const &bit) { return *this = DriveBit(bit); }
|
DriveSpec &operator=(DriveBitMarker const &bit) { return *this = DriveBit(bit); }
|
||||||
DriveSpec &operator=(DriveBitMultiple const &bit) { return *this = DriveBit(bit); }
|
DriveSpec &operator=(DriveBitMultiple const &bit) { return *this = DriveBit(bit); }
|
||||||
|
|
||||||
unsigned int hash() const {
|
void updhash() const {
|
||||||
if (hash_ != 0) return hash_;
|
DriveSpec *that = (DriveSpec*)this;
|
||||||
|
|
||||||
pack();
|
pack();
|
||||||
hash_ = hash_ops<std::vector<DriveChunk>>().hash(chunks_);
|
that->hash_ = run_hash(chunks_);
|
||||||
hash_ |= (hash_ == 0);
|
that->hash_ |= (that->hash_ == 0);
|
||||||
return hash_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Hasher hash_acc(Hasher h) const;
|
||||||
|
|
||||||
bool operator==(DriveSpec const &other) const {
|
bool operator==(DriveSpec const &other) const {
|
||||||
if (size() != other.size() || hash() != other.hash())
|
updhash();
|
||||||
|
other.updhash();
|
||||||
|
if (size() != other.size() || hash_ != other.hash_)
|
||||||
return false;
|
return false;
|
||||||
return chunks() == other.chunks();
|
return chunks() == other.chunks();
|
||||||
}
|
}
|
||||||
|
@ -1181,7 +1111,8 @@ private:
|
||||||
bool operator==(const DriveBitId &other) const { return id == other.id; }
|
bool operator==(const DriveBitId &other) const { return id == other.id; }
|
||||||
bool operator!=(const DriveBitId &other) const { return id != other.id; }
|
bool operator!=(const DriveBitId &other) const { return id != other.id; }
|
||||||
bool operator<(const DriveBitId &other) const { return id < other.id; }
|
bool operator<(const DriveBitId &other) const { return id < other.id; }
|
||||||
unsigned int hash() const { return id; }
|
// unsigned int hash() const { return id; }
|
||||||
|
Hasher hash_acc(Hasher h) const;
|
||||||
};
|
};
|
||||||
// Essentially a dict<DriveBitId, pool<DriveBitId>> but using less memory
|
// Essentially a dict<DriveBitId, pool<DriveBitId>> but using less memory
|
||||||
// and fewer allocations
|
// and fewer allocations
|
||||||
|
@ -1327,6 +1258,133 @@ private:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline Hasher DriveBitWire::hash_acc(Hasher h) const
|
||||||
|
{
|
||||||
|
h.acc(wire->name);
|
||||||
|
h.acc(offset);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Hasher DriveBitPort::hash_acc(Hasher h) const
|
||||||
|
{
|
||||||
|
h.acc(cell->name);
|
||||||
|
h.acc(port);
|
||||||
|
h.acc(offset);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Hasher DriveBitMarker::hash_acc(Hasher h) const
|
||||||
|
{
|
||||||
|
h.acc(marker);
|
||||||
|
h.acc(offset);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Hasher DriveBitMultiple::hash_acc(Hasher h) const
|
||||||
|
{
|
||||||
|
h.acc(multiple_);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Hasher DriveBit::hash_acc(Hasher h) const
|
||||||
|
{
|
||||||
|
switch (type_) {
|
||||||
|
case DriveType::NONE:
|
||||||
|
h.acc(0);
|
||||||
|
break;
|
||||||
|
case DriveType::CONSTANT:
|
||||||
|
h.acc(constant_);
|
||||||
|
break;
|
||||||
|
case DriveType::WIRE:
|
||||||
|
h.acc(wire_);
|
||||||
|
break;
|
||||||
|
case DriveType::PORT:
|
||||||
|
h.acc(port_);
|
||||||
|
break;
|
||||||
|
case DriveType::MARKER:
|
||||||
|
h.acc(marker_);
|
||||||
|
break;
|
||||||
|
case DriveType::MULTIPLE:
|
||||||
|
h.acc(multiple_);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
h.acc(type_);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Hasher DriveChunkWire::hash_acc(Hasher h) const
|
||||||
|
{
|
||||||
|
h.acc(wire->name);
|
||||||
|
h.acc(width);
|
||||||
|
h.acc(offset);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Hasher DriveChunkPort::hash_acc(Hasher h) const
|
||||||
|
{
|
||||||
|
h.acc(cell->name);
|
||||||
|
h.acc(port);
|
||||||
|
h.acc(width);
|
||||||
|
h.acc(offset);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Hasher DriveChunkMarker::hash_acc(Hasher h) const
|
||||||
|
{
|
||||||
|
h.acc(marker);
|
||||||
|
h.acc(width);
|
||||||
|
h.acc(offset);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Hasher DriveChunkMultiple::hash_acc(Hasher h) const
|
||||||
|
{
|
||||||
|
h.acc(width_);
|
||||||
|
h.acc(multiple_);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Hasher DriveChunk::hash_acc(Hasher h) const
|
||||||
|
{
|
||||||
|
switch (type_) {
|
||||||
|
case DriveType::NONE:
|
||||||
|
h.acc(0);
|
||||||
|
break;
|
||||||
|
case DriveType::CONSTANT:
|
||||||
|
h.acc(constant_);
|
||||||
|
break;
|
||||||
|
case DriveType::WIRE:
|
||||||
|
h.acc(wire_);
|
||||||
|
break;
|
||||||
|
case DriveType::PORT:
|
||||||
|
h.acc(port_);
|
||||||
|
break;
|
||||||
|
case DriveType::MARKER:
|
||||||
|
h.acc(marker_);
|
||||||
|
break;
|
||||||
|
case DriveType::MULTIPLE:
|
||||||
|
h.acc(multiple_);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
h.acc(type_);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Hasher DriveSpec::hash_acc(Hasher h) const
|
||||||
|
{
|
||||||
|
if (hash_ == 0)
|
||||||
|
updhash();
|
||||||
|
|
||||||
|
h.acc(hash_);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Hasher DriverMap::DriveBitId::hash_acc(Hasher h) const
|
||||||
|
{
|
||||||
|
h.acc(id);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
YOSYS_NAMESPACE_END
|
YOSYS_NAMESPACE_END
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -151,7 +151,7 @@ namespace Functional {
|
||||||
// returns the data width of a bitvector sort, errors out for other sorts
|
// returns the data width of a bitvector sort, errors out for other sorts
|
||||||
int data_width() const { return std::get<1>(_v).second; }
|
int data_width() const { return std::get<1>(_v).second; }
|
||||||
bool operator==(Sort const& other) const { return _v == other._v; }
|
bool operator==(Sort const& other) const { return _v == other._v; }
|
||||||
unsigned int hash() const { return mkhash(_v); }
|
Hasher hash_acc(Hasher h) const { h.acc(_v); return h; }
|
||||||
};
|
};
|
||||||
class IR;
|
class IR;
|
||||||
class Factory;
|
class Factory;
|
||||||
|
@ -225,8 +225,10 @@ namespace Functional {
|
||||||
const RTLIL::Const &as_const() const { return std::get<RTLIL::Const>(_extra); }
|
const RTLIL::Const &as_const() const { return std::get<RTLIL::Const>(_extra); }
|
||||||
std::pair<IdString, IdString> as_idstring_pair() const { return std::get<std::pair<IdString, IdString>>(_extra); }
|
std::pair<IdString, IdString> as_idstring_pair() const { return std::get<std::pair<IdString, IdString>>(_extra); }
|
||||||
int as_int() const { return std::get<int>(_extra); }
|
int as_int() const { return std::get<int>(_extra); }
|
||||||
int hash() const {
|
Hasher hash_acc(Hasher h) const {
|
||||||
return mkhash((unsigned int) _fn, mkhash(_extra));
|
h.acc((unsigned int) _fn);
|
||||||
|
h.acc(_extra);
|
||||||
|
return h;
|
||||||
}
|
}
|
||||||
bool operator==(NodeData const &other) const {
|
bool operator==(NodeData const &other) const {
|
||||||
return _fn == other._fn && _extra == other._extra;
|
return _fn == other._fn && _extra == other._extra;
|
||||||
|
|
301
kernel/hashlib.h
301
kernel/hashlib.h
|
@ -17,27 +17,47 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <type_traits>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace hashlib {
|
namespace hashlib {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HASHING
|
||||||
|
*
|
||||||
|
* The Hasher knows how to hash 32 and 64-bit integers. That's it.
|
||||||
|
* In the future, it could be expanded to do vectors with SIMD.
|
||||||
|
*
|
||||||
|
* The Hasher doesn't know how to hash common standard containers
|
||||||
|
* and compositions. However, hashlib provides centralized wrappers.
|
||||||
|
*
|
||||||
|
* Hashlib doesn't know how to hash silly Yosys-specific types.
|
||||||
|
* Hashlib doesn't depend on Yosys and can be used standalone.
|
||||||
|
* Please don't use hashlib standalone for new projects.
|
||||||
|
*
|
||||||
|
* The hash_ops type is now always left to its default value, derived
|
||||||
|
* from templated functions through SFINAE. Providing custom ops is
|
||||||
|
* still supported.
|
||||||
|
*
|
||||||
|
* HASH TABLES
|
||||||
|
*
|
||||||
|
* We implement associative data structures with separate chaining.
|
||||||
|
* Linked lists use integers into the indirection hashtable array
|
||||||
|
* instead of pointers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO describe how comparison hashes are special
|
||||||
|
// TODO draw the line between generic and hash function specific code
|
||||||
|
|
||||||
const int hashtable_size_trigger = 2;
|
const int hashtable_size_trigger = 2;
|
||||||
const int hashtable_size_factor = 3;
|
const int hashtable_size_factor = 3;
|
||||||
|
|
||||||
// The XOR version of DJB2
|
#define DJB2_BROKEN_SIZE
|
||||||
inline unsigned int mkhash(unsigned int a, unsigned int b) {
|
|
||||||
return ((a << 5) + a) ^ b;
|
|
||||||
}
|
|
||||||
|
|
||||||
// traditionally 5381 is used as starting value for the djb2 hash
|
#ifdef DJB2_BROKEN_SIZE
|
||||||
const unsigned int mkhash_init = 5381;
|
|
||||||
|
|
||||||
// The ADD version of DJB2
|
template<typename T>
|
||||||
// (use this version for cache locality in b)
|
struct hash_ops;
|
||||||
inline unsigned int mkhash_add(unsigned int a, unsigned int b) {
|
|
||||||
return ((a << 5) + a) + b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned int mkhash_xorshift(unsigned int a) {
|
inline unsigned int mkhash_xorshift(unsigned int a) {
|
||||||
if (sizeof(a) == 4) {
|
if (sizeof(a) == 4) {
|
||||||
|
@ -53,62 +73,76 @@ inline unsigned int mkhash_xorshift(unsigned int a) {
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> struct hash_ops {
|
class Hasher {
|
||||||
|
public: //TODO
|
||||||
|
using hash_t = uint32_t;
|
||||||
|
|
||||||
|
Hasher() {
|
||||||
|
// traditionally 5381 is used as starting value for the djb2 hash
|
||||||
|
state = 5381;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t state;
|
||||||
|
// The XOR version of DJB2
|
||||||
|
[[nodiscard]]
|
||||||
|
static uint32_t mkhash(uint32_t a, uint32_t b) {
|
||||||
|
return ((a << 5) + a) ^ b;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
void hash32(uint32_t i) {
|
||||||
|
state = mkhash(i, state);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void hash64(uint64_t i) {
|
||||||
|
state = mkhash((uint32_t)(i % (1ULL << 32ULL)), state);
|
||||||
|
state = mkhash((uint32_t)(i >> 32ULL), state);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hash_t yield() {
|
||||||
|
return (hash_t)state;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void acc(T t) {
|
||||||
|
*this = hash_ops<T>::hash_acc(t, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void commutative_acc(uint32_t t) {
|
||||||
|
state ^= t;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct hash_ops {
|
||||||
static inline bool cmp(const T &a, const T &b) {
|
static inline bool cmp(const T &a, const T &b) {
|
||||||
return a == b;
|
return a == b;
|
||||||
}
|
}
|
||||||
static inline unsigned int hash(const T &a) {
|
static inline Hasher hash_acc(const T &a, Hasher h) {
|
||||||
return a.hash();
|
if constexpr (std::is_same_v<T, bool>) {
|
||||||
}
|
h.hash32(a ? 1 : 0);
|
||||||
};
|
return h;
|
||||||
|
} else if constexpr (std::is_integral_v<T>) {
|
||||||
struct hash_int_ops {
|
static_assert(sizeof(T) <= sizeof(uint64_t));
|
||||||
template<typename T>
|
if (sizeof(T) == sizeof(uint64_t))
|
||||||
static inline bool cmp(T a, T b) {
|
h.hash64(a);
|
||||||
return a == b;
|
else
|
||||||
}
|
h.hash32(a);
|
||||||
};
|
return h;
|
||||||
|
} else if constexpr (std::is_enum_v<T>) {
|
||||||
template<> struct hash_ops<bool> : hash_int_ops
|
using u_type = std::underlying_type_t<T>;
|
||||||
{
|
return hash_ops<u_type>::hash_acc((u_type) a, h);
|
||||||
static inline unsigned int hash(bool a) {
|
} else if constexpr (std::is_pointer_v<T>) {
|
||||||
return a ? 1 : 0;
|
return hash_ops<uintptr_t>::hash_acc((uintptr_t) a, h);
|
||||||
}
|
} else if constexpr (std::is_same_v<T, std::string>) {
|
||||||
};
|
|
||||||
template<> struct hash_ops<int32_t> : hash_int_ops
|
|
||||||
{
|
|
||||||
static inline unsigned int hash(int32_t a) {
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
template<> struct hash_ops<int64_t> : hash_int_ops
|
|
||||||
{
|
|
||||||
static inline unsigned int hash(int64_t a) {
|
|
||||||
return mkhash((unsigned int)(a), (unsigned int)(a >> 32));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
template<> struct hash_ops<uint32_t> : hash_int_ops
|
|
||||||
{
|
|
||||||
static inline unsigned int hash(uint32_t a) {
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
template<> struct hash_ops<uint64_t> : hash_int_ops
|
|
||||||
{
|
|
||||||
static inline unsigned int hash(uint64_t a) {
|
|
||||||
return mkhash((unsigned int)(a), (unsigned int)(a >> 32));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<> struct hash_ops<std::string> {
|
|
||||||
static inline bool cmp(const std::string &a, const std::string &b) {
|
|
||||||
return a == b;
|
|
||||||
}
|
|
||||||
static inline unsigned int hash(const std::string &a) {
|
|
||||||
unsigned int v = 0;
|
|
||||||
for (auto c : a)
|
for (auto c : a)
|
||||||
v = mkhash(v, c);
|
h.hash32(c);
|
||||||
return v;
|
return h;
|
||||||
|
} else {
|
||||||
|
return a.hash_acc(h);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -116,8 +150,10 @@ template<typename P, typename Q> struct hash_ops<std::pair<P, Q>> {
|
||||||
static inline bool cmp(std::pair<P, Q> a, std::pair<P, Q> b) {
|
static inline bool cmp(std::pair<P, Q> a, std::pair<P, Q> b) {
|
||||||
return a == b;
|
return a == b;
|
||||||
}
|
}
|
||||||
static inline unsigned int hash(std::pair<P, Q> a) {
|
static inline Hasher hash_acc(std::pair<P, Q> a, Hasher h) {
|
||||||
return mkhash(hash_ops<P>::hash(a.first), hash_ops<Q>::hash(a.second));
|
h = hash_ops<P>::hash_acc(a.first, h);
|
||||||
|
h = hash_ops<Q>::hash_acc(a.second, h);
|
||||||
|
return h;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -126,13 +162,15 @@ template<typename... T> struct hash_ops<std::tuple<T...>> {
|
||||||
return a == b;
|
return a == b;
|
||||||
}
|
}
|
||||||
template<size_t I = 0>
|
template<size_t I = 0>
|
||||||
static inline typename std::enable_if<I == sizeof...(T), unsigned int>::type hash(std::tuple<T...>) {
|
static inline typename std::enable_if<I == sizeof...(T), Hasher>::type hash_acc(std::tuple<T...>, Hasher h) {
|
||||||
return mkhash_init;
|
return h;
|
||||||
}
|
}
|
||||||
template<size_t I = 0>
|
template<size_t I = 0>
|
||||||
static inline typename std::enable_if<I != sizeof...(T), unsigned int>::type hash(std::tuple<T...> a) {
|
static inline typename std::enable_if<I != sizeof...(T), Hasher>::type hash_acc(std::tuple<T...> a, Hasher h) {
|
||||||
typedef hash_ops<typename std::tuple_element<I, std::tuple<T...>>::type> element_ops_t;
|
typedef hash_ops<typename std::tuple_element<I, std::tuple<T...>>::type> element_ops_t;
|
||||||
return mkhash(hash<I+1>(a), element_ops_t::hash(std::get<I>(a)));
|
h = hash_acc<I+1>(a, h);
|
||||||
|
h = element_ops_t::hash_acc(std::get<I>(a), h);
|
||||||
|
return h;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -140,10 +178,10 @@ template<typename T> struct hash_ops<std::vector<T>> {
|
||||||
static inline bool cmp(std::vector<T> a, std::vector<T> b) {
|
static inline bool cmp(std::vector<T> a, std::vector<T> b) {
|
||||||
return a == b;
|
return a == b;
|
||||||
}
|
}
|
||||||
static inline unsigned int hash(std::vector<T> a) {
|
static inline Hasher hash_acc(std::vector<T> a, Hasher h) {
|
||||||
unsigned int h = mkhash_init;
|
h.acc(a.size());
|
||||||
for (auto k : a)
|
for (auto k : a)
|
||||||
h = mkhash(h, hash_ops<T>::hash(k));
|
h.acc(k);
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -155,20 +193,21 @@ struct hash_cstr_ops {
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
static inline unsigned int hash(const char *a) {
|
static inline Hasher hash_acc(const char *a, Hasher h) {
|
||||||
unsigned int hash = mkhash_init;
|
|
||||||
while (*a)
|
while (*a)
|
||||||
hash = mkhash(hash, *(a++));
|
h.hash32(*(a++));
|
||||||
return hash;
|
return h;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <> struct hash_ops<char*> : hash_cstr_ops {};
|
||||||
|
|
||||||
struct hash_ptr_ops {
|
struct hash_ptr_ops {
|
||||||
static inline bool cmp(const void *a, const void *b) {
|
static inline bool cmp(const void *a, const void *b) {
|
||||||
return a == b;
|
return a == b;
|
||||||
}
|
}
|
||||||
static inline unsigned int hash(const void *a) {
|
static inline Hasher hash_acc(const void *a, Hasher h) {
|
||||||
return (uintptr_t)a;
|
return hash_ops<uintptr_t>::hash_acc((uintptr_t)a, h);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -177,22 +216,36 @@ struct hash_obj_ops {
|
||||||
return a == b;
|
return a == b;
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static inline unsigned int hash(const T *a) {
|
static inline Hasher hash_acc(const T *a, Hasher h) {
|
||||||
return a ? a->hash() : 0;
|
return a ? a->hash_acc(h) : h;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* If you find yourself using this function, think hard
|
||||||
|
* about if it's the right thing to do. Mixing finalized
|
||||||
|
* hashes together with XORs or worse can destroy
|
||||||
|
* desirable qualities of the hash function
|
||||||
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline unsigned int mkhash(const T &v) {
|
Hasher::hash_t run_hash(const T& obj) {
|
||||||
return hash_ops<T>().hash(v);
|
Hasher h;
|
||||||
|
h.acc(obj);
|
||||||
|
return h.yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #ifdef OTHER_HASH...
|
||||||
|
|
||||||
|
// [[deprecated]]
|
||||||
|
// inline unsigned int mkhash_add(unsigned int a, unsigned int b) {
|
||||||
|
// return mkhash(a, b);
|
||||||
|
// }
|
||||||
|
|
||||||
template<> struct hash_ops<std::monostate> {
|
template<> struct hash_ops<std::monostate> {
|
||||||
static inline bool cmp(std::monostate a, std::monostate b) {
|
static inline bool cmp(std::monostate a, std::monostate b) {
|
||||||
return a == b;
|
return a == b;
|
||||||
}
|
}
|
||||||
static inline unsigned int hash(std::monostate) {
|
static inline Hasher hash_acc(std::monostate, Hasher h) {
|
||||||
return mkhash_init;
|
return h;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -200,9 +253,10 @@ template<typename... T> struct hash_ops<std::variant<T...>> {
|
||||||
static inline bool cmp(std::variant<T...> a, std::variant<T...> b) {
|
static inline bool cmp(std::variant<T...> a, std::variant<T...> b) {
|
||||||
return a == b;
|
return a == b;
|
||||||
}
|
}
|
||||||
static inline unsigned int hash(std::variant<T...> a) {
|
static inline Hasher hash_acc(std::variant<T...> a, Hasher h) {
|
||||||
unsigned int h = std::visit([](const auto &v) { return mkhash(v); }, a);
|
std::visit([& h](const auto &v) { h.acc(v); }, a);
|
||||||
return mkhash(a.index(), h);
|
h.acc(a.index());
|
||||||
|
return h;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -210,11 +264,12 @@ template<typename T> struct hash_ops<std::optional<T>> {
|
||||||
static inline bool cmp(std::optional<T> a, std::optional<T> b) {
|
static inline bool cmp(std::optional<T> a, std::optional<T> b) {
|
||||||
return a == b;
|
return a == b;
|
||||||
}
|
}
|
||||||
static inline unsigned int hash(std::optional<T> a) {
|
static inline Hasher hash_acc(std::optional<T> a, Hasher h) {
|
||||||
if(a.has_value())
|
if(a.has_value())
|
||||||
return mkhash(*a);
|
h.acc(*a);
|
||||||
else
|
else
|
||||||
return 0;
|
h.acc(0);
|
||||||
|
return h;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -246,14 +301,13 @@ inline int hashtable_size(int min_size)
|
||||||
throw std::length_error("hash table exceeded maximum size.");
|
throw std::length_error("hash table exceeded maximum size.");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename K, typename T, typename OPS = hash_ops<K>> class dict;
|
template<typename K, typename T> class dict;
|
||||||
template<typename K, int offset = 0, typename OPS = hash_ops<K>> class idict;
|
template<typename K, int offset = 0> class idict;
|
||||||
template<typename K, typename OPS = hash_ops<K>> class pool;
|
template<typename K> class pool;
|
||||||
template<typename K, typename OPS = hash_ops<K>> class mfp;
|
template<typename K> class mfp;
|
||||||
|
|
||||||
template<typename K, typename T, typename OPS>
|
template<typename K, typename T>
|
||||||
class dict
|
class dict {
|
||||||
{
|
|
||||||
struct entry_t
|
struct entry_t
|
||||||
{
|
{
|
||||||
std::pair<K, T> udata;
|
std::pair<K, T> udata;
|
||||||
|
@ -267,7 +321,7 @@ class dict
|
||||||
|
|
||||||
std::vector<int> hashtable;
|
std::vector<int> hashtable;
|
||||||
std::vector<entry_t> entries;
|
std::vector<entry_t> entries;
|
||||||
OPS ops;
|
hash_ops<K> ops;
|
||||||
|
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
static inline void do_assert(bool) { }
|
static inline void do_assert(bool) { }
|
||||||
|
@ -279,9 +333,9 @@ class dict
|
||||||
|
|
||||||
int do_hash(const K &key) const
|
int do_hash(const K &key) const
|
||||||
{
|
{
|
||||||
unsigned int hash = 0;
|
Hasher::hash_t hash = 0;
|
||||||
if (!hashtable.empty())
|
if (!hashtable.empty())
|
||||||
hash = ops.hash(key) % (unsigned int)(hashtable.size());
|
hash = run_hash<K>(key) % (unsigned int)(hashtable.size());
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -683,11 +737,13 @@ public:
|
||||||
return !operator==(other);
|
return !operator==(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int hash() const {
|
Hasher hash_acc(Hasher h) const {
|
||||||
unsigned int h = mkhash_init;
|
h.acc(entries.size());
|
||||||
for (auto &entry : entries) {
|
for (auto &it : entries) {
|
||||||
h ^= hash_ops<K>::hash(entry.udata.first);
|
Hasher entry_hash;
|
||||||
h ^= hash_ops<T>::hash(entry.udata.second);
|
entry_hash.acc(it.udata.first);
|
||||||
|
entry_hash.acc(it.udata.second);
|
||||||
|
h.commutative_acc(entry_hash.yield());
|
||||||
}
|
}
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
@ -706,10 +762,10 @@ public:
|
||||||
const_iterator end() const { return const_iterator(nullptr, -1); }
|
const_iterator end() const { return const_iterator(nullptr, -1); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename K, typename OPS>
|
template<typename K>
|
||||||
class pool
|
class pool
|
||||||
{
|
{
|
||||||
template<typename, int, typename> friend class idict;
|
template<typename, int> friend class idict;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct entry_t
|
struct entry_t
|
||||||
|
@ -724,7 +780,7 @@ protected:
|
||||||
|
|
||||||
std::vector<int> hashtable;
|
std::vector<int> hashtable;
|
||||||
std::vector<entry_t> entries;
|
std::vector<entry_t> entries;
|
||||||
OPS ops;
|
hash_ops<K> ops;
|
||||||
|
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
static inline void do_assert(bool) { }
|
static inline void do_assert(bool) { }
|
||||||
|
@ -736,9 +792,9 @@ protected:
|
||||||
|
|
||||||
int do_hash(const K &key) const
|
int do_hash(const K &key) const
|
||||||
{
|
{
|
||||||
unsigned int hash = 0;
|
Hasher::hash_t hash = 0;
|
||||||
if (!hashtable.empty())
|
if (!hashtable.empty())
|
||||||
hash = ops.hash(key) % (unsigned int)(hashtable.size());
|
hash = run_hash<K>(key) % (unsigned int)(hashtable.size());
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1051,11 +1107,12 @@ public:
|
||||||
return !operator==(other);
|
return !operator==(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int hash() const {
|
Hasher hash_acc(Hasher h) const {
|
||||||
unsigned int hashval = mkhash_init;
|
h.acc(entries.size());
|
||||||
for (auto &it : entries)
|
for (auto &it : entries) {
|
||||||
hashval ^= ops.hash(it.udata);
|
h.commutative_acc(run_hash(it.udata));
|
||||||
return hashval;
|
}
|
||||||
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reserve(size_t n) { entries.reserve(n); }
|
void reserve(size_t n) { entries.reserve(n); }
|
||||||
|
@ -1072,10 +1129,10 @@ public:
|
||||||
const_iterator end() const { return const_iterator(nullptr, -1); }
|
const_iterator end() const { return const_iterator(nullptr, -1); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename K, int offset, typename OPS>
|
template<typename K, int offset>
|
||||||
class idict
|
class idict
|
||||||
{
|
{
|
||||||
pool<K, OPS> database;
|
pool<K> database;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class const_iterator
|
class const_iterator
|
||||||
|
@ -1169,14 +1226,14 @@ public:
|
||||||
* mfp stands for "merge, find, promote"
|
* mfp stands for "merge, find, promote"
|
||||||
* i-prefixed methods operate on indices in parents
|
* i-prefixed methods operate on indices in parents
|
||||||
*/
|
*/
|
||||||
template<typename K, typename OPS>
|
template<typename K>
|
||||||
class mfp
|
class mfp
|
||||||
{
|
{
|
||||||
mutable idict<K, 0, OPS> database;
|
mutable idict<K, 0> database;
|
||||||
mutable std::vector<int> parents;
|
mutable std::vector<int> parents;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef typename idict<K, 0, OPS>::const_iterator const_iterator;
|
typedef typename idict<K, 0>::const_iterator const_iterator;
|
||||||
|
|
||||||
constexpr mfp()
|
constexpr mfp()
|
||||||
{
|
{
|
||||||
|
|
12
kernel/log.h
12
kernel/log.h
|
@ -363,13 +363,13 @@ void log_dump_val_worker(RTLIL::IdString v);
|
||||||
void log_dump_val_worker(RTLIL::SigSpec v);
|
void log_dump_val_worker(RTLIL::SigSpec v);
|
||||||
void log_dump_val_worker(RTLIL::State v);
|
void log_dump_val_worker(RTLIL::State v);
|
||||||
|
|
||||||
template<typename K, typename T, typename OPS> static inline void log_dump_val_worker(dict<K, T, OPS> &v);
|
template<typename K, typename T> static inline void log_dump_val_worker(dict<K, T> &v);
|
||||||
template<typename K, typename OPS> static inline void log_dump_val_worker(pool<K, OPS> &v);
|
template<typename K> static inline void log_dump_val_worker(pool<K> &v);
|
||||||
template<typename K> static inline void log_dump_val_worker(std::vector<K> &v);
|
template<typename K> static inline void log_dump_val_worker(std::vector<K> &v);
|
||||||
template<typename T> static inline void log_dump_val_worker(T *ptr);
|
template<typename T> static inline void log_dump_val_worker(T *ptr);
|
||||||
|
|
||||||
template<typename K, typename T, typename OPS>
|
template<typename K, typename T>
|
||||||
static inline void log_dump_val_worker(dict<K, T, OPS> &v) {
|
static inline void log_dump_val_worker(dict<K, T> &v) {
|
||||||
log("{");
|
log("{");
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (auto &it : v) {
|
for (auto &it : v) {
|
||||||
|
@ -382,8 +382,8 @@ static inline void log_dump_val_worker(dict<K, T, OPS> &v) {
|
||||||
log(" }");
|
log(" }");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename K, typename OPS>
|
template<typename K>
|
||||||
static inline void log_dump_val_worker(pool<K, OPS> &v) {
|
static inline void log_dump_val_worker(pool<K> &v) {
|
||||||
log("{");
|
log("{");
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (auto &it : v) {
|
for (auto &it : v) {
|
||||||
|
|
|
@ -48,8 +48,11 @@ struct ModIndex : public RTLIL::Monitor
|
||||||
return cell == other.cell && port == other.port && offset == other.offset;
|
return cell == other.cell && port == other.port && offset == other.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int hash() const {
|
Hasher hash_acc(Hasher h) const {
|
||||||
return mkhash_add(mkhash(cell->name.hash(), port.hash()), offset);
|
h.acc(cell->name);
|
||||||
|
h.acc(port);
|
||||||
|
h.acc(offset);
|
||||||
|
return h;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -57,6 +60,8 @@ struct ModIndex : public RTLIL::Monitor
|
||||||
{
|
{
|
||||||
bool is_input, is_output;
|
bool is_input, is_output;
|
||||||
pool<PortInfo> ports;
|
pool<PortInfo> ports;
|
||||||
|
// SigBitInfo() : SigBitInfo{} {}
|
||||||
|
// SigBitInfo& operator=(const SigBitInfo&) = default;
|
||||||
|
|
||||||
SigBitInfo() : is_input(false), is_output(false) { }
|
SigBitInfo() : is_input(false), is_output(false) { }
|
||||||
|
|
||||||
|
@ -304,6 +309,8 @@ struct ModWalker
|
||||||
RTLIL::Cell *cell;
|
RTLIL::Cell *cell;
|
||||||
RTLIL::IdString port;
|
RTLIL::IdString port;
|
||||||
int offset;
|
int offset;
|
||||||
|
PortBit(Cell* c, IdString p, int o) : cell(c), port(p), offset(o) {}
|
||||||
|
// PortBit& operator=(const PortBit&) = default;
|
||||||
|
|
||||||
bool operator<(const PortBit &other) const {
|
bool operator<(const PortBit &other) const {
|
||||||
if (cell != other.cell)
|
if (cell != other.cell)
|
||||||
|
@ -317,8 +324,11 @@ struct ModWalker
|
||||||
return cell == other.cell && port == other.port && offset == other.offset;
|
return cell == other.cell && port == other.port && offset == other.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int hash() const {
|
Hasher hash_acc(Hasher h) const {
|
||||||
return mkhash_add(mkhash(cell->name.hash(), port.hash()), offset);
|
h.acc(cell->name);
|
||||||
|
h.acc(port);
|
||||||
|
h.acc(offset);
|
||||||
|
return h;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -355,7 +365,7 @@ struct ModWalker
|
||||||
{
|
{
|
||||||
for (int i = 0; i < int(bits.size()); i++)
|
for (int i = 0; i < int(bits.size()); i++)
|
||||||
if (bits[i].wire != NULL) {
|
if (bits[i].wire != NULL) {
|
||||||
PortBit pbit = { cell, port, i };
|
PortBit pbit {cell, port, i};
|
||||||
if (is_output) {
|
if (is_output) {
|
||||||
signal_drivers[bits[i]].insert(pbit);
|
signal_drivers[bits[i]].insert(pbit);
|
||||||
cell_outputs[cell].insert(bits[i]);
|
cell_outputs[cell].insert(bits[i]);
|
||||||
|
|
|
@ -35,7 +35,7 @@ YOSYS_NAMESPACE_BEGIN
|
||||||
bool RTLIL::IdString::destruct_guard_ok = false;
|
bool RTLIL::IdString::destruct_guard_ok = false;
|
||||||
RTLIL::IdString::destruct_guard_t RTLIL::IdString::destruct_guard;
|
RTLIL::IdString::destruct_guard_t RTLIL::IdString::destruct_guard;
|
||||||
std::vector<char*> RTLIL::IdString::global_id_storage_;
|
std::vector<char*> RTLIL::IdString::global_id_storage_;
|
||||||
dict<char*, int, hash_cstr_ops> RTLIL::IdString::global_id_index_;
|
dict<char*, int> RTLIL::IdString::global_id_index_;
|
||||||
#ifndef YOSYS_NO_IDS_REFCNT
|
#ifndef YOSYS_NO_IDS_REFCNT
|
||||||
std::vector<int> RTLIL::IdString::global_refcount_storage_;
|
std::vector<int> RTLIL::IdString::global_refcount_storage_;
|
||||||
std::vector<int> RTLIL::IdString::global_free_idx_list_;
|
std::vector<int> RTLIL::IdString::global_free_idx_list_;
|
||||||
|
@ -4461,17 +4461,17 @@ void RTLIL::SigSpec::updhash() const
|
||||||
cover("kernel.rtlil.sigspec.hash");
|
cover("kernel.rtlil.sigspec.hash");
|
||||||
that->pack();
|
that->pack();
|
||||||
|
|
||||||
that->hash_ = mkhash_init;
|
Hasher h;
|
||||||
for (auto &c : that->chunks_)
|
for (auto &c : that->chunks_)
|
||||||
if (c.wire == NULL) {
|
if (c.wire == NULL) {
|
||||||
for (auto &v : c.data)
|
for (auto &v : c.data)
|
||||||
that->hash_ = mkhash(that->hash_, v);
|
h.acc(v);
|
||||||
} else {
|
} else {
|
||||||
that->hash_ = mkhash(that->hash_, c.wire->name.index_);
|
h.acc(c.wire->name.index_);
|
||||||
that->hash_ = mkhash(that->hash_, c.offset);
|
h.acc(c.offset);
|
||||||
that->hash_ = mkhash(that->hash_, c.width);
|
h.acc(c.width);
|
||||||
}
|
}
|
||||||
|
that->hash_ = h.yield();
|
||||||
if (that->hash_ == 0)
|
if (that->hash_ == 0)
|
||||||
that->hash_ = 1;
|
that->hash_ = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,7 +95,7 @@ namespace RTLIL
|
||||||
} destruct_guard;
|
} destruct_guard;
|
||||||
|
|
||||||
static std::vector<char*> global_id_storage_;
|
static std::vector<char*> global_id_storage_;
|
||||||
static dict<char*, int, hash_cstr_ops> global_id_index_;
|
static dict<char*, int> global_id_index_;
|
||||||
#ifndef YOSYS_NO_IDS_REFCNT
|
#ifndef YOSYS_NO_IDS_REFCNT
|
||||||
static std::vector<int> global_refcount_storage_;
|
static std::vector<int> global_refcount_storage_;
|
||||||
static std::vector<int> global_free_idx_list_;
|
static std::vector<int> global_free_idx_list_;
|
||||||
|
@ -360,8 +360,8 @@ namespace RTLIL
|
||||||
*this = IdString();
|
*this = IdString();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int hash() const {
|
Hasher hash_acc(Hasher h) const {
|
||||||
return index_;
|
return hash_ops<int>::hash_acc(index_, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The following is a helper key_compare class. Instead of for example std::set<Cell*>
|
// The following is a helper key_compare class. Instead of for example std::set<Cell*>
|
||||||
|
@ -796,11 +796,10 @@ public:
|
||||||
bv.resize(width, bv.empty() ? RTLIL::State::Sx : bv.back());
|
bv.resize(width, bv.empty() ? RTLIL::State::Sx : bv.back());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned int hash() const {
|
inline Hasher hash_acc(Hasher h) const {
|
||||||
unsigned int h = mkhash_init;
|
// TODO hash size
|
||||||
|
for (auto b : *this)
|
||||||
for (State b : *this)
|
h.acc(b);
|
||||||
h = mkhash(h, b);
|
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -889,7 +888,7 @@ struct RTLIL::SigBit
|
||||||
bool operator <(const RTLIL::SigBit &other) const;
|
bool operator <(const RTLIL::SigBit &other) const;
|
||||||
bool operator ==(const RTLIL::SigBit &other) const;
|
bool operator ==(const RTLIL::SigBit &other) const;
|
||||||
bool operator !=(const RTLIL::SigBit &other) const;
|
bool operator !=(const RTLIL::SigBit &other) const;
|
||||||
unsigned int hash() const;
|
Hasher hash_acc(Hasher h) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RTLIL::SigSpecIterator
|
struct RTLIL::SigSpecIterator
|
||||||
|
@ -930,7 +929,7 @@ struct RTLIL::SigSpec
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
int width_;
|
int width_;
|
||||||
unsigned long hash_;
|
Hasher::hash_t hash_;
|
||||||
std::vector<RTLIL::SigChunk> chunks_; // LSB at index 0
|
std::vector<RTLIL::SigChunk> chunks_; // LSB at index 0
|
||||||
std::vector<RTLIL::SigBit> bits_; // LSB at index 0
|
std::vector<RTLIL::SigBit> bits_; // LSB at index 0
|
||||||
|
|
||||||
|
@ -971,9 +970,10 @@ public:
|
||||||
SigSpec(const std::set<RTLIL::SigBit> &bits);
|
SigSpec(const std::set<RTLIL::SigBit> &bits);
|
||||||
explicit SigSpec(bool bit);
|
explicit SigSpec(bool bit);
|
||||||
|
|
||||||
|
[[deprecated]]
|
||||||
size_t get_hash() const {
|
size_t get_hash() const {
|
||||||
if (!hash_) hash();
|
log_assert(false && "deprecated");
|
||||||
return hash_;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::vector<RTLIL::SigChunk> &chunks() const { pack(); return chunks_; }
|
inline const std::vector<RTLIL::SigChunk> &chunks() const { pack(); return chunks_; }
|
||||||
|
@ -1082,7 +1082,7 @@ public:
|
||||||
operator std::vector<RTLIL::SigBit>() const { return bits(); }
|
operator std::vector<RTLIL::SigBit>() const { return bits(); }
|
||||||
const RTLIL::SigBit &at(int offset, const RTLIL::SigBit &defval) { return offset < width_ ? (*this)[offset] : defval; }
|
const RTLIL::SigBit &at(int offset, const RTLIL::SigBit &defval) { return offset < width_ ? (*this)[offset] : defval; }
|
||||||
|
|
||||||
unsigned int hash() const { if (!hash_) updhash(); return hash_; };
|
Hasher hash_acc(Hasher h) const { if (!hash_) updhash(); h.acc(hash_); return h; }
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
void check(Module *mod = nullptr) const;
|
void check(Module *mod = nullptr) const;
|
||||||
|
@ -1123,8 +1123,8 @@ struct RTLIL::Selection
|
||||||
|
|
||||||
struct RTLIL::Monitor
|
struct RTLIL::Monitor
|
||||||
{
|
{
|
||||||
unsigned int hashidx_;
|
Hasher::hash_t hashidx_;
|
||||||
unsigned int hash() const { return hashidx_; }
|
Hasher hash_acc(Hasher h) const { h.acc(hashidx_); return h; }
|
||||||
|
|
||||||
Monitor() {
|
Monitor() {
|
||||||
static unsigned int hashidx_count = 123456789;
|
static unsigned int hashidx_count = 123456789;
|
||||||
|
@ -1146,8 +1146,8 @@ struct define_map_t;
|
||||||
|
|
||||||
struct RTLIL::Design
|
struct RTLIL::Design
|
||||||
{
|
{
|
||||||
unsigned int hashidx_;
|
Hasher::hash_t hashidx_;
|
||||||
unsigned int hash() const { return hashidx_; }
|
Hasher hash_acc(Hasher h) const { h.acc(hashidx_); return h; }
|
||||||
|
|
||||||
pool<RTLIL::Monitor*> monitors;
|
pool<RTLIL::Monitor*> monitors;
|
||||||
dict<std::string, std::string> scratchpad;
|
dict<std::string, std::string> scratchpad;
|
||||||
|
@ -1251,8 +1251,8 @@ struct RTLIL::Design
|
||||||
|
|
||||||
struct RTLIL::Module : public RTLIL::AttrObject
|
struct RTLIL::Module : public RTLIL::AttrObject
|
||||||
{
|
{
|
||||||
unsigned int hashidx_;
|
Hasher::hash_t hashidx_;
|
||||||
unsigned int hash() const { return hashidx_; }
|
Hasher hash_acc(Hasher h) const { h.acc(hashidx_); return h; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void add(RTLIL::Wire *wire);
|
void add(RTLIL::Wire *wire);
|
||||||
|
@ -1602,8 +1602,8 @@ void dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire);
|
||||||
|
|
||||||
struct RTLIL::Wire : public RTLIL::AttrObject
|
struct RTLIL::Wire : public RTLIL::AttrObject
|
||||||
{
|
{
|
||||||
unsigned int hashidx_;
|
Hasher::hash_t hashidx_;
|
||||||
unsigned int hash() const { return hashidx_; }
|
Hasher hash_acc(Hasher h) const { h.acc(hashidx_); return h; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// use module->addWire() and module->remove() to create or destroy wires
|
// use module->addWire() and module->remove() to create or destroy wires
|
||||||
|
@ -1641,8 +1641,8 @@ inline int GetSize(RTLIL::Wire *wire) {
|
||||||
|
|
||||||
struct RTLIL::Memory : public RTLIL::AttrObject
|
struct RTLIL::Memory : public RTLIL::AttrObject
|
||||||
{
|
{
|
||||||
unsigned int hashidx_;
|
Hasher::hash_t hashidx_;
|
||||||
unsigned int hash() const { return hashidx_; }
|
Hasher hash_acc(Hasher h) const { h.acc(hashidx_); return h; }
|
||||||
|
|
||||||
Memory();
|
Memory();
|
||||||
|
|
||||||
|
@ -1656,8 +1656,8 @@ struct RTLIL::Memory : public RTLIL::AttrObject
|
||||||
|
|
||||||
struct RTLIL::Cell : public RTLIL::AttrObject
|
struct RTLIL::Cell : public RTLIL::AttrObject
|
||||||
{
|
{
|
||||||
unsigned int hashidx_;
|
Hasher::hash_t hashidx_;
|
||||||
unsigned int hash() const { return hashidx_; }
|
Hasher hash_acc(Hasher h) const { h.acc(hashidx_); return h; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// use module->addCell() and module->remove() to create or destroy cells
|
// use module->addCell() and module->remove() to create or destroy cells
|
||||||
|
@ -1766,8 +1766,8 @@ struct RTLIL::SyncRule
|
||||||
|
|
||||||
struct RTLIL::Process : public RTLIL::AttrObject
|
struct RTLIL::Process : public RTLIL::AttrObject
|
||||||
{
|
{
|
||||||
unsigned int hashidx_;
|
Hasher::hash_t hashidx_;
|
||||||
unsigned int hash() const { return hashidx_; }
|
Hasher hash_acc(Hasher h) const { h.acc(hashidx_); return h; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// use module->addProcess() and module->remove() to create or destroy processes
|
// use module->addProcess() and module->remove() to create or destroy processes
|
||||||
|
@ -1811,10 +1811,14 @@ inline bool RTLIL::SigBit::operator!=(const RTLIL::SigBit &other) const {
|
||||||
return (wire != other.wire) || (wire ? (offset != other.offset) : (data != other.data));
|
return (wire != other.wire) || (wire ? (offset != other.offset) : (data != other.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned int RTLIL::SigBit::hash() const {
|
inline Hasher RTLIL::SigBit::hash_acc(Hasher h) const {
|
||||||
if (wire)
|
if (wire) {
|
||||||
return mkhash_add(wire->name.hash(), offset);
|
h = wire->name.hash_acc(h);
|
||||||
return data;
|
h.acc(offset);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
h.acc(data);
|
||||||
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline RTLIL::SigBit &RTLIL::SigSpecIterator::operator*() const {
|
inline RTLIL::SigBit &RTLIL::SigSpecIterator::operator*() const {
|
||||||
|
|
|
@ -318,7 +318,7 @@ struct ModuleItem {
|
||||||
Cell *cell() const { return type == Type::Cell ? static_cast<Cell *>(ptr) : nullptr; }
|
Cell *cell() const { return type == Type::Cell ? static_cast<Cell *>(ptr) : nullptr; }
|
||||||
|
|
||||||
bool operator==(const ModuleItem &other) const { return ptr == other.ptr && type == other.type; }
|
bool operator==(const ModuleItem &other) const { return ptr == other.ptr && type == other.type; }
|
||||||
unsigned int hash() const { return (uintptr_t)ptr; }
|
Hasher hash_acc(Hasher h) const { h.acc(ptr); return h; }
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void log_dump_val_worker(typename IdTree<ModuleItem>::Cursor cursor ) { log("%p %s", cursor.target, log_id(cursor.scope_name)); }
|
static inline void log_dump_val_worker(typename IdTree<ModuleItem>::Cursor cursor ) { log("%p %s", cursor.target, log_id(cursor.scope_name)); }
|
||||||
|
|
|
@ -29,7 +29,11 @@ struct SigPool
|
||||||
struct bitDef_t : public std::pair<RTLIL::Wire*, int> {
|
struct bitDef_t : public std::pair<RTLIL::Wire*, int> {
|
||||||
bitDef_t() : std::pair<RTLIL::Wire*, int>(NULL, 0) { }
|
bitDef_t() : std::pair<RTLIL::Wire*, int>(NULL, 0) { }
|
||||||
bitDef_t(const RTLIL::SigBit &bit) : std::pair<RTLIL::Wire*, int>(bit.wire, bit.offset) { }
|
bitDef_t(const RTLIL::SigBit &bit) : std::pair<RTLIL::Wire*, int>(bit.wire, bit.offset) { }
|
||||||
unsigned int hash() const { return first->name.hash() + second; }
|
Hasher hash_acc(Hasher h) const {
|
||||||
|
h.acc(first->name);
|
||||||
|
h.acc(second);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pool<bitDef_t> bits;
|
pool<bitDef_t> bits;
|
||||||
|
@ -143,7 +147,11 @@ struct SigSet
|
||||||
struct bitDef_t : public std::pair<RTLIL::Wire*, int> {
|
struct bitDef_t : public std::pair<RTLIL::Wire*, int> {
|
||||||
bitDef_t() : std::pair<RTLIL::Wire*, int>(NULL, 0) { }
|
bitDef_t() : std::pair<RTLIL::Wire*, int>(NULL, 0) { }
|
||||||
bitDef_t(const RTLIL::SigBit &bit) : std::pair<RTLIL::Wire*, int>(bit.wire, bit.offset) { }
|
bitDef_t(const RTLIL::SigBit &bit) : std::pair<RTLIL::Wire*, int>(bit.wire, bit.offset) { }
|
||||||
unsigned int hash() const { return first->name.hash() + second; }
|
Hasher hash_acc(Hasher h) const {
|
||||||
|
h.acc(first->name);
|
||||||
|
h.acc(second);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
dict<bitDef_t, std::set<T, Compare>> bits;
|
dict<bitDef_t, std::set<T, Compare>> bits;
|
||||||
|
|
|
@ -36,7 +36,6 @@ struct TimingInfo
|
||||||
explicit NameBit(const RTLIL::SigBit &b) : name(b.wire->name), offset(b.offset) {}
|
explicit NameBit(const RTLIL::SigBit &b) : name(b.wire->name), offset(b.offset) {}
|
||||||
bool operator==(const NameBit& nb) const { return nb.name == name && nb.offset == offset; }
|
bool operator==(const NameBit& nb) const { return nb.name == name && nb.offset == offset; }
|
||||||
bool operator!=(const NameBit& nb) const { return !operator==(nb); }
|
bool operator!=(const NameBit& nb) const { return !operator==(nb); }
|
||||||
unsigned int hash() const { return mkhash_add(name.hash(), offset); }
|
|
||||||
std::optional<SigBit> get_connection(RTLIL::Cell *cell) {
|
std::optional<SigBit> get_connection(RTLIL::Cell *cell) {
|
||||||
if (!cell->hasPort(name))
|
if (!cell->hasPort(name))
|
||||||
return {};
|
return {};
|
||||||
|
@ -45,6 +44,11 @@ struct TimingInfo
|
||||||
return {};
|
return {};
|
||||||
return port[offset];
|
return port[offset];
|
||||||
}
|
}
|
||||||
|
Hasher hash_acc(Hasher h) const {
|
||||||
|
h.acc(name);
|
||||||
|
h.acc(offset);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
struct BitBit
|
struct BitBit
|
||||||
{
|
{
|
||||||
|
@ -52,7 +56,11 @@ struct TimingInfo
|
||||||
BitBit(const NameBit &first, const NameBit &second) : first(first), second(second) {}
|
BitBit(const NameBit &first, const NameBit &second) : first(first), second(second) {}
|
||||||
BitBit(const SigBit &first, const SigBit &second) : first(first), second(second) {}
|
BitBit(const SigBit &first, const SigBit &second) : first(first), second(second) {}
|
||||||
bool operator==(const BitBit& bb) const { return bb.first == first && bb.second == second; }
|
bool operator==(const BitBit& bb) const { return bb.first == first && bb.second == second; }
|
||||||
unsigned int hash() const { return mkhash_add(first.hash(), second.hash()); }
|
Hasher hash_acc(Hasher h) const {
|
||||||
|
h.acc(first);
|
||||||
|
h.acc(second);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ModuleTiming
|
struct ModuleTiming
|
||||||
|
|
|
@ -31,17 +31,17 @@ YOSYS_NAMESPACE_BEGIN
|
||||||
// A map-like container, but you can save and restore the state
|
// A map-like container, but you can save and restore the state
|
||||||
// ------------------------------------------------
|
// ------------------------------------------------
|
||||||
|
|
||||||
template<typename Key, typename T, typename OPS = hash_ops<Key>>
|
template<typename Key, typename T>
|
||||||
struct stackmap
|
struct stackmap
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::vector<dict<Key, T*, OPS>> backup_state;
|
std::vector<dict<Key, T*>> backup_state;
|
||||||
dict<Key, T, OPS> current_state;
|
dict<Key, T> current_state;
|
||||||
static T empty_tuple;
|
static T empty_tuple;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
stackmap() { }
|
stackmap() { }
|
||||||
stackmap(const dict<Key, T, OPS> &other) : current_state(other) { }
|
stackmap(const dict<Key, T> &other) : current_state(other) { }
|
||||||
|
|
||||||
template<typename Other>
|
template<typename Other>
|
||||||
void operator=(const Other &other)
|
void operator=(const Other &other)
|
||||||
|
@ -94,7 +94,7 @@ public:
|
||||||
current_state.erase(k);
|
current_state.erase(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
const dict<Key, T, OPS> &stdmap()
|
const dict<Key, T> &stdmap()
|
||||||
{
|
{
|
||||||
return current_state;
|
return current_state;
|
||||||
}
|
}
|
||||||
|
@ -128,7 +128,7 @@ public:
|
||||||
// A simple class for topological sorting
|
// A simple class for topological sorting
|
||||||
// ------------------------------------------------
|
// ------------------------------------------------
|
||||||
|
|
||||||
template <typename T, typename C = std::less<T>, typename OPS = hash_ops<T>> class TopoSort
|
template <typename T, typename C = std::less<T>> class TopoSort
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// We use this ordering of the edges in the adjacency matrix for
|
// We use this ordering of the edges in the adjacency matrix for
|
||||||
|
|
|
@ -176,6 +176,15 @@ using std::get;
|
||||||
using std::min;
|
using std::min;
|
||||||
using std::max;
|
using std::max;
|
||||||
|
|
||||||
|
using hashlib::Hasher;
|
||||||
|
using hashlib::run_hash;
|
||||||
|
using hashlib::hash_ops;
|
||||||
|
using hashlib::mkhash_xorshift;
|
||||||
|
using hashlib::dict;
|
||||||
|
using hashlib::idict;
|
||||||
|
using hashlib::pool;
|
||||||
|
using hashlib::mfp;
|
||||||
|
|
||||||
// A primitive shared string implementation that does not
|
// A primitive shared string implementation that does not
|
||||||
// move its .c_str() when the object is copied or moved.
|
// move its .c_str() when the object is copied or moved.
|
||||||
struct shared_str {
|
struct shared_str {
|
||||||
|
@ -186,22 +195,12 @@ struct shared_str {
|
||||||
const char *c_str() const { return content->c_str(); }
|
const char *c_str() const { return content->c_str(); }
|
||||||
const string &str() const { return *content; }
|
const string &str() const { return *content; }
|
||||||
bool operator==(const shared_str &other) const { return *content == *other.content; }
|
bool operator==(const shared_str &other) const { return *content == *other.content; }
|
||||||
unsigned int hash() const { return hashlib::hash_ops<std::string>::hash(*content); }
|
Hasher hash_acc(Hasher h) const {
|
||||||
|
h.acc(*content);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using hashlib::mkhash;
|
|
||||||
using hashlib::mkhash_init;
|
|
||||||
using hashlib::mkhash_add;
|
|
||||||
using hashlib::mkhash_xorshift;
|
|
||||||
using hashlib::hash_ops;
|
|
||||||
using hashlib::hash_cstr_ops;
|
|
||||||
using hashlib::hash_ptr_ops;
|
|
||||||
using hashlib::hash_obj_ops;
|
|
||||||
using hashlib::dict;
|
|
||||||
using hashlib::idict;
|
|
||||||
using hashlib::pool;
|
|
||||||
using hashlib::mfp;
|
|
||||||
|
|
||||||
namespace RTLIL {
|
namespace RTLIL {
|
||||||
struct IdString;
|
struct IdString;
|
||||||
struct Const;
|
struct Const;
|
||||||
|
@ -240,26 +239,6 @@ using RTLIL::State;
|
||||||
using RTLIL::SigChunk;
|
using RTLIL::SigChunk;
|
||||||
using RTLIL::SigSig;
|
using RTLIL::SigSig;
|
||||||
|
|
||||||
namespace hashlib {
|
|
||||||
template<> struct hash_ops<RTLIL::Wire*> : hash_obj_ops {};
|
|
||||||
template<> struct hash_ops<RTLIL::Cell*> : hash_obj_ops {};
|
|
||||||
template<> struct hash_ops<RTLIL::Memory*> : hash_obj_ops {};
|
|
||||||
template<> struct hash_ops<RTLIL::Process*> : hash_obj_ops {};
|
|
||||||
template<> struct hash_ops<RTLIL::Module*> : hash_obj_ops {};
|
|
||||||
template<> struct hash_ops<RTLIL::Design*> : hash_obj_ops {};
|
|
||||||
template<> struct hash_ops<RTLIL::Monitor*> : hash_obj_ops {};
|
|
||||||
template<> struct hash_ops<AST::AstNode*> : hash_obj_ops {};
|
|
||||||
|
|
||||||
template<> struct hash_ops<const RTLIL::Wire*> : hash_obj_ops {};
|
|
||||||
template<> struct hash_ops<const RTLIL::Cell*> : hash_obj_ops {};
|
|
||||||
template<> struct hash_ops<const RTLIL::Memory*> : hash_obj_ops {};
|
|
||||||
template<> struct hash_ops<const RTLIL::Process*> : hash_obj_ops {};
|
|
||||||
template<> struct hash_ops<const RTLIL::Module*> : hash_obj_ops {};
|
|
||||||
template<> struct hash_ops<const RTLIL::Design*> : hash_obj_ops {};
|
|
||||||
template<> struct hash_ops<const RTLIL::Monitor*> : hash_obj_ops {};
|
|
||||||
template<> struct hash_ops<const AST::AstNode*> : hash_obj_ops {};
|
|
||||||
}
|
|
||||||
|
|
||||||
void memhasher_on();
|
void memhasher_on();
|
||||||
void memhasher_off();
|
void memhasher_off();
|
||||||
void memhasher_do();
|
void memhasher_do();
|
||||||
|
@ -370,10 +349,6 @@ RTLIL::IdString new_id_suffix(std::string file, int line, std::string func, std:
|
||||||
static const YOSYS_NAMESPACE_PREFIX RTLIL::IdString id(q); return id; })()
|
static const YOSYS_NAMESPACE_PREFIX RTLIL::IdString id(q); return id; })()
|
||||||
namespace ID = RTLIL::ID;
|
namespace ID = RTLIL::ID;
|
||||||
|
|
||||||
namespace hashlib {
|
|
||||||
template<> struct hash_ops<RTLIL::State> : hash_ops<int> {};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
YOSYS_NAMESPACE_END
|
YOSYS_NAMESPACE_END
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ struct IdPath : public std::vector<RTLIL::IdString>
|
||||||
bool has_address() const { int tmp; return get_address(tmp); };
|
bool has_address() const { int tmp; return get_address(tmp); };
|
||||||
bool get_address(int &addr) const;
|
bool get_address(int &addr) const;
|
||||||
|
|
||||||
int hash() const { return hashlib::hash_ops<std::vector<RTLIL::IdString>>::hash(*this); }
|
Hasher hash_acc(Hasher h) const { h.acc(*this); return h; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WitnessHierarchyItem {
|
struct WitnessHierarchyItem {
|
||||||
|
|
|
@ -47,7 +47,7 @@ struct DftTagWorker {
|
||||||
bool operator<(const tag_set &other) const { return index < other.index; }
|
bool operator<(const tag_set &other) const { return index < other.index; }
|
||||||
bool operator==(const tag_set &other) const { return index == other.index; }
|
bool operator==(const tag_set &other) const { return index == other.index; }
|
||||||
|
|
||||||
unsigned int hash() const { return hash_ops<int>::hash(index); }
|
Hasher hash_acc(Hasher h) const { h.acc(index); return h; }
|
||||||
|
|
||||||
bool empty() const { return index == 0; }
|
bool empty() const { return index == 0; }
|
||||||
};
|
};
|
||||||
|
|
|
@ -52,8 +52,10 @@ struct ExampleDtPass : public Pass
|
||||||
return name == other.name && parameters == other.parameters;
|
return name == other.name && parameters == other.parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int hash() const {
|
Hasher hash_acc(Hasher h) const {
|
||||||
return mkhash(name.hash(), parameters.hash());
|
h.acc(name);
|
||||||
|
h.acc(parameters);
|
||||||
|
return h;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -70,13 +70,13 @@ struct GraphNode {
|
||||||
|
|
||||||
pool<IdString> names_;
|
pool<IdString> names_;
|
||||||
dict<int, uint8_t> tags_;
|
dict<int, uint8_t> tags_;
|
||||||
pool<GraphNode*, hash_ptr_ops> upstream_;
|
pool<GraphNode*> upstream_;
|
||||||
pool<GraphNode*, hash_ptr_ops> downstream_;
|
pool<GraphNode*> downstream_;
|
||||||
|
|
||||||
pool<IdString> &names() { return get()->names_; }
|
pool<IdString> &names() { return get()->names_; }
|
||||||
dict<int, uint8_t> &tags() { return get()->tags_; }
|
dict<int, uint8_t> &tags() { return get()->tags_; }
|
||||||
pool<GraphNode*, hash_ptr_ops> &upstream() { return get()->upstream_; }
|
pool<GraphNode*> &upstream() { return get()->upstream_; }
|
||||||
pool<GraphNode*, hash_ptr_ops> &downstream() { return get()->downstream_; }
|
pool<GraphNode*> &downstream() { return get()->downstream_; }
|
||||||
|
|
||||||
uint8_t tag(int index) {
|
uint8_t tag(int index) {
|
||||||
return tags().at(index, 0);
|
return tags().at(index, 0);
|
||||||
|
@ -154,8 +154,8 @@ struct Graph {
|
||||||
nodes.push_back(n);
|
nodes.push_back(n);
|
||||||
n->index = GetSize(nodes);
|
n->index = GetSize(nodes);
|
||||||
|
|
||||||
pool<GraphNode*, hash_ptr_ops> new_upstream;
|
pool<GraphNode*> new_upstream;
|
||||||
pool<GraphNode*, hash_ptr_ops> new_downstream;
|
pool<GraphNode*> new_downstream;
|
||||||
|
|
||||||
for (auto g : n->upstream()) {
|
for (auto g : n->upstream()) {
|
||||||
if (n != (g = g->get()))
|
if (n != (g = g->get()))
|
||||||
|
@ -302,7 +302,7 @@ struct Graph {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pool<GraphNode*, hash_ptr_ops> excluded;
|
pool<GraphNode*> excluded;
|
||||||
|
|
||||||
for (auto grp : config.groups)
|
for (auto grp : config.groups)
|
||||||
{
|
{
|
||||||
|
@ -348,7 +348,7 @@ struct Graph {
|
||||||
excluded.insert(g->get());
|
excluded.insert(g->get());
|
||||||
|
|
||||||
dict<Cell*, GraphNode*> cell_nodes;
|
dict<Cell*, GraphNode*> cell_nodes;
|
||||||
dict<SigBit, pool<GraphNode*, hash_ptr_ops>> sig_users;
|
dict<SigBit, pool<GraphNode*>> sig_users;
|
||||||
|
|
||||||
for (auto cell : module->selected_cells()) {
|
for (auto cell : module->selected_cells()) {
|
||||||
auto g = new GraphNode;
|
auto g = new GraphNode;
|
||||||
|
@ -483,8 +483,8 @@ struct Graph {
|
||||||
|
|
||||||
{
|
{
|
||||||
header("Any nodes with identical connections");
|
header("Any nodes with identical connections");
|
||||||
typedef pair<pool<GraphNode*, hash_ptr_ops>, pool<GraphNode*, hash_ptr_ops>> node_conn_t;
|
typedef pair<pool<GraphNode*>, pool<GraphNode*>> node_conn_t;
|
||||||
dict<node_conn_t, pool<GraphNode*, hash_ptr_ops>> nodes_by_conn;
|
dict<node_conn_t, pool<GraphNode*>> nodes_by_conn;
|
||||||
for (auto g : term ? term_nodes : nonterm_nodes) {
|
for (auto g : term ? term_nodes : nonterm_nodes) {
|
||||||
auto &entry = nodes_by_conn[node_conn_t(g->upstream(), g->downstream())];
|
auto &entry = nodes_by_conn[node_conn_t(g->upstream(), g->downstream())];
|
||||||
for (auto n : entry)
|
for (auto n : entry)
|
||||||
|
@ -506,8 +506,8 @@ struct Graph {
|
||||||
|
|
||||||
header("Sibblings with identical tags");
|
header("Sibblings with identical tags");
|
||||||
for (auto g : nonterm_nodes) {
|
for (auto g : nonterm_nodes) {
|
||||||
auto process_conns = [&](const pool<GraphNode*, hash_ptr_ops> &stream) {
|
auto process_conns = [&](const pool<GraphNode*> &stream) {
|
||||||
dict<std::vector<int>, pool<GraphNode*, hash_ptr_ops>> nodes_by_tags;
|
dict<std::vector<int>, pool<GraphNode*>> nodes_by_tags;
|
||||||
for (auto n : stream) {
|
for (auto n : stream) {
|
||||||
if (n->terminal) continue;
|
if (n->terminal) continue;
|
||||||
std::vector<int> key;
|
std::vector<int> key;
|
||||||
|
@ -556,7 +556,7 @@ struct Graph {
|
||||||
if (!term) {
|
if (!term) {
|
||||||
header("Sibblings with similar tags (strict)");
|
header("Sibblings with similar tags (strict)");
|
||||||
for (auto g : nonterm_nodes) {
|
for (auto g : nonterm_nodes) {
|
||||||
auto process_conns = [&](const pool<GraphNode*, hash_ptr_ops> &stream) {
|
auto process_conns = [&](const pool<GraphNode*> &stream) {
|
||||||
std::vector<GraphNode*> nodes;
|
std::vector<GraphNode*> nodes;
|
||||||
for (auto n : stream)
|
for (auto n : stream)
|
||||||
if (!n->terminal) nodes.push_back(n);
|
if (!n->terminal) nodes.push_back(n);
|
||||||
|
@ -585,7 +585,7 @@ struct Graph {
|
||||||
if (!term) {
|
if (!term) {
|
||||||
header("Sibblings with similar tags (non-strict)");
|
header("Sibblings with similar tags (non-strict)");
|
||||||
for (auto g : nonterm_nodes) {
|
for (auto g : nonterm_nodes) {
|
||||||
auto process_conns = [&](const pool<GraphNode*, hash_ptr_ops> &stream) {
|
auto process_conns = [&](const pool<GraphNode*> &stream) {
|
||||||
std::vector<GraphNode*> nodes;
|
std::vector<GraphNode*> nodes;
|
||||||
for (auto n : stream)
|
for (auto n : stream)
|
||||||
if (!n->terminal) nodes.push_back(n);
|
if (!n->terminal) nodes.push_back(n);
|
||||||
|
@ -603,7 +603,7 @@ struct Graph {
|
||||||
|
|
||||||
{
|
{
|
||||||
header("Any nodes with identical fan-in or fan-out");
|
header("Any nodes with identical fan-in or fan-out");
|
||||||
dict<pool<GraphNode*, hash_ptr_ops>, pool<GraphNode*, hash_ptr_ops>> nodes_by_conn[2];
|
dict<pool<GraphNode*>, pool<GraphNode*>> nodes_by_conn[2];
|
||||||
for (auto g : term ? term_nodes : nonterm_nodes) {
|
for (auto g : term ? term_nodes : nonterm_nodes) {
|
||||||
auto &up_entry = nodes_by_conn[0][g->upstream()];
|
auto &up_entry = nodes_by_conn[0][g->upstream()];
|
||||||
auto &down_entry = nodes_by_conn[1][g->downstream()];
|
auto &down_entry = nodes_by_conn[1][g->downstream()];
|
||||||
|
@ -629,7 +629,7 @@ struct Graph {
|
||||||
if (!term) {
|
if (!term) {
|
||||||
header("Sibblings with similar tags (lax)");
|
header("Sibblings with similar tags (lax)");
|
||||||
for (auto g : nonterm_nodes) {
|
for (auto g : nonterm_nodes) {
|
||||||
auto process_conns = [&](const pool<GraphNode*, hash_ptr_ops> &stream) {
|
auto process_conns = [&](const pool<GraphNode*> &stream) {
|
||||||
std::vector<GraphNode*> nodes;
|
std::vector<GraphNode*> nodes;
|
||||||
for (auto n : stream)
|
for (auto n : stream)
|
||||||
if (!n->terminal) nodes.push_back(n);
|
if (!n->terminal) nodes.push_back(n);
|
||||||
|
@ -720,9 +720,9 @@ struct VizWorker
|
||||||
fprintf(f, "digraph \"%s\" {\n", log_id(module));
|
fprintf(f, "digraph \"%s\" {\n", log_id(module));
|
||||||
fprintf(f, " rankdir = LR;\n");
|
fprintf(f, " rankdir = LR;\n");
|
||||||
|
|
||||||
dict<GraphNode*, std::vector<std::vector<std::string>>, hash_ptr_ops> extra_lines;
|
dict<GraphNode*, std::vector<std::vector<std::string>>> extra_lines;
|
||||||
dict<GraphNode*, GraphNode*, hash_ptr_ops> bypass_nodes;
|
dict<GraphNode*, GraphNode*> bypass_nodes;
|
||||||
pool<GraphNode*, hash_ptr_ops> bypass_candidates;
|
pool<GraphNode*> bypass_candidates;
|
||||||
|
|
||||||
auto bypass = [&](GraphNode *g, GraphNode *n) {
|
auto bypass = [&](GraphNode *g, GraphNode *n) {
|
||||||
log_assert(g->terminal);
|
log_assert(g->terminal);
|
||||||
|
|
|
@ -46,11 +46,11 @@ struct EquivStructWorker
|
||||||
parameters == other.parameters && port_sizes == other.port_sizes;
|
parameters == other.parameters && port_sizes == other.port_sizes;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int hash() const {
|
Hasher hash_acc(Hasher h) const {
|
||||||
unsigned int h = mkhash_init;
|
h.acc(type);
|
||||||
h = mkhash(h, mkhash(type));
|
h.acc(parameters);
|
||||||
h = mkhash(h, mkhash(parameters));
|
h.acc(port_sizes);
|
||||||
h = mkhash(h, mkhash(connections));
|
h.acc(connections);
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -127,11 +127,10 @@ struct proc_dlatch_db_t
|
||||||
return signal == other.signal && match == other.match && children == other.children;
|
return signal == other.signal && match == other.match && children == other.children;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int hash() const {
|
Hasher hash_acc(Hasher h) const {
|
||||||
unsigned int h = mkhash_init;
|
h.acc(signal);
|
||||||
mkhash(h, signal.hash());
|
h.acc(match);
|
||||||
mkhash(h, match.hash());
|
h.acc(children);
|
||||||
for (auto i : children) mkhash(h, i);
|
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -108,8 +108,8 @@ struct SigSnippets
|
||||||
|
|
||||||
struct SnippetSwCache
|
struct SnippetSwCache
|
||||||
{
|
{
|
||||||
dict<RTLIL::SwitchRule*, pool<RTLIL::SigBit>, hash_ptr_ops> full_case_bits_cache;
|
dict<RTLIL::SwitchRule*, pool<RTLIL::SigBit>> full_case_bits_cache;
|
||||||
dict<RTLIL::SwitchRule*, pool<int>, hash_ptr_ops> cache;
|
dict<RTLIL::SwitchRule*, pool<int>> cache;
|
||||||
const SigSnippets *snippets;
|
const SigSnippets *snippets;
|
||||||
int current_snippet;
|
int current_snippet;
|
||||||
|
|
||||||
|
@ -318,7 +318,7 @@ const pool<SigBit> &get_full_case_bits(SnippetSwCache &swcache, RTLIL::SwitchRul
|
||||||
return swcache.full_case_bits_cache.at(sw);
|
return swcache.full_case_bits_cache.at(sw);
|
||||||
}
|
}
|
||||||
|
|
||||||
RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, SnippetSwCache &swcache, dict<RTLIL::SwitchRule*, bool, hash_ptr_ops> &swpara,
|
RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, SnippetSwCache &swcache, dict<RTLIL::SwitchRule*, bool> &swpara,
|
||||||
RTLIL::CaseRule *cs, const RTLIL::SigSpec &sig, const RTLIL::SigSpec &defval, bool ifxmode)
|
RTLIL::CaseRule *cs, const RTLIL::SigSpec &sig, const RTLIL::SigSpec &defval, bool ifxmode)
|
||||||
{
|
{
|
||||||
RTLIL::SigSpec result = defval;
|
RTLIL::SigSpec result = defval;
|
||||||
|
@ -421,7 +421,7 @@ void proc_mux(RTLIL::Module *mod, RTLIL::Process *proc, bool ifxmode)
|
||||||
swcache.snippets = &sigsnip;
|
swcache.snippets = &sigsnip;
|
||||||
swcache.insert(&proc->root_case);
|
swcache.insert(&proc->root_case);
|
||||||
|
|
||||||
dict<RTLIL::SwitchRule*, bool, hash_ptr_ops> swpara;
|
dict<RTLIL::SwitchRule*, bool> swpara;
|
||||||
|
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
for (int idx : sigsnip.snippets)
|
for (int idx : sigsnip.snippets)
|
||||||
|
|
|
@ -176,7 +176,7 @@ struct coverdb_t
|
||||||
|
|
||||||
struct mutate_queue_t
|
struct mutate_queue_t
|
||||||
{
|
{
|
||||||
pool<mutate_t*, hash_ptr_ops> db;
|
pool<mutate_t*> db;
|
||||||
|
|
||||||
mutate_t *pick(xs128_t &rng, coverdb_t &coverdb, const mutate_opts_t &opts) {
|
mutate_t *pick(xs128_t &rng, coverdb_t &coverdb, const mutate_opts_t &opts) {
|
||||||
mutate_t *m = nullptr;
|
mutate_t *m = nullptr;
|
||||||
|
|
|
@ -46,9 +46,11 @@ struct IdBit {
|
||||||
|
|
||||||
bool operator==(const IdBit &other) const { return name == other.name && bit == other.bit; };
|
bool operator==(const IdBit &other) const { return name == other.name && bit == other.bit; };
|
||||||
bool operator!=(const IdBit &other) const { return name != other.name || bit != other.bit; };
|
bool operator!=(const IdBit &other) const { return name != other.name || bit != other.bit; };
|
||||||
unsigned hash() const
|
Hasher hash_acc(Hasher h) const
|
||||||
{
|
{
|
||||||
return mkhash_add(name.hash(), bit);
|
h.acc(name);
|
||||||
|
h.acc(bit);
|
||||||
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
IdString name;
|
IdString name;
|
||||||
|
@ -62,9 +64,11 @@ struct InvBit {
|
||||||
|
|
||||||
bool operator==(const InvBit &other) const { return bit == other.bit && inverted == other.inverted; };
|
bool operator==(const InvBit &other) const { return bit == other.bit && inverted == other.inverted; };
|
||||||
bool operator!=(const InvBit &other) const { return bit != other.bit || inverted != other.inverted; };
|
bool operator!=(const InvBit &other) const { return bit != other.bit || inverted != other.inverted; };
|
||||||
unsigned hash() const
|
Hasher hash_acc(Hasher h) const
|
||||||
{
|
{
|
||||||
return mkhash(bit.hash(), inverted);
|
h.acc(bit);
|
||||||
|
h.acc(inverted);
|
||||||
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
IdBit bit;
|
IdBit bit;
|
||||||
|
|
|
@ -161,7 +161,7 @@ struct SimInstance
|
||||||
pool<SigBit> dirty_bits;
|
pool<SigBit> dirty_bits;
|
||||||
pool<Cell*> dirty_cells;
|
pool<Cell*> dirty_cells;
|
||||||
pool<IdString> dirty_memories;
|
pool<IdString> dirty_memories;
|
||||||
pool<SimInstance*, hash_ptr_ops> dirty_children;
|
pool<SimInstance*> dirty_children;
|
||||||
|
|
||||||
struct ff_state_t
|
struct ff_state_t
|
||||||
{
|
{
|
||||||
|
|
|
@ -111,7 +111,7 @@ struct AlumaccWorker
|
||||||
|
|
||||||
dict<RTLIL::SigBit, int> bit_users;
|
dict<RTLIL::SigBit, int> bit_users;
|
||||||
dict<RTLIL::SigSpec, maccnode_t*> sig_macc;
|
dict<RTLIL::SigSpec, maccnode_t*> sig_macc;
|
||||||
dict<RTLIL::SigSig, pool<alunode_t*, hash_ptr_ops>> sig_alu;
|
dict<RTLIL::SigSig, pool<alunode_t*>> sig_alu;
|
||||||
int macc_counter, alu_counter;
|
int macc_counter, alu_counter;
|
||||||
|
|
||||||
AlumaccWorker(RTLIL::Module *module) : module(module), sigmap(module)
|
AlumaccWorker(RTLIL::Module *module) : module(module), sigmap(module)
|
||||||
|
@ -226,7 +226,7 @@ struct AlumaccWorker
|
||||||
{
|
{
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
pool<maccnode_t*, hash_ptr_ops> delete_nodes;
|
pool<maccnode_t*> delete_nodes;
|
||||||
|
|
||||||
for (auto &it : sig_macc)
|
for (auto &it : sig_macc)
|
||||||
{
|
{
|
||||||
|
@ -278,7 +278,7 @@ struct AlumaccWorker
|
||||||
|
|
||||||
void macc_to_alu()
|
void macc_to_alu()
|
||||||
{
|
{
|
||||||
pool<maccnode_t*, hash_ptr_ops> delete_nodes;
|
pool<maccnode_t*> delete_nodes;
|
||||||
|
|
||||||
for (auto &it : sig_macc)
|
for (auto &it : sig_macc)
|
||||||
{
|
{
|
||||||
|
|
|
@ -77,10 +77,9 @@ struct ClockgatePass : public Pass {
|
||||||
SigBit ce_bit;
|
SigBit ce_bit;
|
||||||
bool pol_clk;
|
bool pol_clk;
|
||||||
bool pol_ce;
|
bool pol_ce;
|
||||||
unsigned int hash() const {
|
Hasher hash_acc(Hasher h) const {
|
||||||
auto t = std::make_tuple(clk_bit, ce_bit, pol_clk, pol_ce);
|
auto t = std::make_tuple(clk_bit, ce_bit, pol_clk, pol_ce);
|
||||||
unsigned int h = mkhash_init;
|
h.acc(t);
|
||||||
h = mkhash(h, hash_ops<decltype(t)>::hash(t));
|
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
bool operator==(const ClkNetInfo& other) const {
|
bool operator==(const ClkNetInfo& other) const {
|
||||||
|
|
|
@ -250,9 +250,11 @@ struct FlowGraph
|
||||||
{
|
{
|
||||||
return !(*this == other);
|
return !(*this == other);
|
||||||
}
|
}
|
||||||
unsigned int hash() const
|
Hasher hash_acc(Hasher h) const
|
||||||
{
|
{
|
||||||
return hash_ops<pair<RTLIL::SigBit, int>>::hash({node, is_bottom});
|
std::pair<RTLIL::SigBit, int> p = {node, is_bottom};
|
||||||
|
h.acc(p);
|
||||||
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NodePrime top(RTLIL::SigBit node)
|
static NodePrime top(RTLIL::SigBit node)
|
||||||
|
|
|
@ -53,7 +53,7 @@ struct QlDspSimdPass : public Pass {
|
||||||
DspConfig(const DspConfig &ref) = default;
|
DspConfig(const DspConfig &ref) = default;
|
||||||
DspConfig(DspConfig &&ref) = default;
|
DspConfig(DspConfig &&ref) = default;
|
||||||
|
|
||||||
unsigned int hash() const { return connections.hash(); }
|
Hasher hash_acc(Hasher h) const { h.acc(connections); return h; }
|
||||||
|
|
||||||
bool operator==(const DspConfig &ref) const { return connections == ref.connections; }
|
bool operator==(const DspConfig &ref) const { return connections == ref.connections; }
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue