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.
79 lines
1.9 KiB
79 lines
1.9 KiB
package hal
|
|
|
|
import "fmt"
|
|
|
|
const maxInstructions = 1000
|
|
|
|
type Program map[int64]*ProgrammedInstruction
|
|
|
|
type Module struct {
|
|
accumulator float64
|
|
programStorage Program
|
|
register []float64
|
|
IO []float64
|
|
|
|
isStopped bool
|
|
debugEnabled bool
|
|
}
|
|
|
|
func (h *Module) programCounter() int64 {
|
|
return int64(h.register[0])
|
|
}
|
|
func (h *Module) setProgramCounter(counter int64) error {
|
|
h.register[0] = float64(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.register[0]++
|
|
}
|
|
|
|
func (h *Module) debug(format string, args ...interface{}) {
|
|
if !h.debugEnabled {
|
|
return
|
|
}
|
|
fmt.Printf("[DEBUG] "+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 uint64, debug bool) (*Module, error) {
|
|
if registerSize <= 10 {
|
|
return nil, fmt.Errorf("register size must be greater then 10 [ registerSize = %d ]", registerSize)
|
|
}
|
|
return &Module{
|
|
programStorage: program,
|
|
register: make([]float64, registerSize),
|
|
IO: make([]float64, ioSize),
|
|
debugEnabled: debug,
|
|
}, nil
|
|
}
|
|
|