Project

General

Profile

Statistics
| Branch: | Revision:

root / src / sim / parsim / cidealsimulationprot.cc @ 81ad8b66

History | View | Annotate | Download (5.25 KB)

1
//=========================================================================
2
//  CIDEALSIMULATIONPROT.CC - part of
3
//
4
//                  OMNeT++/OMNEST
5
//           Discrete System Simulation in C++
6
//
7
//  Author: Andras Varga, 2003
8
//          Dept. of Electrical and Computer Systems Engineering,
9
//          Monash University, Melbourne, Australia
10
//
11
//=========================================================================
12

    
13
/*--------------------------------------------------------------*
14
  Copyright (C) 2003-2008 Andras Varga
15
  Copyright (C) 2006-2008 OpenSim Ltd.
16

17
  This file is distributed WITHOUT ANY WARRANTY. See the file
18
  `license' for details on this and other legal matters.
19
*--------------------------------------------------------------*/
20

    
21

    
22
#include "cmessage.h"
23
#include "cmodule.h"
24
#include "cgate.h"
25
#include "cenvir.h"
26
#include "cconfiguration.h"
27
#include "cidealsimulationprot.h"
28
#include "cplaceholdermod.h"
29
#include "cparsimpartition.h"
30
#include "cparsimcomm.h"
31
#include "ccommbuffer.h"
32
#include "messagetags.h"
33
#include "globals.h"
34
#include "cconfigoption.h"
35
#include "regmacros.h"
36

    
37
USING_NAMESPACE
38

    
39

    
40
Register_Class(cIdealSimulationProtocol);
41

    
42
// load 100,000 values from eventlog at once (~800K allocated memory)
43
#define TABLESIZE   "100000"
44

    
45
Register_GlobalConfigOption(CFGID_PARSIM_IDEALSIMULATIONPROTOCOL_TABLESIZE, "parsim-idealsimulationprotocol-tablesize", CFG_INT, TABLESIZE, "When cIdealSimulationProtocol is selected as parsim synchronization class: specifies the memory buffer size for reading the ISP event trace file.");
46
extern cConfigOption *CFGID_PARSIM_DEBUG; // registered in cparsimpartition.cc
47

    
48

    
49
cIdealSimulationProtocol::cIdealSimulationProtocol() : cParsimProtocolBase()
50
{
51
    fin = NULL;
52
    debug = ev.getConfig()->getAsBool(CFGID_PARSIM_DEBUG);
53

    
54
    tableSize = ev.getConfig()->getAsInt(CFGID_PARSIM_IDEALSIMULATIONPROTOCOL_TABLESIZE);
55
    table = new ExternalEvent[tableSize];
56
    numItems = 0;
57
    nextPos = 0;
58
}
59

    
60
cIdealSimulationProtocol::~cIdealSimulationProtocol()
61
{
62
    delete [] table;
63
}
64

    
65
void cIdealSimulationProtocol::startRun()
66
{
67
    char fname[200];
68
    sprintf(fname, "ispeventlog-%d.dat", comm->getProcId());
69
    fin = fopen(fname,"rb");
70
    if (!fin)
71
        throw cRuntimeError("cIdealSimulationProtocol error: cannot open file `%s' for read", fname);
72

    
73
    readNextRecordedEvent();
74
}
75

    
76
void cIdealSimulationProtocol::endRun()
77
{
78
    fclose(fin);
79
}
80

    
81
void cIdealSimulationProtocol::processReceivedMessage(cMessage *msg, int destModuleId, int destGateId, int sourceProcId)
82
{
83
    msg->setSchedulingPriority(sourceProcId);
84
    cParsimProtocolBase::processReceivedMessage(msg, destModuleId, destGateId, sourceProcId);
85
}
86

    
87
cMessage *cIdealSimulationProtocol::getNextEvent()
88
{
89
    // if no more local events, wait for something to come from other partitions
90
    while (sim->msgQueue.isEmpty())
91
        if (!receiveBlocking())
92
            return NULL;
93

    
94
    cMessage *msg = sim->msgQueue.peekFirst();
95
    simtime_t msgTime = msg->getArrivalTime();
96

    
97
    // if we aren't at the next external even yet --> nothing special to do
98
    if (msgTime < nextExternalEvent.t)
99
    {
100
        ASSERT(msg->getSrcProcId()==-1); // must be local message
101
        return msg;
102
    }
103

    
104
    // if we reached the next external event in the log file, do it
105
    if (msg->getSrcProcId()==nextExternalEvent.srcProcId && msgTime==nextExternalEvent.t)
106
    {
107
        if (debug) ev << "expected external event (srcProcId=" << msg->getSrcProcId()
108
                      << " t=" << nextExternalEvent.t << ") has already arrived, good!\n";
109
        readNextRecordedEvent();
110
        msg->setSchedulingPriority(0);
111
        return msg;
112
    }
113

    
114
    // next external event not yet here, we have to wait until we've received it
115
    ASSERT(msgTime > nextExternalEvent.t);
116
    if (debug)
117
    {
118
        ev << "next local event at " << msgTime << " is PAST the next external event "
119
              "expected for t=" << nextExternalEvent.t << " -- waiting...\n";
120
    }
121

    
122
    do
123
    {
124
        if (!receiveBlocking())
125
            return NULL;
126
        msg = sim->msgQueue.peekFirst();
127
        msgTime = msg->getArrivalTime();
128
    }
129
    while (msg->getSrcProcId()!=nextExternalEvent.srcProcId || msgTime > nextExternalEvent.t);
130

    
131
    if (msgTime < nextExternalEvent.t)
132
    {
133
        throw cRuntimeError("cIdealSimulationProtocol: event trace does not match actual events: "
134
                            "expected event with timestamp %s from proc=%d, and got one with timestamp %s",
135
                            SIMTIME_STR(nextExternalEvent.t), nextExternalEvent.srcProcId, SIMTIME_STR(msgTime));
136
    }
137

    
138
    // we have the next external event we wanted, return it
139
    ASSERT(msgTime==nextExternalEvent.t);
140
    readNextRecordedEvent();
141
    msg->setSchedulingPriority(0);
142
    return msg;
143
}
144

    
145
void cIdealSimulationProtocol::readNextRecordedEvent()
146
{
147
    // if table is empty, load new values into it
148
    if (nextPos==numItems)
149
    {
150
        nextPos = 0;
151
        numItems = fread(table, sizeof(ExternalEvent), tableSize, fin);
152
        if (numItems==0)
153
            throw cTerminationException("cIdealSimulationProtocol: end of event trace file");
154
    }
155

    
156
    // get next entry from table
157
    nextExternalEvent = table[nextPos++];
158

    
159
    if (debug) ev << "next expected external event: srcProcId=" << nextExternalEvent.srcProcId
160
                  << " t=" << nextExternalEvent.t << "\n";
161
}
162