fix endian issues with condition codes
use memcpy instead of bcopy s/u_int32_t/uint32_t/g fixup endian code to work with solaris hack to make sure htole() works... Nate, have a good idea to fix this? src/arch/sparc/faults.cc: set the reset address to be 40 bits. Makes PC printing easier at least for now. src/arch/sparc/isa/base.isa: fix endian issues with condition codes src/arch/sparc/tlb.hh: add implemented physical addres constants src/arch/sparc/utility.hh: add tlb.hh to utilities src/base/loader/raw_object.cc: add a symbol <filename>_start to the symbol table for binaries files src/base/remote_gdb.cc: use memcpy instead of bcopy src/cpu/exetrace.cc: clean up printing a bit more src/cpu/m5legion_interface.h: add tons to the shared interface src/dev/ethertap.cc: s/u_int32_t/uint32_t/g src/dev/ide_atareg.h: fixup endian code to work with solaris src/dev/pcidev.cc: src/sim/param.hh: hack to make sure htole() works... --HG-- extra : convert_revision : 4579392184b40bcc1062671a953c6595c685e9b2
This commit is contained in:
parent
6d54a77518
commit
aa19b2e7bc
12 changed files with 116 additions and 48 deletions
|
@ -494,7 +494,7 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv)
|
||||||
void getREDVector(MiscReg TT, Addr & PC, Addr & NPC)
|
void getREDVector(MiscReg TT, Addr & PC, Addr & NPC)
|
||||||
{
|
{
|
||||||
//XXX The following constant might belong in a header file.
|
//XXX The following constant might belong in a header file.
|
||||||
const Addr RSTVAddr = 0xFFFFFFFFF0000000ULL;
|
const Addr RSTVAddr = 0xFFF0000000ULL;
|
||||||
PC = RSTVAddr | ((TT << 5) & 0xFF);
|
PC = RSTVAddr | ((TT << 5) & 0xFF);
|
||||||
NPC = PC + sizeof(MachInst);
|
NPC = PC + sizeof(MachInst);
|
||||||
}
|
}
|
||||||
|
|
|
@ -244,7 +244,12 @@ output decoder {{
|
||||||
bool passesCondition(uint32_t codes, uint32_t condition)
|
bool passesCondition(uint32_t codes, uint32_t condition)
|
||||||
{
|
{
|
||||||
CondCodes condCodes;
|
CondCodes condCodes;
|
||||||
condCodes.bits = codes;
|
condCodes.bits = 0;
|
||||||
|
condCodes.c = codes & 0x1 ? 1 : 0;
|
||||||
|
condCodes.v = codes & 0x2 ? 1 : 0;
|
||||||
|
condCodes.z = codes & 0x4 ? 1 : 0;
|
||||||
|
condCodes.n = codes & 0x8 ? 1 : 0;
|
||||||
|
|
||||||
switch(condition)
|
switch(condition)
|
||||||
{
|
{
|
||||||
case Always:
|
case Always:
|
||||||
|
|
|
@ -40,6 +40,9 @@ class ThreadContext;
|
||||||
|
|
||||||
namespace SparcISA
|
namespace SparcISA
|
||||||
{
|
{
|
||||||
|
const int PAddrImplBits = 40;
|
||||||
|
const Addr PAddrImplMask = (ULL(1) << PAddrImplBits) - 1;
|
||||||
|
|
||||||
class TLB : public SimObject
|
class TLB : public SimObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -59,7 +62,7 @@ namespace SparcISA
|
||||||
{
|
{
|
||||||
//For now, always assume the address is already physical.
|
//For now, always assume the address is already physical.
|
||||||
//Also assume that there are 40 bits of physical address space.
|
//Also assume that there are 40 bits of physical address space.
|
||||||
req->setPaddr(req->getVaddr() & ((1ULL << 40) - 1));
|
req->setPaddr(req->getVaddr() & PAddrImplMask);
|
||||||
return NoFault;
|
return NoFault;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
#include "arch/sparc/faults.hh"
|
#include "arch/sparc/faults.hh"
|
||||||
#include "arch/sparc/isa_traits.hh"
|
#include "arch/sparc/isa_traits.hh"
|
||||||
|
#include "arch/sparc/tlb.hh"
|
||||||
#include "base/misc.hh"
|
#include "base/misc.hh"
|
||||||
#include "base/bitfield.hh"
|
#include "base/bitfield.hh"
|
||||||
#include "cpu/thread_context.hh"
|
#include "cpu/thread_context.hh"
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "base/loader/raw_object.hh"
|
#include "base/loader/raw_object.hh"
|
||||||
|
#include "base/loader/symtab.hh"
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
|
|
||||||
ObjectFile *
|
ObjectFile *
|
||||||
|
@ -62,11 +63,19 @@ RawObject::RawObject(const std::string &_filename, int _fd, size_t _len,
|
||||||
bool
|
bool
|
||||||
RawObject::loadGlobalSymbols(SymbolTable *symtab)
|
RawObject::loadGlobalSymbols(SymbolTable *symtab)
|
||||||
{
|
{
|
||||||
|
int fnameStart = filename.rfind('/',filename.size()) + 1;
|
||||||
|
int extStart = filename.rfind('.',filename.size());
|
||||||
|
symtab->insert(text.baseAddr, filename.substr(fnameStart,
|
||||||
|
extStart-fnameStart) + "_start");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
RawObject::loadLocalSymbols(SymbolTable *symtab)
|
RawObject::loadLocalSymbols(SymbolTable *symtab)
|
||||||
{
|
{
|
||||||
|
int fnameStart = filename.rfind('/',filename.size()) + 1;
|
||||||
|
int extStart = filename.rfind('.',filename.size());
|
||||||
|
symtab->insert(text.baseAddr, filename.substr(fnameStart,
|
||||||
|
extStart-fnameStart) + "_start");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -421,7 +421,7 @@ BaseRemoteGDB::recv(char *bp, int maxlen)
|
||||||
putbyte(bp[0]);
|
putbyte(bp[0]);
|
||||||
putbyte(bp[1]);
|
putbyte(bp[1]);
|
||||||
len -= 3;
|
len -= 3;
|
||||||
bcopy(bp + 3, bp, len);
|
memcpy(bp, bp+3, len);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
|
|
||||||
#include "arch/regfile.hh"
|
#include "arch/regfile.hh"
|
||||||
#include "arch/utility.hh"
|
#include "arch/utility.hh"
|
||||||
|
#include "arch/tlb.hh"
|
||||||
#include "base/loader/symtab.hh"
|
#include "base/loader/symtab.hh"
|
||||||
#include "cpu/base.hh"
|
#include "cpu/base.hh"
|
||||||
#include "cpu/exetrace.hh"
|
#include "cpu/exetrace.hh"
|
||||||
|
@ -232,17 +233,22 @@ Trace::InstRecord::dump(ostream &outs)
|
||||||
bool diffPC = false;
|
bool diffPC = false;
|
||||||
bool diffInst = false;
|
bool diffInst = false;
|
||||||
bool diffRegs = false;
|
bool diffRegs = false;
|
||||||
|
Addr m5Pc, lgnPc;
|
||||||
|
|
||||||
|
|
||||||
if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) {
|
if(!staticInst->isMicroOp() || staticInst->isLastMicroOp()) {
|
||||||
while (!compared) {
|
while (!compared) {
|
||||||
|
m5Pc = PC & TheISA::PAddrImplMask;
|
||||||
|
lgnPc = shared_data->pc & TheISA::PAddrImplMask;
|
||||||
if (shared_data->flags == OWN_M5) {
|
if (shared_data->flags == OWN_M5) {
|
||||||
if (shared_data->pc != PC)
|
if (lgnPc != m5Pc)
|
||||||
diffPC = true;
|
diffPC = true;
|
||||||
if (shared_data->instruction != staticInst->machInst)
|
if (shared_data->instruction != staticInst->machInst)
|
||||||
diffInst = true;
|
diffInst = true;
|
||||||
for (int i = 0; i < TheISA::NumIntRegs; i++) {
|
for (int i = 0; i < TheISA::NumRegularIntRegs; i++) {
|
||||||
if (thread->readIntReg(i) != shared_data->intregs[i])
|
if (thread->readIntReg(i) != shared_data->intregs[i]) {
|
||||||
diffRegs = true;
|
diffRegs = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (diffPC || diffInst || diffRegs ) {
|
if (diffPC || diffInst || diffRegs ) {
|
||||||
|
@ -253,19 +259,19 @@ Trace::InstRecord::dump(ostream &outs)
|
||||||
outs << " [Instruction]";
|
outs << " [Instruction]";
|
||||||
if (diffRegs)
|
if (diffRegs)
|
||||||
outs << " [IntRegs]";
|
outs << " [IntRegs]";
|
||||||
outs << endl << endl;;
|
outs << endl << endl;
|
||||||
|
|
||||||
outs << setfill(' ') << setw(15)
|
outs << right << setfill(' ') << setw(15)
|
||||||
<< "M5 PC: " << "0x"<< setw(16) << setfill('0')
|
<< "M5 PC: " << "0x"<< setw(16) << setfill('0')
|
||||||
<< hex << PC << endl;
|
<< hex << m5Pc << endl;
|
||||||
outs << setfill(' ') << setw(15)
|
outs << setfill(' ') << setw(15)
|
||||||
<< "Legion PC: " << "0x"<< setw(16) << setfill('0') << hex
|
<< "Legion PC: " << "0x"<< setw(16) << setfill('0') << hex
|
||||||
<< shared_data->pc << endl << endl;
|
<< lgnPc << endl << endl;
|
||||||
|
|
||||||
outs << setfill(' ') << setw(15)
|
outs << setfill(' ') << setw(15)
|
||||||
<< "M5 Inst: " << "0x"<< setw(8)
|
<< "M5 Inst: " << "0x"<< setw(8)
|
||||||
<< setfill('0') << hex << staticInst->machInst
|
<< setfill('0') << hex << staticInst->machInst
|
||||||
<< staticInst->disassemble(PC, debugSymbolTable)
|
<< staticInst->disassemble(m5Pc, debugSymbolTable)
|
||||||
<< endl;
|
<< endl;
|
||||||
|
|
||||||
StaticInstPtr legionInst = StaticInst::decode(makeExtMI(shared_data->instruction, thread));
|
StaticInstPtr legionInst = StaticInst::decode(makeExtMI(shared_data->instruction, thread));
|
||||||
|
@ -273,7 +279,7 @@ Trace::InstRecord::dump(ostream &outs)
|
||||||
<< " Legion Inst: "
|
<< " Legion Inst: "
|
||||||
<< "0x" << setw(8) << setfill('0') << hex
|
<< "0x" << setw(8) << setfill('0') << hex
|
||||||
<< shared_data->instruction
|
<< shared_data->instruction
|
||||||
<< legionInst->disassemble(shared_data->pc, debugSymbolTable)
|
<< legionInst->disassemble(lgnPc, debugSymbolTable)
|
||||||
<< endl;
|
<< endl;
|
||||||
|
|
||||||
outs << endl;
|
outs << endl;
|
||||||
|
@ -386,7 +392,7 @@ Trace::InstRecord::setParams()
|
||||||
// If were going to be in lockstep with Legion
|
// If were going to be in lockstep with Legion
|
||||||
// Setup shared memory, and get otherwise ready
|
// Setup shared memory, and get otherwise ready
|
||||||
if (flags[LEGION_LOCKSTEP]) {
|
if (flags[LEGION_LOCKSTEP]) {
|
||||||
int shmfd = shmget(getuid(), sizeof(SharedData), 0777);
|
int shmfd = shmget('M' << 24 | getuid(), sizeof(SharedData), 0777);
|
||||||
if (shmfd < 0)
|
if (shmfd < 0)
|
||||||
fatal("Couldn't get shared memory fd. Is Legion running?");
|
fatal("Couldn't get shared memory fd. Is Legion running?");
|
||||||
|
|
||||||
|
@ -401,6 +407,8 @@ Trace::InstRecord::setParams()
|
||||||
fatal("Shared Data is wrong version! M5: %d Legion: %d", VERSION,
|
fatal("Shared Data is wrong version! M5: %d Legion: %d", VERSION,
|
||||||
shared_data->version);
|
shared_data->version);
|
||||||
|
|
||||||
|
// step legion forward one cycle so we can get register values
|
||||||
|
shared_data->flags = OWN_LEGION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#define VERSION 0xA1000002
|
#define VERSION 0xA1000005
|
||||||
#define OWN_M5 0x000000AA
|
#define OWN_M5 0x000000AA
|
||||||
#define OWN_LEGION 0x00000055
|
#define OWN_LEGION 0x00000055
|
||||||
|
|
||||||
|
@ -41,9 +41,35 @@ typedef struct {
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
|
|
||||||
uint64_t pc;
|
uint64_t pc;
|
||||||
|
uint64_t new_pc;
|
||||||
uint32_t instruction;
|
uint32_t instruction;
|
||||||
|
uint32_t new_instruction;
|
||||||
uint64_t intregs[32];
|
uint64_t intregs[32];
|
||||||
|
|
||||||
|
uint64_t tpc[8];
|
||||||
|
uint64_t tnpc[8];
|
||||||
|
uint64_t tstate[8];
|
||||||
|
uint16_t tt[8];
|
||||||
|
uint64_t tba;
|
||||||
|
|
||||||
|
uint64_t hpstate;
|
||||||
|
uint64_t htstate[8];
|
||||||
|
uint64_t htba;
|
||||||
|
uint16_t pstate;
|
||||||
|
|
||||||
|
uint64_t y;
|
||||||
|
uint8_t ccr;
|
||||||
|
uint8_t tl;
|
||||||
|
uint8_t gl;
|
||||||
|
uint8_t asi;
|
||||||
|
uint8_t pil;
|
||||||
|
|
||||||
|
uint8_t cwp;
|
||||||
|
uint8_t cansave;
|
||||||
|
uint8_t canrestore;
|
||||||
|
uint8_t otherwin;
|
||||||
|
uint8_t cleanwin;
|
||||||
|
|
||||||
} SharedData;
|
} SharedData;
|
||||||
|
|
||||||
/** !!! ^^^ Increment VERSION on change ^^^ !!! **/
|
/** !!! ^^^ Increment VERSION on change ^^^ !!! **/
|
||||||
|
|
|
@ -178,7 +178,7 @@ EtherTap::recvPacket(EthPacketPtr packet)
|
||||||
|
|
||||||
DPRINTF(Ethernet, "EtherTap output len=%d\n", packet->length);
|
DPRINTF(Ethernet, "EtherTap output len=%d\n", packet->length);
|
||||||
DDUMP(EthernetData, packet->data, packet->length);
|
DDUMP(EthernetData, packet->data, packet->length);
|
||||||
u_int32_t len = htonl(packet->length);
|
uint32_t len = htonl(packet->length);
|
||||||
write(socket, &len, sizeof(len));
|
write(socket, &len, sizeof(len));
|
||||||
write(socket, packet->data, packet->length);
|
write(socket, packet->data, packet->length);
|
||||||
|
|
||||||
|
@ -199,11 +199,11 @@ EtherTap::process(int revent)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *data = buffer + sizeof(u_int32_t);
|
char *data = buffer + sizeof(uint32_t);
|
||||||
if (!(revent & POLLIN))
|
if (!(revent & POLLIN))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (buffer_offset < data_len + sizeof(u_int32_t)) {
|
if (buffer_offset < data_len + sizeof(uint32_t)) {
|
||||||
int len = read(socket, buffer + buffer_offset, buflen - buffer_offset);
|
int len = read(socket, buffer + buffer_offset, buflen - buffer_offset);
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
detach();
|
detach();
|
||||||
|
@ -213,23 +213,23 @@ EtherTap::process(int revent)
|
||||||
buffer_offset += len;
|
buffer_offset += len;
|
||||||
|
|
||||||
if (data_len == 0)
|
if (data_len == 0)
|
||||||
data_len = ntohl(*(u_int32_t *)buffer);
|
data_len = ntohl(*(uint32_t *)buffer);
|
||||||
|
|
||||||
DPRINTF(Ethernet, "Received data from peer: len=%d buffer_offset=%d "
|
DPRINTF(Ethernet, "Received data from peer: len=%d buffer_offset=%d "
|
||||||
"data_len=%d\n", len, buffer_offset, data_len);
|
"data_len=%d\n", len, buffer_offset, data_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (data_len != 0 && buffer_offset >= data_len + sizeof(u_int32_t)) {
|
while (data_len != 0 && buffer_offset >= data_len + sizeof(uint32_t)) {
|
||||||
EthPacketPtr packet;
|
EthPacketPtr packet;
|
||||||
packet = new EthPacketData(data_len);
|
packet = new EthPacketData(data_len);
|
||||||
packet->length = data_len;
|
packet->length = data_len;
|
||||||
memcpy(packet->data, data, data_len);
|
memcpy(packet->data, data, data_len);
|
||||||
|
|
||||||
buffer_offset -= data_len + sizeof(u_int32_t);
|
buffer_offset -= data_len + sizeof(uint32_t);
|
||||||
assert(buffer_offset >= 0);
|
assert(buffer_offset >= 0);
|
||||||
if (buffer_offset > 0) {
|
if (buffer_offset > 0) {
|
||||||
memmove(buffer, data + data_len, buffer_offset);
|
memmove(buffer, data + data_len, buffer_offset);
|
||||||
data_len = ntohl(*(u_int32_t *)buffer);
|
data_len = ntohl(*(uint32_t *)buffer);
|
||||||
} else
|
} else
|
||||||
data_len = 0;
|
data_len = 0;
|
||||||
|
|
||||||
|
|
|
@ -35,11 +35,25 @@
|
||||||
|
|
||||||
#if defined(linux)
|
#if defined(linux)
|
||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
|
#elif defined(__sun__)
|
||||||
|
#include <sys/isa_defs.h>
|
||||||
#else
|
#else
|
||||||
#include <machine/endian.h>
|
#include <machine/endian.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef LITTLE_ENDIAN
|
||||||
#define ATA_BYTE_ORDER LITTLE_ENDIAN
|
#define ATA_BYTE_ORDER LITTLE_ENDIAN
|
||||||
|
#elif defined(BIG_ENDIAN)
|
||||||
|
#define ATA_BYTE_ORDER BIG_ENDIAN
|
||||||
|
#elif defined(_LITTLE_ENDIAN)
|
||||||
|
#define ATA_BYTE_ORDER 1
|
||||||
|
#define LITTLE_ENDIAN 1
|
||||||
|
#elif defined(_BIG_ENDIAN)
|
||||||
|
#define ATA_BYTE_ORDER 0
|
||||||
|
#define LITTLE_ENDIAN 1
|
||||||
|
#else
|
||||||
|
#error "No endianess defined"
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Drive parameter structure for ATA/ATAPI.
|
* Drive parameter structure for ATA/ATAPI.
|
||||||
|
|
|
@ -387,33 +387,33 @@ CREATE_SIM_OBJECT(PciConfigData)
|
||||||
{
|
{
|
||||||
PciConfigData *data = new PciConfigData(getInstanceName());
|
PciConfigData *data = new PciConfigData(getInstanceName());
|
||||||
|
|
||||||
data->config.vendor = htole(VendorID);
|
data->config.vendor = htole(VendorID.returnValue());
|
||||||
data->config.device = htole(DeviceID);
|
data->config.device = htole(DeviceID.returnValue());
|
||||||
data->config.command = htole(Command);
|
data->config.command = htole(Command.returnValue());
|
||||||
data->config.status = htole(Status);
|
data->config.status = htole(Status.returnValue());
|
||||||
data->config.revision = htole(Revision);
|
data->config.revision = htole(Revision.returnValue());
|
||||||
data->config.progIF = htole(ProgIF);
|
data->config.progIF = htole(ProgIF.returnValue());
|
||||||
data->config.subClassCode = htole(SubClassCode);
|
data->config.subClassCode = htole(SubClassCode.returnValue());
|
||||||
data->config.classCode = htole(ClassCode);
|
data->config.classCode = htole(ClassCode.returnValue());
|
||||||
data->config.cacheLineSize = htole(CacheLineSize);
|
data->config.cacheLineSize = htole(CacheLineSize.returnValue());
|
||||||
data->config.latencyTimer = htole(LatencyTimer);
|
data->config.latencyTimer = htole(LatencyTimer.returnValue());
|
||||||
data->config.headerType = htole(HeaderType);
|
data->config.headerType = htole(HeaderType.returnValue());
|
||||||
data->config.bist = htole(BIST);
|
data->config.bist = htole(BIST.returnValue());
|
||||||
|
|
||||||
data->config.baseAddr[0] = htole(BAR0);
|
data->config.baseAddr[0] = htole(BAR0.returnValue());
|
||||||
data->config.baseAddr[1] = htole(BAR1);
|
data->config.baseAddr[1] = htole(BAR1.returnValue());
|
||||||
data->config.baseAddr[2] = htole(BAR2);
|
data->config.baseAddr[2] = htole(BAR2.returnValue());
|
||||||
data->config.baseAddr[3] = htole(BAR3);
|
data->config.baseAddr[3] = htole(BAR3.returnValue());
|
||||||
data->config.baseAddr[4] = htole(BAR4);
|
data->config.baseAddr[4] = htole(BAR4.returnValue());
|
||||||
data->config.baseAddr[5] = htole(BAR5);
|
data->config.baseAddr[5] = htole(BAR5.returnValue());
|
||||||
data->config.cardbusCIS = htole(CardbusCIS);
|
data->config.cardbusCIS = htole(CardbusCIS.returnValue());
|
||||||
data->config.subsystemVendorID = htole(SubsystemVendorID);
|
data->config.subsystemVendorID = htole(SubsystemVendorID.returnValue());
|
||||||
data->config.subsystemID = htole(SubsystemID);
|
data->config.subsystemID = htole(SubsystemID.returnValue());
|
||||||
data->config.expansionROM = htole(ExpansionROM);
|
data->config.expansionROM = htole(ExpansionROM.returnValue());
|
||||||
data->config.interruptLine = htole(InterruptLine);
|
data->config.interruptLine = htole(InterruptLine.returnValue());
|
||||||
data->config.interruptPin = htole(InterruptPin);
|
data->config.interruptPin = htole(InterruptPin.returnValue());
|
||||||
data->config.minimumGrant = htole(MinimumGrant);
|
data->config.minimumGrant = htole(MinimumGrant.returnValue());
|
||||||
data->config.maximumLatency = htole(MaximumLatency);
|
data->config.maximumLatency = htole(MaximumLatency.returnValue());
|
||||||
|
|
||||||
data->BARSize[0] = BAR0Size;
|
data->BARSize[0] = BAR0Size;
|
||||||
data->BARSize[1] = BAR1Size;
|
data->BARSize[1] = BAR1Size;
|
||||||
|
|
|
@ -242,6 +242,8 @@ class Param : public BaseParam
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T returnValue() const { return value; }
|
||||||
|
|
||||||
// display value to stream
|
// display value to stream
|
||||||
virtual void showValue(std::ostream &os) const;
|
virtual void showValue(std::ostream &os) const;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue