cpu: separate into cpu/cmd/test/world files
This commit is contained in:
parent
647998df5e
commit
8fe73f0c2d
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,2 +1 @@
|
|||||||
riscvemu
|
cmd/riscvrun/riscvrun
|
||||||
riscvemu.debug
|
|
||||||
|
43
cmd/riscvrun/main.go
Normal file
43
cmd/riscvrun/main.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"riscvemu"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
memorySize := flag.Int("MemorySize", 4096, "Memory size (bytes)")
|
||||||
|
loadAddress := flag.Int("LoadAddress", 0, "Load address and initial progRam counter")
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
files := flag.Args()
|
||||||
|
if len(files) != 1 {
|
||||||
|
flag.Usage()
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
sw := riscvemu.MemoryWorld{
|
||||||
|
Ram: make([]byte, *memorySize),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy file into working memory
|
||||||
|
fb, err := ioutil.ReadFile(files[0])
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
copy(sw.Ram[*loadAddress:*loadAddress+len(fb)], fb)
|
||||||
|
|
||||||
|
c := riscvemu.NewCPU(&sw)
|
||||||
|
c.Pc = uint32(*loadAddress)
|
||||||
|
|
||||||
|
for {
|
||||||
|
err := c.Step()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package main
|
package riscvemu
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -14,6 +14,10 @@ type CPUState struct {
|
|||||||
w World
|
w World
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewCPU(w World) CPUState {
|
||||||
|
return CPUState{w: w}
|
||||||
|
}
|
||||||
|
|
||||||
func opcode_rd(opcode uint32) uint32 { return (opcode >> 7) & 0b11111 }
|
func opcode_rd(opcode uint32) uint32 { return (opcode >> 7) & 0b11111 }
|
||||||
func opcode_rs1(opcode uint32) uint32 { return (opcode >> 15) & 0b11111 } // 2^5 is 32 for 32 registers
|
func opcode_rs1(opcode uint32) uint32 { return (opcode >> 15) & 0b11111 } // 2^5 is 32 for 32 registers
|
||||||
func opcode_rs2(opcode uint32) uint32 { return (opcode >> 19) & 0b11111 }
|
func opcode_rs2(opcode uint32) uint32 { return (opcode >> 19) & 0b11111 }
|
||||||
@ -27,7 +31,7 @@ func (c *CPUState) ReadRegister(r uint32) uint32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *CPUState) Step() error {
|
func (c *CPUState) Step() error {
|
||||||
opcode, err := c.w.ReadMemory(c.Pc)
|
opcode, err := c.w.Read32(c.Pc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("ReadMemory: %w", err)
|
return fmt.Errorf("ReadMemory: %w", err)
|
||||||
}
|
}
|
||||||
@ -164,51 +168,3 @@ func (c *CPUState) Step() error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type World interface {
|
|
||||||
ReadMemory(addr uint32) (uint32, error)
|
|
||||||
WriteMemory(addr, value uint32) error
|
|
||||||
Syscall()
|
|
||||||
Trap() (bool, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type SampleWorld struct {
|
|
||||||
ram [1024]uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sw *SampleWorld) ReadMemory(addr uint32) (uint32, error) {
|
|
||||||
if addr >= uint32(len(sw.ram)) {
|
|
||||||
panic("out of bounds")
|
|
||||||
}
|
|
||||||
|
|
||||||
return sw.ram[addr], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sw *SampleWorld) WriteMemory(addr, value uint32) error {
|
|
||||||
if addr >= uint32(len(sw.ram)) {
|
|
||||||
panic("out of bounds")
|
|
||||||
}
|
|
||||||
|
|
||||||
sw.ram[addr] = value
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sw *SampleWorld) Syscall() {
|
|
||||||
panic("syscall")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sw *SampleWorld) Trap() (bool, error) {
|
|
||||||
panic("trap")
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
sw := SampleWorld{}
|
|
||||||
sw.ram[0] = 0b00000000000100000000000001110011 // EBREAK
|
|
||||||
|
|
||||||
c := CPUState{
|
|
||||||
w: &sw,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := c.Step()
|
|
||||||
panic(err)
|
|
||||||
}
|
|
21
cpu_test.go
Normal file
21
cpu_test.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package riscvemu
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCPU(t *testing.T) {
|
||||||
|
|
||||||
|
sw := MemoryWorld{
|
||||||
|
Ram: make([]byte, 1024),
|
||||||
|
}
|
||||||
|
_ = sw.Write32(0, 0b00000000000100000000000001110011) // EBREAK
|
||||||
|
|
||||||
|
c := CPUState{
|
||||||
|
w: &sw,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := c.Step()
|
||||||
|
panic(err)
|
||||||
|
|
||||||
|
}
|
45
memoryWorld.go
Normal file
45
memoryWorld.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package riscvemu
|
||||||
|
|
||||||
|
type MemoryWorld struct {
|
||||||
|
Ram []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mw *MemoryWorld) ReadByte(addr uint32) (byte, error) {
|
||||||
|
if addr >= uint32(len(mw.Ram)) {
|
||||||
|
panic("out of bounds")
|
||||||
|
}
|
||||||
|
|
||||||
|
return mw.Ram[addr], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mw *MemoryWorld) Read32(addr uint32) (uint32, error) {
|
||||||
|
// n.b. will panic on overflow
|
||||||
|
return (uint32(mw.Ram[addr]) << 24) | (uint32(mw.Ram[addr+1]) << 16) | (uint32(mw.Ram[addr+2]) << 8) | uint32(mw.Ram[addr+3]), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mw *MemoryWorld) WriteByte(addr uint32, value byte) error {
|
||||||
|
if addr >= uint32(len(mw.Ram)) {
|
||||||
|
panic("out of bounds")
|
||||||
|
}
|
||||||
|
|
||||||
|
mw.Ram[addr] = value
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mw *MemoryWorld) Write32(addr, value uint32) error {
|
||||||
|
// n.b. will panic on overflow
|
||||||
|
mw.Ram[addr] = byte((value >> 24) & 0b11111111)
|
||||||
|
mw.Ram[addr+1] = byte((value >> 16) & 0b11111111)
|
||||||
|
mw.Ram[addr+2] = byte((value >> 8) & 0b11111111)
|
||||||
|
mw.Ram[addr+3] = byte(value & 0b11111111)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mw *MemoryWorld) Syscall() {
|
||||||
|
panic("syscall")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mw *MemoryWorld) Trap() (bool, error) {
|
||||||
|
panic("trap")
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user