Skip to content

Commit

Permalink
GateControlList: Fixed #897: PeriodicGate durations vector was incorr…
Browse files Browse the repository at this point in the history
…ectly calculated.
  • Loading branch information
levy committed Oct 13, 2023
1 parent b5b5364 commit 881fbe6
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 84 deletions.
110 changes: 43 additions & 67 deletions src/inet/queueing/gate/GateControlList.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,96 +16,72 @@ void GateControlList::initialize(int stage)
{
if (stage == INITSTAGE_LOCAL) {
numGates = par("numGates");
offset = par("offset");
durations = check_and_cast<cValueArray *>(par("durations").objectValue());
gateStates = check_and_cast<cValueArray *>(par("gateStates").objectValue());

if (durations->size() != gateStates->size())
throw cRuntimeError("The length of durations is not equal to the length of gateStates");
parseGcl();
}
else if (stage == INITSTAGE_QUEUEING) {
for (int index = 0; index < numGates; ++index) {
std::string modulePath = "^.transmissionGate[" + std::to_string(index) + "]";
PeriodicGate *mod = check_and_cast<PeriodicGate *>(getModuleByPath(modulePath.c_str()));
cPar& offsetPar = mod->par("offset");
offsetPar.setDoubleValue(offset.dbl());
cPar& durationsPar = mod->par("durations");
durationsPar.copyIfShared();
durationsPar.setObjectValue(durations);
for (int i = 0; i < numGates; ++i) {
std::string modulePath = "^.transmissionGate[" + std::to_string(i) + "]";
PeriodicGate *periodicGate = check_and_cast<PeriodicGate *>(getModuleByPath(modulePath.c_str()));
periodicGate->par("initiallyOpen").setBoolValue(initiallyOpens[i]);
periodicGate->par("offset").setDoubleValue(offsets[i].dbl());
cPar& durationsParameter = periodicGate->par("durations");
durationsParameter.copyIfShared();
durationsParameter.setObjectValue(gateDurations[i]);
}
}
}

void GateControlList::handleMessage(cMessage *msg)
void GateControlList::parseGcl()
{
throw cRuntimeError("Do not handle cMessage");
}

void GateControlList::parseGcl() {
if (durations->size() != gateStates->size()) {
throw cRuntimeError("The length of durations is not equal to gateStates.");
}

initiallyOpens = parseGclLine(gateStates->get(0).stringValue());
for (int i = 0; i < numGates; ++i) {
gateDurations.emplace_back(new cValueArray());
offsets.push_back(0);
gateDurations.push_back(new cValueArray());
}

int numEntries = durations->size();
std::vector<bool> currentGateStates(numGates, true);
std::vector<bool> currentGateStates = initiallyOpens;
std::vector<double> currentDuration(numGates, 0);

for (int indexEntry = 0; indexEntry < numEntries; ++indexEntry) {
const char *curGateStates = gateStates->get(indexEntry).stringValue();
double duration = durations->get(indexEntry).doubleValueInUnit("s");

std::vector<bool> entry = retrieveGateStates(curGateStates, numGates);

for (int i = 0; i < numGates; ++i) {
if (entry.at(i) != currentGateStates.at(i)) {
gateDurations.at(i)->add(cValue(currentDuration[i], "s"));

currentGateStates[i] = !currentGateStates[i];
currentDuration[i] = 0;
for (int i = 0; i < gateStates->size(); ++i) {
double duration = durations->get(i).doubleValueInUnit("s");
std::vector<bool> entry = parseGclLine(gateStates->get(i).stringValue());
for (int j = 0; j < numGates; ++j) {
if (entry.at(j) != currentGateStates.at(j)) {
gateDurations.at(j)->add(cValue(currentDuration[j], "s"));
currentGateStates[j] = !currentGateStates[j];
currentDuration[j] = 0;
}

currentDuration[i] += duration;
currentDuration[j] += duration;
}

}

for (int i = 0; i < numGates; ++i) {
gateDurations.at(i)->add(cValue(currentDuration[i], "s"));

if (gateDurations.at(i)->size() % 2 != 0) {
gateDurations.at(i)->add(cValue(0.0, "s"));
auto durations = gateDurations.at(i);
if (durations->size() % 2 != 0)
durations->add(cValue(currentDuration[i], "s"));
else {
durations->set(i, cValue(durations->get(i).doubleValueInUnit("s") + currentDuration[i], "s"));
offsets[i] = currentDuration[i];
}
}

}

std::vector<bool> GateControlList::retrieveGateStates(const char *gateStates, uint numGates) {
std::vector<bool> res(numGates);

if (strlen(gateStates) != numGates) {
throw cRuntimeError("The length of the entry is not equal to numGates.");
}

for (size_t indexGate = 0; indexGate < numGates; ++indexGate) {
char ch = *(gateStates + indexGate);
if (ch == '1') {
res[numGates - indexGate - 1] = true;
} else if (ch == '0') {
res[numGates - indexGate - 1] = false;
} else {
throw cRuntimeError("Unknown char");
}
}
return res;
}

GateControlList::~GateControlList() {
std::vector<bool> GateControlList::parseGclLine(const char *gateStates)
{
std::vector<bool> result(numGates);
if (strlen(gateStates) != numGates)
throw cRuntimeError("The length of the entry is not equal to numGates");
for (int i = 0; i < numGates; ++i) {
delete gateDurations.at(i);
char ch = *(gateStates + i);
if (ch == '1')
result[numGates - i - 1] = true;
else if (ch == '0')
result[numGates - i - 1] = false;
else
throw cRuntimeError("Unknown char");
}
return result;
}

} // namespace queueing
Expand Down
19 changes: 6 additions & 13 deletions src/inet/queueing/gate/GateControlList.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,19 @@ namespace queueing {
class INET_API GateControlList : public cSimpleModule
{
protected:
int numGates;
clocktime_t offset;
int numGates = -1;
cValueArray *durations = nullptr;
cValueArray *gateStates = nullptr;
std::vector<bool> initiallyOpens;
std::vector<simtime_t> offsets;
std::vector<cValueArray *> gateDurations;

protected:
virtual int numInitStages() const override { return NUM_INIT_STAGES; }
virtual void initialize(int stage) override;
virtual void handleMessage(cMessage *msg) override;

private:
// ownership
std::vector<cValueArray *> gateDurations;

void parseGcl();
static std::vector<bool> retrieveGateStates(const char *gateStates, uint numGates);

public:
~GateControlList();

virtual void parseGcl();
virtual std::vector<bool> parseGclLine(const char *gateStates);
};

} // namespace queueing
Expand Down
7 changes: 3 additions & 4 deletions src/inet/queueing/gate/GateControlList.ned
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,14 @@
package inet.queueing.gate;

//
// This module configures PeriodicGate.
// This module configures multiple PeriodicGate modules according to a gate control list.
//
simple GateControlList
{
parameters:
int numGates = default(8);
double offset @mutable @unit(s) = default(0s);
object durations @mutable @unit(s) = default([]); // list of entry durations. E.g., [4ms, 2ms, 2ms, 2ms]
object gateStates @mutable = default([]); // list of gateStates. E.g., ["10000000", "01111111", "10000000", "01111111"]
object durations @mutable @unit(s) = default([]); // list of entry durations, e.g. [4ms, 2ms, 2ms, 2ms]
object gateStates @mutable = default([]); // list of gateStates, e.g. ["10000000", "01111111", "10000000", "01111111"]
@class(GateControlList);
@display("i=block/table");
}

3 comments on commit 881fbe6

@Frt0214
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi levy, When I set hasgcl to true, can I configure the offset parameter for the gcl entry? It appears that the offset parameter is invalid.

@levy
Copy link
Contributor Author

@levy levy commented on 881fbe6 Mar 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no offset parameter in the GateControlList module. The offset parameter of the individual PeriodicGate modules are set by the GateControlList module, so currently you can't directly set the offset parameter.

@Frt0214
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your reply! I have some misunderstanding of the value of offset. I saw in the time synchronization example that offset is used to absorb the time of the packet from the source node to the switch node, so I wonder if there are similar functions or parameters for GCL to perform such operations? Recently I was thinking about configuring GCL myself and discovered that packets don't arrive at the gate immediately, so GCL will work only after the propagation delay and the processing delay of the switching node.

timesync

Best Regards
Jack

Please sign in to comment.