add support for simple character input via the system console

dev/alpha_access.h:
    -  use our standard types instead of this extra typedef
    -  advance the ALPHA_ACCESS version since the interface
    has changed.  *this means you need a new console binary*
    -  shuffle a couple things around to pack the data structure
    a bit better
    -  add a placeholder for character input
dev/alpha_console.cc:
    Clean up the read code path a bit and add support for character
    input via the console

    Clean up the write path and use a switch instead of a bunch of
    if statements

--HG--
extra : convert_revision : a1a5bc8fed9ec9c4c46548fdf79604661668b81a
This commit is contained in:
Nathan Binkert 2003-12-22 17:51:14 -05:00
parent c3ba166e65
commit 318e0c93ed
4 changed files with 105 additions and 76 deletions

View file

@ -33,52 +33,44 @@
* System Console Memory Mapped Register Definition * System Console Memory Mapped Register Definition
*/ */
#define ALPHA_ACCESS_VERSION (1291+1) /* CH++*/ #define ALPHA_ACCESS_VERSION (1301) /* CH++*/
#ifdef CONSOLE
typedef uint32 UINT32;
typedef uint64 UINT64;
#else
typedef uint32_t UINT32;
typedef uint64_t UINT64;
#ifndef CONSOLE
#include <ostream> #include <ostream>
#include <string> #include <string>
class Checkpoint; class Checkpoint;
#endif #endif
// This structure hacked up from simos // This structure hacked up from simos
struct AlphaAccess struct AlphaAccess
{ {
UINT32 last_offset; // 00: must be first field uint32_t last_offset; // 00: must be first field
UINT32 version; // 04: uint32_t version; // 04:
UINT32 numCPUs; // 08: uint32_t numCPUs; // 08:
UINT32 align0; // 0C: Placeholder for alignment uint32_t intrClockFrequency; // 0C: Hz
UINT64 mem_size; // 10: uint64_t cpuClock; // 10: MHz
UINT64 cpuClock; // 18: MHz uint64_t mem_size; // 18:
UINT32 intrClockFrequency; // 20: Hz
UINT32 align1; // 24: Placeholder for alignment
// Loaded kernel // Loaded kernel
UINT64 kernStart; // 28: uint64_t kernStart; // 20:
UINT64 kernEnd; // 30: uint64_t kernEnd; // 28:
UINT64 entryPoint; // 38: uint64_t entryPoint; // 30:
// console disk stuff // console disk stuff
UINT64 diskUnit; // 40: uint64_t diskUnit; // 38:
UINT64 diskCount; // 48: uint64_t diskCount; // 40:
UINT64 diskPAddr; // 50: uint64_t diskPAddr; // 48:
UINT64 diskBlock; // 58: uint64_t diskBlock; // 50:
UINT64 diskOperation; // 60: uint64_t diskOperation; // 58:
// console simple output stuff // console simple output stuff
UINT64 outputChar; // 68: uint64_t outputChar; // 60: Placeholder for output
uint64_t inputChar; // 68: Placeholder for input
// MP boot // MP boot
UINT64 bootStrapImpure; // 70: uint64_t bootStrapImpure; // 70:
UINT32 bootStrapCPU; // 78: uint32_t bootStrapCPU; // 78:
UINT32 align2; // 7C: Dummy placeholder for alignment uint32_t align2; // 7C: Dummy placeholder for alignment
#ifndef CONSOLE #ifndef CONSOLE
void serialize(std::ostream &os); void serialize(std::ostream &os);

View file

@ -76,17 +76,35 @@ Fault
AlphaConsole::read(MemReqPtr req, uint8_t *data) AlphaConsole::read(MemReqPtr req, uint8_t *data)
{ {
memset(data, 0, req->size); memset(data, 0, req->size);
uint64_t val;
if (req->size == sizeof(uint32_t)) { Addr daddr = req->paddr & addr_mask;
Addr daddr = req->paddr & addr_mask; switch (daddr) {
*(uint32_t *)data = *(uint32_t *)(consoleData + daddr); case offsetof(AlphaAccess, inputChar):
val = console->in();
break;
#if 0 default:
DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", val = *(uint64_t *)(consoleData + daddr);
daddr, *(uint32_t *)data); break;
#endif
} }
DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr, val);
switch (req->size) {
case sizeof(uint32_t):
*(uint32_t *)data = (uint32_t)val;
break;
case sizeof(uint64_t):
*(uint64_t *)data = val;
break;
default:
return Machine_Check_Fault;
}
return No_Fault; return No_Fault;
} }
@ -99,6 +117,7 @@ AlphaConsole::write(MemReqPtr req, const uint8_t *data)
case sizeof(uint32_t): case sizeof(uint32_t):
val = *(uint32_t *)data; val = *(uint32_t *)data;
break; break;
case sizeof(uint64_t): case sizeof(uint64_t):
val = *(uint64_t *)data; val = *(uint64_t *)data;
break; break;
@ -106,60 +125,57 @@ AlphaConsole::write(MemReqPtr req, const uint8_t *data)
return Machine_Check_Fault; return Machine_Check_Fault;
} }
Addr paddr = req->paddr & addr_mask; Addr daddr = req->paddr & addr_mask;
ExecContext *other_xc;
if (paddr == offsetof(AlphaAccess, diskUnit)) { switch (daddr) {
case offsetof(AlphaAccess, diskUnit):
alphaAccess->diskUnit = val; alphaAccess->diskUnit = val;
return No_Fault; break;
}
if (paddr == offsetof(AlphaAccess, diskCount)) { case offsetof(AlphaAccess, diskCount):
alphaAccess->diskCount = val; alphaAccess->diskCount = val;
return No_Fault; break;
}
if (paddr == offsetof(AlphaAccess, diskPAddr)) { case offsetof(AlphaAccess, diskPAddr):
alphaAccess->diskPAddr = val; alphaAccess->diskPAddr = val;
return No_Fault; break;
}
if (paddr == offsetof(AlphaAccess, diskBlock)) { case offsetof(AlphaAccess, diskBlock):
alphaAccess->diskBlock = val; alphaAccess->diskBlock = val;
return No_Fault; break;
}
if (paddr == offsetof(AlphaAccess, diskOperation)) { case offsetof(AlphaAccess, diskOperation):
if (val == 0x13) if (val == 0x13)
disk->read(alphaAccess->diskPAddr, alphaAccess->diskBlock, disk->read(alphaAccess->diskPAddr, alphaAccess->diskBlock,
alphaAccess->diskCount); alphaAccess->diskCount);
else else
panic("Invalid disk operation!"); panic("Invalid disk operation!");
return No_Fault; break;
}
if (paddr == offsetof(AlphaAccess, outputChar)) { case offsetof(AlphaAccess, outputChar):
console->out((char)(val & 0xff), false); console->out((char)(val & 0xff), false);
return No_Fault; break;
}
if (paddr == offsetof(AlphaAccess, bootStrapImpure)) { case offsetof(AlphaAccess, bootStrapImpure):
alphaAccess->bootStrapImpure = val; alphaAccess->bootStrapImpure = val;
return No_Fault; break;
}
if (paddr == offsetof(AlphaAccess, bootStrapCPU)) { case offsetof(AlphaAccess, bootStrapCPU):
warn("%d: Trying to launch another CPU!", curTick); warn("%d: Trying to launch another CPU!", curTick);
int cpu = val; assert(val > 0 && "Must not access primary cpu");
assert(cpu > 0 && "Must not access primary cpu");
ExecContext *other_xc = req->xc->system->execContexts[cpu]; other_xc = req->xc->system->execContexts[val];
other_xc->regs.intRegFile[16] = cpu; other_xc->regs.intRegFile[16] = val;
other_xc->regs.ipr[TheISA::IPR_PALtemp16] = cpu; other_xc->regs.ipr[TheISA::IPR_PALtemp16] = val;
other_xc->regs.intRegFile[0] = cpu; other_xc->regs.intRegFile[0] = val;
other_xc->regs.intRegFile[30] = alphaAccess->bootStrapImpure; other_xc->regs.intRegFile[30] = alphaAccess->bootStrapImpure;
other_xc->activate(); //Start the cpu other_xc->activate(); //Start the cpu
return No_Fault; break;
default:
return Machine_Check_Fault;
} }
return No_Fault; return No_Fault;
@ -183,6 +199,7 @@ AlphaAccess::serialize(ostream &os)
SERIALIZE_SCALAR(diskBlock); SERIALIZE_SCALAR(diskBlock);
SERIALIZE_SCALAR(diskOperation); SERIALIZE_SCALAR(diskOperation);
SERIALIZE_SCALAR(outputChar); SERIALIZE_SCALAR(outputChar);
SERIALIZE_SCALAR(inputChar);
SERIALIZE_SCALAR(bootStrapImpure); SERIALIZE_SCALAR(bootStrapImpure);
SERIALIZE_SCALAR(bootStrapCPU); SERIALIZE_SCALAR(bootStrapCPU);
} }
@ -205,6 +222,7 @@ AlphaAccess::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_SCALAR(diskBlock); UNSERIALIZE_SCALAR(diskBlock);
UNSERIALIZE_SCALAR(diskOperation); UNSERIALIZE_SCALAR(diskOperation);
UNSERIALIZE_SCALAR(outputChar); UNSERIALIZE_SCALAR(outputChar);
UNSERIALIZE_SCALAR(inputChar);
UNSERIALIZE_SCALAR(bootStrapImpure); UNSERIALIZE_SCALAR(bootStrapImpure);
UNSERIALIZE_SCALAR(bootStrapCPU); UNSERIALIZE_SCALAR(bootStrapCPU);
} }

View file

@ -223,21 +223,32 @@ SimConsole::configTerm()
} }
} }
int #define MORE_PENDING (ULL(1) << 61)
#define RECEIVE_SUCCESS (ULL(0) << 62)
#define RECEIVE_NONE (ULL(2) << 62)
#define RECEIVE_ERROR (ULL(3) << 62)
uint64_t
SimConsole::in() SimConsole::in()
{ {
char c = 0;
uint64_t val = 0;
if (rxbuf.empty()) { if (rxbuf.empty()) {
clearInt(ReceiveInterrupt); clearInt(ReceiveInterrupt);
return -1; val |= RECEIVE_NONE;
return 0x8;
} else {
uint64_t val;
rxbuf.read(&c, 1);
val |= RECEIVE_SUCCESS | c;
if (!rxbuf.empty())
val |= MORE_PENDING;
} }
char c; DPRINTF(ConsoleVerbose, "in: \'%c\' %#02x retval: %#x\n",
rxbuf.read(&c, 1); isprint(c) ? c : ' ', c, val);
DPRINTF(ConsoleVerbose, "in: \'%c\' %#02x status: %#x\n", return val;
isprint(c) ? c : ' ', c, _status);
return c;
} }
void void

View file

@ -109,9 +109,17 @@ class SimConsole : public SimObject
// OS interface // OS interface
// Get a character from the console. // Get a character from the console.
// return of -1 means there is no character pending. // the return value corresponds to the console GETC return value:
// retval<63:61>
// 000: success: character received
// 001: success: character received, more pending
// 100: failure: no character ready
// 110: failure: character received with error
// 111: failure: character received with error, more pending
// retval<31:0>
// character read from console
// Interrupts are cleared when the buffer is empty. // Interrupts are cleared when the buffer is empty.
int in(); uint64_t in();
// Send a character to the console // Send a character to the console
void out(char c, bool raise_int = true); void out(char c, bool raise_int = true);