X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=kernel%2Ftiminginfo.h;h=e7e4eab6e2e4df489529a3f5b28dc23270cb5803;hb=98c7804b89f5d384c920fe2280ed33432207f0cb;hp=8c16fff6c2008ac91d44eaf8df37354e9dc2813a;hpb=cda4acb544614711b2c187e93f515bfc43ca8da1;p=yosys.git diff --git a/kernel/timinginfo.h b/kernel/timinginfo.h index 8c16fff6c..e7e4eab6e 100644 --- a/kernel/timinginfo.h +++ b/kernel/timinginfo.h @@ -1,7 +1,7 @@ /* * yosys -- Yosys Open SYnthesis Suite * - * Copyright (C) 2012 Clifford Wolf + * Copyright (C) 2012 Claire Xenia Wolf * (C) 2020 Eddie Hung * * Permission to use, copy, modify, and/or distribute this software for any @@ -18,25 +18,43 @@ * */ -#ifndef TIMINGARCS_H -#define TIMINGARCS_H +#ifndef TIMINGINFO_H +#define TIMINGINFO_H #include "kernel/yosys.h" YOSYS_NAMESPACE_BEGIN -typedef std::pair BitBit; - -struct ModuleTiming -{ - RTLIL::IdString type; - dict comb; - dict arrival, required; -}; - struct TimingInfo { - dict data; + struct NameBit + { + RTLIL::IdString name; + int offset; + NameBit() : offset(0) {} + NameBit(const RTLIL::IdString name, int offset) : name(name), offset(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 !operator==(nb); } + unsigned int hash() const { return mkhash_add(name.hash(), offset); } + }; + struct BitBit + { + NameBit first, second; + BitBit(const NameBit &first, const NameBit &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; } + unsigned int hash() const { return mkhash_add(first.hash(), second.hash()); } + }; + + struct ModuleTiming + { + dict comb; + dict> arrival, required; + bool has_inputs; + }; + + dict data; TimingInfo() { @@ -53,119 +71,120 @@ struct TimingInfo if (!module->get_blackbox_attribute()) continue; setup_module(module); - } + } } - void setup_module(RTLIL::Module *module) + const ModuleTiming& setup_module(RTLIL::Module *module) { - auto r = data.insert(module->name); - log_assert(r.second); - auto &t = r.first->second; + auto r = data.insert(module->name); + log_assert(r.second); + auto &t = r.first->second; for (auto cell : module->cells()) { - if (cell->type == ID($specify2)) { - auto src = cell->getPort(ID(SRC)); - auto dst = cell->getPort(ID(DST)); - for (const auto &c : src.chunks()) - if (!c.wire->port_input) - log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); - for (const auto &c : dst.chunks()) - if (!c.wire->port_output) - log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module output.\n", log_id(module), log_id(cell), log_signal(dst)); - int rise_max = cell->getParam(ID(T_RISE_MAX)).as_int(); - int fall_max = cell->getParam(ID(T_FALL_MAX)).as_int(); - int max = std::max(rise_max,fall_max); - if (max < 0) - log_error("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0.\n", log_id(module), log_id(cell)); - if (cell->getParam(ID(FULL)).as_bool()) { - for (const auto &s : src) - for (const auto &d : dst) { - auto r = t.comb.insert(BitBit(s,d)); - if (!r.second) - log_error("Module '%s' contains multiple specify cells for SRC '%s' and DST '%s'.\n", log_id(module), log_signal(s), log_signal(d)); - r.first->second = max; - } - } - else { - log_assert(GetSize(src) == GetSize(dst)); - for (auto i = 0; i < GetSize(src); i++) { - const auto &s = src[i]; - const auto &d = dst[i]; - auto r = t.comb.insert(BitBit(s,d)); - if (!r.second) - log_error("Module '%s' contains multiple specify cells for SRC '%s' and DST '%s'.\n", log_id(module), log_signal(s), log_signal(d)); - r.first->second = max; - } - } - } - else if (cell->type == ID($specify3)) { - auto src = cell->getPort(ID(SRC)); - auto dst = cell->getPort(ID(DST)); + if (cell->type == ID($specify2)) { + auto en = cell->getPort(ID::EN); + if (en.is_fully_const() && !en.as_bool()) + continue; + auto src = cell->getPort(ID::SRC); + auto dst = cell->getPort(ID::DST); for (const auto &c : src.chunks()) - if (!c.wire->port_input) + if (!c.wire || !c.wire->port_input) log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); for (const auto &c : dst.chunks()) - if (!c.wire->port_output) + if (!c.wire || !c.wire->port_output) log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module output.\n", log_id(module), log_id(cell), log_signal(dst)); - int rise_max = cell->getParam(ID(T_RISE_MAX)).as_int(); - int fall_max = cell->getParam(ID(T_FALL_MAX)).as_int(); + int rise_max = cell->getParam(ID::T_RISE_MAX).as_int(); + int fall_max = cell->getParam(ID::T_FALL_MAX).as_int(); int max = std::max(rise_max,fall_max); if (max < 0) - log_warning("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); - if (max <= 0) { - log_debug("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX <= 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); - continue; + log_error("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0.\n", log_id(module), log_id(cell)); + if (cell->getParam(ID::FULL).as_bool()) { + for (const auto &s : src) + for (const auto &d : dst) { + auto r = t.comb.insert(BitBit(s,d)); + if (!r.second) + log_error("Module '%s' contains multiple specify cells for SRC '%s' and DST '%s'.\n", log_id(module), log_signal(s), log_signal(d)); + r.first->second = max; + } + } + else { + log_assert(GetSize(src) == GetSize(dst)); + for (auto i = 0; i < GetSize(src); i++) { + const auto &s = src[i]; + const auto &d = dst[i]; + auto r = t.comb.insert(BitBit(s,d)); + if (!r.second) + log_error("Module '%s' contains multiple specify cells for SRC '%s' and DST '%s'.\n", log_id(module), log_signal(s), log_signal(d)); + r.first->second = max; + } + } + } + else if (cell->type == ID($specify3)) { + auto src = cell->getPort(ID::SRC).as_bit(); + auto dst = cell->getPort(ID::DST); + if (!src.wire || !src.wire->port_input) + log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); + for (const auto &c : dst.chunks()) + if (!c.wire->port_output) + log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module output.\n", log_id(module), log_id(cell), log_signal(dst)); + int rise_max = cell->getParam(ID::T_RISE_MAX).as_int(); + int fall_max = cell->getParam(ID::T_FALL_MAX).as_int(); + int max = std::max(rise_max,fall_max); + if (max < 0) { + log_warning("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0 which is currently unsupported. Clamping to 0.\n", log_id(module), log_id(cell)); + max = 0; } for (const auto &d : dst) { - auto &v = t.arrival[d]; - v = std::max(v, max); - } + auto r = t.arrival.insert(NameBit(d)); + auto &v = r.first->second; + if (r.second || v.first < max) { + v.first = max; + v.second = NameBit(src); + } + } } else if (cell->type == ID($specrule)) { - auto type = cell->getParam(ID(TYPE)).decode_string(); - if (type != "$setup" && type != "$setuphold") + IdString type = cell->getParam(ID::TYPE).decode_string(); + if (type != ID($setup) && type != ID($setuphold)) continue; - auto src = cell->getPort(ID(SRC)); - auto dst = cell->getPort(ID(DST)); + auto src = cell->getPort(ID::SRC); + auto dst = cell->getPort(ID::DST).as_bit(); for (const auto &c : src.chunks()) - if (!c.wire->port_input) + if (!c.wire || !c.wire->port_input) log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); - for (const auto &c : dst.chunks()) - if (!c.wire->port_input) - log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(dst)); - int max = cell->getParam(ID(T_LIMIT_MAX)).as_int(); - if (max < 0) - log_warning("Module '%s' contains specify cell '%s' with T_LIMIT_MAX < 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); - if (max <= 0) { - log_debug("Module '%s' contains specify cell '%s' with T_LIMIT_MAX <= 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); - continue; + if (!dst.wire || !dst.wire->port_input) + log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(dst)); + int max = cell->getParam(ID::T_LIMIT_MAX).as_int(); + if (max < 0) { + log_warning("Module '%s' contains specify cell '%s' with T_LIMIT_MAX < 0 which is currently unsupported. Clamping to 0.\n", log_id(module), log_id(cell)); + max = 0; } for (const auto &s : src) { - auto &v = t.required[s]; - v = std::max(v, max); - } + auto r = t.required.insert(NameBit(s)); + auto &v = r.first->second; + if (r.second || v.first < max) { + v.first = max; + v.second = NameBit(dst); + } + } } } + + for (auto port_name : module->ports) { + auto wire = module->wire(port_name); + if (wire->port_input) { + t.has_inputs = true; + break; + } + } + + return t; } - int delay(IdString module_name, const SigBit &src, const SigBit &dst) const { - auto it = data.find(module_name); - if (it == data.end()) - return 0; - return it->second.comb.at(BitBit(src,dst), 0); - } - int arrival(IdString module_name, const SigBit &src) const { - auto it = data.find(module_name); - if (it == data.end()) - return 0; - return it->second.arrival.at(src, 0); - } - int required(IdString module_name, const SigBit &dst) const { - auto it = data.find(module_name); - if (it == data.end()) - return 0; - return it->second.required.at(dst, 0); - } + decltype(data)::const_iterator find(RTLIL::IdString module_name) const { return data.find(module_name); } + decltype(data)::const_iterator end() const { return data.end(); } + int count(RTLIL::IdString module_name) const { return data.count(module_name); } + const ModuleTiming& at(RTLIL::IdString module_name) const { return data.at(module_name); } }; YOSYS_NAMESPACE_END