New and improved configuration mechanism. No more writing of
authorNathan Binkert <binkertn@umich.edu>
Sat, 15 Jan 2005 09:12:25 +0000 (04:12 -0500)
committerNathan Binkert <binkertn@umich.edu>
Sat, 15 Jan 2005 09:12:25 +0000 (04:12 -0500)
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

61 files changed:
SConscript
base/inifile.cc
base/inifile.hh
base/trace.cc
dev/alpha_console.cc
dev/alpha_console.hh
dev/baddev.cc
dev/baddev.hh
dev/etherlink.cc
dev/ethertap.cc
dev/ide_ctrl.cc
dev/ide_disk.cc
dev/io_device.cc
dev/io_device.hh
dev/ns_gige.cc
dev/ns_gige.hh
dev/pciconfigall.cc
dev/pcidev.cc
dev/platform.hh
dev/tsunami.cc
dev/tsunami_cchip.cc
dev/tsunami_io.cc
dev/tsunami_pchip.cc
dev/uart.cc
dev/uart.hh
kern/linux/linux_system.cc
kern/tru64/tru64_system.cc
objects/AlphaConsole.mpy [new file with mode: 0644]
objects/AlphaTLB.mpy [new file with mode: 0644]
objects/BadDevice.mpy [new file with mode: 0644]
objects/BaseCPU.mpy [new file with mode: 0644]
objects/BaseCache.mpy [new file with mode: 0644]
objects/BaseSystem.mpy [new file with mode: 0644]
objects/Bus.mpy [new file with mode: 0644]
objects/CoherenceProtocol.mpy [new file with mode: 0644]
objects/Device.mpy [new file with mode: 0644]
objects/DiskImage.mpy [new file with mode: 0644]
objects/Ethernet.mpy [new file with mode: 0644]
objects/Ide.mpy [new file with mode: 0644]
objects/IntrControl.mpy [new file with mode: 0644]
objects/MemTest.mpy [new file with mode: 0644]
objects/Pci.mpy [new file with mode: 0644]
objects/PhysicalMemory.mpy [new file with mode: 0644]
objects/Platform.mpy [new file with mode: 0644]
objects/Process.mpy [new file with mode: 0644]
objects/Repl.mpy [new file with mode: 0644]
objects/Root.mpy [new file with mode: 0644]
objects/SimConsole.mpy [new file with mode: 0644]
objects/SimpleDisk.mpy [new file with mode: 0644]
objects/Tsunami.mpy [new file with mode: 0644]
objects/Uart.mpy [new file with mode: 0644]
sim/builder.cc
sim/builder.hh
sim/main.cc
sim/param.cc
sim/process.cc
sim/pyconfig/SConscript
sim/pyconfig/m5config.py [new file with mode: 0644]
sim/pyconfig/m5configbase.py [deleted file]
sim/universe.cc
test/genini.py [new file with mode: 0644]

index f6c472216dc89461c6348dd82d84000968109b1a..187edadff7bb1c02065c99beea120b613b8cda9f 100644 (file)
@@ -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
index 94b17966a35fe1fa2cca48b27bd1c996127247b2..862e4082f805c333c93920a985f0ba2e74cd7ccf 100644 (file)
@@ -333,47 +333,6 @@ IniFile::find(const string &sectionName, const string &entryName,
     return true;
 }
 
-bool
-IniFile::findDefault(const string &_section, const string &entry,
-                     string &value) const
-{
-    string section = _section;
-    while (!findAppend(section, entry, value)) {
-        if (!find(section, "default", section)) {
-            return false;
-        }
-    }
-
-    return true;
-}
-
-bool
-IniFile::findAppend(const string &_section, const string &entry,
-                    string &value) const
-{
-    string section = _section;
-    bool ret = false;
-    bool first = true;
-
-    do {
-        string val;
-        if (find(section, entry, val)) {
-            ret = true;
-            if (first) {
-                value = val;
-                first = false;
-            } else {
-                value += " ";
-                value += val;
-            }
-
-        }
-    } while (find(section, "append", section));
-
-    return ret;
-}
-
-
 bool
 IniFile::sectionExists(const string &sectionName) const
 {
index 58a657db41772ded84e783305413a36abb9ef50e..d5d6bab5eb381a83a4baa57ae751b3ceaa16f92c 100644 (file)
@@ -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
index bc6c9aa7a4b3690879f463e00fb466a27af22af4..1c07e408f59bc5547ab921a113aafaef26f7127c 100644 (file)
@@ -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
index 7deabe2fc5322e98dafcd4679f31141a0ec3ef99..8309ea16d153a8d167cbe30b9894e9b556074573 100644 (file)
 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)
index 49c3a9f78a688e232b8cd000027541ec85cee212..96b0a22c2a2e56a9e5197d5dd7943abc2dc68861 100644 (file)
@@ -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 */
index 73b082d4772a480600e72a32c154254c88a43eac..bb1d289ab97e18329ee20d397085633223847345 100644 (file)
@@ -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)
index 8680f6b0a942d121bbb5c96fdf1bd793ef4e8a0b..a9e904c62c19c1ce6ad72cb4334e1ae9d7cc5d3b 100644 (file)
@@ -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__
index d637e152ad9cbaebea43065270ca50ea3a9e8df2..0acc50b0b32b2298fe1399af86c85e632daf502d 100644 (file)
@@ -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)
index 1603a9bd3a25f5a37cd59c6122a53630e3c56d9f..807765d91ac289e8703ee8878677827303f81dc5 100644 (file)
@@ -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);
index 109908ead7e1d6a2d989c486bd5bd2cceec66875..037de1dea165ec03399690256fa327f21d1cfc92 100644 (file)
@@ -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"),
index 073c10436cf9e58ddc7ad99d0c8fbdffd9c7dc13..bfaf3d3aa4254ab63c4ef6be8f6a439084d9dfc3 100644 (file)
@@ -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)
index 7703ad5e303647e2ff5045a50602ebd2c5179fe0..ffded5858339e1537feac3d295e20e46276d0e7d 100644 (file)
@@ -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()
index 8c9dc4a35172648561f1f67676d564a1ea2e1989..649706956e3157ea6c2d8f6042775ab06682c5af 100644 (file)
  * 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__
index eee8fbbce7154ee7ca5d248cc7a569c4f725ea43..aa47436f79330fdbdc77b478fee15ca47f24c7bb 100644 (file)
@@ -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;
index 8d601612659e7395a62f19a4657ce0a30ea24976..bc7a873731113a97891eb62b4c677779263944aa 100644 (file)
@@ -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();
index 609763e928d742bb52c6ddabc32f8e500a7d52c4..1a9804f795969858ddc103fc4e284dcd09d7c9b8 100644 (file)
 
 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));
 
index d156b6a02b49dadcdee1bb32462d129949bf4bbb..c45afadd4c8e64de02574a889fd1acbabdaa438a 100644 (file)
@@ -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),
index 717e494119a30148d14d71337de4fbd6f9291c1f..47ca6209fb860f67ccb0650e9e6bee86bc859cfc 100644 (file)
@@ -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;
 
index f98254354fde1a6abcc0de037cce09d22b6b8eff..a95b7365d79df80bd56b4439e32886bc06812b15 100644 (file)
@@ -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)
index a1f90015374ebd266ee512dd72891a1f8f8a802e..823d1f11848e2cfb0fabc1d4c8d3d7e04cea9491 100644 (file)
@@ -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));
 
index 51ff8b81c30edad6d5b3c6170be85680d1f38927..a223c95c7282758f24f85111e8e9ee497c1980a0 100644 (file)
@@ -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));
 
index 9af19d9304fa19d401154e0bef7bc1672f055b14..f846725f99fcc64f52c51c806adfb6d6991ebee0 100644 (file)
@@ -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));
 
index 2ff94dda5ec5134957f359a2a5d390f4aae7c4b6..3c4ab6d0479c0ec8edd71da53add0ba6b2ced391 100644 (file)
@@ -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));
 
index 855915840d14e5fe215dec29f47b2fb00947b12e..d1f167526943dc2973dc9d4f0c79f7ce730a52b0 100644 (file)
@@ -72,7 +72,6 @@ class Uart : public PioDevice
 
     IntrEvent txIntrEvent;
     IntrEvent rxIntrEvent;
-    Platform *platform;
 
   public:
     Uart(const std::string &name, SimConsole *c, MemoryController *mmu,
index 4342463c372f887cefb917588cf78201fe41aff9..401b4ef44a573a6845a720e8e39698b8b1c44c99 100644 (file)
@@ -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;
index c6435cb1870642564a95ea84208e410db5658e86..7a2e033d86755f45b0fedb14cfbadc556f9e74f8 100644 (file)
@@ -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 (file)
index 0000000..bcb47bf
--- /dev/null
@@ -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 (file)
index 0000000..571b983
--- /dev/null
@@ -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 (file)
index 0000000..5c56b80
--- /dev/null
@@ -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 (file)
index 0000000..2aca912
--- /dev/null
@@ -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 (file)
index 0000000..67ca3c0
--- /dev/null
@@ -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 (file)
index 0000000..2a8b983
--- /dev/null
@@ -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 (file)
index 0000000..9e112bf
--- /dev/null
@@ -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 (file)
index 0000000..a2518bf
--- /dev/null
@@ -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 (file)
index 0000000..babc8aa
--- /dev/null
@@ -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 (file)
index 0000000..bea2e56
--- /dev/null
@@ -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 (file)
index 0000000..64eab00
--- /dev/null
@@ -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 (file)
index 0000000..816b33c
--- /dev/null
@@ -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 (file)
index 0000000..7c97746
--- /dev/null
@@ -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 (file)
index 0000000..49319e1
--- /dev/null
@@ -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 (file)
index 0000000..d6917b0
--- /dev/null
@@ -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 (file)
index 0000000..9644c50
--- /dev/null
@@ -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 (file)
index 0000000..8700262
--- /dev/null
@@ -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 (file)
index 0000000..4f5c4a6
--- /dev/null
@@ -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 (file)
index 0000000..87e7bfb
--- /dev/null
@@ -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 (file)
index 0000000..2649d59
--- /dev/null
@@ -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 (file)
index 0000000..0676738
--- /dev/null
@@ -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 (file)
index 0000000..46bbdb8
--- /dev/null
@@ -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 (file)
index 0000000..6f9555d
--- /dev/null
@@ -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 (file)
index 0000000..a54e19d
--- /dev/null
@@ -0,0 +1,5 @@
+from Device import PioDevice
+
+simobj Uart(PioDevice):
+    console = Param.SimConsole(Super, "The console")
+    size = Param.Addr(0x8, "Device size")
index fa5c113a796bd8f1c1bcde045a4bebae63cb8d73..011694797b4fd6102001ae38f6f1c9dfcc9bc168 100644 (file)
 
 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);
index 36e40c2a9a3698766f7c28bed88dccb240faa756..f6b7b1a1f3818ae768526887595a42a61915eb20 100644 (file)
@@ -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,               \
index e8ac58786256df3b051f6455738c883a477e972b..a99ac26d623473a4f87c2efaf62f3afbf545ac45 100644 (file)
 #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();
 
index d20be8d3358bf215108fc2978714e29ce47b0da6..d666463c95352674b9fde830d6bc553632ef9e9a 100644 (file)
  */
 
 #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;
 }
index bd1a2d8fd197843b6936f3374a3cb8462b78366c..c725d3b1c3cc0b44dd7c489001353fcce9912c08 100644 (file)
@@ -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)
index 7661e7603e5dd5ef938bbfb726c1c8e38e53488f..127b0efae3c7990f713ad00b001be3492c185cc3 100644 (file)
@@ -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
 # (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 (file)
index 0000000..39c2be7
--- /dev/null
@@ -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 (file)
index 6666099..0000000
+++ /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()
-
-
index 824b985fa8642acc4c4bcacf56f210f13e7f1394..69563650d48c3f8863a3b2c8e9b2f03ffa909796 100644 (file)
 #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 (file)
index 0000000..1b740d5
--- /dev/null
@@ -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)