|
|
|
@ -20,9 +20,9 @@ type PageErrorHandler interface { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type MMU struct { |
|
|
|
|
module *Module |
|
|
|
|
PageTable PageTable |
|
|
|
|
LoadedPages []*Page |
|
|
|
|
Registers []float64 // 4k registers
|
|
|
|
|
|
|
|
|
|
// pseudo hard drive which holds all pages
|
|
|
|
|
drive map[uint16][]float64 |
|
|
|
@ -38,7 +38,7 @@ func (address Address) Offset() uint16 { |
|
|
|
|
return uint16(address) & 0x03FF |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func NewMMU(pageErrorHandler PageErrorHandler) *MMU { |
|
|
|
|
func NewMMU(module *Module, pageErrorHandler PageErrorHandler) *MMU { |
|
|
|
|
pageCount := uint16(PageSize / 16) |
|
|
|
|
drive := make(map[uint16][]float64) |
|
|
|
|
pageTable := make(PageTable) |
|
|
|
@ -51,9 +51,9 @@ func NewMMU(pageErrorHandler PageErrorHandler) *MMU { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return &MMU{ |
|
|
|
|
module: module, |
|
|
|
|
PageTable: pageTable, |
|
|
|
|
LoadedPages: make([]*Page, 0, 4), |
|
|
|
|
Registers: make([]float64, PageSize*4, PageSize*4), |
|
|
|
|
drive: drive, |
|
|
|
|
pageErrorHandler: pageErrorHandler, |
|
|
|
|
} |
|
|
|
@ -71,11 +71,11 @@ func (mmu *MMU) Read(address Address) float64 { |
|
|
|
|
// Page not loaded in "physical" register
|
|
|
|
|
if page.RegisterAddress == nil { |
|
|
|
|
// Page Error
|
|
|
|
|
mmu.pageErrorHandler(address, false) |
|
|
|
|
mmu.pageErrorHandler.handlePageError(address, false) |
|
|
|
|
mmu.Load(page) |
|
|
|
|
} |
|
|
|
|
page.Referenced = true |
|
|
|
|
return mmu.Registers[page.RegisterOffset()+int(address.Offset())] |
|
|
|
|
return mmu.module.register[page.RegisterOffset()+int(address.Offset())] |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (mmu *MMU) Write(address Address, content float64) { |
|
|
|
@ -90,11 +90,11 @@ func (mmu *MMU) Write(address Address, content float64) { |
|
|
|
|
// Page not loaded in "physical" register
|
|
|
|
|
if page.RegisterAddress == nil { |
|
|
|
|
// Page Error
|
|
|
|
|
mmu.pageErrorHandler(address, true) |
|
|
|
|
mmu.pageErrorHandler.handlePageError(address, true) |
|
|
|
|
mmu.Load(page) |
|
|
|
|
} |
|
|
|
|
page.Referenced = true |
|
|
|
|
mmu.Registers[page.RegisterOffset()+int(address.Offset())] = content |
|
|
|
|
mmu.module.register[page.RegisterOffset()+int(address.Offset())] = content |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
@ -123,7 +123,7 @@ func (mmu *MMU) Load(page *Page) { |
|
|
|
|
|
|
|
|
|
func (mmu *MMU) findEmptyRegisterAddress() *uint16 { |
|
|
|
|
var i uint16 |
|
|
|
|
for i = 0; i < uint16(len(mmu.Registers)/PageSize); i++ { |
|
|
|
|
for i = 0; i < uint16(len(mmu.module.register)/PageSize); i++ { |
|
|
|
|
for _, loadedPage := range mmu.LoadedPages { |
|
|
|
|
if *loadedPage.RegisterAddress == i { |
|
|
|
|
continue |
|
|
|
@ -138,7 +138,7 @@ func (mmu *MMU) findEmptyRegisterAddress() *uint16 { |
|
|
|
|
func (mmu *MMU) movePageToDrive(page *Page) { |
|
|
|
|
|
|
|
|
|
for i := 0; i < PageSize-1; i++ { |
|
|
|
|
mmu.drive[page.PageNumber][i] = mmu.Registers[i+page.RegisterOffset()] |
|
|
|
|
mmu.drive[page.PageNumber][i] = mmu.module.register[i+page.RegisterOffset()] |
|
|
|
|
} |
|
|
|
|
page.Referenced = false |
|
|
|
|
page.RegisterAddress = nil |
|
|
|
@ -146,7 +146,7 @@ func (mmu *MMU) movePageToDrive(page *Page) { |
|
|
|
|
|
|
|
|
|
func (mmu *MMU) loadPageFromDrive(page *Page) { |
|
|
|
|
for i := 0; i < PageSize-1; i++ { |
|
|
|
|
mmu.Registers[i+page.RegisterOffset()] = mmu.drive[page.PageNumber][i] |
|
|
|
|
mmu.module.register[i+page.RegisterOffset()] = mmu.drive[page.PageNumber][i] |
|
|
|
|
} |
|
|
|
|
page.RegisterAddress = mmu.findEmptyRegisterAddress() |
|
|
|
|
} |
|
|
|
|