Skip to content

Commit

Permalink
wip impl devices
Browse files Browse the repository at this point in the history
  • Loading branch information
hidetatz committed Nov 28, 2022
1 parent b0837c2 commit ce646a7
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 57 deletions.
7 changes: 7 additions & 0 deletions clint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package main

type Clint struct{}

func NewClint() *Clint {
return nil
}
172 changes: 118 additions & 54 deletions cpu.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"io"
"math"
"math/big"
)
Expand All @@ -16,7 +17,7 @@ const (
xlen64 = 2

// memory size
byt = 8
byt = 8 // "byte" is reserved
halfword = 16
word = 32
doubleword = 64
Expand Down Expand Up @@ -94,6 +95,10 @@ const (
userExternalIntr = 8
supervisorExternalIntr = 9
machineExternalIntr = 11

// memory management
drambase = 0x8000_0000
dtbsize = 0xfe0
)

type trap struct {
Expand All @@ -115,7 +120,12 @@ type CPU struct {
fregs [32]float64
lrsc map[uint64]struct{}

ram *Memory
dtb [dtbsize]uint8
clint *Clint
disk *VirtIODisk
plic *Plic
ram *Memory
uart *Uart
}

func NewCPU() *CPU {
Expand All @@ -132,7 +142,13 @@ func NewCPU() *CPU {
fregs: [32]float64{},
lrsc: make(map[uint64]struct{}),

ram: NewMemory(),
// TODO: initialize device tree
dtb: [dtbsize]uint8{},
clint: NewClint(),
disk: NewVirtIODisk(),
plic: NewPlic(),
uart: NewUart(os.Stdout),
ram: NewMemory(),
}
}

Expand Down Expand Up @@ -295,7 +311,7 @@ func (cpu *CPU) fetch() (uint64, *trap) {
return 0, &trap{code: instPageFault, value: vAddr}
}

v := cpu.ram.Read(pa, word)
v := cpu.readRaw(pa, word)

return v, nil
}
Expand All @@ -315,82 +331,127 @@ func (cpu *CPU) fetch() (uint64, *trap) {
return data, nil
}

func (cpu *CPU) read(addr uint64, size int) (uint64, *trap) {
if size == byt {
eAddr := cpu.getEffectiveAddr(addr)
pAddr, excp := cpu.translate(eAddr, maLoad)
func (cpu *CPU) read(vaddr uint64, size int) (uint64, *trap) {
//if (vaddr & 0xfff) <= 0x1000-uint64(size/8) {
// paddr, excp := cpu.translate(vaddr, maLoad)
// if excp != nil {
// return 0, &trap{code: loadPageFault, value: vaddr}
// }

// return cpu.readRaw(paddr, size), nil
//}

data := uint64(0)
for i := 0; i < size/8; i++ {
eaddr := cpu.getEffectiveAddr(vaddr + uint64(i))
paddr, excp := cpu.translate(eaddr, maLoad)
if excp != nil {
return 0, &trap{code: loadPageFault, value: addr}
return 0, &trap{code: loadPageFault, value: vaddr}
}

return cpu.ram.Read(pAddr, byt), nil
v := cpu.readRaw(paddr, byt)
data |= v << (i * 8)
}

if (addr & 0xfff) <= 0x1000-uint64(size/8) {
eAddr := cpu.getEffectiveAddr(addr)
pAddr, excp := cpu.translate(eAddr, maLoad)
if excp != nil {
return 0, &trap{code: loadPageFault, value: addr}
}
return data, nil
}

func (cpu *CPU) readRaw(vaddr uint64, size int) uint64 {
eaddr := cpu.getEffectiveAddr(vaddr)

overflow := false
if size > byt {
overflow = eaddr+uint64(size/8-1) > eaddr
}

return cpu.ram.Read(pAddr, size), nil
if eaddr >= drambase && !overflow {
return cpu.ram.Read(eaddr, size)
}

data := uint64(0)
for i := uint64(0); i < uint64(size/8); i++ {
eAddr := cpu.getEffectiveAddr(addr + i)
pa, excp := cpu.translate(eAddr, maLoad)
if excp != nil {
return 0, &trap{code: loadPageFault, value: addr}
for i := 0; i < size/8; i++ {
a := eaddr + uint64(i)
d := 0
switch {
case 0x00001010 <= a && a < 0x00001fff:
d = uint64(cpu.dtb[a-0x1020])
case 0x02000000 <= a && a < 0x0200ffff:
d = cpu.clint.read(a)
case 0x0c000000 <= a && a < 0x0fffffff:
d = cpu.plic.read(a)
case 0x10000000 <= a && a < 0x10000fff:
d = cpu.uart.read(a)
case 0x10001000 <= a && a < 0x10001fff:
d = cpu.disk.read(a)
default:
panic("unknown mem seg")
}

v := cpu.ram.Read(pa, byt)
data |= v << (i * 8)
data |= d << (i * 8)
}

return data, nil
return data
}

func (cpu *CPU) write(addr, val uint64, size int) *trap {
func (cpu *CPU) write(vaddr, val uint64, size int) *trap {
// Cancel reserved memory to make SC fail when an write is called
// between LR and SC.
if cpu.reserved(addr) {
cpu.cancel(addr)
}

if size == byt {
eAddr := cpu.getEffectiveAddr(addr)
pAddr, excp := cpu.translate(eAddr, maStore)
//if cpu.reserved(addr) {
// cpu.cancel(addr)
//}

//if (addr & 0xfff) <= 0x1000-uint64(size/8) {
// eAddr := cpu.getEffectiveAddr(addr)
// pAddr, excp := cpu.translate(eAddr, maStore)
// if excp != nil {
// return &trap{code: storePageFault, value: addr}
// }

// cpu.ram.Write(pAddr, val, size)
//}

for i := 0; i < size/8; i++ {
a := vaddr + uint64(i)
v := (val >> (i * 8)) & 0xff
paddr, excp := cpu.translate(a, maStore)
if excp != nil {
return &trap{code: storePageFault, value: addr}
return &trap{code: storePageFault, value: a}
}

cpu.ram.Write(pAddr, val, byt)
cpu.writeRaw(paddr, v, byt)
}

// multiple bytes
return nil
}

if (addr & 0xfff) <= 0x1000-uint64(size/8) {
eAddr := cpu.getEffectiveAddr(addr)
pAddr, excp := cpu.translate(eAddr, maStore)
if excp != nil {
return &trap{code: storePageFault, value: addr}
}
func (cpu *CPU) writeRaw(addr, val uint64, size int) {
ea := cpu.getEffectiveAddr(addr)

cpu.ram.Write(pAddr, val, size)
overflow := false
if size > byt {
overflow = ea+uint64(size/8-1) > ea
}

for i := uint64(0); i < uint64(size/8); i++ {
eAddr := cpu.getEffectiveAddr(addr + i)
pa, excp := cpu.translate(eAddr, maStore)
if excp != nil {
return &trap{code: storePageFault, value: addr}
}

cpu.ram.Write(pa, (val>>(i*8))&0xff, byt)
if ea >= drambase && !overflow {
cpu.ram.Write(ea, val, size)
return
}

return nil
for i := 0; i < size/8; i++ {
v := (val >> (i * 8)) & 0xff
a := ea + uint64(i)
switch {
case 0x02000000 <= a && a < 0x0200ffff:
cpu.clint.write(a, v)
case 0x0c000000 <= a && a < 0x0fffffff:
cpu.plic.write(a, v)
case 0x10000000 <= a && a < 0x10000fff:
cpu.uart.write(a, v)
case 0x10001000 <= a && a < 0x10001fff:
cpu.disk.write(a, v)
default:
panic("unknown mem seg")
}
}
}

func (cpu *CPU) translate(vAddr uint64, ma int) (uint64, *trap) {
Expand Down Expand Up @@ -697,7 +758,10 @@ func (cpu *CPU) tick() {
cpu.handleExcp(excp, pc)
}

//cpu.ram.tick()
//cpu.clint.tick(cpu.rcsr(mip))
//cpu.disk.tick()
//cpu.uart.tick()
//cpu.plic.tick()
cpu.handleIntr(cpu.pc)
cpu.clock++
cpu.wcsr(cycle, cpu.clock*8)
Expand Down
9 changes: 6 additions & 3 deletions memory.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package main

const DramBase = 0x0
const (
dramBase = 0x80000000
dtbSize = 0xfe0
)

type Memory struct {
// 3GiB
Expand All @@ -12,7 +15,7 @@ func NewMemory() *Memory {
}

func (mem *Memory) Read(addr uint64, size int) uint64 {
index := addr - DramBase
index := addr - dramBase
switch size {
case byt:
return uint64(mem.Mem[index])
Expand All @@ -39,7 +42,7 @@ func (mem *Memory) Read(addr uint64, size int) uint64 {
}

func (mem *Memory) Write(addr, val uint64, size int) {
index := addr - DramBase
index := addr - dramBase
switch size {
case byt:
mem.Mem[index] = uint8(val)
Expand Down
7 changes: 7 additions & 0 deletions plic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package main

type Plic struct{}

func NewPlic() *Plic {
return nil
}
7 changes: 7 additions & 0 deletions uart.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package main

type Uart struct{}

func NewUart() *Uart {
return nil
}
7 changes: 7 additions & 0 deletions virtio.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package main

type VirtIODisk struct{}

func NewVirtIODisk() *VirtIODisk {
return nil
}

0 comments on commit ce646a7

Please sign in to comment.