Skip to content

Fix multiplex sig pack #32

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
74 changes: 67 additions & 7 deletions src/codegen/c-main-generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,7 @@ void CiMainGenerator::PrintPackCommonText(const std::string& arrtxt, const CiExp
{
// this function will print body of packing function

// pring array content clearin loop
// print array content clearing loop
fwriter.Append(" uint8_t i; for (i = 0u; i < %s(%s_DLC); %s[i++] = %s);",
prt_dlcValidateMacroName.c_str(),
sgs->msg.Name.c_str(), arrtxt.c_str(),
Expand Down Expand Up @@ -842,14 +842,75 @@ void CiMainGenerator::PrintPackCommonText(const std::string& arrtxt, const CiExp
fwriter.Append();
}

for (size_t i = 0; i < sgs->to_bytes.size(); i++)
// Find the master multiplex signal (if any)
const SignalDescriptor_t* masterSignal = nullptr;
for (const auto& sig : sgs->msg.Signals)
{
if (sgs->to_bytes[i].size() < 2)
if (sig.Multiplex == MultiplexType::kMaster)
{
continue;
masterSignal = &sig;
break;
}
}

// Generate packing code for each byte in the CAN message
for (size_t i = 0; i < sgs->to_bytes.size(); i++)
{

fwriter.Append(" %s[%d] |= (uint8_t) ( %s );", arrtxt.c_str(), i, sgs->to_bytes[i].c_str());
if (masterSignal)
{
bool first = true;
// Handle the case where only a master multiplexor signal exists and there are no other kMulValue signal types in the CAN msg.
// There may or may not be other normal signals in the CAN msg.
if (sgs->mux_values.size() == 0)
{
// Filter out any empty bytes in the CAN msg.
if ( !sgs->to_bytes[i].empty() )
{
fwriter.Append(" %s[%d] |= (uint8_t) ( %s );", arrtxt.c_str(), i, sgs->to_bytes[i].c_str());
}
}
else
{
// handle the case where there is a mux master and kMulValue (and other normal signals) in the CAN msg.
for (size_t mux_idx = 0; mux_idx < sgs->mux_values.size(); ++mux_idx)
{
int mux_val = sgs->mux_values[mux_idx];
if (sgs->to_bytes_mux[i].size() > mux_idx && !sgs->to_bytes_mux[i][mux_idx].empty())
{
if (first)
{
fwriter.Append(" if (_m->%s == %d) {", masterSignal->Name.c_str(), mux_val);
first = false;
}
else
{
fwriter.Append(" else if (_m->%s == %d) {", masterSignal->Name.c_str(), mux_val);
}
fwriter.Append(" %s[%d] |= (uint8_t) ( %s );", arrtxt.c_str(), i, sgs->to_bytes_mux[i][mux_idx].c_str());
fwriter.Append(" }");
}
}
// Add the final else block for the case where no expected multiplex value matches. Just encode all signals in the byte.
if (!first)
{
fwriter.Append(" else {");
if ( !sgs->to_bytes[i].empty() )
{
fwriter.Append(" %s[%d] |= (uint8_t) ( %s );", arrtxt.c_str(), i, sgs->to_bytes[i].c_str());
}
fwriter.Append(" }");
}
}
}
else
{
// Handle for when there is no master multiplexor signal. Just pack the signal values from all signals making up this byte.
if ( !sgs->to_bytes[i].empty() )
{
fwriter.Append(" %s[%d] |= (uint8_t) ( %s );", arrtxt.c_str(), i, sgs->to_bytes[i].c_str());
}
}
}

fwriter.Append("");
Expand All @@ -868,5 +929,4 @@ void CiMainGenerator::PrintPackCommonText(const std::string& arrtxt, const CiExp
fwriter.Append("#endif // %s", fdesc->gen.usecsm_def.c_str());
fwriter.Append();
}
}

}
123 changes: 111 additions & 12 deletions src/codegen/c-sigprinter.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <stdlib.h>
#include <memory>
#include <algorithm> // For std::find
#include "c-sigprinter.h"
#include "helpers/formatter.h"
#include "conf-and-limits.h"
Expand Down Expand Up @@ -42,6 +43,9 @@ void CSigPrinter::LoadMessage(const MessageDescriptor_t& message)

nexpr->msg = message;

// Find the multiplexor master signal in the message
FindMultiplexorValues(message, nexpr->mux_values);

// do for this new expr to_byte and to_field expression building,
// add them to dedicated members, set signal stdint type
// and push it to vector
Expand Down Expand Up @@ -130,7 +134,14 @@ int32_t CSigPrinter::BuildCConvertExprs(CiExpr_t* msgprinter)

msgprinter->to_bytes.clear();
msgprinter->to_signals.clear();
msgprinter->to_bytes_mux.clear();
msgprinter->to_bytes.resize(msgprinter->msg.DLC);
// Resize the to_bytes_mux vector to the number of bytes in the message for the first dimension
// and the number of multiplexor values msgprinter->mux_values.size() for the second dimension.
for (size_t i = 0; i < msgprinter->msg.DLC; i++)
{
msgprinter->to_bytes_mux.push_back(std::vector<std::string>(msgprinter->mux_values.size()));
}

// for each signal specific to_signal expression must be defined,
// and during all signals processing, for each byte to_byte expression
Expand All @@ -154,37 +165,50 @@ int32_t CSigPrinter::BuildCConvertExprs(CiExpr_t* msgprinter)
//
// bytes expression is saved to vector @to_bytes, where id is the
// byte number in frame payload (i.e. to_bytes.size() == frame.DLC)
msgprinter->to_signals.push_back(PrintSignalExpr(&msgprinter->msg.Signals[i], msgprinter->to_bytes));
msgprinter->to_signals.push_back(PrintSignalExpr(&msgprinter->msg.Signals[i], msgprinter->mux_values, msgprinter->to_bytes, msgprinter->to_bytes_mux));
}

if (msgprinter->msg.CsmSig != nullptr)
{
std::vector<std::string> v(8);
std::vector<std::vector<std::string>> v2(8);
// resize the v2 vector to the number of multiplex values
for (size_t i = 0; i < 8; i++)
{
v2[i].resize(msgprinter->mux_values.size());
}

PrintSignalExpr(msgprinter->msg.CsmSig, v);
PrintSignalExpr(msgprinter->msg.CsmSig, msgprinter->mux_values, v, v2);

for (uint8_t i = 0; i < v.size() && i < 8; i++)
{
if (v[i].size() > 0)
// As long as the checksum signal is not a multiplex signal.
if (msgprinter->msg.CsmSig->Multiplex != MultiplexType::kMulValue)
{
msgprinter->msg.CsmToByteExpr = v[i];
msgprinter->msg.CsmByteNum = i;
break;
if (v[i].size() > 0)
{
msgprinter->msg.CsmToByteExpr = v[i];
msgprinter->msg.CsmByteNum = i;
break;
}
} else {
printf("Error in DBC file !!!! Checksum signal cannot be a multiplexor signal.");
ret = -1;
}
}
}

return ret;
}

std::string CSigPrinter::PrintSignalExpr(const SignalDescriptor_t* sig, std::vector<std::string>& to_bytes)
std::string CSigPrinter::PrintSignalExpr(const SignalDescriptor_t* sig, const std::vector<int> mux_values, std::vector<std::string>& to_bytes, std::vector<std::vector<std::string>>& to_bytes_mux)
{
// value for collecting expression (to_signal)
std::string tosigexpr;

if (to_bytes.size() == 0)
{
// return empty line is bytes count somehow equals 0
// return empty line if bytes count somehow equals 0
return "Error in DBC file !!!! Dlc of this message must be greater.";
}

Expand All @@ -206,9 +230,20 @@ std::string CSigPrinter::PrintSignalExpr(const SignalDescriptor_t* sig, std::vec
return to_bytes[0];
}

// Find the multiplexor index if the signal is multiplexed
int mux_ind = -1;
if (sig->Multiplex == MultiplexType::kMulValue)
{
auto it = std::find(mux_values.begin(), mux_values.end(), sig->MultiplexValue);
if (it != mux_values.end())
{
mux_ind = std::distance(mux_values.begin(), it);
}
}

// set valid to_byte prefix
int32_t bbc = (startb % 8) + 1;
int32_t slen = sig->LengthBit;
int32_t bbc = (startb % 8) + 1; // Byte bit
int32_t slen = sig->LengthBit; // Signal length in bits

if (bbc > slen)
{
Expand All @@ -217,6 +252,8 @@ std::string CSigPrinter::PrintSignalExpr(const SignalDescriptor_t* sig, std::vec

snprintf(workbuff, WBUFF_LEN, "((_m->%s & (%s)) << %dU)", sig->Name.c_str(), msk[slen].c_str(), bbc - slen);
AppendToByteLine(to_bytes[bn], workbuff);

AppendToAllMuxValues(to_bytes_mux[bn], mux_ind, workbuff);
}
else if (bbc == slen)
{
Expand All @@ -226,6 +263,8 @@ std::string CSigPrinter::PrintSignalExpr(const SignalDescriptor_t* sig, std::vec

snprintf(workbuff, WBUFF_LEN, "(_m->%s & (%s))", sig->Name.c_str(), msk[slen].c_str());
AppendToByteLine(to_bytes[bn], workbuff);

AppendToAllMuxValues(to_bytes_mux[bn], mux_ind, workbuff);
}
else
{
Expand All @@ -243,6 +282,8 @@ std::string CSigPrinter::PrintSignalExpr(const SignalDescriptor_t* sig, std::vec
snprintf(workbuff, WBUFF_LEN, "((_m->%s >> %dU) & (%s))", sig->Name.c_str(), slen, msk[bbc].c_str());
AppendToByteLine(to_bytes[bn], workbuff);

AppendToAllMuxValues(to_bytes_mux[bn], mux_ind, workbuff);

while ((slen - 8) >= 0)
{
t64.clear();
Expand Down Expand Up @@ -270,6 +311,7 @@ std::string CSigPrinter::PrintSignalExpr(const SignalDescriptor_t* sig, std::vec
snprintf(workbuff, WBUFF_LEN, "(_m->%s & (%s))", sig->Name.c_str(), msk[8].c_str());
AppendToByteLine(to_bytes[bn], workbuff);

AppendToAllMuxValues(to_bytes_mux[bn], mux_ind, workbuff);
}
else
{
Expand All @@ -283,6 +325,8 @@ std::string CSigPrinter::PrintSignalExpr(const SignalDescriptor_t* sig, std::vec

snprintf(workbuff, WBUFF_LEN, "((_m->%s >> %dU) & (%s))", sig->Name.c_str(), slen, msk[8].c_str());
AppendToByteLine(to_bytes[bn], workbuff);

AppendToAllMuxValues(to_bytes_mux[bn], mux_ind, workbuff);
}
}

Expand All @@ -293,15 +337,32 @@ std::string CSigPrinter::PrintSignalExpr(const SignalDescriptor_t* sig, std::vec
snprintf(workbuff, WBUFF_LEN, " | ((_d[%d] >> %dU) & (%s))", bn, 8 - slen, msk[slen].c_str());
tosigexpr += workbuff;

snprintf(workbuff, WBUFF_LEN, "((_m->%s & (%s)) << %dU)", sig->Name.c_str(), msk[slen].c_str(),
8 - slen);
snprintf(workbuff, WBUFF_LEN, "((_m->%s & (%s)) << %dU)", sig->Name.c_str(), msk[slen].c_str(), 8 - slen);
AppendToByteLine(to_bytes[bn], workbuff);

AppendToAllMuxValues(to_bytes_mux[bn], mux_ind, workbuff);
}
}

return tosigexpr;
}

void CSigPrinter::AppendToAllMuxValues(std::vector<std::string>& to_bytes_mux, int mux_ind, const std::string& workbuff)
{
if (mux_ind >= 0)
{
AppendToByteLine(to_bytes_mux[mux_ind], workbuff);
}
else
{
// Append to all multiplexor values if the signal is not multiplexed
for (size_t i = 0; i < to_bytes_mux.size(); ++i)
{
AppendToByteLine(to_bytes_mux[i], workbuff);
}
}
}

void CSigPrinter::AppendToByteLine(std::string& expr, std::string str)
{
if (expr.size() > 0)
Expand All @@ -315,3 +376,41 @@ void CSigPrinter::AppendToByteLine(std::string& expr, std::string str)
expr = str;
}
}

void CSigPrinter::FindMultiplexorValues(const MessageDescriptor_t& message, std::vector<int>& mux_values)
{
// Clear the vectors to ensure they are empty before filling them
mux_values.clear();

// First, find the master multiplexor signal
SignalDescriptor_t* master_signal = nullptr;
for (const auto& signal : message.Signals)
{
if (signal.Multiplex == MultiplexType::kMaster)
{
master_signal = const_cast<SignalDescriptor_t*>(&signal);
break;
}
}

// If there's no master multiplexor signal, return
if (!master_signal)
{
return;
}

// Now find all multiplex values
for (const auto& signal : message.Signals)
{
if (signal.Multiplex == MultiplexType::kMulValue)
{
// Extract and add to the list of total possible multiplex values for the CAN message.
int mux_value = signal.MultiplexValue; // Extract the multiplexor value this signal corresponds to
// If the multiplexor value is not already in the list, add it
if (std::find(mux_values.begin(), mux_values.end(), mux_value) == mux_values.end())
{
mux_values.push_back(mux_value);
}
}
}
}
5 changes: 4 additions & 1 deletion src/codegen/c-sigprinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@ class CSigPrinter {
private:
int32_t BuildCConvertExprs(CiExpr_t* msg);

std::string PrintSignalExpr(const SignalDescriptor_t* sig, std::vector<std::string>& to_bytes);
std::string PrintSignalExpr(const SignalDescriptor_t* sig, const std::vector<int> mux_values, std::vector<std::string>& to_bytes, std::vector<std::vector<std::string>>& to_bytes_mux);

void AppendToAllMuxValues(std::vector<std::string>& to_bytes_mux, int mux_ind, const std::string& workbuff);

void AppendToByteLine(std::string& expr, std::string str);

void FindMultiplexorValues(const MessageDescriptor_t& message, std::vector<int>& mux_values);
};
3 changes: 3 additions & 0 deletions src/parser/dbclineparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,9 @@ bool DbcLineParser::ParseSignalLine(SignalDescriptor_t* sig, const std::string&
else
{
sig->Multiplex = MultiplexType::kMulValue;
// Multiplex value e.g m0, m1, m2...
// Convert to integer
sig->MultiplexValue = atoi(halfs[2].c_str() + 1);
}
}
}
Expand Down
15 changes: 15 additions & 0 deletions src/types/c-expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,19 @@ typedef struct
// frame fields to data bytes
std::vector<std::string> to_bytes;

// another field containing expressions for converting
// frame fields to data bytes, but includes a different expression
// for each potential multiplexor value.
// i.e if the master multiplexor signal is 0, the first expression
// should be used, if it is 1, the second expression is used, etc.
// First dimension is the byte index, second dimension is the multiplexor value.
std::vector<std::vector<std::string>> to_bytes_mux;
// Store the corresponding multiplexor values for each expression
// since multiplexor values are not necessarily contiguous, we need
// to store the values explicitly. This vector should have the same
// size as the second dim of the to_bytes_mux and each element corresponds to the multiplexor
// value for the corresponding expression in to_bytes_mux.
// i.e to_bytes_mux[0 to 7].size() == mux_values.size()
std::vector<int> mux_values;

} CiExpr_t;
2 changes: 2 additions & 0 deletions src/types/message.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ typedef struct

MultiplexType Multiplex;

uint32_t MultiplexValue;

} SignalDescriptor_t;

typedef struct
Expand Down
Loading