You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
hal/hal/module.go

105 lines
2.6 KiB

package hal
import "fmt"
const maxInstructions = 10000
type Program map[int64]*ProgrammedInstruction
type IO interface {
Read() (float64, error)
Write(output float64) error
}
type Module struct {
mmu *MMU
pCounter int64
accumulator float64
programStorage Program
register []float64
IO map[int64]IO
pageTable *PageTable
isStopped bool
debugEnabled bool
name string // Used to print the module name when debugging
}
func (h *Module) programCounter() int64 {
return h.pCounter
}
func (h *Module) setProgramCounter(counter int64) error {
h.pCounter = counter
if _, ok := h.programStorage[counter]; !ok {
return fmt.Errorf("index %d does not exist in program storage", counter)
}
return nil
}
func (h *Module) increaseProgramCounter() {
h.pCounter++
}
func (h *Module) debug(format string, args ...interface{}) {
if !h.debugEnabled {
return
}
fmt.Printf("[DEBUG] ["+h.name+"] "+format+"\n", args...)
}
func (h *Module) Step() error {
instruction := h.programStorage[h.programCounter()]
h.increaseProgramCounter()
if instruction == nil {
//h.debug("Skip undefined instruction %d", h.programCounter())
return nil
}
h.debug("Instruction: %s", instruction.Instruction.Name)
h.debug("Accumulator before: %f", h.accumulator)
if err := instruction.Execute(h); err != nil {
return err
}
h.debug("Accumulator after: %f", h.accumulator)
return nil
}
func (h *Module) Run() error {
for !h.isStopped && h.programCounter() <= maxInstructions {
if err := h.Step(); err != nil {
return err
}
}
if h.programCounter() > maxInstructions {
return fmt.Errorf("module exceeded max instructions without being stopped")
}
return nil
}
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, handler PageErrorHandler) (*Module, error) {
if registerSize <= 10 {
return nil, fmt.Errorf("register size must be greater then 10 [ registerSize = %d ]", registerSize)
}
ios := make(map[int64]IO)
if ioSize < 0 {
return nil, fmt.Errorf("io size must positive")
}
for i := int64(0); i <= ioSize; i++ {
ios[i] = NewCommandLineIO(i, name)
}
module := &Module{
pCounter: 1,
programStorage: program,
register: make([]float64, registerSize),
IO: ios,
debugEnabled: debug,
name: name,
}
module.mmu = NewMMU(module, handler)
return module, nil
}