Commit 3f93d119 authored by Wesley W. Terpstra's avatar Wesley W. Terpstra

Debug ROM driver for phase

parent 9faf2067
......@@ -24,5 +24,6 @@ libcomponents_a_SOURCES = \
lm32/lm32-break.cpp \
lm32/lm32-write.cpp \
lm32/lm32-read.cpp \
lm32/lm32-drom.cpp \
gdb-rsp/gdb-rsp.cpp \
gdb-rsp/gdb-serial.cpp
#include "common/compat.h"
#include "lm32-drom.h"
#include "pinouts/pinouts.h"
#include <cstring>
#include <assert.h>
LM32_DROM::LM32_DROM(Interconnect* ic)
: Component(ic),
register_address(*addMasterPort("register/address", Pinout("address", 8))),
register_write (*addMasterPort("register/write", Pinout("data", 32))),
register_read (*addMasterPort("register/read", Pinout("data", 32))),
memory_address (*addMasterPort("memory/address", Pinout("address", 32))),
memory_write (*addMasterPort("memory/write", Pinout("data", 8))),
memory_read (*addMasterPort("memory/read", Pinout("data", 8))),
run (*addMasterPort("run", command_pinout)),
echo (*addSlavePort("echo", uint32_pinout)),
uart_write(*addSlavePort("uart/write", uint8_pinout)),
uart_read (*addSlavePort("uart/read", uint8_pinout)),
state(STOPPED) {
}
SendQueue::const_iterator LM32_DROM::send(SendQueue::const_iterator i, SendQueue::const_iterator end) {
for (; i != end; ++i) {
if (i->master == &reset) {
state = RUNNING;
registers = 0;
memset(now, 0, sizeof(now));
memset(old, 0, sizeof(now));
continue;
}
switch (state) {
case RUNNING: {
uart_read();
return i;
}
case LOAD_BASE: {
uart_write(Bits(static_cast<uint8_t>(0x80)));
uart_read();
uart_read();
uart_read();
uart_read();
return i;
}
case LOAD_REGS: {
/* don't read R0 */
read(registers+4, (RW_regs+R_regs-1)*4);
return i;
}
case STOPPED: {
if (i->master == &register_address) {
activeReg = static_cast<uint8_t>(i->bits);
} else if (i->master == &register_read) {
echo(Bits(getReg(activeReg)));
} else if (i->master == &register_write) {
setReg(activeReg, static_cast<uint32_t>(i->bits));
} else if (i->master == &memory_address) {
activeMem = i->bits;
} else if (i->master == &memory_read) {
uint32_t len;
for (len = 0; i != end && i->master == &memory_read; ++i)
++len;
read(activeMem, len);
--i;
} else if (i->master == &memory_write) {
write(activeMem, i, end);
--i;
} else {
assert (i->master == &run);
update();
uart_write(Bits(static_cast<uint8_t>(0)));
state = RUNNING;
}
}
}
}
return i;
}
void LM32_DROM::recv(RecvQueue::const_iterator i, RecvQueue::const_iterator end) {
for (; i != end; ++i) {
if (i->slave == &echo) {
register_read(i->bits);
} else {
switch (state) {
case RUNNING: {
if (static_cast<uint8_t>(i->bits) == 0x80 + 'B') {
if (registers == 0)
state = LOAD_BASE;
else
state = LOAD_REGS;
}
break;
}
case LOAD_BASE: {
registers =
static_cast<uint32_t>(static_cast<uint8_t>((i++)->bits)) << 24 |
static_cast<uint32_t>(static_cast<uint8_t>((i++)->bits)) << 16 |
static_cast<uint32_t>(static_cast<uint8_t>((i++)->bits)) << 8 |
static_cast<uint32_t>(static_cast<uint8_t>((i++)->bits)) << 0;
--i;
state = LOAD_REGS;
break;
}
case LOAD_REGS: {
int pulled = (RW_regs + R_regs)*4;
old[0] = old[1] = old[2] = old[3] = 0; /* R0 */
for (int j = 4; j < pulled; ++i, ++j) /* Skip R0 */
old[j] = static_cast<uint8_t>(i->bits);
--i;
memcpy(now, old, pulled);
/* Fixup SIG and PC */
switch ((getReg(SIG) & 0xff) >> 5) {
case 0: /* reset */
setReg(SIG, 0);
setReg(PC, getReg(EA));
break;
case 1: /* breakpoint */
setReg(SIG, 5); /* SIGTRAP */
setReg(PC, getReg(BA));
break;
case 2: /* instruction bus error */
setReg(SIG, 11); /* SIGSEGV */
setReg(PC, getReg(EA));
break;
case 3: /* watchpoint */
setReg(SIG, 5); /* SIGTRAP */
setReg(PC, getReg(BA));
break;
case 4: /* data bus error */
setReg(SIG, 11); /* SIGSEGV */
setReg(PC, getReg(EA));
break;
case 5: /* divide by zero */
setReg(SIG, 8); /* SIGFPE */
setReg(PC, getReg(EA));
break;
case 6: /* interrupt */
setReg(SIG, 2); /* SIGINT */
setReg(PC, getReg(EA));
break;
case 7: /* system call */
setReg(SIG, 1); /* SIGHUP */
setReg(PC, getReg(EA));
break;
}
state = STOPPED;
break;
}
case STOPPED: {
memory_read(i->bits);
break;
}
}
}
}
}
void LM32_DROM::read(uint32_t address, uint32_t len) {
while (len > 0) {
uint32_t cut;
if (len > 127) cut = 127; else cut = len;
uart_write(Bits(static_cast<uint8_t>(0x80 | cut)));
uart_write(Bits(static_cast<uint8_t>(address >> 24)));
uart_write(Bits(static_cast<uint8_t>(address >> 16)));
uart_write(Bits(static_cast<uint8_t>(address >> 8)));
uart_write(Bits(static_cast<uint8_t>(address >> 0)));
for (uint32_t j = 0; j < cut; ++j)
uart_read();
address += cut;
len -= cut;
}
}
void LM32_DROM::write(uint32_t address, SendQueue::const_iterator& i, SendQueue::const_iterator end) {
uint32_t len = 0;
for (SendQueue::const_iterator scan = i; scan != end && scan->master == &memory_write; ++scan)
++len;
while (len > 0) {
uint32_t cut;
if (len > 127) cut = 127; else cut = len;
uart_write(Bits(static_cast<uint8_t>(cut)));
uart_write(Bits(static_cast<uint8_t>(address >> 24)));
uart_write(Bits(static_cast<uint8_t>(address >> 16)));
uart_write(Bits(static_cast<uint8_t>(address >> 8)));
uart_write(Bits(static_cast<uint8_t>(address >> 0)));
for (uint32_t j = 0; j < cut; ++j, ++i)
uart_write(i->bits);
address += cut;
len -= cut;
}
}
void LM32_DROM::setReg(int reg, uint32_t val) {
now[reg*4+0] = val >> 24;
now[reg*4+1] = val >> 16;
now[reg*4+2] = val >> 8;
now[reg*4+3] = val >> 0;
}
uint32_t LM32_DROM::getReg(int reg) {
return
static_cast<uint32_t>(now[reg*4+0]) << 24 |
static_cast<uint32_t>(now[reg*4+1]) << 16 |
static_cast<uint32_t>(now[reg*4+2]) << 8 |
static_cast<uint32_t>(now[reg*4+3]) << 0;
}
void LM32_DROM::update() {
now[0] = now[1] = now[2] = now[3] = 0; /* R0 */
#if 0
/* Analyze the longest run-length needing update */
int runLen[regs*4];
for (int j = regs*4-1; j >= 0; --j
#endif
/* !!! For now, write it all */
uart_write(Bits(static_cast<uint8_t>(100)));
uart_write(Bits(static_cast<uint8_t>(registers >> 24)));
uart_write(Bits(static_cast<uint8_t>(registers >> 16)));
uart_write(Bits(static_cast<uint8_t>(registers >> 8)));
uart_write(Bits(static_cast<uint8_t>(registers >> 0)));
for (uint32_t j = 0; j < 100; ++j)
uart_write(Bits(now[j]));
uart_write(Bits(static_cast<uint8_t>(100)));
uart_write(Bits(static_cast<uint8_t>((registers+100) >> 24)));
uart_write(Bits(static_cast<uint8_t>((registers+100) >> 16)));
uart_write(Bits(static_cast<uint8_t>((registers+100) >> 8)));
uart_write(Bits(static_cast<uint8_t>((registers+100) >> 0)));
for (uint32_t j = 100; j < 200; ++j)
uart_write(Bits(now[j]));
}
#ifndef LM32_DROM_H
#define LM32_DROM_H
#include "common/component.h"
class LM32_DROM : public Component {
public:
LM32_DROM(Interconnect* ic);
SendQueue::const_iterator send(SendQueue::const_iterator i, SendQueue::const_iterator end);
void recv(RecvQueue::const_iterator i, RecvQueue::const_iterator end);
MasterPort& register_address;
MasterPort& register_write;
MasterPort& register_read;
MasterPort& memory_address;
MasterPort& memory_write;
MasterPort& memory_read;
MasterPort& run;
SlavePort& echo;
SlavePort& uart_write;
SlavePort& uart_read;
static const int PC = 32;
static const int SIG = 33;
static const int SP = 28;
protected:
static const int gdb_regs = 37; /* a subset of the RW regs */
static const int RW_regs = 38;
static const int R_regs = 3;
static const int W_regs = 9;
static const int regs = RW_regs + R_regs + W_regs;
static const int EA = 30;
static const int BA = 31;
static const int DC = 41;
static const int BP0 = 42;
static const int WP0 = 46;
enum State { RUNNING, LOAD_BASE, LOAD_REGS, STOPPED } state;
uint32_t registers;
uint32_t activeMem;
uint8_t activeReg;
unsigned char old[regs*4];
unsigned char now[regs*4];
void read (uint32_t address, uint32_t len);
void write(uint32_t address, SendQueue::const_iterator& i, SendQueue::const_iterator end);
uint32_t getReg(int reg);
void setReg(int reg, uint32_t val);
void update();
};
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment