diff --git a/cmd/cluster.go b/cmd/cluster.go index 3c1633b..08d49c1 100644 --- a/cmd/cluster.go +++ b/cmd/cluster.go @@ -37,8 +37,14 @@ func runClusterCommand(cmd *cobra.Command, args []string) error { return err } + logger, err := hal.NewPageErrorLogger("page_errors") + if err != nil { + return err + } + defer logger.Close() + // Parse modules - modules, err := parser.GetModulesFromConfig(config, debug) + modules, err := parser.GetModulesFromConfig(config, debug, logger) if err != nil { return err } diff --git a/cmd/root.go b/cmd/root.go index 0c8f04b..d739566 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -45,7 +45,12 @@ func runRootCommand(cmd *cobra.Command, args []string) error { if err != nil { return err } - module, err := hal.NewHALModule(program, 256, 2, debug) + logger, err := hal.NewPageErrorLogger("page_errors") + if err != nil { + return err + } + defer logger.Close() + module, err := hal.NewHALModule(program, 256, 2, debug, logger) if err != nil { return err } diff --git a/hal/module.go b/hal/module.go index bc42034..7980f8c 100644 --- a/hal/module.go +++ b/hal/module.go @@ -12,6 +12,8 @@ type IO interface { } type Module struct { + mmu *MMU + pCounter int64 accumulator float64 programStorage Program register []float64 @@ -24,10 +26,10 @@ type Module struct { } func (h *Module) programCounter() int64 { - return int64(h.register[0]) + return h.pCounter } func (h *Module) setProgramCounter(counter int64) error { - h.register[0] = float64(counter) + h.pCounter = counter if _, ok := h.programStorage[counter]; !ok { return fmt.Errorf("index %d does not exist in program storage", counter) } @@ -74,11 +76,11 @@ func (h *Module) Run() error { return nil } -func NewHALModule(program Program, registerSize uint64, ioSize int64, debug bool) (*Module, error) { - return NewNamedHALModule(program, registerSize, ioSize, debug, "") +func NewHALModule(program Program, registerSize uint64, ioSize int64, debug bool, handler PageErrorHandler) (*Module, error) { + return NewNamedHALModule(program, registerSize, ioSize, debug, "", handler) } -func NewNamedHALModule(program Program, registerSize uint64, ioSize int64, debug bool, name string) (*Module, error) { +func NewNamedHALModule(program Program, registerSize uint64, ioSize int64, debug bool, name string, handler PageErrorHandler) (*Module, error) { if registerSize <= 10 { return nil, fmt.Errorf("register size must be greater then 10 [ registerSize = %d ]", registerSize) } @@ -89,11 +91,14 @@ func NewNamedHALModule(program Program, registerSize uint64, ioSize int64, debug for i := int64(0); i <= ioSize; i++ { ios[i] = NewCommandLineIO(i, name) } - return &Module{ + + module := &Module{ programStorage: program, register: make([]float64, registerSize), IO: ios, debugEnabled: debug, name: name, - }, nil + } + module.mmu = NewMMU(module, handler) + return module, nil } diff --git a/hal/page_error_logger.go b/hal/page_error_logger.go new file mode 100644 index 0000000..b92c7df --- /dev/null +++ b/hal/page_error_logger.go @@ -0,0 +1,26 @@ +package hal + +import ( + "fmt" + "os" + "time" +) + +type PageErrorLogger struct { + file *os.File +} + +func NewPageErrorLogger(path string) (logger *PageErrorLogger, err error) { + logger = new(PageErrorLogger) + os.Remove(path) + logger.file, err = os.Create(path) + return +} + +func (logger *PageErrorLogger) handlePageError(address Address, write bool) { + fmt.Fprintf(logger.file, "[timestamp = %s addr = 0x%X write=%t]", time.Now().String(), address, write) +} + +func (logger *PageErrorLogger) Close() error { + return logger.file.Close() +} diff --git a/hal/paging.go b/hal/paging.go index b4878b5..0edfea2 100644 --- a/hal/paging.go +++ b/hal/paging.go @@ -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() } diff --git a/parser/from_config.go b/parser/from_config.go index a0b451b..3eaf126 100644 --- a/parser/from_config.go +++ b/parser/from_config.go @@ -4,7 +4,7 @@ import ( "git.jfdev.de/JonasFranzDEV/hal/hal" ) -func GetModulesFromConfig(config *hal.ClusterConfig, debug bool) (modules map[string]*hal.Module, err error) { +func GetModulesFromConfig(config *hal.ClusterConfig, debug bool, handler hal.PageErrorHandler) (modules map[string]*hal.Module, err error) { // all modules with their name as key modules = make(map[string]*hal.Module) @@ -14,7 +14,7 @@ func GetModulesFromConfig(config *hal.ClusterConfig, debug bool) (modules map[st return nil, err } // By default, all IO is the standard IO, we'll override it with channels where needed. - modules[node.Name], err = hal.NewNamedHALModule(program, 256, 4, debug, node.Name) + modules[node.Name], err = hal.NewNamedHALModule(program, 256, 4, debug, node.Name, handler) if err != nil { return nil, err }