summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Binkert <binkertn@umich.edu>2005-01-15 04:12:25 -0500
committerNathan Binkert <binkertn@umich.edu>2005-01-15 04:12:25 -0500
commit3ece6ab029756fa40679677d124e14acd1349416 (patch)
tree917c6adc11d19f9da82bc51511e6fb0cace8cce9
parentdfecc891509d318ffaefee95b6c6a1ec83b6f28d (diff)
downloadgem5-3ece6ab029756fa40679677d124e14acd1349416.tar.xz
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
-rw-r--r--SConscript88
-rw-r--r--base/inifile.cc41
-rw-r--r--base/inifile.hh18
-rw-r--r--base/trace.cc2
-rw-r--r--dev/alpha_console.cc8
-rw-r--r--dev/alpha_console.hh3
-rw-r--r--dev/baddev.cc7
-rw-r--r--dev/baddev.hh6
-rw-r--r--dev/etherlink.cc23
-rw-r--r--dev/ethertap.cc6
-rw-r--r--dev/ide_ctrl.cc2
-rw-r--r--dev/ide_disk.cc13
-rw-r--r--dev/io_device.cc8
-rw-r--r--dev/io_device.hh12
-rw-r--r--dev/ns_gige.cc9
-rw-r--r--dev/ns_gige.hh2
-rw-r--r--dev/pciconfigall.cc5
-rw-r--r--dev/pcidev.cc14
-rw-r--r--dev/platform.hh2
-rw-r--r--dev/tsunami.cc2
-rw-r--r--dev/tsunami_cchip.cc2
-rw-r--r--dev/tsunami_io.cc2
-rw-r--r--dev/tsunami_pchip.cc2
-rw-r--r--dev/uart.cc4
-rw-r--r--dev/uart.hh1
-rw-r--r--kern/linux/linux_system.cc24
-rw-r--r--kern/tru64/tru64_system.cc24
-rw-r--r--objects/AlphaConsole.mpy8
-rw-r--r--objects/AlphaTLB.mpy9
-rw-r--r--objects/BadDevice.mpy4
-rw-r--r--objects/BaseCPU.mpy38
-rw-r--r--objects/BaseCache.mpy30
-rw-r--r--objects/BaseSystem.mpy14
-rw-r--r--objects/Bus.mpy5
-rw-r--r--objects/CoherenceProtocol.mpy5
-rw-r--r--objects/Device.mpy31
-rw-r--r--objects/DiskImage.mpy12
-rw-r--r--objects/Ethernet.mpy77
-rw-r--r--objects/Ide.mpy12
-rw-r--r--objects/IntrControl.mpy2
-rw-r--r--objects/MemTest.mpy20
-rw-r--r--objects/Pci.mpy50
-rw-r--r--objects/PhysicalMemory.mpy6
-rw-r--r--objects/Platform.mpy4
-rw-r--r--objects/Process.mpy12
-rw-r--r--objects/Repl.mpy7
-rw-r--r--objects/Root.mpy9
-rw-r--r--objects/SimConsole.mpy9
-rw-r--r--objects/SimpleDisk.mpy3
-rw-r--r--objects/Tsunami.mpy21
-rw-r--r--objects/Uart.mpy5
-rw-r--r--sim/builder.cc66
-rw-r--r--sim/builder.hh46
-rw-r--r--sim/main.cc29
-rw-r--r--sim/param.cc50
-rw-r--r--sim/process.cc26
-rw-r--r--sim/pyconfig/SConscript169
-rw-r--r--sim/pyconfig/m5config.py1250
-rw-r--r--sim/pyconfig/m5configbase.py723
-rw-r--r--sim/universe.cc126
-rw-r--r--test/genini.py56
61 files changed, 2128 insertions, 1136 deletions
diff --git a/SConscript b/SConscript
index f6c472216..187edadff 100644
--- a/SConscript
+++ b/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
diff --git a/base/inifile.cc b/base/inifile.cc
index 94b17966a..862e4082f 100644
--- a/base/inifile.cc
+++ b/base/inifile.cc
@@ -334,47 +334,6 @@ IniFile::find(const string &sectionName, const string &entryName,
}
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 &sectionName) const
{
return findSection(sectionName) != NULL;
diff --git a/base/inifile.hh b/base/inifile.hh
index 58a657db4..d5d6bab5e 100644
--- a/base/inifile.hh
+++ b/base/inifile.hh
@@ -190,24 +190,6 @@ class IniFile
bool find(const std::string &section, 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 &section, 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 &section, 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
diff --git a/base/trace.cc b/base/trace.cc
index bc6c9aa7a..1c07e408f 100644
--- a/base/trace.cc
+++ b/base/trace.cc
@@ -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
diff --git a/dev/alpha_console.cc b/dev/alpha_console.cc
index 7deabe2fc..8309ea16d 100644
--- a/dev/alpha_console.cc
+++ b/dev/alpha_console.cc
@@ -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)
diff --git a/dev/alpha_console.hh b/dev/alpha_console.hh
index 49c3a9f78..96b0a22c2 100644
--- a/dev/alpha_console.hh
+++ b/dev/alpha_console.hh
@@ -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 */
diff --git a/dev/baddev.cc b/dev/baddev.cc
index 73b082d47..bb1d289ab 100644
--- a/dev/baddev.cc
+++ b/dev/baddev.cc
@@ -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)
diff --git a/dev/baddev.hh b/dev/baddev.hh
index 8680f6b0a..a9e904c62 100644
--- a/dev/baddev.hh
+++ b/dev/baddev.hh
@@ -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__
diff --git a/dev/etherlink.cc b/dev/etherlink.cc
index d637e152a..0acc50b0b 100644
--- a/dev/etherlink.cc
+++ b/dev/etherlink.cc
@@ -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)
diff --git a/dev/ethertap.cc b/dev/ethertap.cc
index 1603a9bd3..807765d91 100644
--- a/dev/ethertap.cc
+++ b/dev/ethertap.cc
@@ -311,7 +311,7 @@ EtherTap::unserialize(Checkpoint *cp, const std::string &section)
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);
diff --git a/dev/ide_ctrl.cc b/dev/ide_ctrl.cc
index 109908ead..037de1dea 100644
--- a/dev/ide_ctrl.cc
+++ b/dev/ide_ctrl.cc
@@ -664,6 +664,7 @@ IdeController::unserialize(Checkpoint *cp, const std::string &section)
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"),
diff --git a/dev/ide_disk.cc b/dev/ide_disk.cc
index 073c10436..bfaf3d3aa 100644
--- a/dev/ide_disk.cc
+++ b/dev/ide_disk.cc
@@ -1171,12 +1171,14 @@ IdeDisk::unserialize(Checkpoint *cp, const string &section)
#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)
diff --git a/dev/io_device.cc b/dev/io_device.cc
index 7703ad5e3..ffded5858 100644
--- a/dev/io_device.cc
+++ b/dev/io_device.cc
@@ -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()
diff --git a/dev/io_device.hh b/dev/io_device.hh
index 8c9dc4a35..649706956 100644
--- a/dev/io_device.hh
+++ b/dev/io_device.hh
@@ -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__
diff --git a/dev/ns_gige.cc b/dev/ns_gige.cc
index eee8fbbce..aa47436f7 100644
--- a/dev/ns_gige.cc
+++ b/dev/ns_gige.cc
@@ -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;
diff --git a/dev/ns_gige.hh b/dev/ns_gige.hh
index 8d6016126..bc7a87373 100644
--- a/dev/ns_gige.hh
+++ b/dev/ns_gige.hh
@@ -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();
diff --git a/dev/pciconfigall.cc b/dev/pciconfigall.cc
index 609763e92..1a9804f79 100644
--- a/dev/pciconfigall.cc
+++ b/dev/pciconfigall.cc
@@ -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));
diff --git a/dev/pcidev.cc b/dev/pcidev.cc
index d156b6a02..c45afadd4 100644
--- a/dev/pcidev.cc
+++ b/dev/pcidev.cc
@@ -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 &section)
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),
diff --git a/dev/platform.hh b/dev/platform.hh
index 717e49411..47ca6209f 100644
--- a/dev/platform.hh
+++ b/dev/platform.hh
@@ -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;
diff --git a/dev/tsunami.cc b/dev/tsunami.cc
index f98254354..a95b7365d 100644
--- a/dev/tsunami.cc
+++ b/dev/tsunami.cc
@@ -107,7 +107,6 @@ Tsunami::unserialize(Checkpoint *cp, const std::string &section)
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)
diff --git a/dev/tsunami_cchip.cc b/dev/tsunami_cchip.cc
index a1f900153..823d1f118 100644
--- a/dev/tsunami_cchip.cc
+++ b/dev/tsunami_cchip.cc
@@ -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));
diff --git a/dev/tsunami_io.cc b/dev/tsunami_io.cc
index 51ff8b81c..a223c95c7 100644
--- a/dev/tsunami_io.cc
+++ b/dev/tsunami_io.cc
@@ -162,7 +162,7 @@ TsunamiIO::ClockEvent::unserialize(Checkpoint *cp, const std::string &section)
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));
diff --git a/dev/tsunami_pchip.cc b/dev/tsunami_pchip.cc
index 9af19d930..f846725f9 100644
--- a/dev/tsunami_pchip.cc
+++ b/dev/tsunami_pchip.cc
@@ -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));
diff --git a/dev/uart.cc b/dev/uart.cc
index 2ff94dda5..3c4ab6d04 100644
--- a/dev/uart.cc
+++ b/dev/uart.cc
@@ -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));
diff --git a/dev/uart.hh b/dev/uart.hh
index 855915840..d1f167526 100644
--- a/dev/uart.hh
+++ b/dev/uart.hh
@@ -72,7 +72,6 @@ class Uart : public PioDevice
IntrEvent txIntrEvent;
IntrEvent rxIntrEvent;
- Platform *platform;
public:
Uart(const std::string &name, SimConsole *c, MemoryController *mmu,
diff --git a/kern/linux/linux_system.cc b/kern/linux/linux_system.cc
index 4342463c3..401b4ef44 100644
--- a/kern/linux/linux_system.cc
+++ b/kern/linux/linux_system.cc
@@ -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;
diff --git a/kern/tru64/tru64_system.cc b/kern/tru64/tru64_system.cc
index c6435cb18..7a2e033d8 100644
--- a/kern/tru64/tru64_system.cc
+++ b/kern/tru64/tru64_system.cc
@@ -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;
diff --git a/objects/AlphaConsole.mpy b/objects/AlphaConsole.mpy
new file mode 100644
index 000000000..bcb47bf8b
--- /dev/null
+++ b/objects/AlphaConsole.mpy
@@ -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")
diff --git a/objects/AlphaTLB.mpy b/objects/AlphaTLB.mpy
new file mode 100644
index 000000000..571b98374
--- /dev/null
+++ b/objects/AlphaTLB.mpy
@@ -0,0 +1,9 @@
+simobj AlphaTLB(SimObject):
+ abstract = True
+ size = Param.Int("TLB size")
+
+simobj AlphaDTB(AlphaTLB):
+ size = 64
+
+simobj AlphaITB(AlphaTLB):
+ size = 48
diff --git a/objects/BadDevice.mpy b/objects/BadDevice.mpy
new file mode 100644
index 000000000..5c56b8036
--- /dev/null
+++ b/objects/BadDevice.mpy
@@ -0,0 +1,4 @@
+from Device import PioDevice
+
+simobj BadDevice(PioDevice):
+ devicename = Param.String("Name of device to error on")
diff --git a/objects/BaseCPU.mpy b/objects/BaseCPU.mpy
new file mode 100644
index 000000000..2aca9120d
--- /dev/null
+++ b/objects/BaseCPU.mpy
@@ -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
diff --git a/objects/BaseCache.mpy b/objects/BaseCache.mpy
new file mode 100644
index 000000000..67ca3c04e
--- /dev/null
+++ b/objects/BaseCache.mpy
@@ -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")
diff --git a/objects/BaseSystem.mpy b/objects/BaseSystem.mpy
new file mode 100644
index 000000000..2a8b98338
--- /dev/null
+++ b/objects/BaseSystem.mpy
@@ -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")
diff --git a/objects/Bus.mpy b/objects/Bus.mpy
new file mode 100644
index 000000000..9e112bfe6
--- /dev/null
+++ b/objects/Bus.mpy
@@ -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")
diff --git a/objects/CoherenceProtocol.mpy b/objects/CoherenceProtocol.mpy
new file mode 100644
index 000000000..a2518bf39
--- /dev/null
+++ b/objects/CoherenceProtocol.mpy
@@ -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")
diff --git a/objects/Device.mpy b/objects/Device.mpy
new file mode 100644
index 000000000..babc8aa9d
--- /dev/null
+++ b/objects/Device.mpy
@@ -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
+
diff --git a/objects/DiskImage.mpy b/objects/DiskImage.mpy
new file mode 100644
index 000000000..bea2e56a8
--- /dev/null
+++ b/objects/DiskImage.mpy
@@ -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 = ''
diff --git a/objects/Ethernet.mpy b/objects/Ethernet.mpy
new file mode 100644
index 000000000..64eab00a3
--- /dev/null
+++ b/objects/Ethernet.mpy
@@ -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")
+
+
diff --git a/objects/Ide.mpy b/objects/Ide.mpy
new file mode 100644
index 000000000..816b33c8c
--- /dev/null
+++ b/objects/Ide.mpy
@@ -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")
diff --git a/objects/IntrControl.mpy b/objects/IntrControl.mpy
new file mode 100644
index 000000000..7c97746ff
--- /dev/null
+++ b/objects/IntrControl.mpy
@@ -0,0 +1,2 @@
+simobj IntrControl(SimObject):
+ cpu = Param.BaseCPU(Super, "the cpu")
diff --git a/objects/MemTest.mpy b/objects/MemTest.mpy
new file mode 100644
index 000000000..49319e163
--- /dev/null
+++ b/objects/MemTest.mpy
@@ -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")
diff --git a/objects/Pci.mpy b/objects/Pci.mpy
new file mode 100644
index 000000000..d6917b020
--- /dev/null
+++ b/objects/Pci.mpy
@@ -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
diff --git a/objects/PhysicalMemory.mpy b/objects/PhysicalMemory.mpy
new file mode 100644
index 000000000..9644c503a
--- /dev/null
+++ b/objects/PhysicalMemory.mpy
@@ -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")
diff --git a/objects/Platform.mpy b/objects/Platform.mpy
new file mode 100644
index 000000000..870026259
--- /dev/null
+++ b/objects/Platform.mpy
@@ -0,0 +1,4 @@
+simobj Platform(SimObject):
+ abstract = True
+ interrupt_frequency = Param.Tick(1200, "frequency of interrupts")
+ intrctrl = Param.IntrControl(Super, "interrupt controller")
diff --git a/objects/Process.mpy b/objects/Process.mpy
new file mode 100644
index 000000000..4f5c4a674
--- /dev/null
+++ b/objects/Process.mpy
@@ -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")
diff --git a/objects/Repl.mpy b/objects/Repl.mpy
new file mode 100644
index 000000000..87e7bfb7d
--- /dev/null
+++ b/objects/Repl.mpy
@@ -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")
diff --git a/objects/Root.mpy b/objects/Root.mpy
new file mode 100644
index 000000000..2649d59fa
--- /dev/null
+++ b/objects/Root.mpy
@@ -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)
diff --git a/objects/SimConsole.mpy b/objects/SimConsole.mpy
new file mode 100644
index 000000000..0676738f9
--- /dev/null
+++ b/objects/SimConsole.mpy
@@ -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")
diff --git a/objects/SimpleDisk.mpy b/objects/SimpleDisk.mpy
new file mode 100644
index 000000000..46bbdb8fd
--- /dev/null
+++ b/objects/SimpleDisk.mpy
@@ -0,0 +1,3 @@
+simobj SimpleDisk(SimObject):
+ disk = Param.DiskImage("Disk Image")
+ physmem = Param.PhysicalMemory(Super, "Physical Memory")
diff --git a/objects/Tsunami.mpy b/objects/Tsunami.mpy
new file mode 100644
index 000000000..6f9555d49
--- /dev/null
+++ b/objects/Tsunami.mpy
@@ -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")
diff --git a/objects/Uart.mpy b/objects/Uart.mpy
new file mode 100644
index 000000000..a54e19dcd
--- /dev/null
+++ b/objects/Uart.mpy
@@ -0,0 +1,5 @@
+from Device import PioDevice
+
+simobj Uart(PioDevice):
+ console = Param.SimConsole(Super, "The console")
+ size = Param.Addr(0x8, "Device size")
diff --git a/sim/builder.cc b/sim/builder.cc
index fa5c113a7..011694797 100644
--- a/sim/builder.cc
+++ b/sim/builder.cc
@@ -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)) {
- (*i)->parse(string_value);
- }
- else if (iniFile.findDefault(iniSection, (*i)->name, string_value)) {
+ if (iniFile.find(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);
diff --git a/sim/builder.hh b/sim/builder.hh
index 36e40c2a9..f6b7b1a1f 100644
--- a/sim/builder.hh
+++ b/sim/builder.hh
@@ -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, \
diff --git a/sim/main.cc b/sim/main.cc
index e8ac58786..a99ac26d6 100644
--- a/sim/main.cc
+++ b/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();
diff --git a/sim/param.cc b/sim/param.cc
index d20be8d33..d666463c9 100644
--- a/sim/param.cc
+++ b/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)
-{
- // 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);
- }
+ParamContext::resolveSimObject(const string &name)
+{
ConfigNode *n = getConfigNode();
return n ? n->resolveSimObject(name) : NULL;
}
diff --git a/sim/process.cc b/sim/process.cc
index bd1a2d8fd..c725d3b1c 100644
--- a/sim/process.cc
+++ b/sim/process.cc
@@ -397,19 +397,29 @@ END_INIT_SIM_OBJECT_PARAMS(LiveProcess)
CREATE_SIM_OBJECT(LiveProcess)
{
+ string in = input;
+ string out = output;
+
// 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;
+ int stdin_fd, stdout_fd, stderr_fd;
+
+ if (in == "stdin" || in == "cin")
+ stdin_fd = STDIN_FILENO;
+ else
+ stdin_fd = Process::openInputFile(input);
- // dummy for default env
- vector<string> null_vec;
+ 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)
diff --git a/sim/pyconfig/SConscript b/sim/pyconfig/SConscript
index 7661e7603..127b0efae 100644
--- a/sim/pyconfig/SConscript
+++ b/sim/pyconfig/SConscript
@@ -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)
diff --git a/sim/pyconfig/m5config.py b/sim/pyconfig/m5config.py
new file mode 100644
index 000000000..39c2be7ab
--- /dev/null
+++ b/sim/pyconfig/m5config.py
@@ -0,0 +1,1250 @@
+# 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, re, sys, types
+
+env = {}
+env.update(os.environ)
+def defined(key):
+ return env.has_key(key)
+
+def define(key, value = True):
+ env[key] = value
+
+def issequence(value):
+ return isinstance(value, tuple) or isinstance(value, list)
+
+class Singleton(type):
+ def __call__(cls, *args, **kwargs):
+ if hasattr(cls, '_instance'):
+ return cls._instance
+
+ cls._instance = super(Singleton, cls).__call__(*args, **kwargs)
+ return cls._instance
+
+#class MetaTempObject(type):
+# classes = {}
+# def __new__(mcls, name, bases, dict):
+# _bases = []
+# for base in bases:
+# if base.__name__ is 'TempObject':
+# _bases.append('SimObject')
+# else:
+# _bases.append(base.__name__)
+# newdict = { '_bases' : _bases, '_name' : name, '_params' : dict }
+# cls = type.__new__(mcls, name, bases, newdict)
+# mcls.classes[name] = cls
+# return cls
+#
+#class TempObject(object):
+# __metaclass__ = MetaTempObject
+
+def defined(s):
+ try:
+ eval(s)
+ return True
+ except NameError:
+ return False
+
+if os.environ.has_key('FULL_SYSTEM'):
+ FULL_SYSTEM = True
+
+#####################################################################
+#
+# 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
+# _params 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
+# _params 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.
+#
+#####################################################################
+
+class Proxy(object):
+ def __init__(self, path = ()):
+ self._object = None
+ self._path = path
+
+ def __getattr__(self, attr):
+ return Proxy(self._path + (attr, ))
+
+ def __setattr__(self, attr, value):
+ if not attr.startswith('_'):
+ raise AttributeError, 'cannot set attribute %s' % attr
+ super(Proxy, self).__setattr__(attr, value)
+
+ def _convert(self):
+ obj = self._object
+ for attr in self._path:
+ obj = obj.__getattribute__(attr)
+ return obj
+
+Super = Proxy()
+
+def isSubClass(value, cls):
+ try:
+ return issubclass(value, cls)
+ except:
+ return False
+
+def isParam(self):
+ return isinstance(self, _Param)
+
+def isConfigNode(value):
+ try:
+ return issubclass(value, ConfigNode)
+ except:
+ return False
+
+def isSimObject(value):
+ try:
+ return issubclass(value, SimObject)
+ except:
+ return False
+
+def isSimObjSequence(value):
+ if not issequence(value):
+ return False
+
+ for val in value:
+ if not isNullPointer(val) and not isConfigNode(val):
+ return False
+
+ return True
+
+# 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):
+ keywords = { 'abstract' : types.BooleanType,
+ 'check' : types.FunctionType,
+ '_init' : types.FunctionType,
+ 'type' : (types.NoneType, types.StringType) }
+
+ # __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__(mcls, name, bases, dict):
+ priv = { 'abstract' : False,
+ # initialize _params and _values dicts to empty
+ '_params' : {},
+ '_values' : {},
+ '_disable' : {} }
+
+ for key,val in dict.items():
+ if mcls.keywords.has_key(key):
+ if not isinstance(val, mcls.keywords[key]):
+ raise TypeError, \
+ 'keyword %s has the wrong type %s should be %s' % \
+ (key, type(val), mcls.keywords[key])
+
+ if isinstance(val, types.FunctionType):
+ val = classmethod(val)
+ priv[key] = val
+ del dict[key]
+
+ elif key.startswith('_'):
+ priv[key] = val
+ del dict[key]
+
+ elif not isNullPointer(val) and isConfigNode(val):
+ dict[key] = val()
+
+ elif isSimObjSequence(val):
+ dict[key] = [ v() for v in val ]
+
+ # If your parent has a value in it that's a config node, clone it.
+ for base in bases:
+ if not isConfigNode(base):
+ continue
+
+ for name,value in base._values.iteritems():
+ if dict.has_key(name):
+ continue
+
+ if isConfigNode(value):
+ priv['_values'][name] = value()
+ elif isSimObjSequence(value):
+ priv['_values'][name] = [ val() for val in value ]
+
+ # entries left in dict will get passed to __init__, where we'll
+ # deal with them as params.
+ return super(MetaConfigNode, mcls).__new__(mcls, name, bases, priv)
+
+ # initialization: start out with an empty _params dict (makes life
+ # simpler if we can assume _params is always valid).
+ def __init__(cls, name, bases, dict):
+ super(MetaConfigNode, cls).__init__(cls, name, bases, {})
+
+ cls._bases = [c for c in cls.__mro__ if isConfigNode(c)]
+
+ # initialize attributes with values from class definition
+ for pname,value in dict.iteritems():
+ setattr(cls, pname, value)
+
+ if hasattr(cls, '_init'):
+ cls._init()
+ del cls._init
+
+ def _isvalue(cls, name):
+ for c in cls._bases:
+ if c._params.has_key(name):
+ return True
+
+ for c in cls._bases:
+ if c._values.has_key(name):
+ return True
+
+ return False
+
+ # generator that iterates across all parameters for this class and
+ # all classes it inherits from
+ def _getparams(cls):
+ params = {}
+ for c in cls._bases:
+ for p,v in c._params.iteritems():
+ if not params.has_key(p):
+ params[p] = v
+ return params
+
+ # Lookup a parameter description by name in the given class.
+ def _getparam(cls, name, default = AttributeError):
+ for c in cls._bases:
+ if c._params.has_key(name):
+ return c._params[name]
+ if isSubClass(default, Exception):
+ raise default, \
+ "object '%s' has no attribute '%s'" % (cls.__name__, name)
+ else:
+ return default
+
+ def _setparam(cls, name, value):
+ cls._params[name] = value
+
+ def _hasvalue(cls, name):
+ for c in cls._bases:
+ if c._values.has_key(name):
+ return True
+
+ return False
+
+ def _getvalues(cls):
+ values = {}
+ for i,c in enumerate(cls._bases):
+ for p,v in c._values.iteritems():
+ if not values.has_key(p):
+ values[p] = v
+ return values
+
+ def _getvalue(cls, name, default = AttributeError):
+ value = None
+ for c in cls._bases:
+ if c._values.has_key(name):
+ value = c._values[name]
+ break
+ if value is not None:
+ return value
+
+ param = cls._getparam(name, None)
+ if param is not None and hasattr(param, 'default'):
+ param.valid(param.default)
+ value = param.default
+ cls._setvalue(name, value)
+ return value
+
+ if isSubClass(default, Exception):
+ raise default, 'value for %s not found' % name
+ else:
+ return default
+
+ def _setvalue(cls, name, value):
+ cls._values[name] = value
+
+ def _getdisable(cls, name):
+ for c in cls._bases:
+ if c._disable.has_key(name):
+ return c._disable[name]
+ return False
+
+ def _setdisable(cls, name, value):
+ cls._disable[name] = value
+
+ def __getattr__(cls, attr):
+ if cls._isvalue(attr):
+ return Value(cls, attr)
+
+ raise AttributeError, \
+ "object '%s' has no attribute '%s'" % (cls.__name__, cls)
+
+
+ # Set attribute (called on foo.attr = value when foo is an
+ # instance of class cls).
+ def __setattr__(cls, attr, value):
+ # normal processing for private attributes
+ if attr.startswith('_'):
+ type.__setattr__(cls, attr, value)
+ return
+
+ if cls.keywords.has_key(attr):
+ raise TypeError, \
+ "keyword '%s' can only be set in a simobj definition" % attr
+
+ if isParam(value):
+ cls._setparam(attr, value)
+ return
+
+ # must be SimObject param
+ param = cls._getparam(attr, None)
+ if param:
+ # It's ok: set attribute by delegating to 'object' class.
+ # Note the use of param.make_value() to verify/canonicalize
+ # the assigned value
+ param.valid(value)
+ cls._setvalue(attr, value)
+ elif isConfigNode(value) or isSimObjSequence(value):
+ cls._setvalue(attr, value)
+ else:
+ for p,v in cls._getparams().iteritems():
+ print p,v
+ raise AttributeError, \
+ "Class %s has no parameter %s" % (cls.__name__, attr)
+
+ def add_child(cls, instance, name, child):
+ if isNullPointer(child) or instance.top_child_names.has_key(name):
+ return
+
+ if issequence(child):
+ kid = []
+ for i,c in enumerate(child):
+ n = '%s%d' % (name, i)
+ k = c.instantiate(n, instance)
+
+ instance.children.append(k)
+ instance.child_names[n] = k
+ instance.child_objects[c] = k
+ kid.append(k)
+ else:
+ kid = child.instantiate(name, instance)
+ instance.children.append(kid)
+ instance.child_names[name] = kid
+ instance.child_objects[child] = kid
+
+ instance.top_child_names[name] = kid
+
+ # Print instance info to .ini file.
+ def instantiate(cls, name, parent = None):
+ instance = Node(name, cls, cls.type, parent)
+
+ if hasattr(cls, 'check'):
+ cls.check()
+
+ for key,value in cls._getvalues().iteritems():
+ if cls._getdisable(key):
+ continue
+
+ if isConfigNode(value):
+ cls.add_child(instance, key, value)
+ if issequence(value):
+ list = [ v for v in value if isConfigNode(v) ]
+ if len(list):
+ cls.add_child(instance, key, list)
+
+ for pname,param in cls._getparams().iteritems():
+ try:
+ if cls._getdisable(pname):
+ continue
+
+ value = cls._getvalue(pname)
+
+ if isConfigNode(value):
+ value = instance.child_objects[value]
+ elif issequence(value):
+ v = []
+ for val in value:
+ if isConfigNode(val):
+ v.append(instance.child_objects[val])
+ else:
+ v.append(val)
+ value = v
+
+ p = NodeParam(pname, param, value)
+ instance.params.append(p)
+ instance.param_names[pname] = p
+ except:
+ print 'Exception while evaluating %s.%s' % \
+ (instance.path, pname)
+ raise
+
+ return instance
+
+ def _convert(cls, value):
+ realvalue = value
+ if isinstance(value, Node):
+ realvalue = value.realtype
+
+ if isinstance(realvalue, Proxy):
+ return value
+
+ if realvalue == None or isNullPointer(realvalue):
+ return value
+
+ if isSubClass(realvalue, cls):
+ return value
+
+ raise TypeError, 'object %s type %s wrong type, should be %s' % \
+ (repr(realvalue), realvalue, cls)
+
+ def _string(cls, value):
+ if isNullPointer(value):
+ return 'Null'
+ return Node._string(value)
+
+# 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
+ type = None
+
+ def __new__(cls, **kwargs):
+ return MetaConfigNode(cls.__name__, (cls, ), kwargs)
+
+ # 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, value):
+ # if attr.startswith('_'):
+ # object.__setattr__(self, attr, value)
+ # return
+ # not private; look up as param
+ # param = self.__class__.lookup_param(attr)
+ # if not param:
+ # raise AttributeError, \
+ # "Class %s has no parameter %s" \
+ # % (self.__class__.__name__, attr)
+ # 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.convert(value)
+ # object.__setattr__(self, attr, v)
+
+# 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):
+ def _sim_code(cls):
+ name = cls.__name__
+ param_names = cls._params.keys()
+ param_names.sort()
+ code = "BEGIN_DECLARE_SIM_OBJECT_PARAMS(%s)\n" % name
+ decls = [" " + cls._params[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._params[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)
+
+class NodeParam(object):
+ def __init__(self, name, param, value):
+ self.name = name
+ self.param = param
+ self.ptype = param.ptype
+ self.convert = param.convert
+ self.string = param.string
+ self.value = value
+
+class Node(object):
+ all = {}
+ def __init__(self, name, realtype, type, parent):
+ self.name = name
+ self.realtype = realtype
+ self.type = type
+ self.parent = parent
+ self.children = []
+ self.child_names = {}
+ self.child_objects = {}
+ self.top_child_names = {}
+ self.params = []
+ self.param_names = {}
+
+ path = [ self.name ]
+ node = self.parent
+ while node is not None:
+ if node.name != 'root':
+ path.insert(0, node.name)
+ else:
+ assert(node.parent is None)
+ node = node.parent
+ self.path = '.'.join(path)
+
+ def find(self, realtype, path):
+ rtype = eval(realtype)
+ if not path:
+ if issubclass(self.realtype, rtype):
+ return self, True
+
+ obj = None
+ for child in self.children:
+ if issubclass(child.realtype, rtype):
+ if obj is not None:
+ raise AttributeError, \
+ 'Super matched more than one: %s %s' % \
+ (obj.path, child.path)
+ obj = child
+ return obj, obj is not None
+
+ try:
+ obj = self
+ for node in path[:-1]:
+ obj = obj.child_names[node]
+
+ last = path[-1]
+ if obj.child_names.has_key(last):
+ value = obj.child_names[last]
+ if issubclass(value.realtype, rtype):
+ return value, True
+ elif obj.param_names.has_key(last):
+ value = obj.param_names[last]
+ rtype._convert(value.value)
+ return value.value, True
+ except KeyError:
+ pass
+
+ return None, False
+
+ def unproxy(self, ptype, value):
+ if not isinstance(value, Proxy):
+ return value
+
+ if value is None:
+ raise AttributeError, 'Error while fixing up %s' % self.path
+
+ obj = self
+ done = False
+ while not done:
+ if obj is None:
+ raise AttributeError, \
+ 'Parent of %s type %s not found at path %s' \
+ % (self.name, ptype, value._path)
+ found, done = obj.find(ptype, value._path)
+ if isinstance(found, Proxy):
+ done = false
+ obj = obj.parent
+
+ return found
+
+ def fixup(self):
+ self.all[self.path] = self
+
+ for param in self.params:
+ ptype = param.ptype
+ pval = param.value
+
+ try:
+ if issequence(pval):
+ param.value = [ self.unproxy(ptype, pv) for pv in pval ]
+ else:
+ param.value = self.unproxy(ptype, pval)
+ except:
+ print 'Error while fixing up %s:%s' % (self.path, param.name)
+ raise
+
+ for child in self.children:
+ assert(child != self)
+ child.fixup()
+
+ # print type and parameter values to .ini file
+ def display(self):
+ print '[' + self.path + ']' # .ini section header
+
+ if isSimObject(self.realtype):
+ print 'type = %s' % self.type
+
+ if self.children:
+ # 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.children])
+
+ for param in self.params:
+ try:
+ if param.value is None:
+ raise AttributeError, 'Parameter with no value'
+
+ value = param.convert(param.value)
+ string = param.string(value)
+ except:
+ print 'exception in %s:%s' % (self.path, param.name)
+ raise
+
+ print '%s = %s' % (param.name, string)
+
+ print
+
+ # recursively dump out children
+ for c in self.children:
+ c.display()
+
+ def _string(cls, value):
+ if not isinstance(value, Node):
+ raise AttributeError, 'expecting %s got %s' % (Node, value)
+ return value.path
+ _string = classmethod(_string)
+
+#####################################################################
+#
+# Parameter description classes
+#
+# The _params 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
+# _convert() 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._setparams()); after that point they aren't used.
+#
+#####################################################################
+
+def isNullPointer(value):
+ return isinstance(value, NullSimObject)
+
+class Value(object):
+ def __init__(self, obj, attr):
+ super(Value, self).__setattr__('attr', attr)
+ super(Value, self).__setattr__('obj', obj)
+
+ def _getattr(self):
+ return self.obj._getvalue(self.attr)
+
+ def __setattr__(self, attr, value):
+ if attr == 'disable':
+ self.obj._setdisable(self.attr, value)
+ else:
+ setattr(self._getattr(), attr, value)
+
+ def __getattr__(self, attr):
+ if attr == 'disable':
+ return self.obj._getdisable(self.attr)
+ else:
+ return getattr(self._getattr(), attr)
+
+ def __getitem__(self, index):
+ return self._getattr().__getitem__(index)
+
+ def __call__(self, *args, **kwargs):
+ return self._getattr().__call__(*args, **kwargs)
+
+ def __nonzero__(self):
+ return bool(self._getattr())
+
+ def __str__(self):
+ return str(self._getattr())
+
+# Regular parameter.
+class _Param(object):
+ def __init__(self, ptype, *args, **kwargs):
+ self.ptype = ptype
+
+ if args:
+ if len(args) == 1:
+ self.desc = args[0]
+ elif len(args) == 2:
+ self.default = args[0]
+ self.desc = args[1]
+ else:
+ raise TypeError, 'too many arguments'
+
+ if kwargs.has_key('desc'):
+ assert(not hasattr(self, 'desc'))
+ self.desc = kwargs['desc']
+ del kwargs['desc']
+
+ if kwargs.has_key('default'):
+ assert(not hasattr(self, 'default'))
+ self.default = kwargs['default']
+ del kwargs['default']
+
+ if kwargs:
+ raise TypeError, 'extra unknown kwargs %s' % kwargs
+
+ if not hasattr(self, 'desc'):
+ raise TypeError, 'desc attribute missing'
+
+ def valid(self, value):
+ if not isinstance(value, Proxy):
+ ptype = eval(self.ptype)
+ ptype._convert(value)
+
+ def convert(self, value):
+ ptype = eval(self.ptype)
+ return ptype._convert(value)
+
+ def string(self, value):
+ ptype = eval(self.ptype)
+ return ptype._string(value)
+
+ def get(self, name, instance, owner):
+ # nothing to do if None or already correct type. Also allow NULL
+ # pointer to be assigned where a SimObject is expected.
+ try:
+ if value == None or isinstance(value, self.ptype) or \
+ isConfigNode(self.ptype) and \
+ (isNullPointer(value) or issubclass(value, self.ptype)):
+ return value
+
+ except TypeError:
+ # this type conversion will raise an exception if it's illegal
+ return self.ptype(value)
+
+ def set(self, name, instance, value):
+ instance.__dict__[name] = 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))
+
+class _ParamProxy(object):
+ def __init__(self, type):
+ self.ptype = type
+
+ # E.g., Param.Int(5, "number of widgets")
+ def __call__(self, *args, **kwargs):
+ return _Param(self.ptype, *args, **kwargs)
+
+ def __getattr__(self, attr):
+ if attr == '__bases__':
+ raise AttributeError, ''
+ cls = type(self)
+ return cls(attr)
+
+ def __setattr__(self, attr, value):
+ if attr != 'ptype':
+ raise AttributeError, \
+ 'Attribute %s not available in %s' % (attr, self.__class__)
+ super(_ParamProxy, self).__setattr__(attr, value)
+
+
+Param = _ParamProxy(None)
+
+# 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):
+ def __init__(self, type, *args, **kwargs):
+ _Param.__init__(self, type, *args, **kwargs)
+
+ def valid(self, value):
+ if value == None:
+ return True
+
+ ptype = eval(self.ptype)
+ if issequence(value):
+ for val in value:
+ if not isinstance(val, Proxy):
+ ptype._convert(val)
+ elif not isinstance(value, Proxy):
+ ptype._convert(value)
+
+ # Convert assigned value to appropriate type. If the RHS is not a
+ # list or tuple, it generates a single-element list.
+ def convert(self, value):
+ if value == None:
+ return []
+
+ ptype = eval(self.ptype)
+ if issequence(value):
+ # list: coerce each element into new list
+ return [ ptype._convert(v) for v in value ]
+ else:
+ # singleton: coerce & wrap in a list
+ return ptype._convert(value)
+
+ def string(self, value):
+ ptype = eval(self.ptype)
+ if issequence(value):
+ return ' '.join([ ptype._string(v) for v in value])
+ else:
+ return ptype._string(value)
+
+ def sim_decl(self, name):
+ return 'VectorParam<%s> %s;' % (self.ptype.__name__, name)
+
+class _VectorParamProxy(_ParamProxy):
+ # E.g., VectorParam.Int(5, "number of widgets")
+ def __call__(self, *args, **kwargs):
+ return _VectorParam(self.ptype, *args, **kwargs)
+
+VectorParam = _VectorParamProxy(None)
+
+#####################################################################
+#
+# 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 _CheckedInt(object):
+ def _convert(cls, value):
+ t = type(value)
+ if t == bool:
+ return int(value)
+
+ if t != int and t != long and t != float and t != str:
+ raise TypeError, 'Integer parameter of invalid type %s' % t
+
+ if t == str or t == float:
+ value = long(value)
+
+ if not cls._min <= value <= cls._max:
+ raise TypeError, 'Integer parameter out of bounds %d < %d < %d' % \
+ (cls._min, value, cls._max)
+
+ return value
+ _convert = classmethod(_convert)
+
+ def _string(cls, value):
+ return str(value)
+ _string = classmethod(_string)
+
+class CheckedInt(type):
+ def __new__(cls, name, min, max):
+ # New class derives from _CheckedInt base with proper bounding
+ # parameters
+ dict = { '_name' : name, '_min' : min, '_max' : max }
+ return type.__new__(cls, name, (_CheckedInt, ), dict)
+
+class CheckedIntType(CheckedInt):
+ def __new__(cls, name, size, unsigned):
+ dict = {}
+ if unsigned:
+ min = 0
+ max = 2 ** size - 1
+ else:
+ min = -(2 ** (size - 1))
+ max = (2 ** (size - 1)) - 1
+
+ return super(cls, CheckedIntType).__new__(cls, name, min, max)
+
+Int = CheckedIntType('int', 32, False)
+Unsigned = CheckedIntType('unsigned', 32, True)
+
+Int8 = CheckedIntType('int8_t', 8, False)
+UInt8 = CheckedIntType('uint8_t', 8, True)
+Int16 = CheckedIntType('int16_t', 16, False)
+UInt16 = CheckedIntType('uint16_t', 16, True)
+Int32 = CheckedIntType('int32_t', 32, False)
+UInt32 = CheckedIntType('uint32_t', 32, True)
+Int64 = CheckedIntType('int64_t', 64, False)
+UInt64 = CheckedIntType('uint64_t', 64, True)
+
+Counter = CheckedIntType('Counter', 64, True)
+Addr = CheckedIntType('Addr', 64, True)
+Tick = CheckedIntType('Tick', 64, True)
+
+Percent = CheckedInt('int', 0, 100)
+
+class Pair(object):
+ def __init__(self, first, second):
+ self.first = first
+ self.second = second
+
+class _Range(object):
+ def _convert(cls, value):
+ if not isinstance(value, Pair):
+ raise TypeError, 'value %s is not a Pair' % value
+ return Pair(cls._type._convert(value.first),
+ cls._type._convert(value.second))
+ _convert = classmethod(_convert)
+
+ def _string(cls, value):
+ return '%s:%s' % (cls._type._string(value.first),
+ cls._type._string(value.second))
+ _string = classmethod(_string)
+
+def RangeSize(start, size):
+ return Pair(start, start + size - 1)
+
+class Range(type):
+ def __new__(cls, type):
+ dict = { '_name' : 'Range<%s>' + type._name, '_type' : type }
+ cname = 'Range_' + type.__name__
+ return super(cls, Range).__new__(cls, cname, (_Range, ), dict)
+
+AddrRange = Range(Addr)
+
+# Boolean parameter type.
+class Bool(object):
+ _name = 'bool'
+ def _convert(value):
+ t = type(value)
+ if t == bool:
+ return value
+
+ if t == int or t == long:
+ return bool(value)
+
+ if t == str:
+ v = value.lower()
+ if v == "true" or v == "t" or v == "yes" or v == "y":
+ return True
+ elif v == "false" or v == "f" or v == "no" or v == "n":
+ return False
+
+ raise TypeError, 'Bool parameter (%s) of invalid type %s' % (v, t)
+ _convert = staticmethod(_convert)
+
+ def _string(value):
+ if value:
+ return "true"
+ else:
+ return "false"
+ _string = staticmethod(_string)
+
+# String-valued parameter.
+class String(object):
+ _name = 'string'
+
+ # Constructor. Value must be Python string.
+ def _convert(cls,value):
+ if value is None:
+ return ''
+ if isinstance(value, str):
+ return value
+
+ raise TypeError, \
+ "String param got value %s %s" % (repr(value), type(value))
+ _convert = classmethod(_convert)
+
+ # Generate printable string version. Not too tricky.
+ def _string(cls, value):
+ return value
+ _string = classmethod(_string)
+
+
+def IncEthernetAddr(addr, val = 1):
+ bytes = map(lambda x: int(x, 16), addr.split(':'))
+ bytes[5] += val
+ for i in (5, 4, 3, 2, 1):
+ val,rem = divmod(bytes[i], 256)
+ bytes[i] = rem
+ if val == 0:
+ break
+ bytes[i - 1] += val
+ assert(bytes[0] <= 255)
+ return ':'.join(map(lambda x: '%02x' % x, bytes))
+
+class NextEthernetAddr(object):
+ __metaclass__ = Singleton
+ addr = "00:90:00:00:00:01"
+
+ def __init__(self, inc = 1):
+ self.value = self.addr
+ self.addr = IncEthernetAddr(self.addr, inc)
+
+class EthernetAddr(object):
+ _name = 'EthAddr'
+
+ def _convert(cls, value):
+ if value == NextEthernetAddr:
+ return value
+
+ if not isinstance(value, str):
+ raise TypeError, "expected an ethernet address and didn't get one"
+
+ bytes = value.split(':')
+ if len(bytes) != 6:
+ raise TypeError, 'invalid ethernet address %s' % value
+
+ for byte in bytes:
+ if not 0 <= int(byte) <= 256:
+ raise TypeError, 'invalid ethernet address %s' % value
+
+ return value
+ _convert = classmethod(_convert)
+
+ def _string(cls, value):
+ if value == NextEthernetAddr:
+ value = value().value
+ return value
+ _string = classmethod(_string)
+
+# Special class for NULL pointers. Note the special check in
+# make_param_value() above that lets these be assigned where a
+# SimObject is required.
+# only one copy of a particular node
+class NullSimObject(object):
+ __metaclass__ = Singleton
+ _name = 'NULL'
+
+ def __call__(cls):
+ return cls
+
+ def _sim_code(cls):
+ pass
+ _sim_code = classmethod(_sim_code)
+
+ def _instantiate(self, parent = None, path = ''):
+ pass
+
+ def _convert(cls, value):
+ if value == Nxone:
+ return
+
+ if isinstance(value, cls):
+ return value
+
+ raise TypeError, 'object %s %s of the wrong type, should be %s' % \
+ (repr(value), type(value), cls)
+ _convert = classmethod(_convert)
+
+ def _string():
+ return 'NULL'
+ _string = staticmethod(_string)
+
+# The only instance you'll ever need...
+Null = 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 Enum types.
+class _Enum(object):
+ def _convert(self, value):
+ if value not in self.map:
+ raise TypeError, "Enum param got bad value '%s' (not in %s)" \
+ % (value, self.map)
+ return value
+ _convert = classmethod(_convert)
+
+ # Generate printable string version of value.
+ def _string(self, value):
+ return str(value)
+ _string = classmethod(_string)
+
+# 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, *args):
+ if len(args) > 1:
+ enum_map = args
+ else:
+ enum_map = args[0]
+
+ if isinstance(enum_map, dict):
+ map = enum_map
+ elif issequence(enum_map):
+ map = {}
+ for idx,val in enumerate(enum_map):
+ map[val] = idx
+ 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 _Enum base, and gets a 'map'
+ # attribute containing the specified list or dict.
+ return type.__new__(cls, classname, (_Enum, ), { '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 = Addr._max
+
+# 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(root):
+ if not issubclass(root, Root):
+ raise AttributeError, 'Can only instantiate the Root of the tree'
+
+ instance = root.instantiate('root')
+ instance.fixup()
+ instance.display()
+
+from objects import *
+
diff --git a/sim/pyconfig/m5configbase.py b/sim/pyconfig/m5configbase.py
deleted file mode 100644
index 66660994e..000000000
--- a/sim/pyconfig/m5configbase.py
+++ /dev/null
@@ -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()
-
-
diff --git a/sim/universe.cc b/sim/universe.cc
index 824b985fa..69563650d 100644
--- a/sim/universe.cc
+++ b/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)
diff --git a/test/genini.py b/test/genini.py
new file mode 100644
index 000000000..1b740d554
--- /dev/null
+++ b/test/genini.py
@@ -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)