mirror of
https://github.com/ringtailsoftware/uvm32.git
synced 2026-06-05 22:43:39 +00:00
Handle 8, 16 and 32 bit accesses to extram.
This commit is contained in:
parent
63386f9a92
commit
7a1656ab10
5 changed files with 163 additions and 12 deletions
|
|
@ -13,19 +13,36 @@ void main(void) {
|
||||||
} break;
|
} break;
|
||||||
case TEST2: {
|
case TEST2: {
|
||||||
uint32_t *p = (uint32_t *)UVM32_EXTRAM_BASE;
|
uint32_t *p = (uint32_t *)UVM32_EXTRAM_BASE;
|
||||||
printdec(p[32]); // past the end
|
printdec(p[32]); // word read
|
||||||
} break;
|
} break;
|
||||||
case TEST3: {
|
case TEST3: {
|
||||||
uint32_t *p = (uint32_t *)UVM32_EXTRAM_BASE;
|
uint32_t *p = (uint32_t *)UVM32_EXTRAM_BASE;
|
||||||
p[32] = 1234; // past the end
|
p[32] = 1234; // past the end, out of bounds
|
||||||
} break;
|
} break;
|
||||||
case TEST4: {
|
case TEST4: {
|
||||||
uint32_t *p = (uint32_t *)UVM32_EXTRAM_BASE;
|
uint32_t *p = (uint32_t *)UVM32_EXTRAM_BASE;
|
||||||
p[0] = 1234; // good write
|
p[0] = 1234; // word write
|
||||||
yield(0);
|
yield(0);
|
||||||
} break;
|
} break;
|
||||||
|
case TEST5: {
|
||||||
|
uint8_t *p = (uint8_t *)UVM32_EXTRAM_BASE;
|
||||||
|
p[7] = 0xAB; // single byte write
|
||||||
|
yield(0);
|
||||||
|
} break;
|
||||||
|
case TEST6: {
|
||||||
|
uint8_t *p = (uint8_t *)UVM32_EXTRAM_BASE;
|
||||||
|
printdec(p[7]); // single byte read
|
||||||
|
} break;
|
||||||
|
case TEST7: {
|
||||||
|
uint16_t *p = (uint16_t *)UVM32_EXTRAM_BASE;
|
||||||
|
p[7] = 0xABCD; // short write
|
||||||
|
yield(0);
|
||||||
|
} break;
|
||||||
|
case TEST8: {
|
||||||
|
uint16_t *p = (uint16_t *)UVM32_EXTRAM_BASE;
|
||||||
|
printdec(p[7]); // short read
|
||||||
|
} break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,5 +6,11 @@ enum {
|
||||||
TEST2,
|
TEST2,
|
||||||
TEST3,
|
TEST3,
|
||||||
TEST4,
|
TEST4,
|
||||||
|
TEST5,
|
||||||
|
TEST6,
|
||||||
|
TEST7,
|
||||||
|
TEST8,
|
||||||
|
TEST9,
|
||||||
|
TEST10,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -97,3 +97,96 @@ void test_extram_out_of_bounds_dirty_flag(void) {
|
||||||
TEST_ASSERT_EQUAL(false, uvm32_extramDirty(&vmst));
|
TEST_ASSERT_EQUAL(false, uvm32_extramDirty(&vmst));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_extram_byte_write(void) {
|
||||||
|
// run the vm
|
||||||
|
uvm32_run(&vmst, &evt, 100);
|
||||||
|
TEST_ASSERT_EQUAL(false, uvm32_extramDirty(&vmst));
|
||||||
|
|
||||||
|
// check for picktest syscall
|
||||||
|
TEST_ASSERT_EQUAL(evt.typ, UVM32_EVT_SYSCALL);
|
||||||
|
TEST_ASSERT_EQUAL(evt.data.syscall.code, SYSCALL_PICKTEST);
|
||||||
|
uvm32_setval(&vmst, &evt, RET, TEST5);
|
||||||
|
|
||||||
|
uvm32_run(&vmst, &evt, 100);
|
||||||
|
TEST_ASSERT_EQUAL(true, uvm32_extramDirty(&vmst));
|
||||||
|
|
||||||
|
// check that byte 7 only of extram has changed
|
||||||
|
uint8_t *p = (uint8_t *)extram;
|
||||||
|
for (int i=0;i<sizeof(extram);i++) {
|
||||||
|
if (i == 7) {
|
||||||
|
TEST_ASSERT_EQUAL(0xAB, p[i]);
|
||||||
|
} else {
|
||||||
|
TEST_ASSERT_EQUAL(0x00, p[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_extram_byte_read(void) {
|
||||||
|
// run the vm
|
||||||
|
uvm32_run(&vmst, &evt, 100);
|
||||||
|
TEST_ASSERT_EQUAL(false, uvm32_extramDirty(&vmst));
|
||||||
|
|
||||||
|
// check for picktest syscall
|
||||||
|
TEST_ASSERT_EQUAL(evt.typ, UVM32_EVT_SYSCALL);
|
||||||
|
TEST_ASSERT_EQUAL(evt.data.syscall.code, SYSCALL_PICKTEST);
|
||||||
|
uvm32_setval(&vmst, &evt, RET, TEST6);
|
||||||
|
|
||||||
|
// set only byte 7 in extram
|
||||||
|
uint8_t *p = (uint8_t *)extram;
|
||||||
|
p[7] = 0xCD;
|
||||||
|
|
||||||
|
uvm32_run(&vmst, &evt, 100);
|
||||||
|
TEST_ASSERT_EQUAL(false, uvm32_extramDirty(&vmst));
|
||||||
|
// check for printdec of val
|
||||||
|
TEST_ASSERT_EQUAL(UVM32_EVT_SYSCALL, evt.typ);
|
||||||
|
TEST_ASSERT_EQUAL(evt.data.syscall.code, UVM32_SYSCALL_PRINTDEC);
|
||||||
|
TEST_ASSERT_EQUAL(0xCD, uvm32_getval(&vmst, &evt, ARG0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_extram_short_write(void) {
|
||||||
|
// run the vm
|
||||||
|
uvm32_run(&vmst, &evt, 100);
|
||||||
|
TEST_ASSERT_EQUAL(false, uvm32_extramDirty(&vmst));
|
||||||
|
|
||||||
|
// check for picktest syscall
|
||||||
|
TEST_ASSERT_EQUAL(evt.typ, UVM32_EVT_SYSCALL);
|
||||||
|
TEST_ASSERT_EQUAL(evt.data.syscall.code, SYSCALL_PICKTEST);
|
||||||
|
uvm32_setval(&vmst, &evt, RET, TEST7);
|
||||||
|
|
||||||
|
uvm32_run(&vmst, &evt, 100);
|
||||||
|
TEST_ASSERT_EQUAL(true, uvm32_extramDirty(&vmst));
|
||||||
|
|
||||||
|
// check that short 7 only of extram has changed
|
||||||
|
uint16_t *p = (uint16_t *)extram;
|
||||||
|
for (int i=0;i<sizeof(extram);i++) {
|
||||||
|
if (i == 7) {
|
||||||
|
TEST_ASSERT_EQUAL(0xABCD, p[i]);
|
||||||
|
} else {
|
||||||
|
TEST_ASSERT_EQUAL(0x00, p[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_extram_short_read(void) {
|
||||||
|
// run the vm
|
||||||
|
uvm32_run(&vmst, &evt, 100);
|
||||||
|
TEST_ASSERT_EQUAL(false, uvm32_extramDirty(&vmst));
|
||||||
|
|
||||||
|
// check for picktest syscall
|
||||||
|
TEST_ASSERT_EQUAL(evt.typ, UVM32_EVT_SYSCALL);
|
||||||
|
TEST_ASSERT_EQUAL(evt.data.syscall.code, SYSCALL_PICKTEST);
|
||||||
|
uvm32_setval(&vmst, &evt, RET, TEST8);
|
||||||
|
|
||||||
|
// set only short 7 in extram
|
||||||
|
uint16_t *p = (uint16_t *)extram;
|
||||||
|
p[7] = 0xCDEF;
|
||||||
|
|
||||||
|
uvm32_run(&vmst, &evt, 100);
|
||||||
|
TEST_ASSERT_EQUAL(false, uvm32_extramDirty(&vmst));
|
||||||
|
// check for printdec of val
|
||||||
|
TEST_ASSERT_EQUAL(UVM32_EVT_SYSCALL, evt.typ);
|
||||||
|
TEST_ASSERT_EQUAL(evt.data.syscall.code, UVM32_SYSCALL_PRINTDEC);
|
||||||
|
TEST_ASSERT_EQUAL(0xCDEF, uvm32_getval(&vmst, &evt, ARG0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -326,12 +326,34 @@ uvm32_evt_syscall_buf_t uvm32_getbuf_fixed(uvm32_state_t *vmst, uvm32_evt_t *evt
|
||||||
return scb;
|
return scb;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t uvm32_extramLoad(void *userdata, uint32_t addr) {
|
uint32_t uvm32_extramLoad(void *userdata, uint32_t addr, uint32_t accessTyp) {
|
||||||
|
|
||||||
uvm32_state_t *vmst = (uvm32_state_t *)userdata;
|
uvm32_state_t *vmst = (uvm32_state_t *)userdata;
|
||||||
addr -= UVM32_EXTRAM_BASE;
|
addr -= UVM32_EXTRAM_BASE;
|
||||||
|
|
||||||
if (vmst->extram != UVM32_NULL) {
|
if (vmst->extram != UVM32_NULL) {
|
||||||
if (addr < vmst->extramLen) {
|
if (addr < vmst->extramLen) {
|
||||||
return ((uint32_t *)vmst->extram)[addr / 4];
|
switch(accessTyp) {
|
||||||
|
case 0:
|
||||||
|
return ((int8_t *)vmst->extram)[addr];
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
return ((int16_t *)vmst->extram)[addr/2];
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
return ((uint32_t *)vmst->extram)[addr / 4];
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
return ((uint8_t *)vmst->extram)[addr];
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
return ((uint16_t *)vmst->extram)[addr/2];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
setStatusErr(vmst, UVM32_ERR_MEM_RD);
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
setStatusErr(vmst, UVM32_ERR_MEM_RD);
|
setStatusErr(vmst, UVM32_ERR_MEM_RD);
|
||||||
}
|
}
|
||||||
|
|
@ -339,12 +361,25 @@ uint32_t uvm32_extramLoad(void *userdata, uint32_t addr) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t uvm32_extramStore(void *userdata, uint32_t addr, uint32_t val ) {
|
uint32_t uvm32_extramStore(void *userdata, uint32_t addr, uint32_t val, uint32_t accessTyp) {
|
||||||
uvm32_state_t *vmst = (uvm32_state_t *)userdata;
|
uvm32_state_t *vmst = (uvm32_state_t *)userdata;
|
||||||
addr -= UVM32_EXTRAM_BASE;
|
addr -= UVM32_EXTRAM_BASE;
|
||||||
if (vmst->extram != UVM32_NULL) {
|
if (vmst->extram != UVM32_NULL) {
|
||||||
if (addr < vmst->extramLen) {
|
if (addr < vmst->extramLen) {
|
||||||
((uint32_t *)vmst->extram)[addr / 4] = val;
|
switch(accessTyp) {
|
||||||
|
case 0:
|
||||||
|
((uint8_t *)vmst->extram)[addr] = val;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
((uint16_t *)vmst->extram)[addr/2] = val;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
((uint32_t *)vmst->extram)[addr/4] = val;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
setStatusErr(vmst, UVM32_ERR_MEM_WR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
vmst->extramDirty = true;
|
vmst->extramDirty = true;
|
||||||
} else {
|
} else {
|
||||||
setStatusErr(vmst, UVM32_ERR_MEM_WR);
|
setStatusErr(vmst, UVM32_ERR_MEM_WR);
|
||||||
|
|
|
||||||
|
|
@ -55,10 +55,10 @@ typedef struct {
|
||||||
#define MINIRV32_DECORATE static
|
#define MINIRV32_DECORATE static
|
||||||
#define MINI_RV32_RAM_SIZE UVM32_MEMORY_SIZE
|
#define MINI_RV32_RAM_SIZE UVM32_MEMORY_SIZE
|
||||||
#define MINIRV32_POSTEXEC(pc, ir, retval) {if (retval > 0) return retval;}
|
#define MINIRV32_POSTEXEC(pc, ir, retval) {if (retval > 0) return retval;}
|
||||||
uint32_t uvm32_extramLoad(void *userdata, uint32_t addr);
|
uint32_t uvm32_extramLoad(void *userdata, uint32_t addr, uint32_t accessTyp);
|
||||||
uint32_t uvm32_extramStore(void *userdata, uint32_t addr, uint32_t val);
|
uint32_t uvm32_extramStore(void *userdata, uint32_t addr, uint32_t val, uint32_t accessTyp);
|
||||||
#define MINIRV32_HANDLE_MEM_LOAD_CONTROL( addy, rval ) rval = uvm32_extramLoad(userdata, addy);
|
#define MINIRV32_HANDLE_MEM_LOAD_CONTROL( addy, rval ) rval = uvm32_extramLoad(userdata, addy, ( ir >> 12 ) & 0x7);
|
||||||
#define MINIRV32_HANDLE_MEM_STORE_CONTROL( addy, val ) if( uvm32_extramStore(userdata, addy, val) ) return val;
|
#define MINIRV32_HANDLE_MEM_STORE_CONTROL( addy, val ) if( uvm32_extramStore(userdata, addy, val, ( ir >> 12 ) & 0x7) ) return val;
|
||||||
|
|
||||||
#ifndef MINIRV32_IMPLEMENTATION
|
#ifndef MINIRV32_IMPLEMENTATION
|
||||||
#define MINIRV32_STEPPROTO
|
#define MINIRV32_STEPPROTO
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue