eei: implement paging-based eei
This commit is contained in:
parent
29a94dd442
commit
453e8b39e4
@ -9,8 +9,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
memorySize := flag.Int("MemorySize", 4096, "Memory size (bytes)")
|
loadAddress := flag.Int64("LoadAddress", 0, "Load address and initial program counter")
|
||||||
loadAddress := flag.Int("LoadAddress", 0, "Load address and initial progRam counter")
|
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
@ -20,9 +19,7 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
sw := riscvemu.VirtualEEI{
|
sw := riscvemu.NewVirtualEEI()
|
||||||
Ram: make([]byte, *memorySize),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy file into working memory
|
// Copy file into working memory
|
||||||
fb, err := ioutil.ReadFile(files[0])
|
fb, err := ioutil.ReadFile(files[0])
|
||||||
|
10
cpu_test.go
10
cpu_test.go
@ -6,14 +6,10 @@ import (
|
|||||||
|
|
||||||
func TestCPU(t *testing.T) {
|
func TestCPU(t *testing.T) {
|
||||||
|
|
||||||
sw := VirtualEEI{
|
env := NewVirtualEEI()
|
||||||
Ram: make([]byte, 1024),
|
_ = env.Write32(0, 0b00000000000100000000000001110011) // EBREAK
|
||||||
}
|
|
||||||
_ = sw.Write32(0, 0b00000000000100000000000001110011) // EBREAK
|
|
||||||
|
|
||||||
c := CPUState{
|
c := NewCPU(&env)
|
||||||
w: &sw,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := c.Step()
|
err := c.Step()
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -1,39 +1,64 @@
|
|||||||
package riscvemu
|
package riscvemu
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
type VirtualEEI struct {
|
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) {
|
func (ve *VirtualEEI) ReadByte(addr uint32) (byte, error) {
|
||||||
if addr >= uint32(len(ve.Ram)) {
|
page, _ := ve.memPages[addr>>12]
|
||||||
panic("out of bounds")
|
return page[addr&0b111111111111], nil
|
||||||
}
|
|
||||||
|
|
||||||
return ve.Ram[addr], nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ve *VirtualEEI) Read32(addr uint32) (uint32, error) {
|
func (ve *VirtualEEI) Read32(addr uint32) (uint32, error) {
|
||||||
// n.b. will panic on overflow
|
// n.b. will panic on overflow
|
||||||
// RISC-V allows 32-bit load/stores to be implemented as either little-endian
|
// RISC-V allows 32-bit load/stores to be implemented as either little-endian
|
||||||
// or big-endian. This is the little-endian version
|
// 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 {
|
func (ve *VirtualEEI) WriteByte(addr uint32, value byte) error {
|
||||||
if addr >= uint32(len(ve.Ram)) {
|
page, ok := ve.memPages[addr>>12]
|
||||||
panic("out of bounds")
|
|
||||||
|
// 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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ve *VirtualEEI) Write32(addr, value uint32) error {
|
func (ve *VirtualEEI) Write32(addr, value uint32) error {
|
||||||
// n.b. will panic on overflow
|
// n.b. will panic on overflow
|
||||||
ve.Ram[addr] = byte((value >> 24) & 0b11111111)
|
|
||||||
ve.Ram[addr+1] = byte((value >> 16) & 0b11111111)
|
page, ok := ve.memPages[addr>>12]
|
||||||
ve.Ram[addr+2] = byte((value >> 8) & 0b11111111)
|
inPageAddr := addr & 0b111111111111
|
||||||
ve.Ram[addr+3] = byte(value & 0b11111111)
|
|
||||||
|
// 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
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user