// This is free and unencumbered software released into the public domain. // // Anyone is free to copy, modify, publish, use, compile, sell, or // distribute this software, either in source code form or as a compiled // binary, for any purpose, commercial or non-commercial, and by any // means. #include "kernel/yosys.h" #include "kernel/sigtools.h" #include #include #include USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN // this function is called for each module in the design static void find_stub_nets(RTLIL::Design *design, RTLIL::Module *module, bool report_bits) { // use a SigMap to convert nets to a unique representation SigMap sigmap(module); // count how many times a single-bit signal is used std::map bit_usage_count; // count output lines for this module (needed only for summary output at the end) int line_count = 0; log("Looking for stub wires in module %s:\n", RTLIL::id2cstr(module->name)); // For all ports on all cells for (auto &cell_iter : module->cells_) for (auto &conn : cell_iter.second->connections()) { // Get the signals on the port // (use sigmap to get a uniqe signal name) RTLIL::SigSpec sig = sigmap(conn.second); // add each bit to bit_usage_count, unless it is a constant for (auto &bit : sig) if (bit.wire != NULL) bit_usage_count[bit]++; } // for each wire in the module for (auto &wire_iter : module->wires_) { RTLIL::Wire *wire = wire_iter.second; // .. but only selected wires if (!design->selected(module, wire)) continue; // add +1 usage if this wire actually is a port int usage_offset = wire->port_id > 0 ? 1 : 0; // we will record which bits of the (possibly multi-bit) wire are stub signals std::set stub_bits; // get a signal description for this wire and split it into separate bits RTLIL::SigSpec sig = sigmap(wire); // for each bit (unless it is a constant): // check if it is used at least two times and add to stub_bits otherwise for (int i = 0; i < GetSize(sig); i++) if (sig[i].wire != NULL && (bit_usage_count[sig[i]] + usage_offset) < 2) stub_bits.insert(i); // continue if no stub bits found if (stub_bits.size() == 0) continue; // report stub bits and/or stub wires, don't report single bits // if called with report_bits set to false. if (GetSize(stub_bits) == GetSize(sig)) { log(" found stub wire: %s\n", RTLIL::id2cstr(wire->name)); } else { if (!report_bits) continue; log(" found wire with stub bits: %s [", RTLIL::id2cstr(wire->name)); for (int bit : stub_bits) log("%s%d", bit == *stub_bits.begin() ? "" : ", ", bit); log("]\n"); } // we have outputted a line, increment summary counter line_count++; } // report summary if (report_bits) log(" found %d stub wires or wires with stub bits.\n", line_count); else log(" found %d stub wires.\n", line_count); } // each pass contains a singleton object that is derived from Pass struct StubnetsPass : public Pass { StubnetsPass() : Pass("stubnets") { } void execute(std::vector args, RTLIL::Design *design) override { // variables to mirror information from passed options bool report_bits = 0; log_header(design, "Executing STUBNETS pass (find stub nets).\n"); // parse options size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { std::string arg = args[argidx]; if (arg == "-report_bits") { report_bits = true; continue; } break; } // handle extra options (e.g. selection) extra_args(args, argidx, design); // call find_stub_nets() for each module that is either // selected as a whole or contains selected objects. for (auto &it : design->modules_) if (design->selected_module(it.first)) find_stub_nets(design, it.second, report_bits); } } StubnetsPass; PRIVATE_NAMESPACE_END ef='#n24'>24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
/*
    ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
                 2011,2012 Giovanni Di Sirio.

    This file is part of ChibiOS/RT.

    ChibiOS/RT is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    ChibiOS/RT is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/**
 * @file    chlists.c
 * @brief   Thread queues/lists code.
 *
 * @addtogroup internals
 * @details All the functions present in this module, while public, are not
 *          OS APIs and should not be directly used in the user applications
 *          code.
 * @{
 */
#include "ch.h"

#if !CH_OPTIMIZE_SPEED || defined(__DOXYGEN__)
/**
 * @brief   Inserts a thread into a priority ordered queue.
 * @note    The insertion is done by scanning the list from the highest
 *          priority toward the lowest.
 *
 * @param[in] tp        the pointer to the thread to be inserted in the list
 * @param[in] tqp       the pointer to the threads list header
 *
 * @notapi
 */
void prio_insert(Thread *tp, ThreadsQueue *tqp) {

  /* cp iterates over the queue.*/
  Thread *cp = (Thread *)tqp;
  do {
    /* Iterate to next thread in queue.*/
    cp = cp->p_next;
    /* Not end of queue? and cp has equal or higher priority than tp?.*/
  } while ((cp != (Thread *)tqp) && (cp->p_prio >= tp->p_prio));
  /* Insertion on p_prev.*/
  tp->p_next = cp;
  tp->p_prev = cp->p_prev;
  tp->p_prev->p_next = cp->p_prev = tp;
}

/**
 * @brief   Inserts a Thread into a queue.
 *
 * @param[in] tp        the pointer to the thread to be inserted in the list
 * @param[in] tqp       the pointer to the threads list header
 *
 * @notapi
 */
void queue_insert(Thread *tp, ThreadsQueue *tqp) {

  tp->p_next = (Thread *)tqp;
  tp->p_prev = tqp->p_prev;
  tp->p_prev->p_next = tqp->p_prev = tp;
}

/**
 * @brief   Removes the first-out Thread from a queue and returns it.
 * @note    If the queue is priority ordered then this function returns the
 *          thread with the highest priority.
 *
 * @param[in] tqp       the pointer to the threads list header
 * @return              The removed thread pointer.
 *
 * @notapi
 */
Thread *fifo_remove(ThreadsQueue *tqp) {
  Thread *tp = tqp->p_next;

  (tqp->p_next = tp->p_next)->p_prev = (Thread *)tqp;
  return tp;
}

/**
 * @brief   Removes the last-out Thread from a queue and returns it.
 * @note    If the queue is priority ordered then this function returns the
 *          thread with the lowest priority.
 *
 * @param[in] tqp   the pointer to the threads list header
 * @return          The removed thread pointer.
 *
 * @notapi
 */
Thread *lifo_remove(ThreadsQueue *tqp) {
  Thread *tp = tqp->p_prev;

  (tqp->p_prev = tp->p_prev)->p_next = (Thread *)tqp;
  return tp;
}

/**
 * @brief   Removes a Thread from a queue and returns it.
 * @details The thread is removed from the queue regardless of its relative
 *          position and regardless the used insertion method.
 *
 * @param[in] tp        the pointer to the thread to be removed from the queue
 * @return              The removed thread pointer.
 *
 * @notapi
 */
Thread *dequeue(Thread *tp) {

  tp->p_prev->p_next = tp->p_next;
  tp->p_next->p_prev = tp->p_prev;
  return tp;
}

/**
 * @brief   Pushes a Thread on top of a stack list.
 *
 * @param[in] tp    the pointer to the thread to be inserted in the list
 * @param[in] tlp   the pointer to the threads list header
 *
 * @notapi
 */
void list_insert(Thread *tp, ThreadsList *tlp) {

  tp->p_next = tlp->p_next;
  tlp->p_next = tp;
}

/**
 * @brief   Pops a Thread from the top of a stack list and returns it.
 * @pre     The list must be non-empty before calling this function.
 *
 * @param[in] tlp       the pointer to the threads list header
 * @return              The removed thread pointer.
 *
 * @notapi
 */
Thread *list_remove(ThreadsList *tlp) {

  Thread *tp = tlp->p_next;
  tlp->p_next = tp->p_next;
  return tp;
}
#endif /* CH_OPTIMIZE_SPEED */

/** @} */