|
|
|
@ -21,14 +21,15 @@ enum |
|
|
|
APP_CMD_NACK |
|
|
|
}; |
|
|
|
|
|
|
|
#define APP_DATA_ALIGN 8 |
|
|
|
#define APP_MAX_DATA_SIZE 1024 |
|
|
|
#define HTIF_DATA_ALIGN 8 |
|
|
|
struct packet |
|
|
|
{ |
|
|
|
uint16_t cmd; |
|
|
|
uint16_t seqno; |
|
|
|
uint32_t data_size; |
|
|
|
uint64_t addr; |
|
|
|
reg_t cmd : 4; |
|
|
|
reg_t data_size : 12; |
|
|
|
reg_t seqno : 8; |
|
|
|
reg_t addr : 40; |
|
|
|
|
|
|
|
uint8_t data[APP_MAX_DATA_SIZE]; |
|
|
|
}; |
|
|
|
|
|
|
|
@ -65,18 +66,19 @@ void htif_t::wait_for_fromhost_write() |
|
|
|
|
|
|
|
void htif_t::send_packet(packet* p) |
|
|
|
{ |
|
|
|
int bytes = write(tohost_fd,p,offsetof(packet,data)+p->data_size); |
|
|
|
if((size_t)bytes != offsetof(packet,data) + p->data_size) |
|
|
|
size_t data_size = p->data_size*HTIF_DATA_ALIGN; |
|
|
|
size_t bytes = write(tohost_fd, p, offsetof(packet,data) + data_size); |
|
|
|
if(bytes != offsetof(packet,data) + data_size) |
|
|
|
{ |
|
|
|
const char* error = bytes == -1 ? strerror(errno) : "not all bytes sent"; |
|
|
|
const char* error = (ssize_t)bytes == -1 ? strerror(errno) : "not all bytes sent"; |
|
|
|
fprintf(stderr,"HTIF error: %s\n", error); |
|
|
|
exit(-1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void htif_t::nack(uint16_t nack_seqno) |
|
|
|
void htif_t::nack(uint8_t nack_seqno) |
|
|
|
{ |
|
|
|
packet p = {APP_CMD_NACK,nack_seqno,0,0}; |
|
|
|
packet p = {APP_CMD_NACK,0,nack_seqno,0}; |
|
|
|
send_packet(&p); |
|
|
|
} |
|
|
|
|
|
|
|
@ -110,7 +112,7 @@ int htif_t::wait_for_packet() |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
packet ackpacket = {APP_CMD_ACK,seqno,0,0}; |
|
|
|
packet ackpacket = {APP_CMD_ACK,0,seqno,0}; |
|
|
|
|
|
|
|
switch(p.cmd) |
|
|
|
{ |
|
|
|
@ -120,34 +122,32 @@ int htif_t::wait_for_packet() |
|
|
|
sim->stop(); |
|
|
|
break; |
|
|
|
case APP_CMD_READ_MEM: |
|
|
|
assert(p.addr % APP_DATA_ALIGN == 0); |
|
|
|
assert(p.data_size % APP_DATA_ALIGN == 0); |
|
|
|
assert(p.data_size <= APP_MAX_DATA_SIZE); |
|
|
|
assert(p.addr <= sim->memsz && p.addr+p.data_size <= sim->memsz); |
|
|
|
assert(p.data_size <= APP_MAX_DATA_SIZE/HTIF_DATA_ALIGN); |
|
|
|
assert(p.addr < sim->memsz/HTIF_DATA_ALIGN); |
|
|
|
assert(p.addr+p.data_size <= sim->memsz/HTIF_DATA_ALIGN); |
|
|
|
ackpacket.data_size = p.data_size; |
|
|
|
|
|
|
|
static_assert(APP_DATA_ALIGN >= sizeof(uint64_t)) |
|
|
|
for(size_t i = 0; i < p.data_size/8; i++) |
|
|
|
((uint64_t*)ackpacket.data)[i] = sim->mmu->load_uint64(p.addr+i*8); |
|
|
|
assert(HTIF_DATA_ALIGN == sizeof(uint64_t)); |
|
|
|
for(size_t i = 0; i < p.data_size; i++) |
|
|
|
((uint64_t*)ackpacket.data)[i] = sim->mmu->load_uint64((p.addr+i)*HTIF_DATA_ALIGN); |
|
|
|
break; |
|
|
|
case APP_CMD_WRITE_MEM: |
|
|
|
assert(p.addr % APP_DATA_ALIGN == 0); |
|
|
|
assert(p.data_size % APP_DATA_ALIGN == 0); |
|
|
|
assert(p.data_size <= bytes - offsetof(packet,data)); |
|
|
|
assert(p.addr <= sim->memsz && p.addr+p.data_size <= sim->memsz); |
|
|
|
assert(p.data_size*HTIF_DATA_ALIGN <= bytes - offsetof(packet,data)); |
|
|
|
assert(p.addr < sim->memsz/HTIF_DATA_ALIGN); |
|
|
|
assert(p.addr+p.data_size <= sim->memsz/HTIF_DATA_ALIGN); |
|
|
|
|
|
|
|
for(size_t i = 0; i < p.data_size/8; i++) |
|
|
|
sim->mmu->store_uint64(p.addr+i*8, ((uint64_t*)p.data)[i]); |
|
|
|
for(size_t i = 0; i < p.data_size; i++) |
|
|
|
sim->mmu->store_uint64((p.addr+i)*HTIF_DATA_ALIGN, ((uint64_t*)p.data)[i]); |
|
|
|
break; |
|
|
|
case APP_CMD_READ_CONTROL_REG: |
|
|
|
assert(p.addr == 16); |
|
|
|
assert(p.data_size == sizeof(reg_t)); |
|
|
|
ackpacket.data_size = sizeof(reg_t); |
|
|
|
assert(p.data_size == 1); |
|
|
|
ackpacket.data_size = 1; |
|
|
|
memcpy(ackpacket.data,&sim->tohost,sizeof(reg_t)); |
|
|
|
break; |
|
|
|
case APP_CMD_WRITE_CONTROL_REG: |
|
|
|
assert(p.addr == 17); |
|
|
|
assert(p.data_size == sizeof(reg_t)); |
|
|
|
assert(p.data_size == 1); |
|
|
|
sim->tohost = 0; |
|
|
|
memcpy(&sim->fromhost,p.data,sizeof(reg_t)); |
|
|
|
break; |
|
|
|
|