mirror of https://github.com/YosysHQ/yosys.git
Merge pull request #5512 from YosysHQ/emil/turbo-celltypes
celltypes: compile-time lookup tables for internal cells
This commit is contained in:
commit
0d7a875675
1
Makefile
1
Makefile
|
|
@ -613,6 +613,7 @@ $(eval $(call add_include_file,kernel/bitpattern.h))
|
|||
$(eval $(call add_include_file,kernel/cellaigs.h))
|
||||
$(eval $(call add_include_file,kernel/celledges.h))
|
||||
$(eval $(call add_include_file,kernel/celltypes.h))
|
||||
$(eval $(call add_include_file,kernel/newcelltypes.h))
|
||||
$(eval $(call add_include_file,kernel/consteval.h))
|
||||
$(eval $(call add_include_file,kernel/constids.inc))
|
||||
$(eval $(call add_include_file,kernel/cost.h))
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
// - zero-width operands
|
||||
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include "kernel/rtlil.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
|
|
@ -45,8 +45,22 @@ PRIVATE_NAMESPACE_BEGIN
|
|||
// TODO
|
||||
//#define ARITH_OPS ID($add), ID($sub), ID($neg)
|
||||
|
||||
#define KNOWN_OPS BITWISE_OPS, REDUCE_OPS, LOGIC_OPS, GATE_OPS, ID($pos), CMP_OPS, \
|
||||
ID($pmux), ID($bmux) /*, ARITH_OPS*/
|
||||
static constexpr auto known_ops = []() constexpr {
|
||||
StaticCellTypes::Categories::Category c{};
|
||||
for (auto id : {BITWISE_OPS})
|
||||
c.set_id(id);
|
||||
for (auto id : {REDUCE_OPS})
|
||||
c.set_id(id);
|
||||
for (auto id : {LOGIC_OPS})
|
||||
c.set_id(id);
|
||||
for (auto id : {GATE_OPS})
|
||||
c.set_id(id);
|
||||
for (auto id : {CMP_OPS})
|
||||
c.set_id(id);
|
||||
for (auto id : {ID($pos), ID($pmux), ID($bmux)})
|
||||
c.set_id(id);
|
||||
return c;
|
||||
}();
|
||||
|
||||
template<typename Writer, typename Lit, Lit CFALSE, Lit CTRUE>
|
||||
struct Index {
|
||||
|
|
@ -92,7 +106,7 @@ struct Index {
|
|||
int pos = index_wires(info, m);
|
||||
|
||||
for (auto cell : m->cells()) {
|
||||
if (cell->type.in(KNOWN_OPS) || cell->type.in(ID($scopeinfo), ID($specify2), ID($specify3), ID($input_port)))
|
||||
if (known_ops(cell->type) || cell->type.in(ID($scopeinfo), ID($specify2), ID($specify3), ID($input_port)))
|
||||
continue;
|
||||
|
||||
Module *submodule = m->design->module(cell->type);
|
||||
|
|
@ -104,7 +118,7 @@ struct Index {
|
|||
pos += index_module(submodule);
|
||||
} else {
|
||||
if (allow_blackboxes) {
|
||||
info.found_blackboxes.insert(cell);
|
||||
info.found_blackboxes.insert(cell);
|
||||
} else {
|
||||
// Even if we don't allow blackboxes these might still be
|
||||
// present outside of any traversed input cones, so we
|
||||
|
|
@ -269,7 +283,7 @@ struct Index {
|
|||
} else if (cell->type.in(ID($lt), ID($le), ID($gt), ID($ge))) {
|
||||
if (cell->type.in(ID($gt), ID($ge)))
|
||||
std::swap(aport, bport);
|
||||
int carry = cell->type.in(ID($le), ID($ge)) ? CFALSE : CTRUE;
|
||||
int carry = cell->type.in(ID($le), ID($ge)) ? CFALSE : CTRUE;
|
||||
Lit a = Writer::EMPTY_LIT;
|
||||
Lit b = Writer::EMPTY_LIT;
|
||||
// TODO: this might not be the most economic structure; revisit at a later date
|
||||
|
|
@ -579,7 +593,7 @@ struct Index {
|
|||
// an output of a cell
|
||||
Cell *driver = bit.wire->driverCell();
|
||||
|
||||
if (driver->type.in(KNOWN_OPS)) {
|
||||
if (known_ops(driver->type)) {
|
||||
ret = impl_op(cursor, driver, bit.wire->driverPort(), bit.offset);
|
||||
} else {
|
||||
Module *def = cursor.enter(*this, driver);
|
||||
|
|
@ -916,15 +930,15 @@ struct XAigerWriter : AigerWriter {
|
|||
std::vector<HierBit> pos;
|
||||
std::vector<HierBit> pis;
|
||||
|
||||
// * The aiger output port sequence is COs (inputs to modeled boxes),
|
||||
// inputs to opaque boxes, then module outputs. COs going first is
|
||||
// required by abc.
|
||||
// * proper_pos_counter counts ports which follow after COs
|
||||
// * The mapping file `pseudopo` and `po` statements use indexing relative
|
||||
// to the first port following COs.
|
||||
// * If a module output is directly driven by an opaque box, the emission
|
||||
// of the po statement in the mapping file is skipped. This is done to
|
||||
// aid re-integration of the mapped result.
|
||||
// * The aiger output port sequence is COs (inputs to modeled boxes),
|
||||
// inputs to opaque boxes, then module outputs. COs going first is
|
||||
// required by abc.
|
||||
// * proper_pos_counter counts ports which follow after COs
|
||||
// * The mapping file `pseudopo` and `po` statements use indexing relative
|
||||
// to the first port following COs.
|
||||
// * If a module output is directly driven by an opaque box, the emission
|
||||
// of the po statement in the mapping file is skipped. This is done to
|
||||
// aid re-integration of the mapped result.
|
||||
int proper_pos_counter = 0;
|
||||
|
||||
pool<SigBit> driven_by_opaque_box;
|
||||
|
|
@ -1331,41 +1345,50 @@ struct Aiger2Backend : Backend {
|
|||
log(" perform structural hashing while writing\n");
|
||||
log("\n");
|
||||
log(" -flatten\n");
|
||||
log(" allow descending into submodules and write a flattened view of the design\n");
|
||||
log(" hierarchy starting at the selected top\n");
|
||||
log("\n");
|
||||
log(" allow descending into submodules and write a flattened view of the design\n");
|
||||
log(" hierarchy starting at the selected top\n");
|
||||
log("\n");
|
||||
log("This command is able to ingest all combinational cells except for:\n");
|
||||
log("\n");
|
||||
pool<IdString> supported = {KNOWN_OPS};
|
||||
CellTypes ct;
|
||||
ct.setup_internals_eval();
|
||||
log(" ");
|
||||
int col = 0;
|
||||
for (auto pair : ct.cell_types)
|
||||
if (!supported.count(pair.first)) {
|
||||
if (col + pair.first.size() + 2 > 72) {
|
||||
for (size_t i = 0; i < StaticCellTypes::builder.count; i++) {
|
||||
auto &cell = StaticCellTypes::builder.cells[i];
|
||||
if (!cell.features.is_evaluable)
|
||||
continue;
|
||||
if (cell.features.is_stdcell)
|
||||
continue;
|
||||
if (known_ops(cell.type))
|
||||
continue;
|
||||
std::string name = log_id(cell.type);
|
||||
if (col + name.size() + 2 > 72) {
|
||||
log("\n ");
|
||||
col = 0;
|
||||
}
|
||||
col += pair.first.size() + 2;
|
||||
log("%s, ", log_id(pair.first));
|
||||
col += name.size() + 2;
|
||||
log("%s, ", name.c_str());
|
||||
}
|
||||
log("\n");
|
||||
log("\n");
|
||||
log("And all combinational gates except for:\n");
|
||||
log("\n");
|
||||
CellTypes ct2;
|
||||
ct2.setup_stdcells();
|
||||
log(" ");
|
||||
col = 0;
|
||||
for (auto pair : ct2.cell_types)
|
||||
if (!supported.count(pair.first)) {
|
||||
if (col + pair.first.size() + 2 > 72) {
|
||||
for (size_t i = 0; i < StaticCellTypes::builder.count; i++) {
|
||||
auto &cell = StaticCellTypes::builder.cells[i];
|
||||
if (!cell.features.is_evaluable)
|
||||
continue;
|
||||
if (!cell.features.is_stdcell)
|
||||
continue;
|
||||
if (known_ops(cell.type))
|
||||
continue;
|
||||
std::string name = log_id(cell.type);
|
||||
if (col + name.size() + 2 > 72) {
|
||||
log("\n ");
|
||||
col = 0;
|
||||
}
|
||||
col += pair.first.size() + 2;
|
||||
log("%s, ", log_id(pair.first));
|
||||
col += name.size() + 2;
|
||||
log("%s, ", name.c_str());
|
||||
}
|
||||
log("\n");
|
||||
}
|
||||
|
|
@ -1423,20 +1446,20 @@ struct XAiger2Backend : Backend {
|
|||
log(" perform structural hashing while writing\n");
|
||||
log("\n");
|
||||
log(" -flatten\n");
|
||||
log(" allow descending into submodules and write a flattened view of the design\n");
|
||||
log(" hierarchy starting at the selected top\n");
|
||||
log("\n");
|
||||
log(" -mapping_prep\n");
|
||||
log(" after the file is written, prepare the module for reintegration of\n");
|
||||
log(" a mapping in a subsequent command. all cells which are not blackboxed nor\n");
|
||||
log(" whiteboxed are removed from the design as well as all wires which only\n");
|
||||
log(" connect to removed cells\n");
|
||||
log(" (conflicts with -flatten)\n");
|
||||
log("\n");
|
||||
log(" -map2 <file>\n");
|
||||
log(" write a map2 file which 'read_xaiger2 -sc_mapping' can read to\n");
|
||||
log(" reintegrate a mapping\n");
|
||||
log(" (conflicts with -flatten)\n");
|
||||
log(" allow descending into submodules and write a flattened view of the design\n");
|
||||
log(" hierarchy starting at the selected top\n");
|
||||
log("\n");
|
||||
log(" -mapping_prep\n");
|
||||
log(" after the file is written, prepare the module for reintegration of\n");
|
||||
log(" a mapping in a subsequent command. all cells which are not blackboxed nor\n");
|
||||
log(" whiteboxed are removed from the design as well as all wires which only\n");
|
||||
log(" connect to removed cells\n");
|
||||
log(" (conflicts with -flatten)\n");
|
||||
log("\n");
|
||||
log(" -map2 <file>\n");
|
||||
log(" write a map2 file which 'read_xaiger2 -sc_mapping' can read to\n");
|
||||
log(" reintegrate a mapping\n");
|
||||
log(" (conflicts with -flatten)\n");
|
||||
log("\n");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
#include "kernel/rtlil.h"
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include "kernel/log.h"
|
||||
#include <string>
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ struct BlifDumper
|
|||
RTLIL::Module *module;
|
||||
RTLIL::Design *design;
|
||||
BlifDumperConfig *config;
|
||||
CellTypes ct;
|
||||
NewCellTypes ct;
|
||||
|
||||
SigMap sigmap;
|
||||
dict<SigBit, int> init_bits;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
#include "kernel/rtlil.h"
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include "kernel/log.h"
|
||||
#include <string>
|
||||
|
||||
|
|
@ -138,7 +138,7 @@ struct EdifBackend : public Backend {
|
|||
bool lsbidx = false;
|
||||
std::map<RTLIL::IdString, std::map<RTLIL::IdString, int>> lib_cell_ports;
|
||||
bool nogndvcc = false, gndvccy = false, keepmode = false;
|
||||
CellTypes ct(design);
|
||||
NewCellTypes ct(design);
|
||||
EdifNames edif_names;
|
||||
|
||||
size_t argidx;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
#include "kernel/rtlil.h"
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include "kernel/log.h"
|
||||
#include <string>
|
||||
|
||||
|
|
@ -117,7 +117,7 @@ struct IntersynthBackend : public Backend {
|
|||
|
||||
std::set<std::string> conntypes_code, celltypes_code;
|
||||
std::string netlists_code;
|
||||
CellTypes ct(design);
|
||||
NewCellTypes ct(design);
|
||||
|
||||
for (auto lib : libs)
|
||||
ct.setup_design(lib);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
#include "kernel/rtlil.h"
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include "kernel/log.h"
|
||||
#include "kernel/mem.h"
|
||||
#include "libs/json11/json11.hpp"
|
||||
|
|
@ -32,7 +32,7 @@ PRIVATE_NAMESPACE_BEGIN
|
|||
|
||||
struct Smt2Worker
|
||||
{
|
||||
CellTypes ct;
|
||||
NewCellTypes ct;
|
||||
SigMap sigmap;
|
||||
RTLIL::Module *module;
|
||||
bool bvmode, memmode, wiresmode, verbose, statebv, statedt, forallmode;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
#include "kernel/rtlil.h"
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include "kernel/log.h"
|
||||
#include <string>
|
||||
|
||||
|
|
@ -29,7 +29,7 @@ PRIVATE_NAMESPACE_BEGIN
|
|||
|
||||
struct SmvWorker
|
||||
{
|
||||
CellTypes ct;
|
||||
NewCellTypes ct;
|
||||
SigMap sigmap;
|
||||
RTLIL::Module *module;
|
||||
std::ostream &f;
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
#include "kernel/yosys.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include "aigerparse.h"
|
||||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
|
|
|||
|
|
@ -87,22 +87,22 @@ struct CellTypes
|
|||
{
|
||||
setup_internals_eval();
|
||||
|
||||
setup_type(ID($tribuf), {ID::A, ID::EN}, {ID::Y}, true);
|
||||
setup_type(ID($tribuf), {ID::A, ID::EN}, {ID::Y});
|
||||
|
||||
setup_type(ID($assert), {ID::A, ID::EN}, pool<RTLIL::IdString>(), true);
|
||||
setup_type(ID($assume), {ID::A, ID::EN}, pool<RTLIL::IdString>(), true);
|
||||
setup_type(ID($live), {ID::A, ID::EN}, pool<RTLIL::IdString>(), true);
|
||||
setup_type(ID($fair), {ID::A, ID::EN}, pool<RTLIL::IdString>(), true);
|
||||
setup_type(ID($cover), {ID::A, ID::EN}, pool<RTLIL::IdString>(), true);
|
||||
setup_type(ID($initstate), pool<RTLIL::IdString>(), {ID::Y}, true);
|
||||
setup_type(ID($anyconst), pool<RTLIL::IdString>(), {ID::Y}, true);
|
||||
setup_type(ID($anyseq), pool<RTLIL::IdString>(), {ID::Y}, true);
|
||||
setup_type(ID($allconst), pool<RTLIL::IdString>(), {ID::Y}, true);
|
||||
setup_type(ID($allseq), pool<RTLIL::IdString>(), {ID::Y}, true);
|
||||
setup_type(ID($equiv), {ID::A, ID::B}, {ID::Y}, true);
|
||||
setup_type(ID($specify2), {ID::EN, ID::SRC, ID::DST}, pool<RTLIL::IdString>(), true);
|
||||
setup_type(ID($specify3), {ID::EN, ID::SRC, ID::DST, ID::DAT}, pool<RTLIL::IdString>(), true);
|
||||
setup_type(ID($specrule), {ID::EN_SRC, ID::EN_DST, ID::SRC, ID::DST}, pool<RTLIL::IdString>(), true);
|
||||
setup_type(ID($assert), {ID::A, ID::EN}, pool<RTLIL::IdString>());
|
||||
setup_type(ID($assume), {ID::A, ID::EN}, pool<RTLIL::IdString>());
|
||||
setup_type(ID($live), {ID::A, ID::EN}, pool<RTLIL::IdString>());
|
||||
setup_type(ID($fair), {ID::A, ID::EN}, pool<RTLIL::IdString>());
|
||||
setup_type(ID($cover), {ID::A, ID::EN}, pool<RTLIL::IdString>());
|
||||
setup_type(ID($initstate), pool<RTLIL::IdString>(), {ID::Y});
|
||||
setup_type(ID($anyconst), pool<RTLIL::IdString>(), {ID::Y});
|
||||
setup_type(ID($anyseq), pool<RTLIL::IdString>(), {ID::Y});
|
||||
setup_type(ID($allconst), pool<RTLIL::IdString>(), {ID::Y});
|
||||
setup_type(ID($allseq), pool<RTLIL::IdString>(), {ID::Y});
|
||||
setup_type(ID($equiv), {ID::A, ID::B}, {ID::Y});
|
||||
setup_type(ID($specify2), {ID::EN, ID::SRC, ID::DST}, pool<RTLIL::IdString>());
|
||||
setup_type(ID($specify3), {ID::EN, ID::SRC, ID::DST, ID::DAT}, pool<RTLIL::IdString>());
|
||||
setup_type(ID($specrule), {ID::EN_SRC, ID::EN_DST, ID::SRC, ID::DST}, pool<RTLIL::IdString>());
|
||||
setup_type(ID($print), {ID::EN, ID::ARGS, ID::TRG}, pool<RTLIL::IdString>());
|
||||
setup_type(ID($check), {ID::A, ID::EN, ID::ARGS, ID::TRG}, pool<RTLIL::IdString>());
|
||||
setup_type(ID($set_tag), {ID::A, ID::SET, ID::CLR}, {ID::Y});
|
||||
|
|
@ -195,7 +195,7 @@ struct CellTypes
|
|||
{
|
||||
setup_stdcells_eval();
|
||||
|
||||
setup_type(ID($_TBUF_), {ID::A, ID::E}, {ID::Y}, true);
|
||||
setup_type(ID($_TBUF_), {ID::A, ID::E}, {ID::Y});
|
||||
}
|
||||
|
||||
void setup_stdcells_eval()
|
||||
|
|
@ -548,9 +548,6 @@ struct CellTypes
|
|||
}
|
||||
};
|
||||
|
||||
// initialized by yosys_setup()
|
||||
extern CellTypes yosys_celltypes;
|
||||
|
||||
YOSYS_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "kernel/sigtools.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/macc.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
|
|
@ -44,9 +45,8 @@ struct ConstEval
|
|||
|
||||
ConstEval(RTLIL::Module *module, RTLIL::State defaultval = RTLIL::State::Sm) : module(module), assign_map(module), defaultval(defaultval)
|
||||
{
|
||||
CellTypes ct;
|
||||
ct.setup_internals();
|
||||
ct.setup_stdcells();
|
||||
auto ct = NewCellTypes();
|
||||
ct.static_cell_types = StaticCellTypes::Compat::nomem_noff;
|
||||
|
||||
for (auto &it : module->cells_) {
|
||||
if (!ct.cell_known(it.second->type))
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
#include "kernel/rtlil.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
|
|
@ -1093,10 +1093,10 @@ private:
|
|||
|
||||
struct DriverMap
|
||||
{
|
||||
CellTypes celltypes;
|
||||
NewCellTypes celltypes;
|
||||
|
||||
DriverMap() { celltypes.setup(); }
|
||||
DriverMap(Design *design) { celltypes.setup(); celltypes.setup_design(design); }
|
||||
DriverMap(Design *design) { celltypes.setup(design); }
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include "kernel/yosys.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
|
|
@ -357,7 +358,7 @@ struct ModWalker
|
|||
RTLIL::Design *design;
|
||||
RTLIL::Module *module;
|
||||
|
||||
CellTypes ct;
|
||||
NewCellTypes ct;
|
||||
SigMap sigmap;
|
||||
|
||||
dict<RTLIL::SigBit, pool<PortBit>> signal_drivers;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,651 @@
|
|||
#ifndef NEWCELLTYPES_H
|
||||
#define NEWCELLTYPES_H
|
||||
|
||||
#include "kernel/rtlil.h"
|
||||
#include "kernel/yosys.h"
|
||||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* This API is unstable.
|
||||
* It may change or be removed in future versions and break dependent code.
|
||||
*/
|
||||
|
||||
namespace StaticCellTypes {
|
||||
|
||||
// Given by last internal cell type IdString constids.inc, compilation error if too low
|
||||
constexpr int MAX_CELLS = 300;
|
||||
// Currently given by _MUX16_, compilation error if too low
|
||||
constexpr int MAX_PORTS = 20;
|
||||
struct CellTableBuilder {
|
||||
struct PortList {
|
||||
std::array<RTLIL::IdString, MAX_PORTS> ports{};
|
||||
size_t count = 0;
|
||||
constexpr PortList() = default;
|
||||
constexpr PortList(std::initializer_list<RTLIL::IdString> init) {
|
||||
for (auto p : init) {
|
||||
ports[count++] = p;
|
||||
}
|
||||
}
|
||||
constexpr auto begin() const { return ports.begin(); }
|
||||
constexpr auto end() const { return ports.begin() + count; }
|
||||
constexpr bool contains(RTLIL::IdString port) const {
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
if (port == ports[i])
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
constexpr size_t size() const { return count; }
|
||||
};
|
||||
struct Features {
|
||||
bool is_evaluable = false;
|
||||
bool is_combinatorial = false;
|
||||
bool is_synthesizable = false;
|
||||
bool is_stdcell = false;
|
||||
bool is_ff = false;
|
||||
bool is_mem_noff = false;
|
||||
bool is_anyinit = false;
|
||||
bool is_tristate = false;
|
||||
};
|
||||
struct CellInfo {
|
||||
RTLIL::IdString type;
|
||||
PortList inputs, outputs;
|
||||
Features features;
|
||||
};
|
||||
std::array<CellInfo, MAX_CELLS> cells{};
|
||||
size_t count = 0;
|
||||
|
||||
constexpr void setup_type(RTLIL::IdString type, std::initializer_list<RTLIL::IdString> inputs, std::initializer_list<RTLIL::IdString> outputs, const Features& features) {
|
||||
cells[count++] = {type, PortList(inputs), PortList(outputs), features};
|
||||
}
|
||||
constexpr void setup_internals_other()
|
||||
{
|
||||
Features features {};
|
||||
features.is_tristate = true;
|
||||
setup_type(ID($tribuf), {ID::A, ID::EN}, {ID::Y}, features);
|
||||
|
||||
features = {};
|
||||
setup_type(ID($assert), {ID::A, ID::EN}, {}, features);
|
||||
setup_type(ID($assume), {ID::A, ID::EN}, {}, features);
|
||||
setup_type(ID($live), {ID::A, ID::EN}, {}, features);
|
||||
setup_type(ID($fair), {ID::A, ID::EN}, {}, features);
|
||||
setup_type(ID($cover), {ID::A, ID::EN}, {}, features);
|
||||
setup_type(ID($initstate), {}, {ID::Y}, features);
|
||||
setup_type(ID($anyconst), {}, {ID::Y}, features);
|
||||
setup_type(ID($anyseq), {}, {ID::Y}, features);
|
||||
setup_type(ID($allconst), {}, {ID::Y}, features);
|
||||
setup_type(ID($allseq), {}, {ID::Y}, features);
|
||||
setup_type(ID($equiv), {ID::A, ID::B}, {ID::Y}, features);
|
||||
setup_type(ID($specify2), {ID::EN, ID::SRC, ID::DST}, {}, features);
|
||||
setup_type(ID($specify3), {ID::EN, ID::SRC, ID::DST, ID::DAT}, {}, features);
|
||||
setup_type(ID($specrule), {ID::EN_SRC, ID::EN_DST, ID::SRC, ID::DST}, {}, features);
|
||||
setup_type(ID($print), {ID::EN, ID::ARGS, ID::TRG}, {}, features);
|
||||
setup_type(ID($check), {ID::A, ID::EN, ID::ARGS, ID::TRG}, {}, features);
|
||||
setup_type(ID($set_tag), {ID::A, ID::SET, ID::CLR}, {ID::Y}, features);
|
||||
setup_type(ID($get_tag), {ID::A}, {ID::Y}, features);
|
||||
setup_type(ID($overwrite_tag), {ID::A, ID::SET, ID::CLR}, {}, features);
|
||||
setup_type(ID($original_tag), {ID::A}, {ID::Y}, features);
|
||||
setup_type(ID($future_ff), {ID::A}, {ID::Y}, features);
|
||||
setup_type(ID($scopeinfo), {}, {}, features);
|
||||
setup_type(ID($input_port), {}, {ID::Y}, features);
|
||||
setup_type(ID($connect), {ID::A, ID::B}, {}, features);
|
||||
}
|
||||
constexpr void setup_internals_eval()
|
||||
{
|
||||
Features features {};
|
||||
features.is_evaluable = true;
|
||||
std::initializer_list<RTLIL::IdString> unary_ops = {
|
||||
ID($not), ID($pos), ID($buf), ID($neg),
|
||||
ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool),
|
||||
ID($logic_not), ID($slice), ID($lut), ID($sop)
|
||||
};
|
||||
|
||||
std::initializer_list<RTLIL::IdString> binary_ops = {
|
||||
ID($and), ID($or), ID($xor), ID($xnor),
|
||||
ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx),
|
||||
ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt),
|
||||
ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($pow),
|
||||
ID($logic_and), ID($logic_or), ID($concat), ID($macc),
|
||||
ID($bweqx)
|
||||
};
|
||||
|
||||
for (auto type : unary_ops)
|
||||
setup_type(type, {ID::A}, {ID::Y}, features);
|
||||
|
||||
for (auto type : binary_ops)
|
||||
setup_type(type, {ID::A, ID::B}, {ID::Y}, features);
|
||||
|
||||
for (auto type : {ID($mux), ID($pmux), ID($bwmux)})
|
||||
setup_type(type, {ID::A, ID::B, ID::S}, {ID::Y}, features);
|
||||
|
||||
for (auto type : {ID($bmux), ID($demux)})
|
||||
setup_type(type, {ID::A, ID::S}, {ID::Y}, features);
|
||||
|
||||
setup_type(ID($lcu), {ID::P, ID::G, ID::CI}, {ID::CO}, features);
|
||||
setup_type(ID($alu), {ID::A, ID::B, ID::CI, ID::BI}, {ID::X, ID::Y, ID::CO}, features);
|
||||
setup_type(ID($macc_v2), {ID::A, ID::B, ID::C}, {ID::Y}, features);
|
||||
setup_type(ID($fa), {ID::A, ID::B, ID::C}, {ID::X, ID::Y}, features);
|
||||
}
|
||||
constexpr void setup_internals_ff()
|
||||
{
|
||||
Features features {};
|
||||
features.is_ff = true;
|
||||
setup_type(ID($sr), {ID::SET, ID::CLR}, {ID::Q}, features);
|
||||
setup_type(ID($ff), {ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($dff), {ID::CLK, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($dffe), {ID::CLK, ID::EN, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($dffsr), {ID::CLK, ID::SET, ID::CLR, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($dffsre), {ID::CLK, ID::SET, ID::CLR, ID::D, ID::EN}, {ID::Q}, features);
|
||||
setup_type(ID($adff), {ID::CLK, ID::ARST, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($adffe), {ID::CLK, ID::ARST, ID::D, ID::EN}, {ID::Q}, features);
|
||||
setup_type(ID($aldff), {ID::CLK, ID::ALOAD, ID::AD, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($aldffe), {ID::CLK, ID::ALOAD, ID::AD, ID::D, ID::EN}, {ID::Q}, features);
|
||||
setup_type(ID($sdff), {ID::CLK, ID::SRST, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($sdffe), {ID::CLK, ID::SRST, ID::D, ID::EN}, {ID::Q}, features);
|
||||
setup_type(ID($sdffce), {ID::CLK, ID::SRST, ID::D, ID::EN}, {ID::Q}, features);
|
||||
setup_type(ID($dlatch), {ID::EN, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($adlatch), {ID::EN, ID::D, ID::ARST}, {ID::Q}, features);
|
||||
setup_type(ID($dlatchsr), {ID::EN, ID::SET, ID::CLR, ID::D}, {ID::Q}, features);
|
||||
}
|
||||
constexpr void setup_internals_anyinit()
|
||||
{
|
||||
Features features {};
|
||||
features.is_anyinit = true;
|
||||
setup_type(ID($anyinit), {ID::D}, {ID::Q}, features);
|
||||
}
|
||||
constexpr void setup_internals_mem_noff()
|
||||
{
|
||||
Features features {};
|
||||
features.is_mem_noff = true;
|
||||
// NOT setup_internals_ff()
|
||||
|
||||
setup_type(ID($memrd), {ID::CLK, ID::EN, ID::ADDR}, {ID::DATA}, features);
|
||||
setup_type(ID($memrd_v2), {ID::CLK, ID::EN, ID::ARST, ID::SRST, ID::ADDR}, {ID::DATA}, features);
|
||||
setup_type(ID($memwr), {ID::CLK, ID::EN, ID::ADDR, ID::DATA}, {}, features);
|
||||
setup_type(ID($memwr_v2), {ID::CLK, ID::EN, ID::ADDR, ID::DATA}, {}, features);
|
||||
setup_type(ID($meminit), {ID::ADDR, ID::DATA}, {}, features);
|
||||
setup_type(ID($meminit_v2), {ID::ADDR, ID::DATA, ID::EN}, {}, features);
|
||||
setup_type(ID($mem), {ID::RD_CLK, ID::RD_EN, ID::RD_ADDR, ID::WR_CLK, ID::WR_EN, ID::WR_ADDR, ID::WR_DATA}, {ID::RD_DATA}, features);
|
||||
setup_type(ID($mem_v2), {ID::RD_CLK, ID::RD_EN, ID::RD_ARST, ID::RD_SRST, ID::RD_ADDR, ID::WR_CLK, ID::WR_EN, ID::WR_ADDR, ID::WR_DATA}, {ID::RD_DATA}, features);
|
||||
|
||||
// What?
|
||||
setup_type(ID($fsm), {ID::CLK, ID::ARST, ID::CTRL_IN}, {ID::CTRL_OUT}, features);
|
||||
}
|
||||
constexpr void setup_stdcells_tristate()
|
||||
{
|
||||
Features features {};
|
||||
features.is_stdcell = true;
|
||||
features.is_tristate = true;
|
||||
setup_type(ID($_TBUF_), {ID::A, ID::E}, {ID::Y}, features);
|
||||
}
|
||||
|
||||
constexpr void setup_stdcells_eval()
|
||||
{
|
||||
Features features {};
|
||||
features.is_stdcell = true;
|
||||
features.is_evaluable = true;
|
||||
setup_type(ID($_BUF_), {ID::A}, {ID::Y}, features);
|
||||
setup_type(ID($_NOT_), {ID::A}, {ID::Y}, features);
|
||||
setup_type(ID($_AND_), {ID::A, ID::B}, {ID::Y}, features);
|
||||
setup_type(ID($_NAND_), {ID::A, ID::B}, {ID::Y}, features);
|
||||
setup_type(ID($_OR_), {ID::A, ID::B}, {ID::Y}, features);
|
||||
setup_type(ID($_NOR_), {ID::A, ID::B}, {ID::Y}, features);
|
||||
setup_type(ID($_XOR_), {ID::A, ID::B}, {ID::Y}, features);
|
||||
setup_type(ID($_XNOR_), {ID::A, ID::B}, {ID::Y}, features);
|
||||
setup_type(ID($_ANDNOT_), {ID::A, ID::B}, {ID::Y}, features);
|
||||
setup_type(ID($_ORNOT_), {ID::A, ID::B}, {ID::Y}, features);
|
||||
setup_type(ID($_MUX_), {ID::A, ID::B, ID::S}, {ID::Y}, features);
|
||||
setup_type(ID($_NMUX_), {ID::A, ID::B, ID::S}, {ID::Y}, features);
|
||||
setup_type(ID($_MUX4_), {ID::A, ID::B, ID::C, ID::D, ID::S, ID::T}, {ID::Y}, features);
|
||||
setup_type(ID($_MUX8_), {ID::A, ID::B, ID::C, ID::D, ID::E, ID::F, ID::G, ID::H, ID::S, ID::T, ID::U}, {ID::Y}, features);
|
||||
setup_type(ID($_MUX16_), {ID::A, ID::B, ID::C, ID::D, ID::E, ID::F, ID::G, ID::H, ID::I, ID::J, ID::K, ID::L, ID::M, ID::N, ID::O, ID::P, ID::S, ID::T, ID::U, ID::V}, {ID::Y}, features);
|
||||
setup_type(ID($_AOI3_), {ID::A, ID::B, ID::C}, {ID::Y}, features);
|
||||
setup_type(ID($_OAI3_), {ID::A, ID::B, ID::C}, {ID::Y}, features);
|
||||
setup_type(ID($_AOI4_), {ID::A, ID::B, ID::C, ID::D}, {ID::Y}, features);
|
||||
setup_type(ID($_OAI4_), {ID::A, ID::B, ID::C, ID::D}, {ID::Y}, features);
|
||||
}
|
||||
|
||||
constexpr void setup_stdcells_ff() {
|
||||
Features features {};
|
||||
features.is_stdcell = true;
|
||||
features.is_ff = true;
|
||||
|
||||
// for (auto c1 : list_np)
|
||||
// for (auto c2 : list_np)
|
||||
// setup_type(std::string("$_SR_") + c1 + c2 + "_", {ID::S, ID::R}, {ID::Q}, features);
|
||||
setup_type(ID($_SR_NN_), {ID::S, ID::R}, {ID::Q}, features);
|
||||
setup_type(ID($_SR_NP_), {ID::S, ID::R}, {ID::Q}, features);
|
||||
setup_type(ID($_SR_PN_), {ID::S, ID::R}, {ID::Q}, features);
|
||||
setup_type(ID($_SR_PP_), {ID::S, ID::R}, {ID::Q}, features);
|
||||
|
||||
setup_type(ID($_FF_), {ID::D}, {ID::Q}, features);
|
||||
|
||||
// for (auto c1 : list_np)
|
||||
// setup_type(std::string("$_DFF_") + c1 + "_", {ID::C, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID::$_DFF_N_, {ID::C, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID::$_DFF_P_, {ID::C, ID::D}, {ID::Q}, features);
|
||||
|
||||
// for (auto c1 : list_np)
|
||||
// for (auto c2 : list_np)
|
||||
// setup_type(std::string("$_DFFE_") + c1 + c2 + "_", {ID::C, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID::$_DFFE_NN_, {ID::C, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID::$_DFFE_NP_, {ID::C, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID::$_DFFE_PN_, {ID::C, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID::$_DFFE_PP_, {ID::C, ID::D, ID::E}, {ID::Q}, features);
|
||||
// for (auto c1 : list_np)
|
||||
// for (auto c2 : list_np)
|
||||
// for (auto c3 : list_01)
|
||||
// setup_type(std::string("$_DFF_") + c1 + c2 + c3 + "_", {ID::C, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DFF_NN0_), {ID::C, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DFF_NN1_), {ID::C, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DFF_NP0_), {ID::C, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DFF_NP1_), {ID::C, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DFF_PN0_), {ID::C, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DFF_PN1_), {ID::C, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DFF_PP0_), {ID::C, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DFF_PP1_), {ID::C, ID::R, ID::D}, {ID::Q}, features);
|
||||
// for (auto c1 : list_np)
|
||||
// for (auto c2 : list_np)
|
||||
// for (auto c3 : list_01)
|
||||
// for (auto c4 : list_np)
|
||||
// setup_type(std::string("$_DFFE_") + c1 + c2 + c3 + c4 + "_", {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFE_NN0N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFE_NN0P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFE_NN1N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFE_NN1P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFE_NP0N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFE_NP0P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFE_NP1N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFE_NP1P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFE_PN0N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFE_PN0P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFE_PN1N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFE_PN1P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFE_PP0N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFE_PP0P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFE_PP1N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFE_PP1P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
// for (auto c1 : list_np)
|
||||
// for (auto c2 : list_np)
|
||||
// setup_type(std::string("$_ALDFF_") + c1 + c2 + "_", {ID::C, ID::L, ID::AD, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_ALDFF_NN_), {ID::C, ID::L, ID::AD, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_ALDFF_NP_), {ID::C, ID::L, ID::AD, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_ALDFF_PN_), {ID::C, ID::L, ID::AD, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_ALDFF_PP_), {ID::C, ID::L, ID::AD, ID::D}, {ID::Q}, features);
|
||||
// for (auto c1 : list_np)
|
||||
// for (auto c2 : list_np)
|
||||
// for (auto c3 : list_np)
|
||||
// setup_type(std::string("$_ALDFFE_") + c1 + c2 + c3 + "_", {ID::C, ID::L, ID::AD, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_ALDFFE_NNN_), {ID::C, ID::L, ID::AD, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_ALDFFE_NNP_), {ID::C, ID::L, ID::AD, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_ALDFFE_NPN_), {ID::C, ID::L, ID::AD, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_ALDFFE_NPP_), {ID::C, ID::L, ID::AD, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_ALDFFE_PNN_), {ID::C, ID::L, ID::AD, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_ALDFFE_PNP_), {ID::C, ID::L, ID::AD, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_ALDFFE_PPN_), {ID::C, ID::L, ID::AD, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_ALDFFE_PPP_), {ID::C, ID::L, ID::AD, ID::D, ID::E}, {ID::Q}, features);
|
||||
// for (auto c1 : list_np)
|
||||
// for (auto c2 : list_np)
|
||||
// for (auto c3 : list_np)
|
||||
// setup_type(std::string("$_DFFSR_") + c1 + c2 + c3 + "_", {ID::C, ID::S, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFSR_NNN_), {ID::C, ID::S, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFSR_NNP_), {ID::C, ID::S, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFSR_NPN_), {ID::C, ID::S, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFSR_NPP_), {ID::C, ID::S, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFSR_PNN_), {ID::C, ID::S, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFSR_PNP_), {ID::C, ID::S, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFSR_PPN_), {ID::C, ID::S, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFSR_PPP_), {ID::C, ID::S, ID::R, ID::D}, {ID::Q}, features);
|
||||
// for (auto c1 : list_np)
|
||||
// for (auto c2 : list_np)
|
||||
// for (auto c3 : list_np)
|
||||
// for (auto c4 : list_np)
|
||||
// setup_type(std::string("$_DFFSRE_") + c1 + c2 + c3 + c4 + "_", {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFSRE_NNNN_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFSRE_NNNP_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFSRE_NNPN_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFSRE_NNPP_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFSRE_NPNN_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFSRE_NPNP_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFSRE_NPPN_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFSRE_NPPP_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFSRE_PNNN_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFSRE_PNNP_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFSRE_PNPN_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFSRE_PNPP_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFSRE_PPNN_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFSRE_PPNP_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFSRE_PPPN_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_DFFSRE_PPPP_), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
// for (auto c1 : list_np)
|
||||
// for (auto c2 : list_np)
|
||||
// for (auto c3 : list_01)
|
||||
// setup_type(std::string("$_SDFF_") + c1 + c2 + c3 + "_", {ID::C, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFF_NN0_), {ID::C, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFF_NN1_), {ID::C, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFF_NP0_), {ID::C, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFF_NP1_), {ID::C, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFF_PN0_), {ID::C, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFF_PN1_), {ID::C, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFF_PP0_), {ID::C, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFF_PP1_), {ID::C, ID::R, ID::D}, {ID::Q}, features);
|
||||
// for (auto c1 : list_np)
|
||||
// for (auto c2 : list_np)
|
||||
// for (auto c3 : list_01)
|
||||
// for (auto c4 : list_np)
|
||||
// setup_type(std::string("$_SDFFE_") + c1 + c2 + c3 + c4 + "_", {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFE_NN0N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFE_NN0P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFE_NN1N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFE_NN1P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFE_NP0N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFE_NP0P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFE_NP1N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFE_NP1P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFE_PN0N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFE_PN0P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFE_PN1N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFE_PN1P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFE_PP0N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFE_PP0P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFE_PP1N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFE_PP1P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
// for (auto c1 : list_np)
|
||||
// for (auto c2 : list_np)
|
||||
// for (auto c3 : list_01)
|
||||
// for (auto c4 : list_np)
|
||||
// setup_type(std::string("$_SDFFCE_") + c1 + c2 + c3 + c4 + "_", {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFCE_NN0N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFCE_NN0P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFCE_NN1N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFCE_NN1P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFCE_NP0N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFCE_NP0P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFCE_NP1N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFCE_NP1P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFCE_PN0N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFCE_PN0P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFCE_PN1N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFCE_PN1P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFCE_PP0N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFCE_PP0P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFCE_PP1N_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
setup_type(ID($_SDFFCE_PP1P_), {ID::C, ID::R, ID::D, ID::E}, {ID::Q}, features);
|
||||
// for (auto c1 : list_np)
|
||||
// setup_type(std::string("$_DLATCH_") + c1 + "_", {ID::E, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DLATCH_N_), {ID::E, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DLATCH_P_), {ID::E, ID::D}, {ID::Q}, features);
|
||||
|
||||
// for (auto c1 : list_np)
|
||||
// for (auto c2 : list_np)
|
||||
// for (auto c3 : list_01)
|
||||
// setup_type(std::string("$_DLATCH_") + c1 + c2 + c3 + "_", {ID::E, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DLATCH_NN0_), {ID::E, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DLATCH_NN1_), {ID::E, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DLATCH_NP0_), {ID::E, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DLATCH_NP1_), {ID::E, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DLATCH_PN0_), {ID::E, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DLATCH_PN1_), {ID::E, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DLATCH_PP0_), {ID::E, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DLATCH_PP1_), {ID::E, ID::R, ID::D}, {ID::Q}, features);
|
||||
// for (auto c1 : list_np)
|
||||
// for (auto c2 : list_np)
|
||||
// for (auto c3 : list_np)
|
||||
// setup_type(std::string("$_DLATCHSR_") + c1 + c2 + c3 + "_", {ID::E, ID::S, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DLATCHSR_NNN_), {ID::E, ID::S, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DLATCHSR_NNP_), {ID::E, ID::S, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DLATCHSR_NPN_), {ID::E, ID::S, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DLATCHSR_NPP_), {ID::E, ID::S, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DLATCHSR_PNN_), {ID::E, ID::S, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DLATCHSR_PNP_), {ID::E, ID::S, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DLATCHSR_PPN_), {ID::E, ID::S, ID::R, ID::D}, {ID::Q}, features);
|
||||
setup_type(ID($_DLATCHSR_PPP_), {ID::E, ID::S, ID::R, ID::D}, {ID::Q}, features);
|
||||
}
|
||||
constexpr CellTableBuilder() {
|
||||
setup_internals_other();
|
||||
setup_internals_eval();
|
||||
setup_internals_ff();
|
||||
setup_internals_anyinit();
|
||||
setup_internals_mem_noff();
|
||||
setup_stdcells_tristate();
|
||||
setup_stdcells_eval();
|
||||
setup_stdcells_ff();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
constexpr CellTableBuilder builder{};
|
||||
|
||||
struct PortInfo {
|
||||
struct PortLists {
|
||||
std::array<CellTableBuilder::PortList, MAX_CELLS> data{};
|
||||
constexpr CellTableBuilder::PortList operator()(IdString type) const {
|
||||
return data[type.index_];
|
||||
}
|
||||
constexpr CellTableBuilder::PortList& operator[](size_t idx) {
|
||||
return data[idx];
|
||||
}
|
||||
constexpr size_t size() const { return data.size(); }
|
||||
};
|
||||
PortLists inputs {};
|
||||
PortLists outputs {};
|
||||
constexpr PortInfo() {
|
||||
for (size_t i = 0; i < builder.count; ++i) {
|
||||
auto& cell = builder.cells[i];
|
||||
size_t idx = cell.type.index_;
|
||||
inputs[idx] = cell.inputs;
|
||||
outputs[idx] = cell.outputs;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct Categories {
|
||||
struct Category {
|
||||
std::array<bool, MAX_CELLS> data{};
|
||||
constexpr bool operator()(IdString type) const {
|
||||
size_t idx = type.index_;
|
||||
if (idx >= MAX_CELLS)
|
||||
return false;
|
||||
return data[idx];
|
||||
}
|
||||
constexpr bool operator[](size_t idx) {
|
||||
return data[idx];
|
||||
}
|
||||
constexpr void set_id(IdString type, bool val = true) {
|
||||
size_t idx = type.index_;
|
||||
if (idx >= MAX_CELLS)
|
||||
return; // TODO should be an assert but then it's not constexpr
|
||||
data[idx] = val;
|
||||
}
|
||||
constexpr void set(size_t idx, bool val = true) {
|
||||
data[idx] = val;
|
||||
}
|
||||
constexpr size_t size() const { return data.size(); }
|
||||
};
|
||||
Category empty {};
|
||||
Category is_known {};
|
||||
Category is_evaluable {};
|
||||
Category is_combinatorial {};
|
||||
Category is_synthesizable {};
|
||||
Category is_stdcell {};
|
||||
Category is_ff {};
|
||||
Category is_mem_noff {};
|
||||
Category is_anyinit {};
|
||||
Category is_tristate {};
|
||||
constexpr Categories() {
|
||||
for (size_t i = 0; i < builder.count; ++i) {
|
||||
auto& cell = builder.cells[i];
|
||||
size_t idx = cell.type.index_;
|
||||
is_known.set(idx);
|
||||
is_evaluable.set(idx, cell.features.is_evaluable);
|
||||
is_combinatorial.set(idx, cell.features.is_combinatorial);
|
||||
is_synthesizable.set(idx, cell.features.is_synthesizable);
|
||||
is_stdcell.set(idx, cell.features.is_stdcell);
|
||||
is_ff.set(idx, cell.features.is_ff);
|
||||
is_mem_noff.set(idx, cell.features.is_mem_noff);
|
||||
is_anyinit.set(idx, cell.features.is_anyinit);
|
||||
is_tristate.set(idx, cell.features.is_tristate);
|
||||
}
|
||||
}
|
||||
constexpr static Category join(Category left, Category right) {
|
||||
Category c {};
|
||||
for (size_t i = 0; i < MAX_CELLS; ++i) {
|
||||
c.set(i, left[i] || right[i]);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
constexpr static Category meet(Category left, Category right) {
|
||||
Category c {};
|
||||
for (size_t i = 0; i < MAX_CELLS; ++i) {
|
||||
c.set(i, left[i] && right[i]);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
// Sketchy! Make sure to always meet with only the known universe.
|
||||
// In other words, no modus tollens allowed
|
||||
constexpr static Category complement(Category arg) {
|
||||
Category c {};
|
||||
for (size_t i = 0; i < MAX_CELLS; ++i) {
|
||||
c.set(i, !arg[i]);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
};
|
||||
|
||||
// Pure
|
||||
static constexpr PortInfo port_info;
|
||||
static constexpr Categories categories;
|
||||
|
||||
// Legacy
|
||||
namespace Compat {
|
||||
static constexpr auto internals_all = Categories::meet(categories.is_known, Categories::complement(categories.is_stdcell));
|
||||
static constexpr auto mem_ff = Categories::join(categories.is_ff, categories.is_mem_noff);
|
||||
// old setup_internals + setup_stdcells
|
||||
static constexpr auto nomem_noff = Categories::meet(categories.is_known, Categories::complement(mem_ff));
|
||||
static constexpr auto internals_mem_ff = Categories::meet(internals_all, mem_ff);
|
||||
// old setup_internals
|
||||
static constexpr auto internals_nomem_noff = Categories::meet(internals_all, nomem_noff);
|
||||
// old setup_stdcells
|
||||
static constexpr auto stdcells_nomem_noff = Categories::meet(categories.is_stdcell, nomem_noff);
|
||||
static constexpr auto stdcells_mem = Categories::meet(categories.is_stdcell, categories.is_mem_noff);
|
||||
// old setup_internals_eval
|
||||
// static constexpr auto internals_eval = Categories::meet(internals_all, categories.is_evaluable);
|
||||
};
|
||||
|
||||
namespace {
|
||||
static_assert(categories.is_evaluable(ID($and)));
|
||||
static_assert(!categories.is_ff(ID($and)));
|
||||
static_assert(Categories::join(categories.is_evaluable, categories.is_ff)(ID($and)));
|
||||
static_assert(Categories::join(categories.is_evaluable, categories.is_ff)(ID($dffsr)));
|
||||
static_assert(!Categories::join(categories.is_evaluable, categories.is_ff)(ID($anyinit)));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct NewCellType {
|
||||
RTLIL::IdString type;
|
||||
pool<RTLIL::IdString> inputs, outputs;
|
||||
bool is_evaluable;
|
||||
bool is_combinatorial;
|
||||
bool is_synthesizable;
|
||||
};
|
||||
|
||||
struct NewCellTypes {
|
||||
struct IdStringHash {
|
||||
std::size_t operator()(const IdString id) const {
|
||||
return static_cast<size_t>(id.hash_top().yield());
|
||||
}
|
||||
};
|
||||
StaticCellTypes::Categories::Category static_cell_types = StaticCellTypes::categories.empty;
|
||||
std::unordered_map<RTLIL::IdString, NewCellType, IdStringHash> custom_cell_types {};
|
||||
|
||||
NewCellTypes() {
|
||||
static_cell_types = StaticCellTypes::categories.empty;
|
||||
}
|
||||
|
||||
NewCellTypes(RTLIL::Design *design) {
|
||||
static_cell_types = StaticCellTypes::categories.empty;
|
||||
setup(design);
|
||||
}
|
||||
void setup(RTLIL::Design *design = NULL) {
|
||||
if (design)
|
||||
setup_design(design);
|
||||
static_cell_types = StaticCellTypes::categories.is_known;
|
||||
}
|
||||
void setup_design(RTLIL::Design *design) {
|
||||
for (auto module : design->modules())
|
||||
setup_module(module);
|
||||
}
|
||||
|
||||
void setup_module(RTLIL::Module *module) {
|
||||
pool<RTLIL::IdString> inputs, outputs;
|
||||
for (RTLIL::IdString wire_name : module->ports) {
|
||||
RTLIL::Wire *wire = module->wire(wire_name);
|
||||
if (wire->port_input)
|
||||
inputs.insert(wire->name);
|
||||
if (wire->port_output)
|
||||
outputs.insert(wire->name);
|
||||
}
|
||||
setup_type(module->name, inputs, outputs);
|
||||
}
|
||||
|
||||
void setup_type(RTLIL::IdString type, const pool<RTLIL::IdString> &inputs, const pool<RTLIL::IdString> &outputs, bool is_evaluable = false, bool is_combinatorial = false, bool is_synthesizable = false) {
|
||||
NewCellType ct = {type, inputs, outputs, is_evaluable, is_combinatorial, is_synthesizable};
|
||||
custom_cell_types[ct.type] = ct;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
custom_cell_types.clear();
|
||||
static_cell_types = StaticCellTypes::categories.empty;
|
||||
}
|
||||
|
||||
bool cell_known(const RTLIL::IdString &type) const {
|
||||
return static_cell_types(type) || custom_cell_types.count(type) != 0;
|
||||
}
|
||||
|
||||
bool cell_output(const RTLIL::IdString &type, const RTLIL::IdString &port) const
|
||||
{
|
||||
if (static_cell_types(type) && StaticCellTypes::port_info.outputs(type).contains(port)) {
|
||||
return true;
|
||||
}
|
||||
auto it = custom_cell_types.find(type);
|
||||
return it != custom_cell_types.end() && it->second.outputs.count(port) != 0;
|
||||
}
|
||||
|
||||
bool cell_input(const RTLIL::IdString &type, const RTLIL::IdString &port) const
|
||||
{
|
||||
if (static_cell_types(type) && StaticCellTypes::port_info.inputs(type).contains(port)) {
|
||||
return true;
|
||||
}
|
||||
auto it = custom_cell_types.find(type);
|
||||
return it != custom_cell_types.end() && it->second.inputs.count(port) != 0;
|
||||
}
|
||||
|
||||
RTLIL::PortDir cell_port_dir(RTLIL::IdString type, RTLIL::IdString port) const
|
||||
{
|
||||
bool is_input, is_output;
|
||||
if (static_cell_types(type)) {
|
||||
is_input = StaticCellTypes::port_info.inputs(type).contains(port);
|
||||
is_output = StaticCellTypes::port_info.outputs(type).contains(port);
|
||||
} else {
|
||||
auto it = custom_cell_types.find(type);
|
||||
if (it == custom_cell_types.end())
|
||||
return RTLIL::PD_UNKNOWN;
|
||||
is_input = it->second.inputs.count(port);
|
||||
is_output = it->second.outputs.count(port);
|
||||
}
|
||||
return RTLIL::PortDir(is_input + is_output * 2);
|
||||
}
|
||||
bool cell_evaluable(const RTLIL::IdString &type) const
|
||||
{
|
||||
return static_cell_types(type) && StaticCellTypes::categories.is_evaluable(type);
|
||||
}
|
||||
};
|
||||
|
||||
extern NewCellTypes yosys_celltypes;
|
||||
|
||||
YOSYS_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
|
|
@ -22,6 +22,7 @@
|
|||
#include "kernel/json.h"
|
||||
#include "kernel/gzip.h"
|
||||
#include "kernel/log_help.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -975,16 +976,18 @@ struct HelpPass : public Pass {
|
|||
json.entry("generator", yosys_maybe_version());
|
||||
|
||||
dict<string, vector<string>> groups;
|
||||
dict<string, pair<SimHelper, CellType>> cells;
|
||||
dict<string, pair<SimHelper, StaticCellTypes::CellTableBuilder::CellInfo>> cells;
|
||||
|
||||
// iterate over cells
|
||||
bool raise_error = false;
|
||||
for (auto &it : yosys_celltypes.cell_types) {
|
||||
auto name = it.first.str();
|
||||
for (auto it : StaticCellTypes::builder.cells) {
|
||||
if (!StaticCellTypes::categories.is_known(it.type))
|
||||
continue;
|
||||
auto name = it.type.str();
|
||||
if (cell_help_messages.contains(name)) {
|
||||
auto cell_help = cell_help_messages.get(name);
|
||||
groups[cell_help.group].emplace_back(name);
|
||||
auto cell_pair = pair<SimHelper, CellType>(cell_help, it.second);
|
||||
auto cell_pair = pair<SimHelper, StaticCellTypes::CellTableBuilder::CellInfo>(cell_help, it);
|
||||
cells.emplace(name, cell_pair);
|
||||
} else {
|
||||
log("ERROR: Missing cell help for cell '%s'.\n", name);
|
||||
|
|
@ -1025,9 +1028,9 @@ struct HelpPass : public Pass {
|
|||
json.name("outputs"); json.value(outputs);
|
||||
vector<string> properties;
|
||||
// CellType properties
|
||||
if (ct.is_evaluable) properties.push_back("is_evaluable");
|
||||
if (ct.is_combinatorial) properties.push_back("is_combinatorial");
|
||||
if (ct.is_synthesizable) properties.push_back("is_synthesizable");
|
||||
if (ct.features.is_evaluable) properties.push_back("is_evaluable");
|
||||
if (ct.features.is_combinatorial) properties.push_back("is_combinatorial");
|
||||
if (ct.features.is_synthesizable) properties.push_back("is_synthesizable");
|
||||
// SimHelper properties
|
||||
size_t last = 0; size_t next = 0;
|
||||
while ((next = ch.tags.find(", ", last)) != string::npos) {
|
||||
|
|
|
|||
166
kernel/rtlil.cc
166
kernel/rtlil.cc
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include "kernel/yosys.h"
|
||||
#include "kernel/macc.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include "kernel/binding.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "frontends/verilog/verilog_frontend.h"
|
||||
|
|
@ -288,159 +288,17 @@ void RTLIL::OwningIdString::collect_garbage()
|
|||
|
||||
dict<std::string, std::string> RTLIL::constpad;
|
||||
|
||||
static const pool<IdString> &builtin_ff_cell_types_internal() {
|
||||
static const pool<IdString> res = {
|
||||
ID($sr),
|
||||
ID($ff),
|
||||
ID($dff),
|
||||
ID($dffe),
|
||||
ID($dffsr),
|
||||
ID($dffsre),
|
||||
ID($adff),
|
||||
ID($adffe),
|
||||
ID($aldff),
|
||||
ID($aldffe),
|
||||
ID($sdff),
|
||||
ID($sdffe),
|
||||
ID($sdffce),
|
||||
ID($dlatch),
|
||||
ID($adlatch),
|
||||
ID($dlatchsr),
|
||||
ID($_DFFE_NN_),
|
||||
ID($_DFFE_NP_),
|
||||
ID($_DFFE_PN_),
|
||||
ID($_DFFE_PP_),
|
||||
ID($_DFFSR_NNN_),
|
||||
ID($_DFFSR_NNP_),
|
||||
ID($_DFFSR_NPN_),
|
||||
ID($_DFFSR_NPP_),
|
||||
ID($_DFFSR_PNN_),
|
||||
ID($_DFFSR_PNP_),
|
||||
ID($_DFFSR_PPN_),
|
||||
ID($_DFFSR_PPP_),
|
||||
ID($_DFFSRE_NNNN_),
|
||||
ID($_DFFSRE_NNNP_),
|
||||
ID($_DFFSRE_NNPN_),
|
||||
ID($_DFFSRE_NNPP_),
|
||||
ID($_DFFSRE_NPNN_),
|
||||
ID($_DFFSRE_NPNP_),
|
||||
ID($_DFFSRE_NPPN_),
|
||||
ID($_DFFSRE_NPPP_),
|
||||
ID($_DFFSRE_PNNN_),
|
||||
ID($_DFFSRE_PNNP_),
|
||||
ID($_DFFSRE_PNPN_),
|
||||
ID($_DFFSRE_PNPP_),
|
||||
ID($_DFFSRE_PPNN_),
|
||||
ID($_DFFSRE_PPNP_),
|
||||
ID($_DFFSRE_PPPN_),
|
||||
ID($_DFFSRE_PPPP_),
|
||||
ID($_DFF_N_),
|
||||
ID($_DFF_P_),
|
||||
ID($_DFF_NN0_),
|
||||
ID($_DFF_NN1_),
|
||||
ID($_DFF_NP0_),
|
||||
ID($_DFF_NP1_),
|
||||
ID($_DFF_PN0_),
|
||||
ID($_DFF_PN1_),
|
||||
ID($_DFF_PP0_),
|
||||
ID($_DFF_PP1_),
|
||||
ID($_DFFE_NN0N_),
|
||||
ID($_DFFE_NN0P_),
|
||||
ID($_DFFE_NN1N_),
|
||||
ID($_DFFE_NN1P_),
|
||||
ID($_DFFE_NP0N_),
|
||||
ID($_DFFE_NP0P_),
|
||||
ID($_DFFE_NP1N_),
|
||||
ID($_DFFE_NP1P_),
|
||||
ID($_DFFE_PN0N_),
|
||||
ID($_DFFE_PN0P_),
|
||||
ID($_DFFE_PN1N_),
|
||||
ID($_DFFE_PN1P_),
|
||||
ID($_DFFE_PP0N_),
|
||||
ID($_DFFE_PP0P_),
|
||||
ID($_DFFE_PP1N_),
|
||||
ID($_DFFE_PP1P_),
|
||||
ID($_ALDFF_NN_),
|
||||
ID($_ALDFF_NP_),
|
||||
ID($_ALDFF_PN_),
|
||||
ID($_ALDFF_PP_),
|
||||
ID($_ALDFFE_NNN_),
|
||||
ID($_ALDFFE_NNP_),
|
||||
ID($_ALDFFE_NPN_),
|
||||
ID($_ALDFFE_NPP_),
|
||||
ID($_ALDFFE_PNN_),
|
||||
ID($_ALDFFE_PNP_),
|
||||
ID($_ALDFFE_PPN_),
|
||||
ID($_ALDFFE_PPP_),
|
||||
ID($_SDFF_NN0_),
|
||||
ID($_SDFF_NN1_),
|
||||
ID($_SDFF_NP0_),
|
||||
ID($_SDFF_NP1_),
|
||||
ID($_SDFF_PN0_),
|
||||
ID($_SDFF_PN1_),
|
||||
ID($_SDFF_PP0_),
|
||||
ID($_SDFF_PP1_),
|
||||
ID($_SDFFE_NN0N_),
|
||||
ID($_SDFFE_NN0P_),
|
||||
ID($_SDFFE_NN1N_),
|
||||
ID($_SDFFE_NN1P_),
|
||||
ID($_SDFFE_NP0N_),
|
||||
ID($_SDFFE_NP0P_),
|
||||
ID($_SDFFE_NP1N_),
|
||||
ID($_SDFFE_NP1P_),
|
||||
ID($_SDFFE_PN0N_),
|
||||
ID($_SDFFE_PN0P_),
|
||||
ID($_SDFFE_PN1N_),
|
||||
ID($_SDFFE_PN1P_),
|
||||
ID($_SDFFE_PP0N_),
|
||||
ID($_SDFFE_PP0P_),
|
||||
ID($_SDFFE_PP1N_),
|
||||
ID($_SDFFE_PP1P_),
|
||||
ID($_SDFFCE_NN0N_),
|
||||
ID($_SDFFCE_NN0P_),
|
||||
ID($_SDFFCE_NN1N_),
|
||||
ID($_SDFFCE_NN1P_),
|
||||
ID($_SDFFCE_NP0N_),
|
||||
ID($_SDFFCE_NP0P_),
|
||||
ID($_SDFFCE_NP1N_),
|
||||
ID($_SDFFCE_NP1P_),
|
||||
ID($_SDFFCE_PN0N_),
|
||||
ID($_SDFFCE_PN0P_),
|
||||
ID($_SDFFCE_PN1N_),
|
||||
ID($_SDFFCE_PN1P_),
|
||||
ID($_SDFFCE_PP0N_),
|
||||
ID($_SDFFCE_PP0P_),
|
||||
ID($_SDFFCE_PP1N_),
|
||||
ID($_SDFFCE_PP1P_),
|
||||
ID($_SR_NN_),
|
||||
ID($_SR_NP_),
|
||||
ID($_SR_PN_),
|
||||
ID($_SR_PP_),
|
||||
ID($_DLATCH_N_),
|
||||
ID($_DLATCH_P_),
|
||||
ID($_DLATCH_NN0_),
|
||||
ID($_DLATCH_NN1_),
|
||||
ID($_DLATCH_NP0_),
|
||||
ID($_DLATCH_NP1_),
|
||||
ID($_DLATCH_PN0_),
|
||||
ID($_DLATCH_PN1_),
|
||||
ID($_DLATCH_PP0_),
|
||||
ID($_DLATCH_PP1_),
|
||||
ID($_DLATCHSR_NNN_),
|
||||
ID($_DLATCHSR_NNP_),
|
||||
ID($_DLATCHSR_NPN_),
|
||||
ID($_DLATCHSR_NPP_),
|
||||
ID($_DLATCHSR_PNN_),
|
||||
ID($_DLATCHSR_PNP_),
|
||||
ID($_DLATCHSR_PPN_),
|
||||
ID($_DLATCHSR_PPP_),
|
||||
ID($_FF_),
|
||||
};
|
||||
return res;
|
||||
}
|
||||
|
||||
const pool<IdString> &RTLIL::builtin_ff_cell_types() {
|
||||
return builtin_ff_cell_types_internal();
|
||||
static const pool<IdString> res = []() {
|
||||
pool<IdString> r;
|
||||
for (size_t i = 0; i < StaticCellTypes::builder.count; i++) {
|
||||
auto &cell = StaticCellTypes::builder.cells[i];
|
||||
if (cell.features.is_ff)
|
||||
r.insert(cell.type);
|
||||
}
|
||||
return r;
|
||||
}();
|
||||
return res;
|
||||
}
|
||||
|
||||
#define check(condition) log_assert(condition && "malformed Const union")
|
||||
|
|
@ -4610,7 +4468,7 @@ bool RTLIL::Cell::is_mem_cell() const
|
|||
}
|
||||
|
||||
bool RTLIL::Cell::is_builtin_ff() const {
|
||||
return builtin_ff_cell_types_internal().count(type) > 0;
|
||||
return StaticCellTypes::categories.is_ff(type);
|
||||
}
|
||||
|
||||
RTLIL::SigChunk::SigChunk(const RTLIL::SigBit &bit)
|
||||
|
|
|
|||
|
|
@ -737,6 +737,7 @@ template <> struct IDMacroHelper<-1> {
|
|||
namespace RTLIL {
|
||||
extern dict<std::string, std::string> constpad;
|
||||
|
||||
[[deprecated("use StaticCellTypes::categories.is_ff() instead")]]
|
||||
const pool<IdString> &builtin_ff_cell_types();
|
||||
|
||||
static inline std::string escape_id(const std::string &str) {
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@
|
|||
*/
|
||||
|
||||
#include "kernel/yosys.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/log.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
|
||||
#ifdef YOSYS_ENABLE_READLINE
|
||||
# include <readline/readline.h>
|
||||
|
|
@ -92,7 +92,7 @@ const char* yosys_maybe_version() {
|
|||
}
|
||||
|
||||
RTLIL::Design *yosys_design = NULL;
|
||||
CellTypes yosys_celltypes;
|
||||
NewCellTypes yosys_celltypes;
|
||||
|
||||
#ifdef YOSYS_ENABLE_TCL
|
||||
Tcl_Interp *yosys_tcl_interp = NULL;
|
||||
|
|
@ -262,7 +262,7 @@ void yosys_setup()
|
|||
|
||||
Pass::init_register();
|
||||
yosys_design = new RTLIL::Design;
|
||||
yosys_celltypes.setup();
|
||||
yosys_celltypes.static_cell_types = StaticCellTypes::categories.is_known;
|
||||
log_push();
|
||||
}
|
||||
|
||||
|
|
@ -291,8 +291,6 @@ void yosys_shutdown()
|
|||
log_errfile = NULL;
|
||||
log_files.clear();
|
||||
|
||||
yosys_celltypes.clear();
|
||||
|
||||
#ifdef YOSYS_ENABLE_TCL
|
||||
if (yosys_tcl_interp != NULL) {
|
||||
if (!Tcl_InterpDeleted(yosys_tcl_interp)) {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
#include "kernel/yosys.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/celledges.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include "kernel/utils.h"
|
||||
#include "kernel/log_help.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "kernel/yosys.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include "kernel/ff.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
|
|
@ -123,7 +124,7 @@ struct LibertyStubber {
|
|||
return;
|
||||
}
|
||||
|
||||
if (RTLIL::builtin_ff_cell_types().count(base_name))
|
||||
if (StaticCellTypes::categories.is_ff(base_name))
|
||||
return liberty_flop(base, derived, f);
|
||||
|
||||
auto& base_type = ct.cell_types[base_name];
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
#include "kernel/yosys.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/log_help.h"
|
||||
|
||||
|
|
@ -488,7 +488,7 @@ static int parse_comma_list(std::set<RTLIL::IdString> &tokens, const std::string
|
|||
}
|
||||
}
|
||||
|
||||
static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::vector<expand_rule_t> &rules, std::set<RTLIL::IdString> &limits, int max_objects, char mode, CellTypes &ct, bool eval_only)
|
||||
static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::vector<expand_rule_t> &rules, std::set<RTLIL::IdString> &limits, int max_objects, char mode, NewCellTypes &ct, bool eval_only)
|
||||
{
|
||||
int sel_objects = 0;
|
||||
bool is_input, is_output;
|
||||
|
|
@ -564,7 +564,7 @@ static void select_op_expand(RTLIL::Design *design, const std::string &arg, char
|
|||
std::vector<expand_rule_t> rules;
|
||||
std::set<RTLIL::IdString> limits;
|
||||
|
||||
CellTypes ct;
|
||||
NewCellTypes ct;
|
||||
|
||||
if (mode != 'x')
|
||||
ct.setup(design);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
#include "kernel/yosys.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/utils.h"
|
||||
#include "kernel/log_help.h"
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "kernel/yosys_common.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/satgen.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "kernel/sigtools.h"
|
||||
#include "kernel/log.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include "kernel/ffinit.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
|
@ -101,7 +102,10 @@ struct keep_cache_t
|
|||
};
|
||||
|
||||
keep_cache_t keep_cache;
|
||||
CellTypes ct_reg, ct_all;
|
||||
static constexpr auto ct_reg = StaticCellTypes::Categories::join(
|
||||
StaticCellTypes::Compat::mem_ff,
|
||||
StaticCellTypes::categories.is_anyinit);
|
||||
NewCellTypes ct_all;
|
||||
int count_rm_cells, count_rm_wires;
|
||||
|
||||
void rmunused_module_cells(Module *module, bool verbose)
|
||||
|
|
@ -310,10 +314,10 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
|
|||
if (!purge_mode)
|
||||
for (auto &it : module->cells_) {
|
||||
RTLIL::Cell *cell = it.second;
|
||||
if (ct_reg.cell_known(cell->type)) {
|
||||
if (ct_reg(cell->type)) {
|
||||
bool clk2fflogic = cell->get_bool_attribute(ID(clk2fflogic));
|
||||
for (auto &it2 : cell->connections())
|
||||
if (clk2fflogic ? it2.first == ID::D : ct_reg.cell_output(cell->type, it2.first))
|
||||
if (clk2fflogic ? it2.first == ID::D : ct_all.cell_output(cell->type, it2.first))
|
||||
register_signals.add(it2.second);
|
||||
}
|
||||
for (auto &it2 : cell->connections())
|
||||
|
|
@ -517,14 +521,12 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
|
|||
bool rmunused_module_init(RTLIL::Module *module, bool verbose)
|
||||
{
|
||||
bool did_something = false;
|
||||
CellTypes fftypes;
|
||||
fftypes.setup_internals_mem();
|
||||
|
||||
SigMap sigmap(module);
|
||||
dict<SigBit, State> qbits;
|
||||
|
||||
for (auto cell : module->cells())
|
||||
if (fftypes.cell_known(cell->type) && cell->hasPort(ID::Q))
|
||||
if (StaticCellTypes::Compat::internals_mem_ff(cell->type) && cell->hasPort(ID::Q))
|
||||
{
|
||||
SigSpec sig = cell->getPort(ID::Q);
|
||||
|
||||
|
|
@ -697,10 +699,6 @@ struct OptCleanPass : public Pass {
|
|||
|
||||
keep_cache.reset(design, purge_mode);
|
||||
|
||||
ct_reg.setup_internals_mem();
|
||||
ct_reg.setup_internals_anyinit();
|
||||
ct_reg.setup_stdcells_mem();
|
||||
|
||||
ct_all.setup(design);
|
||||
|
||||
count_rm_cells = 0;
|
||||
|
|
@ -719,7 +717,6 @@ struct OptCleanPass : public Pass {
|
|||
design->check();
|
||||
|
||||
keep_cache.reset();
|
||||
ct_reg.clear();
|
||||
ct_all.clear();
|
||||
log_pop();
|
||||
|
||||
|
|
@ -760,10 +757,6 @@ struct CleanPass : public Pass {
|
|||
|
||||
keep_cache.reset(design);
|
||||
|
||||
ct_reg.setup_internals_mem();
|
||||
ct_reg.setup_internals_anyinit();
|
||||
ct_reg.setup_stdcells_mem();
|
||||
|
||||
ct_all.setup(design);
|
||||
|
||||
count_rm_cells = 0;
|
||||
|
|
@ -783,7 +776,6 @@ struct CleanPass : public Pass {
|
|||
design->check();
|
||||
|
||||
keep_cache.reset();
|
||||
ct_reg.clear();
|
||||
ct_all.clear();
|
||||
|
||||
request_garbage_collection();
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "kernel/register.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include "kernel/utils.h"
|
||||
#include "kernel/log.h"
|
||||
#include <stdlib.h>
|
||||
|
|
@ -31,7 +32,7 @@ PRIVATE_NAMESPACE_BEGIN
|
|||
|
||||
bool did_something;
|
||||
|
||||
void replace_undriven(RTLIL::Module *module, const CellTypes &ct)
|
||||
void replace_undriven(RTLIL::Module *module, const NewCellTypes &ct)
|
||||
{
|
||||
SigMap sigmap(module);
|
||||
SigPool driven_signals;
|
||||
|
|
@ -407,9 +408,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
}
|
||||
}
|
||||
|
||||
CellTypes ct_memcells;
|
||||
ct_memcells.setup_stdcells_mem();
|
||||
|
||||
if (!noclkinv)
|
||||
for (auto cell : module->cells())
|
||||
if (design->selected(module, cell)) {
|
||||
|
|
@ -433,7 +431,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
if (cell->type.in(ID($dffe), ID($adffe), ID($aldffe), ID($sdffe), ID($sdffce), ID($dffsre), ID($dlatch), ID($adlatch), ID($dlatchsr)))
|
||||
handle_polarity_inv(cell, ID::EN, ID::EN_POLARITY, assign_map, invert_map);
|
||||
|
||||
if (!ct_memcells.cell_known(cell->type))
|
||||
if (!StaticCellTypes::Compat::stdcells_mem(cell->type))
|
||||
continue;
|
||||
|
||||
handle_clkpol_celltype_swap(cell, "$_SR_N?_", "$_SR_P?_", ID::S, assign_map, invert_map);
|
||||
|
|
@ -2294,7 +2292,7 @@ struct OptExprPass : public Pass {
|
|||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
CellTypes ct(design);
|
||||
NewCellTypes ct(design);
|
||||
for (auto module : design->selected_modules())
|
||||
{
|
||||
log("Optimizing module %s.\n", log_id(module));
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include "kernel/modtools.h"
|
||||
#include "kernel/utils.h"
|
||||
#include "kernel/macc.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include <iterator>
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
|
|
@ -38,19 +39,18 @@ struct ShareWorkerConfig
|
|||
bool opt_force;
|
||||
bool opt_aggressive;
|
||||
bool opt_fast;
|
||||
pool<RTLIL::IdString> generic_uni_ops, generic_bin_ops, generic_cbin_ops, generic_other_ops;
|
||||
StaticCellTypes::Categories::Category generic_uni_ops, generic_bin_ops, generic_cbin_ops, generic_other_ops;
|
||||
};
|
||||
|
||||
struct ShareWorker
|
||||
{
|
||||
const ShareWorkerConfig config;
|
||||
int limit;
|
||||
pool<RTLIL::IdString> generic_ops;
|
||||
StaticCellTypes::Categories::Category generic_ops;
|
||||
|
||||
RTLIL::Design *design;
|
||||
RTLIL::Module *module;
|
||||
|
||||
CellTypes fwd_ct, cone_ct;
|
||||
ModWalker modwalker;
|
||||
|
||||
pool<RTLIL::Cell*> cells_to_remove;
|
||||
|
|
@ -75,7 +75,7 @@ struct ShareWorker
|
|||
queue_bits.insert(modwalker.signal_outputs.begin(), modwalker.signal_outputs.end());
|
||||
|
||||
for (auto &it : module->cells_)
|
||||
if (!fwd_ct.cell_known(it.second->type)) {
|
||||
if (!StaticCellTypes::Compat::internals_nomem_noff(it.second->type)) {
|
||||
pool<RTLIL::SigBit> &bits = modwalker.cell_inputs[it.second];
|
||||
queue_bits.insert(bits.begin(), bits.end());
|
||||
}
|
||||
|
|
@ -95,7 +95,7 @@ struct ShareWorker
|
|||
queue_bits.insert(bits.begin(), bits.end());
|
||||
visited_cells.insert(pbit.cell);
|
||||
}
|
||||
if (fwd_ct.cell_known(pbit.cell->type) && visited_cells.count(pbit.cell) == 0) {
|
||||
if (StaticCellTypes::Compat::internals_nomem_noff(pbit.cell->type) && visited_cells.count(pbit.cell) == 0) {
|
||||
pool<RTLIL::SigBit> &bits = modwalker.cell_inputs[pbit.cell];
|
||||
terminal_bits.insert(bits.begin(), bits.end());
|
||||
queue_bits.insert(bits.begin(), bits.end());
|
||||
|
|
@ -388,7 +388,7 @@ struct ShareWorker
|
|||
continue;
|
||||
}
|
||||
|
||||
if (generic_ops.count(cell->type)) {
|
||||
if (generic_ops(cell->type)) {
|
||||
if (config.opt_aggressive)
|
||||
shareable_cells.insert(cell);
|
||||
continue;
|
||||
|
|
@ -412,7 +412,7 @@ struct ShareWorker
|
|||
return true;
|
||||
}
|
||||
|
||||
if (config.generic_uni_ops.count(c1->type))
|
||||
if (config.generic_uni_ops(c1->type))
|
||||
{
|
||||
if (!config.opt_aggressive)
|
||||
{
|
||||
|
|
@ -429,7 +429,7 @@ struct ShareWorker
|
|||
return true;
|
||||
}
|
||||
|
||||
if (config.generic_bin_ops.count(c1->type) || c1->type == ID($alu))
|
||||
if (config.generic_bin_ops(c1->type) || c1->type == ID($alu))
|
||||
{
|
||||
if (!config.opt_aggressive)
|
||||
{
|
||||
|
|
@ -449,7 +449,7 @@ struct ShareWorker
|
|||
return true;
|
||||
}
|
||||
|
||||
if (config.generic_cbin_ops.count(c1->type))
|
||||
if (config.generic_cbin_ops(c1->type))
|
||||
{
|
||||
if (!config.opt_aggressive)
|
||||
{
|
||||
|
|
@ -511,7 +511,7 @@ struct ShareWorker
|
|||
{
|
||||
log_assert(c1->type == c2->type);
|
||||
|
||||
if (config.generic_uni_ops.count(c1->type))
|
||||
if (config.generic_uni_ops(c1->type))
|
||||
{
|
||||
if (c1->parameters.at(ID::A_SIGNED).as_bool() != c2->parameters.at(ID::A_SIGNED).as_bool())
|
||||
{
|
||||
|
|
@ -560,11 +560,11 @@ struct ShareWorker
|
|||
return supercell;
|
||||
}
|
||||
|
||||
if (config.generic_bin_ops.count(c1->type) || config.generic_cbin_ops.count(c1->type) || c1->type == ID($alu))
|
||||
if (config.generic_bin_ops(c1->type) || config.generic_cbin_ops(c1->type) || c1->type == ID($alu))
|
||||
{
|
||||
bool modified_src_cells = false;
|
||||
|
||||
if (config.generic_cbin_ops.count(c1->type))
|
||||
if (config.generic_cbin_ops(c1->type))
|
||||
{
|
||||
int score_unflipped = max(c1->parameters.at(ID::A_WIDTH).as_int(), c2->parameters.at(ID::A_WIDTH).as_int()) +
|
||||
max(c1->parameters.at(ID::B_WIDTH).as_int(), c2->parameters.at(ID::B_WIDTH).as_int());
|
||||
|
|
@ -758,7 +758,7 @@ struct ShareWorker
|
|||
recursion_state.insert(cell);
|
||||
|
||||
for (auto c : consumer_cells)
|
||||
if (fwd_ct.cell_known(c->type)) {
|
||||
if (StaticCellTypes::Compat::internals_nomem_noff(c->type)) {
|
||||
const pool<RTLIL::SigBit> &bits = find_forbidden_controls(c);
|
||||
forbidden_controls_cache[cell].insert(bits.begin(), bits.end());
|
||||
}
|
||||
|
|
@ -897,7 +897,7 @@ struct ShareWorker
|
|||
return activation_patterns_cache.at(cell);
|
||||
}
|
||||
for (auto &pbit : modwalker.signal_consumers[bit]) {
|
||||
log_assert(fwd_ct.cell_known(pbit.cell->type));
|
||||
log_assert(StaticCellTypes::Compat::internals_nomem_noff(pbit.cell->type));
|
||||
if ((pbit.cell->type == ID($mux) || pbit.cell->type == ID($pmux)) && (pbit.port == ID::A || pbit.port == ID::B))
|
||||
driven_data_muxes.insert(pbit.cell);
|
||||
else
|
||||
|
|
@ -1214,24 +1214,10 @@ struct ShareWorker
|
|||
ShareWorker(ShareWorkerConfig config, RTLIL::Design* design) :
|
||||
config(config), design(design), modwalker(design)
|
||||
{
|
||||
generic_ops.insert(config.generic_uni_ops.begin(), config.generic_uni_ops.end());
|
||||
generic_ops.insert(config.generic_bin_ops.begin(), config.generic_bin_ops.end());
|
||||
generic_ops.insert(config.generic_cbin_ops.begin(), config.generic_cbin_ops.end());
|
||||
generic_ops.insert(config.generic_other_ops.begin(), config.generic_other_ops.end());
|
||||
|
||||
fwd_ct.setup_internals();
|
||||
|
||||
cone_ct.setup_internals();
|
||||
cone_ct.cell_types.erase(ID($mul));
|
||||
cone_ct.cell_types.erase(ID($mod));
|
||||
cone_ct.cell_types.erase(ID($div));
|
||||
cone_ct.cell_types.erase(ID($modfloor));
|
||||
cone_ct.cell_types.erase(ID($divfloor));
|
||||
cone_ct.cell_types.erase(ID($pow));
|
||||
cone_ct.cell_types.erase(ID($shl));
|
||||
cone_ct.cell_types.erase(ID($shr));
|
||||
cone_ct.cell_types.erase(ID($sshl));
|
||||
cone_ct.cell_types.erase(ID($sshr));
|
||||
generic_ops = StaticCellTypes::Categories::join(generic_ops, config.generic_uni_ops);
|
||||
generic_ops = StaticCellTypes::Categories::join(generic_ops, config.generic_bin_ops);
|
||||
generic_ops = StaticCellTypes::Categories::join(generic_ops, config.generic_cbin_ops);
|
||||
generic_ops = StaticCellTypes::Categories::join(generic_ops, config.generic_other_ops);
|
||||
}
|
||||
|
||||
void operator()(RTLIL::Module *module) {
|
||||
|
|
@ -1561,45 +1547,45 @@ struct SharePass : public Pass {
|
|||
config.opt_aggressive = false;
|
||||
config.opt_fast = false;
|
||||
|
||||
config.generic_uni_ops.insert(ID($not));
|
||||
// config.generic_uni_ops.insert(ID($pos));
|
||||
config.generic_uni_ops.insert(ID($neg));
|
||||
config.generic_uni_ops.set_id(ID($not));
|
||||
// config.generic_uni_ops.set_id(ID($pos));
|
||||
config.generic_uni_ops.set_id(ID($neg));
|
||||
|
||||
config.generic_cbin_ops.insert(ID($and));
|
||||
config.generic_cbin_ops.insert(ID($or));
|
||||
config.generic_cbin_ops.insert(ID($xor));
|
||||
config.generic_cbin_ops.insert(ID($xnor));
|
||||
config.generic_cbin_ops.set_id(ID($and));
|
||||
config.generic_cbin_ops.set_id(ID($or));
|
||||
config.generic_cbin_ops.set_id(ID($xor));
|
||||
config.generic_cbin_ops.set_id(ID($xnor));
|
||||
|
||||
config.generic_bin_ops.insert(ID($shl));
|
||||
config.generic_bin_ops.insert(ID($shr));
|
||||
config.generic_bin_ops.insert(ID($sshl));
|
||||
config.generic_bin_ops.insert(ID($sshr));
|
||||
config.generic_bin_ops.set_id(ID($shl));
|
||||
config.generic_bin_ops.set_id(ID($shr));
|
||||
config.generic_bin_ops.set_id(ID($sshl));
|
||||
config.generic_bin_ops.set_id(ID($sshr));
|
||||
|
||||
config.generic_bin_ops.insert(ID($lt));
|
||||
config.generic_bin_ops.insert(ID($le));
|
||||
config.generic_bin_ops.insert(ID($eq));
|
||||
config.generic_bin_ops.insert(ID($ne));
|
||||
config.generic_bin_ops.insert(ID($eqx));
|
||||
config.generic_bin_ops.insert(ID($nex));
|
||||
config.generic_bin_ops.insert(ID($ge));
|
||||
config.generic_bin_ops.insert(ID($gt));
|
||||
config.generic_bin_ops.set_id(ID($lt));
|
||||
config.generic_bin_ops.set_id(ID($le));
|
||||
config.generic_bin_ops.set_id(ID($eq));
|
||||
config.generic_bin_ops.set_id(ID($ne));
|
||||
config.generic_bin_ops.set_id(ID($eqx));
|
||||
config.generic_bin_ops.set_id(ID($nex));
|
||||
config.generic_bin_ops.set_id(ID($ge));
|
||||
config.generic_bin_ops.set_id(ID($gt));
|
||||
|
||||
config.generic_cbin_ops.insert(ID($add));
|
||||
config.generic_cbin_ops.insert(ID($mul));
|
||||
config.generic_cbin_ops.set_id(ID($add));
|
||||
config.generic_cbin_ops.set_id(ID($mul));
|
||||
|
||||
config.generic_bin_ops.insert(ID($sub));
|
||||
config.generic_bin_ops.insert(ID($div));
|
||||
config.generic_bin_ops.insert(ID($mod));
|
||||
config.generic_bin_ops.insert(ID($divfloor));
|
||||
config.generic_bin_ops.insert(ID($modfloor));
|
||||
// config.generic_bin_ops.insert(ID($pow));
|
||||
config.generic_bin_ops.set_id(ID($sub));
|
||||
config.generic_bin_ops.set_id(ID($div));
|
||||
config.generic_bin_ops.set_id(ID($mod));
|
||||
config.generic_bin_ops.set_id(ID($divfloor));
|
||||
config.generic_bin_ops.set_id(ID($modfloor));
|
||||
// config.generic_bin_ops.set_id(ID($pow));
|
||||
|
||||
config.generic_uni_ops.insert(ID($logic_not));
|
||||
config.generic_cbin_ops.insert(ID($logic_and));
|
||||
config.generic_cbin_ops.insert(ID($logic_or));
|
||||
config.generic_uni_ops.set_id(ID($logic_not));
|
||||
config.generic_cbin_ops.set_id(ID($logic_and));
|
||||
config.generic_cbin_ops.set_id(ID($logic_or));
|
||||
|
||||
config.generic_other_ops.insert(ID($alu));
|
||||
config.generic_other_ops.insert(ID($macc));
|
||||
config.generic_other_ops.set_id(ID($alu));
|
||||
config.generic_other_ops.set_id(ID($macc));
|
||||
|
||||
log_header(design, "Executing SHARE pass (SAT-based resource sharing).\n");
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "kernel/yosys.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include "kernel/mem.h"
|
||||
#include "kernel/fstdata.h"
|
||||
#include "kernel/ff.h"
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include "kernel/ffinit.h"
|
||||
#include "kernel/ff.h"
|
||||
#include "kernel/cost.h"
|
||||
|
|
@ -2455,7 +2455,7 @@ struct AbcPass : public Pass {
|
|||
continue;
|
||||
}
|
||||
|
||||
CellTypes ct(design);
|
||||
NewCellTypes ct(design);
|
||||
|
||||
std::vector<RTLIL::Cell*> all_cells = mod->selected_cells();
|
||||
pool<RTLIL::Cell*> unassigned_cells(all_cells.begin(), all_cells.end());
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
#include "kernel/register.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/utils.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include "kernel/timinginfo.h"
|
||||
#include <optional>
|
||||
|
||||
|
|
|
|||
|
|
@ -33,12 +33,3 @@ assert repr_test == {'tomato': 'tomato', 'first': 'second', 'key': 'value', 'im
|
|||
before = len(repr_test)
|
||||
print(repr_test.popitem())
|
||||
assert before - 1 == len(repr_test)
|
||||
|
||||
# test noncomparable
|
||||
## if ys.CellType ever gets an == operator just disable this section
|
||||
uncomparable_value = ys.Globals.yosys_celltypes.cell_types[ys.IdString("$not")]
|
||||
|
||||
x = ys.IdstringToCelltypeDict({ ys.IdString("\\a"): uncomparable_value})
|
||||
y = ys.IdstringToCelltypeDict({ ys.IdString("\\a"): uncomparable_value})
|
||||
|
||||
assert x != y # not comparable
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
#include <gtest/gtest.h>
|
||||
#include "kernel/yosys.h"
|
||||
#include "kernel/yosys_common.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
TEST(CellTypesTest, basic)
|
||||
{
|
||||
yosys_setup();
|
||||
log_files.push_back(stdout);
|
||||
CellTypes older;
|
||||
NewCellTypes newer;
|
||||
older.setup(nullptr);
|
||||
newer.setup(nullptr);
|
||||
older.setup_type(ID(bleh), {ID::G}, {ID::H, ID::I}, false, true);
|
||||
newer.setup_type(ID(bleh), {ID::G}, {ID::H, ID::I}, false, true);
|
||||
EXPECT_EQ(older.cell_known(ID(aaaaa)), newer.cell_known(ID(aaaaa)));
|
||||
EXPECT_EQ(older.cell_known(ID($and)), newer.cell_known(ID($and)));
|
||||
auto check_port = [&](auto type, auto port) {
|
||||
EXPECT_EQ(older.cell_port_dir(type, port), newer.cell_port_dir(type, port));
|
||||
EXPECT_EQ(older.cell_input(type, port), newer.cell_input(type, port));
|
||||
EXPECT_EQ(older.cell_output(type, port), newer.cell_output(type, port));
|
||||
};
|
||||
|
||||
// ground truth
|
||||
const pool<IdString> expected_ff_types = {
|
||||
ID($sr), ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($dffsre),
|
||||
ID($adff), ID($adffe), ID($aldff), ID($aldffe),
|
||||
ID($sdff), ID($sdffe), ID($sdffce),
|
||||
ID($dlatch), ID($adlatch), ID($dlatchsr),
|
||||
ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_),
|
||||
ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
|
||||
ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_),
|
||||
ID($_DFFSRE_NNNN_), ID($_DFFSRE_NNNP_), ID($_DFFSRE_NNPN_), ID($_DFFSRE_NNPP_),
|
||||
ID($_DFFSRE_NPNN_), ID($_DFFSRE_NPNP_), ID($_DFFSRE_NPPN_), ID($_DFFSRE_NPPP_),
|
||||
ID($_DFFSRE_PNNN_), ID($_DFFSRE_PNNP_), ID($_DFFSRE_PNPN_), ID($_DFFSRE_PNPP_),
|
||||
ID($_DFFSRE_PPNN_), ID($_DFFSRE_PPNP_), ID($_DFFSRE_PPPN_), ID($_DFFSRE_PPPP_),
|
||||
ID($_DFF_N_), ID($_DFF_P_),
|
||||
ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
|
||||
ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_),
|
||||
ID($_DFFE_NN0N_), ID($_DFFE_NN0P_), ID($_DFFE_NN1N_), ID($_DFFE_NN1P_),
|
||||
ID($_DFFE_NP0N_), ID($_DFFE_NP0P_), ID($_DFFE_NP1N_), ID($_DFFE_NP1P_),
|
||||
ID($_DFFE_PN0N_), ID($_DFFE_PN0P_), ID($_DFFE_PN1N_), ID($_DFFE_PN1P_),
|
||||
ID($_DFFE_PP0N_), ID($_DFFE_PP0P_), ID($_DFFE_PP1N_), ID($_DFFE_PP1P_),
|
||||
ID($_ALDFF_NN_), ID($_ALDFF_NP_), ID($_ALDFF_PN_), ID($_ALDFF_PP_),
|
||||
ID($_ALDFFE_NNN_), ID($_ALDFFE_NNP_), ID($_ALDFFE_NPN_), ID($_ALDFFE_NPP_),
|
||||
ID($_ALDFFE_PNN_), ID($_ALDFFE_PNP_), ID($_ALDFFE_PPN_), ID($_ALDFFE_PPP_),
|
||||
ID($_SDFF_NN0_), ID($_SDFF_NN1_), ID($_SDFF_NP0_), ID($_SDFF_NP1_),
|
||||
ID($_SDFF_PN0_), ID($_SDFF_PN1_), ID($_SDFF_PP0_), ID($_SDFF_PP1_),
|
||||
ID($_SDFFE_NN0N_), ID($_SDFFE_NN0P_), ID($_SDFFE_NN1N_), ID($_SDFFE_NN1P_),
|
||||
ID($_SDFFE_NP0N_), ID($_SDFFE_NP0P_), ID($_SDFFE_NP1N_), ID($_SDFFE_NP1P_),
|
||||
ID($_SDFFE_PN0N_), ID($_SDFFE_PN0P_), ID($_SDFFE_PN1N_), ID($_SDFFE_PN1P_),
|
||||
ID($_SDFFE_PP0N_), ID($_SDFFE_PP0P_), ID($_SDFFE_PP1N_), ID($_SDFFE_PP1P_),
|
||||
ID($_SDFFCE_NN0N_), ID($_SDFFCE_NN0P_), ID($_SDFFCE_NN1N_), ID($_SDFFCE_NN1P_),
|
||||
ID($_SDFFCE_NP0N_), ID($_SDFFCE_NP0P_), ID($_SDFFCE_NP1N_), ID($_SDFFCE_NP1P_),
|
||||
ID($_SDFFCE_PN0N_), ID($_SDFFCE_PN0P_), ID($_SDFFCE_PN1N_), ID($_SDFFCE_PN1P_),
|
||||
ID($_SDFFCE_PP0N_), ID($_SDFFCE_PP0P_), ID($_SDFFCE_PP1N_), ID($_SDFFCE_PP1P_),
|
||||
ID($_SR_NN_), ID($_SR_NP_), ID($_SR_PN_), ID($_SR_PP_),
|
||||
ID($_DLATCH_N_), ID($_DLATCH_P_),
|
||||
ID($_DLATCH_NN0_), ID($_DLATCH_NN1_), ID($_DLATCH_NP0_), ID($_DLATCH_NP1_),
|
||||
ID($_DLATCH_PN0_), ID($_DLATCH_PN1_), ID($_DLATCH_PP0_), ID($_DLATCH_PP1_),
|
||||
ID($_DLATCHSR_NNN_), ID($_DLATCHSR_NNP_), ID($_DLATCHSR_NPN_), ID($_DLATCHSR_NPP_),
|
||||
ID($_DLATCHSR_PNN_), ID($_DLATCHSR_PNP_), ID($_DLATCHSR_PPN_), ID($_DLATCHSR_PPP_),
|
||||
ID($_FF_),
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < static_cast<size_t>(RTLIL::StaticId::STATIC_ID_END); i++) {
|
||||
IdString type;
|
||||
type.index_ = i;
|
||||
EXPECT_EQ(older.cell_known(type), newer.cell_known(type));
|
||||
if (older.cell_evaluable(type) != newer.cell_evaluable(type))
|
||||
std::cout << type.str() << "\n";
|
||||
EXPECT_EQ(older.cell_evaluable(type), newer.cell_evaluable(type));
|
||||
for (auto port : StaticCellTypes::builder.cells.data()->inputs.ports)
|
||||
check_port(type, port);
|
||||
for (auto port : StaticCellTypes::builder.cells.data()->outputs.ports)
|
||||
check_port(type, port);
|
||||
EXPECT_EQ(expected_ff_types.count(type) > 0, StaticCellTypes::categories.is_ff(type));
|
||||
}
|
||||
yosys_shutdown();
|
||||
}
|
||||
|
||||
YOSYS_NAMESPACE_END
|
||||
Loading…
Reference in New Issue