cpu: Move traffic generator sending out of generator states
authorAndreas Hansson <andreas.hansson@arm.com>
Thu, 30 May 2013 16:54:04 +0000 (12:54 -0400)
committerAndreas Hansson <andreas.hansson@arm.com>
Thu, 30 May 2013 16:54:04 +0000 (12:54 -0400)
This patch moves the responsibility for sending packets out of the
generator states and leaves it with the top-level traffic
generator. The main aim of this patch is to enable a transition to
non-queued ports, i.e. with send/retry flow control, and to do so it
is much more convenient to not wrap the port interactions and instead
leave it all local to the traffic generator.

The generator states now only govern when they are ready to send
something new, and the generation of the packets to send. They thus
have no knowledge of the port that is used.

src/cpu/testers/traffic_gen/generators.cc
src/cpu/testers/traffic_gen/generators.hh
src/cpu/testers/traffic_gen/traffic_gen.cc
src/cpu/testers/traffic_gen/traffic_gen.hh

index 22fffc9c3698f63bcb9f3477c5024892bbfb5597..4d1812cd4f958f2e8d3c961f4dbf20e58fd1ff58 100644 (file)
  */
 
 #include "base/random.hh"
+#include "base/trace.hh"
 #include "cpu/testers/traffic_gen/generators.hh"
 #include "debug/TrafficGen.hh"
 #include "proto/packet.pb.h"
 
-BaseGen::BaseGen(QueuedMasterPort& _port, MasterID master_id, Tick _duration)
-    : port(_port), masterID(master_id), duration(_duration)
+BaseGen::BaseGen(const std::string& _name, MasterID master_id, Tick _duration)
+    : _name(_name), masterID(master_id), duration(_duration)
 {
 }
 
-void
-BaseGen::send(Addr addr, unsigned size, const MemCmd& cmd,
-              Request::FlagsType flags)
+PacketPtr
+BaseGen::getPacket(Addr addr, unsigned size, const MemCmd& cmd,
+                   Request::FlagsType flags)
 {
     // Create new request
     Request *req = new Request(addr, size, flags, masterID);
@@ -66,7 +67,7 @@ BaseGen::send(Addr addr, unsigned size, const MemCmd& cmd,
         memset(pkt_data, 0xA, req->getSize());
     }
 
-    port.schedTimingReq(pkt, curTick());
+    return pkt;
 }
 
 void
@@ -75,16 +76,10 @@ LinearGen::enter()
     // reset the address and the data counter
     nextAddr = startAddr;
     dataManipulated = 0;
-
-    // this test only needs to happen once, but cannot be performed
-    // before init() is called and the ports are connected
-    if (port.deviceBlockSize() && blocksize > port.deviceBlockSize())
-        fatal("TrafficGen %s block size (%d) is larger than port"
-              " block size (%d)\n", blocksize, port.deviceBlockSize());
 }
 
-void
-LinearGen::execute()
+PacketPtr
+LinearGen::getNextPacket()
 {
     // choose if we generate a read or a write here
     bool isRead = readPercent != 0 &&
@@ -93,20 +88,23 @@ LinearGen::execute()
     assert((readPercent == 0 && !isRead) || (readPercent == 100 && isRead) ||
            readPercent != 100);
 
-    DPRINTF(TrafficGen, "LinearGen::execute: %c to addr %x, size %d\n",
+    DPRINTF(TrafficGen, "LinearGen::getNextPacket: %c to addr %x, size %d\n",
             isRead ? 'r' : 'w', nextAddr, blocksize);
 
-    send(nextAddr, blocksize, isRead ? MemCmd::ReadReq : MemCmd::WriteReq);
+    // Add the amount of data manipulated to the total
+    dataManipulated += blocksize;
+
+    PacketPtr pkt = getPacket(nextAddr, blocksize,
+                              isRead ? MemCmd::ReadReq : MemCmd::WriteReq);
 
     // increment the address
     nextAddr += blocksize;
 
-    // Add the amount of data manipulated to the total
-    dataManipulated += blocksize;
+    return pkt;
 }
 
 Tick
-LinearGen::nextExecuteTick()
+LinearGen::nextPacketTick()
 {
     // If we have reached the end of the address space, reset the
     // address to the start of the range
@@ -134,16 +132,10 @@ RandomGen::enter()
 {
     // reset the counter to zero
     dataManipulated = 0;
-
-    // this test only needs to happen once, but cannot be performed
-    // before init() is called and the ports are connected
-    if (port.deviceBlockSize() && blocksize > port.deviceBlockSize())
-        fatal("TrafficGen %s block size (%d) is larger than port"
-              " block size (%d)\n", blocksize, port.deviceBlockSize());
 }
 
-void
-RandomGen::execute()
+PacketPtr
+RandomGen::getNextPacket()
 {
     // choose if we generate a read or a write here
     bool isRead = readPercent != 0 &&
@@ -158,18 +150,19 @@ RandomGen::execute()
     // round down to start address of block
     addr -= addr % blocksize;
 
-    DPRINTF(TrafficGen, "RandomGen::execute: %c to addr %x, size %d\n",
+    DPRINTF(TrafficGen, "RandomGen::getNextPacket: %c to addr %x, size %d\n",
             isRead ? 'r' : 'w', addr, blocksize);
 
-    // send a new request packet
-    send(addr, blocksize, isRead ? MemCmd::ReadReq : MemCmd::WriteReq);
-
-    // Add the amount of data manipulated to the total
+    // add the amount of data manipulated to the total
     dataManipulated += blocksize;
+
+    // create a new request packet
+    return getPacket(addr, blocksize,
+                     isRead ? MemCmd::ReadReq : MemCmd::WriteReq);
 }
 
 Tick
-RandomGen::nextExecuteTick()
+RandomGen::nextPacketTick()
 {
     // Check to see if we have reached the data limit. If dataLimit is
     // zero we do not have a data limit and therefore we will keep
@@ -224,7 +217,7 @@ TraceGen::InputStream::read(TraceElement& element)
 }
 
 Tick
-TraceGen::nextExecuteTick() {
+TraceGen::nextPacketTick() {
     if (traceComplete)
         // We are at the end of the file, thus we have no more data in
         // the trace Return MaxTick to signal that there will be no
@@ -274,22 +267,22 @@ TraceGen::enter()
     traceComplete = false;
 }
 
-void
-TraceGen::execute()
+PacketPtr
+TraceGen::getNextPacket()
 {
-    // it is the responsibility of nextExecuteTick to prevent the
+    // it is the responsibility of nextPacketTick to prevent the
     // state graph from executing the state if it should not
     assert(currElement.isValid());
 
-    DPRINTF(TrafficGen, "TraceGen::execute: %c %d %d %d 0x%x\n",
+    DPRINTF(TrafficGen, "TraceGen::getNextPacket: %c %d %d %d 0x%x\n",
             currElement.cmd.isRead() ? 'r' : 'w',
             currElement.addr,
             currElement.blocksize,
             currElement.tick,
             currElement.flags);
 
-    send(currElement.addr + addrOffset, currElement.blocksize,
-         currElement.cmd, currElement.flags);
+    return getPacket(currElement.addr + addrOffset, currElement.blocksize,
+                     currElement.cmd, currElement.flags);
 }
 
 void
index b6c70037ac13c27cdc701185d274ee2dbbb328f5..5bcfc8e808ad160eac2346a30d8b0dcb04635695 100644 (file)
@@ -49,7 +49,7 @@
 #ifndef __CPU_TRAFFIC_GEN_GENERATORS_HH__
 #define __CPU_TRAFFIC_GEN_GENERATORS_HH__
 
-#include "mem/qport.hh"
+#include "mem/packet.hh"
 #include "proto/protoio.hh"
 
 /**
@@ -62,23 +62,22 @@ class BaseGen
 
   protected:
 
-    /** Port used to send requests */
-    QueuedMasterPort& port;
+    /** Name to use for status and debug printing */
+    const std::string _name;
 
     /** The MasterID used for generating requests */
     const MasterID masterID;
 
     /**
-     * Create a new request and associated packet and schedule
-     * it to be sent in the current tick.
+     * Generate a new request and associated packet
      *
      * @param addr Physical address to use
      * @param size Size of the request
      * @param cmd Memory command to send
      * @param flags Optional request flags
      */
-    void send(Addr addr, unsigned size, const MemCmd& cmd,
-              Request::FlagsType flags = 0);
+    PacketPtr getPacket(Addr addr, unsigned size, const MemCmd& cmd,
+                        Request::FlagsType flags = 0);
 
   public:
 
@@ -88,21 +87,20 @@ class BaseGen
     /**
      * Create a base generator.
      *
-     * @param _port port used to send requests
+     * @param _name Name to use for status and debug
      * @param master_id MasterID set on each request
      * @param _duration duration of this state before transitioning
      */
-    BaseGen(QueuedMasterPort& _port, MasterID master_id,
-            Tick _duration);
+    BaseGen(const std::string& _name, MasterID master_id, Tick _duration);
 
     virtual ~BaseGen() { }
 
     /**
      * Get the name, useful for DPRINTFs.
      *
-     * @return the port name
+     * @return the given name
      */
-    std::string name() const { return port.name(); }
+    std::string name() const { return _name; }
 
     /**
      * Enter this generator state.
@@ -110,9 +108,11 @@ class BaseGen
     virtual void enter() = 0;
 
     /**
-     * Execute this generator state.
+     * Get the next generated packet.
+     *
+     * @return A packet to be sent at the current tick
      */
-    virtual void execute() = 0;
+    virtual PacketPtr getNextPacket() = 0;
 
     /**
      * Exit this generator state. By default do nothing.
@@ -120,13 +120,13 @@ class BaseGen
     virtual void exit() { };
 
     /**
-     * Determine the next execute tick. MaxTick means that
-     * there will not be any further event in the current
-     * activation cycle of the state.
+     * Determine the tick when the next packet is available. MaxTick
+     * means that there will not be any further packets in the current
+     * activation cycle of the generator.
      *
-     * @return next tick when the state should be executed
+     * @return next tick when a packet is available
      */
-    virtual Tick nextExecuteTick() = 0;
+    virtual Tick nextPacketTick() = 0;
 
 };
 
@@ -138,16 +138,15 @@ class IdleGen : public BaseGen
 
   public:
 
-    IdleGen(QueuedMasterPort& _port, MasterID master_id,
-            Tick _duration)
-        : BaseGen(_port, master_id, _duration)
+    IdleGen(const std::string& _name, MasterID master_id, Tick _duration)
+        : BaseGen(_name, master_id, _duration)
     { }
 
     void enter() { }
 
-    void execute() { }
+    PacketPtr getNextPacket() { return NULL; }
 
-    Tick nextExecuteTick() { return MaxTick; }
+    Tick nextPacketTick() { return MaxTick; }
 };
 
 /**
@@ -167,7 +166,7 @@ class LinearGen : public BaseGen
      * min_period == max_period for a fixed inter-transaction
      * time.
      *
-     * @param _port port used to send requests
+     * @param _name Name to use for status and debug
      * @param master_id MasterID set on each request
      * @param _duration duration of this state before transitioning
      * @param start_addr Start address
@@ -178,11 +177,11 @@ class LinearGen : public BaseGen
      * @param read_percent Percent of transactions that are reads
      * @param data_limit Upper limit on how much data to read/write
      */
-    LinearGen(QueuedMasterPort& _port, MasterID master_id,
-              Tick _duration, Addr start_addr, Addr end_addr,
-              Addr _blocksize, Tick min_period, Tick max_period,
+    LinearGen(const std::string& _name, MasterID master_id, Tick _duration,
+              Addr start_addr, Addr end_addr, Addr _blocksize,
+              Tick min_period, Tick max_period,
               uint8_t read_percent, Addr data_limit)
-        : BaseGen(_port, master_id, _duration),
+        : BaseGen(_name, master_id, _duration),
           startAddr(start_addr), endAddr(end_addr),
           blocksize(_blocksize), minPeriod(min_period),
           maxPeriod(max_period), readPercent(read_percent),
@@ -191,9 +190,9 @@ class LinearGen : public BaseGen
 
     void enter();
 
-    void execute();
+    PacketPtr getNextPacket();
 
-    Tick nextExecuteTick();
+    Tick nextPacketTick();
 
   private:
 
@@ -244,7 +243,7 @@ class RandomGen : public BaseGen
      * min_period == max_period for a fixed inter-transaction
      * time.
      *
-     * @param _port port used to send requests
+     * @param _name Name to use for status and debug
      * @param master_id MasterID set on each request
      * @param _duration duration of this state before transitioning
      * @param start_addr Start address
@@ -255,11 +254,11 @@ class RandomGen : public BaseGen
      * @param read_percent Percent of transactions that are reads
      * @param data_limit Upper limit on how much data to read/write
      */
-    RandomGen(QueuedMasterPort& _port, MasterID master_id,
-              Tick _duration, Addr start_addr, Addr end_addr,
-              Addr _blocksize, Tick min_period, Tick max_period,
+    RandomGen(const std::string& _name, MasterID master_id, Tick _duration,
+              Addr start_addr, Addr end_addr, Addr _blocksize,
+              Tick min_period, Tick max_period,
               uint8_t read_percent, Addr data_limit)
-        : BaseGen(_port, master_id, _duration),
+        : BaseGen(_name, master_id, _duration),
           startAddr(start_addr), endAddr(end_addr),
           blocksize(_blocksize), minPeriod(min_period),
           maxPeriod(max_period), readPercent(read_percent),
@@ -268,9 +267,9 @@ class RandomGen : public BaseGen
 
     void enter();
 
-    void execute();
+    PacketPtr getNextPacket();
 
-    Tick nextExecuteTick();
+    Tick nextPacketTick();
 
   private:
 
@@ -394,16 +393,15 @@ class TraceGen : public BaseGen
     /**
      * Create a trace generator.
      *
-     * @param _port port used to send requests
+     * @param _name Name to use for status and debug
      * @param master_id MasterID set on each request
      * @param _duration duration of this state before transitioning
      * @param trace_file File to read the transactions from
      * @param addr_offset Positive offset to add to trace address
      */
-    TraceGen(QueuedMasterPort& _port, MasterID master_id,
-             Tick _duration, const std::string& trace_file,
-             Addr addr_offset)
-        : BaseGen(_port, master_id, _duration),
+    TraceGen(const std::string& _name, MasterID master_id, Tick _duration,
+             const std::string& trace_file, Addr addr_offset)
+        : BaseGen(_name, master_id, _duration),
           trace(trace_file),
           addrOffset(addr_offset),
           traceComplete(false)
@@ -412,7 +410,7 @@ class TraceGen : public BaseGen
 
     void enter();
 
-    void execute();
+    PacketPtr getNextPacket();
 
     void exit();
 
@@ -422,7 +420,7 @@ class TraceGen : public BaseGen
      * of the file has been reached, it returns MaxTick to
      * indicate that there will be no more requests.
      */
-    Tick nextExecuteTick();
+    Tick nextPacketTick();
 
   private:
 
index 3e2dc6eb208dc247e44cf7bb9d75308e1a95b389..ea1a74e968ba477247f569cf1c12466e8b088f33 100644 (file)
@@ -54,11 +54,11 @@ TrafficGen::TrafficGen(const TrafficGenParams* p)
     : MemObject(p),
       system(p->system),
       masterID(system->getMasterId(name())),
+      configFile(p->config_file),
       nextTransitionTick(0),
       port(name() + ".port", *this),
       updateEvent(this)
 {
-    parseConfig(p->config_file, masterID);
 }
 
 TrafficGen*
@@ -87,6 +87,8 @@ TrafficGen::init()
     if (system->isTimingMode()) {
         DPRINTF(TrafficGen, "Timing mode, activating request generator\n");
 
+        parseConfig();
+
         // enter initial state
         enterState(currState);
     } else {
@@ -166,12 +168,13 @@ TrafficGen::update()
         transition();
     } else {
         // we are still in the current state and should execute it
-        states[currState]->execute();
+        PacketPtr pkt = states[currState]->getNextPacket();
+        port.schedTimingReq(pkt, curTick());
     }
 }
 
 void
-TrafficGen::parseConfig(const string& file_name, MasterID master_id)
+TrafficGen::parseConfig()
 {
     // keep track of the transitions parsed to create the matrix when
     // done
@@ -179,10 +182,10 @@ TrafficGen::parseConfig(const string& file_name, MasterID master_id)
 
     // open input file
     ifstream infile;
-    infile.open(file_name.c_str(), ifstream::in);
+    infile.open(configFile.c_str(), ifstream::in);
     if (!infile.is_open()) {
         fatal("Traffic generator %s config file not found at %s\n",
-              name(), file_name);
+              name(), configFile);
     }
 
     // read line by line and determine the action based on the first
@@ -213,11 +216,11 @@ TrafficGen::parseConfig(const string& file_name, MasterID master_id)
 
                     is >> traceFile >> addrOffset;
 
-                    states[id] = new TraceGen(port, master_id, duration,
+                    states[id] = new TraceGen(name(), masterID, duration,
                                               traceFile, addrOffset);
                     DPRINTF(TrafficGen, "State: %d TraceGen\n", id);
                 } else if (mode == "IDLE") {
-                    states[id] = new IdleGen(port, master_id, duration);
+                    states[id] = new IdleGen(name(), masterID, duration);
                     DPRINTF(TrafficGen, "State: %d IdleGen\n", id);
                 } else if (mode == "LINEAR" || mode == "RANDOM") {
                     uint32_t read_percent;
@@ -236,18 +239,25 @@ TrafficGen::parseConfig(const string& file_name, MasterID master_id)
                             mode, start_addr, end_addr, blocksize, min_period,
                             max_period, read_percent);
 
+
+                    if (port.deviceBlockSize() &&
+                        blocksize > port.deviceBlockSize())
+                        fatal("TrafficGen %s block size (%d) is larger than "
+                              "port block size (%d)\n", name(),
+                              blocksize, port.deviceBlockSize());
+
                     if (read_percent > 100)
-                        panic("%s cannot have more than 100% reads", name());
+                        fatal("%s cannot have more than 100% reads", name());
 
                     if (mode == "LINEAR") {
-                        states[id] = new LinearGen(port, master_id,
+                        states[id] = new LinearGen(name(), masterID,
                                                    duration, start_addr,
                                                    end_addr, blocksize,
                                                    min_period, max_period,
                                                    read_percent, data_limit);
                         DPRINTF(TrafficGen, "State: %d LinearGen\n", id);
                     } else if (mode == "RANDOM") {
-                        states[id] = new RandomGen(port, master_id,
+                        states[id] = new RandomGen(name(), masterID,
                                                    duration, start_addr,
                                                    end_addr, blocksize,
                                                    min_period, max_period,
index a2fcd3bc00bdc7fdd5b6005bef471cfe4b658e10..c013109b7064f9e0f43a9f2a0bd21104a225eb5e 100644 (file)
@@ -74,25 +74,22 @@ class TrafficGen : public MemObject
     void enterState(uint32_t newState);
 
     /**
-     * Get the tick of the next event, either an execution or a
+     * Get the tick of the next event, either a new packet or a
      * transition.
      *
      * @return tick of the next update event
      */
     Tick nextEventTick()
     {
-        return std::min(states[currState]->nextExecuteTick(),
+        return std::min(states[currState]->nextPacketTick(),
                         nextTransitionTick);
     }
 
     /**
      * Parse the config file and build the state map and
      * transition matrix.
-     *
-     * @param file_name Config file name to parse
-     * @param master_id MasterID to use for generated requests
      */
-    void parseConfig(const std::string& file_name, MasterID master_id);
+    void parseConfig();
 
     /**
      * Schedules event for next update and executes an update on the
@@ -119,6 +116,11 @@ class TrafficGen : public MemObject
      */
     MasterID masterID;
 
+    /**
+     * The config file to parse.
+     */
+    const std::string configFile;
+
     /** Time of next transition */
     Tick nextTransitionTick;