New and improved configuration mechanism. No more writing of

wierd ini files.  The ini files are still used as an intermediate step,
but a sophisticated python library exists to help build them more
easily.

SConscript:
    add the new embedded file stuff
    remove all of the old object description junk
base/inifile.cc:
base/inifile.hh:
    get rid of findDefault and findAppend since they were the source
    of much evil.
base/trace.cc:
    For now, if we don't have the dprintf_stream set up, dump
    to standard out.  We probably want a command line option
    for this.
dev/alpha_console.cc:
    PioDevice now takes a platform parameter.
    All PioDevices must have a pio_latency parameter.  We stick
    a dummy parameter in here for now until we get rid of the
    builder stuff.
dev/alpha_console.hh:
    don't need Platform anymore
dev/baddev.cc:
    PioDevice now takes a platform parameter.
    All PioDevices must have a pio_latency parameter.  We stick
    a dummy parameter in here for now until we get rid of the
    builder stuff. Same for the platform parameter, though we just
    pass the PioDevice a null parameter since it isn't used by
    this device and it's quicker.
dev/baddev.hh:
    fix #include guards
dev/etherlink.cc:
    rename parameters.
dev/ethertap.cc:
    rename parameters
dev/ide_ctrl.cc:
    All devices need an address even if it will get overwritten later.
dev/ide_disk.cc:
    use an enum for the drive ID stuff.
    rename disk_delay -> delay
    Actually, I think that we should implement "cable select" and
    have the controller tell the drive what it is.
dev/io_device.cc:
dev/io_device.hh:
    All IO devices take a Platform *
dev/ns_gige.cc:
    all devices need an io_bus.  rename header_bus to io_bus
    We don't need stuff for the interrupt controller since
    it's all in the platform now.
dev/ns_gige.hh:
    We don't need stuff for the interrupt controller now since
    it's all in the platform.
dev/pciconfigall.cc:
    Pass a dummy NULL to the PioDevice for the platform since
    we don't need one.
dev/pcidev.cc:
    Move a bunch of common functionality into the PciDev
dev/platform.hh:
    remove unneeded code
dev/tsunami.cc:
    remove unused param
dev/tsunami_cchip.cc:
    pass platform pointer
dev/tsunami_io.cc:
dev/tsunami_pchip.cc:
dev/uart.cc:
    pass platform variable
dev/uart.hh:
    don't need to keep a platform pointer.  it's in the base class
kern/linux/linux_system.cc:
kern/tru64/tru64_system.cc:
    rename some parameters
sim/builder.cc:
    clean up builder code. use more parameters from the
    config node.  all sections with a type= are now created,
    the old mechanisms no longer work
sim/builder.hh:
    remove some extra variables since they are found in the ConfigNode
sim/main.cc:
    add a quick hack command line argument -X to dump out the
    embedded files.  (probably should be fixed up a little.)
    accept .mpy files
    printing to the streams has to happen after the hierarchy
    is built since we're moving away from param contexts
sim/param.cc:
    add parsing support for ranges
sim/process.cc:
    isValid isn't very useful anymore.  interpret the names
    stdout, stderr, cout, cerr for the file descriptors
sim/pyconfig/SConscript:
    Add Action handlers for creating an embedded python file
    and for creating an embedded C file.

    use these action handlers to embed all objects found in the objects
    tree into the binary along with the importer and the m5config stuff
sim/pyconfig/m5config.py:
    Major changes to the original configuration file generator.  These
    changes largely involve implementing copy-on-write like semantics
    for all of the SimObjects.  Real documentation must be written.
sim/universe.cc:
    Universe becomes a SimObject since we don't really have the notion of
    param contexts in the python code.

--HG--
rename : sim/pyconfig/m5configbase.py => sim/pyconfig/m5config.py
extra : convert_revision : c353453e5beb91c37f15755998fc0d8858c6829a
This commit is contained in:
Nathan Binkert 2005-01-15 04:12:25 -05:00
parent dfecc89150
commit 3ece6ab029
61 changed files with 2128 additions and 1136 deletions

View 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

View 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
{

View 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

View 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

View file

@ -56,10 +56,10 @@
using namespace std;
AlphaConsole::AlphaConsole(const string &name, SimConsole *cons, SimpleDisk *d,
System *system, BaseCPU *cpu, Platform *platform,
System *system, BaseCPU *cpu, Platform *p,
int num_cpus, MemoryController *mmu, Addr a,
HierParams *hier, Bus *bus)
: PioDevice(name), disk(d), console(cons), addr(a)
: PioDevice(name, p), disk(d), console(cons), addr(a)
{
mmu->add_child(this, RangeSize(addr, size));
@ -79,7 +79,7 @@ AlphaConsole::AlphaConsole(const string &name, SimConsole *cons, SimpleDisk *d,
alphaAccess->numCPUs = num_cpus;
alphaAccess->mem_size = system->physmem->size();
alphaAccess->cpuClock = cpu->getFreq() / 1000000;
alphaAccess->intrClockFrequency = platform->intrFrequency();
alphaAccess->intrClockFrequency = platform->intrFrequency();
alphaAccess->diskUnit = 1;
alphaAccess->diskCount = 0;
@ -329,6 +329,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
SimObjectParam<BaseCPU *> cpu;
SimObjectParam<Platform *> platform;
SimObjectParam<Bus*> io_bus;
Param<Tick> pio_latency;
SimObjectParam<HierParams *> hier;
END_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
@ -344,6 +345,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaConsole)
INIT_PARAM(cpu, "Processor"),
INIT_PARAM(platform, "platform"),
INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL),
INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000),
INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
END_INIT_SIM_OBJECT_PARAMS(AlphaConsole)

View 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 */

View 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)

View 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__

View 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)

View 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);

View 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"),

View 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)

View 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()

View file

@ -26,24 +26,26 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __IO_DEVICE_HH__
#define __IO_DEVICE_HH__
#ifndef __DEV_IO_DEVICE_HH__
#define __DEV_IO_DEVICE_HH__
#include "mem/functional_mem/functional_memory.hh"
class BaseInterface;
class Bus;
class HierParams;
class Platform;
template <class BusType> class DMAInterface;
class PioDevice : public FunctionalMemory
{
protected:
Platform *platform;
BaseInterface *pioInterface;
Tick pioLatency;
public:
PioDevice(const std::string &name);
PioDevice(const std::string &name, Platform *p);
virtual ~PioDevice();
};
@ -53,8 +55,8 @@ class DmaDevice : public PioDevice
DMAInterface<Bus> *dmaInterface;
public:
DmaDevice(const std::string &name);
DmaDevice(const std::string &name, Platform *p);
virtual ~DmaDevice();
};
#endif // __IO_DEVICE_HH__
#endif // __DEV_IO_DEVICE_HH__

View 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;

View 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();

View file

@ -48,9 +48,10 @@
using namespace std;
PciConfigAll::PciConfigAll(const string &name, Addr a, MemoryController *mmu,
PciConfigAll::PciConfigAll(const string &name,
Addr a, MemoryController *mmu,
HierParams *hier, Bus *bus, Tick pio_latency)
: PioDevice(name), addr(a)
: PioDevice(name, NULL), addr(a)
{
mmu->add_child(this, RangeSize(addr, size));

View 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),

View 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;

View 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)

View 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));

View 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));

View 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));

View 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));

View 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,

View 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;

View 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;

8
objects/AlphaConsole.mpy Normal file
View file

@ -0,0 +1,8 @@
from Device import PioDevice
simobj AlphaConsole(PioDevice):
cpu = Param.BaseCPU(Super, "Processor")
disk = Param.SimpleDisk("Simple Disk")
num_cpus = Param.Int(1, "Number of CPU's")
sim_console = Param.SimConsole(Super, "The Simulator Console")
system = Param.BaseSystem(Super, "system object")

9
objects/AlphaTLB.mpy Normal file
View file

@ -0,0 +1,9 @@
simobj AlphaTLB(SimObject):
abstract = True
size = Param.Int("TLB size")
simobj AlphaDTB(AlphaTLB):
size = 64
simobj AlphaITB(AlphaTLB):
size = 48

4
objects/BadDevice.mpy Normal file
View file

@ -0,0 +1,4 @@
from Device import PioDevice
simobj BadDevice(PioDevice):
devicename = Param.String("Name of device to error on")

38
objects/BaseCPU.mpy Normal file
View file

@ -0,0 +1,38 @@
simobj BaseCPU(SimObject):
abstract = True
icache = Param.BaseMem(NULL, "L1 instruction cache object")
dcache = Param.BaseMem(NULL, "L1 data cache object")
dtb = Param.AlphaDTB("Data TLB")
itb = Param.AlphaITB("Instruction TLB")
mem = Param.FunctionalMemory("memory")
system = Param.BaseSystem(Super, "system object")
workload = VectorParam.Process("processes to run")
max_insts_all_threads = Param.Counter(0,
"terminate when all threads have reached this inst count")
max_insts_any_thread = Param.Counter(0,
"terminate when any thread reaches this inst count")
max_loads_all_threads = Param.Counter(0,
"terminate when all threads have reached this load count")
max_loads_any_thread = Param.Counter(0,
"terminate when any thread reaches this load count")
defer_registration = Param.Bool(false,
"defer registration with system (for sampling)")
def check(self):
has_workload = self._hasvalue('workload')
has_dtb = self._hasvalue('dtb')
has_itb = self._hasvalue('itb')
has_mem = self._hasvalue('mem')
has_system = self._hasvalue('system')
if has_workload:
self.dtb.disable = True
self.itb.disable = True
self.mem.disable = True
self.system.disable = True
if has_dtb or has_itb or has_mem or has_system:
self.workload.disable = True

30
objects/BaseCache.mpy Normal file
View file

@ -0,0 +1,30 @@
from BaseMem import BaseMem
simobj BaseCache(BaseMem):
adaptive_compression = Param.Bool(false,
"Use an adaptive compression scheme")
assoc = Param.Int("associativity")
block_size = Param.Int("block size in bytes")
compressed_bus = Param.Bool(false,
"This cache connects to a compressed memory")
compression_latency = Param.Int(0,
"Latency in cycles of compression algorithm")
do_copy = Param.Bool(false, "perform fast copies in the cache")
hash_delay = Param.Int(1, "time in cycles of hash access")
in_bus = Param.Bus(NULL, "incoming bus object")
max_miss_count = Param.Counter(0,
"number of misses to handle before calling exit")
mshrs = Param.Int("number of MSHRs (max outstanding requests)")
out_bus = Param.Bus("outgoing bus object")
prioritizeRequests = Param.Bool(false,
"always service demand misses first")
protocol = Param.CoherenceProtocol(NULL, "coherence protocol to use")
repl = Param.Repl(NULL, "replacement policy")
size = Param.Int("capacity in bytes")
store_compressed = Param.Bool(false,
"Store compressed data in the cache")
subblock_size = Param.Int(0,
"Size of subblock in IIC used for compression")
tgts_per_mshr = Param.Int("max number of accesses per MSHR")
trace_addr = Param.Addr(0, "address to trace")
write_buffers = Param.Int(8, "number of write buffers")

14
objects/BaseSystem.mpy Normal file
View file

@ -0,0 +1,14 @@
simobj BaseSystem(SimObject):
abstract = True
memctrl = Param.MemoryController(Super, "memory controller")
physmem = Param.PhysicalMemory(Super, "phsyical memory")
kernel = Param.String("file that contains the kernel code")
console = Param.String("file that contains the console code")
pal = Param.String("file that contains palcode")
readfile = Param.String("", "file to read startup script from")
init_param = Param.UInt64(0, "numerical value to pass into simulator")
boot_osflags = Param.String("a", "boot flags to pass to the kernel")
system_type = Param.UInt64("Type of system we are emulating")
system_rev = Param.UInt64("Revision of system we are emulating")
bin = Param.Bool(false, "is this system binned")
binned_fns = VectorParam.String([], "functions broken down and binned")

5
objects/Bus.mpy Normal file
View file

@ -0,0 +1,5 @@
from BaseHier import BaseHier
simobj Bus(BaseHier):
clock_ratio = Param.Int("ratio of CPU to bus frequency")
width = Param.Int("bus width in bytes")

View file

@ -0,0 +1,5 @@
Coherence = Enum('uni', 'msi', 'mesi', 'mosi', 'moesi')
simobj CoherenceProtocol(SimObject):
do_upgrades = Param.Bool(true, "use upgrade transactions?")
protocol = Param.Coherence("name of coherence protocol")

31
objects/Device.mpy Normal file
View file

@ -0,0 +1,31 @@
from FunctionalMemory import FunctionalMemory
# This device exists only because there are some devices that I don't
# want to have a Platform parameter because it would cause a cycle in
# the C++ that cannot be easily solved.
#
# The real solution to this problem is to pass the ParamXXX structure
# to the constructor, but with the express condition that SimObject
# parameter values are not to be available at construction time. If
# some further configuration must be done, it must be done during the
# initialization phase at which point all SimObject pointers will be
# valid.
simobj FooPioDevice(FunctionalMemory):
abstract = True
type = 'PioDevice'
addr = Param.Addr("Device Address")
mmu = Param.MemoryController(Super, "Memory Controller")
io_bus = Param.Bus(NULL, "The IO Bus to attach to")
pio_latency = Param.Tick(1, "Programmed IO latency in bus cycles")
simobj FooDmaDevice(FooPioDevice):
abstract = True
type = 'DmaDevice'
simobj PioDevice(FooPioDevice):
abstract = True
platform = Param.Platform(Super, "Platform")
simobj DmaDevice(PioDevice):
abstract = True

12
objects/DiskImage.mpy Normal file
View file

@ -0,0 +1,12 @@
simobj DiskImage(SimObject):
abstract = True
image_file = Param.String("disk image file")
read_only = Param.Bool(false, "read only image")
simobj RawDiskImage(DiskImage):
pass
simobj CowDiskImage(DiskImage):
child = Param.DiskImage("child image")
table_size = Param.Int(65536, "initial table size")
image_file = ''

77
objects/Ethernet.mpy Normal file
View file

@ -0,0 +1,77 @@
from Device import DmaDevice
from Pci import PciDevice
simobj EtherInt(SimObject):
abstract = True
peer = Param.EtherInt(NULL, "peer interface")
simobj EtherLink(SimObject):
int1 = Param.EtherInt("interface 1")
int2 = Param.EtherInt("interface 2")
delay = Param.Tick(0, "transmit delay of packets in us")
speed = Param.Tick(100000000, "link speed in bits per second")
dump = Param.EtherDump(NULL, "dump object")
simobj EtherBus(SimObject):
loopback = Param.Bool(true,
"send packet back to the interface from which it came")
dump = Param.EtherDump(NULL, "dump object")
speed = Param.UInt64(100000000, "bus speed in bits per second")
simobj EtherTap(EtherInt):
bufsz = Param.Int(10000, "tap buffer size")
dump = Param.EtherDump(NULL, "dump object")
port = Param.UInt16(3500, "tap port")
simobj EtherDump(SimObject):
file = Param.String("dump file")
simobj EtherDev(DmaDevice):
hardware_address = Param.EthernetAddr(NextEthernetAddr,
"Ethernet Hardware Address")
dma_data_free = Param.Bool(false, "DMA of Data is free")
dma_desc_free = Param.Bool(false, "DMA of Descriptors is free")
dma_read_delay = Param.Tick(0, "fixed delay for dma reads")
dma_read_factor = Param.Tick(0, "multiplier for dma reads")
dma_write_delay = Param.Tick(0, "fixed delay for dma writes")
dma_write_factor = Param.Tick(0, "multiplier for dma writes")
rx_filter = Param.Bool(true, "Enable Receive Filter")
rx_delay = Param.Tick(1000, "Receive Delay")
tx_delay = Param.Tick(1000, "Transmit Delay")
intr_delay = Param.Tick(0, "Interrupt Delay in microseconds")
payload_bus = Param.Bus(NULL, "The IO Bus to attach to for payload")
physmem = Param.PhysicalMemory(Super, "Physical Memory")
tlaser = Param.Turbolaser(Super, "Turbolaser")
simobj NSGigE(PciDevice):
hardware_address = Param.EthernetAddr(NextEthernetAddr,
"Ethernet Hardware Address")
dma_data_free = Param.Bool(false, "DMA of Data is free")
dma_desc_free = Param.Bool(false, "DMA of Descriptors is free")
dma_read_delay = Param.Tick(0, "fixed delay for dma reads")
dma_read_factor = Param.Tick(0, "multiplier for dma reads")
dma_write_delay = Param.Tick(0, "fixed delay for dma writes")
dma_write_factor = Param.Tick(0, "multiplier for dma writes")
rx_filter = Param.Bool(true, "Enable Receive Filter")
rx_delay = Param.Tick(1000, "Receive Delay")
tx_delay = Param.Tick(1000, "Transmit Delay")
rx_fifo_size = Param.Int(131072, "max size in bytes of rxFifo")
tx_fifo_size = Param.Int(131072, "max size in bytes of txFifo")
intr_delay = Param.Tick(0, "Interrupt Delay in microseconds")
payload_bus = Param.Bus(NULL, "The IO Bus to attach to for payload")
physmem = Param.PhysicalMemory(Super, "Physical Memory")
simobj EtherDevInt(EtherInt):
device = Param.EtherDev("Ethernet device of this interface")
simobj NSGigEInt(EtherInt):
device = Param.NSGigE("Ethernet device of this interface")

12
objects/Ide.mpy Normal file
View file

@ -0,0 +1,12 @@
from Pci import PciDevice
IdeID = Enum('master', 'slave')
simobj IdeDisk(SimObject):
delay = Param.Tick(1, "Fixed disk delay in microseconds")
driveID = Param.IdeID('master', "Drive ID")
image = Param.DiskImage("Disk image")
physmem = Param.PhysicalMemory(Super, "Physical memory")
simobj IdeController(PciDevice):
disks = VectorParam.IdeDisk("IDE disks attached to this controller")

2
objects/IntrControl.mpy Normal file
View file

@ -0,0 +1,2 @@
simobj IntrControl(SimObject):
cpu = Param.BaseCPU(Super, "the cpu")

20
objects/MemTest.mpy Normal file
View file

@ -0,0 +1,20 @@
simobj MemTest(SimObject):
cache = Param.BaseCache("L1 cache")
check_mem = Param.FunctionalMemory("check memory")
main_mem = Param.FunctionalMemory("hierarchical memory")
max_loads_all_threads = Param.Counter(0,
"terminate when all threads have reached this load count")
max_loads_any_thread = Param.Counter(0,
"terminate when any thread reaches this load count")
memory_size = Param.Int(65536, "memory size")
percent_copies = Param.Percent(0, "target copy percentage")
percent_dest_unaligned = Param.Percent(50,
"percent of copy dest address that are unaligned")
percent_reads = Param.Percent(65, "target read percentage")
percent_source_unaligned = Param.Percent(50,
"percent of copy source address that are unaligned")
percent_uncacheable = Param.Percent(10,
"target uncacheable percentage")
progress_interval = Param.Counter(1000000,
"progress report interval (in accesses)")
trace_addr = Param.Addr(0, "address to trace")

50
objects/Pci.mpy Normal file
View file

@ -0,0 +1,50 @@
from Device import FooPioDevice, DmaDevice
simobj PciConfigData(FooPioDevice):
addr = 0xffffffffffffffff
VendorID = Param.UInt16("Vendor ID")
DeviceID = Param.UInt16("Device ID")
Command = Param.UInt16(0, "Command")
Status = Param.UInt16(0, "Status")
Revision = Param.UInt8(0, "Device")
ProgIF = Param.UInt8(0, "Programming Interface")
SubClassCode = Param.UInt8(0, "Sub-Class Code")
ClassCode = Param.UInt8(0, "Class Code")
CacheLineSize = Param.UInt8(0, "System Cacheline Size")
LatencyTimer = Param.UInt8(0, "PCI Latency Timer")
HeaderType = Param.UInt8(0, "PCI Header Type")
BIST = Param.UInt8(0, "Built In Self Test")
BAR0 = Param.UInt32(0x00, "Base Address Register 0")
BAR1 = Param.UInt32(0x00, "Base Address Register 1")
BAR2 = Param.UInt32(0x00, "Base Address Register 2")
BAR3 = Param.UInt32(0x00, "Base Address Register 3")
BAR4 = Param.UInt32(0x00, "Base Address Register 4")
BAR5 = Param.UInt32(0x00, "Base Address Register 5")
BAR0Size = Param.UInt32(0, "Base Address Register 0 Size")
BAR1Size = Param.UInt32(0, "Base Address Register 1 Size")
BAR2Size = Param.UInt32(0, "Base Address Register 2 Size")
BAR3Size = Param.UInt32(0, "Base Address Register 3 Size")
BAR4Size = Param.UInt32(0, "Base Address Register 4 Size")
BAR5Size = Param.UInt32(0, "Base Address Register 5 Size")
CardbusCIS = Param.UInt32(0x00, "Cardbus Card Information Structure")
SubsystemID = Param.UInt16(0x00, "Subsystem ID")
SubsystemVendorID = Param.UInt16(0x00, "Subsystem Vendor ID")
ExpansionROM = Param.UInt32(0x00, "Expansion ROM Base Address")
InterruptLine = Param.UInt8(0x00, "Interrupt Line")
InterruptPin = Param.UInt8(0x00, "Interrupt Pin")
MaximumLatency = Param.UInt8(0x00, "Maximum Latency")
MinimumGrant = Param.UInt8(0x00, "Minimum Grant")
simobj PciConfigAll(FooPioDevice):
pass
simobj PciDevice(DmaDevice):
abstract = True
pci_bus = Param.Int("PCI bus")
pci_dev = Param.Int("PCI device number")
pci_func = Param.Int("PCI function code")
configdata = Param.PciConfigData(Super, "PCI Config data")
configspace = Param.PciConfigAll(Super, "PCI Configspace")
addr = 0xffffffffffffffff

View file

@ -0,0 +1,6 @@
from FunctionalMemory import FunctionalMemory
simobj PhysicalMemory(FunctionalMemory):
range = Param.AddrRange("Device Address")
file = Param.String('', "memory mapped file")
mmu = Param.MemoryController(Super, "Memory Controller")

4
objects/Platform.mpy Normal file
View file

@ -0,0 +1,4 @@
simobj Platform(SimObject):
abstract = True
interrupt_frequency = Param.Tick(1200, "frequency of interrupts")
intrctrl = Param.IntrControl(Super, "interrupt controller")

12
objects/Process.mpy Normal file
View file

@ -0,0 +1,12 @@
simobj Process(SimObject):
abstract = True
output = Param.String('cout', 'filename for stdout/stderr')
simobj LiveProcess(Process):
cmd = VectorParam.String("command line (executable plus arguments)")
env = VectorParam.String('', "environment settings")
input = Param.String('cin', "filename for stdin")
simobj EioProcess(Process):
chkpt = Param.String('', "EIO checkpoint file name (optional)")
file = Param.String("EIO trace file name")

7
objects/Repl.mpy Normal file
View file

@ -0,0 +1,7 @@
simobj Repl(SimObject):
abstract = True
simobj GenRepl(Repl):
fresh_res = Param.Int("associativity")
num_pools = Param.Int("capacity in bytes")
pool_res = Param.Int("block size in bytes")

9
objects/Root.mpy Normal file
View file

@ -0,0 +1,9 @@
from HierParams import HierParams
simobj Root(SimObject):
frequency = Param.Tick(200000000, "tick frequency")
output_dir = Param.String('.', "directory to output data to")
output_file = Param.String('cout', "file to dump simulator output to")
config_output_file = Param.String('m5config.out',
"file to dump simulator config to")
full_system = Param.Bool("Full system simulation?")
hier = HierParams(do_data = false, do_events = true)

9
objects/SimConsole.mpy Normal file
View file

@ -0,0 +1,9 @@
simobj ConsoleListener(SimObject):
port = Param.UInt16(3456, "listen port")
simobj SimConsole(SimObject):
append_name = Param.Bool(true, "append name() to filename")
intr_control = Param.IntrControl(Super, "interrupt controller")
listener = Param.ConsoleListener("console listener")
number = Param.Int(0, "console number")
output = Param.String("", "file to dump output to")

3
objects/SimpleDisk.mpy Normal file
View file

@ -0,0 +1,3 @@
simobj SimpleDisk(SimObject):
disk = Param.DiskImage("Disk Image")
physmem = Param.PhysicalMemory(Super, "Physical Memory")

21
objects/Tsunami.mpy Normal file
View file

@ -0,0 +1,21 @@
from Device import FooPioDevice
from Platform import Platform
simobj Tsunami(Platform):
pciconfig = Param.PciConfigAll("PCI configuration")
system = Param.BaseSystem(Super, "system")
interrupt_frequency = Param.Int(1024, "frequency of interrupts")
simobj TsunamiCChip(FooPioDevice):
tsunami = Param.Tsunami(Super, "Tsunami")
simobj TsunamiFake(FooPioDevice):
pass
simobj TsunamiIO(FooPioDevice):
time = Param.UInt64(1136073600,
"System time to use (0 for actual time, default is 1/1/06)")
tsunami = Param.Tsunami(Super, "Tsunami")
simobj TsunamiPChip(FooPioDevice):
tsunami = Param.Tsunami(Super, "Tsunami")

5
objects/Uart.mpy Normal file
View file

@ -0,0 +1,5 @@
from Device import PioDevice
simobj Uart(PioDevice):
console = Param.SimConsole(Super, "The console")
size = Param.Addr(0x8, "Device size")

View file

@ -39,14 +39,9 @@
using namespace std;
SimObjectBuilder::SimObjectBuilder(const string &_configClass,
const string &_instanceName,
ConfigNode *_configNode,
const string &_simObjClassName)
: ParamContext(_configClass, NoAutoInit),
instanceName(_instanceName),
configNode(_configNode),
simObjClassName(_simObjClassName)
SimObjectBuilder::SimObjectBuilder(ConfigNode *_configNode)
: ParamContext(_configNode->getPath(), NoAutoInit),
configNode(_configNode)
{
}
@ -72,13 +67,8 @@ SimObjectBuilder::parseParams(IniFile &iniFile)
for (i = paramList->begin(); i != paramList->end(); ++i) {
string string_value;
if (iniFile.findDefault(instanceName, (*i)->name, string_value)) {
if (iniFile.find(iniSection, (*i)->name, string_value))
(*i)->parse(string_value);
}
else if (iniFile.findDefault(iniSection, (*i)->name, string_value)) {
(*i)->parse(string_value);
}
}
}
@ -86,9 +76,8 @@ SimObjectBuilder::parseParams(IniFile &iniFile)
void
SimObjectBuilder::printErrorProlog(ostream &os)
{
os << "Error creating object '" << getInstanceName()
<< "' of type '" << simObjClassName
<< "', section '" << iniSection << "':" << endl;
ccprintf(os, "Error creating object '%s' of type '%s':\n",
iniSection, configNode->getType());
}
@ -111,11 +100,7 @@ SimObjectClass::SimObjectClass(const string &className, CreateFunc createFunc)
classMap = new map<string,SimObjectClass::CreateFunc>();
if ((*classMap)[className])
{
cerr << "Error: simulation object class " << className << " redefined"
<< endl;
fatal("");
}
panic("Error: simulation object class '%s' redefined\n", className);
// add className --> createFunc to class map
(*classMap)[className] = createFunc;
@ -125,35 +110,20 @@ SimObjectClass::SimObjectClass(const string &className, CreateFunc createFunc)
//
//
SimObject *
SimObjectClass::createObject(IniFile &configDB,
const string &configClassName,
const string &objName,
ConfigNode *configNode)
SimObjectClass::createObject(IniFile &configDB, ConfigNode *configNode)
{
// find simulation object class name from configuration class
// (specified by 'type=' parameter)
string simObjClassName;
if (!configNode->find("type", simObjClassName)) {
cerr << "Configuration class '" << configClassName << "' not found."
<< endl;
abort();
}
const string &type = configNode->getType();
// look up className to get appropriate createFunc
if (classMap->find(simObjClassName) == classMap->end()) {
cerr << "Simulator object class '" << simObjClassName << "' not found."
<< endl;
abort();
}
if (classMap->find(type) == classMap->end())
panic("Simulator object type '%s' not found.\n", type);
CreateFunc createFunc = (*classMap)[simObjClassName];
CreateFunc createFunc = (*classMap)[type];
// call createFunc with config hierarchy node to get object
// builder instance (context with parameters for object creation)
SimObjectBuilder *objectBuilder = (*createFunc)(configClassName,
objName, configNode,
simObjClassName);
SimObjectBuilder *objectBuilder = (*createFunc)(configNode);
assert(objectBuilder != NULL);
@ -167,10 +137,10 @@ SimObjectClass::createObject(IniFile &configDB,
// echo object parameters to stats file (for documenting the
// config used to generate the associated stats)
*configStream << "[" << object->name() << "]" << endl;
*configStream << "type=" << simObjClassName << endl;
ccprintf(*configStream, "[%s]\n", object->name());
ccprintf(*configStream, "type=%s\n", type);
objectBuilder->showParams(*configStream);
*configStream << endl;
ccprintf(*configStream, "\n");
// done with the SimObjectBuilder now
delete objectBuilder;
@ -194,7 +164,7 @@ SimObjectClass::describeAllClasses(ostream &os)
os << "[" << className << "]\n";
// create dummy object builder just to instantiate parameters
SimObjectBuilder *objectBuilder = (*createFunc)("", "", NULL, "");
SimObjectBuilder *objectBuilder = (*createFunc)(NULL);
// now get the object builder to describe ite params
objectBuilder->describeParams(os);

View 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, \

View file

@ -34,10 +34,12 @@
#include <stdlib.h>
#include <signal.h>
#include <list>
#include <string>
#include <vector>
#include "base/copyright.hh"
#include "base/embedfile.hh"
#include "base/inifile.hh"
#include "base/misc.hh"
#include "base/pollevent.hh"
@ -254,6 +256,21 @@ main(int argc, char **argv)
// switch on second char
switch (arg_str[1]) {
case 'X': {
list<EmbedFile> lst;
EmbedMap::all(lst);
list<EmbedFile>::iterator i = lst.begin();
list<EmbedFile>::iterator end = lst.end();
while (i != end) {
cprintf("Embedded File: %s\n", i->name);
cout.write(i->data, i->length);
++i;
}
return 0;
}
case 'h':
// -h: show help
showLongHelp(cerr);
@ -311,7 +328,7 @@ main(int argc, char **argv)
cprintf("Error processing file %s\n", filename);
exit(1);
}
} else if (ext == ".py") {
} else if (ext == ".py" || ext == ".mpy") {
if (!loadPythonConfig(filename, &simConfigDB)) {
cprintf("Error processing file %s\n", filename);
exit(1);
@ -335,6 +352,11 @@ main(int argc, char **argv)
// the stat file name is set via a .ini param... thus it just got
// opened above during ParamContext::checkAllContexts().
// Now process the configuration hierarchy and create the SimObjects.
ConfigHierarchy configHierarchy(simConfigDB);
configHierarchy.build();
configHierarchy.createSimObjects();
// Print hello message to stats file if it's actually a file. If
// it's not (i.e. it's cout or cerr) then we already did it above.
if (outputStream != &cout && outputStream != &cerr)
@ -344,11 +366,6 @@ main(int argc, char **argv)
echoCommandLine(argc, argv, *outputStream);
ParamContext::showAllContexts(*configStream);
// Now process the configuration hierarchy and create the SimObjects.
ConfigHierarchy configHierarchy(simConfigDB);
configHierarchy.build();
configHierarchy.createSimObjects();
// Do a second pass to finish initializing the sim objects
SimObject::initAll();

View file

@ -27,21 +27,21 @@
*/
#include <algorithm>
#include <cassert>
#include <cstdio>
#include <list>
#include <string>
#include <vector>
#include <stdio.h> // for sscanf()
#include <assert.h>
#include "sim/param.hh"
#include "sim/sim_object.hh"
#include "base/inifile.hh"
#include "sim/configfile.hh"
#include "sim/config_node.hh"
#include "base/misc.hh"
#include "base/range.hh"
#include "base/str.hh"
#include "base/trace.hh"
#include "sim/config_node.hh"
#include "sim/configfile.hh"
#include "sim/param.hh"
#include "sim/sim_object.hh"
using namespace std;
@ -180,6 +180,22 @@ parseParam(const string &s, string &value)
return true;
}
template <>
bool
parseParam(const string &s, Range<uint32_t> &value)
{
value = s;
return value.valid();
}
template <>
bool
parseParam(const string &s, Range<uint64_t> &value)
{
value = s;
return value.valid();
}
//
// End of parseParam/showParam definitions. Now we move on to
// incorporate them into the Param/VectorParam parse() and showValue()
@ -310,6 +326,9 @@ INSTANTIATE_PARAM_TEMPLATES(double, "double")
INSTANTIATE_PARAM_TEMPLATES(bool, "bool")
INSTANTIATE_PARAM_TEMPLATES(string, "string")
INSTANTIATE_PARAM_TEMPLATES(Range<uint64_t>, "uint64 range")
INSTANTIATE_PARAM_TEMPLATES(Range<uint32_t>, "uint32 range")
#undef INSTANTIATE_PARAM_TEMPLATES
//
@ -602,9 +621,8 @@ ParamContext::parseParams(IniFile &iniFile)
for (i = getParamList()->begin(); i != getParamList()->end(); ++i) {
string string_value;
if (iniFile.findDefault(iniSection, (*i)->name, string_value)) {
if (iniFile.find(iniSection, (*i)->name, string_value))
(*i)->parse(string_value);
}
}
}
@ -680,18 +698,8 @@ ParamContext::printErrorProlog(ostream &os)
// SimObjectBuilder objects, which return non-NULL for configNode()).
//
SimObject *
ParamContext::resolveSimObject(const string &_name)
ParamContext::resolveSimObject(const string &name)
{
// look for a colon
string::size_type i = _name.find(':');
string name = _name;
if (i != string::npos) {
// colon found: local object
// add as child to current node and create it
name = _name.substr(0, i);
string objConfigClassName = _name.substr(i + 1);
getConfigNode()->addChild(name, objConfigClassName);
}
ConfigNode *n = getConfigNode();
return n ? n->resolveSimObject(name) : NULL;
}

View file

@ -397,19 +397,29 @@ END_INIT_SIM_OBJECT_PARAMS(LiveProcess)
CREATE_SIM_OBJECT(LiveProcess)
{
// initialize file descriptors to default: same as simulator
int stdin_fd = input.isValid() ? Process::openInputFile(input) : 0;
int stdout_fd = output.isValid() ? Process::openOutputFile(output) : 1;
int stderr_fd = output.isValid() ? stdout_fd : 2;
string in = input;
string out = output;
// dummy for default env
vector<string> null_vec;
// initialize file descriptors to default: same as simulator
int stdin_fd, stdout_fd, stderr_fd;
if (in == "stdin" || in == "cin")
stdin_fd = STDIN_FILENO;
else
stdin_fd = Process::openInputFile(input);
if (out == "stdout" || out == "cout")
stdout_fd = STDOUT_FILENO;
else if (out == "stderr" || out == "cerr")
stdout_fd = STDERR_FILENO;
else
stdout_fd = Process::openOutputFile(out);
stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO;
return LiveProcess::create(getInstanceName(),
stdin_fd, stdout_fd, stderr_fd,
cmd,
env.isValid() ? env : null_vec);
cmd, env);
}
REGISTER_SIM_OBJECT("LiveProcess", LiveProcess)

View 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
@ -26,25 +26,164 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import os
import os, os.path, re
Import('env', 'obj_desc_files')
def WriteEmbeddedPyFile(target, source, path, name, ext):
if isinstance(source, str):
source = file(source, 'r')
my_obj_desc_files = map(lambda x: '../../' + x, obj_desc_files)
if isinstance(target, str):
target = file(target, 'w')
env.Command('m5odescs.py', my_obj_desc_files,
'$TARGET.srcdir/load_odescs.py $_CPPDEFFLAGS $SOURCES $TARGET')
print >>target, "AddModule(%s, %s, %s, '''\\" % (`path`, `name`, `ext`)
# Python modules to encapsulate
string_module_bases = Split('m5config m5configbase m5odescs')
string_modules = map(lambda x: x + '_as_string.py', string_module_bases)
for line in source:
line = line
# escape existing backslashes
line = line.replace('\\', '\\\\')
# escape existing triple quotes
line = line.replace("'''", r"\'\'\'")
for m in string_module_bases:
env.Command(m + '_as_string.py', m + '.py',
'$TARGET.srcdir/make_string_module.py $SOURCE $TARGET')
print >>target, line,
embedded_py_files = Split('string_importer.py') + string_modules
print >>target, "''')"
print >>target
env.Command('code.cc', embedded_py_files,
'$TARGET.srcdir/make_c_file.py pyconfig_code $SOURCES $TARGET')
def WriteCFile(target, source, name):
if isinstance(source, str):
source = file(source, 'r')
if isinstance(target, str):
target = file(target, 'w')
print >>target, 'const char %s_string[] = {' % name
count = 0
from array import array
try:
while True:
foo = array('B')
foo.fromfile(source, 10000)
l = [ str(i) for i in foo.tolist() ]
count += len(l)
for i in xrange(0,9999,20):
print >>target, ','.join(l[i:i+20]) + ','
except EOFError:
l = [ str(i) for i in foo.tolist() ]
count += len(l)
for i in xrange(0,len(l),20):
print >>target, ','.join(l[i:i+20]) + ','
print >>target, ','.join(l[i:]) + ','
print >>target, '};'
print >>target, 'const int %s_length = %d;' % (name, count)
print >>target
def splitpath(path):
dir,file = os.path.split(path)
path = []
assert(file)
while dir:
dir,base = os.path.split(dir)
path.insert(0, base)
return path, file
Import('env')
def MakeEmbeddedPyFile(target, source, env):
target = file(str(target[0]), 'w')
tree = {}
for src in source:
src = str(src)
path,pyfile = splitpath(src)
node = tree
for dir in path:
if not node.has_key(dir):
node[dir] = { }
node = node[dir]
name,ext = pyfile.split('.')
if name == '__init__':
node['.hasinit'] = True
node[pyfile] = (src,name,ext)
done = False
while not done:
done = True
for name,entry in tree.items():
if not isinstance(entry, dict): continue
if entry.has_key('.hasinit'): continue
done = False
del tree[name]
for key,val in entry.iteritems():
if tree.has_key(key):
raise NameError, \
"dir already has %s can't add it again" % key
tree[key] = val
files = []
def populate(node, path = []):
names = node.keys()
names.sort()
for name in names:
if name == '.hasinit':
continue
entry = node[name]
if isinstance(entry, dict):
if not entry.has_key('.hasinit'):
raise NameError, 'package directory missing __init__.py'
populate(entry, path + [ name ])
else:
pyfile,name,ext = entry
files.append((pyfile, path, name, ext))
populate(tree)
for pyfile, path, name, ext in files:
WriteEmbeddedPyFile(target, pyfile, path, name, ext)
CFileCounter = 0
def MakePythonCFile(target, source, env):
global CFileCounter
target = file(str(target[0]), 'w')
print >>target, '''\
#include "base/embedfile.hh"
namespace {
'''
for src in source:
src = str(src)
fname = os.path.basename(src)
name = 'embedded_file%d' % CFileCounter
CFileCounter += 1
WriteCFile(target, src, name)
print >>target, '''\
EmbedMap %(name)s("%(fname)s",
%(name)s_string, %(name)s_length);
''' % locals()
print >>target, '''\
/* namespace */ }
'''
embedded_py_files = ['m5config.py']
objpath = os.path.join(env['SRCDIR'], 'objects')
for root, dirs, files in os.walk(objpath, topdown=True):
for i,dir in enumerate(dirs):
if dir == 'SCCS':
del dirs[i]
break
assert(root.startswith(objpath))
for f in files:
if f.endswith('.mpy') or f.endswith('.py'):
embedded_py_files.append(os.path.join(root, f))
embedfile_hh = os.path.join(env['SRCDIR'], 'base/embedfile.hh')
env.Depends('embedded_py.cc', embedfile_hh)
env.Command('embedded_py.py', embedded_py_files, MakeEmbeddedPyFile)
env.Command('embedded_py.cc', ['importer.py', 'embedded_py.py'],
MakePythonCFile)

1250
sim/pyconfig/m5config.py Normal file

File diff suppressed because it is too large Load diff

View file

@ -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()

View file

@ -36,9 +36,10 @@
#include <vector>
#include "base/misc.hh"
#include "sim/universe.hh"
#include "sim/builder.hh"
#include "sim/host.hh"
#include "sim/param.hh"
#include "sim/sim_object.hh"
#include "sim/universe.hh"
using namespace std;
@ -53,60 +54,13 @@ string outputDirectory;
ostream *outputStream;
ostream *configStream;
class UniverseParamContext : public ParamContext
// Dummy Object
class Root : public SimObject
{
public:
UniverseParamContext(const string &is)
: ParamContext(is, OutputInitPhase) {}
void checkParams();
Root(const std::string &name) : SimObject(name) {}
};
UniverseParamContext universe("Universe");
Param<Tick> universe_freq(&universe, "frequency", "tick frequency",
200000000);
Param<string> universe_output_dir(&universe, "output_dir",
"directory to output data to",
".");
Param<string> universe_output_file(&universe, "output_file",
"file to dump simulator output to",
"cout");
Param<string> universe_config_output_file(&universe, "config_output_file",
"file to dump simulator config to",
"m5config.out");
void
UniverseParamContext::checkParams()
{
ticksPerSecond = universe_freq;
double freq = double(ticksPerSecond);
__ticksPerMS = freq / 1.0e3;
__ticksPerUS = freq / 1.0e6;
__ticksPerNS = freq / 1.0e9;
__ticksPerPS = freq / 1.0e12;
if (universe_output_dir.isValid()) {
outputDirectory = universe_output_dir;
// guarantee that directory ends with a '/'
if (outputDirectory[outputDirectory.size() - 1] != '/')
outputDirectory += "/";
if (mkdir(outputDirectory.c_str(), 0777) < 0) {
if (errno != EEXIST) {
panic("%s\ncould not make output directory: %s\n",
strerror(errno), outputDirectory);
}
}
}
outputStream = makeOutputStream(universe_output_file);
configStream = universe_config_output_file.isValid()
? makeOutputStream(universe_config_output_file)
: outputStream;
}
Root *root = NULL;
std::ostream *
makeOutputStream(std::string &name)
@ -146,4 +100,70 @@ closeOutputStream(std::ostream *os)
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Root)
Param<bool> full_system;
Param<Tick> frequency;
Param<string> output_dir;
Param<string> output_file;
Param<string> config_output_file;
END_DECLARE_SIM_OBJECT_PARAMS(Root)
BEGIN_INIT_SIM_OBJECT_PARAMS(Root)
INIT_PARAM_DFLT(full_system, "full system simulation", true),
INIT_PARAM_DFLT(frequency, "tick frequency", 200000000),
INIT_PARAM_DFLT(output_dir, "directory to output data to", "."),
INIT_PARAM_DFLT(output_file, "file to dump simulator output to", "cout"),
INIT_PARAM_DFLT(config_output_file, "file to dump simulator config to",
"m5config.out")
END_INIT_SIM_OBJECT_PARAMS(Root)
CREATE_SIM_OBJECT(Root)
{
#ifdef FULL_SYSTEM
if (!bool(full_system))
panic("FULL_SYSTEM compiled and configuration not full_system");
#else
if (bool(full_system))
panic("FULL_SYSTEM not compiled but configuration is full_system");
#endif
if (root)
panic("only one root object allowed!");
root = new Root(getInstanceName());
ticksPerSecond = frequency;
double freq = double(ticksPerSecond);
__ticksPerMS = freq / 1.0e3;
__ticksPerUS = freq / 1.0e6;
__ticksPerNS = freq / 1.0e9;
__ticksPerPS = freq / 1.0e12;
if (output_dir.isValid()) {
outputDirectory = output_dir;
// guarantee that directory ends with a '/'
if (outputDirectory[outputDirectory.size() - 1] != '/')
outputDirectory += "/";
if (mkdir(outputDirectory.c_str(), 0777) < 0) {
if (errno != EEXIST) {
panic("%s\ncould not make output directory: %s\n",
strerror(errno), outputDirectory);
}
}
}
outputStream = makeOutputStream(output_file);
configStream = config_output_file.isValid()
? makeOutputStream(config_output_file)
: outputStream;
return root;
}
REGISTER_SIM_OBJECT("Root", Root)

56
test/genini.py Normal file
View file

@ -0,0 +1,56 @@
# Copyright (c) 2005 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import getopt, os, sys
sys.path.append('..')
sys.path.append('../configs/kernel')
sys.path.append('../sim/pyconfig')
from importer import mpy_exec
from m5config import *
try:
opts, args = getopt.getopt(sys.argv[1:], '-E:')
for o,a in opts:
if o == '-E':
offset = a.find('=')
if offset == -1:
name = a
value = True
else:
name = a[:offset]
value = a[offset+1:]
env[name] = value
except getopt.GetoptError:
sys.exit('Improper Usage')
for arg in args:
mpy_exec(file(arg, 'r'), globals())
if globals().has_key('root') and isinstance(root, type) \
and issubclass(root, Root):
instantiate(root)