Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

$scopeinfo support #4084

Merged
merged 14 commits into from
Feb 12, 2024
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,7 @@ $(eval $(call add_include_file,kernel/qcsat.h))
$(eval $(call add_include_file,kernel/register.h))
$(eval $(call add_include_file,kernel/rtlil.h))
$(eval $(call add_include_file,kernel/satgen.h))
$(eval $(call add_include_file,kernel/scopeinfo.h))
$(eval $(call add_include_file,kernel/sigtools.h))
$(eval $(call add_include_file,kernel/timinginfo.h))
$(eval $(call add_include_file,kernel/utils.h))
Expand All @@ -656,7 +657,7 @@ $(eval $(call add_include_file,backends/cxxrtl/runtime/cxxrtl/capi/cxxrtl_capi_v

OBJS += kernel/driver.o kernel/register.o kernel/rtlil.o kernel/log.o kernel/calc.o kernel/yosys.o
OBJS += kernel/binding.o
OBJS += kernel/cellaigs.o kernel/celledges.o kernel/satgen.o kernel/qcsat.o kernel/mem.o kernel/ffmerge.o kernel/ff.o kernel/yw.o kernel/json.o kernel/fmt.o
OBJS += kernel/cellaigs.o kernel/celledges.o kernel/satgen.o kernel/scopeinfo.o kernel/qcsat.o kernel/mem.o kernel/ffmerge.o kernel/ff.o kernel/yw.o kernel/json.o kernel/fmt.o
ifeq ($(ENABLE_ZLIB),1)
OBJS += kernel/fstdata.o
endif
Expand Down
3 changes: 3 additions & 0 deletions backends/aiger/aiger.cc
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,9 @@ struct AigerWriter
continue;
}

if (cell->type == ID($scopeinfo))
continue;

log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell));
}

Expand Down
3 changes: 3 additions & 0 deletions backends/blif/blif.cc
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,9 @@ struct BlifDumper

for (auto cell : module->cells())
{
if (cell->type == ID($scopeinfo))
continue;

if (config->unbuf_types.count(cell->type)) {
auto portnames = config->unbuf_types.at(cell->type);
f << stringf(".names %s %s\n1 1\n",
Expand Down
3 changes: 3 additions & 0 deletions backends/edif/edif.cc
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ struct EdifBackend : public Backend {

for (auto cell : module->cells())
{
if (cell->type == ID($scopeinfo))
continue;

if (design->module(cell->type) == nullptr || design->module(cell->type)->get_blackbox_attribute()) {
lib_cell_ports[cell->type];
for (auto p : cell->connections())
Expand Down
3 changes: 3 additions & 0 deletions backends/firrtl/firrtl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -980,6 +980,9 @@ struct FirrtlWorker
register_reverse_wire_map(y_id, cell->getPort(ID::Y));
continue;
}

if (cell->type == ID($scopeinfo))
continue;
log_error("Cell type not supported: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell));
}

Expand Down
4 changes: 4 additions & 0 deletions backends/json/json.cc
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,10 @@ struct JsonWriter
for (auto c : module->cells()) {
if (use_selection && !module->selected(c))
continue;
// Eventually we will want to emit $scopeinfo, but currently this
// will break JSON netlist consumers like nextpnr
if (c->type == ID($scopeinfo))
continue;
f << stringf("%s\n", first ? "" : ",");
f << stringf(" %s: {\n", get_name(c->name).c_str());
f << stringf(" \"hide_name\": %s,\n", c->name[0] == '$' ? "1" : "0");
Expand Down
3 changes: 3 additions & 0 deletions backends/smv/smv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,9 @@ struct SmvWorker
continue;
}

if (cell->type == ID($scopeinfo))
continue;

if (cell->type[0] == '$') {
if (cell->type.in(ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)) || cell->type.str().substr(0, 6) == "$_SDFF" || (cell->type.str().substr(0, 6) == "$_DFFE" && cell->type.str().size() == 10)) {
log_error("Unsupported cell type %s for cell %s.%s -- please run `dffunmap` before `write_smv`.\n",
Expand Down
3 changes: 3 additions & 0 deletions backends/spice/spice.cc
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ static void print_spice_module(std::ostream &f, RTLIL::Module *module, RTLIL::De

for (auto cell : module->cells())
{
if (cell->type == ID($scopeinfo))
continue;

f << stringf("X%d", cell_counter++);

std::vector<RTLIL::SigSpec> port_sigs;
Expand Down
7 changes: 7 additions & 0 deletions backends/verilog/verilog_backend.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1871,6 +1871,13 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)

void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell)
{
// To keep the output compatible with other tools we ignore $scopeinfo
// cells that exist only to hold metadata. If in the future that metadata
// should be exposed as part of the write_verilog output it should be
// opt-in and/or represented as something else than a $scopeinfo cell.
if (cell->type == ID($scopeinfo))
return;

// Handled by dump_memory
if (cell->is_mem_cell())
return;
Expand Down
144 changes: 144 additions & 0 deletions examples/cxx-api/scopeinfo_example.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2023 Jannis Harder <[email protected]> <[email protected]>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/

// build: yosys-config --build scopeinfo_example.so scopeinfo_example.cc
// use: yosys -m scopeinfo_example.so

#include "backends/rtlil/rtlil_backend.h"
#include "kernel/scopeinfo.h"
#include "kernel/yosys.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

struct ScopeinfoExamplePass : public Pass {
ScopeinfoExamplePass() : Pass("scopeinfo_example", "dump scopeinfo") {}
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" scopeinfo_example [options] [selection]\n");
log("\n");
}

void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
log_header(design, "Executing SCOPEINFO_EXAMPLE pass.\n");

bool do_wires = false;
bool do_common = false;

size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
if (args[argidx] == "-wires") {
do_wires = true;
continue;
}
if (args[argidx] == "-common") {
do_common = true;
continue;
}
break;
}
extra_args(args, argidx, design);


if (do_wires) {
for (auto module : design->selected_modules()) {
log("Source hierarchy for all selected wires within %s:\n", log_id(module));
ModuleHdlnameIndex index(module);

index.index_scopeinfo_cells();

for (auto wire : module->selected_wires()) {
if (!wire->name.isPublic())
continue;

auto wire_scope = index.containing_scope(wire);

if (!wire_scope.first.valid()) {
log_warning("Couldn't find containing scope for %s in index\n", log_id(wire));
continue;
}

log("%s %s\n", wire_scope.first.path_str().c_str(), log_id(wire_scope.second));
for (auto src : index.sources(wire))
log(" - %s\n", src.c_str());
}
}
}

if (do_common) {
for (auto module : design->selected_modules()) {
std::vector<Wire *> wires = module->selected_wires();

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

ModuleHdlnameIndex index(module);

index.index_scopeinfo_cells();

for (auto wire_i = wires.begin(), wire_end = wires.end(); wire_i != wire_end; ++wire_i) {
if (!(*wire_i)->name.isPublic())
continue;

std::pair<ModuleHdlnameIndex::Cursor, IdString> scope_i = index.containing_scope(*wire_i);
if (!scope_i.first.valid())
continue;

int limit = 0;

for (auto wire_j = wire_i + 1; wire_j != wire_end; ++wire_j) {
if (!(*wire_j)->name.isPublic())
continue;

std::pair<ModuleHdlnameIndex::Cursor, IdString> scope_j = index.containing_scope(*wire_j);
if (!scope_j.first.valid())
continue;

// Skip wires in the same hierarchy level
if (scope_i.first == scope_j.first)
continue;


ModuleHdlnameIndex::Cursor common = scope_i.first.common_ancestor(scope_j.first);

// Try to show at least some non-root common ancestors
if (common.is_root() && limit > 5)
continue;

log("common_ancestor(%s %s%s%s, %s %s%s%s) = %s %s\n",
log_id(module), scope_i.first.path_str().c_str(), scope_i.first.is_root() ? "" : " ", log_id(scope_i.second),
log_id(module), scope_j.first.path_str().c_str(), scope_j.first.is_root() ? "" : " ", log_id(scope_j.second),
log_id(module), common.path_str().c_str()
);

if (++limit == 10)
break;
}
}
}
}
}
} ScopeinfoExamplePass;

PRIVATE_NAMESPACE_END
1 change: 1 addition & 0 deletions kernel/celltypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ struct CellTypes
setup_type(ID($overwrite_tag), {ID::A, ID::SET, ID::CLR}, pool<RTLIL::IdString>());
setup_type(ID($original_tag), {ID::A}, {ID::Y});
setup_type(ID($future_ff), {ID::A}, {ID::Y});
setup_type(ID($scopeinfo), {}, {});
}

void setup_internals_eval()
Expand Down
9 changes: 9 additions & 0 deletions kernel/rtlil.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1769,6 +1769,15 @@ namespace {
return;
}

if (cell->type == ID($scopeinfo)) {
param(ID::TYPE);
whitequark marked this conversation as resolved.
Show resolved Hide resolved
check_expected();
std::string scope_type = cell->getParam(ID::TYPE).decode_string();
if (scope_type != "module" && scope_type != "struct")
error(__LINE__);
return;
}

if (cell->type == ID($_BUF_)) { port(ID::A,1); port(ID::Y,1); check_expected(); return; }
if (cell->type == ID($_NOT_)) { port(ID::A,1); port(ID::Y,1); check_expected(); return; }
if (cell->type == ID($_AND_)) { port(ID::A,1); port(ID::B,1); port(ID::Y,1); check_expected(); return; }
Expand Down
5 changes: 5 additions & 0 deletions kernel/satgen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1379,6 +1379,11 @@ bool SatGen::importCell(RTLIL::Cell *cell, int timestep)
return true;
}

if (cell->type == ID($scopeinfo))
{
return true;
}

// Unsupported internal cell types: $pow $fsm $mem*
// .. and all sequential cells with asynchronous inputs
return false;
Expand Down
Loading
Loading