modelprologstate-machinecpu-registerstree-search

Possible to simulate a simple CPU in prolog?


My understanding is that a simple model of a CPU is a state machine.

When I look at prolog, it appears to tree-search (or graph search) combinations, whilst stopping at constraints running until its goals are found.

I've been told that you can simulate a simple CPU in prolog.

Is it possible to represent a state machine model like a simple CPU in prolog?


Solution

  • Prolog is a Turing-complete language, so you can express arbitrary computations in it, including the simulation of a CPU. You can express the execution of a single instruction as a relation between two states of the CPU, one before the execution of the instruction and one after it (the instruction to be executed next is also part of the state, since it is for example available in or via one of the CPU's registers):

    cpustate0_cpustate(State0, State) :-
          ....
    

    A complete execution of a program can be described declaratively as a sequence of state transitions of the CPU. Procedurally, you transform a given state until it reaches some defined final state, for example, until some register contains or points to a specific value:

    cpu_before_after(State0, State) :-
        (    final_state(State0) -> State = State0
        ;    cpustate0_cpustate(State0, State1),
             cpu_before_after(State1, State)
        ).
    

    EDIT: For example, a state of the CPU could look like the Prolog term cpu(10, 20, 0) which could be a specific state where the first register contains the value 10, the second register contains the value 20, and a third register contains the value 0. Let us assume that the third register is the instruction pointer IP, and the CPU always executes the instruction that IP points to in the machine's RAM. So we also need to include the machine's RAM in the state representation. Let us represent the machine's state as a pair RAM-CPU, with RAM being a suitable representation of the machine's RAM contents, and CPU a representation of the CPU's registers:

    cpustate0_cpustate(State0, State) :-
         State0 = RAM0-cpu(_,_,IP0),   
         ram_at_value(RAM0, IP0, Instruction),
         instruction_state0_state(Instruction, State0, State).
    

    Suppose now there is an instruction add, which adds the values of the first two registers and stores the result in the first register, leaving the RAM unmodified:

    instruction_state0_state(add, RAM-cpu(A0,B,IP), RAM-cpu(A1,B,IP)) :-
        A1 #= A0 + B.
    

    You can describe the effects of other available instructions by additional clauses of this predicate.