ruby: Convert most Ruby objects to M5 SimObjects.
The necessary companion conversion of Ruby objects generated by SLICC are converted to M5 SimObjects in the following patch, so this patch alone does not compile. Conversion of Garnet network models is also handled in a separate patch; that code is temporarily disabled from compiling to allow testing of interim code.
This commit is contained in:
parent
b43994ba45
commit
98c94cfe3c
75 changed files with 640 additions and 2186 deletions
|
@ -34,8 +34,6 @@ from m5.defines import buildEnv
|
||||||
from m5.util import addToPath
|
from m5.util import addToPath
|
||||||
import os, optparse, sys
|
import os, optparse, sys
|
||||||
addToPath('../common')
|
addToPath('../common')
|
||||||
addToPath('../../tests/configs/')
|
|
||||||
import ruby_config
|
|
||||||
|
|
||||||
parser = optparse.OptionParser()
|
parser = optparse.OptionParser()
|
||||||
|
|
||||||
|
@ -85,19 +83,43 @@ cpus = [ MemTest(atomic=options.atomic, max_loads=options.maxloads, \
|
||||||
progress_interval=options.progress) \
|
progress_interval=options.progress) \
|
||||||
for i in xrange(options.testers) ]
|
for i in xrange(options.testers) ]
|
||||||
|
|
||||||
# create the desired simulated system
|
system = System(cpu = cpus,
|
||||||
# ruby memory must be at least 16 MB to work with the mem tester
|
funcmem = PhysicalMemory(),
|
||||||
ruby_memory = ruby_config.generate("MI_example-homogeneous.rb",
|
physmem = PhysicalMemory())
|
||||||
cores = options.testers,
|
|
||||||
memory_size = 16,
|
|
||||||
ports_per_cpu = 1)
|
|
||||||
|
|
||||||
system = System(cpu = cpus, funcmem = PhysicalMemory(),
|
class L1Cache(RubyCache):
|
||||||
physmem = ruby_memory)
|
assoc = 2
|
||||||
|
latency = 3
|
||||||
|
size = 32768
|
||||||
|
|
||||||
for cpu in cpus:
|
class L2Cache(RubyCache):
|
||||||
cpu.test = system.physmem.port
|
assoc = 16
|
||||||
cpu.functional = system.funcmem.port
|
latency = 15
|
||||||
|
size = 1048576
|
||||||
|
|
||||||
|
class CrossbarTopology(Topology):
|
||||||
|
connections="hi"
|
||||||
|
|
||||||
|
for cpu in cpus:
|
||||||
|
l1_cntrl = L1Cache_Controller()
|
||||||
|
cpu_seq = RubySequencer(controller=l1_cntrl,
|
||||||
|
icache=L1Cache(controller=l1_cntrl),
|
||||||
|
dcache=L1Cache(controller=l1_cntrl))
|
||||||
|
cpu.controller = l1_cntrl
|
||||||
|
cpu.sequencer = cpu_seq
|
||||||
|
cpu.test = cpu_seq.port
|
||||||
|
cpu_seq.funcmem_port = system.physmem.port
|
||||||
|
cpu.functional = system.funcmem.port
|
||||||
|
|
||||||
|
dir_cntrl = Directory_Controller(directory=RubyDirectoryMemory(),
|
||||||
|
memory_control=RubyMemoryControl())
|
||||||
|
|
||||||
|
network = SimpleNetwork(topology=CrossbarTopology())
|
||||||
|
|
||||||
|
system.ruby = RubySystem(network = network,
|
||||||
|
profiler = RubyProfiler(),
|
||||||
|
tracer = RubyTracer(),
|
||||||
|
debug = RubyDebug())
|
||||||
|
|
||||||
|
|
||||||
# -----------------------
|
# -----------------------
|
||||||
|
|
|
@ -35,9 +35,6 @@ SimObject('Bus.py')
|
||||||
SimObject('MemObject.py')
|
SimObject('MemObject.py')
|
||||||
SimObject('PhysicalMemory.py')
|
SimObject('PhysicalMemory.py')
|
||||||
|
|
||||||
if env['RUBY']:
|
|
||||||
SimObject('RubyMemory.py')
|
|
||||||
|
|
||||||
Source('bridge.cc')
|
Source('bridge.cc')
|
||||||
Source('bus.cc')
|
Source('bus.cc')
|
||||||
Source('dram.cc')
|
Source('dram.cc')
|
||||||
|
@ -48,9 +45,6 @@ Source('port.cc')
|
||||||
Source('tport.cc')
|
Source('tport.cc')
|
||||||
Source('mport.cc')
|
Source('mport.cc')
|
||||||
|
|
||||||
if env['RUBY']:
|
|
||||||
Source('rubymem.cc')
|
|
||||||
|
|
||||||
if env['FULL_SYSTEM']:
|
if env['FULL_SYSTEM']:
|
||||||
Source('vport.cc')
|
Source('vport.cc')
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -72,14 +72,6 @@ def do_embed_text(target, source, env):
|
||||||
fin.close()
|
fin.close()
|
||||||
fout.close()
|
fout.close()
|
||||||
|
|
||||||
def EmbedText(target, source, param):
|
|
||||||
env.Command(target, [source, Value(param)], do_embed_text)
|
|
||||||
|
|
||||||
EmbedText('default_param.hh', 'config/rubyconfig.defaults',
|
|
||||||
'global_default_param')
|
|
||||||
EmbedText('tester_param.hh', 'config/tester.defaults',
|
|
||||||
'global_default_tester_param')
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Link includes
|
# Link includes
|
||||||
#
|
#
|
||||||
|
|
|
@ -87,54 +87,21 @@ void changeDebugFilter(int filter)
|
||||||
g_debug_ptr->setFilter(filter);
|
g_debug_ptr->setFilter(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug::Debug()
|
Debug::Debug(const Params *p)
|
||||||
|
: SimObject(p)
|
||||||
{
|
{
|
||||||
m_verbosityLevel = No_Verb;
|
|
||||||
m_starting_cycle = ~0;
|
|
||||||
clearFilter();
|
|
||||||
debug_cout_ptr = &cout;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug::Debug( const string & name, const vector<string> & argv )
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// must clear the filter before adding filter strings
|
|
||||||
//
|
|
||||||
clearFilter();
|
|
||||||
|
|
||||||
for (size_t i=0;i<argv.size();i+=2) {
|
|
||||||
if (argv[i] == "filter_string") {
|
|
||||||
if (setFilterString(argv[i+1].c_str())) {
|
|
||||||
fatal("could not set filter string to %s\n", argv[i+1].c_str());
|
|
||||||
}
|
|
||||||
} else if (argv[i] == "verbosity_string") {
|
|
||||||
setVerbosityString( argv[i+1].c_str() );
|
|
||||||
} else if (argv[i] == "start_time") {
|
|
||||||
m_starting_cycle = atoi( argv[i+1].c_str() );
|
|
||||||
} else if (argv[i] == "output_filename") {
|
|
||||||
setDebugOutputFile( argv[i+1].c_str() );
|
|
||||||
} else if (argv[i] == "protocol_trace") {
|
|
||||||
m_protocol_trace = string_to_bool(argv[i+1]);
|
|
||||||
} else {
|
|
||||||
fatal("invalid argument %s\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug::Debug( const char *filterString, const char *verboseString,
|
|
||||||
Time filterStartTime, const char *filename )
|
|
||||||
{
|
|
||||||
m_verbosityLevel = No_Verb;
|
|
||||||
clearFilter();
|
clearFilter();
|
||||||
debug_cout_ptr = &cout;
|
debug_cout_ptr = &cout;
|
||||||
|
|
||||||
m_starting_cycle = filterStartTime;
|
setFilterString(p->filter_string.c_str());
|
||||||
if (setFilterString(filterString))
|
setVerbosityString(p->verbosity_string.c_str());
|
||||||
fatal("could not set filter string to %s\n", filterString);
|
setDebugOutputFile(p->output_filename.c_str());
|
||||||
setVerbosityString( verboseString );
|
m_starting_cycle = p->start_time;
|
||||||
setDebugOutputFile( filename );
|
m_protocol_trace = p->protocol_trace;
|
||||||
|
g_debug_ptr = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Debug::~Debug()
|
Debug::~Debug()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -417,3 +384,9 @@ void ERROR_OUT( const char* fmt, ... ) {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
Debug *
|
||||||
|
RubyDebugParams::create()
|
||||||
|
{
|
||||||
|
return new Debug(this);
|
||||||
|
}
|
||||||
|
|
|
@ -41,6 +41,9 @@
|
||||||
|
|
||||||
#include "config/ruby_debug.hh"
|
#include "config/ruby_debug.hh"
|
||||||
#include "mem/ruby/common/Global.hh"
|
#include "mem/ruby/common/Global.hh"
|
||||||
|
#include "sim/sim_object.hh"
|
||||||
|
|
||||||
|
#include "params/RubyDebug.hh"
|
||||||
|
|
||||||
extern std::ostream * debug_cout_ptr;
|
extern std::ostream * debug_cout_ptr;
|
||||||
|
|
||||||
|
@ -70,13 +73,11 @@ enum DebugComponents
|
||||||
enum PriorityLevel {HighPrio, MedPrio, LowPrio};
|
enum PriorityLevel {HighPrio, MedPrio, LowPrio};
|
||||||
enum VerbosityLevel {No_Verb, Low_Verb, Med_Verb, High_Verb};
|
enum VerbosityLevel {No_Verb, Low_Verb, Med_Verb, High_Verb};
|
||||||
|
|
||||||
class Debug {
|
class Debug : public SimObject {
|
||||||
public:
|
public:
|
||||||
// Constructors
|
// Constructors
|
||||||
Debug();
|
typedef RubyDebugParams Params;
|
||||||
Debug(const std::string & name, const std::vector<std::string> & argv);
|
Debug(const Params *p);
|
||||||
Debug( const char *filterString, const char *verboseString,
|
|
||||||
Time filterStartTime, const char *filename );
|
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
~Debug();
|
~Debug();
|
||||||
|
|
23
src/mem/ruby/common/Debug.py
Normal file
23
src/mem/ruby/common/Debug.py
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
from m5.params import *
|
||||||
|
from m5.SimObject import SimObject
|
||||||
|
|
||||||
|
class RubyDebug(SimObject):
|
||||||
|
type = 'RubyDebug'
|
||||||
|
cxx_class = 'Debug'
|
||||||
|
|
||||||
|
filter_string = Param.String('none',
|
||||||
|
"a string for filtering debugging output (see Debug.h)")
|
||||||
|
verbosity_string = Param.String('none',
|
||||||
|
"filters debugging messages based on priority (low, med, high)")
|
||||||
|
output_filename = Param.String('none',
|
||||||
|
"sends debugging messages to a file")
|
||||||
|
start_time = Param.Tick(1,
|
||||||
|
"filters debugging messages based on a ruby time")
|
||||||
|
# For debugging purposes, one can enable a trace of all the protocol
|
||||||
|
# state machine changes. Unfortunately, the code to generate the
|
||||||
|
# trace is protocol specific. To enable the code for some of the
|
||||||
|
# standard protocols,
|
||||||
|
# 1. change protocol_trace = true
|
||||||
|
# 2. enable debug in the Ruby Makefile
|
||||||
|
protocol_trace = Param.Bool(False,
|
||||||
|
"enable protocol state machine trace")
|
|
@ -33,6 +33,8 @@ Import('*')
|
||||||
if not env['RUBY']:
|
if not env['RUBY']:
|
||||||
Return()
|
Return()
|
||||||
|
|
||||||
|
SimObject('Debug.py')
|
||||||
|
|
||||||
Source('Address.cc')
|
Source('Address.cc')
|
||||||
Source('DataBlock.cc')
|
Source('DataBlock.cc')
|
||||||
Source('Debug.cc')
|
Source('Debug.cc')
|
||||||
|
|
|
@ -1,75 +0,0 @@
|
||||||
require "cfg.rb"
|
|
||||||
require "util.rb"
|
|
||||||
|
|
||||||
|
|
||||||
class MESI_CMP_directory_L2CacheController < CacheController
|
|
||||||
attr :cache
|
|
||||||
|
|
||||||
def initialize(obj_name, mach_type, cache)
|
|
||||||
super(obj_name, mach_type, [cache])
|
|
||||||
@cache = cache
|
|
||||||
end
|
|
||||||
def argv()
|
|
||||||
vec = super()
|
|
||||||
vec += " cache " + cache.obj_name
|
|
||||||
vec += " l2_request_latency "+request_latency.to_s
|
|
||||||
vec += " l2_response_latency "+response_latency.to_s
|
|
||||||
vec += " to_l1_latency "+to_L1_latency.to_s
|
|
||||||
return vec
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class MESI_CMP_directory_L1CacheController < L1CacheController
|
|
||||||
attr :icache, :dcache
|
|
||||||
attr :num_l2_controllers
|
|
||||||
|
|
||||||
def initialize(obj_name, mach_type, icache, dcache, sequencer, num_l2_controllers)
|
|
||||||
super(obj_name, mach_type, [icache, dcache], sequencer)
|
|
||||||
@icache = icache
|
|
||||||
@dcache = dcache
|
|
||||||
@num_l2_controllers = num_l2_controllers
|
|
||||||
end
|
|
||||||
|
|
||||||
def argv()
|
|
||||||
num_select_bits = log_int(num_l2_controllers)
|
|
||||||
num_block_bits = log_int(RubySystem.block_size_bytes)
|
|
||||||
l2_select_low_bit = num_block_bits
|
|
||||||
|
|
||||||
vec = super()
|
|
||||||
vec += " icache " + @icache.obj_name
|
|
||||||
vec += " dcache " + @dcache.obj_name
|
|
||||||
vec += " l1_request_latency "+l1_request_latency.to_s
|
|
||||||
vec += " l1_response_latency "+l1_response_latency.to_s
|
|
||||||
vec += " to_l2_latency "+to_L2_latency.to_s
|
|
||||||
vec += " l2_select_low_bit " + l2_select_low_bit.to_s
|
|
||||||
vec += " l2_select_num_bits " + num_select_bits.to_s
|
|
||||||
return vec
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class MESI_CMP_directory_DMAController < DMAController
|
|
||||||
def initialize(obj_name, mach_type, dma_sequencer)
|
|
||||||
super(obj_name, mach_type, dma_sequencer)
|
|
||||||
end
|
|
||||||
def argv()
|
|
||||||
vec = super
|
|
||||||
vec += " request_latency "+request_latency.to_s
|
|
||||||
return vec
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
class MESI_CMP_directory_DirectoryController < DirectoryController
|
|
||||||
def initialize(obj_name, mach_type, directory, memory_control)
|
|
||||||
super(obj_name, mach_type, directory, memory_control)
|
|
||||||
end
|
|
||||||
def argv()
|
|
||||||
vec = super()
|
|
||||||
vec += " to_mem_ctrl_latency "+to_mem_ctrl_latency.to_s
|
|
||||||
vec += " directory_latency "+directory_latency.to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
require "defaults.rb"
|
|
|
@ -1,91 +0,0 @@
|
||||||
#!/usr/bin/ruby
|
|
||||||
#
|
|
||||||
# Creates a homogeneous CMP system with a single unified cache per
|
|
||||||
# core and a crossbar network. Uses the default parameters listed
|
|
||||||
# below, which can be overridden if a wrapper script sets the hash
|
|
||||||
# libruby_args.
|
|
||||||
#
|
|
||||||
|
|
||||||
require "cfg.rb"
|
|
||||||
|
|
||||||
RubySystem.reset
|
|
||||||
|
|
||||||
# default values
|
|
||||||
|
|
||||||
num_cores = 2
|
|
||||||
l1_cache_size_bytes = 32768
|
|
||||||
l1_cache_assoc = 8
|
|
||||||
l1_cache_latency = 1
|
|
||||||
num_memories = 2
|
|
||||||
memory_size_mb = 1024
|
|
||||||
num_dma = 1
|
|
||||||
protocol = "MI_example"
|
|
||||||
|
|
||||||
# check for overrides
|
|
||||||
|
|
||||||
|
|
||||||
for i in 0..$*.size-1 do
|
|
||||||
if $*[i] == "-c"
|
|
||||||
protocol = $*[i+1]
|
|
||||||
i = i+1
|
|
||||||
elsif $*[i] == "-p"
|
|
||||||
num_cores = $*[i+1].to_i
|
|
||||||
i = i+1
|
|
||||||
elsif $*[i] == "-m"
|
|
||||||
num_memories = $*[i+1].to_i
|
|
||||||
i = i+1
|
|
||||||
elsif $*[i] == "-R"
|
|
||||||
if $*[i+1] == "rand"
|
|
||||||
RubySystem.random_seed = "rand"
|
|
||||||
else
|
|
||||||
RubySystem.random_seed = $*[i+1].to_i
|
|
||||||
end
|
|
||||||
i = i+ 1
|
|
||||||
elsif $*[i] == "-s"
|
|
||||||
memory_size_mb = $*[i+1].to_i
|
|
||||||
i = i + 1
|
|
||||||
elsif $*[i] == "-C"
|
|
||||||
l1_cache_size_bytes = $*[i+1].to_i
|
|
||||||
i = i + 1
|
|
||||||
elsif $*[i] == "-A"
|
|
||||||
l1_cache_assoc = $*[i+1].to_i
|
|
||||||
i = i + 1
|
|
||||||
elsif $*[i] == "-D"
|
|
||||||
num_dma = $*[i+1].to_i
|
|
||||||
i = i + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
net_ports = Array.new
|
|
||||||
iface_ports = Array.new
|
|
||||||
|
|
||||||
assert(protocol == "MI_example", __FILE__ + " cannot be used with protocol " + protocol)
|
|
||||||
|
|
||||||
require protocol+".rb"
|
|
||||||
|
|
||||||
num_cores.times { |n|
|
|
||||||
cache = SetAssociativeCache.new("l1u_"+n.to_s, l1_cache_size_bytes, l1_cache_latency, l1_cache_assoc, "PSEUDO_LRU")
|
|
||||||
sequencer = Sequencer.new("Sequencer_"+n.to_s, cache, cache)
|
|
||||||
iface_ports << sequencer
|
|
||||||
net_ports << MI_example_CacheController.new("L1CacheController_"+n.to_s,
|
|
||||||
"L1Cache",
|
|
||||||
cache,
|
|
||||||
sequencer)
|
|
||||||
}
|
|
||||||
num_memories.times { |n|
|
|
||||||
directory = DirectoryMemory.new("DirectoryMemory_"+n.to_s, memory_size_mb/num_memories)
|
|
||||||
memory_control = MemoryControl.new("MemoryControl_"+n.to_s)
|
|
||||||
net_ports << MI_example_DirectoryController.new("DirectoryController_"+n.to_s,
|
|
||||||
"Directory",
|
|
||||||
directory, memory_control)
|
|
||||||
}
|
|
||||||
num_dma.times { |n|
|
|
||||||
dma_sequencer = DMASequencer.new("DMASequencer_"+n.to_s)
|
|
||||||
iface_ports << dma_sequencer
|
|
||||||
net_ports << MI_example_DMAController.new("DMAController_"+n.to_s, "DMA", dma_sequencer)
|
|
||||||
}
|
|
||||||
|
|
||||||
topology = CrossbarTopology.new("theTopology", net_ports)
|
|
||||||
on_chip_net = Network.new("theNetwork", topology)
|
|
||||||
|
|
||||||
RubySystem.init(iface_ports, on_chip_net)
|
|
|
@ -1,37 +0,0 @@
|
||||||
|
|
||||||
require "util.rb"
|
|
||||||
|
|
||||||
class MI_example_CacheController < L1CacheController
|
|
||||||
attr :cache
|
|
||||||
def initialize(obj_name, mach_type, cache, sequencer)
|
|
||||||
super(obj_name, mach_type, [cache], sequencer)
|
|
||||||
@cache = cache
|
|
||||||
end
|
|
||||||
def argv()
|
|
||||||
vec = super()
|
|
||||||
vec += " cache " + @cache.obj_name
|
|
||||||
vec += " issue_latency "+issue_latency.to_s
|
|
||||||
vec += " cache_response_latency "+cache_response_latency.to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class MI_example_DirectoryController < DirectoryController
|
|
||||||
def initialize(obj_name, mach_type, directory, memory_control)
|
|
||||||
super(obj_name, mach_type, directory, memory_control)
|
|
||||||
end
|
|
||||||
def argv()
|
|
||||||
vec = super()
|
|
||||||
vec += " directory_latency "+directory_latency.to_s
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class MI_example_DMAController < DMAController
|
|
||||||
def initialize(obj_name, mach_type, dma_sequencer)
|
|
||||||
super(obj_name, mach_type, dma_sequencer)
|
|
||||||
end
|
|
||||||
def argv()
|
|
||||||
vec = super
|
|
||||||
vec += " request_latency "+request_latency.to_s
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,69 +0,0 @@
|
||||||
|
|
||||||
require "cfg.rb"
|
|
||||||
require "util.rb"
|
|
||||||
|
|
||||||
|
|
||||||
class MOESI_CMP_directory_L1CacheController < L1CacheController
|
|
||||||
attr :icache, :dcache
|
|
||||||
attr :num_l2_controllers
|
|
||||||
def initialize(obj_name, mach_type, icache, dcache, sequencer, num_l2_controllers)
|
|
||||||
super(obj_name, mach_type, [icache, dcache], sequencer)
|
|
||||||
@icache = icache
|
|
||||||
@dcache = dcache
|
|
||||||
@num_l2_controllers = num_l2_controllers
|
|
||||||
end
|
|
||||||
def argv()
|
|
||||||
num_select_bits = log_int(num_l2_controllers)
|
|
||||||
num_block_bits = log_int(RubySystem.block_size_bytes)
|
|
||||||
|
|
||||||
l2_select_low_bit = num_block_bits
|
|
||||||
|
|
||||||
vec = super()
|
|
||||||
vec += " icache " + @icache.obj_name
|
|
||||||
vec += " dcache " + @dcache.obj_name
|
|
||||||
vec += " request_latency "+request_latency().to_s
|
|
||||||
vec += " l2_select_low_bit " + l2_select_low_bit.to_s
|
|
||||||
vec += " l2_select_num_bits " + num_select_bits.to_s
|
|
||||||
return vec
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class MOESI_CMP_directory_L2CacheController < CacheController
|
|
||||||
attr :cache
|
|
||||||
def initialize(obj_name, mach_type, cache)
|
|
||||||
super(obj_name, mach_type, [cache])
|
|
||||||
@cache = cache
|
|
||||||
end
|
|
||||||
def argv()
|
|
||||||
vec = super()
|
|
||||||
vec += " cache " + @cache.obj_name
|
|
||||||
vec += " request_latency "+request_latency().to_s
|
|
||||||
vec += " response_latency "+response_latency().to_s
|
|
||||||
return vec
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
class MOESI_CMP_directory_DirectoryController < DirectoryController
|
|
||||||
def initialize(obj_name, mach_type, directory, memory_control)
|
|
||||||
super(obj_name, mach_type, directory, memory_control)
|
|
||||||
end
|
|
||||||
def argv()
|
|
||||||
vec = super()
|
|
||||||
vec += " directory_latency "+directory_latency.to_s
|
|
||||||
return vec
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class MOESI_CMP_directory_DMAController < DMAController
|
|
||||||
def initialize(obj_name, mach_type, dma_sequencer)
|
|
||||||
super(obj_name, mach_type, dma_sequencer)
|
|
||||||
end
|
|
||||||
def argv()
|
|
||||||
vec = super
|
|
||||||
vec += " request_latency "+request_latency.to_s
|
|
||||||
vec += " response_latency "+response_latency.to_s
|
|
||||||
return vec
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,92 +0,0 @@
|
||||||
|
|
||||||
require "cfg.rb"
|
|
||||||
require "util.rb"
|
|
||||||
|
|
||||||
|
|
||||||
class MOESI_CMP_token_L1CacheController < L1CacheController
|
|
||||||
attr :icache, :dcache
|
|
||||||
attr :num_l2_controllers
|
|
||||||
attr :n_tokens
|
|
||||||
def initialize(obj_name, mach_type, icache, dcache, sequencer, num_l2_controllers, n_tokens)
|
|
||||||
super(obj_name, mach_type, [icache, dcache], sequencer)
|
|
||||||
@icache = icache
|
|
||||||
@dcache = dcache
|
|
||||||
@num_l2_controllers = num_l2_controllers
|
|
||||||
@n_tokens = n_tokens
|
|
||||||
end
|
|
||||||
def argv()
|
|
||||||
num_select_bits = log_int(num_l2_controllers)
|
|
||||||
num_block_bits = log_int(RubySystem.block_size_bytes)
|
|
||||||
|
|
||||||
l2_select_low_bit = num_block_bits
|
|
||||||
|
|
||||||
vec = super()
|
|
||||||
vec += " icache " + @icache.obj_name
|
|
||||||
vec += " dcache " + @dcache.obj_name
|
|
||||||
vec += " l1_request_latency " + l1_request_latency.to_s
|
|
||||||
vec += " l1_response_latency " + l1_response_latency.to_s
|
|
||||||
vec += " l2_select_low_bit " + l2_select_low_bit.to_s
|
|
||||||
vec += " l2_select_num_bits " + num_select_bits.to_s
|
|
||||||
vec += " N_tokens " + n_tokens.to_s
|
|
||||||
vec += " retry_threshold " + retry_threshold.to_s
|
|
||||||
vec += " fixed_timeout_latency " + fixed_timeout_latency.to_s
|
|
||||||
vec += " dynamic_timeout_enabled " + dynamic_timeout_enabled.to_s
|
|
||||||
|
|
||||||
return vec
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class MOESI_CMP_token_L2CacheController < CacheController
|
|
||||||
attr :cache
|
|
||||||
attr :n_tokens
|
|
||||||
def initialize(obj_name, mach_type, cache, n_tokens)
|
|
||||||
super(obj_name, mach_type, [cache])
|
|
||||||
@cache = cache
|
|
||||||
@n_tokens = n_tokens
|
|
||||||
end
|
|
||||||
def argv()
|
|
||||||
vec = super()
|
|
||||||
vec += " cache " + @cache.obj_name
|
|
||||||
vec += " l2_request_latency " + l2_request_latency.to_s
|
|
||||||
vec += " l2_response_latency " + l2_response_latency.to_s
|
|
||||||
vec += " N_tokens " + n_tokens.to_s
|
|
||||||
vec += " filtering_enabled " + filtering_enabled.to_s
|
|
||||||
return vec
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
class MOESI_CMP_token_DirectoryController < DirectoryController
|
|
||||||
attr :num_l2_controllers
|
|
||||||
def initialize(obj_name, mach_type, directory, memory_control, num_l2_controllers)
|
|
||||||
super(obj_name, mach_type, directory, memory_control)
|
|
||||||
@num_l2_controllers = num_l2_controllers
|
|
||||||
end
|
|
||||||
def argv()
|
|
||||||
num_select_bits = log_int(num_l2_controllers)
|
|
||||||
num_block_bits = log_int(RubySystem.block_size_bytes)
|
|
||||||
|
|
||||||
l2_select_low_bit = num_block_bits
|
|
||||||
|
|
||||||
vec = super()
|
|
||||||
vec += " directory_latency "+directory_latency.to_s
|
|
||||||
vec += " l2_select_low_bit " + l2_select_low_bit.to_s
|
|
||||||
vec += " l2_select_num_bits " + num_select_bits.to_s
|
|
||||||
vec += " distributed_persistent "+distributed_persistent.to_s
|
|
||||||
vec += " fixed_timeout_latency " + fixed_timeout_latency.to_s
|
|
||||||
return vec
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class MOESI_CMP_token_DMAController < DMAController
|
|
||||||
def initialize(obj_name, mach_type, dma_sequencer)
|
|
||||||
super(obj_name, mach_type, dma_sequencer)
|
|
||||||
end
|
|
||||||
def argv()
|
|
||||||
vec = super
|
|
||||||
vec += " request_latency "+request_latency.to_s
|
|
||||||
vec += " response_latency "+response_latency.to_s
|
|
||||||
return vec
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,109 +0,0 @@
|
||||||
#!/usr/bin/ruby
|
|
||||||
#
|
|
||||||
# Creates multiple on-chip nodes with three level of cache.
|
|
||||||
#
|
|
||||||
|
|
||||||
require "cfg.rb"
|
|
||||||
|
|
||||||
RubySystem.reset
|
|
||||||
|
|
||||||
# default values
|
|
||||||
|
|
||||||
num_cores = 2
|
|
||||||
l1_cache_size_bytes = 32768
|
|
||||||
l1_cache_assoc = 2
|
|
||||||
l1_cache_latency = 3
|
|
||||||
l2_cache_size_bytes = 1048576
|
|
||||||
l2_cache_assoc = 16
|
|
||||||
l2_cache_latency = 15
|
|
||||||
num_memories = 2
|
|
||||||
memory_size_mb = 1024
|
|
||||||
num_dma = 0
|
|
||||||
use_map = false
|
|
||||||
map_levels = 4
|
|
||||||
protocol = "MOESI_hammer"
|
|
||||||
|
|
||||||
# check for overrides
|
|
||||||
|
|
||||||
|
|
||||||
for i in 0..$*.size-1 do
|
|
||||||
if $*[i] == "-c"
|
|
||||||
protocol = $*[i+1]
|
|
||||||
i = i+1
|
|
||||||
elsif $*[i] == "-p"
|
|
||||||
num_cores = $*[i+1].to_i
|
|
||||||
i = i+1
|
|
||||||
elsif $*[i] == "-m"
|
|
||||||
num_memories = $*[i+1].to_i
|
|
||||||
i = i+1
|
|
||||||
elsif $*[i] == "-s"
|
|
||||||
memory_size_mb = $*[i+1].to_i
|
|
||||||
i = i + 1
|
|
||||||
elsif $*[i] == "-U"
|
|
||||||
use_map = $*[i+1]
|
|
||||||
i = i + 1
|
|
||||||
elsif $*[i] == "-C"
|
|
||||||
l1_cache_size_bytes = $*[i+1].to_i
|
|
||||||
i = i + 1
|
|
||||||
elsif $*[i] == "-A"
|
|
||||||
l1_cache_assoc = $*[i+1].to_i
|
|
||||||
i = i + 1
|
|
||||||
elsif $*[i] == "-M"
|
|
||||||
map_levels = $*[i+1].to_i
|
|
||||||
i = i + 1
|
|
||||||
elsif $*[i] == "-D"
|
|
||||||
num_dma = $*[i+1].to_i
|
|
||||||
i = i + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
net_ports = Array.new
|
|
||||||
iface_ports = Array.new
|
|
||||||
|
|
||||||
assert(protocol == "MOESI_hammer", __FILE__ + " cannot be used with protocol " + protocol)
|
|
||||||
|
|
||||||
require protocol+".rb"
|
|
||||||
|
|
||||||
num_cores.times { |n|
|
|
||||||
icache = SetAssociativeCache.new("l1i_"+n.to_s,
|
|
||||||
l1_cache_size_bytes,
|
|
||||||
l1_cache_latency,
|
|
||||||
l1_cache_assoc,
|
|
||||||
"PSEUDO_LRU")
|
|
||||||
dcache = SetAssociativeCache.new("l1d_"+n.to_s,
|
|
||||||
l1_cache_size_bytes,
|
|
||||||
l1_cache_latency,
|
|
||||||
l1_cache_assoc,
|
|
||||||
"PSEUDO_LRU")
|
|
||||||
l2cache = SetAssociativeCache.new("l2u_"+n.to_s,
|
|
||||||
l2_cache_size_bytes,
|
|
||||||
l2_cache_latency,
|
|
||||||
l2_cache_assoc,
|
|
||||||
"PSEUDO_LRU")
|
|
||||||
sequencer = Sequencer.new("Sequencer_"+n.to_s, icache, dcache)
|
|
||||||
iface_ports << sequencer
|
|
||||||
net_ports << MOESI_hammer_CacheController.new("L1CacheController_"+n.to_s,
|
|
||||||
"L1Cache",
|
|
||||||
icache,
|
|
||||||
dcache,
|
|
||||||
l2cache,
|
|
||||||
sequencer)
|
|
||||||
}
|
|
||||||
num_memories.times { |n|
|
|
||||||
directory = DirectoryMemory.new("DirectoryMemory_"+n.to_s, memory_size_mb/num_memories)
|
|
||||||
memory_control = MemoryControl.new("MemoryControl_"+n.to_s)
|
|
||||||
net_ports << MOESI_hammer_DirectoryController.new("DirectoryController_"+n.to_s,
|
|
||||||
"Directory",
|
|
||||||
directory,
|
|
||||||
memory_control)
|
|
||||||
}
|
|
||||||
num_dma.times { |n|
|
|
||||||
dma_sequencer = DMASequencer.new("DMASequencer_"+n.to_s)
|
|
||||||
iface_ports << dma_sequencer
|
|
||||||
net_ports << MOESI_hammer_DMAController.new("DMAController_"+n.to_s, "DMA", dma_sequencer)
|
|
||||||
}
|
|
||||||
|
|
||||||
topology = CrossbarTopology.new("theTopology", net_ports)
|
|
||||||
on_chip_net = Network.new("theNetwork", topology)
|
|
||||||
|
|
||||||
RubySystem.init(iface_ports, on_chip_net)
|
|
|
@ -1,41 +0,0 @@
|
||||||
|
|
||||||
require "util.rb"
|
|
||||||
|
|
||||||
class MOESI_hammer_CacheController < L1CacheController
|
|
||||||
attr :cache
|
|
||||||
def initialize(obj_name, mach_type, icache, dcache, l2cache, sequencer)
|
|
||||||
super(obj_name, mach_type, [icache, dcache, l2cache], sequencer)
|
|
||||||
@icache = icache
|
|
||||||
@dcache = dcache
|
|
||||||
@l2cache = l2cache
|
|
||||||
end
|
|
||||||
def argv()
|
|
||||||
vec = super()
|
|
||||||
vec += " icache " + @icache.obj_name
|
|
||||||
vec += " dcache " + @dcache.obj_name
|
|
||||||
vec += " l2cache " + @l2cache.obj_name
|
|
||||||
vec += " issue_latency "+issue_latency.to_s
|
|
||||||
vec += " cache_response_latency "+cache_response_latency.to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class MOESI_hammer_DirectoryController < DirectoryController
|
|
||||||
def initialize(obj_name, mach_type, directory, memory_control)
|
|
||||||
super(obj_name, mach_type, directory, memory_control)
|
|
||||||
end
|
|
||||||
def argv()
|
|
||||||
vec = super()
|
|
||||||
vec += " memory_controller_latency "+memory_controller_latency.to_s
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class MOESI_hammer_DMAController < DMAController
|
|
||||||
def initialize(obj_name, mach_type, dma_sequencer)
|
|
||||||
super(obj_name, mach_type, dma_sequencer)
|
|
||||||
end
|
|
||||||
def argv()
|
|
||||||
vec = super
|
|
||||||
vec += " request_latency "+request_latency.to_s
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,139 +0,0 @@
|
||||||
#!/usr/bin/ruby
|
|
||||||
#
|
|
||||||
# Creates a homogeneous CMP system with a single unified cache per
|
|
||||||
# core and a crossbar network. Uses the default parameters listed
|
|
||||||
# below, which can be overridden using command line args.
|
|
||||||
#
|
|
||||||
|
|
||||||
require "cfg.rb"
|
|
||||||
|
|
||||||
RubySystem.reset
|
|
||||||
|
|
||||||
# default values
|
|
||||||
|
|
||||||
num_cores = 2
|
|
||||||
l1_icache_size_kb = 64
|
|
||||||
l1_icache_assoc = 8
|
|
||||||
l1_icache_latency = 1
|
|
||||||
l1_dcache_size_kb = 32
|
|
||||||
l1_dcache_assoc = 8
|
|
||||||
l1_dcache_latency = 1
|
|
||||||
l2_cache_size_kb = 8192 # total size (sum of all banks)
|
|
||||||
l2_cache_assoc = 16
|
|
||||||
l2_cache_latency = 12
|
|
||||||
num_l2_banks = num_cores
|
|
||||||
num_memories = 1
|
|
||||||
memory_size_mb = 1024
|
|
||||||
num_dma = 1
|
|
||||||
|
|
||||||
#default protocol
|
|
||||||
protocol = "MOESI_CMP_directory"
|
|
||||||
|
|
||||||
# check for overrides
|
|
||||||
|
|
||||||
for i in 0..$*.size-1 do
|
|
||||||
if $*[i] == "-c" or $*[i] == "--protocol"
|
|
||||||
i += 1
|
|
||||||
protocol = $*[i]
|
|
||||||
elsif $*[i] == "-A"
|
|
||||||
l1_dcache_size_kb = $*[i+1].to_i
|
|
||||||
i = i+1
|
|
||||||
elsif $*[i] == "-B"
|
|
||||||
num_l2_banks = $*[i+1].to_i
|
|
||||||
i = i+1
|
|
||||||
elsif $*[i] == "-m"
|
|
||||||
num_memories = $*[i+1].to_i
|
|
||||||
i = i+1
|
|
||||||
elsif $*[i] == "-p"
|
|
||||||
num_cores = $*[i+1].to_i
|
|
||||||
i = i+1
|
|
||||||
elsif $*[i] == "-R"
|
|
||||||
if $*[i+1] == "rand"
|
|
||||||
RubySystem.random_seed = "rand"
|
|
||||||
else
|
|
||||||
RubySystem.random_seed = $*[i+1].to_i
|
|
||||||
end
|
|
||||||
i = i+ 1
|
|
||||||
elsif $*[i] == "-s"
|
|
||||||
memory_size_mb = $*[i+1].to_i
|
|
||||||
i = i + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
net_ports = Array.new
|
|
||||||
iface_ports = Array.new
|
|
||||||
|
|
||||||
assert((protocol == "MESI_CMP_directory" or protocol == "MOESI_CMP_directory"), __FILE__+" cannot be used with protocol '#{protocol}'");
|
|
||||||
|
|
||||||
require protocol+".rb"
|
|
||||||
|
|
||||||
num_cores.times { |n|
|
|
||||||
icache = SetAssociativeCache.new("l1i_"+n.to_s, l1_icache_size_kb*1024, l1_icache_latency, l1_icache_assoc, "PSEUDO_LRU")
|
|
||||||
dcache = SetAssociativeCache.new("l1d_"+n.to_s, l1_dcache_size_kb*1024, l1_dcache_latency, l1_dcache_assoc, "PSEUDO_LRU")
|
|
||||||
sequencer = Sequencer.new("Sequencer_"+n.to_s, icache, dcache)
|
|
||||||
iface_ports << sequencer
|
|
||||||
if protocol == "MOESI_CMP_directory"
|
|
||||||
net_ports << MOESI_CMP_directory_L1CacheController.new("L1CacheController_"+n.to_s,
|
|
||||||
"L1Cache",
|
|
||||||
icache, dcache,
|
|
||||||
sequencer,
|
|
||||||
num_l2_banks)
|
|
||||||
elsif protocol == "MESI_CMP_directory"
|
|
||||||
net_ports << MESI_CMP_directory_L1CacheController.new("L1CacheController_"+n.to_s,
|
|
||||||
"L1Cache",
|
|
||||||
icache, dcache,
|
|
||||||
sequencer,
|
|
||||||
num_l2_banks)
|
|
||||||
end
|
|
||||||
}
|
|
||||||
num_l2_banks.times { |n|
|
|
||||||
cache = SetAssociativeCache.new("l2u_"+n.to_s, (l2_cache_size_kb*1024)/num_l2_banks, l2_cache_latency, l2_cache_assoc, "PSEUDO_LRU")
|
|
||||||
if protocol == "MOESI_CMP_directory"
|
|
||||||
net_ports << MOESI_CMP_directory_L2CacheController.new("L2CacheController_"+n.to_s,
|
|
||||||
"L2Cache",
|
|
||||||
cache)
|
|
||||||
elsif protocol == "MESI_CMP_directory"
|
|
||||||
net_ports << MESI_CMP_directory_L2CacheController.new("L2CacheController_"+n.to_s,
|
|
||||||
"L2Cache",
|
|
||||||
cache)
|
|
||||||
end
|
|
||||||
|
|
||||||
net_ports.last.request_latency = l2_cache_latency + 2
|
|
||||||
net_ports.last.response_latency = l2_cache_latency + 2
|
|
||||||
}
|
|
||||||
num_memories.times { |n|
|
|
||||||
directory = DirectoryMemory.new("DirectoryMemory_"+n.to_s, memory_size_mb/num_memories)
|
|
||||||
memory_control = MemoryControl.new("MemoryControl_"+n.to_s)
|
|
||||||
if protocol == "MOESI_CMP_directory"
|
|
||||||
net_ports << MOESI_CMP_directory_DirectoryController.new("DirectoryController_"+n.to_s,
|
|
||||||
"Directory",
|
|
||||||
directory,
|
|
||||||
memory_control)
|
|
||||||
elsif protocol == "MESI_CMP_directory"
|
|
||||||
net_ports << MESI_CMP_directory_DirectoryController.new("DirectoryController_"+n.to_s,
|
|
||||||
"Directory",
|
|
||||||
directory,
|
|
||||||
memory_control)
|
|
||||||
end
|
|
||||||
|
|
||||||
}
|
|
||||||
num_dma.times { |n|
|
|
||||||
dma_sequencer = DMASequencer.new("DMASequencer_"+n.to_s)
|
|
||||||
iface_ports << dma_sequencer
|
|
||||||
if protocol == "MOESI_CMP_directory"
|
|
||||||
net_ports << MOESI_CMP_directory_DMAController.new("DMAController_"+n.to_s,
|
|
||||||
"DMA",
|
|
||||||
dma_sequencer)
|
|
||||||
elsif protocol == "MESI_CMP_directory"
|
|
||||||
net_ports << MESI_CMP_directory_DMAController.new("DMAController_"+n.to_s,
|
|
||||||
"DMA",
|
|
||||||
dma_sequencer)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
topology = CrossbarTopology.new("theTopology", net_ports)
|
|
||||||
on_chip_net = Network.new("theNetwork", topology)
|
|
||||||
|
|
||||||
RubySystem.init(iface_ports, on_chip_net)
|
|
|
@ -1,18 +0,0 @@
|
||||||
#!/usr/bin/env ruby
|
|
||||||
|
|
||||||
class AssertionFailure < RuntimeError
|
|
||||||
attr_reader :msg, :output
|
|
||||||
def initialize(message, out=nil)
|
|
||||||
@msg = message
|
|
||||||
@output = out
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class NotImplementedException < Exception
|
|
||||||
end
|
|
||||||
|
|
||||||
def assert(condition,message)
|
|
||||||
unless condition
|
|
||||||
raise AssertionFailure.new(message), "\n\nAssertion failed: \n\n #{message}\n\n"
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,672 +0,0 @@
|
||||||
#!/usr/bin/ruby
|
|
||||||
|
|
||||||
root = File.dirname(File.expand_path(__FILE__))
|
|
||||||
require root+'/assert.rb'
|
|
||||||
|
|
||||||
class Boolean
|
|
||||||
def self.is_a?(obj)
|
|
||||||
return self.name == "Boolean"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class LibRubyObject
|
|
||||||
@@all_objs = Array.new
|
|
||||||
@@default_params = Hash.new
|
|
||||||
@@param_types = Hash.new
|
|
||||||
|
|
||||||
attr_reader :obj_name
|
|
||||||
|
|
||||||
def initialize(obj_name)
|
|
||||||
assert obj_name.is_a?(String), "Obj_Name must be a string"
|
|
||||||
@obj_name = obj_name
|
|
||||||
@@all_objs << self
|
|
||||||
@params = Hash.new
|
|
||||||
|
|
||||||
# add all parent parameter accessors if they don't exist
|
|
||||||
self.class.ancestors.each { |ancestor|
|
|
||||||
if @@default_params.key?(ancestor.name.to_sym)
|
|
||||||
@@default_params[ancestor.name.to_sym].each { |p, default|
|
|
||||||
p = p.to_sym
|
|
||||||
@params[p] = default
|
|
||||||
if ! respond_to?(p)
|
|
||||||
self.class.send(:define_method, p) {
|
|
||||||
@params[p] = @@default_params[ancestor.name.to_sym][p] if ! @params.key?(p)
|
|
||||||
return @params[p]
|
|
||||||
}
|
|
||||||
end
|
|
||||||
setter_method_name = (p.to_s + "=").to_sym
|
|
||||||
if ! respond_to?(setter_method_name)
|
|
||||||
self.class.send(:define_method, setter_method_name) { |val|
|
|
||||||
type = @@param_types[ancestor.name.to_sym][p]
|
|
||||||
if val.is_a?(FalseClass) || val.is_a?(TrueClass)
|
|
||||||
assert type.is_a?(Boolean), "default value of param \"#{p}\" must be either true or false"
|
|
||||||
else
|
|
||||||
assert val.is_a?(type), "default value of param \"#{p}\", which is of type #{val.class.name} does not match expected type #{type}"
|
|
||||||
end
|
|
||||||
@params[p] = val
|
|
||||||
}
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def cppClassName()
|
|
||||||
raise NotImplementedException
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.param(param_name, type)
|
|
||||||
idx = self.name.to_sym
|
|
||||||
@@default_params[idx] = Hash.new if ! @@default_params.key?(idx)
|
|
||||||
@@default_params[idx][param_name] = nil
|
|
||||||
@@param_types[idx] = Hash.new if ! @@param_types.key?(idx)
|
|
||||||
@@param_types[idx][param_name] = type
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.default_param(param_name, type, default)
|
|
||||||
|
|
||||||
if default.is_a?(FalseClass) || default.is_a?(TrueClass)
|
|
||||||
assert type.is_a?(Boolean), "default value of param \"#{param_name}\" must be either true or false"
|
|
||||||
else
|
|
||||||
assert default.is_a?(type), "default value of param \"#{param_name}\" does not match type #{type}"
|
|
||||||
end
|
|
||||||
|
|
||||||
idx = self.name.to_sym
|
|
||||||
@@default_params[idx] = Hash.new if ! @@default_params.key?(idx)
|
|
||||||
@@default_params[idx][param_name] = default
|
|
||||||
@@param_types[idx] = Hash.new if ! @@param_types.key?(idx)
|
|
||||||
@@param_types[idx][param_name] = type
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
def applyDefaults()
|
|
||||||
idx = self.class.name.to_sym
|
|
||||||
@@default_params[idx] = Hash.new if ! @@default_params.key?(idx)
|
|
||||||
@@default_params[idx].each { |key, val|
|
|
||||||
@params[key] = val if ! @params.key?(key)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def argv()
|
|
||||||
str = ""
|
|
||||||
|
|
||||||
applyDefaults
|
|
||||||
|
|
||||||
@params.each { |key, val|
|
|
||||||
str += key.id2name + " "
|
|
||||||
assert(val != nil, "parameter #{key} is nil")
|
|
||||||
if val.is_a?(LibRubyObject)
|
|
||||||
str += val.obj_name + " "
|
|
||||||
else
|
|
||||||
if val.is_a?(String) and val == ""
|
|
||||||
str += "null "
|
|
||||||
else
|
|
||||||
str += val.to_s + " "
|
|
||||||
end
|
|
||||||
end
|
|
||||||
}
|
|
||||||
return str
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.printConstructors()
|
|
||||||
str = ""
|
|
||||||
@@all_objs.each { |obj|
|
|
||||||
str += obj.cppClassName + " " + obj.obj_name + " " + obj.argv + "\n"
|
|
||||||
}
|
|
||||||
return str
|
|
||||||
end
|
|
||||||
def self.all()
|
|
||||||
@@all_objs
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class IfacePort < LibRubyObject
|
|
||||||
def initialize(obj_name)
|
|
||||||
super(obj_name)
|
|
||||||
end
|
|
||||||
|
|
||||||
def bochsConnType
|
|
||||||
raise NotImplementedException
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class NetPort < LibRubyObject
|
|
||||||
attr :mach_type
|
|
||||||
param :version, Integer
|
|
||||||
|
|
||||||
@@type_cnt = Hash.new
|
|
||||||
def initialize(obj_name, mach_type)
|
|
||||||
super(obj_name)
|
|
||||||
@mach_type = mach_type
|
|
||||||
@@type_cnt[mach_type] ||= 0
|
|
||||||
self.version= @@type_cnt[mach_type] # sets the version parameter
|
|
||||||
|
|
||||||
@@type_cnt[mach_type] += 1
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
def port_name
|
|
||||||
mach_type
|
|
||||||
end
|
|
||||||
def port_num
|
|
||||||
version
|
|
||||||
end
|
|
||||||
def self.totalOfType(mach_type)
|
|
||||||
return @@type_cnt[mach_type]
|
|
||||||
end
|
|
||||||
def cppClassName()
|
|
||||||
"generated:"+@mach_type
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class MemoryVector < LibRubyObject
|
|
||||||
def initialize(obj_name)
|
|
||||||
super(obj_name)
|
|
||||||
end
|
|
||||||
|
|
||||||
def cppClassName
|
|
||||||
"MemoryVector"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class Debug < LibRubyObject
|
|
||||||
def initialize *args
|
|
||||||
case args.size
|
|
||||||
when 1
|
|
||||||
super(args[0])
|
|
||||||
when 6
|
|
||||||
init_params *args[1]
|
|
||||||
else
|
|
||||||
raise Exception
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def init_params (protocol_trace, filter_string, verbosity_string, start_time, output_filename)
|
|
||||||
@params[:protocol_trace] = protocol_trace
|
|
||||||
@params[:filter_string] = filter_string
|
|
||||||
@params[:verbosity_string] = verbosity_string
|
|
||||||
@params[:start_time] = start_time
|
|
||||||
@params[:output_filename] = output_filename
|
|
||||||
end
|
|
||||||
|
|
||||||
def cppClassName
|
|
||||||
"Debug"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class RubySystem
|
|
||||||
|
|
||||||
@@params = Hash.new
|
|
||||||
@@defaults = Hash.new
|
|
||||||
@@network = nil
|
|
||||||
|
|
||||||
def self.init(iface_ports, network)
|
|
||||||
@@iface_ports = iface_ports
|
|
||||||
@@network = network
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.reset()
|
|
||||||
@@iface_ports = nil
|
|
||||||
@@network = nil
|
|
||||||
@@params.each { |param_name, param|
|
|
||||||
param = @@defaults[param_name]
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.default_param(param_name, type, default)
|
|
||||||
if default.is_a?(FalseClass) || default.is_a?(TrueClass)
|
|
||||||
assert type.is_a?(Boolean), "default value of param \"#{param_name}\" must be either true or false"
|
|
||||||
else
|
|
||||||
assert default.is_a?(type), "default value of param \"#{param_name}\" does not match type #{type}"
|
|
||||||
end
|
|
||||||
@@params[param_name] = default
|
|
||||||
@@defaults[param_name] = default
|
|
||||||
method_name = (param_name.to_s).to_sym
|
|
||||||
instance_eval <<-EOS
|
|
||||||
def #{method_name.to_s}
|
|
||||||
@@params[:#{param_name.to_s}]
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
instance_eval <<-EOS
|
|
||||||
def #{method_name.to_s}=(val)
|
|
||||||
@@params[:#{param_name.to_s}] = val
|
|
||||||
end
|
|
||||||
EOS
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.getConfig()
|
|
||||||
# get current time for random seed if set to "rand"
|
|
||||||
if @@params[:random_seed] == "rand"
|
|
||||||
t = Time.now
|
|
||||||
@@params[:random_seed] = t.usec.to_i
|
|
||||||
end
|
|
||||||
if ! @@params[:random_seed].is_a?(Integer)
|
|
||||||
raise TypeException
|
|
||||||
end
|
|
||||||
str = "System sys0 "+argv+"\n"
|
|
||||||
LibRubyObject.all.each { |obj|
|
|
||||||
if obj.is_a?(SetAssociativeCache)
|
|
||||||
obj.calculateLatency
|
|
||||||
end
|
|
||||||
}
|
|
||||||
str += LibRubyObject.printConstructors
|
|
||||||
#puts str.gsub('%',' ').gsub('#','\n')
|
|
||||||
return str
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.generateConfig()
|
|
||||||
puts getConfig
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.printIfacePorts()
|
|
||||||
@@iface_ports.each { |port|
|
|
||||||
print port.obj_name, " "
|
|
||||||
}
|
|
||||||
puts
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.getBochsConnections()
|
|
||||||
ports = Hash.new
|
|
||||||
@@iface_ports.each { |port|
|
|
||||||
ports[port.obj_name] = port.bochsConnType
|
|
||||||
}
|
|
||||||
return ports
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.getMemorySizeMB()
|
|
||||||
DirectoryMemory.memorySizeMB
|
|
||||||
end
|
|
||||||
|
|
||||||
# override the default accessors (generated by default_param) for random_seed
|
|
||||||
def self.random_seed=(seed)
|
|
||||||
assert (val.is_a?(Integer) or val == "rand"), "RubySystem.random_seed takes either an integer value or the string \"rand\""
|
|
||||||
@@params[:random_seed] = seed
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def self.argv()
|
|
||||||
str = ""
|
|
||||||
@@params.each { |key, val|
|
|
||||||
str += key.id2name + " "
|
|
||||||
str += val.to_s + " "
|
|
||||||
}
|
|
||||||
return str
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.writeConfig()
|
|
||||||
@@network.printTopology
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class CacheController < NetPort
|
|
||||||
|
|
||||||
def initialize(obj_name, mach_type, caches)
|
|
||||||
super(obj_name, mach_type)
|
|
||||||
caches.each { |cache|
|
|
||||||
cache.controller = self
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def cppClassName()
|
|
||||||
"generated:"+@mach_type
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class Sequencer < IfacePort
|
|
||||||
end
|
|
||||||
|
|
||||||
class L1CacheController < CacheController
|
|
||||||
param :sequencer, Sequencer
|
|
||||||
|
|
||||||
def initialize(obj_name, mach_type, caches, sequencer)
|
|
||||||
super(obj_name, mach_type, caches)
|
|
||||||
|
|
||||||
sequencer.controller = self
|
|
||||||
sequencer.version = version
|
|
||||||
self.sequencer= sequencer
|
|
||||||
end
|
|
||||||
|
|
||||||
# def argv()
|
|
||||||
# vec = super()
|
|
||||||
# vec += " sequencer "+@sequencer.obj_name
|
|
||||||
# end
|
|
||||||
end
|
|
||||||
|
|
||||||
class DirectoryMemory < LibRubyObject
|
|
||||||
end
|
|
||||||
class MemoryControl < LibRubyObject
|
|
||||||
end
|
|
||||||
|
|
||||||
class DirectoryController < NetPort
|
|
||||||
@@total_directory_controllers = 0
|
|
||||||
param :directory, DirectoryMemory
|
|
||||||
param :memory_control, MemoryControl
|
|
||||||
|
|
||||||
def initialize(obj_name, mach_type, directory, memory_control)
|
|
||||||
super(obj_name, mach_type)
|
|
||||||
|
|
||||||
directory.controller = self
|
|
||||||
directory.version = @@total_directory_controllers
|
|
||||||
self.directory = directory
|
|
||||||
self.memory_control = memory_control
|
|
||||||
|
|
||||||
@version = @@total_directory_controllers
|
|
||||||
@@total_directory_controllers += 1
|
|
||||||
buffer_size()
|
|
||||||
end
|
|
||||||
|
|
||||||
def cppClassName()
|
|
||||||
"generated:"+@mach_type
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class DMASequencer < IfacePort
|
|
||||||
end
|
|
||||||
|
|
||||||
class DMAController < NetPort
|
|
||||||
@@total_dma_controllers = 0
|
|
||||||
param :dma_sequencer, DMASequencer
|
|
||||||
param :version, Integer
|
|
||||||
|
|
||||||
def initialize(obj_name, mach_type, dma_sequencer)
|
|
||||||
super(obj_name, mach_type)
|
|
||||||
dma_sequencer.controller = self
|
|
||||||
dma_sequencer.version = @@total_dma_controllers
|
|
||||||
self.dma_sequencer = dma_sequencer
|
|
||||||
|
|
||||||
self.version = @@total_dma_controllers
|
|
||||||
@@total_dma_controllers += 1
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class Cache < LibRubyObject
|
|
||||||
param :size, Integer
|
|
||||||
param :latency, Integer
|
|
||||||
param :controller, NetPort
|
|
||||||
def initialize(obj_name, size, latency)
|
|
||||||
super(obj_name)
|
|
||||||
self.size = size
|
|
||||||
self.latency = latency
|
|
||||||
# controller must be set manually by the configuration script
|
|
||||||
# because there is a cyclic dependence
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class SetAssociativeCache < Cache
|
|
||||||
param :assoc, Integer
|
|
||||||
param :replacement_policy, String
|
|
||||||
|
|
||||||
# latency can be either an integer, a float, or the string "auto"
|
|
||||||
# when an integer, it represents the number of cycles for a hit
|
|
||||||
# when a float, it represents the cache access time in ns
|
|
||||||
# when set to "auto", libruby will attempt to find a realistic latency by running CACTI
|
|
||||||
def initialize(obj_name, size, latency, assoc, replacement_policy)
|
|
||||||
super(obj_name, size, latency)
|
|
||||||
self.assoc = assoc
|
|
||||||
self.replacement_policy = replacement_policy
|
|
||||||
end
|
|
||||||
|
|
||||||
def calculateLatency()
|
|
||||||
if self.latency == "auto"
|
|
||||||
cacti_args = Array.new()
|
|
||||||
cacti_args << (self.size*1024) << RubySystem.block_size_bytes << self.assoc
|
|
||||||
cacti_args << 1 << 0 << 0 << 0 << 1
|
|
||||||
cacti_args << RubySystem.tech_nm << RubySystem.block_size_bytes*8
|
|
||||||
cacti_args << 0 << 0 << 0 << 1 << 0 << 0 << 0 << 0 << 1
|
|
||||||
cacti_args << 360 << 0 << 0 << 0 << 0 << 1 << 1 << 1 << 1 << 0 << 0
|
|
||||||
cacti_args << 50 << 10 << 10 << 0 << 1 << 1
|
|
||||||
|
|
||||||
cacti_cmd = File.dirname(__FILE__) + "/cacti/cacti " + cacti_args.join(" ")
|
|
||||||
|
|
||||||
IO.popen(cacti_cmd) { |pipe|
|
|
||||||
str1 = pipe.readline
|
|
||||||
str2 = pipe.readline
|
|
||||||
results = str2.split(", ")
|
|
||||||
if results.size != 61
|
|
||||||
print "CACTI ERROR: CACTI produced unexpected output.\n"
|
|
||||||
print "Are you using the version shipped with libruby?\n"
|
|
||||||
raise Exception
|
|
||||||
end
|
|
||||||
latency_ns = results[5].to_f
|
|
||||||
if (latency_ns == "1e+39")
|
|
||||||
print "CACTI ERROR: CACTI was unable to realistically model the cache ",@obj_name,"\n"
|
|
||||||
print "Either change the cache parameters or manually set the latency values\n"
|
|
||||||
raise Exception
|
|
||||||
end
|
|
||||||
clk_period_ns = 1e9 * (1.0 / (RubySystem.freq_mhz * 1e6))
|
|
||||||
latency_cycles = (latency_ns / clk_period_ns).ceil
|
|
||||||
self.latency = latency_cycles
|
|
||||||
}
|
|
||||||
elsif self.latency.is_a?(Float)
|
|
||||||
clk_period_ns = 1e9 * (1.0 / (RubySystem.freq_mhz * 1e6))
|
|
||||||
latency_cycles = (self.latency / clk_period_ns).ceil
|
|
||||||
self.latency = latency_cycles
|
|
||||||
elsif ! self.latency.is_a?(Integer)
|
|
||||||
raise Exception
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def cppClassName()
|
|
||||||
"SetAssociativeCache"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class DirectoryMemory < LibRubyObject
|
|
||||||
param :size_mb, Integer
|
|
||||||
param :controller, NetPort
|
|
||||||
param :version, Integer
|
|
||||||
|
|
||||||
@@total_size_mb = 0
|
|
||||||
|
|
||||||
def initialize(obj_name, size_mb)
|
|
||||||
super(obj_name)
|
|
||||||
self.size_mb = size_mb
|
|
||||||
@@total_size_mb += size_mb
|
|
||||||
end
|
|
||||||
|
|
||||||
def cppClassName()
|
|
||||||
"DirectoryMemory"
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.memorySizeMB()
|
|
||||||
@@total_size_mb
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class MemoryControl < LibRubyObject
|
|
||||||
def initialize(obj_name)
|
|
||||||
super(obj_name)
|
|
||||||
end
|
|
||||||
|
|
||||||
def cppClassName()
|
|
||||||
"MemoryControl"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
class Sequencer < IfacePort
|
|
||||||
|
|
||||||
def cppClassName()
|
|
||||||
"Sequencer"
|
|
||||||
end
|
|
||||||
|
|
||||||
param :controller, NetPort # must be set after initialization
|
|
||||||
param :icache, Cache
|
|
||||||
param :dcache, Cache
|
|
||||||
param :version, Integer
|
|
||||||
|
|
||||||
def initialize(obj_name, icache, dcache)
|
|
||||||
super(obj_name)
|
|
||||||
self.icache=icache
|
|
||||||
self.dcache=dcache
|
|
||||||
end
|
|
||||||
|
|
||||||
def bochsConnType()
|
|
||||||
return "cpu"+version.to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class DMASequencer < IfacePort
|
|
||||||
param :controller, NetPort
|
|
||||||
param :version, Integer
|
|
||||||
|
|
||||||
def initialize(obj_name)
|
|
||||||
super(obj_name)
|
|
||||||
end
|
|
||||||
|
|
||||||
def cppClassName()
|
|
||||||
"DMASequencer"
|
|
||||||
end
|
|
||||||
|
|
||||||
def bochsConnType()
|
|
||||||
return "dma"+self.version.to_s
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class IntNode
|
|
||||||
@@num = 0
|
|
||||||
def initialize()
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class Network < LibRubyObject
|
|
||||||
end
|
|
||||||
|
|
||||||
class Topology < LibRubyObject
|
|
||||||
attr :net_ports
|
|
||||||
param :network, Network
|
|
||||||
def initialize(name, net_ports)
|
|
||||||
super(name)
|
|
||||||
@net_ports = net_ports
|
|
||||||
end
|
|
||||||
|
|
||||||
def cppClassName
|
|
||||||
"Topology"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class Network < LibRubyObject
|
|
||||||
param :topology, Topology
|
|
||||||
def initialize(name, topo)
|
|
||||||
super(name)
|
|
||||||
topo.network= self
|
|
||||||
self.topology = topo
|
|
||||||
end
|
|
||||||
|
|
||||||
def printTopology()
|
|
||||||
topology().printFile
|
|
||||||
end
|
|
||||||
def cppClassName()
|
|
||||||
"SimpleNetwork"
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class PtToPtTopology < Topology
|
|
||||||
|
|
||||||
param :connections,String
|
|
||||||
|
|
||||||
def initialize(name, net_ports)
|
|
||||||
super(name, net_ports)
|
|
||||||
@params[:connections] = ""
|
|
||||||
@net_ports.each_index { |idx|
|
|
||||||
@params[:connections] << ("ext_node:"+@net_ports[idx].port_name+":"+@net_ports[idx].port_num.to_s)
|
|
||||||
@params[:connections] << ("%int_node:"+ idx.to_s+ "%link_latency:"+ link_latency.to_s)
|
|
||||||
@params[:connections] << ("%bw_multiplier:"+external_bw.to_s+"#")
|
|
||||||
}
|
|
||||||
@net_ports.each_index { |outer_idx|
|
|
||||||
@net_ports.each_index { |inner_idx|
|
|
||||||
if (outer_idx != inner_idx)
|
|
||||||
@params[:connections] << ("int_node:"+ outer_idx.to_s+ "%int_node:"+ inner_idx.to_s)
|
|
||||||
@params[:connections] << ("%link_latency:"+link_latency.to_s+"%bw_multiplier:"+internal_bw.to_s)
|
|
||||||
@params[:connections] << ("%link_weight:"+1.to_s+"#")
|
|
||||||
end
|
|
||||||
}
|
|
||||||
}
|
|
||||||
# call the accessors of the parent class to initialize them
|
|
||||||
# need to find a better method!!
|
|
||||||
print_config
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class CrossbarTopology < Topology
|
|
||||||
param :connections,String
|
|
||||||
|
|
||||||
def initialize(name, net_ports)
|
|
||||||
super(name, net_ports)
|
|
||||||
@params[:connections] = ""
|
|
||||||
crossbar_node = @net_ports.size
|
|
||||||
@net_ports.each_index { |idx|
|
|
||||||
@params[:connections] << ("ext_node:"+@net_ports[idx].port_name+":"+@net_ports[idx].port_num.to_s)
|
|
||||||
@params[:connections] << ("%int_node:"+ idx.to_s+ "%link_latency:"+ link_latency.to_s)
|
|
||||||
@params[:connections] << ("%bw_multiplier:"+external_bw.to_s+"#")
|
|
||||||
}
|
|
||||||
@net_ports.each_index { |idx|
|
|
||||||
@params[:connections] << ("int_node:"+idx.to_s+"%int_node:"+crossbar_node.to_s)
|
|
||||||
@params[:connections] << ("%link_latency:"+link_latency.to_s+"%bw_multiplier:"+internal_bw.to_s)
|
|
||||||
@params[:connections] << ("%link_weight:"+1.to_s+"#")
|
|
||||||
}
|
|
||||||
print_config
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class Tracer < LibRubyObject
|
|
||||||
def initialize(obj_name)
|
|
||||||
super(obj_name)
|
|
||||||
end
|
|
||||||
|
|
||||||
def cppClassName()
|
|
||||||
"Tracer"
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class Profiler < LibRubyObject
|
|
||||||
def initialize(obj_name)
|
|
||||||
super(obj_name)
|
|
||||||
end
|
|
||||||
|
|
||||||
def cppClassName()
|
|
||||||
"Profiler"
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class GarnetNetwork < Network
|
|
||||||
def initialize(name, topo)
|
|
||||||
super(name, topo)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class GarnetFixedPipeline < GarnetNetwork
|
|
||||||
def initialize(name, net_ports)
|
|
||||||
super(name, net_ports)
|
|
||||||
end
|
|
||||||
|
|
||||||
def cppClassName()
|
|
||||||
"GarnetNetwork_d"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class GarnetFlexiblePipeline < GarnetNetwork
|
|
||||||
def initialize(name, net_ports)
|
|
||||||
super(name, net_ports)
|
|
||||||
end
|
|
||||||
|
|
||||||
def cppClassName()
|
|
||||||
"GarnetNetwork"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
require "defaults.rb"
|
|
|
@ -1,248 +0,0 @@
|
||||||
#!/usr/bin/ruby
|
|
||||||
|
|
||||||
class NetPort < LibRubyObject
|
|
||||||
# number of transitions a SLICC state machine can transition per
|
|
||||||
# cycle
|
|
||||||
default_param :transitions_per_cycle, Integer, 32
|
|
||||||
|
|
||||||
# buffer_size limits the size of all other buffers connecting to
|
|
||||||
# SLICC Controllers. When 0, infinite buffering is used.
|
|
||||||
default_param :buffer_size, Integer, 32
|
|
||||||
|
|
||||||
default_param :number_of_TBEs, Integer, 256
|
|
||||||
|
|
||||||
default_param :recycle_latency, Integer, 10
|
|
||||||
end
|
|
||||||
|
|
||||||
class Sequencer < IfacePort
|
|
||||||
# Maximum number of requests (including prefetches) outstanding from
|
|
||||||
# the sequencer
|
|
||||||
default_param :max_outstanding_requests, Integer, 16
|
|
||||||
|
|
||||||
# Maximum number of cycles a request is can be outstanding before
|
|
||||||
# the Sequencer declares we're in deadlock/livelock
|
|
||||||
default_param :deadlock_threshold, Integer, 500000
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class Debug < LibRubyObject
|
|
||||||
# For debugging purposes, one can enable a trace of all the protocol
|
|
||||||
# state machine changes. Unfortunately, the code to generate the
|
|
||||||
# trace is protocol specific. To enable the code for some of the
|
|
||||||
# standard protocols,
|
|
||||||
# 1. change protocol_trace = true
|
|
||||||
# 2. enable debug in the Ruby Makefile
|
|
||||||
# 3. set start_time = 1
|
|
||||||
default_param :protocol_trace, Boolean, false
|
|
||||||
|
|
||||||
# a string for filtering debugging output. Valid options (also see Debug.cc):
|
|
||||||
# {"System", 's' },
|
|
||||||
# {"Node", 'N' },
|
|
||||||
# {"Queue", 'q' },
|
|
||||||
# {"Event Queue", 'e' },
|
|
||||||
# {"Network", 'n' },
|
|
||||||
# {"Sequencer", 'S' },
|
|
||||||
# {"Tester", 't' },
|
|
||||||
# {"Generated", 'g' },
|
|
||||||
# {"SLICC", 'l' },
|
|
||||||
# {"Network Queues", 'Q' },
|
|
||||||
# {"Time", 'T' },
|
|
||||||
# {"Network Internals", 'i' },
|
|
||||||
# {"Store Buffer", 'b' },
|
|
||||||
# {"Cache", 'c' },
|
|
||||||
# {"Predictor", 'p' },
|
|
||||||
# {"Allocator", 'a' }
|
|
||||||
#
|
|
||||||
# e.g., "sq" will print system and queue debugging messages
|
|
||||||
# Set to "none" for no debugging output
|
|
||||||
default_param :filter_string, String, "none"
|
|
||||||
|
|
||||||
# filters debugging messages based on priority (none, low, med, high)
|
|
||||||
default_param :verbosity_string, String, "none"
|
|
||||||
|
|
||||||
# filters debugging messages based on a ruby time
|
|
||||||
default_param :start_time, Integer, 1
|
|
||||||
|
|
||||||
# sends debugging messages to a output filename
|
|
||||||
# set to "none" to print to stdout
|
|
||||||
default_param :output_filename, String, "none"
|
|
||||||
end
|
|
||||||
|
|
||||||
class Topology < LibRubyObject
|
|
||||||
# The default link latency between all nodes (internal and external)
|
|
||||||
# in the toplogy
|
|
||||||
default_param :link_latency, Integer, 1
|
|
||||||
|
|
||||||
# the bandwidth from an external network port to it's corresponding
|
|
||||||
# internal switch
|
|
||||||
default_param :external_bw, Integer, 64
|
|
||||||
|
|
||||||
# the bandwitch between internal switches in the network
|
|
||||||
default_param :internal_bw, Integer, 16
|
|
||||||
|
|
||||||
# indicates whether the topology config will be displayed in the
|
|
||||||
# stats file
|
|
||||||
default_param :print_config, Boolean, false
|
|
||||||
end
|
|
||||||
|
|
||||||
class Network < LibRubyObject
|
|
||||||
default_param :endpoint_bandwidth, Integer, 10000
|
|
||||||
default_param :adaptive_routing, Boolean, true
|
|
||||||
default_param :number_of_virtual_networks, Integer, 5
|
|
||||||
# default_param :fan_out_degree, Integer, 4
|
|
||||||
|
|
||||||
# default buffer size. Setting to 0 indicates infinite buffering
|
|
||||||
# default_param :buffer_size, Integer, 0
|
|
||||||
|
|
||||||
# local memory latency ?? NetworkLinkLatency
|
|
||||||
default_param :link_latency, Integer, 1
|
|
||||||
|
|
||||||
# on chip latency
|
|
||||||
# default_param :on_chip_latency, Integer, 1
|
|
||||||
|
|
||||||
default_param :control_msg_size, Integer, 8
|
|
||||||
end
|
|
||||||
|
|
||||||
class GarnetNetwork < Network
|
|
||||||
default_param :flit_size, Integer, 16
|
|
||||||
default_param :number_of_pipe_stages, Integer, 4
|
|
||||||
default_param :vcs_per_class, Integer, 4
|
|
||||||
default_param :buffer_size, Integer, 4
|
|
||||||
default_param :using_network_testing, Boolean, false
|
|
||||||
end
|
|
||||||
|
|
||||||
class Tracer < LibRubyObject
|
|
||||||
default_param :warmup_length, Integer, 1000000
|
|
||||||
end
|
|
||||||
|
|
||||||
class Profiler < LibRubyObject
|
|
||||||
default_param :hot_lines, Boolean, false
|
|
||||||
default_param :all_instructions, Boolean, false
|
|
||||||
end
|
|
||||||
|
|
||||||
class MemoryControl < LibRubyObject
|
|
||||||
|
|
||||||
default_param :mem_bus_cycle_multiplier, Integer, 10
|
|
||||||
default_param :banks_per_rank, Integer, 8
|
|
||||||
default_param :ranks_per_dimm, Integer, 2
|
|
||||||
default_param :dimms_per_channel, Integer, 2
|
|
||||||
default_param :bank_bit_0, Integer, 8
|
|
||||||
default_param :rank_bit_0, Integer, 11
|
|
||||||
default_param :dimm_bit_0, Integer, 12
|
|
||||||
default_param :bank_queue_size, Integer, 12
|
|
||||||
default_param :bank_busy_time, Integer, 11
|
|
||||||
default_param :rank_rank_delay, Integer, 1
|
|
||||||
default_param :read_write_delay, Integer, 2
|
|
||||||
default_param :basic_bus_busy_time, Integer, 2
|
|
||||||
default_param :mem_ctl_latency, Integer, 12
|
|
||||||
default_param :refresh_period, Integer, 1560
|
|
||||||
default_param :tFaw, Integer, 0
|
|
||||||
default_param :mem_random_arbitrate, Integer, 11
|
|
||||||
default_param :mem_fixed_delay, Integer, 0
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
###### Protocols #######
|
|
||||||
|
|
||||||
## MI_example protocol
|
|
||||||
|
|
||||||
class MI_example_CacheController < L1CacheController
|
|
||||||
default_param :issue_latency, Integer, 2
|
|
||||||
default_param :cache_response_latency, Integer, 12
|
|
||||||
end
|
|
||||||
|
|
||||||
class MI_example_DirectoryController < DirectoryController
|
|
||||||
default_param :directory_latency, Integer, 6
|
|
||||||
end
|
|
||||||
|
|
||||||
class MI_example_DMAController < DMAController
|
|
||||||
default_param :request_latency, Integer, 6
|
|
||||||
end
|
|
||||||
|
|
||||||
## MOESI_CMP_directory protocol
|
|
||||||
|
|
||||||
class MOESI_CMP_directory_L1CacheController < L1CacheController
|
|
||||||
default_param :request_latency, Integer, 2
|
|
||||||
end
|
|
||||||
|
|
||||||
class MOESI_CMP_directory_L2CacheController < CacheController
|
|
||||||
default_param :request_latency, Integer, 2
|
|
||||||
default_param :response_latency, Integer, 2
|
|
||||||
end
|
|
||||||
|
|
||||||
class MOESI_CMP_directory_DirectoryController < DirectoryController
|
|
||||||
default_param :directory_latency, Integer, 6
|
|
||||||
end
|
|
||||||
|
|
||||||
class MOESI_CMP_directory_DMAController < DMAController
|
|
||||||
default_param :request_latency, Integer, 14
|
|
||||||
default_param :response_latency, Integer, 14
|
|
||||||
end
|
|
||||||
|
|
||||||
class MESI_CMP_directory_L2CacheController < CacheController
|
|
||||||
default_param :request_latency, Integer, 2
|
|
||||||
default_param :response_latency, Integer, 2
|
|
||||||
default_param :to_L1_latency, Integer, 1
|
|
||||||
|
|
||||||
#if 0 then automatically calculated
|
|
||||||
default_param :lowest_bit, Integer, 0
|
|
||||||
default_param :highest_bit, Integer, 0
|
|
||||||
end
|
|
||||||
|
|
||||||
class MESI_CMP_directory_L1CacheController < L1CacheController
|
|
||||||
default_param :l1_request_latency, Integer, 2
|
|
||||||
default_param :l1_response_latency, Integer, 2
|
|
||||||
default_param :to_L2_latency, Integer, 1
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
class MESI_CMP_directory_DirectoryController < DirectoryController
|
|
||||||
default_param :to_mem_ctrl_latency, Integer, 1
|
|
||||||
default_param :directory_latency, Integer, 6
|
|
||||||
end
|
|
||||||
|
|
||||||
class MESI_CMP_directory_DMAController < DMAController
|
|
||||||
default_param :request_latency, Integer, 6
|
|
||||||
end
|
|
||||||
|
|
||||||
class RubySystem
|
|
||||||
|
|
||||||
# Random seed used by the simulation. If set to "rand", the seed
|
|
||||||
# will be set to the current wall clock at libruby
|
|
||||||
# initialization. Otherwise, set this to an integer.
|
|
||||||
default_param :random_seed, Object, 1234 #"rand"
|
|
||||||
|
|
||||||
# When set to true, the simulation will insert random delays on
|
|
||||||
# message enqueue times. Note that even if this is set to false,
|
|
||||||
# you can still have a non-deterministic simulation if random seed
|
|
||||||
# is set to "rand". This is used mainly to debug protocols by forcing
|
|
||||||
# really strange interleavings and should not be used for
|
|
||||||
# performance runs.
|
|
||||||
default_param :randomization, Boolean, false
|
|
||||||
|
|
||||||
# tech_nm is the device size used to calculate latency and area
|
|
||||||
# information about system components
|
|
||||||
default_param :tech_nm, Integer, 45
|
|
||||||
|
|
||||||
# default frequency for the system
|
|
||||||
default_param :freq_mhz, Integer, 3000
|
|
||||||
|
|
||||||
# the default cache block size in the system
|
|
||||||
# libruby does not currently support different block sizes
|
|
||||||
# among different caches
|
|
||||||
# Must be a power of two
|
|
||||||
default_param :block_size_bytes, Integer, 64
|
|
||||||
|
|
||||||
# The default debug object. There shouldn't be a reason to ever
|
|
||||||
# change this line. To adjust debug paramters statically, adjust
|
|
||||||
# them in the Debug class above. To adjust these fields
|
|
||||||
# dynamically, access this RubySystem object,
|
|
||||||
# e.g. RubySystem.debug.protocol_trace = true
|
|
||||||
default_param :debug, Debug, Debug.new("dbg0")
|
|
||||||
default_param :tracer, Tracer, Tracer.new("tracer0")
|
|
||||||
|
|
||||||
default_param :profiler, Profiler, Profiler.new("profiler0")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "../libruby.hh"
|
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
|
||||||
{
|
|
||||||
assert(argc == 2);
|
|
||||||
const char* cfg_file = argv[1];
|
|
||||||
|
|
||||||
libruby_init(cfg_file);
|
|
||||||
libruby_print_config(std::cout);
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
ruby_cfg_file = nil
|
|
||||||
$stderr.puts $*.inspect
|
|
||||||
for i in 0..$*.size-1 do
|
|
||||||
if $*[i] == "-r" # ruby config file
|
|
||||||
i += 1
|
|
||||||
ruby_cfg_file = $*[i]
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
require ruby_cfg_file
|
|
||||||
|
|
||||||
RubySystem.generateConfig
|
|
|
@ -1,10 +0,0 @@
|
||||||
|
|
||||||
def log_int(n)
|
|
||||||
assert(n.is_a?(Fixnum), "log_int takes a number for an argument")
|
|
||||||
counter = 0
|
|
||||||
while n >= 2 do
|
|
||||||
counter += 1
|
|
||||||
n = n >> 1
|
|
||||||
end
|
|
||||||
return counter
|
|
||||||
end
|
|
|
@ -40,10 +40,14 @@
|
||||||
|
|
||||||
// Class public method definitions
|
// Class public method definitions
|
||||||
|
|
||||||
|
RubyEventQueue theEventQueue;
|
||||||
|
|
||||||
RubyEventQueue::RubyEventQueue()
|
RubyEventQueue::RubyEventQueue()
|
||||||
{
|
{
|
||||||
m_prio_heap_ptr = NULL;
|
m_prio_heap_ptr = NULL;
|
||||||
init();
|
init();
|
||||||
|
assert(g_eventQueue_ptr == NULL);
|
||||||
|
g_eventQueue_ptr = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
RubyEventQueue::~RubyEventQueue()
|
RubyEventQueue::~RubyEventQueue()
|
||||||
|
|
|
@ -89,6 +89,15 @@ vector<string> tokenizeString(string str, string delims)
|
||||||
return tokens;
|
return tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The current state of M5/Ruby integration breaks the libruby
|
||||||
|
* interface. This code is ifdef'd out for now so that we can move
|
||||||
|
* forward with the integration process for non-libruby uses. We'll
|
||||||
|
* have to go back and resolve the libruby compatibility issue at a
|
||||||
|
* later date.
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
void libruby_init(const char* cfg_filename)
|
void libruby_init(const char* cfg_filename)
|
||||||
{
|
{
|
||||||
ifstream cfg_output(cfg_filename);
|
ifstream cfg_output(cfg_filename);
|
||||||
|
@ -115,6 +124,7 @@ void libruby_init(const char* cfg_filename)
|
||||||
RubySystem::create(*sys_conf);
|
RubySystem::create(*sys_conf);
|
||||||
delete sys_conf;
|
delete sys_conf;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
RubyPortHandle libruby_get_port(const char* port_name, void (*hit_callback)(int64_t access_id))
|
RubyPortHandle libruby_get_port(const char* port_name, void (*hit_callback)(int64_t access_id))
|
||||||
{
|
{
|
||||||
|
|
|
@ -29,38 +29,26 @@
|
||||||
#include "mem/protocol/MachineType.hh"
|
#include "mem/protocol/MachineType.hh"
|
||||||
#include "mem/ruby/network/Network.hh"
|
#include "mem/ruby/network/Network.hh"
|
||||||
|
|
||||||
Network::Network(const string & name)
|
Network::Network(const Params *p)
|
||||||
: m_name(name)
|
: SimObject(p)
|
||||||
{
|
{
|
||||||
m_virtual_networks = 0;
|
m_virtual_networks = p->number_of_virtual_networks;
|
||||||
m_topology_ptr = NULL;
|
m_topology_ptr = p->topology;
|
||||||
|
m_buffer_size = p->buffer_size;
|
||||||
|
m_endpoint_bandwidth = p->endpoint_bandwidth;
|
||||||
|
m_adaptive_routing = p->adaptive_routing;
|
||||||
|
m_link_latency = p->link_latency;
|
||||||
|
m_control_msg_size = p->control_msg_size;
|
||||||
|
|
||||||
|
assert(m_virtual_networks != 0);
|
||||||
|
assert(m_topology_ptr != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Network::init(const vector<string> & argv)
|
void Network::init()
|
||||||
{
|
{
|
||||||
m_nodes = MachineType_base_number(MachineType_NUM); // Total nodes in network
|
m_nodes = MachineType_base_number(MachineType_NUM); // Total nodes in network
|
||||||
|
|
||||||
for (size_t i=0; i<argv.size(); i+=2) {
|
|
||||||
if (argv[i] == "number_of_virtual_networks")
|
|
||||||
m_virtual_networks = atoi(argv[i+1].c_str());
|
|
||||||
else if (argv[i] == "topology")
|
|
||||||
m_topology_ptr = RubySystem::getTopology(argv[i+1]);
|
|
||||||
else if (argv[i] == "buffer_size")
|
|
||||||
m_buffer_size = atoi(argv[i+1].c_str());
|
|
||||||
else if (argv[i] == "endpoint_bandwidth")
|
|
||||||
m_endpoint_bandwidth = atoi(argv[i+1].c_str());
|
|
||||||
else if (argv[i] == "adaptive_routing")
|
|
||||||
m_adaptive_routing = (argv[i+1]=="true");
|
|
||||||
else if (argv[i] == "link_latency")
|
|
||||||
m_link_latency = atoi(argv[i+1].c_str());
|
|
||||||
else if (argv[i] == "control_msg_size")
|
|
||||||
m_control_msg_size = atoi(argv[i+1].c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
m_data_msg_size = RubySystem::getBlockSizeBytes() + m_control_msg_size;
|
m_data_msg_size = RubySystem::getBlockSizeBytes() + m_control_msg_size;
|
||||||
|
|
||||||
assert(m_virtual_networks != 0);
|
|
||||||
assert(m_topology_ptr != NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Network::MessageSizeType_to_int(MessageSizeType size_type)
|
int Network::MessageSizeType_to_int(MessageSizeType size_type)
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
|
@ -50,17 +49,20 @@
|
||||||
#include "mem/ruby/system/NodeID.hh"
|
#include "mem/ruby/system/NodeID.hh"
|
||||||
#include "mem/protocol/MessageSizeType.hh"
|
#include "mem/protocol/MessageSizeType.hh"
|
||||||
#include "mem/ruby/system/System.hh"
|
#include "mem/ruby/system/System.hh"
|
||||||
|
#include "sim/sim_object.hh"
|
||||||
|
#include "params/RubyNetwork.hh"
|
||||||
|
|
||||||
class NetDest;
|
class NetDest;
|
||||||
class MessageBuffer;
|
class MessageBuffer;
|
||||||
class Throttle;
|
class Throttle;
|
||||||
class Topology;
|
class Topology;
|
||||||
|
|
||||||
class Network {
|
class Network : public SimObject {
|
||||||
public:
|
public:
|
||||||
// Constructors
|
// Constructors
|
||||||
Network(const string & name);
|
typedef RubyNetworkParams Params;
|
||||||
virtual void init(const vector<string> & argv);
|
Network(const Params *p);
|
||||||
|
virtual void init();
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
virtual ~Network() {}
|
virtual ~Network() {}
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
# -*- mode:python -*-
|
# Copyright (c) 2009 Advanced Micro Devices, Inc.
|
||||||
|
|
||||||
# Copyright (c) 2009 The Hewlett-Packard Development Company
|
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -26,10 +24,28 @@
|
||||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# Authors: Nathan Binkert
|
# Authors: Steve Reinhardt
|
||||||
|
# Brad Beckmann
|
||||||
|
|
||||||
Import('*')
|
from m5.params import *
|
||||||
|
from m5.SimObject import SimObject
|
||||||
|
|
||||||
if not env['RUBY']:
|
class Topology(SimObject):
|
||||||
Return()
|
type = 'Topology'
|
||||||
|
connections = Param.String("")
|
||||||
|
print_config = Param.Bool(False,
|
||||||
|
"display topology config in the stats file")
|
||||||
|
|
||||||
|
class RubyNetwork(SimObject):
|
||||||
|
type = 'RubyNetwork'
|
||||||
|
cxx_class = 'Network'
|
||||||
|
abstract = True
|
||||||
|
number_of_virtual_networks = Param.Int(10, "");
|
||||||
|
topology = Param.Topology("");
|
||||||
|
buffer_size = Param.Int(0,
|
||||||
|
"default buffer size; 0 indicates infinite buffering");
|
||||||
|
endpoint_bandwidth = Param.Int(10000, "");
|
||||||
|
adaptive_routing = Param.Bool(True, "");
|
||||||
|
link_latency = Param.Int(1,
|
||||||
|
"local memory latency ?? NetworkLinkLatency");
|
||||||
|
control_msg_size = Param.Int(8, "");
|
|
@ -33,4 +33,6 @@ Import('*')
|
||||||
if not env['RUBY']:
|
if not env['RUBY']:
|
||||||
Return()
|
Return()
|
||||||
|
|
||||||
|
SimObject('Network.py')
|
||||||
|
|
||||||
Source('Network.cc')
|
Source('Network.cc')
|
||||||
|
|
|
@ -43,7 +43,7 @@ GarnetNetwork_d::GarnetNetwork_d(const string & name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void GarnetNetwork_d::init(const vector<string> & argv)
|
void GarnetNetwork_d::init()
|
||||||
{
|
{
|
||||||
Network::init(argv);
|
Network::init(argv);
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ public:
|
||||||
|
|
||||||
~GarnetNetwork_d();
|
~GarnetNetwork_d();
|
||||||
|
|
||||||
void init(const vector<string> & argv);
|
void init();
|
||||||
|
|
||||||
//added by SS
|
//added by SS
|
||||||
NetworkConfig* getNetworkConfig() { return m_network_config_ptr; }
|
NetworkConfig* getNetworkConfig() { return m_network_config_ptr; }
|
||||||
|
|
|
@ -30,6 +30,9 @@
|
||||||
|
|
||||||
Import('*')
|
Import('*')
|
||||||
|
|
||||||
|
# temporarily disable
|
||||||
|
Return()
|
||||||
|
|
||||||
if not env['RUBY']:
|
if not env['RUBY']:
|
||||||
Return()
|
Return()
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ GarnetNetwork::GarnetNetwork(const string & name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void GarnetNetwork::init(const vector<string> & argv)
|
void GarnetNetwork::init()
|
||||||
{
|
{
|
||||||
// printf("hello\n");
|
// printf("hello\n");
|
||||||
Network::init(argv);
|
Network::init(argv);
|
||||||
|
|
|
@ -49,7 +49,7 @@ public:
|
||||||
|
|
||||||
~GarnetNetwork();
|
~GarnetNetwork();
|
||||||
|
|
||||||
void init(const vector<string> & argv);
|
void init();
|
||||||
|
|
||||||
//added by SS
|
//added by SS
|
||||||
NetworkConfig* getNetworkConfig() { return m_network_config_ptr; }
|
NetworkConfig* getNetworkConfig() { return m_network_config_ptr; }
|
||||||
|
|
|
@ -48,7 +48,7 @@ class NetworkConfig {
|
||||||
bool m_using_network_testing;
|
bool m_using_network_testing;
|
||||||
public:
|
public:
|
||||||
NetworkConfig(){}
|
NetworkConfig(){}
|
||||||
void init(const vector<string> & argv) {
|
void init() {
|
||||||
for (size_t i=0; i<argv.size(); i+=2) {
|
for (size_t i=0; i<argv.size(); i+=2) {
|
||||||
if (argv[i] == "flit_size")
|
if (argv[i] == "flit_size")
|
||||||
m_flit_size = atoi(argv[i+1].c_str());
|
m_flit_size = atoi(argv[i+1].c_str());
|
||||||
|
|
|
@ -30,6 +30,9 @@
|
||||||
|
|
||||||
Import('*')
|
Import('*')
|
||||||
|
|
||||||
|
# temporarily disable
|
||||||
|
Return()
|
||||||
|
|
||||||
if not env['RUBY']:
|
if not env['RUBY']:
|
||||||
Return()
|
Return()
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,9 @@
|
||||||
|
|
||||||
Import('*')
|
Import('*')
|
||||||
|
|
||||||
|
# temporarily disable
|
||||||
|
Return()
|
||||||
|
|
||||||
if not env['RUBY']:
|
if not env['RUBY']:
|
||||||
Return()
|
Return()
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ class HierarchicalSwitchTopology : public Topology
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
HierarchicalSwitchTopology(const string & name);
|
HierarchicalSwitchTopology(const string & name);
|
||||||
void init(const vector<string> & argv);
|
void init();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void construct();
|
void construct();
|
||||||
|
|
|
@ -8,7 +8,7 @@ class PtToPtTopology : public Topology
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PtToPtTopology(const string & name);
|
PtToPtTopology(const string & name);
|
||||||
void init(const vector<string> & argv);
|
void init();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void construct();
|
void construct();
|
||||||
|
|
|
@ -33,6 +33,8 @@ Import('*')
|
||||||
if not env['RUBY']:
|
if not env['RUBY']:
|
||||||
Return()
|
Return()
|
||||||
|
|
||||||
|
SimObject('SimpleNetwork.py')
|
||||||
|
|
||||||
Source('PerfectSwitch.cc')
|
Source('PerfectSwitch.cc')
|
||||||
Source('SimpleNetwork.cc')
|
Source('SimpleNetwork.cc')
|
||||||
Source('Switch.cc')
|
Source('Switch.cc')
|
||||||
|
|
|
@ -59,17 +59,17 @@ Network* Network::createNetwork(int nodes)
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SimpleNetwork::SimpleNetwork(const string & name)
|
SimpleNetwork::SimpleNetwork(const Params *p)
|
||||||
: Network(name)
|
: Network(p)
|
||||||
{
|
{
|
||||||
m_virtual_networks = 0;
|
m_virtual_networks = 0;
|
||||||
m_topology_ptr = NULL;
|
m_topology_ptr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleNetwork::init(const vector<string> & argv)
|
void SimpleNetwork::init()
|
||||||
{
|
{
|
||||||
|
|
||||||
Network::init(argv);
|
Network::init();
|
||||||
|
|
||||||
m_endpoint_switches.setSize(m_nodes);
|
m_endpoint_switches.setSize(m_nodes);
|
||||||
|
|
||||||
|
@ -263,3 +263,10 @@ void SimpleNetwork::print(ostream& out) const
|
||||||
{
|
{
|
||||||
out << "[SimpleNetwork]";
|
out << "[SimpleNetwork]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SimpleNetwork *
|
||||||
|
SimpleNetworkParams::create()
|
||||||
|
{
|
||||||
|
return new SimpleNetwork(this);
|
||||||
|
}
|
||||||
|
|
|
@ -73,6 +73,8 @@
|
||||||
#include "mem/gems_common/Vector.hh"
|
#include "mem/gems_common/Vector.hh"
|
||||||
#include "mem/ruby/network/Network.hh"
|
#include "mem/ruby/network/Network.hh"
|
||||||
#include "mem/ruby/system/NodeID.hh"
|
#include "mem/ruby/system/NodeID.hh"
|
||||||
|
#include "sim/sim_object.hh"
|
||||||
|
#include "params/SimpleNetwork.hh"
|
||||||
|
|
||||||
class NetDest;
|
class NetDest;
|
||||||
class MessageBuffer;
|
class MessageBuffer;
|
||||||
|
@ -83,13 +85,13 @@ class Topology;
|
||||||
class SimpleNetwork : public Network {
|
class SimpleNetwork : public Network {
|
||||||
public:
|
public:
|
||||||
// Constructors
|
// Constructors
|
||||||
// SimpleNetwork(int nodes);
|
typedef SimpleNetworkParams Params;
|
||||||
SimpleNetwork(const string & name);
|
SimpleNetwork(const Params *p);
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
~SimpleNetwork();
|
~SimpleNetwork();
|
||||||
|
|
||||||
void init(const vector<string> & argv);
|
void init();
|
||||||
|
|
||||||
// Public Methods
|
// Public Methods
|
||||||
void printStats(ostream& out) const;
|
void printStats(ostream& out) const;
|
||||||
|
|
5
src/mem/ruby/network/simple/SimpleNetwork.py
Normal file
5
src/mem/ruby/network/simple/SimpleNetwork.py
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
from m5.params import *
|
||||||
|
from Network import RubyNetwork
|
||||||
|
|
||||||
|
class SimpleNetwork(RubyNetwork):
|
||||||
|
type = 'SimpleNetwork'
|
|
@ -62,26 +62,18 @@ static Matrix shortest_path(const Matrix& weights, Matrix& latencies, Matrix& in
|
||||||
static bool link_is_shortest_path_to_node(SwitchID src, SwitchID next, SwitchID final, const Matrix& weights, const Matrix& dist);
|
static bool link_is_shortest_path_to_node(SwitchID src, SwitchID next, SwitchID final, const Matrix& weights, const Matrix& dist);
|
||||||
static NetDest shortest_path_to_node(SwitchID src, SwitchID next, const Matrix& weights, const Matrix& dist);
|
static NetDest shortest_path_to_node(SwitchID src, SwitchID next, const Matrix& weights, const Matrix& dist);
|
||||||
|
|
||||||
Topology::Topology(const string & name)
|
Topology::Topology(const Params *p)
|
||||||
: m_name(name)
|
: SimObject(p)
|
||||||
{
|
{
|
||||||
m_network_ptr = NULL;
|
// m_network_ptr = p->network;
|
||||||
|
m_connections = p->connections;
|
||||||
|
m_print_config = p->print_config;
|
||||||
m_nodes = MachineType_base_number(MachineType_NUM);
|
m_nodes = MachineType_base_number(MachineType_NUM);
|
||||||
m_number_of_switches = 0;
|
m_number_of_switches = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Topology::init(const vector<string> & argv)
|
void Topology::init()
|
||||||
{
|
{
|
||||||
for (size_t i=0; i<argv.size(); i+=2) {
|
|
||||||
if (argv[i] == "network")
|
|
||||||
m_network_ptr = RubySystem::getNetwork();
|
|
||||||
else if (argv[i] == "connections")
|
|
||||||
m_connections = argv[i+1];
|
|
||||||
else if (argv[i] == "print_config") {
|
|
||||||
m_print_config = string_to_bool(argv[i+1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(m_network_ptr != NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Topology::makeTopology()
|
void Topology::makeTopology()
|
||||||
|
@ -457,3 +449,8 @@ static NetDest shortest_path_to_node(SwitchID src, SwitchID next,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Topology *
|
||||||
|
TopologyParams::create()
|
||||||
|
{
|
||||||
|
return new Topology(this);
|
||||||
|
}
|
||||||
|
|
|
@ -50,22 +50,24 @@
|
||||||
#include "mem/ruby/common/Global.hh"
|
#include "mem/ruby/common/Global.hh"
|
||||||
#include "mem/gems_common/Vector.hh"
|
#include "mem/gems_common/Vector.hh"
|
||||||
#include "mem/ruby/system/NodeID.hh"
|
#include "mem/ruby/system/NodeID.hh"
|
||||||
|
#include "sim/sim_object.hh"
|
||||||
|
#include "params/Topology.hh"
|
||||||
|
|
||||||
class Network;
|
class Network;
|
||||||
class NetDest;
|
class NetDest;
|
||||||
|
|
||||||
typedef Vector < Vector <int> > Matrix;
|
typedef Vector < Vector <int> > Matrix;
|
||||||
|
|
||||||
class Topology {
|
class Topology : public SimObject {
|
||||||
public:
|
public:
|
||||||
// Constructors
|
// Constructors
|
||||||
// Topology(Network* network_ptr, int number_of_nodes);
|
typedef TopologyParams Params;
|
||||||
Topology(const string & name);
|
Topology(const Params *p);
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
virtual ~Topology() {}
|
virtual ~Topology() {}
|
||||||
|
|
||||||
virtual void init(const vector<string> & argv);
|
virtual void init();
|
||||||
|
|
||||||
// Public Methods
|
// Public Methods
|
||||||
void makeTopology();
|
void makeTopology();
|
||||||
|
@ -80,7 +82,6 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Private Methods
|
// Private Methods
|
||||||
void init();
|
|
||||||
SwitchID newSwitchID();
|
SwitchID newSwitchID();
|
||||||
void addLink(SwitchID src, SwitchID dest, int link_latency);
|
void addLink(SwitchID src, SwitchID dest, int link_latency);
|
||||||
void addLink(SwitchID src, SwitchID dest, int link_latency, int bw_multiplier);
|
void addLink(SwitchID src, SwitchID dest, int link_latency, int bw_multiplier);
|
||||||
|
|
|
@ -8,7 +8,7 @@ class Torus2DTopology : public Topology
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Torus2DTopology(const string & name);
|
Torus2DTopology(const string & name);
|
||||||
void init(const vector<string> & argv);
|
void init();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void construct();
|
void construct();
|
||||||
|
|
|
@ -63,6 +63,8 @@
|
||||||
#include "mem/ruby/common/Debug.hh"
|
#include "mem/ruby/common/Debug.hh"
|
||||||
#include "mem/protocol/MachineType.hh"
|
#include "mem/protocol/MachineType.hh"
|
||||||
|
|
||||||
|
#include "mem/ruby/system/System.hh"
|
||||||
|
|
||||||
// Allows use of times() library call, which determines virtual runtime
|
// Allows use of times() library call, which determines virtual runtime
|
||||||
#include <sys/times.h>
|
#include <sys/times.h>
|
||||||
|
|
||||||
|
@ -71,9 +73,9 @@ extern std::ostream * debug_cout_ptr;
|
||||||
static double process_memory_total();
|
static double process_memory_total();
|
||||||
static double process_memory_resident();
|
static double process_memory_resident();
|
||||||
|
|
||||||
Profiler::Profiler(const string & name)
|
Profiler::Profiler(const Params *p)
|
||||||
|
: SimObject(p)
|
||||||
{
|
{
|
||||||
m_name = name;
|
|
||||||
m_requestProfileMap_ptr = new Map<string, int>;
|
m_requestProfileMap_ptr = new Map<string, int>;
|
||||||
|
|
||||||
m_inst_profiler_ptr = NULL;
|
m_inst_profiler_ptr = NULL;
|
||||||
|
@ -83,6 +85,10 @@ Profiler::Profiler(const string & name)
|
||||||
m_stats_period = 1000000; // Default
|
m_stats_period = 1000000; // Default
|
||||||
m_periodic_output_file_ptr = &cerr;
|
m_periodic_output_file_ptr = &cerr;
|
||||||
|
|
||||||
|
m_hot_lines = p->hot_lines;
|
||||||
|
m_all_instructions = p->all_instructions;
|
||||||
|
|
||||||
|
RubySystem::m_profiler_ptr = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Profiler::~Profiler()
|
Profiler::~Profiler()
|
||||||
|
@ -136,17 +142,6 @@ void Profiler::init(const vector<string> & argv, vector<string> memory_control_n
|
||||||
m_hot_lines = false;
|
m_hot_lines = false;
|
||||||
m_all_instructions = false;
|
m_all_instructions = false;
|
||||||
|
|
||||||
for (size_t i=0; i<argv.size(); i+=2) {
|
|
||||||
if ( argv[i] == "hot_lines") {
|
|
||||||
m_hot_lines = (argv[i+1]=="true");
|
|
||||||
} else if ( argv[i] == "all_instructions") {
|
|
||||||
m_all_instructions = (argv[i+1]=="true");
|
|
||||||
}else {
|
|
||||||
cerr << "WARNING: Profiler: Unkown configuration parameter: " << argv[i] << endl;
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_address_profiler_ptr = new AddressProfiler;
|
m_address_profiler_ptr = new AddressProfiler;
|
||||||
m_address_profiler_ptr -> setHotLines(m_hot_lines);
|
m_address_profiler_ptr -> setHotLines(m_hot_lines);
|
||||||
m_address_profiler_ptr -> setAllInstructions(m_all_instructions);
|
m_address_profiler_ptr -> setAllInstructions(m_all_instructions);
|
||||||
|
@ -849,3 +844,9 @@ void Profiler::profileMemArbWait(string name, int cycles) { assert(m_memory_co
|
||||||
void Profiler::profileMemRandBusy(string name) { assert(m_memory_control_profilers.count(name) == 1); m_memory_control_profilers[name] -> m_memRandBusy++; }
|
void Profiler::profileMemRandBusy(string name) { assert(m_memory_control_profilers.count(name) == 1); m_memory_control_profilers[name] -> m_memRandBusy++; }
|
||||||
void Profiler::profileMemNotOld(string name) { assert(m_memory_control_profilers.count(name) == 1); m_memory_control_profilers[name] -> m_memNotOld++; }
|
void Profiler::profileMemNotOld(string name) { assert(m_memory_control_profilers.count(name) == 1); m_memory_control_profilers[name] -> m_memNotOld++; }
|
||||||
|
|
||||||
|
|
||||||
|
Profiler *
|
||||||
|
RubyProfilerParams::create()
|
||||||
|
{
|
||||||
|
return new Profiler(this);
|
||||||
|
}
|
||||||
|
|
|
@ -71,6 +71,9 @@
|
||||||
#include "mem/protocol/GenericRequestType.hh"
|
#include "mem/protocol/GenericRequestType.hh"
|
||||||
#include "mem/ruby/system/MemoryControl.hh"
|
#include "mem/ruby/system/MemoryControl.hh"
|
||||||
|
|
||||||
|
#include "params/RubyProfiler.hh"
|
||||||
|
#include "sim/sim_object.hh"
|
||||||
|
|
||||||
class CacheMsg;
|
class CacheMsg;
|
||||||
class AddressProfiler;
|
class AddressProfiler;
|
||||||
|
|
||||||
|
@ -99,10 +102,11 @@ struct memory_control_profiler {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Profiler : public Consumer {
|
class Profiler : public SimObject, public Consumer {
|
||||||
public:
|
public:
|
||||||
// Constructors
|
// Constructors
|
||||||
Profiler(const string & name);
|
typedef RubyProfilerParams Params;
|
||||||
|
Profiler(const Params *);
|
||||||
|
|
||||||
void init(const vector<string> & argv, vector<string> memory_control_names);
|
void init(const vector<string> & argv, vector<string> memory_control_names);
|
||||||
|
|
||||||
|
@ -260,8 +264,6 @@ private:
|
||||||
//added by SS
|
//added by SS
|
||||||
bool m_hot_lines;
|
bool m_hot_lines;
|
||||||
bool m_all_instructions;
|
bool m_all_instructions;
|
||||||
string m_name;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Output operator declaration
|
// Output operator declaration
|
||||||
|
|
8
src/mem/ruby/profiler/Profiler.py
Normal file
8
src/mem/ruby/profiler/Profiler.py
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
from m5.params import *
|
||||||
|
from m5.SimObject import SimObject
|
||||||
|
|
||||||
|
class RubyProfiler(SimObject):
|
||||||
|
type = 'RubyProfiler'
|
||||||
|
cxx_class = 'Profiler'
|
||||||
|
hot_lines = Param.Bool(False, "")
|
||||||
|
all_instructions = Param.Bool(False, "")
|
|
@ -33,6 +33,8 @@ Import('*')
|
||||||
if not env['RUBY']:
|
if not env['RUBY']:
|
||||||
Return()
|
Return()
|
||||||
|
|
||||||
|
SimObject('Profiler.py')
|
||||||
|
|
||||||
Source('AccessTraceForAddress.cc')
|
Source('AccessTraceForAddress.cc')
|
||||||
Source('AddressProfiler.cc')
|
Source('AddressProfiler.cc')
|
||||||
Source('CacheProfiler.cc')
|
Source('CacheProfiler.cc')
|
||||||
|
|
|
@ -33,6 +33,8 @@ Import('*')
|
||||||
if not env['RUBY']:
|
if not env['RUBY']:
|
||||||
Return()
|
Return()
|
||||||
|
|
||||||
|
SimObject('Tracer.py')
|
||||||
|
|
||||||
Source('CacheRecorder.cc')
|
Source('CacheRecorder.cc')
|
||||||
Source('Tracer.cc')
|
Source('Tracer.cc')
|
||||||
Source('TraceRecord.cc', Werror=False)
|
Source('TraceRecord.cc', Werror=False)
|
||||||
|
|
|
@ -39,10 +39,13 @@
|
||||||
#include "mem/ruby/system/System.hh"
|
#include "mem/ruby/system/System.hh"
|
||||||
|
|
||||||
//added by SS
|
//added by SS
|
||||||
Tracer::Tracer(const string & name)
|
Tracer::Tracer(const Params *p)
|
||||||
|
: SimObject(p)
|
||||||
{
|
{
|
||||||
m_name = name;
|
|
||||||
m_enabled = false;
|
m_enabled = false;
|
||||||
|
m_warmup_length = p->warmup_length;
|
||||||
|
assert(m_warmup_length > 0);
|
||||||
|
RubySystem::m_tracer_ptr = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
//commented by SS
|
//commented by SS
|
||||||
|
@ -55,20 +58,8 @@ Tracer::~Tracer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tracer::init(const vector<string> & argv)
|
void Tracer::init()
|
||||||
{
|
{
|
||||||
m_warmup_length = 0;
|
|
||||||
|
|
||||||
for (size_t i=0; i<argv.size(); i+=2) {
|
|
||||||
if ( argv[i] == "warmup_length") {
|
|
||||||
m_warmup_length = atoi(argv[i+1].c_str());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cerr << "WARNING: Tracer: Unkown configuration parameter: " << argv[i] << endl;
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(m_warmup_length > 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tracer::startTrace(string filename)
|
void Tracer::startTrace(string filename)
|
||||||
|
@ -155,3 +146,10 @@ int Tracer::playbackTrace(string filename)
|
||||||
void Tracer::print(ostream& out) const
|
void Tracer::print(ostream& out) const
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Tracer *
|
||||||
|
RubyTracerParams::create()
|
||||||
|
{
|
||||||
|
return new Tracer(this);
|
||||||
|
}
|
||||||
|
|
|
@ -43,17 +43,22 @@
|
||||||
#include "mem/ruby/common/Global.hh"
|
#include "mem/ruby/common/Global.hh"
|
||||||
#include "mem/ruby/system/NodeID.hh"
|
#include "mem/ruby/system/NodeID.hh"
|
||||||
#include "mem/protocol/CacheRequestType.hh"
|
#include "mem/protocol/CacheRequestType.hh"
|
||||||
|
#include "sim/sim_object.hh"
|
||||||
|
|
||||||
|
#include "params/RubyTracer.hh"
|
||||||
|
|
||||||
#include "gzstream.hh"
|
#include "gzstream.hh"
|
||||||
|
|
||||||
template <class TYPE> class PrioHeap;
|
template <class TYPE> class PrioHeap;
|
||||||
class Address;
|
class Address;
|
||||||
class TraceRecord;
|
class TraceRecord;
|
||||||
|
|
||||||
class Tracer {
|
class Tracer : public SimObject {
|
||||||
public:
|
public:
|
||||||
// Constructors
|
// Constructors
|
||||||
// Tracer();
|
// Tracer();
|
||||||
Tracer(const string & name);
|
typedef RubyTracerParams Params;
|
||||||
|
Tracer(const Params *p);
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
~Tracer();
|
~Tracer();
|
||||||
|
@ -68,7 +73,7 @@ public:
|
||||||
|
|
||||||
// Public Class Methods
|
// Public Class Methods
|
||||||
int playbackTrace(string filename);
|
int playbackTrace(string filename);
|
||||||
void init(const vector<string> & argv);
|
void init();
|
||||||
private:
|
private:
|
||||||
// Private Methods
|
// Private Methods
|
||||||
|
|
||||||
|
@ -82,7 +87,6 @@ private:
|
||||||
|
|
||||||
//added by SS
|
//added by SS
|
||||||
int m_warmup_length;
|
int m_warmup_length;
|
||||||
string m_name;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Output operator declaration
|
// Output operator declaration
|
||||||
|
|
7
src/mem/ruby/recorder/Tracer.py
Normal file
7
src/mem/ruby/recorder/Tracer.py
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
from m5.params import *
|
||||||
|
from m5.SimObject import SimObject
|
||||||
|
|
||||||
|
class RubyTracer(SimObject):
|
||||||
|
type = 'RubyTracer'
|
||||||
|
cxx_class = 'Tracer'
|
||||||
|
warmup_length = Param.Int(100000, "")
|
|
@ -2,6 +2,9 @@
|
||||||
#ifndef ABSTRACTCONTROLLER_H
|
#ifndef ABSTRACTCONTROLLER_H
|
||||||
#define ABSTRACTCONTROLLER_H
|
#define ABSTRACTCONTROLLER_H
|
||||||
|
|
||||||
|
#include "sim/sim_object.hh"
|
||||||
|
#include "params/RubyController.hh"
|
||||||
|
|
||||||
#include "mem/ruby/common/Consumer.hh"
|
#include "mem/ruby/common/Consumer.hh"
|
||||||
#include "mem/protocol/MachineType.hh"
|
#include "mem/protocol/MachineType.hh"
|
||||||
#include "mem/ruby/common/Address.hh"
|
#include "mem/ruby/common/Address.hh"
|
||||||
|
@ -9,9 +12,10 @@
|
||||||
class MessageBuffer;
|
class MessageBuffer;
|
||||||
class Network;
|
class Network;
|
||||||
|
|
||||||
class AbstractController : public Consumer {
|
class AbstractController : public SimObject, public Consumer {
|
||||||
public:
|
public:
|
||||||
AbstractController() {}
|
typedef RubyControllerParams Params;
|
||||||
|
AbstractController(const Params *p) : SimObject(p) {}
|
||||||
virtual void init(Network* net_ptr, const vector<string> & argv) = 0;
|
virtual void init(Network* net_ptr, const vector<string> & argv) = 0;
|
||||||
|
|
||||||
// returns the number of controllers created of the specific subtype
|
// returns the number of controllers created of the specific subtype
|
||||||
|
|
13
src/mem/ruby/slicc_interface/Controller.py
Normal file
13
src/mem/ruby/slicc_interface/Controller.py
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
from m5.params import *
|
||||||
|
from m5.SimObject import SimObject
|
||||||
|
|
||||||
|
class RubyController(SimObject):
|
||||||
|
type = 'RubyController'
|
||||||
|
cxx_class = 'AbstractController'
|
||||||
|
abstract = True
|
||||||
|
version = Param.Int("")
|
||||||
|
transitions_per_cycle = \
|
||||||
|
Param.Int(32, "no. of SLICC state machine transitions per cycle")
|
||||||
|
buffer_size = Param.Int(0, "max buffer size 0 means infinite")
|
||||||
|
recycle_latency = Param.Int(10, "")
|
||||||
|
number_of_TBEs = Param.Int(256, "")
|
|
@ -33,6 +33,8 @@ Import('*')
|
||||||
if not env['RUBY']:
|
if not env['RUBY']:
|
||||||
Return()
|
Return()
|
||||||
|
|
||||||
|
SimObject('Controller.py')
|
||||||
|
|
||||||
Source('AbstractCacheEntry.cc')
|
Source('AbstractCacheEntry.cc')
|
||||||
Source('RubySlicc_Profiler_interface.cc')
|
Source('RubySlicc_Profiler_interface.cc')
|
||||||
Source('RubySlicc_ComponentMapping.cc')
|
Source('RubySlicc_ComponentMapping.cc')
|
||||||
|
|
12
src/mem/ruby/system/Cache.py
Normal file
12
src/mem/ruby/system/Cache.py
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
from m5.params import *
|
||||||
|
from m5.SimObject import SimObject
|
||||||
|
from Controller import RubyController
|
||||||
|
|
||||||
|
class RubyCache(SimObject):
|
||||||
|
type = 'RubyCache'
|
||||||
|
cxx_class = 'CacheMemory'
|
||||||
|
size = Param.Int("");
|
||||||
|
latency = Param.Int("");
|
||||||
|
assoc = Param.Int("");
|
||||||
|
replacement_policy = Param.String("PSEUDO_LRU", "");
|
||||||
|
controller = Param.RubyController("");
|
|
@ -47,41 +47,20 @@ ostream& operator<<(ostream& out, const CacheMemory& obj)
|
||||||
|
|
||||||
// ****************************************************************
|
// ****************************************************************
|
||||||
|
|
||||||
CacheMemory::CacheMemory(const string & name)
|
CacheMemory *
|
||||||
: m_cache_name(name)
|
RubyCacheParams::create()
|
||||||
{
|
{
|
||||||
m_profiler_ptr = new CacheProfiler(name);
|
return new CacheMemory(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CacheMemory::init(const vector<string> & argv)
|
CacheMemory::CacheMemory(const Params *p)
|
||||||
|
: SimObject(p)
|
||||||
{
|
{
|
||||||
int cache_size = -1;
|
int cache_size = p->size;
|
||||||
string policy;
|
m_latency = p->latency;
|
||||||
|
m_cache_assoc = p->assoc;
|
||||||
m_num_last_level_caches =
|
string policy = p->replacement_policy;
|
||||||
MachineType_base_count(MachineType_FIRST);
|
m_controller = p->controller;
|
||||||
m_controller = NULL;
|
|
||||||
for (uint32 i=0; i<argv.size(); i+=2) {
|
|
||||||
if (argv[i] == "size") {
|
|
||||||
cache_size = atoi(argv[i+1].c_str());
|
|
||||||
} else if (argv[i] == "latency") {
|
|
||||||
m_latency = atoi(argv[i+1].c_str());
|
|
||||||
} else if (argv[i] == "assoc") {
|
|
||||||
m_cache_assoc = atoi(argv[i+1].c_str());
|
|
||||||
} else if (argv[i] == "replacement_policy") {
|
|
||||||
policy = argv[i+1];
|
|
||||||
} else if (argv[i] == "controller") {
|
|
||||||
m_controller = RubySystem::getController(argv[i+1]);
|
|
||||||
if (m_last_level_machine_type < m_controller->getMachineType()) {
|
|
||||||
m_num_last_level_caches =
|
|
||||||
MachineType_base_count(m_controller->getMachineType());
|
|
||||||
m_last_level_machine_type =
|
|
||||||
m_controller->getMachineType();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cerr << "WARNING: CacheMemory: Unknown configuration parameter: " << argv[i] << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int num_lines = cache_size/RubySystem::getBlockSizeBytes();
|
int num_lines = cache_size/RubySystem::getBlockSizeBytes();
|
||||||
m_cache_num_sets = num_lines / m_cache_assoc;
|
m_cache_num_sets = num_lines / m_cache_assoc;
|
||||||
|
@ -95,6 +74,24 @@ void CacheMemory::init(const vector<string> & argv)
|
||||||
else
|
else
|
||||||
assert(false);
|
assert(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CacheMemory::init()
|
||||||
|
{
|
||||||
|
m_num_last_level_caches =
|
||||||
|
MachineType_base_count(MachineType_FIRST);
|
||||||
|
#if 0
|
||||||
|
for (uint32 i=0; i<argv.size(); i+=2) {
|
||||||
|
if (m_last_level_machine_type < m_controller->getMachineType()) {
|
||||||
|
m_num_last_level_caches =
|
||||||
|
MachineType_base_count(m_controller->getMachineType());
|
||||||
|
m_last_level_machine_type =
|
||||||
|
m_controller->getMachineType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
m_cache.setSize(m_cache_num_sets);
|
m_cache.setSize(m_cache_num_sets);
|
||||||
m_locked.setSize(m_cache_num_sets);
|
m_locked.setSize(m_cache_num_sets);
|
||||||
for (int i = 0; i < m_cache_num_sets; i++) {
|
for (int i = 0; i < m_cache_num_sets; i++) {
|
||||||
|
|
|
@ -38,6 +38,9 @@
|
||||||
#ifndef CACHEMEMORY_H
|
#ifndef CACHEMEMORY_H
|
||||||
#define CACHEMEMORY_H
|
#define CACHEMEMORY_H
|
||||||
|
|
||||||
|
#include "sim/sim_object.hh"
|
||||||
|
#include "params/RubyCache.hh"
|
||||||
|
|
||||||
#include "mem/ruby/common/Global.hh"
|
#include "mem/ruby/common/Global.hh"
|
||||||
#include "mem/protocol/AccessPermission.hh"
|
#include "mem/protocol/AccessPermission.hh"
|
||||||
#include "mem/ruby/common/Address.hh"
|
#include "mem/ruby/common/Address.hh"
|
||||||
|
@ -57,12 +60,14 @@
|
||||||
#include "base/hashmap.hh"
|
#include "base/hashmap.hh"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class CacheMemory {
|
class CacheMemory : public SimObject {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
typedef RubyCacheParams Params;
|
||||||
// Constructors
|
// Constructors
|
||||||
CacheMemory(const string & name);
|
CacheMemory(const Params *p);
|
||||||
void init(const vector<string> & argv);
|
// CacheMemory(const string & name);
|
||||||
|
void init();
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
~CacheMemory();
|
~CacheMemory();
|
||||||
|
|
|
@ -8,25 +8,13 @@
|
||||||
#include "mem/protocol/SequencerRequestType.hh"
|
#include "mem/protocol/SequencerRequestType.hh"
|
||||||
#include "mem/ruby/system/System.hh"
|
#include "mem/ruby/system/System.hh"
|
||||||
|
|
||||||
DMASequencer::DMASequencer(const string & name)
|
DMASequencer::DMASequencer(const Params *p)
|
||||||
: RubyPort(name)
|
: RubyPort(p)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void DMASequencer::init(const vector<string> & argv)
|
void DMASequencer::init()
|
||||||
{
|
{
|
||||||
m_version = -1;
|
|
||||||
m_controller = NULL;
|
|
||||||
for (size_t i=0;i<argv.size();i+=2) {
|
|
||||||
if (argv[i] == "controller")
|
|
||||||
m_controller = RubySystem::getController(argv[i+1]);
|
|
||||||
else if (argv[i] == "version")
|
|
||||||
m_version = atoi(argv[i+1].c_str());
|
|
||||||
}
|
|
||||||
assert(m_controller != NULL);
|
|
||||||
assert(m_version != -1);
|
|
||||||
|
|
||||||
m_mandatory_q_ptr = m_controller->getMandatoryQueue();
|
|
||||||
m_is_busy = false;
|
m_is_busy = false;
|
||||||
m_data_block_mask = ~ (~0 << RubySystem::getBlockSizeBits());
|
m_data_block_mask = ~ (~0 << RubySystem::getBlockSizeBits());
|
||||||
}
|
}
|
||||||
|
@ -135,3 +123,10 @@ void DMASequencer::printConfig(ostream & out)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DMASequencer *
|
||||||
|
DMASequencerParams::create()
|
||||||
|
{
|
||||||
|
return new DMASequencer(this);
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#include "mem/ruby/common/DataBlock.hh"
|
#include "mem/ruby/common/DataBlock.hh"
|
||||||
#include "mem/ruby/system/RubyPort.hh"
|
#include "mem/ruby/system/RubyPort.hh"
|
||||||
|
|
||||||
|
#include "params/DMASequencer.hh"
|
||||||
|
|
||||||
struct DMARequest {
|
struct DMARequest {
|
||||||
uint64_t start_paddr;
|
uint64_t start_paddr;
|
||||||
int len;
|
int len;
|
||||||
|
@ -16,13 +18,11 @@ struct DMARequest {
|
||||||
int64_t id;
|
int64_t id;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MessageBuffer;
|
|
||||||
class AbstractController;
|
|
||||||
|
|
||||||
class DMASequencer :public RubyPort {
|
class DMASequencer :public RubyPort {
|
||||||
public:
|
public:
|
||||||
DMASequencer(const string & name);
|
typedef DMASequencerParams Params;
|
||||||
void init(const vector<string> & argv);
|
DMASequencer(const Params *);
|
||||||
|
void init();
|
||||||
/* external interface */
|
/* external interface */
|
||||||
int64_t makeRequest(const RubyRequest & request);
|
int64_t makeRequest(const RubyRequest & request);
|
||||||
bool isReady(const RubyRequest & request, bool dont_set = false) { assert(0); return false;};
|
bool isReady(const RubyRequest & request, bool dont_set = false) { assert(0); return false;};
|
||||||
|
@ -39,13 +39,10 @@ private:
|
||||||
void issueNext();
|
void issueNext();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_version;
|
|
||||||
AbstractController* m_controller;
|
|
||||||
bool m_is_busy;
|
bool m_is_busy;
|
||||||
uint64_t m_data_block_mask;
|
uint64_t m_data_block_mask;
|
||||||
DMARequest active_request;
|
DMARequest active_request;
|
||||||
int num_active_requests;
|
int num_active_requests;
|
||||||
MessageBuffer* m_mandatory_q_ptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DMACONTROLLER_H
|
#endif // DMACONTROLLER_H
|
||||||
|
|
|
@ -46,29 +46,17 @@ int DirectoryMemory::m_num_directories = 0;
|
||||||
int DirectoryMemory::m_num_directories_bits = 0;
|
int DirectoryMemory::m_num_directories_bits = 0;
|
||||||
uint64_t DirectoryMemory::m_total_size_bytes = 0;
|
uint64_t DirectoryMemory::m_total_size_bytes = 0;
|
||||||
|
|
||||||
DirectoryMemory::DirectoryMemory(const string & name)
|
DirectoryMemory::DirectoryMemory(const Params *p)
|
||||||
: m_name(name)
|
: SimObject(p)
|
||||||
{
|
{
|
||||||
|
m_version = p->version;
|
||||||
|
m_size_bytes = p->size_mb * static_cast<uint64>(1<<20);
|
||||||
|
m_size_bits = log_int(m_size_bytes);
|
||||||
|
m_controller = p->controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DirectoryMemory::init(const vector<string> & argv)
|
void DirectoryMemory::init()
|
||||||
{
|
{
|
||||||
m_controller = NULL;
|
|
||||||
for (vector<string>::const_iterator it = argv.begin(); it != argv.end(); it++) {
|
|
||||||
if ( (*it) == "version" )
|
|
||||||
m_version = atoi( (*(++it)).c_str() );
|
|
||||||
else if ( (*it) == "size_mb" ) {
|
|
||||||
m_size_bytes = atoi((*(++it)).c_str()) * static_cast<uint64>(1<<20);
|
|
||||||
m_size_bits = log_int(m_size_bytes);
|
|
||||||
} else if ( (*it) == "controller" ) {
|
|
||||||
m_controller = RubySystem::getController((*(++it)));
|
|
||||||
} else {
|
|
||||||
cerr << "DirectoryMemory: Unkown config parameter: " << (*it) << endl;
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(m_controller != NULL);
|
|
||||||
|
|
||||||
m_num_entries = m_size_bytes / RubySystem::getBlockSizeBytes();
|
m_num_entries = m_size_bytes / RubySystem::getBlockSizeBytes();
|
||||||
m_entries = new Directory_Entry*[m_num_entries];
|
m_entries = new Directory_Entry*[m_num_entries];
|
||||||
for (int i=0; i < m_num_entries; i++)
|
for (int i=0; i < m_num_entries; i++)
|
||||||
|
@ -205,3 +193,8 @@ void DirectoryMemory::print(ostream& out) const
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DirectoryMemory *
|
||||||
|
RubyDirectoryMemoryParams::create()
|
||||||
|
{
|
||||||
|
return new DirectoryMemory(this);
|
||||||
|
}
|
||||||
|
|
|
@ -43,14 +43,17 @@
|
||||||
#include "mem/ruby/common/Address.hh"
|
#include "mem/ruby/common/Address.hh"
|
||||||
#include "mem/ruby/system/MemoryVector.hh"
|
#include "mem/ruby/system/MemoryVector.hh"
|
||||||
#include "mem/protocol/Directory_Entry.hh"
|
#include "mem/protocol/Directory_Entry.hh"
|
||||||
|
#include "sim/sim_object.hh"
|
||||||
|
#include "params/RubyDirectoryMemory.hh"
|
||||||
|
|
||||||
class AbstractController;
|
class AbstractController;
|
||||||
|
|
||||||
class DirectoryMemory {
|
class DirectoryMemory : public SimObject {
|
||||||
public:
|
public:
|
||||||
// Constructors
|
// Constructors
|
||||||
DirectoryMemory(const string & name);
|
typedef RubyDirectoryMemoryParams Params;
|
||||||
void init(const vector<string> & argv);
|
DirectoryMemory(const Params *p);
|
||||||
|
void init();
|
||||||
// DirectoryMemory(int version);
|
// DirectoryMemory(int version);
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
|
|
10
src/mem/ruby/system/DirectoryMemory.py
Normal file
10
src/mem/ruby/system/DirectoryMemory.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
from m5.params import *
|
||||||
|
from m5.proxy import *
|
||||||
|
from m5.SimObject import SimObject
|
||||||
|
|
||||||
|
class RubyDirectoryMemory(SimObject):
|
||||||
|
type = 'RubyDirectoryMemory'
|
||||||
|
cxx_class = 'DirectoryMemory'
|
||||||
|
version = Param.Int(0, "")
|
||||||
|
size_mb = Param.Int(1024, "")
|
||||||
|
controller = Param.RubyController(Parent.any, "")
|
|
@ -151,61 +151,30 @@ ostream& operator<<(ostream& out, const MemoryControl& obj)
|
||||||
// ****************************************************************
|
// ****************************************************************
|
||||||
|
|
||||||
// CONSTRUCTOR
|
// CONSTRUCTOR
|
||||||
MemoryControl::MemoryControl(const string & name)
|
MemoryControl::MemoryControl(const Params *p)
|
||||||
: m_name(name)
|
: SimObject(p)
|
||||||
{
|
{
|
||||||
m_name = name;
|
m_mem_bus_cycle_multiplier = p->mem_bus_cycle_multiplier;
|
||||||
// printf ("MemoryControl name is %s \n", m_name.c_str());
|
m_banks_per_rank = p->banks_per_rank;
|
||||||
|
m_ranks_per_dimm = p->ranks_per_dimm;
|
||||||
|
m_dimms_per_channel = p->dimms_per_channel;
|
||||||
|
m_bank_bit_0 = p->bank_bit_0;
|
||||||
|
m_rank_bit_0 = p->rank_bit_0;
|
||||||
|
m_dimm_bit_0 = p->dimm_bit_0;
|
||||||
|
m_bank_queue_size = p->bank_queue_size;
|
||||||
|
m_bank_busy_time = p->bank_busy_time;
|
||||||
|
m_rank_rank_delay = p->rank_rank_delay;
|
||||||
|
m_read_write_delay = p->read_write_delay;
|
||||||
|
m_basic_bus_busy_time = p->basic_bus_busy_time;
|
||||||
|
m_mem_ctl_latency = p->mem_ctl_latency;
|
||||||
|
m_refresh_period = p->refresh_period;
|
||||||
|
m_tFaw = p->tFaw;
|
||||||
|
m_mem_random_arbitrate = p->mem_random_arbitrate;
|
||||||
|
m_mem_fixed_delay = p->mem_fixed_delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryControl::init(const vector<string> & argv)
|
void MemoryControl::init()
|
||||||
{
|
{
|
||||||
|
|
||||||
for (vector<string>::const_iterator it = argv.begin(); it != argv.end(); it++) {
|
|
||||||
if ( (*it) == "version" )
|
|
||||||
m_version = atoi( (*(++it)).c_str() );
|
|
||||||
else if ( (*it) == "mem_bus_cycle_multiplier" ) {
|
|
||||||
m_mem_bus_cycle_multiplier = atoi((*(++it)).c_str());
|
|
||||||
} else if ( (*it) == "banks_per_rank" ) {
|
|
||||||
m_banks_per_rank = atoi((*(++it)).c_str());
|
|
||||||
} else if ( (*it) == "ranks_per_dimm" ) {
|
|
||||||
m_ranks_per_dimm = atoi((*(++it)).c_str());
|
|
||||||
} else if ( (*it) == "dimms_per_channel" ) {
|
|
||||||
m_dimms_per_channel = atoi((*(++it)).c_str());
|
|
||||||
} else if ( (*it) == "bank_bit_0" ) {
|
|
||||||
m_bank_bit_0 = atoi((*(++it)).c_str());
|
|
||||||
} else if ( (*it) == "rank_bit_0" ) {
|
|
||||||
m_rank_bit_0 = atoi((*(++it)).c_str());
|
|
||||||
} else if ( (*it) == "dimm_bit_0" ) {
|
|
||||||
m_dimm_bit_0 = atoi((*(++it)).c_str());
|
|
||||||
} else if ( (*it) == "bank_queue_size" ) {
|
|
||||||
m_bank_queue_size = atoi((*(++it)).c_str());
|
|
||||||
} else if ( (*it) == "bank_busy_time" ) {
|
|
||||||
m_bank_busy_time = atoi((*(++it)).c_str());
|
|
||||||
} else if ( (*it) == "rank_rank_delay" ) {
|
|
||||||
m_rank_rank_delay = atoi((*(++it)).c_str());
|
|
||||||
} else if ( (*it) == "read_write_delay" ) {
|
|
||||||
m_read_write_delay = atoi((*(++it)).c_str());
|
|
||||||
} else if ( (*it) == "basic_bus_busy_time" ) {
|
|
||||||
m_basic_bus_busy_time = atoi((*(++it)).c_str());
|
|
||||||
} else if ( (*it) == "mem_ctl_latency" ) {
|
|
||||||
m_mem_ctl_latency = atoi((*(++it)).c_str());
|
|
||||||
} else if ( (*it) == "refresh_period" ) {
|
|
||||||
m_refresh_period = atoi((*(++it)).c_str());
|
|
||||||
} else if ( (*it) == "tFaw" ) {
|
|
||||||
m_tFaw = atoi((*(++it)).c_str());
|
|
||||||
} else if ( (*it) == "mem_random_arbitrate" ) {
|
|
||||||
m_mem_random_arbitrate = atoi((*(++it)).c_str());
|
|
||||||
} else if ( (*it) == "mem_fixed_delay" ) {
|
|
||||||
m_mem_fixed_delay = atoi((*(++it)).c_str());
|
|
||||||
}
|
|
||||||
// } else
|
|
||||||
// assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////
|
|
||||||
//m_version = version;
|
|
||||||
m_msg_counter = 0;
|
m_msg_counter = 0;
|
||||||
|
|
||||||
m_debug = 0;
|
m_debug = 0;
|
||||||
|
@ -351,7 +320,6 @@ void MemoryControl::print (ostream& out) const {
|
||||||
|
|
||||||
|
|
||||||
void MemoryControl::printConfig (ostream& out) {
|
void MemoryControl::printConfig (ostream& out) {
|
||||||
out << "Memory Control " << m_version << ":" << endl;
|
|
||||||
out << " Ruby cycles per memory cycle: " << m_mem_bus_cycle_multiplier << endl;
|
out << " Ruby cycles per memory cycle: " << m_mem_bus_cycle_multiplier << endl;
|
||||||
out << " Basic read latency: " << m_mem_ctl_latency << endl;
|
out << " Basic read latency: " << m_mem_ctl_latency << endl;
|
||||||
if (m_mem_fixed_delay) {
|
if (m_mem_fixed_delay) {
|
||||||
|
@ -662,4 +630,9 @@ void MemoryControl::wakeup () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MemoryControl *
|
||||||
|
RubyMemoryControlParams::create()
|
||||||
|
{
|
||||||
|
return new MemoryControl(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,8 @@
|
||||||
#include "mem/protocol/MemoryMsg.hh"
|
#include "mem/protocol/MemoryMsg.hh"
|
||||||
#include "mem/ruby/common/Consumer.hh"
|
#include "mem/ruby/common/Consumer.hh"
|
||||||
#include "mem/ruby/system/AbstractMemOrCache.hh"
|
#include "mem/ruby/system/AbstractMemOrCache.hh"
|
||||||
|
#include "sim/sim_object.hh"
|
||||||
|
#include "params/RubyMemoryControl.hh"
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
|
@ -62,12 +64,13 @@
|
||||||
|
|
||||||
class Consumer;
|
class Consumer;
|
||||||
|
|
||||||
class MemoryControl : public Consumer, public AbstractMemOrCache {
|
class MemoryControl : public SimObject, public Consumer, public AbstractMemOrCache {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
MemoryControl(const string & name);
|
typedef RubyMemoryControlParams Params;
|
||||||
void init(const vector<string> & argv);
|
MemoryControl(const Params *p);
|
||||||
|
void init();
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
~MemoryControl ();
|
~MemoryControl ();
|
||||||
|
@ -122,7 +125,6 @@ private:
|
||||||
Consumer* m_consumer_ptr; // Consumer to signal a wakeup()
|
Consumer* m_consumer_ptr; // Consumer to signal a wakeup()
|
||||||
string m_name;
|
string m_name;
|
||||||
string m_description;
|
string m_description;
|
||||||
int m_version;
|
|
||||||
int m_msg_counter;
|
int m_msg_counter;
|
||||||
int m_awakened;
|
int m_awakened;
|
||||||
|
|
||||||
|
|
23
src/mem/ruby/system/MemoryControl.py
Normal file
23
src/mem/ruby/system/MemoryControl.py
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
from m5.params import *
|
||||||
|
from m5.SimObject import SimObject
|
||||||
|
|
||||||
|
class RubyMemoryControl(SimObject):
|
||||||
|
type = 'RubyMemoryControl'
|
||||||
|
cxx_class = 'MemoryControl'
|
||||||
|
mem_bus_cycle_multiplier = Param.Int(10, "");
|
||||||
|
banks_per_rank = Param.Int(8, "");
|
||||||
|
ranks_per_dimm = Param.Int(2, "");
|
||||||
|
dimms_per_channel = Param.Int(2, "");
|
||||||
|
bank_bit_0 = Param.Int(8, "");
|
||||||
|
rank_bit_0 = Param.Int(11, "");
|
||||||
|
dimm_bit_0 = Param.Int(12, "");
|
||||||
|
bank_queue_size = Param.Int(12, "");
|
||||||
|
bank_busy_time = Param.Int(11, "");
|
||||||
|
rank_rank_delay = Param.Int(1, "");
|
||||||
|
read_write_delay = Param.Int(2, "");
|
||||||
|
basic_bus_busy_time = Param.Int(2, "");
|
||||||
|
mem_ctl_latency = Param.Int(12, "");
|
||||||
|
refresh_period = Param.Int(1560, "");
|
||||||
|
tFaw = Param.Int(0, "");
|
||||||
|
mem_random_arbitrate = Param.Int(0, "");
|
||||||
|
mem_fixed_delay = Param.Int(0, "");
|
|
@ -1,5 +1,57 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2009 Advanced Micro Devices, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mem/physical.hh"
|
||||||
#include "mem/ruby/system/RubyPort.hh"
|
#include "mem/ruby/system/RubyPort.hh"
|
||||||
|
#include "mem/ruby/slicc_interface/AbstractController.hh"
|
||||||
|
|
||||||
//void (*RubyPort::m_hit_callback)(int64_t) = NULL;
|
//void (*RubyPort::m_hit_callback)(int64_t) = NULL;
|
||||||
uint16_t RubyPort::m_num_ports = 0;
|
uint16_t RubyPort::m_num_ports = 0;
|
||||||
|
|
||||||
|
RubyPort::RubyPort(const Params *p)
|
||||||
|
: MemObject(p)
|
||||||
|
{
|
||||||
|
m_version = p->version;
|
||||||
|
assert(m_version != -1);
|
||||||
|
m_controller = p->controller;
|
||||||
|
assert(m_controller != NULL);
|
||||||
|
|
||||||
|
m_mandatory_q_ptr = m_controller->getMandatoryQueue();
|
||||||
|
|
||||||
|
m_port_id = m_num_ports++;
|
||||||
|
m_request_cnt = 0;
|
||||||
|
m_hit_callback = NULL;
|
||||||
|
assert(m_num_ports <= 2048); // see below for reason
|
||||||
|
}
|
||||||
|
|
||||||
|
Port *
|
||||||
|
RubyPort::getPort(const std::string &if_name, int idx)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,32 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2009 Advanced Micro Devices, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met: redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer;
|
||||||
|
* redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution;
|
||||||
|
* neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef RUBYPORT_H
|
#ifndef RUBYPORT_H
|
||||||
#define RUBYPORT_H
|
#define RUBYPORT_H
|
||||||
|
|
||||||
|
@ -5,20 +34,24 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "mem/mem_object.hh"
|
||||||
|
#include "mem/tport.hh"
|
||||||
|
|
||||||
|
#include "params/RubyPort.hh"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
class RubyPort {
|
class MessageBuffer;
|
||||||
|
class AbstractController;
|
||||||
|
|
||||||
|
class RubyPort : public MemObject {
|
||||||
public:
|
public:
|
||||||
RubyPort(const string & name)
|
typedef RubyPortParams Params;
|
||||||
: m_name(name)
|
RubyPort(const Params *p);
|
||||||
{
|
|
||||||
m_port_id = m_num_ports++;
|
|
||||||
m_request_cnt = 0;
|
|
||||||
m_hit_callback = NULL;
|
|
||||||
assert(m_num_ports <= 2048); // see below for reason
|
|
||||||
}
|
|
||||||
virtual ~RubyPort() {}
|
virtual ~RubyPort() {}
|
||||||
|
|
||||||
|
Port *getPort(const std::string &if_name, int idx);
|
||||||
|
|
||||||
virtual int64_t makeRequest(const RubyRequest & request) = 0;
|
virtual int64_t makeRequest(const RubyRequest & request) = 0;
|
||||||
|
|
||||||
void registerHitCallback(void (*hit_callback)(int64_t request_id)) {
|
void registerHitCallback(void (*hit_callback)(int64_t request_id)) {
|
||||||
|
@ -51,6 +84,10 @@ protected:
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int m_version;
|
||||||
|
AbstractController* m_controller;
|
||||||
|
MessageBuffer* m_mandatory_q_ptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static uint16_t m_num_ports;
|
static uint16_t m_num_ports;
|
||||||
uint16_t m_port_id;
|
uint16_t m_port_id;
|
||||||
|
|
18
src/mem/ruby/system/RubySystem.py
Normal file
18
src/mem/ruby/system/RubySystem.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
from m5.params import *
|
||||||
|
from m5.SimObject import SimObject
|
||||||
|
|
||||||
|
class RubySystem(SimObject):
|
||||||
|
type = 'RubySystem'
|
||||||
|
random_seed = Param.Int(1234, "random seed used by the simulation");
|
||||||
|
randomization = Param.Bool(False,
|
||||||
|
"insert random delays on message enqueue times");
|
||||||
|
tech_nm = Param.Int(45,
|
||||||
|
"device size used to calculate latency and area information");
|
||||||
|
freq_mhz = Param.Int(3000, "default frequency for the system");
|
||||||
|
block_size_bytes = Param.Int(64,
|
||||||
|
"default cache block size; must be a power of two");
|
||||||
|
network = Param.RubyNetwork("")
|
||||||
|
debug = Param.RubyDebug("the default debug object")
|
||||||
|
profiler = Param.RubyProfiler("");
|
||||||
|
tracer = Param.RubyTracer("");
|
||||||
|
|
|
@ -33,6 +33,12 @@ Import('*')
|
||||||
if not env['RUBY']:
|
if not env['RUBY']:
|
||||||
Return()
|
Return()
|
||||||
|
|
||||||
|
SimObject('Cache.py')
|
||||||
|
SimObject('Sequencer.py')
|
||||||
|
SimObject('DirectoryMemory.py')
|
||||||
|
SimObject('MemoryControl.py')
|
||||||
|
SimObject('RubySystem.py')
|
||||||
|
|
||||||
Source('DMASequencer.cc')
|
Source('DMASequencer.cc')
|
||||||
Source('DirectoryMemory.cc')
|
Source('DirectoryMemory.cc')
|
||||||
Source('CacheMemory.cc')
|
Source('CacheMemory.cc')
|
||||||
|
|
|
@ -42,55 +42,44 @@
|
||||||
#include "mem/ruby/buffers/MessageBuffer.hh"
|
#include "mem/ruby/buffers/MessageBuffer.hh"
|
||||||
#include "mem/ruby/slicc_interface/AbstractController.hh"
|
#include "mem/ruby/slicc_interface/AbstractController.hh"
|
||||||
|
|
||||||
|
#include "params/RubySequencer.hh"
|
||||||
|
|
||||||
//Sequencer::Sequencer(int core_id, MessageBuffer* mandatory_q)
|
//Sequencer::Sequencer(int core_id, MessageBuffer* mandatory_q)
|
||||||
|
|
||||||
#define LLSC_FAIL -2
|
#define LLSC_FAIL -2
|
||||||
long int already = 0;
|
long int already = 0;
|
||||||
Sequencer::Sequencer(const string & name)
|
|
||||||
:RubyPort(name)
|
Sequencer *
|
||||||
|
RubySequencerParams::create()
|
||||||
{
|
{
|
||||||
m_store_waiting_on_load_cycles = 0;
|
return new Sequencer(this);
|
||||||
m_store_waiting_on_store_cycles = 0;
|
|
||||||
m_load_waiting_on_store_cycles = 0;
|
|
||||||
m_load_waiting_on_load_cycles = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sequencer::init(const vector<string> & argv)
|
Sequencer::Sequencer(const Params *p)
|
||||||
|
: RubyPort(p)
|
||||||
{
|
{
|
||||||
m_deadlock_check_scheduled = false;
|
m_store_waiting_on_load_cycles = 0;
|
||||||
m_outstanding_count = 0;
|
m_store_waiting_on_store_cycles = 0;
|
||||||
|
m_load_waiting_on_store_cycles = 0;
|
||||||
|
m_load_waiting_on_load_cycles = 0;
|
||||||
|
|
||||||
m_max_outstanding_requests = 0;
|
m_deadlock_check_scheduled = false;
|
||||||
m_deadlock_threshold = 0;
|
m_outstanding_count = 0;
|
||||||
m_version = -1;
|
|
||||||
m_instCache_ptr = NULL;
|
m_max_outstanding_requests = 0;
|
||||||
m_dataCache_ptr = NULL;
|
m_deadlock_threshold = 0;
|
||||||
m_controller = NULL;
|
m_instCache_ptr = NULL;
|
||||||
for (size_t i=0; i<argv.size(); i+=2) {
|
m_dataCache_ptr = NULL;
|
||||||
if ( argv[i] == "controller") {
|
|
||||||
m_controller = RubySystem::getController(argv[i+1]); // args[i] = "L1Cache"
|
m_instCache_ptr = p->icache;
|
||||||
m_mandatory_q_ptr = m_controller->getMandatoryQueue();
|
m_dataCache_ptr = p->dcache;
|
||||||
} else if ( argv[i] == "icache")
|
m_max_outstanding_requests = p->max_outstanding_requests;
|
||||||
m_instCache_ptr = RubySystem::getCache(argv[i+1]);
|
m_deadlock_threshold = p->deadlock_threshold;
|
||||||
else if ( argv[i] == "dcache")
|
|
||||||
m_dataCache_ptr = RubySystem::getCache(argv[i+1]);
|
assert(m_max_outstanding_requests > 0);
|
||||||
else if ( argv[i] == "version")
|
assert(m_deadlock_threshold > 0);
|
||||||
m_version = atoi(argv[i+1].c_str());
|
assert(m_instCache_ptr != NULL);
|
||||||
else if ( argv[i] == "max_outstanding_requests")
|
assert(m_dataCache_ptr != NULL);
|
||||||
m_max_outstanding_requests = atoi(argv[i+1].c_str());
|
|
||||||
else if ( argv[i] == "deadlock_threshold")
|
|
||||||
m_deadlock_threshold = atoi(argv[i+1].c_str());
|
|
||||||
else {
|
|
||||||
cerr << "WARNING: Sequencer: Unkown configuration parameter: " << argv[i] << endl;
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(m_max_outstanding_requests > 0);
|
|
||||||
assert(m_deadlock_threshold > 0);
|
|
||||||
assert(m_version > -1);
|
|
||||||
assert(m_instCache_ptr != NULL);
|
|
||||||
assert(m_dataCache_ptr != NULL);
|
|
||||||
assert(m_controller != NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Sequencer::~Sequencer() {
|
Sequencer::~Sequencer() {
|
||||||
|
@ -495,7 +484,7 @@ void Sequencer::issueRequest(const RubyRequest& request) {
|
||||||
// Send the message to the cache controller
|
// Send the message to the cache controller
|
||||||
assert(latency > 0);
|
assert(latency > 0);
|
||||||
|
|
||||||
|
assert(m_mandatory_q_ptr != NULL);
|
||||||
m_mandatory_q_ptr->enqueue(msg, latency);
|
m_mandatory_q_ptr->enqueue(msg, latency);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -51,7 +51,8 @@ class DataBlock;
|
||||||
class CacheMsg;
|
class CacheMsg;
|
||||||
class MachineID;
|
class MachineID;
|
||||||
class CacheMemory;
|
class CacheMemory;
|
||||||
class AbstractController;
|
|
||||||
|
class RubySequencerParams;
|
||||||
|
|
||||||
struct SequencerRequest {
|
struct SequencerRequest {
|
||||||
RubyRequest ruby_request;
|
RubyRequest ruby_request;
|
||||||
|
@ -65,11 +66,11 @@ struct SequencerRequest {
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& out, const SequencerRequest& obj);
|
std::ostream& operator<<(std::ostream& out, const SequencerRequest& obj);
|
||||||
|
|
||||||
class Sequencer : public Consumer, public RubyPort {
|
class Sequencer : public RubyPort, public Consumer {
|
||||||
public:
|
public:
|
||||||
|
typedef RubySequencerParams Params;
|
||||||
// Constructors
|
// Constructors
|
||||||
Sequencer(const string & name);
|
Sequencer(const Params *);
|
||||||
void init(const vector<string> & argv);
|
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
~Sequencer();
|
~Sequencer();
|
||||||
|
@ -114,13 +115,10 @@ private:
|
||||||
int m_max_outstanding_requests;
|
int m_max_outstanding_requests;
|
||||||
int m_deadlock_threshold;
|
int m_deadlock_threshold;
|
||||||
|
|
||||||
AbstractController* m_controller;
|
|
||||||
MessageBuffer* m_mandatory_q_ptr;
|
|
||||||
CacheMemory* m_dataCache_ptr;
|
CacheMemory* m_dataCache_ptr;
|
||||||
CacheMemory* m_instCache_ptr;
|
CacheMemory* m_instCache_ptr;
|
||||||
|
|
||||||
// indicates what processor on the chip this sequencer is associated with
|
// indicates what processor on the chip this sequencer is associated with
|
||||||
int m_version;
|
|
||||||
int m_controller_type;
|
int m_controller_type;
|
||||||
|
|
||||||
Map<Address, SequencerRequest*> m_writeRequestTable;
|
Map<Address, SequencerRequest*> m_writeRequestTable;
|
||||||
|
|
23
src/mem/ruby/system/Sequencer.py
Normal file
23
src/mem/ruby/system/Sequencer.py
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
from m5.params import *
|
||||||
|
from MemObject import MemObject
|
||||||
|
|
||||||
|
class RubyPort(MemObject):
|
||||||
|
type = 'RubyPort'
|
||||||
|
abstract = True
|
||||||
|
port = VectorPort("M5 port")
|
||||||
|
controller = Param.RubyController("")
|
||||||
|
version = Param.Int(0, "")
|
||||||
|
|
||||||
|
class RubySequencer(RubyPort):
|
||||||
|
type = 'RubySequencer'
|
||||||
|
cxx_class = 'Sequencer'
|
||||||
|
icache = Param.RubyCache("")
|
||||||
|
dcache = Param.RubyCache("")
|
||||||
|
max_outstanding_requests = Param.Int(16,
|
||||||
|
"max requests (incl. prefetches) outstanding")
|
||||||
|
deadlock_threshold = Param.Int(500000,
|
||||||
|
"max outstanding cycles for a request before deadlock/livelock declared")
|
||||||
|
funcmem_port = Port("port to functional memory")
|
||||||
|
|
||||||
|
class DMASequencer(RubyPort):
|
||||||
|
type = 'DMASequencer'
|
|
@ -47,15 +47,14 @@
|
||||||
#include "mem/ruby/system/Sequencer.hh"
|
#include "mem/ruby/system/Sequencer.hh"
|
||||||
#include "mem/ruby/system/DMASequencer.hh"
|
#include "mem/ruby/system/DMASequencer.hh"
|
||||||
#include "mem/ruby/system/MemoryVector.hh"
|
#include "mem/ruby/system/MemoryVector.hh"
|
||||||
#include "mem/protocol/ControllerFactory.hh"
|
|
||||||
#include "mem/ruby/slicc_interface/AbstractController.hh"
|
#include "mem/ruby/slicc_interface/AbstractController.hh"
|
||||||
#include "mem/ruby/system/CacheMemory.hh"
|
#include "mem/ruby/system/CacheMemory.hh"
|
||||||
#include "mem/ruby/system/DirectoryMemory.hh"
|
#include "mem/ruby/system/DirectoryMemory.hh"
|
||||||
#include "mem/ruby/network/simple/Topology.hh"
|
#include "mem/ruby/network/simple/Topology.hh"
|
||||||
#include "mem/ruby/network/simple/SimpleNetwork.hh"
|
#include "mem/ruby/network/simple/SimpleNetwork.hh"
|
||||||
#include "mem/ruby/system/RubyPort.hh"
|
#include "mem/ruby/system/RubyPort.hh"
|
||||||
#include "mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.hh"
|
//#include "mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.hh"
|
||||||
#include "mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh"
|
//#include "mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh"
|
||||||
#include "mem/ruby/system/MemoryControl.hh"
|
#include "mem/ruby/system/MemoryControl.hh"
|
||||||
|
|
||||||
int RubySystem::m_random_seed;
|
int RubySystem::m_random_seed;
|
||||||
|
@ -84,180 +83,32 @@ Tracer* RubySystem::m_tracer_ptr;
|
||||||
MemoryVector* RubySystem::m_mem_vec_ptr;
|
MemoryVector* RubySystem::m_mem_vec_ptr;
|
||||||
|
|
||||||
|
|
||||||
RubySystem* RubySystem::create(const vector <RubyObjConf> & sys_conf)
|
RubySystem::RubySystem(const Params *p)
|
||||||
|
: SimObject(p)
|
||||||
{
|
{
|
||||||
if (g_system_ptr == NULL)
|
if (g_system_ptr != NULL)
|
||||||
return new RubySystem(sys_conf);
|
fatal("Only one RubySystem object currently allowed.\n");
|
||||||
return g_system_ptr;
|
|
||||||
|
m_random_seed = p->random_seed;
|
||||||
|
srandom(m_random_seed);
|
||||||
|
m_randomization = p->randomization;
|
||||||
|
m_tech_nm = p->tech_nm;
|
||||||
|
m_freq_mhz = p->freq_mhz;
|
||||||
|
m_block_size_bytes = p->block_size_bytes;
|
||||||
|
assert(is_power_of_2(m_block_size_bytes));
|
||||||
|
m_block_size_bits = log_int(m_block_size_bytes);
|
||||||
|
m_network_ptr = p->network;
|
||||||
|
g_debug_ptr = p->debug;
|
||||||
|
m_profiler_ptr = p->profiler;
|
||||||
|
m_tracer_ptr = p->tracer;
|
||||||
|
|
||||||
|
g_system_ptr = this;
|
||||||
|
m_mem_vec_ptr = new MemoryVector;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RubySystem::init(const vector<string> & argv)
|
|
||||||
|
void RubySystem::init()
|
||||||
{
|
{
|
||||||
for (size_t i=0; i < argv.size(); i+=2) {
|
|
||||||
if (argv[i] == "random_seed") {
|
|
||||||
m_random_seed = atoi(argv[i+1].c_str());
|
|
||||||
srandom(m_random_seed);
|
|
||||||
} else if (argv[i] == "randomization") {
|
|
||||||
m_randomization = string_to_bool(argv[i+1]);
|
|
||||||
} else if (argv[i] == "tech_nm") {
|
|
||||||
m_tech_nm = atoi(argv[i+1].c_str());
|
|
||||||
} else if (argv[i] == "freq_mhz") {
|
|
||||||
m_freq_mhz = atoi(argv[i+1].c_str());
|
|
||||||
} else if (argv[i] == "block_size_bytes") {
|
|
||||||
m_block_size_bytes = atoi(argv[i+1].c_str());
|
|
||||||
assert(is_power_of_2(m_block_size_bytes));
|
|
||||||
m_block_size_bits = log_int(m_block_size_bytes);
|
|
||||||
} else if (argv[i] == "debug") {
|
|
||||||
|
|
||||||
} else if (argv[i] == "tracer") {
|
|
||||||
|
|
||||||
} else if (argv[i] == "profiler") {
|
|
||||||
|
|
||||||
// } else if (argv[i] == "MI_example") {
|
|
||||||
|
|
||||||
} else {
|
|
||||||
cerr << "Error: Unknown RubySystem config parameter -- " << argv[i] << endl;
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RubySystem::RubySystem(const vector <RubyObjConf> & sys_conf)
|
|
||||||
{
|
|
||||||
// DEBUG_MSG(SYSTEM_COMP, MedPrio,"initializing");
|
|
||||||
|
|
||||||
for (size_t i=0;i<sys_conf.size(); i++) {
|
|
||||||
const string & type = sys_conf[i].type;
|
|
||||||
const string & name = sys_conf[i].name;
|
|
||||||
const vector<string> & argv = sys_conf[i].argv;
|
|
||||||
if (type == "System") {
|
|
||||||
init(argv); // initialize system-wide variables before doing anything else!
|
|
||||||
} else if (type == "Debug") {
|
|
||||||
g_debug_ptr = new Debug(name, argv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert( g_debug_ptr != NULL);
|
|
||||||
g_eventQueue_ptr = new RubyEventQueue;
|
|
||||||
g_system_ptr = this;
|
|
||||||
m_mem_vec_ptr = new MemoryVector;
|
|
||||||
|
|
||||||
/* object contruction is broken into two steps (Constructor and init) to avoid cyclic dependencies
|
|
||||||
* e.g. a sequencer needs a pointer to a controller and a controller needs a pointer to a sequencer
|
|
||||||
*/
|
|
||||||
|
|
||||||
vector<string> memory_control_names;
|
|
||||||
|
|
||||||
for (size_t i=0;i<sys_conf.size(); i++) {
|
|
||||||
const string & type = sys_conf[i].type;
|
|
||||||
const string & name = sys_conf[i].name;
|
|
||||||
if (type == "System" || type == "Debug")
|
|
||||||
continue;
|
|
||||||
else if (type == "SetAssociativeCache")
|
|
||||||
m_caches[name] = new CacheMemory(name);
|
|
||||||
else if (type == "DirectoryMemory")
|
|
||||||
m_directories[name] = new DirectoryMemory(name);
|
|
||||||
else if (type == "Sequencer") {
|
|
||||||
m_sequencers[name] = new Sequencer(name);
|
|
||||||
m_ports[name] = m_sequencers[name];
|
|
||||||
} else if (type == "DMASequencer") {
|
|
||||||
m_dma_sequencers[name] = new DMASequencer(name);
|
|
||||||
m_ports[name] = m_dma_sequencers[name];
|
|
||||||
} else if (type == "Topology") {
|
|
||||||
assert(m_topologies.size() == 0); // only one toplogy at a time is supported right now
|
|
||||||
m_topologies[name] = new Topology(name);
|
|
||||||
} else if (type == "SimpleNetwork") {
|
|
||||||
assert(m_network_ptr == NULL); // only one network at a time is supported right now
|
|
||||||
m_network_ptr = new SimpleNetwork(name);
|
|
||||||
} else if (type.find("generated") == 0) {
|
|
||||||
string controller_type = type.substr(10);
|
|
||||||
m_controllers[name] = ControllerFactory::createController(controller_type, name);
|
|
||||||
// printf ("ss: generated %s \n", controller_type);
|
|
||||||
//added by SS
|
|
||||||
} else if (type == "Tracer") {
|
|
||||||
//m_tracers[name] = new Tracer(name);
|
|
||||||
m_tracer_ptr = new Tracer(name);
|
|
||||||
} else if (type == "Profiler") {
|
|
||||||
m_profiler_ptr = new Profiler(name);
|
|
||||||
} else if (type == "GarnetNetwork") {
|
|
||||||
assert(m_network_ptr == NULL); // only one network at a time is supported right now
|
|
||||||
m_network_ptr = new GarnetNetwork(name);
|
|
||||||
} else if (type == "GarnetNetwork_d") {
|
|
||||||
assert(m_network_ptr == NULL); // only one network at a time is supported right now
|
|
||||||
m_network_ptr = new GarnetNetwork_d(name);
|
|
||||||
} else if (type == "MemoryControl") {
|
|
||||||
m_memorycontrols[name] = new MemoryControl(name);
|
|
||||||
memory_control_names.push_back (name);
|
|
||||||
} else {
|
|
||||||
cerr << "Error: Unknown object type -- " << type << endl;
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i=0;i<sys_conf.size(); i++) {
|
|
||||||
string type = sys_conf[i].type;
|
|
||||||
string name = sys_conf[i].name;
|
|
||||||
const vector<string> & argv = sys_conf[i].argv;
|
|
||||||
if (type == "Topology")
|
|
||||||
m_topologies[name]->init(argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i=0;i<sys_conf.size(); i++) {
|
|
||||||
string type = sys_conf[i].type;
|
|
||||||
string name = sys_conf[i].name;
|
|
||||||
const vector<string> & argv = sys_conf[i].argv;
|
|
||||||
if (type == "SimpleNetwork" || type == "GarnetNetwork" || type == "GarnetNetwork_d"){
|
|
||||||
m_network_ptr->init(argv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i=0;i<sys_conf.size(); i++) {
|
|
||||||
string type = sys_conf[i].type;
|
|
||||||
string name = sys_conf[i].name;
|
|
||||||
const vector<string> & argv = sys_conf[i].argv;
|
|
||||||
if (type == "MemoryControl" ){
|
|
||||||
m_memorycontrols[name]->init(argv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i=0;i<sys_conf.size(); i++) {
|
|
||||||
string type = sys_conf[i].type;
|
|
||||||
string name = sys_conf[i].name;
|
|
||||||
const vector<string> & argv = sys_conf[i].argv;
|
|
||||||
if (type == "System" || type == "Debug")
|
|
||||||
continue;
|
|
||||||
else if (type == "SetAssociativeCache")
|
|
||||||
m_caches[name]->init(argv);
|
|
||||||
else if (type == "DirectoryMemory")
|
|
||||||
m_directories[name]->init(argv);
|
|
||||||
else if (type == "MemoryControl")
|
|
||||||
continue;
|
|
||||||
else if (type == "Sequencer")
|
|
||||||
m_sequencers[name]->init(argv);
|
|
||||||
else if (type == "DMASequencer")
|
|
||||||
m_dma_sequencers[name]->init(argv);
|
|
||||||
else if (type == "Topology")
|
|
||||||
continue;
|
|
||||||
else if (type == "SimpleNetwork" || type == "GarnetNetwork" || type == "GarnetNetwork_d")
|
|
||||||
continue;
|
|
||||||
else if (type.find("generated") == 0) {
|
|
||||||
string controller_type = type.substr(11);
|
|
||||||
m_controllers[name]->init(m_network_ptr, argv);
|
|
||||||
}
|
|
||||||
//added by SS
|
|
||||||
else if (type == "Tracer")
|
|
||||||
//m_tracers[name]->init(argv);
|
|
||||||
m_tracer_ptr->init(argv);
|
|
||||||
else if (type == "Profiler")
|
|
||||||
m_profiler_ptr->init(argv, memory_control_names);
|
|
||||||
// else if (type == "MI_example"){
|
|
||||||
// }
|
|
||||||
else
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// m_profiler_ptr = new Profiler;
|
|
||||||
|
|
||||||
// calculate system-wide parameters
|
// calculate system-wide parameters
|
||||||
m_memory_size_bytes = 0;
|
m_memory_size_bytes = 0;
|
||||||
DirectoryMemory* prev = NULL;
|
DirectoryMemory* prev = NULL;
|
||||||
|
@ -270,12 +121,9 @@ RubySystem::RubySystem(const vector <RubyObjConf> & sys_conf)
|
||||||
}
|
}
|
||||||
m_mem_vec_ptr->setSize(m_memory_size_bytes);
|
m_mem_vec_ptr->setSize(m_memory_size_bytes);
|
||||||
m_memory_size_bits = log_int(m_memory_size_bytes);
|
m_memory_size_bits = log_int(m_memory_size_bytes);
|
||||||
|
|
||||||
// m_tracer_ptr = new Tracer;
|
|
||||||
DEBUG_MSG(SYSTEM_COMP, MedPrio,"finished initializing");
|
|
||||||
DEBUG_NEWLINE(SYSTEM_COMP, MedPrio);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RubySystem::~RubySystem()
|
RubySystem::~RubySystem()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -423,5 +271,8 @@ void RubySystem::checkGlobalCoherenceInvariant(const Address& addr ) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
RubySystem *
|
||||||
|
RubySystemParams::create()
|
||||||
|
{
|
||||||
|
return new RubySystem(this);
|
||||||
|
}
|
||||||
|
|
|
@ -46,6 +46,8 @@
|
||||||
#include "mem/gems_common/Vector.hh"
|
#include "mem/gems_common/Vector.hh"
|
||||||
#include "mem/ruby/eventqueue/RubyEventQueue.hh"
|
#include "mem/ruby/eventqueue/RubyEventQueue.hh"
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include "sim/sim_object.hh"
|
||||||
|
#include "params/RubySystem.hh"
|
||||||
|
|
||||||
class Profiler;
|
class Profiler;
|
||||||
class Network;
|
class Network;
|
||||||
|
@ -84,9 +86,10 @@ struct RubyObjConf {
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
class RubySystem {
|
class RubySystem : public SimObject {
|
||||||
public:
|
public:
|
||||||
static RubySystem* create(const vector <RubyObjConf> & sys_conf);
|
typedef RubySystemParams Params;
|
||||||
|
RubySystem(const Params *p);
|
||||||
// Destructor
|
// Destructor
|
||||||
~RubySystem();
|
~RubySystem();
|
||||||
|
|
||||||
|
@ -152,7 +155,7 @@ private:
|
||||||
RubySystem(const RubySystem& obj);
|
RubySystem(const RubySystem& obj);
|
||||||
RubySystem& operator=(const RubySystem& obj);
|
RubySystem& operator=(const RubySystem& obj);
|
||||||
|
|
||||||
void init(const vector<string> & argv);
|
void init();
|
||||||
|
|
||||||
static void printSystemConfig(ostream& out);
|
static void printSystemConfig(ostream& out);
|
||||||
|
|
||||||
|
@ -181,6 +184,7 @@ private:
|
||||||
//added by SS
|
//added by SS
|
||||||
//static map< string, Tracer* > m_tracers;
|
//static map< string, Tracer* > m_tracers;
|
||||||
|
|
||||||
|
public:
|
||||||
static Profiler* m_profiler_ptr;
|
static Profiler* m_profiler_ptr;
|
||||||
static Tracer* m_tracer_ptr;
|
static Tracer* m_tracer_ptr;
|
||||||
static MemoryVector* m_mem_vec_ptr;
|
static MemoryVector* m_mem_vec_ptr;
|
||||||
|
|
Loading…
Reference in a new issue