文章目录
1 涉及到的相关文件
四个文件夹
compressors
prefetch
replacement_policies
tags
分别表示“缓存压缩”、“预取”、“替换算法”、“标志位”等相关结构
此外,还包括基本文件:
base.hh
base.cc
cache_blk.hh
cache_blk.cc
cache.hh
cache.cc
mshr_queue.hh
mshr_queue.cc
mshr.hh
mshr.cc
noncoherent_cache.hh
noncoherent_cache.cc
queue_entry.hh
queue.hh
write_queue_entry.hh
write_queue_entry.cc
write_queue.hh
write_queue.cc
Cache.py
SConscript
从这些文件中,可以观察到其中的文件包括三类:
- SConscript:负责编译用 Scons
- Cache.py:Python 提供接口
- xx.hh/cc:c++ 实现具体的功能
2 SConscript
2.1 具体结构
Import('*')
SimObject('Cache.py', sim_objects=[
'WriteAllocator', 'BaseCache', 'Cache', 'NoncoherentCache'],
enums=['Clusivity'])
Source('base.cc')
Source('cache.cc')
Source('cache_blk.cc')
Source('mshr.cc')
Source('mshr_queue.cc')
Source('noncoherent_cache.cc')
Source('write_queue.cc')
Source('write_queue_entry.cc')
DebugFlag('Cache')
DebugFlag('CacheComp')
DebugFlag('CachePort')
DebugFlag('CacheRepl')
DebugFlag('CacheTags')
DebugFlag('CacheVerbose')
DebugFlag('HWPrefetch')
DebugFlag('MSHR')
DebugFlag('HWPrefetchQueue')
CompoundFlag('CacheAll', ['Cache', 'CacheComp', 'CachePort', 'CacheRepl',
'CacheVerbose', 'HWPrefetch', 'MSHR'])
2.2 SConscript 简介
SConscript 是 scons 默认自动寻找并执行的配置脚本,对环境进行基本的信息处理,然后创造环境对象,并调用 osconfig.py(硬件相关性较大的配置)build_tools.py(定义了各项公用的操作)
SConscript()方法,递归调用各级子目录中的SConscript,从而实现根据不同项目特点定义相应的代码组织、编译行为。
gem5 中,主要用 scons编译,并 SConscript 完成编译相关内容,主要用的语法有:
SimObject()
Source()
DebugFlag()
CompoundFlag()
2.3 SimoObject
# gem5-stable\src\SConscript
class SimObject(PySource):
'''Add a SimObject python file as a python source object and add
it to a list of sim object modules'''
class PySource(SourceFile):
'''Add a python source file to the named package'''
# gem5-stable\site_scons\gem5_scons\sources.py
class SourceFile(object, metaclass=SourceMeta):
'''Base object that encapsulates the notion of a source file.
This includes, the source node, target node, various manipulations
of those. A source file also specifies a set of tags which
describing arbitrary properties of the source file.'''
def __init__(self, source, tags=None, add_tags=None, append=None):
主要功能是添加一个 python 对象到仿真对象中
2.4 Source
# gem5-stable\src\SConscript
class Source(SourceFile):
pass
应该是加了一层封装,还是使用 SourceFile的初始化函数
从使用上来看,主要是指明源文件
2.5 DebugFlag
# gem5-stable\src\SConscript
def DebugFlag(name, desc=None, fmt=False, tags=None, add_tags=None):
DebugFlagCommon(name, (), desc, fmt, tags=tags, add_tags=add_tags)
def DebugFlagCommon(name, flags, desc, fmt, tags, add_tags):
...
用于指示出调试信息,调试位
2.6 CompoundFlag
# gem5-stable\src\SConscript
def CompoundFlag(name, flags, desc=None, tags=None, add_tags=None):
DebugFlagCommon(name, flags, desc, False, tags=tags, add_tags=add_tags)
2.2.3和2.2.4主要是为增加调试信息,和复合标志(?)
3 Cache.py
主要定义了基本的模块
class Clusivity(Enum)
class WriteAllocator(SimObject)
class BaseCache(ClockedObject)
class Cache(BaseCache)
class NoncoherentCache(BaseCache)
# SConscript
SimObject('Cache.py', sim_objects=[
'WriteAllocator', 'BaseCache', 'Cache', 'NoncoherentCache'],
enums=['Clusivity'])
Tips. 这个文件中的类,与 SConscript 的 SimObejct 是一一对应
class Cache(BaseCache):
type = 'Cache'
cxx_header = 'mem/cache/cache.hh'
cxx_class = 'gem5::Cache'
比较核心的内容:
- type 指明类型
- cxx_header
- cxx_class
4 xx.hh/cc
具体的功能实现,那么 Python 和 C++ 是如何一起?Python 是怎么调用 C++ 实现的功能(以 BaseCache 类为例,进行具体分析)
回顾 Cache.py 中关于 Basecache 类的定义
class BaseCache(ClockedObject):
type = 'BaseCache'
abstract = True
cxx_header = "mem/cache/base.hh"
size = Param.MemorySize("Capacity")
assoc = Param.Unsigned("Associativity")
tag_latency = Param.Cycles("Tag lookup latency")
data_latency = Param.Cycles("Data access latency")
response_latency = Param.Cycles("Latency for the return path on a miss");
warmup_percentage = Param.Percent(0,
"Percentage of tags to be touched to warm up the cache")
max_miss_count = Param.Counter(0,
"Number of misses to handle before calling exit")
mshrs = Param.Unsigned("Number of MSHRs (max outstanding requests)")
demand_mshr_reserve = Param.Unsigned(1, "MSHRs reserved for demand access")
tgts_per_mshr = Param.Unsigned("Max number of accesses per MSHR")
write_buffers = Param.Unsigned(8, "Number of write buffers")
is_read_only = Param.Bool(False, "Is this cache read only (e.g. inst)")
prefetcher = Param.BasePrefetcher(NULL,"Prefetcher attached to cache")
prefetch_on_access = Param.Bool(False,
"Notify the hardware prefetcher on every access (not just misses)")
tags = Param.BaseTags(BaseSetAssoc(), "Tag store")
replacement_policy = Param.BaseReplacementPolicy(LRURP(),
"Replacement policy")
compressor = Param.BaseCacheCompressor(NULL, "Cache compressor.")
sequential_access = Param.Bool(False,
"Whether to access tags and data sequentially")
cpu_side = SlavePort("Upstream port closer to the CPU and/or device")
mem_side = MasterPort("Downstream port closer to memory")
addr_ranges = VectorParam.AddrRange([AllMemory],
"Address range for the CPU-side port (to allow striping)")
system = Param.System(Parent.any, "System we belong to")
writeback_clean = Param.Bool(False, "Writeback clean lines")
clusivity = Param.Clusivity('mostly_incl',
"Clusivity with upstream cache")
write_allocator = Param.WriteAllocator(NULL, "Write allocator")
用到了 Param 把参数传递进来,这部分是编译后,会有一个参数对应表。
注意: src 文件夹中用到的参数,与编译后 build/X86文件夹下的代码不完全相同,并且会自动生成 Param 相关参数
那么,是如何与 C++ 中对应上?看 BaseCache 类
gem5-stable\src\mem\cache\base.hh
class BaseCache : public ClockedObject
{
protected:
/**
* Indexes to enumerate the MSHR queues.
*/
enum MSHRQueueIndex
{
MSHRQueue_MSHRs,
MSHRQueue_WriteBuffer
};
}
编译结束后,gem5会自动生成一些文件
// \build\X86\params\BaseCache.hh
struct BaseCacheParams
: public ClockedObjectParams
{
std::vector< AddrRange > addr_ranges;
unsigned assoc;
Enums::Clusivity clusivity;
BaseCacheCompressor * compressor;
Cycles data_latency;
unsigned demand_mshr_reserve;
bool is_read_only;
Counter max_miss_count;
unsigned mshrs;
bool prefetch_on_access;
BasePrefetcher * prefetcher;
BaseReplacementPolicy * replacement_policy;
Cycles response_latency;
bool sequential_access;
uint64_t size;
System * system;
Cycles tag_latency;
BaseTags * tags;
unsigned tgts_per_mshr;
int warmup_percentage;
WriteAllocator * write_allocator;
unsigned write_buffers;
bool writeback_clean;
unsigned int port_mem_side_connection_count;
unsigned int port_cpu_side_connection_count;
};
此时,可根据 Cache.py 中的相关变量,把对应的值输入到 c++ 代码中
5 总结
至此,把一个文件夹中的多个部分进行了分析,并梳理了一下各自间的联系:
- SConscript:负责编译文件,指明 Source(源文件)、Debug(调试信息)、SimObject(提供的仿真对象)
- x.py:负责提供简要配置,并用于传输具体的接口信息
- x.hh/cc:根据 x.py 提供的端口配置参数,实现具体的功能