From 453e8b39e400047889d6217d0eadc8944b9820bb Mon Sep 17 00:00:00 2001 From: mappu Date: Wed, 28 Dec 2022 14:11:07 +1300 Subject: [PATCH] eei: implement paging-based eei --- cmd/riscvrun/main.go | 7 ++---- cpu_test.go | 10 +++------ virtualEei.go | 53 ++++++++++++++++++++++++++++++++------------ 3 files changed, 44 insertions(+), 26 deletions(-) diff --git a/cmd/riscvrun/main.go b/cmd/riscvrun/main.go index 2e59675..dffac15 100644 --- a/cmd/riscvrun/main.go +++ b/cmd/riscvrun/main.go @@ -9,8 +9,7 @@ import ( ) func main() { - memorySize := flag.Int("MemorySize", 4096, "Memory size (bytes)") - loadAddress := flag.Int("LoadAddress", 0, "Load address and initial progRam counter") + loadAddress := flag.Int64("LoadAddress", 0, "Load address and initial program counter") flag.Parse() @@ -20,9 +19,7 @@ func main() { os.Exit(1) } - sw := riscvemu.VirtualEEI{ - Ram: make([]byte, *memorySize), - } + sw := riscvemu.NewVirtualEEI() // Copy file into working memory fb, err := ioutil.ReadFile(files[0]) diff --git a/cpu_test.go b/cpu_test.go index c9a58e0..71ce102 100644 --- a/cpu_test.go +++ b/cpu_test.go @@ -6,14 +6,10 @@ import ( func TestCPU(t *testing.T) { - sw := VirtualEEI{ - Ram: make([]byte, 1024), - } - _ = sw.Write32(0, 0b00000000000100000000000001110011) // EBREAK + env := NewVirtualEEI() + _ = env.Write32(0, 0b00000000000100000000000001110011) // EBREAK - c := CPUState{ - w: &sw, - } + c := NewCPU(&env) err := c.Step() panic(err) diff --git a/virtualEei.go b/virtualEei.go index 1ace7ac..0c82df9 100644 --- a/virtualEei.go +++ b/virtualEei.go @@ -1,39 +1,64 @@ package riscvemu +import ( + "math" + "os" +) + type VirtualEEI struct { - Ram []byte + memPages map[uint32][4096]byte +} + +func NewVirtualEEI() VirtualEEI { + return VirtualEEI{ + memPages: make(map[uint32][4096]byte), + } } func (ve *VirtualEEI) ReadByte(addr uint32) (byte, error) { - if addr >= uint32(len(ve.Ram)) { - panic("out of bounds") - } - - return ve.Ram[addr], nil + page, _ := ve.memPages[addr>>12] + return page[addr&0b111111111111], nil } func (ve *VirtualEEI) Read32(addr uint32) (uint32, error) { // n.b. will panic on overflow // RISC-V allows 32-bit load/stores to be implemented as either little-endian // or big-endian. This is the little-endian version - return (uint32(ve.Ram[addr]) << 24) | (uint32(ve.Ram[addr+1]) << 16) | (uint32(ve.Ram[addr+2]) << 8) | uint32(ve.Ram[addr+3]), nil + + page, _ := ve.memPages[addr>>12] + inPageAddr := addr & 0b111111111111 + + return (uint32(page[inPageAddr]) << 24) | (uint32(page[inPageAddr+1]) << 16) | (uint32(page[inPageAddr+2]) << 8) | uint32(page[inPageAddr+3]), nil } func (ve *VirtualEEI) WriteByte(addr uint32, value byte) error { - if addr >= uint32(len(ve.Ram)) { - panic("out of bounds") + page, ok := ve.memPages[addr>>12] + + // Slices are reference-types, this will write-through into ve.memPages + page[addr&0b111111111111] = value + + if !ok { + ve.memPages[addr>>12] = page } - ve.Ram[addr] = value return nil } func (ve *VirtualEEI) Write32(addr, value uint32) error { // n.b. will panic on overflow - ve.Ram[addr] = byte((value >> 24) & 0b11111111) - ve.Ram[addr+1] = byte((value >> 16) & 0b11111111) - ve.Ram[addr+2] = byte((value >> 8) & 0b11111111) - ve.Ram[addr+3] = byte(value & 0b11111111) + + page, ok := ve.memPages[addr>>12] + inPageAddr := addr & 0b111111111111 + + // Slices are reference-types, this will write-through into ve.memPages + page[inPageAddr] = byte((value >> 24) & 0b11111111) + page[inPageAddr+1] = byte((value >> 16) & 0b11111111) + page[inPageAddr+2] = byte((value >> 8) & 0b11111111) + page[inPageAddr+3] = byte(value & 0b11111111) + + if !ok { + ve.memPages[addr>>12] = page + } return nil }