diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/SConscript | 1 | ||||
-rw-r--r-- | src/arch/sparc/system.cc | 42 | ||||
-rw-r--r-- | src/arch/sparc/system.hh | 9 | ||||
-rw-r--r-- | src/base/loader/object_file.cc | 6 | ||||
-rw-r--r-- | src/base/loader/object_file.hh | 4 | ||||
-rw-r--r-- | src/base/loader/raw_object.cc | 72 | ||||
-rw-r--r-- | src/base/loader/raw_object.hh | 53 | ||||
-rw-r--r-- | src/cpu/exetrace.cc | 111 | ||||
-rw-r--r-- | src/cpu/m5legion_interface.h | 4 | ||||
-rw-r--r-- | src/mem/physical.cc | 4 | ||||
-rw-r--r-- | src/python/m5/objects/BaseCPU.py | 13 | ||||
-rw-r--r-- | src/python/m5/objects/SparcTLB.py | 14 | ||||
-rw-r--r-- | src/python/m5/objects/System.py | 19 | ||||
-rw-r--r-- | src/python/m5/params.py | 5 |
14 files changed, 290 insertions, 67 deletions
diff --git a/src/SConscript b/src/SConscript index 6d7783113..44bcb5320 100644 --- a/src/SConscript +++ b/src/SConscript @@ -74,6 +74,7 @@ base_sources = Split(''' base/loader/aout_object.cc base/loader/ecoff_object.cc base/loader/elf_object.cc + base/loader/raw_object.cc base/loader/object_file.cc base/loader/symtab.cc base/stats/events.cc diff --git a/src/arch/sparc/system.cc b/src/arch/sparc/system.cc index 952ac2deb..4e907f002 100644 --- a/src/arch/sparc/system.cc +++ b/src/arch/sparc/system.cc @@ -42,39 +42,46 @@ using namespace BigEndianGuest; SparcSystem::SparcSystem(Params *p) - : System(p), sysTick(0) + : System(p), sysTick(0),funcRomPort(p->name + "-fport") { resetSymtab = new SymbolTable; hypervisorSymtab = new SymbolTable; openbootSymtab = new SymbolTable; + Port *rom_port; + rom_port = params()->rom->getPort("functional"); + funcRomPort.setPeer(rom_port); + rom_port->setPeer(&funcRomPort); /** * Load the boot code, and hypervisor into memory. */ // Read the reset binary - reset = createObjectFile(params()->reset_bin); + reset = createObjectFile(params()->reset_bin, true); if (reset == NULL) fatal("Could not load reset binary %s", params()->reset_bin); // Read the openboot binary - openboot = createObjectFile(params()->openboot_bin); + openboot = createObjectFile(params()->openboot_bin, true); if (openboot == NULL) fatal("Could not load openboot bianry %s", params()->openboot_bin); // Read the hypervisor binary - hypervisor = createObjectFile(params()->hypervisor_bin); + hypervisor = createObjectFile(params()->hypervisor_bin, true); if (hypervisor == NULL) fatal("Could not load hypervisor binary %s", params()->hypervisor_bin); // Load reset binary into memory - reset->loadSections(&functionalPort, SparcISA::LoadAddrMask); + reset->setTextBase(params()->reset_addr); + reset->loadSections(&funcRomPort); // Load the openboot binary - openboot->loadSections(&functionalPort, SparcISA::LoadAddrMask); + openboot->setTextBase(params()->openboot_addr); + openboot->loadSections(&funcRomPort); // Load the hypervisor binary - hypervisor->loadSections(&functionalPort, SparcISA::LoadAddrMask); + hypervisor->setTextBase(params()->hypervisor_addr); + hypervisor->loadSections(&funcRomPort); // load symbols if (!reset->loadGlobalSymbols(resetSymtab)) @@ -141,8 +148,13 @@ SparcSystem::unserialize(Checkpoint *cp, const std::string §ion) BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcSystem) SimObjectParam<PhysicalMemory *> physmem; + SimObjectParam<PhysicalMemory *> rom; SimpleEnumParam<System::MemoryMode> mem_mode; + Param<Addr> reset_addr; + Param<Addr> hypervisor_addr; + Param<Addr> openboot_addr; + Param<std::string> kernel; Param<std::string> reset_bin; Param<std::string> hypervisor_bin; @@ -150,8 +162,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcSystem) Param<Tick> boot_cpu_frequency; Param<std::string> boot_osflags; - Param<uint64_t> system_type; - Param<uint64_t> system_rev; Param<std::string> readfile; Param<unsigned int> init_param; @@ -160,8 +170,14 @@ END_DECLARE_SIM_OBJECT_PARAMS(SparcSystem) BEGIN_INIT_SIM_OBJECT_PARAMS(SparcSystem) INIT_PARAM(physmem, "phsyical memory"), + INIT_PARAM(rom, "ROM for boot code"), INIT_ENUM_PARAM(mem_mode, "Memory Mode, (1=atomic, 2=timing)", System::MemoryModeStrings), + + INIT_PARAM(reset_addr, "Address that reset should be loaded at"), + INIT_PARAM(hypervisor_addr, "Address that hypervisor should be loaded at"), + INIT_PARAM(openboot_addr, "Address that openboot should be loaded at"), + INIT_PARAM(kernel, "file that contains the kernel code"), INIT_PARAM(reset_bin, "file that contains the reset code"), INIT_PARAM(hypervisor_bin, "file that contains the hypervisor code"), @@ -169,8 +185,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SparcSystem) INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"), INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot", "a"), - INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34), - INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10), INIT_PARAM_DFLT(readfile, "file to read startup script from", ""), INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0) @@ -182,16 +196,18 @@ CREATE_SIM_OBJECT(SparcSystem) p->name = getInstanceName(); p->boot_cpu_frequency = boot_cpu_frequency; p->physmem = physmem; + p->rom = rom; p->mem_mode = mem_mode; p->kernel_path = kernel; + p->reset_addr = reset_addr; + p->hypervisor_addr = hypervisor_addr; + p->openboot_addr = openboot_addr; p->reset_bin = reset_bin; p->hypervisor_bin = hypervisor_bin; p->openboot_bin = openboot_bin; p->boot_osflags = boot_osflags; p->init_param = init_param; p->readfile = readfile; - p->system_type = system_type; - p->system_rev = system_rev; return new SparcSystem(p); } diff --git a/src/arch/sparc/system.hh b/src/arch/sparc/system.hh index 0b79eda38..9cf3bb568 100644 --- a/src/arch/sparc/system.hh +++ b/src/arch/sparc/system.hh @@ -45,12 +45,14 @@ class SparcSystem : public System public: struct Params : public System::Params { + PhysicalMemory *rom; + Addr reset_addr; + Addr hypervisor_addr; + Addr openboot_addr; std::string reset_bin; std::string hypervisor_bin; std::string openboot_bin; std::string boot_osflags; - uint64_t system_type; - uint64_t system_rev; }; SparcSystem(Params *p); @@ -87,6 +89,9 @@ class SparcSystem : public System /** System Tick for syncronized tick across all cpus. */ Tick sysTick; + /** functional port to ROM */ + FunctionalPort funcRomPort; + protected: const Params *params() const { return (const Params *)_params; } diff --git a/src/base/loader/object_file.cc b/src/base/loader/object_file.cc index 42c74d418..ad2cd34ba 100644 --- a/src/base/loader/object_file.cc +++ b/src/base/loader/object_file.cc @@ -45,6 +45,7 @@ #include "base/loader/ecoff_object.hh" #include "base/loader/aout_object.hh" #include "base/loader/elf_object.hh" +#include "base/loader/raw_object.hh" #include "mem/translating_port.hh" @@ -107,7 +108,7 @@ ObjectFile::close() ObjectFile * -createObjectFile(const string &fname) +createObjectFile(const string &fname, bool raw) { // open the file int fd = open(fname.c_str(), O_RDONLY); @@ -141,6 +142,9 @@ createObjectFile(const string &fname) return fileObj; } + if (raw) + return RawObject::tryFile(fname, fd, len, fileData); + // don't know what it is close(fd); munmap(fileData, len); diff --git a/src/base/loader/object_file.hh b/src/base/loader/object_file.hh index 79fa394c6..64085185d 100644 --- a/src/base/loader/object_file.hh +++ b/src/base/loader/object_file.hh @@ -114,9 +114,11 @@ class ObjectFile size_t textSize() const { return text.size; } size_t dataSize() const { return data.size; } size_t bssSize() const { return bss.size; } + + void setTextBase(Addr a) { text.baseAddr = a; } }; -ObjectFile *createObjectFile(const std::string &fname); +ObjectFile *createObjectFile(const std::string &fname, bool raw = false); #endif // __OBJECT_FILE_HH__ diff --git a/src/base/loader/raw_object.cc b/src/base/loader/raw_object.cc new file mode 100644 index 000000000..79ddb81fe --- /dev/null +++ b/src/base/loader/raw_object.cc @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2006 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. + * + * Authors: Steve Reinhardt + */ + +#include "base/loader/raw_object.hh" +#include "base/trace.hh" + +ObjectFile * +RawObject::tryFile(const std::string &fname, int fd, size_t len, uint8_t *data) +{ + return new RawObject(fname, fd, len, data, ObjectFile::UnknownArch, + ObjectFile::UnknownOpSys); +} + +RawObject::RawObject(const std::string &_filename, int _fd, size_t _len, + uint8_t *_data, Arch _arch, OpSys _opSys) + : ObjectFile(_filename, _fd, _len, _data, _arch, _opSys) +{ + text.baseAddr = 0; + text.size = len; + text.fileImage = fileData; + + data.baseAddr = 0; + data.size = 0; + data.fileImage = NULL; + + bss.baseAddr = 0; + bss.size = 0; + bss.fileImage = NULL; + + DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n", + text.baseAddr, text.size, data.baseAddr, data.size, + bss.baseAddr, bss.size); +} + +bool +RawObject::loadGlobalSymbols(SymbolTable *symtab) +{ + return true; +} + +bool +RawObject::loadLocalSymbols(SymbolTable *symtab) +{ + return true; +} diff --git a/src/base/loader/raw_object.hh b/src/base/loader/raw_object.hh new file mode 100644 index 000000000..c7fff4e66 --- /dev/null +++ b/src/base/loader/raw_object.hh @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2006 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. + * + * Authors: Ali Saidi + */ + +#ifndef __BASE_LOADER_RAW_OBJECT_HH__ +#define __BASE_LOADER_RAW_OBJECT_HH__ + +#include "base/loader/object_file.hh" + +class RawObject: public ObjectFile +{ + protected: + RawObject(const std::string &_filename, int _fd, size_t _len, + uint8_t *_data, Arch _arch, OpSys _opSys); + public: + virtual ~RawObject() {} + + virtual bool loadGlobalSymbols(SymbolTable *symtab); + virtual bool loadLocalSymbols(SymbolTable *symtab); + + static ObjectFile *tryFile(const std::string &fname, int fd, size_t len, + uint8_t *data); +}; + + + +#endif // __BASE_LOADER_RAW_OBJECT_HH__ diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc index 80b144e85..881fbbd9b 100644 --- a/src/cpu/exetrace.cc +++ b/src/cpu/exetrace.cc @@ -37,6 +37,7 @@ #include <sys/shm.h> #include "arch/regfile.hh" +#include "arch/utility.hh" #include "base/loader/symtab.hh" #include "cpu/base.hh" #include "cpu/exetrace.hh" @@ -231,6 +232,7 @@ Trace::InstRecord::dump(ostream &outs) // outs << endl; } +#if THE_ISA == SPARC_ISA // Compare if (flags[LEGION_LOCKSTEP]) { @@ -239,57 +241,76 @@ Trace::InstRecord::dump(ostream &outs) bool diffInst = false; bool diffRegs = false; - while (!compared) { - if (shared_data->flags == OWN_M5) { - if (shared_data->pc != PC) - diffPC = true; - if (shared_data->instruction != staticInst->machInst) - diffInst = true; - for (int i = 0; i < TheISA::NumIntRegs; i++) { - if (thread->readIntReg(i) != shared_data->intregs[i]) - diffRegs = true; - } - - if (diffPC || diffInst || diffRegs ) { - outs << "Differences found between M5 and Legion:"; - if (diffPC) - outs << " PC"; - if (diffInst) - outs << " Instruction"; - if (diffRegs) - outs << " IntRegs"; - outs << endl; - - outs << "M5 PC: " << setw(20) << "0x" << hex << PC; - outs << "Legion PC: " << setw(20) << "0x" << hex << - shared_data->pc << endl; - - - - outs << "M5 Instruction: " << staticInst->machInst << "(" - << staticInst->disassemble(PC, debugSymbolTable) - << ")" << "Legion Instruction: " << - shared_data->instruction << "(" - /*<< legionInst->disassemble(shared_data->pc, - debugSymbolTable)*/ - << ")" << endl; - + if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) { + while (!compared) { + if (shared_data->flags == OWN_M5) { + if (shared_data->pc != PC) + diffPC = true; + if (shared_data->instruction != staticInst->machInst) + diffInst = true; for (int i = 0; i < TheISA::NumIntRegs; i++) { - outs << setw(16) << "0x" << hex << thread->readIntReg(i) - << setw(16) << "0x" << hex << shared_data->intregs[i]; - if (thread->readIntReg(i) != shared_data->intregs[i]) - outs << "<--- Different"; - outs << endl; + diffRegs = true; } - } - compared = true; - shared_data->flags = OWN_LEGION; - } - } + if (diffPC || diffInst || diffRegs ) { + outs << "Differences found between M5 and Legion:"; + if (diffPC) + outs << " [PC]"; + if (diffInst) + outs << " [Instruction]"; + if (diffRegs) + outs << " [IntRegs]"; + outs << endl << endl;; + + outs << setfill(' ') << setw(15) + << "M5 PC: " << "0x"<< setw(16) << setfill('0') + << hex << PC << endl; + outs << setfill(' ') << setw(15) + << "Legion PC: " << "0x"<< setw(16) << setfill('0') << hex + << shared_data->pc << endl << endl; + + outs << setfill(' ') << setw(15) + << "M5 Inst: " << "0x"<< setw(8) + << setfill('0') << hex << staticInst->machInst + << staticInst->disassemble(PC, debugSymbolTable) + << endl; + + StaticInstPtr legionInst = StaticInst::decode(makeExtMI(shared_data->instruction, thread)); + outs << setfill(' ') << setw(15) + << " Legion Inst: " + << "0x" << setw(8) << setfill('0') << hex + << shared_data->instruction + << legionInst->disassemble(shared_data->pc, debugSymbolTable) + << endl; + + outs << endl; + static const char * regtypes[4] = {"%g", "%o", "%l", "%i"}; + for(int y = 0; y < 4; y++) + { + for(int x = 0; x < 8; x++) + { + outs << regtypes[y] << x << " " ; + outs << "0x" << hex << setw(16) << thread->readIntReg(y*8+x); + if (thread->readIntReg(y*8 + x) != shared_data->intregs[y*8+x]) + outs << " X "; + else + outs << " | "; + outs << "0x" << setw(16) << hex << shared_data->intregs[y*8+x] + << endl; + } + } + fatal("Differences found between Legion and M5\n"); + } + + compared = true; + shared_data->flags = OWN_LEGION; + } + } // while + } // if not microop } +#endif } diff --git a/src/cpu/m5legion_interface.h b/src/cpu/m5legion_interface.h index 0fa0e7279..9338d9ca0 100644 --- a/src/cpu/m5legion_interface.h +++ b/src/cpu/m5legion_interface.h @@ -30,7 +30,7 @@ #include <unistd.h> -#define VERSION 0xA1000001 +#define VERSION 0xA1000002 #define OWN_M5 0x000000AA #define OWN_LEGION 0x00000055 @@ -41,7 +41,7 @@ typedef struct { uint32_t version; uint64_t pc; - uint64_t instruction; + uint32_t instruction; uint64_t intregs[32]; } SharedData; diff --git a/src/mem/physical.cc b/src/mem/physical.cc index 0302f7351..39eb63108 100644 --- a/src/mem/physical.cc +++ b/src/mem/physical.cc @@ -191,7 +191,9 @@ PhysicalMemory::checkLockedAddrList(Request *req) void PhysicalMemory::doFunctionalAccess(PacketPtr pkt) { - assert(pkt->getAddr() + pkt->getSize() <= params()->addrRange.size()); + assert(pkt->getAddr() + pkt->getSize() > params()->addrRange.start && + pkt->getAddr() + pkt->getSize() <= params()->addrRange.start + + params()->addrRange.size()); if (pkt->isRead()) { if (pkt->req->isLocked()) { diff --git a/src/python/m5/objects/BaseCPU.py b/src/python/m5/objects/BaseCPU.py index 4e34e8a4e..b6e05627d 100644 --- a/src/python/m5/objects/BaseCPU.py +++ b/src/python/m5/objects/BaseCPU.py @@ -3,7 +3,9 @@ from m5.params import * from m5.proxy import * from m5 import build_env from AlphaTLB import AlphaDTB, AlphaITB +from SparcTLB import SparcDTB, SparcITB from Bus import Bus +import sys class BaseCPU(SimObject): type = 'BaseCPU' @@ -13,8 +15,15 @@ class BaseCPU(SimObject): cpu_id = Param.Int("CPU identifier") if build_env['FULL_SYSTEM']: - dtb = Param.AlphaDTB(AlphaDTB(), "Data TLB") - itb = Param.AlphaITB(AlphaITB(), "Instruction TLB") + if build_env['TARGET_ISA'] == 'sparc': + dtb = Param.SparcDTB(SparcDTB(), "Data TLB") + itb = Param.SparcITB(SparcITB(), "Instruction TLB") + elif build_env['TARGET_ISA'] == 'alpha': + dtb = Param.AlphaDTB(AlphaDTB(), "Data TLB") + itb = Param.AlphaITB(AlphaITB(), "Instruction TLB") + else: + print "Unknown architecture, can't pick TLBs" + sys.exit(1) else: workload = VectorParam.Process("processes to run") diff --git a/src/python/m5/objects/SparcTLB.py b/src/python/m5/objects/SparcTLB.py new file mode 100644 index 000000000..de732e8de --- /dev/null +++ b/src/python/m5/objects/SparcTLB.py @@ -0,0 +1,14 @@ +from m5.SimObject import SimObject +from m5.params import * +class SparcTLB(SimObject): + type = 'SparcTLB' + abstract = True + size = Param.Int("TLB size") + +class SparcDTB(SparcTLB): + type = 'SparcDTB' + size = 64 + +class SparcITB(SparcTLB): + type = 'SparcITB' + size = 48 diff --git a/src/python/m5/objects/System.py b/src/python/m5/objects/System.py index e7dd1bc60..908c3d4ad 100644 --- a/src/python/m5/objects/System.py +++ b/src/python/m5/objects/System.py @@ -2,6 +2,7 @@ from m5.SimObject import SimObject from m5.params import * from m5.proxy import * from m5 import build_env +from PhysicalMemory import * class MemoryMode(Enum): vals = ['invalid', 'atomic', 'timing'] @@ -24,3 +25,21 @@ class AlphaSystem(System): pal = Param.String("file that contains palcode") system_type = Param.UInt64("Type of system we are emulating") system_rev = Param.UInt64("Revision of system we are emulating") + +class SparcSystem(System): + type = 'SparcSystem' + _rom_base = 0xfff0000000 + # ROM for OBP/Reset/Hypervisor + rom = Param.PhysicalMemory(PhysicalMemory(range = AddrRange(_rom_base, size = '8MB')), + "Memory to hold the ROM data") + + reset_addr = Param.Addr(_rom_base, "Address to load ROM at") + hypervisor_addr = Param.Addr(Addr('64kB') + _rom_base, + "Address to load hypervisor at") + openboot_addr = Param.Addr(Addr('512kB') + _rom_base, + "Address to load openboot at") + + reset_bin = Param.String("file that contains the reset code") + hypervisor_bin = Param.String("file that contains the hypervisor code") + openboot_bin = Param.String("file that contains the openboot code") + diff --git a/src/python/m5/params.py b/src/python/m5/params.py index 93d784181..4b5953bcb 100644 --- a/src/python/m5/params.py +++ b/src/python/m5/params.py @@ -369,6 +369,11 @@ class Addr(CheckedInt): except TypeError: self.value = long(value) self._check() + def __add__(self, other): + if isinstance(other, Addr): + return self.value + other.value + else: + return self.value + other class MetaRange(type): |