Skip to content

Commit

Permalink
Merge pull request #4084 from jix/scopeinfo
Browse files Browse the repository at this point in the history
$scopeinfo support
  • Loading branch information
mmicko authored Feb 12, 2024
2 parents 1029712 + 364bcfb commit edb95c6
Show file tree
Hide file tree
Showing 20 changed files with 976 additions and 21 deletions.
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);
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

0 comments on commit edb95c6

Please sign in to comment.