Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
  • 5 commits
  • 4 files changed
  • 0 commit comments
  • 1 contributor
Commits on Mar 15, 2013
@andysan scons: Don't explicitly add tcmalloc_minimal
SCons automatically adds a library to LIBS if conf.CheckLib succeeds,
so there is no need to explicitly add the library.
b33342c
@andysan scons: Tell the compiler to avoid internal malloc when using tcmalloc
According to the tcmalloc readme, the recommended way of compiling
applications that make use of tcmalloc is to disable some
optimizations in gcc that make assumptions about malloc et al. This
changeset adds the necessary compiler flags for both gcc and
clang.

From the tcmalloc readme:
"NOTE: When compiling with programs with gcc, that you plan to link
with libtcmalloc, it's safest to pass in the flags

 -fno-builtin-malloc -fno-builtin-calloc
 -fno-builtin-realloc -fno-builtin-free

when compiling."
311f63d
@andysan scons: Try to use 'tcmalloc' before 'tcmalloc_minimal'
tcmalloc_minimal doesn't support the heap checker on Debian, while
tcmalloc does. Instead of always linking with tcmalloc_minimal, if it
exists, we first check for tcmalloc and then use tcmalloc_minimal as a
fallback.
c31eb51
@andysan cpu: Add support for throttling the traffic generator
Add the parameter maxPendingRequests to the traffic generator. This
parameter controls the maximum number of outstanding memory
requests. Once this limit has been reached, the traffic generators
simply drops excess requests until a response has been received.

Traffic generators may check the return value of BaseGen::send() to
determine if a send request succeeded and retry the current address in
that case.
87fa4ac
@andysan cpu: Don't count data if send failed in TrafficGen
Use the return value of send() to determine if a memory request was
unsuccessful. In that case, don't update the dataManipulated counter
(used to stop generating requests after a fixed amount of data has
been touched) and don't advance the linear generator to the next
address.
68b9e6a
View
21 SConstruct
@@ -505,6 +505,12 @@ Export('MakeAction')
main['LTO_CCFLAGS'] = []
main['LTO_LDFLAGS'] = []
+# The tcmalloc works best if the compiler doesn't assume that we're
+# using the builtin malloc and friends. These flags are
+# compiler-specific, so we need to set them after we detect which
+# compiler we're using.
+main['TCMALLOC_CCFLAGS'] = []
+
CXX_version = readCommand([main['CXX'],'--version'], exception=False)
CXX_V = readCommand([main['CXX'],'-V'], exception=False)
@@ -581,6 +587,9 @@ if main['GCC']:
main['LTO_LDFLAGS'] = ['-flto=%d' % GetOption('num_jobs'),
'-fuse-linker-plugin']
+ main.Append(TCMALLOC_CCFLAGS=['-fno-builtin-malloc', '-fno-builtin-calloc',
+ '-fno-builtin-realloc', '-fno-builtin-free'])
+
elif main['CLANG']:
# Check for a supported version of clang, >= 2.9 is needed to
# support similar features as gcc 4.4. See
@@ -607,6 +616,8 @@ elif main['CLANG']:
'-Wno-parentheses',
'-Wno-self-assign'])
+ main.Append(TCMALLOC_CCFLAGS=['-fno-builtin'])
+
# On Mac OS X/Darwin we need to also use libc++ (part of XCode) as
# opposed to libstdc++ to make the transition from TR1 to
# C++11. See http://libcxx.llvm.org. However, clang has chosen a
@@ -911,10 +922,11 @@ have_posix_clock = \
conf.CheckLibWithHeader('rt', 'time.h', 'C',
'clock_nanosleep(0,0,NULL,NULL);')
-if conf.CheckLib('tcmalloc_minimal'):
- have_tcmalloc = True
+if conf.CheckLib('tcmalloc'):
+ main.Append(CCFLAGS=main['TCMALLOC_CCFLAGS'])
+elif conf.CheckLib('tcmalloc_minimal'):
+ main.Append(CCFLAGS=main['TCMALLOC_CCFLAGS'])
else:
- have_tcmalloc = False
print termcap.Yellow + termcap.Bold + \
"You can get a 12% performance improvement by installing tcmalloc "\
"(libgoogle-perftools-dev package on Ubuntu or RedHat)." + \
@@ -1196,9 +1208,6 @@ for variant_path in variant_paths:
if env['USE_SSE2']:
env.Append(CCFLAGS=['-msse2'])
- if have_tcmalloc:
- env.Append(LIBS=['tcmalloc_minimal'])
-
# The src/SConscript file sets up the build rules in 'env' according
# to the configured variables. It returns a list of environments,
# one for each variant build (debug, opt, etc.)
View
3  src/cpu/testers/traffic_gen/TrafficGen.py
@@ -71,3 +71,6 @@ class TrafficGen(MemObject):
# System used to determine the mode of the memory system
system = Param.System(Parent.any, "System this generator is part of")
+
+ maxPendingRequests = Param.Unsigned(16, "Maximum number of pending " \
+ "memory accesses")
View
112 src/cpu/testers/traffic_gen/traffic_gen.cc
@@ -56,6 +56,7 @@ TrafficGen::TrafficGen(const TrafficGenParams* p)
system(p->system),
masterID(system->getMasterId(name())),
port(name() + ".port", *this),
+ pendingRequests(0), maxPendingRequests(p->maxPendingRequests),
stateGraph(*this, port, p->config_file, masterID),
updateStateGraphEvent(this)
{
@@ -152,6 +153,38 @@ TrafficGen::unserialize(Checkpoint* cp, const string& section)
stateGraph.nextTransitionTick = nextTransitionTick;
}
+bool
+TrafficGen::send(Addr addr, unsigned size, const MemCmd& cmd, uint8_t *data)
+{
+ if (pendingRequests < maxPendingRequests) {
+ // Create new request
+ Request::Flags flags;
+ Request *req = new Request(addr, size, flags, masterID);
+
+ // Embed it in a packet
+ PacketPtr pkt = new Packet(req, cmd);
+ pkt->dataDynamicArray(data);
+
+ ++pendingRequests;
+ port.schedTimingReq(pkt, curTick());
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool
+TrafficGen::recvTimingResp(PacketPtr pkt)
+{
+ assert(pendingRequests >= 1);
+ --pendingRequests;
+
+ delete pkt->req;
+ delete pkt;
+
+ return true;
+}
+
void
TrafficGen::updateStateGraph()
{
@@ -210,11 +243,11 @@ TrafficGen::StateGraph::parseConfig(const string& file_name,
is >> traceFile >> addrOffset;
- states[id] = new TraceGen(port, master_id, duration,
+ states[id] = new TraceGen(owner, 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(owner, duration);
DPRINTF(TrafficGen, "State: %d IdleGen\n", id);
} else if (mode == "LINEAR" || mode == "RANDOM") {
uint32_t read_percent;
@@ -237,14 +270,14 @@ TrafficGen::StateGraph::parseConfig(const string& file_name,
panic("%s cannot have more than 100% reads", name());
if (mode == "LINEAR") {
- states[id] = new LinearGen(port, master_id,
+ states[id] = new LinearGen(owner,
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(owner,
duration, start_addr,
end_addr, blocksize,
min_period, max_period,
@@ -344,32 +377,25 @@ TrafficGen::StateGraph::enterState(uint32_t newState)
states[currState]->enter();
}
-TrafficGen::StateGraph::BaseGen::BaseGen(QueuedMasterPort& _port,
- MasterID master_id,
- Tick _duration)
- : port(_port), masterID(master_id), duration(_duration)
+TrafficGen::StateGraph::BaseGen::BaseGen(TrafficGen& _owner, Tick _duration)
+ : owner(_owner), duration(_duration)
{
}
-void
+bool
TrafficGen::StateGraph::BaseGen::send(Addr addr, unsigned size,
- const MemCmd& cmd)
+ const MemCmd& cmd)
{
- // Create new request
- Request::Flags flags;
- Request *req = new Request(addr, size, flags, masterID);
+ uint8_t* pkt_data = new uint8_t[size];
+ if (cmd.isWrite())
+ memset(pkt_data, 0xA, size);
- // Embed it in a packet
- PacketPtr pkt = new Packet(req, cmd);
-
- uint8_t* pkt_data = new uint8_t[req->getSize()];
- pkt->dataDynamicArray(pkt_data);
-
- if (cmd.isWrite()) {
- memset(pkt_data, 0xA, req->getSize());
+ if (!owner.send(addr, size, cmd, pkt_data)) {
+ delete[] pkt_data;
+ return false;
+ } else {
+ return true;
}
-
- port.schedTimingReq(pkt, curTick());
}
void
@@ -381,9 +407,10 @@ TrafficGen::StateGraph::LinearGen::enter()
// 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())
+ if (owner.port.deviceBlockSize() &&
+ blocksize > owner.port.deviceBlockSize())
fatal("TrafficGen %s block size (%d) is larger than port"
- " block size (%d)\n", blocksize, port.deviceBlockSize());
+ " block size (%d)\n", blocksize, owner.port.deviceBlockSize());
}
@@ -400,13 +427,13 @@ TrafficGen::StateGraph::LinearGen::execute()
DPRINTF(TrafficGen, "LinearGen::execute: %c to addr %x, size %d\n",
isRead ? 'r' : 'w', nextAddr, blocksize);
- send(nextAddr, blocksize, isRead ? MemCmd::ReadReq : MemCmd::WriteReq);
+ if (send(nextAddr, blocksize, isRead ? MemCmd::ReadReq : MemCmd::WriteReq)) {
+ // increment the address
+ nextAddr += blocksize;
- // increment the address
- nextAddr += blocksize;
-
- // Add the amount of data manipulated to the total
- dataManipulated += blocksize;
+ // Add the amount of data manipulated to the total
+ dataManipulated += blocksize;
+ }
}
Tick
@@ -441,9 +468,11 @@ TrafficGen::StateGraph::RandomGen::enter()
// 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())
+ if (owner.port.deviceBlockSize() &&
+ blocksize > owner.port.deviceBlockSize())
fatal("TrafficGen %s block size (%d) is larger than port"
- " block size (%d)\n", name(), blocksize, port.deviceBlockSize());
+ " block size (%d)\n", name(), blocksize,
+ owner.port.deviceBlockSize());
}
void
@@ -466,10 +495,10 @@ TrafficGen::StateGraph::RandomGen::execute()
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
- dataManipulated += blocksize;
+ if (send(addr, blocksize, isRead ? MemCmd::ReadReq : MemCmd::WriteReq)) {
+ // Add the amount of data manipulated to the total
+ dataManipulated += blocksize;
+ }
}
Tick
@@ -607,12 +636,3 @@ TrafficGen::StateGraph::TraceGen::exit() {
// file
trace.reset();
}
-
-bool
-TrafficGen::TrafficGenPort::recvTimingResp(PacketPtr pkt)
-{
- delete pkt->req;
- delete pkt;
-
- return true;
-}
View
94 src/cpu/testers/traffic_gen/traffic_gen.hh
@@ -164,22 +164,23 @@ class TrafficGen : public MemObject
{
protected:
-
- /** Port used to send requests */
- QueuedMasterPort& port;
-
- /** 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.
*
+ * @note This method may return false to indicate that a packet
+ * couldn't be delivered because the maximum number of outstanding
+ * memory requests has been reached.
+ *
* @param addr Physical address to use
* @param size Size of the request
* @param cmd Memory command to send
+ * @return True if the request was sent, false otherwise.
*/
- void send(Addr addr, unsigned size, const MemCmd& cmd);
+ bool send(Addr addr, unsigned size, const MemCmd& cmd);
+
+ /** Pointer to owner of generator */
+ TrafficGen& owner;
public:
@@ -189,12 +190,10 @@ class TrafficGen : public MemObject
/**
* Create a base generator.
*
- * @param _port port used to send requests
- * @param master_id MasterID set on each request
+ * @param _owner object owning the generator instance
* @param _duration duration of this state before transitioning
*/
- BaseGen(QueuedMasterPort& _port, MasterID master_id,
- Tick _duration);
+ BaseGen(TrafficGen& _owner, Tick _duration);
virtual ~BaseGen() { }
@@ -203,7 +202,7 @@ class TrafficGen : public MemObject
*
* @return the port name
*/
- std::string name() const { return port.name(); }
+ std::string name() const { return owner.name(); }
/**
* Enter this generator state.
@@ -239,9 +238,8 @@ class TrafficGen : public MemObject
public:
- IdleGen(QueuedMasterPort& _port, MasterID master_id,
- Tick _duration)
- : BaseGen(_port, master_id, _duration)
+ IdleGen(TrafficGen& _owner, Tick _duration)
+ : BaseGen(_owner, _duration)
{ }
void enter() { }
@@ -268,8 +266,7 @@ class TrafficGen : public MemObject
* min_period == max_period for a fixed inter-transaction
* time.
*
- * @param _port port used to send requests
- * @param master_id MasterID set on each request
+ * @param _owner object owning the generator instance
* @param _duration duration of this state before transitioning
* @param start_addr Start address
* @param end_addr End address
@@ -279,11 +276,11 @@ class TrafficGen : public MemObject
* @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,
+ LinearGen(TrafficGen& _owner, 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(_owner, _duration),
startAddr(start_addr), endAddr(end_addr),
blocksize(_blocksize), minPeriod(min_period),
maxPeriod(max_period), readPercent(read_percent),
@@ -345,8 +342,7 @@ class TrafficGen : public MemObject
* min_period == max_period for a fixed inter-transaction
* time.
*
- * @param _port port used to send requests
- * @param master_id MasterID set on each request
+ * @param _owner object owning the generator instance
* @param _duration duration of this state before transitioning
* @param start_addr Start address
* @param end_addr End address
@@ -356,11 +352,11 @@ class TrafficGen : public MemObject
* @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,
+ RandomGen(TrafficGen& _owner, 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(_owner, _duration),
startAddr(start_addr), endAddr(end_addr),
blocksize(_blocksize), minPeriod(min_period),
maxPeriod(max_period), readPercent(read_percent),
@@ -492,16 +488,15 @@ class TrafficGen : public MemObject
/**
* Create a trace generator.
*
- * @param _port port used to send requests
- * @param master_id MasterID set on each request
+ * @param _owner object owning the generator instance
* @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,
+ TraceGen(TrafficGen& _owner, Tick _duration,
+ const std::string& trace_file,
Addr addr_offset)
- : BaseGen(_port, master_id, _duration),
+ : BaseGen(_owner, _duration),
trace(trace_file),
addrOffset(addr_offset),
traceComplete(false)
@@ -575,21 +570,52 @@ class TrafficGen : public MemObject
public:
TrafficGenPort(const std::string& name, TrafficGen& _owner)
- : QueuedMasterPort(name, &_owner, queue), queue(_owner, *this)
+ : QueuedMasterPort(name, &_owner, queue), queue(_owner, *this),
+ owner(_owner)
{ }
protected:
- bool recvTimingResp(PacketPtr pkt);
+ bool recvTimingResp(PacketPtr pkt) {
+ return owner.recvTimingResp(pkt);
+ }
private:
MasterPacketQueue queue;
-
+ TrafficGen &owner;
};
+ /**
+ * Create a new request and associated packet and schedule it to
+ * be sent in the current tick.
+ *
+ * @note This method may return false to indicate that a packet
+ * couldn't be delivered because the maximum number of outstanding
+ * memory requests has been reached.
+ *
+ * @param addr Request address
+ * @param size Request size
+ * @param cmd Memory command
+ * @param data Dynamic array of data associated with the packet.
+ * @return True if the request was sent, false otherwise.
+ */
+ bool send(Addr addr, unsigned size, const MemCmd& cmd, uint8_t *data);
+
+ /**
+ * Handle a timing response from the memory system.
+ *
+ * @see MasterPort::recvTimingResp()
+ */
+ bool recvTimingResp(PacketPtr pkt);
+
TrafficGenPort port;
+ /** Number of requests still pending in the memory system */
+ unsigned pendingRequests;
+ /** Maximum number of pending requests */
+ const unsigned maxPendingRequests;
+
/** Request generator state graph */
StateGraph stateGraph;

No commit comments for this range

Something went wrong with that request. Please try again.