0

I am trying to implement a new pass to calculate the sequential depth and complexity of a given module in Yosys. To do so, I am getting inspired by scc pass. To implement it, I need to specifically perform DFS starting from the module's input ports. To do so, I am trying to find all of the cells which are immediately connected to the input ports. I am starting from the module's port and find the associate wires:

SigPool inputPorts;
for (auto &it : module->ports) 
  if (module->wires_[it]->port_input)  
     inputPorts.add((sigmap(RTLIL::SigSpec(module->wires_[it]))));

but the problem that I have is that I am not able to find the cells which are immediately connected to the input ports from there (there is not APR for that purpose in the wires/sigspec/sigpool types).

Any help/hint would be greatly appreciated.

Mehrdad
  • 107
  • 8

2 Answers2

1

I was able to implement that part as follows, that works but I am not sure if it is the best way. any advice/comment would be greatly appreciated.

// for all input the cells of the module find its incoming signals (inputSignals in this code), and for each bit of them do the following:
for (auto &bit : inputSignals)
  if (bit.wire != NULL) {
    if (inputPortsSet.count(bit.wire->port_id)) {
      log ("found an input port\n");
      log ("%s :",cell->name.c_str());
      log(" %s ", bit.wire->name.c_str());
      log(" %d \n", bit.wire->port_id);       
      break;
    }
  }
Mehrdad
  • 107
  • 8
1

I think the following code example (although not DFS) should contain all the relevant idiomatic Yosys code snippets that you'd need:

    // create canonical versions of all sigbits
    SigMap sigmap(module);

    // first layer of bits
    pool<SigBit> input_bits;

    for (auto wire : module->wires())
        if (wire->port_input)
            for (auto bit : sigmap(wire))
                input_bits.insert(bit);

    // index: from sigbit to driven cells
    dict<SigBit, pool<Cell*>> bit2cells;

    // index: from cell to driven sigbits
    dict<Cell*, pool<SigBit>> cell2bits;

    for (auto cell : module->cells())
    for (auto &conn : cell->connections()) {
        if (cell->input(conn.first)) {
            for (auto bit : sigmap(conn.second))
                bit2cells[bit].insert(cell);
        }
        if (cell->output(conn.first)) {
            for (auto bit : sigmap(conn.second))
                cell2bits[cell].insert(bit);
        }
    }

    pool<SigBit> queue = input_bits;
    pool<Cell*> visited_cells;

    while (!queue.empty())
    {
        log("------\n");

        pool<Cell*> this_iter_cells;

        for (auto bit : queue)
        for (auto cell : bit2cells[bit])
            if (!visited_cells.count(cell)) {
                log("  %s\n", log_id(cell));
                visited_cells.insert(cell);
                this_iter_cells.insert(cell);
            }

        queue.clear();
        for (auto cell : this_iter_cells)
        for (auto bit : cell2bits[cell])
            queue.insert(bit);
    }

The most important things to take away from that:

  • Use SigMap to create canonical representations of signal bits (in case two wires are connected to each other and are just "alias names" for the same actual bit).

  • Break up your algorithm in two stages: (1) create the index structures that you need and (2) perform the actual algorithm.

You might also find the answers to this and this question useful.

(I'm writing this answer in a hurry.. Please ask further questions in comments below if anything is unclear.)

Community
  • 1
  • 1
CliffordVienna
  • 7,995
  • 1
  • 37
  • 57