Добавление ячейки в write_verilog вызывает ошибку

#yosys

#yosys

Вопрос:

прежде всего, я хотел бы сказать, что я вообще плохо разбираюсь в c или verilog, поэтому у меня есть несколько проблем с реализацией вещей в Yosys.

В настоящее время я ищу способ реализовать наивный подход к отслеживанию потока информации для write_verilog. Способ, которым я намереваюсь это реализовать, заключается в создании новой переменной для каждого ввода / вывода и т.д. Все типы операций будут заменены простыми «или«. Удвоенные переменные служат в качестве поврежденных битов. Удвоение всех проводов было простой задачей. Однако, когда я пытаюсь добавить новую ячейку, я сталкиваюсь с ошибкой ‘std:: out_of_range‘ (редактировать: так же, как я пробовал это снова, теперь это ошибка ‘Найдена ошибка во внутренней ячейке‘) при сбросе модуля. Поскольку ошибка возникает при вызове функции dump_module, я предполагаю, что модель модуля сломалась.

Что я сделал, так это то, что для каждого провода в модуле я добавил тот же провод, только с добавлением _taint к его имени, его свойства остаются такими же, как у исходного провода, я в основном использовал слегка измененную версию add_wire из /passes/add.cc .

 // adding taint wires

void attach_ift(RTLIL::Module *module, bool precise)
{

    auto wires = module->wires_;
    for (auto amp;wire : wires){
        std::string ift_wire_name = RTLIL::id2cstr(wire.second->name)   std::string("_taint");
        add_wire(module, ift_wire_name, 1, wire.second->port_input, wire.second->port_output);
    }

    //add cells and connections

}

static void add_wire(RTLIL::Module *module, std::string name, int width, bool flag_input, bool flag_output)
{
    RTLIL::Wire *wire = nullptr;
    name = RTLIL::escape_id(name);

    if (module->count_id(name) != 0)
    {
        wire = module->wire(name);

        if (wire != nullptr amp;amp; wire->width != width)
            wire = nullptr;

        if (wire != nullptr amp;amp; wire->port_input != flag_input)
            wire = nullptr;

        if (wire != nullptr amp;amp; wire->port_output != flag_output)
            wire = nullptr;

        if (wire == nullptr)
            log_cmd_error("Found incompatible object with same name in module %s!n", module->name.c_str());

        log("Module %s already has such an object.n", module->name.c_str());
    }
    else
    {
        wire = module->addWire(name, width);
        wire->port_input = flag_input;
        wire->port_output = flag_output;

        if (flag_input || flag_output) {
            module->fixup_ports();
        }

        log("Added wire %s to module %s.n", name.c_str(), module->name.c_str());
    }
}
  

Это работает нормально.

Теперь о проблеме с ячейками. Как мне правильно добавлять ячейки?
сначала я попытался использовать

 //add cells

void attach_ift(RTLIL::Module *module, bool precise)
{
    // add wires

    auto cells = module->cells_;
    for (auto amp;cell : cells){
        std::string ift_cell_name = cell.first.c_str()  std::string("_taint");
        auto cell_ = cell.second;
        add_cell(module, ift_cell_name, cell_);
    }

    // add connections
}

static void add_wire(RTLIL::Module *module, std::string name, int width, bool flag_input, bool flag_output)
{
    RTLIL::Wire *wire = nullptr;
    name = RTLIL::escape_id(name);

    if (module->count_id(name) != 0)
    {
        wire = module->wire(name);

        if (wire != nullptr amp;amp; wire->width != width)
            wire = nullptr;

        if (wire != nullptr amp;amp; wire->port_input != flag_input)
            wire = nullptr;

        if (wire != nullptr amp;amp; wire->port_output != flag_output)
            wire = nullptr;

        if (wire == nullptr)
            log_cmd_error("Found incompatible object with same name in module %s!n", module->name.c_str());

        log("Module %s already has such an object.n", module->name.c_str());
    }
    else
    {
        auto ift_cell = module->addCell(name, "$or");
        auto cons = cell->connections();
        for (auto con : cons){

            auto wire_ = cell->getPort(con.first).as_wire();
            auto taint_wire_name = string(wire_->name.c_str())   "_taint";
            auto wire = module->wire(taint_wire_name);
            ift_cell->setPort(taint_wire_name, wire);
        }

        log("Added cell %s to module %s.n", name.c_str(), module->name.c_str());
    }
}
  

Я подключаю функцию ift непосредственно перед сбросом модуля, так что на этом этапе

     void execute(std::ostream *amp;f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
    {

        // some code

        for (auto module : design->modules()) {

            //more code

            log("Attaching ift annotations to `%s'.n", module->name.c_str());
            attach_ift(module, precise);

            log("Dumping module `%s'.n", module->name.c_str());
            dump_module(*f, "", module);
        }

        auto_name_map.clear();
        reg_wires.clear();
    }

  

Тогда я подумал, что, возможно, мне не удалось установить правильные соединения.
Однако даже простое добавление простой module->addCell("$dummyName", "$or"); разбило мою программу.

Кто-нибудь, пожалуйста, может мне помочь?

Ответ №1:

Внутренние ячейки, начинающиеся с $, Имеют определенный контракт, которому они должны следовать с точки зрения портов, параметров и т. Д., И Который не будет выполняться пустой ячейкой. Для их создания используйте такие функции, как addOr, а не addCell.