New and improved configuration mechanism. No more writing of
wierd ini files. The ini files are still used as an intermediate step, but a sophisticated python library exists to help build them more easily. SConscript: add the new embedded file stuff remove all of the old object description junk base/inifile.cc: base/inifile.hh: get rid of findDefault and findAppend since they were the source of much evil. base/trace.cc: For now, if we don't have the dprintf_stream set up, dump to standard out. We probably want a command line option for this. dev/alpha_console.cc: PioDevice now takes a platform parameter. All PioDevices must have a pio_latency parameter. We stick a dummy parameter in here for now until we get rid of the builder stuff. dev/alpha_console.hh: don't need Platform anymore dev/baddev.cc: PioDevice now takes a platform parameter. All PioDevices must have a pio_latency parameter. We stick a dummy parameter in here for now until we get rid of the builder stuff. Same for the platform parameter, though we just pass the PioDevice a null parameter since it isn't used by this device and it's quicker. dev/baddev.hh: fix #include guards dev/etherlink.cc: rename parameters. dev/ethertap.cc: rename parameters dev/ide_ctrl.cc: All devices need an address even if it will get overwritten later. dev/ide_disk.cc: use an enum for the drive ID stuff. rename disk_delay -> delay Actually, I think that we should implement "cable select" and have the controller tell the drive what it is. dev/io_device.cc: dev/io_device.hh: All IO devices take a Platform * dev/ns_gige.cc: all devices need an io_bus. rename header_bus to io_bus We don't need stuff for the interrupt controller since it's all in the platform now. dev/ns_gige.hh: We don't need stuff for the interrupt controller now since it's all in the platform. dev/pciconfigall.cc: Pass a dummy NULL to the PioDevice for the platform since we don't need one. dev/pcidev.cc: Move a bunch of common functionality into the PciDev dev/platform.hh: remove unneeded code dev/tsunami.cc: remove unused param dev/tsunami_cchip.cc: pass platform pointer dev/tsunami_io.cc: dev/tsunami_pchip.cc: dev/uart.cc: pass platform variable dev/uart.hh: don't need to keep a platform pointer. it's in the base class kern/linux/linux_system.cc: kern/tru64/tru64_system.cc: rename some parameters sim/builder.cc: clean up builder code. use more parameters from the config node. all sections with a type= are now created, the old mechanisms no longer work sim/builder.hh: remove some extra variables since they are found in the ConfigNode sim/main.cc: add a quick hack command line argument -X to dump out the embedded files. (probably should be fixed up a little.) accept .mpy files printing to the streams has to happen after the hierarchy is built since we're moving away from param contexts sim/param.cc: add parsing support for ranges sim/process.cc: isValid isn't very useful anymore. interpret the names stdout, stderr, cout, cerr for the file descriptors sim/pyconfig/SConscript: Add Action handlers for creating an embedded python file and for creating an embedded C file. use these action handlers to embed all objects found in the objects tree into the binary along with the importer and the m5config stuff sim/pyconfig/m5config.py: Major changes to the original configuration file generator. These changes largely involve implementing copy-on-write like semantics for all of the SimObjects. Real documentation must be written. sim/universe.cc: Universe becomes a SimObject since we don't really have the notion of param contexts in the python code. --HG-- rename : sim/pyconfig/m5configbase.py => sim/pyconfig/m5config.py extra : convert_revision : c353453e5beb91c37f15755998fc0d8858c6829a
This commit is contained in:
parent
dfecc89150
commit
3ece6ab029
61 changed files with 2128 additions and 1136 deletions
88
SConscript
88
SConscript
|
@ -54,6 +54,7 @@ base_sources = Split('''
|
|||
base/circlebuf.cc
|
||||
base/copyright.cc
|
||||
base/cprintf.cc
|
||||
base/embedfile.cc
|
||||
base/fast_alloc.cc
|
||||
base/fifo_buffer.cc
|
||||
base/hostinfo.cc
|
||||
|
@ -198,42 +199,9 @@ base_sources = Split('''
|
|||
sim/trace_context.cc
|
||||
sim/universe.cc
|
||||
sim/pyconfig/pyconfig.cc
|
||||
sim/pyconfig/code.cc
|
||||
sim/pyconfig/embedded_py.cc
|
||||
''')
|
||||
|
||||
base_obj_desc_files = Split('''
|
||||
cpu/full_cpu/iq/segmented/SegmentedIQ.od
|
||||
cpu/full_cpu/iq/seznec/SeznecIQ.od
|
||||
cpu/full_cpu/iq/standard/StandardIQ.od
|
||||
cpu/full_cpu/iq/BaseIQ.od
|
||||
cpu/full_cpu/BranchPred.od
|
||||
cpu/full_cpu/FUDesc.od
|
||||
cpu/full_cpu/FullCPU.od
|
||||
cpu/full_cpu/FuncUnitPool.od
|
||||
cpu/full_cpu/OpDesc.od
|
||||
cpu/full_cpu/PipeTrace.od
|
||||
cpu/sampling_cpu/SamplingCPU.od
|
||||
cpu/simple_cpu/SimpleCPU.od
|
||||
cpu/inorder_cpu/InorderCPU.od
|
||||
cpu/BaseCPU.od
|
||||
cpu/IntrControl.od
|
||||
mem/bus/Bus.od
|
||||
mem/bus/BusBridge.od
|
||||
mem/cache/coherence/CoherenceProtocol.od
|
||||
mem/cache/tags/repl/GenRepl.od
|
||||
mem/cache/tags/repl/Repl.od
|
||||
mem/cache/BaseCache.od
|
||||
mem/functional_mem/FunctionalMemory.od
|
||||
mem/functional_mem/MainMemory.od
|
||||
mem/functional_mem/MemoryController.od
|
||||
mem/functional_mem/PhysicalMemory.od
|
||||
mem/timing_mem/BaseMemory.od
|
||||
mem/BaseHier.od
|
||||
mem/BaseMem.od
|
||||
mem/HierParams.od
|
||||
''')
|
||||
|
||||
|
||||
# MySql sources
|
||||
mysql_sources = Split('''
|
||||
base/mysql.cc
|
||||
|
@ -316,44 +284,6 @@ full_system_sources = Split('''
|
|||
sim/system.cc
|
||||
''')
|
||||
|
||||
full_system_obj_desc_files = Split('''
|
||||
arch/alpha/AlphaDTB.od
|
||||
arch/alpha/AlphaITB.od
|
||||
arch/alpha/AlphaTLB.od
|
||||
dev/AlphaConsole.od
|
||||
dev/ConsoleListener.od
|
||||
dev/CowDiskImage.od
|
||||
dev/DiskImage.od
|
||||
dev/DmaDevice.od
|
||||
dev/DmaEngine.od
|
||||
dev/EtherBus.od
|
||||
dev/EtherDev.od
|
||||
dev/EtherDevInt.od
|
||||
dev/EtherDump.od
|
||||
dev/EtherInt.od
|
||||
dev/EtherLink.od
|
||||
dev/EtherTap.od
|
||||
dev/PioDevice.od
|
||||
dev/RawDiskImage.od
|
||||
dev/ScsiController.od
|
||||
dev/ScsiDevice.od
|
||||
dev/ScsiDisk.od
|
||||
dev/SimConsole.od
|
||||
dev/SimpleDisk.od
|
||||
dev/TlaserClock.od
|
||||
dev/TlaserIpi.od
|
||||
dev/TlaserMBox.od
|
||||
dev/TlaserMC146818.od
|
||||
dev/TlaserNode.od
|
||||
dev/TlaserPciDev.od
|
||||
dev/TlaserPcia.od
|
||||
dev/TlaserSerial.od
|
||||
dev/TlaserUart.od
|
||||
dev/Turbolaser.od
|
||||
kern/tru64/Tru64System.od
|
||||
sim/System.od
|
||||
''')
|
||||
|
||||
# Syscall emulation (non-full-system) sources
|
||||
syscall_emulation_sources = Split('''
|
||||
arch/alpha/alpha_common_syscall_emul.cc
|
||||
|
@ -369,13 +299,6 @@ syscall_emulation_sources = Split('''
|
|||
sim/syscall_emul.cc
|
||||
''')
|
||||
|
||||
syscall_emulation_obj_desc_files = Split('''
|
||||
cpu/memtest/MemTest.od
|
||||
eio/EioProcess.od
|
||||
sim/LiveProcess.od
|
||||
sim/Process.od
|
||||
''')
|
||||
|
||||
targetarch_files = Split('''
|
||||
alpha_common_syscall_emul.hh
|
||||
alpha_linux_process.hh
|
||||
|
@ -404,14 +327,11 @@ for f in targetarch_files:
|
|||
|
||||
# Set up complete list of sources based on configuration.
|
||||
sources = base_sources
|
||||
obj_desc_files = base_obj_desc_files
|
||||
|
||||
if env['FULL_SYSTEM']:
|
||||
sources += full_system_sources
|
||||
obj_desc_files += full_system_obj_desc_files
|
||||
else:
|
||||
sources += syscall_emulation_sources
|
||||
obj_desc_files += syscall_emulation_obj_desc_files
|
||||
|
||||
extra_libraries = []
|
||||
env.Append(LIBS=['z'])
|
||||
|
@ -455,9 +375,7 @@ env.Command(Split('''arch/alpha/decoder.cc
|
|||
# SConscript-local is the per-config build, which just copies some
|
||||
# header files into a place where they can be found.
|
||||
SConscript('libelf/SConscript-local', exports = 'env', duplicate=0)
|
||||
|
||||
SConscript('sim/pyconfig/SConscript', exports = ['env', 'obj_desc_files'],
|
||||
duplicate=0)
|
||||
SConscript('sim/pyconfig/SConscript', exports = ['env'], duplicate=0)
|
||||
|
||||
|
||||
# This function adds the specified sources to the given build
|
||||
|
|
|
@ -333,47 +333,6 @@ IniFile::find(const string §ionName, const string &entryName,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IniFile::findDefault(const string &_section, const string &entry,
|
||||
string &value) const
|
||||
{
|
||||
string section = _section;
|
||||
while (!findAppend(section, entry, value)) {
|
||||
if (!find(section, "default", section)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IniFile::findAppend(const string &_section, const string &entry,
|
||||
string &value) const
|
||||
{
|
||||
string section = _section;
|
||||
bool ret = false;
|
||||
bool first = true;
|
||||
|
||||
do {
|
||||
string val;
|
||||
if (find(section, entry, val)) {
|
||||
ret = true;
|
||||
if (first) {
|
||||
value = val;
|
||||
first = false;
|
||||
} else {
|
||||
value += " ";
|
||||
value += val;
|
||||
}
|
||||
|
||||
}
|
||||
} while (find(section, "append", section));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
IniFile::sectionExists(const string §ionName) const
|
||||
{
|
||||
|
|
|
@ -190,24 +190,6 @@ class IniFile
|
|||
bool find(const std::string §ion, const std::string &entry,
|
||||
std::string &value) const;
|
||||
|
||||
/// Find value corresponding to given section and entry names,
|
||||
/// following "default" links to other sections where possible.
|
||||
/// Value is returned by reference in 'value' param.
|
||||
/// @return True if found, false if not.
|
||||
bool findDefault(const std::string §ion, const std::string &entry,
|
||||
std::string &value) const;
|
||||
|
||||
/**
|
||||
* Find a value corresponding to the given section and entry names
|
||||
* following "append" links to other sections where possible.
|
||||
* @param section The section to start with.
|
||||
* @param entry The entry to find.
|
||||
* @param value The value found.
|
||||
* @return True if the entry was found.
|
||||
*/
|
||||
bool findAppend(const std::string §ion, const std::string &entry,
|
||||
std::string &value) const;
|
||||
|
||||
/// Determine whether the named section exists in the .ini file.
|
||||
/// Note that the 'Section' class is (intentionally) not public,
|
||||
/// so all clients can do is get a bool that says whether there
|
||||
|
|
|
@ -98,6 +98,8 @@ Log::append(Record *rec)
|
|||
// dump record to output stream if there's one open
|
||||
if (dprintf_stream != NULL) {
|
||||
rec->dump(*dprintf_stream);
|
||||
} else {
|
||||
rec->dump(cout);
|
||||
}
|
||||
|
||||
// no buffering: justget rid of it now
|
||||
|
|
|
@ -56,10 +56,10 @@
|
|||
using namespace std;
|
||||
|
||||
AlphaConsole::AlphaConsole(const string &name, SimConsole *cons, SimpleDisk *d,
|
||||
System *system, BaseCPU *cpu, Platform *platform,
|
||||
System *system, BaseCPU *cpu, Platform *p,
|
||||
int num_cpus, MemoryController *mmu, Addr a,
|
||||
HierParams *hier, Bus *bus)
|
||||
: PioDevice(name), disk(d), console(cons), addr(a)
|
||||
: PioDevice(name, p), disk(d), console(cons), addr(a)
|
||||
{
|
||||
mmu->add_child(this, RangeSize(addr, size));
|
||||
|
||||
|
@ -79,7 +79,7 @@ AlphaConsole::AlphaConsole(const string &name, SimConsole *cons, SimpleDisk *d,
|
|||
alphaAccess->numCPUs = num_cpus;
|
||||
alphaAccess->mem_size = system->physmem->size();
|
||||
alphaAccess->cpuClock = cpu->getFreq() / 1000000;
|
||||
alphaAccess->intrClockFrequency = platform->intrFrequency();
|
||||
alphaAccess->intrClockFrequency = platform->intrFrequency();
|
||||
alphaAccess->diskUnit = 1;
|
||||
|
||||
alphaAccess->diskCount = 0;
|
||||
|
@ -329,6 +329,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
|
|||
SimObjectParam<BaseCPU *> cpu;
|
||||
SimObjectParam<Platform *> platform;
|
||||
SimObjectParam<Bus*> io_bus;
|
||||
Param<Tick> pio_latency;
|
||||
SimObjectParam<HierParams *> hier;
|
||||
|
||||
END_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
|
||||
|
@ -344,6 +345,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaConsole)
|
|||
INIT_PARAM(cpu, "Processor"),
|
||||
INIT_PARAM(platform, "platform"),
|
||||
INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL),
|
||||
INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000),
|
||||
INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
|
||||
|
||||
END_INIT_SIM_OBJECT_PARAMS(AlphaConsole)
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
class BaseCPU;
|
||||
class SimConsole;
|
||||
class System;
|
||||
class Platform;
|
||||
class SimpleDisk;
|
||||
|
||||
/*
|
||||
|
@ -75,7 +74,7 @@ class AlphaConsole : public PioDevice
|
|||
protected:
|
||||
union {
|
||||
AlphaAccess *alphaAccess;
|
||||
uint8_t *consoleData;
|
||||
uint8_t *consoleData;
|
||||
};
|
||||
|
||||
/** the disk must be accessed from the console */
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "base/trace.hh"
|
||||
#include "cpu/exec_context.hh"
|
||||
#include "dev/baddev.hh"
|
||||
#include "dev/platform.hh"
|
||||
#include "mem/bus/bus.hh"
|
||||
#include "mem/bus/pio_interface.hh"
|
||||
#include "mem/bus/pio_interface_impl.hh"
|
||||
|
@ -48,7 +49,7 @@ using namespace std;
|
|||
|
||||
BadDevice::BadDevice(const string &name, Addr a, MemoryController *mmu,
|
||||
HierParams *hier, Bus *bus, const string &devicename)
|
||||
: PioDevice(name), addr(a), devname(devicename)
|
||||
: PioDevice(name, NULL), addr(a), devname(devicename)
|
||||
{
|
||||
mmu->add_child(this, RangeSize(addr, size));
|
||||
|
||||
|
@ -83,20 +84,24 @@ BadDevice::cacheAccess(MemReqPtr &req)
|
|||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(BadDevice)
|
||||
|
||||
SimObjectParam<Platform *> platform;
|
||||
SimObjectParam<MemoryController *> mmu;
|
||||
Param<Addr> addr;
|
||||
SimObjectParam<HierParams *> hier;
|
||||
SimObjectParam<Bus*> io_bus;
|
||||
Param<Tick> pio_latency;
|
||||
Param<string> devicename;
|
||||
|
||||
END_DECLARE_SIM_OBJECT_PARAMS(BadDevice)
|
||||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(BadDevice)
|
||||
|
||||
INIT_PARAM(platform, "Platform"),
|
||||
INIT_PARAM(mmu, "Memory Controller"),
|
||||
INIT_PARAM(addr, "Device Address"),
|
||||
INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams),
|
||||
INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL),
|
||||
INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000),
|
||||
INIT_PARAM(devicename, "Name of device to error on")
|
||||
|
||||
END_INIT_SIM_OBJECT_PARAMS(BadDevice)
|
||||
|
|
|
@ -31,8 +31,8 @@
|
|||
* kernel that touches the frame buffer which isn't allowed.
|
||||
*/
|
||||
|
||||
#ifndef __BADDEV_HH__
|
||||
#define __BADDEV_HH__
|
||||
#ifndef __DEV_BADDEV_HH__
|
||||
#define __DEV_BADDEV_HH__
|
||||
|
||||
#include "base/range.hh"
|
||||
#include "dev/io_device.hh"
|
||||
|
@ -90,4 +90,4 @@ class BadDevice : public PioDevice
|
|||
Tick cacheAccess(MemReqPtr &req);
|
||||
};
|
||||
|
||||
#endif // __BADDEV_HH__
|
||||
#endif // __DEV_BADDEV_HH__
|
||||
|
|
|
@ -261,28 +261,27 @@ REGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent)
|
|||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherLink)
|
||||
|
||||
SimObjectParam<EtherInt *> interface1;
|
||||
SimObjectParam<EtherInt *> interface2;
|
||||
Param<Tick> link_speed;
|
||||
Param<Tick> link_delay;
|
||||
SimObjectParam<EtherDump *> packet_dump;
|
||||
SimObjectParam<EtherInt *> int1;
|
||||
SimObjectParam<EtherInt *> int2;
|
||||
Param<Tick> speed;
|
||||
Param<Tick> delay;
|
||||
SimObjectParam<EtherDump *> dump;
|
||||
|
||||
END_DECLARE_SIM_OBJECT_PARAMS(EtherLink)
|
||||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(EtherLink)
|
||||
|
||||
INIT_PARAM(interface1, "interface 1"),
|
||||
INIT_PARAM(interface2, "interface 2"),
|
||||
INIT_PARAM_DFLT(link_speed, "link speed in bits per second", 100000000),
|
||||
INIT_PARAM_DFLT(link_delay, "transmit delay of packets in us", 0),
|
||||
INIT_PARAM_DFLT(packet_dump, "object to dump network packets to", NULL)
|
||||
INIT_PARAM(int1, "interface 1"),
|
||||
INIT_PARAM(int2, "interface 2"),
|
||||
INIT_PARAM_DFLT(speed, "link speed in bits per second", 100000000),
|
||||
INIT_PARAM_DFLT(delay, "transmit delay of packets in us", 0),
|
||||
INIT_PARAM_DFLT(dump, "object to dump network packets to", NULL)
|
||||
|
||||
END_INIT_SIM_OBJECT_PARAMS(EtherLink)
|
||||
|
||||
CREATE_SIM_OBJECT(EtherLink)
|
||||
{
|
||||
return new EtherLink(getInstanceName(), interface1, interface2, link_speed,
|
||||
link_delay, packet_dump);
|
||||
return new EtherLink(getInstanceName(), int1, int2, speed, delay, dump);
|
||||
}
|
||||
|
||||
REGISTER_SIM_OBJECT("EtherLink", EtherLink)
|
||||
|
|
|
@ -311,7 +311,7 @@ EtherTap::unserialize(Checkpoint *cp, const std::string §ion)
|
|||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherTap)
|
||||
|
||||
SimObjectParam<EtherInt *> peer;
|
||||
SimObjectParam<EtherDump *> packet_dump;
|
||||
SimObjectParam<EtherDump *> dump;
|
||||
Param<unsigned> port;
|
||||
Param<unsigned> bufsz;
|
||||
|
||||
|
@ -320,7 +320,7 @@ END_DECLARE_SIM_OBJECT_PARAMS(EtherTap)
|
|||
BEGIN_INIT_SIM_OBJECT_PARAMS(EtherTap)
|
||||
|
||||
INIT_PARAM_DFLT(peer, "peer interface", NULL),
|
||||
INIT_PARAM_DFLT(packet_dump, "object to dump network packets to", NULL),
|
||||
INIT_PARAM_DFLT(dump, "object to dump network packets to", NULL),
|
||||
INIT_PARAM_DFLT(port, "tap port", 3500),
|
||||
INIT_PARAM_DFLT(bufsz, "tap buffer size", 10000)
|
||||
|
||||
|
@ -329,7 +329,7 @@ END_INIT_SIM_OBJECT_PARAMS(EtherTap)
|
|||
|
||||
CREATE_SIM_OBJECT(EtherTap)
|
||||
{
|
||||
EtherTap *tap = new EtherTap(getInstanceName(), packet_dump, port, bufsz);
|
||||
EtherTap *tap = new EtherTap(getInstanceName(), dump, port, bufsz);
|
||||
|
||||
if (peer) {
|
||||
tap->setPeer(peer);
|
||||
|
|
|
@ -664,6 +664,7 @@ IdeController::unserialize(Checkpoint *cp, const std::string §ion)
|
|||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController)
|
||||
|
||||
Param<Addr> addr;
|
||||
SimObjectVectorParam<IdeDisk *> disks;
|
||||
SimObjectParam<MemoryController *> mmu;
|
||||
SimObjectParam<PciConfigAll *> configspace;
|
||||
|
@ -680,6 +681,7 @@ END_DECLARE_SIM_OBJECT_PARAMS(IdeController)
|
|||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController)
|
||||
|
||||
INIT_PARAM(addr, "Device Address"),
|
||||
INIT_PARAM(disks, "IDE disks attached to this controller"),
|
||||
INIT_PARAM(mmu, "Memory controller"),
|
||||
INIT_PARAM(configspace, "PCI Configspace"),
|
||||
|
|
|
@ -1171,12 +1171,14 @@ IdeDisk::unserialize(Checkpoint *cp, const string §ion)
|
|||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
enum DriveID { master, slave };
|
||||
static const char *DriveID_strings[] = { "master", "slave" };
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeDisk)
|
||||
|
||||
SimObjectParam<DiskImage *> image;
|
||||
SimObjectParam<PhysicalMemory *> physmem;
|
||||
Param<int> driveID;
|
||||
Param<int> disk_delay;
|
||||
SimpleEnumParam<DriveID> driveID;
|
||||
Param<int> delay;
|
||||
|
||||
END_DECLARE_SIM_OBJECT_PARAMS(IdeDisk)
|
||||
|
||||
|
@ -1184,16 +1186,15 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(IdeDisk)
|
|||
|
||||
INIT_PARAM(image, "Disk image"),
|
||||
INIT_PARAM(physmem, "Physical memory"),
|
||||
INIT_PARAM(driveID, "Drive ID (0=master 1=slave)"),
|
||||
INIT_PARAM_DFLT(disk_delay, "Fixed disk delay in microseconds", 1)
|
||||
INIT_ENUM_PARAM(driveID, "Drive ID (0=master 1=slave)", DriveID_strings),
|
||||
INIT_PARAM_DFLT(delay, "Fixed disk delay in microseconds", 1)
|
||||
|
||||
END_INIT_SIM_OBJECT_PARAMS(IdeDisk)
|
||||
|
||||
|
||||
CREATE_SIM_OBJECT(IdeDisk)
|
||||
{
|
||||
return new IdeDisk(getInstanceName(), image, physmem, driveID,
|
||||
disk_delay);
|
||||
return new IdeDisk(getInstanceName(), image, physmem, driveID, delay);
|
||||
}
|
||||
|
||||
REGISTER_SIM_OBJECT("IdeDisk", IdeDisk)
|
||||
|
|
|
@ -31,8 +31,8 @@
|
|||
#include "mem/bus/dma_interface.hh"
|
||||
#include "sim/builder.hh"
|
||||
|
||||
PioDevice::PioDevice(const std::string &name)
|
||||
: FunctionalMemory(name), pioInterface(NULL), pioLatency(0)
|
||||
PioDevice::PioDevice(const std::string &name, Platform *p)
|
||||
: FunctionalMemory(name), platform(p), pioInterface(NULL), pioLatency(0)
|
||||
{}
|
||||
|
||||
PioDevice::~PioDevice()
|
||||
|
@ -43,8 +43,8 @@ PioDevice::~PioDevice()
|
|||
|
||||
DEFINE_SIM_OBJECT_CLASS_NAME("PioDevice", PioDevice)
|
||||
|
||||
DmaDevice::DmaDevice(const std::string &name)
|
||||
: PioDevice(name), dmaInterface(NULL)
|
||||
DmaDevice::DmaDevice(const std::string &name, Platform *p)
|
||||
: PioDevice(name, p), dmaInterface(NULL)
|
||||
{}
|
||||
|
||||
DmaDevice::~DmaDevice()
|
||||
|
|
|
@ -26,24 +26,26 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __IO_DEVICE_HH__
|
||||
#define __IO_DEVICE_HH__
|
||||
#ifndef __DEV_IO_DEVICE_HH__
|
||||
#define __DEV_IO_DEVICE_HH__
|
||||
|
||||
#include "mem/functional_mem/functional_memory.hh"
|
||||
|
||||
class BaseInterface;
|
||||
class Bus;
|
||||
class HierParams;
|
||||
class Platform;
|
||||
template <class BusType> class DMAInterface;
|
||||
|
||||
class PioDevice : public FunctionalMemory
|
||||
{
|
||||
protected:
|
||||
Platform *platform;
|
||||
BaseInterface *pioInterface;
|
||||
Tick pioLatency;
|
||||
|
||||
public:
|
||||
PioDevice(const std::string &name);
|
||||
PioDevice(const std::string &name, Platform *p);
|
||||
virtual ~PioDevice();
|
||||
};
|
||||
|
||||
|
@ -53,8 +55,8 @@ class DmaDevice : public PioDevice
|
|||
DMAInterface<Bus> *dmaInterface;
|
||||
|
||||
public:
|
||||
DmaDevice(const std::string &name);
|
||||
DmaDevice(const std::string &name, Platform *p);
|
||||
virtual ~DmaDevice();
|
||||
};
|
||||
|
||||
#endif // __IO_DEVICE_HH__
|
||||
#endif // __DEV_IO_DEVICE_HH__
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
|
||||
#include "base/inet.hh"
|
||||
#include "cpu/exec_context.hh"
|
||||
#include "cpu/intr_control.hh"
|
||||
#include "dev/dma.hh"
|
||||
#include "dev/etherlink.hh"
|
||||
#include "dev/ns_gige.hh"
|
||||
|
@ -2637,6 +2636,7 @@ REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt)
|
|||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
|
||||
|
||||
Param<Addr> addr;
|
||||
Param<Tick> tx_delay;
|
||||
Param<Tick> rx_delay;
|
||||
Param<Tick> intr_delay;
|
||||
|
@ -2644,7 +2644,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
|
|||
SimObjectParam<PhysicalMemory *> physmem;
|
||||
Param<bool> rx_filter;
|
||||
Param<string> hardware_address;
|
||||
SimObjectParam<Bus*> header_bus;
|
||||
SimObjectParam<Bus*> io_bus;
|
||||
SimObjectParam<Bus*> payload_bus;
|
||||
SimObjectParam<HierParams *> hier;
|
||||
Param<Tick> pio_latency;
|
||||
|
@ -2667,6 +2667,7 @@ END_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
|
|||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
|
||||
|
||||
INIT_PARAM(addr, "Device Address"),
|
||||
INIT_PARAM_DFLT(tx_delay, "Transmit Delay", 1000),
|
||||
INIT_PARAM_DFLT(rx_delay, "Receive Delay", 1000),
|
||||
INIT_PARAM_DFLT(intr_delay, "Interrupt Delay in microseconds", 0),
|
||||
|
@ -2675,7 +2676,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
|
|||
INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true),
|
||||
INIT_PARAM_DFLT(hardware_address, "Ethernet Hardware Address",
|
||||
"00:99:00:00:00:01"),
|
||||
INIT_PARAM_DFLT(header_bus, "The IO Bus to attach to for headers", NULL),
|
||||
INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to for headers", NULL),
|
||||
INIT_PARAM_DFLT(payload_bus, "The IO Bus to attach to for payload", NULL),
|
||||
INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams),
|
||||
INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
|
||||
|
@ -2715,7 +2716,7 @@ CREATE_SIM_OBJECT(NSGigE)
|
|||
params->tx_delay = tx_delay;
|
||||
params->rx_delay = rx_delay;
|
||||
params->hier = hier;
|
||||
params->header_bus = header_bus;
|
||||
params->header_bus = io_bus;
|
||||
params->payload_bus = payload_bus;
|
||||
params->pio_latency = pio_latency;
|
||||
params->dma_desc_free = dma_desc_free;
|
||||
|
|
|
@ -91,7 +91,6 @@ struct dp_rom {
|
|||
uint8_t perfectMatch[ETH_ADDR_LEN];
|
||||
};
|
||||
|
||||
class IntrControl;
|
||||
class NSGigEInt;
|
||||
class PhysicalMemory;
|
||||
class BaseInterface;
|
||||
|
@ -302,7 +301,6 @@ class NSGigE : public PciDev
|
|||
/**
|
||||
* Interrupt management
|
||||
*/
|
||||
IntrControl *intctrl;
|
||||
void devIntrPost(uint32_t interrupts);
|
||||
void devIntrClear(uint32_t interrupts);
|
||||
void devIntrChangeMask();
|
||||
|
|
|
@ -48,9 +48,10 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
PciConfigAll::PciConfigAll(const string &name, Addr a, MemoryController *mmu,
|
||||
PciConfigAll::PciConfigAll(const string &name,
|
||||
Addr a, MemoryController *mmu,
|
||||
HierParams *hier, Bus *bus, Tick pio_latency)
|
||||
: PioDevice(name), addr(a)
|
||||
: PioDevice(name, NULL), addr(a)
|
||||
{
|
||||
mmu->add_child(this, RangeSize(addr, size));
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "dev/pciareg.h"
|
||||
#include "dev/pcidev.hh"
|
||||
#include "dev/pciconfigall.hh"
|
||||
#include "mem/bus/bus.hh"
|
||||
#include "mem/functional_mem/memory_control.hh"
|
||||
#include "sim/builder.hh"
|
||||
#include "sim/param.hh"
|
||||
|
@ -51,7 +52,8 @@
|
|||
using namespace std;
|
||||
|
||||
PciDev::PciDev(Params *p)
|
||||
: DmaDevice(p->name), _params(p), plat(p->plat), configData(p->configData)
|
||||
: DmaDevice(p->name, p->plat), _params(p), plat(p->plat),
|
||||
configData(p->configData)
|
||||
{
|
||||
// copy the config data from the PciConfigData object
|
||||
if (configData) {
|
||||
|
@ -283,6 +285,11 @@ PciDev::unserialize(Checkpoint *cp, const std::string §ion)
|
|||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(PciConfigData)
|
||||
|
||||
SimObjectParam<MemoryController *> mmu;
|
||||
Param<Addr> addr;
|
||||
SimObjectParam<Bus*> io_bus;
|
||||
Param<Tick> pio_latency;
|
||||
|
||||
Param<uint16_t> VendorID;
|
||||
Param<uint16_t> DeviceID;
|
||||
Param<uint16_t> Command;
|
||||
|
@ -320,6 +327,11 @@ END_DECLARE_SIM_OBJECT_PARAMS(PciConfigData)
|
|||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(PciConfigData)
|
||||
|
||||
INIT_PARAM(mmu, "Memory Controller"),
|
||||
INIT_PARAM(addr, "Device Address"),
|
||||
INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL),
|
||||
INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
|
||||
|
||||
INIT_PARAM(VendorID, "Vendor ID"),
|
||||
INIT_PARAM(DeviceID, "Device ID"),
|
||||
INIT_PARAM_DFLT(Command, "Command Register", 0x00),
|
||||
|
|
|
@ -47,8 +47,6 @@ class Platform : public SimObject
|
|||
public:
|
||||
/** Pointer to the interrupt controller */
|
||||
IntrControl *intrctrl;
|
||||
/** Pointer to the simulation console */
|
||||
SimConsole *cons;
|
||||
/** Pointer to the PCI configuration space */
|
||||
PciConfigAll *pciconfig;
|
||||
|
||||
|
|
|
@ -107,7 +107,6 @@ Tsunami::unserialize(Checkpoint *cp, const std::string §ion)
|
|||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tsunami)
|
||||
|
||||
SimObjectParam<System *> system;
|
||||
SimObjectParam<SimConsole *> cons;
|
||||
SimObjectParam<IntrControl *> intrctrl;
|
||||
SimObjectParam<PciConfigAll *> pciconfig;
|
||||
Param<int> interrupt_frequency;
|
||||
|
@ -117,7 +116,6 @@ END_DECLARE_SIM_OBJECT_PARAMS(Tsunami)
|
|||
BEGIN_INIT_SIM_OBJECT_PARAMS(Tsunami)
|
||||
|
||||
INIT_PARAM(system, "system"),
|
||||
INIT_PARAM(cons, "system console"),
|
||||
INIT_PARAM(intrctrl, "interrupt controller"),
|
||||
INIT_PARAM(pciconfig, "PCI configuration"),
|
||||
INIT_PARAM_DFLT(interrupt_frequency, "frequency of interrupts", 1024)
|
||||
|
|
|
@ -51,7 +51,7 @@ using namespace std;
|
|||
TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a,
|
||||
MemoryController *mmu, HierParams *hier, Bus* bus,
|
||||
Tick pio_latency)
|
||||
: PioDevice(name), addr(a), tsunami(t)
|
||||
: PioDevice(name, t), addr(a), tsunami(t)
|
||||
{
|
||||
mmu->add_child(this, RangeSize(addr, size));
|
||||
|
||||
|
|
|
@ -162,7 +162,7 @@ TsunamiIO::ClockEvent::unserialize(Checkpoint *cp, const std::string §ion)
|
|||
TsunamiIO::TsunamiIO(const string &name, Tsunami *t, time_t init_time,
|
||||
Addr a, MemoryController *mmu, HierParams *hier, Bus *bus,
|
||||
Tick pio_latency)
|
||||
: PioDevice(name), addr(a), tsunami(t), rtc(t)
|
||||
: PioDevice(name, t), addr(a), tsunami(t), rtc(t)
|
||||
{
|
||||
mmu->add_child(this, RangeSize(addr, size));
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ using namespace std;
|
|||
TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a,
|
||||
MemoryController *mmu, HierParams *hier,
|
||||
Bus *bus, Tick pio_latency)
|
||||
: PioDevice(name), addr(a), tsunami(t)
|
||||
: PioDevice(name, t), addr(a), tsunami(t)
|
||||
{
|
||||
mmu->add_child(this, RangeSize(addr, size));
|
||||
|
||||
|
|
|
@ -88,8 +88,8 @@ Uart::IntrEvent::scheduleIntr()
|
|||
|
||||
Uart::Uart(const string &name, SimConsole *c, MemoryController *mmu, Addr a,
|
||||
Addr s, HierParams *hier, Bus *bus, Tick pio_latency, Platform *p)
|
||||
: PioDevice(name), addr(a), size(s), cons(c), txIntrEvent(this, TX_INT),
|
||||
rxIntrEvent(this, RX_INT), platform(p)
|
||||
: PioDevice(name, p), addr(a), size(s), cons(c),
|
||||
txIntrEvent(this, TX_INT), rxIntrEvent(this, RX_INT)
|
||||
{
|
||||
mmu->add_child(this, RangeSize(addr, size));
|
||||
|
||||
|
|
|
@ -72,7 +72,6 @@ class Uart : public PioDevice
|
|||
|
||||
IntrEvent txIntrEvent;
|
||||
IntrEvent rxIntrEvent;
|
||||
Platform *platform;
|
||||
|
||||
public:
|
||||
Uart(const std::string &name, SimConsole *c, MemoryController *mmu,
|
||||
|
|
|
@ -208,12 +208,12 @@ LinuxSystem::setDelayLoop(ExecContext *xc)
|
|||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem)
|
||||
|
||||
SimObjectParam<MemoryController *> mem_ctl;
|
||||
SimObjectParam<MemoryController *> memctrl;
|
||||
SimObjectParam<PhysicalMemory *> physmem;
|
||||
|
||||
Param<string> kernel_code;
|
||||
Param<string> console_code;
|
||||
Param<string> pal_code;
|
||||
Param<string> kernel;
|
||||
Param<string> console;
|
||||
Param<string> pal;
|
||||
|
||||
Param<string> boot_osflags;
|
||||
Param<string> readfile;
|
||||
|
@ -230,11 +230,11 @@ END_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem)
|
|||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxSystem)
|
||||
|
||||
INIT_PARAM(mem_ctl, "memory controller"),
|
||||
INIT_PARAM(memctrl, "memory controller"),
|
||||
INIT_PARAM(physmem, "phsyical memory"),
|
||||
INIT_PARAM(kernel_code, "file that contains the kernel code"),
|
||||
INIT_PARAM(console_code, "file that contains the console code"),
|
||||
INIT_PARAM(pal_code, "file that contains palcode"),
|
||||
INIT_PARAM(kernel, "file that contains the kernel code"),
|
||||
INIT_PARAM(console, "file that contains the console code"),
|
||||
INIT_PARAM(pal, "file that contains palcode"),
|
||||
INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
|
||||
"a"),
|
||||
INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
|
||||
|
@ -251,11 +251,11 @@ CREATE_SIM_OBJECT(LinuxSystem)
|
|||
{
|
||||
System::Params *p = new System::Params;
|
||||
p->name = getInstanceName();
|
||||
p->memctrl = mem_ctl;
|
||||
p->memctrl = memctrl;
|
||||
p->physmem = physmem;
|
||||
p->kernel_path = kernel_code;
|
||||
p->console_path = console_code;
|
||||
p->palcode = pal_code;
|
||||
p->kernel_path = kernel;
|
||||
p->console_path = console;
|
||||
p->palcode = pal;
|
||||
p->boot_osflags = boot_osflags;
|
||||
p->init_param = init_param;
|
||||
p->readfile = readfile;
|
||||
|
|
|
@ -116,12 +116,12 @@ Tru64System::~Tru64System()
|
|||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64System)
|
||||
|
||||
SimObjectParam<MemoryController *> mem_ctl;
|
||||
SimObjectParam<MemoryController *> memctrl;
|
||||
SimObjectParam<PhysicalMemory *> physmem;
|
||||
|
||||
Param<string> kernel_code;
|
||||
Param<string> console_code;
|
||||
Param<string> pal_code;
|
||||
Param<string> kernel;
|
||||
Param<string> console;
|
||||
Param<string> pal;
|
||||
|
||||
Param<string> boot_osflags;
|
||||
Param<string> readfile;
|
||||
|
@ -137,11 +137,11 @@ END_DECLARE_SIM_OBJECT_PARAMS(Tru64System)
|
|||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(Tru64System)
|
||||
|
||||
INIT_PARAM(mem_ctl, "memory controller"),
|
||||
INIT_PARAM(memctrl, "memory controller"),
|
||||
INIT_PARAM(physmem, "phsyical memory"),
|
||||
INIT_PARAM(kernel_code, "file that contains the kernel code"),
|
||||
INIT_PARAM(console_code, "file that contains the console code"),
|
||||
INIT_PARAM(pal_code, "file that contains palcode"),
|
||||
INIT_PARAM(kernel, "file that contains the kernel code"),
|
||||
INIT_PARAM(console, "file that contains the console code"),
|
||||
INIT_PARAM(pal, "file that contains palcode"),
|
||||
INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
|
||||
"a"),
|
||||
INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
|
||||
|
@ -157,11 +157,11 @@ CREATE_SIM_OBJECT(Tru64System)
|
|||
{
|
||||
System::Params *p = new System::Params;
|
||||
p->name = getInstanceName();
|
||||
p->memctrl = mem_ctl;
|
||||
p->memctrl = memctrl;
|
||||
p->physmem = physmem;
|
||||
p->kernel_path = kernel_code;
|
||||
p->console_path = console_code;
|
||||
p->palcode = pal_code;
|
||||
p->kernel_path = kernel;
|
||||
p->console_path = console;
|
||||
p->palcode = pal;
|
||||
p->boot_osflags = boot_osflags;
|
||||
p->init_param = init_param;
|
||||
p->readfile = readfile;
|
||||
|
|
8
objects/AlphaConsole.mpy
Normal file
8
objects/AlphaConsole.mpy
Normal file
|
@ -0,0 +1,8 @@
|
|||
from Device import PioDevice
|
||||
|
||||
simobj AlphaConsole(PioDevice):
|
||||
cpu = Param.BaseCPU(Super, "Processor")
|
||||
disk = Param.SimpleDisk("Simple Disk")
|
||||
num_cpus = Param.Int(1, "Number of CPU's")
|
||||
sim_console = Param.SimConsole(Super, "The Simulator Console")
|
||||
system = Param.BaseSystem(Super, "system object")
|
9
objects/AlphaTLB.mpy
Normal file
9
objects/AlphaTLB.mpy
Normal file
|
@ -0,0 +1,9 @@
|
|||
simobj AlphaTLB(SimObject):
|
||||
abstract = True
|
||||
size = Param.Int("TLB size")
|
||||
|
||||
simobj AlphaDTB(AlphaTLB):
|
||||
size = 64
|
||||
|
||||
simobj AlphaITB(AlphaTLB):
|
||||
size = 48
|
4
objects/BadDevice.mpy
Normal file
4
objects/BadDevice.mpy
Normal file
|
@ -0,0 +1,4 @@
|
|||
from Device import PioDevice
|
||||
|
||||
simobj BadDevice(PioDevice):
|
||||
devicename = Param.String("Name of device to error on")
|
38
objects/BaseCPU.mpy
Normal file
38
objects/BaseCPU.mpy
Normal file
|
@ -0,0 +1,38 @@
|
|||
simobj BaseCPU(SimObject):
|
||||
abstract = True
|
||||
icache = Param.BaseMem(NULL, "L1 instruction cache object")
|
||||
dcache = Param.BaseMem(NULL, "L1 data cache object")
|
||||
|
||||
dtb = Param.AlphaDTB("Data TLB")
|
||||
itb = Param.AlphaITB("Instruction TLB")
|
||||
mem = Param.FunctionalMemory("memory")
|
||||
system = Param.BaseSystem(Super, "system object")
|
||||
workload = VectorParam.Process("processes to run")
|
||||
|
||||
max_insts_all_threads = Param.Counter(0,
|
||||
"terminate when all threads have reached this inst count")
|
||||
max_insts_any_thread = Param.Counter(0,
|
||||
"terminate when any thread reaches this inst count")
|
||||
max_loads_all_threads = Param.Counter(0,
|
||||
"terminate when all threads have reached this load count")
|
||||
max_loads_any_thread = Param.Counter(0,
|
||||
"terminate when any thread reaches this load count")
|
||||
|
||||
defer_registration = Param.Bool(false,
|
||||
"defer registration with system (for sampling)")
|
||||
|
||||
def check(self):
|
||||
has_workload = self._hasvalue('workload')
|
||||
has_dtb = self._hasvalue('dtb')
|
||||
has_itb = self._hasvalue('itb')
|
||||
has_mem = self._hasvalue('mem')
|
||||
has_system = self._hasvalue('system')
|
||||
|
||||
if has_workload:
|
||||
self.dtb.disable = True
|
||||
self.itb.disable = True
|
||||
self.mem.disable = True
|
||||
self.system.disable = True
|
||||
|
||||
if has_dtb or has_itb or has_mem or has_system:
|
||||
self.workload.disable = True
|
30
objects/BaseCache.mpy
Normal file
30
objects/BaseCache.mpy
Normal file
|
@ -0,0 +1,30 @@
|
|||
from BaseMem import BaseMem
|
||||
|
||||
simobj BaseCache(BaseMem):
|
||||
adaptive_compression = Param.Bool(false,
|
||||
"Use an adaptive compression scheme")
|
||||
assoc = Param.Int("associativity")
|
||||
block_size = Param.Int("block size in bytes")
|
||||
compressed_bus = Param.Bool(false,
|
||||
"This cache connects to a compressed memory")
|
||||
compression_latency = Param.Int(0,
|
||||
"Latency in cycles of compression algorithm")
|
||||
do_copy = Param.Bool(false, "perform fast copies in the cache")
|
||||
hash_delay = Param.Int(1, "time in cycles of hash access")
|
||||
in_bus = Param.Bus(NULL, "incoming bus object")
|
||||
max_miss_count = Param.Counter(0,
|
||||
"number of misses to handle before calling exit")
|
||||
mshrs = Param.Int("number of MSHRs (max outstanding requests)")
|
||||
out_bus = Param.Bus("outgoing bus object")
|
||||
prioritizeRequests = Param.Bool(false,
|
||||
"always service demand misses first")
|
||||
protocol = Param.CoherenceProtocol(NULL, "coherence protocol to use")
|
||||
repl = Param.Repl(NULL, "replacement policy")
|
||||
size = Param.Int("capacity in bytes")
|
||||
store_compressed = Param.Bool(false,
|
||||
"Store compressed data in the cache")
|
||||
subblock_size = Param.Int(0,
|
||||
"Size of subblock in IIC used for compression")
|
||||
tgts_per_mshr = Param.Int("max number of accesses per MSHR")
|
||||
trace_addr = Param.Addr(0, "address to trace")
|
||||
write_buffers = Param.Int(8, "number of write buffers")
|
14
objects/BaseSystem.mpy
Normal file
14
objects/BaseSystem.mpy
Normal file
|
@ -0,0 +1,14 @@
|
|||
simobj BaseSystem(SimObject):
|
||||
abstract = True
|
||||
memctrl = Param.MemoryController(Super, "memory controller")
|
||||
physmem = Param.PhysicalMemory(Super, "phsyical memory")
|
||||
kernel = Param.String("file that contains the kernel code")
|
||||
console = Param.String("file that contains the console code")
|
||||
pal = Param.String("file that contains palcode")
|
||||
readfile = Param.String("", "file to read startup script from")
|
||||
init_param = Param.UInt64(0, "numerical value to pass into simulator")
|
||||
boot_osflags = Param.String("a", "boot flags to pass to the kernel")
|
||||
system_type = Param.UInt64("Type of system we are emulating")
|
||||
system_rev = Param.UInt64("Revision of system we are emulating")
|
||||
bin = Param.Bool(false, "is this system binned")
|
||||
binned_fns = VectorParam.String([], "functions broken down and binned")
|
5
objects/Bus.mpy
Normal file
5
objects/Bus.mpy
Normal file
|
@ -0,0 +1,5 @@
|
|||
from BaseHier import BaseHier
|
||||
|
||||
simobj Bus(BaseHier):
|
||||
clock_ratio = Param.Int("ratio of CPU to bus frequency")
|
||||
width = Param.Int("bus width in bytes")
|
5
objects/CoherenceProtocol.mpy
Normal file
5
objects/CoherenceProtocol.mpy
Normal file
|
@ -0,0 +1,5 @@
|
|||
Coherence = Enum('uni', 'msi', 'mesi', 'mosi', 'moesi')
|
||||
|
||||
simobj CoherenceProtocol(SimObject):
|
||||
do_upgrades = Param.Bool(true, "use upgrade transactions?")
|
||||
protocol = Param.Coherence("name of coherence protocol")
|
31
objects/Device.mpy
Normal file
31
objects/Device.mpy
Normal file
|
@ -0,0 +1,31 @@
|
|||
from FunctionalMemory import FunctionalMemory
|
||||
|
||||
# This device exists only because there are some devices that I don't
|
||||
# want to have a Platform parameter because it would cause a cycle in
|
||||
# the C++ that cannot be easily solved.
|
||||
#
|
||||
# The real solution to this problem is to pass the ParamXXX structure
|
||||
# to the constructor, but with the express condition that SimObject
|
||||
# parameter values are not to be available at construction time. If
|
||||
# some further configuration must be done, it must be done during the
|
||||
# initialization phase at which point all SimObject pointers will be
|
||||
# valid.
|
||||
simobj FooPioDevice(FunctionalMemory):
|
||||
abstract = True
|
||||
type = 'PioDevice'
|
||||
addr = Param.Addr("Device Address")
|
||||
mmu = Param.MemoryController(Super, "Memory Controller")
|
||||
io_bus = Param.Bus(NULL, "The IO Bus to attach to")
|
||||
pio_latency = Param.Tick(1, "Programmed IO latency in bus cycles")
|
||||
|
||||
simobj FooDmaDevice(FooPioDevice):
|
||||
abstract = True
|
||||
type = 'DmaDevice'
|
||||
|
||||
simobj PioDevice(FooPioDevice):
|
||||
abstract = True
|
||||
platform = Param.Platform(Super, "Platform")
|
||||
|
||||
simobj DmaDevice(PioDevice):
|
||||
abstract = True
|
||||
|
12
objects/DiskImage.mpy
Normal file
12
objects/DiskImage.mpy
Normal file
|
@ -0,0 +1,12 @@
|
|||
simobj DiskImage(SimObject):
|
||||
abstract = True
|
||||
image_file = Param.String("disk image file")
|
||||
read_only = Param.Bool(false, "read only image")
|
||||
|
||||
simobj RawDiskImage(DiskImage):
|
||||
pass
|
||||
|
||||
simobj CowDiskImage(DiskImage):
|
||||
child = Param.DiskImage("child image")
|
||||
table_size = Param.Int(65536, "initial table size")
|
||||
image_file = ''
|
77
objects/Ethernet.mpy
Normal file
77
objects/Ethernet.mpy
Normal file
|
@ -0,0 +1,77 @@
|
|||
from Device import DmaDevice
|
||||
from Pci import PciDevice
|
||||
|
||||
simobj EtherInt(SimObject):
|
||||
abstract = True
|
||||
peer = Param.EtherInt(NULL, "peer interface")
|
||||
|
||||
simobj EtherLink(SimObject):
|
||||
int1 = Param.EtherInt("interface 1")
|
||||
int2 = Param.EtherInt("interface 2")
|
||||
delay = Param.Tick(0, "transmit delay of packets in us")
|
||||
speed = Param.Tick(100000000, "link speed in bits per second")
|
||||
dump = Param.EtherDump(NULL, "dump object")
|
||||
|
||||
simobj EtherBus(SimObject):
|
||||
loopback = Param.Bool(true,
|
||||
"send packet back to the interface from which it came")
|
||||
dump = Param.EtherDump(NULL, "dump object")
|
||||
speed = Param.UInt64(100000000, "bus speed in bits per second")
|
||||
|
||||
simobj EtherTap(EtherInt):
|
||||
bufsz = Param.Int(10000, "tap buffer size")
|
||||
dump = Param.EtherDump(NULL, "dump object")
|
||||
port = Param.UInt16(3500, "tap port")
|
||||
|
||||
simobj EtherDump(SimObject):
|
||||
file = Param.String("dump file")
|
||||
|
||||
simobj EtherDev(DmaDevice):
|
||||
hardware_address = Param.EthernetAddr(NextEthernetAddr,
|
||||
"Ethernet Hardware Address")
|
||||
|
||||
dma_data_free = Param.Bool(false, "DMA of Data is free")
|
||||
dma_desc_free = Param.Bool(false, "DMA of Descriptors is free")
|
||||
dma_read_delay = Param.Tick(0, "fixed delay for dma reads")
|
||||
dma_read_factor = Param.Tick(0, "multiplier for dma reads")
|
||||
dma_write_delay = Param.Tick(0, "fixed delay for dma writes")
|
||||
dma_write_factor = Param.Tick(0, "multiplier for dma writes")
|
||||
|
||||
rx_filter = Param.Bool(true, "Enable Receive Filter")
|
||||
rx_delay = Param.Tick(1000, "Receive Delay")
|
||||
tx_delay = Param.Tick(1000, "Transmit Delay")
|
||||
|
||||
intr_delay = Param.Tick(0, "Interrupt Delay in microseconds")
|
||||
payload_bus = Param.Bus(NULL, "The IO Bus to attach to for payload")
|
||||
physmem = Param.PhysicalMemory(Super, "Physical Memory")
|
||||
tlaser = Param.Turbolaser(Super, "Turbolaser")
|
||||
|
||||
simobj NSGigE(PciDevice):
|
||||
hardware_address = Param.EthernetAddr(NextEthernetAddr,
|
||||
"Ethernet Hardware Address")
|
||||
|
||||
dma_data_free = Param.Bool(false, "DMA of Data is free")
|
||||
dma_desc_free = Param.Bool(false, "DMA of Descriptors is free")
|
||||
dma_read_delay = Param.Tick(0, "fixed delay for dma reads")
|
||||
dma_read_factor = Param.Tick(0, "multiplier for dma reads")
|
||||
dma_write_delay = Param.Tick(0, "fixed delay for dma writes")
|
||||
dma_write_factor = Param.Tick(0, "multiplier for dma writes")
|
||||
|
||||
rx_filter = Param.Bool(true, "Enable Receive Filter")
|
||||
rx_delay = Param.Tick(1000, "Receive Delay")
|
||||
tx_delay = Param.Tick(1000, "Transmit Delay")
|
||||
|
||||
rx_fifo_size = Param.Int(131072, "max size in bytes of rxFifo")
|
||||
tx_fifo_size = Param.Int(131072, "max size in bytes of txFifo")
|
||||
|
||||
intr_delay = Param.Tick(0, "Interrupt Delay in microseconds")
|
||||
payload_bus = Param.Bus(NULL, "The IO Bus to attach to for payload")
|
||||
physmem = Param.PhysicalMemory(Super, "Physical Memory")
|
||||
|
||||
simobj EtherDevInt(EtherInt):
|
||||
device = Param.EtherDev("Ethernet device of this interface")
|
||||
|
||||
simobj NSGigEInt(EtherInt):
|
||||
device = Param.NSGigE("Ethernet device of this interface")
|
||||
|
||||
|
12
objects/Ide.mpy
Normal file
12
objects/Ide.mpy
Normal file
|
@ -0,0 +1,12 @@
|
|||
from Pci import PciDevice
|
||||
|
||||
IdeID = Enum('master', 'slave')
|
||||
|
||||
simobj IdeDisk(SimObject):
|
||||
delay = Param.Tick(1, "Fixed disk delay in microseconds")
|
||||
driveID = Param.IdeID('master', "Drive ID")
|
||||
image = Param.DiskImage("Disk image")
|
||||
physmem = Param.PhysicalMemory(Super, "Physical memory")
|
||||
|
||||
simobj IdeController(PciDevice):
|
||||
disks = VectorParam.IdeDisk("IDE disks attached to this controller")
|
2
objects/IntrControl.mpy
Normal file
2
objects/IntrControl.mpy
Normal file
|
@ -0,0 +1,2 @@
|
|||
simobj IntrControl(SimObject):
|
||||
cpu = Param.BaseCPU(Super, "the cpu")
|
20
objects/MemTest.mpy
Normal file
20
objects/MemTest.mpy
Normal file
|
@ -0,0 +1,20 @@
|
|||
simobj MemTest(SimObject):
|
||||
cache = Param.BaseCache("L1 cache")
|
||||
check_mem = Param.FunctionalMemory("check memory")
|
||||
main_mem = Param.FunctionalMemory("hierarchical memory")
|
||||
max_loads_all_threads = Param.Counter(0,
|
||||
"terminate when all threads have reached this load count")
|
||||
max_loads_any_thread = Param.Counter(0,
|
||||
"terminate when any thread reaches this load count")
|
||||
memory_size = Param.Int(65536, "memory size")
|
||||
percent_copies = Param.Percent(0, "target copy percentage")
|
||||
percent_dest_unaligned = Param.Percent(50,
|
||||
"percent of copy dest address that are unaligned")
|
||||
percent_reads = Param.Percent(65, "target read percentage")
|
||||
percent_source_unaligned = Param.Percent(50,
|
||||
"percent of copy source address that are unaligned")
|
||||
percent_uncacheable = Param.Percent(10,
|
||||
"target uncacheable percentage")
|
||||
progress_interval = Param.Counter(1000000,
|
||||
"progress report interval (in accesses)")
|
||||
trace_addr = Param.Addr(0, "address to trace")
|
50
objects/Pci.mpy
Normal file
50
objects/Pci.mpy
Normal file
|
@ -0,0 +1,50 @@
|
|||
from Device import FooPioDevice, DmaDevice
|
||||
|
||||
simobj PciConfigData(FooPioDevice):
|
||||
addr = 0xffffffffffffffff
|
||||
VendorID = Param.UInt16("Vendor ID")
|
||||
DeviceID = Param.UInt16("Device ID")
|
||||
Command = Param.UInt16(0, "Command")
|
||||
Status = Param.UInt16(0, "Status")
|
||||
Revision = Param.UInt8(0, "Device")
|
||||
ProgIF = Param.UInt8(0, "Programming Interface")
|
||||
SubClassCode = Param.UInt8(0, "Sub-Class Code")
|
||||
ClassCode = Param.UInt8(0, "Class Code")
|
||||
CacheLineSize = Param.UInt8(0, "System Cacheline Size")
|
||||
LatencyTimer = Param.UInt8(0, "PCI Latency Timer")
|
||||
HeaderType = Param.UInt8(0, "PCI Header Type")
|
||||
BIST = Param.UInt8(0, "Built In Self Test")
|
||||
|
||||
BAR0 = Param.UInt32(0x00, "Base Address Register 0")
|
||||
BAR1 = Param.UInt32(0x00, "Base Address Register 1")
|
||||
BAR2 = Param.UInt32(0x00, "Base Address Register 2")
|
||||
BAR3 = Param.UInt32(0x00, "Base Address Register 3")
|
||||
BAR4 = Param.UInt32(0x00, "Base Address Register 4")
|
||||
BAR5 = Param.UInt32(0x00, "Base Address Register 5")
|
||||
BAR0Size = Param.UInt32(0, "Base Address Register 0 Size")
|
||||
BAR1Size = Param.UInt32(0, "Base Address Register 1 Size")
|
||||
BAR2Size = Param.UInt32(0, "Base Address Register 2 Size")
|
||||
BAR3Size = Param.UInt32(0, "Base Address Register 3 Size")
|
||||
BAR4Size = Param.UInt32(0, "Base Address Register 4 Size")
|
||||
BAR5Size = Param.UInt32(0, "Base Address Register 5 Size")
|
||||
|
||||
CardbusCIS = Param.UInt32(0x00, "Cardbus Card Information Structure")
|
||||
SubsystemID = Param.UInt16(0x00, "Subsystem ID")
|
||||
SubsystemVendorID = Param.UInt16(0x00, "Subsystem Vendor ID")
|
||||
ExpansionROM = Param.UInt32(0x00, "Expansion ROM Base Address")
|
||||
InterruptLine = Param.UInt8(0x00, "Interrupt Line")
|
||||
InterruptPin = Param.UInt8(0x00, "Interrupt Pin")
|
||||
MaximumLatency = Param.UInt8(0x00, "Maximum Latency")
|
||||
MinimumGrant = Param.UInt8(0x00, "Minimum Grant")
|
||||
|
||||
simobj PciConfigAll(FooPioDevice):
|
||||
pass
|
||||
|
||||
simobj PciDevice(DmaDevice):
|
||||
abstract = True
|
||||
pci_bus = Param.Int("PCI bus")
|
||||
pci_dev = Param.Int("PCI device number")
|
||||
pci_func = Param.Int("PCI function code")
|
||||
configdata = Param.PciConfigData(Super, "PCI Config data")
|
||||
configspace = Param.PciConfigAll(Super, "PCI Configspace")
|
||||
addr = 0xffffffffffffffff
|
6
objects/PhysicalMemory.mpy
Normal file
6
objects/PhysicalMemory.mpy
Normal file
|
@ -0,0 +1,6 @@
|
|||
from FunctionalMemory import FunctionalMemory
|
||||
|
||||
simobj PhysicalMemory(FunctionalMemory):
|
||||
range = Param.AddrRange("Device Address")
|
||||
file = Param.String('', "memory mapped file")
|
||||
mmu = Param.MemoryController(Super, "Memory Controller")
|
4
objects/Platform.mpy
Normal file
4
objects/Platform.mpy
Normal file
|
@ -0,0 +1,4 @@
|
|||
simobj Platform(SimObject):
|
||||
abstract = True
|
||||
interrupt_frequency = Param.Tick(1200, "frequency of interrupts")
|
||||
intrctrl = Param.IntrControl(Super, "interrupt controller")
|
12
objects/Process.mpy
Normal file
12
objects/Process.mpy
Normal file
|
@ -0,0 +1,12 @@
|
|||
simobj Process(SimObject):
|
||||
abstract = True
|
||||
output = Param.String('cout', 'filename for stdout/stderr')
|
||||
|
||||
simobj LiveProcess(Process):
|
||||
cmd = VectorParam.String("command line (executable plus arguments)")
|
||||
env = VectorParam.String('', "environment settings")
|
||||
input = Param.String('cin', "filename for stdin")
|
||||
|
||||
simobj EioProcess(Process):
|
||||
chkpt = Param.String('', "EIO checkpoint file name (optional)")
|
||||
file = Param.String("EIO trace file name")
|
7
objects/Repl.mpy
Normal file
7
objects/Repl.mpy
Normal file
|
@ -0,0 +1,7 @@
|
|||
simobj Repl(SimObject):
|
||||
abstract = True
|
||||
|
||||
simobj GenRepl(Repl):
|
||||
fresh_res = Param.Int("associativity")
|
||||
num_pools = Param.Int("capacity in bytes")
|
||||
pool_res = Param.Int("block size in bytes")
|
9
objects/Root.mpy
Normal file
9
objects/Root.mpy
Normal file
|
@ -0,0 +1,9 @@
|
|||
from HierParams import HierParams
|
||||
simobj Root(SimObject):
|
||||
frequency = Param.Tick(200000000, "tick frequency")
|
||||
output_dir = Param.String('.', "directory to output data to")
|
||||
output_file = Param.String('cout', "file to dump simulator output to")
|
||||
config_output_file = Param.String('m5config.out',
|
||||
"file to dump simulator config to")
|
||||
full_system = Param.Bool("Full system simulation?")
|
||||
hier = HierParams(do_data = false, do_events = true)
|
9
objects/SimConsole.mpy
Normal file
9
objects/SimConsole.mpy
Normal file
|
@ -0,0 +1,9 @@
|
|||
simobj ConsoleListener(SimObject):
|
||||
port = Param.UInt16(3456, "listen port")
|
||||
|
||||
simobj SimConsole(SimObject):
|
||||
append_name = Param.Bool(true, "append name() to filename")
|
||||
intr_control = Param.IntrControl(Super, "interrupt controller")
|
||||
listener = Param.ConsoleListener("console listener")
|
||||
number = Param.Int(0, "console number")
|
||||
output = Param.String("", "file to dump output to")
|
3
objects/SimpleDisk.mpy
Normal file
3
objects/SimpleDisk.mpy
Normal file
|
@ -0,0 +1,3 @@
|
|||
simobj SimpleDisk(SimObject):
|
||||
disk = Param.DiskImage("Disk Image")
|
||||
physmem = Param.PhysicalMemory(Super, "Physical Memory")
|
21
objects/Tsunami.mpy
Normal file
21
objects/Tsunami.mpy
Normal file
|
@ -0,0 +1,21 @@
|
|||
from Device import FooPioDevice
|
||||
from Platform import Platform
|
||||
|
||||
simobj Tsunami(Platform):
|
||||
pciconfig = Param.PciConfigAll("PCI configuration")
|
||||
system = Param.BaseSystem(Super, "system")
|
||||
interrupt_frequency = Param.Int(1024, "frequency of interrupts")
|
||||
|
||||
simobj TsunamiCChip(FooPioDevice):
|
||||
tsunami = Param.Tsunami(Super, "Tsunami")
|
||||
|
||||
simobj TsunamiFake(FooPioDevice):
|
||||
pass
|
||||
|
||||
simobj TsunamiIO(FooPioDevice):
|
||||
time = Param.UInt64(1136073600,
|
||||
"System time to use (0 for actual time, default is 1/1/06)")
|
||||
tsunami = Param.Tsunami(Super, "Tsunami")
|
||||
|
||||
simobj TsunamiPChip(FooPioDevice):
|
||||
tsunami = Param.Tsunami(Super, "Tsunami")
|
5
objects/Uart.mpy
Normal file
5
objects/Uart.mpy
Normal file
|
@ -0,0 +1,5 @@
|
|||
from Device import PioDevice
|
||||
|
||||
simobj Uart(PioDevice):
|
||||
console = Param.SimConsole(Super, "The console")
|
||||
size = Param.Addr(0x8, "Device size")
|
|
@ -39,14 +39,9 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
SimObjectBuilder::SimObjectBuilder(const string &_configClass,
|
||||
const string &_instanceName,
|
||||
ConfigNode *_configNode,
|
||||
const string &_simObjClassName)
|
||||
: ParamContext(_configClass, NoAutoInit),
|
||||
instanceName(_instanceName),
|
||||
configNode(_configNode),
|
||||
simObjClassName(_simObjClassName)
|
||||
SimObjectBuilder::SimObjectBuilder(ConfigNode *_configNode)
|
||||
: ParamContext(_configNode->getPath(), NoAutoInit),
|
||||
configNode(_configNode)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -72,13 +67,8 @@ SimObjectBuilder::parseParams(IniFile &iniFile)
|
|||
|
||||
for (i = paramList->begin(); i != paramList->end(); ++i) {
|
||||
string string_value;
|
||||
|
||||
if (iniFile.findDefault(instanceName, (*i)->name, string_value)) {
|
||||
if (iniFile.find(iniSection, (*i)->name, string_value))
|
||||
(*i)->parse(string_value);
|
||||
}
|
||||
else if (iniFile.findDefault(iniSection, (*i)->name, string_value)) {
|
||||
(*i)->parse(string_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,9 +76,8 @@ SimObjectBuilder::parseParams(IniFile &iniFile)
|
|||
void
|
||||
SimObjectBuilder::printErrorProlog(ostream &os)
|
||||
{
|
||||
os << "Error creating object '" << getInstanceName()
|
||||
<< "' of type '" << simObjClassName
|
||||
<< "', section '" << iniSection << "':" << endl;
|
||||
ccprintf(os, "Error creating object '%s' of type '%s':\n",
|
||||
iniSection, configNode->getType());
|
||||
}
|
||||
|
||||
|
||||
|
@ -111,11 +100,7 @@ SimObjectClass::SimObjectClass(const string &className, CreateFunc createFunc)
|
|||
classMap = new map<string,SimObjectClass::CreateFunc>();
|
||||
|
||||
if ((*classMap)[className])
|
||||
{
|
||||
cerr << "Error: simulation object class " << className << " redefined"
|
||||
<< endl;
|
||||
fatal("");
|
||||
}
|
||||
panic("Error: simulation object class '%s' redefined\n", className);
|
||||
|
||||
// add className --> createFunc to class map
|
||||
(*classMap)[className] = createFunc;
|
||||
|
@ -125,35 +110,20 @@ SimObjectClass::SimObjectClass(const string &className, CreateFunc createFunc)
|
|||
//
|
||||
//
|
||||
SimObject *
|
||||
SimObjectClass::createObject(IniFile &configDB,
|
||||
const string &configClassName,
|
||||
const string &objName,
|
||||
ConfigNode *configNode)
|
||||
SimObjectClass::createObject(IniFile &configDB, ConfigNode *configNode)
|
||||
{
|
||||
// find simulation object class name from configuration class
|
||||
// (specified by 'type=' parameter)
|
||||
string simObjClassName;
|
||||
|
||||
if (!configNode->find("type", simObjClassName)) {
|
||||
cerr << "Configuration class '" << configClassName << "' not found."
|
||||
<< endl;
|
||||
abort();
|
||||
}
|
||||
const string &type = configNode->getType();
|
||||
|
||||
// look up className to get appropriate createFunc
|
||||
if (classMap->find(simObjClassName) == classMap->end()) {
|
||||
cerr << "Simulator object class '" << simObjClassName << "' not found."
|
||||
<< endl;
|
||||
abort();
|
||||
}
|
||||
if (classMap->find(type) == classMap->end())
|
||||
panic("Simulator object type '%s' not found.\n", type);
|
||||
|
||||
CreateFunc createFunc = (*classMap)[simObjClassName];
|
||||
|
||||
CreateFunc createFunc = (*classMap)[type];
|
||||
|
||||
// call createFunc with config hierarchy node to get object
|
||||
// builder instance (context with parameters for object creation)
|
||||
SimObjectBuilder *objectBuilder = (*createFunc)(configClassName,
|
||||
objName, configNode,
|
||||
simObjClassName);
|
||||
SimObjectBuilder *objectBuilder = (*createFunc)(configNode);
|
||||
|
||||
assert(objectBuilder != NULL);
|
||||
|
||||
|
@ -167,10 +137,10 @@ SimObjectClass::createObject(IniFile &configDB,
|
|||
|
||||
// echo object parameters to stats file (for documenting the
|
||||
// config used to generate the associated stats)
|
||||
*configStream << "[" << object->name() << "]" << endl;
|
||||
*configStream << "type=" << simObjClassName << endl;
|
||||
ccprintf(*configStream, "[%s]\n", object->name());
|
||||
ccprintf(*configStream, "type=%s\n", type);
|
||||
objectBuilder->showParams(*configStream);
|
||||
*configStream << endl;
|
||||
ccprintf(*configStream, "\n");
|
||||
|
||||
// done with the SimObjectBuilder now
|
||||
delete objectBuilder;
|
||||
|
@ -194,7 +164,7 @@ SimObjectClass::describeAllClasses(ostream &os)
|
|||
os << "[" << className << "]\n";
|
||||
|
||||
// create dummy object builder just to instantiate parameters
|
||||
SimObjectBuilder *objectBuilder = (*createFunc)("", "", NULL, "");
|
||||
SimObjectBuilder *objectBuilder = (*createFunc)(NULL);
|
||||
|
||||
// now get the object builder to describe ite params
|
||||
objectBuilder->describeParams(os);
|
||||
|
|
|
@ -54,22 +54,13 @@ class SimObject;
|
|||
class SimObjectBuilder : public ParamContext
|
||||
{
|
||||
private:
|
||||
// name of the instance we are creating
|
||||
std::string instanceName;
|
||||
|
||||
// The corresponding node in the configuration hierarchy.
|
||||
// (optional: may be null if the created object is not in the
|
||||
// hierarchy)
|
||||
ConfigNode *configNode;
|
||||
|
||||
// The external SimObject class name (for error messages)
|
||||
std::string simObjClassName;
|
||||
|
||||
public:
|
||||
SimObjectBuilder(const std::string &_configClass,
|
||||
const std::string &_instanceName,
|
||||
ConfigNode *_configNode,
|
||||
const std::string &_simObjClassName);
|
||||
SimObjectBuilder(ConfigNode *_configNode);
|
||||
|
||||
virtual ~SimObjectBuilder();
|
||||
|
||||
|
@ -82,7 +73,7 @@ class SimObjectBuilder : public ParamContext
|
|||
|
||||
// generate the name for this SimObject instance (derived from the
|
||||
// configuration hierarchy node label and position)
|
||||
virtual const std::string &getInstanceName() { return instanceName; }
|
||||
virtual const std::string &getInstanceName() { return iniSection; }
|
||||
|
||||
// return the configuration hierarchy node for this context.
|
||||
virtual ConfigNode *getConfigNode() { return configNode; }
|
||||
|
@ -132,10 +123,7 @@ class SimObjectClass
|
|||
// for the object (specified by the second string argument), and
|
||||
// an optional config hierarchy node (specified by the third
|
||||
// argument). A pointer to the new SimObjectBuilder is returned.
|
||||
typedef SimObjectBuilder *(*CreateFunc)(const std::string &configClassName,
|
||||
const std::string &objName,
|
||||
ConfigNode *configNode,
|
||||
const std::string &simObjClassName);
|
||||
typedef SimObjectBuilder *(*CreateFunc)(ConfigNode *configNode);
|
||||
|
||||
static std::map<std::string,CreateFunc> *classMap;
|
||||
|
||||
|
@ -147,10 +135,7 @@ class SimObjectClass
|
|||
|
||||
// create SimObject given name of class and pointer to
|
||||
// configuration hierarchy node
|
||||
static SimObject *createObject(IniFile &configDB,
|
||||
const std::string &configClassName,
|
||||
const std::string &objName,
|
||||
ConfigNode *configNode);
|
||||
static SimObject *createObject(IniFile &configDB, ConfigNode *configNode);
|
||||
|
||||
// print descriptions of all parameters registered with all
|
||||
// SimObject classes
|
||||
|
@ -169,22 +154,15 @@ class OBJ_CLASS##Builder : public SimObjectBuilder \
|
|||
|
||||
#define END_DECLARE_SIM_OBJECT_PARAMS(OBJ_CLASS) \
|
||||
\
|
||||
OBJ_CLASS##Builder(const std::string &configClass, \
|
||||
const std::string &instanceName, \
|
||||
ConfigNode *configNode, \
|
||||
const std::string &simObjClassName); \
|
||||
OBJ_CLASS##Builder(ConfigNode *configNode); \
|
||||
virtual ~OBJ_CLASS##Builder() {} \
|
||||
\
|
||||
OBJ_CLASS *create(); \
|
||||
};
|
||||
|
||||
#define BEGIN_INIT_SIM_OBJECT_PARAMS(OBJ_CLASS) \
|
||||
OBJ_CLASS##Builder::OBJ_CLASS##Builder(const std::string &configClass, \
|
||||
const std::string &instanceName, \
|
||||
ConfigNode *configNode, \
|
||||
const std::string &simObjClassName) \
|
||||
: SimObjectBuilder(configClass, instanceName, \
|
||||
configNode, simObjClassName),
|
||||
#define BEGIN_INIT_SIM_OBJECT_PARAMS(OBJ_CLASS) \
|
||||
OBJ_CLASS##Builder::OBJ_CLASS##Builder(ConfigNode *configNode) \
|
||||
: SimObjectBuilder(configNode),
|
||||
|
||||
|
||||
#define END_INIT_SIM_OBJECT_PARAMS(OBJ_CLASS) \
|
||||
|
@ -196,13 +174,9 @@ OBJ_CLASS *OBJ_CLASS##Builder::create()
|
|||
|
||||
#define REGISTER_SIM_OBJECT(CLASS_NAME, OBJ_CLASS) \
|
||||
SimObjectBuilder * \
|
||||
new##OBJ_CLASS##Builder(const std::string &configClass, \
|
||||
const std::string &instanceName, \
|
||||
ConfigNode *configNode, \
|
||||
const std::string &simObjClassName) \
|
||||
new##OBJ_CLASS##Builder(ConfigNode *configNode) \
|
||||
{ \
|
||||
return new OBJ_CLASS##Builder(configClass, instanceName, \
|
||||
configNode, simObjClassName); \
|
||||
return new OBJ_CLASS##Builder(configNode); \
|
||||
} \
|
||||
\
|
||||
SimObjectClass the##OBJ_CLASS##Class(CLASS_NAME, \
|
||||
|
|
29
sim/main.cc
29
sim/main.cc
|
@ -34,10 +34,12 @@
|
|||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/copyright.hh"
|
||||
#include "base/embedfile.hh"
|
||||
#include "base/inifile.hh"
|
||||
#include "base/misc.hh"
|
||||
#include "base/pollevent.hh"
|
||||
|
@ -254,6 +256,21 @@ main(int argc, char **argv)
|
|||
|
||||
// switch on second char
|
||||
switch (arg_str[1]) {
|
||||
case 'X': {
|
||||
list<EmbedFile> lst;
|
||||
EmbedMap::all(lst);
|
||||
list<EmbedFile>::iterator i = lst.begin();
|
||||
list<EmbedFile>::iterator end = lst.end();
|
||||
|
||||
while (i != end) {
|
||||
cprintf("Embedded File: %s\n", i->name);
|
||||
cout.write(i->data, i->length);
|
||||
++i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case 'h':
|
||||
// -h: show help
|
||||
showLongHelp(cerr);
|
||||
|
@ -311,7 +328,7 @@ main(int argc, char **argv)
|
|||
cprintf("Error processing file %s\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
} else if (ext == ".py") {
|
||||
} else if (ext == ".py" || ext == ".mpy") {
|
||||
if (!loadPythonConfig(filename, &simConfigDB)) {
|
||||
cprintf("Error processing file %s\n", filename);
|
||||
exit(1);
|
||||
|
@ -335,6 +352,11 @@ main(int argc, char **argv)
|
|||
// the stat file name is set via a .ini param... thus it just got
|
||||
// opened above during ParamContext::checkAllContexts().
|
||||
|
||||
// Now process the configuration hierarchy and create the SimObjects.
|
||||
ConfigHierarchy configHierarchy(simConfigDB);
|
||||
configHierarchy.build();
|
||||
configHierarchy.createSimObjects();
|
||||
|
||||
// Print hello message to stats file if it's actually a file. If
|
||||
// it's not (i.e. it's cout or cerr) then we already did it above.
|
||||
if (outputStream != &cout && outputStream != &cerr)
|
||||
|
@ -344,11 +366,6 @@ main(int argc, char **argv)
|
|||
echoCommandLine(argc, argv, *outputStream);
|
||||
ParamContext::showAllContexts(*configStream);
|
||||
|
||||
// Now process the configuration hierarchy and create the SimObjects.
|
||||
ConfigHierarchy configHierarchy(simConfigDB);
|
||||
configHierarchy.build();
|
||||
configHierarchy.createSimObjects();
|
||||
|
||||
// Do a second pass to finish initializing the sim objects
|
||||
SimObject::initAll();
|
||||
|
||||
|
|
48
sim/param.cc
48
sim/param.cc
|
@ -27,21 +27,21 @@
|
|||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdio.h> // for sscanf()
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "sim/param.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
#include "base/inifile.hh"
|
||||
#include "sim/configfile.hh"
|
||||
#include "sim/config_node.hh"
|
||||
#include "base/misc.hh"
|
||||
#include "base/range.hh"
|
||||
#include "base/str.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "sim/config_node.hh"
|
||||
#include "sim/configfile.hh"
|
||||
#include "sim/param.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -180,6 +180,22 @@ parseParam(const string &s, string &value)
|
|||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool
|
||||
parseParam(const string &s, Range<uint32_t> &value)
|
||||
{
|
||||
value = s;
|
||||
return value.valid();
|
||||
}
|
||||
|
||||
template <>
|
||||
bool
|
||||
parseParam(const string &s, Range<uint64_t> &value)
|
||||
{
|
||||
value = s;
|
||||
return value.valid();
|
||||
}
|
||||
|
||||
//
|
||||
// End of parseParam/showParam definitions. Now we move on to
|
||||
// incorporate them into the Param/VectorParam parse() and showValue()
|
||||
|
@ -310,6 +326,9 @@ INSTANTIATE_PARAM_TEMPLATES(double, "double")
|
|||
INSTANTIATE_PARAM_TEMPLATES(bool, "bool")
|
||||
INSTANTIATE_PARAM_TEMPLATES(string, "string")
|
||||
|
||||
INSTANTIATE_PARAM_TEMPLATES(Range<uint64_t>, "uint64 range")
|
||||
INSTANTIATE_PARAM_TEMPLATES(Range<uint32_t>, "uint32 range")
|
||||
|
||||
#undef INSTANTIATE_PARAM_TEMPLATES
|
||||
|
||||
//
|
||||
|
@ -602,9 +621,8 @@ ParamContext::parseParams(IniFile &iniFile)
|
|||
for (i = getParamList()->begin(); i != getParamList()->end(); ++i) {
|
||||
string string_value;
|
||||
|
||||
if (iniFile.findDefault(iniSection, (*i)->name, string_value)) {
|
||||
if (iniFile.find(iniSection, (*i)->name, string_value))
|
||||
(*i)->parse(string_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -680,18 +698,8 @@ ParamContext::printErrorProlog(ostream &os)
|
|||
// SimObjectBuilder objects, which return non-NULL for configNode()).
|
||||
//
|
||||
SimObject *
|
||||
ParamContext::resolveSimObject(const string &_name)
|
||||
ParamContext::resolveSimObject(const string &name)
|
||||
{
|
||||
// look for a colon
|
||||
string::size_type i = _name.find(':');
|
||||
string name = _name;
|
||||
if (i != string::npos) {
|
||||
// colon found: local object
|
||||
// add as child to current node and create it
|
||||
name = _name.substr(0, i);
|
||||
string objConfigClassName = _name.substr(i + 1);
|
||||
getConfigNode()->addChild(name, objConfigClassName);
|
||||
}
|
||||
ConfigNode *n = getConfigNode();
|
||||
return n ? n->resolveSimObject(name) : NULL;
|
||||
}
|
||||
|
|
|
@ -397,19 +397,29 @@ END_INIT_SIM_OBJECT_PARAMS(LiveProcess)
|
|||
|
||||
CREATE_SIM_OBJECT(LiveProcess)
|
||||
{
|
||||
// initialize file descriptors to default: same as simulator
|
||||
int stdin_fd = input.isValid() ? Process::openInputFile(input) : 0;
|
||||
int stdout_fd = output.isValid() ? Process::openOutputFile(output) : 1;
|
||||
int stderr_fd = output.isValid() ? stdout_fd : 2;
|
||||
string in = input;
|
||||
string out = output;
|
||||
|
||||
// dummy for default env
|
||||
vector<string> null_vec;
|
||||
// initialize file descriptors to default: same as simulator
|
||||
int stdin_fd, stdout_fd, stderr_fd;
|
||||
|
||||
if (in == "stdin" || in == "cin")
|
||||
stdin_fd = STDIN_FILENO;
|
||||
else
|
||||
stdin_fd = Process::openInputFile(input);
|
||||
|
||||
if (out == "stdout" || out == "cout")
|
||||
stdout_fd = STDOUT_FILENO;
|
||||
else if (out == "stderr" || out == "cerr")
|
||||
stdout_fd = STDERR_FILENO;
|
||||
else
|
||||
stdout_fd = Process::openOutputFile(out);
|
||||
|
||||
stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO;
|
||||
|
||||
return LiveProcess::create(getInstanceName(),
|
||||
stdin_fd, stdout_fd, stderr_fd,
|
||||
cmd,
|
||||
env.isValid() ? env : null_vec);
|
||||
cmd, env);
|
||||
}
|
||||
|
||||
|
||||
REGISTER_SIM_OBJECT("LiveProcess", LiveProcess)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# -*- mode:python -*-
|
||||
|
||||
# Copyright (c) 2004 The Regents of The University of Michigan
|
||||
# Copyright (c) 2005 The Regents of The University of Michigan
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
|
@ -26,25 +26,164 @@
|
|||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import os
|
||||
import os, os.path, re
|
||||
|
||||
Import('env', 'obj_desc_files')
|
||||
def WriteEmbeddedPyFile(target, source, path, name, ext):
|
||||
if isinstance(source, str):
|
||||
source = file(source, 'r')
|
||||
|
||||
my_obj_desc_files = map(lambda x: '../../' + x, obj_desc_files)
|
||||
if isinstance(target, str):
|
||||
target = file(target, 'w')
|
||||
|
||||
env.Command('m5odescs.py', my_obj_desc_files,
|
||||
'$TARGET.srcdir/load_odescs.py $_CPPDEFFLAGS $SOURCES $TARGET')
|
||||
print >>target, "AddModule(%s, %s, %s, '''\\" % (`path`, `name`, `ext`)
|
||||
|
||||
# Python modules to encapsulate
|
||||
string_module_bases = Split('m5config m5configbase m5odescs')
|
||||
string_modules = map(lambda x: x + '_as_string.py', string_module_bases)
|
||||
for line in source:
|
||||
line = line
|
||||
# escape existing backslashes
|
||||
line = line.replace('\\', '\\\\')
|
||||
# escape existing triple quotes
|
||||
line = line.replace("'''", r"\'\'\'")
|
||||
|
||||
for m in string_module_bases:
|
||||
env.Command(m + '_as_string.py', m + '.py',
|
||||
'$TARGET.srcdir/make_string_module.py $SOURCE $TARGET')
|
||||
print >>target, line,
|
||||
|
||||
embedded_py_files = Split('string_importer.py') + string_modules
|
||||
print >>target, "''')"
|
||||
print >>target
|
||||
|
||||
env.Command('code.cc', embedded_py_files,
|
||||
'$TARGET.srcdir/make_c_file.py pyconfig_code $SOURCES $TARGET')
|
||||
def WriteCFile(target, source, name):
|
||||
if isinstance(source, str):
|
||||
source = file(source, 'r')
|
||||
|
||||
if isinstance(target, str):
|
||||
target = file(target, 'w')
|
||||
|
||||
print >>target, 'const char %s_string[] = {' % name
|
||||
|
||||
count = 0
|
||||
from array import array
|
||||
try:
|
||||
while True:
|
||||
foo = array('B')
|
||||
foo.fromfile(source, 10000)
|
||||
l = [ str(i) for i in foo.tolist() ]
|
||||
count += len(l)
|
||||
for i in xrange(0,9999,20):
|
||||
print >>target, ','.join(l[i:i+20]) + ','
|
||||
except EOFError:
|
||||
l = [ str(i) for i in foo.tolist() ]
|
||||
count += len(l)
|
||||
for i in xrange(0,len(l),20):
|
||||
print >>target, ','.join(l[i:i+20]) + ','
|
||||
print >>target, ','.join(l[i:]) + ','
|
||||
|
||||
print >>target, '};'
|
||||
print >>target, 'const int %s_length = %d;' % (name, count)
|
||||
print >>target
|
||||
|
||||
def splitpath(path):
|
||||
dir,file = os.path.split(path)
|
||||
path = []
|
||||
assert(file)
|
||||
while dir:
|
||||
dir,base = os.path.split(dir)
|
||||
path.insert(0, base)
|
||||
return path, file
|
||||
|
||||
Import('env')
|
||||
def MakeEmbeddedPyFile(target, source, env):
|
||||
target = file(str(target[0]), 'w')
|
||||
|
||||
tree = {}
|
||||
for src in source:
|
||||
src = str(src)
|
||||
path,pyfile = splitpath(src)
|
||||
node = tree
|
||||
for dir in path:
|
||||
if not node.has_key(dir):
|
||||
node[dir] = { }
|
||||
node = node[dir]
|
||||
|
||||
name,ext = pyfile.split('.')
|
||||
if name == '__init__':
|
||||
node['.hasinit'] = True
|
||||
node[pyfile] = (src,name,ext)
|
||||
|
||||
done = False
|
||||
while not done:
|
||||
done = True
|
||||
for name,entry in tree.items():
|
||||
if not isinstance(entry, dict): continue
|
||||
if entry.has_key('.hasinit'): continue
|
||||
|
||||
done = False
|
||||
del tree[name]
|
||||
for key,val in entry.iteritems():
|
||||
if tree.has_key(key):
|
||||
raise NameError, \
|
||||
"dir already has %s can't add it again" % key
|
||||
tree[key] = val
|
||||
|
||||
files = []
|
||||
def populate(node, path = []):
|
||||
names = node.keys()
|
||||
names.sort()
|
||||
for name in names:
|
||||
if name == '.hasinit':
|
||||
continue
|
||||
|
||||
entry = node[name]
|
||||
if isinstance(entry, dict):
|
||||
if not entry.has_key('.hasinit'):
|
||||
raise NameError, 'package directory missing __init__.py'
|
||||
populate(entry, path + [ name ])
|
||||
else:
|
||||
pyfile,name,ext = entry
|
||||
files.append((pyfile, path, name, ext))
|
||||
populate(tree)
|
||||
|
||||
for pyfile, path, name, ext in files:
|
||||
WriteEmbeddedPyFile(target, pyfile, path, name, ext)
|
||||
|
||||
CFileCounter = 0
|
||||
def MakePythonCFile(target, source, env):
|
||||
global CFileCounter
|
||||
target = file(str(target[0]), 'w')
|
||||
|
||||
print >>target, '''\
|
||||
#include "base/embedfile.hh"
|
||||
|
||||
namespace {
|
||||
'''
|
||||
for src in source:
|
||||
src = str(src)
|
||||
fname = os.path.basename(src)
|
||||
name = 'embedded_file%d' % CFileCounter
|
||||
CFileCounter += 1
|
||||
WriteCFile(target, src, name)
|
||||
print >>target, '''\
|
||||
EmbedMap %(name)s("%(fname)s",
|
||||
%(name)s_string, %(name)s_length);
|
||||
|
||||
''' % locals()
|
||||
print >>target, '''\
|
||||
|
||||
/* namespace */ }
|
||||
'''
|
||||
|
||||
embedded_py_files = ['m5config.py']
|
||||
objpath = os.path.join(env['SRCDIR'], 'objects')
|
||||
for root, dirs, files in os.walk(objpath, topdown=True):
|
||||
for i,dir in enumerate(dirs):
|
||||
if dir == 'SCCS':
|
||||
del dirs[i]
|
||||
break
|
||||
|
||||
assert(root.startswith(objpath))
|
||||
for f in files:
|
||||
if f.endswith('.mpy') or f.endswith('.py'):
|
||||
embedded_py_files.append(os.path.join(root, f))
|
||||
|
||||
embedfile_hh = os.path.join(env['SRCDIR'], 'base/embedfile.hh')
|
||||
env.Depends('embedded_py.cc', embedfile_hh)
|
||||
env.Command('embedded_py.py', embedded_py_files, MakeEmbeddedPyFile)
|
||||
env.Command('embedded_py.cc', ['importer.py', 'embedded_py.py'],
|
||||
MakePythonCFile)
|
||||
|
|
1250
sim/pyconfig/m5config.py
Normal file
1250
sim/pyconfig/m5config.py
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,723 +0,0 @@
|
|||
# Copyright (c) 2004 The Regents of The University of Michigan
|
||||
# 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.
|
||||
|
||||
from __future__ import generators
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
#####################################################################
|
||||
#
|
||||
# M5 Python Configuration Utility
|
||||
#
|
||||
# The basic idea is to write simple Python programs that build Python
|
||||
# objects corresponding to M5 SimObjects for the deisred simulation
|
||||
# configuration. For now, the Python emits a .ini file that can be
|
||||
# parsed by M5. In the future, some tighter integration between M5
|
||||
# and the Python interpreter may allow bypassing the .ini file.
|
||||
#
|
||||
# Each SimObject class in M5 is represented by a Python class with the
|
||||
# same name. The Python inheritance tree mirrors the M5 C++ tree
|
||||
# (e.g., SimpleCPU derives from BaseCPU in both cases, and all
|
||||
# SimObjects inherit from a single SimObject base class). To specify
|
||||
# an instance of an M5 SimObject in a configuration, the user simply
|
||||
# instantiates the corresponding Python object. The parameters for
|
||||
# that SimObject are given by assigning to attributes of the Python
|
||||
# object, either using keyword assignment in the constructor or in
|
||||
# separate assignment statements. For example:
|
||||
#
|
||||
# cache = BaseCache('my_cache', root, size=64*K)
|
||||
# cache.hit_latency = 3
|
||||
# cache.assoc = 8
|
||||
#
|
||||
# (The first two constructor arguments specify the name of the created
|
||||
# cache and its parent node in the hierarchy.)
|
||||
#
|
||||
# The magic lies in the mapping of the Python attributes for SimObject
|
||||
# classes to the actual SimObject parameter specifications. This
|
||||
# allows parameter validity checking in the Python code. Continuing
|
||||
# the example above, the statements "cache.blurfl=3" or
|
||||
# "cache.assoc='hello'" would both result in runtime errors in Python,
|
||||
# since the BaseCache object has no 'blurfl' parameter and the 'assoc'
|
||||
# parameter requires an integer, respectively. This magic is done
|
||||
# primarily by overriding the special __setattr__ method that controls
|
||||
# assignment to object attributes.
|
||||
#
|
||||
# The Python module provides another class, ConfigNode, which is a
|
||||
# superclass of SimObject. ConfigNode implements the parent/child
|
||||
# relationship for building the configuration hierarchy tree.
|
||||
# Concrete instances of ConfigNode can be used to group objects in the
|
||||
# hierarchy, but do not correspond to SimObjects themselves (like a
|
||||
# .ini section with "children=" but no "type=".
|
||||
#
|
||||
# Once a set of Python objects have been instantiated in a hierarchy,
|
||||
# calling 'instantiate(obj)' (where obj is the root of the hierarchy)
|
||||
# will generate a .ini file. See simple-4cpu.py for an example
|
||||
# (corresponding to m5-test/simple-4cpu.ini).
|
||||
#
|
||||
#####################################################################
|
||||
|
||||
#####################################################################
|
||||
#
|
||||
# ConfigNode/SimObject classes
|
||||
#
|
||||
# The Python class hierarchy rooted by ConfigNode (which is the base
|
||||
# class of SimObject, which in turn is the base class of all other M5
|
||||
# SimObject classes) has special attribute behavior. In general, an
|
||||
# object in this hierarchy has three categories of attribute-like
|
||||
# things:
|
||||
#
|
||||
# 1. Regular Python methods and variables. These must start with an
|
||||
# underscore to be treated normally.
|
||||
#
|
||||
# 2. SimObject parameters. These values are stored as normal Python
|
||||
# attributes, but all assignments to these attributes are checked
|
||||
# against the pre-defined set of parameters stored in the class's
|
||||
# _param_dict dictionary. Assignments to attributes that do not
|
||||
# correspond to predefined parameters, or that are not of the correct
|
||||
# type, incur runtime errors.
|
||||
#
|
||||
# 3. Hierarchy children. The child nodes of a ConfigNode are stored
|
||||
# in the node's _children dictionary, but can be accessed using the
|
||||
# Python attribute dot-notation (just as they are printed out by the
|
||||
# simulator). Children cannot be created using attribute assigment;
|
||||
# they must be added by specifying the parent node in the child's
|
||||
# constructor or using the '+=' operator.
|
||||
|
||||
# The SimObject parameters are the most complex, for a few reasons.
|
||||
# First, both parameter descriptions and parameter values are
|
||||
# inherited. Thus parameter description lookup must go up the
|
||||
# inheritance chain like normal attribute lookup, but this behavior
|
||||
# must be explicitly coded since the lookup occurs in each class's
|
||||
# _param_dict attribute. Second, because parameter values can be set
|
||||
# on SimObject classes (to implement default values), the parameter
|
||||
# checking behavior must be enforced on class attribute assignments as
|
||||
# well as instance attribute assignments. Finally, because we allow
|
||||
# class specialization via inheritance (e.g., see the L1Cache class in
|
||||
# the simple-4cpu.py example), we must do parameter checking even on
|
||||
# class instantiation. To provide all these features, we use a
|
||||
# metaclass to define most of the SimObject parameter behavior for
|
||||
# this class hierarchy.
|
||||
#
|
||||
#####################################################################
|
||||
|
||||
# The metaclass for ConfigNode (and thus for everything that derives
|
||||
# from ConfigNode, including SimObject). This class controls how new
|
||||
# classes that derive from ConfigNode are instantiated, and provides
|
||||
# inherited class behavior (just like a class controls how instances
|
||||
# of that class are instantiated, and provides inherited instance
|
||||
# behavior).
|
||||
class MetaConfigNode(type):
|
||||
|
||||
# __new__ is called before __init__, and is where the statements
|
||||
# in the body of the class definition get loaded into the class's
|
||||
# __dict__. We intercept this to filter out parameter assignments
|
||||
# and only allow "private" attributes to be passed to the base
|
||||
# __new__ (starting with underscore).
|
||||
def __new__(cls, name, bases, dict):
|
||||
priv_keys = [k for k in dict.iterkeys() if k.startswith('_')]
|
||||
priv_dict = {}
|
||||
for k in priv_keys: priv_dict[k] = dict[k]; del dict[k]
|
||||
# entries left in dict will get passed to __init__, where we'll
|
||||
# deal with them as params.
|
||||
return super(MetaConfigNode, cls).__new__(cls, name, bases, priv_dict)
|
||||
|
||||
# initialization: start out with an empty param dict (makes life
|
||||
# simpler if we can assume _param_dict is always valid). Also
|
||||
# build inheritance list to simplify searching for inherited
|
||||
# params. Finally set parameters specified in class definition
|
||||
# (if any).
|
||||
def __init__(cls, name, bases, dict):
|
||||
super(MetaConfigNode, cls).__init__(cls, name, bases, {})
|
||||
# initialize _param_dict to empty
|
||||
cls._param_dict = {}
|
||||
# __mro__ is the ordered list of classes Python uses for
|
||||
# method resolution. We want to pick out the ones that have a
|
||||
# _param_dict attribute for doing parameter lookups.
|
||||
cls._param_bases = \
|
||||
[c for c in cls.__mro__ if hasattr(c, '_param_dict')]
|
||||
# initialize attributes with values from class definition
|
||||
for (pname, value) in dict.items():
|
||||
try:
|
||||
setattr(cls, pname, value)
|
||||
except Exception, exc:
|
||||
print "Error setting '%s' to '%s' on class '%s'\n" \
|
||||
% (pname, value, cls.__name__), exc
|
||||
|
||||
# set the class's parameter dictionary (called when loading
|
||||
# class descriptions)
|
||||
def set_param_dict(cls, param_dict):
|
||||
# should only be called once (current one should be empty one
|
||||
# from __init__)
|
||||
assert not cls._param_dict
|
||||
cls._param_dict = param_dict
|
||||
# initialize attributes with default values
|
||||
for (pname, param) in param_dict.items():
|
||||
try:
|
||||
setattr(cls, pname, param.default)
|
||||
except Exception, exc:
|
||||
print "Error setting '%s' default on class '%s'\n" \
|
||||
% (pname, cls.__name__), exc
|
||||
|
||||
# Set the class's parameter dictionary given a code string of
|
||||
# parameter initializers (as from an object description file).
|
||||
# Note that the caller must pass in the namespace in which to
|
||||
# execute the code (usually the caller's globals()), since if we
|
||||
# call globals() from inside this function all we get is this
|
||||
# module's internal scope.
|
||||
def init_params(cls, init_code, ctx):
|
||||
dict = {}
|
||||
try:
|
||||
exec fixPythonIndentation(init_code) in ctx, dict
|
||||
except Exception, exc:
|
||||
print "Error in %s.init_params:" % cls.__name__, exc
|
||||
raise
|
||||
cls.set_param_dict(dict)
|
||||
|
||||
# Lookup a parameter description by name in the given class. Use
|
||||
# the _param_bases list defined in __init__ to go up the
|
||||
# inheritance hierarchy if necessary.
|
||||
def lookup_param(cls, param_name):
|
||||
for c in cls._param_bases:
|
||||
param = c._param_dict.get(param_name)
|
||||
if param: return param
|
||||
return None
|
||||
|
||||
# Set attribute (called on foo.attr_name = value when foo is an
|
||||
# instance of class cls).
|
||||
def __setattr__(cls, attr_name, value):
|
||||
# normal processing for private attributes
|
||||
if attr_name.startswith('_'):
|
||||
type.__setattr__(cls, attr_name, value)
|
||||
return
|
||||
# no '_': must be SimObject param
|
||||
param = cls.lookup_param(attr_name)
|
||||
if not param:
|
||||
raise AttributeError, \
|
||||
"Class %s has no parameter %s" % (cls.__name__, attr_name)
|
||||
# It's ok: set attribute by delegating to 'object' class.
|
||||
# Note the use of param.make_value() to verify/canonicalize
|
||||
# the assigned value
|
||||
type.__setattr__(cls, attr_name, param.make_value(value))
|
||||
|
||||
# generator that iterates across all parameters for this class and
|
||||
# all classes it inherits from
|
||||
def all_param_names(cls):
|
||||
for c in cls._param_bases:
|
||||
for p in c._param_dict.iterkeys():
|
||||
yield p
|
||||
|
||||
# The ConfigNode class is the root of the special hierarchy. Most of
|
||||
# the code in this class deals with the configuration hierarchy itself
|
||||
# (parent/child node relationships).
|
||||
class ConfigNode(object):
|
||||
# Specify metaclass. Any class inheriting from ConfigNode will
|
||||
# get this metaclass.
|
||||
__metaclass__ = MetaConfigNode
|
||||
|
||||
# Constructor. Since bare ConfigNodes don't have parameters, just
|
||||
# worry about the name and the parent/child stuff.
|
||||
def __init__(self, _name, _parent=None):
|
||||
# Type-check _name
|
||||
if type(_name) != str:
|
||||
if isinstance(_name, ConfigNode):
|
||||
# special case message for common error of trying to
|
||||
# coerce a SimObject to the wrong type
|
||||
raise TypeError, \
|
||||
"Attempt to coerce %s to %s" \
|
||||
% (_name.__class__.__name__, self.__class__.__name__)
|
||||
else:
|
||||
raise TypeError, \
|
||||
"%s name must be string (was %s, %s)" \
|
||||
% (self.__class__.__name__, _name, type(_name))
|
||||
# if specified, parent must be a subclass of ConfigNode
|
||||
if _parent != None and not isinstance(_parent, ConfigNode):
|
||||
raise TypeError, \
|
||||
"%s parent must be ConfigNode subclass (was %s, %s)" \
|
||||
% (self.__class__.__name__, _name, type(_name))
|
||||
self._name = _name
|
||||
self._parent = _parent
|
||||
if (_parent):
|
||||
_parent._add_child(self)
|
||||
self._children = {}
|
||||
# keep a list of children in addition to the dictionary keys
|
||||
# so we can remember the order they were added and print them
|
||||
# out in that order.
|
||||
self._child_list = []
|
||||
|
||||
# When printing (e.g. to .ini file), just give the name.
|
||||
def __str__(self):
|
||||
return self._name
|
||||
|
||||
# Catch attribute accesses that could be requesting children, and
|
||||
# satisfy them. Note that __getattr__ is called only if the
|
||||
# regular attribute lookup fails, so private and parameter lookups
|
||||
# will already be satisfied before we ever get here.
|
||||
def __getattr__(self, name):
|
||||
try:
|
||||
return self._children[name]
|
||||
except KeyError:
|
||||
raise AttributeError, \
|
||||
"Node '%s' has no attribute or child '%s'" \
|
||||
% (self._name, name)
|
||||
|
||||
# Set attribute. All attribute assignments go through here. Must
|
||||
# be private attribute (starts with '_') or valid parameter entry.
|
||||
# Basically identical to MetaConfigClass.__setattr__(), except
|
||||
# this sets attributes on specific instances rather than on classes.
|
||||
def __setattr__(self, attr_name, value):
|
||||
if attr_name.startswith('_'):
|
||||
object.__setattr__(self, attr_name, value)
|
||||
return
|
||||
# not private; look up as param
|
||||
param = self.__class__.lookup_param(attr_name)
|
||||
if not param:
|
||||
raise AttributeError, \
|
||||
"Class %s has no parameter %s" \
|
||||
% (self.__class__.__name__, attr_name)
|
||||
# It's ok: set attribute by delegating to 'object' class.
|
||||
# Note the use of param.make_value() to verify/canonicalize
|
||||
# the assigned value.
|
||||
v = param.make_value(value)
|
||||
object.__setattr__(self, attr_name, v)
|
||||
|
||||
# A little convenient magic: if the parameter is a ConfigNode
|
||||
# (or vector of ConfigNodes, or anything else with a
|
||||
# '_set_parent_if_none' function attribute) that does not have
|
||||
# a parent (and so is not part of the configuration
|
||||
# hierarchy), then make this node its parent.
|
||||
if hasattr(v, '_set_parent_if_none'):
|
||||
v._set_parent_if_none(self)
|
||||
|
||||
def _path(self):
|
||||
# Return absolute path from root.
|
||||
if not self._parent and self._name != 'Universe':
|
||||
print >> sys.stderr, "Warning:", self._name, "has no parent"
|
||||
parent_path = self._parent and self._parent._path()
|
||||
if parent_path and parent_path != 'Universe':
|
||||
return parent_path + '.' + self._name
|
||||
else:
|
||||
return self._name
|
||||
|
||||
# Add a child to this node.
|
||||
def _add_child(self, new_child):
|
||||
# set child's parent before calling this function
|
||||
assert new_child._parent == self
|
||||
if not isinstance(new_child, ConfigNode):
|
||||
raise TypeError, \
|
||||
"ConfigNode child must also be of class ConfigNode"
|
||||
if new_child._name in self._children:
|
||||
raise AttributeError, \
|
||||
"Node '%s' already has a child '%s'" \
|
||||
% (self._name, new_child._name)
|
||||
self._children[new_child._name] = new_child
|
||||
self._child_list += [new_child]
|
||||
|
||||
# operator overload for '+='. You can say "node += child" to add
|
||||
# a child that was created with parent=None. An early attempt
|
||||
# at playing with syntax; turns out not to be that useful.
|
||||
def __iadd__(self, new_child):
|
||||
if new_child._parent != None:
|
||||
raise AttributeError, \
|
||||
"Node '%s' already has a parent" % new_child._name
|
||||
new_child._parent = self
|
||||
self._add_child(new_child)
|
||||
return self
|
||||
|
||||
# Set this instance's parent to 'parent' if it doesn't already
|
||||
# have one. See ConfigNode.__setattr__().
|
||||
def _set_parent_if_none(self, parent):
|
||||
if self._parent == None:
|
||||
parent += self
|
||||
|
||||
# Print instance info to .ini file.
|
||||
def _instantiate(self):
|
||||
print '[' + self._path() + ']' # .ini section header
|
||||
if self._child_list:
|
||||
# instantiate children in same order they were added for
|
||||
# backward compatibility (else we can end up with cpu1
|
||||
# before cpu0).
|
||||
print 'children =', ' '.join([c._name for c in self._child_list])
|
||||
self._instantiateParams()
|
||||
print
|
||||
# recursively dump out children
|
||||
for c in self._child_list:
|
||||
c._instantiate()
|
||||
|
||||
# ConfigNodes have no parameters. Overridden by SimObject.
|
||||
def _instantiateParams(self):
|
||||
pass
|
||||
|
||||
# SimObject is a minimal extension of ConfigNode, implementing a
|
||||
# hierarchy node that corresponds to an M5 SimObject. It prints out a
|
||||
# "type=" line to indicate its SimObject class, prints out the
|
||||
# assigned parameters corresponding to its class, and allows
|
||||
# parameters to be set by keyword in the constructor. Note that most
|
||||
# of the heavy lifting for the SimObject param handling is done in the
|
||||
# MetaConfigNode metaclass.
|
||||
|
||||
class SimObject(ConfigNode):
|
||||
# initialization: like ConfigNode, but handle keyword-based
|
||||
# parameter initializers.
|
||||
def __init__(self, _name, _parent=None, **params):
|
||||
ConfigNode.__init__(self, _name, _parent)
|
||||
for param, value in params.items():
|
||||
setattr(self, param, value)
|
||||
|
||||
# print type and parameter values to .ini file
|
||||
def _instantiateParams(self):
|
||||
print "type =", self.__class__._name
|
||||
for pname in self.__class__.all_param_names():
|
||||
value = getattr(self, pname)
|
||||
if value != None:
|
||||
print pname, '=', value
|
||||
|
||||
def _sim_code(cls):
|
||||
name = cls.__name__
|
||||
param_names = cls._param_dict.keys()
|
||||
param_names.sort()
|
||||
code = "BEGIN_DECLARE_SIM_OBJECT_PARAMS(%s)\n" % name
|
||||
decls = [" " + cls._param_dict[pname].sim_decl(pname) \
|
||||
for pname in param_names]
|
||||
code += "\n".join(decls) + "\n"
|
||||
code += "END_DECLARE_SIM_OBJECT_PARAMS(%s)\n\n" % name
|
||||
code += "BEGIN_INIT_SIM_OBJECT_PARAMS(%s)\n" % name
|
||||
inits = [" " + cls._param_dict[pname].sim_init(pname) \
|
||||
for pname in param_names]
|
||||
code += ",\n".join(inits) + "\n"
|
||||
code += "END_INIT_SIM_OBJECT_PARAMS(%s)\n\n" % name
|
||||
return code
|
||||
_sim_code = classmethod(_sim_code)
|
||||
|
||||
#####################################################################
|
||||
#
|
||||
# Parameter description classes
|
||||
#
|
||||
# The _param_dict dictionary in each class maps parameter names to
|
||||
# either a Param or a VectorParam object. These objects contain the
|
||||
# parameter description string, the parameter type, and the default
|
||||
# value (loaded from the PARAM section of the .odesc files). The
|
||||
# make_value() method on these objects is used to force whatever value
|
||||
# is assigned to the parameter to the appropriate type.
|
||||
#
|
||||
# Note that the default values are loaded into the class's attribute
|
||||
# space when the parameter dictionary is initialized (in
|
||||
# MetaConfigNode.set_param_dict()); after that point they aren't
|
||||
# used.
|
||||
#
|
||||
#####################################################################
|
||||
|
||||
def isNullPointer(value):
|
||||
return isinstance(value, NullSimObject)
|
||||
|
||||
# Regular parameter.
|
||||
class Param(object):
|
||||
# Constructor. E.g., Param(Int, "number of widgets", 5)
|
||||
def __init__(self, ptype, desc, default=None):
|
||||
self.ptype = ptype
|
||||
self.ptype_name = self.ptype.__name__
|
||||
self.desc = desc
|
||||
self.default = default
|
||||
|
||||
# Convert assigned value to appropriate type. Force parameter
|
||||
# value (rhs of '=') to ptype (or None, which means not set).
|
||||
def make_value(self, value):
|
||||
# nothing to do if None or already correct type. Also allow NULL
|
||||
# pointer to be assigned where a SimObject is expected.
|
||||
if value == None or isinstance(value, self.ptype) or \
|
||||
isNullPointer(value) and issubclass(self.ptype, ConfigNode):
|
||||
return value
|
||||
# this type conversion will raise an exception if it's illegal
|
||||
return self.ptype(value)
|
||||
|
||||
def sim_decl(self, name):
|
||||
return 'Param<%s> %s;' % (self.ptype_name, name)
|
||||
|
||||
def sim_init(self, name):
|
||||
if self.default == None:
|
||||
return 'INIT_PARAM(%s, "%s")' % (name, self.desc)
|
||||
else:
|
||||
return 'INIT_PARAM_DFLT(%s, "%s", %s)' % \
|
||||
(name, self.desc, str(self.default))
|
||||
|
||||
# The _VectorParamValue class is a wrapper for vector-valued
|
||||
# parameters. The leading underscore indicates that users shouldn't
|
||||
# see this class; it's magically generated by VectorParam. The
|
||||
# parameter values are stored in the 'value' field as a Python list of
|
||||
# whatever type the parameter is supposed to be. The only purpose of
|
||||
# storing these instead of a raw Python list is that we can override
|
||||
# the __str__() method to not print out '[' and ']' in the .ini file.
|
||||
class _VectorParamValue(object):
|
||||
def __init__(self, value):
|
||||
assert isinstance(value, list) or value == None
|
||||
self.value = value
|
||||
|
||||
def __str__(self):
|
||||
return ' '.join(map(str, self.value))
|
||||
|
||||
# Set member instance's parents to 'parent' if they don't already
|
||||
# have one. Extends "magic" parenting of ConfigNodes to vectors
|
||||
# of ConfigNodes as well. See ConfigNode.__setattr__().
|
||||
def _set_parent_if_none(self, parent):
|
||||
if self.value and hasattr(self.value[0], '_set_parent_if_none'):
|
||||
for v in self.value:
|
||||
v._set_parent_if_none(parent)
|
||||
|
||||
# Vector-valued parameter description. Just like Param, except that
|
||||
# the value is a vector (list) of the specified type instead of a
|
||||
# single value.
|
||||
class VectorParam(Param):
|
||||
|
||||
# Inherit Param constructor. However, the resulting parameter
|
||||
# will be a list of ptype rather than a single element of ptype.
|
||||
def __init__(self, ptype, desc, default=None):
|
||||
Param.__init__(self, ptype, desc, default)
|
||||
|
||||
# Convert assigned value to appropriate type. If the RHS is not a
|
||||
# list or tuple, it generates a single-element list.
|
||||
def make_value(self, value):
|
||||
if value == None: return value
|
||||
if isinstance(value, list) or isinstance(value, tuple):
|
||||
# list: coerce each element into new list
|
||||
val_list = [Param.make_value(self, v) for v in iter(value)]
|
||||
else:
|
||||
# singleton: coerce & wrap in a list
|
||||
val_list = [Param.make_value(self, value)]
|
||||
# wrap list in _VectorParamValue (see above)
|
||||
return _VectorParamValue(val_list)
|
||||
|
||||
def sim_decl(self, name):
|
||||
return 'VectorParam<%s> %s;' % (self.ptype_name, name)
|
||||
|
||||
# sim_init inherited from Param
|
||||
|
||||
#####################################################################
|
||||
#
|
||||
# Parameter Types
|
||||
#
|
||||
# Though native Python types could be used to specify parameter types
|
||||
# (the 'ptype' field of the Param and VectorParam classes), it's more
|
||||
# flexible to define our own set of types. This gives us more control
|
||||
# over how Python expressions are converted to values (via the
|
||||
# __init__() constructor) and how these values are printed out (via
|
||||
# the __str__() conversion method). Eventually we'll need these types
|
||||
# to correspond to distinct C++ types as well.
|
||||
#
|
||||
#####################################################################
|
||||
|
||||
# Integer parameter type.
|
||||
class Int(object):
|
||||
# Constructor. Value must be Python int or long (long integer).
|
||||
def __init__(self, value):
|
||||
t = type(value)
|
||||
if t == int or t == long:
|
||||
self.value = value
|
||||
else:
|
||||
raise TypeError, "Int param got value %s %s" % (repr(value), t)
|
||||
|
||||
# Use Python string conversion. Note that this puts an 'L' on the
|
||||
# end of long integers; we can strip that off here if it gives us
|
||||
# trouble.
|
||||
def __str__(self):
|
||||
return str(self.value)
|
||||
|
||||
# Counter, Addr, and Tick are just aliases for Int for now.
|
||||
class Counter(Int):
|
||||
pass
|
||||
|
||||
class Addr(Int):
|
||||
pass
|
||||
|
||||
class Tick(Int):
|
||||
pass
|
||||
|
||||
# Boolean parameter type.
|
||||
class Bool(object):
|
||||
|
||||
# Constructor. Typically the value will be one of the Python bool
|
||||
# constants True or False (or the aliases true and false below).
|
||||
# Also need to take integer 0 or 1 values since bool was not a
|
||||
# distinct type in Python 2.2. Parse a bunch of boolean-sounding
|
||||
# strings too just for kicks.
|
||||
def __init__(self, value):
|
||||
t = type(value)
|
||||
if t == bool:
|
||||
self.value = value
|
||||
elif t == int or t == long:
|
||||
if value == 1:
|
||||
self.value = True
|
||||
elif value == 0:
|
||||
self.value = False
|
||||
elif t == str:
|
||||
v = value.lower()
|
||||
if v == "true" or v == "t" or v == "yes" or v == "y":
|
||||
self.value = True
|
||||
elif v == "false" or v == "f" or v == "no" or v == "n":
|
||||
self.value = False
|
||||
# if we didn't set it yet, it must not be something we understand
|
||||
if not hasattr(self, 'value'):
|
||||
raise TypeError, "Bool param got value %s %s" % (repr(value), t)
|
||||
|
||||
# Generate printable string version.
|
||||
def __str__(self):
|
||||
if self.value: return "true"
|
||||
else: return "false"
|
||||
|
||||
# String-valued parameter.
|
||||
class String(object):
|
||||
# Constructor. Value must be Python string.
|
||||
def __init__(self, value):
|
||||
t = type(value)
|
||||
if t == str:
|
||||
self.value = value
|
||||
else:
|
||||
raise TypeError, "String param got value %s %s" % (repr(value), t)
|
||||
|
||||
# Generate printable string version. Not too tricky.
|
||||
def __str__(self):
|
||||
return self.value
|
||||
|
||||
# Special class for NULL pointers. Note the special check in
|
||||
# make_param_value() above that lets these be assigned where a
|
||||
# SimObject is required.
|
||||
class NullSimObject(object):
|
||||
# Constructor. No parameters, nothing to do.
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def __str__(self):
|
||||
return "NULL"
|
||||
|
||||
# The only instance you'll ever need...
|
||||
NULL = NullSimObject()
|
||||
|
||||
# Enumerated types are a little more complex. The user specifies the
|
||||
# type as Enum(foo) where foo is either a list or dictionary of
|
||||
# alternatives (typically strings, but not necessarily so). (In the
|
||||
# long run, the integer value of the parameter will be the list index
|
||||
# or the corresponding dictionary value. For now, since we only check
|
||||
# that the alternative is valid and then spit it into a .ini file,
|
||||
# there's not much point in using the dictionary.)
|
||||
|
||||
# What Enum() must do is generate a new type encapsulating the
|
||||
# provided list/dictionary so that specific values of the parameter
|
||||
# can be instances of that type. We define two hidden internal
|
||||
# classes (_ListEnum and _DictEnum) to serve as base classes, then
|
||||
# derive the new type from the appropriate base class on the fly.
|
||||
|
||||
|
||||
# Base class for list-based Enum types.
|
||||
class _ListEnum(object):
|
||||
# Constructor. Value must be a member of the type's map list.
|
||||
def __init__(self, value):
|
||||
if value in self.map:
|
||||
self.value = value
|
||||
self.index = self.map.index(value)
|
||||
else:
|
||||
raise TypeError, "Enum param got bad value '%s' (not in %s)" \
|
||||
% (value, self.map)
|
||||
|
||||
# Generate printable string version of value.
|
||||
def __str__(self):
|
||||
return str(self.value)
|
||||
|
||||
class _DictEnum(object):
|
||||
# Constructor. Value must be a key in the type's map dictionary.
|
||||
def __init__(self, value):
|
||||
if value in self.map:
|
||||
self.value = value
|
||||
self.index = self.map[value]
|
||||
else:
|
||||
raise TypeError, "Enum param got bad value '%s' (not in %s)" \
|
||||
% (value, self.map.keys())
|
||||
|
||||
# Generate printable string version of value.
|
||||
def __str__(self):
|
||||
return str(self.value)
|
||||
|
||||
# Enum metaclass... calling Enum(foo) generates a new type (class)
|
||||
# that derives from _ListEnum or _DictEnum as appropriate.
|
||||
class Enum(type):
|
||||
# counter to generate unique names for generated classes
|
||||
counter = 1
|
||||
|
||||
def __new__(cls, map):
|
||||
if isinstance(map, dict):
|
||||
base = _DictEnum
|
||||
keys = map.keys()
|
||||
elif isinstance(map, list):
|
||||
base = _ListEnum
|
||||
keys = map
|
||||
else:
|
||||
raise TypeError, "Enum map must be list or dict (got %s)" % map
|
||||
classname = "Enum%04d" % Enum.counter
|
||||
Enum.counter += 1
|
||||
# New class derives from selected base, and gets a 'map'
|
||||
# attribute containing the specified list or dict.
|
||||
return type.__new__(cls, classname, (base,), { 'map': map })
|
||||
|
||||
|
||||
#
|
||||
# "Constants"... handy aliases for various values.
|
||||
#
|
||||
|
||||
# For compatibility with C++ bool constants.
|
||||
false = False
|
||||
true = True
|
||||
|
||||
# Some memory range specifications use this as a default upper bound.
|
||||
MAX_ADDR = 2**64 - 1
|
||||
|
||||
# For power-of-two sizing, e.g. 64*K gives an integer value 65536.
|
||||
K = 1024
|
||||
M = K*K
|
||||
G = K*M
|
||||
|
||||
#####################################################################
|
||||
|
||||
# Munge an arbitrary Python code string to get it to execute (mostly
|
||||
# dealing with indentation). Stolen from isa_parser.py... see
|
||||
# comments there for a more detailed description.
|
||||
def fixPythonIndentation(s):
|
||||
# get rid of blank lines first
|
||||
s = re.sub(r'(?m)^\s*\n', '', s);
|
||||
if (s != '' and re.match(r'[ \t]', s[0])):
|
||||
s = 'if 1:\n' + s
|
||||
return s
|
||||
|
||||
# Hook to generate C++ parameter code.
|
||||
def gen_sim_code(file):
|
||||
for objname in sim_object_list:
|
||||
print >> file, eval("%s._sim_code()" % objname)
|
||||
|
||||
# The final hook to generate .ini files. Called from configuration
|
||||
# script once config is built.
|
||||
def instantiate(*objs):
|
||||
for obj in objs:
|
||||
obj._instantiate()
|
||||
|
||||
|
126
sim/universe.cc
126
sim/universe.cc
|
@ -36,9 +36,10 @@
|
|||
#include <vector>
|
||||
|
||||
#include "base/misc.hh"
|
||||
#include "sim/universe.hh"
|
||||
#include "sim/builder.hh"
|
||||
#include "sim/host.hh"
|
||||
#include "sim/param.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
#include "sim/universe.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -53,60 +54,13 @@ string outputDirectory;
|
|||
ostream *outputStream;
|
||||
ostream *configStream;
|
||||
|
||||
class UniverseParamContext : public ParamContext
|
||||
// Dummy Object
|
||||
class Root : public SimObject
|
||||
{
|
||||
public:
|
||||
UniverseParamContext(const string &is)
|
||||
: ParamContext(is, OutputInitPhase) {}
|
||||
void checkParams();
|
||||
Root(const std::string &name) : SimObject(name) {}
|
||||
};
|
||||
|
||||
UniverseParamContext universe("Universe");
|
||||
|
||||
Param<Tick> universe_freq(&universe, "frequency", "tick frequency",
|
||||
200000000);
|
||||
|
||||
Param<string> universe_output_dir(&universe, "output_dir",
|
||||
"directory to output data to",
|
||||
".");
|
||||
Param<string> universe_output_file(&universe, "output_file",
|
||||
"file to dump simulator output to",
|
||||
"cout");
|
||||
Param<string> universe_config_output_file(&universe, "config_output_file",
|
||||
"file to dump simulator config to",
|
||||
"m5config.out");
|
||||
|
||||
void
|
||||
UniverseParamContext::checkParams()
|
||||
{
|
||||
ticksPerSecond = universe_freq;
|
||||
double freq = double(ticksPerSecond);
|
||||
__ticksPerMS = freq / 1.0e3;
|
||||
__ticksPerUS = freq / 1.0e6;
|
||||
__ticksPerNS = freq / 1.0e9;
|
||||
__ticksPerPS = freq / 1.0e12;
|
||||
|
||||
if (universe_output_dir.isValid()) {
|
||||
outputDirectory = universe_output_dir;
|
||||
|
||||
// guarantee that directory ends with a '/'
|
||||
if (outputDirectory[outputDirectory.size() - 1] != '/')
|
||||
outputDirectory += "/";
|
||||
|
||||
if (mkdir(outputDirectory.c_str(), 0777) < 0) {
|
||||
if (errno != EEXIST) {
|
||||
panic("%s\ncould not make output directory: %s\n",
|
||||
strerror(errno), outputDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
outputStream = makeOutputStream(universe_output_file);
|
||||
configStream = universe_config_output_file.isValid()
|
||||
? makeOutputStream(universe_config_output_file)
|
||||
: outputStream;
|
||||
}
|
||||
|
||||
Root *root = NULL;
|
||||
|
||||
std::ostream *
|
||||
makeOutputStream(std::string &name)
|
||||
|
@ -146,4 +100,70 @@ closeOutputStream(std::ostream *os)
|
|||
}
|
||||
|
||||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Root)
|
||||
|
||||
Param<bool> full_system;
|
||||
Param<Tick> frequency;
|
||||
Param<string> output_dir;
|
||||
Param<string> output_file;
|
||||
Param<string> config_output_file;
|
||||
|
||||
END_DECLARE_SIM_OBJECT_PARAMS(Root)
|
||||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(Root)
|
||||
|
||||
INIT_PARAM_DFLT(full_system, "full system simulation", true),
|
||||
INIT_PARAM_DFLT(frequency, "tick frequency", 200000000),
|
||||
INIT_PARAM_DFLT(output_dir, "directory to output data to", "."),
|
||||
INIT_PARAM_DFLT(output_file, "file to dump simulator output to", "cout"),
|
||||
INIT_PARAM_DFLT(config_output_file, "file to dump simulator config to",
|
||||
"m5config.out")
|
||||
|
||||
END_INIT_SIM_OBJECT_PARAMS(Root)
|
||||
|
||||
CREATE_SIM_OBJECT(Root)
|
||||
{
|
||||
#ifdef FULL_SYSTEM
|
||||
if (!bool(full_system))
|
||||
panic("FULL_SYSTEM compiled and configuration not full_system");
|
||||
#else
|
||||
if (bool(full_system))
|
||||
panic("FULL_SYSTEM not compiled but configuration is full_system");
|
||||
#endif
|
||||
|
||||
if (root)
|
||||
panic("only one root object allowed!");
|
||||
root = new Root(getInstanceName());
|
||||
|
||||
ticksPerSecond = frequency;
|
||||
double freq = double(ticksPerSecond);
|
||||
__ticksPerMS = freq / 1.0e3;
|
||||
__ticksPerUS = freq / 1.0e6;
|
||||
__ticksPerNS = freq / 1.0e9;
|
||||
__ticksPerPS = freq / 1.0e12;
|
||||
|
||||
if (output_dir.isValid()) {
|
||||
outputDirectory = output_dir;
|
||||
|
||||
// guarantee that directory ends with a '/'
|
||||
if (outputDirectory[outputDirectory.size() - 1] != '/')
|
||||
outputDirectory += "/";
|
||||
|
||||
if (mkdir(outputDirectory.c_str(), 0777) < 0) {
|
||||
if (errno != EEXIST) {
|
||||
panic("%s\ncould not make output directory: %s\n",
|
||||
strerror(errno), outputDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
outputStream = makeOutputStream(output_file);
|
||||
configStream = config_output_file.isValid()
|
||||
? makeOutputStream(config_output_file)
|
||||
: outputStream;
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
REGISTER_SIM_OBJECT("Root", Root)
|
||||
|
||||
|
|
56
test/genini.py
Normal file
56
test/genini.py
Normal file
|
@ -0,0 +1,56 @@
|
|||
# Copyright (c) 2005 The Regents of The University of Michigan
|
||||
# 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.
|
||||
|
||||
import getopt, os, sys
|
||||
|
||||
sys.path.append('..')
|
||||
sys.path.append('../configs/kernel')
|
||||
sys.path.append('../sim/pyconfig')
|
||||
|
||||
from importer import mpy_exec
|
||||
from m5config import *
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], '-E:')
|
||||
for o,a in opts:
|
||||
if o == '-E':
|
||||
offset = a.find('=')
|
||||
if offset == -1:
|
||||
name = a
|
||||
value = True
|
||||
else:
|
||||
name = a[:offset]
|
||||
value = a[offset+1:]
|
||||
env[name] = value
|
||||
except getopt.GetoptError:
|
||||
sys.exit('Improper Usage')
|
||||
|
||||
for arg in args:
|
||||
mpy_exec(file(arg, 'r'), globals())
|
||||
|
||||
if globals().has_key('root') and isinstance(root, type) \
|
||||
and issubclass(root, Root):
|
||||
instantiate(root)
|
Loading…
Reference in a new issue