Allow specifying multiple DSP ports in one "port" statement, formatted code. Signed-off-by: Maciej Kurc <mkurc@antmicro.com>
diff --git a/dsp-ff-plugin/dsp_ff.cc b/dsp-ff-plugin/dsp_ff.cc index 09c7e41..8504388 100644 --- a/dsp-ff-plugin/dsp_ff.cc +++ b/dsp-ff-plugin/dsp_ff.cc
@@ -90,7 +90,8 @@ /// integration. dict<RTLIL::IdString, RTLIL::Const> connect; - unsigned int hash() const { + unsigned int hash() const + { unsigned int h = 0; h = mkhash_add(h, params.set.hash()); h = mkhash_add(h, params.map.hash()); @@ -98,10 +99,9 @@ return h; } - bool operator == (const RegisterType& ref) const { - return (params.set == ref.params.set) && - (params.map == ref.params.map) && - (connect == ref.connect); + bool operator==(const RegisterType &ref) const + { + return (params.set == ref.params.set) && (params.map == ref.params.map) && (connect == ref.connect); } }; @@ -221,13 +221,14 @@ // Parse each port as if it was associated with its own DSP register. // Group them each time a port definition is complete. - PortType portType; - RegisterType registerType; + PortType portType; + RegisterType registerType; - std::vector<DspType> dspTypes; + std::vector<DspType> dspTypes; std::vector<FlopType> flopTypes; std::vector<RTLIL::IdString> dspAliases; + std::vector<std::string> portNames; std::vector<std::string> tok; @@ -289,7 +290,7 @@ // DSP port section else if (fields[0] == "port") { - if (fields.size() != 2) { + if (fields.size() < 2) { log_error(" syntax error: '%s'\n", line.c_str()); } if (tok.size() != 1 || tok.back() != "dsp") { @@ -308,6 +309,11 @@ registerType = RegisterType(); + portNames.clear(); + for (size_t i = 2; i < fields.size(); ++i) { + portNames.push_back(fields[i]); + } + } else if (fields[0] == "endport") { if (fields.size() != 1) { log_error(" syntax error: '%s'\n", line.c_str()); @@ -317,8 +323,20 @@ } tok.pop_back(); - auto& dspType = dspTypes.back(); + // Store the DSP port + auto &dspType = dspTypes.back(); dspType.registers[registerType].push_back(portType); + + // Store any extra DSP ports belonging to the same register + for (const auto &name : portNames) { + auto spec = parsePortName(name); + + PortType portTypeCopy = portType; + portTypeCopy.name = RTLIL::escape_id(std::get<0>(spec)); + portTypeCopy.bits = std::make_pair(std::get<2>(spec), std::get<1>(spec)); + + dspType.registers[registerType].push_back(portTypeCopy); + } } // Flip-flop type section @@ -535,9 +553,9 @@ const auto &dsp = it1.second; log(" %s\n", dsp.name.c_str()); - for (const auto& it2 : dsp.registers) { - const auto& reg = it2.first; - const auto& ports = it2.second; + for (const auto &it2 : dsp.registers) { + const auto ® = it2.first; + const auto &ports = it2.second; log(" ports:\n"); for (const auto &port : ports) { @@ -648,7 +666,7 @@ log(" # This is a comment\n"); log("\n"); log(" dsp <dsp_type> [<dsp_type> ...]\n"); - log(" port <dsp_port>\n"); + log(" port <dsp_port> [<dsp_port> ...]\n"); log(" clk <associated clk> <default>\n"); log(" [rst <associated reset>] <default>\n"); log(" [ena <associated enable>] <default>\n"); @@ -675,6 +693,7 @@ log("\n"); log("Each 'dsp' section defines a DSP cell type (can apply to multiple types).\n"); log("Within it each 'port' section defining a data port with internal register.\n"); + log("There can be multiple port names given if they belong to the same control register.\n"); log("The port can be specified as a whole (eg. 'DATA') or as a subset of the whole\n"); log("(eg. 'DATA[7:0]').\n"); log("\n"); @@ -759,7 +778,7 @@ // Process all registers auto &dspType = m_DspTypes.at(cell->type); - for (auto& rule : dspType.registers) { + for (auto &rule : dspType.registers) { processRegister(cell, rule.first, rule.second); } } @@ -812,9 +831,8 @@ return isOk; } - bool checkFlopDataAgainstDspRegister(const FlopData &a_FlopData, RTLIL::Cell *a_Cell, - const RegisterType &a_Register, - const std::vector<PortType>& a_Ports) + bool checkFlopDataAgainstDspRegister(const FlopData &a_FlopData, RTLIL::Cell *a_Cell, const RegisterType &a_Register, + const std::vector<PortType> &a_Ports) { const auto &flopType = m_FlopTypes.at(a_FlopData.type); const auto &changes = m_DspChanges[a_Cell]; @@ -823,7 +841,7 @@ log_debug(" checking connected flip-flop settings against the DSP register... "); // Check control signal connections - for (const auto& port : a_Ports) { + for (const auto &port : a_Ports) { for (const auto &it : port.assoc) { const auto &key = it.first; const auto &port = it.second.first; @@ -926,8 +944,7 @@ // .......................................... - void processRegister(RTLIL::Cell *a_Cell, const RegisterType& a_Register, - const std::vector<PortType>& a_Ports) + void processRegister(RTLIL::Cell *a_Cell, const RegisterType &a_Register, const std::vector<PortType> &a_Ports) { // The cell register control parameter(s) must not be set @@ -940,21 +957,28 @@ } pool<FlopData> groups; - dict<RTLIL::IdString, std::vector<RTLIL::Cell*>> flops; + dict<RTLIL::IdString, std::vector<RTLIL::Cell *>> flops; // Process ports bool flopsOk = true; - for (const auto& port : a_Ports) { + for (const auto &port : a_Ports) { log_debug(" attempting flip-flop integration for %s.%s of %s\n", a_Cell->type.c_str(), port.name.c_str(), a_Cell->name.c_str()); + + if (!a_Cell->hasPort(port.name)) { + log_debug(" port unconnected.\n"); + continue; + } log_assert(a_Cell->output(port.name) || a_Cell->input(port.name)); // Get port connections auto sigspec = a_Cell->getPort(port.name); auto sigbits = sigspec.bits(); - flops[port.name] = std::vector<RTLIL::Cell*>(sigbits.size(), nullptr); + flops[port.name] = std::vector<RTLIL::Cell *>(sigbits.size(), nullptr); for (size_t i = 0; i < sigbits.size(); ++i) { auto sigbit = sigbits[i]; + + // Port connected to a const. if (!sigbit.wire) { continue; } @@ -999,7 +1023,7 @@ // Get the sink, check if this is a flip-flop auto &other = *others.begin(); - auto *flop = other.cell; + auto *flop = other.cell; if (flop == nullptr) { if (!other.port.empty()) { @@ -1078,15 +1102,19 @@ } // Debug log - for (const auto& port : a_Ports) { + for (const auto &port : a_Ports) { + + if (!flops.count(port.name)) { + continue; + } + log(" %s %s.%s\n", a_Cell->type.c_str(), a_Cell->name.c_str(), port.name.c_str()); - const auto& conns = flops.at(port.name); + const auto &conns = flops.at(port.name); for (size_t i = 0; i < conns.size(); ++i) { if (conns[i] != nullptr) { log_debug(" %2zu. %s %s\n", i, conns[i]->type.c_str(), conns[i]->name.c_str()); - } else if ((port.bits.first >= 0 && (int)i < port.bits.first) || - (port.bits.second >= 0 && (int)i > port.bits.second)) { + } else if ((port.bits.first >= 0 && (int)i < port.bits.first) || (port.bits.second >= 0 && (int)i > port.bits.second)) { log_debug(" %2zu. (excluded)\n", i); } else { log_debug(" %2zu. None\n", i); @@ -1096,9 +1124,13 @@ // Reconnect data signals, mark the flip-flop for removal const auto &flopType = m_FlopTypes.at(flopData.type); - for (const auto& port : a_Ports) { + for (const auto &port : a_Ports) { - const auto& conns = flops.at(port.name); + if (!flops.count(port.name)) { + continue; + } + + const auto &conns = flops.at(port.name); auto sigspec = a_Cell->getPort(port.name); auto sigbits = sigspec.bits(); @@ -1135,7 +1167,7 @@ // Reconnect (map) control signals. Connect the default value if // a particular signal is not present in the flip-flop. - for (const auto& port : a_Ports) { + for (const auto &port : a_Ports) { for (const auto &it : port.assoc) { const auto &key = it.first; const auto &port = it.second.first;