|  | #include "kernel/sigtools.h" | 
|  | #include "kernel/yosys.h" | 
|  |  | 
|  | USING_YOSYS_NAMESPACE | 
|  | PRIVATE_NAMESPACE_BEGIN | 
|  |  | 
|  | // ============================================================================ | 
|  |  | 
|  | const std::vector<std::string> ports2del_mult = {"feedback", "load_acc", "saturate_enable", "shift_right", "round", "subtract", "acc_fir", "dly_b"}; | 
|  | const std::vector<std::string> ports2del_mult_add_acc = {"saturate_enable", "shift_right", "round", "acc_fir", "dly_b"}; | 
|  |  | 
|  | void ql_dsp_io_regs_pass(RTLIL::Module *module) | 
|  | { | 
|  |  | 
|  | for (auto cell : module->cells_) { | 
|  | std::string cell_type = cell.second->type.str(); | 
|  | if (cell_type == RTLIL::escape_id("QL_DSP2")) { | 
|  | auto dsp = cell.second; | 
|  | bool del_clk = false; | 
|  |  | 
|  | // Get DSP configuration | 
|  | const RTLIL::SigSpec *register_inputs; | 
|  | register_inputs = &dsp->getPort(RTLIL::escape_id("register_inputs")); | 
|  | if (!register_inputs) | 
|  | log_error("register_inputs port not found!"); | 
|  | auto reg_in_c = register_inputs->as_const(); | 
|  | int reg_in_i = reg_in_c.as_int(); | 
|  |  | 
|  | const RTLIL::SigSpec *output_select; | 
|  | output_select = &dsp->getPort(RTLIL::escape_id("output_select")); | 
|  | if (!output_select) | 
|  | log_error("output_select port not found!"); | 
|  | auto out_sel_c = output_select->as_const(); | 
|  | int out_sel_i = out_sel_c.as_int(); | 
|  |  | 
|  | // Build new type name | 
|  | std::string new_type = cell_type; | 
|  | new_type += "_MULT"; | 
|  |  | 
|  | switch (out_sel_i) { | 
|  | case 1: | 
|  | new_type += "ACC"; | 
|  | break; | 
|  | case 2: | 
|  | case 3: | 
|  | new_type += "ADD"; | 
|  | break; | 
|  | case 5: | 
|  | new_type += "ACC"; | 
|  | break; | 
|  | case 6: | 
|  | case 7: | 
|  | new_type += "ADD"; | 
|  | break; | 
|  | default: | 
|  | break; | 
|  | } | 
|  |  | 
|  | if (reg_in_i) | 
|  | new_type += "_REGIN"; | 
|  |  | 
|  | if (out_sel_i > 3) | 
|  | new_type += "_REGOUT"; | 
|  |  | 
|  | // Set new type name | 
|  | dsp->type = RTLIL::IdString(new_type); | 
|  |  | 
|  | // Delete ports unused in given type of DSP cell | 
|  | del_clk = (!reg_in_i && out_sel_i <= 3 && out_sel_i != 1); | 
|  |  | 
|  | std::vector<std::string> ports2del; | 
|  |  | 
|  | if (del_clk) | 
|  | ports2del.push_back("clk"); | 
|  |  | 
|  | if (out_sel_i == 0 || out_sel_i == 4) { | 
|  | ports2del.insert(ports2del.end(), ports2del_mult.begin(), ports2del_mult.end()); | 
|  | } else { | 
|  | ports2del.insert(ports2del.end(), ports2del_mult_add_acc.begin(), ports2del_mult_add_acc.end()); | 
|  | } | 
|  |  | 
|  | for (auto portname : ports2del) { | 
|  | const RTLIL::SigSpec *port = &dsp->getPort(RTLIL::escape_id(portname)); | 
|  | if (!port) | 
|  | log_error("%s port not found!", portname.c_str()); | 
|  | dsp->connections_.erase(RTLIL::escape_id(portname)); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | struct QlDspIORegs : public Pass { | 
|  |  | 
|  | QlDspIORegs() : Pass("ql_dsp_io_regs", "Does something") {} | 
|  |  | 
|  | void help() override | 
|  | { | 
|  | log("\n"); | 
|  | log("    ql_dsp_io_regs [options] [selection]\n"); | 
|  | log("\n"); | 
|  | } | 
|  |  | 
|  | void execute(std::vector<std::string> a_Args, RTLIL::Design *a_Design) override | 
|  | { | 
|  | log_header(a_Design, "Executing QL_DSP_IO_REGS pass.\n"); | 
|  |  | 
|  | size_t argidx; | 
|  | for (argidx = 1; argidx < a_Args.size(); argidx++) { | 
|  | break; | 
|  | } | 
|  | extra_args(a_Args, argidx, a_Design); | 
|  |  | 
|  | for (auto module : a_Design->selected_modules()) { | 
|  | ql_dsp_io_regs_pass(module); | 
|  | } | 
|  | } | 
|  | } QlDspIORegs; | 
|  |  | 
|  | PRIVATE_NAMESPACE_END |