From Python to silicon
 
import sys, os, shutil
import commands, getopt, glob
import time
from array import array
from binascii import hexlify, unhexlify
 
 
from Stack import *
from Mem import *
from Cpu import *
from Ops import *
 
 
class Simulator():
    """
    ZPU Simulator, this is the version of the CPU that only implements
    11 instructions.  This is useful for a minimal size CPU that can be
    used in an FPGA.
    """
 
    # Constant Defaults
    INTMASK     =  0xFFFFFFFF    #    
    ADDSP       = 16
    LOADSP      = 64+32
    STORESP     = 64
 
    def __init__(self):
        """
        Simulation Object
        """
        #print "Do Something Here"
        self.cpu    = Cpu()
        self.stack  = Stack()
        self.imem   = Mem()
        self.dmem   = Mem()
 
        #
        self.cycles      = 0
        self.iCount      = 0
        self.breakNext   = 0
        self.decodeMask  = False
 
 
    def InstructionLoop(self):
        """
        """
 
        while(True):
            # try
            self.ExecuteInstruction()
 
            # catch ...
 
 
 
    def ExecuteInstruction(self):
        """
        """
 
        # CheckHalt()
        # CheckVector()
        # CheckInterrupts()
        # tracer.InstructionEvent()
 
        commit  = False
        savedSp = self.cpu.GetSp()
        savedPc = self.cpu.GetPc()
        savedDecodeMask = self.decodeMask
        touchedPc = False
 
        # @todo Change prints to logging
        print 'PC: .................0x%04X  ==  0x%02X' % (self.cpu.GetPc(), self.imem.read8(self.cpu.GetPc()))
        instruction = self.imem.read8(self.cpu.GetPc())
        #self.cpu.SetInstr(instruction)
 
        #tick()
 
        # All instructions are 8 bit, most instructions use stack postions
        # as the operands.  A couple operands have 
        if (instruction & 0x80) != 0:
 
            if self.decodeMask:
                a = (self.stack.popInt() << 7) | (instruction & 0x7F)
                self.stack.pushInt(a)
            else:
                self.stack.pushInt(instruction)
 
            #self.decodeMask = True
 
        else:
            self.decodeMask = False
 
            if isAddSP(instruction):
                offset  = instruction - self.ADDSP
                valAddr = self.cpu.GetSp() + offset*4
                a = self.stack.popInt()
                self.stack.pushInt(self.stack.readLong(valAddr) + a)
 
            elif instruction >= self.LOADSP and instruction < self.LOADSP + 0x20:
                addr = self.cpu.GetSp()
                offset = (instruction - self.LOADSP) ^ 0x10
                addr = addr + (4 * offset)
                self.stack.pushInt(self.stack.readLong(addr))
                instruction = instruction & 0xE0
 
            elif isStoreSP(instruction):
                addr = self.cpu.GetSp()
                offset = (instruction - self.STORESP)^0x10
                addr = addr + (4 * offset)
 
            else:
 
                print "..,.",Ops[instruction]['func']
 
                Ops[instruction]['func'](self.cpu, self.stack, self.dmem)
 
        # Update information, total number cycles, etc
        # Increment PC
        self.cpu.SetPc(savedPc+1)
 
        # Dump the stack
        print self.stack
 
 
def LoadBinFile(fname, sim):
    """
    load a .bin file
    """
    fp = open(fname, 'rb')
    b = 0x00
    while b is not None:
        print "%02X " % (b)
        b = fp.read(1)        
 
    #for b in fp:
        #    sim.imem.write8(0, 0x85)   # IM  5   ;; push 5 onto stack
        #print b
        #print "%02X " % (b)
 
 
def LoadHexFile(fname, sim):
    """
    load a .bin file
    """
    fp = open(fname, 'rU')
 
    # Intel Hex Format
    # :ccaaaarrddd...ddhh
    #   : == start code
    #   c == 8 bit byte count
    #   a == 16 bit address
    #   r == 8 bit record type
    #   d == n bit data
    #   h == 8 bit checksum
    for s in fp:
        s = s.strip('\r\n')
        if s[0] == ':':
            bin = array('B', unhexlify(s[1:]))
            slen  = bin[0]
            addr  = (bin[1] << 8) | bin[2]
            rtype = bin[3]
 
            #print "Loading Memory"
            for n in range(slen):
                #print "  %04X:  %02X" % (addr, bin[4+n])
                sim.imem.write8(addr, bin[4+n])
                addr +=1
        #print b
        #print "%02X " % (b)
 
 
 
def Usage():
 
    dsmg = \
"""
EZPU Instruction Set Simulator
  >> python Simulator.py <program.hex>
 
  The Simulator will load a hex file and simulate the hex file
"""
 
    print dmsg
 
def Main():
    """
    Get command line arguemnts, create simulator, run
    """
    try:
        opts, args = getopt.getopt(sys.argv[1:], "h", ["load_mem"])
    except getopt.GetoptError, err:
        usage()
        sys.exit(2)
 
    # default options
 
    # get command line options
    for o, a in opts:
        if o in ("-h"):
            usage()
            sys.exit()
        else:
            usage()
            print "Unhandled Option"
            sys.exit()
 
    if len(args) == 1:
        # @todo, determine if .bin, .asm, .elf, etc
        fname = args[0]
    else:
        Usage()
        sys.exit(2)
 
    # instantiate sim based on command line options
    sim = Simulator()
 
    # @todo load appropriate file
    # load program
    LoadHexFile(fname, sim)
 
    # Execute Instructions
    sim.InstructionLoop()
 
if __name__ == '__main__':
    # @todo call main
    Main()
    sys.exit(0)
    sim = Simulator()
 
    # Test some opcodes
    sim.imem.write8(0, 0x85)   # IM  5   ;; push 5 onto stack
    sim.imem.write8(1, 0x88)   # IM  8   ;; push 8 onto stack
    sim.imem.write8(2, 0x05)   # ADD     ;; adds first 2 values on stack 
 
    sim.ExecuteInstruction()
    sim.ExecuteInstruction()
    sim.ExecuteInstruction()
 
    # @todo prompt to continue or exit
 
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # Code Example
    # /* simple program showing some interesting qualities of the ZPU toolchain */
    # void bar(int);
    # int j;
    # void foo(int a, int b, int c)
    # {
    #     a++;
    #     b+=a;
    #     j=c;
    #     bar(b);
    # }
    #        .org 0000
    # 0000                    ;;
    # ????   bar:
    #            return       ;;
    # ????   foo:
    #            loadsp 4     ;; a is at memory location SP+4
    #            im     1     ;;   
    #            add          ;;
    #            loadsp 12    ;; b is now at memory location SP+12
    #            add          ;;
    #            loadsp 16    ;; c is now at memory location SP+16
    #            im     24    ;; j is at absolute memory location 24. 
    #            ; Notice how the ZPU toolchain is using link-time relaxation
    #            ; to squeeze the address into a single no-op
    #            store        ;;
    #            im     22    ;; the fn bar is at address 22
    #            call         ;;
    #            im     12    ;;
    #            return       ;; 12 bytes of arguments + return from fn
users/cfelton/projects/iss_sim.txt · Last modified: 2010/01/14 03:56 by cfelton
 
Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki